v4.19.13 snapshot.
diff --git a/drivers/net/wireless/broadcom/Kconfig b/drivers/net/wireless/broadcom/Kconfig
new file mode 100644
index 0000000..eebe286
--- /dev/null
+++ b/drivers/net/wireless/broadcom/Kconfig
@@ -0,0 +1,18 @@
+config WLAN_VENDOR_BROADCOM
+	bool "Broadcom devices"
+	default y
+	---help---
+	  If you have a wireless card belonging to this class, say Y.
+
+	  Note that the answer to this question doesn't directly affect the
+	  kernel: saying N will just cause the configurator to skip all the
+	  questions about these cards. If you say Y, you will be asked for
+	  your specific card in the following questions.
+
+if WLAN_VENDOR_BROADCOM
+
+source "drivers/net/wireless/broadcom/b43/Kconfig"
+source "drivers/net/wireless/broadcom/b43legacy/Kconfig"
+source "drivers/net/wireless/broadcom/brcm80211/Kconfig"
+
+endif # WLAN_VENDOR_BROADCOM
diff --git a/drivers/net/wireless/broadcom/Makefile b/drivers/net/wireless/broadcom/Makefile
new file mode 100644
index 0000000..9d5ac95
--- /dev/null
+++ b/drivers/net/wireless/broadcom/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_B43)		+= b43/
+obj-$(CONFIG_B43LEGACY)		+= b43legacy/
+
+obj-$(CONFIG_BRCMFMAC)	+= brcm80211/
+obj-$(CONFIG_BRCMSMAC)	+= brcm80211/
diff --git a/drivers/net/wireless/broadcom/b43/Kconfig b/drivers/net/wireless/broadcom/b43/Kconfig
new file mode 100644
index 0000000..fba8560
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/Kconfig
@@ -0,0 +1,187 @@
+config B43
+	tristate "Broadcom 43xx wireless support (mac80211 stack)"
+	depends on (BCMA_POSSIBLE || SSB_POSSIBLE) && MAC80211 && HAS_DMA
+	select BCMA if B43_BCMA
+	select SSB if B43_SSB
+	select FW_LOADER
+	---help---
+	  b43 is a driver for the Broadcom 43xx series wireless devices.
+
+	  Check "lspci" for something like
+	  "Broadcom Corporation BCM43XX 802.11 Wireless LAN Controller"
+	  to determine whether you own such a device.
+
+	  This driver supports the new BCM43xx IEEE 802.11G devices, but not
+	  the old IEEE 802.11B devices. Old devices are supported by
+	  the b43legacy driver.
+	  Note that this has nothing to do with the standard that your AccessPoint
+	  supports (A, B, G or a combination).
+	  IEEE 802.11G devices can talk to IEEE 802.11B AccessPoints.
+
+	  It is safe to include both b43 and b43legacy as the underlying glue
+	  layer will automatically load the correct version for your device.
+
+	  This driver uses V4 firmware, which must be installed separately using
+	  b43-fwcutter.
+
+	  This driver can be built as a module (recommended) that will be called "b43".
+	  If unsure, say M.
+
+config B43_BCMA
+	bool
+
+config B43_SSB
+	bool
+
+choice
+	prompt "Supported bus types"
+	depends on B43
+	default B43_BUSES_BCMA_AND_SSB
+
+config B43_BUSES_BCMA_AND_SSB
+	bool "BCMA and SSB"
+	depends on BCMA_POSSIBLE && SSB_POSSIBLE
+	select B43_BCMA
+	select B43_SSB
+
+config B43_BUSES_BCMA
+	bool "BCMA only"
+	depends on BCMA_POSSIBLE
+	select B43_BCMA
+
+config B43_BUSES_SSB
+	bool "SSB only"
+	depends on SSB_POSSIBLE
+	select B43_SSB
+
+endchoice
+
+# Auto-select SSB PCI-HOST support, if possible
+config B43_PCI_AUTOSELECT
+	bool
+	depends on B43 && SSB_PCIHOST_POSSIBLE
+	select SSB_PCIHOST
+	select SSB_B43_PCI_BRIDGE
+	default y
+
+# Auto-select SSB PCICORE driver, if possible
+config B43_PCICORE_AUTOSELECT
+	bool
+	depends on B43 && SSB_DRIVER_PCICORE_POSSIBLE
+	select SSB_DRIVER_PCICORE
+	default y
+
+config B43_SDIO
+	bool "Broadcom 43xx SDIO device support"
+	depends on B43 && B43_SSB && SSB_SDIOHOST_POSSIBLE
+	select SSB_SDIOHOST
+	---help---
+	  Broadcom 43xx device support for Soft-MAC SDIO devices.
+
+	  With this config option you can drive Soft-MAC b43 cards with a
+	  Secure Digital I/O interface.
+	  This includes the WLAN daughter card found on the Nintendo Wii
+	  video game console.
+	  Note that this does not support Broadcom 43xx Full-MAC devices.
+
+	  It's safe to select Y here, even if you don't have a B43 SDIO device.
+
+	  If unsure, say N.
+
+#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 && B43_BCMA
+	select BCMA_BLOCKIO
+	default y
+
+config B43_PIO
+	bool
+	depends on B43 && B43_SSB
+	select SSB_BLOCKIO
+	default y
+
+config B43_PHY_G
+	bool "Support for G-PHY (802.11g) devices"
+	depends on B43 && B43_SSB
+	default y
+	---help---
+	  This PHY type can be found in the following chipsets:
+	  PCI: BCM4306, BCM4311, BCM4318
+	  SoC: BCM4712, BCM5352E
+
+config B43_PHY_N
+	bool "Support for N-PHY (the main 802.11n series) devices"
+	depends on B43
+	default y
+	---help---
+	  This PHY type can be found in the following chipsets:
+	  PCI: BCM4321, BCM4322,
+	       BCM43222, BCM43224, BCM43225,
+	       BCM43131, BCM43217, BCM43227, BCM43228
+	  SoC: BCM4716, BCM4717, BCM4718, BCM5356, BCM5357, BCM5358
+
+config B43_PHY_LP
+	bool "Support for LP-PHY (low-power 802.11g) devices"
+	depends on B43 && B43_SSB
+	default y
+	---help---
+	  The LP-PHY is a low-power PHY built into some notebooks
+	  and embedded devices. It supports 802.11a/b/g
+	  (802.11a support is optional, and currently disabled).
+
+config B43_PHY_HT
+	bool "Support for HT-PHY (high throughput 802.11n) devices"
+	depends on B43 && B43_BCMA
+	default y
+	---help---
+	  This PHY type with 3x3:3 MIMO can be found in the BCM4331 PCI chipset.
+
+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.
+
+config B43_PHY_AC
+	bool "Support for AC-PHY (802.11ac) devices (BROKEN)"
+	depends on B43 && B43_BCMA && BROKEN
+	---help---
+	  This PHY type can be found in the following chipsets:
+	  PCI: BCM4352, BCM4360
+
+	  Say N, this is BROKEN and crashes driver.
+
+# This config option automatically enables b43 LEDS support,
+# if it's possible.
+config B43_LEDS
+	bool
+	depends on B43 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = B43)
+	default y
+
+# This config option automatically enables b43 HW-RNG support,
+# if the HW-RNG core is enabled.
+config B43_HWRNG
+	bool
+	depends on B43 && (HW_RANDOM = y || HW_RANDOM = B43)
+	default y
+
+config B43_DEBUG
+	bool "Broadcom 43xx debugging"
+	depends on B43
+	---help---
+	  Broadcom 43xx debugging.
+
+	  This adds additional runtime sanity checks and statistics to the driver.
+	  These checks and statistics might be expensive and hurt the runtime
+	  performance of your system.
+	  This also adds the b43 debugfs interface.
+
+	  Do not enable this, unless you are debugging the driver.
+
+	  Say N, if you are a distributor or user building a release kernel
+	  for production use.
+	  Only say Y, if you are debugging a problem in the b43 driver sourcecode.
diff --git a/drivers/net/wireless/broadcom/b43/Makefile b/drivers/net/wireless/broadcom/b43/Makefile
new file mode 100644
index 0000000..54f92ce
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/Makefile
@@ -0,0 +1,28 @@
+# SPDX-License-Identifier: GPL-2.0
+b43-y				+= main.o
+b43-y				+= bus.o
+b43-$(CONFIG_B43_PHY_G)		+= phy_g.o tables.o lo.o wa.o
+b43-$(CONFIG_B43_PHY_N)		+= tables_nphy.o
+b43-$(CONFIG_B43_PHY_N)		+= radio_2055.o
+b43-$(CONFIG_B43_PHY_N)		+= radio_2056.o
+b43-$(CONFIG_B43_PHY_N)		+= radio_2057.o
+b43-y				+= phy_common.o
+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-$(CONFIG_B43_PHY_AC)	+= phy_ac.o
+b43-y				+= sysfs.o
+b43-y				+= xmit.o
+b43-y				+= dma.o
+b43-y				+= pio.o
+b43-y				+= rfkill.o
+b43-y				+= ppr.o
+b43-$(CONFIG_B43_LEDS)		+= leds.o
+b43-$(CONFIG_B43_SDIO)		+= sdio.o
+b43-$(CONFIG_B43_DEBUG)		+= debugfs.o
+
+obj-$(CONFIG_B43)		+= b43.o
diff --git a/drivers/net/wireless/broadcom/b43/b43.h b/drivers/net/wireless/broadcom/b43/b43.h
new file mode 100644
index 0000000..b77d1a9
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/b43.h
@@ -0,0 +1,1109 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_H_
+#define B43_H_
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/hw_random.h>
+#include <linux/bcma/bcma.h>
+#include <linux/ssb/ssb.h>
+#include <linux/completion.h>
+#include <net/mac80211.h>
+
+#include "debugfs.h"
+#include "leds.h"
+#include "rfkill.h"
+#include "bus.h"
+#include "lo.h"
+#include "phy_common.h"
+
+
+#ifdef CONFIG_B43_DEBUG
+# define B43_DEBUG	1
+#else
+# define B43_DEBUG	0
+#endif
+
+/* MMIO offsets */
+#define B43_MMIO_DMA0_REASON		0x20
+#define B43_MMIO_DMA0_IRQ_MASK		0x24
+#define B43_MMIO_DMA1_REASON		0x28
+#define B43_MMIO_DMA1_IRQ_MASK		0x2C
+#define B43_MMIO_DMA2_REASON		0x30
+#define B43_MMIO_DMA2_IRQ_MASK		0x34
+#define B43_MMIO_DMA3_REASON		0x38
+#define B43_MMIO_DMA3_IRQ_MASK		0x3C
+#define B43_MMIO_DMA4_REASON		0x40
+#define B43_MMIO_DMA4_IRQ_MASK		0x44
+#define B43_MMIO_DMA5_REASON		0x48
+#define B43_MMIO_DMA5_IRQ_MASK		0x4C
+#define B43_MMIO_MACCTL			0x120	/* MAC control */
+#define B43_MMIO_MACCMD			0x124	/* MAC command */
+#define B43_MMIO_GEN_IRQ_REASON		0x128
+#define B43_MMIO_GEN_IRQ_MASK		0x12C
+#define B43_MMIO_RAM_CONTROL		0x130
+#define B43_MMIO_RAM_DATA		0x134
+#define B43_MMIO_PS_STATUS		0x140
+#define B43_MMIO_RADIO_HWENABLED_HI	0x158
+#define B43_MMIO_MAC_HW_CAP		0x15C	/* MAC capabilities (corerev >= 13) */
+#define B43_MMIO_SHM_CONTROL		0x160
+#define B43_MMIO_SHM_DATA		0x164
+#define B43_MMIO_SHM_DATA_UNALIGNED	0x166
+#define B43_MMIO_XMITSTAT_0		0x170
+#define B43_MMIO_XMITSTAT_1		0x174
+#define B43_MMIO_REV3PLUS_TSF_LOW	0x180	/* core rev >= 3 only */
+#define B43_MMIO_REV3PLUS_TSF_HIGH	0x184	/* core rev >= 3 only */
+#define B43_MMIO_TSF_CFP_REP		0x188
+#define B43_MMIO_TSF_CFP_START		0x18C
+#define B43_MMIO_TSF_CFP_MAXDUR		0x190
+
+/* 32-bit DMA */
+#define B43_MMIO_DMA32_BASE0		0x200
+#define B43_MMIO_DMA32_BASE1		0x220
+#define B43_MMIO_DMA32_BASE2		0x240
+#define B43_MMIO_DMA32_BASE3		0x260
+#define B43_MMIO_DMA32_BASE4		0x280
+#define B43_MMIO_DMA32_BASE5		0x2A0
+/* 64-bit DMA */
+#define B43_MMIO_DMA64_BASE0		0x200
+#define B43_MMIO_DMA64_BASE1		0x240
+#define B43_MMIO_DMA64_BASE2		0x280
+#define B43_MMIO_DMA64_BASE3		0x2C0
+#define B43_MMIO_DMA64_BASE4		0x300
+#define B43_MMIO_DMA64_BASE5		0x340
+
+/* PIO on core rev < 11 */
+#define B43_MMIO_PIO_BASE0		0x300
+#define B43_MMIO_PIO_BASE1		0x310
+#define B43_MMIO_PIO_BASE2		0x320
+#define B43_MMIO_PIO_BASE3		0x330
+#define B43_MMIO_PIO_BASE4		0x340
+#define B43_MMIO_PIO_BASE5		0x350
+#define B43_MMIO_PIO_BASE6		0x360
+#define B43_MMIO_PIO_BASE7		0x370
+/* PIO on core rev >= 11 */
+#define B43_MMIO_PIO11_BASE0		0x200
+#define B43_MMIO_PIO11_BASE1		0x240
+#define B43_MMIO_PIO11_BASE2		0x280
+#define B43_MMIO_PIO11_BASE3		0x2C0
+#define B43_MMIO_PIO11_BASE4		0x300
+#define B43_MMIO_PIO11_BASE5		0x340
+
+#define B43_MMIO_RADIO24_CONTROL	0x3D8	/* core rev >= 24 only */
+#define B43_MMIO_RADIO24_DATA		0x3DA	/* core rev >= 24 only */
+#define B43_MMIO_PHY_VER		0x3E0
+#define B43_MMIO_PHY_RADIO		0x3E2
+#define B43_MMIO_PHY0			0x3E6
+#define B43_MMIO_ANTENNA		0x3E8
+#define B43_MMIO_CHANNEL		0x3F0
+#define B43_MMIO_CHANNEL_EXT		0x3F4
+#define B43_MMIO_RADIO_CONTROL		0x3F6
+#define B43_MMIO_RADIO_DATA_HIGH	0x3F8
+#define B43_MMIO_RADIO_DATA_LOW		0x3FA
+#define B43_MMIO_PHY_CONTROL		0x3FC
+#define B43_MMIO_PHY_DATA		0x3FE
+#define B43_MMIO_MACFILTER_CONTROL	0x420
+#define B43_MMIO_MACFILTER_DATA		0x422
+#define B43_MMIO_RCMTA_COUNT		0x43C
+#define B43_MMIO_PSM_PHY_HDR		0x492
+#define B43_MMIO_RADIO_HWENABLED_LO	0x49A
+#define B43_MMIO_GPIO_CONTROL		0x49C
+#define B43_MMIO_GPIO_MASK		0x49E
+#define B43_MMIO_TXE0_CTL		0x500
+#define B43_MMIO_TXE0_AUX		0x502
+#define B43_MMIO_TXE0_TS_LOC		0x504
+#define B43_MMIO_TXE0_TIME_OUT		0x506
+#define B43_MMIO_TXE0_WM_0		0x508
+#define B43_MMIO_TXE0_WM_1		0x50A
+#define B43_MMIO_TXE0_PHYCTL		0x50C
+#define B43_MMIO_TXE0_STATUS		0x50E
+#define B43_MMIO_TXE0_MMPLCP0		0x510
+#define B43_MMIO_TXE0_MMPLCP1		0x512
+#define B43_MMIO_TXE0_PHYCTL1		0x514
+#define B43_MMIO_XMTFIFODEF		0x520
+#define B43_MMIO_XMTFIFO_FRAME_CNT	0x522	/* core rev>= 16 only */
+#define B43_MMIO_XMTFIFO_BYTE_CNT	0x524	/* core rev>= 16 only */
+#define B43_MMIO_XMTFIFO_HEAD		0x526	/* core rev>= 16 only */
+#define B43_MMIO_XMTFIFO_RD_PTR		0x528	/* core rev>= 16 only */
+#define B43_MMIO_XMTFIFO_WR_PTR		0x52A	/* core rev>= 16 only */
+#define B43_MMIO_XMTFIFODEF1		0x52C	/* core rev>= 16 only */
+#define B43_MMIO_XMTFIFOCMD		0x540
+#define B43_MMIO_XMTFIFOFLUSH		0x542
+#define B43_MMIO_XMTFIFOTHRESH		0x544
+#define B43_MMIO_XMTFIFORDY		0x546
+#define B43_MMIO_XMTFIFOPRIRDY		0x548
+#define B43_MMIO_XMTFIFORQPRI		0x54A
+#define B43_MMIO_XMTTPLATETXPTR		0x54C
+#define B43_MMIO_XMTTPLATEPTR		0x550
+#define B43_MMIO_SMPL_CLCT_STRPTR	0x552	/* core rev>= 22 only */
+#define B43_MMIO_SMPL_CLCT_STPPTR	0x554	/* core rev>= 22 only */
+#define B43_MMIO_SMPL_CLCT_CURPTR	0x556	/* core rev>= 22 only */
+#define B43_MMIO_XMTTPLATEDATALO	0x560
+#define B43_MMIO_XMTTPLATEDATAHI	0x562
+#define B43_MMIO_XMTSEL			0x568
+#define B43_MMIO_XMTTXCNT		0x56A
+#define B43_MMIO_XMTTXSHMADDR		0x56C
+#define B43_MMIO_TSF_CFP_START_LOW	0x604
+#define B43_MMIO_TSF_CFP_START_HIGH	0x606
+#define B43_MMIO_TSF_CFP_PRETBTT	0x612
+#define B43_MMIO_TSF_CLK_FRAC_LOW	0x62E
+#define B43_MMIO_TSF_CLK_FRAC_HIGH	0x630
+#define B43_MMIO_TSF_0			0x632	/* core rev < 3 only */
+#define B43_MMIO_TSF_1			0x634	/* core rev < 3 only */
+#define B43_MMIO_TSF_2			0x636	/* core rev < 3 only */
+#define B43_MMIO_TSF_3			0x638	/* core rev < 3 only */
+#define B43_MMIO_RNG			0x65A
+#define B43_MMIO_IFSSLOT		0x684	/* Interframe slot time */
+#define B43_MMIO_IFSCTL			0x688	/* Interframe space control */
+#define B43_MMIO_IFSSTAT		0x690
+#define B43_MMIO_IFSMEDBUSYCTL		0x692
+#define B43_MMIO_IFTXDUR		0x694
+#define  B43_MMIO_IFSCTL_USE_EDCF	0x0004
+#define B43_MMIO_POWERUP_DELAY		0x6A8
+#define B43_MMIO_BTCOEX_CTL		0x6B4 /* Bluetooth Coexistence Control */
+#define B43_MMIO_BTCOEX_STAT		0x6B6 /* Bluetooth Coexistence Status */
+#define B43_MMIO_BTCOEX_TXCTL		0x6B8 /* Bluetooth Coexistence Transmit Control */
+#define B43_MMIO_WEPCTL			0x7C0
+
+/* SPROM boardflags_lo values */
+#define B43_BFL_BTCOEXIST		0x0001	/* implements Bluetooth coexistance */
+#define B43_BFL_PACTRL			0x0002	/* GPIO 9 controlling the PA */
+#define B43_BFL_AIRLINEMODE		0x0004	/* implements GPIO 13 radio disable indication */
+#define B43_BFL_RSSI			0x0008	/* software calculates nrssi slope. */
+#define B43_BFL_ENETSPI			0x0010	/* has ephy roboswitch spi */
+#define B43_BFL_XTAL_NOSLOW		0x0020	/* no slow clock available */
+#define B43_BFL_CCKHIPWR		0x0040	/* can do high power CCK transmission */
+#define B43_BFL_ENETADM			0x0080	/* has ADMtek switch */
+#define B43_BFL_ENETVLAN		0x0100	/* can do vlan */
+#define B43_BFL_AFTERBURNER		0x0200	/* supports Afterburner mode */
+#define B43_BFL_NOPCI			0x0400	/* leaves PCI floating */
+#define B43_BFL_FEM			0x0800	/* supports the Front End Module */
+#define B43_BFL_EXTLNA			0x1000	/* has an external LNA */
+#define B43_BFL_HGPA			0x2000	/* had high gain PA */
+#define B43_BFL_BTCMOD			0x4000	/* BFL_BTCOEXIST is given in alternate GPIOs */
+#define B43_BFL_ALTIQ			0x8000	/* alternate I/Q settings */
+
+/* SPROM boardflags_hi values */
+#define B43_BFH_NOPA			0x0001	/* has no PA */
+#define B43_BFH_RSSIINV			0x0002	/* RSSI uses positive slope (not TSSI) */
+#define B43_BFH_PAREF			0x0004	/* uses the PARef LDO */
+#define B43_BFH_3TSWITCH		0x0008	/* uses a triple throw switch shared
+						 * with bluetooth */
+#define B43_BFH_PHASESHIFT		0x0010	/* can support phase shifter */
+#define B43_BFH_BUCKBOOST		0x0020	/* has buck/booster */
+#define B43_BFH_FEM_BT			0x0040	/* has FEM and switch to share antenna
+						 * with bluetooth */
+#define B43_BFH_NOCBUCK			0x0080
+#define B43_BFH_PALDO			0x0200
+#define B43_BFH_EXTLNA_5GHZ		0x1000	/* has an external LNA (5GHz mode) */
+
+/* SPROM boardflags2_lo values */
+#define B43_BFL2_RXBB_INT_REG_DIS	0x0001	/* external RX BB regulator present */
+#define B43_BFL2_APLL_WAR		0x0002	/* alternative A-band PLL settings implemented */
+#define B43_BFL2_TXPWRCTRL_EN 		0x0004	/* permits enabling TX Power Control */
+#define B43_BFL2_2X4_DIV		0x0008	/* 2x4 diversity switch */
+#define B43_BFL2_5G_PWRGAIN		0x0010	/* supports 5G band power gain */
+#define B43_BFL2_PCIEWAR_OVR		0x0020	/* overrides ASPM and Clkreq settings */
+#define B43_BFL2_CAESERS_BRD		0x0040	/* is Caesers board (unused) */
+#define B43_BFL2_BTC3WIRE		0x0080	/* used 3-wire bluetooth coexist */
+#define B43_BFL2_SKWRKFEM_BRD		0x0100	/* 4321mcm93 uses Skyworks FEM */
+#define B43_BFL2_SPUR_WAR		0x0200	/* has a workaround for clock-harmonic spurs */
+#define B43_BFL2_GPLL_WAR		0x0400	/* altenative G-band PLL settings implemented */
+#define B43_BFL2_SINGLEANT_CCK		0x1000
+#define B43_BFL2_2G_SPUR_WAR		0x2000
+
+/* SPROM boardflags2_hi values */
+#define B43_BFH2_GPLL_WAR2		0x0001
+#define B43_BFH2_IPALVLSHIFT_3P3	0x0002
+#define B43_BFH2_INTERNDET_TXIQCAL	0x0004
+#define B43_BFH2_XTALBUFOUTEN		0x0008
+
+/* GPIO register offset, in both ChipCommon and PCI core. */
+#define B43_GPIO_CONTROL		0x6c
+
+/* SHM Routing */
+enum {
+	B43_SHM_UCODE,		/* Microcode memory */
+	B43_SHM_SHARED,		/* Shared memory */
+	B43_SHM_SCRATCH,	/* Scratch memory */
+	B43_SHM_HW,		/* Internal hardware register */
+	B43_SHM_RCMTA,		/* Receive match transmitter address (rev >= 5 only) */
+};
+/* SHM Routing modifiers */
+#define B43_SHM_AUTOINC_R		0x0200	/* Auto-increment address on read */
+#define B43_SHM_AUTOINC_W		0x0100	/* Auto-increment address on write */
+#define B43_SHM_AUTOINC_RW		(B43_SHM_AUTOINC_R | \
+					 B43_SHM_AUTOINC_W)
+
+/* Misc SHM_SHARED offsets */
+#define B43_SHM_SH_WLCOREREV		0x0016	/* 802.11 core revision */
+#define B43_SHM_SH_PCTLWDPOS		0x0008
+#define B43_SHM_SH_RXPADOFF		0x0034	/* RX Padding data offset (PIO only) */
+#define B43_SHM_SH_FWCAPA		0x0042	/* Firmware capabilities (Opensource firmware only) */
+#define B43_SHM_SH_PHYVER		0x0050	/* PHY version */
+#define B43_SHM_SH_PHYTYPE		0x0052	/* PHY type */
+#define B43_SHM_SH_ANTSWAP		0x005C	/* Antenna swap threshold */
+#define B43_SHM_SH_HOSTF1		0x005E	/* Hostflags 1 for ucode options */
+#define B43_SHM_SH_HOSTF2		0x0060	/* Hostflags 2 for ucode options */
+#define B43_SHM_SH_HOSTF3		0x0062	/* Hostflags 3 for ucode options */
+#define B43_SHM_SH_RFATT		0x0064	/* Current radio attenuation value */
+#define B43_SHM_SH_RADAR		0x0066	/* Radar register */
+#define B43_SHM_SH_PHYTXNOI		0x006E	/* PHY noise directly after TX (lower 8bit only) */
+#define B43_SHM_SH_RFRXSP1		0x0072	/* RF RX SP Register 1 */
+#define B43_SHM_SH_HOSTF4		0x0078	/* Hostflags 4 for ucode options */
+#define B43_SHM_SH_CHAN			0x00A0	/* Current channel (low 8bit only) */
+#define  B43_SHM_SH_CHAN_5GHZ		0x0100	/* Bit set, if 5 Ghz channel */
+#define  B43_SHM_SH_CHAN_40MHZ		0x0200	/* Bit set, if 40 Mhz channel width */
+#define B43_SHM_SH_MACHW_L		0x00C0	/* Location where the ucode expects the MAC capabilities */
+#define B43_SHM_SH_MACHW_H		0x00C2	/* Location where the ucode expects the MAC capabilities */
+#define B43_SHM_SH_HOSTF5		0x00D4	/* Hostflags 5 for ucode options */
+#define B43_SHM_SH_BCMCFIFOID		0x0108	/* Last posted cookie to the bcast/mcast FIFO */
+/* TSSI information */
+#define B43_SHM_SH_TSSI_CCK		0x0058	/* TSSI for last 4 CCK frames (32bit) */
+#define B43_SHM_SH_TSSI_OFDM_A		0x0068	/* TSSI for last 4 OFDM frames (32bit) */
+#define B43_SHM_SH_TSSI_OFDM_G		0x0070	/* TSSI for last 4 OFDM frames (32bit) */
+#define  B43_TSSI_MAX			0x7F	/* Max value for one TSSI value */
+/* SHM_SHARED TX FIFO variables */
+#define B43_SHM_SH_SIZE01		0x0098	/* TX FIFO size for FIFO 0 (low) and 1 (high) */
+#define B43_SHM_SH_SIZE23		0x009A	/* TX FIFO size for FIFO 2 and 3 */
+#define B43_SHM_SH_SIZE45		0x009C	/* TX FIFO size for FIFO 4 and 5 */
+#define B43_SHM_SH_SIZE67		0x009E	/* TX FIFO size for FIFO 6 and 7 */
+/* SHM_SHARED background noise */
+#define B43_SHM_SH_JSSI0		0x0088	/* Measure JSSI 0 */
+#define B43_SHM_SH_JSSI1		0x008A	/* Measure JSSI 1 */
+#define B43_SHM_SH_JSSIAUX		0x008C	/* Measure JSSI AUX */
+/* SHM_SHARED crypto engine */
+#define B43_SHM_SH_DEFAULTIV		0x003C	/* Default IV location */
+#define B43_SHM_SH_NRRXTRANS		0x003E	/* # of soft RX transmitter addresses (max 8) */
+#define B43_SHM_SH_KTP			0x0056	/* Key table pointer */
+#define B43_SHM_SH_TKIPTSCTTAK		0x0318
+#define B43_SHM_SH_KEYIDXBLOCK		0x05D4	/* Key index/algorithm block (v4 firmware) */
+#define B43_SHM_SH_PSM			0x05F4	/* PSM transmitter address match block (rev < 5) */
+/* SHM_SHARED WME variables */
+#define B43_SHM_SH_EDCFSTAT		0x000E	/* EDCF status */
+#define B43_SHM_SH_TXFCUR		0x0030	/* TXF current index */
+#define B43_SHM_SH_EDCFQ		0x0240	/* EDCF Q info */
+/* SHM_SHARED powersave mode related */
+#define B43_SHM_SH_SLOTT		0x0010	/* Slot time */
+#define B43_SHM_SH_DTIMPER		0x0012	/* DTIM period */
+#define B43_SHM_SH_NOSLPZNATDTIM	0x004C	/* NOSLPZNAT DTIM */
+/* SHM_SHARED beacon/AP variables */
+#define B43_SHM_SH_BT_BASE0		0x0068	/* Beacon template base 0 */
+#define B43_SHM_SH_BTL0			0x0018	/* Beacon template length 0 */
+#define B43_SHM_SH_BT_BASE1		0x0468	/* Beacon template base 1 */
+#define B43_SHM_SH_BTL1			0x001A	/* Beacon template length 1 */
+#define B43_SHM_SH_BTSFOFF		0x001C	/* Beacon TSF offset */
+#define B43_SHM_SH_TIMBPOS		0x001E	/* TIM B position in beacon */
+#define B43_SHM_SH_DTIMP		0x0012	/* DTIP period */
+#define B43_SHM_SH_MCASTCOOKIE		0x00A8	/* Last bcast/mcast frame ID */
+#define B43_SHM_SH_SFFBLIM		0x0044	/* Short frame fallback retry limit */
+#define B43_SHM_SH_LFFBLIM		0x0046	/* Long frame fallback retry limit */
+#define B43_SHM_SH_BEACPHYCTL		0x0054	/* Beacon PHY TX control word (see PHY TX control) */
+#define B43_SHM_SH_EXTNPHYCTL		0x00B0	/* Extended bytes for beacon PHY control (N) */
+#define B43_SHM_SH_BCN_LI		0x00B6	/* beacon listen interval */
+/* SHM_SHARED ACK/CTS control */
+#define B43_SHM_SH_ACKCTSPHYCTL		0x0022	/* ACK/CTS PHY control word (see PHY TX control) */
+/* SHM_SHARED probe response variables */
+#define B43_SHM_SH_PRSSID		0x0160	/* Probe Response SSID */
+#define B43_SHM_SH_PRSSIDLEN		0x0048	/* Probe Response SSID length */
+#define B43_SHM_SH_PRTLEN		0x004A	/* Probe Response template length */
+#define B43_SHM_SH_PRMAXTIME		0x0074	/* Probe Response max time */
+#define B43_SHM_SH_PRPHYCTL		0x0188	/* Probe Response PHY TX control word */
+/* SHM_SHARED rate tables */
+#define B43_SHM_SH_OFDMDIRECT		0x01C0	/* Pointer to OFDM direct map */
+#define B43_SHM_SH_OFDMBASIC		0x01E0	/* Pointer to OFDM basic rate map */
+#define B43_SHM_SH_CCKDIRECT		0x0200	/* Pointer to CCK direct map */
+#define B43_SHM_SH_CCKBASIC		0x0220	/* Pointer to CCK basic rate map */
+/* SHM_SHARED microcode soft registers */
+#define B43_SHM_SH_UCODEREV		0x0000	/* Microcode revision */
+#define B43_SHM_SH_UCODEPATCH		0x0002	/* Microcode patchlevel */
+#define B43_SHM_SH_UCODEDATE		0x0004	/* Microcode date */
+#define B43_SHM_SH_UCODETIME		0x0006	/* Microcode time */
+#define B43_SHM_SH_UCODESTAT		0x0040	/* Microcode debug status code */
+#define  B43_SHM_SH_UCODESTAT_INVALID	0
+#define  B43_SHM_SH_UCODESTAT_INIT	1
+#define  B43_SHM_SH_UCODESTAT_ACTIVE	2
+#define  B43_SHM_SH_UCODESTAT_SUSP	3	/* suspended */
+#define  B43_SHM_SH_UCODESTAT_SLEEP	4	/* asleep (PS) */
+#define B43_SHM_SH_MAXBFRAMES		0x0080	/* Maximum number of frames in a burst */
+#define B43_SHM_SH_SPUWKUP		0x0094	/* pre-wakeup for synth PU in us */
+#define B43_SHM_SH_PRETBTT		0x0096	/* pre-TBTT in us */
+/* SHM_SHARED tx iq workarounds */
+#define B43_SHM_SH_NPHY_TXIQW0		0x0700
+#define B43_SHM_SH_NPHY_TXIQW1		0x0702
+#define B43_SHM_SH_NPHY_TXIQW2		0x0704
+#define B43_SHM_SH_NPHY_TXIQW3		0x0706
+/* SHM_SHARED tx pwr ctrl */
+#define B43_SHM_SH_NPHY_TXPWR_INDX0	0x0708
+#define B43_SHM_SH_NPHY_TXPWR_INDX1	0x070E
+
+/* SHM_SCRATCH offsets */
+#define B43_SHM_SC_MINCONT		0x0003	/* Minimum contention window */
+#define B43_SHM_SC_MAXCONT		0x0004	/* Maximum contention window */
+#define B43_SHM_SC_CURCONT		0x0005	/* Current contention window */
+#define B43_SHM_SC_SRLIMIT		0x0006	/* Short retry count limit */
+#define B43_SHM_SC_LRLIMIT		0x0007	/* Long retry count limit */
+#define B43_SHM_SC_DTIMC		0x0008	/* Current DTIM count */
+#define B43_SHM_SC_BTL0LEN		0x0015	/* Beacon 0 template length */
+#define B43_SHM_SC_BTL1LEN		0x0016	/* Beacon 1 template length */
+#define B43_SHM_SC_SCFB			0x0017	/* Short frame transmit count threshold for rate fallback */
+#define B43_SHM_SC_LCFB			0x0018	/* Long frame transmit count threshold for rate fallback */
+
+/* Hardware Radio Enable masks */
+#define B43_MMIO_RADIO_HWENABLED_HI_MASK (1 << 16)
+#define B43_MMIO_RADIO_HWENABLED_LO_MASK (1 << 4)
+
+/* HostFlags. See b43_hf_read/write() */
+#define B43_HF_ANTDIVHELP	0x000000000001ULL /* ucode antenna div helper */
+#define B43_HF_SYMW		0x000000000002ULL /* G-PHY SYM workaround */
+#define B43_HF_RXPULLW		0x000000000004ULL /* RX pullup workaround */
+#define B43_HF_CCKBOOST		0x000000000008ULL /* 4dB CCK power boost (exclusive with OFDM boost) */
+#define B43_HF_BTCOEX		0x000000000010ULL /* Bluetooth coexistance */
+#define B43_HF_GDCW		0x000000000020ULL /* G-PHY DC canceller filter bw workaround */
+#define B43_HF_OFDMPABOOST	0x000000000040ULL /* Enable PA gain boost for OFDM */
+#define B43_HF_ACPR		0x000000000080ULL /* Disable for Japan, channel 14 */
+#define B43_HF_EDCF		0x000000000100ULL /* on if WME and MAC suspended */
+#define B43_HF_TSSIRPSMW	0x000000000200ULL /* TSSI reset PSM ucode workaround */
+#define B43_HF_20IN40IQW	0x000000000200ULL /* 20 in 40 MHz I/Q workaround (rev >= 13 only) */
+#define B43_HF_DSCRQ		0x000000000400ULL /* Disable slow clock request in ucode */
+#define B43_HF_ACIW		0x000000000800ULL /* ACI workaround: shift bits by 2 on PHY CRS */
+#define B43_HF_2060W		0x000000001000ULL /* 2060 radio workaround */
+#define B43_HF_RADARW		0x000000002000ULL /* Radar workaround */
+#define B43_HF_USEDEFKEYS	0x000000004000ULL /* Enable use of default keys */
+#define B43_HF_AFTERBURNER	0x000000008000ULL /* Afterburner enabled */
+#define B43_HF_BT4PRIOCOEX	0x000000010000ULL /* Bluetooth 4-priority coexistance */
+#define B43_HF_FWKUP		0x000000020000ULL /* Fast wake-up ucode */
+#define B43_HF_VCORECALC	0x000000040000ULL /* Force VCO recalculation when powering up synthpu */
+#define B43_HF_PCISCW		0x000000080000ULL /* PCI slow clock workaround */
+#define B43_HF_4318TSSI		0x000000200000ULL /* 4318 TSSI */
+#define B43_HF_FBCMCFIFO	0x000000400000ULL /* Flush bcast/mcast FIFO immediately */
+#define B43_HF_HWPCTL		0x000000800000ULL /* Enable hardwarre power control */
+#define B43_HF_BTCOEXALT	0x000001000000ULL /* Bluetooth coexistance in alternate pins */
+#define B43_HF_TXBTCHECK	0x000002000000ULL /* Bluetooth check during transmission */
+#define B43_HF_SKCFPUP		0x000004000000ULL /* Skip CFP update */
+#define B43_HF_N40W		0x000008000000ULL /* N PHY 40 MHz workaround (rev >= 13 only) */
+#define B43_HF_ANTSEL		0x000020000000ULL /* Antenna selection (for testing antenna div.) */
+#define B43_HF_BT3COEXT		0x000020000000ULL /* Bluetooth 3-wire coexistence (rev >= 13 only) */
+#define B43_HF_BTCANT		0x000040000000ULL /* Bluetooth coexistence (antenna mode) (rev >= 13 only) */
+#define B43_HF_ANTSELEN		0x000100000000ULL /* Antenna selection enabled (rev >= 13 only) */
+#define B43_HF_ANTSELMODE	0x000200000000ULL /* Antenna selection mode (rev >= 13 only) */
+#define B43_HF_MLADVW		0x001000000000ULL /* N PHY ML ADV workaround (rev >= 13 only) */
+#define B43_HF_PR45960W		0x080000000000ULL /* PR 45960 workaround (rev >= 13 only) */
+
+/* Firmware capabilities field in SHM (Opensource firmware only) */
+#define B43_FWCAPA_HWCRYPTO	0x0001
+#define B43_FWCAPA_QOS		0x0002
+
+/* MacFilter offsets. */
+#define B43_MACFILTER_SELF		0x0000
+#define B43_MACFILTER_BSSID		0x0003
+
+/* PowerControl */
+#define B43_PCTL_IN			0xB0
+#define B43_PCTL_OUT			0xB4
+#define B43_PCTL_OUTENABLE		0xB8
+#define B43_PCTL_XTAL_POWERUP		0x40
+#define B43_PCTL_PLL_POWERDOWN		0x80
+
+/* PowerControl Clock Modes */
+#define B43_PCTL_CLK_FAST		0x00
+#define B43_PCTL_CLK_SLOW		0x01
+#define B43_PCTL_CLK_DYNAMIC		0x02
+
+#define B43_PCTL_FORCE_SLOW		0x0800
+#define B43_PCTL_FORCE_PLL		0x1000
+#define B43_PCTL_DYN_XTAL		0x2000
+
+/* PHYVersioning */
+#define B43_PHYTYPE_A			0x00
+#define B43_PHYTYPE_B			0x01
+#define B43_PHYTYPE_G			0x02
+#define B43_PHYTYPE_N			0x04
+#define B43_PHYTYPE_LP			0x05
+#define B43_PHYTYPE_SSLPN		0x06
+#define B43_PHYTYPE_HT			0x07
+#define B43_PHYTYPE_LCN			0x08
+#define B43_PHYTYPE_LCNXN		0x09
+#define B43_PHYTYPE_LCN40		0x0a
+#define B43_PHYTYPE_AC			0x0b
+
+/* PHYRegisters */
+#define B43_PHY_ILT_A_CTRL		0x0072
+#define B43_PHY_ILT_A_DATA1		0x0073
+#define B43_PHY_ILT_A_DATA2		0x0074
+#define B43_PHY_G_LO_CONTROL		0x0810
+#define B43_PHY_ILT_G_CTRL		0x0472
+#define B43_PHY_ILT_G_DATA1		0x0473
+#define B43_PHY_ILT_G_DATA2		0x0474
+#define B43_PHY_A_PCTL			0x007B
+#define B43_PHY_G_PCTL			0x0029
+#define B43_PHY_A_CRS			0x0029
+#define B43_PHY_RADIO_BITFIELD		0x0401
+#define B43_PHY_G_CRS			0x0429
+#define B43_PHY_NRSSILT_CTRL		0x0803
+#define B43_PHY_NRSSILT_DATA		0x0804
+
+/* RadioRegisters */
+#define B43_RADIOCTL_ID			0x01
+
+/* MAC Control bitfield */
+#define B43_MACCTL_ENABLED		0x00000001	/* MAC Enabled */
+#define B43_MACCTL_PSM_RUN		0x00000002	/* Run Microcode */
+#define B43_MACCTL_PSM_JMP0		0x00000004	/* Microcode jump to 0 */
+#define B43_MACCTL_SHM_ENABLED		0x00000100	/* SHM Enabled */
+#define B43_MACCTL_SHM_UPPER		0x00000200	/* SHM Upper */
+#define B43_MACCTL_IHR_ENABLED		0x00000400	/* IHR Region Enabled */
+#define B43_MACCTL_PSM_DBG		0x00002000	/* Microcode debugging enabled */
+#define B43_MACCTL_GPOUTSMSK		0x0000C000	/* GPOUT Select Mask */
+#define B43_MACCTL_BE			0x00010000	/* Big Endian mode */
+#define B43_MACCTL_INFRA		0x00020000	/* Infrastructure mode */
+#define B43_MACCTL_AP			0x00040000	/* AccessPoint mode */
+#define B43_MACCTL_RADIOLOCK		0x00080000	/* Radio lock */
+#define B43_MACCTL_BEACPROMISC		0x00100000	/* Beacon Promiscuous */
+#define B43_MACCTL_KEEP_BADPLCP		0x00200000	/* Keep frames with bad PLCP */
+#define B43_MACCTL_PHY_LOCK		0x00200000
+#define B43_MACCTL_KEEP_CTL		0x00400000	/* Keep control frames */
+#define B43_MACCTL_KEEP_BAD		0x00800000	/* Keep bad frames (FCS) */
+#define B43_MACCTL_PROMISC		0x01000000	/* Promiscuous mode */
+#define B43_MACCTL_HWPS			0x02000000	/* Hardware Power Saving */
+#define B43_MACCTL_AWAKE		0x04000000	/* Device is awake */
+#define B43_MACCTL_CLOSEDNET		0x08000000	/* Closed net (no SSID bcast) */
+#define B43_MACCTL_TBTTHOLD		0x10000000	/* TBTT Hold */
+#define B43_MACCTL_DISCTXSTAT		0x20000000	/* Discard TX status */
+#define B43_MACCTL_DISCPMQ		0x40000000	/* Discard Power Management Queue */
+#define B43_MACCTL_GMODE		0x80000000	/* G Mode */
+
+/* MAC Command bitfield */
+#define B43_MACCMD_BEACON0_VALID	0x00000001	/* Beacon 0 in template RAM is busy/valid */
+#define B43_MACCMD_BEACON1_VALID	0x00000002	/* Beacon 1 in template RAM is busy/valid */
+#define B43_MACCMD_DFQ_VALID		0x00000004	/* Directed frame queue valid (IBSS PS mode, ATIM) */
+#define B43_MACCMD_CCA			0x00000008	/* Clear channel assessment */
+#define B43_MACCMD_BGNOISE		0x00000010	/* Background noise */
+
+/* B43_MMIO_PSM_PHY_HDR bits */
+#define B43_PSM_HDR_MAC_PHY_RESET	0x00000001
+#define B43_PSM_HDR_MAC_PHY_CLOCK_EN	0x00000002
+#define B43_PSM_HDR_MAC_PHY_FORCE_CLK	0x00000004
+
+/* See BCMA_CLKCTLST_EXTRESREQ and BCMA_CLKCTLST_EXTRESST */
+#define B43_BCMA_CLKCTLST_80211_PLL_REQ	0x00000100
+#define B43_BCMA_CLKCTLST_PHY_PLL_REQ	0x00000200
+#define B43_BCMA_CLKCTLST_80211_PLL_ST	0x01000000
+#define B43_BCMA_CLKCTLST_PHY_PLL_ST	0x02000000
+
+/* BCMA 802.11 core specific IO Control (BCMA_IOCTL) flags */
+#define B43_BCMA_IOCTL_PHY_CLKEN	0x00000004	/* PHY Clock Enable */
+#define B43_BCMA_IOCTL_PHY_RESET	0x00000008	/* PHY Reset */
+#define B43_BCMA_IOCTL_MACPHYCLKEN	0x00000010	/* MAC PHY Clock Control Enable */
+#define B43_BCMA_IOCTL_PLLREFSEL	0x00000020	/* PLL Frequency Reference Select */
+#define B43_BCMA_IOCTL_PHY_BW		0x000000C0	/* PHY band width and clock speed mask (N-PHY+ only?) */
+#define  B43_BCMA_IOCTL_PHY_BW_10MHZ	0x00000000	/* 10 MHz bandwidth, 40 MHz PHY */
+#define  B43_BCMA_IOCTL_PHY_BW_20MHZ	0x00000040	/* 20 MHz bandwidth, 80 MHz PHY */
+#define  B43_BCMA_IOCTL_PHY_BW_40MHZ	0x00000080	/* 40 MHz bandwidth, 160 MHz PHY */
+#define  B43_BCMA_IOCTL_PHY_BW_80MHZ	0x000000C0	/* 80 MHz bandwidth */
+#define B43_BCMA_IOCTL_DAC		0x00000300	/* Highspeed DAC mode control field */
+#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) */
+#define  B43_TMSLOW_PHY_BANDWIDTH_10MHZ	0x00000000	/* 10 MHz bandwidth, 40 MHz PHY */
+#define  B43_TMSLOW_PHY_BANDWIDTH_20MHZ	0x00400000	/* 20 MHz bandwidth, 80 MHz PHY */
+#define  B43_TMSLOW_PHY_BANDWIDTH_40MHZ	0x00800000	/* 40 MHz bandwidth, 160 MHz PHY */
+#define B43_TMSLOW_PLLREFSEL		0x00200000	/* PLL Frequency Reference Select (rev >= 5) */
+#define B43_TMSLOW_MACPHYCLKEN		0x00100000	/* MAC PHY Clock Control Enable (rev >= 5) */
+#define B43_TMSLOW_PHYRESET		0x00080000	/* PHY Reset */
+#define B43_TMSLOW_PHYCLKEN		0x00040000	/* PHY Clock Enable */
+
+/* 802.11 core specific TM State High (SSB_TMSHIGH) flags */
+#define B43_TMSHIGH_DUALBAND_PHY	0x00080000	/* Dualband PHY available */
+#define B43_TMSHIGH_FCLOCK		0x00040000	/* Fast Clock Available (rev >= 5) */
+#define B43_TMSHIGH_HAVE_5GHZ_PHY	0x00020000	/* 5 GHz PHY available (rev >= 5) */
+#define B43_TMSHIGH_HAVE_2GHZ_PHY	0x00010000	/* 2.4 GHz PHY available (rev >= 5) */
+
+/* Generic-Interrupt reasons. */
+#define B43_IRQ_MAC_SUSPENDED		0x00000001
+#define B43_IRQ_BEACON			0x00000002
+#define B43_IRQ_TBTT_INDI		0x00000004
+#define B43_IRQ_BEACON_TX_OK		0x00000008
+#define B43_IRQ_BEACON_CANCEL		0x00000010
+#define B43_IRQ_ATIM_END		0x00000020
+#define B43_IRQ_PMQ			0x00000040
+#define B43_IRQ_PIO_WORKAROUND		0x00000100
+#define B43_IRQ_MAC_TXERR		0x00000200
+#define B43_IRQ_PHY_TXERR		0x00000800
+#define B43_IRQ_PMEVENT			0x00001000
+#define B43_IRQ_TIMER0			0x00002000
+#define B43_IRQ_TIMER1			0x00004000
+#define B43_IRQ_DMA			0x00008000
+#define B43_IRQ_TXFIFO_FLUSH_OK		0x00010000
+#define B43_IRQ_CCA_MEASURE_OK		0x00020000
+#define B43_IRQ_NOISESAMPLE_OK		0x00040000
+#define B43_IRQ_UCODE_DEBUG		0x08000000
+#define B43_IRQ_RFKILL			0x10000000
+#define B43_IRQ_TX_OK			0x20000000
+#define B43_IRQ_PHY_G_CHANGED		0x40000000
+#define B43_IRQ_TIMEOUT			0x80000000
+
+#define B43_IRQ_ALL			0xFFFFFFFF
+#define B43_IRQ_MASKTEMPLATE		(B43_IRQ_TBTT_INDI | \
+					 B43_IRQ_ATIM_END | \
+					 B43_IRQ_PMQ | \
+					 B43_IRQ_MAC_TXERR | \
+					 B43_IRQ_PHY_TXERR | \
+					 B43_IRQ_DMA | \
+					 B43_IRQ_TXFIFO_FLUSH_OK | \
+					 B43_IRQ_NOISESAMPLE_OK | \
+					 B43_IRQ_UCODE_DEBUG | \
+					 B43_IRQ_RFKILL | \
+					 B43_IRQ_TX_OK)
+
+/* The firmware register to fetch the debug-IRQ reason from. */
+#define B43_DEBUGIRQ_REASON_REG		63
+/* Debug-IRQ reasons. */
+#define B43_DEBUGIRQ_PANIC		0	/* The firmware panic'ed */
+#define B43_DEBUGIRQ_DUMP_SHM		1	/* Dump shared SHM */
+#define B43_DEBUGIRQ_DUMP_REGS		2	/* Dump the microcode registers */
+#define B43_DEBUGIRQ_MARKER		3	/* A "marker" was thrown by the firmware. */
+#define B43_DEBUGIRQ_ACK		0xFFFF	/* The host writes that to ACK the IRQ */
+
+/* The firmware register that contains the "marker" line. */
+#define B43_MARKER_ID_REG		2
+#define B43_MARKER_LINE_REG		3
+
+/* The firmware register to fetch the panic reason from. */
+#define B43_FWPANIC_REASON_REG		3
+/* Firmware panic reason codes */
+#define B43_FWPANIC_DIE			0 /* Firmware died. Don't auto-restart it. */
+#define B43_FWPANIC_RESTART		1 /* Firmware died. Schedule a controller reset. */
+
+/* The firmware register that contains the watchdog counter. */
+#define B43_WATCHDOG_REG		1
+
+/* Device specific rate values.
+ * The actual values defined here are (rate_in_mbps * 2).
+ * Some code depends on this. Don't change it. */
+#define B43_CCK_RATE_1MB		0x02
+#define B43_CCK_RATE_2MB		0x04
+#define B43_CCK_RATE_5MB		0x0B
+#define B43_CCK_RATE_11MB		0x16
+#define B43_OFDM_RATE_6MB		0x0C
+#define B43_OFDM_RATE_9MB		0x12
+#define B43_OFDM_RATE_12MB		0x18
+#define B43_OFDM_RATE_18MB		0x24
+#define B43_OFDM_RATE_24MB		0x30
+#define B43_OFDM_RATE_36MB		0x48
+#define B43_OFDM_RATE_48MB		0x60
+#define B43_OFDM_RATE_54MB		0x6C
+/* Convert a b43 rate value to a rate in 100kbps */
+#define B43_RATE_TO_BASE100KBPS(rate)	(((rate) * 10) / 2)
+
+#define B43_DEFAULT_SHORT_RETRY_LIMIT	7
+#define B43_DEFAULT_LONG_RETRY_LIMIT	4
+
+#define B43_PHY_TX_BADNESS_LIMIT	1000
+
+/* Max size of a security key */
+#define B43_SEC_KEYSIZE			16
+/* Max number of group keys */
+#define B43_NR_GROUP_KEYS		4
+/* Max number of pairwise keys */
+#define B43_NR_PAIRWISE_KEYS		50
+/* Security algorithms. */
+enum {
+	B43_SEC_ALGO_NONE = 0,	/* unencrypted, as of TX header. */
+	B43_SEC_ALGO_WEP40,
+	B43_SEC_ALGO_TKIP,
+	B43_SEC_ALGO_AES,
+	B43_SEC_ALGO_WEP104,
+	B43_SEC_ALGO_AES_LEGACY,
+};
+
+struct b43_dmaring;
+
+/* The firmware file header */
+#define B43_FW_TYPE_UCODE	'u'
+#define B43_FW_TYPE_PCM		'p'
+#define B43_FW_TYPE_IV		'i'
+struct b43_fw_header {
+	/* File type */
+	u8 type;
+	/* File format version */
+	u8 ver;
+	u8 __padding[2];
+	/* Size of the data. For ucode and PCM this is in bytes.
+	 * For IV this is number-of-ivs. */
+	__be32 size;
+} __packed;
+
+/* Initial Value file format */
+#define B43_IV_OFFSET_MASK	0x7FFF
+#define B43_IV_32BIT		0x8000
+struct b43_iv {
+	__be16 offset_size;
+	union {
+		__be16 d16;
+		__be32 d32;
+	} data __packed;
+} __packed;
+
+
+/* Data structures for DMA transmission, per 80211 core. */
+struct b43_dma {
+	struct b43_dmaring *tx_ring_AC_BK; /* Background */
+	struct b43_dmaring *tx_ring_AC_BE; /* Best Effort */
+	struct b43_dmaring *tx_ring_AC_VI; /* Video */
+	struct b43_dmaring *tx_ring_AC_VO; /* Voice */
+	struct b43_dmaring *tx_ring_mcast; /* Multicast */
+
+	struct b43_dmaring *rx_ring;
+
+	u32 translation; /* Routing bits */
+	bool translation_in_low; /* Should translation bit go into low addr? */
+	bool parity; /* Check for parity */
+};
+
+struct b43_pio_txqueue;
+struct b43_pio_rxqueue;
+
+/* Data structures for PIO transmission, per 80211 core. */
+struct b43_pio {
+	struct b43_pio_txqueue *tx_queue_AC_BK; /* Background */
+	struct b43_pio_txqueue *tx_queue_AC_BE; /* Best Effort */
+	struct b43_pio_txqueue *tx_queue_AC_VI; /* Video */
+	struct b43_pio_txqueue *tx_queue_AC_VO; /* Voice */
+	struct b43_pio_txqueue *tx_queue_mcast; /* Multicast */
+
+	struct b43_pio_rxqueue *rx_queue;
+};
+
+/* Context information for a noise calculation (Link Quality). */
+struct b43_noise_calculation {
+	bool calculation_running;
+	u8 nr_samples;
+	s8 samples[8][4];
+};
+
+struct b43_stats {
+	u8 link_noise;
+};
+
+struct b43_key {
+	/* If keyconf is NULL, this key is disabled.
+	 * keyconf is a cookie. Don't derefenrence it outside of the set_key
+	 * path, because b43 doesn't own it. */
+	struct ieee80211_key_conf *keyconf;
+	u8 algorithm;
+};
+
+/* SHM offsets to the QOS data structures for the 4 different queues. */
+#define B43_QOS_QUEUE_NUM	4
+#define B43_QOS_PARAMS(queue)	(B43_SHM_SH_EDCFQ + \
+				 (B43_NR_QOSPARAMS * sizeof(u16) * (queue)))
+#define B43_QOS_BACKGROUND	B43_QOS_PARAMS(0)
+#define B43_QOS_BESTEFFORT	B43_QOS_PARAMS(1)
+#define B43_QOS_VIDEO		B43_QOS_PARAMS(2)
+#define B43_QOS_VOICE		B43_QOS_PARAMS(3)
+
+/* QOS parameter hardware data structure offsets. */
+#define B43_NR_QOSPARAMS	16
+enum {
+	B43_QOSPARAM_TXOP = 0,
+	B43_QOSPARAM_CWMIN,
+	B43_QOSPARAM_CWMAX,
+	B43_QOSPARAM_CWCUR,
+	B43_QOSPARAM_AIFS,
+	B43_QOSPARAM_BSLOTS,
+	B43_QOSPARAM_REGGAP,
+	B43_QOSPARAM_STATUS,
+};
+
+/* QOS parameters for a queue. */
+struct b43_qos_params {
+	/* The QOS parameters */
+	struct ieee80211_tx_queue_params p;
+};
+
+struct b43_wl;
+
+/* The type of the firmware file. */
+enum b43_firmware_file_type {
+	B43_FWTYPE_PROPRIETARY,
+	B43_FWTYPE_OPENSOURCE,
+	B43_NR_FWTYPES,
+};
+
+/* Context data for fetching firmware. */
+struct b43_request_fw_context {
+	/* The device we are requesting the fw for. */
+	struct b43_wldev *dev;
+	/* a pointer to the firmware object */
+	const struct firmware *blob;
+	/* The type of firmware to request. */
+	enum b43_firmware_file_type req_type;
+	/* Error messages for each firmware type. */
+	char errors[B43_NR_FWTYPES][128];
+	/* Temporary buffer for storing the firmware name. */
+	char fwname[64];
+	/* A fatal error occurred while requesting. Firmware request
+	 * can not continue, as any other request will also fail. */
+	int fatal_failure;
+};
+
+/* In-memory representation of a cached microcode file. */
+struct b43_firmware_file {
+	const char *filename;
+	const struct firmware *data;
+	/* Type of the firmware file name. Note that this does only indicate
+	 * the type by the firmware name. NOT the file contents.
+	 * If you want to check for proprietary vs opensource, use (struct b43_firmware)->opensource
+	 * instead! The (struct b43_firmware)->opensource flag is derived from the actual firmware
+	 * binary code, not just the filename.
+	 */
+	enum b43_firmware_file_type type;
+};
+
+enum b43_firmware_hdr_format {
+	B43_FW_HDR_598,
+	B43_FW_HDR_410,
+	B43_FW_HDR_351,
+};
+
+/* Pointers to the firmware data and meta information about it. */
+struct b43_firmware {
+	/* Microcode */
+	struct b43_firmware_file ucode;
+	/* PCM code */
+	struct b43_firmware_file pcm;
+	/* Initial MMIO values for the firmware */
+	struct b43_firmware_file initvals;
+	/* Initial MMIO values for the firmware, band-specific */
+	struct b43_firmware_file initvals_band;
+
+	/* Firmware revision */
+	u16 rev;
+	/* Firmware patchlevel */
+	u16 patch;
+
+	/* Format of header used by firmware */
+	enum b43_firmware_hdr_format hdr_format;
+
+	/* Set to true, if we are using an opensource firmware.
+	 * Use this to check for proprietary vs opensource. */
+	bool opensource;
+	/* Set to true, if the core needs a PCM firmware, but
+	 * we failed to load one. This is always false for
+	 * core rev > 10, as these don't need PCM firmware. */
+	bool pcm_request_failed;
+};
+
+enum b43_band {
+	B43_BAND_2G = 0,
+	B43_BAND_5G_LO = 1,
+	B43_BAND_5G_MI = 2,
+	B43_BAND_5G_HI = 3,
+};
+
+/* Device (802.11 core) initialization status. */
+enum {
+	B43_STAT_UNINIT = 0,	/* Uninitialized. */
+	B43_STAT_INITIALIZED = 1,	/* Initialized, but not started, yet. */
+	B43_STAT_STARTED = 2,	/* Up and running. */
+};
+#define b43_status(wldev)		atomic_read(&(wldev)->__init_status)
+#define b43_set_status(wldev, stat)	do {			\
+		atomic_set(&(wldev)->__init_status, (stat));	\
+		smp_wmb();					\
+					} while (0)
+
+/* Data structure for one wireless device (802.11 core) */
+struct b43_wldev {
+	struct b43_bus_dev *dev;
+	struct b43_wl *wl;
+	/* a completion event structure needed if this call is asynchronous */
+	struct completion fw_load_complete;
+
+	/* The device initialization status.
+	 * Use b43_status() to query. */
+	atomic_t __init_status;
+
+	bool bad_frames_preempt;	/* Use "Bad Frames Preemption" (default off) */
+	bool dfq_valid;		/* Directed frame queue valid (IBSS PS mode, ATIM) */
+	bool radio_hw_enable;	/* saved state of radio hardware enabled state */
+	bool qos_enabled;		/* TRUE, if QoS is used. */
+	bool hwcrypto_enabled;		/* TRUE, if HW crypto acceleration is enabled. */
+	bool use_pio;			/* TRUE if next init should use PIO */
+
+	/* PHY/Radio device. */
+	struct b43_phy phy;
+
+	union {
+		/* DMA engines. */
+		struct b43_dma dma;
+		/* PIO engines. */
+		struct b43_pio pio;
+	};
+	/* Use b43_using_pio_transfers() to check whether we are using
+	 * DMA or PIO data transfers. */
+	bool __using_pio_transfers;
+
+	/* Various statistics about the physical device. */
+	struct b43_stats stats;
+
+	/* Reason code of the last interrupt. */
+	u32 irq_reason;
+	u32 dma_reason[6];
+	/* The currently active generic-interrupt mask. */
+	u32 irq_mask;
+
+	/* Link Quality calculation context. */
+	struct b43_noise_calculation noisecalc;
+	/* if > 0 MAC is suspended. if == 0 MAC is enabled. */
+	int mac_suspended;
+
+	/* Periodic tasks */
+	struct delayed_work periodic_work;
+	unsigned int periodic_state;
+
+	struct work_struct restart_work;
+
+	/* encryption/decryption */
+	u16 ktp;		/* Key table pointer */
+	struct b43_key key[B43_NR_GROUP_KEYS * 2 + B43_NR_PAIRWISE_KEYS];
+
+	/* Firmware data */
+	struct b43_firmware fw;
+
+	/* Devicelist in struct b43_wl (all 802.11 cores) */
+	struct list_head list;
+
+	/* Debugging stuff follows. */
+#ifdef CONFIG_B43_DEBUG
+	struct b43_dfsentry *dfsentry;
+	unsigned int irq_count;
+	unsigned int irq_bit_count[32];
+	unsigned int tx_count;
+	unsigned int rx_count;
+#endif
+};
+
+/* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */
+struct b43_wl {
+	/* Pointer to the active wireless device on this chip */
+	struct b43_wldev *current_dev;
+	/* Pointer to the ieee80211 hardware data structure */
+	struct ieee80211_hw *hw;
+
+	/* Global driver mutex. Every operation must run with this mutex locked. */
+	struct mutex mutex;
+	/* Hard-IRQ spinlock. This lock protects things used in the hard-IRQ
+	 * handler, only. This basically is just the IRQ mask register. */
+	spinlock_t hardirq_lock;
+
+	/* Set this if we call ieee80211_register_hw() and check if we call
+	 * ieee80211_unregister_hw(). */
+	bool hw_registred;
+
+	/* We can only have one operating interface (802.11 core)
+	 * at a time. General information about this interface follows.
+	 */
+
+	struct ieee80211_vif *vif;
+	/* The MAC address of the operating interface. */
+	u8 mac_addr[ETH_ALEN];
+	/* Current BSSID */
+	u8 bssid[ETH_ALEN];
+	/* Interface type. (NL80211_IFTYPE_XXX) */
+	int if_type;
+	/* Is the card operating in AP, STA or IBSS mode? */
+	bool operating;
+	/* filter flags */
+	unsigned int filter_flags;
+	/* Stats about the wireless interface */
+	struct ieee80211_low_level_stats ieee_stats;
+
+#ifdef CONFIG_B43_HWRNG
+	struct hwrng rng;
+	bool rng_initialized;
+	char rng_name[30 + 1];
+#endif /* CONFIG_B43_HWRNG */
+
+	bool radiotap_enabled;
+	bool radio_enabled;
+
+	/* The beacon we are currently using (AP or IBSS mode). */
+	struct sk_buff *current_beacon;
+	bool beacon0_uploaded;
+	bool beacon1_uploaded;
+	bool beacon_templates_virgin; /* Never wrote the templates? */
+	struct work_struct beacon_update_trigger;
+	spinlock_t beacon_lock;
+
+	/* The current QOS parameters for the 4 queues. */
+	struct b43_qos_params qos_params[B43_QOS_QUEUE_NUM];
+
+	/* Work for adjustment of the transmission power.
+	 * This is scheduled when we determine that the actual TX output
+	 * power doesn't match what we want. */
+	struct work_struct txpower_adjust_work;
+
+	/* Packet transmit work */
+	struct work_struct tx_work;
+
+	/* Queue of packets to be transmitted. */
+	struct sk_buff_head tx_queue[B43_QOS_QUEUE_NUM];
+
+	/* Flag that implement the queues stopping. */
+	bool tx_queue_stopped[B43_QOS_QUEUE_NUM];
+
+	/* firmware loading work */
+	struct work_struct firmware_load;
+
+	/* The device LEDs. */
+	struct b43_leds leds;
+
+	/* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */
+	u8 pio_scratchspace[118] __attribute__((__aligned__(8)));
+	u8 pio_tailspace[4] __attribute__((__aligned__(8)));
+};
+
+static inline struct b43_wl *hw_to_b43_wl(struct ieee80211_hw *hw)
+{
+	return hw->priv;
+}
+
+static inline struct b43_wldev *dev_to_b43_wldev(struct device *dev)
+{
+	struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
+	return ssb_get_drvdata(ssb_dev);
+}
+
+/* Is the device operating in a specified mode (NL80211_IFTYPE_XXX). */
+static inline int b43_is_mode(struct b43_wl *wl, int type)
+{
+	return (wl->operating && wl->if_type == type);
+}
+
+/**
+ * b43_current_band - Returns the currently used band.
+ * Returns one of NL80211_BAND_2GHZ and NL80211_BAND_5GHZ.
+ */
+static inline enum nl80211_band b43_current_band(struct b43_wl *wl)
+{
+	return wl->hw->conf.chandef.chan->band;
+}
+
+static inline int b43_bus_may_powerdown(struct b43_wldev *wldev)
+{
+	return wldev->dev->bus_may_powerdown(wldev->dev);
+}
+static inline int b43_bus_powerup(struct b43_wldev *wldev, bool dynamic_pctl)
+{
+	return wldev->dev->bus_powerup(wldev->dev, dynamic_pctl);
+}
+static inline int b43_device_is_enabled(struct b43_wldev *wldev)
+{
+	return wldev->dev->device_is_enabled(wldev->dev);
+}
+static inline void b43_device_enable(struct b43_wldev *wldev,
+				     u32 core_specific_flags)
+{
+	wldev->dev->device_enable(wldev->dev, core_specific_flags);
+}
+static inline void b43_device_disable(struct b43_wldev *wldev,
+				      u32 core_specific_flags)
+{
+	wldev->dev->device_disable(wldev->dev, core_specific_flags);
+}
+
+static inline u16 b43_read16(struct b43_wldev *dev, u16 offset)
+{
+	return dev->dev->read16(dev->dev, offset);
+}
+
+static inline void b43_write16(struct b43_wldev *dev, u16 offset, u16 value)
+{
+	dev->dev->write16(dev->dev, offset, value);
+}
+
+/* To optimize this check for flush_writes on BCM47XX_BCMA only. */
+static inline void b43_write16f(struct b43_wldev *dev, u16 offset, u16 value)
+{
+	b43_write16(dev, offset, value);
+#if defined(CONFIG_BCM47XX_BCMA)
+	if (dev->dev->flush_writes)
+		b43_read16(dev, offset);
+#endif
+}
+
+static inline void b43_maskset16(struct b43_wldev *dev, u16 offset, u16 mask,
+				 u16 set)
+{
+	b43_write16(dev, offset, (b43_read16(dev, offset) & mask) | set);
+}
+
+static inline u32 b43_read32(struct b43_wldev *dev, u16 offset)
+{
+	return dev->dev->read32(dev->dev, offset);
+}
+
+static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value)
+{
+	dev->dev->write32(dev->dev, offset, value);
+}
+
+static inline void b43_maskset32(struct b43_wldev *dev, u16 offset, u32 mask,
+				 u32 set)
+{
+	b43_write32(dev, offset, (b43_read32(dev, offset) & mask) | set);
+}
+
+static inline void b43_block_read(struct b43_wldev *dev, void *buffer,
+				 size_t count, u16 offset, u8 reg_width)
+{
+	dev->dev->block_read(dev->dev, buffer, count, offset, reg_width);
+}
+
+static inline void b43_block_write(struct b43_wldev *dev, const void *buffer,
+				   size_t count, u16 offset, u8 reg_width)
+{
+	dev->dev->block_write(dev->dev, buffer, count, offset, reg_width);
+}
+
+static inline bool b43_using_pio_transfers(struct b43_wldev *dev)
+{
+	return dev->__using_pio_transfers;
+}
+
+/* Message printing */
+__printf(2, 3) void b43info(struct b43_wl *wl, const char *fmt, ...);
+__printf(2, 3) void b43err(struct b43_wl *wl, const char *fmt, ...);
+__printf(2, 3) void b43warn(struct b43_wl *wl, const char *fmt, ...);
+__printf(2, 3) void b43dbg(struct b43_wl *wl, const char *fmt, ...);
+
+
+/* A WARN_ON variant that vanishes when b43 debugging is disabled.
+ * This _also_ evaluates the arg with debugging disabled. */
+#if B43_DEBUG
+# define B43_WARN_ON(x)	WARN_ON(x)
+#else
+static inline bool __b43_warn_on_dummy(bool x) { return x; }
+# define B43_WARN_ON(x)	__b43_warn_on_dummy(unlikely(!!(x)))
+#endif
+
+/* Convert an integer to a Q5.2 value */
+#define INT_TO_Q52(i)	((i) << 2)
+/* Convert a Q5.2 value to an integer (precision loss!) */
+#define Q52_TO_INT(q52)	((q52) >> 2)
+/* Macros for printing a value in Q5.2 format */
+#define Q52_FMT		"%u.%u"
+#define Q52_ARG(q52)	Q52_TO_INT(q52), ((((q52) & 0x3) * 100) / 4)
+
+#endif /* B43_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/bus.c b/drivers/net/wireless/broadcom/b43/bus.c
new file mode 100644
index 0000000..17d16a3
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/bus.c
@@ -0,0 +1,265 @@
+/*
+
+  Broadcom B43 wireless driver
+  Bus abstraction layer
+
+  Copyright (c) 2011 Rafał Miłecki <zajec5@gmail.com>
+
+  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.
+
+*/
+
+#ifdef CONFIG_BCM47XX_BCMA
+#include <asm/mach-bcm47xx/bcm47xx.h>
+#endif
+
+#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;
+#ifdef CONFIG_BCM47XX_BCMA
+	if (b43_bus_host_is_pci(dev) &&
+	    bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA &&
+	    bcm47xx_bus.bcma.bus.chipinfo.id == BCMA_CHIP_ID_BCM4716)
+		dev->flush_writes = true;
+#endif
+
+	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->sprom.board_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 int b43_bus_ssb_bus_may_powerdown(struct b43_bus_dev *dev)
+{
+	return ssb_bus_may_powerdown(dev->sdev->bus);
+}
+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 int b43_bus_ssb_device_is_enabled(struct b43_bus_dev *dev)
+{
+	return ssb_device_is_enabled(dev->sdev);
+}
+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 void b43_bus_ssb_device_disable(struct b43_bus_dev *dev,
+					      u32 core_specific_flags)
+{
+	ssb_device_disable(dev->sdev, core_specific_flags);
+}
+
+static u16 b43_bus_ssb_read16(struct b43_bus_dev *dev, u16 offset)
+{
+	return ssb_read16(dev->sdev, offset);
+}
+static u32 b43_bus_ssb_read32(struct b43_bus_dev *dev, u16 offset)
+{
+	return ssb_read32(dev->sdev, offset);
+}
+static void b43_bus_ssb_write16(struct b43_bus_dev *dev, u16 offset, u16 value)
+{
+	ssb_write16(dev->sdev, offset, value);
+}
+static void b43_bus_ssb_write32(struct b43_bus_dev *dev, u16 offset, u32 value)
+{
+	ssb_write32(dev->sdev, offset, value);
+}
+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
+void b43_bus_ssb_block_write(struct b43_bus_dev *dev, const void *buffer,
+			     size_t count, u16 offset, u8 reg_width)
+{
+	ssb_block_write(dev->sdev, buffer, count, offset, reg_width);
+}
+
+struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev)
+{
+	struct b43_bus_dev *dev;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+
+	dev->bus_type = B43_BUS_SSB;
+	dev->sdev = sdev;
+
+	dev->bus_may_powerdown = b43_bus_ssb_bus_may_powerdown;
+	dev->bus_powerup = b43_bus_ssb_bus_powerup;
+	dev->device_is_enabled = b43_bus_ssb_device_is_enabled;
+	dev->device_enable = b43_bus_ssb_device_enable;
+	dev->device_disable = b43_bus_ssb_device_disable;
+
+	dev->read16 = b43_bus_ssb_read16;
+	dev->read32 = b43_bus_ssb_read32;
+	dev->write16 = b43_bus_ssb_write16;
+	dev->write32 = b43_bus_ssb_write32;
+	dev->block_read = b43_bus_ssb_block_read;
+	dev->block_write = b43_bus_ssb_block_write;
+
+	dev->dev = sdev->dev;
+	dev->dma_dev = sdev->dma_dev;
+	dev->irq = sdev->irq;
+
+	dev->board_vendor = sdev->bus->boardinfo.vendor;
+	dev->board_type = sdev->bus->boardinfo.type;
+	dev->board_rev = sdev->bus->sprom.board_rev;
+
+	dev->chip_id = sdev->bus->chip_id;
+	dev->chip_rev = sdev->bus->chip_rev;
+	dev->chip_pkg = sdev->bus->chip_package;
+
+	dev->bus_sprom = &sdev->bus->sprom;
+
+	dev->core_id = sdev->id.coreid;
+	dev->core_rev = sdev->id.revision;
+
+	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);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		ssb_set_drvdata(dev->sdev, wldev);
+		break;
+#endif
+	}
+}
diff --git a/drivers/net/wireless/broadcom/b43/bus.h b/drivers/net/wireless/broadcom/b43/bus.h
new file mode 100644
index 0000000..2a695f9
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/bus.h
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_BUS_H_
+#define B43_BUS_H_
+
+enum b43_bus_type {
+#ifdef CONFIG_B43_BCMA
+	B43_BUS_BCMA,
+#endif
+#ifdef CONFIG_B43_SSB
+	B43_BUS_SSB,
+#endif
+};
+
+struct b43_bus_dev {
+	enum b43_bus_type bus_type;
+	union {
+		struct bcma_device *bdev;
+		struct ssb_device *sdev;
+	};
+
+	int (*bus_may_powerdown)(struct b43_bus_dev *dev);
+	int (*bus_powerup)(struct b43_bus_dev *dev, bool dynamic_pctl);
+	int (*device_is_enabled)(struct b43_bus_dev *dev);
+	void (*device_enable)(struct b43_bus_dev *dev,
+			      u32 core_specific_flags);
+	void (*device_disable)(struct b43_bus_dev *dev,
+			       u32 core_specific_flags);
+
+	u16 (*read16)(struct b43_bus_dev *dev, u16 offset);
+	u32 (*read32)(struct b43_bus_dev *dev, u16 offset);
+	void (*write16)(struct b43_bus_dev *dev, u16 offset, u16 value);
+	void (*write32)(struct b43_bus_dev *dev, u16 offset, u32 value);
+	void (*block_read)(struct b43_bus_dev *dev, void *buffer,
+			   size_t count, u16 offset, u8 reg_width);
+	void (*block_write)(struct b43_bus_dev *dev, const void *buffer,
+			    size_t count, u16 offset, u8 reg_width);
+	bool flush_writes;
+
+	struct device *dev;
+	struct device *dma_dev;
+	unsigned int irq;
+
+	u16 board_vendor;
+	u16 board_type;
+	u16 board_rev;
+
+	u16 chip_id;
+	u8 chip_rev;
+	u8 chip_pkg;
+
+	struct ssb_sprom *bus_sprom;
+
+	u16 core_id;
+	u8 core_rev;
+};
+
+static inline bool b43_bus_host_is_pcmcia(struct b43_bus_dev *dev)
+{
+#ifdef CONFIG_B43_SSB
+	return (dev->bus_type == B43_BUS_SSB &&
+		dev->sdev->bus->bustype == SSB_BUSTYPE_PCMCIA);
+#else
+	return false;
+#endif
+};
+
+static inline bool b43_bus_host_is_pci(struct b43_bus_dev *dev)
+{
+#ifdef CONFIG_B43_BCMA
+	if (dev->bus_type == B43_BUS_BCMA)
+		return (dev->bdev->bus->hosttype == BCMA_HOSTTYPE_PCI);
+#endif
+#ifdef CONFIG_B43_SSB
+	if (dev->bus_type == B43_BUS_SSB)
+		return (dev->sdev->bus->bustype == SSB_BUSTYPE_PCI);
+#endif
+	return false;
+}
+
+static inline bool b43_bus_host_is_sdio(struct b43_bus_dev *dev)
+{
+#ifdef CONFIG_B43_SSB
+	return (dev->bus_type == B43_BUS_SSB &&
+		dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO);
+#else
+	return false;
+#endif
+}
+
+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_ */
diff --git a/drivers/net/wireless/broadcom/b43/debugfs.c b/drivers/net/wireless/broadcom/b43/debugfs.c
new file mode 100644
index 0000000..7704638
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/debugfs.c
@@ -0,0 +1,828 @@
+/*
+
+  Broadcom B43 wireless driver
+
+  debugfs driver debugging code
+
+  Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
+
+  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/fs.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/mutex.h>
+
+#include "b43.h"
+#include "main.h"
+#include "debugfs.h"
+#include "dma.h"
+#include "xmit.h"
+
+
+/* The root directory. */
+static struct dentry *rootdir;
+
+struct b43_debugfs_fops {
+	ssize_t (*read)(struct b43_wldev *dev, char *buf, size_t bufsize);
+	int (*write)(struct b43_wldev *dev, const char *buf, size_t count);
+	struct file_operations fops;
+	/* Offset of struct b43_dfs_file in struct b43_dfsentry */
+	size_t file_struct_offset;
+};
+
+static inline
+struct b43_dfs_file *fops_to_dfs_file(struct b43_wldev *dev,
+				      const struct b43_debugfs_fops *dfops)
+{
+	void *p;
+
+	p = dev->dfsentry;
+	p += dfops->file_struct_offset;
+
+	return p;
+}
+
+
+#define fappend(fmt, x...)	\
+	do {							\
+		if (bufsize - count)				\
+			count += snprintf(buf + count,		\
+					  bufsize - count,	\
+					  fmt , ##x);		\
+		else						\
+			printk(KERN_ERR "b43: fappend overflow\n"); \
+	} while (0)
+
+
+/* The biggest address values for SHM access from the debugfs files. */
+#define B43_MAX_SHM_ROUTING	4
+#define B43_MAX_SHM_ADDR	0xFFFF
+
+static ssize_t shm16read__read_file(struct b43_wldev *dev,
+				    char *buf, size_t bufsize)
+{
+	ssize_t count = 0;
+	unsigned int routing, addr;
+	u16 val;
+
+	routing = dev->dfsentry->shm16read_routing_next;
+	addr = dev->dfsentry->shm16read_addr_next;
+	if ((routing > B43_MAX_SHM_ROUTING) ||
+	    (addr > B43_MAX_SHM_ADDR))
+		return -EDESTADDRREQ;
+
+	val = b43_shm_read16(dev, routing, addr);
+	fappend("0x%04X\n", val);
+
+	return count;
+}
+
+static int shm16read__write_file(struct b43_wldev *dev,
+				 const char *buf, size_t count)
+{
+	unsigned int routing, addr;
+	int res;
+
+	res = sscanf(buf, "0x%X 0x%X", &routing, &addr);
+	if (res != 2)
+		return -EINVAL;
+	if (routing > B43_MAX_SHM_ROUTING)
+		return -EADDRNOTAVAIL;
+	if (addr > B43_MAX_SHM_ADDR)
+		return -EADDRNOTAVAIL;
+	if (routing == B43_SHM_SHARED) {
+		if ((addr % 2) != 0)
+			return -EADDRNOTAVAIL;
+	}
+
+	dev->dfsentry->shm16read_routing_next = routing;
+	dev->dfsentry->shm16read_addr_next = addr;
+
+	return 0;
+}
+
+static int shm16write__write_file(struct b43_wldev *dev,
+				  const char *buf, size_t count)
+{
+	unsigned int routing, addr, mask, set;
+	u16 val;
+	int res;
+
+	res = sscanf(buf, "0x%X 0x%X 0x%X 0x%X",
+		     &routing, &addr, &mask, &set);
+	if (res != 4)
+		return -EINVAL;
+	if (routing > B43_MAX_SHM_ROUTING)
+		return -EADDRNOTAVAIL;
+	if (addr > B43_MAX_SHM_ADDR)
+		return -EADDRNOTAVAIL;
+	if (routing == B43_SHM_SHARED) {
+		if ((addr % 2) != 0)
+			return -EADDRNOTAVAIL;
+	}
+	if ((mask > 0xFFFF) || (set > 0xFFFF))
+		return -E2BIG;
+
+	if (mask == 0)
+		val = 0;
+	else
+		val = b43_shm_read16(dev, routing, addr);
+	val &= mask;
+	val |= set;
+	b43_shm_write16(dev, routing, addr, val);
+
+	return 0;
+}
+
+static ssize_t shm32read__read_file(struct b43_wldev *dev,
+				    char *buf, size_t bufsize)
+{
+	ssize_t count = 0;
+	unsigned int routing, addr;
+	u32 val;
+
+	routing = dev->dfsentry->shm32read_routing_next;
+	addr = dev->dfsentry->shm32read_addr_next;
+	if ((routing > B43_MAX_SHM_ROUTING) ||
+	    (addr > B43_MAX_SHM_ADDR))
+		return -EDESTADDRREQ;
+
+	val = b43_shm_read32(dev, routing, addr);
+	fappend("0x%08X\n", val);
+
+	return count;
+}
+
+static int shm32read__write_file(struct b43_wldev *dev,
+				 const char *buf, size_t count)
+{
+	unsigned int routing, addr;
+	int res;
+
+	res = sscanf(buf, "0x%X 0x%X", &routing, &addr);
+	if (res != 2)
+		return -EINVAL;
+	if (routing > B43_MAX_SHM_ROUTING)
+		return -EADDRNOTAVAIL;
+	if (addr > B43_MAX_SHM_ADDR)
+		return -EADDRNOTAVAIL;
+	if (routing == B43_SHM_SHARED) {
+		if ((addr % 2) != 0)
+			return -EADDRNOTAVAIL;
+	}
+
+	dev->dfsentry->shm32read_routing_next = routing;
+	dev->dfsentry->shm32read_addr_next = addr;
+
+	return 0;
+}
+
+static int shm32write__write_file(struct b43_wldev *dev,
+				  const char *buf, size_t count)
+{
+	unsigned int routing, addr, mask, set;
+	u32 val;
+	int res;
+
+	res = sscanf(buf, "0x%X 0x%X 0x%X 0x%X",
+		     &routing, &addr, &mask, &set);
+	if (res != 4)
+		return -EINVAL;
+	if (routing > B43_MAX_SHM_ROUTING)
+		return -EADDRNOTAVAIL;
+	if (addr > B43_MAX_SHM_ADDR)
+		return -EADDRNOTAVAIL;
+	if (routing == B43_SHM_SHARED) {
+		if ((addr % 2) != 0)
+			return -EADDRNOTAVAIL;
+	}
+	if ((mask > 0xFFFFFFFF) || (set > 0xFFFFFFFF))
+		return -E2BIG;
+
+	if (mask == 0)
+		val = 0;
+	else
+		val = b43_shm_read32(dev, routing, addr);
+	val &= mask;
+	val |= set;
+	b43_shm_write32(dev, routing, addr, val);
+
+	return 0;
+}
+
+/* The biggest MMIO address that we allow access to from the debugfs files. */
+#define B43_MAX_MMIO_ACCESS	(0xF00 - 1)
+
+static ssize_t mmio16read__read_file(struct b43_wldev *dev,
+				     char *buf, size_t bufsize)
+{
+	ssize_t count = 0;
+	unsigned int addr;
+	u16 val;
+
+	addr = dev->dfsentry->mmio16read_next;
+	if (addr > B43_MAX_MMIO_ACCESS)
+		return -EDESTADDRREQ;
+
+	val = b43_read16(dev, addr);
+	fappend("0x%04X\n", val);
+
+	return count;
+}
+
+static int mmio16read__write_file(struct b43_wldev *dev,
+				  const char *buf, size_t count)
+{
+	unsigned int addr;
+	int res;
+
+	res = sscanf(buf, "0x%X", &addr);
+	if (res != 1)
+		return -EINVAL;
+	if (addr > B43_MAX_MMIO_ACCESS)
+		return -EADDRNOTAVAIL;
+	if ((addr % 2) != 0)
+		return -EINVAL;
+
+	dev->dfsentry->mmio16read_next = addr;
+
+	return 0;
+}
+
+static int mmio16write__write_file(struct b43_wldev *dev,
+				   const char *buf, size_t count)
+{
+	unsigned int addr, mask, set;
+	int res;
+	u16 val;
+
+	res = sscanf(buf, "0x%X 0x%X 0x%X", &addr, &mask, &set);
+	if (res != 3)
+		return -EINVAL;
+	if (addr > B43_MAX_MMIO_ACCESS)
+		return -EADDRNOTAVAIL;
+	if ((mask > 0xFFFF) || (set > 0xFFFF))
+		return -E2BIG;
+	if ((addr % 2) != 0)
+		return -EINVAL;
+
+	if (mask == 0)
+		val = 0;
+	else
+		val = b43_read16(dev, addr);
+	val &= mask;
+	val |= set;
+	b43_write16(dev, addr, val);
+
+	return 0;
+}
+
+static ssize_t mmio32read__read_file(struct b43_wldev *dev,
+				     char *buf, size_t bufsize)
+{
+	ssize_t count = 0;
+	unsigned int addr;
+	u32 val;
+
+	addr = dev->dfsentry->mmio32read_next;
+	if (addr > B43_MAX_MMIO_ACCESS)
+		return -EDESTADDRREQ;
+
+	val = b43_read32(dev, addr);
+	fappend("0x%08X\n", val);
+
+	return count;
+}
+
+static int mmio32read__write_file(struct b43_wldev *dev,
+				  const char *buf, size_t count)
+{
+	unsigned int addr;
+	int res;
+
+	res = sscanf(buf, "0x%X", &addr);
+	if (res != 1)
+		return -EINVAL;
+	if (addr > B43_MAX_MMIO_ACCESS)
+		return -EADDRNOTAVAIL;
+	if ((addr % 4) != 0)
+		return -EINVAL;
+
+	dev->dfsentry->mmio32read_next = addr;
+
+	return 0;
+}
+
+static int mmio32write__write_file(struct b43_wldev *dev,
+				   const char *buf, size_t count)
+{
+	unsigned int addr, mask, set;
+	int res;
+	u32 val;
+
+	res = sscanf(buf, "0x%X 0x%X 0x%X", &addr, &mask, &set);
+	if (res != 3)
+		return -EINVAL;
+	if (addr > B43_MAX_MMIO_ACCESS)
+		return -EADDRNOTAVAIL;
+	if ((mask > 0xFFFFFFFF) || (set > 0xFFFFFFFF))
+		return -E2BIG;
+	if ((addr % 4) != 0)
+		return -EINVAL;
+
+	if (mask == 0)
+		val = 0;
+	else
+		val = b43_read32(dev, addr);
+	val &= mask;
+	val |= set;
+	b43_write32(dev, addr, val);
+
+	return 0;
+}
+
+static ssize_t txstat_read_file(struct b43_wldev *dev,
+				char *buf, size_t bufsize)
+{
+	struct b43_txstatus_log *log = &dev->dfsentry->txstatlog;
+	ssize_t count = 0;
+	int i, idx;
+	struct b43_txstatus *stat;
+
+	if (log->end < 0) {
+		fappend("Nothing transmitted, yet\n");
+		goto out;
+	}
+	fappend("b43 TX status reports:\n\n"
+		"index | cookie | seq | phy_stat | frame_count | "
+		"rts_count | supp_reason | pm_indicated | "
+		"intermediate | for_ampdu | acked\n" "---\n");
+	i = log->end + 1;
+	idx = 0;
+	while (1) {
+		if (i == B43_NR_LOGGED_TXSTATUS)
+			i = 0;
+		stat = &(log->log[i]);
+		if (stat->cookie) {
+			fappend("%03d | "
+				"0x%04X | 0x%04X | 0x%02X | "
+				"0x%X | 0x%X | "
+				"%u | %u | "
+				"%u | %u | %u\n",
+				idx,
+				stat->cookie, stat->seq, stat->phy_stat,
+				stat->frame_count, stat->rts_count,
+				stat->supp_reason, stat->pm_indicated,
+				stat->intermediate, stat->for_ampdu,
+				stat->acked);
+			idx++;
+		}
+		if (i == log->end)
+			break;
+		i++;
+	}
+out:
+
+	return count;
+}
+
+static int restart_write_file(struct b43_wldev *dev,
+			      const char *buf, size_t count)
+{
+	int err = 0;
+
+	if (count > 0 && buf[0] == '1') {
+		b43_controller_restart(dev, "manually restarted");
+	} else
+		err = -EINVAL;
+
+	return err;
+}
+
+static unsigned long calc_expire_secs(unsigned long now,
+				      unsigned long time,
+				      unsigned long expire)
+{
+	expire = time + expire;
+
+	if (time_after(now, expire))
+		return 0; /* expired */
+	if (expire < now) {
+		/* jiffies wrapped */
+		expire -= MAX_JIFFY_OFFSET;
+		now -= MAX_JIFFY_OFFSET;
+	}
+	B43_WARN_ON(expire < now);
+
+	return (expire - now) / HZ;
+}
+
+static ssize_t loctls_read_file(struct b43_wldev *dev,
+				char *buf, size_t bufsize)
+{
+	ssize_t count = 0;
+	struct b43_txpower_lo_control *lo;
+	int i, err = 0;
+	struct b43_lo_calib *cal;
+	unsigned long now = jiffies;
+	struct b43_phy *phy = &dev->phy;
+
+	if (phy->type != B43_PHYTYPE_G) {
+		fappend("Device is not a G-PHY\n");
+		err = -ENODEV;
+		goto out;
+	}
+	lo = phy->g->lo_control;
+	fappend("-- Local Oscillator calibration data --\n\n");
+	fappend("HW-power-control enabled: %d\n",
+		dev->phy.hardware_power_control);
+	fappend("TX Bias: 0x%02X,  TX Magn: 0x%02X  (expire in %lu sec)\n",
+		lo->tx_bias, lo->tx_magn,
+		calc_expire_secs(now, lo->txctl_measured_time,
+				 B43_LO_TXCTL_EXPIRE));
+	fappend("Power Vector: 0x%08X%08X  (expires in %lu sec)\n",
+		(unsigned int)((lo->power_vector & 0xFFFFFFFF00000000ULL) >> 32),
+		(unsigned int)(lo->power_vector & 0x00000000FFFFFFFFULL),
+		calc_expire_secs(now, lo->pwr_vec_read_time,
+				 B43_LO_PWRVEC_EXPIRE));
+
+	fappend("\nCalibrated settings:\n");
+	list_for_each_entry(cal, &lo->calib_list, list) {
+		bool active;
+
+		active = (b43_compare_bbatt(&cal->bbatt, &phy->g->bbatt) &&
+			  b43_compare_rfatt(&cal->rfatt, &phy->g->rfatt));
+		fappend("BB(%d), RF(%d,%d)  ->  I=%d, Q=%d  "
+			"(expires in %lu sec)%s\n",
+			cal->bbatt.att,
+			cal->rfatt.att, cal->rfatt.with_padmix,
+			cal->ctl.i, cal->ctl.q,
+			calc_expire_secs(now, cal->calib_time,
+					 B43_LO_CALIB_EXPIRE),
+			active ? "  ACTIVE" : "");
+	}
+
+	fappend("\nUsed RF attenuation values:  Value(WithPadmix flag)\n");
+	for (i = 0; i < lo->rfatt_list.len; i++) {
+		fappend("%u(%d), ",
+			lo->rfatt_list.list[i].att,
+			lo->rfatt_list.list[i].with_padmix);
+	}
+	fappend("\n");
+	fappend("\nUsed Baseband attenuation values:\n");
+	for (i = 0; i < lo->bbatt_list.len; i++) {
+		fappend("%u, ",
+			lo->bbatt_list.list[i].att);
+	}
+	fappend("\n");
+
+out:
+	return err ? err : count;
+}
+
+#undef fappend
+
+static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf,
+				size_t count, loff_t *ppos)
+{
+	struct b43_wldev *dev;
+	struct b43_debugfs_fops *dfops;
+	struct b43_dfs_file *dfile;
+	ssize_t uninitialized_var(ret);
+	char *buf;
+	const size_t bufsize = 1024 * 16; /* 16 kiB buffer */
+	const size_t buforder = get_order(bufsize);
+	int err = 0;
+
+	if (!count)
+		return 0;
+	dev = file->private_data;
+	if (!dev)
+		return -ENODEV;
+
+	mutex_lock(&dev->wl->mutex);
+	if (b43_status(dev) < B43_STAT_INITIALIZED) {
+		err = -ENODEV;
+		goto out_unlock;
+	}
+
+	dfops = container_of(debugfs_real_fops(file),
+			     struct b43_debugfs_fops, fops);
+	if (!dfops->read) {
+		err = -ENOSYS;
+		goto out_unlock;
+	}
+	dfile = fops_to_dfs_file(dev, dfops);
+
+	if (!dfile->buffer) {
+		buf = (char *)__get_free_pages(GFP_KERNEL, buforder);
+		if (!buf) {
+			err = -ENOMEM;
+			goto out_unlock;
+		}
+		memset(buf, 0, bufsize);
+		ret = dfops->read(dev, buf, bufsize);
+		if (ret <= 0) {
+			free_pages((unsigned long)buf, buforder);
+			err = ret;
+			goto out_unlock;
+		}
+		dfile->data_len = ret;
+		dfile->buffer = buf;
+	}
+
+	ret = simple_read_from_buffer(userbuf, count, ppos,
+				      dfile->buffer,
+				      dfile->data_len);
+	if (*ppos >= dfile->data_len) {
+		free_pages((unsigned long)dfile->buffer, buforder);
+		dfile->buffer = NULL;
+		dfile->data_len = 0;
+	}
+out_unlock:
+	mutex_unlock(&dev->wl->mutex);
+
+	return err ? err : ret;
+}
+
+static ssize_t b43_debugfs_write(struct file *file,
+				 const char __user *userbuf,
+				 size_t count, loff_t *ppos)
+{
+	struct b43_wldev *dev;
+	struct b43_debugfs_fops *dfops;
+	char *buf;
+	int err = 0;
+
+	if (!count)
+		return 0;
+	if (count > PAGE_SIZE)
+		return -E2BIG;
+	dev = file->private_data;
+	if (!dev)
+		return -ENODEV;
+
+	mutex_lock(&dev->wl->mutex);
+	if (b43_status(dev) < B43_STAT_INITIALIZED) {
+		err = -ENODEV;
+		goto out_unlock;
+	}
+
+	dfops = container_of(debugfs_real_fops(file),
+			     struct b43_debugfs_fops, fops);
+	if (!dfops->write) {
+		err = -ENOSYS;
+		goto out_unlock;
+	}
+
+	buf = (char *)get_zeroed_page(GFP_KERNEL);
+	if (!buf) {
+		err = -ENOMEM;
+		goto out_unlock;
+	}
+	if (copy_from_user(buf, userbuf, count)) {
+		err = -EFAULT;
+		goto out_freepage;
+	}
+	err = dfops->write(dev, buf, count);
+	if (err)
+		goto out_freepage;
+
+out_freepage:
+	free_page((unsigned long)buf);
+out_unlock:
+	mutex_unlock(&dev->wl->mutex);
+
+	return err ? err : count;
+}
+
+
+#define B43_DEBUGFS_FOPS(name, _read, _write)			\
+	static struct b43_debugfs_fops fops_##name = {		\
+		.read	= _read,				\
+		.write	= _write,				\
+		.fops	= {					\
+			.open	= simple_open,			\
+			.read	= b43_debugfs_read,		\
+			.write	= b43_debugfs_write,		\
+			.llseek = generic_file_llseek,		\
+		},						\
+		.file_struct_offset = offsetof(struct b43_dfsentry, \
+					       file_##name),	\
+	}
+
+B43_DEBUGFS_FOPS(shm16read, shm16read__read_file, shm16read__write_file);
+B43_DEBUGFS_FOPS(shm16write, NULL, shm16write__write_file);
+B43_DEBUGFS_FOPS(shm32read, shm32read__read_file, shm32read__write_file);
+B43_DEBUGFS_FOPS(shm32write, NULL, shm32write__write_file);
+B43_DEBUGFS_FOPS(mmio16read, mmio16read__read_file, mmio16read__write_file);
+B43_DEBUGFS_FOPS(mmio16write, NULL, mmio16write__write_file);
+B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file);
+B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file);
+B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL);
+B43_DEBUGFS_FOPS(restart, NULL, restart_write_file);
+B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL);
+
+
+bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature)
+{
+	bool enabled;
+
+	enabled = (dev->dfsentry && dev->dfsentry->dyn_debug[feature]);
+	if (unlikely(enabled)) {
+		/* Force full debugging messages, if the user enabled
+		 * some dynamic debugging feature. */
+		b43_modparam_verbose = B43_VERBOSITY_MAX;
+	}
+
+	return enabled;
+}
+
+static void b43_remove_dynamic_debug(struct b43_wldev *dev)
+{
+	struct b43_dfsentry *e = dev->dfsentry;
+	int i;
+
+	for (i = 0; i < __B43_NR_DYNDBG; i++)
+		debugfs_remove(e->dyn_debug_dentries[i]);
+}
+
+static void b43_add_dynamic_debug(struct b43_wldev *dev)
+{
+	struct b43_dfsentry *e = dev->dfsentry;
+	struct dentry *d;
+
+#define add_dyn_dbg(name, id, initstate) do {		\
+	e->dyn_debug[id] = (initstate);			\
+	d = debugfs_create_bool(name, 0600, e->subdir,	\
+				&(e->dyn_debug[id]));	\
+	if (!IS_ERR(d))					\
+		e->dyn_debug_dentries[id] = d;		\
+				} while (0)
+
+	add_dyn_dbg("debug_xmitpower", B43_DBG_XMITPOWER, false);
+	add_dyn_dbg("debug_dmaoverflow", B43_DBG_DMAOVERFLOW, false);
+	add_dyn_dbg("debug_dmaverbose", B43_DBG_DMAVERBOSE, false);
+	add_dyn_dbg("debug_pwork_fast", B43_DBG_PWORK_FAST, false);
+	add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, false);
+	add_dyn_dbg("debug_lo", B43_DBG_LO, false);
+	add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, false);
+	add_dyn_dbg("debug_keys", B43_DBG_KEYS, false);
+	add_dyn_dbg("debug_verbose_stats", B43_DBG_VERBOSESTATS, false);
+
+#undef add_dyn_dbg
+}
+
+void b43_debugfs_add_device(struct b43_wldev *dev)
+{
+	struct b43_dfsentry *e;
+	struct b43_txstatus_log *log;
+	char devdir[16];
+
+	B43_WARN_ON(!dev);
+	e = kzalloc(sizeof(*e), GFP_KERNEL);
+	if (!e) {
+		b43err(dev->wl, "debugfs: add device OOM\n");
+		return;
+	}
+	e->dev = dev;
+	log = &e->txstatlog;
+	log->log = kcalloc(B43_NR_LOGGED_TXSTATUS,
+			   sizeof(struct b43_txstatus), GFP_KERNEL);
+	if (!log->log) {
+		b43err(dev->wl, "debugfs: add device txstatus OOM\n");
+		kfree(e);
+		return;
+	}
+	log->end = -1;
+
+	dev->dfsentry = e;
+
+	snprintf(devdir, sizeof(devdir), "%s", wiphy_name(dev->wl->hw->wiphy));
+	e->subdir = debugfs_create_dir(devdir, rootdir);
+	if (!e->subdir || IS_ERR(e->subdir)) {
+		if (e->subdir == ERR_PTR(-ENODEV)) {
+			b43dbg(dev->wl, "DebugFS (CONFIG_DEBUG_FS) not "
+			       "enabled in kernel config\n");
+		} else {
+			b43err(dev->wl, "debugfs: cannot create %s directory\n",
+			       devdir);
+		}
+		dev->dfsentry = NULL;
+		kfree(log->log);
+		kfree(e);
+		return;
+	}
+
+	e->mmio16read_next = 0xFFFF; /* invalid address */
+	e->mmio32read_next = 0xFFFF; /* invalid address */
+	e->shm16read_routing_next = 0xFFFFFFFF; /* invalid routing */
+	e->shm16read_addr_next = 0xFFFFFFFF; /* invalid address */
+	e->shm32read_routing_next = 0xFFFFFFFF; /* invalid routing */
+	e->shm32read_addr_next = 0xFFFFFFFF; /* invalid address */
+
+#define ADD_FILE(name, mode)	\
+	do {							\
+		struct dentry *d;				\
+		d = debugfs_create_file(__stringify(name),	\
+					mode, e->subdir, dev,	\
+					&fops_##name.fops);	\
+		e->file_##name.dentry = NULL;			\
+		if (!IS_ERR(d))					\
+			e->file_##name.dentry = d;		\
+	} while (0)
+
+
+	ADD_FILE(shm16read, 0600);
+	ADD_FILE(shm16write, 0200);
+	ADD_FILE(shm32read, 0600);
+	ADD_FILE(shm32write, 0200);
+	ADD_FILE(mmio16read, 0600);
+	ADD_FILE(mmio16write, 0200);
+	ADD_FILE(mmio32read, 0600);
+	ADD_FILE(mmio32write, 0200);
+	ADD_FILE(txstat, 0400);
+	ADD_FILE(restart, 0200);
+	ADD_FILE(loctls, 0400);
+
+#undef ADD_FILE
+
+	b43_add_dynamic_debug(dev);
+}
+
+void b43_debugfs_remove_device(struct b43_wldev *dev)
+{
+	struct b43_dfsentry *e;
+
+	if (!dev)
+		return;
+	e = dev->dfsentry;
+	if (!e)
+		return;
+	b43_remove_dynamic_debug(dev);
+
+	debugfs_remove(e->file_shm16read.dentry);
+	debugfs_remove(e->file_shm16write.dentry);
+	debugfs_remove(e->file_shm32read.dentry);
+	debugfs_remove(e->file_shm32write.dentry);
+	debugfs_remove(e->file_mmio16read.dentry);
+	debugfs_remove(e->file_mmio16write.dentry);
+	debugfs_remove(e->file_mmio32read.dentry);
+	debugfs_remove(e->file_mmio32write.dentry);
+	debugfs_remove(e->file_txstat.dentry);
+	debugfs_remove(e->file_restart.dentry);
+	debugfs_remove(e->file_loctls.dentry);
+
+	debugfs_remove(e->subdir);
+	kfree(e->txstatlog.log);
+	kfree(e);
+}
+
+void b43_debugfs_log_txstat(struct b43_wldev *dev,
+			    const struct b43_txstatus *status)
+{
+	struct b43_dfsentry *e = dev->dfsentry;
+	struct b43_txstatus_log *log;
+	struct b43_txstatus *cur;
+	int i;
+
+	if (!e)
+		return;
+	log = &e->txstatlog;
+	i = log->end + 1;
+	if (i == B43_NR_LOGGED_TXSTATUS)
+		i = 0;
+	log->end = i;
+	cur = &(log->log[i]);
+	memcpy(cur, status, sizeof(*cur));
+}
+
+void b43_debugfs_init(void)
+{
+	rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
+	if (IS_ERR(rootdir))
+		rootdir = NULL;
+}
+
+void b43_debugfs_exit(void)
+{
+	debugfs_remove(rootdir);
+}
diff --git a/drivers/net/wireless/broadcom/b43/debugfs.h b/drivers/net/wireless/broadcom/b43/debugfs.h
new file mode 100644
index 0000000..0bf437c
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/debugfs.h
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_DEBUGFS_H_
+#define B43_DEBUGFS_H_
+
+struct b43_wldev;
+struct b43_txstatus;
+
+enum b43_dyndbg {		/* Dynamic debugging features */
+	B43_DBG_XMITPOWER,
+	B43_DBG_DMAOVERFLOW,
+	B43_DBG_DMAVERBOSE,
+	B43_DBG_PWORK_FAST,
+	B43_DBG_PWORK_STOP,
+	B43_DBG_LO,
+	B43_DBG_FIRMWARE,
+	B43_DBG_KEYS,
+	B43_DBG_VERBOSESTATS,
+	__B43_NR_DYNDBG,
+};
+
+#ifdef CONFIG_B43_DEBUG
+
+struct dentry;
+
+#define B43_NR_LOGGED_TXSTATUS	100
+
+struct b43_txstatus_log {
+	/* This structure is protected by wl->mutex */
+
+	struct b43_txstatus *log;
+	int end;
+};
+
+struct b43_dfs_file {
+	struct dentry *dentry;
+	char *buffer;
+	size_t data_len;
+};
+
+struct b43_dfsentry {
+	struct b43_wldev *dev;
+	struct dentry *subdir;
+
+	struct b43_dfs_file file_shm16read;
+	struct b43_dfs_file file_shm16write;
+	struct b43_dfs_file file_shm32read;
+	struct b43_dfs_file file_shm32write;
+	struct b43_dfs_file file_mmio16read;
+	struct b43_dfs_file file_mmio16write;
+	struct b43_dfs_file file_mmio32read;
+	struct b43_dfs_file file_mmio32write;
+	struct b43_dfs_file file_txstat;
+	struct b43_dfs_file file_txpower_g;
+	struct b43_dfs_file file_restart;
+	struct b43_dfs_file file_loctls;
+
+	struct b43_txstatus_log txstatlog;
+
+	/* The cached address for the next mmio16read file read */
+	u16 mmio16read_next;
+	/* The cached address for the next mmio32read file read */
+	u16 mmio32read_next;
+
+	/* The cached address for the next shm16read file read */
+	u32 shm16read_routing_next;
+	u32 shm16read_addr_next;
+	/* The cached address for the next shm32read file read */
+	u32 shm32read_routing_next;
+	u32 shm32read_addr_next;
+
+	/* Enabled/Disabled list for the dynamic debugging features. */
+	bool dyn_debug[__B43_NR_DYNDBG];
+	/* Dentries for the dynamic debugging entries. */
+	struct dentry *dyn_debug_dentries[__B43_NR_DYNDBG];
+};
+
+bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature);
+
+void b43_debugfs_init(void);
+void b43_debugfs_exit(void);
+void b43_debugfs_add_device(struct b43_wldev *dev);
+void b43_debugfs_remove_device(struct b43_wldev *dev);
+void b43_debugfs_log_txstat(struct b43_wldev *dev,
+			    const struct b43_txstatus *status);
+
+#else /* CONFIG_B43_DEBUG */
+
+static inline bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature)
+{
+	return false;
+}
+
+static inline void b43_debugfs_init(void)
+{
+}
+static inline void b43_debugfs_exit(void)
+{
+}
+static inline void b43_debugfs_add_device(struct b43_wldev *dev)
+{
+}
+static inline void b43_debugfs_remove_device(struct b43_wldev *dev)
+{
+}
+static inline void b43_debugfs_log_txstat(struct b43_wldev *dev,
+					  const struct b43_txstatus *status)
+{
+}
+
+#endif /* CONFIG_B43_DEBUG */
+
+#endif /* B43_DEBUGFS_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/dma.c b/drivers/net/wireless/broadcom/b43/dma.c
new file mode 100644
index 0000000..d46d57b
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/dma.c
@@ -0,0 +1,1833 @@
+/*
+
+  Broadcom B43 wireless driver
+
+  DMA ringbuffer and descriptor allocation/management
+
+  Copyright (c) 2005, 2006 Michael Buesch <m@bues.ch>
+
+  Some code in this file is derived from the b44.c driver
+  Copyright (C) 2002 David S. Miller
+  Copyright (C) Pekka Pietikainen
+
+  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 "dma.h"
+#include "main.h"
+#include "debugfs.h"
+#include "xmit.h"
+
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/slab.h>
+#include <asm/div64.h>
+
+
+/* Required number of TX DMA slots per TX frame.
+ * This currently is 2, because we put the header and the ieee80211 frame
+ * into separate slots. */
+#define TX_SLOTS_PER_FRAME	2
+
+static u32 b43_dma_address(struct b43_dma *dma, dma_addr_t dmaaddr,
+			   enum b43_addrtype addrtype)
+{
+	u32 uninitialized_var(addr);
+
+	switch (addrtype) {
+	case B43_DMA_ADDR_LOW:
+		addr = lower_32_bits(dmaaddr);
+		if (dma->translation_in_low) {
+			addr &= ~SSB_DMA_TRANSLATION_MASK;
+			addr |= dma->translation;
+		}
+		break;
+	case B43_DMA_ADDR_HIGH:
+		addr = upper_32_bits(dmaaddr);
+		if (!dma->translation_in_low) {
+			addr &= ~SSB_DMA_TRANSLATION_MASK;
+			addr |= dma->translation;
+		}
+		break;
+	case B43_DMA_ADDR_EXT:
+		if (dma->translation_in_low)
+			addr = lower_32_bits(dmaaddr);
+		else
+			addr = upper_32_bits(dmaaddr);
+		addr &= SSB_DMA_TRANSLATION_MASK;
+		addr >>= SSB_DMA_TRANSLATION_SHIFT;
+		break;
+	}
+
+	return addr;
+}
+
+/* 32bit DMA ops. */
+static
+struct b43_dmadesc_generic *op32_idx2desc(struct b43_dmaring *ring,
+					  int slot,
+					  struct b43_dmadesc_meta **meta)
+{
+	struct b43_dmadesc32 *desc;
+
+	*meta = &(ring->meta[slot]);
+	desc = ring->descbase;
+	desc = &(desc[slot]);
+
+	return (struct b43_dmadesc_generic *)desc;
+}
+
+static void op32_fill_descriptor(struct b43_dmaring *ring,
+				 struct b43_dmadesc_generic *desc,
+				 dma_addr_t dmaaddr, u16 bufsize,
+				 int start, int end, int irq)
+{
+	struct b43_dmadesc32 *descbase = ring->descbase;
+	int slot;
+	u32 ctl;
+	u32 addr;
+	u32 addrext;
+
+	slot = (int)(&(desc->dma32) - descbase);
+	B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
+
+	addr = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_LOW);
+	addrext = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_EXT);
+
+	ctl = bufsize & B43_DMA32_DCTL_BYTECNT;
+	if (slot == ring->nr_slots - 1)
+		ctl |= B43_DMA32_DCTL_DTABLEEND;
+	if (start)
+		ctl |= B43_DMA32_DCTL_FRAMESTART;
+	if (end)
+		ctl |= B43_DMA32_DCTL_FRAMEEND;
+	if (irq)
+		ctl |= B43_DMA32_DCTL_IRQ;
+	ctl |= (addrext << B43_DMA32_DCTL_ADDREXT_SHIFT)
+	    & B43_DMA32_DCTL_ADDREXT_MASK;
+
+	desc->dma32.control = cpu_to_le32(ctl);
+	desc->dma32.address = cpu_to_le32(addr);
+}
+
+static void op32_poke_tx(struct b43_dmaring *ring, int slot)
+{
+	b43_dma_write(ring, B43_DMA32_TXINDEX,
+		      (u32) (slot * sizeof(struct b43_dmadesc32)));
+}
+
+static void op32_tx_suspend(struct b43_dmaring *ring)
+{
+	b43_dma_write(ring, B43_DMA32_TXCTL, b43_dma_read(ring, B43_DMA32_TXCTL)
+		      | B43_DMA32_TXSUSPEND);
+}
+
+static void op32_tx_resume(struct b43_dmaring *ring)
+{
+	b43_dma_write(ring, B43_DMA32_TXCTL, b43_dma_read(ring, B43_DMA32_TXCTL)
+		      & ~B43_DMA32_TXSUSPEND);
+}
+
+static int op32_get_current_rxslot(struct b43_dmaring *ring)
+{
+	u32 val;
+
+	val = b43_dma_read(ring, B43_DMA32_RXSTATUS);
+	val &= B43_DMA32_RXDPTR;
+
+	return (val / sizeof(struct b43_dmadesc32));
+}
+
+static void op32_set_current_rxslot(struct b43_dmaring *ring, int slot)
+{
+	b43_dma_write(ring, B43_DMA32_RXINDEX,
+		      (u32) (slot * sizeof(struct b43_dmadesc32)));
+}
+
+static const struct b43_dma_ops dma32_ops = {
+	.idx2desc = op32_idx2desc,
+	.fill_descriptor = op32_fill_descriptor,
+	.poke_tx = op32_poke_tx,
+	.tx_suspend = op32_tx_suspend,
+	.tx_resume = op32_tx_resume,
+	.get_current_rxslot = op32_get_current_rxslot,
+	.set_current_rxslot = op32_set_current_rxslot,
+};
+
+/* 64bit DMA ops. */
+static
+struct b43_dmadesc_generic *op64_idx2desc(struct b43_dmaring *ring,
+					  int slot,
+					  struct b43_dmadesc_meta **meta)
+{
+	struct b43_dmadesc64 *desc;
+
+	*meta = &(ring->meta[slot]);
+	desc = ring->descbase;
+	desc = &(desc[slot]);
+
+	return (struct b43_dmadesc_generic *)desc;
+}
+
+static void op64_fill_descriptor(struct b43_dmaring *ring,
+				 struct b43_dmadesc_generic *desc,
+				 dma_addr_t dmaaddr, u16 bufsize,
+				 int start, int end, int irq)
+{
+	struct b43_dmadesc64 *descbase = ring->descbase;
+	int slot;
+	u32 ctl0 = 0, ctl1 = 0;
+	u32 addrlo, addrhi;
+	u32 addrext;
+
+	slot = (int)(&(desc->dma64) - descbase);
+	B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
+
+	addrlo = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_LOW);
+	addrhi = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_HIGH);
+	addrext = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_EXT);
+
+	if (slot == ring->nr_slots - 1)
+		ctl0 |= B43_DMA64_DCTL0_DTABLEEND;
+	if (start)
+		ctl0 |= B43_DMA64_DCTL0_FRAMESTART;
+	if (end)
+		ctl0 |= B43_DMA64_DCTL0_FRAMEEND;
+	if (irq)
+		ctl0 |= B43_DMA64_DCTL0_IRQ;
+	ctl1 |= bufsize & B43_DMA64_DCTL1_BYTECNT;
+	ctl1 |= (addrext << B43_DMA64_DCTL1_ADDREXT_SHIFT)
+	    & B43_DMA64_DCTL1_ADDREXT_MASK;
+
+	desc->dma64.control0 = cpu_to_le32(ctl0);
+	desc->dma64.control1 = cpu_to_le32(ctl1);
+	desc->dma64.address_low = cpu_to_le32(addrlo);
+	desc->dma64.address_high = cpu_to_le32(addrhi);
+}
+
+static void op64_poke_tx(struct b43_dmaring *ring, int slot)
+{
+	b43_dma_write(ring, B43_DMA64_TXINDEX,
+		      (u32) (slot * sizeof(struct b43_dmadesc64)));
+}
+
+static void op64_tx_suspend(struct b43_dmaring *ring)
+{
+	b43_dma_write(ring, B43_DMA64_TXCTL, b43_dma_read(ring, B43_DMA64_TXCTL)
+		      | B43_DMA64_TXSUSPEND);
+}
+
+static void op64_tx_resume(struct b43_dmaring *ring)
+{
+	b43_dma_write(ring, B43_DMA64_TXCTL, b43_dma_read(ring, B43_DMA64_TXCTL)
+		      & ~B43_DMA64_TXSUSPEND);
+}
+
+static int op64_get_current_rxslot(struct b43_dmaring *ring)
+{
+	u32 val;
+
+	val = b43_dma_read(ring, B43_DMA64_RXSTATUS);
+	val &= B43_DMA64_RXSTATDPTR;
+
+	return (val / sizeof(struct b43_dmadesc64));
+}
+
+static void op64_set_current_rxslot(struct b43_dmaring *ring, int slot)
+{
+	b43_dma_write(ring, B43_DMA64_RXINDEX,
+		      (u32) (slot * sizeof(struct b43_dmadesc64)));
+}
+
+static const struct b43_dma_ops dma64_ops = {
+	.idx2desc = op64_idx2desc,
+	.fill_descriptor = op64_fill_descriptor,
+	.poke_tx = op64_poke_tx,
+	.tx_suspend = op64_tx_suspend,
+	.tx_resume = op64_tx_resume,
+	.get_current_rxslot = op64_get_current_rxslot,
+	.set_current_rxslot = op64_set_current_rxslot,
+};
+
+static inline int free_slots(struct b43_dmaring *ring)
+{
+	return (ring->nr_slots - ring->used_slots);
+}
+
+static inline int next_slot(struct b43_dmaring *ring, int slot)
+{
+	B43_WARN_ON(!(slot >= -1 && slot <= ring->nr_slots - 1));
+	if (slot == ring->nr_slots - 1)
+		return 0;
+	return slot + 1;
+}
+
+static inline int prev_slot(struct b43_dmaring *ring, int slot)
+{
+	B43_WARN_ON(!(slot >= 0 && slot <= ring->nr_slots - 1));
+	if (slot == 0)
+		return ring->nr_slots - 1;
+	return slot - 1;
+}
+
+#ifdef CONFIG_B43_DEBUG
+static void update_max_used_slots(struct b43_dmaring *ring,
+				  int current_used_slots)
+{
+	if (current_used_slots <= ring->max_used_slots)
+		return;
+	ring->max_used_slots = current_used_slots;
+	if (b43_debug(ring->dev, B43_DBG_DMAVERBOSE)) {
+		b43dbg(ring->dev->wl,
+		       "max_used_slots increased to %d on %s ring %d\n",
+		       ring->max_used_slots,
+		       ring->tx ? "TX" : "RX", ring->index);
+	}
+}
+#else
+static inline
+    void update_max_used_slots(struct b43_dmaring *ring, int current_used_slots)
+{
+}
+#endif /* DEBUG */
+
+/* Request a slot for usage. */
+static inline int request_slot(struct b43_dmaring *ring)
+{
+	int slot;
+
+	B43_WARN_ON(!ring->tx);
+	B43_WARN_ON(ring->stopped);
+	B43_WARN_ON(free_slots(ring) == 0);
+
+	slot = next_slot(ring, ring->current_slot);
+	ring->current_slot = slot;
+	ring->used_slots++;
+
+	update_max_used_slots(ring, ring->used_slots);
+
+	return slot;
+}
+
+static u16 b43_dmacontroller_base(enum b43_dmatype type, int controller_idx)
+{
+	static const u16 map64[] = {
+		B43_MMIO_DMA64_BASE0,
+		B43_MMIO_DMA64_BASE1,
+		B43_MMIO_DMA64_BASE2,
+		B43_MMIO_DMA64_BASE3,
+		B43_MMIO_DMA64_BASE4,
+		B43_MMIO_DMA64_BASE5,
+	};
+	static const u16 map32[] = {
+		B43_MMIO_DMA32_BASE0,
+		B43_MMIO_DMA32_BASE1,
+		B43_MMIO_DMA32_BASE2,
+		B43_MMIO_DMA32_BASE3,
+		B43_MMIO_DMA32_BASE4,
+		B43_MMIO_DMA32_BASE5,
+	};
+
+	if (type == B43_DMA_64BIT) {
+		B43_WARN_ON(!(controller_idx >= 0 &&
+			      controller_idx < ARRAY_SIZE(map64)));
+		return map64[controller_idx];
+	}
+	B43_WARN_ON(!(controller_idx >= 0 &&
+		      controller_idx < ARRAY_SIZE(map32)));
+	return map32[controller_idx];
+}
+
+static inline
+    dma_addr_t map_descbuffer(struct b43_dmaring *ring,
+			      unsigned char *buf, size_t len, int tx)
+{
+	dma_addr_t dmaaddr;
+
+	if (tx) {
+		dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
+					 buf, len, DMA_TO_DEVICE);
+	} else {
+		dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
+					 buf, len, DMA_FROM_DEVICE);
+	}
+
+	return dmaaddr;
+}
+
+static inline
+    void unmap_descbuffer(struct b43_dmaring *ring,
+			  dma_addr_t addr, size_t len, int tx)
+{
+	if (tx) {
+		dma_unmap_single(ring->dev->dev->dma_dev,
+				 addr, len, DMA_TO_DEVICE);
+	} else {
+		dma_unmap_single(ring->dev->dev->dma_dev,
+				 addr, len, DMA_FROM_DEVICE);
+	}
+}
+
+static inline
+    void sync_descbuffer_for_cpu(struct b43_dmaring *ring,
+				 dma_addr_t addr, size_t len)
+{
+	B43_WARN_ON(ring->tx);
+	dma_sync_single_for_cpu(ring->dev->dev->dma_dev,
+				    addr, len, DMA_FROM_DEVICE);
+}
+
+static inline
+    void sync_descbuffer_for_device(struct b43_dmaring *ring,
+				    dma_addr_t addr, size_t len)
+{
+	B43_WARN_ON(ring->tx);
+	dma_sync_single_for_device(ring->dev->dev->dma_dev,
+				   addr, len, DMA_FROM_DEVICE);
+}
+
+static inline
+    void free_descriptor_buffer(struct b43_dmaring *ring,
+				struct b43_dmadesc_meta *meta)
+{
+	if (meta->skb) {
+		if (ring->tx)
+			ieee80211_free_txskb(ring->dev->wl->hw, meta->skb);
+		else
+			dev_kfree_skb_any(meta->skb);
+		meta->skb = NULL;
+	}
+}
+
+static int alloc_ringmemory(struct b43_dmaring *ring)
+{
+	/* The specs call for 4K buffers for 30- and 32-bit DMA with 4K
+	 * alignment and 8K buffers for 64-bit DMA with 8K alignment.
+	 * In practice we could use smaller buffers for the latter, but the
+	 * alignment is really important because of the hardware bug. If bit
+	 * 0x00001000 is used in DMA address, some hardware (like BCM4331)
+	 * copies that bit into B43_DMA64_RXSTATUS and we get false values from
+	 * B43_DMA64_RXSTATDPTR. Let's just use 8K buffers even if we don't use
+	 * more than 256 slots for ring.
+	 */
+	u16 ring_mem_size = (ring->type == B43_DMA_64BIT) ?
+				B43_DMA64_RINGMEMSIZE : B43_DMA32_RINGMEMSIZE;
+
+	ring->descbase = dma_zalloc_coherent(ring->dev->dev->dma_dev,
+					     ring_mem_size, &(ring->dmabase),
+					     GFP_KERNEL);
+	if (!ring->descbase)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void free_ringmemory(struct b43_dmaring *ring)
+{
+	u16 ring_mem_size = (ring->type == B43_DMA_64BIT) ?
+				B43_DMA64_RINGMEMSIZE : B43_DMA32_RINGMEMSIZE;
+	dma_free_coherent(ring->dev->dev->dma_dev, ring_mem_size,
+			  ring->descbase, ring->dmabase);
+}
+
+/* Reset the RX DMA channel */
+static int b43_dmacontroller_rx_reset(struct b43_wldev *dev, u16 mmio_base,
+				      enum b43_dmatype type)
+{
+	int i;
+	u32 value;
+	u16 offset;
+
+	might_sleep();
+
+	offset = (type == B43_DMA_64BIT) ? B43_DMA64_RXCTL : B43_DMA32_RXCTL;
+	b43_write32(dev, mmio_base + offset, 0);
+	for (i = 0; i < 10; i++) {
+		offset = (type == B43_DMA_64BIT) ? B43_DMA64_RXSTATUS :
+						   B43_DMA32_RXSTATUS;
+		value = b43_read32(dev, mmio_base + offset);
+		if (type == B43_DMA_64BIT) {
+			value &= B43_DMA64_RXSTAT;
+			if (value == B43_DMA64_RXSTAT_DISABLED) {
+				i = -1;
+				break;
+			}
+		} else {
+			value &= B43_DMA32_RXSTATE;
+			if (value == B43_DMA32_RXSTAT_DISABLED) {
+				i = -1;
+				break;
+			}
+		}
+		msleep(1);
+	}
+	if (i != -1) {
+		b43err(dev->wl, "DMA RX reset timed out\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+/* Reset the TX DMA channel */
+static int b43_dmacontroller_tx_reset(struct b43_wldev *dev, u16 mmio_base,
+				      enum b43_dmatype type)
+{
+	int i;
+	u32 value;
+	u16 offset;
+
+	might_sleep();
+
+	for (i = 0; i < 10; i++) {
+		offset = (type == B43_DMA_64BIT) ? B43_DMA64_TXSTATUS :
+						   B43_DMA32_TXSTATUS;
+		value = b43_read32(dev, mmio_base + offset);
+		if (type == B43_DMA_64BIT) {
+			value &= B43_DMA64_TXSTAT;
+			if (value == B43_DMA64_TXSTAT_DISABLED ||
+			    value == B43_DMA64_TXSTAT_IDLEWAIT ||
+			    value == B43_DMA64_TXSTAT_STOPPED)
+				break;
+		} else {
+			value &= B43_DMA32_TXSTATE;
+			if (value == B43_DMA32_TXSTAT_DISABLED ||
+			    value == B43_DMA32_TXSTAT_IDLEWAIT ||
+			    value == B43_DMA32_TXSTAT_STOPPED)
+				break;
+		}
+		msleep(1);
+	}
+	offset = (type == B43_DMA_64BIT) ? B43_DMA64_TXCTL : B43_DMA32_TXCTL;
+	b43_write32(dev, mmio_base + offset, 0);
+	for (i = 0; i < 10; i++) {
+		offset = (type == B43_DMA_64BIT) ? B43_DMA64_TXSTATUS :
+						   B43_DMA32_TXSTATUS;
+		value = b43_read32(dev, mmio_base + offset);
+		if (type == B43_DMA_64BIT) {
+			value &= B43_DMA64_TXSTAT;
+			if (value == B43_DMA64_TXSTAT_DISABLED) {
+				i = -1;
+				break;
+			}
+		} else {
+			value &= B43_DMA32_TXSTATE;
+			if (value == B43_DMA32_TXSTAT_DISABLED) {
+				i = -1;
+				break;
+			}
+		}
+		msleep(1);
+	}
+	if (i != -1) {
+		b43err(dev->wl, "DMA TX reset timed out\n");
+		return -ENODEV;
+	}
+	/* ensure the reset is completed. */
+	msleep(1);
+
+	return 0;
+}
+
+/* Check if a DMA mapping address is invalid. */
+static bool b43_dma_mapping_error(struct b43_dmaring *ring,
+				  dma_addr_t addr,
+				  size_t buffersize, bool dma_to_device)
+{
+	if (unlikely(dma_mapping_error(ring->dev->dev->dma_dev, addr)))
+		return true;
+
+	switch (ring->type) {
+	case B43_DMA_30BIT:
+		if ((u64)addr + buffersize > (1ULL << 30))
+			goto address_error;
+		break;
+	case B43_DMA_32BIT:
+		if ((u64)addr + buffersize > (1ULL << 32))
+			goto address_error;
+		break;
+	case B43_DMA_64BIT:
+		/* Currently we can't have addresses beyond
+		 * 64bit in the kernel. */
+		break;
+	}
+
+	/* The address is OK. */
+	return false;
+
+address_error:
+	/* We can't support this address. Unmap it again. */
+	unmap_descbuffer(ring, addr, buffersize, dma_to_device);
+
+	return true;
+}
+
+static bool b43_rx_buffer_is_poisoned(struct b43_dmaring *ring, struct sk_buff *skb)
+{
+	unsigned char *f = skb->data + ring->frameoffset;
+
+	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7]) == 0xFF);
+}
+
+static void b43_poison_rx_buffer(struct b43_dmaring *ring, struct sk_buff *skb)
+{
+	struct b43_rxhdr_fw4 *rxhdr;
+	unsigned char *frame;
+
+	/* This poisons the RX buffer to detect DMA failures. */
+
+	rxhdr = (struct b43_rxhdr_fw4 *)(skb->data);
+	rxhdr->frame_len = 0;
+
+	B43_WARN_ON(ring->rx_buffersize < ring->frameoffset + sizeof(struct b43_plcp_hdr6) + 2);
+	frame = skb->data + ring->frameoffset;
+	memset(frame, 0xFF, sizeof(struct b43_plcp_hdr6) + 2 /* padding */);
+}
+
+static int setup_rx_descbuffer(struct b43_dmaring *ring,
+			       struct b43_dmadesc_generic *desc,
+			       struct b43_dmadesc_meta *meta, gfp_t gfp_flags)
+{
+	dma_addr_t dmaaddr;
+	struct sk_buff *skb;
+
+	B43_WARN_ON(ring->tx);
+
+	skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags);
+	if (unlikely(!skb))
+		return -ENOMEM;
+	b43_poison_rx_buffer(ring, skb);
+	dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0);
+	if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) {
+		/* ugh. try to realloc in zone_dma */
+		gfp_flags |= GFP_DMA;
+
+		dev_kfree_skb_any(skb);
+
+		skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags);
+		if (unlikely(!skb))
+			return -ENOMEM;
+		b43_poison_rx_buffer(ring, skb);
+		dmaaddr = map_descbuffer(ring, skb->data,
+					 ring->rx_buffersize, 0);
+		if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) {
+			b43err(ring->dev->wl, "RX DMA buffer allocation failed\n");
+			dev_kfree_skb_any(skb);
+			return -EIO;
+		}
+	}
+
+	meta->skb = skb;
+	meta->dmaaddr = dmaaddr;
+	ring->ops->fill_descriptor(ring, desc, dmaaddr,
+				   ring->rx_buffersize, 0, 0, 0);
+
+	return 0;
+}
+
+/* Allocate the initial descbuffers.
+ * This is used for an RX ring only.
+ */
+static int alloc_initial_descbuffers(struct b43_dmaring *ring)
+{
+	int i, err = -ENOMEM;
+	struct b43_dmadesc_generic *desc;
+	struct b43_dmadesc_meta *meta;
+
+	for (i = 0; i < ring->nr_slots; i++) {
+		desc = ring->ops->idx2desc(ring, i, &meta);
+
+		err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL);
+		if (err) {
+			b43err(ring->dev->wl,
+			       "Failed to allocate initial descbuffers\n");
+			goto err_unwind;
+		}
+	}
+	mb();
+	ring->used_slots = ring->nr_slots;
+	err = 0;
+      out:
+	return err;
+
+      err_unwind:
+	for (i--; i >= 0; i--) {
+		desc = ring->ops->idx2desc(ring, i, &meta);
+
+		unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0);
+		dev_kfree_skb(meta->skb);
+	}
+	goto out;
+}
+
+/* Do initial setup of the DMA controller.
+ * Reset the controller, write the ring busaddress
+ * and switch the "enable" bit on.
+ */
+static int dmacontroller_setup(struct b43_dmaring *ring)
+{
+	int err = 0;
+	u32 value;
+	u32 addrext;
+	bool parity = ring->dev->dma.parity;
+	u32 addrlo;
+	u32 addrhi;
+
+	if (ring->tx) {
+		if (ring->type == B43_DMA_64BIT) {
+			u64 ringbase = (u64) (ring->dmabase);
+			addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT);
+			addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW);
+			addrhi = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_HIGH);
+
+			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, addrlo);
+			b43_dma_write(ring, B43_DMA64_TXRINGHI, addrhi);
+		} else {
+			u32 ringbase = (u32) (ring->dmabase);
+			addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT);
+			addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW);
+
+			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, addrlo);
+		}
+	} else {
+		err = alloc_initial_descbuffers(ring);
+		if (err)
+			goto out;
+		if (ring->type == B43_DMA_64BIT) {
+			u64 ringbase = (u64) (ring->dmabase);
+			addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT);
+			addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW);
+			addrhi = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_HIGH);
+
+			value = (ring->frameoffset << B43_DMA64_RXFROFF_SHIFT);
+			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, addrlo);
+			b43_dma_write(ring, B43_DMA64_RXRINGHI, addrhi);
+			b43_dma_write(ring, B43_DMA64_RXINDEX, ring->nr_slots *
+				      sizeof(struct b43_dmadesc64));
+		} else {
+			u32 ringbase = (u32) (ring->dmabase);
+			addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT);
+			addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW);
+
+			value = (ring->frameoffset << B43_DMA32_RXFROFF_SHIFT);
+			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, addrlo);
+			b43_dma_write(ring, B43_DMA32_RXINDEX, ring->nr_slots *
+				      sizeof(struct b43_dmadesc32));
+		}
+	}
+
+out:
+	return err;
+}
+
+/* Shutdown the DMA controller. */
+static void dmacontroller_cleanup(struct b43_dmaring *ring)
+{
+	if (ring->tx) {
+		b43_dmacontroller_tx_reset(ring->dev, ring->mmio_base,
+					   ring->type);
+		if (ring->type == B43_DMA_64BIT) {
+			b43_dma_write(ring, B43_DMA64_TXRINGLO, 0);
+			b43_dma_write(ring, B43_DMA64_TXRINGHI, 0);
+		} else
+			b43_dma_write(ring, B43_DMA32_TXRING, 0);
+	} else {
+		b43_dmacontroller_rx_reset(ring->dev, ring->mmio_base,
+					   ring->type);
+		if (ring->type == B43_DMA_64BIT) {
+			b43_dma_write(ring, B43_DMA64_RXRINGLO, 0);
+			b43_dma_write(ring, B43_DMA64_RXRINGHI, 0);
+		} else
+			b43_dma_write(ring, B43_DMA32_RXRING, 0);
+	}
+}
+
+static void free_all_descbuffers(struct b43_dmaring *ring)
+{
+	struct b43_dmadesc_meta *meta;
+	int i;
+
+	if (!ring->used_slots)
+		return;
+	for (i = 0; i < ring->nr_slots; i++) {
+		/* get meta - ignore returned value */
+		ring->ops->idx2desc(ring, i, &meta);
+
+		if (!meta->skb || b43_dma_ptr_is_poisoned(meta->skb)) {
+			B43_WARN_ON(!ring->tx);
+			continue;
+		}
+		if (ring->tx) {
+			unmap_descbuffer(ring, meta->dmaaddr,
+					 meta->skb->len, 1);
+		} else {
+			unmap_descbuffer(ring, meta->dmaaddr,
+					 ring->rx_buffersize, 0);
+		}
+		free_descriptor_buffer(ring, meta);
+	}
+}
+
+static u64 supported_dma_mask(struct b43_wldev *dev)
+{
+	u32 tmp;
+	u16 mmio_base;
+
+	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);
+	if (tmp & B43_DMA32_TXADDREXT_MASK)
+		return DMA_BIT_MASK(32);
+
+	return DMA_BIT_MASK(30);
+}
+
+static enum b43_dmatype dma_mask_to_engine_type(u64 dmamask)
+{
+	if (dmamask == DMA_BIT_MASK(30))
+		return B43_DMA_30BIT;
+	if (dmamask == DMA_BIT_MASK(32))
+		return B43_DMA_32BIT;
+	if (dmamask == DMA_BIT_MASK(64))
+		return B43_DMA_64BIT;
+	B43_WARN_ON(1);
+	return B43_DMA_30BIT;
+}
+
+/* Main initialization function. */
+static
+struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
+				      int controller_index,
+				      int for_tx,
+				      enum b43_dmatype type)
+{
+	struct b43_dmaring *ring;
+	int i, err;
+	dma_addr_t dma_test;
+
+	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
+	if (!ring)
+		goto out;
+
+	ring->nr_slots = B43_RXRING_SLOTS;
+	if (for_tx)
+		ring->nr_slots = B43_TXRING_SLOTS;
+
+	ring->meta = kcalloc(ring->nr_slots, sizeof(struct b43_dmadesc_meta),
+			     GFP_KERNEL);
+	if (!ring->meta)
+		goto err_kfree_ring;
+	for (i = 0; i < ring->nr_slots; i++)
+		ring->meta->skb = B43_DMA_PTR_POISON;
+
+	ring->type = type;
+	ring->dev = dev;
+	ring->mmio_base = b43_dmacontroller_base(type, controller_index);
+	ring->index = controller_index;
+	if (type == B43_DMA_64BIT)
+		ring->ops = &dma64_ops;
+	else
+		ring->ops = &dma32_ops;
+	if (for_tx) {
+		ring->tx = true;
+		ring->current_slot = -1;
+	} else {
+		if (ring->index == 0) {
+			switch (dev->fw.hdr_format) {
+			case B43_FW_HDR_598:
+				ring->rx_buffersize = B43_DMA0_RX_FW598_BUFSIZE;
+				ring->frameoffset = B43_DMA0_RX_FW598_FO;
+				break;
+			case B43_FW_HDR_410:
+			case B43_FW_HDR_351:
+				ring->rx_buffersize = B43_DMA0_RX_FW351_BUFSIZE;
+				ring->frameoffset = B43_DMA0_RX_FW351_FO;
+				break;
+			}
+		} else
+			B43_WARN_ON(1);
+	}
+#ifdef CONFIG_B43_DEBUG
+	ring->last_injected_overflow = jiffies;
+#endif
+
+	if (for_tx) {
+		/* Assumption: B43_TXRING_SLOTS can be divided by TX_SLOTS_PER_FRAME */
+		BUILD_BUG_ON(B43_TXRING_SLOTS % TX_SLOTS_PER_FRAME != 0);
+
+		ring->txhdr_cache = kcalloc(ring->nr_slots / TX_SLOTS_PER_FRAME,
+					    b43_txhdr_size(dev),
+					    GFP_KERNEL);
+		if (!ring->txhdr_cache)
+			goto err_kfree_meta;
+
+		/* test for ability to dma to txhdr_cache */
+		dma_test = dma_map_single(dev->dev->dma_dev,
+					  ring->txhdr_cache,
+					  b43_txhdr_size(dev),
+					  DMA_TO_DEVICE);
+
+		if (b43_dma_mapping_error(ring, dma_test,
+					  b43_txhdr_size(dev), 1)) {
+			/* ugh realloc */
+			kfree(ring->txhdr_cache);
+			ring->txhdr_cache = kcalloc(ring->nr_slots / TX_SLOTS_PER_FRAME,
+						    b43_txhdr_size(dev),
+						    GFP_KERNEL | GFP_DMA);
+			if (!ring->txhdr_cache)
+				goto err_kfree_meta;
+
+			dma_test = dma_map_single(dev->dev->dma_dev,
+						  ring->txhdr_cache,
+						  b43_txhdr_size(dev),
+						  DMA_TO_DEVICE);
+
+			if (b43_dma_mapping_error(ring, dma_test,
+						  b43_txhdr_size(dev), 1)) {
+
+				b43err(dev->wl,
+				       "TXHDR DMA allocation failed\n");
+				goto err_kfree_txhdr_cache;
+			}
+		}
+
+		dma_unmap_single(dev->dev->dma_dev,
+				 dma_test, b43_txhdr_size(dev),
+				 DMA_TO_DEVICE);
+	}
+
+	err = alloc_ringmemory(ring);
+	if (err)
+		goto err_kfree_txhdr_cache;
+	err = dmacontroller_setup(ring);
+	if (err)
+		goto err_free_ringmemory;
+
+      out:
+	return ring;
+
+      err_free_ringmemory:
+	free_ringmemory(ring);
+      err_kfree_txhdr_cache:
+	kfree(ring->txhdr_cache);
+      err_kfree_meta:
+	kfree(ring->meta);
+      err_kfree_ring:
+	kfree(ring);
+	ring = NULL;
+	goto out;
+}
+
+#define divide(a, b)	({	\
+	typeof(a) __a = a;	\
+	do_div(__a, b);		\
+	__a;			\
+  })
+
+#define modulo(a, b)	({	\
+	typeof(a) __a = a;	\
+	do_div(__a, b);		\
+  })
+
+/* Main cleanup function. */
+static void b43_destroy_dmaring(struct b43_dmaring *ring,
+				const char *ringname)
+{
+	if (!ring)
+		return;
+
+#ifdef CONFIG_B43_DEBUG
+	{
+		/* Print some statistics. */
+		u64 failed_packets = ring->nr_failed_tx_packets;
+		u64 succeed_packets = ring->nr_succeed_tx_packets;
+		u64 nr_packets = failed_packets + succeed_packets;
+		u64 permille_failed = 0, average_tries = 0;
+
+		if (nr_packets)
+			permille_failed = divide(failed_packets * 1000, nr_packets);
+		if (nr_packets)
+			average_tries = divide(ring->nr_total_packet_tries * 100, nr_packets);
+
+		b43dbg(ring->dev->wl, "DMA-%u %s: "
+		       "Used slots %d/%d, Failed frames %llu/%llu = %llu.%01llu%%, "
+		       "Average tries %llu.%02llu\n",
+		       (unsigned int)(ring->type), ringname,
+		       ring->max_used_slots,
+		       ring->nr_slots,
+		       (unsigned long long)failed_packets,
+		       (unsigned long long)nr_packets,
+		       (unsigned long long)divide(permille_failed, 10),
+		       (unsigned long long)modulo(permille_failed, 10),
+		       (unsigned long long)divide(average_tries, 100),
+		       (unsigned long long)modulo(average_tries, 100));
+	}
+#endif /* DEBUG */
+
+	/* Device IRQs are disabled prior entering this function,
+	 * so no need to take care of concurrency with rx handler stuff.
+	 */
+	dmacontroller_cleanup(ring);
+	free_all_descbuffers(ring);
+	free_ringmemory(ring);
+
+	kfree(ring->txhdr_cache);
+	kfree(ring->meta);
+	kfree(ring);
+}
+
+#define destroy_ring(dma, ring) do {				\
+	b43_destroy_dmaring((dma)->ring, __stringify(ring));	\
+	(dma)->ring = NULL;					\
+    } while (0)
+
+void b43_dma_free(struct b43_wldev *dev)
+{
+	struct b43_dma *dma;
+
+	if (b43_using_pio_transfers(dev))
+		return;
+	dma = &dev->dma;
+
+	destroy_ring(dma, rx_ring);
+	destroy_ring(dma, tx_ring_AC_BK);
+	destroy_ring(dma, tx_ring_AC_BE);
+	destroy_ring(dma, tx_ring_AC_VI);
+	destroy_ring(dma, tx_ring_AC_VO);
+	destroy_ring(dma, tx_ring_mcast);
+}
+
+static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask)
+{
+	u64 orig_mask = mask;
+	bool fallback = false;
+	int err;
+
+	/* Try to set the DMA mask. If it fails, try falling back to a
+	 * lower mask, as we can always also support a lower one. */
+	while (1) {
+		err = dma_set_mask_and_coherent(dev->dev->dma_dev, mask);
+		if (!err)
+			break;
+		if (mask == DMA_BIT_MASK(64)) {
+			mask = DMA_BIT_MASK(32);
+			fallback = true;
+			continue;
+		}
+		if (mask == DMA_BIT_MASK(32)) {
+			mask = DMA_BIT_MASK(30);
+			fallback = true;
+			continue;
+		}
+		b43err(dev->wl, "The machine/kernel does not support "
+		       "the required %u-bit DMA mask\n",
+		       (unsigned int)dma_mask_to_engine_type(orig_mask));
+		return -EOPNOTSUPP;
+	}
+	if (fallback) {
+		b43info(dev->wl, "DMA mask fallback from %u-bit to %u-bit\n",
+			(unsigned int)dma_mask_to_engine_type(orig_mask),
+			(unsigned int)dma_mask_to_engine_type(mask));
+	}
+
+	return 0;
+}
+
+/* Some hardware with 64-bit DMA seems to be bugged and looks for translation
+ * bit in low address word instead of high one.
+ */
+static bool b43_dma_translation_in_low_word(struct b43_wldev *dev,
+					    enum b43_dmatype type)
+{
+	if (type != B43_DMA_64BIT)
+		return true;
+
+#ifdef CONFIG_B43_SSB
+	if (dev->dev->bus_type == B43_BUS_SSB &&
+	    dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
+	    !(pci_is_pcie(dev->dev->sdev->bus->host_pci) &&
+	      ssb_read32(dev->dev->sdev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64))
+			return true;
+#endif
+	return false;
+}
+
+int b43_dma_init(struct b43_wldev *dev)
+{
+	struct b43_dma *dma = &dev->dma;
+	int err;
+	u64 dmamask;
+	enum b43_dmatype type;
+
+	dmamask = supported_dma_mask(dev);
+	type = dma_mask_to_engine_type(dmamask);
+	err = b43_dma_set_mask(dev, dmamask);
+	if (err)
+		return err;
+
+	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->translation_in_low = b43_dma_translation_in_low_word(dev, type);
+
+	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. */
+	dma->tx_ring_AC_BK = b43_setup_dmaring(dev, 0, 1, type);
+	if (!dma->tx_ring_AC_BK)
+		goto out;
+
+	dma->tx_ring_AC_BE = b43_setup_dmaring(dev, 1, 1, type);
+	if (!dma->tx_ring_AC_BE)
+		goto err_destroy_bk;
+
+	dma->tx_ring_AC_VI = b43_setup_dmaring(dev, 2, 1, type);
+	if (!dma->tx_ring_AC_VI)
+		goto err_destroy_be;
+
+	dma->tx_ring_AC_VO = b43_setup_dmaring(dev, 3, 1, type);
+	if (!dma->tx_ring_AC_VO)
+		goto err_destroy_vi;
+
+	dma->tx_ring_mcast = b43_setup_dmaring(dev, 4, 1, type);
+	if (!dma->tx_ring_mcast)
+		goto err_destroy_vo;
+
+	/* setup RX DMA channel. */
+	dma->rx_ring = b43_setup_dmaring(dev, 0, 0, type);
+	if (!dma->rx_ring)
+		goto err_destroy_mcast;
+
+	/* No support for the TX status DMA ring. */
+	B43_WARN_ON(dev->dev->core_rev < 5);
+
+	b43dbg(dev->wl, "%u-bit DMA initialized\n",
+	       (unsigned int)type);
+	err = 0;
+out:
+	return err;
+
+err_destroy_mcast:
+	destroy_ring(dma, tx_ring_mcast);
+err_destroy_vo:
+	destroy_ring(dma, tx_ring_AC_VO);
+err_destroy_vi:
+	destroy_ring(dma, tx_ring_AC_VI);
+err_destroy_be:
+	destroy_ring(dma, tx_ring_AC_BE);
+err_destroy_bk:
+	destroy_ring(dma, tx_ring_AC_BK);
+	return err;
+}
+
+/* Generate a cookie for the TX header. */
+static u16 generate_cookie(struct b43_dmaring *ring, int slot)
+{
+	u16 cookie;
+
+	/* Use the upper 4 bits of the cookie as
+	 * DMA controller ID and store the slot number
+	 * in the lower 12 bits.
+	 * Note that the cookie must never be 0, as this
+	 * is a special value used in RX path.
+	 * It can also not be 0xFFFF because that is special
+	 * for multicast frames.
+	 */
+	cookie = (((u16)ring->index + 1) << 12);
+	B43_WARN_ON(slot & ~0x0FFF);
+	cookie |= (u16)slot;
+
+	return cookie;
+}
+
+/* Inspect a cookie and find out to which controller/slot it belongs. */
+static
+struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot)
+{
+	struct b43_dma *dma = &dev->dma;
+	struct b43_dmaring *ring = NULL;
+
+	switch (cookie & 0xF000) {
+	case 0x1000:
+		ring = dma->tx_ring_AC_BK;
+		break;
+	case 0x2000:
+		ring = dma->tx_ring_AC_BE;
+		break;
+	case 0x3000:
+		ring = dma->tx_ring_AC_VI;
+		break;
+	case 0x4000:
+		ring = dma->tx_ring_AC_VO;
+		break;
+	case 0x5000:
+		ring = dma->tx_ring_mcast;
+		break;
+	}
+	*slot = (cookie & 0x0FFF);
+	if (unlikely(!ring || *slot < 0 || *slot >= ring->nr_slots)) {
+		b43dbg(dev->wl, "TX-status contains "
+		       "invalid cookie: 0x%04X\n", cookie);
+		return NULL;
+	}
+
+	return ring;
+}
+
+static int dma_tx_fragment(struct b43_dmaring *ring,
+			   struct sk_buff *skb)
+{
+	const struct b43_dma_ops *ops = ring->ops;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct b43_private_tx_info *priv_info = b43_get_priv_tx_info(info);
+	u8 *header;
+	int slot, old_top_slot, old_used_slots;
+	int err;
+	struct b43_dmadesc_generic *desc;
+	struct b43_dmadesc_meta *meta;
+	struct b43_dmadesc_meta *meta_hdr;
+	u16 cookie;
+	size_t hdrsize = b43_txhdr_size(ring->dev);
+
+	/* Important note: If the number of used DMA slots per TX frame
+	 * is changed here, the TX_SLOTS_PER_FRAME definition at the top of
+	 * the file has to be updated, too!
+	 */
+
+	old_top_slot = ring->current_slot;
+	old_used_slots = ring->used_slots;
+
+	/* Get a slot for the header. */
+	slot = request_slot(ring);
+	desc = ops->idx2desc(ring, slot, &meta_hdr);
+	memset(meta_hdr, 0, sizeof(*meta_hdr));
+
+	header = &(ring->txhdr_cache[(slot / TX_SLOTS_PER_FRAME) * hdrsize]);
+	cookie = generate_cookie(ring, slot);
+	err = b43_generate_txhdr(ring->dev, header,
+				 skb, info, cookie);
+	if (unlikely(err)) {
+		ring->current_slot = old_top_slot;
+		ring->used_slots = old_used_slots;
+		return err;
+	}
+
+	meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header,
+					   hdrsize, 1);
+	if (b43_dma_mapping_error(ring, meta_hdr->dmaaddr, hdrsize, 1)) {
+		ring->current_slot = old_top_slot;
+		ring->used_slots = old_used_slots;
+		return -EIO;
+	}
+	ops->fill_descriptor(ring, desc, meta_hdr->dmaaddr,
+			     hdrsize, 1, 0, 0);
+
+	/* Get a slot for the payload. */
+	slot = request_slot(ring);
+	desc = ops->idx2desc(ring, slot, &meta);
+	memset(meta, 0, sizeof(*meta));
+
+	meta->skb = skb;
+	meta->is_last_fragment = true;
+	priv_info->bouncebuffer = NULL;
+
+	meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
+	/* create a bounce buffer in zone_dma on mapping failure. */
+	if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
+		priv_info->bouncebuffer = kmemdup(skb->data, skb->len,
+						  GFP_ATOMIC | GFP_DMA);
+		if (!priv_info->bouncebuffer) {
+			ring->current_slot = old_top_slot;
+			ring->used_slots = old_used_slots;
+			err = -ENOMEM;
+			goto out_unmap_hdr;
+		}
+
+		meta->dmaaddr = map_descbuffer(ring, priv_info->bouncebuffer, skb->len, 1);
+		if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
+			kfree(priv_info->bouncebuffer);
+			priv_info->bouncebuffer = NULL;
+			ring->current_slot = old_top_slot;
+			ring->used_slots = old_used_slots;
+			err = -EIO;
+			goto out_unmap_hdr;
+		}
+	}
+
+	ops->fill_descriptor(ring, desc, meta->dmaaddr, skb->len, 0, 1, 1);
+
+	if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
+		/* Tell the firmware about the cookie of the last
+		 * mcast frame, so it can clear the more-data bit in it. */
+		b43_shm_write16(ring->dev, B43_SHM_SHARED,
+				B43_SHM_SH_MCASTCOOKIE, cookie);
+	}
+	/* Now transfer the whole frame. */
+	wmb();
+	ops->poke_tx(ring, next_slot(ring, slot));
+	return 0;
+
+out_unmap_hdr:
+	unmap_descbuffer(ring, meta_hdr->dmaaddr,
+			 hdrsize, 1);
+	return err;
+}
+
+static inline int should_inject_overflow(struct b43_dmaring *ring)
+{
+#ifdef CONFIG_B43_DEBUG
+	if (unlikely(b43_debug(ring->dev, B43_DBG_DMAOVERFLOW))) {
+		/* Check if we should inject another ringbuffer overflow
+		 * to test handling of this situation in the stack. */
+		unsigned long next_overflow;
+
+		next_overflow = ring->last_injected_overflow + HZ;
+		if (time_after(jiffies, next_overflow)) {
+			ring->last_injected_overflow = jiffies;
+			b43dbg(ring->dev->wl,
+			       "Injecting TX ring overflow on "
+			       "DMA controller %d\n", ring->index);
+			return 1;
+		}
+	}
+#endif /* CONFIG_B43_DEBUG */
+	return 0;
+}
+
+/* Static mapping of mac80211's queues (priorities) to b43 DMA rings. */
+static struct b43_dmaring *select_ring_by_priority(struct b43_wldev *dev,
+						   u8 queue_prio)
+{
+	struct b43_dmaring *ring;
+
+	if (dev->qos_enabled) {
+		/* 0 = highest priority */
+		switch (queue_prio) {
+		default:
+			B43_WARN_ON(1);
+			/* fallthrough */
+		case 0:
+			ring = dev->dma.tx_ring_AC_VO;
+			break;
+		case 1:
+			ring = dev->dma.tx_ring_AC_VI;
+			break;
+		case 2:
+			ring = dev->dma.tx_ring_AC_BE;
+			break;
+		case 3:
+			ring = dev->dma.tx_ring_AC_BK;
+			break;
+		}
+	} else
+		ring = dev->dma.tx_ring_AC_BE;
+
+	return ring;
+}
+
+int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
+{
+	struct b43_dmaring *ring;
+	struct ieee80211_hdr *hdr;
+	int err = 0;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+	hdr = (struct ieee80211_hdr *)skb->data;
+	if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
+		/* The multicast ring will be sent after the DTIM */
+		ring = dev->dma.tx_ring_mcast;
+		/* Set the more-data bit. Ucode will clear it on
+		 * the last frame for us. */
+		hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+	} else {
+		/* Decide by priority where to put this frame. */
+		ring = select_ring_by_priority(
+			dev, skb_get_queue_mapping(skb));
+	}
+
+	B43_WARN_ON(!ring->tx);
+
+	if (unlikely(ring->stopped)) {
+		/* We get here only because of a bug in mac80211.
+		 * Because of a race, one packet may be queued after
+		 * the queue is stopped, thus we got called when we shouldn't.
+		 * For now, just refuse the transmit. */
+		if (b43_debug(dev, B43_DBG_DMAVERBOSE))
+			b43err(dev->wl, "Packet after queue stopped\n");
+		err = -ENOSPC;
+		goto out;
+	}
+
+	if (unlikely(WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME))) {
+		/* If we get here, we have a real error with the queue
+		 * full, but queues not stopped. */
+		b43err(dev->wl, "DMA queue overflow\n");
+		err = -ENOSPC;
+		goto out;
+	}
+
+	/* Assign the queue number to the ring (if not already done before)
+	 * so TX status handling can use it. The queue to ring mapping is
+	 * static, so we don't need to store it per frame. */
+	ring->queue_prio = skb_get_queue_mapping(skb);
+
+	err = dma_tx_fragment(ring, skb);
+	if (unlikely(err == -ENOKEY)) {
+		/* Drop this packet, as we don't have the encryption key
+		 * anymore and must not transmit it unencrypted. */
+		ieee80211_free_txskb(dev->wl->hw, skb);
+		err = 0;
+		goto out;
+	}
+	if (unlikely(err)) {
+		b43err(dev->wl, "DMA tx mapping failure\n");
+		goto out;
+	}
+	if ((free_slots(ring) < TX_SLOTS_PER_FRAME) ||
+	    should_inject_overflow(ring)) {
+		/* This TX ring is full. */
+		unsigned int skb_mapping = skb_get_queue_mapping(skb);
+		ieee80211_stop_queue(dev->wl->hw, skb_mapping);
+		dev->wl->tx_queue_stopped[skb_mapping] = 1;
+		ring->stopped = true;
+		if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
+			b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index);
+		}
+	}
+out:
+
+	return err;
+}
+
+void b43_dma_handle_txstatus(struct b43_wldev *dev,
+			     const struct b43_txstatus *status)
+{
+	const struct b43_dma_ops *ops;
+	struct b43_dmaring *ring;
+	struct b43_dmadesc_meta *meta;
+	static const struct b43_txstatus fake; /* filled with 0 */
+	const struct b43_txstatus *txstat;
+	int slot, firstused;
+	bool frame_succeed;
+	int skip;
+	static u8 err_out1;
+
+	ring = parse_cookie(dev, status->cookie, &slot);
+	if (unlikely(!ring))
+		return;
+	B43_WARN_ON(!ring->tx);
+
+	/* Sanity check: TX packets are processed in-order on one ring.
+	 * Check if the slot deduced from the cookie really is the first
+	 * used slot. */
+	firstused = ring->current_slot - ring->used_slots + 1;
+	if (firstused < 0)
+		firstused = ring->nr_slots + firstused;
+
+	skip = 0;
+	if (unlikely(slot != firstused)) {
+		/* This possibly is a firmware bug and will result in
+		 * malfunction, memory leaks and/or stall of DMA functionality.
+		 */
+		if (slot == next_slot(ring, next_slot(ring, firstused))) {
+			/* If a single header/data pair was missed, skip over
+			 * the first two slots in an attempt to recover.
+			 */
+			slot = firstused;
+			skip = 2;
+			if (!err_out1) {
+				/* Report the error once. */
+				b43dbg(dev->wl,
+				       "Skip on DMA ring %d slot %d.\n",
+				       ring->index, slot);
+				err_out1 = 1;
+			}
+		} else {
+			/* More than a single header/data pair were missed.
+			 * Report this error. If running with open-source
+			 * firmware, then reset the controller to
+			 * revive operation.
+			 */
+			b43dbg(dev->wl,
+			       "Out of order TX status report on DMA ring %d. Expected %d, but got %d\n",
+			       ring->index, firstused, slot);
+			if (dev->fw.opensource)
+				b43_controller_restart(dev, "Out of order TX");
+			return;
+		}
+	}
+
+	ops = ring->ops;
+	while (1) {
+		B43_WARN_ON(slot < 0 || slot >= ring->nr_slots);
+		/* get meta - ignore returned value */
+		ops->idx2desc(ring, slot, &meta);
+
+		if (b43_dma_ptr_is_poisoned(meta->skb)) {
+			b43dbg(dev->wl, "Poisoned TX slot %d (first=%d) "
+			       "on ring %d\n",
+			       slot, firstused, ring->index);
+			break;
+		}
+
+		if (meta->skb) {
+			struct b43_private_tx_info *priv_info =
+			     b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb));
+
+			unmap_descbuffer(ring, meta->dmaaddr,
+					 meta->skb->len, 1);
+			kfree(priv_info->bouncebuffer);
+			priv_info->bouncebuffer = NULL;
+		} else {
+			unmap_descbuffer(ring, meta->dmaaddr,
+					 b43_txhdr_size(dev), 1);
+		}
+
+		if (meta->is_last_fragment) {
+			struct ieee80211_tx_info *info;
+
+			if (unlikely(!meta->skb)) {
+				/* This is a scatter-gather fragment of a frame,
+				 * so the skb pointer must not be NULL.
+				 */
+				b43dbg(dev->wl, "TX status unexpected NULL skb "
+				       "at slot %d (first=%d) on ring %d\n",
+				       slot, firstused, ring->index);
+				break;
+			}
+
+			info = IEEE80211_SKB_CB(meta->skb);
+
+			/*
+			 * Call back to inform the ieee80211 subsystem about
+			 * the status of the transmission. When skipping over
+			 * a missed TX status report, use a status structure
+			 * filled with zeros to indicate that the frame was not
+			 * sent (frame_count 0) and not acknowledged
+			 */
+			if (unlikely(skip))
+				txstat = &fake;
+			else
+				txstat = status;
+
+			frame_succeed = b43_fill_txstatus_report(dev, info,
+								 txstat);
+#ifdef CONFIG_B43_DEBUG
+			if (frame_succeed)
+				ring->nr_succeed_tx_packets++;
+			else
+				ring->nr_failed_tx_packets++;
+			ring->nr_total_packet_tries += status->frame_count;
+#endif /* DEBUG */
+			ieee80211_tx_status(dev->wl->hw, meta->skb);
+
+			/* skb will be freed by ieee80211_tx_status().
+			 * Poison our pointer. */
+			meta->skb = B43_DMA_PTR_POISON;
+		} else {
+			/* No need to call free_descriptor_buffer here, as
+			 * this is only the txhdr, which is not allocated.
+			 */
+			if (unlikely(meta->skb)) {
+				b43dbg(dev->wl, "TX status unexpected non-NULL skb "
+				       "at slot %d (first=%d) on ring %d\n",
+				       slot, firstused, ring->index);
+				break;
+			}
+		}
+
+		/* Everything unmapped and free'd. So it's not used anymore. */
+		ring->used_slots--;
+
+		if (meta->is_last_fragment && !skip) {
+			/* This is the last scatter-gather
+			 * fragment of the frame. We are done. */
+			break;
+		}
+		slot = next_slot(ring, slot);
+		if (skip > 0)
+			--skip;
+	}
+	if (ring->stopped) {
+		B43_WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME);
+		ring->stopped = false;
+	}
+
+	if (dev->wl->tx_queue_stopped[ring->queue_prio]) {
+		dev->wl->tx_queue_stopped[ring->queue_prio] = 0;
+	} else {
+		/* If the driver queue is running wake the corresponding
+		 * mac80211 queue. */
+		ieee80211_wake_queue(dev->wl->hw, ring->queue_prio);
+		if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
+			b43dbg(dev->wl, "Woke up TX ring %d\n", ring->index);
+		}
+	}
+	/* Add work to the queue. */
+	ieee80211_queue_work(dev->wl->hw, &dev->wl->tx_work);
+}
+
+static void dma_rx(struct b43_dmaring *ring, int *slot)
+{
+	const struct b43_dma_ops *ops = ring->ops;
+	struct b43_dmadesc_generic *desc;
+	struct b43_dmadesc_meta *meta;
+	struct b43_rxhdr_fw4 *rxhdr;
+	struct sk_buff *skb;
+	u16 len;
+	int err;
+	dma_addr_t dmaaddr;
+
+	desc = ops->idx2desc(ring, *slot, &meta);
+
+	sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize);
+	skb = meta->skb;
+
+	rxhdr = (struct b43_rxhdr_fw4 *)skb->data;
+	len = le16_to_cpu(rxhdr->frame_len);
+	if (len == 0) {
+		int i = 0;
+
+		do {
+			udelay(2);
+			barrier();
+			len = le16_to_cpu(rxhdr->frame_len);
+		} while (len == 0 && i++ < 5);
+		if (unlikely(len == 0)) {
+			dmaaddr = meta->dmaaddr;
+			goto drop_recycle_buffer;
+		}
+	}
+	if (unlikely(b43_rx_buffer_is_poisoned(ring, skb))) {
+		/* Something went wrong with the DMA.
+		 * The device did not touch the buffer and did not overwrite the poison. */
+		b43dbg(ring->dev->wl, "DMA RX: Dropping poisoned buffer.\n");
+		dmaaddr = meta->dmaaddr;
+		goto drop_recycle_buffer;
+	}
+	if (unlikely(len + ring->frameoffset > ring->rx_buffersize)) {
+		/* The data did not fit into one descriptor buffer
+		 * and is split over multiple buffers.
+		 * This should never happen, as we try to allocate buffers
+		 * big enough. So simply ignore this packet.
+		 */
+		int cnt = 0;
+		s32 tmp = len;
+
+		while (1) {
+			desc = ops->idx2desc(ring, *slot, &meta);
+			/* recycle the descriptor buffer. */
+			b43_poison_rx_buffer(ring, meta->skb);
+			sync_descbuffer_for_device(ring, meta->dmaaddr,
+						   ring->rx_buffersize);
+			*slot = next_slot(ring, *slot);
+			cnt++;
+			tmp -= ring->rx_buffersize;
+			if (tmp <= 0)
+				break;
+		}
+		b43err(ring->dev->wl, "DMA RX buffer too small "
+		       "(len: %u, buffer: %u, nr-dropped: %d)\n",
+		       len, ring->rx_buffersize, cnt);
+		goto drop;
+	}
+
+	dmaaddr = meta->dmaaddr;
+	err = setup_rx_descbuffer(ring, desc, meta, GFP_ATOMIC);
+	if (unlikely(err)) {
+		b43dbg(ring->dev->wl, "DMA RX: setup_rx_descbuffer() failed\n");
+		goto drop_recycle_buffer;
+	}
+
+	unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0);
+	skb_put(skb, len + ring->frameoffset);
+	skb_pull(skb, ring->frameoffset);
+
+	b43_rx(ring->dev, skb, rxhdr);
+drop:
+	return;
+
+drop_recycle_buffer:
+	/* Poison and recycle the RX buffer. */
+	b43_poison_rx_buffer(ring, skb);
+	sync_descbuffer_for_device(ring, dmaaddr, ring->rx_buffersize);
+}
+
+void b43_dma_handle_rx_overflow(struct b43_dmaring *ring)
+{
+	int current_slot, previous_slot;
+
+	B43_WARN_ON(ring->tx);
+
+	/* Device has filled all buffers, drop all packets and let TCP
+	 * decrease speed.
+	 * Decrement RX index by one will let the device to see all slots
+	 * as free again
+	 */
+	/*
+	*TODO: How to increase rx_drop in mac80211?
+	*/
+	current_slot = ring->ops->get_current_rxslot(ring);
+	previous_slot = prev_slot(ring, current_slot);
+	ring->ops->set_current_rxslot(ring, previous_slot);
+}
+
+void b43_dma_rx(struct b43_dmaring *ring)
+{
+	const struct b43_dma_ops *ops = ring->ops;
+	int slot, current_slot;
+	int used_slots = 0;
+
+	B43_WARN_ON(ring->tx);
+	current_slot = ops->get_current_rxslot(ring);
+	B43_WARN_ON(!(current_slot >= 0 && current_slot < ring->nr_slots));
+
+	slot = ring->current_slot;
+	for (; slot != current_slot; slot = next_slot(ring, slot)) {
+		dma_rx(ring, &slot);
+		update_max_used_slots(ring, ++used_slots);
+	}
+	wmb();
+	ops->set_current_rxslot(ring, slot);
+	ring->current_slot = slot;
+}
+
+static void b43_dma_tx_suspend_ring(struct b43_dmaring *ring)
+{
+	B43_WARN_ON(!ring->tx);
+	ring->ops->tx_suspend(ring);
+}
+
+static void b43_dma_tx_resume_ring(struct b43_dmaring *ring)
+{
+	B43_WARN_ON(!ring->tx);
+	ring->ops->tx_resume(ring);
+}
+
+void b43_dma_tx_suspend(struct b43_wldev *dev)
+{
+	b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
+	b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_BK);
+	b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_BE);
+	b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_VI);
+	b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_VO);
+	b43_dma_tx_suspend_ring(dev->dma.tx_ring_mcast);
+}
+
+void b43_dma_tx_resume(struct b43_wldev *dev)
+{
+	b43_dma_tx_resume_ring(dev->dma.tx_ring_mcast);
+	b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_VO);
+	b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_VI);
+	b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_BE);
+	b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_BK);
+	b43_power_saving_ctl_bits(dev, 0);
+}
+
+static void direct_fifo_rx(struct b43_wldev *dev, enum b43_dmatype type,
+			   u16 mmio_base, bool enable)
+{
+	u32 ctl;
+
+	if (type == B43_DMA_64BIT) {
+		ctl = b43_read32(dev, mmio_base + B43_DMA64_RXCTL);
+		ctl &= ~B43_DMA64_RXDIRECTFIFO;
+		if (enable)
+			ctl |= B43_DMA64_RXDIRECTFIFO;
+		b43_write32(dev, mmio_base + B43_DMA64_RXCTL, ctl);
+	} else {
+		ctl = b43_read32(dev, mmio_base + B43_DMA32_RXCTL);
+		ctl &= ~B43_DMA32_RXDIRECTFIFO;
+		if (enable)
+			ctl |= B43_DMA32_RXDIRECTFIFO;
+		b43_write32(dev, mmio_base + B43_DMA32_RXCTL, ctl);
+	}
+}
+
+/* Enable/Disable Direct FIFO Receive Mode (PIO) on a RX engine.
+ * This is called from PIO code, so DMA structures are not available. */
+void b43_dma_direct_fifo_rx(struct b43_wldev *dev,
+			    unsigned int engine_index, bool enable)
+{
+	enum b43_dmatype type;
+	u16 mmio_base;
+
+	type = dma_mask_to_engine_type(supported_dma_mask(dev));
+
+	mmio_base = b43_dmacontroller_base(type, engine_index);
+	direct_fifo_rx(dev, type, mmio_base, enable);
+}
diff --git a/drivers/net/wireless/broadcom/b43/dma.h b/drivers/net/wireless/broadcom/b43/dma.h
new file mode 100644
index 0000000..c2a3572
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/dma.h
@@ -0,0 +1,306 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_DMA_H_
+#define B43_DMA_H_
+
+#include <linux/err.h>
+
+#include "b43.h"
+
+
+/* DMA-Interrupt reasons. */
+#define B43_DMAIRQ_FATALMASK	((1 << 10) | (1 << 11) | (1 << 12) \
+					 | (1 << 14) | (1 << 15))
+#define B43_DMAIRQ_RDESC_UFLOW		(1 << 13)
+#define B43_DMAIRQ_RX_DONE		(1 << 16)
+
+/*** 32-bit DMA Engine. ***/
+
+/* 32-bit DMA controller registers. */
+#define B43_DMA32_TXCTL				0x00
+#define		B43_DMA32_TXENABLE			0x00000001
+#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
+#define B43_DMA32_TXINDEX				0x08
+#define B43_DMA32_TXSTATUS				0x0C
+#define		B43_DMA32_TXDPTR			0x00000FFF
+#define		B43_DMA32_TXSTATE			0x0000F000
+#define			B43_DMA32_TXSTAT_DISABLED	0x00000000
+#define			B43_DMA32_TXSTAT_ACTIVE	0x00001000
+#define			B43_DMA32_TXSTAT_IDLEWAIT	0x00002000
+#define			B43_DMA32_TXSTAT_STOPPED	0x00003000
+#define			B43_DMA32_TXSTAT_SUSP	0x00004000
+#define		B43_DMA32_TXERROR			0x000F0000
+#define			B43_DMA32_TXERR_NOERR	0x00000000
+#define			B43_DMA32_TXERR_PROT	0x00010000
+#define			B43_DMA32_TXERR_UNDERRUN	0x00020000
+#define			B43_DMA32_TXERR_BUFREAD	0x00030000
+#define			B43_DMA32_TXERR_DESCREAD	0x00040000
+#define		B43_DMA32_TXACTIVE			0xFFF00000
+#define B43_DMA32_RXCTL				0x10
+#define		B43_DMA32_RXENABLE			0x00000001
+#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
+#define B43_DMA32_RXINDEX				0x18
+#define B43_DMA32_RXSTATUS				0x1C
+#define		B43_DMA32_RXDPTR			0x00000FFF
+#define		B43_DMA32_RXSTATE			0x0000F000
+#define			B43_DMA32_RXSTAT_DISABLED	0x00000000
+#define			B43_DMA32_RXSTAT_ACTIVE	0x00001000
+#define			B43_DMA32_RXSTAT_IDLEWAIT	0x00002000
+#define			B43_DMA32_RXSTAT_STOPPED	0x00003000
+#define		B43_DMA32_RXERROR			0x000F0000
+#define			B43_DMA32_RXERR_NOERR	0x00000000
+#define			B43_DMA32_RXERR_PROT	0x00010000
+#define			B43_DMA32_RXERR_OVERFLOW	0x00020000
+#define			B43_DMA32_RXERR_BUFWRITE	0x00030000
+#define			B43_DMA32_RXERR_DESCREAD	0x00040000
+#define		B43_DMA32_RXACTIVE			0xFFF00000
+
+/* 32-bit DMA descriptor. */
+struct b43_dmadesc32 {
+	__le32 control;
+	__le32 address;
+} __packed;
+#define B43_DMA32_DCTL_BYTECNT		0x00001FFF
+#define B43_DMA32_DCTL_ADDREXT_MASK		0x00030000
+#define B43_DMA32_DCTL_ADDREXT_SHIFT	16
+#define B43_DMA32_DCTL_DTABLEEND		0x10000000
+#define B43_DMA32_DCTL_IRQ			0x20000000
+#define B43_DMA32_DCTL_FRAMEEND		0x40000000
+#define B43_DMA32_DCTL_FRAMESTART		0x80000000
+
+/*** 64-bit DMA Engine. ***/
+
+/* 64-bit DMA controller registers. */
+#define B43_DMA64_TXCTL				0x00
+#define		B43_DMA64_TXENABLE			0x00000001
+#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
+#define B43_DMA64_TXRINGLO				0x08
+#define B43_DMA64_TXRINGHI				0x0C
+#define B43_DMA64_TXSTATUS				0x10
+#define		B43_DMA64_TXSTATDPTR		0x00001FFF
+#define		B43_DMA64_TXSTAT			0xF0000000
+#define			B43_DMA64_TXSTAT_DISABLED	0x00000000
+#define			B43_DMA64_TXSTAT_ACTIVE	0x10000000
+#define			B43_DMA64_TXSTAT_IDLEWAIT	0x20000000
+#define			B43_DMA64_TXSTAT_STOPPED	0x30000000
+#define			B43_DMA64_TXSTAT_SUSP	0x40000000
+#define B43_DMA64_TXERROR				0x14
+#define		B43_DMA64_TXERRDPTR			0x0001FFFF
+#define		B43_DMA64_TXERR			0xF0000000
+#define			B43_DMA64_TXERR_NOERR	0x00000000
+#define			B43_DMA64_TXERR_PROT	0x10000000
+#define			B43_DMA64_TXERR_UNDERRUN	0x20000000
+#define			B43_DMA64_TXERR_TRANSFER	0x30000000
+#define			B43_DMA64_TXERR_DESCREAD	0x40000000
+#define			B43_DMA64_TXERR_CORE	0x50000000
+#define B43_DMA64_RXCTL				0x20
+#define		B43_DMA64_RXENABLE			0x00000001
+#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
+#define B43_DMA64_RXRINGLO				0x28
+#define B43_DMA64_RXRINGHI				0x2C
+#define B43_DMA64_RXSTATUS				0x30
+#define		B43_DMA64_RXSTATDPTR		0x00001FFF
+#define		B43_DMA64_RXSTAT			0xF0000000
+#define			B43_DMA64_RXSTAT_DISABLED	0x00000000
+#define			B43_DMA64_RXSTAT_ACTIVE	0x10000000
+#define			B43_DMA64_RXSTAT_IDLEWAIT	0x20000000
+#define			B43_DMA64_RXSTAT_STOPPED	0x30000000
+#define			B43_DMA64_RXSTAT_SUSP	0x40000000
+#define B43_DMA64_RXERROR				0x34
+#define		B43_DMA64_RXERRDPTR			0x0001FFFF
+#define		B43_DMA64_RXERR			0xF0000000
+#define			B43_DMA64_RXERR_NOERR	0x00000000
+#define			B43_DMA64_RXERR_PROT	0x10000000
+#define			B43_DMA64_RXERR_UNDERRUN	0x20000000
+#define			B43_DMA64_RXERR_TRANSFER	0x30000000
+#define			B43_DMA64_RXERR_DESCREAD	0x40000000
+#define			B43_DMA64_RXERR_CORE	0x50000000
+
+/* 64-bit DMA descriptor. */
+struct b43_dmadesc64 {
+	__le32 control0;
+	__le32 control1;
+	__le32 address_low;
+	__le32 address_high;
+} __packed;
+#define B43_DMA64_DCTL0_DTABLEEND		0x10000000
+#define B43_DMA64_DCTL0_IRQ			0x20000000
+#define B43_DMA64_DCTL0_FRAMEEND		0x40000000
+#define B43_DMA64_DCTL0_FRAMESTART		0x80000000
+#define B43_DMA64_DCTL1_BYTECNT		0x00001FFF
+#define B43_DMA64_DCTL1_ADDREXT_MASK	0x00030000
+#define B43_DMA64_DCTL1_ADDREXT_SHIFT	16
+
+struct b43_dmadesc_generic {
+	union {
+		struct b43_dmadesc32 dma32;
+		struct b43_dmadesc64 dma64;
+	} __packed;
+} __packed;
+
+/* Misc DMA constants */
+#define B43_DMA32_RINGMEMSIZE		4096
+#define B43_DMA64_RINGMEMSIZE		8192
+/* Offset of frame with actual data */
+#define B43_DMA0_RX_FW598_FO		38
+#define B43_DMA0_RX_FW351_FO		30
+
+/* DMA engine tuning knobs */
+#define B43_TXRING_SLOTS		256
+#define B43_RXRING_SLOTS		256
+#define B43_DMA0_RX_FW598_BUFSIZE	(B43_DMA0_RX_FW598_FO + IEEE80211_MAX_FRAME_LEN)
+#define B43_DMA0_RX_FW351_BUFSIZE	(B43_DMA0_RX_FW351_FO + IEEE80211_MAX_FRAME_LEN)
+
+/* Pointer poison */
+#define B43_DMA_PTR_POISON		((void *)ERR_PTR(-ENOMEM))
+#define b43_dma_ptr_is_poisoned(ptr)	(unlikely((ptr) == B43_DMA_PTR_POISON))
+
+
+struct sk_buff;
+struct b43_private;
+struct b43_txstatus;
+
+struct b43_dmadesc_meta {
+	/* The kernel DMA-able buffer. */
+	struct sk_buff *skb;
+	/* DMA base bus-address of the descriptor buffer. */
+	dma_addr_t dmaaddr;
+	/* ieee80211 TX status. Only used once per 802.11 frag. */
+	bool is_last_fragment;
+};
+
+struct b43_dmaring;
+
+/* Lowlevel DMA operations that differ between 32bit and 64bit DMA. */
+struct b43_dma_ops {
+	struct b43_dmadesc_generic *(*idx2desc) (struct b43_dmaring * ring,
+						 int slot,
+						 struct b43_dmadesc_meta **
+						 meta);
+	void (*fill_descriptor) (struct b43_dmaring * ring,
+				 struct b43_dmadesc_generic * desc,
+				 dma_addr_t dmaaddr, u16 bufsize, int start,
+				 int end, int irq);
+	void (*poke_tx) (struct b43_dmaring * ring, int slot);
+	void (*tx_suspend) (struct b43_dmaring * ring);
+	void (*tx_resume) (struct b43_dmaring * ring);
+	int (*get_current_rxslot) (struct b43_dmaring * ring);
+	void (*set_current_rxslot) (struct b43_dmaring * ring, int slot);
+};
+
+enum b43_dmatype {
+	B43_DMA_30BIT	= 30,
+	B43_DMA_32BIT	= 32,
+	B43_DMA_64BIT	= 64,
+};
+
+enum b43_addrtype {
+	B43_DMA_ADDR_LOW,
+	B43_DMA_ADDR_HIGH,
+	B43_DMA_ADDR_EXT,
+};
+
+struct b43_dmaring {
+	/* Lowlevel DMA ops. */
+	const struct b43_dma_ops *ops;
+	/* Kernel virtual base address of the ring memory. */
+	void *descbase;
+	/* Meta data about all descriptors. */
+	struct b43_dmadesc_meta *meta;
+	/* Cache of TX headers for each TX frame.
+	 * This is to avoid an allocation on each TX.
+	 * This is NULL for an RX ring.
+	 */
+	u8 *txhdr_cache;
+	/* (Unadjusted) DMA base bus-address of the ring memory. */
+	dma_addr_t dmabase;
+	/* Number of descriptor slots in the ring. */
+	int nr_slots;
+	/* Number of used descriptor slots. */
+	int used_slots;
+	/* Currently used slot in the ring. */
+	int current_slot;
+	/* Frameoffset in octets. */
+	u32 frameoffset;
+	/* Descriptor buffer size. */
+	u16 rx_buffersize;
+	/* The MMIO base register of the DMA controller. */
+	u16 mmio_base;
+	/* DMA controller index number (0-5). */
+	int index;
+	/* Boolean. Is this a TX ring? */
+	bool tx;
+	/* The type of DMA engine used. */
+	enum b43_dmatype type;
+	/* Boolean. Is this ring stopped at ieee80211 level? */
+	bool stopped;
+	/* The QOS priority assigned to this ring. Only used for TX rings.
+	 * This is the mac80211 "queue" value. */
+	u8 queue_prio;
+	struct b43_wldev *dev;
+#ifdef CONFIG_B43_DEBUG
+	/* Maximum number of used slots. */
+	int max_used_slots;
+	/* Last time we injected a ring overflow. */
+	unsigned long last_injected_overflow;
+	/* Statistics: Number of successfully transmitted packets */
+	u64 nr_succeed_tx_packets;
+	/* Statistics: Number of failed TX packets */
+	u64 nr_failed_tx_packets;
+	/* Statistics: Total number of TX plus all retries. */
+	u64 nr_total_packet_tries;
+#endif /* CONFIG_B43_DEBUG */
+};
+
+static inline u32 b43_dma_read(struct b43_dmaring *ring, u16 offset)
+{
+	return b43_read32(ring->dev, ring->mmio_base + offset);
+}
+
+static inline void b43_dma_write(struct b43_dmaring *ring, u16 offset, u32 value)
+{
+	b43_write32(ring->dev, ring->mmio_base + offset, value);
+}
+
+int b43_dma_init(struct b43_wldev *dev);
+void b43_dma_free(struct b43_wldev *dev);
+
+void b43_dma_tx_suspend(struct b43_wldev *dev);
+void b43_dma_tx_resume(struct b43_wldev *dev);
+
+int b43_dma_tx(struct b43_wldev *dev,
+	       struct sk_buff *skb);
+void b43_dma_handle_txstatus(struct b43_wldev *dev,
+			     const struct b43_txstatus *status);
+
+void b43_dma_handle_rx_overflow(struct b43_dmaring *ring);
+
+void b43_dma_rx(struct b43_dmaring *ring);
+
+void b43_dma_direct_fifo_rx(struct b43_wldev *dev,
+			    unsigned int engine_index, bool enable);
+
+#endif /* B43_DMA_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/leds.c b/drivers/net/wireless/broadcom/b43/leds.c
new file mode 100644
index 0000000..87131f6
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/leds.c
@@ -0,0 +1,363 @@
+/*
+
+  Broadcom B43 wireless driver
+  LED control
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+  Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
+  Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
+  Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
+  Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+  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 "leds.h"
+#include "rfkill.h"
+
+
+static void b43_led_turn_on(struct b43_wldev *dev, u8 led_index,
+			    bool activelow)
+{
+	u16 ctl;
+
+	ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL);
+	if (activelow)
+		ctl &= ~(1 << led_index);
+	else
+		ctl |= (1 << led_index);
+	b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl);
+}
+
+static void b43_led_turn_off(struct b43_wldev *dev, u8 led_index,
+			     bool activelow)
+{
+	u16 ctl;
+
+	ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL);
+	if (activelow)
+		ctl |= (1 << led_index);
+	else
+		ctl &= ~(1 << led_index);
+	b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl);
+}
+
+static void b43_led_update(struct b43_wldev *dev,
+			   struct b43_led *led)
+{
+	bool radio_enabled;
+	bool turn_on;
+
+	if (!led->wl)
+		return;
+
+	radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable);
+
+	/* The led->state read is racy, but we don't care. In case we raced
+	 * with the brightness_set handler, we will be called again soon
+	 * to fixup our state. */
+	if (radio_enabled)
+		turn_on = atomic_read(&led->state) != LED_OFF;
+	else
+		turn_on = false;
+	if (turn_on == led->hw_state)
+		return;
+	led->hw_state = turn_on;
+
+	if (turn_on)
+		b43_led_turn_on(dev, led->index, led->activelow);
+	else
+		b43_led_turn_off(dev, led->index, led->activelow);
+}
+
+static void b43_leds_work(struct work_struct *work)
+{
+	struct b43_leds *leds = container_of(work, struct b43_leds, work);
+	struct b43_wl *wl = container_of(leds, struct b43_wl, leds);
+	struct b43_wldev *dev;
+
+	mutex_lock(&wl->mutex);
+	dev = wl->current_dev;
+	if (unlikely(!dev || b43_status(dev) < B43_STAT_STARTED))
+		goto out_unlock;
+
+	b43_led_update(dev, &wl->leds.led_tx);
+	b43_led_update(dev, &wl->leds.led_rx);
+	b43_led_update(dev, &wl->leds.led_radio);
+	b43_led_update(dev, &wl->leds.led_assoc);
+
+out_unlock:
+	mutex_unlock(&wl->mutex);
+}
+
+/* Callback from the LED subsystem. */
+static void b43_led_brightness_set(struct led_classdev *led_dev,
+				   enum led_brightness brightness)
+{
+	struct b43_led *led = container_of(led_dev, struct b43_led, led_dev);
+	struct b43_wl *wl = led->wl;
+
+	if (likely(!wl->leds.stop)) {
+		atomic_set(&led->state, brightness);
+		ieee80211_queue_work(wl->hw, &wl->leds.work);
+	}
+}
+
+static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
+			    const char *name, const char *default_trigger,
+			    u8 led_index, bool activelow)
+{
+	int err;
+
+	if (led->wl)
+		return -EEXIST;
+	if (!default_trigger)
+		return -EINVAL;
+	led->wl = dev->wl;
+	led->index = led_index;
+	led->activelow = activelow;
+	strlcpy(led->name, name, sizeof(led->name));
+	atomic_set(&led->state, 0);
+
+	led->led_dev.name = led->name;
+	led->led_dev.default_trigger = default_trigger;
+	led->led_dev.brightness_set = b43_led_brightness_set;
+
+	err = led_classdev_register(dev->dev->dev, &led->led_dev);
+	if (err) {
+		b43warn(dev->wl, "LEDs: Failed to register %s\n", name);
+		led->wl = NULL;
+		return err;
+	}
+
+	return 0;
+}
+
+static void b43_unregister_led(struct b43_led *led)
+{
+	if (!led->wl)
+		return;
+	led_classdev_unregister(&led->led_dev);
+	led->wl = NULL;
+}
+
+static void b43_map_led(struct b43_wldev *dev,
+			u8 led_index,
+			enum b43_led_behaviour behaviour,
+			bool activelow)
+{
+	struct ieee80211_hw *hw = dev->wl->hw;
+	char name[B43_LED_MAX_NAME_LEN + 1];
+
+	/* Map the b43 specific LED behaviour value to the
+	 * generic LED triggers. */
+	switch (behaviour) {
+	case B43_LED_INACTIVE:
+	case B43_LED_OFF:
+	case B43_LED_ON:
+		break;
+	case B43_LED_ACTIVITY:
+	case B43_LED_TRANSFER:
+	case B43_LED_APTRANSFER:
+		snprintf(name, sizeof(name),
+			 "b43-%s::tx", wiphy_name(hw->wiphy));
+		b43_register_led(dev, &dev->wl->leds.led_tx, name,
+				 ieee80211_get_tx_led_name(hw),
+				 led_index, activelow);
+		snprintf(name, sizeof(name),
+			 "b43-%s::rx", wiphy_name(hw->wiphy));
+		b43_register_led(dev, &dev->wl->leds.led_rx, name,
+				 ieee80211_get_rx_led_name(hw),
+				 led_index, activelow);
+		break;
+	case B43_LED_RADIO_ALL:
+	case B43_LED_RADIO_A:
+	case B43_LED_RADIO_B:
+	case B43_LED_MODE_BG:
+		snprintf(name, sizeof(name),
+			 "b43-%s::radio", wiphy_name(hw->wiphy));
+		b43_register_led(dev, &dev->wl->leds.led_radio, name,
+				 ieee80211_get_radio_led_name(hw),
+				 led_index, activelow);
+		break;
+	case B43_LED_WEIRD:
+	case B43_LED_ASSOC:
+		snprintf(name, sizeof(name),
+			 "b43-%s::assoc", wiphy_name(hw->wiphy));
+		b43_register_led(dev, &dev->wl->leds.led_assoc, name,
+				 ieee80211_get_assoc_led_name(hw),
+				 led_index, activelow);
+		break;
+	default:
+		b43warn(dev->wl, "LEDs: Unknown behaviour 0x%02X\n",
+			behaviour);
+		break;
+	}
+}
+
+static void b43_led_get_sprominfo(struct b43_wldev *dev,
+				  unsigned int led_index,
+				  enum b43_led_behaviour *behaviour,
+				  bool *activelow)
+{
+	u8 sprom[4];
+
+	sprom[0] = dev->dev->bus_sprom->gpio0;
+	sprom[1] = dev->dev->bus_sprom->gpio1;
+	sprom[2] = dev->dev->bus_sprom->gpio2;
+	sprom[3] = dev->dev->bus_sprom->gpio3;
+
+	if ((sprom[0] & sprom[1] & sprom[2] & sprom[3]) == 0xff) {
+		/* There is no LED information in the SPROM
+		 * for this LED. Hardcode it here. */
+		*activelow = false;
+		switch (led_index) {
+		case 0:
+			*behaviour = B43_LED_ACTIVITY;
+			*activelow = true;
+			if (dev->dev->board_vendor == PCI_VENDOR_ID_COMPAQ)
+				*behaviour = B43_LED_RADIO_ALL;
+			break;
+		case 1:
+			*behaviour = B43_LED_RADIO_B;
+			if (dev->dev->board_vendor == PCI_VENDOR_ID_ASUSTEK)
+				*behaviour = B43_LED_ASSOC;
+			break;
+		case 2:
+			*behaviour = B43_LED_RADIO_A;
+			break;
+		case 3:
+			*behaviour = B43_LED_OFF;
+			break;
+		default:
+			*behaviour = B43_LED_OFF;
+			B43_WARN_ON(1);
+			return;
+		}
+	} else {
+		/* keep LED disabled if no mapping is defined */
+		if (sprom[led_index] == 0xff)
+			*behaviour = B43_LED_OFF;
+		else
+			*behaviour = sprom[led_index] & B43_LED_BEHAVIOUR;
+		*activelow = !!(sprom[led_index] & B43_LED_ACTIVELOW);
+	}
+}
+
+void b43_leds_init(struct b43_wldev *dev)
+{
+	struct b43_led *led;
+	unsigned int i;
+	enum b43_led_behaviour behaviour;
+	bool activelow;
+
+	/* Sync the RF-kill LED state (if we have one) with radio and switch states. */
+	led = &dev->wl->leds.led_radio;
+	if (led->wl) {
+		if (dev->phy.radio_on && b43_is_hw_radio_enabled(dev)) {
+			b43_led_turn_on(dev, led->index, led->activelow);
+			led->hw_state = true;
+			atomic_set(&led->state, 1);
+		} else {
+			b43_led_turn_off(dev, led->index, led->activelow);
+			led->hw_state = false;
+			atomic_set(&led->state, 0);
+		}
+	}
+
+	/* Initialize TX/RX/ASSOC leds */
+	led = &dev->wl->leds.led_tx;
+	if (led->wl) {
+		b43_led_turn_off(dev, led->index, led->activelow);
+		led->hw_state = false;
+		atomic_set(&led->state, 0);
+	}
+	led = &dev->wl->leds.led_rx;
+	if (led->wl) {
+		b43_led_turn_off(dev, led->index, led->activelow);
+		led->hw_state = false;
+		atomic_set(&led->state, 0);
+	}
+	led = &dev->wl->leds.led_assoc;
+	if (led->wl) {
+		b43_led_turn_off(dev, led->index, led->activelow);
+		led->hw_state = false;
+		atomic_set(&led->state, 0);
+	}
+
+	/* Initialize other LED states. */
+	for (i = 0; i < B43_MAX_NR_LEDS; i++) {
+		b43_led_get_sprominfo(dev, i, &behaviour, &activelow);
+		switch (behaviour) {
+		case B43_LED_OFF:
+			b43_led_turn_off(dev, i, activelow);
+			break;
+		case B43_LED_ON:
+			b43_led_turn_on(dev, i, activelow);
+			break;
+		default:
+			/* Leave others as-is. */
+			break;
+		}
+	}
+
+	dev->wl->leds.stop = 0;
+}
+
+void b43_leds_exit(struct b43_wldev *dev)
+{
+	struct b43_leds *leds = &dev->wl->leds;
+
+	b43_led_turn_off(dev, leds->led_tx.index, leds->led_tx.activelow);
+	b43_led_turn_off(dev, leds->led_rx.index, leds->led_rx.activelow);
+	b43_led_turn_off(dev, leds->led_assoc.index, leds->led_assoc.activelow);
+	b43_led_turn_off(dev, leds->led_radio.index, leds->led_radio.activelow);
+}
+
+void b43_leds_stop(struct b43_wldev *dev)
+{
+	struct b43_leds *leds = &dev->wl->leds;
+
+	leds->stop = 1;
+	cancel_work_sync(&leds->work);
+}
+
+void b43_leds_register(struct b43_wldev *dev)
+{
+	unsigned int i;
+	enum b43_led_behaviour behaviour;
+	bool activelow;
+
+	INIT_WORK(&dev->wl->leds.work, b43_leds_work);
+
+	/* Register the LEDs to the LED subsystem. */
+	for (i = 0; i < B43_MAX_NR_LEDS; i++) {
+		b43_led_get_sprominfo(dev, i, &behaviour, &activelow);
+		b43_map_led(dev, i, behaviour, activelow);
+	}
+}
+
+void b43_leds_unregister(struct b43_wl *wl)
+{
+	struct b43_leds *leds = &wl->leds;
+
+	b43_unregister_led(&leds->led_tx);
+	b43_unregister_led(&leds->led_rx);
+	b43_unregister_led(&leds->led_assoc);
+	b43_unregister_led(&leds->led_radio);
+}
diff --git a/drivers/net/wireless/broadcom/b43/leds.h b/drivers/net/wireless/broadcom/b43/leds.h
new file mode 100644
index 0000000..5ebd1b2
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/leds.h
@@ -0,0 +1,95 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_LEDS_H_
+#define B43_LEDS_H_
+
+struct b43_wl;
+struct b43_wldev;
+
+#ifdef CONFIG_B43_LEDS
+
+#include <linux/types.h>
+#include <linux/leds.h>
+#include <linux/workqueue.h>
+
+
+#define B43_LED_MAX_NAME_LEN	31
+
+struct b43_led {
+	struct b43_wl *wl;
+	/* The LED class device */
+	struct led_classdev led_dev;
+	/* The index number of the LED. */
+	u8 index;
+	/* If activelow is true, the LED is ON if the
+	 * bit is switched off. */
+	bool activelow;
+	/* The unique name string for this LED device. */
+	char name[B43_LED_MAX_NAME_LEN + 1];
+	/* The current status of the LED. This is updated locklessly. */
+	atomic_t state;
+	/* The active state in hardware. */
+	bool hw_state;
+};
+
+struct b43_leds {
+	struct b43_led led_tx;
+	struct b43_led led_rx;
+	struct b43_led led_radio;
+	struct b43_led led_assoc;
+
+	bool stop;
+	struct work_struct work;
+};
+
+#define B43_MAX_NR_LEDS			4
+
+#define B43_LED_BEHAVIOUR		0x7F
+#define B43_LED_ACTIVELOW		0x80
+/* LED behaviour values */
+enum b43_led_behaviour {
+	B43_LED_OFF,
+	B43_LED_ON,
+	B43_LED_ACTIVITY,
+	B43_LED_RADIO_ALL,
+	B43_LED_RADIO_A,
+	B43_LED_RADIO_B,
+	B43_LED_MODE_BG,
+	B43_LED_TRANSFER,
+	B43_LED_APTRANSFER,
+	B43_LED_WEIRD,		//FIXME
+	B43_LED_ASSOC,
+	B43_LED_INACTIVE,
+};
+
+void b43_leds_register(struct b43_wldev *dev);
+void b43_leds_unregister(struct b43_wl *wl);
+void b43_leds_init(struct b43_wldev *dev);
+void b43_leds_exit(struct b43_wldev *dev);
+void b43_leds_stop(struct b43_wldev *dev);
+
+
+#else /* CONFIG_B43_LEDS */
+/* LED support disabled */
+
+struct b43_leds {
+	/* empty */
+};
+
+static inline void b43_leds_register(struct b43_wldev *dev)
+{
+}
+static inline void b43_leds_unregister(struct b43_wl *wl)
+{
+}
+static inline void b43_leds_init(struct b43_wldev *dev)
+{
+}
+static inline void b43_leds_exit(struct b43_wldev *dev)
+{
+}
+static inline void b43_leds_stop(struct b43_wldev *dev)
+{
+}
+#endif /* CONFIG_B43_LEDS */
+
+#endif /* B43_LEDS_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/lo.c b/drivers/net/wireless/broadcom/b43/lo.c
new file mode 100644
index 0000000..a335f94
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/lo.c
@@ -0,0 +1,1016 @@
+/*
+
+  Broadcom B43 wireless driver
+
+  G PHY LO (LocalOscillator) Measuring and Control routines
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+  Copyright (c) 2005, 2006 Stefano Brivio <stefano.brivio@polimi.it>
+  Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
+  Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
+  Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+  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 "lo.h"
+#include "phy_g.h"
+#include "main.h"
+
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+
+static struct b43_lo_calib *b43_find_lo_calib(struct b43_txpower_lo_control *lo,
+					      const struct b43_bbatt *bbatt,
+					       const struct b43_rfatt *rfatt)
+{
+	struct b43_lo_calib *c;
+
+	list_for_each_entry(c, &lo->calib_list, list) {
+		if (!b43_compare_bbatt(&c->bbatt, bbatt))
+			continue;
+		if (!b43_compare_rfatt(&c->rfatt, rfatt))
+			continue;
+		return c;
+	}
+
+	return NULL;
+}
+
+/* Write the LocalOscillator Control (adjust) value-pair. */
+static void b43_lo_write(struct b43_wldev *dev, struct b43_loctl *control)
+{
+	struct b43_phy *phy = &dev->phy;
+	u16 value;
+
+	if (B43_DEBUG) {
+		if (unlikely(abs(control->i) > 16 || abs(control->q) > 16)) {
+			b43dbg(dev->wl, "Invalid LO control pair "
+			       "(I: %d, Q: %d)\n", control->i, control->q);
+			dump_stack();
+			return;
+		}
+	}
+	B43_WARN_ON(phy->type != B43_PHYTYPE_G);
+
+	value = (u8) (control->q);
+	value |= ((u8) (control->i)) << 8;
+	b43_phy_write(dev, B43_PHY_LO_CTL, value);
+}
+
+static u16 lo_measure_feedthrough(struct b43_wldev *dev,
+				  u16 lna, u16 pga, u16 trsw_rx)
+{
+	struct b43_phy *phy = &dev->phy;
+	u16 rfover;
+	u16 feedthrough;
+
+	if (phy->gmode) {
+		lna <<= B43_PHY_RFOVERVAL_LNA_SHIFT;
+		pga <<= B43_PHY_RFOVERVAL_PGA_SHIFT;
+
+		B43_WARN_ON(lna & ~B43_PHY_RFOVERVAL_LNA);
+		B43_WARN_ON(pga & ~B43_PHY_RFOVERVAL_PGA);
+/*FIXME This assertion fails		B43_WARN_ON(trsw_rx & ~(B43_PHY_RFOVERVAL_TRSWRX |
+				    B43_PHY_RFOVERVAL_BW));
+*/
+		trsw_rx &= (B43_PHY_RFOVERVAL_TRSWRX | B43_PHY_RFOVERVAL_BW);
+
+		/* Construct the RF Override Value */
+		rfover = B43_PHY_RFOVERVAL_UNK;
+		rfover |= pga;
+		rfover |= lna;
+		rfover |= trsw_rx;
+		if ((dev->dev->bus_sprom->boardflags_lo & B43_BFL_EXTLNA)
+		    && phy->rev > 6)
+			rfover |= B43_PHY_RFOVERVAL_EXTLNA;
+
+		b43_phy_write(dev, B43_PHY_PGACTL, 0xE300);
+		b43_phy_write(dev, B43_PHY_RFOVERVAL, rfover);
+		udelay(10);
+		rfover |= B43_PHY_RFOVERVAL_BW_LBW;
+		b43_phy_write(dev, B43_PHY_RFOVERVAL, rfover);
+		udelay(10);
+		rfover |= B43_PHY_RFOVERVAL_BW_LPF;
+		b43_phy_write(dev, B43_PHY_RFOVERVAL, rfover);
+		udelay(10);
+		b43_phy_write(dev, B43_PHY_PGACTL, 0xF300);
+	} else {
+		pga |= B43_PHY_PGACTL_UNKNOWN;
+		b43_phy_write(dev, B43_PHY_PGACTL, pga);
+		udelay(10);
+		pga |= B43_PHY_PGACTL_LOWBANDW;
+		b43_phy_write(dev, B43_PHY_PGACTL, pga);
+		udelay(10);
+		pga |= B43_PHY_PGACTL_LPF;
+		b43_phy_write(dev, B43_PHY_PGACTL, pga);
+	}
+	udelay(21);
+	feedthrough = b43_phy_read(dev, B43_PHY_LO_LEAKAGE);
+
+	/* This is a good place to check if we need to relax a bit,
+	 * as this is the main function called regularly
+	 * in the LO calibration. */
+	cond_resched();
+
+	return feedthrough;
+}
+
+/* TXCTL Register and Value Table.
+ * Returns the "TXCTL Register".
+ * "value" is the "TXCTL Value".
+ * "pad_mix_gain" is the PAD Mixer Gain.
+ */
+static u16 lo_txctl_register_table(struct b43_wldev *dev,
+				   u16 *value, u16 *pad_mix_gain)
+{
+	struct b43_phy *phy = &dev->phy;
+	u16 reg, v, padmix;
+
+	if (phy->type == B43_PHYTYPE_B) {
+		v = 0x30;
+		if (phy->radio_rev <= 5) {
+			reg = 0x43;
+			padmix = 0;
+		} else {
+			reg = 0x52;
+			padmix = 5;
+		}
+	} else {
+		if (phy->rev >= 2 && phy->radio_rev == 8) {
+			reg = 0x43;
+			v = 0x10;
+			padmix = 2;
+		} else {
+			reg = 0x52;
+			v = 0x30;
+			padmix = 5;
+		}
+	}
+	if (value)
+		*value = v;
+	if (pad_mix_gain)
+		*pad_mix_gain = padmix;
+
+	return reg;
+}
+
+static void lo_measure_txctl_values(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	struct b43_txpower_lo_control *lo = gphy->lo_control;
+	u16 reg, mask;
+	u16 trsw_rx, pga;
+	u16 radio_pctl_reg;
+
+	static const u8 tx_bias_values[] = {
+		0x09, 0x08, 0x0A, 0x01, 0x00,
+		0x02, 0x05, 0x04, 0x06,
+	};
+	static const u8 tx_magn_values[] = {
+		0x70, 0x40,
+	};
+
+	if (!has_loopback_gain(phy)) {
+		radio_pctl_reg = 6;
+		trsw_rx = 2;
+		pga = 0;
+	} else {
+		int lb_gain;	/* Loopback gain (in dB) */
+
+		trsw_rx = 0;
+		lb_gain = gphy->max_lb_gain / 2;
+		if (lb_gain > 10) {
+			radio_pctl_reg = 0;
+			pga = abs(10 - lb_gain) / 6;
+			pga = clamp_val(pga, 0, 15);
+		} else {
+			int cmp_val;
+			int tmp;
+
+			pga = 0;
+			cmp_val = 0x24;
+			if ((phy->rev >= 2) &&
+			    (phy->radio_ver == 0x2050) && (phy->radio_rev == 8))
+				cmp_val = 0x3C;
+			tmp = lb_gain;
+			if ((10 - lb_gain) < cmp_val)
+				tmp = (10 - lb_gain);
+			if (tmp < 0)
+				tmp += 6;
+			else
+				tmp += 3;
+			cmp_val /= 4;
+			tmp /= 4;
+			if (tmp >= cmp_val)
+				radio_pctl_reg = cmp_val;
+			else
+				radio_pctl_reg = tmp;
+		}
+	}
+	b43_radio_maskset(dev, 0x43, 0xFFF0, radio_pctl_reg);
+	b43_gphy_set_baseband_attenuation(dev, 2);
+
+	reg = lo_txctl_register_table(dev, &mask, NULL);
+	mask = ~mask;
+	b43_radio_mask(dev, reg, mask);
+
+	if (has_tx_magnification(phy)) {
+		int i, j;
+		int feedthrough;
+		int min_feedth = 0xFFFF;
+		u8 tx_magn, tx_bias;
+
+		for (i = 0; i < ARRAY_SIZE(tx_magn_values); i++) {
+			tx_magn = tx_magn_values[i];
+			b43_radio_maskset(dev, 0x52, 0xFF0F, tx_magn);
+			for (j = 0; j < ARRAY_SIZE(tx_bias_values); j++) {
+				tx_bias = tx_bias_values[j];
+				b43_radio_maskset(dev, 0x52, 0xFFF0, tx_bias);
+				feedthrough =
+				    lo_measure_feedthrough(dev, 0, pga,
+							   trsw_rx);
+				if (feedthrough < min_feedth) {
+					lo->tx_bias = tx_bias;
+					lo->tx_magn = tx_magn;
+					min_feedth = feedthrough;
+				}
+				if (lo->tx_bias == 0)
+					break;
+			}
+			b43_radio_write16(dev, 0x52,
+					  (b43_radio_read16(dev, 0x52)
+					   & 0xFF00) | lo->tx_bias | lo->
+					  tx_magn);
+		}
+	} else {
+		lo->tx_magn = 0;
+		lo->tx_bias = 0;
+		b43_radio_mask(dev, 0x52, 0xFFF0);	/* TX bias == 0 */
+	}
+	lo->txctl_measured_time = jiffies;
+}
+
+static void lo_read_power_vector(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	struct b43_txpower_lo_control *lo = gphy->lo_control;
+	int i;
+	u64 tmp;
+	u64 power_vector = 0;
+
+	for (i = 0; i < 8; i += 2) {
+		tmp = b43_shm_read16(dev, B43_SHM_SHARED, 0x310 + i);
+		power_vector |= (tmp << (i * 8));
+		/* Clear the vector on the device. */
+		b43_shm_write16(dev, B43_SHM_SHARED, 0x310 + i, 0);
+	}
+	if (power_vector)
+		lo->power_vector = power_vector;
+	lo->pwr_vec_read_time = jiffies;
+}
+
+/* 802.11/LO/GPHY/MeasuringGains */
+static void lo_measure_gain_values(struct b43_wldev *dev,
+				   s16 max_rx_gain, int use_trsw_rx)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	u16 tmp;
+
+	if (max_rx_gain < 0)
+		max_rx_gain = 0;
+
+	if (has_loopback_gain(phy)) {
+		int trsw_rx_gain;
+
+		if (use_trsw_rx) {
+			trsw_rx_gain = gphy->trsw_rx_gain / 2;
+			if (max_rx_gain >= trsw_rx_gain) {
+				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
+			}
+		} else
+			trsw_rx_gain = max_rx_gain;
+		if (trsw_rx_gain < 9) {
+			gphy->lna_lod_gain = 0;
+		} else {
+			gphy->lna_lod_gain = 1;
+			trsw_rx_gain -= 8;
+		}
+		trsw_rx_gain = clamp_val(trsw_rx_gain, 0, 0x2D);
+		gphy->pga_gain = trsw_rx_gain / 3;
+		if (gphy->pga_gain >= 5) {
+			gphy->pga_gain -= 5;
+			gphy->lna_gain = 2;
+		} else
+			gphy->lna_gain = 0;
+	} else {
+		gphy->lna_gain = 0;
+		gphy->trsw_rx_gain = 0x20;
+		if (max_rx_gain >= 0x14) {
+			gphy->lna_lod_gain = 1;
+			gphy->pga_gain = 2;
+		} else if (max_rx_gain >= 0x12) {
+			gphy->lna_lod_gain = 1;
+			gphy->pga_gain = 1;
+		} else if (max_rx_gain >= 0xF) {
+			gphy->lna_lod_gain = 1;
+			gphy->pga_gain = 0;
+		} else {
+			gphy->lna_lod_gain = 0;
+			gphy->pga_gain = 0;
+		}
+	}
+
+	tmp = b43_radio_read16(dev, 0x7A);
+	if (gphy->lna_lod_gain == 0)
+		tmp &= ~0x0008;
+	else
+		tmp |= 0x0008;
+	b43_radio_write16(dev, 0x7A, tmp);
+}
+
+struct lo_g_saved_values {
+	u8 old_channel;
+
+	/* Core registers */
+	u16 reg_3F4;
+	u16 reg_3E2;
+
+	/* PHY registers */
+	u16 phy_lo_mask;
+	u16 phy_extg_01;
+	u16 phy_dacctl_hwpctl;
+	u16 phy_dacctl;
+	u16 phy_cck_14;
+	u16 phy_hpwr_tssictl;
+	u16 phy_analogover;
+	u16 phy_analogoverval;
+	u16 phy_rfover;
+	u16 phy_rfoverval;
+	u16 phy_classctl;
+	u16 phy_cck_3E;
+	u16 phy_crs0;
+	u16 phy_pgactl;
+	u16 phy_cck_2A;
+	u16 phy_syncctl;
+	u16 phy_cck_30;
+	u16 phy_cck_06;
+
+	/* Radio registers */
+	u16 radio_43;
+	u16 radio_7A;
+	u16 radio_52;
+};
+
+static void lo_measure_setup(struct b43_wldev *dev,
+			     struct lo_g_saved_values *sav)
+{
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	struct b43_txpower_lo_control *lo = gphy->lo_control;
+	u16 tmp;
+
+	if (b43_has_hardware_pctl(dev)) {
+		sav->phy_lo_mask = b43_phy_read(dev, B43_PHY_LO_MASK);
+		sav->phy_extg_01 = b43_phy_read(dev, B43_PHY_EXTG(0x01));
+		sav->phy_dacctl_hwpctl = b43_phy_read(dev, B43_PHY_DACCTL);
+		sav->phy_cck_14 = b43_phy_read(dev, B43_PHY_CCK(0x14));
+		sav->phy_hpwr_tssictl = b43_phy_read(dev, B43_PHY_HPWR_TSSICTL);
+
+		b43_phy_set(dev, B43_PHY_HPWR_TSSICTL, 0x100);
+		b43_phy_set(dev, B43_PHY_EXTG(0x01), 0x40);
+		b43_phy_set(dev, B43_PHY_DACCTL, 0x40);
+		b43_phy_set(dev, B43_PHY_CCK(0x14), 0x200);
+	}
+	if (phy->type == B43_PHYTYPE_B &&
+	    phy->radio_ver == 0x2050 && phy->radio_rev < 6) {
+		b43_phy_write(dev, B43_PHY_CCK(0x16), 0x410);
+		b43_phy_write(dev, B43_PHY_CCK(0x17), 0x820);
+	}
+	if (phy->rev >= 2) {
+		sav->phy_analogover = b43_phy_read(dev, B43_PHY_ANALOGOVER);
+		sav->phy_analogoverval =
+		    b43_phy_read(dev, B43_PHY_ANALOGOVERVAL);
+		sav->phy_rfover = b43_phy_read(dev, B43_PHY_RFOVER);
+		sav->phy_rfoverval = b43_phy_read(dev, B43_PHY_RFOVERVAL);
+		sav->phy_classctl = b43_phy_read(dev, B43_PHY_CLASSCTL);
+		sav->phy_cck_3E = b43_phy_read(dev, B43_PHY_CCK(0x3E));
+		sav->phy_crs0 = b43_phy_read(dev, B43_PHY_CRS0);
+
+		b43_phy_mask(dev, B43_PHY_CLASSCTL, 0xFFFC);
+		b43_phy_mask(dev, B43_PHY_CRS0, 0x7FFF);
+		b43_phy_set(dev, B43_PHY_ANALOGOVER, 0x0003);
+		b43_phy_mask(dev, B43_PHY_ANALOGOVERVAL, 0xFFFC);
+		if (phy->type == B43_PHYTYPE_G) {
+			if ((phy->rev >= 7) &&
+			    (sprom->boardflags_lo & B43_BFL_EXTLNA)) {
+				b43_phy_write(dev, B43_PHY_RFOVER, 0x933);
+			} else {
+				b43_phy_write(dev, B43_PHY_RFOVER, 0x133);
+			}
+		} else {
+			b43_phy_write(dev, B43_PHY_RFOVER, 0);
+		}
+		b43_phy_write(dev, B43_PHY_CCK(0x3E), 0);
+	}
+	sav->reg_3F4 = b43_read16(dev, 0x3F4);
+	sav->reg_3E2 = b43_read16(dev, 0x3E2);
+	sav->radio_43 = b43_radio_read16(dev, 0x43);
+	sav->radio_7A = b43_radio_read16(dev, 0x7A);
+	sav->phy_pgactl = b43_phy_read(dev, B43_PHY_PGACTL);
+	sav->phy_cck_2A = b43_phy_read(dev, B43_PHY_CCK(0x2A));
+	sav->phy_syncctl = b43_phy_read(dev, B43_PHY_SYNCCTL);
+	sav->phy_dacctl = b43_phy_read(dev, B43_PHY_DACCTL);
+
+	if (!has_tx_magnification(phy)) {
+		sav->radio_52 = b43_radio_read16(dev, 0x52);
+		sav->radio_52 &= 0x00F0;
+	}
+	if (phy->type == B43_PHYTYPE_B) {
+		sav->phy_cck_30 = b43_phy_read(dev, B43_PHY_CCK(0x30));
+		sav->phy_cck_06 = b43_phy_read(dev, B43_PHY_CCK(0x06));
+		b43_phy_write(dev, B43_PHY_CCK(0x30), 0x00FF);
+		b43_phy_write(dev, B43_PHY_CCK(0x06), 0x3F3F);
+	} else {
+		b43_write16(dev, 0x3E2, b43_read16(dev, 0x3E2)
+			    | 0x8000);
+	}
+	b43_write16(dev, 0x3F4, b43_read16(dev, 0x3F4)
+		    & 0xF000);
+
+	tmp =
+	    (phy->type == B43_PHYTYPE_G) ? B43_PHY_LO_MASK : B43_PHY_CCK(0x2E);
+	b43_phy_write(dev, tmp, 0x007F);
+
+	tmp = sav->phy_syncctl;
+	b43_phy_write(dev, B43_PHY_SYNCCTL, tmp & 0xFF7F);
+	tmp = sav->radio_7A;
+	b43_radio_write16(dev, 0x007A, tmp & 0xFFF0);
+
+	b43_phy_write(dev, B43_PHY_CCK(0x2A), 0x8A3);
+	if (phy->type == B43_PHYTYPE_G ||
+	    (phy->type == B43_PHYTYPE_B &&
+	     phy->radio_ver == 0x2050 && phy->radio_rev >= 6)) {
+		b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x1003);
+	} else
+		b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x0802);
+	if (phy->rev >= 2)
+		b43_dummy_transmission(dev, false, true);
+	b43_gphy_channel_switch(dev, 6, 0);
+	b43_radio_read16(dev, 0x51);	/* dummy read */
+	if (phy->type == B43_PHYTYPE_G)
+		b43_phy_write(dev, B43_PHY_CCK(0x2F), 0);
+
+	/* Re-measure the txctl values, if needed. */
+	if (time_before(lo->txctl_measured_time,
+			jiffies - B43_LO_TXCTL_EXPIRE))
+		lo_measure_txctl_values(dev);
+
+	if (phy->type == B43_PHYTYPE_G && phy->rev >= 3) {
+		b43_phy_write(dev, B43_PHY_LO_MASK, 0xC078);
+	} else {
+		if (phy->type == B43_PHYTYPE_B)
+			b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8078);
+		else
+			b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078);
+	}
+}
+
+static void lo_measure_restore(struct b43_wldev *dev,
+			       struct lo_g_saved_values *sav)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	u16 tmp;
+
+	if (phy->rev >= 2) {
+		b43_phy_write(dev, B43_PHY_PGACTL, 0xE300);
+		tmp = (gphy->pga_gain << 8);
+		b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA0);
+		udelay(5);
+		b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA2);
+		udelay(2);
+		b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA3);
+	} else {
+		tmp = (gphy->pga_gain | 0xEFA0);
+		b43_phy_write(dev, B43_PHY_PGACTL, tmp);
+	}
+	if (phy->type == B43_PHYTYPE_G) {
+		if (phy->rev >= 3)
+			b43_phy_write(dev, B43_PHY_CCK(0x2E), 0xC078);
+		else
+			b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8078);
+		if (phy->rev >= 2)
+			b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x0202);
+		else
+			b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x0101);
+	}
+	b43_write16(dev, 0x3F4, sav->reg_3F4);
+	b43_phy_write(dev, B43_PHY_PGACTL, sav->phy_pgactl);
+	b43_phy_write(dev, B43_PHY_CCK(0x2A), sav->phy_cck_2A);
+	b43_phy_write(dev, B43_PHY_SYNCCTL, sav->phy_syncctl);
+	b43_phy_write(dev, B43_PHY_DACCTL, sav->phy_dacctl);
+	b43_radio_write16(dev, 0x43, sav->radio_43);
+	b43_radio_write16(dev, 0x7A, sav->radio_7A);
+	if (!has_tx_magnification(phy)) {
+		tmp = sav->radio_52;
+		b43_radio_maskset(dev, 0x52, 0xFF0F, tmp);
+	}
+	b43_write16(dev, 0x3E2, sav->reg_3E2);
+	if (phy->type == B43_PHYTYPE_B &&
+	    phy->radio_ver == 0x2050 && phy->radio_rev <= 5) {
+		b43_phy_write(dev, B43_PHY_CCK(0x30), sav->phy_cck_30);
+		b43_phy_write(dev, B43_PHY_CCK(0x06), sav->phy_cck_06);
+	}
+	if (phy->rev >= 2) {
+		b43_phy_write(dev, B43_PHY_ANALOGOVER, sav->phy_analogover);
+		b43_phy_write(dev, B43_PHY_ANALOGOVERVAL,
+			      sav->phy_analogoverval);
+		b43_phy_write(dev, B43_PHY_CLASSCTL, sav->phy_classctl);
+		b43_phy_write(dev, B43_PHY_RFOVER, sav->phy_rfover);
+		b43_phy_write(dev, B43_PHY_RFOVERVAL, sav->phy_rfoverval);
+		b43_phy_write(dev, B43_PHY_CCK(0x3E), sav->phy_cck_3E);
+		b43_phy_write(dev, B43_PHY_CRS0, sav->phy_crs0);
+	}
+	if (b43_has_hardware_pctl(dev)) {
+		tmp = (sav->phy_lo_mask & 0xBFFF);
+		b43_phy_write(dev, B43_PHY_LO_MASK, tmp);
+		b43_phy_write(dev, B43_PHY_EXTG(0x01), sav->phy_extg_01);
+		b43_phy_write(dev, B43_PHY_DACCTL, sav->phy_dacctl_hwpctl);
+		b43_phy_write(dev, B43_PHY_CCK(0x14), sav->phy_cck_14);
+		b43_phy_write(dev, B43_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
+	}
+	b43_gphy_channel_switch(dev, sav->old_channel, 1);
+}
+
+struct b43_lo_g_statemachine {
+	int current_state;
+	int nr_measured;
+	int state_val_multiplier;
+	u16 lowest_feedth;
+	struct b43_loctl min_loctl;
+};
+
+/* Loop over each possible value in this state. */
+static int lo_probe_possible_loctls(struct b43_wldev *dev,
+				    struct b43_loctl *probe_loctl,
+				    struct b43_lo_g_statemachine *d)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	struct b43_loctl test_loctl;
+	struct b43_loctl orig_loctl;
+	struct b43_loctl prev_loctl = {
+		.i = -100,
+		.q = -100,
+	};
+	int i;
+	int begin, end;
+	int found_lower = 0;
+	u16 feedth;
+
+	static const struct b43_loctl modifiers[] = {
+		{.i = 1,.q = 1,},
+		{.i = 1,.q = 0,},
+		{.i = 1,.q = -1,},
+		{.i = 0,.q = -1,},
+		{.i = -1,.q = -1,},
+		{.i = -1,.q = 0,},
+		{.i = -1,.q = 1,},
+		{.i = 0,.q = 1,},
+	};
+
+	if (d->current_state == 0) {
+		begin = 1;
+		end = 8;
+	} else if (d->current_state % 2 == 0) {
+		begin = d->current_state - 1;
+		end = d->current_state + 1;
+	} else {
+		begin = d->current_state - 2;
+		end = d->current_state + 2;
+	}
+	if (begin < 1)
+		begin += 8;
+	if (end > 8)
+		end -= 8;
+
+	memcpy(&orig_loctl, probe_loctl, sizeof(struct b43_loctl));
+	i = begin;
+	d->current_state = i;
+	while (1) {
+		B43_WARN_ON(!(i >= 1 && i <= 8));
+		memcpy(&test_loctl, &orig_loctl, sizeof(struct b43_loctl));
+		test_loctl.i += modifiers[i - 1].i * d->state_val_multiplier;
+		test_loctl.q += modifiers[i - 1].q * d->state_val_multiplier;
+		if ((test_loctl.i != prev_loctl.i ||
+		     test_loctl.q != prev_loctl.q) &&
+		    (abs(test_loctl.i) <= 16 && abs(test_loctl.q) <= 16)) {
+			b43_lo_write(dev, &test_loctl);
+			feedth = lo_measure_feedthrough(dev, gphy->lna_gain,
+							gphy->pga_gain,
+							gphy->trsw_rx_gain);
+			if (feedth < d->lowest_feedth) {
+				memcpy(probe_loctl, &test_loctl,
+				       sizeof(struct b43_loctl));
+				found_lower = 1;
+				d->lowest_feedth = feedth;
+				if ((d->nr_measured < 2) &&
+				    !has_loopback_gain(phy))
+					break;
+			}
+		}
+		memcpy(&prev_loctl, &test_loctl, sizeof(prev_loctl));
+		if (i == end)
+			break;
+		if (i == 8)
+			i = 1;
+		else
+			i++;
+		d->current_state = i;
+	}
+
+	return found_lower;
+}
+
+static void lo_probe_loctls_statemachine(struct b43_wldev *dev,
+					 struct b43_loctl *loctl,
+					 int *max_rx_gain)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	struct b43_lo_g_statemachine d;
+	u16 feedth;
+	int found_lower;
+	struct b43_loctl probe_loctl;
+	int max_repeat = 1, repeat_cnt = 0;
+
+	d.nr_measured = 0;
+	d.state_val_multiplier = 1;
+	if (has_loopback_gain(phy))
+		d.state_val_multiplier = 3;
+
+	memcpy(&d.min_loctl, loctl, sizeof(struct b43_loctl));
+	if (has_loopback_gain(phy))
+		max_repeat = 4;
+	do {
+		b43_lo_write(dev, &d.min_loctl);
+		feedth = lo_measure_feedthrough(dev, gphy->lna_gain,
+						gphy->pga_gain,
+						gphy->trsw_rx_gain);
+		if (feedth < 0x258) {
+			if (feedth >= 0x12C)
+				*max_rx_gain += 6;
+			else
+				*max_rx_gain += 3;
+			feedth = lo_measure_feedthrough(dev, gphy->lna_gain,
+							gphy->pga_gain,
+							gphy->trsw_rx_gain);
+		}
+		d.lowest_feedth = feedth;
+
+		d.current_state = 0;
+		do {
+			B43_WARN_ON(!
+				    (d.current_state >= 0
+				     && d.current_state <= 8));
+			memcpy(&probe_loctl, &d.min_loctl,
+			       sizeof(struct b43_loctl));
+			found_lower =
+			    lo_probe_possible_loctls(dev, &probe_loctl, &d);
+			if (!found_lower)
+				break;
+			if ((probe_loctl.i == d.min_loctl.i) &&
+			    (probe_loctl.q == d.min_loctl.q))
+				break;
+			memcpy(&d.min_loctl, &probe_loctl,
+			       sizeof(struct b43_loctl));
+			d.nr_measured++;
+		} while (d.nr_measured < 24);
+		memcpy(loctl, &d.min_loctl, sizeof(struct b43_loctl));
+
+		if (has_loopback_gain(phy)) {
+			if (d.lowest_feedth > 0x1194)
+				*max_rx_gain -= 6;
+			else if (d.lowest_feedth < 0x5DC)
+				*max_rx_gain += 3;
+			if (repeat_cnt == 0) {
+				if (d.lowest_feedth <= 0x5DC) {
+					d.state_val_multiplier = 1;
+					repeat_cnt++;
+				} else
+					d.state_val_multiplier = 2;
+			} else if (repeat_cnt == 2)
+				d.state_val_multiplier = 1;
+		}
+		lo_measure_gain_values(dev, *max_rx_gain,
+				       has_loopback_gain(phy));
+	} while (++repeat_cnt < max_repeat);
+}
+
+static
+struct b43_lo_calib *b43_calibrate_lo_setting(struct b43_wldev *dev,
+					      const struct b43_bbatt *bbatt,
+					      const struct b43_rfatt *rfatt)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	struct b43_loctl loctl = {
+		.i = 0,
+		.q = 0,
+	};
+	int max_rx_gain;
+	struct b43_lo_calib *cal;
+	struct lo_g_saved_values uninitialized_var(saved_regs);
+	/* Values from the "TXCTL Register and Value Table" */
+	u16 txctl_reg;
+	u16 txctl_value;
+	u16 pad_mix_gain;
+
+	saved_regs.old_channel = phy->channel;
+	b43_mac_suspend(dev);
+	lo_measure_setup(dev, &saved_regs);
+
+	txctl_reg = lo_txctl_register_table(dev, &txctl_value, &pad_mix_gain);
+
+	b43_radio_maskset(dev, 0x43, 0xFFF0, rfatt->att);
+	b43_radio_maskset(dev, txctl_reg, ~txctl_value, (rfatt->with_padmix ? txctl_value :0));
+
+	max_rx_gain = rfatt->att * 2;
+	max_rx_gain += bbatt->att / 2;
+	if (rfatt->with_padmix)
+		max_rx_gain -= pad_mix_gain;
+	if (has_loopback_gain(phy))
+		max_rx_gain += gphy->max_lb_gain;
+	lo_measure_gain_values(dev, max_rx_gain,
+			       has_loopback_gain(phy));
+
+	b43_gphy_set_baseband_attenuation(dev, bbatt->att);
+	lo_probe_loctls_statemachine(dev, &loctl, &max_rx_gain);
+
+	lo_measure_restore(dev, &saved_regs);
+	b43_mac_enable(dev);
+
+	if (b43_debug(dev, B43_DBG_LO)) {
+		b43dbg(dev->wl, "LO: Calibrated for BB(%u), RF(%u,%u) "
+		       "=> I=%d Q=%d\n",
+		       bbatt->att, rfatt->att, rfatt->with_padmix,
+		       loctl.i, loctl.q);
+	}
+
+	cal = kmalloc(sizeof(*cal), GFP_KERNEL);
+	if (!cal) {
+		b43warn(dev->wl, "LO calib: out of memory\n");
+		return NULL;
+	}
+	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
+	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
+	memcpy(&cal->ctl, &loctl, sizeof(loctl));
+	cal->calib_time = jiffies;
+	INIT_LIST_HEAD(&cal->list);
+
+	return cal;
+}
+
+/* Get a calibrated LO setting for the given attenuation values.
+ * Might return a NULL pointer under OOM! */
+static
+struct b43_lo_calib *b43_get_calib_lo_settings(struct b43_wldev *dev,
+					       const struct b43_bbatt *bbatt,
+					       const struct b43_rfatt *rfatt)
+{
+	struct b43_txpower_lo_control *lo = dev->phy.g->lo_control;
+	struct b43_lo_calib *c;
+
+	c = b43_find_lo_calib(lo, bbatt, rfatt);
+	if (c)
+		return c;
+	/* Not in the list of calibrated LO settings.
+	 * Calibrate it now. */
+	c = b43_calibrate_lo_setting(dev, bbatt, rfatt);
+	if (!c)
+		return NULL;
+	list_add(&c->list, &lo->calib_list);
+
+	return c;
+}
+
+void b43_gphy_dc_lt_init(struct b43_wldev *dev, bool update_all)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	struct b43_txpower_lo_control *lo = gphy->lo_control;
+	int i;
+	int rf_offset, bb_offset;
+	const struct b43_rfatt *rfatt;
+	const struct b43_bbatt *bbatt;
+	u64 power_vector;
+	bool table_changed = false;
+
+	BUILD_BUG_ON(B43_DC_LT_SIZE != 32);
+	B43_WARN_ON(lo->rfatt_list.len * lo->bbatt_list.len > 64);
+
+	power_vector = lo->power_vector;
+	if (!update_all && !power_vector)
+		return; /* Nothing to do. */
+
+	/* Suspend the MAC now to avoid continuous suspend/enable
+	 * cycles in the loop. */
+	b43_mac_suspend(dev);
+
+	for (i = 0; i < B43_DC_LT_SIZE * 2; i++) {
+		struct b43_lo_calib *cal;
+		int idx;
+		u16 val;
+
+		if (!update_all && !(power_vector & (((u64)1ULL) << i)))
+			continue;
+		/* Update the table entry for this power_vector bit.
+		 * The table rows are RFatt entries and columns are BBatt. */
+		bb_offset = i / lo->rfatt_list.len;
+		rf_offset = i % lo->rfatt_list.len;
+		bbatt = &(lo->bbatt_list.list[bb_offset]);
+		rfatt = &(lo->rfatt_list.list[rf_offset]);
+
+		cal = b43_calibrate_lo_setting(dev, bbatt, rfatt);
+		if (!cal) {
+			b43warn(dev->wl, "LO: Could not "
+				"calibrate DC table entry\n");
+			continue;
+		}
+		/*FIXME: Is Q really in the low nibble? */
+		val = (u8)(cal->ctl.q);
+		val |= ((u8)(cal->ctl.i)) << 4;
+		kfree(cal);
+
+		/* Get the index into the hardware DC LT. */
+		idx = i / 2;
+		/* Change the table in memory. */
+		if (i % 2) {
+			/* Change the high byte. */
+			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00FF)
+					 | ((val & 0x00FF) << 8);
+		} else {
+			/* Change the low byte. */
+			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xFF00)
+					 | (val & 0x00FF);
+		}
+		table_changed = true;
+	}
+	if (table_changed) {
+		/* The table changed in memory. Update the hardware table. */
+		for (i = 0; i < B43_DC_LT_SIZE; i++)
+			b43_phy_write(dev, 0x3A0 + i, lo->dc_lt[i]);
+	}
+	b43_mac_enable(dev);
+}
+
+/* Fixup the RF attenuation value for the case where we are
+ * using the PAD mixer. */
+static inline void b43_lo_fixup_rfatt(struct b43_rfatt *rf)
+{
+	if (!rf->with_padmix)
+		return;
+	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
+		rf->att = 4;
+}
+
+void b43_lo_g_adjust(struct b43_wldev *dev)
+{
+	struct b43_phy_g *gphy = dev->phy.g;
+	struct b43_lo_calib *cal;
+	struct b43_rfatt rf;
+
+	memcpy(&rf, &gphy->rfatt, sizeof(rf));
+	b43_lo_fixup_rfatt(&rf);
+
+	cal = b43_get_calib_lo_settings(dev, &gphy->bbatt, &rf);
+	if (!cal)
+		return;
+	b43_lo_write(dev, &cal->ctl);
+}
+
+void b43_lo_g_adjust_to(struct b43_wldev *dev,
+			u16 rfatt, u16 bbatt, u16 tx_control)
+{
+	struct b43_rfatt rf;
+	struct b43_bbatt bb;
+	struct b43_lo_calib *cal;
+
+	memset(&rf, 0, sizeof(rf));
+	memset(&bb, 0, sizeof(bb));
+	rf.att = rfatt;
+	bb.att = bbatt;
+	b43_lo_fixup_rfatt(&rf);
+	cal = b43_get_calib_lo_settings(dev, &bb, &rf);
+	if (!cal)
+		return;
+	b43_lo_write(dev, &cal->ctl);
+}
+
+/* Periodic LO maintenance work */
+void b43_lo_g_maintenance_work(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	struct b43_txpower_lo_control *lo = gphy->lo_control;
+	unsigned long now;
+	unsigned long expire;
+	struct b43_lo_calib *cal, *tmp;
+	bool current_item_expired = false;
+	bool hwpctl;
+
+	if (!lo)
+		return;
+	now = jiffies;
+	hwpctl = b43_has_hardware_pctl(dev);
+
+	if (hwpctl) {
+		/* Read the power vector and update it, if needed. */
+		expire = now - B43_LO_PWRVEC_EXPIRE;
+		if (time_before(lo->pwr_vec_read_time, expire)) {
+			lo_read_power_vector(dev);
+			b43_gphy_dc_lt_init(dev, 0);
+		}
+		//FIXME Recalc the whole DC table from time to time?
+	}
+
+	if (hwpctl)
+		return;
+	/* Search for expired LO settings. Remove them.
+	 * Recalibrate the current setting, if expired. */
+	expire = now - B43_LO_CALIB_EXPIRE;
+	list_for_each_entry_safe(cal, tmp, &lo->calib_list, list) {
+		if (!time_before(cal->calib_time, expire))
+			continue;
+		/* This item expired. */
+		if (b43_compare_bbatt(&cal->bbatt, &gphy->bbatt) &&
+		    b43_compare_rfatt(&cal->rfatt, &gphy->rfatt)) {
+			B43_WARN_ON(current_item_expired);
+			current_item_expired = true;
+		}
+		if (b43_debug(dev, B43_DBG_LO)) {
+			b43dbg(dev->wl, "LO: Item BB(%u), RF(%u,%u), "
+			       "I=%d, Q=%d expired\n",
+			       cal->bbatt.att, cal->rfatt.att,
+			       cal->rfatt.with_padmix,
+			       cal->ctl.i, cal->ctl.q);
+		}
+		list_del(&cal->list);
+		kfree(cal);
+	}
+	if (current_item_expired || unlikely(list_empty(&lo->calib_list))) {
+		/* Recalibrate currently used LO setting. */
+		if (b43_debug(dev, B43_DBG_LO))
+			b43dbg(dev->wl, "LO: Recalibrating current LO setting\n");
+		cal = b43_calibrate_lo_setting(dev, &gphy->bbatt, &gphy->rfatt);
+		if (cal) {
+			list_add(&cal->list, &lo->calib_list);
+			b43_lo_write(dev, &cal->ctl);
+		} else
+			b43warn(dev->wl, "Failed to recalibrate current LO setting\n");
+	}
+}
+
+void b43_lo_g_cleanup(struct b43_wldev *dev)
+{
+	struct b43_txpower_lo_control *lo = dev->phy.g->lo_control;
+	struct b43_lo_calib *cal, *tmp;
+
+	if (!lo)
+		return;
+	list_for_each_entry_safe(cal, tmp, &lo->calib_list, list) {
+		list_del(&cal->list);
+		kfree(cal);
+	}
+}
+
+/* LO Initialization */
+void b43_lo_g_init(struct b43_wldev *dev)
+{
+	if (b43_has_hardware_pctl(dev)) {
+		lo_read_power_vector(dev);
+		b43_gphy_dc_lt_init(dev, 1);
+	}
+}
diff --git a/drivers/net/wireless/broadcom/b43/lo.h b/drivers/net/wireless/broadcom/b43/lo.h
new file mode 100644
index 0000000..66e07ab
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/lo.h
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_LO_H_
+#define B43_LO_H_
+
+/* G-PHY Local Oscillator */
+
+#include "phy_g.h"
+
+struct b43_wldev;
+
+/* Local Oscillator control value-pair. */
+struct b43_loctl {
+	/* Control values. */
+	s8 i;
+	s8 q;
+};
+/* Debugging: Poison value for i and q values. */
+#define B43_LOCTL_POISON	111
+
+/* This struct holds calibrated LO settings for a set of
+ * Baseband and RF attenuation settings. */
+struct b43_lo_calib {
+	/* The set of attenuation values this set of LO
+	 * control values is calibrated for. */
+	struct b43_bbatt bbatt;
+	struct b43_rfatt rfatt;
+	/* The set of control values for the LO. */
+	struct b43_loctl ctl;
+	/* The time when these settings were calibrated (in jiffies) */
+	unsigned long calib_time;
+	/* List. */
+	struct list_head list;
+};
+
+/* Size of the DC Lookup Table in 16bit words. */
+#define B43_DC_LT_SIZE		32
+
+/* Local Oscillator calibration information */
+struct b43_txpower_lo_control {
+	/* Lists of RF and BB attenuation values for this device.
+	 * Used for building hardware power control tables. */
+	struct b43_rfatt_list rfatt_list;
+	struct b43_bbatt_list bbatt_list;
+
+	/* The DC Lookup Table is cached in memory here.
+	 * Note that this is only used for Hardware Power Control. */
+	u16 dc_lt[B43_DC_LT_SIZE];
+
+	/* List of calibrated control values (struct b43_lo_calib). */
+	struct list_head calib_list;
+	/* Last time the power vector was read (jiffies). */
+	unsigned long pwr_vec_read_time;
+	/* Last time the txctl values were measured (jiffies). */
+	unsigned long txctl_measured_time;
+
+	/* Current TX Bias value */
+	u8 tx_bias;
+	/* Current TX Magnification Value (if used by the device) */
+	u8 tx_magn;
+
+	/* Saved device PowerVector */
+	u64 power_vector;
+};
+
+/* Calibration expire timeouts.
+ * Timeouts must be multiple of 15 seconds. To make sure
+ * the item really expired when the 15 second timer hits, we
+ * subtract two additional seconds from the timeout. */
+#define B43_LO_CALIB_EXPIRE	(HZ * (30 - 2))
+#define B43_LO_PWRVEC_EXPIRE	(HZ * (30 - 2))
+#define B43_LO_TXCTL_EXPIRE	(HZ * (180 - 4))
+
+
+/* Adjust the Local Oscillator to the saved attenuation
+ * and txctl values.
+ */
+void b43_lo_g_adjust(struct b43_wldev *dev);
+/* Adjust to specific values. */
+void b43_lo_g_adjust_to(struct b43_wldev *dev,
+			u16 rfatt, u16 bbatt, u16 tx_control);
+
+void b43_gphy_dc_lt_init(struct b43_wldev *dev, bool update_all);
+
+void b43_lo_g_maintenance_work(struct b43_wldev *dev);
+void b43_lo_g_cleanup(struct b43_wldev *dev);
+void b43_lo_g_init(struct b43_wldev *dev);
+
+#endif /* B43_LO_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c
new file mode 100644
index 0000000..b37e739
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/main.c
@@ -0,0 +1,5886 @@
+/*
+
+  Broadcom B43 wireless driver
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>
+  Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
+  Copyright (c) 2005-2009 Michael Buesch <m@bues.ch>
+  Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
+  Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
+  Copyright (c) 2010-2011 Rafał Miłecki <zajec5@gmail.com>
+
+  SDIO support
+  Copyright (c) 2009 Albert Herranz <albert_herranz@yahoo.es>
+
+  Some parts of the code in this file are derived from the ipw2200
+  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+
+  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/delay.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/if_arp.h>
+#include <linux/etherdevice.h>
+#include <linux/firmware.h>
+#include <linux/workqueue.h>
+#include <linux/skbuff.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <asm/unaligned.h>
+
+#include "b43.h"
+#include "main.h"
+#include "debugfs.h"
+#include "phy_common.h"
+#include "phy_g.h"
+#include "phy_n.h"
+#include "dma.h"
+#include "pio.h"
+#include "sysfs.h"
+#include "xmit.h"
+#include "lo.h"
+#include "sdio.h"
+#include <linux/mmc/sdio_func.h>
+
+MODULE_DESCRIPTION("Broadcom B43 wireless driver");
+MODULE_AUTHOR("Martin Langer");
+MODULE_AUTHOR("Stefano Brivio");
+MODULE_AUTHOR("Michael Buesch");
+MODULE_AUTHOR("Gábor Stefanik");
+MODULE_AUTHOR("Rafał Miłecki");
+MODULE_LICENSE("GPL");
+
+MODULE_FIRMWARE("b43/ucode11.fw");
+MODULE_FIRMWARE("b43/ucode13.fw");
+MODULE_FIRMWARE("b43/ucode14.fw");
+MODULE_FIRMWARE("b43/ucode15.fw");
+MODULE_FIRMWARE("b43/ucode16_lp.fw");
+MODULE_FIRMWARE("b43/ucode16_mimo.fw");
+MODULE_FIRMWARE("b43/ucode24_lcn.fw");
+MODULE_FIRMWARE("b43/ucode25_lcn.fw");
+MODULE_FIRMWARE("b43/ucode25_mimo.fw");
+MODULE_FIRMWARE("b43/ucode26_mimo.fw");
+MODULE_FIRMWARE("b43/ucode29_mimo.fw");
+MODULE_FIRMWARE("b43/ucode33_lcn40.fw");
+MODULE_FIRMWARE("b43/ucode30_mimo.fw");
+MODULE_FIRMWARE("b43/ucode5.fw");
+MODULE_FIRMWARE("b43/ucode40.fw");
+MODULE_FIRMWARE("b43/ucode42.fw");
+MODULE_FIRMWARE("b43/ucode9.fw");
+
+static int modparam_bad_frames_preempt;
+module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
+MODULE_PARM_DESC(bad_frames_preempt,
+		 "enable(1) / disable(0) Bad Frames Preemption");
+
+static char modparam_fwpostfix[16];
+module_param_string(fwpostfix, modparam_fwpostfix, 16, 0444);
+MODULE_PARM_DESC(fwpostfix, "Postfix for the .fw files to load.");
+
+static int modparam_hwpctl;
+module_param_named(hwpctl, modparam_hwpctl, int, 0444);
+MODULE_PARM_DESC(hwpctl, "Enable hardware-side power control (default off)");
+
+static int modparam_nohwcrypt;
+module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
+
+static int modparam_hwtkip;
+module_param_named(hwtkip, modparam_hwtkip, int, 0444);
+MODULE_PARM_DESC(hwtkip, "Enable hardware tkip.");
+
+static int modparam_qos = 1;
+module_param_named(qos, modparam_qos, int, 0444);
+MODULE_PARM_DESC(qos, "Enable QOS support (default on)");
+
+static int modparam_btcoex = 1;
+module_param_named(btcoex, modparam_btcoex, int, 0444);
+MODULE_PARM_DESC(btcoex, "Enable Bluetooth coexistence (default on)");
+
+int b43_modparam_verbose = B43_VERBOSITY_DEFAULT;
+module_param_named(verbose, b43_modparam_verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug");
+
+static int b43_modparam_pio = 0;
+module_param_named(pio, b43_modparam_pio, int, 0644);
+MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO");
+
+static int modparam_allhwsupport = !IS_ENABLED(CONFIG_BRCMSMAC);
+module_param_named(allhwsupport, modparam_allhwsupport, int, 0444);
+MODULE_PARM_DESC(allhwsupport, "Enable support for all hardware (even it if overlaps with the brcmsmac driver)");
+
+#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, 0x15, 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, 0x1C, BCMA_ANY_CLASS),
+	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1D, BCMA_ANY_CLASS),
+	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1E, BCMA_ANY_CLASS),
+	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x28, BCMA_ANY_CLASS),
+	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x2A, BCMA_ANY_CLASS),
+	{},
+};
+MODULE_DEVICE_TABLE(bcma, b43_bcma_tbl);
+#endif
+
+#ifdef CONFIG_B43_SSB
+static const struct ssb_device_id b43_ssb_tbl[] = {
+	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5),
+	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 6),
+	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 7),
+	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 9),
+	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 10),
+	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 11),
+	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 12),
+	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 13),
+	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 15),
+	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 16),
+	{},
+};
+MODULE_DEVICE_TABLE(ssb, b43_ssb_tbl);
+#endif
+
+/* Channel and ratetables are shared for all devices.
+ * They can't be const, because ieee80211 puts some precalculated
+ * data in there. This data is the same for all devices, so we don't
+ * get concurrency issues */
+#define RATETAB_ENT(_rateid, _flags) \
+	{								\
+		.bitrate	= B43_RATE_TO_BASE100KBPS(_rateid),	\
+		.hw_value	= (_rateid),				\
+		.flags		= (_flags),				\
+	}
+
+/*
+ * NOTE: When changing this, sync with xmit.c's
+ *	 b43_plcp_get_bitrate_idx_* functions!
+ */
+static struct ieee80211_rate __b43_ratetable[] = {
+	RATETAB_ENT(B43_CCK_RATE_1MB, 0),
+	RATETAB_ENT(B43_CCK_RATE_2MB, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATETAB_ENT(B43_CCK_RATE_5MB, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATETAB_ENT(B43_CCK_RATE_11MB, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATETAB_ENT(B43_OFDM_RATE_6MB, 0),
+	RATETAB_ENT(B43_OFDM_RATE_9MB, 0),
+	RATETAB_ENT(B43_OFDM_RATE_12MB, 0),
+	RATETAB_ENT(B43_OFDM_RATE_18MB, 0),
+	RATETAB_ENT(B43_OFDM_RATE_24MB, 0),
+	RATETAB_ENT(B43_OFDM_RATE_36MB, 0),
+	RATETAB_ENT(B43_OFDM_RATE_48MB, 0),
+	RATETAB_ENT(B43_OFDM_RATE_54MB, 0),
+};
+
+#define b43_a_ratetable		(__b43_ratetable + 4)
+#define b43_a_ratetable_size	8
+#define b43_b_ratetable		(__b43_ratetable + 0)
+#define b43_b_ratetable_size	4
+#define b43_g_ratetable		(__b43_ratetable + 0)
+#define b43_g_ratetable_size	12
+
+#define CHAN2G(_channel, _freq, _flags) {			\
+	.band			= NL80211_BAND_2GHZ,		\
+	.center_freq		= (_freq),			\
+	.hw_value		= (_channel),			\
+	.flags			= (_flags),			\
+	.max_antenna_gain	= 0,				\
+	.max_power		= 30,				\
+}
+static struct ieee80211_channel b43_2ghz_chantable[] = {
+	CHAN2G(1, 2412, 0),
+	CHAN2G(2, 2417, 0),
+	CHAN2G(3, 2422, 0),
+	CHAN2G(4, 2427, 0),
+	CHAN2G(5, 2432, 0),
+	CHAN2G(6, 2437, 0),
+	CHAN2G(7, 2442, 0),
+	CHAN2G(8, 2447, 0),
+	CHAN2G(9, 2452, 0),
+	CHAN2G(10, 2457, 0),
+	CHAN2G(11, 2462, 0),
+	CHAN2G(12, 2467, 0),
+	CHAN2G(13, 2472, 0),
+	CHAN2G(14, 2484, 0),
+};
+
+/* No support for the last 3 channels (12, 13, 14) */
+#define b43_2ghz_chantable_limited_size		11
+#undef CHAN2G
+
+#define CHAN4G(_channel, _flags) {				\
+	.band			= NL80211_BAND_5GHZ,		\
+	.center_freq		= 4000 + (5 * (_channel)),	\
+	.hw_value		= (_channel),			\
+	.flags			= (_flags),			\
+	.max_antenna_gain	= 0,				\
+	.max_power		= 30,				\
+}
+#define CHAN5G(_channel, _flags) {				\
+	.band			= NL80211_BAND_5GHZ,		\
+	.center_freq		= 5000 + (5 * (_channel)),	\
+	.hw_value		= (_channel),			\
+	.flags			= (_flags),			\
+	.max_antenna_gain	= 0,				\
+	.max_power		= 30,				\
+}
+static struct ieee80211_channel b43_5ghz_nphy_chantable[] = {
+	CHAN4G(184, 0),		CHAN4G(186, 0),
+	CHAN4G(188, 0),		CHAN4G(190, 0),
+	CHAN4G(192, 0),		CHAN4G(194, 0),
+	CHAN4G(196, 0),		CHAN4G(198, 0),
+	CHAN4G(200, 0),		CHAN4G(202, 0),
+	CHAN4G(204, 0),		CHAN4G(206, 0),
+	CHAN4G(208, 0),		CHAN4G(210, 0),
+	CHAN4G(212, 0),		CHAN4G(214, 0),
+	CHAN4G(216, 0),		CHAN4G(218, 0),
+	CHAN4G(220, 0),		CHAN4G(222, 0),
+	CHAN4G(224, 0),		CHAN4G(226, 0),
+	CHAN4G(228, 0),
+	CHAN5G(32, 0),		CHAN5G(34, 0),
+	CHAN5G(36, 0),		CHAN5G(38, 0),
+	CHAN5G(40, 0),		CHAN5G(42, 0),
+	CHAN5G(44, 0),		CHAN5G(46, 0),
+	CHAN5G(48, 0),		CHAN5G(50, 0),
+	CHAN5G(52, 0),		CHAN5G(54, 0),
+	CHAN5G(56, 0),		CHAN5G(58, 0),
+	CHAN5G(60, 0),		CHAN5G(62, 0),
+	CHAN5G(64, 0),		CHAN5G(66, 0),
+	CHAN5G(68, 0),		CHAN5G(70, 0),
+	CHAN5G(72, 0),		CHAN5G(74, 0),
+	CHAN5G(76, 0),		CHAN5G(78, 0),
+	CHAN5G(80, 0),		CHAN5G(82, 0),
+	CHAN5G(84, 0),		CHAN5G(86, 0),
+	CHAN5G(88, 0),		CHAN5G(90, 0),
+	CHAN5G(92, 0),		CHAN5G(94, 0),
+	CHAN5G(96, 0),		CHAN5G(98, 0),
+	CHAN5G(100, 0),		CHAN5G(102, 0),
+	CHAN5G(104, 0),		CHAN5G(106, 0),
+	CHAN5G(108, 0),		CHAN5G(110, 0),
+	CHAN5G(112, 0),		CHAN5G(114, 0),
+	CHAN5G(116, 0),		CHAN5G(118, 0),
+	CHAN5G(120, 0),		CHAN5G(122, 0),
+	CHAN5G(124, 0),		CHAN5G(126, 0),
+	CHAN5G(128, 0),		CHAN5G(130, 0),
+	CHAN5G(132, 0),		CHAN5G(134, 0),
+	CHAN5G(136, 0),		CHAN5G(138, 0),
+	CHAN5G(140, 0),		CHAN5G(142, 0),
+	CHAN5G(144, 0),		CHAN5G(145, 0),
+	CHAN5G(146, 0),		CHAN5G(147, 0),
+	CHAN5G(148, 0),		CHAN5G(149, 0),
+	CHAN5G(150, 0),		CHAN5G(151, 0),
+	CHAN5G(152, 0),		CHAN5G(153, 0),
+	CHAN5G(154, 0),		CHAN5G(155, 0),
+	CHAN5G(156, 0),		CHAN5G(157, 0),
+	CHAN5G(158, 0),		CHAN5G(159, 0),
+	CHAN5G(160, 0),		CHAN5G(161, 0),
+	CHAN5G(162, 0),		CHAN5G(163, 0),
+	CHAN5G(164, 0),		CHAN5G(165, 0),
+	CHAN5G(166, 0),		CHAN5G(168, 0),
+	CHAN5G(170, 0),		CHAN5G(172, 0),
+	CHAN5G(174, 0),		CHAN5G(176, 0),
+	CHAN5G(178, 0),		CHAN5G(180, 0),
+	CHAN5G(182, 0),
+};
+
+static struct ieee80211_channel b43_5ghz_nphy_chantable_limited[] = {
+	CHAN5G(36, 0),		CHAN5G(40, 0),
+	CHAN5G(44, 0),		CHAN5G(48, 0),
+	CHAN5G(149, 0),		CHAN5G(153, 0),
+	CHAN5G(157, 0),		CHAN5G(161, 0),
+	CHAN5G(165, 0),
+};
+
+static struct ieee80211_channel b43_5ghz_aphy_chantable[] = {
+	CHAN5G(34, 0),		CHAN5G(36, 0),
+	CHAN5G(38, 0),		CHAN5G(40, 0),
+	CHAN5G(42, 0),		CHAN5G(44, 0),
+	CHAN5G(46, 0),		CHAN5G(48, 0),
+	CHAN5G(52, 0),		CHAN5G(56, 0),
+	CHAN5G(60, 0),		CHAN5G(64, 0),
+	CHAN5G(100, 0),		CHAN5G(104, 0),
+	CHAN5G(108, 0),		CHAN5G(112, 0),
+	CHAN5G(116, 0),		CHAN5G(120, 0),
+	CHAN5G(124, 0),		CHAN5G(128, 0),
+	CHAN5G(132, 0),		CHAN5G(136, 0),
+	CHAN5G(140, 0),		CHAN5G(149, 0),
+	CHAN5G(153, 0),		CHAN5G(157, 0),
+	CHAN5G(161, 0),		CHAN5G(165, 0),
+	CHAN5G(184, 0),		CHAN5G(188, 0),
+	CHAN5G(192, 0),		CHAN5G(196, 0),
+	CHAN5G(200, 0),		CHAN5G(204, 0),
+	CHAN5G(208, 0),		CHAN5G(212, 0),
+	CHAN5G(216, 0),
+};
+#undef CHAN4G
+#undef CHAN5G
+
+static struct ieee80211_supported_band b43_band_5GHz_nphy = {
+	.band		= NL80211_BAND_5GHZ,
+	.channels	= b43_5ghz_nphy_chantable,
+	.n_channels	= ARRAY_SIZE(b43_5ghz_nphy_chantable),
+	.bitrates	= b43_a_ratetable,
+	.n_bitrates	= b43_a_ratetable_size,
+};
+
+static struct ieee80211_supported_band b43_band_5GHz_nphy_limited = {
+	.band		= NL80211_BAND_5GHZ,
+	.channels	= b43_5ghz_nphy_chantable_limited,
+	.n_channels	= ARRAY_SIZE(b43_5ghz_nphy_chantable_limited),
+	.bitrates	= b43_a_ratetable,
+	.n_bitrates	= b43_a_ratetable_size,
+};
+
+static struct ieee80211_supported_band b43_band_5GHz_aphy = {
+	.band		= NL80211_BAND_5GHZ,
+	.channels	= b43_5ghz_aphy_chantable,
+	.n_channels	= ARRAY_SIZE(b43_5ghz_aphy_chantable),
+	.bitrates	= b43_a_ratetable,
+	.n_bitrates	= b43_a_ratetable_size,
+};
+
+static struct ieee80211_supported_band b43_band_2GHz = {
+	.band		= NL80211_BAND_2GHZ,
+	.channels	= b43_2ghz_chantable,
+	.n_channels	= ARRAY_SIZE(b43_2ghz_chantable),
+	.bitrates	= b43_g_ratetable,
+	.n_bitrates	= b43_g_ratetable_size,
+};
+
+static struct ieee80211_supported_band b43_band_2ghz_limited = {
+	.band		= NL80211_BAND_2GHZ,
+	.channels	= b43_2ghz_chantable,
+	.n_channels	= b43_2ghz_chantable_limited_size,
+	.bitrates	= b43_g_ratetable,
+	.n_bitrates	= b43_g_ratetable_size,
+};
+
+static void b43_wireless_core_exit(struct b43_wldev *dev);
+static int b43_wireless_core_init(struct b43_wldev *dev);
+static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev);
+static int b43_wireless_core_start(struct b43_wldev *dev);
+static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
+				    struct ieee80211_vif *vif,
+				    struct ieee80211_bss_conf *conf,
+				    u32 changed);
+
+static int b43_ratelimit(struct b43_wl *wl)
+{
+	if (!wl || !wl->current_dev)
+		return 1;
+	if (b43_status(wl->current_dev) < B43_STAT_STARTED)
+		return 1;
+	/* We are up and running.
+	 * Ratelimit the messages to avoid DoS over the net. */
+	return net_ratelimit();
+}
+
+void b43info(struct b43_wl *wl, const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+
+	if (b43_modparam_verbose < B43_VERBOSITY_INFO)
+		return;
+	if (!b43_ratelimit(wl))
+		return;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	printk(KERN_INFO "b43-%s: %pV",
+	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
+	va_end(args);
+}
+
+void b43err(struct b43_wl *wl, const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+
+	if (b43_modparam_verbose < B43_VERBOSITY_ERROR)
+		return;
+	if (!b43_ratelimit(wl))
+		return;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	printk(KERN_ERR "b43-%s ERROR: %pV",
+	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
+	va_end(args);
+}
+
+void b43warn(struct b43_wl *wl, const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+
+	if (b43_modparam_verbose < B43_VERBOSITY_WARN)
+		return;
+	if (!b43_ratelimit(wl))
+		return;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	printk(KERN_WARNING "b43-%s warning: %pV",
+	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
+	va_end(args);
+}
+
+void b43dbg(struct b43_wl *wl, const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+
+	if (b43_modparam_verbose < B43_VERBOSITY_DEBUG)
+		return;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	printk(KERN_DEBUG "b43-%s debug: %pV",
+	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
+	va_end(args);
+}
+
+static void b43_ram_write(struct b43_wldev *dev, u16 offset, u32 val)
+{
+	u32 macctl;
+
+	B43_WARN_ON(offset % 4 != 0);
+
+	macctl = b43_read32(dev, B43_MMIO_MACCTL);
+	if (macctl & B43_MACCTL_BE)
+		val = swab32(val);
+
+	b43_write32(dev, B43_MMIO_RAM_CONTROL, offset);
+	mmiowb();
+	b43_write32(dev, B43_MMIO_RAM_DATA, val);
+}
+
+static inline void b43_shm_control_word(struct b43_wldev *dev,
+					u16 routing, u16 offset)
+{
+	u32 control;
+
+	/* "offset" is the WORD offset. */
+	control = routing;
+	control <<= 16;
+	control |= offset;
+	b43_write32(dev, B43_MMIO_SHM_CONTROL, control);
+}
+
+u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset)
+{
+	u32 ret;
+
+	if (routing == B43_SHM_SHARED) {
+		B43_WARN_ON(offset & 0x0001);
+		if (offset & 0x0003) {
+			/* Unaligned access */
+			b43_shm_control_word(dev, routing, offset >> 2);
+			ret = b43_read16(dev, B43_MMIO_SHM_DATA_UNALIGNED);
+			b43_shm_control_word(dev, routing, (offset >> 2) + 1);
+			ret |= ((u32)b43_read16(dev, B43_MMIO_SHM_DATA)) << 16;
+
+			goto out;
+		}
+		offset >>= 2;
+	}
+	b43_shm_control_word(dev, routing, offset);
+	ret = b43_read32(dev, B43_MMIO_SHM_DATA);
+out:
+	return ret;
+}
+
+u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset)
+{
+	u16 ret;
+
+	if (routing == B43_SHM_SHARED) {
+		B43_WARN_ON(offset & 0x0001);
+		if (offset & 0x0003) {
+			/* Unaligned access */
+			b43_shm_control_word(dev, routing, offset >> 2);
+			ret = b43_read16(dev, B43_MMIO_SHM_DATA_UNALIGNED);
+
+			goto out;
+		}
+		offset >>= 2;
+	}
+	b43_shm_control_word(dev, routing, offset);
+	ret = b43_read16(dev, B43_MMIO_SHM_DATA);
+out:
+	return ret;
+}
+
+void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value)
+{
+	if (routing == B43_SHM_SHARED) {
+		B43_WARN_ON(offset & 0x0001);
+		if (offset & 0x0003) {
+			/* Unaligned access */
+			b43_shm_control_word(dev, routing, offset >> 2);
+			b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED,
+				    value & 0xFFFF);
+			b43_shm_control_word(dev, routing, (offset >> 2) + 1);
+			b43_write16(dev, B43_MMIO_SHM_DATA,
+				    (value >> 16) & 0xFFFF);
+			return;
+		}
+		offset >>= 2;
+	}
+	b43_shm_control_word(dev, routing, offset);
+	b43_write32(dev, B43_MMIO_SHM_DATA, value);
+}
+
+void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value)
+{
+	if (routing == B43_SHM_SHARED) {
+		B43_WARN_ON(offset & 0x0001);
+		if (offset & 0x0003) {
+			/* Unaligned access */
+			b43_shm_control_word(dev, routing, offset >> 2);
+			b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED, value);
+			return;
+		}
+		offset >>= 2;
+	}
+	b43_shm_control_word(dev, routing, offset);
+	b43_write16(dev, B43_MMIO_SHM_DATA, value);
+}
+
+/* Read HostFlags */
+u64 b43_hf_read(struct b43_wldev *dev)
+{
+	u64 ret;
+
+	ret = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF3);
+	ret <<= 16;
+	ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF2);
+	ret <<= 16;
+	ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF1);
+
+	return ret;
+}
+
+/* Write HostFlags */
+void b43_hf_write(struct b43_wldev *dev, u64 value)
+{
+	u16 lo, mi, hi;
+
+	lo = (value & 0x00000000FFFFULL);
+	mi = (value & 0x0000FFFF0000ULL) >> 16;
+	hi = (value & 0xFFFF00000000ULL) >> 32;
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF1, lo);
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF2, mi);
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF3, hi);
+}
+
+/* Read the firmware capabilities bitmask (Opensource firmware only) */
+static u16 b43_fwcapa_read(struct b43_wldev *dev)
+{
+	B43_WARN_ON(!dev->fw.opensource);
+	return b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_FWCAPA);
+}
+
+void b43_tsf_read(struct b43_wldev *dev, u64 *tsf)
+{
+	u32 low, high;
+
+	B43_WARN_ON(dev->dev->core_rev < 3);
+
+	/* The hardware guarantees us an atomic read, if we
+	 * read the low register first. */
+	low = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_LOW);
+	high = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_HIGH);
+
+	*tsf = high;
+	*tsf <<= 32;
+	*tsf |= low;
+}
+
+static void b43_time_lock(struct b43_wldev *dev)
+{
+	b43_maskset32(dev, B43_MMIO_MACCTL, ~0, B43_MACCTL_TBTTHOLD);
+	/* Commit the write */
+	b43_read32(dev, B43_MMIO_MACCTL);
+}
+
+static void b43_time_unlock(struct b43_wldev *dev)
+{
+	b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_TBTTHOLD, 0);
+	/* Commit the write */
+	b43_read32(dev, B43_MMIO_MACCTL);
+}
+
+static void b43_tsf_write_locked(struct b43_wldev *dev, u64 tsf)
+{
+	u32 low, high;
+
+	B43_WARN_ON(dev->dev->core_rev < 3);
+
+	low = tsf;
+	high = (tsf >> 32);
+	/* The hardware guarantees us an atomic write, if we
+	 * write the low register first. */
+	b43_write32(dev, B43_MMIO_REV3PLUS_TSF_LOW, low);
+	mmiowb();
+	b43_write32(dev, B43_MMIO_REV3PLUS_TSF_HIGH, high);
+	mmiowb();
+}
+
+void b43_tsf_write(struct b43_wldev *dev, u64 tsf)
+{
+	b43_time_lock(dev);
+	b43_tsf_write_locked(dev, tsf);
+	b43_time_unlock(dev);
+}
+
+static
+void b43_macfilter_set(struct b43_wldev *dev, u16 offset, const u8 *mac)
+{
+	static const u8 zero_addr[ETH_ALEN] = { 0 };
+	u16 data;
+
+	if (!mac)
+		mac = zero_addr;
+
+	offset |= 0x0020;
+	b43_write16(dev, B43_MMIO_MACFILTER_CONTROL, offset);
+
+	data = mac[0];
+	data |= mac[1] << 8;
+	b43_write16(dev, B43_MMIO_MACFILTER_DATA, data);
+	data = mac[2];
+	data |= mac[3] << 8;
+	b43_write16(dev, B43_MMIO_MACFILTER_DATA, data);
+	data = mac[4];
+	data |= mac[5] << 8;
+	b43_write16(dev, B43_MMIO_MACFILTER_DATA, data);
+}
+
+static void b43_write_mac_bssid_templates(struct b43_wldev *dev)
+{
+	const u8 *mac;
+	const u8 *bssid;
+	u8 mac_bssid[ETH_ALEN * 2];
+	int i;
+	u32 tmp;
+
+	bssid = dev->wl->bssid;
+	mac = dev->wl->mac_addr;
+
+	b43_macfilter_set(dev, B43_MACFILTER_BSSID, bssid);
+
+	memcpy(mac_bssid, mac, ETH_ALEN);
+	memcpy(mac_bssid + ETH_ALEN, bssid, ETH_ALEN);
+
+	/* Write our MAC address and BSSID to template ram */
+	for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32)) {
+		tmp = (u32) (mac_bssid[i + 0]);
+		tmp |= (u32) (mac_bssid[i + 1]) << 8;
+		tmp |= (u32) (mac_bssid[i + 2]) << 16;
+		tmp |= (u32) (mac_bssid[i + 3]) << 24;
+		b43_ram_write(dev, 0x20 + i, tmp);
+	}
+}
+
+static void b43_upload_card_macaddress(struct b43_wldev *dev)
+{
+	b43_write_mac_bssid_templates(dev);
+	b43_macfilter_set(dev, B43_MACFILTER_SELF, dev->wl->mac_addr);
+}
+
+static void b43_set_slot_time(struct b43_wldev *dev, u16 slot_time)
+{
+	/* slot_time is in usec. */
+	/* This test used to exit for all but a G PHY. */
+	if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
+		return;
+	b43_write16(dev, B43_MMIO_IFSSLOT, 510 + slot_time);
+	/* Shared memory location 0x0010 is the slot time and should be
+	 * set to slot_time; however, this register is initially 0 and changing
+	 * the value adversely affects the transmit rate for BCM4311
+	 * devices. Until this behavior is unterstood, delete this step
+	 *
+	 * b43_shm_write16(dev, B43_SHM_SHARED, 0x0010, slot_time);
+	 */
+}
+
+static void b43_short_slot_timing_enable(struct b43_wldev *dev)
+{
+	b43_set_slot_time(dev, 9);
+}
+
+static void b43_short_slot_timing_disable(struct b43_wldev *dev)
+{
+	b43_set_slot_time(dev, 20);
+}
+
+/* DummyTransmission function, as documented on
+ * http://bcm-v4.sipsolutions.net/802.11/DummyTransmission
+ */
+void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on)
+{
+	struct b43_phy *phy = &dev->phy;
+	unsigned int i, max_loop;
+	u16 value;
+	u32 buffer[5] = {
+		0x00000000,
+		0x00D40000,
+		0x00000000,
+		0x01000000,
+		0x00000000,
+	};
+
+	if (ofdm) {
+		max_loop = 0x1E;
+		buffer[0] = 0x000201CC;
+	} else {
+		max_loop = 0xFA;
+		buffer[0] = 0x000B846E;
+	}
+
+	for (i = 0; i < 5; i++)
+		b43_ram_write(dev, i * 4, buffer[i]);
+
+	b43_write16(dev, B43_MMIO_XMTSEL, 0x0000);
+
+	if (dev->dev->core_rev < 11)
+		b43_write16(dev, B43_MMIO_WEPCTL, 0x0000);
+	else
+		b43_write16(dev, B43_MMIO_WEPCTL, 0x0100);
+
+	value = (ofdm ? 0x41 : 0x40);
+	b43_write16(dev, B43_MMIO_TXE0_PHYCTL, value);
+	if (phy->type == B43_PHYTYPE_N || phy->type == B43_PHYTYPE_LP ||
+	    phy->type == B43_PHYTYPE_LCN)
+		b43_write16(dev, B43_MMIO_TXE0_PHYCTL1, 0x1A02);
+
+	b43_write16(dev, B43_MMIO_TXE0_WM_0, 0x0000);
+	b43_write16(dev, B43_MMIO_TXE0_WM_1, 0x0000);
+
+	b43_write16(dev, B43_MMIO_XMTTPLATETXPTR, 0x0000);
+	b43_write16(dev, B43_MMIO_XMTTXCNT, 0x0014);
+	b43_write16(dev, B43_MMIO_XMTSEL, 0x0826);
+	b43_write16(dev, B43_MMIO_TXE0_CTL, 0x0000);
+
+	if (!pa_on && phy->type == B43_PHYTYPE_N)
+		; /*b43_nphy_pa_override(dev, false) */
+
+	switch (phy->type) {
+	case B43_PHYTYPE_N:
+	case B43_PHYTYPE_LCN:
+		b43_write16(dev, B43_MMIO_TXE0_AUX, 0x00D0);
+		break;
+	case B43_PHYTYPE_LP:
+		b43_write16(dev, B43_MMIO_TXE0_AUX, 0x0050);
+		break;
+	default:
+		b43_write16(dev, B43_MMIO_TXE0_AUX, 0x0030);
+	}
+	b43_read16(dev, B43_MMIO_TXE0_AUX);
+
+	if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5)
+		b43_radio_write16(dev, 0x0051, 0x0017);
+	for (i = 0x00; i < max_loop; i++) {
+		value = b43_read16(dev, B43_MMIO_TXE0_STATUS);
+		if (value & 0x0080)
+			break;
+		udelay(10);
+	}
+	for (i = 0x00; i < 0x0A; i++) {
+		value = b43_read16(dev, B43_MMIO_TXE0_STATUS);
+		if (value & 0x0400)
+			break;
+		udelay(10);
+	}
+	for (i = 0x00; i < 0x19; i++) {
+		value = b43_read16(dev, B43_MMIO_IFSSTAT);
+		if (!(value & 0x0100))
+			break;
+		udelay(10);
+	}
+	if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5)
+		b43_radio_write16(dev, 0x0051, 0x0037);
+}
+
+static void key_write(struct b43_wldev *dev,
+		      u8 index, u8 algorithm, const u8 *key)
+{
+	unsigned int i;
+	u32 offset;
+	u16 value;
+	u16 kidx;
+
+	/* Key index/algo block */
+	kidx = b43_kidx_to_fw(dev, index);
+	value = ((kidx << 4) | algorithm);
+	b43_shm_write16(dev, B43_SHM_SHARED,
+			B43_SHM_SH_KEYIDXBLOCK + (kidx * 2), value);
+
+	/* Write the key to the Key Table Pointer offset */
+	offset = dev->ktp + (index * B43_SEC_KEYSIZE);
+	for (i = 0; i < B43_SEC_KEYSIZE; i += 2) {
+		value = key[i];
+		value |= (u16) (key[i + 1]) << 8;
+		b43_shm_write16(dev, B43_SHM_SHARED, offset + i, value);
+	}
+}
+
+static void keymac_write(struct b43_wldev *dev, u8 index, const u8 *addr)
+{
+	u32 addrtmp[2] = { 0, 0, };
+	u8 pairwise_keys_start = B43_NR_GROUP_KEYS * 2;
+
+	if (b43_new_kidx_api(dev))
+		pairwise_keys_start = B43_NR_GROUP_KEYS;
+
+	B43_WARN_ON(index < pairwise_keys_start);
+	/* We have four default TX keys and possibly four default RX keys.
+	 * Physical mac 0 is mapped to physical key 4 or 8, depending
+	 * on the firmware version.
+	 * So we must adjust the index here.
+	 */
+	index -= pairwise_keys_start;
+	B43_WARN_ON(index >= B43_NR_PAIRWISE_KEYS);
+
+	if (addr) {
+		addrtmp[0] = addr[0];
+		addrtmp[0] |= ((u32) (addr[1]) << 8);
+		addrtmp[0] |= ((u32) (addr[2]) << 16);
+		addrtmp[0] |= ((u32) (addr[3]) << 24);
+		addrtmp[1] = addr[4];
+		addrtmp[1] |= ((u32) (addr[5]) << 8);
+	}
+
+	/* Receive match transmitter address (RCMTA) mechanism */
+	b43_shm_write32(dev, B43_SHM_RCMTA,
+			(index * 2) + 0, addrtmp[0]);
+	b43_shm_write16(dev, B43_SHM_RCMTA,
+			(index * 2) + 1, addrtmp[1]);
+}
+
+/* The ucode will use phase1 key with TEK key to decrypt rx packets.
+ * When a packet is received, the iv32 is checked.
+ * - if it doesn't the packet is returned without modification (and software
+ *   decryption can be done). That's what happen when iv16 wrap.
+ * - if it does, the rc4 key is computed, and decryption is tried.
+ *   Either it will success and B43_RX_MAC_DEC is returned,
+ *   either it fails and B43_RX_MAC_DEC|B43_RX_MAC_DECERR is returned
+ *   and the packet is not usable (it got modified by the ucode).
+ * So in order to never have B43_RX_MAC_DECERR, we should provide
+ * a iv32 and phase1key that match. Because we drop packets in case of
+ * B43_RX_MAC_DECERR, if we have a correct iv32 but a wrong phase1key, all
+ * packets will be lost without higher layer knowing (ie no resync possible
+ * until next wrap).
+ *
+ * NOTE : this should support 50 key like RCMTA because
+ * (B43_SHM_SH_KEYIDXBLOCK - B43_SHM_SH_TKIPTSCTTAK)/14 = 50
+ */
+static void rx_tkip_phase1_write(struct b43_wldev *dev, u8 index, u32 iv32,
+		u16 *phase1key)
+{
+	unsigned int i;
+	u32 offset;
+	u8 pairwise_keys_start = B43_NR_GROUP_KEYS * 2;
+
+	if (!modparam_hwtkip)
+		return;
+
+	if (b43_new_kidx_api(dev))
+		pairwise_keys_start = B43_NR_GROUP_KEYS;
+
+	B43_WARN_ON(index < pairwise_keys_start);
+	/* We have four default TX keys and possibly four default RX keys.
+	 * Physical mac 0 is mapped to physical key 4 or 8, depending
+	 * on the firmware version.
+	 * So we must adjust the index here.
+	 */
+	index -= pairwise_keys_start;
+	B43_WARN_ON(index >= B43_NR_PAIRWISE_KEYS);
+
+	if (b43_debug(dev, B43_DBG_KEYS)) {
+		b43dbg(dev->wl, "rx_tkip_phase1_write : idx 0x%x, iv32 0x%x\n",
+				index, iv32);
+	}
+	/* Write the key to the  RX tkip shared mem */
+	offset = B43_SHM_SH_TKIPTSCTTAK + index * (10 + 4);
+	for (i = 0; i < 10; i += 2) {
+		b43_shm_write16(dev, B43_SHM_SHARED, offset + i,
+				phase1key ? phase1key[i / 2] : 0);
+	}
+	b43_shm_write16(dev, B43_SHM_SHARED, offset + i, iv32);
+	b43_shm_write16(dev, B43_SHM_SHARED, offset + i + 2, iv32 >> 16);
+}
+
+static void b43_op_update_tkip_key(struct ieee80211_hw *hw,
+				   struct ieee80211_vif *vif,
+				   struct ieee80211_key_conf *keyconf,
+				   struct ieee80211_sta *sta,
+				   u32 iv32, u16 *phase1key)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+	struct b43_wldev *dev;
+	int index = keyconf->hw_key_idx;
+
+	if (B43_WARN_ON(!modparam_hwtkip))
+		return;
+
+	/* This is only called from the RX path through mac80211, where
+	 * our mutex is already locked. */
+	B43_WARN_ON(!mutex_is_locked(&wl->mutex));
+	dev = wl->current_dev;
+	B43_WARN_ON(!dev || b43_status(dev) < B43_STAT_INITIALIZED);
+
+	keymac_write(dev, index, NULL);	/* First zero out mac to avoid race */
+
+	rx_tkip_phase1_write(dev, index, iv32, phase1key);
+	/* only pairwise TKIP keys are supported right now */
+	if (WARN_ON(!sta))
+		return;
+	keymac_write(dev, index, sta->addr);
+}
+
+static void do_key_write(struct b43_wldev *dev,
+			 u8 index, u8 algorithm,
+			 const u8 *key, size_t key_len, const u8 *mac_addr)
+{
+	u8 buf[B43_SEC_KEYSIZE] = { 0, };
+	u8 pairwise_keys_start = B43_NR_GROUP_KEYS * 2;
+
+	if (b43_new_kidx_api(dev))
+		pairwise_keys_start = B43_NR_GROUP_KEYS;
+
+	B43_WARN_ON(index >= ARRAY_SIZE(dev->key));
+	B43_WARN_ON(key_len > B43_SEC_KEYSIZE);
+
+	if (index >= pairwise_keys_start)
+		keymac_write(dev, index, NULL);	/* First zero out mac. */
+	if (algorithm == B43_SEC_ALGO_TKIP) {
+		/*
+		 * We should provide an initial iv32, phase1key pair.
+		 * We could start with iv32=0 and compute the corresponding
+		 * phase1key, but this means calling ieee80211_get_tkip_key
+		 * with a fake skb (or export other tkip function).
+		 * Because we are lazy we hope iv32 won't start with
+		 * 0xffffffff and let's b43_op_update_tkip_key provide a
+		 * correct pair.
+		 */
+		rx_tkip_phase1_write(dev, index, 0xffffffff, (u16*)buf);
+	} else if (index >= pairwise_keys_start) /* clear it */
+		rx_tkip_phase1_write(dev, index, 0, NULL);
+	if (key)
+		memcpy(buf, key, key_len);
+	key_write(dev, index, algorithm, buf);
+	if (index >= pairwise_keys_start)
+		keymac_write(dev, index, mac_addr);
+
+	dev->key[index].algorithm = algorithm;
+}
+
+static int b43_key_write(struct b43_wldev *dev,
+			 int index, u8 algorithm,
+			 const u8 *key, size_t key_len,
+			 const u8 *mac_addr,
+			 struct ieee80211_key_conf *keyconf)
+{
+	int i;
+	int pairwise_keys_start;
+
+	/* For ALG_TKIP the key is encoded as a 256-bit (32 byte) data block:
+	 * 	- Temporal Encryption Key (128 bits)
+	 * 	- Temporal Authenticator Tx MIC Key (64 bits)
+	 * 	- Temporal Authenticator Rx MIC Key (64 bits)
+	 *
+	 * 	Hardware only store TEK
+	 */
+	if (algorithm == B43_SEC_ALGO_TKIP && key_len == 32)
+		key_len = 16;
+	if (key_len > B43_SEC_KEYSIZE)
+		return -EINVAL;
+	for (i = 0; i < ARRAY_SIZE(dev->key); i++) {
+		/* Check that we don't already have this key. */
+		B43_WARN_ON(dev->key[i].keyconf == keyconf);
+	}
+	if (index < 0) {
+		/* Pairwise key. Get an empty slot for the key. */
+		if (b43_new_kidx_api(dev))
+			pairwise_keys_start = B43_NR_GROUP_KEYS;
+		else
+			pairwise_keys_start = B43_NR_GROUP_KEYS * 2;
+		for (i = pairwise_keys_start;
+		     i < pairwise_keys_start + B43_NR_PAIRWISE_KEYS;
+		     i++) {
+			B43_WARN_ON(i >= ARRAY_SIZE(dev->key));
+			if (!dev->key[i].keyconf) {
+				/* found empty */
+				index = i;
+				break;
+			}
+		}
+		if (index < 0) {
+			b43warn(dev->wl, "Out of hardware key memory\n");
+			return -ENOSPC;
+		}
+	} else
+		B43_WARN_ON(index > 3);
+
+	do_key_write(dev, index, algorithm, key, key_len, mac_addr);
+	if ((index <= 3) && !b43_new_kidx_api(dev)) {
+		/* Default RX key */
+		B43_WARN_ON(mac_addr);
+		do_key_write(dev, index + 4, algorithm, key, key_len, NULL);
+	}
+	keyconf->hw_key_idx = index;
+	dev->key[index].keyconf = keyconf;
+
+	return 0;
+}
+
+static int b43_key_clear(struct b43_wldev *dev, int index)
+{
+	if (B43_WARN_ON((index < 0) || (index >= ARRAY_SIZE(dev->key))))
+		return -EINVAL;
+	do_key_write(dev, index, B43_SEC_ALGO_NONE,
+		     NULL, B43_SEC_KEYSIZE, NULL);
+	if ((index <= 3) && !b43_new_kidx_api(dev)) {
+		do_key_write(dev, index + 4, B43_SEC_ALGO_NONE,
+			     NULL, B43_SEC_KEYSIZE, NULL);
+	}
+	dev->key[index].keyconf = NULL;
+
+	return 0;
+}
+
+static void b43_clear_keys(struct b43_wldev *dev)
+{
+	int i, count;
+
+	if (b43_new_kidx_api(dev))
+		count = B43_NR_GROUP_KEYS + B43_NR_PAIRWISE_KEYS;
+	else
+		count = B43_NR_GROUP_KEYS * 2 + B43_NR_PAIRWISE_KEYS;
+	for (i = 0; i < count; i++)
+		b43_key_clear(dev, i);
+}
+
+static void b43_dump_keymemory(struct b43_wldev *dev)
+{
+	unsigned int i, index, count, offset, pairwise_keys_start;
+	u8 mac[ETH_ALEN];
+	u16 algo;
+	u32 rcmta0;
+	u16 rcmta1;
+	u64 hf;
+	struct b43_key *key;
+
+	if (!b43_debug(dev, B43_DBG_KEYS))
+		return;
+
+	hf = b43_hf_read(dev);
+	b43dbg(dev->wl, "Hardware key memory dump:  USEDEFKEYS=%u\n",
+	       !!(hf & B43_HF_USEDEFKEYS));
+	if (b43_new_kidx_api(dev)) {
+		pairwise_keys_start = B43_NR_GROUP_KEYS;
+		count = B43_NR_GROUP_KEYS + B43_NR_PAIRWISE_KEYS;
+	} else {
+		pairwise_keys_start = B43_NR_GROUP_KEYS * 2;
+		count = B43_NR_GROUP_KEYS * 2 + B43_NR_PAIRWISE_KEYS;
+	}
+	for (index = 0; index < count; index++) {
+		key = &(dev->key[index]);
+		printk(KERN_DEBUG "Key slot %02u: %s",
+		       index, (key->keyconf == NULL) ? " " : "*");
+		offset = dev->ktp + (index * B43_SEC_KEYSIZE);
+		for (i = 0; i < B43_SEC_KEYSIZE; i += 2) {
+			u16 tmp = b43_shm_read16(dev, B43_SHM_SHARED, offset + i);
+			printk("%02X%02X", (tmp & 0xFF), ((tmp >> 8) & 0xFF));
+		}
+
+		algo = b43_shm_read16(dev, B43_SHM_SHARED,
+				      B43_SHM_SH_KEYIDXBLOCK + (index * 2));
+		printk("   Algo: %04X/%02X", algo, key->algorithm);
+
+		if (index >= pairwise_keys_start) {
+			if (key->algorithm == B43_SEC_ALGO_TKIP) {
+				printk("   TKIP: ");
+				offset = B43_SHM_SH_TKIPTSCTTAK + (index - 4) * (10 + 4);
+				for (i = 0; i < 14; i += 2) {
+					u16 tmp = b43_shm_read16(dev, B43_SHM_SHARED, offset + i);
+					printk("%02X%02X", (tmp & 0xFF), ((tmp >> 8) & 0xFF));
+				}
+			}
+			rcmta0 = b43_shm_read32(dev, B43_SHM_RCMTA,
+						((index - pairwise_keys_start) * 2) + 0);
+			rcmta1 = b43_shm_read16(dev, B43_SHM_RCMTA,
+						((index - pairwise_keys_start) * 2) + 1);
+			*((__le32 *)(&mac[0])) = cpu_to_le32(rcmta0);
+			*((__le16 *)(&mac[4])) = cpu_to_le16(rcmta1);
+			printk("   MAC: %pM", mac);
+		} else
+			printk("   DEFAULT KEY");
+		printk("\n");
+	}
+}
+
+void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags)
+{
+	u32 macctl;
+	u16 ucstat;
+	bool hwps;
+	bool awake;
+	int i;
+
+	B43_WARN_ON((ps_flags & B43_PS_ENABLED) &&
+		    (ps_flags & B43_PS_DISABLED));
+	B43_WARN_ON((ps_flags & B43_PS_AWAKE) && (ps_flags & B43_PS_ASLEEP));
+
+	if (ps_flags & B43_PS_ENABLED) {
+		hwps = true;
+	} else if (ps_flags & B43_PS_DISABLED) {
+		hwps = false;
+	} else {
+		//TODO: If powersave is not off and FIXME is not set and we are not in adhoc
+		//      and thus is not an AP and we are associated, set bit 25
+	}
+	if (ps_flags & B43_PS_AWAKE) {
+		awake = true;
+	} else if (ps_flags & B43_PS_ASLEEP) {
+		awake = false;
+	} else {
+		//TODO: If the device is awake or this is an AP, or we are scanning, or FIXME,
+		//      or we are associated, or FIXME, or the latest PS-Poll packet sent was
+		//      successful, set bit26
+	}
+
+/* FIXME: For now we force awake-on and hwps-off */
+	hwps = false;
+	awake = true;
+
+	macctl = b43_read32(dev, B43_MMIO_MACCTL);
+	if (hwps)
+		macctl |= B43_MACCTL_HWPS;
+	else
+		macctl &= ~B43_MACCTL_HWPS;
+	if (awake)
+		macctl |= B43_MACCTL_AWAKE;
+	else
+		macctl &= ~B43_MACCTL_AWAKE;
+	b43_write32(dev, B43_MMIO_MACCTL, macctl);
+	/* Commit write */
+	b43_read32(dev, B43_MMIO_MACCTL);
+	if (awake && dev->dev->core_rev >= 5) {
+		/* Wait for the microcode to wake up. */
+		for (i = 0; i < 100; i++) {
+			ucstat = b43_shm_read16(dev, B43_SHM_SHARED,
+						B43_SHM_SH_UCODESTAT);
+			if (ucstat != B43_SHM_SH_UCODESTAT_SLEEP)
+				break;
+			udelay(10);
+		}
+	}
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/BmacCorePllReset */
+void b43_wireless_core_phy_pll_reset(struct b43_wldev *dev)
+{
+	struct bcma_drv_cc *bcma_cc __maybe_unused;
+	struct ssb_chipcommon *ssb_cc __maybe_unused;
+
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		bcma_cc = &dev->dev->bdev->bus->drv_cc;
+
+		bcma_cc_write32(bcma_cc, BCMA_CC_PMU_CHIPCTL_ADDR, 0);
+		bcma_cc_mask32(bcma_cc, BCMA_CC_PMU_CHIPCTL_DATA, ~0x4);
+		bcma_cc_set32(bcma_cc, BCMA_CC_PMU_CHIPCTL_DATA, 0x4);
+		bcma_cc_mask32(bcma_cc, BCMA_CC_PMU_CHIPCTL_DATA, ~0x4);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		ssb_cc = &dev->dev->sdev->bus->chipco;
+
+		chipco_write32(ssb_cc, SSB_CHIPCO_CHIPCTL_ADDR, 0);
+		chipco_mask32(ssb_cc, SSB_CHIPCO_CHIPCTL_DATA, ~0x4);
+		chipco_set32(ssb_cc, SSB_CHIPCO_CHIPCTL_DATA, 0x4);
+		chipco_mask32(ssb_cc, SSB_CHIPCO_CHIPCTL_DATA, ~0x4);
+		break;
+#endif
+	}
+}
+
+#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);
+
+	b43_phy_take_out_of_reset(dev);
+}
+
+static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode)
+{
+	u32 req = B43_BCMA_CLKCTLST_80211_PLL_REQ |
+		  B43_BCMA_CLKCTLST_PHY_PLL_REQ;
+	u32 status = B43_BCMA_CLKCTLST_80211_PLL_ST |
+		     B43_BCMA_CLKCTLST_PHY_PLL_ST;
+	u32 flags;
+
+	flags = B43_BCMA_IOCTL_PHY_CLKEN;
+	if (gmode)
+		flags |= B43_BCMA_IOCTL_GMODE;
+	b43_device_enable(dev, flags);
+
+	if (dev->phy.type == B43_PHYTYPE_AC) {
+		u16 tmp;
+
+		tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+		tmp &= ~B43_BCMA_IOCTL_DAC;
+		tmp |= 0x100;
+		bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
+
+		tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+		tmp &= ~B43_BCMA_IOCTL_PHY_CLKEN;
+		bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
+
+		tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+		tmp |= B43_BCMA_IOCTL_PHY_CLKEN;
+		bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
+	}
+
+	bcma_core_set_clockmode(dev->dev->bdev, BCMA_CLKMODE_FAST);
+	b43_bcma_phy_reset(dev);
+	bcma_core_pll_ctl(dev->dev->bdev, req, status, true);
+}
+#endif
+
+#ifdef CONFIG_B43_SSB
+static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, bool gmode)
+{
+	u32 flags = 0;
+
+	if (gmode)
+		flags |= B43_TMSLOW_GMODE;
+	flags |= B43_TMSLOW_PHYCLKEN;
+	flags |= B43_TMSLOW_PHYRESET;
+	if (dev->phy.type == B43_PHYTYPE_N)
+		flags |= B43_TMSLOW_PHY_BANDWIDTH_20MHZ; /* Make 20 MHz def */
+	b43_device_enable(dev, flags);
+	msleep(2);		/* Wait for the PLL to turn on. */
+
+	b43_phy_take_out_of_reset(dev);
+}
+#endif
+
+void b43_wireless_core_reset(struct b43_wldev *dev, bool gmode)
+{
+	u32 macctl;
+
+	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
+	 * PHY-type, yet. wireless_core_reset will be called once again later,
+	 * when we know the PHY-type. */
+	if (dev->phy.ops)
+		dev->phy.ops->switch_analog(dev, 1);
+
+	macctl = b43_read32(dev, B43_MMIO_MACCTL);
+	macctl &= ~B43_MACCTL_GMODE;
+	if (gmode)
+		macctl |= B43_MACCTL_GMODE;
+	macctl |= B43_MACCTL_IHR_ENABLED;
+	b43_write32(dev, B43_MMIO_MACCTL, macctl);
+}
+
+static void handle_irq_transmit_status(struct b43_wldev *dev)
+{
+	u32 v0, v1;
+	u16 tmp;
+	struct b43_txstatus stat;
+
+	while (1) {
+		v0 = b43_read32(dev, B43_MMIO_XMITSTAT_0);
+		if (!(v0 & 0x00000001))
+			break;
+		v1 = b43_read32(dev, B43_MMIO_XMITSTAT_1);
+
+		stat.cookie = (v0 >> 16);
+		stat.seq = (v1 & 0x0000FFFF);
+		stat.phy_stat = ((v1 & 0x00FF0000) >> 16);
+		tmp = (v0 & 0x0000FFFF);
+		stat.frame_count = ((tmp & 0xF000) >> 12);
+		stat.rts_count = ((tmp & 0x0F00) >> 8);
+		stat.supp_reason = ((tmp & 0x001C) >> 2);
+		stat.pm_indicated = !!(tmp & 0x0080);
+		stat.intermediate = !!(tmp & 0x0040);
+		stat.for_ampdu = !!(tmp & 0x0020);
+		stat.acked = !!(tmp & 0x0002);
+
+		b43_handle_txstatus(dev, &stat);
+	}
+}
+
+static void drain_txstatus_queue(struct b43_wldev *dev)
+{
+	u32 dummy;
+
+	if (dev->dev->core_rev < 5)
+		return;
+	/* Read all entries from the microcode TXstatus FIFO
+	 * and throw them away.
+	 */
+	while (1) {
+		dummy = b43_read32(dev, B43_MMIO_XMITSTAT_0);
+		if (!(dummy & 0x00000001))
+			break;
+		dummy = b43_read32(dev, B43_MMIO_XMITSTAT_1);
+	}
+}
+
+static u32 b43_jssi_read(struct b43_wldev *dev)
+{
+	u32 val = 0;
+
+	val = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_JSSI1);
+	val <<= 16;
+	val |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_JSSI0);
+
+	return val;
+}
+
+static void b43_jssi_write(struct b43_wldev *dev, u32 jssi)
+{
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_JSSI0,
+			(jssi & 0x0000FFFF));
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_JSSI1,
+			(jssi & 0xFFFF0000) >> 16);
+}
+
+static void b43_generate_noise_sample(struct b43_wldev *dev)
+{
+	b43_jssi_write(dev, 0x7F7F7F7F);
+	b43_write32(dev, B43_MMIO_MACCMD,
+		    b43_read32(dev, B43_MMIO_MACCMD) | B43_MACCMD_BGNOISE);
+}
+
+static void b43_calculate_link_quality(struct b43_wldev *dev)
+{
+	/* Top half of Link Quality calculation. */
+
+	if (dev->phy.type != B43_PHYTYPE_G)
+		return;
+	if (dev->noisecalc.calculation_running)
+		return;
+	dev->noisecalc.calculation_running = true;
+	dev->noisecalc.nr_samples = 0;
+
+	b43_generate_noise_sample(dev);
+}
+
+static void handle_irq_noise(struct b43_wldev *dev)
+{
+	struct b43_phy_g *phy = dev->phy.g;
+	u16 tmp;
+	u8 noise[4];
+	u8 i, j;
+	s32 average;
+
+	/* Bottom half of Link Quality calculation. */
+
+	if (dev->phy.type != B43_PHYTYPE_G)
+		return;
+
+	/* Possible race condition: It might be possible that the user
+	 * changed to a different channel in the meantime since we
+	 * started the calculation. We ignore that fact, since it's
+	 * not really that much of a problem. The background noise is
+	 * an estimation only anyway. Slightly wrong results will get damped
+	 * by the averaging of the 8 sample rounds. Additionally the
+	 * value is shortlived. So it will be replaced by the next noise
+	 * calculation round soon. */
+
+	B43_WARN_ON(!dev->noisecalc.calculation_running);
+	*((__le32 *)noise) = cpu_to_le32(b43_jssi_read(dev));
+	if (noise[0] == 0x7F || noise[1] == 0x7F ||
+	    noise[2] == 0x7F || noise[3] == 0x7F)
+		goto generate_new;
+
+	/* Get the noise samples. */
+	B43_WARN_ON(dev->noisecalc.nr_samples >= 8);
+	i = dev->noisecalc.nr_samples;
+	noise[0] = clamp_val(noise[0], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+	noise[1] = clamp_val(noise[1], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+	noise[2] = clamp_val(noise[2], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+	noise[3] = clamp_val(noise[3], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+	dev->noisecalc.samples[i][0] = phy->nrssi_lt[noise[0]];
+	dev->noisecalc.samples[i][1] = phy->nrssi_lt[noise[1]];
+	dev->noisecalc.samples[i][2] = phy->nrssi_lt[noise[2]];
+	dev->noisecalc.samples[i][3] = phy->nrssi_lt[noise[3]];
+	dev->noisecalc.nr_samples++;
+	if (dev->noisecalc.nr_samples == 8) {
+		/* Calculate the Link Quality by the noise samples. */
+		average = 0;
+		for (i = 0; i < 8; i++) {
+			for (j = 0; j < 4; j++)
+				average += dev->noisecalc.samples[i][j];
+		}
+		average /= (8 * 4);
+		average *= 125;
+		average += 64;
+		average /= 128;
+		tmp = b43_shm_read16(dev, B43_SHM_SHARED, 0x40C);
+		tmp = (tmp / 128) & 0x1F;
+		if (tmp >= 8)
+			average += 2;
+		else
+			average -= 25;
+		if (tmp == 8)
+			average -= 72;
+		else
+			average -= 48;
+
+		dev->stats.link_noise = average;
+		dev->noisecalc.calculation_running = false;
+		return;
+	}
+generate_new:
+	b43_generate_noise_sample(dev);
+}
+
+static void handle_irq_tbtt_indication(struct b43_wldev *dev)
+{
+	if (b43_is_mode(dev->wl, NL80211_IFTYPE_AP)) {
+		///TODO: PS TBTT
+	} else {
+		if (1 /*FIXME: the last PSpoll frame was sent successfully */ )
+			b43_power_saving_ctl_bits(dev, 0);
+	}
+	if (b43_is_mode(dev->wl, NL80211_IFTYPE_ADHOC))
+		dev->dfq_valid = true;
+}
+
+static void handle_irq_atim_end(struct b43_wldev *dev)
+{
+	if (dev->dfq_valid) {
+		b43_write32(dev, B43_MMIO_MACCMD,
+			    b43_read32(dev, B43_MMIO_MACCMD)
+			    | B43_MACCMD_DFQ_VALID);
+		dev->dfq_valid = false;
+	}
+}
+
+static void handle_irq_pmq(struct b43_wldev *dev)
+{
+	u32 tmp;
+
+	//TODO: AP mode.
+
+	while (1) {
+		tmp = b43_read32(dev, B43_MMIO_PS_STATUS);
+		if (!(tmp & 0x00000008))
+			break;
+	}
+	/* 16bit write is odd, but correct. */
+	b43_write16(dev, B43_MMIO_PS_STATUS, 0x0002);
+}
+
+static void b43_write_template_common(struct b43_wldev *dev,
+				      const u8 *data, u16 size,
+				      u16 ram_offset,
+				      u16 shm_size_offset, u8 rate)
+{
+	u32 i, tmp;
+	struct b43_plcp_hdr4 plcp;
+
+	plcp.data = 0;
+	b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
+	b43_ram_write(dev, ram_offset, le32_to_cpu(plcp.data));
+	ram_offset += sizeof(u32);
+	/* The PLCP is 6 bytes long, but we only wrote 4 bytes, yet.
+	 * So leave the first two bytes of the next write blank.
+	 */
+	tmp = (u32) (data[0]) << 16;
+	tmp |= (u32) (data[1]) << 24;
+	b43_ram_write(dev, ram_offset, tmp);
+	ram_offset += sizeof(u32);
+	for (i = 2; i < size; i += sizeof(u32)) {
+		tmp = (u32) (data[i + 0]);
+		if (i + 1 < size)
+			tmp |= (u32) (data[i + 1]) << 8;
+		if (i + 2 < size)
+			tmp |= (u32) (data[i + 2]) << 16;
+		if (i + 3 < size)
+			tmp |= (u32) (data[i + 3]) << 24;
+		b43_ram_write(dev, ram_offset + i - 2, tmp);
+	}
+	b43_shm_write16(dev, B43_SHM_SHARED, shm_size_offset,
+			size + sizeof(struct b43_plcp_hdr6));
+}
+
+/* Check if the use of the antenna that ieee80211 told us to
+ * use is possible. This will fall back to DEFAULT.
+ * "antenna_nr" is the antenna identifier we got from ieee80211. */
+u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev,
+				  u8 antenna_nr)
+{
+	u8 antenna_mask;
+
+	if (antenna_nr == 0) {
+		/* Zero means "use default antenna". That's always OK. */
+		return 0;
+	}
+
+	/* Get the mask of available antennas. */
+	if (dev->phy.gmode)
+		antenna_mask = dev->dev->bus_sprom->ant_available_bg;
+	else
+		antenna_mask = dev->dev->bus_sprom->ant_available_a;
+
+	if (!(antenna_mask & (1 << (antenna_nr - 1)))) {
+		/* This antenna is not available. Fall back to default. */
+		return 0;
+	}
+
+	return antenna_nr;
+}
+
+/* Convert a b43 antenna number value to the PHY TX control value. */
+static u16 b43_antenna_to_phyctl(int antenna)
+{
+	switch (antenna) {
+	case B43_ANTENNA0:
+		return B43_TXH_PHY_ANT0;
+	case B43_ANTENNA1:
+		return B43_TXH_PHY_ANT1;
+	case B43_ANTENNA2:
+		return B43_TXH_PHY_ANT2;
+	case B43_ANTENNA3:
+		return B43_TXH_PHY_ANT3;
+	case B43_ANTENNA_AUTO0:
+	case B43_ANTENNA_AUTO1:
+		return B43_TXH_PHY_ANT01AUTO;
+	}
+	B43_WARN_ON(1);
+	return 0;
+}
+
+static void b43_write_beacon_template(struct b43_wldev *dev,
+				      u16 ram_offset,
+				      u16 shm_size_offset)
+{
+	unsigned int i, len, variable_len;
+	const struct ieee80211_mgmt *bcn;
+	const u8 *ie;
+	bool tim_found = false;
+	unsigned int rate;
+	u16 ctl;
+	int antenna;
+	struct ieee80211_tx_info *info;
+	unsigned long flags;
+	struct sk_buff *beacon_skb;
+
+	spin_lock_irqsave(&dev->wl->beacon_lock, flags);
+	info = IEEE80211_SKB_CB(dev->wl->current_beacon);
+	rate = ieee80211_get_tx_rate(dev->wl->hw, info)->hw_value;
+	/* Clone the beacon, so it cannot go away, while we write it to hw. */
+	beacon_skb = skb_clone(dev->wl->current_beacon, GFP_ATOMIC);
+	spin_unlock_irqrestore(&dev->wl->beacon_lock, flags);
+
+	if (!beacon_skb) {
+		b43dbg(dev->wl, "Could not upload beacon. "
+		       "Failed to clone beacon skb.");
+		return;
+	}
+
+	bcn = (const struct ieee80211_mgmt *)(beacon_skb->data);
+	len = min_t(size_t, beacon_skb->len,
+		    0x200 - sizeof(struct b43_plcp_hdr6));
+
+	b43_write_template_common(dev, (const u8 *)bcn,
+				  len, ram_offset, shm_size_offset, rate);
+
+	/* Write the PHY TX control parameters. */
+	antenna = B43_ANTENNA_DEFAULT;
+	antenna = b43_antenna_to_phyctl(antenna);
+	ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
+	/* We can't send beacons with short preamble. Would get PHY errors. */
+	ctl &= ~B43_TXH_PHY_SHORTPRMBL;
+	ctl &= ~B43_TXH_PHY_ANT;
+	ctl &= ~B43_TXH_PHY_ENC;
+	ctl |= antenna;
+	if (b43_is_cck_rate(rate))
+		ctl |= B43_TXH_PHY_ENC_CCK;
+	else
+		ctl |= B43_TXH_PHY_ENC_OFDM;
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, ctl);
+
+	/* Find the position of the TIM and the DTIM_period value
+	 * and write them to SHM. */
+	ie = bcn->u.beacon.variable;
+	variable_len = len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
+	for (i = 0; i < variable_len - 2; ) {
+		uint8_t ie_id, ie_len;
+
+		ie_id = ie[i];
+		ie_len = ie[i + 1];
+		if (ie_id == 5) {
+			u16 tim_position;
+			u16 dtim_period;
+			/* This is the TIM Information Element */
+
+			/* Check whether the ie_len is in the beacon data range. */
+			if (variable_len < ie_len + 2 + i)
+				break;
+			/* A valid TIM is at least 4 bytes long. */
+			if (ie_len < 4)
+				break;
+			tim_found = true;
+
+			tim_position = sizeof(struct b43_plcp_hdr6);
+			tim_position += offsetof(struct ieee80211_mgmt, u.beacon.variable);
+			tim_position += i;
+
+			dtim_period = ie[i + 3];
+
+			b43_shm_write16(dev, B43_SHM_SHARED,
+					B43_SHM_SH_TIMBPOS, tim_position);
+			b43_shm_write16(dev, B43_SHM_SHARED,
+					B43_SHM_SH_DTIMPER, dtim_period);
+			break;
+		}
+		i += ie_len + 2;
+	}
+	if (!tim_found) {
+		/*
+		 * If ucode wants to modify TIM do it behind the beacon, this
+		 * will happen, for example, when doing mesh networking.
+		 */
+		b43_shm_write16(dev, B43_SHM_SHARED,
+				B43_SHM_SH_TIMBPOS,
+				len + sizeof(struct b43_plcp_hdr6));
+		b43_shm_write16(dev, B43_SHM_SHARED,
+				B43_SHM_SH_DTIMPER, 0);
+	}
+	b43dbg(dev->wl, "Updated beacon template at 0x%x\n", ram_offset);
+
+	dev_kfree_skb_any(beacon_skb);
+}
+
+static void b43_upload_beacon0(struct b43_wldev *dev)
+{
+	struct b43_wl *wl = dev->wl;
+
+	if (wl->beacon0_uploaded)
+		return;
+	b43_write_beacon_template(dev, B43_SHM_SH_BT_BASE0, B43_SHM_SH_BTL0);
+	wl->beacon0_uploaded = true;
+}
+
+static void b43_upload_beacon1(struct b43_wldev *dev)
+{
+	struct b43_wl *wl = dev->wl;
+
+	if (wl->beacon1_uploaded)
+		return;
+	b43_write_beacon_template(dev, B43_SHM_SH_BT_BASE1, B43_SHM_SH_BTL1);
+	wl->beacon1_uploaded = true;
+}
+
+static void handle_irq_beacon(struct b43_wldev *dev)
+{
+	struct b43_wl *wl = dev->wl;
+	u32 cmd, beacon0_valid, beacon1_valid;
+
+	if (!b43_is_mode(wl, NL80211_IFTYPE_AP) &&
+	    !b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT) &&
+	    !b43_is_mode(wl, NL80211_IFTYPE_ADHOC))
+		return;
+
+	/* This is the bottom half of the asynchronous beacon update. */
+
+	/* Ignore interrupt in the future. */
+	dev->irq_mask &= ~B43_IRQ_BEACON;
+
+	cmd = b43_read32(dev, B43_MMIO_MACCMD);
+	beacon0_valid = (cmd & B43_MACCMD_BEACON0_VALID);
+	beacon1_valid = (cmd & B43_MACCMD_BEACON1_VALID);
+
+	/* Schedule interrupt manually, if busy. */
+	if (beacon0_valid && beacon1_valid) {
+		b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_BEACON);
+		dev->irq_mask |= B43_IRQ_BEACON;
+		return;
+	}
+
+	if (unlikely(wl->beacon_templates_virgin)) {
+		/* We never uploaded a beacon before.
+		 * Upload both templates now, but only mark one valid. */
+		wl->beacon_templates_virgin = false;
+		b43_upload_beacon0(dev);
+		b43_upload_beacon1(dev);
+		cmd = b43_read32(dev, B43_MMIO_MACCMD);
+		cmd |= B43_MACCMD_BEACON0_VALID;
+		b43_write32(dev, B43_MMIO_MACCMD, cmd);
+	} else {
+		if (!beacon0_valid) {
+			b43_upload_beacon0(dev);
+			cmd = b43_read32(dev, B43_MMIO_MACCMD);
+			cmd |= B43_MACCMD_BEACON0_VALID;
+			b43_write32(dev, B43_MMIO_MACCMD, cmd);
+		} else if (!beacon1_valid) {
+			b43_upload_beacon1(dev);
+			cmd = b43_read32(dev, B43_MMIO_MACCMD);
+			cmd |= B43_MACCMD_BEACON1_VALID;
+			b43_write32(dev, B43_MMIO_MACCMD, cmd);
+		}
+	}
+}
+
+static void b43_do_beacon_update_trigger_work(struct b43_wldev *dev)
+{
+	u32 old_irq_mask = dev->irq_mask;
+
+	/* update beacon right away or defer to irq */
+	handle_irq_beacon(dev);
+	if (old_irq_mask != dev->irq_mask) {
+		/* The handler updated the IRQ mask. */
+		B43_WARN_ON(!dev->irq_mask);
+		if (b43_read32(dev, B43_MMIO_GEN_IRQ_MASK)) {
+			b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
+		} else {
+			/* Device interrupts are currently disabled. That means
+			 * we just ran the hardirq handler and scheduled the
+			 * IRQ thread. The thread will write the IRQ mask when
+			 * it finished, so there's nothing to do here. Writing
+			 * the mask _here_ would incorrectly re-enable IRQs. */
+		}
+	}
+}
+
+static void b43_beacon_update_trigger_work(struct work_struct *work)
+{
+	struct b43_wl *wl = container_of(work, struct b43_wl,
+					 beacon_update_trigger);
+	struct b43_wldev *dev;
+
+	mutex_lock(&wl->mutex);
+	dev = wl->current_dev;
+	if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
+		if (b43_bus_host_is_sdio(dev->dev)) {
+			/* wl->mutex is enough. */
+			b43_do_beacon_update_trigger_work(dev);
+			mmiowb();
+		} else {
+			spin_lock_irq(&wl->hardirq_lock);
+			b43_do_beacon_update_trigger_work(dev);
+			mmiowb();
+			spin_unlock_irq(&wl->hardirq_lock);
+		}
+	}
+	mutex_unlock(&wl->mutex);
+}
+
+/* Asynchronously update the packet templates in template RAM. */
+static void b43_update_templates(struct b43_wl *wl)
+{
+	struct sk_buff *beacon, *old_beacon;
+	unsigned long flags;
+
+	/* This is the top half of the asynchronous beacon update.
+	 * The bottom half is the beacon IRQ.
+	 * Beacon update must be asynchronous to avoid sending an
+	 * invalid beacon. This can happen for example, if the firmware
+	 * transmits a beacon while we are updating it. */
+
+	/* We could modify the existing beacon and set the aid bit in
+	 * the TIM field, but that would probably require resizing and
+	 * moving of data within the beacon template.
+	 * Simply request a new beacon and let mac80211 do the hard work. */
+	beacon = ieee80211_beacon_get(wl->hw, wl->vif);
+	if (unlikely(!beacon))
+		return;
+
+	spin_lock_irqsave(&wl->beacon_lock, flags);
+	old_beacon = wl->current_beacon;
+	wl->current_beacon = beacon;
+	wl->beacon0_uploaded = false;
+	wl->beacon1_uploaded = false;
+	spin_unlock_irqrestore(&wl->beacon_lock, flags);
+
+	ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger);
+
+	if (old_beacon)
+		dev_kfree_skb_any(old_beacon);
+}
+
+static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
+{
+	b43_time_lock(dev);
+	if (dev->dev->core_rev >= 3) {
+		b43_write32(dev, B43_MMIO_TSF_CFP_REP, (beacon_int << 16));
+		b43_write32(dev, B43_MMIO_TSF_CFP_START, (beacon_int << 10));
+	} else {
+		b43_write16(dev, 0x606, (beacon_int >> 6));
+		b43_write16(dev, 0x610, beacon_int);
+	}
+	b43_time_unlock(dev);
+	b43dbg(dev->wl, "Set beacon interval to %u\n", beacon_int);
+}
+
+static void b43_handle_firmware_panic(struct b43_wldev *dev)
+{
+	u16 reason;
+
+	/* Read the register that contains the reason code for the panic. */
+	reason = b43_shm_read16(dev, B43_SHM_SCRATCH, B43_FWPANIC_REASON_REG);
+	b43err(dev->wl, "Whoopsy, firmware panic! Reason: %u\n", reason);
+
+	switch (reason) {
+	default:
+		b43dbg(dev->wl, "The panic reason is unknown.\n");
+		/* fallthrough */
+	case B43_FWPANIC_DIE:
+		/* Do not restart the controller or firmware.
+		 * The device is nonfunctional from now on.
+		 * Restarting would result in this panic to trigger again,
+		 * so we avoid that recursion. */
+		break;
+	case B43_FWPANIC_RESTART:
+		b43_controller_restart(dev, "Microcode panic");
+		break;
+	}
+}
+
+static void handle_irq_ucode_debug(struct b43_wldev *dev)
+{
+	unsigned int i, cnt;
+	u16 reason, marker_id, marker_line;
+	__le16 *buf;
+
+	/* The proprietary firmware doesn't have this IRQ. */
+	if (!dev->fw.opensource)
+		return;
+
+	/* Read the register that contains the reason code for this IRQ. */
+	reason = b43_shm_read16(dev, B43_SHM_SCRATCH, B43_DEBUGIRQ_REASON_REG);
+
+	switch (reason) {
+	case B43_DEBUGIRQ_PANIC:
+		b43_handle_firmware_panic(dev);
+		break;
+	case B43_DEBUGIRQ_DUMP_SHM:
+		if (!B43_DEBUG)
+			break; /* Only with driver debugging enabled. */
+		buf = kmalloc(4096, GFP_ATOMIC);
+		if (!buf) {
+			b43dbg(dev->wl, "SHM-dump: Failed to allocate memory\n");
+			goto out;
+		}
+		for (i = 0; i < 4096; i += 2) {
+			u16 tmp = b43_shm_read16(dev, B43_SHM_SHARED, i);
+			buf[i / 2] = cpu_to_le16(tmp);
+		}
+		b43info(dev->wl, "Shared memory dump:\n");
+		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET,
+			       16, 2, buf, 4096, 1);
+		kfree(buf);
+		break;
+	case B43_DEBUGIRQ_DUMP_REGS:
+		if (!B43_DEBUG)
+			break; /* Only with driver debugging enabled. */
+		b43info(dev->wl, "Microcode register dump:\n");
+		for (i = 0, cnt = 0; i < 64; i++) {
+			u16 tmp = b43_shm_read16(dev, B43_SHM_SCRATCH, i);
+			if (cnt == 0)
+				printk(KERN_INFO);
+			printk("r%02u: 0x%04X  ", i, tmp);
+			cnt++;
+			if (cnt == 6) {
+				printk("\n");
+				cnt = 0;
+			}
+		}
+		printk("\n");
+		break;
+	case B43_DEBUGIRQ_MARKER:
+		if (!B43_DEBUG)
+			break; /* Only with driver debugging enabled. */
+		marker_id = b43_shm_read16(dev, B43_SHM_SCRATCH,
+					   B43_MARKER_ID_REG);
+		marker_line = b43_shm_read16(dev, B43_SHM_SCRATCH,
+					     B43_MARKER_LINE_REG);
+		b43info(dev->wl, "The firmware just executed the MARKER(%u) "
+			"at line number %u\n",
+			marker_id, marker_line);
+		break;
+	default:
+		b43dbg(dev->wl, "Debug-IRQ triggered for unknown reason: %u\n",
+		       reason);
+	}
+out:
+	/* Acknowledge the debug-IRQ, so the firmware can continue. */
+	b43_shm_write16(dev, B43_SHM_SCRATCH,
+			B43_DEBUGIRQ_REASON_REG, B43_DEBUGIRQ_ACK);
+}
+
+static void b43_do_interrupt_thread(struct b43_wldev *dev)
+{
+	u32 reason;
+	u32 dma_reason[ARRAY_SIZE(dev->dma_reason)];
+	u32 merged_dma_reason = 0;
+	int i;
+
+	if (unlikely(b43_status(dev) != B43_STAT_STARTED))
+		return;
+
+	reason = dev->irq_reason;
+	for (i = 0; i < ARRAY_SIZE(dma_reason); i++) {
+		dma_reason[i] = dev->dma_reason[i];
+		merged_dma_reason |= dma_reason[i];
+	}
+
+	if (unlikely(reason & B43_IRQ_MAC_TXERR))
+		b43err(dev->wl, "MAC transmission error\n");
+
+	if (unlikely(reason & B43_IRQ_PHY_TXERR)) {
+		b43err(dev->wl, "PHY transmission error\n");
+		rmb();
+		if (unlikely(atomic_dec_and_test(&dev->phy.txerr_cnt))) {
+			atomic_set(&dev->phy.txerr_cnt,
+				   B43_PHY_TX_BADNESS_LIMIT);
+			b43err(dev->wl, "Too many PHY TX errors, "
+					"restarting the controller\n");
+			b43_controller_restart(dev, "PHY TX errors");
+		}
+	}
+
+	if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK))) {
+		b43err(dev->wl,
+			"Fatal DMA error: 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X\n",
+			dma_reason[0], dma_reason[1],
+			dma_reason[2], dma_reason[3],
+			dma_reason[4], dma_reason[5]);
+		b43err(dev->wl, "This device does not support DMA "
+			       "on your system. It will now be switched to PIO.\n");
+		/* Fall back to PIO transfers if we get fatal DMA errors! */
+		dev->use_pio = true;
+		b43_controller_restart(dev, "DMA error");
+		return;
+	}
+
+	if (unlikely(reason & B43_IRQ_UCODE_DEBUG))
+		handle_irq_ucode_debug(dev);
+	if (reason & B43_IRQ_TBTT_INDI)
+		handle_irq_tbtt_indication(dev);
+	if (reason & B43_IRQ_ATIM_END)
+		handle_irq_atim_end(dev);
+	if (reason & B43_IRQ_BEACON)
+		handle_irq_beacon(dev);
+	if (reason & B43_IRQ_PMQ)
+		handle_irq_pmq(dev);
+	if (reason & B43_IRQ_TXFIFO_FLUSH_OK)
+		;/* TODO */
+	if (reason & B43_IRQ_NOISESAMPLE_OK)
+		handle_irq_noise(dev);
+
+	/* Check the DMA reason registers for received data. */
+	if (dma_reason[0] & B43_DMAIRQ_RDESC_UFLOW) {
+		if (B43_DEBUG)
+			b43warn(dev->wl, "RX descriptor underrun\n");
+		b43_dma_handle_rx_overflow(dev->dma.rx_ring);
+	}
+	if (dma_reason[0] & B43_DMAIRQ_RX_DONE) {
+		if (b43_using_pio_transfers(dev))
+			b43_pio_rx(dev->pio.rx_queue);
+		else
+			b43_dma_rx(dev->dma.rx_ring);
+	}
+	B43_WARN_ON(dma_reason[1] & B43_DMAIRQ_RX_DONE);
+	B43_WARN_ON(dma_reason[2] & B43_DMAIRQ_RX_DONE);
+	B43_WARN_ON(dma_reason[3] & B43_DMAIRQ_RX_DONE);
+	B43_WARN_ON(dma_reason[4] & B43_DMAIRQ_RX_DONE);
+	B43_WARN_ON(dma_reason[5] & B43_DMAIRQ_RX_DONE);
+
+	if (reason & B43_IRQ_TX_OK)
+		handle_irq_transmit_status(dev);
+
+	/* Re-enable interrupts on the device by restoring the current interrupt mask. */
+	b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
+
+#if B43_DEBUG
+	if (b43_debug(dev, B43_DBG_VERBOSESTATS)) {
+		dev->irq_count++;
+		for (i = 0; i < ARRAY_SIZE(dev->irq_bit_count); i++) {
+			if (reason & (1 << i))
+				dev->irq_bit_count[i]++;
+		}
+	}
+#endif
+}
+
+/* Interrupt thread handler. Handles device interrupts in thread context. */
+static irqreturn_t b43_interrupt_thread_handler(int irq, void *dev_id)
+{
+	struct b43_wldev *dev = dev_id;
+
+	mutex_lock(&dev->wl->mutex);
+	b43_do_interrupt_thread(dev);
+	mmiowb();
+	mutex_unlock(&dev->wl->mutex);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t b43_do_interrupt(struct b43_wldev *dev)
+{
+	u32 reason;
+
+	/* This code runs under wl->hardirq_lock, but _only_ on non-SDIO busses.
+	 * On SDIO, this runs under wl->mutex. */
+
+	reason = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
+	if (reason == 0xffffffff)	/* shared IRQ */
+		return IRQ_NONE;
+	reason &= dev->irq_mask;
+	if (!reason)
+		return IRQ_NONE;
+
+	dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON)
+	    & 0x0001FC00;
+	dev->dma_reason[1] = b43_read32(dev, B43_MMIO_DMA1_REASON)
+	    & 0x0000DC00;
+	dev->dma_reason[2] = b43_read32(dev, B43_MMIO_DMA2_REASON)
+	    & 0x0000DC00;
+	dev->dma_reason[3] = b43_read32(dev, B43_MMIO_DMA3_REASON)
+	    & 0x0001DC00;
+	dev->dma_reason[4] = b43_read32(dev, B43_MMIO_DMA4_REASON)
+	    & 0x0000DC00;
+/* Unused ring
+	dev->dma_reason[5] = b43_read32(dev, B43_MMIO_DMA5_REASON)
+	    & 0x0000DC00;
+*/
+
+	/* ACK the interrupt. */
+	b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, reason);
+	b43_write32(dev, B43_MMIO_DMA0_REASON, dev->dma_reason[0]);
+	b43_write32(dev, B43_MMIO_DMA1_REASON, dev->dma_reason[1]);
+	b43_write32(dev, B43_MMIO_DMA2_REASON, dev->dma_reason[2]);
+	b43_write32(dev, B43_MMIO_DMA3_REASON, dev->dma_reason[3]);
+	b43_write32(dev, B43_MMIO_DMA4_REASON, dev->dma_reason[4]);
+/* Unused ring
+	b43_write32(dev, B43_MMIO_DMA5_REASON, dev->dma_reason[5]);
+*/
+
+	/* Disable IRQs on the device. The IRQ thread handler will re-enable them. */
+	b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
+	/* Save the reason bitmasks for the IRQ thread handler. */
+	dev->irq_reason = reason;
+
+	return IRQ_WAKE_THREAD;
+}
+
+/* Interrupt handler top-half. This runs with interrupts disabled. */
+static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
+{
+	struct b43_wldev *dev = dev_id;
+	irqreturn_t ret;
+
+	if (unlikely(b43_status(dev) < B43_STAT_STARTED))
+		return IRQ_NONE;
+
+	spin_lock(&dev->wl->hardirq_lock);
+	ret = b43_do_interrupt(dev);
+	mmiowb();
+	spin_unlock(&dev->wl->hardirq_lock);
+
+	return ret;
+}
+
+/* SDIO interrupt handler. This runs in process context. */
+static void b43_sdio_interrupt_handler(struct b43_wldev *dev)
+{
+	struct b43_wl *wl = dev->wl;
+	irqreturn_t ret;
+
+	mutex_lock(&wl->mutex);
+
+	ret = b43_do_interrupt(dev);
+	if (ret == IRQ_WAKE_THREAD)
+		b43_do_interrupt_thread(dev);
+
+	mutex_unlock(&wl->mutex);
+}
+
+void b43_do_release_fw(struct b43_firmware_file *fw)
+{
+	release_firmware(fw->data);
+	fw->data = NULL;
+	fw->filename = NULL;
+}
+
+static void b43_release_firmware(struct b43_wldev *dev)
+{
+	complete(&dev->fw_load_complete);
+	b43_do_release_fw(&dev->fw.ucode);
+	b43_do_release_fw(&dev->fw.pcm);
+	b43_do_release_fw(&dev->fw.initvals);
+	b43_do_release_fw(&dev->fw.initvals_band);
+}
+
+static void b43_print_fw_helptext(struct b43_wl *wl, bool error)
+{
+	const char text[] =
+		"You must go to " \
+		"http://wireless.kernel.org/en/users/Drivers/b43#devicefirmware " \
+		"and download the correct firmware for this driver version. " \
+		"Please carefully read all instructions on this website.\n";
+
+	if (error)
+		b43err(wl, text);
+	else
+		b43warn(wl, text);
+}
+
+static void b43_fw_cb(const struct firmware *firmware, void *context)
+{
+	struct b43_request_fw_context *ctx = context;
+
+	ctx->blob = firmware;
+	complete(&ctx->dev->fw_load_complete);
+}
+
+int b43_do_request_fw(struct b43_request_fw_context *ctx,
+		      const char *name,
+		      struct b43_firmware_file *fw, bool async)
+{
+	struct b43_fw_header *hdr;
+	u32 size;
+	int err;
+
+	if (!name) {
+		/* Don't fetch anything. Free possibly cached firmware. */
+		/* FIXME: We should probably keep it anyway, to save some headache
+		 * on suspend/resume with multiband devices. */
+		b43_do_release_fw(fw);
+		return 0;
+	}
+	if (fw->filename) {
+		if ((fw->type == ctx->req_type) &&
+		    (strcmp(fw->filename, name) == 0))
+			return 0; /* Already have this fw. */
+		/* Free the cached firmware first. */
+		/* FIXME: We should probably do this later after we successfully
+		 * got the new fw. This could reduce headache with multiband devices.
+		 * We could also redesign this to cache the firmware for all possible
+		 * bands all the time. */
+		b43_do_release_fw(fw);
+	}
+
+	switch (ctx->req_type) {
+	case B43_FWTYPE_PROPRIETARY:
+		snprintf(ctx->fwname, sizeof(ctx->fwname),
+			 "b43%s/%s.fw",
+			 modparam_fwpostfix, name);
+		break;
+	case B43_FWTYPE_OPENSOURCE:
+		snprintf(ctx->fwname, sizeof(ctx->fwname),
+			 "b43-open%s/%s.fw",
+			 modparam_fwpostfix, name);
+		break;
+	default:
+		B43_WARN_ON(1);
+		return -ENOSYS;
+	}
+	if (async) {
+		/* do this part asynchronously */
+		init_completion(&ctx->dev->fw_load_complete);
+		err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname,
+					      ctx->dev->dev->dev, GFP_KERNEL,
+					      ctx, b43_fw_cb);
+		if (err < 0) {
+			pr_err("Unable to load firmware\n");
+			return err;
+		}
+		wait_for_completion(&ctx->dev->fw_load_complete);
+		if (ctx->blob)
+			goto fw_ready;
+	/* On some ARM systems, the async request will fail, but the next sync
+	 * request works. For this reason, we fall through here
+	 */
+	}
+	err = request_firmware(&ctx->blob, ctx->fwname,
+			       ctx->dev->dev->dev);
+	if (err == -ENOENT) {
+		snprintf(ctx->errors[ctx->req_type],
+			 sizeof(ctx->errors[ctx->req_type]),
+			 "Firmware file \"%s\" not found\n",
+			 ctx->fwname);
+		return err;
+	} else if (err) {
+		snprintf(ctx->errors[ctx->req_type],
+			 sizeof(ctx->errors[ctx->req_type]),
+			 "Firmware file \"%s\" request failed (err=%d)\n",
+			 ctx->fwname, err);
+		return err;
+	}
+fw_ready:
+	if (ctx->blob->size < sizeof(struct b43_fw_header))
+		goto err_format;
+	hdr = (struct b43_fw_header *)(ctx->blob->data);
+	switch (hdr->type) {
+	case B43_FW_TYPE_UCODE:
+	case B43_FW_TYPE_PCM:
+		size = be32_to_cpu(hdr->size);
+		if (size != ctx->blob->size - sizeof(struct b43_fw_header))
+			goto err_format;
+		/* fallthrough */
+	case B43_FW_TYPE_IV:
+		if (hdr->ver != 1)
+			goto err_format;
+		break;
+	default:
+		goto err_format;
+	}
+
+	fw->data = ctx->blob;
+	fw->filename = name;
+	fw->type = ctx->req_type;
+
+	return 0;
+
+err_format:
+	snprintf(ctx->errors[ctx->req_type],
+		 sizeof(ctx->errors[ctx->req_type]),
+		 "Firmware file \"%s\" format error.\n", ctx->fwname);
+	release_firmware(ctx->blob);
+
+	return -EPROTO;
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/Init/Firmware */
+static int b43_try_request_fw(struct b43_request_fw_context *ctx)
+{
+	struct b43_wldev *dev = ctx->dev;
+	struct b43_firmware *fw = &ctx->dev->fw;
+	struct b43_phy *phy = &dev->phy;
+	const u8 rev = ctx->dev->dev->core_rev;
+	const char *filename;
+	int err;
+
+	/* Get microcode */
+	filename = NULL;
+	switch (rev) {
+	case 42:
+		if (phy->type == B43_PHYTYPE_AC)
+			filename = "ucode42";
+		break;
+	case 40:
+		if (phy->type == B43_PHYTYPE_AC)
+			filename = "ucode40";
+		break;
+	case 33:
+		if (phy->type == B43_PHYTYPE_LCN40)
+			filename = "ucode33_lcn40";
+		break;
+	case 30:
+		if (phy->type == B43_PHYTYPE_N)
+			filename = "ucode30_mimo";
+		break;
+	case 29:
+		if (phy->type == B43_PHYTYPE_HT)
+			filename = "ucode29_mimo";
+		break;
+	case 26:
+		if (phy->type == B43_PHYTYPE_HT)
+			filename = "ucode26_mimo";
+		break;
+	case 28:
+	case 25:
+		if (phy->type == B43_PHYTYPE_N)
+			filename = "ucode25_mimo";
+		else if (phy->type == B43_PHYTYPE_LCN)
+			filename = "ucode25_lcn";
+		break;
+	case 24:
+		if (phy->type == B43_PHYTYPE_LCN)
+			filename = "ucode24_lcn";
+		break;
+	case 23:
+		if (phy->type == B43_PHYTYPE_N)
+			filename = "ucode16_mimo";
+		break;
+	case 16 ... 19:
+		if (phy->type == B43_PHYTYPE_N)
+			filename = "ucode16_mimo";
+		else if (phy->type == B43_PHYTYPE_LP)
+			filename = "ucode16_lp";
+		break;
+	case 15:
+		filename = "ucode15";
+		break;
+	case 14:
+		filename = "ucode14";
+		break;
+	case 13:
+		filename = "ucode13";
+		break;
+	case 11 ... 12:
+		filename = "ucode11";
+		break;
+	case 5 ... 10:
+		filename = "ucode5";
+		break;
+	}
+	if (!filename)
+		goto err_no_ucode;
+	err = b43_do_request_fw(ctx, filename, &fw->ucode, true);
+	if (err)
+		goto err_load;
+
+	/* Get PCM code */
+	if ((rev >= 5) && (rev <= 10))
+		filename = "pcm5";
+	else if (rev >= 11)
+		filename = NULL;
+	else
+		goto err_no_pcm;
+	fw->pcm_request_failed = false;
+	err = b43_do_request_fw(ctx, filename, &fw->pcm, false);
+	if (err == -ENOENT) {
+		/* We did not find a PCM file? Not fatal, but
+		 * core rev <= 10 must do without hwcrypto then. */
+		fw->pcm_request_failed = true;
+	} else if (err)
+		goto err_load;
+
+	/* Get initvals */
+	filename = NULL;
+	switch (dev->phy.type) {
+	case B43_PHYTYPE_G:
+		if (rev == 13)
+			filename = "b0g0initvals13";
+		else if (rev >= 5 && rev <= 10)
+			filename = "b0g0initvals5";
+		break;
+	case B43_PHYTYPE_N:
+		if (rev == 30)
+			filename = "n16initvals30";
+		else if (rev == 28 || rev == 25)
+			filename = "n0initvals25";
+		else if (rev == 24)
+			filename = "n0initvals24";
+		else if (rev == 23)
+			filename = "n0initvals16"; /* What about n0initvals22? */
+		else if (rev >= 16 && rev <= 18)
+			filename = "n0initvals16";
+		else if (rev >= 11 && rev <= 12)
+			filename = "n0initvals11";
+		break;
+	case B43_PHYTYPE_LP:
+		if (rev >= 16 && rev <= 18)
+			filename = "lp0initvals16";
+		else if (rev == 15)
+			filename = "lp0initvals15";
+		else if (rev == 14)
+			filename = "lp0initvals14";
+		else if (rev == 13)
+			filename = "lp0initvals13";
+		break;
+	case B43_PHYTYPE_HT:
+		if (rev == 29)
+			filename = "ht0initvals29";
+		else if (rev == 26)
+			filename = "ht0initvals26";
+		break;
+	case B43_PHYTYPE_LCN:
+		if (rev == 24)
+			filename = "lcn0initvals24";
+		break;
+	case B43_PHYTYPE_LCN40:
+		if (rev == 33)
+			filename = "lcn400initvals33";
+		break;
+	case B43_PHYTYPE_AC:
+		if (rev == 42)
+			filename = "ac1initvals42";
+		else if (rev == 40)
+			filename = "ac0initvals40";
+		break;
+	}
+	if (!filename)
+		goto err_no_initvals;
+	err = b43_do_request_fw(ctx, filename, &fw->initvals, false);
+	if (err)
+		goto err_load;
+
+	/* Get bandswitch initvals */
+	filename = NULL;
+	switch (dev->phy.type) {
+	case B43_PHYTYPE_G:
+		if (rev == 13)
+			filename = "b0g0bsinitvals13";
+		else if (rev >= 5 && rev <= 10)
+			filename = "b0g0bsinitvals5";
+		break;
+	case B43_PHYTYPE_N:
+		if (rev == 30)
+			filename = "n16bsinitvals30";
+		else if (rev == 28 || rev == 25)
+			filename = "n0bsinitvals25";
+		else if (rev == 24)
+			filename = "n0bsinitvals24";
+		else if (rev == 23)
+			filename = "n0bsinitvals16"; /* What about n0bsinitvals22? */
+		else if (rev >= 16 && rev <= 18)
+			filename = "n0bsinitvals16";
+		else if (rev >= 11 && rev <= 12)
+			filename = "n0bsinitvals11";
+		break;
+	case B43_PHYTYPE_LP:
+		if (rev >= 16 && rev <= 18)
+			filename = "lp0bsinitvals16";
+		else if (rev == 15)
+			filename = "lp0bsinitvals15";
+		else if (rev == 14)
+			filename = "lp0bsinitvals14";
+		else if (rev == 13)
+			filename = "lp0bsinitvals13";
+		break;
+	case B43_PHYTYPE_HT:
+		if (rev == 29)
+			filename = "ht0bsinitvals29";
+		else if (rev == 26)
+			filename = "ht0bsinitvals26";
+		break;
+	case B43_PHYTYPE_LCN:
+		if (rev == 24)
+			filename = "lcn0bsinitvals24";
+		break;
+	case B43_PHYTYPE_LCN40:
+		if (rev == 33)
+			filename = "lcn400bsinitvals33";
+		break;
+	case B43_PHYTYPE_AC:
+		if (rev == 42)
+			filename = "ac1bsinitvals42";
+		else if (rev == 40)
+			filename = "ac0bsinitvals40";
+		break;
+	}
+	if (!filename)
+		goto err_no_initvals;
+	err = b43_do_request_fw(ctx, filename, &fw->initvals_band, false);
+	if (err)
+		goto err_load;
+
+	fw->opensource = (ctx->req_type == B43_FWTYPE_OPENSOURCE);
+
+	return 0;
+
+err_no_ucode:
+	err = ctx->fatal_failure = -EOPNOTSUPP;
+	b43err(dev->wl, "The driver does not know which firmware (ucode) "
+	       "is required for your device (wl-core rev %u)\n", rev);
+	goto error;
+
+err_no_pcm:
+	err = ctx->fatal_failure = -EOPNOTSUPP;
+	b43err(dev->wl, "The driver does not know which firmware (PCM) "
+	       "is required for your device (wl-core rev %u)\n", rev);
+	goto error;
+
+err_no_initvals:
+	err = ctx->fatal_failure = -EOPNOTSUPP;
+	b43err(dev->wl, "The driver does not know which firmware (initvals) "
+	       "is required for your device (wl-core rev %u)\n", rev);
+	goto error;
+
+err_load:
+	/* We failed to load this firmware image. The error message
+	 * already is in ctx->errors. Return and let our caller decide
+	 * what to do. */
+	goto error;
+
+error:
+	b43_release_firmware(dev);
+	return err;
+}
+
+static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl);
+static void b43_one_core_detach(struct b43_bus_dev *dev);
+static int b43_rng_init(struct b43_wl *wl);
+
+static void b43_request_firmware(struct work_struct *work)
+{
+	struct b43_wl *wl = container_of(work,
+			    struct b43_wl, firmware_load);
+	struct b43_wldev *dev = wl->current_dev;
+	struct b43_request_fw_context *ctx;
+	unsigned int i;
+	int err;
+	const char *errmsg;
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return;
+	ctx->dev = dev;
+
+	ctx->req_type = B43_FWTYPE_PROPRIETARY;
+	err = b43_try_request_fw(ctx);
+	if (!err)
+		goto start_ieee80211; /* Successfully loaded it. */
+	/* Was fw version known? */
+	if (ctx->fatal_failure)
+		goto out;
+
+	/* proprietary fw not found, try open source */
+	ctx->req_type = B43_FWTYPE_OPENSOURCE;
+	err = b43_try_request_fw(ctx);
+	if (!err)
+		goto start_ieee80211; /* Successfully loaded it. */
+	if(ctx->fatal_failure)
+		goto out;
+
+	/* Could not find a usable firmware. Print the errors. */
+	for (i = 0; i < B43_NR_FWTYPES; i++) {
+		errmsg = ctx->errors[i];
+		if (strlen(errmsg))
+			b43err(dev->wl, "%s", errmsg);
+	}
+	b43_print_fw_helptext(dev->wl, 1);
+	goto out;
+
+start_ieee80211:
+	wl->hw->queues = B43_QOS_QUEUE_NUM;
+	if (!modparam_qos || dev->fw.opensource)
+		wl->hw->queues = 1;
+
+	err = ieee80211_register_hw(wl->hw);
+	if (err)
+		goto err_one_core_detach;
+	wl->hw_registred = true;
+	b43_leds_register(wl->current_dev);
+
+	/* Register HW RNG driver */
+	b43_rng_init(wl);
+
+	goto out;
+
+err_one_core_detach:
+	b43_one_core_detach(dev->dev);
+
+out:
+	kfree(ctx);
+}
+
+static int b43_upload_microcode(struct b43_wldev *dev)
+{
+	struct wiphy *wiphy = dev->wl->hw->wiphy;
+	const size_t hdr_len = sizeof(struct b43_fw_header);
+	const __be32 *data;
+	unsigned int i, len;
+	u16 fwrev, fwpatch, fwdate, fwtime;
+	u32 tmp, macctl;
+	int err = 0;
+
+	/* Jump the microcode PSM to offset 0 */
+	macctl = b43_read32(dev, B43_MMIO_MACCTL);
+	B43_WARN_ON(macctl & B43_MACCTL_PSM_RUN);
+	macctl |= B43_MACCTL_PSM_JMP0;
+	b43_write32(dev, B43_MMIO_MACCTL, macctl);
+	/* Zero out all microcode PSM registers and shared memory. */
+	for (i = 0; i < 64; i++)
+		b43_shm_write16(dev, B43_SHM_SCRATCH, i, 0);
+	for (i = 0; i < 4096; i += 2)
+		b43_shm_write16(dev, B43_SHM_SHARED, i, 0);
+
+	/* Upload Microcode. */
+	data = (__be32 *) (dev->fw.ucode.data->data + hdr_len);
+	len = (dev->fw.ucode.data->size - hdr_len) / sizeof(__be32);
+	b43_shm_control_word(dev, B43_SHM_UCODE | B43_SHM_AUTOINC_W, 0x0000);
+	for (i = 0; i < len; i++) {
+		b43_write32(dev, B43_MMIO_SHM_DATA, be32_to_cpu(data[i]));
+		udelay(10);
+	}
+
+	if (dev->fw.pcm.data) {
+		/* Upload PCM data. */
+		data = (__be32 *) (dev->fw.pcm.data->data + hdr_len);
+		len = (dev->fw.pcm.data->size - hdr_len) / sizeof(__be32);
+		b43_shm_control_word(dev, B43_SHM_HW, 0x01EA);
+		b43_write32(dev, B43_MMIO_SHM_DATA, 0x00004000);
+		/* No need for autoinc bit in SHM_HW */
+		b43_shm_control_word(dev, B43_SHM_HW, 0x01EB);
+		for (i = 0; i < len; i++) {
+			b43_write32(dev, B43_MMIO_SHM_DATA, be32_to_cpu(data[i]));
+			udelay(10);
+		}
+	}
+
+	b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_ALL);
+
+	/* Start the microcode PSM */
+	b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_PSM_JMP0,
+		      B43_MACCTL_PSM_RUN);
+
+	/* Wait for the microcode to load and respond */
+	i = 0;
+	while (1) {
+		tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
+		if (tmp == B43_IRQ_MAC_SUSPENDED)
+			break;
+		i++;
+		if (i >= 20) {
+			b43err(dev->wl, "Microcode not responding\n");
+			b43_print_fw_helptext(dev->wl, 1);
+			err = -ENODEV;
+			goto error;
+		}
+		msleep(50);
+	}
+	b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);	/* dummy read */
+
+	/* Get and check the revisions. */
+	fwrev = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_UCODEREV);
+	fwpatch = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_UCODEPATCH);
+	fwdate = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_UCODEDATE);
+	fwtime = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_UCODETIME);
+
+	if (fwrev <= 0x128) {
+		b43err(dev->wl, "YOUR FIRMWARE IS TOO OLD. Firmware from "
+		       "binary drivers older than version 4.x is unsupported. "
+		       "You must upgrade your firmware files.\n");
+		b43_print_fw_helptext(dev->wl, 1);
+		err = -EOPNOTSUPP;
+		goto error;
+	}
+	dev->fw.rev = fwrev;
+	dev->fw.patch = fwpatch;
+	if (dev->fw.rev >= 598)
+		dev->fw.hdr_format = B43_FW_HDR_598;
+	else if (dev->fw.rev >= 410)
+		dev->fw.hdr_format = B43_FW_HDR_410;
+	else
+		dev->fw.hdr_format = B43_FW_HDR_351;
+	WARN_ON(dev->fw.opensource != (fwdate == 0xFFFF));
+
+	dev->qos_enabled = dev->wl->hw->queues > 1;
+	/* Default to firmware/hardware crypto acceleration. */
+	dev->hwcrypto_enabled = true;
+
+	if (dev->fw.opensource) {
+		u16 fwcapa;
+
+		/* Patchlevel info is encoded in the "time" field. */
+		dev->fw.patch = fwtime;
+		b43info(dev->wl, "Loading OpenSource firmware version %u.%u\n",
+			dev->fw.rev, dev->fw.patch);
+
+		fwcapa = b43_fwcapa_read(dev);
+		if (!(fwcapa & B43_FWCAPA_HWCRYPTO) || dev->fw.pcm_request_failed) {
+			b43info(dev->wl, "Hardware crypto acceleration not supported by firmware\n");
+			/* Disable hardware crypto and fall back to software crypto. */
+			dev->hwcrypto_enabled = false;
+		}
+		/* adding QoS support should use an offline discovery mechanism */
+		WARN(fwcapa & B43_FWCAPA_QOS, "QoS in OpenFW not supported\n");
+	} else {
+		b43info(dev->wl, "Loading firmware version %u.%u "
+			"(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n",
+			fwrev, fwpatch,
+			(fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF,
+			(fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, fwtime & 0x1F);
+		if (dev->fw.pcm_request_failed) {
+			b43warn(dev->wl, "No \"pcm5.fw\" firmware file found. "
+				"Hardware accelerated cryptography is disabled.\n");
+			b43_print_fw_helptext(dev->wl, 0);
+		}
+	}
+
+	snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u",
+			dev->fw.rev, dev->fw.patch);
+	wiphy->hw_version = dev->dev->core_id;
+
+	if (dev->fw.hdr_format == B43_FW_HDR_351) {
+		/* We're over the deadline, but we keep support for old fw
+		 * until it turns out to be in major conflict with something new. */
+		b43warn(dev->wl, "You are using an old firmware image. "
+			"Support for old firmware will be removed soon "
+			"(official deadline was July 2008).\n");
+		b43_print_fw_helptext(dev->wl, 0);
+	}
+
+	return 0;
+
+error:
+	/* Stop the microcode PSM. */
+	b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_PSM_RUN,
+		      B43_MACCTL_PSM_JMP0);
+
+	return err;
+}
+
+static int b43_write_initvals(struct b43_wldev *dev,
+			      const struct b43_iv *ivals,
+			      size_t count,
+			      size_t array_size)
+{
+	const struct b43_iv *iv;
+	u16 offset;
+	size_t i;
+	bool bit32;
+
+	BUILD_BUG_ON(sizeof(struct b43_iv) != 6);
+	iv = ivals;
+	for (i = 0; i < count; i++) {
+		if (array_size < sizeof(iv->offset_size))
+			goto err_format;
+		array_size -= sizeof(iv->offset_size);
+		offset = be16_to_cpu(iv->offset_size);
+		bit32 = !!(offset & B43_IV_32BIT);
+		offset &= B43_IV_OFFSET_MASK;
+		if (offset >= 0x1000)
+			goto err_format;
+		if (bit32) {
+			u32 value;
+
+			if (array_size < sizeof(iv->data.d32))
+				goto err_format;
+			array_size -= sizeof(iv->data.d32);
+
+			value = get_unaligned_be32(&iv->data.d32);
+			b43_write32(dev, offset, value);
+
+			iv = (const struct b43_iv *)((const uint8_t *)iv +
+							sizeof(__be16) +
+							sizeof(__be32));
+		} else {
+			u16 value;
+
+			if (array_size < sizeof(iv->data.d16))
+				goto err_format;
+			array_size -= sizeof(iv->data.d16);
+
+			value = be16_to_cpu(iv->data.d16);
+			b43_write16(dev, offset, value);
+
+			iv = (const struct b43_iv *)((const uint8_t *)iv +
+							sizeof(__be16) +
+							sizeof(__be16));
+		}
+	}
+	if (array_size)
+		goto err_format;
+
+	return 0;
+
+err_format:
+	b43err(dev->wl, "Initial Values Firmware file-format error.\n");
+	b43_print_fw_helptext(dev->wl, 1);
+
+	return -EPROTO;
+}
+
+static int b43_upload_initvals(struct b43_wldev *dev)
+{
+	const size_t hdr_len = sizeof(struct b43_fw_header);
+	const struct b43_fw_header *hdr;
+	struct b43_firmware *fw = &dev->fw;
+	const struct b43_iv *ivals;
+	size_t count;
+
+	hdr = (const struct b43_fw_header *)(fw->initvals.data->data);
+	ivals = (const struct b43_iv *)(fw->initvals.data->data + hdr_len);
+	count = be32_to_cpu(hdr->size);
+	return b43_write_initvals(dev, ivals, count,
+				 fw->initvals.data->size - hdr_len);
+}
+
+static int b43_upload_initvals_band(struct b43_wldev *dev)
+{
+	const size_t hdr_len = sizeof(struct b43_fw_header);
+	const struct b43_fw_header *hdr;
+	struct b43_firmware *fw = &dev->fw;
+	const struct b43_iv *ivals;
+	size_t count;
+
+	if (!fw->initvals_band.data)
+		return 0;
+
+	hdr = (const struct b43_fw_header *)(fw->initvals_band.data->data);
+	ivals = (const struct b43_iv *)(fw->initvals_band.data->data + hdr_len);
+	count = be32_to_cpu(hdr->size);
+	return b43_write_initvals(dev, ivals, count,
+				  fw->initvals_band.data->size - hdr_len);
+}
+
+/* Initialize the GPIOs
+ * http://bcm-specs.sipsolutions.net/GPIO
+ */
+
+#ifdef CONFIG_B43_SSB
+static struct ssb_device *b43_ssb_gpio_dev(struct b43_wldev *dev)
+{
+	struct ssb_bus *bus = dev->dev->sdev->bus;
+
+#ifdef CONFIG_SSB_DRIVER_PCICORE
+	return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev);
+#else
+	return bus->chipco.dev;
+#endif
+}
+#endif
+
+static int b43_gpio_init(struct b43_wldev *dev)
+{
+#ifdef CONFIG_B43_SSB
+	struct ssb_device *gpiodev;
+#endif
+	u32 mask, set;
+
+	b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0);
+	b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, 0xF);
+
+	mask = 0x0000001F;
+	set = 0x0000000F;
+	if (dev->dev->chip_id == 0x4301) {
+		mask |= 0x0060;
+		set |= 0x0060;
+	} else if (dev->dev->chip_id == 0x5354) {
+		/* Don't allow overtaking buttons GPIOs */
+		set &= 0x2; /* 0x2 is LED GPIO on BCM5354 */
+	}
+
+	if (0 /* FIXME: conditional unknown */ ) {
+		b43_write16(dev, B43_MMIO_GPIO_MASK,
+			    b43_read16(dev, B43_MMIO_GPIO_MASK)
+			    | 0x0100);
+		/* BT Coexistance Input */
+		mask |= 0x0080;
+		set |= 0x0080;
+		/* BT Coexistance Out */
+		mask |= 0x0100;
+		set |= 0x0100;
+	}
+	if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL) {
+		/* PA is controlled by gpio 9, let ucode handle it */
+		b43_write16(dev, B43_MMIO_GPIO_MASK,
+			    b43_read16(dev, B43_MMIO_GPIO_MASK)
+			    | 0x0200);
+		mask |= 0x0200;
+		set |= 0x0200;
+	}
+
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc, 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;
+}
+
+/* Turn off all GPIO stuff. Call this on module unload, for example. */
+static void b43_gpio_cleanup(struct b43_wldev *dev)
+{
+#ifdef CONFIG_B43_SSB
+	struct ssb_device *gpiodev;
+#endif
+
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc, ~0, 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 */
+void b43_mac_enable(struct b43_wldev *dev)
+{
+	if (b43_debug(dev, B43_DBG_FIRMWARE)) {
+		u16 fwstate;
+
+		fwstate = b43_shm_read16(dev, B43_SHM_SHARED,
+					 B43_SHM_SH_UCODESTAT);
+		if ((fwstate != B43_SHM_SH_UCODESTAT_SUSP) &&
+		    (fwstate != B43_SHM_SH_UCODESTAT_SLEEP)) {
+			b43err(dev->wl, "b43_mac_enable(): The firmware "
+			       "should be suspended, but current state is %u\n",
+			       fwstate);
+		}
+	}
+
+	dev->mac_suspended--;
+	B43_WARN_ON(dev->mac_suspended < 0);
+	if (dev->mac_suspended == 0) {
+		b43_maskset32(dev, B43_MMIO_MACCTL, ~0, B43_MACCTL_ENABLED);
+		b43_write32(dev, B43_MMIO_GEN_IRQ_REASON,
+			    B43_IRQ_MAC_SUSPENDED);
+		/* Commit writes */
+		b43_read32(dev, B43_MMIO_MACCTL);
+		b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
+		b43_power_saving_ctl_bits(dev, 0);
+	}
+}
+
+/* http://bcm-specs.sipsolutions.net/SuspendMAC */
+void b43_mac_suspend(struct b43_wldev *dev)
+{
+	int i;
+	u32 tmp;
+
+	might_sleep();
+	B43_WARN_ON(dev->mac_suspended < 0);
+
+	if (dev->mac_suspended == 0) {
+		b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
+		b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_ENABLED, 0);
+		/* force pci to flush the write */
+		b43_read32(dev, B43_MMIO_MACCTL);
+		for (i = 35; i; i--) {
+			tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
+			if (tmp & B43_IRQ_MAC_SUSPENDED)
+				goto out;
+			udelay(10);
+		}
+		/* Hm, it seems this will take some time. Use msleep(). */
+		for (i = 40; i; i--) {
+			tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
+			if (tmp & B43_IRQ_MAC_SUSPENDED)
+				goto out;
+			msleep(1);
+		}
+		b43err(dev->wl, "MAC suspend failed\n");
+	}
+out:
+	dev->mac_suspended++;
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */
+void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on)
+{
+	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
+	}
+}
+
+/* brcms_b_switch_macfreq */
+void b43_mac_switch_freq(struct b43_wldev *dev, u8 spurmode)
+{
+	u16 chip_id = dev->dev->chip_id;
+
+	if (chip_id == BCMA_CHIP_ID_BCM4331) {
+		switch (spurmode) {
+		case 2: /* 168 Mhz: 2^26/168 = 0x61862 */
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x1862);
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x6);
+			break;
+		case 1: /* 164 Mhz: 2^26/164 = 0x63e70 */
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x3e70);
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x6);
+			break;
+		default: /* 160 Mhz: 2^26/160 = 0x66666 */
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x6666);
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x6);
+			break;
+		}
+	} else if (chip_id == BCMA_CHIP_ID_BCM43131 ||
+	    chip_id == BCMA_CHIP_ID_BCM43217 ||
+	    chip_id == BCMA_CHIP_ID_BCM43222 ||
+	    chip_id == BCMA_CHIP_ID_BCM43224 ||
+	    chip_id == BCMA_CHIP_ID_BCM43225 ||
+	    chip_id == BCMA_CHIP_ID_BCM43227 ||
+	    chip_id == BCMA_CHIP_ID_BCM43228) {
+		switch (spurmode) {
+		case 2: /* 126 Mhz */
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x2082);
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
+			break;
+		case 1: /* 123 Mhz */
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x5341);
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
+			break;
+		default: /* 120 Mhz */
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x8889);
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
+			break;
+		}
+	} else if (dev->phy.type == B43_PHYTYPE_LCN) {
+		switch (spurmode) {
+		case 1: /* 82 Mhz */
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x7CE0);
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
+			break;
+		default: /* 80 Mhz */
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0xCCCD);
+			b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
+			break;
+		}
+	}
+}
+
+static void b43_adjust_opmode(struct b43_wldev *dev)
+{
+	struct b43_wl *wl = dev->wl;
+	u32 ctl;
+	u16 cfp_pretbtt;
+
+	ctl = b43_read32(dev, B43_MMIO_MACCTL);
+	/* Reset status to STA infrastructure mode. */
+	ctl &= ~B43_MACCTL_AP;
+	ctl &= ~B43_MACCTL_KEEP_CTL;
+	ctl &= ~B43_MACCTL_KEEP_BADPLCP;
+	ctl &= ~B43_MACCTL_KEEP_BAD;
+	ctl &= ~B43_MACCTL_PROMISC;
+	ctl &= ~B43_MACCTL_BEACPROMISC;
+	ctl |= B43_MACCTL_INFRA;
+
+	if (b43_is_mode(wl, NL80211_IFTYPE_AP) ||
+	    b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT))
+		ctl |= B43_MACCTL_AP;
+	else if (b43_is_mode(wl, NL80211_IFTYPE_ADHOC))
+		ctl &= ~B43_MACCTL_INFRA;
+
+	if (wl->filter_flags & FIF_CONTROL)
+		ctl |= B43_MACCTL_KEEP_CTL;
+	if (wl->filter_flags & FIF_FCSFAIL)
+		ctl |= B43_MACCTL_KEEP_BAD;
+	if (wl->filter_flags & FIF_PLCPFAIL)
+		ctl |= B43_MACCTL_KEEP_BADPLCP;
+	if (wl->filter_flags & FIF_BCN_PRBRESP_PROMISC)
+		ctl |= B43_MACCTL_BEACPROMISC;
+
+	/* Workaround: On old hardware the HW-MAC-address-filter
+	 * doesn't work properly, so always run promisc in filter
+	 * it in software. */
+	if (dev->dev->core_rev <= 4)
+		ctl |= B43_MACCTL_PROMISC;
+
+	b43_write32(dev, B43_MMIO_MACCTL, ctl);
+
+	cfp_pretbtt = 2;
+	if ((ctl & B43_MACCTL_INFRA) && !(ctl & B43_MACCTL_AP)) {
+		if (dev->dev->chip_id == 0x4306 &&
+		    dev->dev->chip_rev == 3)
+			cfp_pretbtt = 100;
+		else
+			cfp_pretbtt = 50;
+	}
+	b43_write16(dev, 0x612, cfp_pretbtt);
+
+	/* FIXME: We don't currently implement the PMQ mechanism,
+	 *        so always disable it. If we want to implement PMQ,
+	 *        we need to enable it here (clear DISCPMQ) in AP mode.
+	 */
+	if (0  /* ctl & B43_MACCTL_AP */)
+		b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_DISCPMQ, 0);
+	else
+		b43_maskset32(dev, B43_MMIO_MACCTL, ~0, B43_MACCTL_DISCPMQ);
+}
+
+static void b43_rate_memory_write(struct b43_wldev *dev, u16 rate, int is_ofdm)
+{
+	u16 offset;
+
+	if (is_ofdm) {
+		offset = 0x480;
+		offset += (b43_plcp_get_ratecode_ofdm(rate) & 0x000F) * 2;
+	} else {
+		offset = 0x4C0;
+		offset += (b43_plcp_get_ratecode_cck(rate) & 0x000F) * 2;
+	}
+	b43_shm_write16(dev, B43_SHM_SHARED, offset + 0x20,
+			b43_shm_read16(dev, B43_SHM_SHARED, offset));
+}
+
+static void b43_rate_memory_init(struct b43_wldev *dev)
+{
+	switch (dev->phy.type) {
+	case B43_PHYTYPE_G:
+	case B43_PHYTYPE_N:
+	case B43_PHYTYPE_LP:
+	case B43_PHYTYPE_HT:
+	case B43_PHYTYPE_LCN:
+		b43_rate_memory_write(dev, B43_OFDM_RATE_6MB, 1);
+		b43_rate_memory_write(dev, B43_OFDM_RATE_9MB, 1);
+		b43_rate_memory_write(dev, B43_OFDM_RATE_12MB, 1);
+		b43_rate_memory_write(dev, B43_OFDM_RATE_18MB, 1);
+		b43_rate_memory_write(dev, B43_OFDM_RATE_24MB, 1);
+		b43_rate_memory_write(dev, B43_OFDM_RATE_36MB, 1);
+		b43_rate_memory_write(dev, B43_OFDM_RATE_48MB, 1);
+		b43_rate_memory_write(dev, B43_OFDM_RATE_54MB, 1);
+		/* fallthrough */
+	case B43_PHYTYPE_B:
+		b43_rate_memory_write(dev, B43_CCK_RATE_1MB, 0);
+		b43_rate_memory_write(dev, B43_CCK_RATE_2MB, 0);
+		b43_rate_memory_write(dev, B43_CCK_RATE_5MB, 0);
+		b43_rate_memory_write(dev, B43_CCK_RATE_11MB, 0);
+		break;
+	default:
+		B43_WARN_ON(1);
+	}
+}
+
+/* Set the default values for the PHY TX Control Words. */
+static void b43_set_phytxctl_defaults(struct b43_wldev *dev)
+{
+	u16 ctl = 0;
+
+	ctl |= B43_TXH_PHY_ENC_CCK;
+	ctl |= B43_TXH_PHY_ANT01AUTO;
+	ctl |= B43_TXH_PHY_TXPWR;
+
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, ctl);
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL, ctl);
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL, ctl);
+}
+
+/* Set the TX-Antenna for management frames sent by firmware. */
+static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna)
+{
+	u16 ant;
+	u16 tmp;
+
+	ant = b43_antenna_to_phyctl(antenna);
+
+	/* For ACK/CTS */
+	tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL);
+	tmp = (tmp & ~B43_TXH_PHY_ANT) | ant;
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL, tmp);
+	/* For Probe Resposes */
+	tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL);
+	tmp = (tmp & ~B43_TXH_PHY_ANT) | ant;
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL, tmp);
+}
+
+/* This is the opposite of b43_chip_init() */
+static void b43_chip_exit(struct b43_wldev *dev)
+{
+	b43_phy_exit(dev);
+	b43_gpio_cleanup(dev);
+	/* firmware is released later */
+}
+
+/* Initialize the chip
+ * http://bcm-specs.sipsolutions.net/ChipInit
+ */
+static int b43_chip_init(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	int err;
+	u32 macctl;
+	u16 value16;
+
+	/* Initialize the MAC control */
+	macctl = B43_MACCTL_IHR_ENABLED | B43_MACCTL_SHM_ENABLED;
+	if (dev->phy.gmode)
+		macctl |= B43_MACCTL_GMODE;
+	macctl |= B43_MACCTL_INFRA;
+	b43_write32(dev, B43_MMIO_MACCTL, macctl);
+
+	err = b43_upload_microcode(dev);
+	if (err)
+		goto out;	/* firmware is released later */
+
+	err = b43_gpio_init(dev);
+	if (err)
+		goto out;	/* firmware is released later */
+
+	err = b43_upload_initvals(dev);
+	if (err)
+		goto err_gpio_clean;
+
+	err = b43_upload_initvals_band(dev);
+	if (err)
+		goto err_gpio_clean;
+
+	/* Turn the Analog on and initialize the PHY. */
+	phy->ops->switch_analog(dev, 1);
+	err = b43_phy_init(dev);
+	if (err)
+		goto err_gpio_clean;
+
+	/* Disable Interference Mitigation. */
+	if (phy->ops->interf_mitigation)
+		phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE);
+
+	/* Select the antennae */
+	if (phy->ops->set_rx_antenna)
+		phy->ops->set_rx_antenna(dev, B43_ANTENNA_DEFAULT);
+	b43_mgmtframe_txantenna(dev, B43_ANTENNA_DEFAULT);
+
+	if (phy->type == B43_PHYTYPE_B) {
+		value16 = b43_read16(dev, 0x005E);
+		value16 |= 0x0004;
+		b43_write16(dev, 0x005E, value16);
+	}
+	b43_write32(dev, 0x0100, 0x01000000);
+	if (dev->dev->core_rev < 5)
+		b43_write32(dev, 0x010C, 0x01000000);
+
+	b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_INFRA, 0);
+	b43_maskset32(dev, B43_MMIO_MACCTL, ~0, B43_MACCTL_INFRA);
+
+	/* Probe Response Timeout value */
+	/* FIXME: Default to 0, has to be set by ioctl probably... :-/ */
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRMAXTIME, 0);
+
+	/* Initially set the wireless operation mode. */
+	b43_adjust_opmode(dev);
+
+	if (dev->dev->core_rev < 3) {
+		b43_write16(dev, 0x060E, 0x0000);
+		b43_write16(dev, 0x0610, 0x8000);
+		b43_write16(dev, 0x0604, 0x0000);
+		b43_write16(dev, 0x0606, 0x0200);
+	} else {
+		b43_write32(dev, 0x0188, 0x80000000);
+		b43_write32(dev, 0x018C, 0x02000000);
+	}
+	b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, 0x00004000);
+	b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001FC00);
+	b43_write32(dev, B43_MMIO_DMA1_IRQ_MASK, 0x0000DC00);
+	b43_write32(dev, B43_MMIO_DMA2_IRQ_MASK, 0x0000DC00);
+	b43_write32(dev, B43_MMIO_DMA3_IRQ_MASK, 0x0001DC00);
+	b43_write32(dev, B43_MMIO_DMA4_IRQ_MASK, 0x0000DC00);
+	b43_write32(dev, B43_MMIO_DMA5_IRQ_MASK, 0x0000DC00);
+
+	b43_mac_phy_clock_set(dev, true);
+
+	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");
+out:
+	return err;
+
+err_gpio_clean:
+	b43_gpio_cleanup(dev);
+	return err;
+}
+
+static void b43_periodic_every60sec(struct b43_wldev *dev)
+{
+	const struct b43_phy_operations *ops = dev->phy.ops;
+
+	if (ops->pwork_60sec)
+		ops->pwork_60sec(dev);
+
+	/* Force check the TX power emission now. */
+	b43_phy_txpower_check(dev, B43_TXPWR_IGNORE_TIME);
+}
+
+static void b43_periodic_every30sec(struct b43_wldev *dev)
+{
+	/* Update device statistics. */
+	b43_calculate_link_quality(dev);
+}
+
+static void b43_periodic_every15sec(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	u16 wdr;
+
+	if (dev->fw.opensource) {
+		/* Check if the firmware is still alive.
+		 * It will reset the watchdog counter to 0 in its idle loop. */
+		wdr = b43_shm_read16(dev, B43_SHM_SCRATCH, B43_WATCHDOG_REG);
+		if (unlikely(wdr)) {
+			b43err(dev->wl, "Firmware watchdog: The firmware died!\n");
+			b43_controller_restart(dev, "Firmware watchdog");
+			return;
+		} else {
+			b43_shm_write16(dev, B43_SHM_SCRATCH,
+					B43_WATCHDOG_REG, 1);
+		}
+	}
+
+	if (phy->ops->pwork_15sec)
+		phy->ops->pwork_15sec(dev);
+
+	atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
+	wmb();
+
+#if B43_DEBUG
+	if (b43_debug(dev, B43_DBG_VERBOSESTATS)) {
+		unsigned int i;
+
+		b43dbg(dev->wl, "Stats: %7u IRQs/sec, %7u TX/sec, %7u RX/sec\n",
+		       dev->irq_count / 15,
+		       dev->tx_count / 15,
+		       dev->rx_count / 15);
+		dev->irq_count = 0;
+		dev->tx_count = 0;
+		dev->rx_count = 0;
+		for (i = 0; i < ARRAY_SIZE(dev->irq_bit_count); i++) {
+			if (dev->irq_bit_count[i]) {
+				b43dbg(dev->wl, "Stats: %7u IRQ-%02u/sec (0x%08X)\n",
+				       dev->irq_bit_count[i] / 15, i, (1 << i));
+				dev->irq_bit_count[i] = 0;
+			}
+		}
+	}
+#endif
+}
+
+static void do_periodic_work(struct b43_wldev *dev)
+{
+	unsigned int state;
+
+	state = dev->periodic_state;
+	if (state % 4 == 0)
+		b43_periodic_every60sec(dev);
+	if (state % 2 == 0)
+		b43_periodic_every30sec(dev);
+	b43_periodic_every15sec(dev);
+}
+
+/* Periodic work locking policy:
+ * 	The whole periodic work handler is protected by
+ * 	wl->mutex. If another lock is needed somewhere in the
+ * 	pwork callchain, it's acquired in-place, where it's needed.
+ */
+static void b43_periodic_work_handler(struct work_struct *work)
+{
+	struct b43_wldev *dev = container_of(work, struct b43_wldev,
+					     periodic_work.work);
+	struct b43_wl *wl = dev->wl;
+	unsigned long delay;
+
+	mutex_lock(&wl->mutex);
+
+	if (unlikely(b43_status(dev) != B43_STAT_STARTED))
+		goto out;
+	if (b43_debug(dev, B43_DBG_PWORK_STOP))
+		goto out_requeue;
+
+	do_periodic_work(dev);
+
+	dev->periodic_state++;
+out_requeue:
+	if (b43_debug(dev, B43_DBG_PWORK_FAST))
+		delay = msecs_to_jiffies(50);
+	else
+		delay = round_jiffies_relative(HZ * 15);
+	ieee80211_queue_delayed_work(wl->hw, &dev->periodic_work, delay);
+out:
+	mutex_unlock(&wl->mutex);
+}
+
+static void b43_periodic_tasks_setup(struct b43_wldev *dev)
+{
+	struct delayed_work *work = &dev->periodic_work;
+
+	dev->periodic_state = 0;
+	INIT_DELAYED_WORK(work, b43_periodic_work_handler);
+	ieee80211_queue_delayed_work(dev->wl->hw, work, 0);
+}
+
+/* Check if communication with the device works correctly. */
+static int b43_validate_chipaccess(struct b43_wldev *dev)
+{
+	u32 v, backup0, backup4;
+
+	backup0 = b43_shm_read32(dev, B43_SHM_SHARED, 0);
+	backup4 = b43_shm_read32(dev, B43_SHM_SHARED, 4);
+
+	/* Check for read/write and endianness problems. */
+	b43_shm_write32(dev, B43_SHM_SHARED, 0, 0x55AAAA55);
+	if (b43_shm_read32(dev, B43_SHM_SHARED, 0) != 0x55AAAA55)
+		goto error;
+	b43_shm_write32(dev, B43_SHM_SHARED, 0, 0xAA5555AA);
+	if (b43_shm_read32(dev, B43_SHM_SHARED, 0) != 0xAA5555AA)
+		goto error;
+
+	/* Check if unaligned 32bit SHM_SHARED access works properly.
+	 * However, don't bail out on failure, because it's noncritical. */
+	b43_shm_write16(dev, B43_SHM_SHARED, 0, 0x1122);
+	b43_shm_write16(dev, B43_SHM_SHARED, 2, 0x3344);
+	b43_shm_write16(dev, B43_SHM_SHARED, 4, 0x5566);
+	b43_shm_write16(dev, B43_SHM_SHARED, 6, 0x7788);
+	if (b43_shm_read32(dev, B43_SHM_SHARED, 2) != 0x55663344)
+		b43warn(dev->wl, "Unaligned 32bit SHM read access is broken\n");
+	b43_shm_write32(dev, B43_SHM_SHARED, 2, 0xAABBCCDD);
+	if (b43_shm_read16(dev, B43_SHM_SHARED, 0) != 0x1122 ||
+	    b43_shm_read16(dev, B43_SHM_SHARED, 2) != 0xCCDD ||
+	    b43_shm_read16(dev, B43_SHM_SHARED, 4) != 0xAABB ||
+	    b43_shm_read16(dev, B43_SHM_SHARED, 6) != 0x7788)
+		b43warn(dev->wl, "Unaligned 32bit SHM write access is broken\n");
+
+	b43_shm_write32(dev, B43_SHM_SHARED, 0, backup0);
+	b43_shm_write32(dev, B43_SHM_SHARED, 4, backup4);
+
+	if ((dev->dev->core_rev >= 3) && (dev->dev->core_rev <= 10)) {
+		/* The 32bit register shadows the two 16bit registers
+		 * with update sideeffects. Validate this. */
+		b43_write16(dev, B43_MMIO_TSF_CFP_START, 0xAAAA);
+		b43_write32(dev, B43_MMIO_TSF_CFP_START, 0xCCCCBBBB);
+		if (b43_read16(dev, B43_MMIO_TSF_CFP_START_LOW) != 0xBBBB)
+			goto error;
+		if (b43_read16(dev, B43_MMIO_TSF_CFP_START_HIGH) != 0xCCCC)
+			goto error;
+	}
+	b43_write32(dev, B43_MMIO_TSF_CFP_START, 0);
+
+	v = b43_read32(dev, B43_MMIO_MACCTL);
+	v |= B43_MACCTL_GMODE;
+	if (v != (B43_MACCTL_GMODE | B43_MACCTL_IHR_ENABLED))
+		goto error;
+
+	return 0;
+error:
+	b43err(dev->wl, "Failed to validate the chipaccess\n");
+	return -ENODEV;
+}
+
+static void b43_security_init(struct b43_wldev *dev)
+{
+	dev->ktp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_KTP);
+	/* KTP is a word address, but we address SHM bytewise.
+	 * So multiply by two.
+	 */
+	dev->ktp *= 2;
+	/* Number of RCMTA address slots */
+	b43_write16(dev, B43_MMIO_RCMTA_COUNT, B43_NR_PAIRWISE_KEYS);
+	/* Clear the key memory. */
+	b43_clear_keys(dev);
+}
+
+#ifdef CONFIG_B43_HWRNG
+static int b43_rng_read(struct hwrng *rng, u32 *data)
+{
+	struct b43_wl *wl = (struct b43_wl *)rng->priv;
+	struct b43_wldev *dev;
+	int count = -ENODEV;
+
+	mutex_lock(&wl->mutex);
+	dev = wl->current_dev;
+	if (likely(dev && b43_status(dev) >= B43_STAT_INITIALIZED)) {
+		*data = b43_read16(dev, B43_MMIO_RNG);
+		count = sizeof(u16);
+	}
+	mutex_unlock(&wl->mutex);
+
+	return count;
+}
+#endif /* CONFIG_B43_HWRNG */
+
+static void b43_rng_exit(struct b43_wl *wl)
+{
+#ifdef CONFIG_B43_HWRNG
+	if (wl->rng_initialized)
+		hwrng_unregister(&wl->rng);
+#endif /* CONFIG_B43_HWRNG */
+}
+
+static int b43_rng_init(struct b43_wl *wl)
+{
+	int err = 0;
+
+#ifdef CONFIG_B43_HWRNG
+	snprintf(wl->rng_name, ARRAY_SIZE(wl->rng_name),
+		 "%s_%s", KBUILD_MODNAME, wiphy_name(wl->hw->wiphy));
+	wl->rng.name = wl->rng_name;
+	wl->rng.data_read = b43_rng_read;
+	wl->rng.priv = (unsigned long)wl;
+	wl->rng_initialized = true;
+	err = hwrng_register(&wl->rng);
+	if (err) {
+		wl->rng_initialized = false;
+		b43err(wl, "Failed to register the random "
+		       "number generator (%d)\n", err);
+	}
+#endif /* CONFIG_B43_HWRNG */
+
+	return err;
+}
+
+static void b43_tx_work(struct work_struct *work)
+{
+	struct b43_wl *wl = container_of(work, struct b43_wl, tx_work);
+	struct b43_wldev *dev;
+	struct sk_buff *skb;
+	int queue_num;
+	int err = 0;
+
+	mutex_lock(&wl->mutex);
+	dev = wl->current_dev;
+	if (unlikely(!dev || b43_status(dev) < B43_STAT_STARTED)) {
+		mutex_unlock(&wl->mutex);
+		return;
+	}
+
+	for (queue_num = 0; queue_num < B43_QOS_QUEUE_NUM; queue_num++) {
+		while (skb_queue_len(&wl->tx_queue[queue_num])) {
+			skb = skb_dequeue(&wl->tx_queue[queue_num]);
+			if (b43_using_pio_transfers(dev))
+				err = b43_pio_tx(dev, skb);
+			else
+				err = b43_dma_tx(dev, skb);
+			if (err == -ENOSPC) {
+				wl->tx_queue_stopped[queue_num] = 1;
+				ieee80211_stop_queue(wl->hw, queue_num);
+				skb_queue_head(&wl->tx_queue[queue_num], skb);
+				break;
+			}
+			if (unlikely(err))
+				ieee80211_free_txskb(wl->hw, skb);
+			err = 0;
+		}
+
+		if (!err)
+			wl->tx_queue_stopped[queue_num] = 0;
+	}
+
+#if B43_DEBUG
+	dev->tx_count++;
+#endif
+	mutex_unlock(&wl->mutex);
+}
+
+static void b43_op_tx(struct ieee80211_hw *hw,
+		      struct ieee80211_tx_control *control,
+		      struct sk_buff *skb)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+
+	if (unlikely(skb->len < 2 + 2 + 6)) {
+		/* Too short, this can't be a valid frame. */
+		ieee80211_free_txskb(hw, skb);
+		return;
+	}
+	B43_WARN_ON(skb_shinfo(skb)->nr_frags);
+
+	skb_queue_tail(&wl->tx_queue[skb->queue_mapping], skb);
+	if (!wl->tx_queue_stopped[skb->queue_mapping]) {
+		ieee80211_queue_work(wl->hw, &wl->tx_work);
+	} else {
+		ieee80211_stop_queue(wl->hw, skb->queue_mapping);
+	}
+}
+
+static void b43_qos_params_upload(struct b43_wldev *dev,
+				  const struct ieee80211_tx_queue_params *p,
+				  u16 shm_offset)
+{
+	u16 params[B43_NR_QOSPARAMS];
+	int bslots, tmp;
+	unsigned int i;
+
+	if (!dev->qos_enabled)
+		return;
+
+	bslots = b43_read16(dev, B43_MMIO_RNG) & p->cw_min;
+
+	memset(&params, 0, sizeof(params));
+
+	params[B43_QOSPARAM_TXOP] = p->txop * 32;
+	params[B43_QOSPARAM_CWMIN] = p->cw_min;
+	params[B43_QOSPARAM_CWMAX] = p->cw_max;
+	params[B43_QOSPARAM_CWCUR] = p->cw_min;
+	params[B43_QOSPARAM_AIFS] = p->aifs;
+	params[B43_QOSPARAM_BSLOTS] = bslots;
+	params[B43_QOSPARAM_REGGAP] = bslots + p->aifs;
+
+	for (i = 0; i < ARRAY_SIZE(params); i++) {
+		if (i == B43_QOSPARAM_STATUS) {
+			tmp = b43_shm_read16(dev, B43_SHM_SHARED,
+					     shm_offset + (i * 2));
+			/* Mark the parameters as updated. */
+			tmp |= 0x100;
+			b43_shm_write16(dev, B43_SHM_SHARED,
+					shm_offset + (i * 2),
+					tmp);
+		} else {
+			b43_shm_write16(dev, B43_SHM_SHARED,
+					shm_offset + (i * 2),
+					params[i]);
+		}
+	}
+}
+
+/* Mapping of mac80211 queue numbers to b43 QoS SHM offsets. */
+static const u16 b43_qos_shm_offsets[] = {
+	/* [mac80211-queue-nr] = SHM_OFFSET, */
+	[0] = B43_QOS_VOICE,
+	[1] = B43_QOS_VIDEO,
+	[2] = B43_QOS_BESTEFFORT,
+	[3] = B43_QOS_BACKGROUND,
+};
+
+/* Update all QOS parameters in hardware. */
+static void b43_qos_upload_all(struct b43_wldev *dev)
+{
+	struct b43_wl *wl = dev->wl;
+	struct b43_qos_params *params;
+	unsigned int i;
+
+	if (!dev->qos_enabled)
+		return;
+
+	BUILD_BUG_ON(ARRAY_SIZE(b43_qos_shm_offsets) !=
+		     ARRAY_SIZE(wl->qos_params));
+
+	b43_mac_suspend(dev);
+	for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) {
+		params = &(wl->qos_params[i]);
+		b43_qos_params_upload(dev, &(params->p),
+				      b43_qos_shm_offsets[i]);
+	}
+	b43_mac_enable(dev);
+}
+
+static void b43_qos_clear(struct b43_wl *wl)
+{
+	struct b43_qos_params *params;
+	unsigned int i;
+
+	/* Initialize QoS parameters to sane defaults. */
+
+	BUILD_BUG_ON(ARRAY_SIZE(b43_qos_shm_offsets) !=
+		     ARRAY_SIZE(wl->qos_params));
+
+	for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) {
+		params = &(wl->qos_params[i]);
+
+		switch (b43_qos_shm_offsets[i]) {
+		case B43_QOS_VOICE:
+			params->p.txop = 0;
+			params->p.aifs = 2;
+			params->p.cw_min = 0x0001;
+			params->p.cw_max = 0x0001;
+			break;
+		case B43_QOS_VIDEO:
+			params->p.txop = 0;
+			params->p.aifs = 2;
+			params->p.cw_min = 0x0001;
+			params->p.cw_max = 0x0001;
+			break;
+		case B43_QOS_BESTEFFORT:
+			params->p.txop = 0;
+			params->p.aifs = 3;
+			params->p.cw_min = 0x0001;
+			params->p.cw_max = 0x03FF;
+			break;
+		case B43_QOS_BACKGROUND:
+			params->p.txop = 0;
+			params->p.aifs = 7;
+			params->p.cw_min = 0x0001;
+			params->p.cw_max = 0x03FF;
+			break;
+		default:
+			B43_WARN_ON(1);
+		}
+	}
+}
+
+/* Initialize the core's QOS capabilities */
+static void b43_qos_init(struct b43_wldev *dev)
+{
+	if (!dev->qos_enabled) {
+		/* Disable QOS support. */
+		b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_EDCF);
+		b43_write16(dev, B43_MMIO_IFSCTL,
+			    b43_read16(dev, B43_MMIO_IFSCTL)
+			    & ~B43_MMIO_IFSCTL_USE_EDCF);
+		b43dbg(dev->wl, "QoS disabled\n");
+		return;
+	}
+
+	/* Upload the current QOS parameters. */
+	b43_qos_upload_all(dev);
+
+	/* Enable QOS support. */
+	b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF);
+	b43_write16(dev, B43_MMIO_IFSCTL,
+		    b43_read16(dev, B43_MMIO_IFSCTL)
+		    | B43_MMIO_IFSCTL_USE_EDCF);
+	b43dbg(dev->wl, "QoS enabled\n");
+}
+
+static int b43_op_conf_tx(struct ieee80211_hw *hw,
+			  struct ieee80211_vif *vif, u16 _queue,
+			  const struct ieee80211_tx_queue_params *params)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+	struct b43_wldev *dev;
+	unsigned int queue = (unsigned int)_queue;
+	int err = -ENODEV;
+
+	if (queue >= ARRAY_SIZE(wl->qos_params)) {
+		/* Queue not available or don't support setting
+		 * params on this queue. Return success to not
+		 * confuse mac80211. */
+		return 0;
+	}
+	BUILD_BUG_ON(ARRAY_SIZE(b43_qos_shm_offsets) !=
+		     ARRAY_SIZE(wl->qos_params));
+
+	mutex_lock(&wl->mutex);
+	dev = wl->current_dev;
+	if (unlikely(!dev || (b43_status(dev) < B43_STAT_INITIALIZED)))
+		goto out_unlock;
+
+	memcpy(&(wl->qos_params[queue].p), params, sizeof(*params));
+	b43_mac_suspend(dev);
+	b43_qos_params_upload(dev, &(wl->qos_params[queue].p),
+			      b43_qos_shm_offsets[queue]);
+	b43_mac_enable(dev);
+	err = 0;
+
+out_unlock:
+	mutex_unlock(&wl->mutex);
+
+	return err;
+}
+
+static int b43_op_get_stats(struct ieee80211_hw *hw,
+			    struct ieee80211_low_level_stats *stats)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+
+	mutex_lock(&wl->mutex);
+	memcpy(stats, &wl->ieee_stats, sizeof(*stats));
+	mutex_unlock(&wl->mutex);
+
+	return 0;
+}
+
+static u64 b43_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+	struct b43_wldev *dev;
+	u64 tsf;
+
+	mutex_lock(&wl->mutex);
+	dev = wl->current_dev;
+
+	if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED))
+		b43_tsf_read(dev, &tsf);
+	else
+		tsf = 0;
+
+	mutex_unlock(&wl->mutex);
+
+	return tsf;
+}
+
+static void b43_op_set_tsf(struct ieee80211_hw *hw,
+			   struct ieee80211_vif *vif, u64 tsf)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+	struct b43_wldev *dev;
+
+	mutex_lock(&wl->mutex);
+	dev = wl->current_dev;
+
+	if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED))
+		b43_tsf_write(dev, tsf);
+
+	mutex_unlock(&wl->mutex);
+}
+
+static const char *band_to_string(enum nl80211_band band)
+{
+	switch (band) {
+	case NL80211_BAND_5GHZ:
+		return "5";
+	case NL80211_BAND_2GHZ:
+		return "2.4";
+	default:
+		break;
+	}
+	B43_WARN_ON(1);
+	return "";
+}
+
+/* Expects wl->mutex locked */
+static int b43_switch_band(struct b43_wldev *dev,
+			   struct ieee80211_channel *chan)
+{
+	struct b43_phy *phy = &dev->phy;
+	bool gmode;
+	u32 tmp;
+
+	switch (chan->band) {
+	case NL80211_BAND_5GHZ:
+		gmode = false;
+		break;
+	case NL80211_BAND_2GHZ:
+		gmode = true;
+		break;
+	default:
+		B43_WARN_ON(1);
+		return -EINVAL;
+	}
+
+	if (!((gmode && phy->supports_2ghz) ||
+	      (!gmode && phy->supports_5ghz))) {
+		b43err(dev->wl, "This device doesn't support %s-GHz band\n",
+		       band_to_string(chan->band));
+		return -ENODEV;
+	}
+
+	if (!!phy->gmode == !!gmode) {
+		/* This device is already running. */
+		return 0;
+	}
+
+	b43dbg(dev->wl, "Switching to %s GHz band\n",
+	       band_to_string(chan->band));
+
+	/* Some new devices don't need disabling radio for band switching */
+	if (!(phy->type == B43_PHYTYPE_N && phy->rev >= 3))
+		b43_software_rfkill(dev, true);
+
+	phy->gmode = gmode;
+	b43_phy_put_into_reset(dev);
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+		if (gmode)
+			tmp |= B43_BCMA_IOCTL_GMODE;
+		else
+			tmp &= ~B43_BCMA_IOCTL_GMODE;
+		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 (gmode)
+			tmp |= B43_TMSLOW_GMODE;
+		else
+			tmp &= ~B43_TMSLOW_GMODE;
+		ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+		break;
+#endif
+	}
+	b43_phy_take_out_of_reset(dev);
+
+	b43_upload_initvals_band(dev);
+
+	b43_phy_init(dev);
+
+	return 0;
+}
+
+static void b43_set_beacon_listen_interval(struct b43_wldev *dev, u16 interval)
+{
+	interval = min_t(u16, interval, (u16)0xFF);
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BCN_LI, interval);
+}
+
+/* Write the short and long frame retry limit values. */
+static void b43_set_retry_limits(struct b43_wldev *dev,
+				 unsigned int short_retry,
+				 unsigned int long_retry)
+{
+	/* The retry limit is a 4-bit counter. Enforce this to avoid overflowing
+	 * the chip-internal counter. */
+	short_retry = min(short_retry, (unsigned int)0xF);
+	long_retry = min(long_retry, (unsigned int)0xF);
+
+	b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_SRLIMIT,
+			short_retry);
+	b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_LRLIMIT,
+			long_retry);
+}
+
+static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+	struct b43_wldev *dev = wl->current_dev;
+	struct b43_phy *phy = &dev->phy;
+	struct ieee80211_conf *conf = &hw->conf;
+	int antenna;
+	int err = 0;
+
+	mutex_lock(&wl->mutex);
+	b43_mac_suspend(dev);
+
+	if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL)
+		b43_set_beacon_listen_interval(dev, conf->listen_interval);
+
+	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+		phy->chandef = &conf->chandef;
+		phy->channel = conf->chandef.chan->hw_value;
+
+		/* Switch the band (if necessary). */
+		err = b43_switch_band(dev, conf->chandef.chan);
+		if (err)
+			goto out_mac_enable;
+
+		/* Switch to the requested channel.
+		 * The firmware takes care of races with the TX handler.
+		 */
+		b43_switch_channel(dev, phy->channel);
+	}
+
+	if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+		b43_set_retry_limits(dev, conf->short_frame_max_tx_count,
+					  conf->long_frame_max_tx_count);
+	changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS;
+	if (!changed)
+		goto out_mac_enable;
+
+	dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_MONITOR);
+
+	/* Adjust the desired TX power level. */
+	if (conf->power_level != 0) {
+		if (conf->power_level != phy->desired_txpower) {
+			phy->desired_txpower = conf->power_level;
+			b43_phy_txpower_check(dev, B43_TXPWR_IGNORE_TIME |
+						   B43_TXPWR_IGNORE_TSSI);
+		}
+	}
+
+	/* Antennas for RX and management frame TX. */
+	antenna = B43_ANTENNA_DEFAULT;
+	b43_mgmtframe_txantenna(dev, antenna);
+	antenna = B43_ANTENNA_DEFAULT;
+	if (phy->ops->set_rx_antenna)
+		phy->ops->set_rx_antenna(dev, antenna);
+
+	if (wl->radio_enabled != phy->radio_on) {
+		if (wl->radio_enabled) {
+			b43_software_rfkill(dev, false);
+			b43info(dev->wl, "Radio turned on by software\n");
+			if (!dev->radio_hw_enable) {
+				b43info(dev->wl, "The hardware RF-kill button "
+					"still turns the radio physically off. "
+					"Press the button to turn it on.\n");
+			}
+		} else {
+			b43_software_rfkill(dev, true);
+			b43info(dev->wl, "Radio turned off by software\n");
+		}
+	}
+
+out_mac_enable:
+	b43_mac_enable(dev);
+	mutex_unlock(&wl->mutex);
+
+	return err;
+}
+
+static void b43_update_basic_rates(struct b43_wldev *dev, u32 brates)
+{
+	struct ieee80211_supported_band *sband =
+		dev->wl->hw->wiphy->bands[b43_current_band(dev->wl)];
+	struct ieee80211_rate *rate;
+	int i;
+	u16 basic, direct, offset, basic_offset, rateptr;
+
+	for (i = 0; i < sband->n_bitrates; i++) {
+		rate = &sband->bitrates[i];
+
+		if (b43_is_cck_rate(rate->hw_value)) {
+			direct = B43_SHM_SH_CCKDIRECT;
+			basic = B43_SHM_SH_CCKBASIC;
+			offset = b43_plcp_get_ratecode_cck(rate->hw_value);
+			offset &= 0xF;
+		} else {
+			direct = B43_SHM_SH_OFDMDIRECT;
+			basic = B43_SHM_SH_OFDMBASIC;
+			offset = b43_plcp_get_ratecode_ofdm(rate->hw_value);
+			offset &= 0xF;
+		}
+
+		rate = ieee80211_get_response_rate(sband, brates, rate->bitrate);
+
+		if (b43_is_cck_rate(rate->hw_value)) {
+			basic_offset = b43_plcp_get_ratecode_cck(rate->hw_value);
+			basic_offset &= 0xF;
+		} else {
+			basic_offset = b43_plcp_get_ratecode_ofdm(rate->hw_value);
+			basic_offset &= 0xF;
+		}
+
+		/*
+		 * Get the pointer that we need to point to
+		 * from the direct map
+		 */
+		rateptr = b43_shm_read16(dev, B43_SHM_SHARED,
+					 direct + 2 * basic_offset);
+		/* and write it to the basic map */
+		b43_shm_write16(dev, B43_SHM_SHARED, basic + 2 * offset,
+				rateptr);
+	}
+}
+
+static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
+				    struct ieee80211_vif *vif,
+				    struct ieee80211_bss_conf *conf,
+				    u32 changed)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+	struct b43_wldev *dev;
+
+	mutex_lock(&wl->mutex);
+
+	dev = wl->current_dev;
+	if (!dev || b43_status(dev) < B43_STAT_STARTED)
+		goto out_unlock_mutex;
+
+	B43_WARN_ON(wl->vif != vif);
+
+	if (changed & BSS_CHANGED_BSSID) {
+		if (conf->bssid)
+			memcpy(wl->bssid, conf->bssid, ETH_ALEN);
+		else
+			eth_zero_addr(wl->bssid);
+	}
+
+	if (b43_status(dev) >= B43_STAT_INITIALIZED) {
+		if (changed & BSS_CHANGED_BEACON &&
+		    (b43_is_mode(wl, NL80211_IFTYPE_AP) ||
+		     b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT) ||
+		     b43_is_mode(wl, NL80211_IFTYPE_ADHOC)))
+			b43_update_templates(wl);
+
+		if (changed & BSS_CHANGED_BSSID)
+			b43_write_mac_bssid_templates(dev);
+	}
+
+	b43_mac_suspend(dev);
+
+	/* Update templates for AP/mesh mode. */
+	if (changed & BSS_CHANGED_BEACON_INT &&
+	    (b43_is_mode(wl, NL80211_IFTYPE_AP) ||
+	     b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT) ||
+	     b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) &&
+	    conf->beacon_int)
+		b43_set_beacon_int(dev, conf->beacon_int);
+
+	if (changed & BSS_CHANGED_BASIC_RATES)
+		b43_update_basic_rates(dev, conf->basic_rates);
+
+	if (changed & BSS_CHANGED_ERP_SLOT) {
+		if (conf->use_short_slot)
+			b43_short_slot_timing_enable(dev);
+		else
+			b43_short_slot_timing_disable(dev);
+	}
+
+	b43_mac_enable(dev);
+out_unlock_mutex:
+	mutex_unlock(&wl->mutex);
+}
+
+static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+			  struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+			  struct ieee80211_key_conf *key)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+	struct b43_wldev *dev;
+	u8 algorithm;
+	u8 index;
+	int err;
+	static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+	if (modparam_nohwcrypt)
+		return -ENOSPC; /* User disabled HW-crypto */
+
+	if ((vif->type == NL80211_IFTYPE_ADHOC ||
+	     vif->type == NL80211_IFTYPE_MESH_POINT) &&
+	    (key->cipher == WLAN_CIPHER_SUITE_TKIP ||
+	     key->cipher == WLAN_CIPHER_SUITE_CCMP) &&
+	    !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
+		/*
+		 * For now, disable hw crypto for the RSN IBSS group keys. This
+		 * could be optimized in the future, but until that gets
+		 * implemented, use of software crypto for group addressed
+		 * frames is a acceptable to allow RSN IBSS to be used.
+		 */
+		return -EOPNOTSUPP;
+	}
+
+	mutex_lock(&wl->mutex);
+
+	dev = wl->current_dev;
+	err = -ENODEV;
+	if (!dev || b43_status(dev) < B43_STAT_INITIALIZED)
+		goto out_unlock;
+
+	if (dev->fw.pcm_request_failed || !dev->hwcrypto_enabled) {
+		/* We don't have firmware for the crypto engine.
+		 * Must use software-crypto. */
+		err = -EOPNOTSUPP;
+		goto out_unlock;
+	}
+
+	err = -EINVAL;
+	switch (key->cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+		algorithm = B43_SEC_ALGO_WEP40;
+		break;
+	case WLAN_CIPHER_SUITE_WEP104:
+		algorithm = B43_SEC_ALGO_WEP104;
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
+		algorithm = B43_SEC_ALGO_TKIP;
+		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		algorithm = B43_SEC_ALGO_AES;
+		break;
+	default:
+		B43_WARN_ON(1);
+		goto out_unlock;
+	}
+	index = (u8) (key->keyidx);
+	if (index > 3)
+		goto out_unlock;
+
+	switch (cmd) {
+	case SET_KEY:
+		if (algorithm == B43_SEC_ALGO_TKIP &&
+		    (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE) ||
+		    !modparam_hwtkip)) {
+			/* We support only pairwise key */
+			err = -EOPNOTSUPP;
+			goto out_unlock;
+		}
+
+		if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
+			if (WARN_ON(!sta)) {
+				err = -EOPNOTSUPP;
+				goto out_unlock;
+			}
+			/* Pairwise key with an assigned MAC address. */
+			err = b43_key_write(dev, -1, algorithm,
+					    key->key, key->keylen,
+					    sta->addr, key);
+		} else {
+			/* Group key */
+			err = b43_key_write(dev, index, algorithm,
+					    key->key, key->keylen, NULL, key);
+		}
+		if (err)
+			goto out_unlock;
+
+		if (algorithm == B43_SEC_ALGO_WEP40 ||
+		    algorithm == B43_SEC_ALGO_WEP104) {
+			b43_hf_write(dev, b43_hf_read(dev) | B43_HF_USEDEFKEYS);
+		} else {
+			b43_hf_write(dev,
+				     b43_hf_read(dev) & ~B43_HF_USEDEFKEYS);
+		}
+		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+		if (algorithm == B43_SEC_ALGO_TKIP)
+			key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+		break;
+	case DISABLE_KEY: {
+		err = b43_key_clear(dev, key->hw_key_idx);
+		if (err)
+			goto out_unlock;
+		break;
+	}
+	default:
+		B43_WARN_ON(1);
+	}
+
+out_unlock:
+	if (!err) {
+		b43dbg(wl, "%s hardware based encryption for keyidx: %d, "
+		       "mac: %pM\n",
+		       cmd == SET_KEY ? "Using" : "Disabling", key->keyidx,
+		       sta ? sta->addr : bcast_addr);
+		b43_dump_keymemory(dev);
+	}
+	mutex_unlock(&wl->mutex);
+
+	return err;
+}
+
+static void b43_op_configure_filter(struct ieee80211_hw *hw,
+				    unsigned int changed, unsigned int *fflags,
+				    u64 multicast)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+	struct b43_wldev *dev;
+
+	mutex_lock(&wl->mutex);
+	dev = wl->current_dev;
+	if (!dev) {
+		*fflags = 0;
+		goto out_unlock;
+	}
+
+	*fflags &= FIF_ALLMULTI |
+		  FIF_FCSFAIL |
+		  FIF_PLCPFAIL |
+		  FIF_CONTROL |
+		  FIF_OTHER_BSS |
+		  FIF_BCN_PRBRESP_PROMISC;
+
+	changed &= FIF_ALLMULTI |
+		   FIF_FCSFAIL |
+		   FIF_PLCPFAIL |
+		   FIF_CONTROL |
+		   FIF_OTHER_BSS |
+		   FIF_BCN_PRBRESP_PROMISC;
+
+	wl->filter_flags = *fflags;
+
+	if (changed && b43_status(dev) >= B43_STAT_INITIALIZED)
+		b43_adjust_opmode(dev);
+
+out_unlock:
+	mutex_unlock(&wl->mutex);
+}
+
+/* Locking: wl->mutex
+ * Returns the current dev. This might be different from the passed in dev,
+ * because the core might be gone away while we unlocked the mutex. */
+static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev)
+{
+	struct b43_wl *wl;
+	struct b43_wldev *orig_dev;
+	u32 mask;
+	int queue_num;
+
+	if (!dev)
+		return NULL;
+	wl = dev->wl;
+redo:
+	if (!dev || b43_status(dev) < B43_STAT_STARTED)
+		return dev;
+
+	/* Cancel work. Unlock to avoid deadlocks. */
+	mutex_unlock(&wl->mutex);
+	cancel_delayed_work_sync(&dev->periodic_work);
+	cancel_work_sync(&wl->tx_work);
+	b43_leds_stop(dev);
+	mutex_lock(&wl->mutex);
+	dev = wl->current_dev;
+	if (!dev || b43_status(dev) < B43_STAT_STARTED) {
+		/* Whoops, aliens ate up the device while we were unlocked. */
+		return dev;
+	}
+
+	/* Disable interrupts on the device. */
+	b43_set_status(dev, B43_STAT_INITIALIZED);
+	if (b43_bus_host_is_sdio(dev->dev)) {
+		/* wl->mutex is locked. That is enough. */
+		b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
+		b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);	/* Flush */
+	} else {
+		spin_lock_irq(&wl->hardirq_lock);
+		b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
+		b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);	/* Flush */
+		spin_unlock_irq(&wl->hardirq_lock);
+	}
+	/* Synchronize and free the interrupt handlers. Unlock to avoid deadlocks. */
+	orig_dev = dev;
+	mutex_unlock(&wl->mutex);
+	if (b43_bus_host_is_sdio(dev->dev))
+		b43_sdio_free_irq(dev);
+	else
+		free_irq(dev->dev->irq, dev);
+	mutex_lock(&wl->mutex);
+	dev = wl->current_dev;
+	if (!dev)
+		return dev;
+	if (dev != orig_dev) {
+		if (b43_status(dev) >= B43_STAT_STARTED)
+			goto redo;
+		return dev;
+	}
+	mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
+	B43_WARN_ON(mask != 0xFFFFFFFF && mask);
+
+	/* Drain all TX queues. */
+	for (queue_num = 0; queue_num < B43_QOS_QUEUE_NUM; queue_num++) {
+		while (skb_queue_len(&wl->tx_queue[queue_num])) {
+			struct sk_buff *skb;
+
+			skb = skb_dequeue(&wl->tx_queue[queue_num]);
+			ieee80211_free_txskb(wl->hw, skb);
+		}
+	}
+
+	b43_mac_suspend(dev);
+	b43_leds_exit(dev);
+	b43dbg(wl, "Wireless interface stopped\n");
+
+	return dev;
+}
+
+/* Locking: wl->mutex */
+static int b43_wireless_core_start(struct b43_wldev *dev)
+{
+	int err;
+
+	B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED);
+
+	drain_txstatus_queue(dev);
+	if (b43_bus_host_is_sdio(dev->dev)) {
+		err = b43_sdio_request_irq(dev, b43_sdio_interrupt_handler);
+		if (err) {
+			b43err(dev->wl, "Cannot request SDIO IRQ\n");
+			goto out;
+		}
+	} else {
+		err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler,
+					   b43_interrupt_thread_handler,
+					   IRQF_SHARED, KBUILD_MODNAME, dev);
+		if (err) {
+			b43err(dev->wl, "Cannot request IRQ-%d\n",
+			       dev->dev->irq);
+			goto out;
+		}
+	}
+
+	/* We are ready to run. */
+	ieee80211_wake_queues(dev->wl->hw);
+	b43_set_status(dev, B43_STAT_STARTED);
+
+	/* Start data flow (TX/RX). */
+	b43_mac_enable(dev);
+	b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
+
+	/* Start maintenance work */
+	b43_periodic_tasks_setup(dev);
+
+	b43_leds_init(dev);
+
+	b43dbg(dev->wl, "Wireless interface started\n");
+out:
+	return err;
+}
+
+static char *b43_phy_name(struct b43_wldev *dev, u8 phy_type)
+{
+	switch (phy_type) {
+	case B43_PHYTYPE_A:
+		return "A";
+	case B43_PHYTYPE_B:
+		return "B";
+	case B43_PHYTYPE_G:
+		return "G";
+	case B43_PHYTYPE_N:
+		return "N";
+	case B43_PHYTYPE_LP:
+		return "LP";
+	case B43_PHYTYPE_SSLPN:
+		return "SSLPN";
+	case B43_PHYTYPE_HT:
+		return "HT";
+	case B43_PHYTYPE_LCN:
+		return "LCN";
+	case B43_PHYTYPE_LCNXN:
+		return "LCNXN";
+	case B43_PHYTYPE_LCN40:
+		return "LCN40";
+	case B43_PHYTYPE_AC:
+		return "AC";
+	}
+	return "UNKNOWN";
+}
+
+/* Get PHY and RADIO versioning numbers */
+static int b43_phy_versioning(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	const u8 core_rev = dev->dev->core_rev;
+	u32 tmp;
+	u8 analog_type;
+	u8 phy_type;
+	u8 phy_rev;
+	u16 radio_manuf;
+	u16 radio_id;
+	u16 radio_rev;
+	u8 radio_ver;
+	int unsupported = 0;
+
+	/* Get PHY versioning */
+	tmp = b43_read16(dev, B43_MMIO_PHY_VER);
+	analog_type = (tmp & B43_PHYVER_ANALOG) >> B43_PHYVER_ANALOG_SHIFT;
+	phy_type = (tmp & B43_PHYVER_TYPE) >> B43_PHYVER_TYPE_SHIFT;
+	phy_rev = (tmp & B43_PHYVER_VERSION);
+
+	/* LCNXN is continuation of N which run out of revisions */
+	if (phy_type == B43_PHYTYPE_LCNXN) {
+		phy_type = B43_PHYTYPE_N;
+		phy_rev += 16;
+	}
+
+	switch (phy_type) {
+#ifdef CONFIG_B43_PHY_G
+	case B43_PHYTYPE_G:
+		if (phy_rev > 9)
+			unsupported = 1;
+		break;
+#endif
+#ifdef CONFIG_B43_PHY_N
+	case B43_PHYTYPE_N:
+		if (phy_rev >= 19)
+			unsupported = 1;
+		break;
+#endif
+#ifdef CONFIG_B43_PHY_LP
+	case B43_PHYTYPE_LP:
+		if (phy_rev > 2)
+			unsupported = 1;
+		break;
+#endif
+#ifdef CONFIG_B43_PHY_HT
+	case B43_PHYTYPE_HT:
+		if (phy_rev > 1)
+			unsupported = 1;
+		break;
+#endif
+#ifdef CONFIG_B43_PHY_LCN
+	case B43_PHYTYPE_LCN:
+		if (phy_rev > 1)
+			unsupported = 1;
+		break;
+#endif
+#ifdef CONFIG_B43_PHY_AC
+	case B43_PHYTYPE_AC:
+		if (phy_rev > 1)
+			unsupported = 1;
+		break;
+#endif
+	default:
+		unsupported = 1;
+	}
+	if (unsupported) {
+		b43err(dev->wl, "FOUND UNSUPPORTED PHY (Analog %u, Type %d (%s), Revision %u)\n",
+		       analog_type, phy_type, b43_phy_name(dev, phy_type),
+		       phy_rev);
+		return -EOPNOTSUPP;
+	}
+	b43info(dev->wl, "Found PHY: Analog %u, Type %d (%s), Revision %u\n",
+		analog_type, phy_type, b43_phy_name(dev, phy_type), phy_rev);
+
+	/* Get RADIO versioning */
+	if (core_rev == 40 || core_rev == 42) {
+		radio_manuf = 0x17F;
+
+		b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, 0);
+		radio_rev = b43_read16(dev, B43_MMIO_RADIO24_DATA);
+
+		b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, 1);
+		radio_id = b43_read16(dev, B43_MMIO_RADIO24_DATA);
+
+		radio_ver = 0; /* Is there version somewhere? */
+	} else if (core_rev >= 24) {
+		u16 radio24[3];
+
+		for (tmp = 0; tmp < 3; tmp++) {
+			b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, tmp);
+			radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA);
+		}
+
+		radio_manuf = 0x17F;
+		radio_id = (radio24[2] << 8) | radio24[1];
+		radio_rev = (radio24[0] & 0xF);
+		radio_ver = (radio24[0] & 0xF0) >> 4;
+	} else {
+		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_write16f(dev, B43_MMIO_RADIO_CONTROL,
+				     B43_RADIOCTL_ID);
+			tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
+			b43_write16f(dev, B43_MMIO_RADIO_CONTROL,
+				     B43_RADIOCTL_ID);
+			tmp |= b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH) << 16;
+		}
+		radio_manuf = (tmp & 0x00000FFF);
+		radio_id = (tmp & 0x0FFFF000) >> 12;
+		radio_rev = (tmp & 0xF0000000) >> 28;
+		radio_ver = 0; /* Probably not available on old hw */
+	}
+
+	if (radio_manuf != 0x17F /* Broadcom */)
+		unsupported = 1;
+	switch (phy_type) {
+	case B43_PHYTYPE_B:
+		if ((radio_id & 0xFFF0) != 0x2050)
+			unsupported = 1;
+		break;
+	case B43_PHYTYPE_G:
+		if (radio_id != 0x2050)
+			unsupported = 1;
+		break;
+	case B43_PHYTYPE_N:
+		if (radio_id != 0x2055 && radio_id != 0x2056 &&
+		    radio_id != 0x2057)
+			unsupported = 1;
+		if (radio_id == 0x2057 &&
+		    !(radio_rev == 9 || radio_rev == 14))
+			unsupported = 1;
+		break;
+	case B43_PHYTYPE_LP:
+		if (radio_id != 0x2062 && radio_id != 0x2063)
+			unsupported = 1;
+		break;
+	case B43_PHYTYPE_HT:
+		if (radio_id != 0x2059)
+			unsupported = 1;
+		break;
+	case B43_PHYTYPE_LCN:
+		if (radio_id != 0x2064)
+			unsupported = 1;
+		break;
+	case B43_PHYTYPE_AC:
+		if (radio_id != 0x2069)
+			unsupported = 1;
+		break;
+	default:
+		B43_WARN_ON(1);
+	}
+	if (unsupported) {
+		b43err(dev->wl,
+		       "FOUND UNSUPPORTED RADIO (Manuf 0x%X, ID 0x%X, Revision %u, Version %u)\n",
+		       radio_manuf, radio_id, radio_rev, radio_ver);
+		return -EOPNOTSUPP;
+	}
+	b43info(dev->wl,
+		"Found Radio: Manuf 0x%X, ID 0x%X, Revision %u, Version %u\n",
+		radio_manuf, radio_id, radio_rev, radio_ver);
+
+	/* FIXME: b43 treats "id" as "ver" and ignores the real "ver" */
+	phy->radio_manuf = radio_manuf;
+	phy->radio_ver = radio_id;
+	phy->radio_rev = radio_rev;
+
+	phy->analog = analog_type;
+	phy->type = phy_type;
+	phy->rev = phy_rev;
+
+	return 0;
+}
+
+static void setup_struct_phy_for_init(struct b43_wldev *dev,
+				      struct b43_phy *phy)
+{
+	phy->hardware_power_control = !!modparam_hwpctl;
+	phy->next_txpwr_check_time = jiffies;
+	/* PHY TX errors counter. */
+	atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
+
+#if B43_DEBUG
+	phy->phy_locked = false;
+	phy->radio_locked = false;
+#endif
+}
+
+static void setup_struct_wldev_for_init(struct b43_wldev *dev)
+{
+	dev->dfq_valid = false;
+
+	/* Assume the radio is enabled. If it's not enabled, the state will
+	 * immediately get fixed on the first periodic work run. */
+	dev->radio_hw_enable = true;
+
+	/* Stats */
+	memset(&dev->stats, 0, sizeof(dev->stats));
+
+	setup_struct_phy_for_init(dev, &dev->phy);
+
+	/* IRQ related flags */
+	dev->irq_reason = 0;
+	memset(dev->dma_reason, 0, sizeof(dev->dma_reason));
+	dev->irq_mask = B43_IRQ_MASKTEMPLATE;
+	if (b43_modparam_verbose < B43_VERBOSITY_DEBUG)
+		dev->irq_mask &= ~B43_IRQ_PHY_TXERR;
+
+	dev->mac_suspended = 1;
+
+	/* Noise calculation context */
+	memset(&dev->noisecalc, 0, sizeof(dev->noisecalc));
+}
+
+static void b43_bluetooth_coext_enable(struct b43_wldev *dev)
+{
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+	u64 hf;
+
+	if (!modparam_btcoex)
+		return;
+	if (!(sprom->boardflags_lo & B43_BFL_BTCOEXIST))
+		return;
+	if (dev->phy.type != B43_PHYTYPE_B && !dev->phy.gmode)
+		return;
+
+	hf = b43_hf_read(dev);
+	if (sprom->boardflags_lo & B43_BFL_BTCMOD)
+		hf |= B43_HF_BTCOEXALT;
+	else
+		hf |= B43_HF_BTCOEX;
+	b43_hf_write(dev, hf);
+}
+
+static void b43_bluetooth_coext_disable(struct b43_wldev *dev)
+{
+	if (!modparam_btcoex)
+		return;
+	//TODO
+}
+
+static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev)
+{
+	struct ssb_bus *bus;
+	u32 tmp;
+
+#ifdef CONFIG_B43_SSB
+	if (dev->dev->bus_type != B43_BUS_SSB)
+		return;
+#else
+	return;
+#endif
+
+	bus = dev->dev->sdev->bus;
+
+	if ((bus->chip_id == 0x4311 && bus->chip_rev == 2) ||
+	    (bus->chip_id == 0x4312)) {
+		tmp = ssb_read32(dev->dev->sdev, SSB_IMCFGLO);
+		tmp &= ~SSB_IMCFGLO_REQTO;
+		tmp &= ~SSB_IMCFGLO_SERTO;
+		tmp |= 0x3;
+		ssb_write32(dev->dev->sdev, SSB_IMCFGLO, tmp);
+		ssb_commit_settings(bus);
+	}
+}
+
+static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle)
+{
+	u16 pu_delay;
+
+	/* The time value is in microseconds. */
+	pu_delay = 1050;
+	if (b43_is_mode(dev->wl, NL80211_IFTYPE_ADHOC) || idle)
+		pu_delay = 500;
+	if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8))
+		pu_delay = max(pu_delay, (u16)2400);
+
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_SPUWKUP, pu_delay);
+}
+
+/* Set the TSF CFP pre-TargetBeaconTransmissionTime. */
+static void b43_set_pretbtt(struct b43_wldev *dev)
+{
+	u16 pretbtt;
+
+	/* The time value is in microseconds. */
+	if (b43_is_mode(dev->wl, NL80211_IFTYPE_ADHOC))
+		pretbtt = 2;
+	else
+		pretbtt = 250;
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRETBTT, pretbtt);
+	b43_write16(dev, B43_MMIO_TSF_CFP_PRETBTT, pretbtt);
+}
+
+/* Shutdown a wireless core */
+/* Locking: wl->mutex */
+static void b43_wireless_core_exit(struct b43_wldev *dev)
+{
+	B43_WARN_ON(dev && b43_status(dev) > B43_STAT_INITIALIZED);
+	if (!dev || b43_status(dev) != B43_STAT_INITIALIZED)
+		return;
+
+	b43_set_status(dev, B43_STAT_UNINIT);
+
+	/* Stop the microcode PSM. */
+	b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_PSM_RUN,
+		      B43_MACCTL_PSM_JMP0);
+
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		bcma_host_pci_down(dev->dev->bdev->bus);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		/* TODO */
+		break;
+#endif
+	}
+
+	b43_dma_free(dev);
+	b43_pio_free(dev);
+	b43_chip_exit(dev);
+	dev->phy.ops->switch_analog(dev, 0);
+	if (dev->wl->current_beacon) {
+		dev_kfree_skb_any(dev->wl->current_beacon);
+		dev->wl->current_beacon = NULL;
+	}
+
+	b43_device_disable(dev, 0);
+	b43_bus_may_powerdown(dev);
+}
+
+/* Initialize a wireless core */
+static int b43_wireless_core_init(struct b43_wldev *dev)
+{
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+	struct b43_phy *phy = &dev->phy;
+	int err;
+	u64 hf;
+
+	B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT);
+
+	err = b43_bus_powerup(dev, 0);
+	if (err)
+		goto out;
+	if (!b43_device_is_enabled(dev))
+		b43_wireless_core_reset(dev, phy->gmode);
+
+	/* Reset all data structures. */
+	setup_struct_wldev_for_init(dev);
+	phy->ops->prepare_structs(dev);
+
+	/* Enable IRQ routing to this device. */
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		bcma_host_pci_irq_ctl(dev->dev->bdev->bus,
+				      dev->dev->bdev, true);
+		bcma_host_pci_up(dev->dev->bdev->bus);
+		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);
+	if (phy->ops->prepare_hardware) {
+		err = phy->ops->prepare_hardware(dev);
+		if (err)
+			goto err_busdown;
+	}
+	err = b43_chip_init(dev);
+	if (err)
+		goto err_busdown;
+	b43_shm_write16(dev, B43_SHM_SHARED,
+			B43_SHM_SH_WLCOREREV, dev->dev->core_rev);
+	hf = b43_hf_read(dev);
+	if (phy->type == B43_PHYTYPE_G) {
+		hf |= B43_HF_SYMW;
+		if (phy->rev == 1)
+			hf |= B43_HF_GDCW;
+		if (sprom->boardflags_lo & B43_BFL_PACTRL)
+			hf |= B43_HF_OFDMPABOOST;
+	}
+	if (phy->radio_ver == 0x2050) {
+		if (phy->radio_rev == 6)
+			hf |= B43_HF_4318TSSI;
+		if (phy->radio_rev < 6)
+			hf |= B43_HF_VCORECALC;
+	}
+	if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)
+		hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */
+#if defined(CONFIG_B43_SSB) && defined(CONFIG_SSB_DRIVER_PCICORE)
+	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;
+	b43_hf_write(dev, hf);
+
+	/* tell the ucode MAC capabilities */
+	if (dev->dev->core_rev >= 13) {
+		u32 mac_hw_cap = b43_read32(dev, B43_MMIO_MAC_HW_CAP);
+
+		b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_MACHW_L,
+				mac_hw_cap & 0xffff);
+		b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_MACHW_H,
+				(mac_hw_cap >> 16) & 0xffff);
+	}
+
+	b43_set_retry_limits(dev, B43_DEFAULT_SHORT_RETRY_LIMIT,
+			     B43_DEFAULT_LONG_RETRY_LIMIT);
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_SFFBLIM, 3);
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_LFFBLIM, 2);
+
+	/* Disable sending probe responses from firmware.
+	 * Setting the MaxTime to one usec will always trigger
+	 * a timeout, so we never send any probe resp.
+	 * A timeout of zero is infinite. */
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRMAXTIME, 1);
+
+	b43_rate_memory_init(dev);
+	b43_set_phytxctl_defaults(dev);
+
+	/* Minimum Contention Window */
+	if (phy->type == B43_PHYTYPE_B)
+		b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MINCONT, 0x1F);
+	else
+		b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MINCONT, 0xF);
+	/* Maximum Contention Window */
+	b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF);
+
+	/* write phytype and phyvers */
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PHYTYPE, phy->type);
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PHYVER, phy->rev);
+
+	if (b43_bus_host_is_pcmcia(dev->dev) ||
+	    b43_bus_host_is_sdio(dev->dev)) {
+		dev->__using_pio_transfers = true;
+		err = b43_pio_init(dev);
+	} else if (dev->use_pio) {
+		b43warn(dev->wl, "Forced PIO by use_pio module parameter. "
+			"This should not be needed and will result in lower "
+			"performance.\n");
+		dev->__using_pio_transfers = true;
+		err = b43_pio_init(dev);
+	} else {
+		dev->__using_pio_transfers = false;
+		err = b43_dma_init(dev);
+	}
+	if (err)
+		goto err_chip_exit;
+	b43_qos_init(dev);
+	b43_set_synth_pu_delay(dev, 1);
+	b43_bluetooth_coext_enable(dev);
+
+	b43_bus_powerup(dev, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW));
+	b43_upload_card_macaddress(dev);
+	b43_security_init(dev);
+
+	ieee80211_wake_queues(dev->wl->hw);
+
+	b43_set_status(dev, B43_STAT_INITIALIZED);
+
+out:
+	return err;
+
+err_chip_exit:
+	b43_chip_exit(dev);
+err_busdown:
+	b43_bus_may_powerdown(dev);
+	B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT);
+	return err;
+}
+
+static int b43_op_add_interface(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+	struct b43_wldev *dev;
+	int err = -EOPNOTSUPP;
+
+	/* TODO: allow WDS/AP devices to coexist */
+
+	if (vif->type != NL80211_IFTYPE_AP &&
+	    vif->type != NL80211_IFTYPE_MESH_POINT &&
+	    vif->type != NL80211_IFTYPE_STATION &&
+	    vif->type != NL80211_IFTYPE_WDS &&
+	    vif->type != NL80211_IFTYPE_ADHOC)
+		return -EOPNOTSUPP;
+
+	mutex_lock(&wl->mutex);
+	if (wl->operating)
+		goto out_mutex_unlock;
+
+	b43dbg(wl, "Adding Interface type %d\n", vif->type);
+
+	dev = wl->current_dev;
+	wl->operating = true;
+	wl->vif = vif;
+	wl->if_type = vif->type;
+	memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
+
+	b43_adjust_opmode(dev);
+	b43_set_pretbtt(dev);
+	b43_set_synth_pu_delay(dev, 0);
+	b43_upload_card_macaddress(dev);
+
+	err = 0;
+ out_mutex_unlock:
+	mutex_unlock(&wl->mutex);
+
+	if (err == 0)
+		b43_op_bss_info_changed(hw, vif, &vif->bss_conf, ~0);
+
+	return err;
+}
+
+static void b43_op_remove_interface(struct ieee80211_hw *hw,
+				    struct ieee80211_vif *vif)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+	struct b43_wldev *dev = wl->current_dev;
+
+	b43dbg(wl, "Removing Interface type %d\n", vif->type);
+
+	mutex_lock(&wl->mutex);
+
+	B43_WARN_ON(!wl->operating);
+	B43_WARN_ON(wl->vif != vif);
+	wl->vif = NULL;
+
+	wl->operating = false;
+
+	b43_adjust_opmode(dev);
+	eth_zero_addr(wl->mac_addr);
+	b43_upload_card_macaddress(dev);
+
+	mutex_unlock(&wl->mutex);
+}
+
+static int b43_op_start(struct ieee80211_hw *hw)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+	struct b43_wldev *dev = wl->current_dev;
+	int did_init = 0;
+	int err = 0;
+
+	/* Kill all old instance specific information to make sure
+	 * the card won't use it in the short timeframe between start
+	 * and mac80211 reconfiguring it. */
+	eth_zero_addr(wl->bssid);
+	eth_zero_addr(wl->mac_addr);
+	wl->filter_flags = 0;
+	wl->radiotap_enabled = false;
+	b43_qos_clear(wl);
+	wl->beacon0_uploaded = false;
+	wl->beacon1_uploaded = false;
+	wl->beacon_templates_virgin = true;
+	wl->radio_enabled = true;
+
+	mutex_lock(&wl->mutex);
+
+	if (b43_status(dev) < B43_STAT_INITIALIZED) {
+		err = b43_wireless_core_init(dev);
+		if (err)
+			goto out_mutex_unlock;
+		did_init = 1;
+	}
+
+	if (b43_status(dev) < B43_STAT_STARTED) {
+		err = b43_wireless_core_start(dev);
+		if (err) {
+			if (did_init)
+				b43_wireless_core_exit(dev);
+			goto out_mutex_unlock;
+		}
+	}
+
+	/* XXX: only do if device doesn't support rfkill irq */
+	wiphy_rfkill_start_polling(hw->wiphy);
+
+ out_mutex_unlock:
+	mutex_unlock(&wl->mutex);
+
+	/*
+	 * Configuration may have been overwritten during initialization.
+	 * Reload the configuration, but only if initialization was
+	 * successful. Reloading the configuration after a failed init
+	 * may hang the system.
+	 */
+	if (!err)
+		b43_op_config(hw, ~0);
+
+	return err;
+}
+
+static void b43_op_stop(struct ieee80211_hw *hw)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+	struct b43_wldev *dev = wl->current_dev;
+
+	cancel_work_sync(&(wl->beacon_update_trigger));
+
+	if (!dev)
+		goto out;
+
+	mutex_lock(&wl->mutex);
+	if (b43_status(dev) >= B43_STAT_STARTED) {
+		dev = b43_wireless_core_stop(dev);
+		if (!dev)
+			goto out_unlock;
+	}
+	b43_wireless_core_exit(dev);
+	wl->radio_enabled = false;
+
+out_unlock:
+	mutex_unlock(&wl->mutex);
+out:
+	cancel_work_sync(&(wl->txpower_adjust_work));
+}
+
+static int b43_op_beacon_set_tim(struct ieee80211_hw *hw,
+				 struct ieee80211_sta *sta, bool set)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+
+	b43_update_templates(wl);
+
+	return 0;
+}
+
+static void b43_op_sta_notify(struct ieee80211_hw *hw,
+			      struct ieee80211_vif *vif,
+			      enum sta_notify_cmd notify_cmd,
+			      struct ieee80211_sta *sta)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+
+	B43_WARN_ON(!vif || wl->vif != vif);
+}
+
+static void b43_op_sw_scan_start_notifier(struct ieee80211_hw *hw,
+					  struct ieee80211_vif *vif,
+					  const u8 *mac_addr)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+	struct b43_wldev *dev;
+
+	mutex_lock(&wl->mutex);
+	dev = wl->current_dev;
+	if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED)) {
+		/* Disable CFP update during scan on other channels. */
+		b43_hf_write(dev, b43_hf_read(dev) | B43_HF_SKCFPUP);
+	}
+	mutex_unlock(&wl->mutex);
+}
+
+static void b43_op_sw_scan_complete_notifier(struct ieee80211_hw *hw,
+					     struct ieee80211_vif *vif)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+	struct b43_wldev *dev;
+
+	mutex_lock(&wl->mutex);
+	dev = wl->current_dev;
+	if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED)) {
+		/* Re-enable CFP update. */
+		b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_SKCFPUP);
+	}
+	mutex_unlock(&wl->mutex);
+}
+
+static int b43_op_get_survey(struct ieee80211_hw *hw, int idx,
+			     struct survey_info *survey)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+	struct b43_wldev *dev = wl->current_dev;
+	struct ieee80211_conf *conf = &hw->conf;
+
+	if (idx != 0)
+		return -ENOENT;
+
+	survey->channel = conf->chandef.chan;
+	survey->filled = SURVEY_INFO_NOISE_DBM;
+	survey->noise = dev->stats.link_noise;
+
+	return 0;
+}
+
+static const struct ieee80211_ops b43_hw_ops = {
+	.tx			= b43_op_tx,
+	.conf_tx		= b43_op_conf_tx,
+	.add_interface		= b43_op_add_interface,
+	.remove_interface	= b43_op_remove_interface,
+	.config			= b43_op_config,
+	.bss_info_changed	= b43_op_bss_info_changed,
+	.configure_filter	= b43_op_configure_filter,
+	.set_key		= b43_op_set_key,
+	.update_tkip_key	= b43_op_update_tkip_key,
+	.get_stats		= b43_op_get_stats,
+	.get_tsf		= b43_op_get_tsf,
+	.set_tsf		= b43_op_set_tsf,
+	.start			= b43_op_start,
+	.stop			= b43_op_stop,
+	.set_tim		= b43_op_beacon_set_tim,
+	.sta_notify		= b43_op_sta_notify,
+	.sw_scan_start		= b43_op_sw_scan_start_notifier,
+	.sw_scan_complete	= b43_op_sw_scan_complete_notifier,
+	.get_survey		= b43_op_get_survey,
+	.rfkill_poll		= b43_rfkill_poll,
+};
+
+/* Hard-reset the chip. Do not call this directly.
+ * Use b43_controller_restart()
+ */
+static void b43_chip_reset(struct work_struct *work)
+{
+	struct b43_wldev *dev =
+	    container_of(work, struct b43_wldev, restart_work);
+	struct b43_wl *wl = dev->wl;
+	int err = 0;
+	int prev_status;
+
+	mutex_lock(&wl->mutex);
+
+	prev_status = b43_status(dev);
+	/* Bring the device down... */
+	if (prev_status >= B43_STAT_STARTED) {
+		dev = b43_wireless_core_stop(dev);
+		if (!dev) {
+			err = -ENODEV;
+			goto out;
+		}
+	}
+	if (prev_status >= B43_STAT_INITIALIZED)
+		b43_wireless_core_exit(dev);
+
+	/* ...and up again. */
+	if (prev_status >= B43_STAT_INITIALIZED) {
+		err = b43_wireless_core_init(dev);
+		if (err)
+			goto out;
+	}
+	if (prev_status >= B43_STAT_STARTED) {
+		err = b43_wireless_core_start(dev);
+		if (err) {
+			b43_wireless_core_exit(dev);
+			goto out;
+		}
+	}
+out:
+	if (err)
+		wl->current_dev = NULL; /* Failed to init the dev. */
+	mutex_unlock(&wl->mutex);
+
+	if (err) {
+		b43err(wl, "Controller restart FAILED\n");
+		return;
+	}
+
+	/* reload configuration */
+	b43_op_config(wl->hw, ~0);
+	if (wl->vif)
+		b43_op_bss_info_changed(wl->hw, wl->vif, &wl->vif->bss_conf, ~0);
+
+	b43info(wl, "Controller restarted\n");
+}
+
+static int b43_setup_bands(struct b43_wldev *dev,
+			   bool have_2ghz_phy, bool have_5ghz_phy)
+{
+	struct ieee80211_hw *hw = dev->wl->hw;
+	struct b43_phy *phy = &dev->phy;
+	bool limited_2g;
+	bool limited_5g;
+
+	/* We don't support all 2 GHz channels on some devices */
+	limited_2g = phy->radio_ver == 0x2057 &&
+		     (phy->radio_rev == 9 || phy->radio_rev == 14);
+	limited_5g = phy->radio_ver == 0x2057 &&
+		     phy->radio_rev == 9;
+
+	if (have_2ghz_phy)
+		hw->wiphy->bands[NL80211_BAND_2GHZ] = limited_2g ?
+			&b43_band_2ghz_limited : &b43_band_2GHz;
+	if (dev->phy.type == B43_PHYTYPE_N) {
+		if (have_5ghz_phy)
+			hw->wiphy->bands[NL80211_BAND_5GHZ] = limited_5g ?
+				&b43_band_5GHz_nphy_limited :
+				&b43_band_5GHz_nphy;
+	} else {
+		if (have_5ghz_phy)
+			hw->wiphy->bands[NL80211_BAND_5GHZ] = &b43_band_5GHz_aphy;
+	}
+
+	dev->phy.supports_2ghz = have_2ghz_phy;
+	dev->phy.supports_5ghz = have_5ghz_phy;
+
+	return 0;
+}
+
+static void b43_wireless_core_detach(struct b43_wldev *dev)
+{
+	/* We release firmware that late to not be required to re-request
+	 * is all the time when we reinit the core. */
+	b43_release_firmware(dev);
+	b43_phy_free(dev);
+}
+
+static void b43_supported_bands(struct b43_wldev *dev, bool *have_2ghz_phy,
+				bool *have_5ghz_phy)
+{
+	u16 dev_id = 0;
+
+#ifdef CONFIG_B43_BCMA
+	if (dev->dev->bus_type == B43_BUS_BCMA &&
+	    dev->dev->bdev->bus->hosttype == BCMA_HOSTTYPE_PCI)
+		dev_id = dev->dev->bdev->bus->host_pci->device;
+#endif
+#ifdef CONFIG_B43_SSB
+	if (dev->dev->bus_type == B43_BUS_SSB &&
+	    dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI)
+		dev_id = dev->dev->sdev->bus->host_pci->device;
+#endif
+	/* Override with SPROM value if available */
+	if (dev->dev->bus_sprom->dev_id)
+		dev_id = dev->dev->bus_sprom->dev_id;
+
+	/* Note: below IDs can be "virtual" (not maching e.g. real PCI ID) */
+	switch (dev_id) {
+	case 0x4324: /* BCM4306 */
+	case 0x4312: /* BCM4311 */
+	case 0x4319: /* BCM4318 */
+	case 0x4328: /* BCM4321 */
+	case 0x432b: /* BCM4322 */
+	case 0x4350: /* BCM43222 */
+	case 0x4353: /* BCM43224 */
+	case 0x0576: /* BCM43224 */
+	case 0x435f: /* BCM6362 */
+	case 0x4331: /* BCM4331 */
+	case 0x4359: /* BCM43228 */
+	case 0x43a0: /* BCM4360 */
+	case 0x43b1: /* BCM4352 */
+		/* Dual band devices */
+		*have_2ghz_phy = true;
+		*have_5ghz_phy = true;
+		return;
+	case 0x4321: /* BCM4306 */
+		/* There are 14e4:4321 PCI devs with 2.4 GHz BCM4321 (N-PHY) */
+		if (dev->phy.type != B43_PHYTYPE_G)
+			break;
+		/* fall through */
+	case 0x4313: /* BCM4311 */
+	case 0x431a: /* BCM4318 */
+	case 0x432a: /* BCM4321 */
+	case 0x432d: /* BCM4322 */
+	case 0x4352: /* BCM43222 */
+	case 0x435a: /* BCM43228 */
+	case 0x4333: /* BCM4331 */
+	case 0x43a2: /* BCM4360 */
+	case 0x43b3: /* BCM4352 */
+		/* 5 GHz only devices */
+		*have_2ghz_phy = false;
+		*have_5ghz_phy = true;
+		return;
+	}
+
+	/* As a fallback, try to guess using PHY type */
+	switch (dev->phy.type) {
+	case B43_PHYTYPE_G:
+	case B43_PHYTYPE_N:
+	case B43_PHYTYPE_LP:
+	case B43_PHYTYPE_HT:
+	case B43_PHYTYPE_LCN:
+		*have_2ghz_phy = true;
+		*have_5ghz_phy = false;
+		return;
+	}
+
+	B43_WARN_ON(1);
+}
+
+static int b43_wireless_core_attach(struct b43_wldev *dev)
+{
+	struct b43_wl *wl = dev->wl;
+	struct b43_phy *phy = &dev->phy;
+	int err;
+	u32 tmp;
+	bool have_2ghz_phy = false, have_5ghz_phy = false;
+
+	/* Do NOT do any device initialization here.
+	 * Do it in wireless_core_init() instead.
+	 * This function is for gathering basic information about the HW, only.
+	 * Also some structs may be set up here. But most likely you want to have
+	 * that in core_init(), too.
+	 */
+
+	err = b43_bus_powerup(dev, 0);
+	if (err) {
+		b43err(wl, "Bus powerup failed\n");
+		goto out;
+	}
+
+	phy->do_full_init = true;
+
+	/* Try to guess supported bands for the first init needs */
+	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;
+	b43_wireless_core_reset(dev, dev->phy.gmode);
+
+	/* Get the PHY type. */
+	err = b43_phy_versioning(dev);
+	if (err)
+		goto err_powerdown;
+
+	/* Get real info about supported bands */
+	b43_supported_bands(dev, &have_2ghz_phy, &have_5ghz_phy);
+
+	/* We don't support 5 GHz on some PHYs yet */
+	if (have_5ghz_phy) {
+		switch (dev->phy.type) {
+		case B43_PHYTYPE_G:
+		case B43_PHYTYPE_LP:
+		case B43_PHYTYPE_HT:
+			b43warn(wl, "5 GHz band is unsupported on this PHY\n");
+			have_5ghz_phy = false;
+		}
+	}
+
+	if (!have_2ghz_phy && !have_5ghz_phy) {
+		b43err(wl, "b43 can't support any band on this device\n");
+		err = -EOPNOTSUPP;
+		goto err_powerdown;
+	}
+
+	err = b43_phy_allocate(dev);
+	if (err)
+		goto err_powerdown;
+
+	dev->phy.gmode = have_2ghz_phy;
+	b43_wireless_core_reset(dev, dev->phy.gmode);
+
+	err = b43_validate_chipaccess(dev);
+	if (err)
+		goto err_phy_free;
+	err = b43_setup_bands(dev, have_2ghz_phy, have_5ghz_phy);
+	if (err)
+		goto err_phy_free;
+
+	/* Now set some default "current_dev" */
+	if (!wl->current_dev)
+		wl->current_dev = dev;
+	INIT_WORK(&dev->restart_work, b43_chip_reset);
+
+	dev->phy.ops->switch_analog(dev, 0);
+	b43_device_disable(dev, 0);
+	b43_bus_may_powerdown(dev);
+
+out:
+	return err;
+
+err_phy_free:
+	b43_phy_free(dev);
+err_powerdown:
+	b43_bus_may_powerdown(dev);
+	return err;
+}
+
+static void b43_one_core_detach(struct b43_bus_dev *dev)
+{
+	struct b43_wldev *wldev;
+	struct b43_wl *wl;
+
+	/* Do not cancel ieee80211-workqueue based work here.
+	 * See comment in b43_remove(). */
+
+	wldev = b43_bus_get_wldev(dev);
+	wl = wldev->wl;
+	b43_debugfs_remove_device(wldev);
+	b43_wireless_core_detach(wldev);
+	list_del(&wldev->list);
+	b43_bus_set_wldev(dev, NULL);
+	kfree(wldev);
+}
+
+static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl)
+{
+	struct b43_wldev *wldev;
+	int err = -ENOMEM;
+
+	wldev = kzalloc(sizeof(*wldev), GFP_KERNEL);
+	if (!wldev)
+		goto out;
+
+	wldev->use_pio = b43_modparam_pio;
+	wldev->dev = dev;
+	wldev->wl = wl;
+	b43_set_status(wldev, B43_STAT_UNINIT);
+	wldev->bad_frames_preempt = modparam_bad_frames_preempt;
+	INIT_LIST_HEAD(&wldev->list);
+
+	err = b43_wireless_core_attach(wldev);
+	if (err)
+		goto err_kfree_wldev;
+
+	b43_bus_set_wldev(dev, wldev);
+	b43_debugfs_add_device(wldev);
+
+      out:
+	return err;
+
+      err_kfree_wldev:
+	kfree(wldev);
+	return err;
+}
+
+#define IS_PDEV(pdev, _vendor, _device, _subvendor, _subdevice)		( \
+	(pdev->vendor == PCI_VENDOR_ID_##_vendor) &&			\
+	(pdev->device == _device) &&					\
+	(pdev->subsystem_vendor == PCI_VENDOR_ID_##_subvendor) &&	\
+	(pdev->subsystem_device == _subdevice)				)
+
+#ifdef CONFIG_B43_SSB
+static void b43_sprom_fixup(struct ssb_bus *bus)
+{
+	struct pci_dev *pdev;
+
+	/* boardflags workarounds */
+	if (bus->boardinfo.vendor == SSB_BOARDVENDOR_DELL &&
+	    bus->chip_id == 0x4301 && bus->sprom.board_rev == 0x74)
+		bus->sprom.boardflags_lo |= B43_BFL_BTCOEXIST;
+	if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
+	    bus->boardinfo.type == 0x4E && bus->sprom.board_rev > 0x40)
+		bus->sprom.boardflags_lo |= B43_BFL_PACTRL;
+	if (bus->bustype == SSB_BUSTYPE_PCI) {
+		pdev = bus->host_pci;
+		if (IS_PDEV(pdev, BROADCOM, 0x4318, ASUSTEK, 0x100F) ||
+		    IS_PDEV(pdev, BROADCOM, 0x4320,    DELL, 0x0003) ||
+		    IS_PDEV(pdev, BROADCOM, 0x4320,      HP, 0x12f8) ||
+		    IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0015) ||
+		    IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0014) ||
+		    IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0013) ||
+		    IS_PDEV(pdev, BROADCOM, 0x4320, MOTOROLA, 0x7010))
+			bus->sprom.boardflags_lo &= ~B43_BFL_BTCOEXIST;
+	}
+}
+
+static void b43_wireless_exit(struct b43_bus_dev *dev, struct b43_wl *wl)
+{
+	struct ieee80211_hw *hw = wl->hw;
+
+	ssb_set_devtypedata(dev->sdev, NULL);
+	ieee80211_free_hw(hw);
+}
+#endif
+
+static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
+{
+	struct ssb_sprom *sprom = dev->bus_sprom;
+	struct ieee80211_hw *hw;
+	struct b43_wl *wl;
+	char chip_name[6];
+	int queue_num;
+
+	hw = ieee80211_alloc_hw(sizeof(*wl), &b43_hw_ops);
+	if (!hw) {
+		b43err(NULL, "Could not allocate ieee80211 device\n");
+		return ERR_PTR(-ENOMEM);
+	}
+	wl = hw_to_b43_wl(hw);
+
+	/* fill hw info */
+	ieee80211_hw_set(hw, RX_INCLUDES_FCS);
+	ieee80211_hw_set(hw, SIGNAL_DBM);
+
+	hw->wiphy->interface_modes =
+		BIT(NL80211_IFTYPE_AP) |
+		BIT(NL80211_IFTYPE_MESH_POINT) |
+		BIT(NL80211_IFTYPE_STATION) |
+#ifdef CONFIG_WIRELESS_WDS
+		BIT(NL80211_IFTYPE_WDS) |
+#endif
+		BIT(NL80211_IFTYPE_ADHOC);
+
+	hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
+
+	wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
+
+	wl->hw_registred = false;
+	hw->max_rates = 2;
+	SET_IEEE80211_DEV(hw, dev->dev);
+	if (is_valid_ether_addr(sprom->et1mac))
+		SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
+	else
+		SET_IEEE80211_PERM_ADDR(hw, sprom->il0mac);
+
+	/* Initialize struct b43_wl */
+	wl->hw = hw;
+	mutex_init(&wl->mutex);
+	spin_lock_init(&wl->hardirq_lock);
+	spin_lock_init(&wl->beacon_lock);
+	INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work);
+	INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work);
+	INIT_WORK(&wl->tx_work, b43_tx_work);
+
+	/* Initialize queues and flags. */
+	for (queue_num = 0; queue_num < B43_QOS_QUEUE_NUM; queue_num++) {
+		skb_queue_head_init(&wl->tx_queue[queue_num]);
+		wl->tx_queue_stopped[queue_num] = 0;
+	}
+
+	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)
+{
+	struct b43_bus_dev *dev;
+	struct b43_wl *wl;
+	int err;
+
+	if (!modparam_allhwsupport &&
+	    (core->id.rev == 0x17 || core->id.rev == 0x18)) {
+		pr_err("Support for cores revisions 0x17 and 0x18 disabled by module param allhwsupport=0. Try b43.allhwsupport=1\n");
+		return -ENOTSUPP;
+	}
+
+	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;
+
+	/* setup and start work to load firmware */
+	INIT_WORK(&wl->firmware_load, b43_request_firmware);
+	schedule_work(&wl->firmware_load);
+
+	return err;
+
+bcma_err_wireless_exit:
+	ieee80211_free_hw(wl->hw);
+bcma_out:
+	kfree(dev);
+	return err;
+}
+
+static void b43_bcma_remove(struct bcma_device *core)
+{
+	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);
+	cancel_work_sync(&wl->firmware_load);
+
+	B43_WARN_ON(!wl);
+	if (!wldev->fw.ucode.data)
+		return;			/* NULL if firmware never loaded */
+	if (wl->current_dev == wldev && wl->hw_registred) {
+		b43_leds_stop(wldev);
+		ieee80211_unregister_hw(wl->hw);
+	}
+
+	b43_one_core_detach(wldev->dev);
+
+	/* Unregister HW RNG driver */
+	b43_rng_exit(wl);
+
+	b43_leds_unregister(wl);
+	ieee80211_free_hw(wl->hw);
+	kfree(wldev->dev);
+}
+
+static struct bcma_driver b43_bcma_driver = {
+	.name		= KBUILD_MODNAME,
+	.id_table	= b43_bcma_tbl,
+	.probe		= b43_bcma_probe,
+	.remove		= b43_bcma_remove,
+};
+#endif
+
+#ifdef CONFIG_B43_SSB
+static
+int b43_ssb_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
+{
+	struct b43_bus_dev *dev;
+	struct b43_wl *wl;
+	int err;
+
+	dev = b43_bus_dev_ssb_init(sdev);
+	if (!dev)
+		return -ENOMEM;
+
+	wl = ssb_get_devtypedata(sdev);
+	if (wl) {
+		b43err(NULL, "Dual-core devices are not supported\n");
+		err = -ENOTSUPP;
+		goto err_ssb_kfree_dev;
+	}
+
+	b43_sprom_fixup(sdev->bus);
+
+	wl = b43_wireless_init(dev);
+	if (IS_ERR(wl)) {
+		err = PTR_ERR(wl);
+		goto err_ssb_kfree_dev;
+	}
+	ssb_set_devtypedata(sdev, wl);
+	B43_WARN_ON(ssb_get_devtypedata(sdev) != wl);
+
+	err = b43_one_core_attach(dev, wl);
+	if (err)
+		goto err_ssb_wireless_exit;
+
+	/* setup and start work to load firmware */
+	INIT_WORK(&wl->firmware_load, b43_request_firmware);
+	schedule_work(&wl->firmware_load);
+
+	return err;
+
+err_ssb_wireless_exit:
+	b43_wireless_exit(dev, wl);
+err_ssb_kfree_dev:
+	kfree(dev);
+	return err;
+}
+
+static void b43_ssb_remove(struct ssb_device *sdev)
+{
+	struct b43_wl *wl = ssb_get_devtypedata(sdev);
+	struct b43_wldev *wldev = ssb_get_drvdata(sdev);
+	struct b43_bus_dev *dev = wldev->dev;
+
+	/* We must cancel any work here before unregistering from ieee80211,
+	 * as the ieee80211 unreg will destroy the workqueue. */
+	cancel_work_sync(&wldev->restart_work);
+	cancel_work_sync(&wl->firmware_load);
+
+	B43_WARN_ON(!wl);
+	if (!wldev->fw.ucode.data)
+		return;			/* NULL if firmware never loaded */
+	if (wl->current_dev == wldev && wl->hw_registred) {
+		b43_leds_stop(wldev);
+		ieee80211_unregister_hw(wl->hw);
+	}
+
+	b43_one_core_detach(dev);
+
+	/* Unregister HW RNG driver */
+	b43_rng_exit(wl);
+
+	b43_leds_unregister(wl);
+	b43_wireless_exit(dev, wl);
+	kfree(dev);
+}
+
+static struct ssb_driver b43_ssb_driver = {
+	.name		= KBUILD_MODNAME,
+	.id_table	= b43_ssb_tbl,
+	.probe		= b43_ssb_probe,
+	.remove		= b43_ssb_remove,
+};
+#endif /* CONFIG_B43_SSB */
+
+/* Perform a hardware reset. This can be called from any context. */
+void b43_controller_restart(struct b43_wldev *dev, const char *reason)
+{
+	/* Must avoid requeueing, if we are in shutdown. */
+	if (b43_status(dev) < B43_STAT_INITIALIZED)
+		return;
+	b43info(dev->wl, "Controller RESET (%s) ...\n", reason);
+	ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
+}
+
+static void b43_print_driverinfo(void)
+{
+	const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "",
+		   *feat_leds = "", *feat_sdio = "";
+
+#ifdef CONFIG_B43_PCI_AUTOSELECT
+	feat_pci = "P";
+#endif
+#ifdef CONFIG_B43_PCMCIA
+	feat_pcmcia = "M";
+#endif
+#ifdef CONFIG_B43_PHY_N
+	feat_nphy = "N";
+#endif
+#ifdef CONFIG_B43_LEDS
+	feat_leds = "L";
+#endif
+#ifdef CONFIG_B43_SDIO
+	feat_sdio = "S";
+#endif
+	printk(KERN_INFO "Broadcom 43xx driver loaded "
+	       "[ Features: %s%s%s%s%s ]\n",
+	       feat_pci, feat_pcmcia, feat_nphy,
+	       feat_leds, feat_sdio);
+}
+
+static int __init b43_init(void)
+{
+	int err;
+
+	b43_debugfs_init();
+	err = b43_sdio_init();
+	if (err)
+		goto err_dfs_exit;
+#ifdef CONFIG_B43_BCMA
+	err = bcma_driver_register(&b43_bcma_driver);
+	if (err)
+		goto err_sdio_exit;
+#endif
+#ifdef CONFIG_B43_SSB
+	err = ssb_driver_register(&b43_ssb_driver);
+	if (err)
+		goto err_bcma_driver_exit;
+#endif
+	b43_print_driverinfo();
+
+	return err;
+
+#ifdef CONFIG_B43_SSB
+err_bcma_driver_exit:
+#endif
+#ifdef CONFIG_B43_BCMA
+	bcma_driver_unregister(&b43_bcma_driver);
+err_sdio_exit:
+#endif
+	b43_sdio_exit();
+err_dfs_exit:
+	b43_debugfs_exit();
+	return err;
+}
+
+static void __exit b43_exit(void)
+{
+#ifdef CONFIG_B43_SSB
+	ssb_driver_unregister(&b43_ssb_driver);
+#endif
+#ifdef CONFIG_B43_BCMA
+	bcma_driver_unregister(&b43_bcma_driver);
+#endif
+	b43_sdio_exit();
+	b43_debugfs_exit();
+}
+
+module_init(b43_init)
+module_exit(b43_exit)
diff --git a/drivers/net/wireless/broadcom/b43/main.h b/drivers/net/wireless/broadcom/b43/main.h
new file mode 100644
index 0000000..c46430c
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/main.h
@@ -0,0 +1,112 @@
+/*
+
+  Broadcom B43 wireless driver
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+                     Stefano Brivio <stefano.brivio@polimi.it>
+                     Michael Buesch <m@bues.ch>
+                     Danny van Dyk <kugelfang@gentoo.org>
+                     Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+  Some parts of the code in this file are derived from the ipw2200
+  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+
+  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.
+
+*/
+
+#ifndef B43_MAIN_H_
+#define B43_MAIN_H_
+
+#include "b43.h"
+
+#define P4D_BYT3S(magic, nr_bytes)	u8 __p4dding##magic[nr_bytes]
+#define P4D_BYTES(line, nr_bytes)	P4D_BYT3S(line, nr_bytes)
+/* Magic helper macro to pad structures. Ignore those above. It's magic. */
+#define PAD_BYTES(nr_bytes)		P4D_BYTES( __LINE__ , (nr_bytes))
+
+
+extern int b43_modparam_verbose;
+
+/* Logmessage verbosity levels. Update the b43_modparam_verbose helptext, if
+ * you add or remove levels. */
+enum b43_verbosity {
+	B43_VERBOSITY_ERROR,
+	B43_VERBOSITY_WARN,
+	B43_VERBOSITY_INFO,
+	B43_VERBOSITY_DEBUG,
+	__B43_VERBOSITY_AFTERLAST, /* keep last */
+
+	B43_VERBOSITY_MAX = __B43_VERBOSITY_AFTERLAST - 1,
+#if B43_DEBUG
+	B43_VERBOSITY_DEFAULT = B43_VERBOSITY_DEBUG,
+#else
+	B43_VERBOSITY_DEFAULT = B43_VERBOSITY_INFO,
+#endif
+};
+
+static inline int b43_is_cck_rate(int rate)
+{
+	return (rate == B43_CCK_RATE_1MB ||
+		rate == B43_CCK_RATE_2MB ||
+		rate == B43_CCK_RATE_5MB || rate == B43_CCK_RATE_11MB);
+}
+
+static inline int b43_is_ofdm_rate(int rate)
+{
+	return !b43_is_cck_rate(rate);
+}
+
+u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev,
+				  u8 antenna_nr);
+
+void b43_tsf_read(struct b43_wldev *dev, u64 * tsf);
+void b43_tsf_write(struct b43_wldev *dev, u64 tsf);
+
+u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset);
+u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset);
+void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value);
+void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value);
+
+u64 b43_hf_read(struct b43_wldev *dev);
+void b43_hf_write(struct b43_wldev *dev, u64 value);
+
+void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on);
+
+void b43_wireless_core_reset(struct b43_wldev *dev, bool gmode);
+
+void b43_controller_restart(struct b43_wldev *dev, const char *reason);
+
+#define B43_PS_ENABLED	(1 << 0)	/* Force enable hardware power saving */
+#define B43_PS_DISABLED	(1 << 1)	/* Force disable hardware power saving */
+#define B43_PS_AWAKE	(1 << 2)	/* Force device awake */
+#define B43_PS_ASLEEP	(1 << 3)	/* Force device asleep */
+void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags);
+
+void b43_wireless_core_phy_pll_reset(struct b43_wldev *dev);
+
+void b43_mac_suspend(struct b43_wldev *dev);
+void b43_mac_enable(struct b43_wldev *dev);
+void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on);
+void b43_mac_switch_freq(struct b43_wldev *dev, u8 spurmode);
+
+
+struct b43_request_fw_context;
+int b43_do_request_fw(struct b43_request_fw_context *ctx, const char *name,
+		      struct b43_firmware_file *fw, bool async);
+void b43_do_release_fw(struct b43_firmware_file *fw);
+
+#endif /* B43_MAIN_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/phy_a.h b/drivers/net/wireless/broadcom/b43/phy_a.h
new file mode 100644
index 0000000..b1cbfc0
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/phy_a.h
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef LINUX_B43_PHY_A_H_
+#define LINUX_B43_PHY_A_H_
+
+#include "phy_common.h"
+
+
+/* OFDM (A) PHY Registers */
+#define B43_PHY_VERSION_OFDM		B43_PHY_OFDM(0x00)	/* Versioning register for A-PHY */
+#define B43_PHY_BBANDCFG		B43_PHY_OFDM(0x01)	/* Baseband config */
+#define  B43_PHY_BBANDCFG_RXANT		0x180	/* RX Antenna selection */
+#define  B43_PHY_BBANDCFG_RXANT_SHIFT	7
+#define B43_PHY_PWRDOWN			B43_PHY_OFDM(0x03)	/* Powerdown */
+#define B43_PHY_CRSTHRES1_R1		B43_PHY_OFDM(0x06)	/* CRS Threshold 1 (phy.rev 1 only) */
+#define B43_PHY_LNAHPFCTL		B43_PHY_OFDM(0x1C)	/* LNA/HPF control */
+#define B43_PHY_LPFGAINCTL		B43_PHY_OFDM(0x20)	/* LPF Gain control */
+#define B43_PHY_ADIVRELATED		B43_PHY_OFDM(0x27)	/* FIXME rename */
+#define B43_PHY_CRS0			B43_PHY_OFDM(0x29)
+#define  B43_PHY_CRS0_EN		0x4000
+#define B43_PHY_PEAK_COUNT		B43_PHY_OFDM(0x30)
+#define B43_PHY_ANTDWELL		B43_PHY_OFDM(0x2B)	/* Antenna dwell */
+#define  B43_PHY_ANTDWELL_AUTODIV1	0x0100	/* Automatic RX diversity start antenna */
+#define B43_PHY_ENCORE			B43_PHY_OFDM(0x49)	/* "Encore" (RangeMax / BroadRange) */
+#define  B43_PHY_ENCORE_EN		0x0200	/* Encore enable */
+#define B43_PHY_LMS			B43_PHY_OFDM(0x55)
+#define B43_PHY_OFDM61			B43_PHY_OFDM(0x61)	/* FIXME rename */
+#define  B43_PHY_OFDM61_10		0x0010	/* FIXME rename */
+#define B43_PHY_IQBAL			B43_PHY_OFDM(0x69)	/* I/Q balance */
+#define B43_PHY_BBTXDC_BIAS		B43_PHY_OFDM(0x6B)	/* Baseband TX DC bias */
+#define B43_PHY_OTABLECTL		B43_PHY_OFDM(0x72)	/* OFDM table control (see below) */
+#define  B43_PHY_OTABLEOFF		0x03FF	/* OFDM table offset (see below) */
+#define  B43_PHY_OTABLENR		0xFC00	/* OFDM table number (see below) */
+#define  B43_PHY_OTABLENR_SHIFT		10
+#define B43_PHY_OTABLEI			B43_PHY_OFDM(0x73)	/* OFDM table data I */
+#define B43_PHY_OTABLEQ			B43_PHY_OFDM(0x74)	/* OFDM table data Q */
+#define B43_PHY_HPWR_TSSICTL		B43_PHY_OFDM(0x78)	/* Hardware power TSSI control */
+#define B43_PHY_ADCCTL			B43_PHY_OFDM(0x7A)	/* ADC control */
+#define B43_PHY_IDLE_TSSI		B43_PHY_OFDM(0x7B)
+#define B43_PHY_A_TEMP_SENSE		B43_PHY_OFDM(0x7C)	/* A PHY temperature sense */
+#define B43_PHY_NRSSITHRES		B43_PHY_OFDM(0x8A)	/* NRSSI threshold */
+#define B43_PHY_ANTWRSETT		B43_PHY_OFDM(0x8C)	/* Antenna WR settle */
+#define  B43_PHY_ANTWRSETT_ARXDIV	0x2000	/* Automatic RX diversity enabled */
+#define B43_PHY_CLIPPWRDOWNT		B43_PHY_OFDM(0x93)	/* Clip powerdown threshold */
+#define B43_PHY_OFDM9B			B43_PHY_OFDM(0x9B)	/* FIXME rename */
+#define B43_PHY_N1P1GAIN		B43_PHY_OFDM(0xA0)
+#define B43_PHY_P1P2GAIN		B43_PHY_OFDM(0xA1)
+#define B43_PHY_N1N2GAIN		B43_PHY_OFDM(0xA2)
+#define B43_PHY_CLIPTHRES		B43_PHY_OFDM(0xA3)
+#define B43_PHY_CLIPN1P2THRES		B43_PHY_OFDM(0xA4)
+#define B43_PHY_CCKSHIFTBITS_WA		B43_PHY_OFDM(0xA5)	/* CCK shiftbits workaround, FIXME rename */
+#define B43_PHY_CCKSHIFTBITS		B43_PHY_OFDM(0xA7)	/* FIXME rename */
+#define B43_PHY_DIVSRCHIDX		B43_PHY_OFDM(0xA8)	/* Divider search gain/index */
+#define B43_PHY_CLIPP2THRES		B43_PHY_OFDM(0xA9)
+#define B43_PHY_CLIPP3THRES		B43_PHY_OFDM(0xAA)
+#define B43_PHY_DIVP1P2GAIN		B43_PHY_OFDM(0xAB)
+#define B43_PHY_DIVSRCHGAINBACK		B43_PHY_OFDM(0xAD)	/* Divider search gain back */
+#define B43_PHY_DIVSRCHGAINCHNG		B43_PHY_OFDM(0xAE)	/* Divider search gain change */
+#define B43_PHY_CRSTHRES1		B43_PHY_OFDM(0xC0)	/* CRS Threshold 1 (phy.rev >= 2 only) */
+#define B43_PHY_CRSTHRES2		B43_PHY_OFDM(0xC1)	/* CRS Threshold 2 (phy.rev >= 2 only) */
+#define B43_PHY_TSSIP_LTBASE		B43_PHY_OFDM(0x380)	/* TSSI power lookup table base */
+#define B43_PHY_DC_LTBASE		B43_PHY_OFDM(0x3A0)	/* DC lookup table base */
+#define B43_PHY_GAIN_LTBASE		B43_PHY_OFDM(0x3C0)	/* Gain lookup table base */
+
+/*** OFDM table numbers ***/
+#define B43_OFDMTAB(number, offset)	(((number) << B43_PHY_OTABLENR_SHIFT) | (offset))
+#define B43_OFDMTAB_AGC1		B43_OFDMTAB(0x00, 0)
+#define B43_OFDMTAB_GAIN0		B43_OFDMTAB(0x00, 0)
+#define B43_OFDMTAB_GAINX		B43_OFDMTAB(0x01, 0)	//TODO rename
+#define B43_OFDMTAB_GAIN1		B43_OFDMTAB(0x01, 4)
+#define B43_OFDMTAB_AGC3		B43_OFDMTAB(0x02, 0)
+#define B43_OFDMTAB_GAIN2		B43_OFDMTAB(0x02, 3)
+#define B43_OFDMTAB_LNAHPFGAIN1		B43_OFDMTAB(0x03, 0)
+#define B43_OFDMTAB_WRSSI		B43_OFDMTAB(0x04, 0)
+#define B43_OFDMTAB_LNAHPFGAIN2		B43_OFDMTAB(0x04, 0)
+#define B43_OFDMTAB_NOISESCALE		B43_OFDMTAB(0x05, 0)
+#define B43_OFDMTAB_AGC2		B43_OFDMTAB(0x06, 0)
+#define B43_OFDMTAB_ROTOR		B43_OFDMTAB(0x08, 0)
+#define B43_OFDMTAB_ADVRETARD		B43_OFDMTAB(0x09, 0)
+#define B43_OFDMTAB_DAC			B43_OFDMTAB(0x0C, 0)
+#define B43_OFDMTAB_DC			B43_OFDMTAB(0x0E, 7)
+#define B43_OFDMTAB_PWRDYN2		B43_OFDMTAB(0x0E, 12)
+#define B43_OFDMTAB_LNAGAIN		B43_OFDMTAB(0x0E, 13)
+#define B43_OFDMTAB_UNKNOWN_0F		B43_OFDMTAB(0x0F, 0)	//TODO rename
+#define B43_OFDMTAB_UNKNOWN_APHY	B43_OFDMTAB(0x0F, 7)	//TODO rename
+#define B43_OFDMTAB_LPFGAIN		B43_OFDMTAB(0x0F, 12)
+#define B43_OFDMTAB_RSSI		B43_OFDMTAB(0x10, 0)
+#define B43_OFDMTAB_UNKNOWN_11		B43_OFDMTAB(0x11, 4)	//TODO rename
+#define B43_OFDMTAB_AGC1_R1		B43_OFDMTAB(0x13, 0)
+#define B43_OFDMTAB_GAINX_R1		B43_OFDMTAB(0x14, 0)	//TODO remove!
+#define B43_OFDMTAB_MINSIGSQ		B43_OFDMTAB(0x14, 0)
+#define B43_OFDMTAB_AGC3_R1		B43_OFDMTAB(0x15, 0)
+#define B43_OFDMTAB_WRSSI_R1		B43_OFDMTAB(0x15, 4)
+#define B43_OFDMTAB_TSSI		B43_OFDMTAB(0x15, 0)
+#define B43_OFDMTAB_DACRFPABB		B43_OFDMTAB(0x16, 0)
+#define B43_OFDMTAB_DACOFF		B43_OFDMTAB(0x17, 0)
+#define B43_OFDMTAB_DCBIAS		B43_OFDMTAB(0x18, 0)
+
+u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset);
+void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table,
+			 u16 offset, u16 value);
+u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset);
+void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table,
+			 u16 offset, u32 value);
+
+#endif /* LINUX_B43_PHY_A_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/phy_ac.c b/drivers/net/wireless/broadcom/b43/phy_ac.c
new file mode 100644
index 0000000..52f8aba
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/phy_ac.c
@@ -0,0 +1,92 @@
+/*
+ * Broadcom B43 wireless driver
+ * IEEE 802.11ac AC-PHY support
+ *
+ * Copyright (c) 2015 Rafał Miłecki <zajec5@gmail.com>
+ *
+ * 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.
+ */
+
+#include "b43.h"
+#include "phy_ac.h"
+
+/**************************************************
+ * Basic PHY ops
+ **************************************************/
+
+static int b43_phy_ac_op_allocate(struct b43_wldev *dev)
+{
+	struct b43_phy_ac *phy_ac;
+
+	phy_ac = kzalloc(sizeof(*phy_ac), GFP_KERNEL);
+	if (!phy_ac)
+		return -ENOMEM;
+	dev->phy.ac = phy_ac;
+
+	return 0;
+}
+
+static void b43_phy_ac_op_free(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_ac *phy_ac = phy->ac;
+
+	kfree(phy_ac);
+	phy->ac = NULL;
+}
+
+static void b43_phy_ac_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
+				  u16 set)
+{
+	b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
+	b43_write16(dev, B43_MMIO_PHY_DATA,
+		    (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
+}
+
+static u16 b43_phy_ac_op_radio_read(struct b43_wldev *dev, u16 reg)
+{
+	b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg);
+	return b43_read16(dev, B43_MMIO_RADIO24_DATA);
+}
+
+static void b43_phy_ac_op_radio_write(struct b43_wldev *dev, u16 reg,
+				      u16 value)
+{
+	b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg);
+	b43_write16(dev, B43_MMIO_RADIO24_DATA, value);
+}
+
+static unsigned int b43_phy_ac_op_get_default_chan(struct b43_wldev *dev)
+{
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+		return 11;
+	return 36;
+}
+
+static enum b43_txpwr_result
+b43_phy_ac_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi)
+{
+	return B43_TXPWR_RES_DONE;
+}
+
+static void b43_phy_ac_op_adjust_txpower(struct b43_wldev *dev)
+{
+}
+
+/**************************************************
+ * PHY ops struct
+ **************************************************/
+
+const struct b43_phy_operations b43_phyops_ac = {
+	.allocate		= b43_phy_ac_op_allocate,
+	.free			= b43_phy_ac_op_free,
+	.phy_maskset		= b43_phy_ac_op_maskset,
+	.radio_read		= b43_phy_ac_op_radio_read,
+	.radio_write		= b43_phy_ac_op_radio_write,
+	.get_default_chan	= b43_phy_ac_op_get_default_chan,
+	.recalc_txpower		= b43_phy_ac_op_recalc_txpower,
+	.adjust_txpower		= b43_phy_ac_op_adjust_txpower,
+};
diff --git a/drivers/net/wireless/broadcom/b43/phy_ac.h b/drivers/net/wireless/broadcom/b43/phy_ac.h
new file mode 100644
index 0000000..02eb6c0
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/phy_ac.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_PHY_AC_H_
+#define B43_PHY_AC_H_
+
+#include "phy_common.h"
+
+#define B43_PHY_AC_BBCFG			0x001
+#define  B43_PHY_AC_BBCFG_RSTCCA		0x4000	/* Reset CCA */
+#define B43_PHY_AC_BANDCTL			0x003	/* Band control */
+#define  B43_PHY_AC_BANDCTL_5GHZ		0x0001
+#define B43_PHY_AC_TABLE_ID			0x00d
+#define B43_PHY_AC_TABLE_OFFSET			0x00e
+#define B43_PHY_AC_TABLE_DATA1			0x00f
+#define B43_PHY_AC_TABLE_DATA2			0x010
+#define B43_PHY_AC_TABLE_DATA3			0x011
+#define B43_PHY_AC_CLASSCTL			0x140	/* Classifier control */
+#define  B43_PHY_AC_CLASSCTL_CCKEN		0x0001	/* CCK enable */
+#define  B43_PHY_AC_CLASSCTL_OFDMEN		0x0002	/* OFDM enable */
+#define  B43_PHY_AC_CLASSCTL_WAITEDEN		0x0004	/* Waited enable */
+#define B43_PHY_AC_BW1A				0x371
+#define B43_PHY_AC_BW2				0x372
+#define B43_PHY_AC_BW3				0x373
+#define B43_PHY_AC_BW4				0x374
+#define B43_PHY_AC_BW5				0x375
+#define B43_PHY_AC_BW6				0x376
+#define B43_PHY_AC_RFCTL_CMD			0x408
+#define B43_PHY_AC_C1_CLIP			0x6d4
+#define  B43_PHY_AC_C1_CLIP_DIS			0x4000
+#define B43_PHY_AC_C2_CLIP			0x8d4
+#define  B43_PHY_AC_C2_CLIP_DIS			0x4000
+#define B43_PHY_AC_C3_CLIP			0xad4
+#define  B43_PHY_AC_C3_CLIP_DIS			0x4000
+
+struct b43_phy_ac {
+};
+
+extern const struct b43_phy_operations b43_phyops_ac;
+
+#endif /* B43_PHY_AC_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/phy_common.c b/drivers/net/wireless/broadcom/b43/phy_common.c
new file mode 100644
index 0000000..85f2ca9
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/phy_common.c
@@ -0,0 +1,653 @@
+/*
+
+  Broadcom B43 wireless driver
+  Common PHY routines
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+  Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
+  Copyright (c) 2005-2008 Michael Buesch <m@bues.ch>
+  Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
+  Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+  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 "phy_common.h"
+#include "phy_g.h"
+#include "phy_a.h"
+#include "phy_n.h"
+#include "phy_lp.h"
+#include "phy_ht.h"
+#include "phy_lcn.h"
+#include "phy_ac.h"
+#include "b43.h"
+#include "main.h"
+
+
+int b43_phy_allocate(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &(dev->phy);
+	int err;
+
+	phy->ops = NULL;
+
+	switch (phy->type) {
+	case B43_PHYTYPE_G:
+#ifdef CONFIG_B43_PHY_G
+		phy->ops = &b43_phyops_g;
+#endif
+		break;
+	case B43_PHYTYPE_N:
+#ifdef CONFIG_B43_PHY_N
+		phy->ops = &b43_phyops_n;
+#endif
+		break;
+	case B43_PHYTYPE_LP:
+#ifdef CONFIG_B43_PHY_LP
+		phy->ops = &b43_phyops_lp;
+#endif
+		break;
+	case B43_PHYTYPE_HT:
+#ifdef CONFIG_B43_PHY_HT
+		phy->ops = &b43_phyops_ht;
+#endif
+		break;
+	case B43_PHYTYPE_LCN:
+#ifdef CONFIG_B43_PHY_LCN
+		phy->ops = &b43_phyops_lcn;
+#endif
+		break;
+	case B43_PHYTYPE_AC:
+#ifdef CONFIG_B43_PHY_AC
+		phy->ops = &b43_phyops_ac;
+#endif
+		break;
+	}
+	if (B43_WARN_ON(!phy->ops))
+		return -ENODEV;
+
+	err = phy->ops->allocate(dev);
+	if (err)
+		phy->ops = NULL;
+
+	return err;
+}
+
+void b43_phy_free(struct b43_wldev *dev)
+{
+	dev->phy.ops->free(dev);
+	dev->phy.ops = NULL;
+}
+
+int b43_phy_init(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	const struct b43_phy_operations *ops = phy->ops;
+	int err;
+
+	/* During PHY init we need to use some channel. On the first init this
+	 * function is called *before* b43_op_config, so our pointer is NULL.
+	 */
+	if (!phy->chandef) {
+		phy->chandef = &dev->wl->hw->conf.chandef;
+		phy->channel = phy->chandef->chan->hw_value;
+	}
+
+	phy->ops->switch_analog(dev, true);
+	b43_software_rfkill(dev, false);
+
+	err = ops->init(dev);
+	if (err) {
+		b43err(dev->wl, "PHY init failed\n");
+		goto err_block_rf;
+	}
+	phy->do_full_init = false;
+
+	err = b43_switch_channel(dev, phy->channel);
+	if (err) {
+		b43err(dev->wl, "PHY init: Channel switch to default failed\n");
+		goto err_phy_exit;
+	}
+
+	return 0;
+
+err_phy_exit:
+	phy->do_full_init = true;
+	if (ops->exit)
+		ops->exit(dev);
+err_block_rf:
+	b43_software_rfkill(dev, true);
+
+	return err;
+}
+
+void b43_phy_exit(struct b43_wldev *dev)
+{
+	const struct b43_phy_operations *ops = dev->phy.ops;
+
+	b43_software_rfkill(dev, true);
+	dev->phy.do_full_init = true;
+	if (ops->exit)
+		ops->exit(dev);
+}
+
+bool b43_has_hardware_pctl(struct b43_wldev *dev)
+{
+	if (!dev->phy.hardware_power_control)
+		return false;
+	if (!dev->phy.ops->supports_hwpctl)
+		return false;
+	return dev->phy.ops->supports_hwpctl(dev);
+}
+
+void b43_radio_lock(struct b43_wldev *dev)
+{
+	u32 macctl;
+
+#if B43_DEBUG
+	B43_WARN_ON(dev->phy.radio_locked);
+	dev->phy.radio_locked = true;
+#endif
+
+	macctl = b43_read32(dev, B43_MMIO_MACCTL);
+	macctl |= B43_MACCTL_RADIOLOCK;
+	b43_write32(dev, B43_MMIO_MACCTL, macctl);
+	/* Commit the write and wait for the firmware
+	 * to finish any radio register access. */
+	b43_read32(dev, B43_MMIO_MACCTL);
+	udelay(10);
+}
+
+void b43_radio_unlock(struct b43_wldev *dev)
+{
+	u32 macctl;
+
+#if B43_DEBUG
+	B43_WARN_ON(!dev->phy.radio_locked);
+	dev->phy.radio_locked = false;
+#endif
+
+	/* Commit any write */
+	b43_read16(dev, B43_MMIO_PHY_VER);
+	/* unlock */
+	macctl = b43_read32(dev, B43_MMIO_MACCTL);
+	macctl &= ~B43_MACCTL_RADIOLOCK;
+	b43_write32(dev, B43_MMIO_MACCTL, macctl);
+}
+
+void b43_phy_lock(struct b43_wldev *dev)
+{
+#if B43_DEBUG
+	B43_WARN_ON(dev->phy.phy_locked);
+	dev->phy.phy_locked = true;
+#endif
+	B43_WARN_ON(dev->dev->core_rev < 3);
+
+	if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP))
+		b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
+}
+
+void b43_phy_unlock(struct b43_wldev *dev)
+{
+#if B43_DEBUG
+	B43_WARN_ON(!dev->phy.phy_locked);
+	dev->phy.phy_locked = false;
+#endif
+	B43_WARN_ON(dev->dev->core_rev < 3);
+
+	if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP))
+		b43_power_saving_ctl_bits(dev, 0);
+}
+
+static inline void assert_mac_suspended(struct b43_wldev *dev)
+{
+	if (!B43_DEBUG)
+		return;
+	if ((b43_status(dev) >= B43_STAT_INITIALIZED) &&
+	    (dev->mac_suspended <= 0)) {
+		b43dbg(dev->wl, "PHY/RADIO register access with "
+		       "enabled MAC.\n");
+		dump_stack();
+	}
+}
+
+u16 b43_radio_read(struct b43_wldev *dev, u16 reg)
+{
+	assert_mac_suspended(dev);
+	dev->phy.writes_counter = 0;
+	return dev->phy.ops->radio_read(dev, reg);
+}
+
+void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+	assert_mac_suspended(dev);
+	if (b43_bus_host_is_pci(dev->dev) &&
+	    ++dev->phy.writes_counter > B43_MAX_WRITES_IN_ROW) {
+		b43_read32(dev, B43_MMIO_MACCTL);
+		dev->phy.writes_counter = 1;
+	}
+	dev->phy.ops->radio_write(dev, reg, value);
+}
+
+void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask)
+{
+	b43_radio_write16(dev, offset,
+			  b43_radio_read16(dev, offset) & mask);
+}
+
+void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set)
+{
+	b43_radio_write16(dev, offset,
+			  b43_radio_read16(dev, offset) | set);
+}
+
+void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
+{
+	b43_radio_write16(dev, offset,
+			  (b43_radio_read16(dev, offset) & mask) | set);
+}
+
+bool b43_radio_wait_value(struct b43_wldev *dev, u16 offset, u16 mask,
+			  u16 value, int delay, int timeout)
+{
+	u16 val;
+	int i;
+
+	for (i = 0; i < timeout; i += delay) {
+		val = b43_radio_read(dev, offset);
+		if ((val & mask) == value)
+			return true;
+		udelay(delay);
+	}
+	return false;
+}
+
+u16 b43_phy_read(struct b43_wldev *dev, u16 reg)
+{
+	assert_mac_suspended(dev);
+	dev->phy.writes_counter = 0;
+
+	if (dev->phy.ops->phy_read)
+		return dev->phy.ops->phy_read(dev, reg);
+
+	b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
+	return b43_read16(dev, B43_MMIO_PHY_DATA);
+}
+
+void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+	assert_mac_suspended(dev);
+	if (b43_bus_host_is_pci(dev->dev) &&
+	    ++dev->phy.writes_counter > B43_MAX_WRITES_IN_ROW) {
+		b43_read16(dev, B43_MMIO_PHY_VER);
+		dev->phy.writes_counter = 1;
+	}
+
+	if (dev->phy.ops->phy_write)
+		return dev->phy.ops->phy_write(dev, reg, value);
+
+	b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
+	b43_write16(dev, B43_MMIO_PHY_DATA, value);
+}
+
+void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg)
+{
+	b43_phy_write(dev, destreg, b43_phy_read(dev, srcreg));
+}
+
+void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask)
+{
+	if (dev->phy.ops->phy_maskset) {
+		assert_mac_suspended(dev);
+		dev->phy.ops->phy_maskset(dev, offset, mask, 0);
+	} else {
+		b43_phy_write(dev, offset,
+			      b43_phy_read(dev, offset) & mask);
+	}
+}
+
+void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set)
+{
+	if (dev->phy.ops->phy_maskset) {
+		assert_mac_suspended(dev);
+		dev->phy.ops->phy_maskset(dev, offset, 0xFFFF, set);
+	} else {
+		b43_phy_write(dev, offset,
+			      b43_phy_read(dev, offset) | set);
+	}
+}
+
+void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
+{
+	if (dev->phy.ops->phy_maskset) {
+		assert_mac_suspended(dev);
+		dev->phy.ops->phy_maskset(dev, offset, mask, set);
+	} else {
+		b43_phy_write(dev, offset,
+			      (b43_phy_read(dev, offset) & mask) | set);
+	}
+}
+
+void b43_phy_put_into_reset(struct b43_wldev *dev)
+{
+	u32 tmp;
+
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+		tmp &= ~B43_BCMA_IOCTL_GMODE;
+		tmp |= B43_BCMA_IOCTL_PHY_RESET;
+		tmp |= BCMA_IOCTL_FGC;
+		bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
+		udelay(1);
+
+		tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+		tmp &= ~BCMA_IOCTL_FGC;
+		bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
+		udelay(1);
+		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);
+		usleep_range(1000, 2000);
+
+		tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+		tmp &= ~SSB_TMSLOW_FGC;
+		ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+		usleep_range(1000, 2000);
+
+		break;
+#endif
+	}
+}
+
+void b43_phy_take_out_of_reset(struct b43_wldev *dev)
+{
+	u32 tmp;
+
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		/* Unset reset bit (with forcing clock) */
+		tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+		tmp &= ~B43_BCMA_IOCTL_PHY_RESET;
+		tmp &= ~B43_BCMA_IOCTL_PHY_CLKEN;
+		tmp |= BCMA_IOCTL_FGC;
+		bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
+		udelay(1);
+
+		/* Do not force clock anymore */
+		tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+		tmp &= ~BCMA_IOCTL_FGC;
+		tmp |= B43_BCMA_IOCTL_PHY_CLKEN;
+		bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
+		udelay(1);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		/* Unset reset bit (with forcing clock) */
+		tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+		tmp &= ~B43_TMSLOW_PHYRESET;
+		tmp &= ~B43_TMSLOW_PHYCLKEN;
+		tmp |= SSB_TMSLOW_FGC;
+		ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+		ssb_read32(dev->dev->sdev, SSB_TMSLOW); /* flush */
+		usleep_range(1000, 2000);
+
+		tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+		tmp &= ~SSB_TMSLOW_FGC;
+		tmp |= B43_TMSLOW_PHYCLKEN;
+		ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+		ssb_read32(dev->dev->sdev, SSB_TMSLOW); /* flush */
+		usleep_range(1000, 2000);
+		break;
+#endif
+	}
+}
+
+int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel)
+{
+	struct b43_phy *phy = &(dev->phy);
+	u16 channelcookie, savedcookie;
+	int err;
+
+	/* First we set the channel radio code to prevent the
+	 * firmware from sending ghost packets.
+	 */
+	channelcookie = new_channel;
+	if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
+		channelcookie |= B43_SHM_SH_CHAN_5GHZ;
+	/* FIXME: set 40Mhz flag if required */
+	if (0)
+		channelcookie |= B43_SHM_SH_CHAN_40MHZ;
+	savedcookie = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN);
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN, channelcookie);
+
+	/* Now try to switch the PHY hardware channel. */
+	err = phy->ops->switch_channel(dev, new_channel);
+	if (err)
+		goto err_restore_cookie;
+
+	/* Wait for the radio to tune to the channel and stabilize. */
+	msleep(8);
+
+	return 0;
+
+err_restore_cookie:
+	b43_shm_write16(dev, B43_SHM_SHARED,
+			B43_SHM_SH_CHAN, savedcookie);
+
+	return err;
+}
+
+void b43_software_rfkill(struct b43_wldev *dev, bool blocked)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	b43_mac_suspend(dev);
+	phy->ops->software_rfkill(dev, blocked);
+	phy->radio_on = !blocked;
+	b43_mac_enable(dev);
+}
+
+/**
+ * b43_phy_txpower_adjust_work - TX power workqueue.
+ *
+ * Workqueue for updating the TX power parameters in hardware.
+ */
+void b43_phy_txpower_adjust_work(struct work_struct *work)
+{
+	struct b43_wl *wl = container_of(work, struct b43_wl,
+					 txpower_adjust_work);
+	struct b43_wldev *dev;
+
+	mutex_lock(&wl->mutex);
+	dev = wl->current_dev;
+
+	if (likely(dev && (b43_status(dev) >= B43_STAT_STARTED)))
+		dev->phy.ops->adjust_txpower(dev);
+
+	mutex_unlock(&wl->mutex);
+}
+
+void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags)
+{
+	struct b43_phy *phy = &dev->phy;
+	unsigned long now = jiffies;
+	enum b43_txpwr_result result;
+
+	if (!(flags & B43_TXPWR_IGNORE_TIME)) {
+		/* Check if it's time for a TXpower check. */
+		if (time_before(now, phy->next_txpwr_check_time))
+			return; /* Not yet */
+	}
+	/* The next check will be needed in two seconds, or later. */
+	phy->next_txpwr_check_time = round_jiffies(now + (HZ * 2));
+
+	if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) &&
+	    (dev->dev->board_type == SSB_BOARD_BU4306))
+		return; /* No software txpower adjustment needed */
+
+	result = phy->ops->recalc_txpower(dev, !!(flags & B43_TXPWR_IGNORE_TSSI));
+	if (result == B43_TXPWR_RES_DONE)
+		return; /* We are done. */
+	B43_WARN_ON(result != B43_TXPWR_RES_NEED_ADJUST);
+	B43_WARN_ON(phy->ops->adjust_txpower == NULL);
+
+	/* We must adjust the transmission power in hardware.
+	 * Schedule b43_phy_txpower_adjust_work(). */
+	ieee80211_queue_work(dev->wl->hw, &dev->wl->txpower_adjust_work);
+}
+
+int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset)
+{
+	const bool is_ofdm = (shm_offset != B43_SHM_SH_TSSI_CCK);
+	unsigned int a, b, c, d;
+	unsigned int average;
+	u32 tmp;
+
+	tmp = b43_shm_read32(dev, B43_SHM_SHARED, shm_offset);
+	a = tmp & 0xFF;
+	b = (tmp >> 8) & 0xFF;
+	c = (tmp >> 16) & 0xFF;
+	d = (tmp >> 24) & 0xFF;
+	if (a == 0 || a == B43_TSSI_MAX ||
+	    b == 0 || b == B43_TSSI_MAX ||
+	    c == 0 || c == B43_TSSI_MAX ||
+	    d == 0 || d == B43_TSSI_MAX)
+		return -ENOENT;
+	/* The values are OK. Clear them. */
+	tmp = B43_TSSI_MAX | (B43_TSSI_MAX << 8) |
+	      (B43_TSSI_MAX << 16) | (B43_TSSI_MAX << 24);
+	b43_shm_write32(dev, B43_SHM_SHARED, shm_offset, tmp);
+
+	if (is_ofdm) {
+		a = (a + 32) & 0x3F;
+		b = (b + 32) & 0x3F;
+		c = (c + 32) & 0x3F;
+		d = (d + 32) & 0x3F;
+	}
+
+	/* Get the average of the values with 0.5 added to each value. */
+	average = (a + b + c + d + 2) / 4;
+	if (is_ofdm) {
+		/* Adjust for CCK-boost */
+		if (b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF1)
+		    & B43_HF_CCKBOOST)
+			average = (average >= 13) ? (average - 13) : 0;
+	}
+
+	return average;
+}
+
+void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on)
+{
+	b43_write16(dev, B43_MMIO_PHY0, on ? 0 : 0xF4);
+}
+
+
+bool b43_is_40mhz(struct b43_wldev *dev)
+{
+	return dev->phy.chandef->width == NL80211_CHAN_WIDTH_40;
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
+void b43_phy_force_clock(struct b43_wldev *dev, bool force)
+{
+	u32 tmp;
+
+	WARN_ON(dev->phy.type != B43_PHYTYPE_N &&
+		dev->phy.type != B43_PHYTYPE_HT &&
+		dev->phy.type != B43_PHYTYPE_AC);
+
+	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/Cordic */
+struct b43_c32 b43_cordic(int theta)
+{
+	static const u32 arctg[] = {
+		2949120, 1740967, 919879, 466945, 234379, 117304,
+		  58666,   29335,  14668,   7334,   3667,   1833,
+		    917,     458,    229,    115,     57,     29,
+	};
+	u8 i;
+	s32 tmp;
+	s8 signx = 1;
+	u32 angle = 0;
+	struct b43_c32 ret = { .i = 39797, .q = 0, };
+
+	while (theta > (180 << 16))
+		theta -= (360 << 16);
+	while (theta < -(180 << 16))
+		theta += (360 << 16);
+
+	if (theta > (90 << 16)) {
+		theta -= (180 << 16);
+		signx = -1;
+	} else if (theta < -(90 << 16)) {
+		theta += (180 << 16);
+		signx = -1;
+	}
+
+	for (i = 0; i <= 17; i++) {
+		if (theta > angle) {
+			tmp = ret.i - (ret.q >> i);
+			ret.q += ret.i >> i;
+			ret.i = tmp;
+			angle += arctg[i];
+		} else {
+			tmp = ret.i + (ret.q >> i);
+			ret.q -= ret.i >> i;
+			ret.i = tmp;
+			angle -= arctg[i];
+		}
+	}
+
+	ret.i *= signx;
+	ret.q *= signx;
+
+	return ret;
+}
diff --git a/drivers/net/wireless/broadcom/b43/phy_common.h b/drivers/net/wireless/broadcom/b43/phy_common.h
new file mode 100644
index 0000000..57a1ad8
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/phy_common.h
@@ -0,0 +1,455 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef LINUX_B43_PHY_COMMON_H_
+#define LINUX_B43_PHY_COMMON_H_
+
+#include <linux/types.h>
+#include <linux/nl80211.h>
+
+struct b43_wldev;
+
+/* Complex number using 2 32-bit signed integers */
+struct b43_c32 { s32 i, q; };
+
+#define CORDIC_CONVERT(value)	(((value) >= 0) ? \
+				 ((((value) >> 15) + 1) >> 1) : \
+				 -((((-(value)) >> 15) + 1) >> 1))
+
+/* PHY register routing bits */
+#define B43_PHYROUTE			0x0C00 /* PHY register routing bits mask */
+#define  B43_PHYROUTE_BASE		0x0000 /* Base registers */
+#define  B43_PHYROUTE_OFDM_GPHY		0x0400 /* OFDM register routing for G-PHYs */
+#define  B43_PHYROUTE_EXT_GPHY		0x0800 /* Extended G-PHY registers */
+#define  B43_PHYROUTE_N_BMODE		0x0C00 /* N-PHY BMODE registers */
+
+/* CCK (B-PHY) registers. */
+#define B43_PHY_CCK(reg)		((reg) | B43_PHYROUTE_BASE)
+/* N-PHY registers. */
+#define B43_PHY_N(reg)			((reg) | B43_PHYROUTE_BASE)
+/* N-PHY BMODE registers. */
+#define B43_PHY_N_BMODE(reg)		((reg) | B43_PHYROUTE_N_BMODE)
+/* OFDM (A-PHY) registers. */
+#define B43_PHY_OFDM(reg)		((reg) | B43_PHYROUTE_OFDM_GPHY)
+/* Extended G-PHY registers. */
+#define B43_PHY_EXTG(reg)		((reg) | B43_PHYROUTE_EXT_GPHY)
+
+
+/* Masks for the PHY versioning registers. */
+#define B43_PHYVER_ANALOG		0xF000
+#define B43_PHYVER_ANALOG_SHIFT		12
+#define B43_PHYVER_TYPE			0x0F00
+#define B43_PHYVER_TYPE_SHIFT		8
+#define B43_PHYVER_VERSION		0x00FF
+
+/* PHY writes need to be flushed if we reach limit */
+#define B43_MAX_WRITES_IN_ROW		24
+
+/**
+ * enum b43_interference_mitigation - Interference Mitigation mode
+ *
+ * @B43_INTERFMODE_NONE:	Disabled
+ * @B43_INTERFMODE_NONWLAN:	Non-WLAN Interference Mitigation
+ * @B43_INTERFMODE_MANUALWLAN:	WLAN Interference Mitigation
+ * @B43_INTERFMODE_AUTOWLAN:	Automatic WLAN Interference Mitigation
+ */
+enum b43_interference_mitigation {
+	B43_INTERFMODE_NONE,
+	B43_INTERFMODE_NONWLAN,
+	B43_INTERFMODE_MANUALWLAN,
+	B43_INTERFMODE_AUTOWLAN,
+};
+
+/* Antenna identifiers */
+enum {
+	B43_ANTENNA0 = 0,	/* Antenna 0 */
+	B43_ANTENNA1 = 1,	/* Antenna 1 */
+	B43_ANTENNA_AUTO0 = 2,	/* Automatic, starting with antenna 0 */
+	B43_ANTENNA_AUTO1 = 3,	/* Automatic, starting with antenna 1 */
+	B43_ANTENNA2 = 4,
+	B43_ANTENNA3 = 8,
+
+	B43_ANTENNA_AUTO = B43_ANTENNA_AUTO0,
+	B43_ANTENNA_DEFAULT = B43_ANTENNA_AUTO,
+};
+
+/**
+ * enum b43_txpwr_result - Return value for the recalc_txpower PHY op.
+ *
+ * @B43_TXPWR_RES_NEED_ADJUST:	Values changed. Hardware adjustment is needed.
+ * @B43_TXPWR_RES_DONE:		No more work to do. Everything is done.
+ */
+enum b43_txpwr_result {
+	B43_TXPWR_RES_NEED_ADJUST,
+	B43_TXPWR_RES_DONE,
+};
+
+/**
+ * struct b43_phy_operations - Function pointers for PHY ops.
+ *
+ * @allocate:		Allocate and initialise the PHY data structures.
+ * 			Must not be NULL.
+ * @free:		Destroy and free the PHY data structures.
+ * 			Must not be NULL.
+ *
+ * @prepare_structs:	Prepare the PHY data structures.
+ * 			The data structures allocated in @allocate are
+ * 			initialized here.
+ * 			Must not be NULL.
+ * @prepare_hardware:	Prepare the PHY. This is called before b43_chip_init to
+ * 			do some early early PHY hardware init.
+ * 			Can be NULL, if not required.
+ * @init:		Initialize the PHY.
+ * 			Must not be NULL.
+ * @exit:		Shutdown the PHY.
+ * 			Can be NULL, if not required.
+ *
+ * @phy_read:		Read from a PHY register.
+ * 			Must not be NULL.
+ * @phy_write:		Write to a PHY register.
+ * 			Must not be NULL.
+ * @phy_maskset:	Maskset a PHY register, taking shortcuts.
+ *			If it is NULL, a generic algorithm is used.
+ * @radio_read:		Read from a Radio register.
+ * 			Must not be NULL.
+ * @radio_write:	Write to a Radio register.
+ * 			Must not be NULL.
+ *
+ * @supports_hwpctl:	Returns a boolean whether Hardware Power Control
+ * 			is supported or not.
+ * 			If NULL, hwpctl is assumed to be never supported.
+ * @software_rfkill:	Turn the radio ON or OFF.
+ * 			Possible state values are
+ * 			RFKILL_STATE_SOFT_BLOCKED or
+ * 			RFKILL_STATE_UNBLOCKED
+ * 			Must not be NULL.
+ * @switch_analog:	Turn the Analog on/off.
+ * 			Must not be NULL.
+ * @switch_channel:	Switch the radio to another channel.
+ * 			Must not be NULL.
+ * @get_default_chan:	Just returns the default channel number.
+ * 			Must not be NULL.
+ * @set_rx_antenna:	Set the antenna used for RX.
+ * 			Can be NULL, if not supported.
+ * @interf_mitigation:	Switch the Interference Mitigation mode.
+ * 			Can be NULL, if not supported.
+ *
+ * @recalc_txpower:	Recalculate the transmission power parameters.
+ * 			This callback has to recalculate the TX power settings,
+ * 			but does not need to write them to the hardware, yet.
+ * 			Returns enum b43_txpwr_result to indicate whether the hardware
+ * 			needs to be adjusted.
+ * 			If B43_TXPWR_NEED_ADJUST is returned, @adjust_txpower
+ * 			will be called later.
+ * 			If the parameter "ignore_tssi" is true, the TSSI values should
+ * 			be ignored and a recalculation of the power settings should be
+ * 			done even if the TSSI values did not change.
+ * 			This function may sleep, but should not.
+ * 			Must not be NULL.
+ * @adjust_txpower:	Write the previously calculated TX power settings
+ * 			(from @recalc_txpower) to the hardware.
+ * 			This function may sleep.
+ * 			Can be NULL, if (and ONLY if) @recalc_txpower _always_
+ * 			returns B43_TXPWR_RES_DONE.
+ *
+ * @pwork_15sec:	Periodic work. Called every 15 seconds.
+ * 			Can be NULL, if not required.
+ * @pwork_60sec:	Periodic work. Called every 60 seconds.
+ * 			Can be NULL, if not required.
+ */
+struct b43_phy_operations {
+	/* Initialisation */
+	int (*allocate)(struct b43_wldev *dev);
+	void (*free)(struct b43_wldev *dev);
+	void (*prepare_structs)(struct b43_wldev *dev);
+	int (*prepare_hardware)(struct b43_wldev *dev);
+	int (*init)(struct b43_wldev *dev);
+	void (*exit)(struct b43_wldev *dev);
+
+	/* Register access */
+	u16 (*phy_read)(struct b43_wldev *dev, u16 reg);
+	void (*phy_write)(struct b43_wldev *dev, u16 reg, u16 value);
+	void (*phy_maskset)(struct b43_wldev *dev, u16 reg, u16 mask, u16 set);
+	u16 (*radio_read)(struct b43_wldev *dev, u16 reg);
+	void (*radio_write)(struct b43_wldev *dev, u16 reg, u16 value);
+
+	/* Radio */
+	bool (*supports_hwpctl)(struct b43_wldev *dev);
+	void (*software_rfkill)(struct b43_wldev *dev, bool blocked);
+	void (*switch_analog)(struct b43_wldev *dev, bool on);
+	int (*switch_channel)(struct b43_wldev *dev, unsigned int new_channel);
+	unsigned int (*get_default_chan)(struct b43_wldev *dev);
+	void (*set_rx_antenna)(struct b43_wldev *dev, int antenna);
+	int (*interf_mitigation)(struct b43_wldev *dev,
+				 enum b43_interference_mitigation new_mode);
+
+	/* Transmission power adjustment */
+	enum b43_txpwr_result (*recalc_txpower)(struct b43_wldev *dev,
+						bool ignore_tssi);
+	void (*adjust_txpower)(struct b43_wldev *dev);
+
+	/* Misc */
+	void (*pwork_15sec)(struct b43_wldev *dev);
+	void (*pwork_60sec)(struct b43_wldev *dev);
+};
+
+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. */
+	const struct b43_phy_operations *ops;
+
+	/* Most hardware context information is stored in the standard-
+	 * specific data structures pointed to by the pointers below.
+	 * Only one of them is valid (the currently enabled PHY). */
+#ifdef CONFIG_B43_DEBUG
+	/* No union for debug build to force NULL derefs in buggy code. */
+	struct {
+#else
+	union {
+#endif
+		/* G-PHY specific information */
+		struct b43_phy_g *g;
+		/* N-PHY specific information */
+		struct b43_phy_n *n;
+		/* LP-PHY specific information */
+		struct b43_phy_lp *lp;
+		/* HT-PHY specific information */
+		struct b43_phy_ht *ht;
+		/* LCN-PHY specific information */
+		struct b43_phy_lcn *lcn;
+		/* AC-PHY specific information */
+		struct b43_phy_ac *ac;
+	};
+
+	/* Band support flags. */
+	bool supports_2ghz;
+	bool supports_5ghz;
+
+	/* Is GMODE (2 GHz mode) bit enabled? */
+	bool gmode;
+
+	/* After power reset full init has to be performed */
+	bool do_full_init;
+
+	/* Analog Type */
+	u8 analog;
+	/* B43_PHYTYPE_ */
+	u8 type;
+	/* PHY revision number. */
+	u8 rev;
+
+	/* Count writes since last read */
+	u8 writes_counter;
+
+	/* Radio versioning */
+	u16 radio_manuf;	/* Radio manufacturer */
+	u16 radio_ver;		/* Radio version */
+	u8 radio_rev;		/* Radio revision */
+
+	/* Software state of the radio */
+	bool radio_on;
+
+	/* Desired TX power level (in dBm).
+	 * This is set by the user and adjusted in b43_phy_xmitpower(). */
+	int desired_txpower;
+
+	/* Hardware Power Control enabled? */
+	bool hardware_power_control;
+
+	/* The time (in absolute jiffies) when the next TX power output
+	 * check is needed. */
+	unsigned long next_txpwr_check_time;
+
+	/* Current channel */
+	struct cfg80211_chan_def *chandef;
+	unsigned int channel;
+
+	/* PHY TX errors counter. */
+	atomic_t txerr_cnt;
+
+#ifdef CONFIG_B43_DEBUG
+	/* PHY registers locked (w.r.t. firmware) */
+	bool phy_locked;
+	/* Radio registers locked (w.r.t. firmware) */
+	bool radio_locked;
+#endif /* B43_DEBUG */
+};
+
+
+/**
+ * b43_phy_allocate - Allocate PHY structs
+ * Allocate the PHY data structures, based on the current dev->phy.type
+ */
+int b43_phy_allocate(struct b43_wldev *dev);
+
+/**
+ * b43_phy_free - Free PHY structs
+ */
+void b43_phy_free(struct b43_wldev *dev);
+
+/**
+ * b43_phy_init - Initialise the PHY
+ */
+int b43_phy_init(struct b43_wldev *dev);
+
+/**
+ * b43_phy_exit - Cleanup PHY
+ */
+void b43_phy_exit(struct b43_wldev *dev);
+
+/**
+ * b43_has_hardware_pctl - Hardware Power Control supported?
+ * Returns a boolean, whether hardware power control is supported.
+ */
+bool b43_has_hardware_pctl(struct b43_wldev *dev);
+
+/**
+ * b43_phy_read - 16bit PHY register read access
+ */
+u16 b43_phy_read(struct b43_wldev *dev, u16 reg);
+
+/**
+ * b43_phy_write - 16bit PHY register write access
+ */
+void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value);
+
+/**
+ * b43_phy_copy - copy contents of 16bit PHY register to another
+ */
+void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg);
+
+/**
+ * b43_phy_mask - Mask a PHY register with a mask
+ */
+void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask);
+
+/**
+ * b43_phy_set - OR a PHY register with a bitmap
+ */
+void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set);
+
+/**
+ * b43_phy_maskset - Mask and OR a PHY register with a mask and bitmap
+ */
+void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set);
+
+/**
+ * b43_radio_read - 16bit Radio register read access
+ */
+u16 b43_radio_read(struct b43_wldev *dev, u16 reg);
+#define b43_radio_read16	b43_radio_read /* DEPRECATED */
+
+/**
+ * b43_radio_write - 16bit Radio register write access
+ */
+void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value);
+#define b43_radio_write16	b43_radio_write /* DEPRECATED */
+
+/**
+ * b43_radio_mask - Mask a 16bit radio register with a mask
+ */
+void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask);
+
+/**
+ * b43_radio_set - OR a 16bit radio register with a bitmap
+ */
+void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set);
+
+/**
+ * b43_radio_maskset - Mask and OR a radio register with a mask and bitmap
+ */
+void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set);
+
+/**
+ * b43_radio_wait_value - Waits for a given value in masked register read
+ */
+bool b43_radio_wait_value(struct b43_wldev *dev, u16 offset, u16 mask,
+			  u16 value, int delay, int timeout);
+
+/**
+ * b43_radio_lock - Lock firmware radio register access
+ */
+void b43_radio_lock(struct b43_wldev *dev);
+
+/**
+ * b43_radio_unlock - Unlock firmware radio register access
+ */
+void b43_radio_unlock(struct b43_wldev *dev);
+
+/**
+ * b43_phy_lock - Lock firmware PHY register access
+ */
+void b43_phy_lock(struct b43_wldev *dev);
+
+/**
+ * b43_phy_unlock - Unlock firmware PHY register access
+ */
+void b43_phy_unlock(struct b43_wldev *dev);
+
+void b43_phy_put_into_reset(struct b43_wldev *dev);
+void b43_phy_take_out_of_reset(struct b43_wldev *dev);
+
+/**
+ * b43_switch_channel - Switch to another channel
+ */
+int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel);
+
+/**
+ * b43_software_rfkill - Turn the radio ON or OFF in software.
+ */
+void b43_software_rfkill(struct b43_wldev *dev, bool blocked);
+
+/**
+ * b43_phy_txpower_check - Check TX power output.
+ *
+ * Compare the current TX power output to the desired power emission
+ * and schedule an adjustment in case it mismatches.
+ *
+ * @flags:	OR'ed enum b43_phy_txpower_check_flags flags.
+ * 		See the docs below.
+ */
+void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags);
+/**
+ * enum b43_phy_txpower_check_flags - Flags for b43_phy_txpower_check()
+ *
+ * @B43_TXPWR_IGNORE_TIME: Ignore the schedule time and force-redo
+ *                         the check now.
+ * @B43_TXPWR_IGNORE_TSSI: Redo the recalculation, even if the average
+ *                         TSSI did not change.
+ */
+enum b43_phy_txpower_check_flags {
+	B43_TXPWR_IGNORE_TIME		= (1 << 0),
+	B43_TXPWR_IGNORE_TSSI		= (1 << 1),
+};
+
+struct work_struct;
+void b43_phy_txpower_adjust_work(struct work_struct *work);
+
+/**
+ * b43_phy_shm_tssi_read - Read the average of the last 4 TSSI from SHM.
+ *
+ * @shm_offset:		The SHM address to read the values from.
+ *
+ * Returns the average of the 4 TSSI values, or a negative error code.
+ */
+int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset);
+
+/**
+ * b43_phy_switch_analog_generic - Generic PHY operation for switching the Analog.
+ *
+ * It does the switching based on the PHY0 core register.
+ * Do _not_ call this directly. Only use it as a switch_analog callback
+ * for struct b43_phy_operations.
+ */
+void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on);
+
+bool b43_is_40mhz(struct b43_wldev *dev);
+
+void b43_phy_force_clock(struct b43_wldev *dev, bool force);
+
+struct b43_c32 b43_cordic(int theta);
+
+#endif /* LINUX_B43_PHY_COMMON_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/phy_g.c b/drivers/net/wireless/broadcom/b43/phy_g.c
new file mode 100644
index 0000000..f59c021
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/phy_g.c
@@ -0,0 +1,3070 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11g PHY driver
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+  Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
+  Copyright (c) 2005-2008 Michael Buesch <m@bues.ch>
+  Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
+  Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+  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 "phy_g.h"
+#include "phy_common.h"
+#include "lo.h"
+#include "main.h"
+#include "wa.h"
+
+#include <linux/bitrev.h>
+#include <linux/slab.h>
+
+
+static const s8 b43_tssi2dbm_g_table[] = {
+	77, 77, 77, 76,
+	76, 76, 75, 75,
+	74, 74, 73, 73,
+	73, 72, 72, 71,
+	71, 70, 70, 69,
+	68, 68, 67, 67,
+	66, 65, 65, 64,
+	63, 63, 62, 61,
+	60, 59, 58, 57,
+	56, 55, 54, 53,
+	52, 50, 49, 47,
+	45, 43, 40, 37,
+	33, 28, 22, 14,
+	5, -7, -20, -20,
+	-20, -20, -20, -20,
+	-20, -20, -20, -20,
+};
+
+static const u8 b43_radio_channel_codes_bg[] = {
+	12, 17, 22, 27,
+	32, 37, 42, 47,
+	52, 57, 62, 67,
+	72, 84,
+};
+
+
+static void b43_calc_nrssi_threshold(struct b43_wldev *dev);
+
+
+#define bitrev4(tmp) (bitrev8(tmp) >> 4)
+
+
+/* Get the freq, as it has to be written to the device. */
+static inline u16 channel2freq_bg(u8 channel)
+{
+	B43_WARN_ON(!(channel >= 1 && channel <= 14));
+
+	return b43_radio_channel_codes_bg[channel - 1];
+}
+
+static void generate_rfatt_list(struct b43_wldev *dev,
+				struct b43_rfatt_list *list)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	/* APHY.rev < 5 || GPHY.rev < 6 */
+	static const struct b43_rfatt rfatt_0[] = {
+		{.att = 3,.with_padmix = 0,},
+		{.att = 1,.with_padmix = 0,},
+		{.att = 5,.with_padmix = 0,},
+		{.att = 7,.with_padmix = 0,},
+		{.att = 9,.with_padmix = 0,},
+		{.att = 2,.with_padmix = 0,},
+		{.att = 0,.with_padmix = 0,},
+		{.att = 4,.with_padmix = 0,},
+		{.att = 6,.with_padmix = 0,},
+		{.att = 8,.with_padmix = 0,},
+		{.att = 1,.with_padmix = 1,},
+		{.att = 2,.with_padmix = 1,},
+		{.att = 3,.with_padmix = 1,},
+		{.att = 4,.with_padmix = 1,},
+	};
+	/* Radio.rev == 8 && Radio.version == 0x2050 */
+	static const struct b43_rfatt rfatt_1[] = {
+		{.att = 2,.with_padmix = 1,},
+		{.att = 4,.with_padmix = 1,},
+		{.att = 6,.with_padmix = 1,},
+		{.att = 8,.with_padmix = 1,},
+		{.att = 10,.with_padmix = 1,},
+		{.att = 12,.with_padmix = 1,},
+		{.att = 14,.with_padmix = 1,},
+	};
+	/* Otherwise */
+	static const struct b43_rfatt rfatt_2[] = {
+		{.att = 0,.with_padmix = 1,},
+		{.att = 2,.with_padmix = 1,},
+		{.att = 4,.with_padmix = 1,},
+		{.att = 6,.with_padmix = 1,},
+		{.att = 8,.with_padmix = 1,},
+		{.att = 9,.with_padmix = 1,},
+		{.att = 9,.with_padmix = 1,},
+	};
+
+	if (!b43_has_hardware_pctl(dev)) {
+		/* Software pctl */
+		list->list = rfatt_0;
+		list->len = ARRAY_SIZE(rfatt_0);
+		list->min_val = 0;
+		list->max_val = 9;
+		return;
+	}
+	if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) {
+		/* Hardware pctl */
+		list->list = rfatt_1;
+		list->len = ARRAY_SIZE(rfatt_1);
+		list->min_val = 0;
+		list->max_val = 14;
+		return;
+	}
+	/* Hardware pctl */
+	list->list = rfatt_2;
+	list->len = ARRAY_SIZE(rfatt_2);
+	list->min_val = 0;
+	list->max_val = 9;
+}
+
+static void generate_bbatt_list(struct b43_wldev *dev,
+				struct b43_bbatt_list *list)
+{
+	static const struct b43_bbatt bbatt_0[] = {
+		{.att = 0,},
+		{.att = 1,},
+		{.att = 2,},
+		{.att = 3,},
+		{.att = 4,},
+		{.att = 5,},
+		{.att = 6,},
+		{.att = 7,},
+		{.att = 8,},
+	};
+
+	list->list = bbatt_0;
+	list->len = ARRAY_SIZE(bbatt_0);
+	list->min_val = 0;
+	list->max_val = 8;
+}
+
+static void b43_shm_clear_tssi(struct b43_wldev *dev)
+{
+	b43_shm_write16(dev, B43_SHM_SHARED, 0x0058, 0x7F7F);
+	b43_shm_write16(dev, B43_SHM_SHARED, 0x005a, 0x7F7F);
+	b43_shm_write16(dev, B43_SHM_SHARED, 0x0070, 0x7F7F);
+	b43_shm_write16(dev, B43_SHM_SHARED, 0x0072, 0x7F7F);
+}
+
+/* Synthetic PU workaround */
+static void b43_synth_pu_workaround(struct b43_wldev *dev, u8 channel)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	might_sleep();
+
+	if (phy->radio_ver != 0x2050 || phy->radio_rev >= 6) {
+		/* We do not need the workaround. */
+		return;
+	}
+
+	if (channel <= 10) {
+		b43_write16(dev, B43_MMIO_CHANNEL,
+			    channel2freq_bg(channel + 4));
+	} else {
+		b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(1));
+	}
+	msleep(1);
+	b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel));
+}
+
+/* Set the baseband attenuation value on chip. */
+void b43_gphy_set_baseband_attenuation(struct b43_wldev *dev,
+				       u16 baseband_attenuation)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	if (phy->analog == 0) {
+		b43_write16(dev, B43_MMIO_PHY0, (b43_read16(dev, B43_MMIO_PHY0)
+						 & 0xFFF0) |
+			    baseband_attenuation);
+	} else if (phy->analog > 1) {
+		b43_phy_maskset(dev, B43_PHY_DACCTL, 0xFFC3, (baseband_attenuation << 2));
+	} else {
+		b43_phy_maskset(dev, B43_PHY_DACCTL, 0xFF87, (baseband_attenuation << 3));
+	}
+}
+
+/* Adjust the transmission power output (G-PHY) */
+static void b43_set_txpower_g(struct b43_wldev *dev,
+			      const struct b43_bbatt *bbatt,
+			      const struct b43_rfatt *rfatt, u8 tx_control)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	struct b43_txpower_lo_control *lo = gphy->lo_control;
+	u16 bb, rf;
+	u16 tx_bias, tx_magn;
+
+	bb = bbatt->att;
+	rf = rfatt->att;
+	tx_bias = lo->tx_bias;
+	tx_magn = lo->tx_magn;
+	if (unlikely(tx_bias == 0xFF))
+		tx_bias = 0;
+
+	/* Save the values for later. Use memmove, because it's valid
+	 * to pass &gphy->rfatt as rfatt pointer argument. Same for bbatt. */
+	gphy->tx_control = tx_control;
+	memmove(&gphy->rfatt, rfatt, sizeof(*rfatt));
+	gphy->rfatt.with_padmix = !!(tx_control & B43_TXCTL_TXMIX);
+	memmove(&gphy->bbatt, bbatt, sizeof(*bbatt));
+
+	if (b43_debug(dev, B43_DBG_XMITPOWER)) {
+		b43dbg(dev->wl, "Tuning TX-power to bbatt(%u), "
+		       "rfatt(%u), tx_control(0x%02X), "
+		       "tx_bias(0x%02X), tx_magn(0x%02X)\n",
+		       bb, rf, tx_control, tx_bias, tx_magn);
+	}
+
+	b43_gphy_set_baseband_attenuation(dev, bb);
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_RFATT, rf);
+	if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) {
+		b43_radio_write16(dev, 0x43,
+				  (rf & 0x000F) | (tx_control & 0x0070));
+	} else {
+		b43_radio_maskset(dev, 0x43, 0xFFF0, (rf & 0x000F));
+		b43_radio_maskset(dev, 0x52, ~0x0070, (tx_control & 0x0070));
+	}
+	if (has_tx_magnification(phy)) {
+		b43_radio_write16(dev, 0x52, tx_magn | tx_bias);
+	} else {
+		b43_radio_maskset(dev, 0x52, 0xFFF0, (tx_bias & 0x000F));
+	}
+	b43_lo_g_adjust(dev);
+}
+
+/* GPHY_TSSI_Power_Lookup_Table_Init */
+static void b43_gphy_tssi_power_lt_init(struct b43_wldev *dev)
+{
+	struct b43_phy_g *gphy = dev->phy.g;
+	int i;
+	u16 value;
+
+	for (i = 0; i < 32; i++)
+		b43_ofdmtab_write16(dev, 0x3C20, i, gphy->tssi2dbm[i]);
+	for (i = 32; i < 64; i++)
+		b43_ofdmtab_write16(dev, 0x3C00, i - 32, gphy->tssi2dbm[i]);
+	for (i = 0; i < 64; i += 2) {
+		value = (u16) gphy->tssi2dbm[i];
+		value |= ((u16) gphy->tssi2dbm[i + 1]) << 8;
+		b43_phy_write(dev, 0x380 + (i / 2), value);
+	}
+}
+
+/* GPHY_Gain_Lookup_Table_Init */
+static void b43_gphy_gain_lt_init(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	struct b43_txpower_lo_control *lo = gphy->lo_control;
+	u16 nr_written = 0;
+	u16 tmp;
+	u8 rf, bb;
+
+	for (rf = 0; rf < lo->rfatt_list.len; rf++) {
+		for (bb = 0; bb < lo->bbatt_list.len; bb++) {
+			if (nr_written >= 0x40)
+				return;
+			tmp = lo->bbatt_list.list[bb].att;
+			tmp <<= 8;
+			if (phy->radio_rev == 8)
+				tmp |= 0x50;
+			else
+				tmp |= 0x40;
+			tmp |= lo->rfatt_list.list[rf].att;
+			b43_phy_write(dev, 0x3C0 + nr_written, tmp);
+			nr_written++;
+		}
+	}
+}
+
+static void b43_set_all_gains(struct b43_wldev *dev,
+			      s16 first, s16 second, s16 third)
+{
+	struct b43_phy *phy = &dev->phy;
+	u16 i;
+	u16 start = 0x08, end = 0x18;
+	u16 tmp;
+	u16 table;
+
+	if (phy->rev <= 1) {
+		start = 0x10;
+		end = 0x20;
+	}
+
+	table = B43_OFDMTAB_GAINX;
+	if (phy->rev <= 1)
+		table = B43_OFDMTAB_GAINX_R1;
+	for (i = 0; i < 4; i++)
+		b43_ofdmtab_write16(dev, table, i, first);
+
+	for (i = start; i < end; i++)
+		b43_ofdmtab_write16(dev, table, i, second);
+
+	if (third != -1) {
+		tmp = ((u16) third << 14) | ((u16) third << 6);
+		b43_phy_maskset(dev, 0x04A0, 0xBFBF, tmp);
+		b43_phy_maskset(dev, 0x04A1, 0xBFBF, tmp);
+		b43_phy_maskset(dev, 0x04A2, 0xBFBF, tmp);
+	}
+	b43_dummy_transmission(dev, false, true);
+}
+
+static void b43_set_original_gains(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	u16 i, tmp;
+	u16 table;
+	u16 start = 0x0008, end = 0x0018;
+
+	if (phy->rev <= 1) {
+		start = 0x0010;
+		end = 0x0020;
+	}
+
+	table = B43_OFDMTAB_GAINX;
+	if (phy->rev <= 1)
+		table = B43_OFDMTAB_GAINX_R1;
+	for (i = 0; i < 4; i++) {
+		tmp = (i & 0xFFFC);
+		tmp |= (i & 0x0001) << 1;
+		tmp |= (i & 0x0002) >> 1;
+
+		b43_ofdmtab_write16(dev, table, i, tmp);
+	}
+
+	for (i = start; i < end; i++)
+		b43_ofdmtab_write16(dev, table, i, i - start);
+
+	b43_phy_maskset(dev, 0x04A0, 0xBFBF, 0x4040);
+	b43_phy_maskset(dev, 0x04A1, 0xBFBF, 0x4040);
+	b43_phy_maskset(dev, 0x04A2, 0xBFBF, 0x4000);
+	b43_dummy_transmission(dev, false, true);
+}
+
+/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+static void b43_nrssi_hw_write(struct b43_wldev *dev, u16 offset, s16 val)
+{
+	b43_phy_write(dev, B43_PHY_NRSSILT_CTRL, offset);
+	b43_phy_write(dev, B43_PHY_NRSSILT_DATA, (u16) val);
+}
+
+/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+static s16 b43_nrssi_hw_read(struct b43_wldev *dev, u16 offset)
+{
+	u16 val;
+
+	b43_phy_write(dev, B43_PHY_NRSSILT_CTRL, offset);
+	val = b43_phy_read(dev, B43_PHY_NRSSILT_DATA);
+
+	return (s16) val;
+}
+
+/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+static void b43_nrssi_hw_update(struct b43_wldev *dev, u16 val)
+{
+	u16 i;
+	s16 tmp;
+
+	for (i = 0; i < 64; i++) {
+		tmp = b43_nrssi_hw_read(dev, i);
+		tmp -= val;
+		tmp = clamp_val(tmp, -32, 31);
+		b43_nrssi_hw_write(dev, i, tmp);
+	}
+}
+
+/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+static void b43_nrssi_mem_update(struct b43_wldev *dev)
+{
+	struct b43_phy_g *gphy = dev->phy.g;
+	s16 i, delta;
+	s32 tmp;
+
+	delta = 0x1F - gphy->nrssi[0];
+	for (i = 0; i < 64; i++) {
+		tmp = (i - delta) * gphy->nrssislope;
+		tmp /= 0x10000;
+		tmp += 0x3A;
+		tmp = clamp_val(tmp, 0, 0x3F);
+		gphy->nrssi_lt[i] = tmp;
+	}
+}
+
+static void b43_calc_nrssi_offset(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	u16 backup[20] = { 0 };
+	s16 v47F;
+	u16 i;
+	u16 saved = 0xFFFF;
+
+	backup[0] = b43_phy_read(dev, 0x0001);
+	backup[1] = b43_phy_read(dev, 0x0811);
+	backup[2] = b43_phy_read(dev, 0x0812);
+	if (phy->rev != 1) {	/* Not in specs, but needed to prevent PPC machine check */
+		backup[3] = b43_phy_read(dev, 0x0814);
+		backup[4] = b43_phy_read(dev, 0x0815);
+	}
+	backup[5] = b43_phy_read(dev, 0x005A);
+	backup[6] = b43_phy_read(dev, 0x0059);
+	backup[7] = b43_phy_read(dev, 0x0058);
+	backup[8] = b43_phy_read(dev, 0x000A);
+	backup[9] = b43_phy_read(dev, 0x0003);
+	backup[10] = b43_radio_read16(dev, 0x007A);
+	backup[11] = b43_radio_read16(dev, 0x0043);
+
+	b43_phy_mask(dev, 0x0429, 0x7FFF);
+	b43_phy_maskset(dev, 0x0001, 0x3FFF, 0x4000);
+	b43_phy_set(dev, 0x0811, 0x000C);
+	b43_phy_maskset(dev, 0x0812, 0xFFF3, 0x0004);
+	b43_phy_mask(dev, 0x0802, ~(0x1 | 0x2));
+	if (phy->rev >= 6) {
+		backup[12] = b43_phy_read(dev, 0x002E);
+		backup[13] = b43_phy_read(dev, 0x002F);
+		backup[14] = b43_phy_read(dev, 0x080F);
+		backup[15] = b43_phy_read(dev, 0x0810);
+		backup[16] = b43_phy_read(dev, 0x0801);
+		backup[17] = b43_phy_read(dev, 0x0060);
+		backup[18] = b43_phy_read(dev, 0x0014);
+		backup[19] = b43_phy_read(dev, 0x0478);
+
+		b43_phy_write(dev, 0x002E, 0);
+		b43_phy_write(dev, 0x002F, 0);
+		b43_phy_write(dev, 0x080F, 0);
+		b43_phy_write(dev, 0x0810, 0);
+		b43_phy_set(dev, 0x0478, 0x0100);
+		b43_phy_set(dev, 0x0801, 0x0040);
+		b43_phy_set(dev, 0x0060, 0x0040);
+		b43_phy_set(dev, 0x0014, 0x0200);
+	}
+	b43_radio_set(dev, 0x007A, 0x0070);
+	b43_radio_set(dev, 0x007A, 0x0080);
+	udelay(30);
+
+	v47F = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F);
+	if (v47F >= 0x20)
+		v47F -= 0x40;
+	if (v47F == 31) {
+		for (i = 7; i >= 4; i--) {
+			b43_radio_write16(dev, 0x007B, i);
+			udelay(20);
+			v47F =
+			    (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F);
+			if (v47F >= 0x20)
+				v47F -= 0x40;
+			if (v47F < 31 && saved == 0xFFFF)
+				saved = i;
+		}
+		if (saved == 0xFFFF)
+			saved = 4;
+	} else {
+		b43_radio_mask(dev, 0x007A, 0x007F);
+		if (phy->rev != 1) {	/* Not in specs, but needed to prevent PPC machine check */
+			b43_phy_set(dev, 0x0814, 0x0001);
+			b43_phy_mask(dev, 0x0815, 0xFFFE);
+		}
+		b43_phy_set(dev, 0x0811, 0x000C);
+		b43_phy_set(dev, 0x0812, 0x000C);
+		b43_phy_set(dev, 0x0811, 0x0030);
+		b43_phy_set(dev, 0x0812, 0x0030);
+		b43_phy_write(dev, 0x005A, 0x0480);
+		b43_phy_write(dev, 0x0059, 0x0810);
+		b43_phy_write(dev, 0x0058, 0x000D);
+		if (phy->rev == 0) {
+			b43_phy_write(dev, 0x0003, 0x0122);
+		} else {
+			b43_phy_set(dev, 0x000A, 0x2000);
+		}
+		if (phy->rev != 1) {	/* Not in specs, but needed to prevent PPC machine check */
+			b43_phy_set(dev, 0x0814, 0x0004);
+			b43_phy_mask(dev, 0x0815, 0xFFFB);
+		}
+		b43_phy_maskset(dev, 0x0003, 0xFF9F, 0x0040);
+		b43_radio_set(dev, 0x007A, 0x000F);
+		b43_set_all_gains(dev, 3, 0, 1);
+		b43_radio_maskset(dev, 0x0043, 0x00F0, 0x000F);
+		udelay(30);
+		v47F = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F);
+		if (v47F >= 0x20)
+			v47F -= 0x40;
+		if (v47F == -32) {
+			for (i = 0; i < 4; i++) {
+				b43_radio_write16(dev, 0x007B, i);
+				udelay(20);
+				v47F =
+				    (s16) ((b43_phy_read(dev, 0x047F) >> 8) &
+					   0x003F);
+				if (v47F >= 0x20)
+					v47F -= 0x40;
+				if (v47F > -31 && saved == 0xFFFF)
+					saved = i;
+			}
+			if (saved == 0xFFFF)
+				saved = 3;
+		} else
+			saved = 0;
+	}
+	b43_radio_write16(dev, 0x007B, saved);
+
+	if (phy->rev >= 6) {
+		b43_phy_write(dev, 0x002E, backup[12]);
+		b43_phy_write(dev, 0x002F, backup[13]);
+		b43_phy_write(dev, 0x080F, backup[14]);
+		b43_phy_write(dev, 0x0810, backup[15]);
+	}
+	if (phy->rev != 1) {	/* Not in specs, but needed to prevent PPC machine check */
+		b43_phy_write(dev, 0x0814, backup[3]);
+		b43_phy_write(dev, 0x0815, backup[4]);
+	}
+	b43_phy_write(dev, 0x005A, backup[5]);
+	b43_phy_write(dev, 0x0059, backup[6]);
+	b43_phy_write(dev, 0x0058, backup[7]);
+	b43_phy_write(dev, 0x000A, backup[8]);
+	b43_phy_write(dev, 0x0003, backup[9]);
+	b43_radio_write16(dev, 0x0043, backup[11]);
+	b43_radio_write16(dev, 0x007A, backup[10]);
+	b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) | 0x1 | 0x2);
+	b43_phy_set(dev, 0x0429, 0x8000);
+	b43_set_original_gains(dev);
+	if (phy->rev >= 6) {
+		b43_phy_write(dev, 0x0801, backup[16]);
+		b43_phy_write(dev, 0x0060, backup[17]);
+		b43_phy_write(dev, 0x0014, backup[18]);
+		b43_phy_write(dev, 0x0478, backup[19]);
+	}
+	b43_phy_write(dev, 0x0001, backup[0]);
+	b43_phy_write(dev, 0x0812, backup[2]);
+	b43_phy_write(dev, 0x0811, backup[1]);
+}
+
+static void b43_calc_nrssi_slope(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	u16 backup[18] = { 0 };
+	u16 tmp;
+	s16 nrssi0, nrssi1;
+
+	B43_WARN_ON(phy->type != B43_PHYTYPE_G);
+
+	if (phy->radio_rev >= 9)
+		return;
+	if (phy->radio_rev == 8)
+		b43_calc_nrssi_offset(dev);
+
+	b43_phy_mask(dev, B43_PHY_G_CRS, 0x7FFF);
+	b43_phy_mask(dev, 0x0802, 0xFFFC);
+	backup[7] = b43_read16(dev, 0x03E2);
+	b43_write16(dev, 0x03E2, b43_read16(dev, 0x03E2) | 0x8000);
+	backup[0] = b43_radio_read16(dev, 0x007A);
+	backup[1] = b43_radio_read16(dev, 0x0052);
+	backup[2] = b43_radio_read16(dev, 0x0043);
+	backup[3] = b43_phy_read(dev, 0x0015);
+	backup[4] = b43_phy_read(dev, 0x005A);
+	backup[5] = b43_phy_read(dev, 0x0059);
+	backup[6] = b43_phy_read(dev, 0x0058);
+	backup[8] = b43_read16(dev, 0x03E6);
+	backup[9] = b43_read16(dev, B43_MMIO_CHANNEL_EXT);
+	if (phy->rev >= 3) {
+		backup[10] = b43_phy_read(dev, 0x002E);
+		backup[11] = b43_phy_read(dev, 0x002F);
+		backup[12] = b43_phy_read(dev, 0x080F);
+		backup[13] = b43_phy_read(dev, B43_PHY_G_LO_CONTROL);
+		backup[14] = b43_phy_read(dev, 0x0801);
+		backup[15] = b43_phy_read(dev, 0x0060);
+		backup[16] = b43_phy_read(dev, 0x0014);
+		backup[17] = b43_phy_read(dev, 0x0478);
+		b43_phy_write(dev, 0x002E, 0);
+		b43_phy_write(dev, B43_PHY_G_LO_CONTROL, 0);
+		switch (phy->rev) {
+		case 4:
+		case 6:
+		case 7:
+			b43_phy_set(dev, 0x0478, 0x0100);
+			b43_phy_set(dev, 0x0801, 0x0040);
+			break;
+		case 3:
+		case 5:
+			b43_phy_mask(dev, 0x0801, 0xFFBF);
+			break;
+		}
+		b43_phy_set(dev, 0x0060, 0x0040);
+		b43_phy_set(dev, 0x0014, 0x0200);
+	}
+	b43_radio_set(dev, 0x007A, 0x0070);
+	b43_set_all_gains(dev, 0, 8, 0);
+	b43_radio_mask(dev, 0x007A, 0x00F7);
+	if (phy->rev >= 2) {
+		b43_phy_maskset(dev, 0x0811, 0xFFCF, 0x0030);
+		b43_phy_maskset(dev, 0x0812, 0xFFCF, 0x0010);
+	}
+	b43_radio_set(dev, 0x007A, 0x0080);
+	udelay(20);
+
+	nrssi0 = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F);
+	if (nrssi0 >= 0x0020)
+		nrssi0 -= 0x0040;
+
+	b43_radio_mask(dev, 0x007A, 0x007F);
+	if (phy->rev >= 2) {
+		b43_phy_maskset(dev, 0x0003, 0xFF9F, 0x0040);
+	}
+
+	b43_write16(dev, B43_MMIO_CHANNEL_EXT,
+		    b43_read16(dev, B43_MMIO_CHANNEL_EXT)
+		    | 0x2000);
+	b43_radio_set(dev, 0x007A, 0x000F);
+	b43_phy_write(dev, 0x0015, 0xF330);
+	if (phy->rev >= 2) {
+		b43_phy_maskset(dev, 0x0812, 0xFFCF, 0x0020);
+		b43_phy_maskset(dev, 0x0811, 0xFFCF, 0x0020);
+	}
+
+	b43_set_all_gains(dev, 3, 0, 1);
+	if (phy->radio_rev == 8) {
+		b43_radio_write16(dev, 0x0043, 0x001F);
+	} else {
+		tmp = b43_radio_read16(dev, 0x0052) & 0xFF0F;
+		b43_radio_write16(dev, 0x0052, tmp | 0x0060);
+		tmp = b43_radio_read16(dev, 0x0043) & 0xFFF0;
+		b43_radio_write16(dev, 0x0043, tmp | 0x0009);
+	}
+	b43_phy_write(dev, 0x005A, 0x0480);
+	b43_phy_write(dev, 0x0059, 0x0810);
+	b43_phy_write(dev, 0x0058, 0x000D);
+	udelay(20);
+	nrssi1 = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F);
+	if (nrssi1 >= 0x0020)
+		nrssi1 -= 0x0040;
+	if (nrssi0 == nrssi1)
+		gphy->nrssislope = 0x00010000;
+	else
+		gphy->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
+	if (nrssi0 >= -4) {
+		gphy->nrssi[0] = nrssi1;
+		gphy->nrssi[1] = nrssi0;
+	}
+	if (phy->rev >= 3) {
+		b43_phy_write(dev, 0x002E, backup[10]);
+		b43_phy_write(dev, 0x002F, backup[11]);
+		b43_phy_write(dev, 0x080F, backup[12]);
+		b43_phy_write(dev, B43_PHY_G_LO_CONTROL, backup[13]);
+	}
+	if (phy->rev >= 2) {
+		b43_phy_mask(dev, 0x0812, 0xFFCF);
+		b43_phy_mask(dev, 0x0811, 0xFFCF);
+	}
+
+	b43_radio_write16(dev, 0x007A, backup[0]);
+	b43_radio_write16(dev, 0x0052, backup[1]);
+	b43_radio_write16(dev, 0x0043, backup[2]);
+	b43_write16(dev, 0x03E2, backup[7]);
+	b43_write16(dev, 0x03E6, backup[8]);
+	b43_write16(dev, B43_MMIO_CHANNEL_EXT, backup[9]);
+	b43_phy_write(dev, 0x0015, backup[3]);
+	b43_phy_write(dev, 0x005A, backup[4]);
+	b43_phy_write(dev, 0x0059, backup[5]);
+	b43_phy_write(dev, 0x0058, backup[6]);
+	b43_synth_pu_workaround(dev, phy->channel);
+	b43_phy_set(dev, 0x0802, (0x0001 | 0x0002));
+	b43_set_original_gains(dev);
+	b43_phy_set(dev, B43_PHY_G_CRS, 0x8000);
+	if (phy->rev >= 3) {
+		b43_phy_write(dev, 0x0801, backup[14]);
+		b43_phy_write(dev, 0x0060, backup[15]);
+		b43_phy_write(dev, 0x0014, backup[16]);
+		b43_phy_write(dev, 0x0478, backup[17]);
+	}
+	b43_nrssi_mem_update(dev);
+	b43_calc_nrssi_threshold(dev);
+}
+
+static void b43_calc_nrssi_threshold(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	s32 a, b;
+	s16 tmp16;
+	u16 tmp_u16;
+
+	B43_WARN_ON(phy->type != B43_PHYTYPE_G);
+
+	if (!phy->gmode ||
+	    !(dev->dev->bus_sprom->boardflags_lo & B43_BFL_RSSI)) {
+		tmp16 = b43_nrssi_hw_read(dev, 0x20);
+		if (tmp16 >= 0x20)
+			tmp16 -= 0x40;
+		if (tmp16 < 3) {
+			b43_phy_maskset(dev, 0x048A, 0xF000, 0x09EB);
+		} else {
+			b43_phy_maskset(dev, 0x048A, 0xF000, 0x0AED);
+		}
+	} else {
+		if (gphy->interfmode == B43_INTERFMODE_NONWLAN) {
+			a = 0xE;
+			b = 0xA;
+		} else if (!gphy->aci_wlan_automatic && gphy->aci_enable) {
+			a = 0x13;
+			b = 0x12;
+		} else {
+			a = 0xE;
+			b = 0x11;
+		}
+
+		a = a * (gphy->nrssi[1] - gphy->nrssi[0]);
+		a += (gphy->nrssi[0] << 6);
+		if (a < 32)
+			a += 31;
+		else
+			a += 32;
+		a = a >> 6;
+		a = clamp_val(a, -31, 31);
+
+		b = b * (gphy->nrssi[1] - gphy->nrssi[0]);
+		b += (gphy->nrssi[0] << 6);
+		if (b < 32)
+			b += 31;
+		else
+			b += 32;
+		b = b >> 6;
+		b = clamp_val(b, -31, 31);
+
+		tmp_u16 = b43_phy_read(dev, 0x048A) & 0xF000;
+		tmp_u16 |= ((u32) b & 0x0000003F);
+		tmp_u16 |= (((u32) a & 0x0000003F) << 6);
+		b43_phy_write(dev, 0x048A, tmp_u16);
+	}
+}
+
+/* Stack implementation to save/restore values from the
+ * interference mitigation code.
+ * It is save to restore values in random order.
+ */
+static void _stack_save(u32 *_stackptr, size_t *stackidx,
+			u8 id, u16 offset, u16 value)
+{
+	u32 *stackptr = &(_stackptr[*stackidx]);
+
+	B43_WARN_ON(offset & 0xF000);
+	B43_WARN_ON(id & 0xF0);
+	*stackptr = offset;
+	*stackptr |= ((u32) id) << 12;
+	*stackptr |= ((u32) value) << 16;
+	(*stackidx)++;
+	B43_WARN_ON(*stackidx >= B43_INTERFSTACK_SIZE);
+}
+
+static u16 _stack_restore(u32 *stackptr, u8 id, u16 offset)
+{
+	size_t i;
+
+	B43_WARN_ON(offset & 0xF000);
+	B43_WARN_ON(id & 0xF0);
+	for (i = 0; i < B43_INTERFSTACK_SIZE; i++, stackptr++) {
+		if ((*stackptr & 0x00000FFF) != offset)
+			continue;
+		if (((*stackptr & 0x0000F000) >> 12) != id)
+			continue;
+		return ((*stackptr & 0xFFFF0000) >> 16);
+	}
+	B43_WARN_ON(1);
+
+	return 0;
+}
+
+#define phy_stacksave(offset)					\
+	do {							\
+		_stack_save(stack, &stackidx, 0x1, (offset),	\
+			    b43_phy_read(dev, (offset)));	\
+	} while (0)
+#define phy_stackrestore(offset)				\
+	do {							\
+		b43_phy_write(dev, (offset),		\
+				  _stack_restore(stack, 0x1,	\
+						 (offset)));	\
+	} while (0)
+#define radio_stacksave(offset)						\
+	do {								\
+		_stack_save(stack, &stackidx, 0x2, (offset),		\
+			    b43_radio_read16(dev, (offset)));	\
+	} while (0)
+#define radio_stackrestore(offset)					\
+	do {								\
+		b43_radio_write16(dev, (offset),			\
+				      _stack_restore(stack, 0x2,	\
+						     (offset)));	\
+	} while (0)
+#define ofdmtab_stacksave(table, offset)			\
+	do {							\
+		_stack_save(stack, &stackidx, 0x3, (offset)|(table),	\
+			    b43_ofdmtab_read16(dev, (table), (offset)));	\
+	} while (0)
+#define ofdmtab_stackrestore(table, offset)			\
+	do {							\
+		b43_ofdmtab_write16(dev, (table),	(offset),	\
+				  _stack_restore(stack, 0x3,	\
+						 (offset)|(table)));	\
+	} while (0)
+
+static void
+b43_radio_interference_mitigation_enable(struct b43_wldev *dev, int mode)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	u16 tmp, flipped;
+	size_t stackidx = 0;
+	u32 *stack = gphy->interfstack;
+
+	switch (mode) {
+	case B43_INTERFMODE_NONWLAN:
+		if (phy->rev != 1) {
+			b43_phy_set(dev, 0x042B, 0x0800);
+			b43_phy_mask(dev, B43_PHY_G_CRS, ~0x4000);
+			break;
+		}
+		radio_stacksave(0x0078);
+		tmp = (b43_radio_read16(dev, 0x0078) & 0x001E);
+		B43_WARN_ON(tmp > 15);
+		flipped = bitrev4(tmp);
+		if (flipped < 10 && flipped >= 8)
+			flipped = 7;
+		else if (flipped >= 10)
+			flipped -= 3;
+		flipped = (bitrev4(flipped) << 1) | 0x0020;
+		b43_radio_write16(dev, 0x0078, flipped);
+
+		b43_calc_nrssi_threshold(dev);
+
+		phy_stacksave(0x0406);
+		b43_phy_write(dev, 0x0406, 0x7E28);
+
+		b43_phy_set(dev, 0x042B, 0x0800);
+		b43_phy_set(dev, B43_PHY_RADIO_BITFIELD, 0x1000);
+
+		phy_stacksave(0x04A0);
+		b43_phy_maskset(dev, 0x04A0, 0xC0C0, 0x0008);
+		phy_stacksave(0x04A1);
+		b43_phy_maskset(dev, 0x04A1, 0xC0C0, 0x0605);
+		phy_stacksave(0x04A2);
+		b43_phy_maskset(dev, 0x04A2, 0xC0C0, 0x0204);
+		phy_stacksave(0x04A8);
+		b43_phy_maskset(dev, 0x04A8, 0xC0C0, 0x0803);
+		phy_stacksave(0x04AB);
+		b43_phy_maskset(dev, 0x04AB, 0xC0C0, 0x0605);
+
+		phy_stacksave(0x04A7);
+		b43_phy_write(dev, 0x04A7, 0x0002);
+		phy_stacksave(0x04A3);
+		b43_phy_write(dev, 0x04A3, 0x287A);
+		phy_stacksave(0x04A9);
+		b43_phy_write(dev, 0x04A9, 0x2027);
+		phy_stacksave(0x0493);
+		b43_phy_write(dev, 0x0493, 0x32F5);
+		phy_stacksave(0x04AA);
+		b43_phy_write(dev, 0x04AA, 0x2027);
+		phy_stacksave(0x04AC);
+		b43_phy_write(dev, 0x04AC, 0x32F5);
+		break;
+	case B43_INTERFMODE_MANUALWLAN:
+		if (b43_phy_read(dev, 0x0033) & 0x0800)
+			break;
+
+		gphy->aci_enable = true;
+
+		phy_stacksave(B43_PHY_RADIO_BITFIELD);
+		phy_stacksave(B43_PHY_G_CRS);
+		if (phy->rev < 2) {
+			phy_stacksave(0x0406);
+		} else {
+			phy_stacksave(0x04C0);
+			phy_stacksave(0x04C1);
+		}
+		phy_stacksave(0x0033);
+		phy_stacksave(0x04A7);
+		phy_stacksave(0x04A3);
+		phy_stacksave(0x04A9);
+		phy_stacksave(0x04AA);
+		phy_stacksave(0x04AC);
+		phy_stacksave(0x0493);
+		phy_stacksave(0x04A1);
+		phy_stacksave(0x04A0);
+		phy_stacksave(0x04A2);
+		phy_stacksave(0x048A);
+		phy_stacksave(0x04A8);
+		phy_stacksave(0x04AB);
+		if (phy->rev == 2) {
+			phy_stacksave(0x04AD);
+			phy_stacksave(0x04AE);
+		} else if (phy->rev >= 3) {
+			phy_stacksave(0x04AD);
+			phy_stacksave(0x0415);
+			phy_stacksave(0x0416);
+			phy_stacksave(0x0417);
+			ofdmtab_stacksave(0x1A00, 0x2);
+			ofdmtab_stacksave(0x1A00, 0x3);
+		}
+		phy_stacksave(0x042B);
+		phy_stacksave(0x048C);
+
+		b43_phy_mask(dev, B43_PHY_RADIO_BITFIELD, ~0x1000);
+		b43_phy_maskset(dev, B43_PHY_G_CRS, 0xFFFC, 0x0002);
+
+		b43_phy_write(dev, 0x0033, 0x0800);
+		b43_phy_write(dev, 0x04A3, 0x2027);
+		b43_phy_write(dev, 0x04A9, 0x1CA8);
+		b43_phy_write(dev, 0x0493, 0x287A);
+		b43_phy_write(dev, 0x04AA, 0x1CA8);
+		b43_phy_write(dev, 0x04AC, 0x287A);
+
+		b43_phy_maskset(dev, 0x04A0, 0xFFC0, 0x001A);
+		b43_phy_write(dev, 0x04A7, 0x000D);
+
+		if (phy->rev < 2) {
+			b43_phy_write(dev, 0x0406, 0xFF0D);
+		} else if (phy->rev == 2) {
+			b43_phy_write(dev, 0x04C0, 0xFFFF);
+			b43_phy_write(dev, 0x04C1, 0x00A9);
+		} else {
+			b43_phy_write(dev, 0x04C0, 0x00C1);
+			b43_phy_write(dev, 0x04C1, 0x0059);
+		}
+
+		b43_phy_maskset(dev, 0x04A1, 0xC0FF, 0x1800);
+		b43_phy_maskset(dev, 0x04A1, 0xFFC0, 0x0015);
+		b43_phy_maskset(dev, 0x04A8, 0xCFFF, 0x1000);
+		b43_phy_maskset(dev, 0x04A8, 0xF0FF, 0x0A00);
+		b43_phy_maskset(dev, 0x04AB, 0xCFFF, 0x1000);
+		b43_phy_maskset(dev, 0x04AB, 0xF0FF, 0x0800);
+		b43_phy_maskset(dev, 0x04AB, 0xFFCF, 0x0010);
+		b43_phy_maskset(dev, 0x04AB, 0xFFF0, 0x0005);
+		b43_phy_maskset(dev, 0x04A8, 0xFFCF, 0x0010);
+		b43_phy_maskset(dev, 0x04A8, 0xFFF0, 0x0006);
+		b43_phy_maskset(dev, 0x04A2, 0xF0FF, 0x0800);
+		b43_phy_maskset(dev, 0x04A0, 0xF0FF, 0x0500);
+		b43_phy_maskset(dev, 0x04A2, 0xFFF0, 0x000B);
+
+		if (phy->rev >= 3) {
+			b43_phy_mask(dev, 0x048A, 0x7FFF);
+			b43_phy_maskset(dev, 0x0415, 0x8000, 0x36D8);
+			b43_phy_maskset(dev, 0x0416, 0x8000, 0x36D8);
+			b43_phy_maskset(dev, 0x0417, 0xFE00, 0x016D);
+		} else {
+			b43_phy_set(dev, 0x048A, 0x1000);
+			b43_phy_maskset(dev, 0x048A, 0x9FFF, 0x2000);
+			b43_hf_write(dev, b43_hf_read(dev) | B43_HF_ACIW);
+		}
+		if (phy->rev >= 2) {
+			b43_phy_set(dev, 0x042B, 0x0800);
+		}
+		b43_phy_maskset(dev, 0x048C, 0xF0FF, 0x0200);
+		if (phy->rev == 2) {
+			b43_phy_maskset(dev, 0x04AE, 0xFF00, 0x007F);
+			b43_phy_maskset(dev, 0x04AD, 0x00FF, 0x1300);
+		} else if (phy->rev >= 6) {
+			b43_ofdmtab_write16(dev, 0x1A00, 0x3, 0x007F);
+			b43_ofdmtab_write16(dev, 0x1A00, 0x2, 0x007F);
+			b43_phy_mask(dev, 0x04AD, 0x00FF);
+		}
+		b43_calc_nrssi_slope(dev);
+		break;
+	default:
+		B43_WARN_ON(1);
+	}
+}
+
+static void
+b43_radio_interference_mitigation_disable(struct b43_wldev *dev, int mode)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	u32 *stack = gphy->interfstack;
+
+	switch (mode) {
+	case B43_INTERFMODE_NONWLAN:
+		if (phy->rev != 1) {
+			b43_phy_mask(dev, 0x042B, ~0x0800);
+			b43_phy_set(dev, B43_PHY_G_CRS, 0x4000);
+			break;
+		}
+		radio_stackrestore(0x0078);
+		b43_calc_nrssi_threshold(dev);
+		phy_stackrestore(0x0406);
+		b43_phy_mask(dev, 0x042B, ~0x0800);
+		if (!dev->bad_frames_preempt) {
+			b43_phy_mask(dev, B43_PHY_RADIO_BITFIELD, ~(1 << 11));
+		}
+		b43_phy_set(dev, B43_PHY_G_CRS, 0x4000);
+		phy_stackrestore(0x04A0);
+		phy_stackrestore(0x04A1);
+		phy_stackrestore(0x04A2);
+		phy_stackrestore(0x04A8);
+		phy_stackrestore(0x04AB);
+		phy_stackrestore(0x04A7);
+		phy_stackrestore(0x04A3);
+		phy_stackrestore(0x04A9);
+		phy_stackrestore(0x0493);
+		phy_stackrestore(0x04AA);
+		phy_stackrestore(0x04AC);
+		break;
+	case B43_INTERFMODE_MANUALWLAN:
+		if (!(b43_phy_read(dev, 0x0033) & 0x0800))
+			break;
+
+		gphy->aci_enable = false;
+
+		phy_stackrestore(B43_PHY_RADIO_BITFIELD);
+		phy_stackrestore(B43_PHY_G_CRS);
+		phy_stackrestore(0x0033);
+		phy_stackrestore(0x04A3);
+		phy_stackrestore(0x04A9);
+		phy_stackrestore(0x0493);
+		phy_stackrestore(0x04AA);
+		phy_stackrestore(0x04AC);
+		phy_stackrestore(0x04A0);
+		phy_stackrestore(0x04A7);
+		if (phy->rev >= 2) {
+			phy_stackrestore(0x04C0);
+			phy_stackrestore(0x04C1);
+		} else
+			phy_stackrestore(0x0406);
+		phy_stackrestore(0x04A1);
+		phy_stackrestore(0x04AB);
+		phy_stackrestore(0x04A8);
+		if (phy->rev == 2) {
+			phy_stackrestore(0x04AD);
+			phy_stackrestore(0x04AE);
+		} else if (phy->rev >= 3) {
+			phy_stackrestore(0x04AD);
+			phy_stackrestore(0x0415);
+			phy_stackrestore(0x0416);
+			phy_stackrestore(0x0417);
+			ofdmtab_stackrestore(0x1A00, 0x2);
+			ofdmtab_stackrestore(0x1A00, 0x3);
+		}
+		phy_stackrestore(0x04A2);
+		phy_stackrestore(0x048A);
+		phy_stackrestore(0x042B);
+		phy_stackrestore(0x048C);
+		b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_ACIW);
+		b43_calc_nrssi_slope(dev);
+		break;
+	default:
+		B43_WARN_ON(1);
+	}
+}
+
+#undef phy_stacksave
+#undef phy_stackrestore
+#undef radio_stacksave
+#undef radio_stackrestore
+#undef ofdmtab_stacksave
+#undef ofdmtab_stackrestore
+
+static u16 b43_radio_core_calibration_value(struct b43_wldev *dev)
+{
+	u16 reg, index, ret;
+
+	static const u8 rcc_table[] = {
+		0x02, 0x03, 0x01, 0x0F,
+		0x06, 0x07, 0x05, 0x0F,
+		0x0A, 0x0B, 0x09, 0x0F,
+		0x0E, 0x0F, 0x0D, 0x0F,
+	};
+
+	reg = b43_radio_read16(dev, 0x60);
+	index = (reg & 0x001E) >> 1;
+	ret = rcc_table[index] << 1;
+	ret |= (reg & 0x0001);
+	ret |= 0x0020;
+
+	return ret;
+}
+
+#define LPD(L, P, D)	(((L) << 2) | ((P) << 1) | ((D) << 0))
+static u16 radio2050_rfover_val(struct b43_wldev *dev,
+				u16 phy_register, unsigned int lpd)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+
+	if (!phy->gmode)
+		return 0;
+
+	if (has_loopback_gain(phy)) {
+		int max_lb_gain = gphy->max_lb_gain;
+		u16 extlna;
+		u16 i;
+
+		if (phy->radio_rev == 8)
+			max_lb_gain += 0x3E;
+		else
+			max_lb_gain += 0x26;
+		if (max_lb_gain >= 0x46) {
+			extlna = 0x3000;
+			max_lb_gain -= 0x46;
+		} else if (max_lb_gain >= 0x3A) {
+			extlna = 0x1000;
+			max_lb_gain -= 0x3A;
+		} else if (max_lb_gain >= 0x2E) {
+			extlna = 0x2000;
+			max_lb_gain -= 0x2E;
+		} else {
+			extlna = 0;
+			max_lb_gain -= 0x10;
+		}
+
+		for (i = 0; i < 16; i++) {
+			max_lb_gain -= (i * 6);
+			if (max_lb_gain < 6)
+				break;
+		}
+
+		if ((phy->rev < 7) ||
+		    !(sprom->boardflags_lo & B43_BFL_EXTLNA)) {
+			if (phy_register == B43_PHY_RFOVER) {
+				return 0x1B3;
+			} else if (phy_register == B43_PHY_RFOVERVAL) {
+				extlna |= (i << 8);
+				switch (lpd) {
+				case LPD(0, 1, 1):
+					return 0x0F92;
+				case LPD(0, 0, 1):
+				case LPD(1, 0, 1):
+					return (0x0092 | extlna);
+				case LPD(1, 0, 0):
+					return (0x0093 | extlna);
+				}
+				B43_WARN_ON(1);
+			}
+			B43_WARN_ON(1);
+		} else {
+			if (phy_register == B43_PHY_RFOVER) {
+				return 0x9B3;
+			} else if (phy_register == B43_PHY_RFOVERVAL) {
+				if (extlna)
+					extlna |= 0x8000;
+				extlna |= (i << 8);
+				switch (lpd) {
+				case LPD(0, 1, 1):
+					return 0x8F92;
+				case LPD(0, 0, 1):
+					return (0x8092 | extlna);
+				case LPD(1, 0, 1):
+					return (0x2092 | extlna);
+				case LPD(1, 0, 0):
+					return (0x2093 | extlna);
+				}
+				B43_WARN_ON(1);
+			}
+			B43_WARN_ON(1);
+		}
+	} else {
+		if ((phy->rev < 7) ||
+		    !(sprom->boardflags_lo & B43_BFL_EXTLNA)) {
+			if (phy_register == B43_PHY_RFOVER) {
+				return 0x1B3;
+			} else if (phy_register == B43_PHY_RFOVERVAL) {
+				switch (lpd) {
+				case LPD(0, 1, 1):
+					return 0x0FB2;
+				case LPD(0, 0, 1):
+					return 0x00B2;
+				case LPD(1, 0, 1):
+					return 0x30B2;
+				case LPD(1, 0, 0):
+					return 0x30B3;
+				}
+				B43_WARN_ON(1);
+			}
+			B43_WARN_ON(1);
+		} else {
+			if (phy_register == B43_PHY_RFOVER) {
+				return 0x9B3;
+			} else if (phy_register == B43_PHY_RFOVERVAL) {
+				switch (lpd) {
+				case LPD(0, 1, 1):
+					return 0x8FB2;
+				case LPD(0, 0, 1):
+					return 0x80B2;
+				case LPD(1, 0, 1):
+					return 0x20B2;
+				case LPD(1, 0, 0):
+					return 0x20B3;
+				}
+				B43_WARN_ON(1);
+			}
+			B43_WARN_ON(1);
+		}
+	}
+	return 0;
+}
+
+struct init2050_saved_values {
+	/* Core registers */
+	u16 reg_3EC;
+	u16 reg_3E6;
+	u16 reg_3F4;
+	/* Radio registers */
+	u16 radio_43;
+	u16 radio_51;
+	u16 radio_52;
+	/* PHY registers */
+	u16 phy_pgactl;
+	u16 phy_cck_5A;
+	u16 phy_cck_59;
+	u16 phy_cck_58;
+	u16 phy_cck_30;
+	u16 phy_rfover;
+	u16 phy_rfoverval;
+	u16 phy_analogover;
+	u16 phy_analogoverval;
+	u16 phy_crs0;
+	u16 phy_classctl;
+	u16 phy_lo_mask;
+	u16 phy_lo_ctl;
+	u16 phy_syncctl;
+};
+
+static u16 b43_radio_init2050(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct init2050_saved_values sav;
+	u16 rcc;
+	u16 radio78;
+	u16 ret;
+	u16 i, j;
+	u32 tmp1 = 0, tmp2 = 0;
+
+	memset(&sav, 0, sizeof(sav));	/* get rid of "may be used uninitialized..." */
+
+	sav.radio_43 = b43_radio_read16(dev, 0x43);
+	sav.radio_51 = b43_radio_read16(dev, 0x51);
+	sav.radio_52 = b43_radio_read16(dev, 0x52);
+	sav.phy_pgactl = b43_phy_read(dev, B43_PHY_PGACTL);
+	sav.phy_cck_5A = b43_phy_read(dev, B43_PHY_CCK(0x5A));
+	sav.phy_cck_59 = b43_phy_read(dev, B43_PHY_CCK(0x59));
+	sav.phy_cck_58 = b43_phy_read(dev, B43_PHY_CCK(0x58));
+
+	if (phy->type == B43_PHYTYPE_B) {
+		sav.phy_cck_30 = b43_phy_read(dev, B43_PHY_CCK(0x30));
+		sav.reg_3EC = b43_read16(dev, 0x3EC);
+
+		b43_phy_write(dev, B43_PHY_CCK(0x30), 0xFF);
+		b43_write16(dev, 0x3EC, 0x3F3F);
+	} else if (phy->gmode || phy->rev >= 2) {
+		sav.phy_rfover = b43_phy_read(dev, B43_PHY_RFOVER);
+		sav.phy_rfoverval = b43_phy_read(dev, B43_PHY_RFOVERVAL);
+		sav.phy_analogover = b43_phy_read(dev, B43_PHY_ANALOGOVER);
+		sav.phy_analogoverval =
+		    b43_phy_read(dev, B43_PHY_ANALOGOVERVAL);
+		sav.phy_crs0 = b43_phy_read(dev, B43_PHY_CRS0);
+		sav.phy_classctl = b43_phy_read(dev, B43_PHY_CLASSCTL);
+
+		b43_phy_set(dev, B43_PHY_ANALOGOVER, 0x0003);
+		b43_phy_mask(dev, B43_PHY_ANALOGOVERVAL, 0xFFFC);
+		b43_phy_mask(dev, B43_PHY_CRS0, 0x7FFF);
+		b43_phy_mask(dev, B43_PHY_CLASSCTL, 0xFFFC);
+		if (has_loopback_gain(phy)) {
+			sav.phy_lo_mask = b43_phy_read(dev, B43_PHY_LO_MASK);
+			sav.phy_lo_ctl = b43_phy_read(dev, B43_PHY_LO_CTL);
+
+			if (phy->rev >= 3)
+				b43_phy_write(dev, B43_PHY_LO_MASK, 0xC020);
+			else
+				b43_phy_write(dev, B43_PHY_LO_MASK, 0x8020);
+			b43_phy_write(dev, B43_PHY_LO_CTL, 0);
+		}
+
+		b43_phy_write(dev, B43_PHY_RFOVERVAL,
+			      radio2050_rfover_val(dev, B43_PHY_RFOVERVAL,
+						   LPD(0, 1, 1)));
+		b43_phy_write(dev, B43_PHY_RFOVER,
+			      radio2050_rfover_val(dev, B43_PHY_RFOVER, 0));
+	}
+	b43_write16(dev, 0x3E2, b43_read16(dev, 0x3E2) | 0x8000);
+
+	sav.phy_syncctl = b43_phy_read(dev, B43_PHY_SYNCCTL);
+	b43_phy_mask(dev, B43_PHY_SYNCCTL, 0xFF7F);
+	sav.reg_3E6 = b43_read16(dev, 0x3E6);
+	sav.reg_3F4 = b43_read16(dev, 0x3F4);
+
+	if (phy->analog == 0) {
+		b43_write16(dev, 0x03E6, 0x0122);
+	} else {
+		if (phy->analog >= 2) {
+			b43_phy_maskset(dev, B43_PHY_CCK(0x03), 0xFFBF, 0x40);
+		}
+		b43_write16(dev, B43_MMIO_CHANNEL_EXT,
+			    (b43_read16(dev, B43_MMIO_CHANNEL_EXT) | 0x2000));
+	}
+
+	rcc = b43_radio_core_calibration_value(dev);
+
+	if (phy->type == B43_PHYTYPE_B)
+		b43_radio_write16(dev, 0x78, 0x26);
+	if (phy->gmode || phy->rev >= 2) {
+		b43_phy_write(dev, B43_PHY_RFOVERVAL,
+			      radio2050_rfover_val(dev, B43_PHY_RFOVERVAL,
+						   LPD(0, 1, 1)));
+	}
+	b43_phy_write(dev, B43_PHY_PGACTL, 0xBFAF);
+	b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x1403);
+	if (phy->gmode || phy->rev >= 2) {
+		b43_phy_write(dev, B43_PHY_RFOVERVAL,
+			      radio2050_rfover_val(dev, B43_PHY_RFOVERVAL,
+						   LPD(0, 0, 1)));
+	}
+	b43_phy_write(dev, B43_PHY_PGACTL, 0xBFA0);
+	b43_radio_set(dev, 0x51, 0x0004);
+	if (phy->radio_rev == 8) {
+		b43_radio_write16(dev, 0x43, 0x1F);
+	} else {
+		b43_radio_write16(dev, 0x52, 0);
+		b43_radio_maskset(dev, 0x43, 0xFFF0, 0x0009);
+	}
+	b43_phy_write(dev, B43_PHY_CCK(0x58), 0);
+
+	for (i = 0; i < 16; i++) {
+		b43_phy_write(dev, B43_PHY_CCK(0x5A), 0x0480);
+		b43_phy_write(dev, B43_PHY_CCK(0x59), 0xC810);
+		b43_phy_write(dev, B43_PHY_CCK(0x58), 0x000D);
+		if (phy->gmode || phy->rev >= 2) {
+			b43_phy_write(dev, B43_PHY_RFOVERVAL,
+				      radio2050_rfover_val(dev,
+							   B43_PHY_RFOVERVAL,
+							   LPD(1, 0, 1)));
+		}
+		b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0);
+		udelay(10);
+		if (phy->gmode || phy->rev >= 2) {
+			b43_phy_write(dev, B43_PHY_RFOVERVAL,
+				      radio2050_rfover_val(dev,
+							   B43_PHY_RFOVERVAL,
+							   LPD(1, 0, 1)));
+		}
+		b43_phy_write(dev, B43_PHY_PGACTL, 0xEFB0);
+		udelay(10);
+		if (phy->gmode || phy->rev >= 2) {
+			b43_phy_write(dev, B43_PHY_RFOVERVAL,
+				      radio2050_rfover_val(dev,
+							   B43_PHY_RFOVERVAL,
+							   LPD(1, 0, 0)));
+		}
+		b43_phy_write(dev, B43_PHY_PGACTL, 0xFFF0);
+		udelay(20);
+		tmp1 += b43_phy_read(dev, B43_PHY_LO_LEAKAGE);
+		b43_phy_write(dev, B43_PHY_CCK(0x58), 0);
+		if (phy->gmode || phy->rev >= 2) {
+			b43_phy_write(dev, B43_PHY_RFOVERVAL,
+				      radio2050_rfover_val(dev,
+							   B43_PHY_RFOVERVAL,
+							   LPD(1, 0, 1)));
+		}
+		b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0);
+	}
+	udelay(10);
+
+	b43_phy_write(dev, B43_PHY_CCK(0x58), 0);
+	tmp1++;
+	tmp1 >>= 9;
+
+	for (i = 0; i < 16; i++) {
+		radio78 = (bitrev4(i) << 1) | 0x0020;
+		b43_radio_write16(dev, 0x78, radio78);
+		udelay(10);
+		for (j = 0; j < 16; j++) {
+			b43_phy_write(dev, B43_PHY_CCK(0x5A), 0x0D80);
+			b43_phy_write(dev, B43_PHY_CCK(0x59), 0xC810);
+			b43_phy_write(dev, B43_PHY_CCK(0x58), 0x000D);
+			if (phy->gmode || phy->rev >= 2) {
+				b43_phy_write(dev, B43_PHY_RFOVERVAL,
+					      radio2050_rfover_val(dev,
+								   B43_PHY_RFOVERVAL,
+								   LPD(1, 0,
+								       1)));
+			}
+			b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0);
+			udelay(10);
+			if (phy->gmode || phy->rev >= 2) {
+				b43_phy_write(dev, B43_PHY_RFOVERVAL,
+					      radio2050_rfover_val(dev,
+								   B43_PHY_RFOVERVAL,
+								   LPD(1, 0,
+								       1)));
+			}
+			b43_phy_write(dev, B43_PHY_PGACTL, 0xEFB0);
+			udelay(10);
+			if (phy->gmode || phy->rev >= 2) {
+				b43_phy_write(dev, B43_PHY_RFOVERVAL,
+					      radio2050_rfover_val(dev,
+								   B43_PHY_RFOVERVAL,
+								   LPD(1, 0,
+								       0)));
+			}
+			b43_phy_write(dev, B43_PHY_PGACTL, 0xFFF0);
+			udelay(10);
+			tmp2 += b43_phy_read(dev, B43_PHY_LO_LEAKAGE);
+			b43_phy_write(dev, B43_PHY_CCK(0x58), 0);
+			if (phy->gmode || phy->rev >= 2) {
+				b43_phy_write(dev, B43_PHY_RFOVERVAL,
+					      radio2050_rfover_val(dev,
+								   B43_PHY_RFOVERVAL,
+								   LPD(1, 0,
+								       1)));
+			}
+			b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0);
+		}
+		tmp2++;
+		tmp2 >>= 8;
+		if (tmp1 < tmp2)
+			break;
+	}
+
+	/* Restore the registers */
+	b43_phy_write(dev, B43_PHY_PGACTL, sav.phy_pgactl);
+	b43_radio_write16(dev, 0x51, sav.radio_51);
+	b43_radio_write16(dev, 0x52, sav.radio_52);
+	b43_radio_write16(dev, 0x43, sav.radio_43);
+	b43_phy_write(dev, B43_PHY_CCK(0x5A), sav.phy_cck_5A);
+	b43_phy_write(dev, B43_PHY_CCK(0x59), sav.phy_cck_59);
+	b43_phy_write(dev, B43_PHY_CCK(0x58), sav.phy_cck_58);
+	b43_write16(dev, 0x3E6, sav.reg_3E6);
+	if (phy->analog != 0)
+		b43_write16(dev, 0x3F4, sav.reg_3F4);
+	b43_phy_write(dev, B43_PHY_SYNCCTL, sav.phy_syncctl);
+	b43_synth_pu_workaround(dev, phy->channel);
+	if (phy->type == B43_PHYTYPE_B) {
+		b43_phy_write(dev, B43_PHY_CCK(0x30), sav.phy_cck_30);
+		b43_write16(dev, 0x3EC, sav.reg_3EC);
+	} else if (phy->gmode) {
+		b43_write16(dev, B43_MMIO_PHY_RADIO,
+			    b43_read16(dev, B43_MMIO_PHY_RADIO)
+			    & 0x7FFF);
+		b43_phy_write(dev, B43_PHY_RFOVER, sav.phy_rfover);
+		b43_phy_write(dev, B43_PHY_RFOVERVAL, sav.phy_rfoverval);
+		b43_phy_write(dev, B43_PHY_ANALOGOVER, sav.phy_analogover);
+		b43_phy_write(dev, B43_PHY_ANALOGOVERVAL,
+			      sav.phy_analogoverval);
+		b43_phy_write(dev, B43_PHY_CRS0, sav.phy_crs0);
+		b43_phy_write(dev, B43_PHY_CLASSCTL, sav.phy_classctl);
+		if (has_loopback_gain(phy)) {
+			b43_phy_write(dev, B43_PHY_LO_MASK, sav.phy_lo_mask);
+			b43_phy_write(dev, B43_PHY_LO_CTL, sav.phy_lo_ctl);
+		}
+	}
+	if (i > 15)
+		ret = radio78;
+	else
+		ret = rcc;
+
+	return ret;
+}
+
+static void b43_phy_initb5(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	u16 offset, value;
+	u8 old_channel;
+
+	if (phy->analog == 1) {
+		b43_radio_set(dev, 0x007A, 0x0050);
+	}
+	if ((dev->dev->board_vendor != SSB_BOARDVENDOR_BCM) &&
+	    (dev->dev->board_type != SSB_BOARD_BU4306)) {
+		value = 0x2120;
+		for (offset = 0x00A8; offset < 0x00C7; offset++) {
+			b43_phy_write(dev, offset, value);
+			value += 0x202;
+		}
+	}
+	b43_phy_maskset(dev, 0x0035, 0xF0FF, 0x0700);
+	if (phy->radio_ver == 0x2050)
+		b43_phy_write(dev, 0x0038, 0x0667);
+
+	if (phy->gmode || phy->rev >= 2) {
+		if (phy->radio_ver == 0x2050) {
+			b43_radio_set(dev, 0x007A, 0x0020);
+			b43_radio_set(dev, 0x0051, 0x0004);
+		}
+		b43_write16(dev, B43_MMIO_PHY_RADIO, 0x0000);
+
+		b43_phy_set(dev, 0x0802, 0x0100);
+		b43_phy_set(dev, 0x042B, 0x2000);
+
+		b43_phy_write(dev, 0x001C, 0x186A);
+
+		b43_phy_maskset(dev, 0x0013, 0x00FF, 0x1900);
+		b43_phy_maskset(dev, 0x0035, 0xFFC0, 0x0064);
+		b43_phy_maskset(dev, 0x005D, 0xFF80, 0x000A);
+	}
+
+	if (dev->bad_frames_preempt) {
+		b43_phy_set(dev, B43_PHY_RADIO_BITFIELD, (1 << 11));
+	}
+
+	if (phy->analog == 1) {
+		b43_phy_write(dev, 0x0026, 0xCE00);
+		b43_phy_write(dev, 0x0021, 0x3763);
+		b43_phy_write(dev, 0x0022, 0x1BC3);
+		b43_phy_write(dev, 0x0023, 0x06F9);
+		b43_phy_write(dev, 0x0024, 0x037E);
+	} else
+		b43_phy_write(dev, 0x0026, 0xCC00);
+	b43_phy_write(dev, 0x0030, 0x00C6);
+	b43_write16(dev, 0x03EC, 0x3F22);
+
+	if (phy->analog == 1)
+		b43_phy_write(dev, 0x0020, 0x3E1C);
+	else
+		b43_phy_write(dev, 0x0020, 0x301C);
+
+	if (phy->analog == 0)
+		b43_write16(dev, 0x03E4, 0x3000);
+
+	old_channel = phy->channel;
+	/* Force to channel 7, even if not supported. */
+	b43_gphy_channel_switch(dev, 7, 0);
+
+	if (phy->radio_ver != 0x2050) {
+		b43_radio_write16(dev, 0x0075, 0x0080);
+		b43_radio_write16(dev, 0x0079, 0x0081);
+	}
+
+	b43_radio_write16(dev, 0x0050, 0x0020);
+	b43_radio_write16(dev, 0x0050, 0x0023);
+
+	if (phy->radio_ver == 0x2050) {
+		b43_radio_write16(dev, 0x0050, 0x0020);
+		b43_radio_write16(dev, 0x005A, 0x0070);
+	}
+
+	b43_radio_write16(dev, 0x005B, 0x007B);
+	b43_radio_write16(dev, 0x005C, 0x00B0);
+
+	b43_radio_set(dev, 0x007A, 0x0007);
+
+	b43_gphy_channel_switch(dev, old_channel, 0);
+
+	b43_phy_write(dev, 0x0014, 0x0080);
+	b43_phy_write(dev, 0x0032, 0x00CA);
+	b43_phy_write(dev, 0x002A, 0x88A3);
+
+	b43_set_txpower_g(dev, &gphy->bbatt, &gphy->rfatt, gphy->tx_control);
+
+	if (phy->radio_ver == 0x2050)
+		b43_radio_write16(dev, 0x005D, 0x000D);
+
+	b43_write16(dev, 0x03E4, (b43_read16(dev, 0x03E4) & 0xFFC0) | 0x0004);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/Init/B6 */
+static void b43_phy_initb6(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	u16 offset, val;
+	u8 old_channel;
+
+	b43_phy_write(dev, 0x003E, 0x817A);
+	b43_radio_write16(dev, 0x007A,
+			  (b43_radio_read16(dev, 0x007A) | 0x0058));
+	if (phy->radio_rev == 4 || phy->radio_rev == 5) {
+		b43_radio_write16(dev, 0x51, 0x37);
+		b43_radio_write16(dev, 0x52, 0x70);
+		b43_radio_write16(dev, 0x53, 0xB3);
+		b43_radio_write16(dev, 0x54, 0x9B);
+		b43_radio_write16(dev, 0x5A, 0x88);
+		b43_radio_write16(dev, 0x5B, 0x88);
+		b43_radio_write16(dev, 0x5D, 0x88);
+		b43_radio_write16(dev, 0x5E, 0x88);
+		b43_radio_write16(dev, 0x7D, 0x88);
+		b43_hf_write(dev, b43_hf_read(dev)
+			     | B43_HF_TSSIRPSMW);
+	}
+	B43_WARN_ON(phy->radio_rev == 6 || phy->radio_rev == 7);	/* We had code for these revs here... */
+	if (phy->radio_rev == 8) {
+		b43_radio_write16(dev, 0x51, 0);
+		b43_radio_write16(dev, 0x52, 0x40);
+		b43_radio_write16(dev, 0x53, 0xB7);
+		b43_radio_write16(dev, 0x54, 0x98);
+		b43_radio_write16(dev, 0x5A, 0x88);
+		b43_radio_write16(dev, 0x5B, 0x6B);
+		b43_radio_write16(dev, 0x5C, 0x0F);
+		if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_ALTIQ) {
+			b43_radio_write16(dev, 0x5D, 0xFA);
+			b43_radio_write16(dev, 0x5E, 0xD8);
+		} else {
+			b43_radio_write16(dev, 0x5D, 0xF5);
+			b43_radio_write16(dev, 0x5E, 0xB8);
+		}
+		b43_radio_write16(dev, 0x0073, 0x0003);
+		b43_radio_write16(dev, 0x007D, 0x00A8);
+		b43_radio_write16(dev, 0x007C, 0x0001);
+		b43_radio_write16(dev, 0x007E, 0x0008);
+	}
+	val = 0x1E1F;
+	for (offset = 0x0088; offset < 0x0098; offset++) {
+		b43_phy_write(dev, offset, val);
+		val -= 0x0202;
+	}
+	val = 0x3E3F;
+	for (offset = 0x0098; offset < 0x00A8; offset++) {
+		b43_phy_write(dev, offset, val);
+		val -= 0x0202;
+	}
+	val = 0x2120;
+	for (offset = 0x00A8; offset < 0x00C8; offset++) {
+		b43_phy_write(dev, offset, (val & 0x3F3F));
+		val += 0x0202;
+	}
+	if (phy->type == B43_PHYTYPE_G) {
+		b43_radio_set(dev, 0x007A, 0x0020);
+		b43_radio_set(dev, 0x0051, 0x0004);
+		b43_phy_set(dev, 0x0802, 0x0100);
+		b43_phy_set(dev, 0x042B, 0x2000);
+		b43_phy_write(dev, 0x5B, 0);
+		b43_phy_write(dev, 0x5C, 0);
+	}
+
+	old_channel = phy->channel;
+	if (old_channel >= 8)
+		b43_gphy_channel_switch(dev, 1, 0);
+	else
+		b43_gphy_channel_switch(dev, 13, 0);
+
+	b43_radio_write16(dev, 0x0050, 0x0020);
+	b43_radio_write16(dev, 0x0050, 0x0023);
+	udelay(40);
+	if (phy->radio_rev < 6 || phy->radio_rev == 8) {
+		b43_radio_write16(dev, 0x7C, (b43_radio_read16(dev, 0x7C)
+					      | 0x0002));
+		b43_radio_write16(dev, 0x50, 0x20);
+	}
+	if (phy->radio_rev <= 2) {
+		b43_radio_write16(dev, 0x50, 0x20);
+		b43_radio_write16(dev, 0x5A, 0x70);
+		b43_radio_write16(dev, 0x5B, 0x7B);
+		b43_radio_write16(dev, 0x5C, 0xB0);
+	}
+	b43_radio_maskset(dev, 0x007A, 0x00F8, 0x0007);
+
+	b43_gphy_channel_switch(dev, old_channel, 0);
+
+	b43_phy_write(dev, 0x0014, 0x0200);
+	if (phy->radio_rev >= 6)
+		b43_phy_write(dev, 0x2A, 0x88C2);
+	else
+		b43_phy_write(dev, 0x2A, 0x8AC0);
+	b43_phy_write(dev, 0x0038, 0x0668);
+	b43_set_txpower_g(dev, &gphy->bbatt, &gphy->rfatt, gphy->tx_control);
+	if (phy->radio_rev == 4 || phy->radio_rev == 5)
+		b43_phy_maskset(dev, 0x5D, 0xFF80, 0x0003);
+	if (phy->radio_rev <= 2)
+		b43_radio_write16(dev, 0x005D, 0x000D);
+
+	if (phy->analog == 4) {
+		b43_write16(dev, 0x3E4, 9);
+		b43_phy_mask(dev, 0x61, 0x0FFF);
+	} else {
+		b43_phy_maskset(dev, 0x0002, 0xFFC0, 0x0004);
+	}
+	if (phy->type == B43_PHYTYPE_B)
+		B43_WARN_ON(1);
+	else if (phy->type == B43_PHYTYPE_G)
+		b43_write16(dev, 0x03E6, 0x0);
+}
+
+static void b43_calc_loopback_gain(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	u16 backup_phy[16] = { 0 };
+	u16 backup_radio[3];
+	u16 backup_bband;
+	u16 i, j, loop_i_max;
+	u16 trsw_rx;
+	u16 loop1_outer_done, loop1_inner_done;
+
+	backup_phy[0] = b43_phy_read(dev, B43_PHY_CRS0);
+	backup_phy[1] = b43_phy_read(dev, B43_PHY_CCKBBANDCFG);
+	backup_phy[2] = b43_phy_read(dev, B43_PHY_RFOVER);
+	backup_phy[3] = b43_phy_read(dev, B43_PHY_RFOVERVAL);
+	if (phy->rev != 1) {	/* Not in specs, but needed to prevent PPC machine check */
+		backup_phy[4] = b43_phy_read(dev, B43_PHY_ANALOGOVER);
+		backup_phy[5] = b43_phy_read(dev, B43_PHY_ANALOGOVERVAL);
+	}
+	backup_phy[6] = b43_phy_read(dev, B43_PHY_CCK(0x5A));
+	backup_phy[7] = b43_phy_read(dev, B43_PHY_CCK(0x59));
+	backup_phy[8] = b43_phy_read(dev, B43_PHY_CCK(0x58));
+	backup_phy[9] = b43_phy_read(dev, B43_PHY_CCK(0x0A));
+	backup_phy[10] = b43_phy_read(dev, B43_PHY_CCK(0x03));
+	backup_phy[11] = b43_phy_read(dev, B43_PHY_LO_MASK);
+	backup_phy[12] = b43_phy_read(dev, B43_PHY_LO_CTL);
+	backup_phy[13] = b43_phy_read(dev, B43_PHY_CCK(0x2B));
+	backup_phy[14] = b43_phy_read(dev, B43_PHY_PGACTL);
+	backup_phy[15] = b43_phy_read(dev, B43_PHY_LO_LEAKAGE);
+	backup_bband = gphy->bbatt.att;
+	backup_radio[0] = b43_radio_read16(dev, 0x52);
+	backup_radio[1] = b43_radio_read16(dev, 0x43);
+	backup_radio[2] = b43_radio_read16(dev, 0x7A);
+
+	b43_phy_mask(dev, B43_PHY_CRS0, 0x3FFF);
+	b43_phy_set(dev, B43_PHY_CCKBBANDCFG, 0x8000);
+	b43_phy_set(dev, B43_PHY_RFOVER, 0x0002);
+	b43_phy_mask(dev, B43_PHY_RFOVERVAL, 0xFFFD);
+	b43_phy_set(dev, B43_PHY_RFOVER, 0x0001);
+	b43_phy_mask(dev, B43_PHY_RFOVERVAL, 0xFFFE);
+	if (phy->rev != 1) {	/* Not in specs, but needed to prevent PPC machine check */
+		b43_phy_set(dev, B43_PHY_ANALOGOVER, 0x0001);
+		b43_phy_mask(dev, B43_PHY_ANALOGOVERVAL, 0xFFFE);
+		b43_phy_set(dev, B43_PHY_ANALOGOVER, 0x0002);
+		b43_phy_mask(dev, B43_PHY_ANALOGOVERVAL, 0xFFFD);
+	}
+	b43_phy_set(dev, B43_PHY_RFOVER, 0x000C);
+	b43_phy_set(dev, B43_PHY_RFOVERVAL, 0x000C);
+	b43_phy_set(dev, B43_PHY_RFOVER, 0x0030);
+	b43_phy_maskset(dev, B43_PHY_RFOVERVAL, 0xFFCF, 0x10);
+
+	b43_phy_write(dev, B43_PHY_CCK(0x5A), 0x0780);
+	b43_phy_write(dev, B43_PHY_CCK(0x59), 0xC810);
+	b43_phy_write(dev, B43_PHY_CCK(0x58), 0x000D);
+
+	b43_phy_set(dev, B43_PHY_CCK(0x0A), 0x2000);
+	if (phy->rev != 1) {	/* Not in specs, but needed to prevent PPC machine check */
+		b43_phy_set(dev, B43_PHY_ANALOGOVER, 0x0004);
+		b43_phy_mask(dev, B43_PHY_ANALOGOVERVAL, 0xFFFB);
+	}
+	b43_phy_maskset(dev, B43_PHY_CCK(0x03), 0xFF9F, 0x40);
+
+	if (phy->radio_rev == 8) {
+		b43_radio_write16(dev, 0x43, 0x000F);
+	} else {
+		b43_radio_write16(dev, 0x52, 0);
+		b43_radio_maskset(dev, 0x43, 0xFFF0, 0x9);
+	}
+	b43_gphy_set_baseband_attenuation(dev, 11);
+
+	if (phy->rev >= 3)
+		b43_phy_write(dev, B43_PHY_LO_MASK, 0xC020);
+	else
+		b43_phy_write(dev, B43_PHY_LO_MASK, 0x8020);
+	b43_phy_write(dev, B43_PHY_LO_CTL, 0);
+
+	b43_phy_maskset(dev, B43_PHY_CCK(0x2B), 0xFFC0, 0x01);
+	b43_phy_maskset(dev, B43_PHY_CCK(0x2B), 0xC0FF, 0x800);
+
+	b43_phy_set(dev, B43_PHY_RFOVER, 0x0100);
+	b43_phy_mask(dev, B43_PHY_RFOVERVAL, 0xCFFF);
+
+	if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_EXTLNA) {
+		if (phy->rev >= 7) {
+			b43_phy_set(dev, B43_PHY_RFOVER, 0x0800);
+			b43_phy_set(dev, B43_PHY_RFOVERVAL, 0x8000);
+		}
+	}
+	b43_radio_mask(dev, 0x7A, 0x00F7);
+
+	j = 0;
+	loop_i_max = (phy->radio_rev == 8) ? 15 : 9;
+	for (i = 0; i < loop_i_max; i++) {
+		for (j = 0; j < 16; j++) {
+			b43_radio_write16(dev, 0x43, i);
+			b43_phy_maskset(dev, B43_PHY_RFOVERVAL, 0xF0FF, (j << 8));
+			b43_phy_maskset(dev, B43_PHY_PGACTL, 0x0FFF, 0xA000);
+			b43_phy_set(dev, B43_PHY_PGACTL, 0xF000);
+			udelay(20);
+			if (b43_phy_read(dev, B43_PHY_LO_LEAKAGE) >= 0xDFC)
+				goto exit_loop1;
+		}
+	}
+      exit_loop1:
+	loop1_outer_done = i;
+	loop1_inner_done = j;
+	if (j >= 8) {
+		b43_phy_set(dev, B43_PHY_RFOVERVAL, 0x30);
+		trsw_rx = 0x1B;
+		for (j = j - 8; j < 16; j++) {
+			b43_phy_maskset(dev, B43_PHY_RFOVERVAL, 0xF0FF, (j << 8));
+			b43_phy_maskset(dev, B43_PHY_PGACTL, 0x0FFF, 0xA000);
+			b43_phy_set(dev, B43_PHY_PGACTL, 0xF000);
+			udelay(20);
+			trsw_rx -= 3;
+			if (b43_phy_read(dev, B43_PHY_LO_LEAKAGE) >= 0xDFC)
+				goto exit_loop2;
+		}
+	} else
+		trsw_rx = 0x18;
+      exit_loop2:
+
+	if (phy->rev != 1) {	/* Not in specs, but needed to prevent PPC machine check */
+		b43_phy_write(dev, B43_PHY_ANALOGOVER, backup_phy[4]);
+		b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, backup_phy[5]);
+	}
+	b43_phy_write(dev, B43_PHY_CCK(0x5A), backup_phy[6]);
+	b43_phy_write(dev, B43_PHY_CCK(0x59), backup_phy[7]);
+	b43_phy_write(dev, B43_PHY_CCK(0x58), backup_phy[8]);
+	b43_phy_write(dev, B43_PHY_CCK(0x0A), backup_phy[9]);
+	b43_phy_write(dev, B43_PHY_CCK(0x03), backup_phy[10]);
+	b43_phy_write(dev, B43_PHY_LO_MASK, backup_phy[11]);
+	b43_phy_write(dev, B43_PHY_LO_CTL, backup_phy[12]);
+	b43_phy_write(dev, B43_PHY_CCK(0x2B), backup_phy[13]);
+	b43_phy_write(dev, B43_PHY_PGACTL, backup_phy[14]);
+
+	b43_gphy_set_baseband_attenuation(dev, backup_bband);
+
+	b43_radio_write16(dev, 0x52, backup_radio[0]);
+	b43_radio_write16(dev, 0x43, backup_radio[1]);
+	b43_radio_write16(dev, 0x7A, backup_radio[2]);
+
+	b43_phy_write(dev, B43_PHY_RFOVER, backup_phy[2] | 0x0003);
+	udelay(10);
+	b43_phy_write(dev, B43_PHY_RFOVER, backup_phy[2]);
+	b43_phy_write(dev, B43_PHY_RFOVERVAL, backup_phy[3]);
+	b43_phy_write(dev, B43_PHY_CRS0, backup_phy[0]);
+	b43_phy_write(dev, B43_PHY_CCKBBANDCFG, backup_phy[1]);
+
+	gphy->max_lb_gain =
+	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
+	gphy->trsw_rx_gain = trsw_rx * 2;
+}
+
+static void b43_hardware_pctl_early_init(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	if (!b43_has_hardware_pctl(dev)) {
+		b43_phy_write(dev, 0x047A, 0xC111);
+		return;
+	}
+
+	b43_phy_mask(dev, 0x0036, 0xFEFF);
+	b43_phy_write(dev, 0x002F, 0x0202);
+	b43_phy_set(dev, 0x047C, 0x0002);
+	b43_phy_set(dev, 0x047A, 0xF000);
+	if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) {
+		b43_phy_maskset(dev, 0x047A, 0xFF0F, 0x0010);
+		b43_phy_set(dev, 0x005D, 0x8000);
+		b43_phy_maskset(dev, 0x004E, 0xFFC0, 0x0010);
+		b43_phy_write(dev, 0x002E, 0xC07F);
+		b43_phy_set(dev, 0x0036, 0x0400);
+	} else {
+		b43_phy_set(dev, 0x0036, 0x0200);
+		b43_phy_set(dev, 0x0036, 0x0400);
+		b43_phy_mask(dev, 0x005D, 0x7FFF);
+		b43_phy_mask(dev, 0x004F, 0xFFFE);
+		b43_phy_maskset(dev, 0x004E, 0xFFC0, 0x0010);
+		b43_phy_write(dev, 0x002E, 0xC07F);
+		b43_phy_maskset(dev, 0x047A, 0xFF0F, 0x0010);
+	}
+}
+
+/* Hardware power control for G-PHY */
+static void b43_hardware_pctl_init_gphy(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+
+	if (!b43_has_hardware_pctl(dev)) {
+		/* No hardware power control */
+		b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_HWPCTL);
+		return;
+	}
+
+	b43_phy_maskset(dev, 0x0036, 0xFFC0, (gphy->tgt_idle_tssi - gphy->cur_idle_tssi));
+	b43_phy_maskset(dev, 0x0478, 0xFF00, (gphy->tgt_idle_tssi - gphy->cur_idle_tssi));
+	b43_gphy_tssi_power_lt_init(dev);
+	b43_gphy_gain_lt_init(dev);
+	b43_phy_mask(dev, 0x0060, 0xFFBF);
+	b43_phy_write(dev, 0x0014, 0x0000);
+
+	B43_WARN_ON(phy->rev < 6);
+	b43_phy_set(dev, 0x0478, 0x0800);
+	b43_phy_mask(dev, 0x0478, 0xFEFF);
+	b43_phy_mask(dev, 0x0801, 0xFFBF);
+
+	b43_gphy_dc_lt_init(dev, 1);
+
+	/* Enable hardware pctl in firmware. */
+	b43_hf_write(dev, b43_hf_read(dev) | B43_HF_HWPCTL);
+}
+
+/* Initialize B/G PHY power control */
+static void b43_phy_init_pctl(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	struct b43_rfatt old_rfatt;
+	struct b43_bbatt old_bbatt;
+	u8 old_tx_control = 0;
+
+	B43_WARN_ON(phy->type != B43_PHYTYPE_G);
+
+	if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) &&
+	    (dev->dev->board_type == SSB_BOARD_BU4306))
+		return;
+
+	b43_phy_write(dev, 0x0028, 0x8018);
+
+	/* This does something with the Analog... */
+	b43_write16(dev, B43_MMIO_PHY0, b43_read16(dev, B43_MMIO_PHY0)
+		    & 0xFFDF);
+
+	if (!phy->gmode)
+		return;
+	b43_hardware_pctl_early_init(dev);
+	if (gphy->cur_idle_tssi == 0) {
+		if (phy->radio_ver == 0x2050 && phy->analog == 0) {
+			b43_radio_maskset(dev, 0x0076, 0x00F7, 0x0084);
+		} else {
+			struct b43_rfatt rfatt;
+			struct b43_bbatt bbatt;
+
+			memcpy(&old_rfatt, &gphy->rfatt, sizeof(old_rfatt));
+			memcpy(&old_bbatt, &gphy->bbatt, sizeof(old_bbatt));
+			old_tx_control = gphy->tx_control;
+
+			bbatt.att = 11;
+			if (phy->radio_rev == 8) {
+				rfatt.att = 15;
+				rfatt.with_padmix = true;
+			} else {
+				rfatt.att = 9;
+				rfatt.with_padmix = false;
+			}
+			b43_set_txpower_g(dev, &bbatt, &rfatt, 0);
+		}
+		b43_dummy_transmission(dev, false, true);
+		gphy->cur_idle_tssi = b43_phy_read(dev, B43_PHY_ITSSI);
+		if (B43_DEBUG) {
+			/* Current-Idle-TSSI sanity check. */
+			if (abs(gphy->cur_idle_tssi - gphy->tgt_idle_tssi) >= 20) {
+				b43dbg(dev->wl,
+				       "!WARNING! Idle-TSSI phy->cur_idle_tssi "
+				       "measuring failed. (cur=%d, tgt=%d). Disabling TX power "
+				       "adjustment.\n", gphy->cur_idle_tssi,
+				       gphy->tgt_idle_tssi);
+				gphy->cur_idle_tssi = 0;
+			}
+		}
+		if (phy->radio_ver == 0x2050 && phy->analog == 0) {
+			b43_radio_mask(dev, 0x0076, 0xFF7B);
+		} else {
+			b43_set_txpower_g(dev, &old_bbatt,
+					  &old_rfatt, old_tx_control);
+		}
+	}
+	b43_hardware_pctl_init_gphy(dev);
+	b43_shm_clear_tssi(dev);
+}
+
+static void b43_phy_inita(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	might_sleep();
+
+	if (phy->rev >= 6) {
+		if (b43_phy_read(dev, B43_PHY_ENCORE) & B43_PHY_ENCORE_EN)
+			b43_phy_set(dev, B43_PHY_ENCORE, 0x0010);
+		else
+			b43_phy_mask(dev, B43_PHY_ENCORE, ~0x1010);
+	}
+
+	b43_wa_all(dev);
+
+	if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)
+		b43_phy_maskset(dev, B43_PHY_OFDM(0x6E), 0xE000, 0x3CF);
+}
+
+static void b43_phy_initg(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	u16 tmp;
+
+	if (phy->rev == 1)
+		b43_phy_initb5(dev);
+	else
+		b43_phy_initb6(dev);
+
+	if (phy->rev >= 2 || phy->gmode)
+		b43_phy_inita(dev);
+
+	if (phy->rev >= 2) {
+		b43_phy_write(dev, B43_PHY_ANALOGOVER, 0);
+		b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, 0);
+	}
+	if (phy->rev == 2) {
+		b43_phy_write(dev, B43_PHY_RFOVER, 0);
+		b43_phy_write(dev, B43_PHY_PGACTL, 0xC0);
+	}
+	if (phy->rev > 5) {
+		b43_phy_write(dev, B43_PHY_RFOVER, 0x400);
+		b43_phy_write(dev, B43_PHY_PGACTL, 0xC0);
+	}
+	if (phy->gmode || phy->rev >= 2) {
+		tmp = b43_phy_read(dev, B43_PHY_VERSION_OFDM);
+		tmp &= B43_PHYVER_VERSION;
+		if (tmp == 3 || tmp == 5) {
+			b43_phy_write(dev, B43_PHY_OFDM(0xC2), 0x1816);
+			b43_phy_write(dev, B43_PHY_OFDM(0xC3), 0x8006);
+		}
+		if (tmp == 5) {
+			b43_phy_maskset(dev, B43_PHY_OFDM(0xCC), 0x00FF, 0x1F00);
+		}
+	}
+	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
+		b43_phy_write(dev, B43_PHY_OFDM(0x7E), 0x78);
+	if (phy->radio_rev == 8) {
+		b43_phy_set(dev, B43_PHY_EXTG(0x01), 0x80);
+		b43_phy_set(dev, B43_PHY_OFDM(0x3E), 0x4);
+	}
+	if (has_loopback_gain(phy))
+		b43_calc_loopback_gain(dev);
+
+	if (phy->radio_rev != 8) {
+		if (gphy->initval == 0xFFFF)
+			gphy->initval = b43_radio_init2050(dev);
+		else
+			b43_radio_write16(dev, 0x0078, gphy->initval);
+	}
+	b43_lo_g_init(dev);
+	if (has_tx_magnification(phy)) {
+		b43_radio_write16(dev, 0x52,
+				  (b43_radio_read16(dev, 0x52) & 0xFF00)
+				  | gphy->lo_control->tx_bias | gphy->
+				  lo_control->tx_magn);
+	} else {
+		b43_radio_maskset(dev, 0x52, 0xFFF0, gphy->lo_control->tx_bias);
+	}
+	if (phy->rev >= 6) {
+		b43_phy_maskset(dev, B43_PHY_CCK(0x36), 0x0FFF, (gphy->lo_control->tx_bias << 12));
+	}
+	if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)
+		b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075);
+	else
+		b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F);
+	if (phy->rev < 2)
+		b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x101);
+	else
+		b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x202);
+	if (phy->gmode || phy->rev >= 2) {
+		b43_lo_g_adjust(dev);
+		b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078);
+	}
+
+	if (!(dev->dev->bus_sprom->boardflags_lo & B43_BFL_RSSI)) {
+		/* The specs state to update the NRSSI LT with
+		 * the value 0x7FFFFFFF here. I think that is some weird
+		 * compiler optimization in the original driver.
+		 * Essentially, what we do here is resetting all NRSSI LT
+		 * entries to -32 (see the clamp_val() in nrssi_hw_update())
+		 */
+		b43_nrssi_hw_update(dev, 0xFFFF);	//FIXME?
+		b43_calc_nrssi_threshold(dev);
+	} else if (phy->gmode || phy->rev >= 2) {
+		if (gphy->nrssi[0] == -1000) {
+			B43_WARN_ON(gphy->nrssi[1] != -1000);
+			b43_calc_nrssi_slope(dev);
+		} else
+			b43_calc_nrssi_threshold(dev);
+	}
+	if (phy->radio_rev == 8)
+		b43_phy_write(dev, B43_PHY_EXTG(0x05), 0x3230);
+	b43_phy_init_pctl(dev);
+	/* FIXME: The spec says in the following if, the 0 should be replaced
+	   'if OFDM may not be used in the current locale'
+	   but OFDM is legal everywhere */
+	if ((dev->dev->chip_id == 0x4306
+	     && dev->dev->chip_pkg == 2) || 0) {
+		b43_phy_mask(dev, B43_PHY_CRS0, 0xBFFF);
+		b43_phy_mask(dev, B43_PHY_OFDM(0xC3), 0x7FFF);
+	}
+}
+
+void b43_gphy_channel_switch(struct b43_wldev *dev,
+			     unsigned int channel,
+			     bool synthetic_pu_workaround)
+{
+	if (synthetic_pu_workaround)
+		b43_synth_pu_workaround(dev, channel);
+
+	b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel));
+
+	if (channel == 14) {
+		if (dev->dev->bus_sprom->country_code ==
+		    SSB_SPROM1CCODE_JAPAN)
+			b43_hf_write(dev,
+				     b43_hf_read(dev) & ~B43_HF_ACPR);
+		else
+			b43_hf_write(dev,
+				     b43_hf_read(dev) | B43_HF_ACPR);
+		b43_write16(dev, B43_MMIO_CHANNEL_EXT,
+			    b43_read16(dev, B43_MMIO_CHANNEL_EXT)
+			    | (1 << 11));
+	} else {
+		b43_write16(dev, B43_MMIO_CHANNEL_EXT,
+			    b43_read16(dev, B43_MMIO_CHANNEL_EXT)
+			    & 0xF7BF);
+	}
+}
+
+static void default_baseband_attenuation(struct b43_wldev *dev,
+					 struct b43_bbatt *bb)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	if (phy->radio_ver == 0x2050 && phy->radio_rev < 6)
+		bb->att = 0;
+	else
+		bb->att = 2;
+}
+
+static void default_radio_attenuation(struct b43_wldev *dev,
+				      struct b43_rfatt *rf)
+{
+	struct b43_bus_dev *bdev = dev->dev;
+	struct b43_phy *phy = &dev->phy;
+
+	rf->with_padmix = false;
+
+	if (dev->dev->board_vendor == SSB_BOARDVENDOR_BCM &&
+	    dev->dev->board_type == SSB_BOARD_BCM4309G) {
+		if (dev->dev->board_rev < 0x43) {
+			rf->att = 2;
+			return;
+		} else if (dev->dev->board_rev < 0x51) {
+			rf->att = 3;
+			return;
+		}
+	}
+
+	switch (phy->radio_ver) {
+	case 0x2053:
+		switch (phy->radio_rev) {
+		case 1:
+			rf->att = 6;
+			return;
+		}
+		break;
+	case 0x2050:
+		switch (phy->radio_rev) {
+		case 0:
+			rf->att = 5;
+			return;
+		case 1:
+			if (phy->type == B43_PHYTYPE_G) {
+				if (bdev->board_vendor == SSB_BOARDVENDOR_BCM
+				    && bdev->board_type == SSB_BOARD_BCM4309G
+				    && bdev->board_rev >= 30)
+					rf->att = 3;
+				else if (bdev->board_vendor ==
+					 SSB_BOARDVENDOR_BCM
+					 && bdev->board_type ==
+					 SSB_BOARD_BU4306)
+					rf->att = 3;
+				else
+					rf->att = 1;
+			} else {
+				if (bdev->board_vendor == SSB_BOARDVENDOR_BCM
+				    && bdev->board_type == SSB_BOARD_BCM4309G
+				    && bdev->board_rev >= 30)
+					rf->att = 7;
+				else
+					rf->att = 6;
+			}
+			return;
+		case 2:
+			if (phy->type == B43_PHYTYPE_G) {
+				if (bdev->board_vendor == SSB_BOARDVENDOR_BCM
+				    && bdev->board_type == SSB_BOARD_BCM4309G
+				    && bdev->board_rev >= 30)
+					rf->att = 3;
+				else if (bdev->board_vendor ==
+					 SSB_BOARDVENDOR_BCM
+					 && bdev->board_type ==
+					 SSB_BOARD_BU4306)
+					rf->att = 5;
+				else if (bdev->chip_id == 0x4320)
+					rf->att = 4;
+				else
+					rf->att = 3;
+			} else
+				rf->att = 6;
+			return;
+		case 3:
+			rf->att = 5;
+			return;
+		case 4:
+		case 5:
+			rf->att = 1;
+			return;
+		case 6:
+		case 7:
+			rf->att = 5;
+			return;
+		case 8:
+			rf->att = 0xA;
+			rf->with_padmix = true;
+			return;
+		case 9:
+		default:
+			rf->att = 5;
+			return;
+		}
+	}
+	rf->att = 5;
+}
+
+static u16 default_tx_control(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	if (phy->radio_ver != 0x2050)
+		return 0;
+	if (phy->radio_rev == 1)
+		return B43_TXCTL_PA2DB | B43_TXCTL_TXMIX;
+	if (phy->radio_rev < 6)
+		return B43_TXCTL_PA2DB;
+	if (phy->radio_rev == 8)
+		return B43_TXCTL_TXMIX;
+	return 0;
+}
+
+static u8 b43_gphy_aci_detect(struct b43_wldev *dev, u8 channel)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	u8 ret = 0;
+	u16 saved, rssi, temp;
+	int i, j = 0;
+
+	saved = b43_phy_read(dev, 0x0403);
+	b43_switch_channel(dev, channel);
+	b43_phy_write(dev, 0x0403, (saved & 0xFFF8) | 5);
+	if (gphy->aci_hw_rssi)
+		rssi = b43_phy_read(dev, 0x048A) & 0x3F;
+	else
+		rssi = saved & 0x3F;
+	/* clamp temp to signed 5bit */
+	if (rssi > 32)
+		rssi -= 64;
+	for (i = 0; i < 100; i++) {
+		temp = (b43_phy_read(dev, 0x047F) >> 8) & 0x3F;
+		if (temp > 32)
+			temp -= 64;
+		if (temp < rssi)
+			j++;
+		if (j >= 20)
+			ret = 1;
+	}
+	b43_phy_write(dev, 0x0403, saved);
+
+	return ret;
+}
+
+static u8 b43_gphy_aci_scan(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	u8 ret[13] = { 0 };
+	unsigned int channel = phy->channel;
+	unsigned int i, j, start, end;
+
+	if (!((phy->type == B43_PHYTYPE_G) && (phy->rev > 0)))
+		return 0;
+
+	b43_phy_lock(dev);
+	b43_radio_lock(dev);
+	b43_phy_mask(dev, 0x0802, 0xFFFC);
+	b43_phy_mask(dev, B43_PHY_G_CRS, 0x7FFF);
+	b43_set_all_gains(dev, 3, 8, 1);
+
+	start = (channel - 5 > 0) ? channel - 5 : 1;
+	end = (channel + 5 < 14) ? channel + 5 : 13;
+
+	for (i = start; i <= end; i++) {
+		if (abs(channel - i) > 2)
+			ret[i - 1] = b43_gphy_aci_detect(dev, i);
+	}
+	b43_switch_channel(dev, channel);
+	b43_phy_maskset(dev, 0x0802, 0xFFFC, 0x0003);
+	b43_phy_mask(dev, 0x0403, 0xFFF8);
+	b43_phy_set(dev, B43_PHY_G_CRS, 0x8000);
+	b43_set_original_gains(dev);
+	for (i = 0; i < 13; i++) {
+		if (!ret[i])
+			continue;
+		end = (i + 5 < 13) ? i + 5 : 13;
+		for (j = i; j < end; j++)
+			ret[j] = 1;
+	}
+	b43_radio_unlock(dev);
+	b43_phy_unlock(dev);
+
+	return ret[channel - 1];
+}
+
+static s32 b43_tssi2dbm_ad(s32 num, s32 den)
+{
+	if (num < 0)
+		return num / den;
+	else
+		return (num + den / 2) / den;
+}
+
+static s8 b43_tssi2dbm_entry(s8 entry[], u8 index,
+			     s16 pab0, s16 pab1, s16 pab2)
+{
+	s32 m1, m2, f = 256, q, delta;
+	s8 i = 0;
+
+	m1 = b43_tssi2dbm_ad(16 * pab0 + index * pab1, 32);
+	m2 = max(b43_tssi2dbm_ad(32768 + index * pab2, 256), 1);
+	do {
+		if (i > 15)
+			return -EINVAL;
+		q = b43_tssi2dbm_ad(f * 4096 -
+				    b43_tssi2dbm_ad(m2 * f, 16) * f, 2048);
+		delta = abs(q - f);
+		f = q;
+		i++;
+	} while (delta >= 2);
+	entry[index] = clamp_val(b43_tssi2dbm_ad(m1 * f, 8192), -127, 128);
+	return 0;
+}
+
+u8 *b43_generate_dyn_tssi2dbm_tab(struct b43_wldev *dev,
+				  s16 pab0, s16 pab1, s16 pab2)
+{
+	unsigned int i;
+	u8 *tab;
+	int err;
+
+	tab = kmalloc(64, GFP_KERNEL);
+	if (!tab) {
+		b43err(dev->wl, "Could not allocate memory "
+		       "for tssi2dbm table\n");
+		return NULL;
+	}
+	for (i = 0; i < 64; i++) {
+		err = b43_tssi2dbm_entry(tab, i, pab0, pab1, pab2);
+		if (err) {
+			b43err(dev->wl, "Could not generate "
+			       "tssi2dBm table\n");
+			kfree(tab);
+			return NULL;
+		}
+	}
+
+	return tab;
+}
+
+/* Initialise the TSSI->dBm lookup table */
+static int b43_gphy_init_tssi2dbm_table(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	s16 pab0, pab1, pab2;
+
+	pab0 = (s16) (dev->dev->bus_sprom->pa0b0);
+	pab1 = (s16) (dev->dev->bus_sprom->pa0b1);
+	pab2 = (s16) (dev->dev->bus_sprom->pa0b2);
+
+	B43_WARN_ON((dev->dev->chip_id == 0x4301) &&
+		    (phy->radio_ver != 0x2050)); /* Not supported anymore */
+
+	gphy->dyn_tssi_tbl = false;
+
+	if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
+	    pab0 != -1 && pab1 != -1 && pab2 != -1) {
+		/* The pabX values are set in SPROM. Use them. */
+		if ((s8) dev->dev->bus_sprom->itssi_bg != 0 &&
+		    (s8) dev->dev->bus_sprom->itssi_bg != -1) {
+			gphy->tgt_idle_tssi =
+				(s8) (dev->dev->bus_sprom->itssi_bg);
+		} else
+			gphy->tgt_idle_tssi = 62;
+		gphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0,
+							       pab1, pab2);
+		if (!gphy->tssi2dbm)
+			return -ENOMEM;
+		gphy->dyn_tssi_tbl = true;
+	} else {
+		/* pabX values not set in SPROM. */
+		gphy->tgt_idle_tssi = 52;
+		gphy->tssi2dbm = b43_tssi2dbm_g_table;
+	}
+
+	return 0;
+}
+
+static int b43_gphy_op_allocate(struct b43_wldev *dev)
+{
+	struct b43_phy_g *gphy;
+	struct b43_txpower_lo_control *lo;
+	int err;
+
+	gphy = kzalloc(sizeof(*gphy), GFP_KERNEL);
+	if (!gphy) {
+		err = -ENOMEM;
+		goto error;
+	}
+	dev->phy.g = gphy;
+
+	lo = kzalloc(sizeof(*lo), GFP_KERNEL);
+	if (!lo) {
+		err = -ENOMEM;
+		goto err_free_gphy;
+	}
+	gphy->lo_control = lo;
+
+	err = b43_gphy_init_tssi2dbm_table(dev);
+	if (err)
+		goto err_free_lo;
+
+	return 0;
+
+err_free_lo:
+	kfree(lo);
+err_free_gphy:
+	kfree(gphy);
+error:
+	return err;
+}
+
+static void b43_gphy_op_prepare_structs(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	const void *tssi2dbm;
+	int tgt_idle_tssi;
+	struct b43_txpower_lo_control *lo;
+	unsigned int i;
+
+	/* tssi2dbm table is constant, so it is initialized at alloc time.
+	 * Save a copy of the pointer. */
+	tssi2dbm = gphy->tssi2dbm;
+	tgt_idle_tssi = gphy->tgt_idle_tssi;
+	/* Save the LO pointer. */
+	lo = gphy->lo_control;
+
+	/* Zero out the whole PHY structure. */
+	memset(gphy, 0, sizeof(*gphy));
+
+	/* Restore pointers. */
+	gphy->tssi2dbm = tssi2dbm;
+	gphy->tgt_idle_tssi = tgt_idle_tssi;
+	gphy->lo_control = lo;
+
+	memset(gphy->minlowsig, 0xFF, sizeof(gphy->minlowsig));
+
+	/* NRSSI */
+	for (i = 0; i < ARRAY_SIZE(gphy->nrssi); i++)
+		gphy->nrssi[i] = -1000;
+	for (i = 0; i < ARRAY_SIZE(gphy->nrssi_lt); i++)
+		gphy->nrssi_lt[i] = i;
+
+	gphy->lofcal = 0xFFFF;
+	gphy->initval = 0xFFFF;
+
+	gphy->interfmode = B43_INTERFMODE_NONE;
+
+	/* OFDM-table address caching. */
+	gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_UNKNOWN;
+
+	gphy->average_tssi = 0xFF;
+
+	/* Local Osciallator structure */
+	lo->tx_bias = 0xFF;
+	INIT_LIST_HEAD(&lo->calib_list);
+}
+
+static void b43_gphy_op_free(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+
+	kfree(gphy->lo_control);
+
+	if (gphy->dyn_tssi_tbl)
+		kfree(gphy->tssi2dbm);
+	gphy->dyn_tssi_tbl = false;
+	gphy->tssi2dbm = NULL;
+
+	kfree(gphy);
+	dev->phy.g = NULL;
+}
+
+static int b43_gphy_op_prepare_hardware(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	struct b43_txpower_lo_control *lo = gphy->lo_control;
+
+	B43_WARN_ON(phy->type != B43_PHYTYPE_G);
+
+	default_baseband_attenuation(dev, &gphy->bbatt);
+	default_radio_attenuation(dev, &gphy->rfatt);
+	gphy->tx_control = (default_tx_control(dev) << 4);
+	generate_rfatt_list(dev, &lo->rfatt_list);
+	generate_bbatt_list(dev, &lo->bbatt_list);
+
+	/* Commit previous writes */
+	b43_read32(dev, B43_MMIO_MACCTL);
+
+	if (phy->rev == 1) {
+		/* Workaround: Temporarly disable gmode through the early init
+		 * phase, as the gmode stuff is not needed for phy rev 1 */
+		phy->gmode = false;
+		b43_wireless_core_reset(dev, 0);
+		b43_phy_initg(dev);
+		phy->gmode = true;
+		b43_wireless_core_reset(dev, 1);
+	}
+
+	return 0;
+}
+
+static int b43_gphy_op_init(struct b43_wldev *dev)
+{
+	b43_phy_initg(dev);
+
+	return 0;
+}
+
+static void b43_gphy_op_exit(struct b43_wldev *dev)
+{
+	b43_lo_g_cleanup(dev);
+}
+
+static u16 b43_gphy_op_read(struct b43_wldev *dev, u16 reg)
+{
+	b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
+	return b43_read16(dev, B43_MMIO_PHY_DATA);
+}
+
+static void b43_gphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+	b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
+	b43_write16(dev, B43_MMIO_PHY_DATA, value);
+}
+
+static u16 b43_gphy_op_radio_read(struct b43_wldev *dev, u16 reg)
+{
+	/* Register 1 is a 32-bit register. */
+	B43_WARN_ON(reg == 1);
+	/* G-PHY needs 0x80 for read access. */
+	reg |= 0x80;
+
+	b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);
+	return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
+}
+
+static void b43_gphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+	/* Register 1 is a 32-bit register. */
+	B43_WARN_ON(reg == 1);
+
+	b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);
+	b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
+}
+
+static bool b43_gphy_op_supports_hwpctl(struct b43_wldev *dev)
+{
+	return (dev->phy.rev >= 6);
+}
+
+static void b43_gphy_op_software_rfkill(struct b43_wldev *dev,
+					bool blocked)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	unsigned int channel;
+
+	might_sleep();
+
+	if (!blocked) {
+		/* Turn radio ON */
+		if (phy->radio_on)
+			return;
+
+		b43_phy_write(dev, 0x0015, 0x8000);
+		b43_phy_write(dev, 0x0015, 0xCC00);
+		b43_phy_write(dev, 0x0015, (phy->gmode ? 0x00C0 : 0x0000));
+		if (gphy->radio_off_context.valid) {
+			/* Restore the RFover values. */
+			b43_phy_write(dev, B43_PHY_RFOVER,
+				      gphy->radio_off_context.rfover);
+			b43_phy_write(dev, B43_PHY_RFOVERVAL,
+				      gphy->radio_off_context.rfoverval);
+			gphy->radio_off_context.valid = false;
+		}
+		channel = phy->channel;
+		b43_gphy_channel_switch(dev, 6, 1);
+		b43_gphy_channel_switch(dev, channel, 0);
+	} else {
+		/* Turn radio OFF */
+		u16 rfover, rfoverval;
+
+		rfover = b43_phy_read(dev, B43_PHY_RFOVER);
+		rfoverval = b43_phy_read(dev, B43_PHY_RFOVERVAL);
+		gphy->radio_off_context.rfover = rfover;
+		gphy->radio_off_context.rfoverval = rfoverval;
+		gphy->radio_off_context.valid = true;
+		b43_phy_write(dev, B43_PHY_RFOVER, rfover | 0x008C);
+		b43_phy_write(dev, B43_PHY_RFOVERVAL, rfoverval & 0xFF73);
+	}
+}
+
+static int b43_gphy_op_switch_channel(struct b43_wldev *dev,
+				      unsigned int new_channel)
+{
+	if ((new_channel < 1) || (new_channel > 14))
+		return -EINVAL;
+	b43_gphy_channel_switch(dev, new_channel, 0);
+
+	return 0;
+}
+
+static unsigned int b43_gphy_op_get_default_chan(struct b43_wldev *dev)
+{
+	return 1; /* Default to channel 1 */
+}
+
+static void b43_gphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)
+{
+	struct b43_phy *phy = &dev->phy;
+	u16 tmp;
+	int autodiv = 0;
+
+	if (antenna == B43_ANTENNA_AUTO0 || antenna == B43_ANTENNA_AUTO1)
+		autodiv = 1;
+
+	b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_ANTDIVHELP);
+
+	b43_phy_maskset(dev, B43_PHY_BBANDCFG, ~B43_PHY_BBANDCFG_RXANT,
+			(autodiv ? B43_ANTENNA_AUTO1 : antenna) <<
+			B43_PHY_BBANDCFG_RXANT_SHIFT);
+
+	if (autodiv) {
+		tmp = b43_phy_read(dev, B43_PHY_ANTDWELL);
+		if (antenna == B43_ANTENNA_AUTO1)
+			tmp &= ~B43_PHY_ANTDWELL_AUTODIV1;
+		else
+			tmp |= B43_PHY_ANTDWELL_AUTODIV1;
+		b43_phy_write(dev, B43_PHY_ANTDWELL, tmp);
+	}
+
+	tmp = b43_phy_read(dev, B43_PHY_ANTWRSETT);
+	if (autodiv)
+		tmp |= B43_PHY_ANTWRSETT_ARXDIV;
+	else
+		tmp &= ~B43_PHY_ANTWRSETT_ARXDIV;
+	b43_phy_write(dev, B43_PHY_ANTWRSETT, tmp);
+
+	if (autodiv)
+		b43_phy_set(dev, B43_PHY_ANTWRSETT, B43_PHY_ANTWRSETT_ARXDIV);
+	else {
+		b43_phy_mask(dev, B43_PHY_ANTWRSETT,
+			     B43_PHY_ANTWRSETT_ARXDIV);
+	}
+
+	if (phy->rev >= 2) {
+		b43_phy_set(dev, B43_PHY_OFDM61, B43_PHY_OFDM61_10);
+		b43_phy_maskset(dev, B43_PHY_DIVSRCHGAINBACK, 0xFF00, 0x15);
+
+		if (phy->rev == 2)
+			b43_phy_write(dev, B43_PHY_ADIVRELATED, 8);
+		else
+			b43_phy_maskset(dev, B43_PHY_ADIVRELATED, 0xFF00, 8);
+	}
+	if (phy->rev >= 6)
+		b43_phy_write(dev, B43_PHY_OFDM9B, 0xDC);
+
+	b43_hf_write(dev, b43_hf_read(dev) | B43_HF_ANTDIVHELP);
+}
+
+static int b43_gphy_op_interf_mitigation(struct b43_wldev *dev,
+					 enum b43_interference_mitigation mode)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	int currentmode;
+
+	B43_WARN_ON(phy->type != B43_PHYTYPE_G);
+	if ((phy->rev == 0) || (!phy->gmode))
+		return -ENODEV;
+
+	gphy->aci_wlan_automatic = false;
+	switch (mode) {
+	case B43_INTERFMODE_AUTOWLAN:
+		gphy->aci_wlan_automatic = true;
+		if (gphy->aci_enable)
+			mode = B43_INTERFMODE_MANUALWLAN;
+		else
+			mode = B43_INTERFMODE_NONE;
+		break;
+	case B43_INTERFMODE_NONE:
+	case B43_INTERFMODE_NONWLAN:
+	case B43_INTERFMODE_MANUALWLAN:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	currentmode = gphy->interfmode;
+	if (currentmode == mode)
+		return 0;
+	if (currentmode != B43_INTERFMODE_NONE)
+		b43_radio_interference_mitigation_disable(dev, currentmode);
+
+	if (mode == B43_INTERFMODE_NONE) {
+		gphy->aci_enable = false;
+		gphy->aci_hw_rssi = false;
+	} else
+		b43_radio_interference_mitigation_enable(dev, mode);
+	gphy->interfmode = mode;
+
+	return 0;
+}
+
+/* http://bcm-specs.sipsolutions.net/EstimatePowerOut
+ * This function converts a TSSI value to dBm in Q5.2
+ */
+static s8 b43_gphy_estimate_power_out(struct b43_wldev *dev, s8 tssi)
+{
+	struct b43_phy_g *gphy = dev->phy.g;
+	s8 dbm;
+	s32 tmp;
+
+	tmp = (gphy->tgt_idle_tssi - gphy->cur_idle_tssi + tssi);
+	tmp = clamp_val(tmp, 0x00, 0x3F);
+	dbm = gphy->tssi2dbm[tmp];
+
+	return dbm;
+}
+
+static void b43_put_attenuation_into_ranges(struct b43_wldev *dev,
+					    int *_bbatt, int *_rfatt)
+{
+	int rfatt = *_rfatt;
+	int bbatt = *_bbatt;
+	struct b43_txpower_lo_control *lo = dev->phy.g->lo_control;
+
+	/* Get baseband and radio attenuation values into their permitted ranges.
+	 * Radio attenuation affects power level 4 times as much as baseband. */
+
+	/* Range constants */
+	const int rf_min = lo->rfatt_list.min_val;
+	const int rf_max = lo->rfatt_list.max_val;
+	const int bb_min = lo->bbatt_list.min_val;
+	const int bb_max = lo->bbatt_list.max_val;
+
+	while (1) {
+		if (rfatt > rf_max && bbatt > bb_max - 4)
+			break;	/* Can not get it into ranges */
+		if (rfatt < rf_min && bbatt < bb_min + 4)
+			break;	/* Can not get it into ranges */
+		if (bbatt > bb_max && rfatt > rf_max - 1)
+			break;	/* Can not get it into ranges */
+		if (bbatt < bb_min && rfatt < rf_min + 1)
+			break;	/* Can not get it into ranges */
+
+		if (bbatt > bb_max) {
+			bbatt -= 4;
+			rfatt += 1;
+			continue;
+		}
+		if (bbatt < bb_min) {
+			bbatt += 4;
+			rfatt -= 1;
+			continue;
+		}
+		if (rfatt > rf_max) {
+			rfatt -= 1;
+			bbatt += 4;
+			continue;
+		}
+		if (rfatt < rf_min) {
+			rfatt += 1;
+			bbatt -= 4;
+			continue;
+		}
+		break;
+	}
+
+	*_rfatt = clamp_val(rfatt, rf_min, rf_max);
+	*_bbatt = clamp_val(bbatt, bb_min, bb_max);
+}
+
+static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	int rfatt, bbatt;
+	u8 tx_control;
+
+	b43_mac_suspend(dev);
+
+	/* Calculate the new attenuation values. */
+	bbatt = gphy->bbatt.att;
+	bbatt += gphy->bbatt_delta;
+	rfatt = gphy->rfatt.att;
+	rfatt += gphy->rfatt_delta;
+
+	b43_put_attenuation_into_ranges(dev, &bbatt, &rfatt);
+	tx_control = gphy->tx_control;
+	if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 2)) {
+		if (rfatt <= 1) {
+			if (tx_control == 0) {
+				tx_control =
+				    B43_TXCTL_PA2DB |
+				    B43_TXCTL_TXMIX;
+				rfatt += 2;
+				bbatt += 2;
+			} else if (dev->dev->bus_sprom->
+				   boardflags_lo &
+				   B43_BFL_PACTRL) {
+				bbatt += 4 * (rfatt - 2);
+				rfatt = 2;
+			}
+		} else if (rfatt > 4 && tx_control) {
+			tx_control = 0;
+			if (bbatt < 3) {
+				rfatt -= 3;
+				bbatt += 2;
+			} else {
+				rfatt -= 2;
+				bbatt -= 2;
+			}
+		}
+	}
+	/* Save the control values */
+	gphy->tx_control = tx_control;
+	b43_put_attenuation_into_ranges(dev, &bbatt, &rfatt);
+	gphy->rfatt.att = rfatt;
+	gphy->bbatt.att = bbatt;
+
+	if (b43_debug(dev, B43_DBG_XMITPOWER))
+		b43dbg(dev->wl, "Adjusting TX power\n");
+
+	/* Adjust the hardware */
+	b43_phy_lock(dev);
+	b43_radio_lock(dev);
+	b43_set_txpower_g(dev, &gphy->bbatt, &gphy->rfatt,
+			  gphy->tx_control);
+	b43_radio_unlock(dev);
+	b43_phy_unlock(dev);
+
+	b43_mac_enable(dev);
+}
+
+static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev,
+							bool ignore_tssi)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	unsigned int average_tssi;
+	int cck_result, ofdm_result;
+	int estimated_pwr, desired_pwr, pwr_adjust;
+	int rfatt_delta, bbatt_delta;
+	unsigned int max_pwr;
+
+	/* First get the average TSSI */
+	cck_result = b43_phy_shm_tssi_read(dev, B43_SHM_SH_TSSI_CCK);
+	ofdm_result = b43_phy_shm_tssi_read(dev, B43_SHM_SH_TSSI_OFDM_G);
+	if ((cck_result < 0) && (ofdm_result < 0)) {
+		/* No TSSI information available */
+		if (!ignore_tssi)
+			goto no_adjustment_needed;
+		cck_result = 0;
+		ofdm_result = 0;
+	}
+	if (cck_result < 0)
+		average_tssi = ofdm_result;
+	else if (ofdm_result < 0)
+		average_tssi = cck_result;
+	else
+		average_tssi = (cck_result + ofdm_result) / 2;
+	/* Merge the average with the stored value. */
+	if (likely(gphy->average_tssi != 0xFF))
+		average_tssi = (average_tssi + gphy->average_tssi) / 2;
+	gphy->average_tssi = average_tssi;
+	B43_WARN_ON(average_tssi >= B43_TSSI_MAX);
+
+	/* Estimate the TX power emission based on the TSSI */
+	estimated_pwr = b43_gphy_estimate_power_out(dev, average_tssi);
+
+	B43_WARN_ON(phy->type != B43_PHYTYPE_G);
+	max_pwr = dev->dev->bus_sprom->maxpwr_bg;
+	if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)
+		max_pwr -= 3; /* minus 0.75 */
+	if (unlikely(max_pwr >= INT_TO_Q52(30/*dBm*/))) {
+		b43warn(dev->wl,
+			"Invalid max-TX-power value in SPROM.\n");
+		max_pwr = INT_TO_Q52(20); /* fake it */
+		dev->dev->bus_sprom->maxpwr_bg = max_pwr;
+	}
+
+	/* Get desired power (in Q5.2) */
+	if (phy->desired_txpower < 0)
+		desired_pwr = INT_TO_Q52(0);
+	else
+		desired_pwr = INT_TO_Q52(phy->desired_txpower);
+	/* And limit it. max_pwr already is Q5.2 */
+	desired_pwr = clamp_val(desired_pwr, 0, max_pwr);
+	if (b43_debug(dev, B43_DBG_XMITPOWER)) {
+		b43dbg(dev->wl,
+		       "[TX power]  current = " Q52_FMT
+		       " dBm,  desired = " Q52_FMT
+		       " dBm,  max = " Q52_FMT "\n",
+		       Q52_ARG(estimated_pwr),
+		       Q52_ARG(desired_pwr),
+		       Q52_ARG(max_pwr));
+	}
+
+	/* Calculate the adjustment delta. */
+	pwr_adjust = desired_pwr - estimated_pwr;
+	if (pwr_adjust == 0)
+		goto no_adjustment_needed;
+
+	/* RF attenuation delta. */
+	rfatt_delta = ((pwr_adjust + 7) / 8);
+	/* Lower attenuation => Bigger power output. Negate it. */
+	rfatt_delta = -rfatt_delta;
+
+	/* Baseband attenuation delta. */
+	bbatt_delta = pwr_adjust / 2;
+	/* Lower attenuation => Bigger power output. Negate it. */
+	bbatt_delta = -bbatt_delta;
+	/* RF att affects power level 4 times as much as
+	 * Baseband attennuation. Subtract it. */
+	bbatt_delta -= 4 * rfatt_delta;
+
+#if B43_DEBUG
+	if (b43_debug(dev, B43_DBG_XMITPOWER)) {
+		int dbm = pwr_adjust < 0 ? -pwr_adjust : pwr_adjust;
+		b43dbg(dev->wl,
+		       "[TX power deltas]  %s" Q52_FMT " dBm   =>   "
+		       "bbatt-delta = %d,  rfatt-delta = %d\n",
+		       (pwr_adjust < 0 ? "-" : ""), Q52_ARG(dbm),
+		       bbatt_delta, rfatt_delta);
+	}
+#endif /* DEBUG */
+
+	/* So do we finally need to adjust something in hardware? */
+	if ((rfatt_delta == 0) && (bbatt_delta == 0))
+		goto no_adjustment_needed;
+
+	/* Save the deltas for later when we adjust the power. */
+	gphy->bbatt_delta = bbatt_delta;
+	gphy->rfatt_delta = rfatt_delta;
+
+	/* We need to adjust the TX power on the device. */
+	return B43_TXPWR_RES_NEED_ADJUST;
+
+no_adjustment_needed:
+	return B43_TXPWR_RES_DONE;
+}
+
+static void b43_gphy_op_pwork_15sec(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+
+	b43_mac_suspend(dev);
+	//TODO: update_aci_moving_average
+	if (gphy->aci_enable && gphy->aci_wlan_automatic) {
+		if (!gphy->aci_enable && 1 /*TODO: not scanning? */ ) {
+			if (0 /*TODO: bunch of conditions */ ) {
+				phy->ops->interf_mitigation(dev,
+					B43_INTERFMODE_MANUALWLAN);
+			}
+		} else if (0 /*TODO*/) {
+			   if (/*(aci_average > 1000) &&*/ !b43_gphy_aci_scan(dev))
+				phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE);
+		}
+	} else if (gphy->interfmode == B43_INTERFMODE_NONWLAN &&
+		   phy->rev == 1) {
+		//TODO: implement rev1 workaround
+	}
+	b43_lo_g_maintenance_work(dev);
+	b43_mac_enable(dev);
+}
+
+static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	if (!(dev->dev->bus_sprom->boardflags_lo & B43_BFL_RSSI))
+		return;
+
+	b43_mac_suspend(dev);
+	b43_calc_nrssi_slope(dev);
+	if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 8)) {
+		u8 old_chan = phy->channel;
+
+		/* VCO Calibration */
+		if (old_chan >= 8)
+			b43_switch_channel(dev, 1);
+		else
+			b43_switch_channel(dev, 13);
+		b43_switch_channel(dev, old_chan);
+	}
+	b43_mac_enable(dev);
+}
+
+const struct b43_phy_operations b43_phyops_g = {
+	.allocate		= b43_gphy_op_allocate,
+	.free			= b43_gphy_op_free,
+	.prepare_structs	= b43_gphy_op_prepare_structs,
+	.prepare_hardware	= b43_gphy_op_prepare_hardware,
+	.init			= b43_gphy_op_init,
+	.exit			= b43_gphy_op_exit,
+	.phy_read		= b43_gphy_op_read,
+	.phy_write		= b43_gphy_op_write,
+	.radio_read		= b43_gphy_op_radio_read,
+	.radio_write		= b43_gphy_op_radio_write,
+	.supports_hwpctl	= b43_gphy_op_supports_hwpctl,
+	.software_rfkill	= b43_gphy_op_software_rfkill,
+	.switch_analog		= b43_phyop_switch_analog_generic,
+	.switch_channel		= b43_gphy_op_switch_channel,
+	.get_default_chan	= b43_gphy_op_get_default_chan,
+	.set_rx_antenna		= b43_gphy_op_set_rx_antenna,
+	.interf_mitigation	= b43_gphy_op_interf_mitigation,
+	.recalc_txpower		= b43_gphy_op_recalc_txpower,
+	.adjust_txpower		= b43_gphy_op_adjust_txpower,
+	.pwork_15sec		= b43_gphy_op_pwork_15sec,
+	.pwork_60sec		= b43_gphy_op_pwork_60sec,
+};
diff --git a/drivers/net/wireless/broadcom/b43/phy_g.h b/drivers/net/wireless/broadcom/b43/phy_g.h
new file mode 100644
index 0000000..a27b860
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/phy_g.h
@@ -0,0 +1,209 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef LINUX_B43_PHY_G_H_
+#define LINUX_B43_PHY_G_H_
+
+/* OFDM PHY registers are defined in the A-PHY header. */
+#include "phy_a.h"
+
+/* CCK (B) PHY Registers */
+#define B43_PHY_VERSION_CCK		B43_PHY_CCK(0x00)	/* Versioning register for B-PHY */
+#define B43_PHY_CCKBBANDCFG		B43_PHY_CCK(0x01)	/* Contains antenna 0/1 control bit */
+#define B43_PHY_PGACTL			B43_PHY_CCK(0x15)	/* PGA control */
+#define  B43_PHY_PGACTL_LPF		0x1000	/* Low pass filter (?) */
+#define  B43_PHY_PGACTL_LOWBANDW	0x0040	/* Low bandwidth flag */
+#define  B43_PHY_PGACTL_UNKNOWN		0xEFA0
+#define B43_PHY_FBCTL1			B43_PHY_CCK(0x18)	/* Frequency bandwidth control 1 */
+#define B43_PHY_ITSSI			B43_PHY_CCK(0x29)	/* Idle TSSI */
+#define B43_PHY_LO_LEAKAGE		B43_PHY_CCK(0x2D)	/* Measured LO leakage */
+#define B43_PHY_ENERGY			B43_PHY_CCK(0x33)	/* Energy */
+#define B43_PHY_SYNCCTL			B43_PHY_CCK(0x35)
+#define B43_PHY_FBCTL2			B43_PHY_CCK(0x38)	/* Frequency bandwidth control 2 */
+#define B43_PHY_DACCTL			B43_PHY_CCK(0x60)	/* DAC control */
+#define B43_PHY_RCCALOVER		B43_PHY_CCK(0x78)	/* RC calibration override */
+
+/* Extended G-PHY Registers */
+#define B43_PHY_CLASSCTL		B43_PHY_EXTG(0x02)	/* Classify control */
+#define B43_PHY_GTABCTL			B43_PHY_EXTG(0x03)	/* G-PHY table control (see below) */
+#define  B43_PHY_GTABOFF		0x03FF	/* G-PHY table offset (see below) */
+#define  B43_PHY_GTABNR			0xFC00	/* G-PHY table number (see below) */
+#define  B43_PHY_GTABNR_SHIFT		10
+#define B43_PHY_GTABDATA		B43_PHY_EXTG(0x04)	/* G-PHY table data */
+#define B43_PHY_LO_MASK			B43_PHY_EXTG(0x0F)	/* Local Oscillator control mask */
+#define B43_PHY_LO_CTL			B43_PHY_EXTG(0x10)	/* Local Oscillator control */
+#define B43_PHY_RFOVER			B43_PHY_EXTG(0x11)	/* RF override */
+#define B43_PHY_RFOVERVAL		B43_PHY_EXTG(0x12)	/* RF override value */
+#define  B43_PHY_RFOVERVAL_EXTLNA	0x8000
+#define  B43_PHY_RFOVERVAL_LNA		0x7000
+#define  B43_PHY_RFOVERVAL_LNA_SHIFT	12
+#define  B43_PHY_RFOVERVAL_PGA		0x0F00
+#define  B43_PHY_RFOVERVAL_PGA_SHIFT	8
+#define  B43_PHY_RFOVERVAL_UNK		0x0010	/* Unknown, always set. */
+#define  B43_PHY_RFOVERVAL_TRSWRX	0x00E0
+#define  B43_PHY_RFOVERVAL_BW		0x0003	/* Bandwidth flags */
+#define   B43_PHY_RFOVERVAL_BW_LPF	0x0001	/* Low Pass Filter */
+#define   B43_PHY_RFOVERVAL_BW_LBW	0x0002	/* Low Bandwidth (when set), high when unset */
+#define B43_PHY_ANALOGOVER		B43_PHY_EXTG(0x14)	/* Analog override */
+#define B43_PHY_ANALOGOVERVAL		B43_PHY_EXTG(0x15)	/* Analog override value */
+
+
+/*** G-PHY table numbers */
+#define B43_GTAB(number, offset)	(((number) << B43_PHY_GTABNR_SHIFT) | (offset))
+#define B43_GTAB_NRSSI			B43_GTAB(0x00, 0)
+#define B43_GTAB_TRFEMW			B43_GTAB(0x0C, 0x120)
+#define B43_GTAB_ORIGTR			B43_GTAB(0x2E, 0x298)
+
+u16 b43_gtab_read(struct b43_wldev *dev, u16 table, u16 offset);
+void b43_gtab_write(struct b43_wldev *dev, u16 table, u16 offset, u16 value);
+
+
+/* Returns the boolean whether "TX Magnification" is enabled. */
+#define has_tx_magnification(phy) \
+	(((phy)->rev >= 2) &&			\
+	 ((phy)->radio_ver == 0x2050) &&	\
+	 ((phy)->radio_rev == 8))
+/* Card uses the loopback gain stuff */
+#define has_loopback_gain(phy) \
+	(((phy)->rev > 1) || ((phy)->gmode))
+
+/* Radio Attenuation (RF Attenuation) */
+struct b43_rfatt {
+	u8 att;			/* Attenuation value */
+	bool with_padmix;	/* Flag, PAD Mixer enabled. */
+};
+struct b43_rfatt_list {
+	/* Attenuation values list */
+	const struct b43_rfatt *list;
+	u8 len;
+	/* Minimum/Maximum attenuation values */
+	u8 min_val;
+	u8 max_val;
+};
+
+/* Returns true, if the values are the same. */
+static inline bool b43_compare_rfatt(const struct b43_rfatt *a,
+				     const struct b43_rfatt *b)
+{
+	return ((a->att == b->att) &&
+		(a->with_padmix == b->with_padmix));
+}
+
+/* Baseband Attenuation */
+struct b43_bbatt {
+	u8 att;			/* Attenuation value */
+};
+struct b43_bbatt_list {
+	/* Attenuation values list */
+	const struct b43_bbatt *list;
+	u8 len;
+	/* Minimum/Maximum attenuation values */
+	u8 min_val;
+	u8 max_val;
+};
+
+/* Returns true, if the values are the same. */
+static inline bool b43_compare_bbatt(const struct b43_bbatt *a,
+				     const struct b43_bbatt *b)
+{
+	return (a->att == b->att);
+}
+
+/* tx_control bits. */
+#define B43_TXCTL_PA3DB		0x40	/* PA Gain 3dB */
+#define B43_TXCTL_PA2DB		0x20	/* PA Gain 2dB */
+#define B43_TXCTL_TXMIX		0x10	/* TX Mixer Gain */
+
+struct b43_txpower_lo_control;
+
+struct b43_phy_g {
+	/* ACI (adjacent channel interference) flags. */
+	bool aci_enable;
+	bool aci_wlan_automatic;
+	bool aci_hw_rssi;
+
+	/* Radio switched on/off */
+	bool radio_on;
+	struct {
+		/* Values saved when turning the radio off.
+		 * They are needed when turning it on again. */
+		bool valid;
+		u16 rfover;
+		u16 rfoverval;
+	} radio_off_context;
+
+	u16 minlowsig[2];
+	u16 minlowsigpos[2];
+
+	/* Pointer to the table used to convert a
+	 * TSSI value to dBm-Q5.2 */
+	const s8 *tssi2dbm;
+	/* tssi2dbm is kmalloc()ed. Only used for free()ing. */
+	bool dyn_tssi_tbl;
+	/* Target idle TSSI */
+	int tgt_idle_tssi;
+	/* Current idle TSSI */
+	int cur_idle_tssi;
+	/* The current average TSSI. */
+	u8 average_tssi;
+	/* Current TX power level attenuation control values */
+	struct b43_bbatt bbatt;
+	struct b43_rfatt rfatt;
+	u8 tx_control;		/* B43_TXCTL_XXX */
+	/* The calculated attenuation deltas that are used later
+	 * when adjusting the actual power output. */
+	int bbatt_delta;
+	int rfatt_delta;
+
+	/* LocalOscillator control values. */
+	struct b43_txpower_lo_control *lo_control;
+	/* Values from b43_calc_loopback_gain() */
+	s16 max_lb_gain;	/* Maximum Loopback gain in hdB */
+	s16 trsw_rx_gain;	/* TRSW RX gain in hdB */
+	s16 lna_lod_gain;	/* LNA lod */
+	s16 lna_gain;		/* LNA */
+	s16 pga_gain;		/* PGA */
+
+	/* Current Interference Mitigation mode */
+	int interfmode;
+	/* Stack of saved values from the Interference Mitigation code.
+	 * Each value in the stack is laid out as follows:
+	 * bit 0-11:  offset
+	 * bit 12-15: register ID
+	 * bit 16-32: value
+	 * register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT
+	 */
+#define B43_INTERFSTACK_SIZE	26
+	u32 interfstack[B43_INTERFSTACK_SIZE];	//FIXME: use a data structure
+
+	/* Saved values from the NRSSI Slope calculation */
+	s16 nrssi[2];
+	s32 nrssislope;
+	/* In memory nrssi lookup table. */
+	s8 nrssi_lt[64];
+
+	u16 lofcal;
+
+	u16 initval;		//FIXME rename?
+
+	/* The device does address auto increment for the OFDM tables.
+	 * We cache the previously used address here and omit the address
+	 * write on the next table access, if possible. */
+	u16 ofdmtab_addr; /* The address currently set in hardware. */
+	enum { /* The last data flow direction. */
+		B43_OFDMTAB_DIRECTION_UNKNOWN = 0,
+		B43_OFDMTAB_DIRECTION_READ,
+		B43_OFDMTAB_DIRECTION_WRITE,
+	} ofdmtab_addr_direction;
+};
+
+void b43_gphy_set_baseband_attenuation(struct b43_wldev *dev,
+				       u16 baseband_attenuation);
+void b43_gphy_channel_switch(struct b43_wldev *dev,
+			     unsigned int channel,
+			     bool synthetic_pu_workaround);
+u8 * b43_generate_dyn_tssi2dbm_tab(struct b43_wldev *dev,
+				   s16 pab0, s16 pab1, s16 pab2);
+
+struct b43_phy_operations;
+extern const struct b43_phy_operations b43_phyops_g;
+
+#endif /* LINUX_B43_PHY_G_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/phy_ht.c b/drivers/net/wireless/broadcom/b43/phy_ht.c
new file mode 100644
index 0000000..c3158d0
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/phy_ht.c
@@ -0,0 +1,1153 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11n HT-PHY support
+
+  Copyright (c) 2011 Rafał Miłecki <zajec5@gmail.com>
+
+  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_ht.h"
+#include "tables_phy_ht.h"
+#include "radio_2059.h"
+#include "main.h"
+
+/* Force values to keep compatibility with wl */
+enum ht_rssi_type {
+	HT_RSSI_W1 = 0,
+	HT_RSSI_W2 = 1,
+	HT_RSSI_NB = 2,
+	HT_RSSI_IQ = 3,
+	HT_RSSI_TSSI_2G = 4,
+	HT_RSSI_TSSI_5G = 5,
+	HT_RSSI_TBD = 6,
+};
+
+/**************************************************
+ * Radio 2059.
+ **************************************************/
+
+static void b43_radio_2059_channel_setup(struct b43_wldev *dev,
+			const struct b43_phy_ht_channeltab_e_radio2059 *e)
+{
+	static const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3, };
+	u16 r;
+	int core;
+
+	b43_radio_write(dev, 0x16, e->radio_syn16);
+	b43_radio_write(dev, 0x17, e->radio_syn17);
+	b43_radio_write(dev, 0x22, e->radio_syn22);
+	b43_radio_write(dev, 0x25, e->radio_syn25);
+	b43_radio_write(dev, 0x27, e->radio_syn27);
+	b43_radio_write(dev, 0x28, e->radio_syn28);
+	b43_radio_write(dev, 0x29, e->radio_syn29);
+	b43_radio_write(dev, 0x2c, e->radio_syn2c);
+	b43_radio_write(dev, 0x2d, e->radio_syn2d);
+	b43_radio_write(dev, 0x37, e->radio_syn37);
+	b43_radio_write(dev, 0x41, e->radio_syn41);
+	b43_radio_write(dev, 0x43, e->radio_syn43);
+	b43_radio_write(dev, 0x47, e->radio_syn47);
+
+	for (core = 0; core < 3; core++) {
+		r = routing[core];
+		b43_radio_write(dev, r | 0x4a, e->radio_rxtx4a);
+		b43_radio_write(dev, r | 0x58, e->radio_rxtx58);
+		b43_radio_write(dev, r | 0x5a, e->radio_rxtx5a);
+		b43_radio_write(dev, r | 0x6a, e->radio_rxtx6a);
+		b43_radio_write(dev, r | 0x6d, e->radio_rxtx6d);
+		b43_radio_write(dev, r | 0x6e, e->radio_rxtx6e);
+		b43_radio_write(dev, r | 0x92, e->radio_rxtx92);
+		b43_radio_write(dev, r | 0x98, e->radio_rxtx98);
+	}
+
+	udelay(50);
+
+	/* Calibration */
+	b43_radio_mask(dev, R2059_RFPLL_MISC_EN, ~0x1);
+	b43_radio_mask(dev, R2059_RFPLL_MISC_CAL_RESETN, ~0x4);
+	b43_radio_set(dev, R2059_RFPLL_MISC_CAL_RESETN, 0x4);
+	b43_radio_set(dev, R2059_RFPLL_MISC_EN, 0x1);
+
+	udelay(300);
+}
+
+/* Calibrate resistors in LPF of PLL? */
+static void b43_radio_2059_rcal(struct b43_wldev *dev)
+{
+	/* Enable */
+	b43_radio_set(dev, R2059_C3 | R2059_RCAL_CONFIG, 0x1);
+	usleep_range(10, 20);
+
+	b43_radio_set(dev, R2059_C3 | 0x0BF, 0x1);
+	b43_radio_maskset(dev, R2059_C3 | 0x19B, 0x3, 0x2);
+
+	/* Start */
+	b43_radio_set(dev, R2059_C3 | R2059_RCAL_CONFIG, 0x2);
+	usleep_range(100, 200);
+
+	/* Stop */
+	b43_radio_mask(dev, R2059_C3 | R2059_RCAL_CONFIG, ~0x2);
+
+	if (!b43_radio_wait_value(dev, R2059_C3 | R2059_RCAL_STATUS, 1, 1, 100,
+				  1000000))
+		b43err(dev->wl, "Radio 0x2059 rcal timeout\n");
+
+	/* Disable */
+	b43_radio_mask(dev, R2059_C3 | R2059_RCAL_CONFIG, ~0x1);
+
+	b43_radio_set(dev, 0xa, 0x60);
+}
+
+/* Calibrate the internal RC oscillator? */
+static void b43_radio_2057_rccal(struct b43_wldev *dev)
+{
+	static const u16 radio_values[3][2] = {
+		{ 0x61, 0xE9 }, { 0x69, 0xD5 }, { 0x73, 0x99 },
+	};
+	int i;
+
+	for (i = 0; i < 3; i++) {
+		b43_radio_write(dev, R2059_RCCAL_MASTER, radio_values[i][0]);
+		b43_radio_write(dev, R2059_RCCAL_X1, 0x6E);
+		b43_radio_write(dev, R2059_RCCAL_TRC0, radio_values[i][1]);
+
+		/* Start */
+		b43_radio_write(dev, R2059_RCCAL_START_R1_Q1_P1, 0x55);
+
+		/* Wait */
+		if (!b43_radio_wait_value(dev, R2059_RCCAL_DONE_OSCCAP, 2, 2,
+					  500, 5000000))
+			b43err(dev->wl, "Radio 0x2059 rccal timeout\n");
+
+		/* Stop */
+		b43_radio_write(dev, R2059_RCCAL_START_R1_Q1_P1, 0x15);
+	}
+
+	b43_radio_mask(dev, R2059_RCCAL_MASTER, ~0x1);
+}
+
+static void b43_radio_2059_init_pre(struct b43_wldev *dev)
+{
+	b43_phy_mask(dev, B43_PHY_HT_RF_CTL_CMD, ~B43_PHY_HT_RF_CTL_CMD_CHIP0_PU);
+	b43_phy_set(dev, B43_PHY_HT_RF_CTL_CMD, B43_PHY_HT_RF_CTL_CMD_FORCE);
+	b43_phy_mask(dev, B43_PHY_HT_RF_CTL_CMD, ~B43_PHY_HT_RF_CTL_CMD_FORCE);
+	b43_phy_set(dev, B43_PHY_HT_RF_CTL_CMD, B43_PHY_HT_RF_CTL_CMD_CHIP0_PU);
+}
+
+static void b43_radio_2059_init(struct b43_wldev *dev)
+{
+	static const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3 };
+	int i;
+
+	/* Prepare (reset?) radio */
+	b43_radio_2059_init_pre(dev);
+
+	r2059_upload_inittabs(dev);
+
+	for (i = 0; i < ARRAY_SIZE(routing); i++)
+		b43_radio_set(dev, routing[i] | 0x146, 0x3);
+
+	/* Post init starts below */
+
+	b43_radio_set(dev, R2059_RFPLL_MISC_CAL_RESETN, 0x0078);
+	b43_radio_set(dev, R2059_XTAL_CONFIG2, 0x0080);
+	msleep(2);
+	b43_radio_mask(dev, R2059_RFPLL_MISC_CAL_RESETN, ~0x0078);
+	b43_radio_mask(dev, R2059_XTAL_CONFIG2, ~0x0080);
+
+	if (1) { /* FIXME */
+		b43_radio_2059_rcal(dev);
+		b43_radio_2057_rccal(dev);
+	}
+
+	b43_radio_mask(dev, R2059_RFPLL_MASTER, ~0x0008);
+}
+
+/**************************************************
+ * RF
+ **************************************************/
+
+static void b43_phy_ht_force_rf_sequence(struct b43_wldev *dev, u16 rf_seq)
+{
+	u8 i;
+
+	u16 save_seq_mode = b43_phy_read(dev, B43_PHY_HT_RF_SEQ_MODE);
+	b43_phy_set(dev, B43_PHY_HT_RF_SEQ_MODE, 0x3);
+
+	b43_phy_set(dev, B43_PHY_HT_RF_SEQ_TRIG, rf_seq);
+	for (i = 0; i < 200; i++) {
+		if (!(b43_phy_read(dev, B43_PHY_HT_RF_SEQ_STATUS) & rf_seq)) {
+			i = 0;
+			break;
+		}
+		msleep(1);
+	}
+	if (i)
+		b43err(dev->wl, "Forcing RF sequence timeout\n");
+
+	b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode);
+}
+
+static void b43_phy_ht_pa_override(struct b43_wldev *dev, bool enable)
+{
+	struct b43_phy_ht *htphy = dev->phy.ht;
+	static const u16 regs[3] = { B43_PHY_HT_RF_CTL_INT_C1,
+				     B43_PHY_HT_RF_CTL_INT_C2,
+				     B43_PHY_HT_RF_CTL_INT_C3 };
+	int i;
+
+	if (enable) {
+		for (i = 0; i < 3; i++)
+			b43_phy_write(dev, regs[i], htphy->rf_ctl_int_save[i]);
+	} else {
+		for (i = 0; i < 3; i++)
+			htphy->rf_ctl_int_save[i] = b43_phy_read(dev, regs[i]);
+		/* TODO: Does 5GHz band use different value (not 0x0400)? */
+		for (i = 0; i < 3; i++)
+			b43_phy_write(dev, regs[i], 0x0400);
+	}
+}
+
+/**************************************************
+ * Various PHY ops
+ **************************************************/
+
+static u16 b43_phy_ht_classifier(struct b43_wldev *dev, u16 mask, u16 val)
+{
+	u16 tmp;
+	u16 allowed = B43_PHY_HT_CLASS_CTL_CCK_EN |
+		      B43_PHY_HT_CLASS_CTL_OFDM_EN |
+		      B43_PHY_HT_CLASS_CTL_WAITED_EN;
+
+	tmp = b43_phy_read(dev, B43_PHY_HT_CLASS_CTL);
+	tmp &= allowed;
+	tmp &= ~mask;
+	tmp |= (val & mask);
+	b43_phy_maskset(dev, B43_PHY_HT_CLASS_CTL, ~allowed, tmp);
+
+	return tmp;
+}
+
+static void b43_phy_ht_reset_cca(struct b43_wldev *dev)
+{
+	u16 bbcfg;
+
+	b43_phy_force_clock(dev, true);
+	bbcfg = b43_phy_read(dev, B43_PHY_HT_BBCFG);
+	b43_phy_write(dev, B43_PHY_HT_BBCFG, bbcfg | B43_PHY_HT_BBCFG_RSTCCA);
+	udelay(1);
+	b43_phy_write(dev, B43_PHY_HT_BBCFG, bbcfg & ~B43_PHY_HT_BBCFG_RSTCCA);
+	b43_phy_force_clock(dev, false);
+
+	b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX);
+}
+
+static void b43_phy_ht_zero_extg(struct b43_wldev *dev)
+{
+	u8 i, j;
+	static const u16 base[] = { 0x40, 0x60, 0x80 };
+
+	for (i = 0; i < ARRAY_SIZE(base); i++) {
+		for (j = 0; j < 4; j++)
+			b43_phy_write(dev, B43_PHY_EXTG(base[i] + j), 0);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(base); i++)
+		b43_phy_write(dev, B43_PHY_EXTG(base[i] + 0xc), 0);
+}
+
+/* Some unknown AFE (Analog Frondned) op */
+static void b43_phy_ht_afe_unk1(struct b43_wldev *dev)
+{
+	u8 i;
+
+	static const u16 ctl_regs[3][2] = {
+		{ B43_PHY_HT_AFE_C1_OVER, B43_PHY_HT_AFE_C1 },
+		{ B43_PHY_HT_AFE_C2_OVER, B43_PHY_HT_AFE_C2 },
+		{ B43_PHY_HT_AFE_C3_OVER, B43_PHY_HT_AFE_C3},
+	};
+
+	for (i = 0; i < 3; i++) {
+		/* TODO: verify masks&sets */
+		b43_phy_set(dev, ctl_regs[i][1], 0x4);
+		b43_phy_set(dev, ctl_regs[i][0], 0x4);
+		b43_phy_mask(dev, ctl_regs[i][1], ~0x1);
+		b43_phy_set(dev, ctl_regs[i][0], 0x1);
+		b43_httab_write(dev, B43_HTTAB16(8, 5 + (i * 0x10)), 0);
+		b43_phy_mask(dev, ctl_regs[i][0], ~0x4);
+	}
+}
+
+static void b43_phy_ht_read_clip_detection(struct b43_wldev *dev, u16 *clip_st)
+{
+	clip_st[0] = b43_phy_read(dev, B43_PHY_HT_C1_CLIP1THRES);
+	clip_st[1] = b43_phy_read(dev, B43_PHY_HT_C2_CLIP1THRES);
+	clip_st[2] = b43_phy_read(dev, B43_PHY_HT_C3_CLIP1THRES);
+}
+
+static void b43_phy_ht_bphy_init(struct b43_wldev *dev)
+{
+	unsigned int i;
+	u16 val;
+
+	val = 0x1E1F;
+	for (i = 0; i < 16; i++) {
+		b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val);
+		val -= 0x202;
+	}
+	val = 0x3E3F;
+	for (i = 0; i < 16; i++) {
+		b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val);
+		val -= 0x202;
+	}
+	b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668);
+}
+
+static void b43_phy_ht_bphy_reset(struct b43_wldev *dev, bool reset)
+{
+	u16 tmp;
+
+	tmp = b43_read16(dev, B43_MMIO_PSM_PHY_HDR);
+	b43_write16(dev, B43_MMIO_PSM_PHY_HDR,
+		    tmp | B43_PSM_HDR_MAC_PHY_FORCE_CLK);
+
+	/* Put BPHY in or take it out of the reset */
+	if (reset)
+		b43_phy_set(dev, B43_PHY_B_BBCFG,
+			    B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX);
+	else
+		b43_phy_mask(dev, B43_PHY_B_BBCFG,
+			     (u16)~(B43_PHY_B_BBCFG_RSTCCA |
+				    B43_PHY_B_BBCFG_RSTRX));
+
+	b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp);
+}
+
+/**************************************************
+ * Samples
+ **************************************************/
+
+static void b43_phy_ht_stop_playback(struct b43_wldev *dev)
+{
+	struct b43_phy_ht *phy_ht = dev->phy.ht;
+	u16 tmp;
+	int i;
+
+	tmp = b43_phy_read(dev, B43_PHY_HT_SAMP_STAT);
+	if (tmp & 0x1)
+		b43_phy_set(dev, B43_PHY_HT_SAMP_CMD, B43_PHY_HT_SAMP_CMD_STOP);
+	else if (tmp & 0x2)
+		b43_phy_mask(dev, B43_PHY_HT_IQLOCAL_CMDGCTL, 0x7FFF);
+
+	b43_phy_mask(dev, B43_PHY_HT_SAMP_CMD, ~0x0004);
+
+	for (i = 0; i < 3; i++) {
+		if (phy_ht->bb_mult_save[i] >= 0) {
+			b43_httab_write(dev, B43_HTTAB16(13, 0x63 + i * 4),
+					phy_ht->bb_mult_save[i]);
+			b43_httab_write(dev, B43_HTTAB16(13, 0x67 + i * 4),
+					phy_ht->bb_mult_save[i]);
+		}
+	}
+}
+
+static u16 b43_phy_ht_load_samples(struct b43_wldev *dev)
+{
+	int i;
+	u16 len = 20 << 3;
+
+	b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, 0x4400);
+
+	for (i = 0; i < len; i++) {
+		b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI, 0);
+		b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, 0);
+	}
+
+	return len;
+}
+
+static void b43_phy_ht_run_samples(struct b43_wldev *dev, u16 samps, u16 loops,
+				   u16 wait)
+{
+	struct b43_phy_ht *phy_ht = dev->phy.ht;
+	u16 save_seq_mode;
+	int i;
+
+	for (i = 0; i < 3; i++) {
+		if (phy_ht->bb_mult_save[i] < 0)
+			phy_ht->bb_mult_save[i] = b43_httab_read(dev, B43_HTTAB16(13, 0x63 + i * 4));
+	}
+
+	b43_phy_write(dev, B43_PHY_HT_SAMP_DEP_CNT, samps - 1);
+	if (loops != 0xFFFF)
+		loops--;
+	b43_phy_write(dev, B43_PHY_HT_SAMP_LOOP_CNT, loops);
+	b43_phy_write(dev, B43_PHY_HT_SAMP_WAIT_CNT, wait);
+
+	save_seq_mode = b43_phy_read(dev, B43_PHY_HT_RF_SEQ_MODE);
+	b43_phy_set(dev, B43_PHY_HT_RF_SEQ_MODE,
+		    B43_PHY_HT_RF_SEQ_MODE_CA_OVER);
+
+	/* TODO: find out mask bits! Do we need more function arguments? */
+	b43_phy_mask(dev, B43_PHY_HT_SAMP_CMD, ~0);
+	b43_phy_mask(dev, B43_PHY_HT_SAMP_CMD, ~0);
+	b43_phy_mask(dev, B43_PHY_HT_IQLOCAL_CMDGCTL, ~0);
+	b43_phy_set(dev, B43_PHY_HT_SAMP_CMD, 0x1);
+
+	for (i = 0; i < 100; i++) {
+		if (!(b43_phy_read(dev, B43_PHY_HT_RF_SEQ_STATUS) & 1)) {
+			i = 0;
+			break;
+		}
+		udelay(10);
+	}
+	if (i)
+		b43err(dev->wl, "run samples timeout\n");
+
+	b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode);
+}
+
+static void b43_phy_ht_tx_tone(struct b43_wldev *dev)
+{
+	u16 samp;
+
+	samp = b43_phy_ht_load_samples(dev);
+	b43_phy_ht_run_samples(dev, samp, 0xFFFF, 0);
+}
+
+/**************************************************
+ * RSSI
+ **************************************************/
+
+static void b43_phy_ht_rssi_select(struct b43_wldev *dev, u8 core_sel,
+				   enum ht_rssi_type rssi_type)
+{
+	static const u16 ctl_regs[3][2] = {
+		{ B43_PHY_HT_AFE_C1, B43_PHY_HT_AFE_C1_OVER, },
+		{ B43_PHY_HT_AFE_C2, B43_PHY_HT_AFE_C2_OVER, },
+		{ B43_PHY_HT_AFE_C3, B43_PHY_HT_AFE_C3_OVER, },
+	};
+	static const u16 radio_r[] = { R2059_C1, R2059_C2, R2059_C3, };
+	int core;
+
+	if (core_sel == 0) {
+		b43err(dev->wl, "RSSI selection for core off not implemented yet\n");
+	} else {
+		for (core = 0; core < 3; core++) {
+			/* Check if caller requested a one specific core */
+			if ((core_sel == 1 && core != 0) ||
+			    (core_sel == 2 && core != 1) ||
+			    (core_sel == 3 && core != 2))
+				continue;
+
+			switch (rssi_type) {
+			case HT_RSSI_TSSI_2G:
+				b43_phy_set(dev, ctl_regs[core][0], 0x3 << 8);
+				b43_phy_set(dev, ctl_regs[core][0], 0x3 << 10);
+				b43_phy_set(dev, ctl_regs[core][1], 0x1 << 9);
+				b43_phy_set(dev, ctl_regs[core][1], 0x1 << 10);
+
+				b43_radio_set(dev, R2059_C3 | 0xbf, 0x1);
+				b43_radio_write(dev, radio_r[core] | 0x159,
+						0x11);
+				break;
+			default:
+				b43err(dev->wl, "RSSI selection for type %d not implemented yet\n",
+				       rssi_type);
+			}
+		}
+	}
+}
+
+static void b43_phy_ht_poll_rssi(struct b43_wldev *dev, enum ht_rssi_type type,
+				 s32 *buf, u8 nsamp)
+{
+	u16 phy_regs_values[12];
+	static const u16 phy_regs_to_save[] = {
+		B43_PHY_HT_AFE_C1, B43_PHY_HT_AFE_C1_OVER,
+		0x848, 0x841,
+		B43_PHY_HT_AFE_C2, B43_PHY_HT_AFE_C2_OVER,
+		0x868, 0x861,
+		B43_PHY_HT_AFE_C3, B43_PHY_HT_AFE_C3_OVER,
+		0x888, 0x881,
+	};
+	u16 tmp[3];
+	int i;
+
+	for (i = 0; i < 12; i++)
+		phy_regs_values[i] = b43_phy_read(dev, phy_regs_to_save[i]);
+
+	b43_phy_ht_rssi_select(dev, 5, type);
+
+	for (i = 0; i < 6; i++)
+		buf[i] = 0;
+
+	for (i = 0; i < nsamp; i++) {
+		tmp[0] = b43_phy_read(dev, B43_PHY_HT_RSSI_C1);
+		tmp[1] = b43_phy_read(dev, B43_PHY_HT_RSSI_C2);
+		tmp[2] = b43_phy_read(dev, B43_PHY_HT_RSSI_C3);
+
+		buf[0] += ((s8)((tmp[0] & 0x3F) << 2)) >> 2;
+		buf[1] += ((s8)(((tmp[0] >> 8) & 0x3F) << 2)) >> 2;
+		buf[2] += ((s8)((tmp[1] & 0x3F) << 2)) >> 2;
+		buf[3] += ((s8)(((tmp[1] >> 8) & 0x3F) << 2)) >> 2;
+		buf[4] += ((s8)((tmp[2] & 0x3F) << 2)) >> 2;
+		buf[5] += ((s8)(((tmp[2] >> 8) & 0x3F) << 2)) >> 2;
+	}
+
+	for (i = 0; i < 12; i++)
+		b43_phy_write(dev, phy_regs_to_save[i], phy_regs_values[i]);
+}
+
+/**************************************************
+ * Tx/Rx
+ **************************************************/
+
+static void b43_phy_ht_tx_power_fix(struct b43_wldev *dev)
+{
+	int i;
+
+	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);
+	}
+}
+
+static void b43_phy_ht_tx_power_ctl(struct b43_wldev *dev, bool enable)
+{
+	struct b43_phy_ht *phy_ht = dev->phy.ht;
+	u16 en_bits = B43_PHY_HT_TXPCTL_CMD_C1_COEFF |
+		      B43_PHY_HT_TXPCTL_CMD_C1_HWPCTLEN |
+		      B43_PHY_HT_TXPCTL_CMD_C1_PCTLEN;
+	static const u16 cmd_regs[3] = { B43_PHY_HT_TXPCTL_CMD_C1,
+					 B43_PHY_HT_TXPCTL_CMD_C2,
+					 B43_PHY_HT_TXPCTL_CMD_C3 };
+	static const u16 status_regs[3] = { B43_PHY_HT_TX_PCTL_STATUS_C1,
+					    B43_PHY_HT_TX_PCTL_STATUS_C2,
+					    B43_PHY_HT_TX_PCTL_STATUS_C3 };
+	int i;
+
+	if (!enable) {
+		if (b43_phy_read(dev, B43_PHY_HT_TXPCTL_CMD_C1) & en_bits) {
+			/* We disable enabled TX pwr ctl, save it's state */
+			for (i = 0; i < 3; i++)
+				phy_ht->tx_pwr_idx[i] =
+					b43_phy_read(dev, status_regs[i]);
+		}
+		b43_phy_mask(dev, B43_PHY_HT_TXPCTL_CMD_C1, ~en_bits);
+	} else {
+		b43_phy_set(dev, B43_PHY_HT_TXPCTL_CMD_C1, en_bits);
+
+		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
+			for (i = 0; i < 3; i++)
+				b43_phy_write(dev, cmd_regs[i], 0x32);
+		}
+
+		for (i = 0; i < 3; i++)
+			if (phy_ht->tx_pwr_idx[i] <=
+			    B43_PHY_HT_TXPCTL_CMD_C1_INIT)
+				b43_phy_write(dev, cmd_regs[i],
+					      phy_ht->tx_pwr_idx[i]);
+	}
+
+	phy_ht->tx_pwr_ctl = enable;
+}
+
+static void b43_phy_ht_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
+{
+	struct b43_phy_ht *phy_ht = dev->phy.ht;
+	static const u16 base[] = { 0x840, 0x860, 0x880 };
+	u16 save_regs[3][3];
+	s32 rssi_buf[6];
+	int core;
+
+	for (core = 0; core < 3; core++) {
+		save_regs[core][1] = b43_phy_read(dev, base[core] + 6);
+		save_regs[core][2] = b43_phy_read(dev, base[core] + 7);
+		save_regs[core][0] = b43_phy_read(dev, base[core] + 0);
+
+		b43_phy_write(dev, base[core] + 6, 0);
+		b43_phy_mask(dev, base[core] + 7, ~0xF); /* 0xF? Or just 0x6? */
+		b43_phy_set(dev, base[core] + 0, 0x0400);
+		b43_phy_set(dev, base[core] + 0, 0x1000);
+	}
+
+	b43_phy_ht_tx_tone(dev);
+	udelay(20);
+	b43_phy_ht_poll_rssi(dev, HT_RSSI_TSSI_2G, rssi_buf, 1);
+	b43_phy_ht_stop_playback(dev);
+	b43_phy_ht_reset_cca(dev);
+
+	phy_ht->idle_tssi[0] = rssi_buf[0] & 0xff;
+	phy_ht->idle_tssi[1] = rssi_buf[2] & 0xff;
+	phy_ht->idle_tssi[2] = rssi_buf[4] & 0xff;
+
+	for (core = 0; core < 3; core++) {
+		b43_phy_write(dev, base[core] + 0, save_regs[core][0]);
+		b43_phy_write(dev, base[core] + 6, save_regs[core][1]);
+		b43_phy_write(dev, base[core] + 7, save_regs[core][2]);
+	}
+}
+
+static void b43_phy_ht_tssi_setup(struct b43_wldev *dev)
+{
+	static const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3, };
+	int core;
+
+	/* 0x159 is probably TX_SSI_MUX or TSSIG (by comparing to N-PHY) */
+	for (core = 0; core < 3; core++) {
+		b43_radio_set(dev, 0x8bf, 0x1);
+		b43_radio_write(dev, routing[core] | 0x0159, 0x0011);
+	}
+}
+
+static void b43_phy_ht_tx_power_ctl_setup(struct b43_wldev *dev)
+{
+	struct b43_phy_ht *phy_ht = dev->phy.ht;
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+
+	u8 *idle = phy_ht->idle_tssi;
+	u8 target[3];
+	s16 a1[3], b0[3], b1[3];
+
+	u16 freq = dev->phy.chandef->chan->center_freq;
+	int i, c;
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+		for (c = 0; c < 3; c++) {
+			target[c] = sprom->core_pwr_info[c].maxpwr_2g;
+			a1[c] = sprom->core_pwr_info[c].pa_2g[0];
+			b0[c] = sprom->core_pwr_info[c].pa_2g[1];
+			b1[c] = sprom->core_pwr_info[c].pa_2g[2];
+		}
+	} else if (freq >= 4900 && freq < 5100) {
+		for (c = 0; c < 3; c++) {
+			target[c] = sprom->core_pwr_info[c].maxpwr_5gl;
+			a1[c] = sprom->core_pwr_info[c].pa_5gl[0];
+			b0[c] = sprom->core_pwr_info[c].pa_5gl[1];
+			b1[c] = sprom->core_pwr_info[c].pa_5gl[2];
+		}
+	} else if (freq >= 5100 && freq < 5500) {
+		for (c = 0; c < 3; c++) {
+			target[c] = sprom->core_pwr_info[c].maxpwr_5g;
+			a1[c] = sprom->core_pwr_info[c].pa_5g[0];
+			b0[c] = sprom->core_pwr_info[c].pa_5g[1];
+			b1[c] = sprom->core_pwr_info[c].pa_5g[2];
+		}
+	} else if (freq >= 5500) {
+		for (c = 0; c < 3; c++) {
+			target[c] = sprom->core_pwr_info[c].maxpwr_5gh;
+			a1[c] = sprom->core_pwr_info[c].pa_5gh[0];
+			b0[c] = sprom->core_pwr_info[c].pa_5gh[1];
+			b1[c] = sprom->core_pwr_info[c].pa_5gh[2];
+		}
+	} else {
+		target[0] = target[1] = target[2] = 52;
+		a1[0] = a1[1] = a1[2] = -424;
+		b0[0] = b0[1] = b0[2] = 5612;
+		b1[0] = b1[1] = b1[2] = -1393;
+	}
+
+	b43_phy_set(dev, B43_PHY_HT_TSSIMODE, B43_PHY_HT_TSSIMODE_EN);
+	b43_phy_mask(dev, B43_PHY_HT_TXPCTL_CMD_C1,
+		     ~B43_PHY_HT_TXPCTL_CMD_C1_PCTLEN & 0xFFFF);
+
+	/* TODO: Does it depend on sprom->fem.ghz2.tssipos? */
+	b43_phy_set(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, 0x4000);
+
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1,
+			~B43_PHY_HT_TXPCTL_CMD_C1_INIT, 0x19);
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C2,
+			~B43_PHY_HT_TXPCTL_CMD_C2_INIT, 0x19);
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C3,
+			~B43_PHY_HT_TXPCTL_CMD_C3_INIT, 0x19);
+
+	b43_phy_set(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI,
+		    B43_PHY_HT_TXPCTL_IDLE_TSSI_BINF);
+
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI,
+			~B43_PHY_HT_TXPCTL_IDLE_TSSI_C1,
+			idle[0] << B43_PHY_HT_TXPCTL_IDLE_TSSI_C1_SHIFT);
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI,
+			~B43_PHY_HT_TXPCTL_IDLE_TSSI_C2,
+			idle[1] << B43_PHY_HT_TXPCTL_IDLE_TSSI_C2_SHIFT);
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI2,
+			~B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3,
+			idle[2] << B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3_SHIFT);
+
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_N, ~B43_PHY_HT_TXPCTL_N_TSSID,
+			0xf0);
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_N, ~B43_PHY_HT_TXPCTL_N_NPTIL2,
+			0x3 << B43_PHY_HT_TXPCTL_N_NPTIL2_SHIFT);
+#if 0
+	/* TODO: what to mask/set? */
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1, 0x800, 0)
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1, 0x400, 0)
+#endif
+
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR,
+			~B43_PHY_HT_TXPCTL_TARG_PWR_C1,
+			target[0] << B43_PHY_HT_TXPCTL_TARG_PWR_C1_SHIFT);
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR,
+			~B43_PHY_HT_TXPCTL_TARG_PWR_C2 & 0xFFFF,
+			target[1] << B43_PHY_HT_TXPCTL_TARG_PWR_C2_SHIFT);
+	b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR2,
+			~B43_PHY_HT_TXPCTL_TARG_PWR2_C3,
+			target[2] << B43_PHY_HT_TXPCTL_TARG_PWR2_C3_SHIFT);
+
+	for (c = 0; c < 3; c++) {
+		s32 num, den, pwr;
+		u32 regval[64];
+
+		for (i = 0; i < 64; i++) {
+			num = 8 * (16 * b0[c] + b1[c] * i);
+			den = 32768 + a1[c] * i;
+			pwr = max((4 * num + den / 2) / den, -8);
+			regval[i] = pwr;
+		}
+		b43_httab_write_bulk(dev, B43_HTTAB16(26 + c, 0), 64, regval);
+	}
+}
+
+/**************************************************
+ * Channel switching ops.
+ **************************************************/
+
+static void b43_phy_ht_spur_avoid(struct b43_wldev *dev,
+				  struct ieee80211_channel *new_channel)
+{
+	struct bcma_device *core = dev->dev->bdev;
+	int spuravoid = 0;
+
+	/* Check for 13 and 14 is just a guess, we don't have enough logs. */
+	if (new_channel->hw_value == 13 || new_channel->hw_value == 14)
+		spuravoid = 1;
+	bcma_core_pll_ctl(core, B43_BCMA_CLKCTLST_PHY_PLL_REQ, 0, false);
+	bcma_pmu_spuravoid_pllupdate(&core->bus->drv_cc, spuravoid);
+	bcma_core_pll_ctl(core,
+			  B43_BCMA_CLKCTLST_80211_PLL_REQ |
+			  B43_BCMA_CLKCTLST_PHY_PLL_REQ,
+			  B43_BCMA_CLKCTLST_80211_PLL_ST |
+			  B43_BCMA_CLKCTLST_PHY_PLL_ST, false);
+
+	b43_mac_switch_freq(dev, spuravoid);
+
+	b43_wireless_core_phy_pll_reset(dev);
+
+	if (spuravoid)
+		b43_phy_set(dev, B43_PHY_HT_BBCFG, B43_PHY_HT_BBCFG_RSTRX);
+	else
+		b43_phy_mask(dev, B43_PHY_HT_BBCFG,
+				~B43_PHY_HT_BBCFG_RSTRX & 0xFFFF);
+
+	b43_phy_ht_reset_cca(dev);
+}
+
+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)
+{
+	if (new_channel->band == NL80211_BAND_5GHZ) {
+		/* Switch to 2 GHz for a moment to access B-PHY regs */
+		b43_phy_mask(dev, B43_PHY_HT_BANDCTL, ~B43_PHY_HT_BANDCTL_5GHZ);
+
+		b43_phy_ht_bphy_reset(dev, true);
+
+		/* Switch to 5 GHz */
+		b43_phy_set(dev, B43_PHY_HT_BANDCTL, B43_PHY_HT_BANDCTL_5GHZ);
+	} else {
+		/* Switch to 2 GHz */
+		b43_phy_mask(dev, B43_PHY_HT_BANDCTL, ~B43_PHY_HT_BANDCTL_5GHZ);
+
+		b43_phy_ht_bphy_reset(dev, false);
+	}
+
+	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);
+
+	if (new_channel->hw_value == 14) {
+		b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_OFDM_EN, 0);
+		b43_phy_set(dev, B43_PHY_HT_TEST, 0x0800);
+	} else {
+		b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_OFDM_EN,
+				      B43_PHY_HT_CLASS_CTL_OFDM_EN);
+		if (new_channel->band == NL80211_BAND_2GHZ)
+			b43_phy_mask(dev, B43_PHY_HT_TEST, ~0x840);
+	}
+
+	if (1) /* TODO: On N it's for early devices only, what about HT? */
+		b43_phy_ht_tx_power_fix(dev);
+
+	b43_phy_ht_spur_avoid(dev, new_channel);
+
+	b43_phy_write(dev, 0x017e, 0x3830);
+}
+
+static int b43_phy_ht_set_channel(struct b43_wldev *dev,
+				  struct ieee80211_channel *channel,
+				  enum nl80211_channel_type channel_type)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	const struct b43_phy_ht_channeltab_e_radio2059 *chent_r2059 = NULL;
+
+	if (phy->radio_ver == 0x2059) {
+		chent_r2059 = b43_phy_ht_get_channeltab_e_r2059(dev,
+							channel->center_freq);
+		if (!chent_r2059)
+			return -ESRCH;
+	} else {
+		return -ESRCH;
+	}
+
+	/* TODO: In case of N-PHY some bandwidth switching goes here */
+
+	if (phy->radio_ver == 0x2059) {
+		b43_radio_2059_channel_setup(dev, chent_r2059);
+		b43_phy_ht_channel_setup(dev, &(chent_r2059->phy_regs),
+					 channel);
+	} else {
+		return -ESRCH;
+	}
+
+	return 0;
+}
+
+/**************************************************
+ * Basic PHY ops.
+ **************************************************/
+
+static int b43_phy_ht_op_allocate(struct b43_wldev *dev)
+{
+	struct b43_phy_ht *phy_ht;
+
+	phy_ht = kzalloc(sizeof(*phy_ht), GFP_KERNEL);
+	if (!phy_ht)
+		return -ENOMEM;
+	dev->phy.ht = phy_ht;
+
+	return 0;
+}
+
+static void b43_phy_ht_op_prepare_structs(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_ht *phy_ht = phy->ht;
+	int i;
+
+	memset(phy_ht, 0, sizeof(*phy_ht));
+
+	phy_ht->tx_pwr_ctl = true;
+	for (i = 0; i < 3; i++)
+		phy_ht->tx_pwr_idx[i] = B43_PHY_HT_TXPCTL_CMD_C1_INIT + 1;
+
+	for (i = 0; i < 3; i++)
+		phy_ht->bb_mult_save[i] = -1;
+}
+
+static int b43_phy_ht_op_init(struct b43_wldev *dev)
+{
+	struct b43_phy_ht *phy_ht = dev->phy.ht;
+	u16 tmp;
+	u16 clip_state[3];
+	bool saved_tx_pwr_ctl;
+
+	if (dev->dev->bus_type != B43_BUS_BCMA) {
+		b43err(dev->wl, "HT-PHY is supported only on BCMA bus!\n");
+		return -EOPNOTSUPP;
+	}
+
+	b43_phy_ht_tables_init(dev);
+
+	b43_phy_mask(dev, 0x0be, ~0x2);
+	b43_phy_set(dev, 0x23f, 0x7ff);
+	b43_phy_set(dev, 0x240, 0x7ff);
+	b43_phy_set(dev, 0x241, 0x7ff);
+
+	b43_phy_ht_zero_extg(dev);
+
+	b43_phy_mask(dev, B43_PHY_EXTG(0), ~0x3);
+
+	b43_phy_write(dev, B43_PHY_HT_AFE_C1_OVER, 0);
+	b43_phy_write(dev, B43_PHY_HT_AFE_C2_OVER, 0);
+	b43_phy_write(dev, B43_PHY_HT_AFE_C3_OVER, 0);
+
+	b43_phy_write(dev, B43_PHY_EXTG(0x103), 0x20);
+	b43_phy_write(dev, B43_PHY_EXTG(0x101), 0x20);
+	b43_phy_write(dev, 0x20d, 0xb8);
+	b43_phy_write(dev, B43_PHY_EXTG(0x14f), 0xc8);
+	b43_phy_write(dev, 0x70, 0x50);
+	b43_phy_write(dev, 0x1ff, 0x30);
+
+	if (0) /* TODO: condition */
+		; /* TODO: PHY op on reg 0x217 */
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
+		b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_CCK_EN, 0);
+	else
+		b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_CCK_EN,
+				      B43_PHY_HT_CLASS_CTL_CCK_EN);
+
+	b43_phy_set(dev, 0xb1, 0x91);
+	b43_phy_write(dev, 0x32f, 0x0003);
+	b43_phy_write(dev, 0x077, 0x0010);
+	b43_phy_write(dev, 0x0b4, 0x0258);
+	b43_phy_mask(dev, 0x17e, ~0x4000);
+
+	b43_phy_write(dev, 0x0b9, 0x0072);
+
+	b43_httab_write_few(dev, B43_HTTAB16(7, 0x14e), 2, 0x010f, 0x010f);
+	b43_httab_write_few(dev, B43_HTTAB16(7, 0x15e), 2, 0x010f, 0x010f);
+	b43_httab_write_few(dev, B43_HTTAB16(7, 0x16e), 2, 0x010f, 0x010f);
+
+	b43_phy_ht_afe_unk1(dev);
+
+	b43_httab_write_few(dev, B43_HTTAB16(7, 0x130), 9, 0x777, 0x111, 0x111,
+			    0x777, 0x111, 0x111, 0x777, 0x111, 0x111);
+
+	b43_httab_write(dev, B43_HTTAB16(7, 0x120), 0x0777);
+	b43_httab_write(dev, B43_HTTAB16(7, 0x124), 0x0777);
+
+	b43_httab_write(dev, B43_HTTAB16(8, 0x00), 0x02);
+	b43_httab_write(dev, B43_HTTAB16(8, 0x10), 0x02);
+	b43_httab_write(dev, B43_HTTAB16(8, 0x20), 0x02);
+
+	b43_httab_write_few(dev, B43_HTTAB16(8, 0x08), 4,
+			    0x8e, 0x96, 0x96, 0x96);
+	b43_httab_write_few(dev, B43_HTTAB16(8, 0x18), 4,
+			    0x8f, 0x9f, 0x9f, 0x9f);
+	b43_httab_write_few(dev, B43_HTTAB16(8, 0x28), 4,
+			    0x8f, 0x9f, 0x9f, 0x9f);
+
+	b43_httab_write_few(dev, B43_HTTAB16(8, 0x0c), 4, 0x2, 0x2, 0x2, 0x2);
+	b43_httab_write_few(dev, B43_HTTAB16(8, 0x1c), 4, 0x2, 0x2, 0x2, 0x2);
+	b43_httab_write_few(dev, B43_HTTAB16(8, 0x2c), 4, 0x2, 0x2, 0x2, 0x2);
+
+	b43_phy_maskset(dev, 0x0280, 0xff00, 0x3e);
+	b43_phy_maskset(dev, 0x0283, 0xff00, 0x3e);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0x0141), 0xff00, 0x46);
+	b43_phy_maskset(dev, 0x0283, 0xff00, 0x40);
+
+	b43_httab_write_few(dev, B43_HTTAB16(00, 0x8), 4,
+			    0x09, 0x0e, 0x13, 0x18);
+	b43_httab_write_few(dev, B43_HTTAB16(01, 0x8), 4,
+			    0x09, 0x0e, 0x13, 0x18);
+	/* TODO: Did wl mean 2 instead of 40? */
+	b43_httab_write_few(dev, B43_HTTAB16(40, 0x8), 4,
+			    0x09, 0x0e, 0x13, 0x18);
+
+	b43_phy_maskset(dev, B43_PHY_OFDM(0x24), 0x3f, 0xd);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0x64), 0x3f, 0xd);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0xa4), 0x3f, 0xd);
+
+	b43_phy_set(dev, B43_PHY_EXTG(0x060), 0x1);
+	b43_phy_set(dev, B43_PHY_EXTG(0x064), 0x1);
+	b43_phy_set(dev, B43_PHY_EXTG(0x080), 0x1);
+	b43_phy_set(dev, B43_PHY_EXTG(0x084), 0x1);
+
+	/* Copy some tables entries */
+	tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x144));
+	b43_httab_write(dev, B43_HTTAB16(7, 0x14a), tmp);
+	tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x154));
+	b43_httab_write(dev, B43_HTTAB16(7, 0x15a), tmp);
+	tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x164));
+	b43_httab_write(dev, B43_HTTAB16(7, 0x16a), tmp);
+
+	/* Reset CCA */
+	b43_phy_force_clock(dev, true);
+	tmp = b43_phy_read(dev, B43_PHY_HT_BBCFG);
+	b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp | B43_PHY_HT_BBCFG_RSTCCA);
+	b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp & ~B43_PHY_HT_BBCFG_RSTCCA);
+	b43_phy_force_clock(dev, false);
+
+	b43_mac_phy_clock_set(dev, true);
+
+	b43_phy_ht_pa_override(dev, false);
+	b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RX2TX);
+	b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX);
+	b43_phy_ht_pa_override(dev, true);
+
+	/* TODO: Should we restore it? Or store it in global PHY info? */
+	b43_phy_ht_classifier(dev, 0, 0);
+	b43_phy_ht_read_clip_detection(dev, clip_state);
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+		b43_phy_ht_bphy_init(dev);
+
+	b43_httab_write_bulk(dev, B43_HTTAB32(0x1a, 0xc0),
+			B43_HTTAB_1A_C0_LATE_SIZE, b43_httab_0x1a_0xc0_late);
+
+	saved_tx_pwr_ctl = phy_ht->tx_pwr_ctl;
+	b43_phy_ht_tx_power_fix(dev);
+	b43_phy_ht_tx_power_ctl(dev, false);
+	b43_phy_ht_tx_power_ctl_idle_tssi(dev);
+	b43_phy_ht_tx_power_ctl_setup(dev);
+	b43_phy_ht_tssi_setup(dev);
+	b43_phy_ht_tx_power_ctl(dev, saved_tx_pwr_ctl);
+
+	return 0;
+}
+
+static void b43_phy_ht_op_free(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_ht *phy_ht = phy->ht;
+
+	kfree(phy_ht);
+	phy->ht = NULL;
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */
+static void b43_phy_ht_op_software_rfkill(struct b43_wldev *dev,
+					bool blocked)
+{
+	if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
+		b43err(dev->wl, "MAC not suspended\n");
+
+	if (blocked) {
+		b43_phy_mask(dev, B43_PHY_HT_RF_CTL_CMD,
+			     ~B43_PHY_HT_RF_CTL_CMD_CHIP0_PU);
+	} else {
+		if (dev->phy.radio_ver == 0x2059)
+			b43_radio_2059_init(dev);
+		else
+			B43_WARN_ON(1);
+
+		b43_switch_channel(dev, dev->phy.channel);
+	}
+}
+
+static void b43_phy_ht_op_switch_analog(struct b43_wldev *dev, bool on)
+{
+	if (on) {
+		b43_phy_write(dev, B43_PHY_HT_AFE_C1, 0x00cd);
+		b43_phy_write(dev, B43_PHY_HT_AFE_C1_OVER, 0x0000);
+		b43_phy_write(dev, B43_PHY_HT_AFE_C2, 0x00cd);
+		b43_phy_write(dev, B43_PHY_HT_AFE_C2_OVER, 0x0000);
+		b43_phy_write(dev, B43_PHY_HT_AFE_C3, 0x00cd);
+		b43_phy_write(dev, B43_PHY_HT_AFE_C3_OVER, 0x0000);
+	} else {
+		b43_phy_write(dev, B43_PHY_HT_AFE_C1_OVER, 0x07ff);
+		b43_phy_write(dev, B43_PHY_HT_AFE_C1, 0x00fd);
+		b43_phy_write(dev, B43_PHY_HT_AFE_C2_OVER, 0x07ff);
+		b43_phy_write(dev, B43_PHY_HT_AFE_C2, 0x00fd);
+		b43_phy_write(dev, B43_PHY_HT_AFE_C3_OVER, 0x07ff);
+		b43_phy_write(dev, B43_PHY_HT_AFE_C3, 0x00fd);
+	}
+}
+
+static int b43_phy_ht_op_switch_channel(struct b43_wldev *dev,
+					unsigned int new_channel)
+{
+	struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan;
+	enum nl80211_channel_type channel_type =
+		cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef);
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+		if ((new_channel < 1) || (new_channel > 14))
+			return -EINVAL;
+	} else {
+		return -EINVAL;
+	}
+
+	return b43_phy_ht_set_channel(dev, channel, channel_type);
+}
+
+static unsigned int b43_phy_ht_op_get_default_chan(struct b43_wldev *dev)
+{
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+		return 11;
+	return 36;
+}
+
+/**************************************************
+ * R/W ops.
+ **************************************************/
+
+static void b43_phy_ht_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
+				 u16 set)
+{
+	b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
+	b43_write16(dev, B43_MMIO_PHY_DATA,
+		    (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
+}
+
+static u16 b43_phy_ht_op_radio_read(struct b43_wldev *dev, u16 reg)
+{
+	/* HT-PHY needs 0x200 for read access */
+	reg |= 0x200;
+
+	b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg);
+	return b43_read16(dev, B43_MMIO_RADIO24_DATA);
+}
+
+static void b43_phy_ht_op_radio_write(struct b43_wldev *dev, u16 reg,
+				      u16 value)
+{
+	b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg);
+	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.
+ **************************************************/
+
+const struct b43_phy_operations b43_phyops_ht = {
+	.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_maskset		= b43_phy_ht_op_maskset,
+	.radio_read		= b43_phy_ht_op_radio_read,
+	.radio_write		= b43_phy_ht_op_radio_write,
+	.software_rfkill	= b43_phy_ht_op_software_rfkill,
+	.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,
+};
diff --git a/drivers/net/wireless/broadcom/b43/phy_ht.h b/drivers/net/wireless/broadcom/b43/phy_ht.h
new file mode 100644
index 0000000..0467538
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/phy_ht.h
@@ -0,0 +1,142 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_PHY_HT_H_
+#define B43_PHY_HT_H_
+
+#include "phy_common.h"
+
+
+#define B43_PHY_HT_BBCFG			0x001 /* BB config */
+#define  B43_PHY_HT_BBCFG_RSTCCA		0x4000 /* Reset CCA */
+#define  B43_PHY_HT_BBCFG_RSTRX			0x8000 /* Reset RX */
+#define B43_PHY_HT_BANDCTL			0x009 /* Band control */
+#define  B43_PHY_HT_BANDCTL_5GHZ		0x0001 /* Use the 5GHz band */
+#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_CLASS_CTL			0x0B0 /* Classifier control */
+#define  B43_PHY_HT_CLASS_CTL_CCK_EN		0x0001 /* CCK enable */
+#define  B43_PHY_HT_CLASS_CTL_OFDM_EN		0x0002 /* OFDM enable */
+#define  B43_PHY_HT_CLASS_CTL_WAITED_EN		0x0004 /* Waited enable */
+#define B43_PHY_HT_IQLOCAL_CMDGCTL		0x0C2	/* I/Q LO cal command G control */
+#define B43_PHY_HT_SAMP_CMD			0x0C3	/* Sample command */
+#define  B43_PHY_HT_SAMP_CMD_STOP		0x0002	/* Stop */
+#define B43_PHY_HT_SAMP_LOOP_CNT		0x0C4	/* Sample loop count */
+#define B43_PHY_HT_SAMP_WAIT_CNT		0x0C5	/* Sample wait count */
+#define B43_PHY_HT_SAMP_DEP_CNT			0x0C6	/* Sample depth count */
+#define B43_PHY_HT_SAMP_STAT			0x0C7	/* Sample status */
+#define B43_PHY_HT_EST_PWR_C1			0x118
+#define B43_PHY_HT_EST_PWR_C2			0x119
+#define B43_PHY_HT_EST_PWR_C3			0x11A
+#define B43_PHY_HT_TSSIMODE			0x122	/* TSSI mode */
+#define  B43_PHY_HT_TSSIMODE_EN			0x0001	/* TSSI enable */
+#define  B43_PHY_HT_TSSIMODE_PDEN		0x0002	/* Power det enable */
+#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_TXPCTL_CMD_C1		0x1E7	/* TX power control command */
+#define  B43_PHY_HT_TXPCTL_CMD_C1_INIT		0x007F	/* Init */
+#define  B43_PHY_HT_TXPCTL_CMD_C1_COEFF		0x2000	/* Power control coefficients */
+#define  B43_PHY_HT_TXPCTL_CMD_C1_HWPCTLEN	0x4000	/* Hardware TX power control enable */
+#define  B43_PHY_HT_TXPCTL_CMD_C1_PCTLEN	0x8000	/* TX power control enable */
+#define B43_PHY_HT_TXPCTL_N			0x1E8	/* TX power control N num */
+#define  B43_PHY_HT_TXPCTL_N_TSSID		0x00FF	/* N TSSI delay */
+#define  B43_PHY_HT_TXPCTL_N_TSSID_SHIFT	0
+#define  B43_PHY_HT_TXPCTL_N_NPTIL2		0x0700	/* N PT integer log2 */
+#define  B43_PHY_HT_TXPCTL_N_NPTIL2_SHIFT	8
+#define B43_PHY_HT_TXPCTL_IDLE_TSSI		0x1E9	/* TX power control idle TSSI */
+#define  B43_PHY_HT_TXPCTL_IDLE_TSSI_C1		0x003F
+#define  B43_PHY_HT_TXPCTL_IDLE_TSSI_C1_SHIFT	0
+#define  B43_PHY_HT_TXPCTL_IDLE_TSSI_C2		0x3F00
+#define  B43_PHY_HT_TXPCTL_IDLE_TSSI_C2_SHIFT	8
+#define  B43_PHY_HT_TXPCTL_IDLE_TSSI_BINF	0x8000	/* Raw TSSI offset bin format */
+#define B43_PHY_HT_TXPCTL_TARG_PWR		0x1EA	/* TX power control target power */
+#define  B43_PHY_HT_TXPCTL_TARG_PWR_C1		0x00FF	/* Power 0 */
+#define  B43_PHY_HT_TXPCTL_TARG_PWR_C1_SHIFT	0
+#define  B43_PHY_HT_TXPCTL_TARG_PWR_C2		0xFF00	/* Power 1 */
+#define  B43_PHY_HT_TXPCTL_TARG_PWR_C2_SHIFT	8
+#define B43_PHY_HT_TX_PCTL_STATUS_C1		0x1ED
+#define B43_PHY_HT_TX_PCTL_STATUS_C2		0x1EE
+#define B43_PHY_HT_TXPCTL_CMD_C2		0x222
+#define  B43_PHY_HT_TXPCTL_CMD_C2_INIT		0x007F
+#define B43_PHY_HT_RSSI_C1			0x219
+#define B43_PHY_HT_RSSI_C2			0x21A
+#define B43_PHY_HT_RSSI_C3			0x21B
+
+#define B43_PHY_HT_C1_CLIP1THRES		B43_PHY_OFDM(0x00E)
+#define B43_PHY_HT_C2_CLIP1THRES		B43_PHY_OFDM(0x04E)
+#define B43_PHY_HT_C3_CLIP1THRES		B43_PHY_OFDM(0x08E)
+
+#define B43_PHY_HT_RF_SEQ_MODE			B43_PHY_EXTG(0x000)
+#define  B43_PHY_HT_RF_SEQ_MODE_CA_OVER		0x0001	/* Core active override */
+#define  B43_PHY_HT_RF_SEQ_MODE_TR_OVER		0x0002	/* Trigger override */
+#define B43_PHY_HT_RF_SEQ_TRIG			B43_PHY_EXTG(0x003)
+#define  B43_PHY_HT_RF_SEQ_TRIG_RX2TX		0x0001 /* RX2TX */
+#define  B43_PHY_HT_RF_SEQ_TRIG_TX2RX		0x0002 /* TX2RX */
+#define  B43_PHY_HT_RF_SEQ_TRIG_UPGH		0x0004 /* Update gain H */
+#define  B43_PHY_HT_RF_SEQ_TRIG_UPGL		0x0008 /* Update gain L */
+#define  B43_PHY_HT_RF_SEQ_TRIG_UPGU		0x0010 /* Update gain U */
+#define  B43_PHY_HT_RF_SEQ_TRIG_RST2RX		0x0020 /* Reset to RX */
+#define B43_PHY_HT_RF_SEQ_STATUS		B43_PHY_EXTG(0x004)
+/* Values for the status are the same as for the trigger */
+
+#define B43_PHY_HT_RF_CTL_CMD			0x810
+#define  B43_PHY_HT_RF_CTL_CMD_FORCE		0x0001
+#define  B43_PHY_HT_RF_CTL_CMD_CHIP0_PU		0x0002
+
+#define B43_PHY_HT_RF_CTL_INT_C1		B43_PHY_EXTG(0x04c)
+#define B43_PHY_HT_RF_CTL_INT_C2		B43_PHY_EXTG(0x06c)
+#define B43_PHY_HT_RF_CTL_INT_C3		B43_PHY_EXTG(0x08c)
+
+#define B43_PHY_HT_AFE_C1_OVER			B43_PHY_EXTG(0x110)
+#define B43_PHY_HT_AFE_C1			B43_PHY_EXTG(0x111)
+#define B43_PHY_HT_AFE_C2_OVER			B43_PHY_EXTG(0x114)
+#define B43_PHY_HT_AFE_C2			B43_PHY_EXTG(0x115)
+#define B43_PHY_HT_AFE_C3_OVER			B43_PHY_EXTG(0x118)
+#define B43_PHY_HT_AFE_C3			B43_PHY_EXTG(0x119)
+
+#define B43_PHY_HT_TXPCTL_CMD_C3		B43_PHY_EXTG(0x164)
+#define  B43_PHY_HT_TXPCTL_CMD_C3_INIT		0x007F
+#define B43_PHY_HT_TXPCTL_IDLE_TSSI2		B43_PHY_EXTG(0x165)	/* TX power control idle TSSI */
+#define  B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3	0x003F
+#define  B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3_SHIFT	0
+#define B43_PHY_HT_TXPCTL_TARG_PWR2		B43_PHY_EXTG(0x166)	/* TX power control target power */
+#define  B43_PHY_HT_TXPCTL_TARG_PWR2_C3		0x00FF
+#define  B43_PHY_HT_TXPCTL_TARG_PWR2_C3_SHIFT	0
+#define B43_PHY_HT_TX_PCTL_STATUS_C3		B43_PHY_EXTG(0x169)
+
+#define B43_PHY_B_BBCFG				B43_PHY_N_BMODE(0x001)
+#define  B43_PHY_B_BBCFG_RSTCCA			0x4000 /* Reset CCA */
+#define  B43_PHY_B_BBCFG_RSTRX			0x8000 /* Reset RX */
+#define B43_PHY_HT_TEST				B43_PHY_N_BMODE(0x00A)
+
+
+/* Values for PHY registers used on channel switching */
+struct b43_phy_ht_channeltab_e_phy {
+	u16 bw1;
+	u16 bw2;
+	u16 bw3;
+	u16 bw4;
+	u16 bw5;
+	u16 bw6;
+};
+
+
+struct b43_phy_ht {
+	u16 rf_ctl_int_save[3];
+
+	bool tx_pwr_ctl;
+	u8 tx_pwr_idx[3];
+
+	s32 bb_mult_save[3];
+
+	u8 idle_tssi[3];
+};
+
+
+struct b43_phy_operations;
+extern const struct b43_phy_operations b43_phyops_ht;
+
+#endif /* B43_PHY_HT_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/phy_lcn.c b/drivers/net/wireless/broadcom/b43/phy_lcn.c
new file mode 100644
index 0000000..63bd29f
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/phy_lcn.c
@@ -0,0 +1,855 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11n LCN-PHY support
+
+  Copyright (c) 2011 Rafał Miłecki <zajec5@gmail.com>
+
+  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.
+
+  This file incorporates work covered by the following copyright and
+  permission notice:
+
+      Copyright (c) 2010 Broadcom Corporation
+
+      Permission to use, copy, modify, and/or distribute this software for any
+      purpose with or without fee is hereby granted, provided that the above
+      copyright notice and this permission notice appear in all copies.
+*/
+
+#include <linux/slab.h>
+
+#include "b43.h"
+#include "phy_lcn.h"
+#include "tables_phy_lcn.h"
+#include "main.h"
+
+struct lcn_tx_gains {
+	u16 gm_gain;
+	u16 pga_gain;
+	u16 pad_gain;
+	u16 dac_gain;
+};
+
+struct lcn_tx_iir_filter {
+	u8 type;
+	u16 values[16];
+};
+
+enum lcn_sense_type {
+	B43_SENSE_TEMP,
+	B43_SENSE_VBAT,
+};
+
+/**************************************************
+ * Radio 2064.
+ **************************************************/
+
+/* wlc_lcnphy_radio_2064_channel_tune_4313 */
+static void b43_radio_2064_channel_setup(struct b43_wldev *dev)
+{
+	u16 save[2];
+
+	b43_radio_set(dev, 0x09d, 0x4);
+	b43_radio_write(dev, 0x09e, 0xf);
+
+	/* Channel specific values in theory, in practice always the same */
+	b43_radio_write(dev, 0x02a, 0xb);
+	b43_radio_maskset(dev, 0x030, ~0x3, 0xa);
+	b43_radio_maskset(dev, 0x091, ~0x3, 0);
+	b43_radio_maskset(dev, 0x038, ~0xf, 0x7);
+	b43_radio_maskset(dev, 0x030, ~0xc, 0x8);
+	b43_radio_maskset(dev, 0x05e, ~0xf, 0x8);
+	b43_radio_maskset(dev, 0x05e, ~0xf0, 0x80);
+	b43_radio_write(dev, 0x06c, 0x80);
+
+	save[0] = b43_radio_read(dev, 0x044);
+	save[1] = b43_radio_read(dev, 0x12b);
+
+	b43_radio_set(dev, 0x044, 0x7);
+	b43_radio_set(dev, 0x12b, 0xe);
+
+	/* TODO */
+
+	b43_radio_write(dev, 0x040, 0xfb);
+
+	b43_radio_write(dev, 0x041, 0x9a);
+	b43_radio_write(dev, 0x042, 0xa3);
+	b43_radio_write(dev, 0x043, 0x0c);
+
+	/* TODO */
+
+	b43_radio_set(dev, 0x044, 0x0c);
+	udelay(1);
+
+	b43_radio_write(dev, 0x044, save[0]);
+	b43_radio_write(dev, 0x12b, save[1]);
+
+	if (dev->phy.rev == 1) {
+		/* brcmsmac uses outdated 0x3 for 0x038 */
+		b43_radio_write(dev, 0x038, 0x0);
+		b43_radio_write(dev, 0x091, 0x7);
+	}
+}
+
+/* wlc_radio_2064_init */
+static void b43_radio_2064_init(struct b43_wldev *dev)
+{
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+		b43_radio_write(dev, 0x09c, 0x0020);
+		b43_radio_write(dev, 0x105, 0x0008);
+	} else {
+		/* TODO */
+	}
+	b43_radio_write(dev, 0x032, 0x0062);
+	b43_radio_write(dev, 0x033, 0x0019);
+	b43_radio_write(dev, 0x090, 0x0010);
+	b43_radio_write(dev, 0x010, 0x0000);
+	if (dev->phy.rev == 1) {
+		b43_radio_write(dev, 0x060, 0x007f);
+		b43_radio_write(dev, 0x061, 0x0072);
+		b43_radio_write(dev, 0x062, 0x007f);
+	}
+	b43_radio_write(dev, 0x01d, 0x0002);
+	b43_radio_write(dev, 0x01e, 0x0006);
+
+	b43_phy_write(dev, 0x4ea, 0x4688);
+	b43_phy_maskset(dev, 0x4eb, ~0x7, 0x2);
+	b43_phy_mask(dev, 0x4eb, ~0x01c0);
+	b43_phy_maskset(dev, 0x46a, 0xff00, 0x19);
+
+	b43_lcntab_write(dev, B43_LCNTAB16(0x00, 0x55), 0);
+
+	b43_radio_mask(dev, 0x05b, (u16) ~0xff02);
+	b43_radio_set(dev, 0x004, 0x40);
+	b43_radio_set(dev, 0x120, 0x10);
+	b43_radio_set(dev, 0x078, 0x80);
+	b43_radio_set(dev, 0x129, 0x2);
+	b43_radio_set(dev, 0x057, 0x1);
+	b43_radio_set(dev, 0x05b, 0x2);
+
+	/* TODO: wait for some bit to be set */
+	b43_radio_read(dev, 0x05c);
+
+	b43_radio_mask(dev, 0x05b, (u16) ~0xff02);
+	b43_radio_mask(dev, 0x057, (u16) ~0xff01);
+
+	b43_phy_write(dev, 0x933, 0x2d6b);
+	b43_phy_write(dev, 0x934, 0x2d6b);
+	b43_phy_write(dev, 0x935, 0x2d6b);
+	b43_phy_write(dev, 0x936, 0x2d6b);
+	b43_phy_write(dev, 0x937, 0x016b);
+
+	b43_radio_mask(dev, 0x057, (u16) ~0xff02);
+	b43_radio_write(dev, 0x0c2, 0x006f);
+}
+
+/**************************************************
+ * Various PHY ops
+ **************************************************/
+
+/* wlc_lcnphy_toggle_afe_pwdn */
+static void b43_phy_lcn_afe_set_unset(struct b43_wldev *dev)
+{
+	u16 afe_ctl2 = b43_phy_read(dev, B43_PHY_LCN_AFE_CTL2);
+	u16 afe_ctl1 = b43_phy_read(dev, B43_PHY_LCN_AFE_CTL1);
+
+	b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2 | 0x1);
+	b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1 | 0x1);
+
+	b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2 & ~0x1);
+	b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1 & ~0x1);
+
+	b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2);
+	b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1);
+}
+
+/* wlc_lcnphy_get_pa_gain */
+static u16 b43_phy_lcn_get_pa_gain(struct b43_wldev *dev)
+{
+	return (b43_phy_read(dev, 0x4fb) & 0x7f00) >> 8;
+}
+
+/* wlc_lcnphy_set_dac_gain */
+static void b43_phy_lcn_set_dac_gain(struct b43_wldev *dev, u16 dac_gain)
+{
+	u16 dac_ctrl;
+
+	dac_ctrl = b43_phy_read(dev, 0x439);
+	dac_ctrl = dac_ctrl & 0xc7f;
+	dac_ctrl = dac_ctrl | (dac_gain << 7);
+	b43_phy_maskset(dev, 0x439, ~0xfff, dac_ctrl);
+}
+
+/* wlc_lcnphy_set_bbmult */
+static void b43_phy_lcn_set_bbmult(struct b43_wldev *dev, u8 m0)
+{
+	b43_lcntab_write(dev, B43_LCNTAB16(0x00, 0x57), m0 << 8);
+}
+
+/* wlc_lcnphy_clear_tx_power_offsets */
+static void b43_phy_lcn_clear_tx_power_offsets(struct b43_wldev *dev)
+{
+	u8 i;
+
+	if (1) { /* FIXME */
+		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x340);
+		for (i = 0; i < 30; i++) {
+			b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0);
+			b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0);
+		}
+	}
+
+	b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x80);
+	for (i = 0; i < 64; i++) {
+		b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0);
+		b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0);
+	}
+}
+
+/* wlc_lcnphy_rev0_baseband_init */
+static void b43_phy_lcn_rev0_baseband_init(struct b43_wldev *dev)
+{
+	b43_radio_write(dev, 0x11c, 0);
+
+	b43_phy_write(dev, 0x43b, 0);
+	b43_phy_write(dev, 0x43c, 0);
+	b43_phy_write(dev, 0x44c, 0);
+	b43_phy_write(dev, 0x4e6, 0);
+	b43_phy_write(dev, 0x4f9, 0);
+	b43_phy_write(dev, 0x4b0, 0);
+	b43_phy_write(dev, 0x938, 0);
+	b43_phy_write(dev, 0x4b0, 0);
+	b43_phy_write(dev, 0x44e, 0);
+
+	b43_phy_set(dev, 0x567, 0x03);
+
+	b43_phy_set(dev, 0x44a, 0x44);
+	b43_phy_write(dev, 0x44a, 0x80);
+
+	if (!(dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM))
+		; /* TODO */
+	b43_phy_maskset(dev, 0x634, ~0xff, 0xc);
+	if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM) {
+		b43_phy_maskset(dev, 0x634, ~0xff, 0xa);
+		b43_phy_write(dev, 0x910, 0x1);
+	}
+
+	b43_phy_write(dev, 0x910, 0x1);
+
+	b43_phy_maskset(dev, 0x448, ~0x300, 0x100);
+	b43_phy_maskset(dev, 0x608, ~0xff, 0x17);
+	b43_phy_maskset(dev, 0x604, ~0x7ff, 0x3ea);
+}
+
+/* wlc_lcnphy_bu_tweaks */
+static void b43_phy_lcn_bu_tweaks(struct b43_wldev *dev)
+{
+	b43_phy_set(dev, 0x805, 0x1);
+
+	b43_phy_maskset(dev, 0x42f, ~0x7, 0x3);
+	b43_phy_maskset(dev, 0x030, ~0x7, 0x3);
+
+	b43_phy_write(dev, 0x414, 0x1e10);
+	b43_phy_write(dev, 0x415, 0x0640);
+
+	b43_phy_maskset(dev, 0x4df, (u16) ~0xff00, 0xf700);
+
+	b43_phy_set(dev, 0x44a, 0x44);
+	b43_phy_write(dev, 0x44a, 0x80);
+
+	b43_phy_maskset(dev, 0x434, ~0xff, 0xfd);
+	b43_phy_maskset(dev, 0x420, ~0xff, 0x10);
+
+	if (dev->dev->bus_sprom->board_rev >= 0x1204)
+		b43_radio_set(dev, 0x09b, 0xf0);
+
+	b43_phy_write(dev, 0x7d6, 0x0902);
+
+	b43_phy_maskset(dev, 0x429, ~0xf, 0x9);
+	b43_phy_maskset(dev, 0x429, ~(0x3f << 4), 0xe << 4);
+
+	if (dev->phy.rev == 1) {
+		b43_phy_maskset(dev, 0x423, ~0xff, 0x46);
+		b43_phy_maskset(dev, 0x411, ~0xff, 1);
+		b43_phy_set(dev, 0x434, 0xff); /* FIXME: update to wl */
+
+		/* TODO: wl operates on PHY 0x416, brcmsmac is outdated here */
+
+		b43_phy_maskset(dev, 0x656, ~0xf, 2);
+		b43_phy_set(dev, 0x44d, 4);
+
+		b43_radio_set(dev, 0x0f7, 0x4);
+		b43_radio_mask(dev, 0x0f1, ~0x3);
+		b43_radio_maskset(dev, 0x0f2, ~0xf8, 0x90);
+		b43_radio_maskset(dev, 0x0f3, ~0x3, 0x2);
+		b43_radio_maskset(dev, 0x0f3, ~0xf0, 0xa0);
+
+		b43_radio_set(dev, 0x11f, 0x2);
+
+		b43_phy_lcn_clear_tx_power_offsets(dev);
+
+		/* TODO: something more? */
+	}
+}
+
+/* wlc_lcnphy_vbat_temp_sense_setup */
+static void b43_phy_lcn_sense_setup(struct b43_wldev *dev,
+				    enum lcn_sense_type sense_type)
+{
+	u8 auxpga_vmidcourse, auxpga_vmidfine, auxpga_gain;
+	u16 auxpga_vmid;
+	u8 tx_pwr_idx;
+	u8 i;
+
+	u16 save_radio_regs[6][2] = {
+		{ 0x007, 0 }, { 0x0ff, 0 }, { 0x11f, 0 }, { 0x005, 0 },
+		{ 0x025, 0 }, { 0x112, 0 },
+	};
+	u16 save_phy_regs[14][2] = {
+		{ 0x503, 0 }, { 0x4a4, 0 }, { 0x4d0, 0 }, { 0x4d9, 0 },
+		{ 0x4da, 0 }, { 0x4a6, 0 }, { 0x938, 0 }, { 0x939, 0 },
+		{ 0x4d8, 0 }, { 0x4d0, 0 }, { 0x4d7, 0 }, { 0x4a5, 0 },
+		{ 0x40d, 0 }, { 0x4a2, 0 },
+	};
+	u16 save_radio_4a4;
+
+	msleep(1);
+
+	/* Save */
+	for (i = 0; i < 6; i++)
+		save_radio_regs[i][1] = b43_radio_read(dev,
+						       save_radio_regs[i][0]);
+	for (i = 0; i < 14; i++)
+		save_phy_regs[i][1] = b43_phy_read(dev, save_phy_regs[i][0]);
+	b43_mac_suspend(dev);
+	save_radio_4a4 = b43_radio_read(dev, 0x4a4);
+	/* wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); */
+	tx_pwr_idx = dev->phy.lcn->tx_pwr_curr_idx;
+
+	/* Setup */
+	/* TODO: wlc_lcnphy_set_tx_pwr_by_index(pi, 127); */
+	b43_radio_set(dev, 0x007, 0x1);
+	b43_radio_set(dev, 0x0ff, 0x10);
+	b43_radio_set(dev, 0x11f, 0x4);
+
+	b43_phy_mask(dev, 0x503, ~0x1);
+	b43_phy_mask(dev, 0x503, ~0x4);
+	b43_phy_mask(dev, 0x4a4, ~0x4000);
+	b43_phy_mask(dev, 0x4a4, (u16) ~0x8000);
+	b43_phy_mask(dev, 0x4d0, ~0x20);
+	b43_phy_set(dev, 0x4a5, 0xff);
+	b43_phy_maskset(dev, 0x4a5, ~0x7000, 0x5000);
+	b43_phy_mask(dev, 0x4a5, ~0x700);
+	b43_phy_maskset(dev, 0x40d, ~0xff, 64);
+	b43_phy_maskset(dev, 0x40d, ~0x700, 0x600);
+	b43_phy_maskset(dev, 0x4a2, ~0xff, 64);
+	b43_phy_maskset(dev, 0x4a2, ~0x700, 0x600);
+	b43_phy_maskset(dev, 0x4d9, ~0x70, 0x20);
+	b43_phy_maskset(dev, 0x4d9, ~0x700, 0x300);
+	b43_phy_maskset(dev, 0x4d9, ~0x7000, 0x1000);
+	b43_phy_mask(dev, 0x4da, ~0x1000);
+	b43_phy_set(dev, 0x4da, 0x2000);
+	b43_phy_set(dev, 0x4a6, 0x8000);
+
+	b43_radio_write(dev, 0x025, 0xc);
+	b43_radio_set(dev, 0x005, 0x8);
+	b43_phy_set(dev, 0x938, 0x4);
+	b43_phy_set(dev, 0x939, 0x4);
+	b43_phy_set(dev, 0x4a4, 0x1000);
+
+	/* FIXME: don't hardcode */
+	b43_lcntab_write(dev, B43_LCNTAB16(0x8, 0x6), 0x640);
+
+	switch (sense_type) {
+	case B43_SENSE_TEMP:
+		b43_phy_set(dev, 0x4d7, 0x8);
+		b43_phy_maskset(dev, 0x4d7, ~0x7000, 0x1000);
+		auxpga_vmidcourse = 8;
+		auxpga_vmidfine = 0x4;
+		auxpga_gain = 2;
+		b43_radio_set(dev, 0x082, 0x20);
+		break;
+	case B43_SENSE_VBAT:
+		b43_phy_set(dev, 0x4d7, 0x8);
+		b43_phy_maskset(dev, 0x4d7, ~0x7000, 0x3000);
+		auxpga_vmidcourse = 7;
+		auxpga_vmidfine = 0xa;
+		auxpga_gain = 2;
+		break;
+	}
+	auxpga_vmid = (0x200 | (auxpga_vmidcourse << 4) | auxpga_vmidfine);
+
+	b43_phy_set(dev, 0x4d8, 0x1);
+	b43_phy_maskset(dev, 0x4d8, ~(0x3ff << 2), auxpga_vmid << 2);
+	b43_phy_set(dev, 0x4d8, 0x2);
+	b43_phy_maskset(dev, 0x4d8, ~(0x7 << 12), auxpga_gain << 12);
+	b43_phy_set(dev, 0x4d0, 0x20);
+	b43_radio_write(dev, 0x112, 0x6);
+
+	b43_dummy_transmission(dev, true, false);
+	/* Wait if not done */
+	if (!(b43_phy_read(dev, 0x476) & 0x8000))
+		udelay(10);
+
+	/* Restore */
+	for (i = 0; i < 6; i++)
+		b43_radio_write(dev, save_radio_regs[i][0],
+				save_radio_regs[i][1]);
+	for (i = 0; i < 14; i++)
+		b43_phy_write(dev, save_phy_regs[i][0], save_phy_regs[i][1]);
+	/* TODO: wlc_lcnphy_set_tx_pwr_by_index(tx_pwr_idx) */
+	b43_radio_write(dev, 0x4a4, save_radio_4a4);
+
+	b43_mac_enable(dev);
+
+	msleep(1);
+}
+
+static bool b43_phy_lcn_load_tx_iir_cck_filter(struct b43_wldev *dev,
+					       u8 filter_type)
+{
+	int i, j;
+	u16 phy_regs[] = { 0x910, 0x91e, 0x91f, 0x924, 0x925, 0x926, 0x920,
+			   0x921, 0x927, 0x928, 0x929, 0x922, 0x923, 0x930,
+			   0x931, 0x932 };
+	/* Table is from brcmsmac, values for type 25 were outdated, probably
+	 * others need updating too */
+	struct lcn_tx_iir_filter tx_iir_filters_cck[] = {
+		{ 0,  { 1, 415, 1874, 64, 128, 64, 792, 1656, 64, 128, 64, 778,
+			1582, 64, 128, 64 } },
+		{ 1,  { 1, 402, 1847, 259, 59, 259, 671, 1794, 68, 54, 68, 608,
+			1863, 93, 167, 93 } },
+		{ 2,  { 1, 415, 1874, 64, 128, 64, 792, 1656, 192, 384, 192,
+			778, 1582, 64, 128, 64 } },
+		{ 3,  { 1, 302, 1841, 129, 258, 129, 658, 1720, 205, 410, 205,
+			754, 1760, 170, 340, 170 } },
+		{ 20, { 1, 360, 1884, 242, 1734, 242, 752, 1720, 205, 1845, 205,
+			767, 1760, 256, 185, 256 } },
+		{ 21, { 1, 360, 1884, 149, 1874, 149, 752, 1720, 205, 1883, 205,
+			767, 1760, 256, 273, 256 } },
+		{ 22, { 1, 360, 1884, 98, 1948, 98, 752, 1720, 205, 1924, 205,
+			767, 1760, 256, 352, 256 } },
+		{ 23, { 1, 350, 1884, 116, 1966, 116, 752, 1720, 205, 2008, 205,
+			767, 1760, 128, 233, 128 } },
+		{ 24, { 1, 325, 1884, 32, 40, 32, 756, 1720, 256, 471, 256, 766,
+			1760, 256, 1881, 256 } },
+		{ 25, { 1, 299, 1884, 51, 64, 51, 736, 1720, 256, 471, 256, 765,
+			1760, 262, 1878, 262 } },
+		/* brcmsmac version { 25, { 1, 299, 1884, 51, 64, 51, 736, 1720,
+		 * 256, 471, 256, 765, 1760, 256, 1881, 256 } }, */
+		{ 26, { 1, 277, 1943, 39, 117, 88, 637, 1838, 64, 192, 144, 614,
+			1864, 128, 384, 288 } },
+		{ 27, { 1, 245, 1943, 49, 147, 110, 626, 1838, 256, 768, 576,
+			613, 1864, 128, 384, 288 } },
+		{ 30, { 1, 302, 1841, 61, 122, 61, 658, 1720, 205, 410, 205,
+			754, 1760, 170, 340, 170 } },
+	};
+
+	for (i = 0; i < ARRAY_SIZE(tx_iir_filters_cck); i++) {
+		if (tx_iir_filters_cck[i].type == filter_type) {
+			for (j = 0; j < 16; j++)
+				b43_phy_write(dev, phy_regs[j],
+					      tx_iir_filters_cck[i].values[j]);
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static bool b43_phy_lcn_load_tx_iir_ofdm_filter(struct b43_wldev *dev,
+						u8 filter_type)
+{
+	int i, j;
+	u16 phy_regs[] = { 0x90f, 0x900, 0x901, 0x906, 0x907, 0x908, 0x902,
+			   0x903, 0x909, 0x90a, 0x90b, 0x904, 0x905, 0x90c,
+			   0x90d, 0x90e };
+	struct lcn_tx_iir_filter tx_iir_filters_ofdm[] = {
+		{ 0, { 0, 0xa2, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x100, 0x0,
+		       0x0, 0x278, 0xfea0, 0x80, 0x100, 0x80 } },
+		{ 1, { 0, 374, 0xFF79, 16, 32, 16, 799, 0xFE74, 50, 32, 50, 750,
+		       0xFE2B, 212, 0xFFCE, 212 } },
+		{ 2, { 0, 375, 0xFF16, 37, 76, 37, 799, 0xFE74, 32, 20, 32, 748,
+		       0xFEF2, 128, 0xFFE2, 128 } },
+	};
+
+	for (i = 0; i < ARRAY_SIZE(tx_iir_filters_ofdm); i++) {
+		if (tx_iir_filters_ofdm[i].type == filter_type) {
+			for (j = 0; j < 16; j++)
+				b43_phy_write(dev, phy_regs[j],
+					      tx_iir_filters_ofdm[i].values[j]);
+			return true;
+		}
+	}
+
+	return false;
+}
+
+/* wlc_lcnphy_set_tx_gain_override */
+static void b43_phy_lcn_set_tx_gain_override(struct b43_wldev *dev, bool enable)
+{
+	b43_phy_maskset(dev, 0x4b0, ~(0x1 << 7), enable << 7);
+	b43_phy_maskset(dev, 0x4b0, ~(0x1 << 14), enable << 14);
+	b43_phy_maskset(dev, 0x43b, ~(0x1 << 6), enable << 6);
+}
+
+/* wlc_lcnphy_set_tx_gain */
+static void b43_phy_lcn_set_tx_gain(struct b43_wldev *dev,
+				    struct lcn_tx_gains *target_gains)
+{
+	u16 pa_gain = b43_phy_lcn_get_pa_gain(dev);
+
+	b43_phy_write(dev, 0x4b5,
+		      (target_gains->gm_gain | (target_gains->pga_gain << 8)));
+	b43_phy_maskset(dev, 0x4fb, ~0x7fff,
+			(target_gains->pad_gain | (pa_gain << 8)));
+	b43_phy_write(dev, 0x4fc,
+		      (target_gains->gm_gain | (target_gains->pga_gain << 8)));
+	b43_phy_maskset(dev, 0x4fd, ~0x7fff,
+			(target_gains->pad_gain | (pa_gain << 8)));
+
+	b43_phy_lcn_set_dac_gain(dev, target_gains->dac_gain);
+	b43_phy_lcn_set_tx_gain_override(dev, true);
+}
+
+/* wlc_lcnphy_tx_pwr_ctrl_init */
+static void b43_phy_lcn_tx_pwr_ctl_init(struct b43_wldev *dev)
+{
+	struct lcn_tx_gains tx_gains;
+	u8 bbmult;
+
+	b43_mac_suspend(dev);
+
+	if (!dev->phy.lcn->hw_pwr_ctl_capable) {
+		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+			tx_gains.gm_gain = 4;
+			tx_gains.pga_gain = 12;
+			tx_gains.pad_gain = 12;
+			tx_gains.dac_gain = 0;
+			bbmult = 150;
+		} else {
+			tx_gains.gm_gain = 7;
+			tx_gains.pga_gain = 15;
+			tx_gains.pad_gain = 14;
+			tx_gains.dac_gain = 0;
+			bbmult = 150;
+		}
+		b43_phy_lcn_set_tx_gain(dev, &tx_gains);
+		b43_phy_lcn_set_bbmult(dev, bbmult);
+		b43_phy_lcn_sense_setup(dev, B43_SENSE_TEMP);
+	} else {
+		b43err(dev->wl, "TX power control not supported for this HW\n");
+	}
+
+	b43_mac_enable(dev);
+}
+
+/* wlc_lcnphy_txrx_spur_avoidance_mode */
+static void b43_phy_lcn_txrx_spur_avoidance_mode(struct b43_wldev *dev,
+						 bool enable)
+{
+	if (enable) {
+		b43_phy_write(dev, 0x942, 0x7);
+		b43_phy_write(dev, 0x93b, ((1 << 13) + 23));
+		b43_phy_write(dev, 0x93c, ((1 << 13) + 1989));
+
+		b43_phy_write(dev, 0x44a, 0x084);
+		b43_phy_write(dev, 0x44a, 0x080);
+		b43_phy_write(dev, 0x6d3, 0x2222);
+		b43_phy_write(dev, 0x6d3, 0x2220);
+	} else {
+		b43_phy_write(dev, 0x942, 0x0);
+		b43_phy_write(dev, 0x93b, ((0 << 13) + 23));
+		b43_phy_write(dev, 0x93c, ((0 << 13) + 1989));
+	}
+	b43_mac_switch_freq(dev, enable);
+}
+
+/**************************************************
+ * Channel switching ops.
+ **************************************************/
+
+/* wlc_lcnphy_set_chanspec_tweaks */
+static void b43_phy_lcn_set_channel_tweaks(struct b43_wldev *dev, int channel)
+{
+	struct bcma_drv_cc *cc = &dev->dev->bdev->bus->drv_cc;
+
+	b43_phy_maskset(dev, 0x448, ~0x300, (channel == 14) ? 0x200 : 0x100);
+
+	if (channel == 1 || channel == 2 || channel == 3 || channel == 4 ||
+	    channel == 9 || channel == 10 || channel == 11 || channel == 12) {
+		bcma_chipco_pll_write(cc, 0x2, 0x03000c04);
+		bcma_chipco_pll_maskset(cc, 0x3, 0x00ffffff, 0x0);
+		bcma_chipco_pll_write(cc, 0x4, 0x200005c0);
+
+		bcma_cc_set32(cc, BCMA_CC_PMU_CTL, 0x400);
+
+		b43_phy_write(dev, 0x942, 0);
+
+		b43_phy_lcn_txrx_spur_avoidance_mode(dev, false);
+		b43_phy_maskset(dev, 0x424, (u16) ~0xff00, 0x1b00);
+		b43_phy_write(dev, 0x425, 0x5907);
+	} else {
+		bcma_chipco_pll_write(cc, 0x2, 0x03140c04);
+		bcma_chipco_pll_maskset(cc, 0x3, 0x00ffffff, 0x333333);
+		bcma_chipco_pll_write(cc, 0x4, 0x202c2820);
+
+		bcma_cc_set32(cc, BCMA_CC_PMU_CTL, 0x400);
+
+		b43_phy_write(dev, 0x942, 0);
+
+		b43_phy_lcn_txrx_spur_avoidance_mode(dev, true);
+		b43_phy_maskset(dev, 0x424, (u16) ~0xff00, 0x1f00);
+		b43_phy_write(dev, 0x425, 0x590a);
+	}
+
+	b43_phy_set(dev, 0x44a, 0x44);
+	b43_phy_write(dev, 0x44a, 0x80);
+}
+
+/* wlc_phy_chanspec_set_lcnphy */
+static int b43_phy_lcn_set_channel(struct b43_wldev *dev,
+				   struct ieee80211_channel *channel,
+				   enum nl80211_channel_type channel_type)
+{
+	static const u16 sfo_cfg[14][2] = {
+		{965, 1087}, {967, 1085}, {969, 1082}, {971, 1080}, {973, 1078},
+		{975, 1076}, {977, 1073}, {979, 1071}, {981, 1069}, {983, 1067},
+		{985, 1065}, {987, 1063}, {989, 1060}, {994, 1055},
+	};
+
+	b43_phy_lcn_set_channel_tweaks(dev, channel->hw_value);
+
+	b43_phy_set(dev, 0x44a, 0x44);
+	b43_phy_write(dev, 0x44a, 0x80);
+
+	b43_radio_2064_channel_setup(dev);
+	mdelay(1);
+
+	b43_phy_lcn_afe_set_unset(dev);
+
+	b43_phy_write(dev, 0x657, sfo_cfg[channel->hw_value - 1][0]);
+	b43_phy_write(dev, 0x658, sfo_cfg[channel->hw_value - 1][1]);
+
+	if (channel->hw_value == 14) {
+		b43_phy_maskset(dev, 0x448, ~(0x3 << 8), (2) << 8);
+		b43_phy_lcn_load_tx_iir_cck_filter(dev, 3);
+	} else {
+		b43_phy_maskset(dev, 0x448, ~(0x3 << 8), (1) << 8);
+		/* brcmsmac uses filter_type 2, we follow wl with 25 */
+		b43_phy_lcn_load_tx_iir_cck_filter(dev, 25);
+	}
+	/* brcmsmac uses filter_type 2, we follow wl with 0 */
+	b43_phy_lcn_load_tx_iir_ofdm_filter(dev, 0);
+
+	b43_phy_maskset(dev, 0x4eb, ~(0x7 << 3), 0x1 << 3);
+
+	return 0;
+}
+
+/**************************************************
+ * Basic PHY ops.
+ **************************************************/
+
+static int b43_phy_lcn_op_allocate(struct b43_wldev *dev)
+{
+	struct b43_phy_lcn *phy_lcn;
+
+	phy_lcn = kzalloc(sizeof(*phy_lcn), GFP_KERNEL);
+	if (!phy_lcn)
+		return -ENOMEM;
+	dev->phy.lcn = phy_lcn;
+
+	return 0;
+}
+
+static void b43_phy_lcn_op_free(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_lcn *phy_lcn = phy->lcn;
+
+	kfree(phy_lcn);
+	phy->lcn = NULL;
+}
+
+static void b43_phy_lcn_op_prepare_structs(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_lcn *phy_lcn = phy->lcn;
+
+	memset(phy_lcn, 0, sizeof(*phy_lcn));
+}
+
+/* wlc_phy_init_lcnphy */
+static int b43_phy_lcn_op_init(struct b43_wldev *dev)
+{
+	struct bcma_drv_cc *cc = &dev->dev->bdev->bus->drv_cc;
+
+	b43_phy_set(dev, 0x44a, 0x80);
+	b43_phy_mask(dev, 0x44a, 0x7f);
+	b43_phy_set(dev, 0x6d1, 0x80);
+	b43_phy_write(dev, 0x6d0, 0x7);
+
+	b43_phy_lcn_afe_set_unset(dev);
+
+	b43_phy_write(dev, 0x60a, 0xa0);
+	b43_phy_write(dev, 0x46a, 0x19);
+	b43_phy_maskset(dev, 0x663, 0xFF00, 0x64);
+
+	b43_phy_lcn_tables_init(dev);
+
+	b43_phy_lcn_rev0_baseband_init(dev);
+	b43_phy_lcn_bu_tweaks(dev);
+
+	if (dev->phy.radio_ver == 0x2064)
+		b43_radio_2064_init(dev);
+	else
+		B43_WARN_ON(1);
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+		b43_phy_lcn_tx_pwr_ctl_init(dev);
+
+	b43_switch_channel(dev, dev->phy.channel);
+
+	bcma_chipco_regctl_maskset(cc, 0, 0xf, 0x9);
+	bcma_chipco_chipctl_maskset(cc, 0, 0, 0x03cddddd);
+
+	/* TODO */
+
+	b43_phy_set(dev, 0x448, 0x4000);
+	udelay(100);
+	b43_phy_mask(dev, 0x448, ~0x4000);
+
+	/* TODO */
+
+	return 0;
+}
+
+static void b43_phy_lcn_op_software_rfkill(struct b43_wldev *dev,
+					bool blocked)
+{
+	if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
+		b43err(dev->wl, "MAC not suspended\n");
+
+	if (blocked) {
+		b43_phy_mask(dev, B43_PHY_LCN_RF_CTL2, ~0x7c00);
+		b43_phy_set(dev, B43_PHY_LCN_RF_CTL1, 0x1f00);
+
+		b43_phy_mask(dev, B43_PHY_LCN_RF_CTL5, ~0x7f00);
+		b43_phy_mask(dev, B43_PHY_LCN_RF_CTL4, ~0x2);
+		b43_phy_set(dev, B43_PHY_LCN_RF_CTL3, 0x808);
+
+		b43_phy_mask(dev, B43_PHY_LCN_RF_CTL7, ~0x8);
+		b43_phy_set(dev, B43_PHY_LCN_RF_CTL6, 0x8);
+	} else {
+		b43_phy_mask(dev, B43_PHY_LCN_RF_CTL1, ~0x1f00);
+		b43_phy_mask(dev, B43_PHY_LCN_RF_CTL3, ~0x808);
+		b43_phy_mask(dev, B43_PHY_LCN_RF_CTL6, ~0x8);
+	}
+}
+
+static void b43_phy_lcn_op_switch_analog(struct b43_wldev *dev, bool on)
+{
+	if (on) {
+		b43_phy_mask(dev, B43_PHY_LCN_AFE_CTL1, ~0x7);
+	} else {
+		b43_phy_set(dev, B43_PHY_LCN_AFE_CTL2, 0x7);
+		b43_phy_set(dev, B43_PHY_LCN_AFE_CTL1, 0x7);
+	}
+}
+
+static int b43_phy_lcn_op_switch_channel(struct b43_wldev *dev,
+					unsigned int new_channel)
+{
+	struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan;
+	enum nl80211_channel_type channel_type =
+		cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef);
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+		if ((new_channel < 1) || (new_channel > 14))
+			return -EINVAL;
+	} else {
+		return -EINVAL;
+	}
+
+	return b43_phy_lcn_set_channel(dev, channel, channel_type);
+}
+
+static unsigned int b43_phy_lcn_op_get_default_chan(struct b43_wldev *dev)
+{
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+		return 1;
+	return 36;
+}
+
+static enum b43_txpwr_result
+b43_phy_lcn_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi)
+{
+	return B43_TXPWR_RES_DONE;
+}
+
+static void b43_phy_lcn_op_adjust_txpower(struct b43_wldev *dev)
+{
+}
+
+/**************************************************
+ * R/W ops.
+ **************************************************/
+
+static void b43_phy_lcn_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
+				   u16 set)
+{
+	b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
+	b43_write16(dev, B43_MMIO_PHY_DATA,
+		    (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
+}
+
+static u16 b43_phy_lcn_op_radio_read(struct b43_wldev *dev, u16 reg)
+{
+	/* LCN-PHY needs 0x200 for read access */
+	reg |= 0x200;
+
+	b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg);
+	return b43_read16(dev, B43_MMIO_RADIO24_DATA);
+}
+
+static void b43_phy_lcn_op_radio_write(struct b43_wldev *dev, u16 reg,
+				       u16 value)
+{
+	b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg);
+	b43_write16(dev, B43_MMIO_RADIO24_DATA, value);
+}
+
+/**************************************************
+ * 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_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,
+};
diff --git a/drivers/net/wireless/broadcom/b43/phy_lcn.h b/drivers/net/wireless/broadcom/b43/phy_lcn.h
new file mode 100644
index 0000000..0b1cfaf
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/phy_lcn.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_PHY_LCN_H_
+#define B43_PHY_LCN_H_
+
+#include "phy_common.h"
+
+
+#define B43_PHY_LCN_AFE_CTL1			B43_PHY_OFDM(0x03B)
+#define B43_PHY_LCN_AFE_CTL2			B43_PHY_OFDM(0x03C)
+#define B43_PHY_LCN_RF_CTL1			B43_PHY_OFDM(0x04C)
+#define B43_PHY_LCN_RF_CTL2			B43_PHY_OFDM(0x04D)
+#define B43_PHY_LCN_TABLE_ADDR			B43_PHY_OFDM(0x055) /* Table address */
+#define B43_PHY_LCN_TABLE_DATALO		B43_PHY_OFDM(0x056) /* Table data low */
+#define B43_PHY_LCN_TABLE_DATAHI		B43_PHY_OFDM(0x057) /* Table data high */
+#define B43_PHY_LCN_RF_CTL3			B43_PHY_OFDM(0x0B0)
+#define B43_PHY_LCN_RF_CTL4			B43_PHY_OFDM(0x0B1)
+#define B43_PHY_LCN_RF_CTL5			B43_PHY_OFDM(0x0B7)
+#define B43_PHY_LCN_RF_CTL6			B43_PHY_OFDM(0x0F9)
+#define B43_PHY_LCN_RF_CTL7			B43_PHY_OFDM(0x0FA)
+
+
+struct b43_phy_lcn {
+	bool hw_pwr_ctl;
+	bool hw_pwr_ctl_capable;
+	u8 tx_pwr_curr_idx;
+};
+
+
+struct b43_phy_operations;
+extern const struct b43_phy_operations b43_phyops_lcn;
+
+#endif /* B43_PHY_LCN_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/phy_lp.c b/drivers/net/wireless/broadcom/b43/phy_lp.c
new file mode 100644
index 0000000..6922cbb
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/phy_lp.c
@@ -0,0 +1,2716 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11a/g LP-PHY driver
+
+  Copyright (c) 2008-2009 Michael Buesch <m@bues.ch>
+  Copyright (c) 2009 Gábor Stefanik <netrolller.3d@gmail.com>
+
+  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 "main.h"
+#include "phy_lp.h"
+#include "phy_common.h"
+#include "tables_lpphy.h"
+
+
+static inline u16 channel2freq_lp(u8 channel)
+{
+	if (channel < 14)
+		return (2407 + 5 * channel);
+	else if (channel == 14)
+		return 2484;
+	else if (channel < 184)
+		return (5000 + 5 * channel);
+	else
+		return (4000 + 5 * channel);
+}
+
+static unsigned int b43_lpphy_op_get_default_chan(struct b43_wldev *dev)
+{
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+		return 1;
+	return 36;
+}
+
+static int b43_lpphy_op_allocate(struct b43_wldev *dev)
+{
+	struct b43_phy_lp *lpphy;
+
+	lpphy = kzalloc(sizeof(*lpphy), GFP_KERNEL);
+	if (!lpphy)
+		return -ENOMEM;
+	dev->phy.lp = lpphy;
+
+	return 0;
+}
+
+static void b43_lpphy_op_prepare_structs(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_lp *lpphy = phy->lp;
+
+	memset(lpphy, 0, sizeof(*lpphy));
+	lpphy->antenna = B43_ANTENNA_DEFAULT;
+
+	//TODO
+}
+
+static void b43_lpphy_op_free(struct b43_wldev *dev)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+
+	kfree(lpphy);
+	dev->phy.lp = NULL;
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/LP/ReadBandSrom */
+static void lpphy_read_band_sprom(struct b43_wldev *dev)
+{
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	u16 cckpo, maxpwr;
+	u32 ofdmpo;
+	int i;
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+		lpphy->tx_isolation_med_band = sprom->tri2g;
+		lpphy->bx_arch = sprom->bxa2g;
+		lpphy->rx_pwr_offset = sprom->rxpo2g;
+		lpphy->rssi_vf = sprom->rssismf2g;
+		lpphy->rssi_vc = sprom->rssismc2g;
+		lpphy->rssi_gs = sprom->rssisav2g;
+		lpphy->txpa[0] = sprom->pa0b0;
+		lpphy->txpa[1] = sprom->pa0b1;
+		lpphy->txpa[2] = sprom->pa0b2;
+		maxpwr = sprom->maxpwr_bg;
+		lpphy->max_tx_pwr_med_band = maxpwr;
+		cckpo = sprom->cck2gpo;
+		if (cckpo) {
+			ofdmpo = sprom->ofdm2gpo;
+			for (i = 0; i < 4; i++) {
+				lpphy->tx_max_rate[i] =
+					maxpwr - (ofdmpo & 0xF) * 2;
+				ofdmpo >>= 4;
+			}
+			ofdmpo = sprom->ofdm2gpo;
+			for (i = 4; i < 15; i++) {
+				lpphy->tx_max_rate[i] =
+					maxpwr - (ofdmpo & 0xF) * 2;
+				ofdmpo >>= 4;
+			}
+		} else {
+			u8 opo = sprom->opo;
+			for (i = 0; i < 4; i++)
+				lpphy->tx_max_rate[i] = maxpwr;
+			for (i = 4; i < 15; i++)
+				lpphy->tx_max_rate[i] = maxpwr - opo;
+		}
+	} else { /* 5GHz */
+		lpphy->tx_isolation_low_band = sprom->tri5gl;
+		lpphy->tx_isolation_med_band = sprom->tri5g;
+		lpphy->tx_isolation_hi_band = sprom->tri5gh;
+		lpphy->bx_arch = sprom->bxa5g;
+		lpphy->rx_pwr_offset = sprom->rxpo5g;
+		lpphy->rssi_vf = sprom->rssismf5g;
+		lpphy->rssi_vc = sprom->rssismc5g;
+		lpphy->rssi_gs = sprom->rssisav5g;
+		lpphy->txpa[0] = sprom->pa1b0;
+		lpphy->txpa[1] = sprom->pa1b1;
+		lpphy->txpa[2] = sprom->pa1b2;
+		lpphy->txpal[0] = sprom->pa1lob0;
+		lpphy->txpal[1] = sprom->pa1lob1;
+		lpphy->txpal[2] = sprom->pa1lob2;
+		lpphy->txpah[0] = sprom->pa1hib0;
+		lpphy->txpah[1] = sprom->pa1hib1;
+		lpphy->txpah[2] = sprom->pa1hib2;
+		maxpwr = sprom->maxpwr_al;
+		ofdmpo = sprom->ofdm5glpo;
+		lpphy->max_tx_pwr_low_band = maxpwr;
+		for (i = 4; i < 12; i++) {
+			lpphy->tx_max_ratel[i] = maxpwr - (ofdmpo & 0xF) * 2;
+			ofdmpo >>= 4;
+		}
+		maxpwr = sprom->maxpwr_a;
+		ofdmpo = sprom->ofdm5gpo;
+		lpphy->max_tx_pwr_med_band = maxpwr;
+		for (i = 4; i < 12; i++) {
+			lpphy->tx_max_rate[i] = maxpwr - (ofdmpo & 0xF) * 2;
+			ofdmpo >>= 4;
+		}
+		maxpwr = sprom->maxpwr_ah;
+		ofdmpo = sprom->ofdm5ghpo;
+		lpphy->max_tx_pwr_hi_band = maxpwr;
+		for (i = 4; i < 12; i++) {
+			lpphy->tx_max_rateh[i] = maxpwr - (ofdmpo & 0xF) * 2;
+			ofdmpo >>= 4;
+		}
+	}
+}
+
+static void lpphy_adjust_gain_table(struct b43_wldev *dev, u32 freq)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	u16 temp[3];
+	u16 isolation;
+
+	B43_WARN_ON(dev->phy.rev >= 2);
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+		isolation = lpphy->tx_isolation_med_band;
+	else if (freq <= 5320)
+		isolation = lpphy->tx_isolation_low_band;
+	else if (freq <= 5700)
+		isolation = lpphy->tx_isolation_med_band;
+	else
+		isolation = lpphy->tx_isolation_hi_band;
+
+	temp[0] = ((isolation - 26) / 12) << 12;
+	temp[1] = temp[0] + 0x1000;
+	temp[2] = temp[0] + 0x2000;
+
+	b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0), 3, temp);
+	b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0), 3, temp);
+}
+
+static void lpphy_table_init(struct b43_wldev *dev)
+{
+	u32 freq = channel2freq_lp(b43_lpphy_op_get_default_chan(dev));
+
+	if (dev->phy.rev < 2)
+		lpphy_rev0_1_table_init(dev);
+	else
+		lpphy_rev2plus_table_init(dev);
+
+	lpphy_init_tx_gain_table(dev);
+
+	if (dev->phy.rev < 2)
+		lpphy_adjust_gain_table(dev, freq);
+}
+
+static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
+{
+	struct ssb_bus *bus = dev->dev->sdev->bus;
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	u16 tmp, tmp2;
+
+	b43_phy_mask(dev, B43_LPPHY_AFE_DAC_CTL, 0xF7FF);
+	b43_phy_write(dev, B43_LPPHY_AFE_CTL, 0);
+	b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVR, 0);
+	b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_0, 0);
+	b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0);
+	b43_phy_set(dev, B43_LPPHY_AFE_DAC_CTL, 0x0004);
+	b43_phy_maskset(dev, B43_LPPHY_OFDMSYNCTHRESH0, 0xFF00, 0x0078);
+	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x5800);
+	b43_phy_write(dev, B43_LPPHY_ADC_COMPENSATION_CTL, 0x0016);
+	b43_phy_maskset(dev, B43_LPPHY_AFE_ADC_CTL_0, 0xFFF8, 0x0004);
+	b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0x00FF, 0x5400);
+	b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0x00FF, 0x2400);
+	b43_phy_maskset(dev, B43_LPPHY_LOWGAINDB, 0x00FF, 0x2100);
+	b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0x0006);
+	b43_phy_mask(dev, B43_LPPHY_RX_RADIO_CTL, 0xFFFE);
+	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x0005);
+	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC1F, 0x0180);
+	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x3C00);
+	b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xFFF0, 0x0005);
+	b43_phy_maskset(dev, B43_LPPHY_GAIN_MISMATCH_LIMIT, 0xFFC0, 0x001A);
+	b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0xFF00, 0x00B3);
+	b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0x00FF, 0xAD00);
+	b43_phy_maskset(dev, B43_LPPHY_INPUT_PWRDB,
+			0xFF00, lpphy->rx_pwr_offset);
+	if ((sprom->boardflags_lo & B43_BFL_FEM) &&
+	   ((b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ||
+	   (sprom->boardflags_hi & B43_BFH_PAREF))) {
+		ssb_pmu_set_ldo_voltage(&bus->chipco, LDO_PAREF, 0x28);
+		ssb_pmu_set_ldo_paref(&bus->chipco, true);
+		if (dev->phy.rev == 0) {
+			b43_phy_maskset(dev, B43_LPPHY_LP_RF_SIGNAL_LUT,
+					0xFFCF, 0x0010);
+		}
+		b43_lptab_write(dev, B43_LPTAB16(11, 7), 60);
+	} else {
+		ssb_pmu_set_ldo_paref(&bus->chipco, false);
+		b43_phy_maskset(dev, B43_LPPHY_LP_RF_SIGNAL_LUT,
+				0xFFCF, 0x0020);
+		b43_lptab_write(dev, B43_LPTAB16(11, 7), 100);
+	}
+	tmp = lpphy->rssi_vf | lpphy->rssi_vc << 4 | 0xA000;
+	b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_0, tmp);
+	if (sprom->boardflags_hi & B43_BFH_RSSIINV)
+		b43_phy_maskset(dev, B43_LPPHY_AFE_RSSI_CTL_1, 0xF000, 0x0AAA);
+	else
+		b43_phy_maskset(dev, B43_LPPHY_AFE_RSSI_CTL_1, 0xF000, 0x02AA);
+	b43_lptab_write(dev, B43_LPTAB16(11, 1), 24);
+	b43_phy_maskset(dev, B43_LPPHY_RX_RADIO_CTL,
+			0xFFF9, (lpphy->bx_arch << 1));
+	if (dev->phy.rev == 1 &&
+	   (sprom->boardflags_hi & B43_BFH_FEM_BT)) {
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x000A);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0x3F00, 0x0900);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x000A);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0B00);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x000A);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0400);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x000A);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0B00);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_5, 0xFFC0, 0x000A);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_5, 0xC0FF, 0x0900);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_6, 0xFFC0, 0x000A);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_6, 0xC0FF, 0x0B00);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_7, 0xFFC0, 0x000A);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_7, 0xC0FF, 0x0900);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xFFC0, 0x000A);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xC0FF, 0x0B00);
+	} else if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ ||
+		   (dev->dev->board_type == SSB_BOARD_BU4312) ||
+		   (dev->phy.rev == 0 && (sprom->boardflags_lo & B43_BFL_FEM))) {
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0001);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0400);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0001);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0500);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x0002);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0800);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0002);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0A00);
+	} else if (dev->phy.rev == 1 ||
+		  (sprom->boardflags_lo & B43_BFL_FEM)) {
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0004);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0800);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0004);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0C00);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x0002);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0100);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0002);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0300);
+	} else {
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x000A);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0900);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x000A);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0B00);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x0006);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0500);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0006);
+		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0700);
+	}
+	if (dev->phy.rev == 1 && (sprom->boardflags_hi & B43_BFH_PAREF)) {
+		b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_5, B43_LPPHY_TR_LOOKUP_1);
+		b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_6, B43_LPPHY_TR_LOOKUP_2);
+		b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_7, B43_LPPHY_TR_LOOKUP_3);
+		b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_8, B43_LPPHY_TR_LOOKUP_4);
+	}
+	if ((sprom->boardflags_hi & B43_BFH_FEM_BT) &&
+	    (dev->dev->chip_id == 0x5354) &&
+	    (dev->dev->chip_pkg == SSB_CHIPPACK_BCM4712S)) {
+		b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0006);
+		b43_phy_write(dev, B43_LPPHY_GPIO_SELECT, 0x0005);
+		b43_phy_write(dev, B43_LPPHY_GPIO_OUTEN, 0xFFFF);
+		//FIXME the Broadcom driver caches & delays this HF write!
+		b43_hf_write(dev, b43_hf_read(dev) | B43_HF_PR45960W);
+	}
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+		b43_phy_set(dev, B43_LPPHY_LP_PHY_CTL, 0x8000);
+		b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0040);
+		b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0x00FF, 0xA400);
+		b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xF0FF, 0x0B00);
+		b43_phy_maskset(dev, B43_LPPHY_SYNCPEAKCNT, 0xFFF8, 0x0007);
+		b43_phy_maskset(dev, B43_LPPHY_DSSS_CONFIRM_CNT, 0xFFF8, 0x0003);
+		b43_phy_maskset(dev, B43_LPPHY_DSSS_CONFIRM_CNT, 0xFFC7, 0x0020);
+		b43_phy_mask(dev, B43_LPPHY_IDLEAFTERPKTRXTO, 0x00FF);
+	} else { /* 5GHz */
+		b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0x7FFF);
+		b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFBF);
+	}
+	if (dev->phy.rev == 1) {
+		tmp = b43_phy_read(dev, B43_LPPHY_CLIPCTRTHRESH);
+		tmp2 = (tmp & 0x03E0) >> 5;
+		tmp2 |= tmp2 << 5;
+		b43_phy_write(dev, B43_LPPHY_4C3, tmp2);
+		tmp = b43_phy_read(dev, B43_LPPHY_GAINDIRECTMISMATCH);
+		tmp2 = (tmp & 0x1F00) >> 8;
+		tmp2 |= tmp2 << 5;
+		b43_phy_write(dev, B43_LPPHY_4C4, tmp2);
+		tmp = b43_phy_read(dev, B43_LPPHY_VERYLOWGAINDB);
+		tmp2 = tmp & 0x00FF;
+		tmp2 |= tmp << 8;
+		b43_phy_write(dev, B43_LPPHY_4C5, tmp2);
+	}
+}
+
+static void lpphy_save_dig_flt_state(struct b43_wldev *dev)
+{
+	static const u16 addr[] = {
+		B43_PHY_OFDM(0xC1),
+		B43_PHY_OFDM(0xC2),
+		B43_PHY_OFDM(0xC3),
+		B43_PHY_OFDM(0xC4),
+		B43_PHY_OFDM(0xC5),
+		B43_PHY_OFDM(0xC6),
+		B43_PHY_OFDM(0xC7),
+		B43_PHY_OFDM(0xC8),
+		B43_PHY_OFDM(0xCF),
+	};
+
+	static const u16 coefs[] = {
+		0xDE5E, 0xE832, 0xE331, 0x4D26,
+		0x0026, 0x1420, 0x0020, 0xFE08,
+		0x0008,
+	};
+
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(addr); i++) {
+		lpphy->dig_flt_state[i] = b43_phy_read(dev, addr[i]);
+		b43_phy_write(dev, addr[i], coefs[i]);
+	}
+}
+
+static void lpphy_restore_dig_flt_state(struct b43_wldev *dev)
+{
+	static const u16 addr[] = {
+		B43_PHY_OFDM(0xC1),
+		B43_PHY_OFDM(0xC2),
+		B43_PHY_OFDM(0xC3),
+		B43_PHY_OFDM(0xC4),
+		B43_PHY_OFDM(0xC5),
+		B43_PHY_OFDM(0xC6),
+		B43_PHY_OFDM(0xC7),
+		B43_PHY_OFDM(0xC8),
+		B43_PHY_OFDM(0xCF),
+	};
+
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(addr); i++)
+		b43_phy_write(dev, addr[i], lpphy->dig_flt_state[i]);
+}
+
+static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+
+	b43_phy_write(dev, B43_LPPHY_AFE_DAC_CTL, 0x50);
+	b43_phy_write(dev, B43_LPPHY_AFE_CTL, 0x8800);
+	b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVR, 0);
+	b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0);
+	b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_0, 0);
+	b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0);
+	b43_phy_write(dev, B43_PHY_OFDM(0xF9), 0);
+	b43_phy_write(dev, B43_LPPHY_TR_LOOKUP_1, 0);
+	b43_phy_set(dev, B43_LPPHY_ADC_COMPENSATION_CTL, 0x10);
+	b43_phy_maskset(dev, B43_LPPHY_OFDMSYNCTHRESH0, 0xFF00, 0xB4);
+	b43_phy_maskset(dev, B43_LPPHY_DCOFFSETTRANSIENT, 0xF8FF, 0x200);
+	b43_phy_maskset(dev, B43_LPPHY_DCOFFSETTRANSIENT, 0xFF00, 0x7F);
+	b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xFF0F, 0x40);
+	b43_phy_maskset(dev, B43_LPPHY_PREAMBLECONFIRMTO, 0xFF00, 0x2);
+	b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x4000);
+	b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x2000);
+	b43_phy_set(dev, B43_PHY_OFDM(0x10A), 0x1);
+	if (dev->dev->board_rev >= 0x18) {
+		b43_lptab_write(dev, B43_LPTAB32(17, 65), 0xEC);
+		b43_phy_maskset(dev, B43_PHY_OFDM(0x10A), 0xFF01, 0x14);
+	} else {
+		b43_phy_maskset(dev, B43_PHY_OFDM(0x10A), 0xFF01, 0x10);
+	}
+	b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0xFF00, 0xF4);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0x00FF, 0xF100);
+	b43_phy_write(dev, B43_LPPHY_CLIPTHRESH, 0x48);
+	b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0xFF00, 0x46);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0xE4), 0xFF00, 0x10);
+	b43_phy_maskset(dev, B43_LPPHY_PWR_THRESH1, 0xFFF0, 0x9);
+	b43_phy_mask(dev, B43_LPPHY_GAINDIRECTMISMATCH, ~0xF);
+	b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0x00FF, 0x5500);
+	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC1F, 0xA0);
+	b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xE0FF, 0x300);
+	b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0x00FF, 0x2A00);
+	if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
+		b43_phy_maskset(dev, B43_LPPHY_LOWGAINDB, 0x00FF, 0x2100);
+		b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0xA);
+	} else {
+		b43_phy_maskset(dev, B43_LPPHY_LOWGAINDB, 0x00FF, 0x1E00);
+		b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0xD);
+	}
+	b43_phy_maskset(dev, B43_PHY_OFDM(0xFE), 0xFFE0, 0x1F);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0xFF), 0xFFE0, 0xC);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0x100), 0xFF00, 0x19);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0xFF), 0x03FF, 0x3C00);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0xFE), 0xFC1F, 0x3E0);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0xFF), 0xFFE0, 0xC);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0x100), 0x00FF, 0x1900);
+	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x5800);
+	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x12);
+	b43_phy_maskset(dev, B43_LPPHY_GAINMISMATCH, 0x0FFF, 0x9000);
+
+	if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
+		b43_lptab_write(dev, B43_LPTAB16(0x08, 0x14), 0);
+		b43_lptab_write(dev, B43_LPTAB16(0x08, 0x12), 0x40);
+	}
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+		b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x40);
+		b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xF0FF, 0xB00);
+		b43_phy_maskset(dev, B43_LPPHY_SYNCPEAKCNT, 0xFFF8, 0x6);
+		b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0x00FF, 0x9D00);
+		b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0xFF00, 0xA1);
+		b43_phy_mask(dev, B43_LPPHY_IDLEAFTERPKTRXTO, 0x00FF);
+	} else /* 5GHz */
+		b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x40);
+
+	b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0xFF00, 0xB3);
+	b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0x00FF, 0xAD00);
+	b43_phy_maskset(dev, B43_LPPHY_INPUT_PWRDB, 0xFF00, lpphy->rx_pwr_offset);
+	b43_phy_set(dev, B43_LPPHY_RESET_CTL, 0x44);
+	b43_phy_write(dev, B43_LPPHY_RESET_CTL, 0x80);
+	b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_0, 0xA954);
+	b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_1,
+		      0x2000 | ((u16)lpphy->rssi_gs << 10) |
+		      ((u16)lpphy->rssi_vc << 4) | lpphy->rssi_vf);
+
+	if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
+		b43_phy_set(dev, B43_LPPHY_AFE_ADC_CTL_0, 0x1C);
+		b43_phy_maskset(dev, B43_LPPHY_AFE_CTL, 0x00FF, 0x8800);
+		b43_phy_maskset(dev, B43_LPPHY_AFE_ADC_CTL_1, 0xFC3C, 0x0400);
+	}
+
+	lpphy_save_dig_flt_state(dev);
+}
+
+static void lpphy_baseband_init(struct b43_wldev *dev)
+{
+	lpphy_table_init(dev);
+	if (dev->phy.rev >= 2)
+		lpphy_baseband_rev2plus_init(dev);
+	else
+		lpphy_baseband_rev0_1_init(dev);
+}
+
+struct b2062_freqdata {
+	u16 freq;
+	u8 data[6];
+};
+
+/* Initialize the 2062 radio. */
+static void lpphy_2062_init(struct b43_wldev *dev)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	struct ssb_bus *bus = dev->dev->sdev->bus;
+	u32 crystalfreq, tmp, ref;
+	unsigned int i;
+	const struct b2062_freqdata *fd = NULL;
+
+	static const struct b2062_freqdata freqdata_tab[] = {
+		{ .freq = 12000, .data[0] =  6, .data[1] =  6, .data[2] =  6,
+				 .data[3] =  6, .data[4] = 10, .data[5] =  6, },
+		{ .freq = 13000, .data[0] =  4, .data[1] =  4, .data[2] =  4,
+				 .data[3] =  4, .data[4] = 11, .data[5] =  7, },
+		{ .freq = 14400, .data[0] =  3, .data[1] =  3, .data[2] =  3,
+				 .data[3] =  3, .data[4] = 12, .data[5] =  7, },
+		{ .freq = 16200, .data[0] =  3, .data[1] =  3, .data[2] =  3,
+				 .data[3] =  3, .data[4] = 13, .data[5] =  8, },
+		{ .freq = 18000, .data[0] =  2, .data[1] =  2, .data[2] =  2,
+				 .data[3] =  2, .data[4] = 14, .data[5] =  8, },
+		{ .freq = 19200, .data[0] =  1, .data[1] =  1, .data[2] =  1,
+				 .data[3] =  1, .data[4] = 14, .data[5] =  9, },
+	};
+
+	b2062_upload_init_table(dev);
+
+	b43_radio_write(dev, B2062_N_TX_CTL3, 0);
+	b43_radio_write(dev, B2062_N_TX_CTL4, 0);
+	b43_radio_write(dev, B2062_N_TX_CTL5, 0);
+	b43_radio_write(dev, B2062_N_TX_CTL6, 0);
+	b43_radio_write(dev, B2062_N_PDN_CTL0, 0x40);
+	b43_radio_write(dev, B2062_N_PDN_CTL0, 0);
+	b43_radio_write(dev, B2062_N_CALIB_TS, 0x10);
+	b43_radio_write(dev, B2062_N_CALIB_TS, 0);
+	if (dev->phy.rev > 0) {
+		b43_radio_write(dev, B2062_S_BG_CTL1,
+			(b43_radio_read(dev, B2062_N_COMM2) >> 1) | 0x80);
+	}
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+		b43_radio_set(dev, B2062_N_TSSI_CTL0, 0x1);
+	else
+		b43_radio_mask(dev, B2062_N_TSSI_CTL0, ~0x1);
+
+	/* Get the crystal freq, in Hz. */
+	crystalfreq = bus->chipco.pmu.crystalfreq * 1000;
+
+	B43_WARN_ON(!(bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU));
+	B43_WARN_ON(crystalfreq == 0);
+
+	if (crystalfreq <= 30000000) {
+		lpphy->pdiv = 1;
+		b43_radio_mask(dev, B2062_S_RFPLL_CTL1, 0xFFFB);
+	} else {
+		lpphy->pdiv = 2;
+		b43_radio_set(dev, B2062_S_RFPLL_CTL1, 0x4);
+	}
+
+	tmp = (((800000000 * lpphy->pdiv + crystalfreq) /
+	      (2 * crystalfreq)) - 8) & 0xFF;
+	b43_radio_write(dev, B2062_S_RFPLL_CTL7, tmp);
+
+	tmp = (((100 * crystalfreq + 16000000 * lpphy->pdiv) /
+	      (32000000 * lpphy->pdiv)) - 1) & 0xFF;
+	b43_radio_write(dev, B2062_S_RFPLL_CTL18, tmp);
+
+	tmp = (((2 * crystalfreq + 1000000 * lpphy->pdiv) /
+	      (2000000 * lpphy->pdiv)) - 1) & 0xFF;
+	b43_radio_write(dev, B2062_S_RFPLL_CTL19, tmp);
+
+	ref = (1000 * lpphy->pdiv + 2 * crystalfreq) / (2000 * lpphy->pdiv);
+	ref &= 0xFFFF;
+	for (i = 0; i < ARRAY_SIZE(freqdata_tab); i++) {
+		if (ref < freqdata_tab[i].freq) {
+			fd = &freqdata_tab[i];
+			break;
+		}
+	}
+	if (!fd)
+		fd = &freqdata_tab[ARRAY_SIZE(freqdata_tab) - 1];
+	b43dbg(dev->wl, "b2062: Using crystal tab entry %u kHz.\n",
+	       fd->freq); /* FIXME: Keep this printk until the code is fully debugged. */
+
+	b43_radio_write(dev, B2062_S_RFPLL_CTL8,
+			((u16)(fd->data[1]) << 4) | fd->data[0]);
+	b43_radio_write(dev, B2062_S_RFPLL_CTL9,
+			((u16)(fd->data[3]) << 4) | fd->data[2]);
+	b43_radio_write(dev, B2062_S_RFPLL_CTL10, fd->data[4]);
+	b43_radio_write(dev, B2062_S_RFPLL_CTL11, fd->data[5]);
+}
+
+/* Initialize the 2063 radio. */
+static void lpphy_2063_init(struct b43_wldev *dev)
+{
+	b2063_upload_init_table(dev);
+	b43_radio_write(dev, B2063_LOGEN_SP5, 0);
+	b43_radio_set(dev, B2063_COMM8, 0x38);
+	b43_radio_write(dev, B2063_REG_SP1, 0x56);
+	b43_radio_mask(dev, B2063_RX_BB_CTL2, ~0x2);
+	b43_radio_write(dev, B2063_PA_SP7, 0);
+	b43_radio_write(dev, B2063_TX_RF_SP6, 0x20);
+	b43_radio_write(dev, B2063_TX_RF_SP9, 0x40);
+	if (dev->phy.rev == 2) {
+		b43_radio_write(dev, B2063_PA_SP3, 0xa0);
+		b43_radio_write(dev, B2063_PA_SP4, 0xa0);
+		b43_radio_write(dev, B2063_PA_SP2, 0x18);
+	} else {
+		b43_radio_write(dev, B2063_PA_SP3, 0x20);
+		b43_radio_write(dev, B2063_PA_SP2, 0x20);
+	}
+}
+
+struct lpphy_stx_table_entry {
+	u16 phy_offset;
+	u16 phy_shift;
+	u16 rf_addr;
+	u16 rf_shift;
+	u16 mask;
+};
+
+static const struct lpphy_stx_table_entry lpphy_stx_table[] = {
+	{ .phy_offset = 2, .phy_shift = 6, .rf_addr = 0x3d, .rf_shift = 3, .mask = 0x01, },
+	{ .phy_offset = 1, .phy_shift = 12, .rf_addr = 0x4c, .rf_shift = 1, .mask = 0x01, },
+	{ .phy_offset = 1, .phy_shift = 8, .rf_addr = 0x50, .rf_shift = 0, .mask = 0x7f, },
+	{ .phy_offset = 0, .phy_shift = 8, .rf_addr = 0x44, .rf_shift = 0, .mask = 0xff, },
+	{ .phy_offset = 1, .phy_shift = 0, .rf_addr = 0x4a, .rf_shift = 0, .mask = 0xff, },
+	{ .phy_offset = 0, .phy_shift = 4, .rf_addr = 0x4d, .rf_shift = 0, .mask = 0xff, },
+	{ .phy_offset = 1, .phy_shift = 4, .rf_addr = 0x4e, .rf_shift = 0, .mask = 0xff, },
+	{ .phy_offset = 0, .phy_shift = 12, .rf_addr = 0x4f, .rf_shift = 0, .mask = 0x0f, },
+	{ .phy_offset = 1, .phy_shift = 0, .rf_addr = 0x4f, .rf_shift = 4, .mask = 0x0f, },
+	{ .phy_offset = 3, .phy_shift = 0, .rf_addr = 0x49, .rf_shift = 0, .mask = 0x0f, },
+	{ .phy_offset = 4, .phy_shift = 3, .rf_addr = 0x46, .rf_shift = 4, .mask = 0x07, },
+	{ .phy_offset = 3, .phy_shift = 15, .rf_addr = 0x46, .rf_shift = 0, .mask = 0x01, },
+	{ .phy_offset = 4, .phy_shift = 0, .rf_addr = 0x46, .rf_shift = 1, .mask = 0x07, },
+	{ .phy_offset = 3, .phy_shift = 8, .rf_addr = 0x48, .rf_shift = 4, .mask = 0x07, },
+	{ .phy_offset = 3, .phy_shift = 11, .rf_addr = 0x48, .rf_shift = 0, .mask = 0x0f, },
+	{ .phy_offset = 3, .phy_shift = 4, .rf_addr = 0x49, .rf_shift = 4, .mask = 0x0f, },
+	{ .phy_offset = 2, .phy_shift = 15, .rf_addr = 0x45, .rf_shift = 0, .mask = 0x01, },
+	{ .phy_offset = 5, .phy_shift = 13, .rf_addr = 0x52, .rf_shift = 4, .mask = 0x07, },
+	{ .phy_offset = 6, .phy_shift = 0, .rf_addr = 0x52, .rf_shift = 7, .mask = 0x01, },
+	{ .phy_offset = 5, .phy_shift = 3, .rf_addr = 0x41, .rf_shift = 5, .mask = 0x07, },
+	{ .phy_offset = 5, .phy_shift = 6, .rf_addr = 0x41, .rf_shift = 0, .mask = 0x0f, },
+	{ .phy_offset = 5, .phy_shift = 10, .rf_addr = 0x42, .rf_shift = 5, .mask = 0x07, },
+	{ .phy_offset = 4, .phy_shift = 15, .rf_addr = 0x42, .rf_shift = 0, .mask = 0x01, },
+	{ .phy_offset = 5, .phy_shift = 0, .rf_addr = 0x42, .rf_shift = 1, .mask = 0x07, },
+	{ .phy_offset = 4, .phy_shift = 11, .rf_addr = 0x43, .rf_shift = 4, .mask = 0x0f, },
+	{ .phy_offset = 4, .phy_shift = 7, .rf_addr = 0x43, .rf_shift = 0, .mask = 0x0f, },
+	{ .phy_offset = 4, .phy_shift = 6, .rf_addr = 0x45, .rf_shift = 1, .mask = 0x01, },
+	{ .phy_offset = 2, .phy_shift = 7, .rf_addr = 0x40, .rf_shift = 4, .mask = 0x0f, },
+	{ .phy_offset = 2, .phy_shift = 11, .rf_addr = 0x40, .rf_shift = 0, .mask = 0x0f, },
+};
+
+static void lpphy_sync_stx(struct b43_wldev *dev)
+{
+	const struct lpphy_stx_table_entry *e;
+	unsigned int i;
+	u16 tmp;
+
+	for (i = 0; i < ARRAY_SIZE(lpphy_stx_table); i++) {
+		e = &lpphy_stx_table[i];
+		tmp = b43_radio_read(dev, e->rf_addr);
+		tmp >>= e->rf_shift;
+		tmp <<= e->phy_shift;
+		b43_phy_maskset(dev, B43_PHY_OFDM(0xF2 + e->phy_offset),
+				~(e->mask << e->phy_shift), tmp);
+	}
+}
+
+static void lpphy_radio_init(struct b43_wldev *dev)
+{
+	/* The radio is attached through the 4wire bus. */
+	b43_phy_set(dev, B43_LPPHY_FOURWIRE_CTL, 0x2);
+	udelay(1);
+	b43_phy_mask(dev, B43_LPPHY_FOURWIRE_CTL, 0xFFFD);
+	udelay(1);
+
+	if (dev->phy.radio_ver == 0x2062) {
+		lpphy_2062_init(dev);
+	} else {
+		lpphy_2063_init(dev);
+		lpphy_sync_stx(dev);
+		b43_phy_write(dev, B43_PHY_OFDM(0xF0), 0x5F80);
+		b43_phy_write(dev, B43_PHY_OFDM(0xF1), 0);
+		if (dev->dev->chip_id == 0x4325) {
+			// TODO SSB PMU recalibration
+		}
+	}
+}
+
+struct lpphy_iq_est { u32 iq_prod, i_pwr, q_pwr; };
+
+static void lpphy_set_rc_cap(struct b43_wldev *dev)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+
+	u8 rc_cap = (lpphy->rc_cap & 0x1F) >> 1;
+
+	if (dev->phy.rev == 1) //FIXME check channel 14!
+		rc_cap = min_t(u8, rc_cap + 5, 15);
+
+	b43_radio_write(dev, B2062_N_RXBB_CALIB2,
+			max_t(u8, lpphy->rc_cap - 4, 0x80));
+	b43_radio_write(dev, B2062_N_TX_CTL_A, rc_cap | 0x80);
+	b43_radio_write(dev, B2062_S_RXG_CNT16,
+			((lpphy->rc_cap & 0x1F) >> 2) | 0x80);
+}
+
+static u8 lpphy_get_bb_mult(struct b43_wldev *dev)
+{
+	return (b43_lptab_read(dev, B43_LPTAB16(0, 87)) & 0xFF00) >> 8;
+}
+
+static void lpphy_set_bb_mult(struct b43_wldev *dev, u8 bb_mult)
+{
+	b43_lptab_write(dev, B43_LPTAB16(0, 87), (u16)bb_mult << 8);
+}
+
+static void lpphy_set_deaf(struct b43_wldev *dev, bool user)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+
+	if (user)
+		lpphy->crs_usr_disable = true;
+	else
+		lpphy->crs_sys_disable = true;
+	b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x80);
+}
+
+static void lpphy_clear_deaf(struct b43_wldev *dev, bool user)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+
+	if (user)
+		lpphy->crs_usr_disable = false;
+	else
+		lpphy->crs_sys_disable = false;
+
+	if (!lpphy->crs_usr_disable && !lpphy->crs_sys_disable) {
+		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+			b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL,
+					0xFF1F, 0x60);
+		else
+			b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL,
+					0xFF1F, 0x20);
+	}
+}
+
+static void lpphy_set_trsw_over(struct b43_wldev *dev, bool tx, bool rx)
+{
+	u16 trsw = (tx << 1) | rx;
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, trsw);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
+}
+
+static void lpphy_disable_crs(struct b43_wldev *dev, bool user)
+{
+	lpphy_set_deaf(dev, user);
+	lpphy_set_trsw_over(dev, false, true);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFB);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x4);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFF7);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x10);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFDF);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x20);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFBF);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x7);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x38);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFF3F);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x100);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFDFF);
+	b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL0, 0);
+	b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL1, 1);
+	b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL2, 0x20);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFBFF);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xF7FF);
+	b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
+	b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45AF);
+	b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0x3FF);
+}
+
+static void lpphy_restore_crs(struct b43_wldev *dev, bool user)
+{
+	lpphy_clear_deaf(dev, user);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFF80);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFC00);
+}
+
+struct lpphy_tx_gains { u16 gm, pga, pad, dac; };
+
+static void lpphy_disable_rx_gain_override(struct b43_wldev *dev)
+{
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFEF);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFBF);
+	if (dev->phy.rev >= 2) {
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF);
+		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFBFF);
+			b43_phy_mask(dev, B43_PHY_OFDM(0xE5), 0xFFF7);
+		}
+	} else {
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF);
+	}
+}
+
+static void lpphy_enable_rx_gain_override(struct b43_wldev *dev)
+{
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40);
+	if (dev->phy.rev >= 2) {
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100);
+		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+			b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x400);
+			b43_phy_set(dev, B43_PHY_OFDM(0xE5), 0x8);
+		}
+	} else {
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x200);
+	}
+}
+
+static void lpphy_disable_tx_gain_override(struct b43_wldev *dev)
+{
+	if (dev->phy.rev < 2)
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF);
+	else {
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFF7F);
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xBFFF);
+	}
+	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFBF);
+}
+
+static void lpphy_enable_tx_gain_override(struct b43_wldev *dev)
+{
+	if (dev->phy.rev < 2)
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100);
+	else {
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x80);
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x4000);
+	}
+	b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 0x40);
+}
+
+static struct lpphy_tx_gains lpphy_get_tx_gains(struct b43_wldev *dev)
+{
+	struct lpphy_tx_gains gains;
+	u16 tmp;
+
+	gains.dac = (b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0x380) >> 7;
+	if (dev->phy.rev < 2) {
+		tmp = b43_phy_read(dev,
+				   B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7FF;
+		gains.gm = tmp & 0x0007;
+		gains.pga = (tmp & 0x0078) >> 3;
+		gains.pad = (tmp & 0x780) >> 7;
+	} else {
+		tmp = b43_phy_read(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL);
+		gains.pad = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0xFF;
+		gains.gm = tmp & 0xFF;
+		gains.pga = (tmp >> 8) & 0xFF;
+	}
+
+	return gains;
+}
+
+static void lpphy_set_dac_gain(struct b43_wldev *dev, u16 dac)
+{
+	u16 ctl = b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0xC7F;
+	ctl |= dac << 7;
+	b43_phy_maskset(dev, B43_LPPHY_AFE_DAC_CTL, 0xF000, ctl);
+}
+
+static u16 lpphy_get_pa_gain(struct b43_wldev *dev)
+{
+	return b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x7F;
+}
+
+static void lpphy_set_pa_gain(struct b43_wldev *dev, u16 gain)
+{
+	b43_phy_maskset(dev, B43_PHY_OFDM(0xFB), 0xE03F, gain << 6);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0xFD), 0x80FF, gain << 8);
+}
+
+static void lpphy_set_tx_gains(struct b43_wldev *dev,
+			       struct lpphy_tx_gains gains)
+{
+	u16 rf_gain, pa_gain;
+
+	if (dev->phy.rev < 2) {
+		rf_gain = (gains.pad << 7) | (gains.pga << 3) | gains.gm;
+		b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
+				0xF800, rf_gain);
+	} else {
+		pa_gain = lpphy_get_pa_gain(dev);
+		b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
+			      (gains.pga << 8) | gains.gm);
+		/*
+		 * SPEC FIXME The spec calls for (pa_gain << 8) here, but that
+		 * conflicts with the spec for set_pa_gain! Vendor driver bug?
+		 */
+		b43_phy_maskset(dev, B43_PHY_OFDM(0xFB),
+				0x8000, gains.pad | (pa_gain << 6));
+		b43_phy_write(dev, B43_PHY_OFDM(0xFC),
+			      (gains.pga << 8) | gains.gm);
+		b43_phy_maskset(dev, B43_PHY_OFDM(0xFD),
+				0x8000, gains.pad | (pa_gain << 8));
+	}
+	lpphy_set_dac_gain(dev, gains.dac);
+	lpphy_enable_tx_gain_override(dev);
+}
+
+static void lpphy_rev0_1_set_rx_gain(struct b43_wldev *dev, u32 gain)
+{
+	u16 trsw = gain & 0x1;
+	u16 lna = (gain & 0xFFFC) | ((gain & 0xC) >> 2);
+	u16 ext_lna = (gain & 2) >> 1;
+
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFE, trsw);
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+			0xFBFF, ext_lna << 10);
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+			0xF7FF, ext_lna << 11);
+	b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
+}
+
+static void lpphy_rev2plus_set_rx_gain(struct b43_wldev *dev, u32 gain)
+{
+	u16 low_gain = gain & 0xFFFF;
+	u16 high_gain = (gain >> 16) & 0xF;
+	u16 ext_lna = (gain >> 21) & 0x1;
+	u16 trsw = ~(gain >> 20) & 0x1;
+	u16 tmp;
+
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFE, trsw);
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+			0xFDFF, ext_lna << 9);
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+			0xFBFF, ext_lna << 10);
+	b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
+	b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFF0, high_gain);
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+		tmp = (gain >> 2) & 0x3;
+		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
+				0xE7FF, tmp<<11);
+		b43_phy_maskset(dev, B43_PHY_OFDM(0xE6), 0xFFE7, tmp << 3);
+	}
+}
+
+static void lpphy_set_rx_gain(struct b43_wldev *dev, u32 gain)
+{
+	if (dev->phy.rev < 2)
+		lpphy_rev0_1_set_rx_gain(dev, gain);
+	else
+		lpphy_rev2plus_set_rx_gain(dev, gain);
+	lpphy_enable_rx_gain_override(dev);
+}
+
+static void lpphy_set_rx_gain_by_index(struct b43_wldev *dev, u16 idx)
+{
+	u32 gain = b43_lptab_read(dev, B43_LPTAB16(12, idx));
+	lpphy_set_rx_gain(dev, gain);
+}
+
+static void lpphy_stop_ddfs(struct b43_wldev *dev)
+{
+	b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0xFFFD);
+	b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0xFFDF);
+}
+
+static void lpphy_run_ddfs(struct b43_wldev *dev, int i_on, int q_on,
+			   int incr1, int incr2, int scale_idx)
+{
+	lpphy_stop_ddfs(dev);
+	b43_phy_mask(dev, B43_LPPHY_AFE_DDFS_POINTER_INIT, 0xFF80);
+	b43_phy_mask(dev, B43_LPPHY_AFE_DDFS_POINTER_INIT, 0x80FF);
+	b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0xFF80, incr1);
+	b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0x80FF, incr2 << 8);
+	b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFF7, i_on << 3);
+	b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFEF, q_on << 4);
+	b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFF9F, scale_idx << 5);
+	b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0xFFFB);
+	b43_phy_set(dev, B43_LPPHY_AFE_DDFS, 0x2);
+	b43_phy_set(dev, B43_LPPHY_LP_PHY_CTL, 0x20);
+}
+
+static bool lpphy_rx_iq_est(struct b43_wldev *dev, u16 samples, u8 time,
+			   struct lpphy_iq_est *iq_est)
+{
+	int i;
+
+	b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFF7);
+	b43_phy_write(dev, B43_LPPHY_IQ_NUM_SMPLS_ADDR, samples);
+	b43_phy_maskset(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFF00, time);
+	b43_phy_mask(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFEFF);
+	b43_phy_set(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
+
+	for (i = 0; i < 500; i++) {
+		if (!(b43_phy_read(dev,
+				B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
+			break;
+		msleep(1);
+	}
+
+	if ((b43_phy_read(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
+		b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x8);
+		return false;
+	}
+
+	iq_est->iq_prod = b43_phy_read(dev, B43_LPPHY_IQ_ACC_HI_ADDR);
+	iq_est->iq_prod <<= 16;
+	iq_est->iq_prod |= b43_phy_read(dev, B43_LPPHY_IQ_ACC_LO_ADDR);
+
+	iq_est->i_pwr = b43_phy_read(dev, B43_LPPHY_IQ_I_PWR_ACC_HI_ADDR);
+	iq_est->i_pwr <<= 16;
+	iq_est->i_pwr |= b43_phy_read(dev, B43_LPPHY_IQ_I_PWR_ACC_LO_ADDR);
+
+	iq_est->q_pwr = b43_phy_read(dev, B43_LPPHY_IQ_Q_PWR_ACC_HI_ADDR);
+	iq_est->q_pwr <<= 16;
+	iq_est->q_pwr |= b43_phy_read(dev, B43_LPPHY_IQ_Q_PWR_ACC_LO_ADDR);
+
+	b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x8);
+	return true;
+}
+
+static int lpphy_loopback(struct b43_wldev *dev)
+{
+	struct lpphy_iq_est iq_est;
+	int i, index = -1;
+	u32 tmp;
+
+	memset(&iq_est, 0, sizeof(iq_est));
+
+	lpphy_set_trsw_over(dev, true, true);
+	b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 1);
+	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFFE);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x800);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x800);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x8);
+	b43_radio_write(dev, B2062_N_TX_CTL_A, 0x80);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x80);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x80);
+	for (i = 0; i < 32; i++) {
+		lpphy_set_rx_gain_by_index(dev, i);
+		lpphy_run_ddfs(dev, 1, 1, 5, 5, 0);
+		if (!(lpphy_rx_iq_est(dev, 1000, 32, &iq_est)))
+			continue;
+		tmp = (iq_est.i_pwr + iq_est.q_pwr) / 1000;
+		if ((tmp > 4000) && (tmp < 10000)) {
+			index = i;
+			break;
+		}
+	}
+	lpphy_stop_ddfs(dev);
+	return index;
+}
+
+/* Fixed-point division algorithm using only integer math. */
+static u32 lpphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
+{
+	u32 quotient, remainder;
+
+	if (divisor == 0)
+		return 0;
+
+	quotient = dividend / divisor;
+	remainder = dividend % divisor;
+
+	while (precision > 0) {
+		quotient <<= 1;
+		if (remainder << 1 >= divisor) {
+			quotient++;
+			remainder = (remainder << 1) - divisor;
+		}
+		precision--;
+	}
+
+	if (remainder << 1 >= divisor)
+		quotient++;
+
+	return quotient;
+}
+
+/* Read the TX power control mode from hardware. */
+static void lpphy_read_tx_pctl_mode_from_hardware(struct b43_wldev *dev)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	u16 ctl;
+
+	ctl = b43_phy_read(dev, B43_LPPHY_TX_PWR_CTL_CMD);
+	switch (ctl & B43_LPPHY_TX_PWR_CTL_CMD_MODE) {
+	case B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF:
+		lpphy->txpctl_mode = B43_LPPHY_TXPCTL_OFF;
+		break;
+	case B43_LPPHY_TX_PWR_CTL_CMD_MODE_SW:
+		lpphy->txpctl_mode = B43_LPPHY_TXPCTL_SW;
+		break;
+	case B43_LPPHY_TX_PWR_CTL_CMD_MODE_HW:
+		lpphy->txpctl_mode = B43_LPPHY_TXPCTL_HW;
+		break;
+	default:
+		lpphy->txpctl_mode = B43_LPPHY_TXPCTL_UNKNOWN;
+		B43_WARN_ON(1);
+		break;
+	}
+}
+
+/* Set the TX power control mode in hardware. */
+static void lpphy_write_tx_pctl_mode_to_hardware(struct b43_wldev *dev)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	u16 ctl;
+
+	switch (lpphy->txpctl_mode) {
+	case B43_LPPHY_TXPCTL_OFF:
+		ctl = B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF;
+		break;
+	case B43_LPPHY_TXPCTL_HW:
+		ctl = B43_LPPHY_TX_PWR_CTL_CMD_MODE_HW;
+		break;
+	case B43_LPPHY_TXPCTL_SW:
+		ctl = B43_LPPHY_TX_PWR_CTL_CMD_MODE_SW;
+		break;
+	default:
+		ctl = 0;
+		B43_WARN_ON(1);
+	}
+	b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD,
+			~B43_LPPHY_TX_PWR_CTL_CMD_MODE & 0xFFFF, ctl);
+}
+
+static void lpphy_set_tx_power_control(struct b43_wldev *dev,
+				       enum b43_lpphy_txpctl_mode mode)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	enum b43_lpphy_txpctl_mode oldmode;
+
+	lpphy_read_tx_pctl_mode_from_hardware(dev);
+	oldmode = lpphy->txpctl_mode;
+	if (oldmode == mode)
+		return;
+	lpphy->txpctl_mode = mode;
+
+	if (oldmode == B43_LPPHY_TXPCTL_HW) {
+		//TODO Update TX Power NPT
+		//TODO Clear all TX Power offsets
+	} else {
+		if (mode == B43_LPPHY_TXPCTL_HW) {
+			//TODO Recalculate target TX power
+			b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD,
+					0xFF80, lpphy->tssi_idx);
+			b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_NNUM,
+					0x8FFF, ((u16)lpphy->tssi_npt << 16));
+			//TODO Set "TSSI Transmit Count" variable to total transmitted frame count
+			lpphy_disable_tx_gain_override(dev);
+			lpphy->tx_pwr_idx_over = -1;
+		}
+	}
+	if (dev->phy.rev >= 2) {
+		if (mode == B43_LPPHY_TXPCTL_HW)
+			b43_phy_set(dev, B43_PHY_OFDM(0xD0), 0x2);
+		else
+			b43_phy_mask(dev, B43_PHY_OFDM(0xD0), 0xFFFD);
+	}
+	lpphy_write_tx_pctl_mode_to_hardware(dev);
+}
+
+static int b43_lpphy_op_switch_channel(struct b43_wldev *dev,
+				       unsigned int new_channel);
+
+static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	struct lpphy_iq_est iq_est;
+	struct lpphy_tx_gains tx_gains;
+	static const u32 ideal_pwr_table[21] = {
+		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
+		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
+		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
+		0x0004c, 0x0002c, 0x0001a,
+	};
+	bool old_txg_ovr;
+	u8 old_bbmult;
+	u16 old_rf_ovr, old_rf_ovrval, old_afe_ovr, old_afe_ovrval,
+	    old_rf2_ovr, old_rf2_ovrval, old_phy_ctl;
+	enum b43_lpphy_txpctl_mode old_txpctl;
+	u32 normal_pwr, ideal_pwr, mean_sq_pwr, tmp = 0, mean_sq_pwr_min = 0;
+	int loopback, i, j, inner_sum, err;
+
+	memset(&iq_est, 0, sizeof(iq_est));
+
+	err = b43_lpphy_op_switch_channel(dev, 7);
+	if (err) {
+		b43dbg(dev->wl,
+		       "RC calib: Failed to switch to channel 7, error = %d\n",
+		       err);
+	}
+	old_txg_ovr = !!(b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40);
+	old_bbmult = lpphy_get_bb_mult(dev);
+	if (old_txg_ovr)
+		tx_gains = lpphy_get_tx_gains(dev);
+	old_rf_ovr = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_0);
+	old_rf_ovrval = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_VAL_0);
+	old_afe_ovr = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR);
+	old_afe_ovrval = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVRVAL);
+	old_rf2_ovr = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2);
+	old_rf2_ovrval = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2_VAL);
+	old_phy_ctl = b43_phy_read(dev, B43_LPPHY_LP_PHY_CTL);
+	lpphy_read_tx_pctl_mode_from_hardware(dev);
+	old_txpctl = lpphy->txpctl_mode;
+
+	lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
+	lpphy_disable_crs(dev, true);
+	loopback = lpphy_loopback(dev);
+	if (loopback == -1)
+		goto finish;
+	lpphy_set_rx_gain_by_index(dev, loopback);
+	b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFFBF, 0x40);
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFFF8, 0x1);
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFFC7, 0x8);
+	b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFF3F, 0xC0);
+	for (i = 128; i <= 159; i++) {
+		b43_radio_write(dev, B2062_N_RXBB_CALIB2, i);
+		inner_sum = 0;
+		for (j = 5; j <= 25; j++) {
+			lpphy_run_ddfs(dev, 1, 1, j, j, 0);
+			if (!(lpphy_rx_iq_est(dev, 1000, 32, &iq_est)))
+				goto finish;
+			mean_sq_pwr = iq_est.i_pwr + iq_est.q_pwr;
+			if (j == 5)
+				tmp = mean_sq_pwr;
+			ideal_pwr = ((ideal_pwr_table[j-5] >> 3) + 1) >> 1;
+			normal_pwr = lpphy_qdiv_roundup(mean_sq_pwr, tmp, 12);
+			mean_sq_pwr = ideal_pwr - normal_pwr;
+			mean_sq_pwr *= mean_sq_pwr;
+			inner_sum += mean_sq_pwr;
+			if ((i == 128) || (inner_sum < mean_sq_pwr_min)) {
+				lpphy->rc_cap = i;
+				mean_sq_pwr_min = inner_sum;
+			}
+		}
+	}
+	lpphy_stop_ddfs(dev);
+
+finish:
+	lpphy_restore_crs(dev, true);
+	b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, old_rf_ovrval);
+	b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_0, old_rf_ovr);
+	b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVRVAL, old_afe_ovrval);
+	b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVR, old_afe_ovr);
+	b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, old_rf2_ovrval);
+	b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, old_rf2_ovr);
+	b43_phy_write(dev, B43_LPPHY_LP_PHY_CTL, old_phy_ctl);
+
+	lpphy_set_bb_mult(dev, old_bbmult);
+	if (old_txg_ovr) {
+		/*
+		 * SPEC FIXME: The specs say "get_tx_gains" here, which is
+		 * illogical. According to lwfinger, vendor driver v4.150.10.5
+		 * has a Set here, while v4.174.64.19 has a Get - regression in
+		 * the vendor driver? This should be tested this once the code
+		 * is testable.
+		 */
+		lpphy_set_tx_gains(dev, tx_gains);
+	}
+	lpphy_set_tx_power_control(dev, old_txpctl);
+	if (lpphy->rc_cap)
+		lpphy_set_rc_cap(dev);
+}
+
+static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev)
+{
+	struct ssb_bus *bus = dev->dev->sdev->bus;
+	u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
+	u8 tmp = b43_radio_read(dev, B2063_RX_BB_SP8) & 0xFF;
+	int i;
+
+	b43_radio_write(dev, B2063_RX_BB_SP8, 0x0);
+	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
+	b43_radio_mask(dev, B2063_PLL_SP1, 0xF7);
+	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C);
+	b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x15);
+	b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x70);
+	b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x52);
+	b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1);
+	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7D);
+
+	for (i = 0; i < 10000; i++) {
+		if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)
+			break;
+		msleep(1);
+	}
+
+	if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2))
+		b43_radio_write(dev, B2063_RX_BB_SP8, tmp);
+
+	tmp = b43_radio_read(dev, B2063_TX_BB_SP3) & 0xFF;
+
+	b43_radio_write(dev, B2063_TX_BB_SP3, 0x0);
+	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
+	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C);
+	b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x55);
+	b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x76);
+
+	if (crystal_freq == 24000000) {
+		b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0xFC);
+		b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x0);
+	} else {
+		b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x13);
+		b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1);
+	}
+
+	b43_radio_write(dev, B2063_PA_SP7, 0x7D);
+
+	for (i = 0; i < 10000; i++) {
+		if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)
+			break;
+		msleep(1);
+	}
+
+	if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2))
+		b43_radio_write(dev, B2063_TX_BB_SP3, tmp);
+
+	b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
+}
+
+static void lpphy_calibrate_rc(struct b43_wldev *dev)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+
+	if (dev->phy.rev >= 2) {
+		lpphy_rev2plus_rc_calib(dev);
+	} else if (!lpphy->rc_cap) {
+		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+			lpphy_rev0_1_rc_calib(dev);
+	} else {
+		lpphy_set_rc_cap(dev);
+	}
+}
+
+static void b43_lpphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)
+{
+	if (dev->phy.rev >= 2)
+		return; // rev2+ doesn't support antenna diversity
+
+	if (B43_WARN_ON(antenna > B43_ANTENNA_AUTO1))
+		return;
+
+	b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_ANTDIVHELP);
+
+	b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFD, antenna & 0x2);
+	b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFE, antenna & 0x1);
+
+	b43_hf_write(dev, b43_hf_read(dev) | B43_HF_ANTDIVHELP);
+
+	dev->phy.lp->antenna = antenna;
+}
+
+static void lpphy_set_tx_iqcc(struct b43_wldev *dev, u16 a, u16 b)
+{
+	u16 tmp[2];
+
+	tmp[0] = a;
+	tmp[1] = b;
+	b43_lptab_write_bulk(dev, B43_LPTAB16(0, 80), 2, tmp);
+}
+
+static void lpphy_set_tx_power_by_index(struct b43_wldev *dev, u8 index)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	struct lpphy_tx_gains gains;
+	u32 iq_comp, tx_gain, coeff, rf_power;
+
+	lpphy->tx_pwr_idx_over = index;
+	lpphy_read_tx_pctl_mode_from_hardware(dev);
+	if (lpphy->txpctl_mode != B43_LPPHY_TXPCTL_OFF)
+		lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_SW);
+	if (dev->phy.rev >= 2) {
+		iq_comp = b43_lptab_read(dev, B43_LPTAB32(7, index + 320));
+		tx_gain = b43_lptab_read(dev, B43_LPTAB32(7, index + 192));
+		gains.pad = (tx_gain >> 16) & 0xFF;
+		gains.gm = tx_gain & 0xFF;
+		gains.pga = (tx_gain >> 8) & 0xFF;
+		gains.dac = (iq_comp >> 28) & 0xFF;
+		lpphy_set_tx_gains(dev, gains);
+	} else {
+		iq_comp = b43_lptab_read(dev, B43_LPTAB32(10, index + 320));
+		tx_gain = b43_lptab_read(dev, B43_LPTAB32(10, index + 192));
+		b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
+				0xF800, (tx_gain >> 4) & 0x7FFF);
+		lpphy_set_dac_gain(dev, tx_gain & 0x7);
+		lpphy_set_pa_gain(dev, (tx_gain >> 24) & 0x7F);
+	}
+	lpphy_set_bb_mult(dev, (iq_comp >> 20) & 0xFF);
+	lpphy_set_tx_iqcc(dev, (iq_comp >> 10) & 0x3FF, iq_comp & 0x3FF);
+	if (dev->phy.rev >= 2) {
+		coeff = b43_lptab_read(dev, B43_LPTAB32(7, index + 448));
+	} else {
+		coeff = b43_lptab_read(dev, B43_LPTAB32(10, index + 448));
+	}
+	b43_lptab_write(dev, B43_LPTAB16(0, 85), coeff & 0xFFFF);
+	if (dev->phy.rev >= 2) {
+		rf_power = b43_lptab_read(dev, B43_LPTAB32(7, index + 576));
+		b43_phy_maskset(dev, B43_LPPHY_RF_PWR_OVERRIDE, 0xFF00,
+				rf_power & 0xFFFF);//SPEC FIXME mask & set != 0
+	}
+	lpphy_enable_tx_gain_override(dev);
+}
+
+static void lpphy_btcoex_override(struct b43_wldev *dev)
+{
+	b43_write16(dev, B43_MMIO_BTCOEX_CTL, 0x3);
+	b43_write16(dev, B43_MMIO_BTCOEX_TXCTL, 0xFF);
+}
+
+static void b43_lpphy_op_software_rfkill(struct b43_wldev *dev,
+					 bool blocked)
+{
+	//TODO check MAC control register
+	if (blocked) {
+		if (dev->phy.rev >= 2) {
+			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x83FF);
+			b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1F00);
+			b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0x80FF);
+			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xDFFF);
+			b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x0808);
+		} else {
+			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xE0FF);
+			b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1F00);
+			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFCFF);
+			b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x0018);
+		}
+	} else {
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xE0FF);
+		if (dev->phy.rev >= 2)
+			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xF7F7);
+		else
+			b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFE7);
+	}
+}
+
+/* This was previously called lpphy_japan_filter */
+static void lpphy_set_analog_filter(struct b43_wldev *dev, int channel)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	u16 tmp = (channel == 14); //SPEC FIXME check japanwidefilter!
+
+	if (dev->phy.rev < 2) { //SPEC FIXME Isn't this rev0/1-specific?
+		b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFCFF, tmp << 9);
+		if ((dev->phy.rev == 1) && (lpphy->rc_cap))
+			lpphy_set_rc_cap(dev);
+	} else {
+		b43_radio_write(dev, B2063_TX_BB_SP3, 0x3F);
+	}
+}
+
+static void lpphy_set_tssi_mux(struct b43_wldev *dev, enum tssi_mux_mode mode)
+{
+	if (mode != TSSI_MUX_EXT) {
+		b43_radio_set(dev, B2063_PA_SP1, 0x2);
+		b43_phy_set(dev, B43_PHY_OFDM(0xF3), 0x1000);
+		b43_radio_write(dev, B2063_PA_CTL10, 0x51);
+		if (mode == TSSI_MUX_POSTPA) {
+			b43_radio_mask(dev, B2063_PA_SP1, 0xFFFE);
+			b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFC7);
+		} else {
+			b43_radio_maskset(dev, B2063_PA_SP1, 0xFFFE, 0x1);
+			b43_phy_maskset(dev, B43_LPPHY_AFE_CTL_OVRVAL,
+					0xFFC7, 0x20);
+		}
+	} else {
+		B43_WARN_ON(1);
+	}
+}
+
+static void lpphy_tx_pctl_init_hw(struct b43_wldev *dev)
+{
+	u16 tmp;
+	int i;
+
+	//SPEC TODO Call LP PHY Clear TX Power offsets
+	for (i = 0; i < 64; i++) {
+		if (dev->phy.rev >= 2)
+			b43_lptab_write(dev, B43_LPTAB32(7, i + 1), i);
+		else
+			b43_lptab_write(dev, B43_LPTAB32(10, i + 1), i);
+	}
+
+	b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0xFF00, 0xFF);
+	b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0x8FFF, 0x5000);
+	b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_IDLETSSI, 0xFFC0, 0x1F);
+	if (dev->phy.rev < 2) {
+		b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0xEFFF);
+		b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xDFFF, 0x2000);
+	} else {
+		b43_phy_mask(dev, B43_PHY_OFDM(0x103), 0xFFFE);
+		b43_phy_maskset(dev, B43_PHY_OFDM(0x103), 0xFFFB, 0x4);
+		b43_phy_maskset(dev, B43_PHY_OFDM(0x103), 0xFFEF, 0x10);
+		b43_radio_maskset(dev, B2063_IQ_CALIB_CTL2, 0xF3, 0x1);
+		lpphy_set_tssi_mux(dev, TSSI_MUX_POSTPA);
+	}
+	b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_IDLETSSI, 0x7FFF, 0x8000);
+	b43_phy_mask(dev, B43_LPPHY_TX_PWR_CTL_DELTAPWR_LIMIT, 0xFF);
+	b43_phy_write(dev, B43_LPPHY_TX_PWR_CTL_DELTAPWR_LIMIT, 0xA);
+	b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD,
+			~B43_LPPHY_TX_PWR_CTL_CMD_MODE & 0xFFFF,
+			B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF);
+	b43_phy_mask(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0xF8FF);
+	b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD,
+			~B43_LPPHY_TX_PWR_CTL_CMD_MODE & 0xFFFF,
+			B43_LPPHY_TX_PWR_CTL_CMD_MODE_SW);
+
+	if (dev->phy.rev < 2) {
+		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_0, 0xEFFF, 0x1000);
+		b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xEFFF);
+	} else {
+		lpphy_set_tx_power_by_index(dev, 0x7F);
+	}
+
+	b43_dummy_transmission(dev, true, true);
+
+	tmp = b43_phy_read(dev, B43_LPPHY_TX_PWR_CTL_STAT);
+	if (tmp & 0x8000) {
+		b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_IDLETSSI,
+				0xFFC0, (tmp & 0xFF) - 32);
+	}
+
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xEFFF);
+
+	// (SPEC?) TODO Set "Target TX frequency" variable to 0
+	// SPEC FIXME "Set BB Multiplier to 0xE000" impossible - bb_mult is u8!
+}
+
+static void lpphy_tx_pctl_init_sw(struct b43_wldev *dev)
+{
+	struct lpphy_tx_gains gains;
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+		gains.gm = 4;
+		gains.pad = 12;
+		gains.pga = 12;
+		gains.dac = 0;
+	} else {
+		gains.gm = 7;
+		gains.pad = 14;
+		gains.pga = 15;
+		gains.dac = 0;
+	}
+	lpphy_set_tx_gains(dev, gains);
+	lpphy_set_bb_mult(dev, 150);
+}
+
+/* Initialize TX power control */
+static void lpphy_tx_pctl_init(struct b43_wldev *dev)
+{
+	if (0/*FIXME HWPCTL capable */) {
+		lpphy_tx_pctl_init_hw(dev);
+	} else { /* This device is only software TX power control capable. */
+		lpphy_tx_pctl_init_sw(dev);
+	}
+}
+
+static void lpphy_pr41573_workaround(struct b43_wldev *dev)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	u32 *saved_tab;
+	const unsigned int saved_tab_size = 256;
+	enum b43_lpphy_txpctl_mode txpctl_mode;
+	s8 tx_pwr_idx_over;
+	u16 tssi_npt, tssi_idx;
+
+	saved_tab = kcalloc(saved_tab_size, sizeof(saved_tab[0]), GFP_KERNEL);
+	if (!saved_tab) {
+		b43err(dev->wl, "PR41573 failed. Out of memory!\n");
+		return;
+	}
+
+	lpphy_read_tx_pctl_mode_from_hardware(dev);
+	txpctl_mode = lpphy->txpctl_mode;
+	tx_pwr_idx_over = lpphy->tx_pwr_idx_over;
+	tssi_npt = lpphy->tssi_npt;
+	tssi_idx = lpphy->tssi_idx;
+
+	if (dev->phy.rev < 2) {
+		b43_lptab_read_bulk(dev, B43_LPTAB32(10, 0x140),
+				    saved_tab_size, saved_tab);
+	} else {
+		b43_lptab_read_bulk(dev, B43_LPTAB32(7, 0x140),
+				    saved_tab_size, saved_tab);
+	}
+	//FIXME PHY reset
+	lpphy_table_init(dev); //FIXME is table init needed?
+	lpphy_baseband_init(dev);
+	lpphy_tx_pctl_init(dev);
+	b43_lpphy_op_software_rfkill(dev, false);
+	lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
+	if (dev->phy.rev < 2) {
+		b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0x140),
+				     saved_tab_size, saved_tab);
+	} else {
+		b43_lptab_write_bulk(dev, B43_LPTAB32(7, 0x140),
+				     saved_tab_size, saved_tab);
+	}
+	b43_write16(dev, B43_MMIO_CHANNEL, lpphy->channel);
+	lpphy->tssi_npt = tssi_npt;
+	lpphy->tssi_idx = tssi_idx;
+	lpphy_set_analog_filter(dev, lpphy->channel);
+	if (tx_pwr_idx_over != -1)
+		lpphy_set_tx_power_by_index(dev, tx_pwr_idx_over);
+	if (lpphy->rc_cap)
+		lpphy_set_rc_cap(dev);
+	b43_lpphy_op_set_rx_antenna(dev, lpphy->antenna);
+	lpphy_set_tx_power_control(dev, txpctl_mode);
+	kfree(saved_tab);
+}
+
+struct lpphy_rx_iq_comp { u8 chan; s8 c1, c0; };
+
+static const struct lpphy_rx_iq_comp lpphy_5354_iq_table[] = {
+	{ .chan = 1, .c1 = -66, .c0 = 15, },
+	{ .chan = 2, .c1 = -66, .c0 = 15, },
+	{ .chan = 3, .c1 = -66, .c0 = 15, },
+	{ .chan = 4, .c1 = -66, .c0 = 15, },
+	{ .chan = 5, .c1 = -66, .c0 = 15, },
+	{ .chan = 6, .c1 = -66, .c0 = 15, },
+	{ .chan = 7, .c1 = -66, .c0 = 14, },
+	{ .chan = 8, .c1 = -66, .c0 = 14, },
+	{ .chan = 9, .c1 = -66, .c0 = 14, },
+	{ .chan = 10, .c1 = -66, .c0 = 14, },
+	{ .chan = 11, .c1 = -66, .c0 = 14, },
+	{ .chan = 12, .c1 = -66, .c0 = 13, },
+	{ .chan = 13, .c1 = -66, .c0 = 13, },
+	{ .chan = 14, .c1 = -66, .c0 = 13, },
+};
+
+static const struct lpphy_rx_iq_comp lpphy_rev0_1_iq_table[] = {
+	{ .chan = 1, .c1 = -64, .c0 = 13, },
+	{ .chan = 2, .c1 = -64, .c0 = 13, },
+	{ .chan = 3, .c1 = -64, .c0 = 13, },
+	{ .chan = 4, .c1 = -64, .c0 = 13, },
+	{ .chan = 5, .c1 = -64, .c0 = 12, },
+	{ .chan = 6, .c1 = -64, .c0 = 12, },
+	{ .chan = 7, .c1 = -64, .c0 = 12, },
+	{ .chan = 8, .c1 = -64, .c0 = 12, },
+	{ .chan = 9, .c1 = -64, .c0 = 12, },
+	{ .chan = 10, .c1 = -64, .c0 = 11, },
+	{ .chan = 11, .c1 = -64, .c0 = 11, },
+	{ .chan = 12, .c1 = -64, .c0 = 11, },
+	{ .chan = 13, .c1 = -64, .c0 = 11, },
+	{ .chan = 14, .c1 = -64, .c0 = 10, },
+	{ .chan = 34, .c1 = -62, .c0 = 24, },
+	{ .chan = 38, .c1 = -62, .c0 = 24, },
+	{ .chan = 42, .c1 = -62, .c0 = 24, },
+	{ .chan = 46, .c1 = -62, .c0 = 23, },
+	{ .chan = 36, .c1 = -62, .c0 = 24, },
+	{ .chan = 40, .c1 = -62, .c0 = 24, },
+	{ .chan = 44, .c1 = -62, .c0 = 23, },
+	{ .chan = 48, .c1 = -62, .c0 = 23, },
+	{ .chan = 52, .c1 = -62, .c0 = 23, },
+	{ .chan = 56, .c1 = -62, .c0 = 22, },
+	{ .chan = 60, .c1 = -62, .c0 = 22, },
+	{ .chan = 64, .c1 = -62, .c0 = 22, },
+	{ .chan = 100, .c1 = -62, .c0 = 16, },
+	{ .chan = 104, .c1 = -62, .c0 = 16, },
+	{ .chan = 108, .c1 = -62, .c0 = 15, },
+	{ .chan = 112, .c1 = -62, .c0 = 14, },
+	{ .chan = 116, .c1 = -62, .c0 = 14, },
+	{ .chan = 120, .c1 = -62, .c0 = 13, },
+	{ .chan = 124, .c1 = -62, .c0 = 12, },
+	{ .chan = 128, .c1 = -62, .c0 = 12, },
+	{ .chan = 132, .c1 = -62, .c0 = 12, },
+	{ .chan = 136, .c1 = -62, .c0 = 11, },
+	{ .chan = 140, .c1 = -62, .c0 = 10, },
+	{ .chan = 149, .c1 = -61, .c0 = 9, },
+	{ .chan = 153, .c1 = -61, .c0 = 9, },
+	{ .chan = 157, .c1 = -61, .c0 = 9, },
+	{ .chan = 161, .c1 = -61, .c0 = 8, },
+	{ .chan = 165, .c1 = -61, .c0 = 8, },
+	{ .chan = 184, .c1 = -62, .c0 = 25, },
+	{ .chan = 188, .c1 = -62, .c0 = 25, },
+	{ .chan = 192, .c1 = -62, .c0 = 25, },
+	{ .chan = 196, .c1 = -62, .c0 = 25, },
+	{ .chan = 200, .c1 = -62, .c0 = 25, },
+	{ .chan = 204, .c1 = -62, .c0 = 25, },
+	{ .chan = 208, .c1 = -62, .c0 = 25, },
+	{ .chan = 212, .c1 = -62, .c0 = 25, },
+	{ .chan = 216, .c1 = -62, .c0 = 26, },
+};
+
+static const struct lpphy_rx_iq_comp lpphy_rev2plus_iq_comp = {
+	.chan = 0,
+	.c1 = -64,
+	.c0 = 0,
+};
+
+static int lpphy_calc_rx_iq_comp(struct b43_wldev *dev, u16 samples)
+{
+	struct lpphy_iq_est iq_est;
+	u16 c0, c1;
+	int prod, ipwr, qpwr, prod_msb, q_msb, tmp1, tmp2, tmp3, tmp4, ret;
+
+	c1 = b43_phy_read(dev, B43_LPPHY_RX_COMP_COEFF_S);
+	c0 = c1 >> 8;
+	c1 |= 0xFF;
+
+	b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0xFF00, 0x00C0);
+	b43_phy_mask(dev, B43_LPPHY_RX_COMP_COEFF_S, 0x00FF);
+
+	ret = lpphy_rx_iq_est(dev, samples, 32, &iq_est);
+	if (!ret)
+		goto out;
+
+	prod = iq_est.iq_prod;
+	ipwr = iq_est.i_pwr;
+	qpwr = iq_est.q_pwr;
+
+	if (ipwr + qpwr < 2) {
+		ret = 0;
+		goto out;
+	}
+
+	prod_msb = fls(abs(prod));
+	q_msb = fls(abs(qpwr));
+	tmp1 = prod_msb - 20;
+
+	if (tmp1 >= 0) {
+		tmp3 = ((prod << (30 - prod_msb)) + (ipwr >> (1 + tmp1))) /
+			(ipwr >> tmp1);
+	} else {
+		tmp3 = ((prod << (30 - prod_msb)) + (ipwr << (-1 - tmp1))) /
+			(ipwr << -tmp1);
+	}
+
+	tmp2 = q_msb - 11;
+
+	if (tmp2 >= 0)
+		tmp4 = (qpwr << (31 - q_msb)) / (ipwr >> tmp2);
+	else
+		tmp4 = (qpwr << (31 - q_msb)) / (ipwr << -tmp2);
+
+	tmp4 -= tmp3 * tmp3;
+	tmp4 = -int_sqrt(tmp4);
+
+	c0 = tmp3 >> 3;
+	c1 = tmp4 >> 4;
+
+out:
+	b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0xFF00, c1);
+	b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0x00FF, c0 << 8);
+	return ret;
+}
+
+static void lpphy_run_samples(struct b43_wldev *dev, u16 samples, u16 loops,
+			      u16 wait)
+{
+	b43_phy_maskset(dev, B43_LPPHY_SMPL_PLAY_BUFFER_CTL,
+			0xFFC0, samples - 1);
+	if (loops != 0xFFFF)
+		loops--;
+	b43_phy_maskset(dev, B43_LPPHY_SMPL_PLAY_COUNT, 0xF000, loops);
+	b43_phy_maskset(dev, B43_LPPHY_SMPL_PLAY_BUFFER_CTL, 0x3F, wait << 6);
+	b43_phy_set(dev, B43_LPPHY_A_PHY_CTL_ADDR, 0x1);
+}
+
+//SPEC FIXME what does a negative freq mean?
+static void lpphy_start_tx_tone(struct b43_wldev *dev, s32 freq, u16 max)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	u16 buf[64];
+	int i, samples = 0, angle = 0;
+	int rotation = (((36 * freq) / 20) << 16) / 100;
+	struct b43_c32 sample;
+
+	lpphy->tx_tone_freq = freq;
+
+	if (freq) {
+		/* Find i for which abs(freq) integrally divides 20000 * i */
+		for (i = 1; samples * abs(freq) != 20000 * i; i++) {
+			samples = (20000 * i) / abs(freq);
+			if(B43_WARN_ON(samples > 63))
+				return;
+		}
+	} else {
+		samples = 2;
+	}
+
+	for (i = 0; i < samples; i++) {
+		sample = b43_cordic(angle);
+		angle += rotation;
+		buf[i] = CORDIC_CONVERT((sample.i * max) & 0xFF) << 8;
+		buf[i] |= CORDIC_CONVERT((sample.q * max) & 0xFF);
+	}
+
+	b43_lptab_write_bulk(dev, B43_LPTAB16(5, 0), samples, buf);
+
+	lpphy_run_samples(dev, samples, 0xFFFF, 0);
+}
+
+static void lpphy_stop_tx_tone(struct b43_wldev *dev)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	int i;
+
+	lpphy->tx_tone_freq = 0;
+
+	b43_phy_mask(dev, B43_LPPHY_SMPL_PLAY_COUNT, 0xF000);
+	for (i = 0; i < 31; i++) {
+		if (!(b43_phy_read(dev, B43_LPPHY_A_PHY_CTL_ADDR) & 0x1))
+			break;
+		udelay(100);
+	}
+}
+
+
+static void lpphy_papd_cal(struct b43_wldev *dev, struct lpphy_tx_gains gains,
+			   int mode, bool useindex, u8 index)
+{
+	//TODO
+}
+
+static void lpphy_papd_cal_txpwr(struct b43_wldev *dev)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	struct lpphy_tx_gains gains, oldgains;
+	int old_txpctl, old_afe_ovr, old_rf, old_bbmult;
+
+	lpphy_read_tx_pctl_mode_from_hardware(dev);
+	old_txpctl = lpphy->txpctl_mode;
+	old_afe_ovr = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40;
+	if (old_afe_ovr)
+		oldgains = lpphy_get_tx_gains(dev);
+	old_rf = b43_phy_read(dev, B43_LPPHY_RF_PWR_OVERRIDE) & 0xFF;
+	old_bbmult = lpphy_get_bb_mult(dev);
+
+	lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
+
+	if (dev->dev->chip_id == 0x4325 && dev->dev->chip_rev == 0)
+		lpphy_papd_cal(dev, gains, 0, 1, 30);
+	else
+		lpphy_papd_cal(dev, gains, 0, 1, 65);
+
+	if (old_afe_ovr)
+		lpphy_set_tx_gains(dev, oldgains);
+	lpphy_set_bb_mult(dev, old_bbmult);
+	lpphy_set_tx_power_control(dev, old_txpctl);
+	b43_phy_maskset(dev, B43_LPPHY_RF_PWR_OVERRIDE, 0xFF00, old_rf);
+}
+
+static int lpphy_rx_iq_cal(struct b43_wldev *dev, bool noise, bool tx,
+			    bool rx, bool pa, struct lpphy_tx_gains *gains)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	const struct lpphy_rx_iq_comp *iqcomp = NULL;
+	struct lpphy_tx_gains nogains, oldgains;
+	u16 tmp;
+	int i, ret;
+
+	memset(&nogains, 0, sizeof(nogains));
+	memset(&oldgains, 0, sizeof(oldgains));
+
+	if (dev->dev->chip_id == 0x5354) {
+		for (i = 0; i < ARRAY_SIZE(lpphy_5354_iq_table); i++) {
+			if (lpphy_5354_iq_table[i].chan == lpphy->channel) {
+				iqcomp = &lpphy_5354_iq_table[i];
+			}
+		}
+	} else if (dev->phy.rev >= 2) {
+		iqcomp = &lpphy_rev2plus_iq_comp;
+	} else {
+		for (i = 0; i < ARRAY_SIZE(lpphy_rev0_1_iq_table); i++) {
+			if (lpphy_rev0_1_iq_table[i].chan == lpphy->channel) {
+				iqcomp = &lpphy_rev0_1_iq_table[i];
+			}
+		}
+	}
+
+	if (B43_WARN_ON(!iqcomp))
+		return 0;
+
+	b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0xFF00, iqcomp->c1);
+	b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S,
+			0x00FF, iqcomp->c0 << 8);
+
+	if (noise) {
+		tx = true;
+		rx = false;
+		pa = false;
+	}
+
+	lpphy_set_trsw_over(dev, tx, rx);
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8);
+		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0,
+				0xFFF7, pa << 3);
+	} else {
+		b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x20);
+		b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0,
+				0xFFDF, pa << 5);
+	}
+
+	tmp = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40;
+
+	if (noise)
+		lpphy_set_rx_gain(dev, 0x2D5D);
+	else {
+		if (tmp)
+			oldgains = lpphy_get_tx_gains(dev);
+		if (!gains)
+			gains = &nogains;
+		lpphy_set_tx_gains(dev, *gains);
+	}
+
+	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFFE);
+	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFFE);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x800);
+	b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x800);
+	lpphy_set_deaf(dev, false);
+	if (noise)
+		ret = lpphy_calc_rx_iq_comp(dev, 0xFFF0);
+	else {
+		lpphy_start_tx_tone(dev, 4000, 100);
+		ret = lpphy_calc_rx_iq_comp(dev, 0x4000);
+		lpphy_stop_tx_tone(dev);
+	}
+	lpphy_clear_deaf(dev, false);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFC);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFF7);
+	b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFDF);
+	if (!noise) {
+		if (tmp)
+			lpphy_set_tx_gains(dev, oldgains);
+		else
+			lpphy_disable_tx_gain_override(dev);
+	}
+	lpphy_disable_rx_gain_override(dev);
+	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFFE);
+	b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xF7FF);
+	return ret;
+}
+
+static void lpphy_calibration(struct b43_wldev *dev)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	enum b43_lpphy_txpctl_mode saved_pctl_mode;
+	bool full_cal = false;
+
+	if (lpphy->full_calib_chan != lpphy->channel) {
+		full_cal = true;
+		lpphy->full_calib_chan = lpphy->channel;
+	}
+
+	b43_mac_suspend(dev);
+
+	lpphy_btcoex_override(dev);
+	if (dev->phy.rev >= 2)
+		lpphy_save_dig_flt_state(dev);
+	lpphy_read_tx_pctl_mode_from_hardware(dev);
+	saved_pctl_mode = lpphy->txpctl_mode;
+	lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
+	//TODO Perform transmit power table I/Q LO calibration
+	if ((dev->phy.rev == 0) && (saved_pctl_mode != B43_LPPHY_TXPCTL_OFF))
+		lpphy_pr41573_workaround(dev);
+	if ((dev->phy.rev >= 2) && full_cal) {
+		lpphy_papd_cal_txpwr(dev);
+	}
+	lpphy_set_tx_power_control(dev, saved_pctl_mode);
+	if (dev->phy.rev >= 2)
+		lpphy_restore_dig_flt_state(dev);
+	lpphy_rx_iq_cal(dev, true, true, false, false, NULL);
+
+	b43_mac_enable(dev);
+}
+
+static void b43_lpphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
+				 u16 set)
+{
+	b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
+	b43_write16(dev, B43_MMIO_PHY_DATA,
+		    (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
+}
+
+static u16 b43_lpphy_op_radio_read(struct b43_wldev *dev, u16 reg)
+{
+	/* Register 1 is a 32-bit register. */
+	B43_WARN_ON(reg == 1);
+	/* LP-PHY needs a special bit set for read access */
+	if (dev->phy.rev < 2) {
+		if (reg != 0x4001)
+			reg |= 0x100;
+	} else
+		reg |= 0x200;
+
+	b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);
+	return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
+}
+
+static void b43_lpphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+	/* Register 1 is a 32-bit register. */
+	B43_WARN_ON(reg == 1);
+
+	b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);
+	b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
+}
+
+struct b206x_channel {
+	u8 channel;
+	u16 freq;
+	u8 data[12];
+};
+
+static const struct b206x_channel b2062_chantbl[] = {
+	{ .channel = 1, .freq = 2412, .data[0] = 0xFF, .data[1] = 0xFF,
+	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
+	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
+	{ .channel = 2, .freq = 2417, .data[0] = 0xFF, .data[1] = 0xFF,
+	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
+	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
+	{ .channel = 3, .freq = 2422, .data[0] = 0xFF, .data[1] = 0xFF,
+	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
+	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
+	{ .channel = 4, .freq = 2427, .data[0] = 0xFF, .data[1] = 0xFF,
+	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
+	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
+	{ .channel = 5, .freq = 2432, .data[0] = 0xFF, .data[1] = 0xFF,
+	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
+	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
+	{ .channel = 6, .freq = 2437, .data[0] = 0xFF, .data[1] = 0xFF,
+	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
+	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
+	{ .channel = 7, .freq = 2442, .data[0] = 0xFF, .data[1] = 0xFF,
+	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
+	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
+	{ .channel = 8, .freq = 2447, .data[0] = 0xFF, .data[1] = 0xFF,
+	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
+	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
+	{ .channel = 9, .freq = 2452, .data[0] = 0xFF, .data[1] = 0xFF,
+	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
+	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
+	{ .channel = 10, .freq = 2457, .data[0] = 0xFF, .data[1] = 0xFF,
+	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
+	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
+	{ .channel = 11, .freq = 2462, .data[0] = 0xFF, .data[1] = 0xFF,
+	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
+	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
+	{ .channel = 12, .freq = 2467, .data[0] = 0xFF, .data[1] = 0xFF,
+	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
+	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
+	{ .channel = 13, .freq = 2472, .data[0] = 0xFF, .data[1] = 0xFF,
+	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
+	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
+	{ .channel = 14, .freq = 2484, .data[0] = 0xFF, .data[1] = 0xFF,
+	  .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
+	  .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
+	{ .channel = 34, .freq = 5170, .data[0] = 0x00, .data[1] = 0x22,
+	  .data[2] = 0x20, .data[3] = 0x84, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 38, .freq = 5190, .data[0] = 0x00, .data[1] = 0x11,
+	  .data[2] = 0x10, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 42, .freq = 5210, .data[0] = 0x00, .data[1] = 0x11,
+	  .data[2] = 0x10, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 46, .freq = 5230, .data[0] = 0x00, .data[1] = 0x00,
+	  .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 36, .freq = 5180, .data[0] = 0x00, .data[1] = 0x11,
+	  .data[2] = 0x20, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 40, .freq = 5200, .data[0] = 0x00, .data[1] = 0x11,
+	  .data[2] = 0x10, .data[3] = 0x84, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 44, .freq = 5220, .data[0] = 0x00, .data[1] = 0x11,
+	  .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 48, .freq = 5240, .data[0] = 0x00, .data[1] = 0x00,
+	  .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 52, .freq = 5260, .data[0] = 0x00, .data[1] = 0x00,
+	  .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 56, .freq = 5280, .data[0] = 0x00, .data[1] = 0x00,
+	  .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 60, .freq = 5300, .data[0] = 0x00, .data[1] = 0x00,
+	  .data[2] = 0x00, .data[3] = 0x63, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 64, .freq = 5320, .data[0] = 0x00, .data[1] = 0x00,
+	  .data[2] = 0x00, .data[3] = 0x62, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 100, .freq = 5500, .data[0] = 0x00, .data[1] = 0x00,
+	  .data[2] = 0x00, .data[3] = 0x30, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 104, .freq = 5520, .data[0] = 0x00, .data[1] = 0x00,
+	  .data[2] = 0x00, .data[3] = 0x20, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 108, .freq = 5540, .data[0] = 0x00, .data[1] = 0x00,
+	  .data[2] = 0x00, .data[3] = 0x20, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 112, .freq = 5560, .data[0] = 0x00, .data[1] = 0x00,
+	  .data[2] = 0x00, .data[3] = 0x20, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 116, .freq = 5580, .data[0] = 0x00, .data[1] = 0x00,
+	  .data[2] = 0x00, .data[3] = 0x10, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 120, .freq = 5600, .data[0] = 0x00, .data[1] = 0x00,
+	  .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 124, .freq = 5620, .data[0] = 0x00, .data[1] = 0x00,
+	  .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 128, .freq = 5640, .data[0] = 0x00, .data[1] = 0x00,
+	  .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 132, .freq = 5660, .data[0] = 0x00, .data[1] = 0x00,
+	  .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 136, .freq = 5680, .data[0] = 0x00, .data[1] = 0x00,
+	  .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 140, .freq = 5700, .data[0] = 0x00, .data[1] = 0x00,
+	  .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 149, .freq = 5745, .data[0] = 0x00, .data[1] = 0x00,
+	  .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 153, .freq = 5765, .data[0] = 0x00, .data[1] = 0x00,
+	  .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 157, .freq = 5785, .data[0] = 0x00, .data[1] = 0x00,
+	  .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 161, .freq = 5805, .data[0] = 0x00, .data[1] = 0x00,
+	  .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 165, .freq = 5825, .data[0] = 0x00, .data[1] = 0x00,
+	  .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 184, .freq = 4920, .data[0] = 0x55, .data[1] = 0x77,
+	  .data[2] = 0x90, .data[3] = 0xF7, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, },
+	{ .channel = 188, .freq = 4940, .data[0] = 0x44, .data[1] = 0x77,
+	  .data[2] = 0x80, .data[3] = 0xE7, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, },
+	{ .channel = 192, .freq = 4960, .data[0] = 0x44, .data[1] = 0x66,
+	  .data[2] = 0x80, .data[3] = 0xE7, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, },
+	{ .channel = 196, .freq = 4980, .data[0] = 0x33, .data[1] = 0x66,
+	  .data[2] = 0x70, .data[3] = 0xC7, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, },
+	{ .channel = 200, .freq = 5000, .data[0] = 0x22, .data[1] = 0x55,
+	  .data[2] = 0x60, .data[3] = 0xD7, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, },
+	{ .channel = 204, .freq = 5020, .data[0] = 0x22, .data[1] = 0x55,
+	  .data[2] = 0x60, .data[3] = 0xC7, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, },
+	{ .channel = 208, .freq = 5040, .data[0] = 0x22, .data[1] = 0x44,
+	  .data[2] = 0x50, .data[3] = 0xC7, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, },
+	{ .channel = 212, .freq = 5060, .data[0] = 0x11, .data[1] = 0x44,
+	  .data[2] = 0x50, .data[3] = 0xA5, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
+	{ .channel = 216, .freq = 5080, .data[0] = 0x00, .data[1] = 0x44,
+	  .data[2] = 0x40, .data[3] = 0xB6, .data[4] = 0x3C, .data[5] = 0x77,
+	  .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
+};
+
+static const struct b206x_channel b2063_chantbl[] = {
+	{ .channel = 1, .freq = 2412, .data[0] = 0x6F, .data[1] = 0x3C,
+	  .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
+	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
+	  .data[10] = 0x80, .data[11] = 0x70, },
+	{ .channel = 2, .freq = 2417, .data[0] = 0x6F, .data[1] = 0x3C,
+	  .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
+	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
+	  .data[10] = 0x80, .data[11] = 0x70, },
+	{ .channel = 3, .freq = 2422, .data[0] = 0x6F, .data[1] = 0x3C,
+	  .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
+	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
+	  .data[10] = 0x80, .data[11] = 0x70, },
+	{ .channel = 4, .freq = 2427, .data[0] = 0x6F, .data[1] = 0x2C,
+	  .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
+	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
+	  .data[10] = 0x80, .data[11] = 0x70, },
+	{ .channel = 5, .freq = 2432, .data[0] = 0x6F, .data[1] = 0x2C,
+	  .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
+	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
+	  .data[10] = 0x80, .data[11] = 0x70, },
+	{ .channel = 6, .freq = 2437, .data[0] = 0x6F, .data[1] = 0x2C,
+	  .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
+	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
+	  .data[10] = 0x80, .data[11] = 0x70, },
+	{ .channel = 7, .freq = 2442, .data[0] = 0x6F, .data[1] = 0x2C,
+	  .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
+	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
+	  .data[10] = 0x80, .data[11] = 0x70, },
+	{ .channel = 8, .freq = 2447, .data[0] = 0x6F, .data[1] = 0x2C,
+	  .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
+	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
+	  .data[10] = 0x80, .data[11] = 0x70, },
+	{ .channel = 9, .freq = 2452, .data[0] = 0x6F, .data[1] = 0x1C,
+	  .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
+	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
+	  .data[10] = 0x80, .data[11] = 0x70, },
+	{ .channel = 10, .freq = 2457, .data[0] = 0x6F, .data[1] = 0x1C,
+	  .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
+	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
+	  .data[10] = 0x80, .data[11] = 0x70, },
+	{ .channel = 11, .freq = 2462, .data[0] = 0x6E, .data[1] = 0x1C,
+	  .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
+	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
+	  .data[10] = 0x80, .data[11] = 0x70, },
+	{ .channel = 12, .freq = 2467, .data[0] = 0x6E, .data[1] = 0x1C,
+	  .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
+	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
+	  .data[10] = 0x80, .data[11] = 0x70, },
+	{ .channel = 13, .freq = 2472, .data[0] = 0x6E, .data[1] = 0x1C,
+	  .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
+	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
+	  .data[10] = 0x80, .data[11] = 0x70, },
+	{ .channel = 14, .freq = 2484, .data[0] = 0x6E, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
+	  .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
+	  .data[10] = 0x80, .data[11] = 0x70, },
+	{ .channel = 34, .freq = 5170, .data[0] = 0x6A, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x02, .data[5] = 0x05,
+	  .data[6] = 0x0D, .data[7] = 0x0D, .data[8] = 0x77, .data[9] = 0x80,
+	  .data[10] = 0x20, .data[11] = 0x00, },
+	{ .channel = 36, .freq = 5180, .data[0] = 0x6A, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x05,
+	  .data[6] = 0x0D, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x80,
+	  .data[10] = 0x20, .data[11] = 0x00, },
+	{ .channel = 38, .freq = 5190, .data[0] = 0x6A, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x04,
+	  .data[6] = 0x0C, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x80,
+	  .data[10] = 0x20, .data[11] = 0x00, },
+	{ .channel = 40, .freq = 5200, .data[0] = 0x69, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x04,
+	  .data[6] = 0x0C, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x70,
+	  .data[10] = 0x20, .data[11] = 0x00, },
+	{ .channel = 42, .freq = 5210, .data[0] = 0x69, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x04,
+	  .data[6] = 0x0B, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x70,
+	  .data[10] = 0x20, .data[11] = 0x00, },
+	{ .channel = 44, .freq = 5220, .data[0] = 0x69, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x04,
+	  .data[6] = 0x0B, .data[7] = 0x0B, .data[8] = 0x77, .data[9] = 0x60,
+	  .data[10] = 0x20, .data[11] = 0x00, },
+	{ .channel = 46, .freq = 5230, .data[0] = 0x69, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x03,
+	  .data[6] = 0x0A, .data[7] = 0x0B, .data[8] = 0x77, .data[9] = 0x60,
+	  .data[10] = 0x20, .data[11] = 0x00, },
+	{ .channel = 48, .freq = 5240, .data[0] = 0x69, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x03,
+	  .data[6] = 0x0A, .data[7] = 0x0A, .data[8] = 0x77, .data[9] = 0x60,
+	  .data[10] = 0x20, .data[11] = 0x00, },
+	{ .channel = 52, .freq = 5260, .data[0] = 0x68, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x02,
+	  .data[6] = 0x09, .data[7] = 0x09, .data[8] = 0x77, .data[9] = 0x60,
+	  .data[10] = 0x20, .data[11] = 0x00, },
+	{ .channel = 56, .freq = 5280, .data[0] = 0x68, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x01,
+	  .data[6] = 0x08, .data[7] = 0x08, .data[8] = 0x77, .data[9] = 0x50,
+	  .data[10] = 0x10, .data[11] = 0x00, },
+	{ .channel = 60, .freq = 5300, .data[0] = 0x68, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x01,
+	  .data[6] = 0x08, .data[7] = 0x08, .data[8] = 0x77, .data[9] = 0x50,
+	  .data[10] = 0x10, .data[11] = 0x00, },
+	{ .channel = 64, .freq = 5320, .data[0] = 0x67, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
+	  .data[6] = 0x08, .data[7] = 0x08, .data[8] = 0x77, .data[9] = 0x50,
+	  .data[10] = 0x10, .data[11] = 0x00, },
+	{ .channel = 100, .freq = 5500, .data[0] = 0x64, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
+	  .data[6] = 0x02, .data[7] = 0x01, .data[8] = 0x77, .data[9] = 0x20,
+	  .data[10] = 0x00, .data[11] = 0x00, },
+	{ .channel = 104, .freq = 5520, .data[0] = 0x64, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
+	  .data[6] = 0x01, .data[7] = 0x01, .data[8] = 0x77, .data[9] = 0x20,
+	  .data[10] = 0x00, .data[11] = 0x00, },
+	{ .channel = 108, .freq = 5540, .data[0] = 0x63, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
+	  .data[6] = 0x01, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x10,
+	  .data[10] = 0x00, .data[11] = 0x00, },
+	{ .channel = 112, .freq = 5560, .data[0] = 0x63, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
+	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x10,
+	  .data[10] = 0x00, .data[11] = 0x00, },
+	{ .channel = 116, .freq = 5580, .data[0] = 0x62, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
+	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x10,
+	  .data[10] = 0x00, .data[11] = 0x00, },
+	{ .channel = 120, .freq = 5600, .data[0] = 0x62, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
+	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
+	  .data[10] = 0x00, .data[11] = 0x00, },
+	{ .channel = 124, .freq = 5620, .data[0] = 0x62, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
+	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
+	  .data[10] = 0x00, .data[11] = 0x00, },
+	{ .channel = 128, .freq = 5640, .data[0] = 0x61, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
+	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
+	  .data[10] = 0x00, .data[11] = 0x00, },
+	{ .channel = 132, .freq = 5660, .data[0] = 0x61, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
+	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
+	  .data[10] = 0x00, .data[11] = 0x00, },
+	{ .channel = 136, .freq = 5680, .data[0] = 0x61, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
+	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
+	  .data[10] = 0x00, .data[11] = 0x00, },
+	{ .channel = 140, .freq = 5700, .data[0] = 0x60, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
+	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
+	  .data[10] = 0x00, .data[11] = 0x00, },
+	{ .channel = 149, .freq = 5745, .data[0] = 0x60, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
+	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
+	  .data[10] = 0x00, .data[11] = 0x00, },
+	{ .channel = 153, .freq = 5765, .data[0] = 0x60, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
+	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
+	  .data[10] = 0x00, .data[11] = 0x00, },
+	{ .channel = 157, .freq = 5785, .data[0] = 0x60, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
+	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
+	  .data[10] = 0x00, .data[11] = 0x00, },
+	{ .channel = 161, .freq = 5805, .data[0] = 0x60, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
+	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
+	  .data[10] = 0x00, .data[11] = 0x00, },
+	{ .channel = 165, .freq = 5825, .data[0] = 0x60, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
+	  .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
+	  .data[10] = 0x00, .data[11] = 0x00, },
+	{ .channel = 184, .freq = 4920, .data[0] = 0x6E, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x09, .data[5] = 0x0E,
+	  .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xC0,
+	  .data[10] = 0x50, .data[11] = 0x00, },
+	{ .channel = 188, .freq = 4940, .data[0] = 0x6E, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x09, .data[5] = 0x0D,
+	  .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xB0,
+	  .data[10] = 0x50, .data[11] = 0x00, },
+	{ .channel = 192, .freq = 4960, .data[0] = 0x6E, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0C,
+	  .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xB0,
+	  .data[10] = 0x50, .data[11] = 0x00, },
+	{ .channel = 196, .freq = 4980, .data[0] = 0x6D, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0C,
+	  .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xA0,
+	  .data[10] = 0x40, .data[11] = 0x00, },
+	{ .channel = 200, .freq = 5000, .data[0] = 0x6D, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0B,
+	  .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xA0,
+	  .data[10] = 0x40, .data[11] = 0x00, },
+	{ .channel = 204, .freq = 5020, .data[0] = 0x6D, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0A,
+	  .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xA0,
+	  .data[10] = 0x40, .data[11] = 0x00, },
+	{ .channel = 208, .freq = 5040, .data[0] = 0x6C, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x07, .data[5] = 0x09,
+	  .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0x90,
+	  .data[10] = 0x40, .data[11] = 0x00, },
+	{ .channel = 212, .freq = 5060, .data[0] = 0x6C, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x06, .data[5] = 0x08,
+	  .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0x90,
+	  .data[10] = 0x40, .data[11] = 0x00, },
+	{ .channel = 216, .freq = 5080, .data[0] = 0x6C, .data[1] = 0x0C,
+	  .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x05, .data[5] = 0x08,
+	  .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0x90,
+	  .data[10] = 0x40, .data[11] = 0x00, },
+};
+
+static void lpphy_b2062_reset_pll_bias(struct b43_wldev *dev)
+{
+	b43_radio_write(dev, B2062_S_RFPLL_CTL2, 0xFF);
+	udelay(20);
+	if (dev->dev->chip_id == 0x5354) {
+		b43_radio_write(dev, B2062_N_COMM1, 4);
+		b43_radio_write(dev, B2062_S_RFPLL_CTL2, 4);
+	} else {
+		b43_radio_write(dev, B2062_S_RFPLL_CTL2, 0);
+	}
+	udelay(5);
+}
+
+static void lpphy_b2062_vco_calib(struct b43_wldev *dev)
+{
+	b43_radio_write(dev, B2062_S_RFPLL_CTL21, 0x42);
+	b43_radio_write(dev, B2062_S_RFPLL_CTL21, 0x62);
+	udelay(200);
+}
+
+static int lpphy_b2062_tune(struct b43_wldev *dev,
+			    unsigned int channel)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	struct ssb_bus *bus = dev->dev->sdev->bus;
+	const struct b206x_channel *chandata = NULL;
+	u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
+	u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9;
+	int i, err = 0;
+
+	for (i = 0; i < ARRAY_SIZE(b2062_chantbl); i++) {
+		if (b2062_chantbl[i].channel == channel) {
+			chandata = &b2062_chantbl[i];
+			break;
+		}
+	}
+
+	if (B43_WARN_ON(!chandata))
+		return -EINVAL;
+
+	b43_radio_set(dev, B2062_S_RFPLL_CTL14, 0x04);
+	b43_radio_write(dev, B2062_N_LGENA_TUNE0, chandata->data[0]);
+	b43_radio_write(dev, B2062_N_LGENA_TUNE2, chandata->data[1]);
+	b43_radio_write(dev, B2062_N_LGENA_TUNE3, chandata->data[2]);
+	b43_radio_write(dev, B2062_N_TX_TUNE, chandata->data[3]);
+	b43_radio_write(dev, B2062_S_LGENG_CTL1, chandata->data[4]);
+	b43_radio_write(dev, B2062_N_LGENA_CTL5, chandata->data[5]);
+	b43_radio_write(dev, B2062_N_LGENA_CTL6, chandata->data[6]);
+	b43_radio_write(dev, B2062_N_TX_PGA, chandata->data[7]);
+	b43_radio_write(dev, B2062_N_TX_PAD, chandata->data[8]);
+
+	tmp1 = crystal_freq / 1000;
+	tmp2 = lpphy->pdiv * 1000;
+	b43_radio_write(dev, B2062_S_RFPLL_CTL33, 0xCC);
+	b43_radio_write(dev, B2062_S_RFPLL_CTL34, 0x07);
+	lpphy_b2062_reset_pll_bias(dev);
+	tmp3 = tmp2 * channel2freq_lp(channel);
+	if (channel2freq_lp(channel) < 4000)
+		tmp3 *= 2;
+	tmp4 = 48 * tmp1;
+	tmp6 = tmp3 / tmp4;
+	tmp7 = tmp3 % tmp4;
+	b43_radio_write(dev, B2062_S_RFPLL_CTL26, tmp6);
+	tmp5 = tmp7 * 0x100;
+	tmp6 = tmp5 / tmp4;
+	tmp7 = tmp5 % tmp4;
+	b43_radio_write(dev, B2062_S_RFPLL_CTL27, tmp6);
+	tmp5 = tmp7 * 0x100;
+	tmp6 = tmp5 / tmp4;
+	tmp7 = tmp5 % tmp4;
+	b43_radio_write(dev, B2062_S_RFPLL_CTL28, tmp6);
+	tmp5 = tmp7 * 0x100;
+	tmp6 = tmp5 / tmp4;
+	tmp7 = tmp5 % tmp4;
+	b43_radio_write(dev, B2062_S_RFPLL_CTL29, tmp6 + ((2 * tmp7) / tmp4));
+	tmp8 = b43_radio_read(dev, B2062_S_RFPLL_CTL19);
+	tmp9 = ((2 * tmp3 * (tmp8 + 1)) + (3 * tmp1)) / (6 * tmp1);
+	b43_radio_write(dev, B2062_S_RFPLL_CTL23, (tmp9 >> 8) + 16);
+	b43_radio_write(dev, B2062_S_RFPLL_CTL24, tmp9 & 0xFF);
+
+	lpphy_b2062_vco_calib(dev);
+	if (b43_radio_read(dev, B2062_S_RFPLL_CTL3) & 0x10) {
+		b43_radio_write(dev, B2062_S_RFPLL_CTL33, 0xFC);
+		b43_radio_write(dev, B2062_S_RFPLL_CTL34, 0);
+		lpphy_b2062_reset_pll_bias(dev);
+		lpphy_b2062_vco_calib(dev);
+		if (b43_radio_read(dev, B2062_S_RFPLL_CTL3) & 0x10)
+			err = -EIO;
+	}
+
+	b43_radio_mask(dev, B2062_S_RFPLL_CTL14, ~0x04);
+	return err;
+}
+
+static void lpphy_b2063_vco_calib(struct b43_wldev *dev)
+{
+	u16 tmp;
+
+	b43_radio_mask(dev, B2063_PLL_SP1, ~0x40);
+	tmp = b43_radio_read(dev, B2063_PLL_JTAG_CALNRST) & 0xF8;
+	b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp);
+	udelay(1);
+	b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x4);
+	udelay(1);
+	b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x6);
+	udelay(1);
+	b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x7);
+	udelay(300);
+	b43_radio_set(dev, B2063_PLL_SP1, 0x40);
+}
+
+static int lpphy_b2063_tune(struct b43_wldev *dev,
+			    unsigned int channel)
+{
+	struct ssb_bus *bus = dev->dev->sdev->bus;
+
+	static const struct b206x_channel *chandata = NULL;
+	u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
+	u32 freqref, vco_freq, val1, val2, val3, timeout, timeoutref, count;
+	u16 old_comm15, scale;
+	u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
+	int i, div = (crystal_freq <= 26000000 ? 1 : 2);
+
+	for (i = 0; i < ARRAY_SIZE(b2063_chantbl); i++) {
+		if (b2063_chantbl[i].channel == channel) {
+			chandata = &b2063_chantbl[i];
+			break;
+		}
+	}
+
+	if (B43_WARN_ON(!chandata))
+		return -EINVAL;
+
+	b43_radio_write(dev, B2063_LOGEN_VCOBUF1, chandata->data[0]);
+	b43_radio_write(dev, B2063_LOGEN_MIXER2, chandata->data[1]);
+	b43_radio_write(dev, B2063_LOGEN_BUF2, chandata->data[2]);
+	b43_radio_write(dev, B2063_LOGEN_RCCR1, chandata->data[3]);
+	b43_radio_write(dev, B2063_A_RX_1ST3, chandata->data[4]);
+	b43_radio_write(dev, B2063_A_RX_2ND1, chandata->data[5]);
+	b43_radio_write(dev, B2063_A_RX_2ND4, chandata->data[6]);
+	b43_radio_write(dev, B2063_A_RX_2ND7, chandata->data[7]);
+	b43_radio_write(dev, B2063_A_RX_PS6, chandata->data[8]);
+	b43_radio_write(dev, B2063_TX_RF_CTL2, chandata->data[9]);
+	b43_radio_write(dev, B2063_TX_RF_CTL5, chandata->data[10]);
+	b43_radio_write(dev, B2063_PA_CTL11, chandata->data[11]);
+
+	old_comm15 = b43_radio_read(dev, B2063_COMM15);
+	b43_radio_set(dev, B2063_COMM15, 0x1E);
+
+	if (chandata->freq > 4000) /* spec says 2484, but 4000 is safer */
+		vco_freq = chandata->freq << 1;
+	else
+		vco_freq = chandata->freq << 2;
+
+	freqref = crystal_freq * 3;
+	val1 = lpphy_qdiv_roundup(crystal_freq, 1000000, 16);
+	val2 = lpphy_qdiv_roundup(crystal_freq, 1000000 * div, 16);
+	val3 = lpphy_qdiv_roundup(vco_freq, 3, 16);
+	timeout = ((((8 * crystal_freq) / (div * 5000000)) + 1) >> 1) - 1;
+	b43_radio_write(dev, B2063_PLL_JTAG_PLL_VCO_CALIB3, 0x2);
+	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_VCO_CALIB6,
+			  0xFFF8, timeout >> 2);
+	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_VCO_CALIB7,
+			  0xFF9F,timeout << 5);
+
+	timeoutref = ((((8 * crystal_freq) / (div * (timeout + 1))) +
+						999999) / 1000000) + 1;
+	b43_radio_write(dev, B2063_PLL_JTAG_PLL_VCO_CALIB5, timeoutref);
+
+	count = lpphy_qdiv_roundup(val3, val2 + 16, 16);
+	count *= (timeout + 1) * (timeoutref + 1);
+	count--;
+	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_VCO_CALIB7,
+						0xF0, count >> 8);
+	b43_radio_write(dev, B2063_PLL_JTAG_PLL_VCO_CALIB8, count & 0xFF);
+
+	tmp1 = ((val3 * 62500) / freqref) << 4;
+	tmp2 = ((val3 * 62500) % freqref) << 4;
+	while (tmp2 >= freqref) {
+		tmp1++;
+		tmp2 -= freqref;
+	}
+	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_SG1, 0xFFE0, tmp1 >> 4);
+	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_SG2, 0xFE0F, tmp1 << 4);
+	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_SG2, 0xFFF0, tmp1 >> 16);
+	b43_radio_write(dev, B2063_PLL_JTAG_PLL_SG3, (tmp2 >> 8) & 0xFF);
+	b43_radio_write(dev, B2063_PLL_JTAG_PLL_SG4, tmp2 & 0xFF);
+
+	b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF1, 0xB9);
+	b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF2, 0x88);
+	b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF3, 0x28);
+	b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF4, 0x63);
+
+	tmp3 = ((41 * (val3 - 3000)) /1200) + 27;
+	tmp4 = lpphy_qdiv_roundup(132000 * tmp1, 8451, 16);
+
+	if ((tmp4 + tmp3 - 1) / tmp3 > 60) {
+		scale = 1;
+		tmp5 = ((tmp4 + tmp3) / (tmp3 << 1)) - 8;
+	} else {
+		scale = 0;
+		tmp5 = ((tmp4 + (tmp3 >> 1)) / tmp3) - 8;
+	}
+	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFC0, tmp5);
+	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFBF, scale << 6);
+
+	tmp6 = lpphy_qdiv_roundup(100 * val1, val3, 16);
+	tmp6 *= (tmp5 * 8) * (scale + 1);
+	if (tmp6 > 150)
+		tmp6 = 0;
+
+	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFE0, tmp6);
+	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFDF, scale << 5);
+
+	b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFFFB, 0x4);
+	if (crystal_freq > 26000000)
+		b43_radio_set(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0x2);
+	else
+		b43_radio_mask(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFD);
+
+	if (val1 == 45)
+		b43_radio_set(dev, B2063_PLL_JTAG_PLL_VCO1, 0x2);
+	else
+		b43_radio_mask(dev, B2063_PLL_JTAG_PLL_VCO1, 0xFD);
+
+	b43_radio_set(dev, B2063_PLL_SP2, 0x3);
+	udelay(1);
+	b43_radio_mask(dev, B2063_PLL_SP2, 0xFFFC);
+	lpphy_b2063_vco_calib(dev);
+	b43_radio_write(dev, B2063_COMM15, old_comm15);
+
+	return 0;
+}
+
+static int b43_lpphy_op_switch_channel(struct b43_wldev *dev,
+				       unsigned int new_channel)
+{
+	struct b43_phy_lp *lpphy = dev->phy.lp;
+	int err;
+
+	if (dev->phy.radio_ver == 0x2063) {
+		err = lpphy_b2063_tune(dev, new_channel);
+		if (err)
+			return err;
+	} else {
+		err = lpphy_b2062_tune(dev, new_channel);
+		if (err)
+			return err;
+		lpphy_set_analog_filter(dev, new_channel);
+		lpphy_adjust_gain_table(dev, channel2freq_lp(new_channel));
+	}
+
+	lpphy->channel = new_channel;
+	b43_write16(dev, B43_MMIO_CHANNEL, new_channel);
+
+	return 0;
+}
+
+static int b43_lpphy_op_init(struct b43_wldev *dev)
+{
+	int err;
+
+	if (dev->dev->bus_type != B43_BUS_SSB) {
+		b43err(dev->wl, "LP-PHY is supported only on SSB!\n");
+		return -EOPNOTSUPP;
+	}
+
+	lpphy_read_band_sprom(dev); //FIXME should this be in prepare_structs?
+	lpphy_baseband_init(dev);
+	lpphy_radio_init(dev);
+	lpphy_calibrate_rc(dev);
+	err = b43_lpphy_op_switch_channel(dev, 7);
+	if (err) {
+		b43dbg(dev->wl, "Switch to channel 7 failed, error = %d.\n",
+		       err);
+	}
+	lpphy_tx_pctl_init(dev);
+	lpphy_calibration(dev);
+	//TODO ACI init
+
+	return 0;
+}
+
+static void b43_lpphy_op_adjust_txpower(struct b43_wldev *dev)
+{
+	//TODO
+}
+
+static enum b43_txpwr_result b43_lpphy_op_recalc_txpower(struct b43_wldev *dev,
+							 bool ignore_tssi)
+{
+	//TODO
+	return B43_TXPWR_RES_DONE;
+}
+
+static void b43_lpphy_op_switch_analog(struct b43_wldev *dev, bool on)
+{
+       if (on) {
+               b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xfff8);
+       } else {
+               b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0x0007);
+               b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 0x0007);
+       }
+}
+
+static void b43_lpphy_op_pwork_15sec(struct b43_wldev *dev)
+{
+	//TODO
+}
+
+const struct b43_phy_operations b43_phyops_lp = {
+	.allocate		= b43_lpphy_op_allocate,
+	.free			= b43_lpphy_op_free,
+	.prepare_structs	= b43_lpphy_op_prepare_structs,
+	.init			= b43_lpphy_op_init,
+	.phy_maskset		= b43_lpphy_op_maskset,
+	.radio_read		= b43_lpphy_op_radio_read,
+	.radio_write		= b43_lpphy_op_radio_write,
+	.software_rfkill	= b43_lpphy_op_software_rfkill,
+	.switch_analog		= b43_lpphy_op_switch_analog,
+	.switch_channel		= b43_lpphy_op_switch_channel,
+	.get_default_chan	= b43_lpphy_op_get_default_chan,
+	.set_rx_antenna		= b43_lpphy_op_set_rx_antenna,
+	.recalc_txpower		= b43_lpphy_op_recalc_txpower,
+	.adjust_txpower		= b43_lpphy_op_adjust_txpower,
+	.pwork_15sec		= b43_lpphy_op_pwork_15sec,
+	.pwork_60sec		= lpphy_calibration,
+};
diff --git a/drivers/net/wireless/broadcom/b43/phy_lp.h b/drivers/net/wireless/broadcom/b43/phy_lp.h
new file mode 100644
index 0000000..50bef2e
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/phy_lp.h
@@ -0,0 +1,913 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef LINUX_B43_PHY_LP_H_
+#define LINUX_B43_PHY_LP_H_
+
+/* Definitions for the LP-PHY */
+
+
+/* The CCK PHY register range. */
+#define B43_LPPHY_B_VERSION			B43_PHY_CCK(0x00) /* B PHY version */
+#define B43_LPPHY_B_BBCONFIG			B43_PHY_CCK(0x01) /* B PHY BBConfig */
+#define B43_LPPHY_B_RX_STAT0			B43_PHY_CCK(0x04) /* B PHY RX Status0 */
+#define B43_LPPHY_B_RX_STAT1			B43_PHY_CCK(0x05) /* B PHY RX Status1 */
+#define B43_LPPHY_B_CRS_THRESH			B43_PHY_CCK(0x06) /* B PHY CRS Thresh */
+#define B43_LPPHY_B_TXERROR			B43_PHY_CCK(0x07) /* B PHY TxError */
+#define B43_LPPHY_B_CHANNEL			B43_PHY_CCK(0x08) /* B PHY Channel */
+#define B43_LPPHY_B_WORKAROUND			B43_PHY_CCK(0x09) /* B PHY workaround */
+#define B43_LPPHY_B_TEST			B43_PHY_CCK(0x0A) /* B PHY Test */
+#define B43_LPPHY_B_FOURWIRE_ADDR		B43_PHY_CCK(0x0B) /* B PHY Fourwire Address */
+#define B43_LPPHY_B_FOURWIRE_DATA_HI		B43_PHY_CCK(0x0C) /* B PHY Fourwire Data Hi */
+#define B43_LPPHY_B_FOURWIRE_DATA_LO		B43_PHY_CCK(0x0D) /* B PHY Fourwire Data Lo */
+#define B43_LPPHY_B_BIST_STAT			B43_PHY_CCK(0x0E) /* B PHY Bist Status */
+#define B43_LPPHY_PA_RAMP_TX_TO			B43_PHY_CCK(0x10) /* PA Ramp TX Timeout */
+#define B43_LPPHY_RF_SYNTH_DC_TIMER		B43_PHY_CCK(0x11) /* RF Synth DC Timer */
+#define B43_LPPHY_PA_RAMP_TX_TIME_IN		B43_PHY_CCK(0x12) /* PA ramp TX Time in */
+#define B43_LPPHY_RX_FILTER_TIME_IN		B43_PHY_CCK(0x13) /* RX Filter Time in */
+#define B43_LPPHY_PLL_COEFF_S			B43_PHY_CCK(0x18) /* PLL Coefficient(s) */
+#define B43_LPPHY_PLL_OUT			B43_PHY_CCK(0x19) /* PLL Out */
+#define B43_LPPHY_RSSI_THRES			B43_PHY_CCK(0x20) /* RSSI Threshold */
+#define B43_LPPHY_IQ_THRES_HH			B43_PHY_CCK(0x21) /* IQ Threshold HH */
+#define B43_LPPHY_IQ_THRES_H			B43_PHY_CCK(0x22) /* IQ Threshold H */
+#define B43_LPPHY_IQ_THRES_L			B43_PHY_CCK(0x23) /* IQ Threshold L */
+#define B43_LPPHY_IQ_THRES_LL			B43_PHY_CCK(0x24) /* IQ Threshold LL */
+#define B43_LPPHY_AGC_GAIN			B43_PHY_CCK(0x25) /* AGC Gain */
+#define B43_LPPHY_LNA_GAIN_RANGE		B43_PHY_CCK(0x26) /* LNA Gain Range */
+#define B43_LPPHY_JSSI				B43_PHY_CCK(0x27) /* JSSI */
+#define B43_LPPHY_TSSI_CTL			B43_PHY_CCK(0x28) /* TSSI Control */
+#define B43_LPPHY_TSSI				B43_PHY_CCK(0x29) /* TSSI */
+#define B43_LPPHY_TR_LOSS			B43_PHY_CCK(0x2A) /* TR Loss */
+#define B43_LPPHY_LO_LEAKAGE			B43_PHY_CCK(0x2B) /* LO Leakage */
+#define B43_LPPHY_LO_RSSIACC			B43_PHY_CCK(0x2C) /* LO RSSIAcc */
+#define B43_LPPHY_LO_IQ_MAG_ACC			B43_PHY_CCK(0x2D) /* LO IQ Mag Acc */
+#define B43_LPPHY_TX_DCOFFSET1			B43_PHY_CCK(0x2E) /* TX DCOffset1 */
+#define B43_LPPHY_TX_DCOFFSET2			B43_PHY_CCK(0x2F) /* TX DCOffset2 */
+#define B43_LPPHY_SYNCPEAKCNT			B43_PHY_CCK(0x30) /* SyncPeakCnt */
+#define B43_LPPHY_SYNCFREQ			B43_PHY_CCK(0x31) /* SyncFreq */
+#define B43_LPPHY_SYNCDIVERSITYCTL		B43_PHY_CCK(0x32) /* SyncDiversityControl */
+#define B43_LPPHY_PEAKENERGYL			B43_PHY_CCK(0x33) /* PeakEnergyL */
+#define B43_LPPHY_PEAKENERGYH			B43_PHY_CCK(0x34) /* PeakEnergyH */
+#define B43_LPPHY_SYNCCTL			B43_PHY_CCK(0x35) /* SyncControl */
+#define B43_LPPHY_DSSSSTEP			B43_PHY_CCK(0x38) /* DsssStep */
+#define B43_LPPHY_DSSSWARMUP			B43_PHY_CCK(0x39) /* DsssWarmup */
+#define B43_LPPHY_DSSSSIGPOW			B43_PHY_CCK(0x3D) /* DsssSigPow */
+#define B43_LPPHY_SFDDETECTBLOCKTIME		B43_PHY_CCK(0x40) /* SfdDetectBlockTIme */
+#define B43_LPPHY_SFDTO				B43_PHY_CCK(0x41) /* SFDTimeOut */
+#define B43_LPPHY_SFDCTL			B43_PHY_CCK(0x42) /* SFDControl */
+#define B43_LPPHY_RXDBG				B43_PHY_CCK(0x43) /* rxDebug */
+#define B43_LPPHY_RX_DELAYCOMP			B43_PHY_CCK(0x44) /* RX DelayComp */
+#define B43_LPPHY_CRSDROPOUTTO			B43_PHY_CCK(0x45) /* CRSDropoutTimeout */
+#define B43_LPPHY_PSEUDOSHORTTO			B43_PHY_CCK(0x46) /* PseudoShortTimeout */
+#define B43_LPPHY_PR3931			B43_PHY_CCK(0x47) /* PR3931 */
+#define B43_LPPHY_DSSSCOEFF1			B43_PHY_CCK(0x48) /* DSSSCoeff1 */
+#define B43_LPPHY_DSSSCOEFF2			B43_PHY_CCK(0x49) /* DSSSCoeff2 */
+#define B43_LPPHY_CCKCOEFF1			B43_PHY_CCK(0x4A) /* CCKCoeff1 */
+#define B43_LPPHY_CCKCOEFF2			B43_PHY_CCK(0x4B) /* CCKCoeff2 */
+#define B43_LPPHY_TRCORR			B43_PHY_CCK(0x4C) /* TRCorr */
+#define B43_LPPHY_ANGLESCALE			B43_PHY_CCK(0x4D) /* AngleScale */
+#define B43_LPPHY_OPTIONALMODES2		B43_PHY_CCK(0x4F) /* OptionalModes2 */
+#define B43_LPPHY_CCKLMSSTEPSIZE		B43_PHY_CCK(0x50) /* CCKLMSStepSize */
+#define B43_LPPHY_DFEBYPASS			B43_PHY_CCK(0x51) /* DFEBypass */
+#define B43_LPPHY_CCKSTARTDELAYLONG		B43_PHY_CCK(0x52) /* CCKStartDelayLong */
+#define B43_LPPHY_CCKSTARTDELAYSHORT		B43_PHY_CCK(0x53) /* CCKStartDelayShort */
+#define B43_LPPHY_PPROCCHDELAY			B43_PHY_CCK(0x54) /* PprocChDelay */
+#define B43_LPPHY_PPROCONOFF			B43_PHY_CCK(0x55) /* PProcOnOff */
+#define B43_LPPHY_LNAGAINTWOBIT10		B43_PHY_CCK(0x5B) /* LNAGainTwoBit10 */
+#define B43_LPPHY_LNAGAINTWOBIT32		B43_PHY_CCK(0x5C) /* LNAGainTwoBit32 */
+#define B43_LPPHY_OPTIONALMODES			B43_PHY_CCK(0x5D) /* OptionalModes */
+#define B43_LPPHY_B_RX_STAT2			B43_PHY_CCK(0x5E) /* B PHY RX Status2 */
+#define B43_LPPHY_B_RX_STAT3			B43_PHY_CCK(0x5F) /* B PHY RX Status3 */
+#define B43_LPPHY_PWDNDACDELAY			B43_PHY_CCK(0x63) /* pwdnDacDelay */
+#define B43_LPPHY_FINEDIGIGAIN_CTL		B43_PHY_CCK(0x67) /* FineDigiGain Control */
+#define B43_LPPHY_LG2GAINTBLLNA8		B43_PHY_CCK(0x68) /* Lg2GainTblLNA8 */
+#define B43_LPPHY_LG2GAINTBLLNA28		B43_PHY_CCK(0x69) /* Lg2GainTblLNA28 */
+#define B43_LPPHY_GAINTBLLNATRSW		B43_PHY_CCK(0x6A) /* GainTblLNATrSw */
+#define B43_LPPHY_PEAKENERGY			B43_PHY_CCK(0x6B) /* PeakEnergy */
+#define B43_LPPHY_LG2INITGAIN			B43_PHY_CCK(0x6C) /* lg2InitGain */
+#define B43_LPPHY_BLANKCOUNTLNAPGA		B43_PHY_CCK(0x6D) /* BlankCountLnaPga */
+#define B43_LPPHY_LNAGAINTWOBIT54		B43_PHY_CCK(0x6E) /* LNAGainTwoBit54 */
+#define B43_LPPHY_LNAGAINTWOBIT76		B43_PHY_CCK(0x6F) /* LNAGainTwoBit76 */
+#define B43_LPPHY_JSSICTL			B43_PHY_CCK(0x70) /* JSSIControl */
+#define B43_LPPHY_LG2GAINTBLLNA44		B43_PHY_CCK(0x71) /* Lg2GainTblLNA44 */
+#define B43_LPPHY_LG2GAINTBLLNA62		B43_PHY_CCK(0x72) /* Lg2GainTblLNA62 */
+
+/* The OFDM PHY register range. */
+#define B43_LPPHY_VERSION			B43_PHY_OFDM(0x00) /* Version */
+#define B43_LPPHY_BBCONFIG			B43_PHY_OFDM(0x01) /* BBConfig */
+#define B43_LPPHY_RX_STAT0			B43_PHY_OFDM(0x04) /* RX Status0 */
+#define B43_LPPHY_RX_STAT1			B43_PHY_OFDM(0x05) /* RX Status1 */
+#define B43_LPPHY_TX_ERROR			B43_PHY_OFDM(0x07) /* TX Error */
+#define B43_LPPHY_CHANNEL			B43_PHY_OFDM(0x08) /* Channel */
+#define B43_LPPHY_WORKAROUND			B43_PHY_OFDM(0x09) /* workaround */
+#define B43_LPPHY_FOURWIRE_ADDR			B43_PHY_OFDM(0x0B) /* Fourwire Address */
+#define B43_LPPHY_FOURWIREDATAHI		B43_PHY_OFDM(0x0C) /* FourwireDataHi */
+#define B43_LPPHY_FOURWIREDATALO		B43_PHY_OFDM(0x0D) /* FourwireDataLo */
+#define B43_LPPHY_BISTSTAT0			B43_PHY_OFDM(0x0E) /* BistStatus0 */
+#define B43_LPPHY_BISTSTAT1			B43_PHY_OFDM(0x0F) /* BistStatus1 */
+#define B43_LPPHY_CRSGAIN_CTL			B43_PHY_OFDM(0x10) /* crsgain Control */
+#define B43_LPPHY_OFDMPWR_THRESH0		B43_PHY_OFDM(0x11) /* ofdmPower Thresh0 */
+#define B43_LPPHY_OFDMPWR_THRESH1		B43_PHY_OFDM(0x12) /* ofdmPower Thresh1 */
+#define B43_LPPHY_OFDMPWR_THRESH2		B43_PHY_OFDM(0x13) /* ofdmPower Thresh2 */
+#define B43_LPPHY_DSSSPWR_THRESH0		B43_PHY_OFDM(0x14) /* dsssPower Thresh0 */
+#define B43_LPPHY_DSSSPWR_THRESH1		B43_PHY_OFDM(0x15) /* dsssPower Thresh1 */
+#define B43_LPPHY_MINPWR_LEVEL			B43_PHY_OFDM(0x16) /* MinPower Level */
+#define B43_LPPHY_OFDMSYNCTHRESH0		B43_PHY_OFDM(0x17) /* ofdmSyncThresh0 */
+#define B43_LPPHY_OFDMSYNCTHRESH1		B43_PHY_OFDM(0x18) /* ofdmSyncThresh1 */
+#define B43_LPPHY_FINEFREQEST			B43_PHY_OFDM(0x19) /* FineFreqEst */
+#define B43_LPPHY_IDLEAFTERPKTRXTO		B43_PHY_OFDM(0x1A) /* IDLEafterPktRXTimeout */
+#define B43_LPPHY_LTRN_CTL			B43_PHY_OFDM(0x1B) /* LTRN Control */
+#define B43_LPPHY_DCOFFSETTRANSIENT		B43_PHY_OFDM(0x1C) /* DCOffsetTransient */
+#define B43_LPPHY_PREAMBLEINTO			B43_PHY_OFDM(0x1D) /* PreambleInTimeout */
+#define B43_LPPHY_PREAMBLECONFIRMTO		B43_PHY_OFDM(0x1E) /* PreambleConfirmTimeout */
+#define B43_LPPHY_CLIPTHRESH			B43_PHY_OFDM(0x1F) /* ClipThresh */
+#define B43_LPPHY_CLIPCTRTHRESH			B43_PHY_OFDM(0x20) /* ClipCtrThresh */
+#define B43_LPPHY_OFDMSYNCTIMER_CTL		B43_PHY_OFDM(0x21) /* ofdmSyncTimer Control */
+#define B43_LPPHY_WAITFORPHYSELTO		B43_PHY_OFDM(0x22) /* WaitforPHYSelTimeout */
+#define B43_LPPHY_HIGAINDB			B43_PHY_OFDM(0x23) /* HiGainDB */
+#define B43_LPPHY_LOWGAINDB			B43_PHY_OFDM(0x24) /* LowGainDB */
+#define B43_LPPHY_VERYLOWGAINDB			B43_PHY_OFDM(0x25) /* VeryLowGainDB */
+#define B43_LPPHY_GAINMISMATCH			B43_PHY_OFDM(0x26) /* gainMismatch */
+#define B43_LPPHY_GAINDIRECTMISMATCH		B43_PHY_OFDM(0x27) /* gaindirectMismatch */
+#define B43_LPPHY_PWR_THRESH0			B43_PHY_OFDM(0x28) /* Power Thresh0 */
+#define B43_LPPHY_PWR_THRESH1			B43_PHY_OFDM(0x29) /* Power Thresh1 */
+#define B43_LPPHY_DETECTOR_DELAY_ADJUST		B43_PHY_OFDM(0x2A) /* Detector Delay Adjust */
+#define B43_LPPHY_REDUCED_DETECTOR_DELAY	B43_PHY_OFDM(0x2B) /* Reduced Detector Delay */
+#define B43_LPPHY_DATA_TO			B43_PHY_OFDM(0x2C) /* data Timeout */
+#define B43_LPPHY_CORRELATOR_DIS_DELAY		B43_PHY_OFDM(0x2D) /* correlator Dis Delay */
+#define B43_LPPHY_DIVERSITY_GAINBACK		B43_PHY_OFDM(0x2E) /* Diversity GainBack */
+#define B43_LPPHY_DSSS_CONFIRM_CNT		B43_PHY_OFDM(0x2F) /* DSSS Confirm Cnt */
+#define B43_LPPHY_DC_BLANK_INT			B43_PHY_OFDM(0x30) /* DC Blank Interval */
+#define B43_LPPHY_GAIN_MISMATCH_LIMIT		B43_PHY_OFDM(0x31) /* gain Mismatch Limit */
+#define B43_LPPHY_CRS_ED_THRESH			B43_PHY_OFDM(0x32) /* crs ed thresh */
+#define B43_LPPHY_PHASE_SHIFT_CTL		B43_PHY_OFDM(0x33) /* phase shift Control */
+#define B43_LPPHY_INPUT_PWRDB			B43_PHY_OFDM(0x34) /* Input PowerDB */
+#define B43_LPPHY_OFDM_SYNC_CTL			B43_PHY_OFDM(0x35) /* ofdm sync Control */
+#define B43_LPPHY_AFE_ADC_CTL_0			B43_PHY_OFDM(0x36) /* Afe ADC Control 0 */
+#define B43_LPPHY_AFE_ADC_CTL_1			B43_PHY_OFDM(0x37) /* Afe ADC Control 1 */
+#define B43_LPPHY_AFE_ADC_CTL_2			B43_PHY_OFDM(0x38) /* Afe ADC Control 2 */
+#define B43_LPPHY_AFE_DAC_CTL			B43_PHY_OFDM(0x39) /* Afe DAC Control */
+#define B43_LPPHY_AFE_CTL			B43_PHY_OFDM(0x3A) /* Afe Control */
+#define B43_LPPHY_AFE_CTL_OVR			B43_PHY_OFDM(0x3B) /* Afe Control Ovr */
+#define B43_LPPHY_AFE_CTL_OVRVAL		B43_PHY_OFDM(0x3C) /* Afe Control OvrVal */
+#define B43_LPPHY_AFE_RSSI_CTL_0		B43_PHY_OFDM(0x3D) /* Afe RSSI Control 0 */
+#define B43_LPPHY_AFE_RSSI_CTL_1		B43_PHY_OFDM(0x3E) /* Afe RSSI Control 1 */
+#define B43_LPPHY_AFE_RSSI_SEL			B43_PHY_OFDM(0x3F) /* Afe RSSI Sel */
+#define B43_LPPHY_RADAR_THRESH			B43_PHY_OFDM(0x40) /* Radar Thresh */
+#define B43_LPPHY_RADAR_BLANK_INT		B43_PHY_OFDM(0x41) /* Radar blank Interval */
+#define B43_LPPHY_RADAR_MIN_FM_INT		B43_PHY_OFDM(0x42) /* Radar min fm Interval */
+#define B43_LPPHY_RADAR_GAIN_TO			B43_PHY_OFDM(0x43) /* Radar gain timeout */
+#define B43_LPPHY_RADAR_PULSE_TO		B43_PHY_OFDM(0x44) /* Radar pulse timeout */
+#define B43_LPPHY_RADAR_DETECT_FM_CTL		B43_PHY_OFDM(0x45) /* Radar detect FM Control */
+#define B43_LPPHY_RADAR_DETECT_EN		B43_PHY_OFDM(0x46) /* Radar detect En */
+#define B43_LPPHY_RADAR_RD_DATA_REG		B43_PHY_OFDM(0x47) /* Radar Rd Data Reg */
+#define B43_LPPHY_LP_PHY_CTL			B43_PHY_OFDM(0x48) /* LP PHY Control */
+#define B43_LPPHY_CLASSIFIER_CTL		B43_PHY_OFDM(0x49) /* classifier Control */
+#define B43_LPPHY_RESET_CTL			B43_PHY_OFDM(0x4A) /* reset Control */
+#define B43_LPPHY_CLKEN_CTL			B43_PHY_OFDM(0x4B) /* ClkEn Control */
+#define B43_LPPHY_RF_OVERRIDE_0			B43_PHY_OFDM(0x4C) /* RF Override 0 */
+#define B43_LPPHY_RF_OVERRIDE_VAL_0		B43_PHY_OFDM(0x4D) /* RF Override Val 0 */
+#define B43_LPPHY_TR_LOOKUP_1			B43_PHY_OFDM(0x4E) /* TR Lookup 1 */
+#define B43_LPPHY_TR_LOOKUP_2			B43_PHY_OFDM(0x4F) /* TR Lookup 2 */
+#define B43_LPPHY_RSSISELLOOKUP1		B43_PHY_OFDM(0x50) /* RssiSelLookup1 */
+#define B43_LPPHY_IQLO_CAL_CMD			B43_PHY_OFDM(0x51) /* iqlo Cal Cmd */
+#define B43_LPPHY_IQLO_CAL_CMD_N_NUM		B43_PHY_OFDM(0x52) /* iqlo Cal Cmd N num */
+#define B43_LPPHY_IQLO_CAL_CMD_G_CTL		B43_PHY_OFDM(0x53) /* iqlo Cal Cmd G control */
+#define B43_LPPHY_MACINT_DBG_REGISTER		B43_PHY_OFDM(0x54) /* macint Debug Register */
+#define B43_LPPHY_TABLE_ADDR			B43_PHY_OFDM(0x55) /* Table Address */
+#define B43_LPPHY_TABLEDATALO			B43_PHY_OFDM(0x56) /* TabledataLo */
+#define B43_LPPHY_TABLEDATAHI			B43_PHY_OFDM(0x57) /* TabledataHi */
+#define B43_LPPHY_PHY_CRS_ENABLE_ADDR		B43_PHY_OFDM(0x58) /* phy CRS Enable Address */
+#define B43_LPPHY_IDLETIME_CTL			B43_PHY_OFDM(0x59) /* Idletime Control */
+#define B43_LPPHY_IDLETIME_CRS_ON_LO		B43_PHY_OFDM(0x5A) /* Idletime CRS On Lo */
+#define B43_LPPHY_IDLETIME_CRS_ON_HI		B43_PHY_OFDM(0x5B) /* Idletime CRS On Hi */
+#define B43_LPPHY_IDLETIME_MEAS_TIME_LO		B43_PHY_OFDM(0x5C) /* Idletime Meas Time Lo */
+#define B43_LPPHY_IDLETIME_MEAS_TIME_HI		B43_PHY_OFDM(0x5D) /* Idletime Meas Time Hi */
+#define B43_LPPHY_RESET_LEN_OFDM_TX_ADDR	B43_PHY_OFDM(0x5E) /* Reset len Ofdm TX Address */
+#define B43_LPPHY_RESET_LEN_OFDM_RX_ADDR	B43_PHY_OFDM(0x5F) /* Reset len Ofdm RX Address */
+#define B43_LPPHY_REG_CRS_ENABLE		B43_PHY_OFDM(0x60) /* reg crs enable */
+#define B43_LPPHY_PLCP_TMT_STR0_CTR_MIN		B43_PHY_OFDM(0x61) /* PLCP Tmt Str0 Ctr Min */
+#define B43_LPPHY_PKT_FSM_RESET_LEN_VAL		B43_PHY_OFDM(0x62) /* Pkt fsm Reset Len Value */
+#define B43_LPPHY_READSYM2RESET_CTL		B43_PHY_OFDM(0x63) /* readsym2reset Control */
+#define B43_LPPHY_DC_FILTER_DELAY1		B43_PHY_OFDM(0x64) /* Dc filter delay1 */
+#define B43_LPPHY_PACKET_RX_ACTIVE_TO		B43_PHY_OFDM(0x65) /* packet rx Active timeout */
+#define B43_LPPHY_ED_TOVAL			B43_PHY_OFDM(0x66) /* ed timeoutValue */
+#define B43_LPPHY_HOLD_CRS_ON_VAL		B43_PHY_OFDM(0x67) /* hold CRS On Value */
+#define B43_LPPHY_OFDM_TX_PHY_CRS_DELAY_VAL	B43_PHY_OFDM(0x69) /* ofdm tx phy CRS Delay Value */
+#define B43_LPPHY_CCK_TX_PHY_CRS_DELAY_VAL	B43_PHY_OFDM(0x6A) /* cck tx phy CRS Delay Value */
+#define B43_LPPHY_ED_ON_CONFIRM_TIMER_VAL	B43_PHY_OFDM(0x6B) /* Ed on confirm Timer Value */
+#define B43_LPPHY_ED_OFFSET_CONFIRM_TIMER_VAL	B43_PHY_OFDM(0x6C) /* Ed offset confirm Timer Value */
+#define B43_LPPHY_PHY_CRS_OFFSET_TIMER_VAL	B43_PHY_OFDM(0x6D) /* phy CRS offset Timer Value */
+#define B43_LPPHY_ADC_COMPENSATION_CTL		B43_PHY_OFDM(0x70) /* ADC Compensation Control */
+#define B43_LPPHY_LOG2_RBPSK_ADDR		B43_PHY_OFDM(0x71) /* log2 RBPSK Address */
+#define B43_LPPHY_LOG2_RQPSK_ADDR		B43_PHY_OFDM(0x72) /* log2 RQPSK Address */
+#define B43_LPPHY_LOG2_R16QAM_ADDR		B43_PHY_OFDM(0x73) /* log2 R16QAM Address */
+#define B43_LPPHY_LOG2_R64QAM_ADDR		B43_PHY_OFDM(0x74) /* log2 R64QAM Address */
+#define B43_LPPHY_OFFSET_BPSK_ADDR		B43_PHY_OFDM(0x75) /* offset BPSK Address */
+#define B43_LPPHY_OFFSET_QPSK_ADDR		B43_PHY_OFDM(0x76) /* offset QPSK Address */
+#define B43_LPPHY_OFFSET_16QAM_ADDR		B43_PHY_OFDM(0x77) /* offset 16QAM Address */
+#define B43_LPPHY_OFFSET_64QAM_ADDR		B43_PHY_OFDM(0x78) /* offset 64QAM Address */
+#define B43_LPPHY_ALPHA1			B43_PHY_OFDM(0x79) /* Alpha1 */
+#define B43_LPPHY_ALPHA2			B43_PHY_OFDM(0x7A) /* Alpha2 */
+#define B43_LPPHY_BETA1				B43_PHY_OFDM(0x7B) /* Beta1 */
+#define B43_LPPHY_BETA2				B43_PHY_OFDM(0x7C) /* Beta2 */
+#define B43_LPPHY_LOOP_NUM_ADDR			B43_PHY_OFDM(0x7D) /* Loop Num Address */
+#define B43_LPPHY_STR_COLLMAX_SMPL_ADDR		B43_PHY_OFDM(0x7E) /* Str Collmax Sample Address */
+#define B43_LPPHY_MAX_SMPL_COARSE_FINE_ADDR	B43_PHY_OFDM(0x7F) /* Max Sample Coarse/Fine Address */
+#define B43_LPPHY_MAX_SMPL_COARSE_STR0CTR_ADDR	B43_PHY_OFDM(0x80) /* Max Sample Coarse/Str0Ctr Address */
+#define B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR	B43_PHY_OFDM(0x81) /* IQ Enable Wait Time Address */
+#define B43_LPPHY_IQ_NUM_SMPLS_ADDR		B43_PHY_OFDM(0x82) /* IQ Num Samples Address */
+#define B43_LPPHY_IQ_ACC_HI_ADDR		B43_PHY_OFDM(0x83) /* IQ Acc Hi Address */
+#define B43_LPPHY_IQ_ACC_LO_ADDR		B43_PHY_OFDM(0x84) /* IQ Acc Lo Address */
+#define B43_LPPHY_IQ_I_PWR_ACC_HI_ADDR		B43_PHY_OFDM(0x85) /* IQ I PWR Acc Hi Address */
+#define B43_LPPHY_IQ_I_PWR_ACC_LO_ADDR		B43_PHY_OFDM(0x86) /* IQ I PWR Acc Lo Address */
+#define B43_LPPHY_IQ_Q_PWR_ACC_HI_ADDR		B43_PHY_OFDM(0x87) /* IQ Q PWR Acc Hi Address */
+#define B43_LPPHY_IQ_Q_PWR_ACC_LO_ADDR		B43_PHY_OFDM(0x88) /* IQ Q PWR Acc Lo Address */
+#define B43_LPPHY_MAXNUMSTEPS			B43_PHY_OFDM(0x89) /* MaxNumsteps */
+#define B43_LPPHY_ROTORPHASE_ADDR		B43_PHY_OFDM(0x8A) /* RotorPhase Address */
+#define B43_LPPHY_ADVANCEDRETARDROTOR_ADDR	B43_PHY_OFDM(0x8B) /* AdvancedRetardRotor Address */
+#define B43_LPPHY_RSSIADCDELAY_CTL_ADDR		B43_PHY_OFDM(0x8D) /* rssiAdcdelay Control Address */
+#define B43_LPPHY_TSSISTAT_ADDR			B43_PHY_OFDM(0x8E) /* tssiStatus Address */
+#define B43_LPPHY_TEMPSENSESTAT_ADDR		B43_PHY_OFDM(0x8F) /* tempsenseStatus Address */
+#define B43_LPPHY_TEMPSENSE_CTL_ADDR		B43_PHY_OFDM(0x90) /* tempsense Control Address */
+#define B43_LPPHY_WRSSISTAT_ADDR		B43_PHY_OFDM(0x91) /* wrssistatus Address */
+#define B43_LPPHY_MUFACTORADDR			B43_PHY_OFDM(0x92) /* mufactoraddr */
+#define B43_LPPHY_SCRAMSTATE_ADDR		B43_PHY_OFDM(0x93) /* scramstate Address */
+#define B43_LPPHY_TXHOLDOFFADDR			B43_PHY_OFDM(0x94) /* txholdoffaddr */
+#define B43_LPPHY_PKTGAINVAL_ADDR		B43_PHY_OFDM(0x95) /* pktgainval Address */
+#define B43_LPPHY_COARSEESTIM_ADDR		B43_PHY_OFDM(0x96) /* Coarseestim Address */
+#define B43_LPPHY_STATE_TRANSITION_ADDR		B43_PHY_OFDM(0x97) /* state Transition Address */
+#define B43_LPPHY_TRN_OFFSET_ADDR		B43_PHY_OFDM(0x98) /* TRN offset Address */
+#define B43_LPPHY_NUM_ROTOR_ADDR		B43_PHY_OFDM(0x99) /* Num Rotor Address */
+#define B43_LPPHY_VITERBI_OFFSET_ADDR		B43_PHY_OFDM(0x9A) /* Viterbi Offset Address */
+#define B43_LPPHY_SMPL_COLLECT_WAIT_ADDR	B43_PHY_OFDM(0x9B) /* Sample collect wait Address */
+#define B43_LPPHY_A_PHY_CTL_ADDR		B43_PHY_OFDM(0x9C) /* A PHY Control Address */
+#define B43_LPPHY_NUM_PASS_THROUGH_ADDR		B43_PHY_OFDM(0x9D) /* Num Pass Through Address */
+#define B43_LPPHY_RX_COMP_COEFF_S		B43_PHY_OFDM(0x9E) /* RX Comp coefficient(s) */
+#define B43_LPPHY_CPAROTATEVAL			B43_PHY_OFDM(0x9F) /* cpaRotateValue */
+#define B43_LPPHY_SMPL_PLAY_COUNT		B43_PHY_OFDM(0xA0) /* Sample play count */
+#define B43_LPPHY_SMPL_PLAY_BUFFER_CTL		B43_PHY_OFDM(0xA1) /* Sample play Buffer Control */
+#define B43_LPPHY_FOURWIRE_CTL			B43_PHY_OFDM(0xA2) /* fourwire Control */
+#define B43_LPPHY_CPA_TAILCOUNT_VAL		B43_PHY_OFDM(0xA3) /* CPA TailCount Value */
+#define B43_LPPHY_TX_PWR_CTL_CMD		B43_PHY_OFDM(0xA4) /* TX Power Control Cmd */
+#define  B43_LPPHY_TX_PWR_CTL_CMD_MODE		0xE000 /* TX power control mode mask */
+#define   B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF	0x0000 /* TX power control is OFF */
+#define   B43_LPPHY_TX_PWR_CTL_CMD_MODE_SW	0x8000 /* TX power control is SOFTWARE */
+#define   B43_LPPHY_TX_PWR_CTL_CMD_MODE_HW	0xE000 /* TX power control is HARDWARE */
+#define B43_LPPHY_TX_PWR_CTL_NNUM		B43_PHY_OFDM(0xA5) /* TX Power Control Nnum */
+#define B43_LPPHY_TX_PWR_CTL_IDLETSSI		B43_PHY_OFDM(0xA6) /* TX Power Control IdleTssi */
+#define B43_LPPHY_TX_PWR_CTL_TARGETPWR		B43_PHY_OFDM(0xA7) /* TX Power Control TargetPower */
+#define B43_LPPHY_TX_PWR_CTL_DELTAPWR_LIMIT	B43_PHY_OFDM(0xA8) /* TX Power Control DeltaPower Limit */
+#define B43_LPPHY_TX_PWR_CTL_BASEINDEX		B43_PHY_OFDM(0xA9) /* TX Power Control BaseIndex */
+#define B43_LPPHY_TX_PWR_CTL_PWR_INDEX		B43_PHY_OFDM(0xAA) /* TX Power Control Power Index */
+#define B43_LPPHY_TX_PWR_CTL_STAT		B43_PHY_OFDM(0xAB) /* TX Power Control Status */
+#define B43_LPPHY_LP_RF_SIGNAL_LUT		B43_PHY_OFDM(0xAC) /* LP RF signal LUT */
+#define B43_LPPHY_RX_RADIO_CTL_FILTER_STATE	B43_PHY_OFDM(0xAD) /* RX Radio Control Filter State */
+#define B43_LPPHY_RX_RADIO_CTL			B43_PHY_OFDM(0xAE) /* RX Radio Control */
+#define B43_LPPHY_NRSSI_STAT_ADDR		B43_PHY_OFDM(0xAF) /* NRSSI status Address */
+#define B43_LPPHY_RF_OVERRIDE_2			B43_PHY_OFDM(0xB0) /* RF override 2 */
+#define B43_LPPHY_RF_OVERRIDE_2_VAL		B43_PHY_OFDM(0xB1) /* RF override 2 val */
+#define B43_LPPHY_PS_CTL_OVERRIDE_VAL0		B43_PHY_OFDM(0xB2) /* PS Control override val0 */
+#define B43_LPPHY_PS_CTL_OVERRIDE_VAL1		B43_PHY_OFDM(0xB3) /* PS Control override val1 */
+#define B43_LPPHY_PS_CTL_OVERRIDE_VAL2		B43_PHY_OFDM(0xB4) /* PS Control override val2 */
+#define B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL	B43_PHY_OFDM(0xB5) /* TX gain Control override val */
+#define B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL	B43_PHY_OFDM(0xB6) /* RX gain Control override val */
+#define B43_LPPHY_AFE_DDFS			B43_PHY_OFDM(0xB7) /* AFE DDFS */
+#define B43_LPPHY_AFE_DDFS_POINTER_INIT		B43_PHY_OFDM(0xB8) /* AFE DDFS pointer init */
+#define B43_LPPHY_AFE_DDFS_INCR_INIT		B43_PHY_OFDM(0xB9) /* AFE DDFS incr init */
+#define B43_LPPHY_MRCNOISEREDUCTION		B43_PHY_OFDM(0xBA) /* mrcNoiseReduction */
+#define B43_LPPHY_TR_LOOKUP_3			B43_PHY_OFDM(0xBB) /* TR Lookup 3 */
+#define B43_LPPHY_TR_LOOKUP_4			B43_PHY_OFDM(0xBC) /* TR Lookup 4 */
+#define B43_LPPHY_RADAR_FIFO_STAT		B43_PHY_OFDM(0xBD) /* Radar FIFO Status */
+#define B43_LPPHY_GPIO_OUTEN			B43_PHY_OFDM(0xBE) /* GPIO Out enable */
+#define B43_LPPHY_GPIO_SELECT			B43_PHY_OFDM(0xBF) /* GPIO Select */
+#define B43_LPPHY_GPIO_OUT			B43_PHY_OFDM(0xC0) /* GPIO Out */
+#define B43_LPPHY_4C3				B43_PHY_OFDM(0xC3) /* unknown, used during BB init */
+#define B43_LPPHY_4C4				B43_PHY_OFDM(0xC4) /* unknown, used during BB init */
+#define B43_LPPHY_4C5				B43_PHY_OFDM(0xC5) /* unknown, used during BB init */
+#define B43_LPPHY_TR_LOOKUP_5			B43_PHY_OFDM(0xC7) /* TR Lookup 5 */
+#define B43_LPPHY_TR_LOOKUP_6			B43_PHY_OFDM(0xC8) /* TR Lookup 6 */
+#define B43_LPPHY_TR_LOOKUP_7			B43_PHY_OFDM(0xC9) /* TR Lookup 7 */
+#define B43_LPPHY_TR_LOOKUP_8			B43_PHY_OFDM(0xCA) /* TR Lookup 8 */
+#define B43_LPPHY_RF_PWR_OVERRIDE		B43_PHY_OFDM(0xD3) /* RF power override */
+
+
+
+/* Radio register access decorators. */
+#define B43_LP_RADIO(radio_reg)			(radio_reg)
+#define B43_LP_NORTH(radio_reg)			B43_LP_RADIO(radio_reg)
+#define B43_LP_SOUTH(radio_reg)			B43_LP_RADIO((radio_reg) | 0x4000)
+
+
+/*** Broadcom 2062 NORTH radio registers ***/
+#define B2062_N_COMM1				B43_LP_NORTH(0x000) /* Common 01 (north) */
+#define B2062_N_COMM2				B43_LP_NORTH(0x002) /* Common 02 (north) */
+#define B2062_N_COMM3				B43_LP_NORTH(0x003) /* Common 03 (north) */
+#define B2062_N_COMM4				B43_LP_NORTH(0x004) /* Common 04 (north) */
+#define B2062_N_COMM5				B43_LP_NORTH(0x005) /* Common 05 (north) */
+#define B2062_N_COMM6				B43_LP_NORTH(0x006) /* Common 06 (north) */
+#define B2062_N_COMM7				B43_LP_NORTH(0x007) /* Common 07 (north) */
+#define B2062_N_COMM8				B43_LP_NORTH(0x008) /* Common 08 (north) */
+#define B2062_N_COMM9				B43_LP_NORTH(0x009) /* Common 09 (north) */
+#define B2062_N_COMM10				B43_LP_NORTH(0x00A) /* Common 10 (north) */
+#define B2062_N_COMM11				B43_LP_NORTH(0x00B) /* Common 11 (north) */
+#define B2062_N_COMM12				B43_LP_NORTH(0x00C) /* Common 12 (north) */
+#define B2062_N_COMM13				B43_LP_NORTH(0x00D) /* Common 13 (north) */
+#define B2062_N_COMM14				B43_LP_NORTH(0x00E) /* Common 14 (north) */
+#define B2062_N_COMM15				B43_LP_NORTH(0x00F) /* Common 15 (north) */
+#define B2062_N_PDN_CTL0			B43_LP_NORTH(0x010) /* PDN Control 0 (north) */
+#define B2062_N_PDN_CTL1			B43_LP_NORTH(0x011) /* PDN Control 1 (north) */
+#define B2062_N_PDN_CTL2			B43_LP_NORTH(0x012) /* PDN Control 2 (north) */
+#define B2062_N_PDN_CTL3			B43_LP_NORTH(0x013) /* PDN Control 3 (north) */
+#define B2062_N_PDN_CTL4			B43_LP_NORTH(0x014) /* PDN Control 4 (north) */
+#define B2062_N_GEN_CTL0			B43_LP_NORTH(0x015) /* GEN Control 0 (north) */
+#define B2062_N_IQ_CALIB			B43_LP_NORTH(0x016) /* IQ Calibration (north) */
+#define B2062_N_LGENC				B43_LP_NORTH(0x017) /* LGENC (north) */
+#define B2062_N_LGENA_LPF			B43_LP_NORTH(0x018) /* LGENA LPF (north) */
+#define B2062_N_LGENA_BIAS0			B43_LP_NORTH(0x019) /* LGENA Bias 0 (north) */
+#define B2062_N_LGNEA_BIAS1			B43_LP_NORTH(0x01A) /* LGNEA Bias 1 (north) */
+#define B2062_N_LGENA_CTL0			B43_LP_NORTH(0x01B) /* LGENA Control 0 (north) */
+#define B2062_N_LGENA_CTL1			B43_LP_NORTH(0x01C) /* LGENA Control 1 (north) */
+#define B2062_N_LGENA_CTL2			B43_LP_NORTH(0x01D) /* LGENA Control 2 (north) */
+#define B2062_N_LGENA_TUNE0			B43_LP_NORTH(0x01E) /* LGENA Tune 0 (north) */
+#define B2062_N_LGENA_TUNE1			B43_LP_NORTH(0x01F) /* LGENA Tune 1 (north) */
+#define B2062_N_LGENA_TUNE2			B43_LP_NORTH(0x020) /* LGENA Tune 2 (north) */
+#define B2062_N_LGENA_TUNE3			B43_LP_NORTH(0x021) /* LGENA Tune 3 (north) */
+#define B2062_N_LGENA_CTL3			B43_LP_NORTH(0x022) /* LGENA Control 3 (north) */
+#define B2062_N_LGENA_CTL4			B43_LP_NORTH(0x023) /* LGENA Control 4 (north) */
+#define B2062_N_LGENA_CTL5			B43_LP_NORTH(0x024) /* LGENA Control 5 (north) */
+#define B2062_N_LGENA_CTL6			B43_LP_NORTH(0x025) /* LGENA Control 6 (north) */
+#define B2062_N_LGENA_CTL7			B43_LP_NORTH(0x026) /* LGENA Control 7 (north) */
+#define B2062_N_RXA_CTL0			B43_LP_NORTH(0x027) /* RXA Control 0 (north) */
+#define B2062_N_RXA_CTL1			B43_LP_NORTH(0x028) /* RXA Control 1 (north) */
+#define B2062_N_RXA_CTL2			B43_LP_NORTH(0x029) /* RXA Control 2 (north) */
+#define B2062_N_RXA_CTL3			B43_LP_NORTH(0x02A) /* RXA Control 3 (north) */
+#define B2062_N_RXA_CTL4			B43_LP_NORTH(0x02B) /* RXA Control 4 (north) */
+#define B2062_N_RXA_CTL5			B43_LP_NORTH(0x02C) /* RXA Control 5 (north) */
+#define B2062_N_RXA_CTL6			B43_LP_NORTH(0x02D) /* RXA Control 6 (north) */
+#define B2062_N_RXA_CTL7			B43_LP_NORTH(0x02E) /* RXA Control 7 (north) */
+#define B2062_N_RXBB_CTL0			B43_LP_NORTH(0x02F) /* RXBB Control 0 (north) */
+#define B2062_N_RXBB_CTL1			B43_LP_NORTH(0x030) /* RXBB Control 1 (north) */
+#define B2062_N_RXBB_CTL2			B43_LP_NORTH(0x031) /* RXBB Control 2 (north) */
+#define B2062_N_RXBB_GAIN0			B43_LP_NORTH(0x032) /* RXBB Gain 0 (north) */
+#define B2062_N_RXBB_GAIN1			B43_LP_NORTH(0x033) /* RXBB Gain 1 (north) */
+#define B2062_N_RXBB_GAIN2			B43_LP_NORTH(0x034) /* RXBB Gain 2 (north) */
+#define B2062_N_RXBB_GAIN3			B43_LP_NORTH(0x035) /* RXBB Gain 3 (north) */
+#define B2062_N_RXBB_RSSI0			B43_LP_NORTH(0x036) /* RXBB RSSI 0 (north) */
+#define B2062_N_RXBB_RSSI1			B43_LP_NORTH(0x037) /* RXBB RSSI 1 (north) */
+#define B2062_N_RXBB_CALIB0			B43_LP_NORTH(0x038) /* RXBB Calibration0 (north) */
+#define B2062_N_RXBB_CALIB1			B43_LP_NORTH(0x039) /* RXBB Calibration1 (north) */
+#define B2062_N_RXBB_CALIB2			B43_LP_NORTH(0x03A) /* RXBB Calibration2 (north) */
+#define B2062_N_RXBB_BIAS0			B43_LP_NORTH(0x03B) /* RXBB Bias 0 (north) */
+#define B2062_N_RXBB_BIAS1			B43_LP_NORTH(0x03C) /* RXBB Bias 1 (north) */
+#define B2062_N_RXBB_BIAS2			B43_LP_NORTH(0x03D) /* RXBB Bias 2 (north) */
+#define B2062_N_RXBB_BIAS3			B43_LP_NORTH(0x03E) /* RXBB Bias 3 (north) */
+#define B2062_N_RXBB_BIAS4			B43_LP_NORTH(0x03F) /* RXBB Bias 4 (north) */
+#define B2062_N_RXBB_BIAS5			B43_LP_NORTH(0x040) /* RXBB Bias 5 (north) */
+#define B2062_N_RXBB_RSSI2			B43_LP_NORTH(0x041) /* RXBB RSSI 2 (north) */
+#define B2062_N_RXBB_RSSI3			B43_LP_NORTH(0x042) /* RXBB RSSI 3 (north) */
+#define B2062_N_RXBB_RSSI4			B43_LP_NORTH(0x043) /* RXBB RSSI 4 (north) */
+#define B2062_N_RXBB_RSSI5			B43_LP_NORTH(0x044) /* RXBB RSSI 5 (north) */
+#define B2062_N_TX_CTL0				B43_LP_NORTH(0x045) /* TX Control 0 (north) */
+#define B2062_N_TX_CTL1				B43_LP_NORTH(0x046) /* TX Control 1 (north) */
+#define B2062_N_TX_CTL2				B43_LP_NORTH(0x047) /* TX Control 2 (north) */
+#define B2062_N_TX_CTL3				B43_LP_NORTH(0x048) /* TX Control 3 (north) */
+#define B2062_N_TX_CTL4				B43_LP_NORTH(0x049) /* TX Control 4 (north) */
+#define B2062_N_TX_CTL5				B43_LP_NORTH(0x04A) /* TX Control 5 (north) */
+#define B2062_N_TX_CTL6				B43_LP_NORTH(0x04B) /* TX Control 6 (north) */
+#define B2062_N_TX_CTL7				B43_LP_NORTH(0x04C) /* TX Control 7 (north) */
+#define B2062_N_TX_CTL8				B43_LP_NORTH(0x04D) /* TX Control 8 (north) */
+#define B2062_N_TX_CTL9				B43_LP_NORTH(0x04E) /* TX Control 9 (north) */
+#define B2062_N_TX_CTL_A			B43_LP_NORTH(0x04F) /* TX Control A (north) */
+#define B2062_N_TX_GC2G				B43_LP_NORTH(0x050) /* TX GC2G (north) */
+#define B2062_N_TX_GC5G				B43_LP_NORTH(0x051) /* TX GC5G (north) */
+#define B2062_N_TX_TUNE				B43_LP_NORTH(0x052) /* TX Tune (north) */
+#define B2062_N_TX_PAD				B43_LP_NORTH(0x053) /* TX PAD (north) */
+#define B2062_N_TX_PGA				B43_LP_NORTH(0x054) /* TX PGA (north) */
+#define B2062_N_TX_PADAUX			B43_LP_NORTH(0x055) /* TX PADAUX (north) */
+#define B2062_N_TX_PGAAUX			B43_LP_NORTH(0x056) /* TX PGAAUX (north) */
+#define B2062_N_TSSI_CTL0			B43_LP_NORTH(0x057) /* TSSI Control 0 (north) */
+#define B2062_N_TSSI_CTL1			B43_LP_NORTH(0x058) /* TSSI Control 1 (north) */
+#define B2062_N_TSSI_CTL2			B43_LP_NORTH(0x059) /* TSSI Control 2 (north) */
+#define B2062_N_IQ_CALIB_CTL0			B43_LP_NORTH(0x05A) /* IQ Calibration Control 0 (north) */
+#define B2062_N_IQ_CALIB_CTL1			B43_LP_NORTH(0x05B) /* IQ Calibration Control 1 (north) */
+#define B2062_N_IQ_CALIB_CTL2			B43_LP_NORTH(0x05C) /* IQ Calibration Control 2 (north) */
+#define B2062_N_CALIB_TS			B43_LP_NORTH(0x05D) /* Calibration TS (north) */
+#define B2062_N_CALIB_CTL0			B43_LP_NORTH(0x05E) /* Calibration Control 0 (north) */
+#define B2062_N_CALIB_CTL1			B43_LP_NORTH(0x05F) /* Calibration Control 1 (north) */
+#define B2062_N_CALIB_CTL2			B43_LP_NORTH(0x060) /* Calibration Control 2 (north) */
+#define B2062_N_CALIB_CTL3			B43_LP_NORTH(0x061) /* Calibration Control 3 (north) */
+#define B2062_N_CALIB_CTL4			B43_LP_NORTH(0x062) /* Calibration Control 4 (north) */
+#define B2062_N_CALIB_DBG0			B43_LP_NORTH(0x063) /* Calibration Debug 0 (north) */
+#define B2062_N_CALIB_DBG1			B43_LP_NORTH(0x064) /* Calibration Debug 1 (north) */
+#define B2062_N_CALIB_DBG2			B43_LP_NORTH(0x065) /* Calibration Debug 2 (north) */
+#define B2062_N_CALIB_DBG3			B43_LP_NORTH(0x066) /* Calibration Debug 3 (north) */
+#define B2062_N_PSENSE_CTL0			B43_LP_NORTH(0x069) /* PSENSE Control 0 (north) */
+#define B2062_N_PSENSE_CTL1			B43_LP_NORTH(0x06A) /* PSENSE Control 1 (north) */
+#define B2062_N_PSENSE_CTL2			B43_LP_NORTH(0x06B) /* PSENSE Control 2 (north) */
+#define B2062_N_TEST_BUF0			B43_LP_NORTH(0x06C) /* TEST BUF0 (north) */
+
+/*** Broadcom 2062 SOUTH radio registers ***/
+#define B2062_S_COMM1				B43_LP_SOUTH(0x000) /* Common 01 (south) */
+#define B2062_S_RADIO_ID_CODE			B43_LP_SOUTH(0x001) /* Radio ID code (south) */
+#define B2062_S_COMM2				B43_LP_SOUTH(0x002) /* Common 02 (south) */
+#define B2062_S_COMM3				B43_LP_SOUTH(0x003) /* Common 03 (south) */
+#define B2062_S_COMM4				B43_LP_SOUTH(0x004) /* Common 04 (south) */
+#define B2062_S_COMM5				B43_LP_SOUTH(0x005) /* Common 05 (south) */
+#define B2062_S_COMM6				B43_LP_SOUTH(0x006) /* Common 06 (south) */
+#define B2062_S_COMM7				B43_LP_SOUTH(0x007) /* Common 07 (south) */
+#define B2062_S_COMM8				B43_LP_SOUTH(0x008) /* Common 08 (south) */
+#define B2062_S_COMM9				B43_LP_SOUTH(0x009) /* Common 09 (south) */
+#define B2062_S_COMM10				B43_LP_SOUTH(0x00A) /* Common 10 (south) */
+#define B2062_S_COMM11				B43_LP_SOUTH(0x00B) /* Common 11 (south) */
+#define B2062_S_COMM12				B43_LP_SOUTH(0x00C) /* Common 12 (south) */
+#define B2062_S_COMM13				B43_LP_SOUTH(0x00D) /* Common 13 (south) */
+#define B2062_S_COMM14				B43_LP_SOUTH(0x00E) /* Common 14 (south) */
+#define B2062_S_COMM15				B43_LP_SOUTH(0x00F) /* Common 15 (south) */
+#define B2062_S_PDS_CTL0			B43_LP_SOUTH(0x010) /* PDS Control 0 (south) */
+#define B2062_S_PDS_CTL1			B43_LP_SOUTH(0x011) /* PDS Control 1 (south) */
+#define B2062_S_PDS_CTL2			B43_LP_SOUTH(0x012) /* PDS Control 2 (south) */
+#define B2062_S_PDS_CTL3			B43_LP_SOUTH(0x013) /* PDS Control 3 (south) */
+#define B2062_S_BG_CTL0				B43_LP_SOUTH(0x014) /* BG Control 0 (south) */
+#define B2062_S_BG_CTL1				B43_LP_SOUTH(0x015) /* BG Control 1 (south) */
+#define B2062_S_BG_CTL2				B43_LP_SOUTH(0x016) /* BG Control 2 (south) */
+#define B2062_S_LGENG_CTL0			B43_LP_SOUTH(0x017) /* LGENG Control 00 (south) */
+#define B2062_S_LGENG_CTL1			B43_LP_SOUTH(0x018) /* LGENG Control 01 (south) */
+#define B2062_S_LGENG_CTL2			B43_LP_SOUTH(0x019) /* LGENG Control 02 (south) */
+#define B2062_S_LGENG_CTL3			B43_LP_SOUTH(0x01A) /* LGENG Control 03 (south) */
+#define B2062_S_LGENG_CTL4			B43_LP_SOUTH(0x01B) /* LGENG Control 04 (south) */
+#define B2062_S_LGENG_CTL5			B43_LP_SOUTH(0x01C) /* LGENG Control 05 (south) */
+#define B2062_S_LGENG_CTL6			B43_LP_SOUTH(0x01D) /* LGENG Control 06 (south) */
+#define B2062_S_LGENG_CTL7			B43_LP_SOUTH(0x01E) /* LGENG Control 07 (south) */
+#define B2062_S_LGENG_CTL8			B43_LP_SOUTH(0x01F) /* LGENG Control 08 (south) */
+#define B2062_S_LGENG_CTL9			B43_LP_SOUTH(0x020) /* LGENG Control 09 (south) */
+#define B2062_S_LGENG_CTL10			B43_LP_SOUTH(0x021) /* LGENG Control 10 (south) */
+#define B2062_S_LGENG_CTL11			B43_LP_SOUTH(0x022) /* LGENG Control 11 (south) */
+#define B2062_S_REFPLL_CTL0			B43_LP_SOUTH(0x023) /* REFPLL Control 00 (south) */
+#define B2062_S_REFPLL_CTL1			B43_LP_SOUTH(0x024) /* REFPLL Control 01 (south) */
+#define B2062_S_REFPLL_CTL2			B43_LP_SOUTH(0x025) /* REFPLL Control 02 (south) */
+#define B2062_S_REFPLL_CTL3			B43_LP_SOUTH(0x026) /* REFPLL Control 03 (south) */
+#define B2062_S_REFPLL_CTL4			B43_LP_SOUTH(0x027) /* REFPLL Control 04 (south) */
+#define B2062_S_REFPLL_CTL5			B43_LP_SOUTH(0x028) /* REFPLL Control 05 (south) */
+#define B2062_S_REFPLL_CTL6			B43_LP_SOUTH(0x029) /* REFPLL Control 06 (south) */
+#define B2062_S_REFPLL_CTL7			B43_LP_SOUTH(0x02A) /* REFPLL Control 07 (south) */
+#define B2062_S_REFPLL_CTL8			B43_LP_SOUTH(0x02B) /* REFPLL Control 08 (south) */
+#define B2062_S_REFPLL_CTL9			B43_LP_SOUTH(0x02C) /* REFPLL Control 09 (south) */
+#define B2062_S_REFPLL_CTL10			B43_LP_SOUTH(0x02D) /* REFPLL Control 10 (south) */
+#define B2062_S_REFPLL_CTL11			B43_LP_SOUTH(0x02E) /* REFPLL Control 11 (south) */
+#define B2062_S_REFPLL_CTL12			B43_LP_SOUTH(0x02F) /* REFPLL Control 12 (south) */
+#define B2062_S_REFPLL_CTL13			B43_LP_SOUTH(0x030) /* REFPLL Control 13 (south) */
+#define B2062_S_REFPLL_CTL14			B43_LP_SOUTH(0x031) /* REFPLL Control 14 (south) */
+#define B2062_S_REFPLL_CTL15			B43_LP_SOUTH(0x032) /* REFPLL Control 15 (south) */
+#define B2062_S_REFPLL_CTL16			B43_LP_SOUTH(0x033) /* REFPLL Control 16 (south) */
+#define B2062_S_RFPLL_CTL0			B43_LP_SOUTH(0x034) /* RFPLL Control 00 (south) */
+#define B2062_S_RFPLL_CTL1			B43_LP_SOUTH(0x035) /* RFPLL Control 01 (south) */
+#define B2062_S_RFPLL_CTL2			B43_LP_SOUTH(0x036) /* RFPLL Control 02 (south) */
+#define B2062_S_RFPLL_CTL3			B43_LP_SOUTH(0x037) /* RFPLL Control 03 (south) */
+#define B2062_S_RFPLL_CTL4			B43_LP_SOUTH(0x038) /* RFPLL Control 04 (south) */
+#define B2062_S_RFPLL_CTL5			B43_LP_SOUTH(0x039) /* RFPLL Control 05 (south) */
+#define B2062_S_RFPLL_CTL6			B43_LP_SOUTH(0x03A) /* RFPLL Control 06 (south) */
+#define B2062_S_RFPLL_CTL7			B43_LP_SOUTH(0x03B) /* RFPLL Control 07 (south) */
+#define B2062_S_RFPLL_CTL8			B43_LP_SOUTH(0x03C) /* RFPLL Control 08 (south) */
+#define B2062_S_RFPLL_CTL9			B43_LP_SOUTH(0x03D) /* RFPLL Control 09 (south) */
+#define B2062_S_RFPLL_CTL10			B43_LP_SOUTH(0x03E) /* RFPLL Control 10 (south) */
+#define B2062_S_RFPLL_CTL11			B43_LP_SOUTH(0x03F) /* RFPLL Control 11 (south) */
+#define B2062_S_RFPLL_CTL12			B43_LP_SOUTH(0x040) /* RFPLL Control 12 (south) */
+#define B2062_S_RFPLL_CTL13			B43_LP_SOUTH(0x041) /* RFPLL Control 13 (south) */
+#define B2062_S_RFPLL_CTL14			B43_LP_SOUTH(0x042) /* RFPLL Control 14 (south) */
+#define B2062_S_RFPLL_CTL15			B43_LP_SOUTH(0x043) /* RFPLL Control 15 (south) */
+#define B2062_S_RFPLL_CTL16			B43_LP_SOUTH(0x044) /* RFPLL Control 16 (south) */
+#define B2062_S_RFPLL_CTL17			B43_LP_SOUTH(0x045) /* RFPLL Control 17 (south) */
+#define B2062_S_RFPLL_CTL18			B43_LP_SOUTH(0x046) /* RFPLL Control 18 (south) */
+#define B2062_S_RFPLL_CTL19			B43_LP_SOUTH(0x047) /* RFPLL Control 19 (south) */
+#define B2062_S_RFPLL_CTL20			B43_LP_SOUTH(0x048) /* RFPLL Control 20 (south) */
+#define B2062_S_RFPLL_CTL21			B43_LP_SOUTH(0x049) /* RFPLL Control 21 (south) */
+#define B2062_S_RFPLL_CTL22			B43_LP_SOUTH(0x04A) /* RFPLL Control 22 (south) */
+#define B2062_S_RFPLL_CTL23			B43_LP_SOUTH(0x04B) /* RFPLL Control 23 (south) */
+#define B2062_S_RFPLL_CTL24			B43_LP_SOUTH(0x04C) /* RFPLL Control 24 (south) */
+#define B2062_S_RFPLL_CTL25			B43_LP_SOUTH(0x04D) /* RFPLL Control 25 (south) */
+#define B2062_S_RFPLL_CTL26			B43_LP_SOUTH(0x04E) /* RFPLL Control 26 (south) */
+#define B2062_S_RFPLL_CTL27			B43_LP_SOUTH(0x04F) /* RFPLL Control 27 (south) */
+#define B2062_S_RFPLL_CTL28			B43_LP_SOUTH(0x050) /* RFPLL Control 28 (south) */
+#define B2062_S_RFPLL_CTL29			B43_LP_SOUTH(0x051) /* RFPLL Control 29 (south) */
+#define B2062_S_RFPLL_CTL30			B43_LP_SOUTH(0x052) /* RFPLL Control 30 (south) */
+#define B2062_S_RFPLL_CTL31			B43_LP_SOUTH(0x053) /* RFPLL Control 31 (south) */
+#define B2062_S_RFPLL_CTL32			B43_LP_SOUTH(0x054) /* RFPLL Control 32 (south) */
+#define B2062_S_RFPLL_CTL33			B43_LP_SOUTH(0x055) /* RFPLL Control 33 (south) */
+#define B2062_S_RFPLL_CTL34			B43_LP_SOUTH(0x056) /* RFPLL Control 34 (south) */
+#define B2062_S_RXG_CNT0			B43_LP_SOUTH(0x057) /* RXG Counter 00 (south) */
+#define B2062_S_RXG_CNT1			B43_LP_SOUTH(0x058) /* RXG Counter 01 (south) */
+#define B2062_S_RXG_CNT2			B43_LP_SOUTH(0x059) /* RXG Counter 02 (south) */
+#define B2062_S_RXG_CNT3			B43_LP_SOUTH(0x05A) /* RXG Counter 03 (south) */
+#define B2062_S_RXG_CNT4			B43_LP_SOUTH(0x05B) /* RXG Counter 04 (south) */
+#define B2062_S_RXG_CNT5			B43_LP_SOUTH(0x05C) /* RXG Counter 05 (south) */
+#define B2062_S_RXG_CNT6			B43_LP_SOUTH(0x05D) /* RXG Counter 06 (south) */
+#define B2062_S_RXG_CNT7			B43_LP_SOUTH(0x05E) /* RXG Counter 07 (south) */
+#define B2062_S_RXG_CNT8			B43_LP_SOUTH(0x05F) /* RXG Counter 08 (south) */
+#define B2062_S_RXG_CNT9			B43_LP_SOUTH(0x060) /* RXG Counter 09 (south) */
+#define B2062_S_RXG_CNT10			B43_LP_SOUTH(0x061) /* RXG Counter 10 (south) */
+#define B2062_S_RXG_CNT11			B43_LP_SOUTH(0x062) /* RXG Counter 11 (south) */
+#define B2062_S_RXG_CNT12			B43_LP_SOUTH(0x063) /* RXG Counter 12 (south) */
+#define B2062_S_RXG_CNT13			B43_LP_SOUTH(0x064) /* RXG Counter 13 (south) */
+#define B2062_S_RXG_CNT14			B43_LP_SOUTH(0x065) /* RXG Counter 14 (south) */
+#define B2062_S_RXG_CNT15			B43_LP_SOUTH(0x066) /* RXG Counter 15 (south) */
+#define B2062_S_RXG_CNT16			B43_LP_SOUTH(0x067) /* RXG Counter 16 (south) */
+#define B2062_S_RXG_CNT17			B43_LP_SOUTH(0x068) /* RXG Counter 17 (south) */
+
+
+
+/*** Broadcom 2063 radio registers ***/
+#define B2063_RADIO_ID_CODE			B43_LP_RADIO(0x001) /* Radio ID code */
+#define B2063_COMM1				B43_LP_RADIO(0x000) /* Common 01 */
+#define B2063_COMM2				B43_LP_RADIO(0x002) /* Common 02 */
+#define B2063_COMM3				B43_LP_RADIO(0x003) /* Common 03 */
+#define B2063_COMM4				B43_LP_RADIO(0x004) /* Common 04 */
+#define B2063_COMM5				B43_LP_RADIO(0x005) /* Common 05 */
+#define B2063_COMM6				B43_LP_RADIO(0x006) /* Common 06 */
+#define B2063_COMM7				B43_LP_RADIO(0x007) /* Common 07 */
+#define B2063_COMM8				B43_LP_RADIO(0x008) /* Common 08 */
+#define B2063_COMM9				B43_LP_RADIO(0x009) /* Common 09 */
+#define B2063_COMM10				B43_LP_RADIO(0x00A) /* Common 10 */
+#define B2063_COMM11				B43_LP_RADIO(0x00B) /* Common 11 */
+#define B2063_COMM12				B43_LP_RADIO(0x00C) /* Common 12 */
+#define B2063_COMM13				B43_LP_RADIO(0x00D) /* Common 13 */
+#define B2063_COMM14				B43_LP_RADIO(0x00E) /* Common 14 */
+#define B2063_COMM15				B43_LP_RADIO(0x00F) /* Common 15 */
+#define B2063_COMM16				B43_LP_RADIO(0x010) /* Common 16 */
+#define B2063_COMM17				B43_LP_RADIO(0x011) /* Common 17 */
+#define B2063_COMM18				B43_LP_RADIO(0x012) /* Common 18 */
+#define B2063_COMM19				B43_LP_RADIO(0x013) /* Common 19 */
+#define B2063_COMM20				B43_LP_RADIO(0x014) /* Common 20 */
+#define B2063_COMM21				B43_LP_RADIO(0x015) /* Common 21 */
+#define B2063_COMM22				B43_LP_RADIO(0x016) /* Common 22 */
+#define B2063_COMM23				B43_LP_RADIO(0x017) /* Common 23 */
+#define B2063_COMM24				B43_LP_RADIO(0x018) /* Common 24 */
+#define B2063_PWR_SWITCH_CTL			B43_LP_RADIO(0x019) /* POWER SWITCH Control */
+#define B2063_PLL_SP1				B43_LP_RADIO(0x01A) /* PLL SP 1 */
+#define B2063_PLL_SP2				B43_LP_RADIO(0x01B) /* PLL SP 2 */
+#define B2063_LOGEN_SP1				B43_LP_RADIO(0x01C) /* LOGEN SP 1 */
+#define B2063_LOGEN_SP2				B43_LP_RADIO(0x01D) /* LOGEN SP 2 */
+#define B2063_LOGEN_SP3				B43_LP_RADIO(0x01E) /* LOGEN SP 3 */
+#define B2063_LOGEN_SP4				B43_LP_RADIO(0x01F) /* LOGEN SP 4 */
+#define B2063_LOGEN_SP5				B43_LP_RADIO(0x020) /* LOGEN SP 5 */
+#define B2063_G_RX_SP1				B43_LP_RADIO(0x021) /* G RX SP 1 */
+#define B2063_G_RX_SP2				B43_LP_RADIO(0x022) /* G RX SP 2 */
+#define B2063_G_RX_SP3				B43_LP_RADIO(0x023) /* G RX SP 3 */
+#define B2063_G_RX_SP4				B43_LP_RADIO(0x024) /* G RX SP 4 */
+#define B2063_G_RX_SP5				B43_LP_RADIO(0x025) /* G RX SP 5 */
+#define B2063_G_RX_SP6				B43_LP_RADIO(0x026) /* G RX SP 6 */
+#define B2063_G_RX_SP7				B43_LP_RADIO(0x027) /* G RX SP 7 */
+#define B2063_G_RX_SP8				B43_LP_RADIO(0x028) /* G RX SP 8 */
+#define B2063_G_RX_SP9				B43_LP_RADIO(0x029) /* G RX SP 9 */
+#define B2063_G_RX_SP10				B43_LP_RADIO(0x02A) /* G RX SP 10 */
+#define B2063_G_RX_SP11				B43_LP_RADIO(0x02B) /* G RX SP 11 */
+#define B2063_A_RX_SP1				B43_LP_RADIO(0x02C) /* A RX SP 1 */
+#define B2063_A_RX_SP2				B43_LP_RADIO(0x02D) /* A RX SP 2 */
+#define B2063_A_RX_SP3				B43_LP_RADIO(0x02E) /* A RX SP 3 */
+#define B2063_A_RX_SP4				B43_LP_RADIO(0x02F) /* A RX SP 4 */
+#define B2063_A_RX_SP5				B43_LP_RADIO(0x030) /* A RX SP 5 */
+#define B2063_A_RX_SP6				B43_LP_RADIO(0x031) /* A RX SP 6 */
+#define B2063_A_RX_SP7				B43_LP_RADIO(0x032) /* A RX SP 7 */
+#define B2063_RX_BB_SP1				B43_LP_RADIO(0x033) /* RX BB SP 1 */
+#define B2063_RX_BB_SP2				B43_LP_RADIO(0x034) /* RX BB SP 2 */
+#define B2063_RX_BB_SP3				B43_LP_RADIO(0x035) /* RX BB SP 3 */
+#define B2063_RX_BB_SP4				B43_LP_RADIO(0x036) /* RX BB SP 4 */
+#define B2063_RX_BB_SP5				B43_LP_RADIO(0x037) /* RX BB SP 5 */
+#define B2063_RX_BB_SP6				B43_LP_RADIO(0x038) /* RX BB SP 6 */
+#define B2063_RX_BB_SP7				B43_LP_RADIO(0x039) /* RX BB SP 7 */
+#define B2063_RX_BB_SP8				B43_LP_RADIO(0x03A) /* RX BB SP 8 */
+#define B2063_TX_RF_SP1				B43_LP_RADIO(0x03B) /* TX RF SP 1 */
+#define B2063_TX_RF_SP2				B43_LP_RADIO(0x03C) /* TX RF SP 2 */
+#define B2063_TX_RF_SP3				B43_LP_RADIO(0x03D) /* TX RF SP 3 */
+#define B2063_TX_RF_SP4				B43_LP_RADIO(0x03E) /* TX RF SP 4 */
+#define B2063_TX_RF_SP5				B43_LP_RADIO(0x03F) /* TX RF SP 5 */
+#define B2063_TX_RF_SP6				B43_LP_RADIO(0x040) /* TX RF SP 6 */
+#define B2063_TX_RF_SP7				B43_LP_RADIO(0x041) /* TX RF SP 7 */
+#define B2063_TX_RF_SP8				B43_LP_RADIO(0x042) /* TX RF SP 8 */
+#define B2063_TX_RF_SP9				B43_LP_RADIO(0x043) /* TX RF SP 9 */
+#define B2063_TX_RF_SP10			B43_LP_RADIO(0x044) /* TX RF SP 10 */
+#define B2063_TX_RF_SP11			B43_LP_RADIO(0x045) /* TX RF SP 11 */
+#define B2063_TX_RF_SP12			B43_LP_RADIO(0x046) /* TX RF SP 12 */
+#define B2063_TX_RF_SP13			B43_LP_RADIO(0x047) /* TX RF SP 13 */
+#define B2063_TX_RF_SP14			B43_LP_RADIO(0x048) /* TX RF SP 14 */
+#define B2063_TX_RF_SP15			B43_LP_RADIO(0x049) /* TX RF SP 15 */
+#define B2063_TX_RF_SP16			B43_LP_RADIO(0x04A) /* TX RF SP 16 */
+#define B2063_TX_RF_SP17			B43_LP_RADIO(0x04B) /* TX RF SP 17 */
+#define B2063_PA_SP1				B43_LP_RADIO(0x04C) /* PA SP 1 */
+#define B2063_PA_SP2				B43_LP_RADIO(0x04D) /* PA SP 2 */
+#define B2063_PA_SP3				B43_LP_RADIO(0x04E) /* PA SP 3 */
+#define B2063_PA_SP4				B43_LP_RADIO(0x04F) /* PA SP 4 */
+#define B2063_PA_SP5				B43_LP_RADIO(0x050) /* PA SP 5 */
+#define B2063_PA_SP6				B43_LP_RADIO(0x051) /* PA SP 6 */
+#define B2063_PA_SP7				B43_LP_RADIO(0x052) /* PA SP 7 */
+#define B2063_TX_BB_SP1				B43_LP_RADIO(0x053) /* TX BB SP 1 */
+#define B2063_TX_BB_SP2				B43_LP_RADIO(0x054) /* TX BB SP 2 */
+#define B2063_TX_BB_SP3				B43_LP_RADIO(0x055) /* TX BB SP 3 */
+#define B2063_REG_SP1				B43_LP_RADIO(0x056) /* REG SP 1 */
+#define B2063_BANDGAP_CTL1			B43_LP_RADIO(0x057) /* BANDGAP Control 1 */
+#define B2063_BANDGAP_CTL2			B43_LP_RADIO(0x058) /* BANDGAP Control 2 */
+#define B2063_LPO_CTL1				B43_LP_RADIO(0x059) /* LPO Control 1 */
+#define B2063_RC_CALIB_CTL1			B43_LP_RADIO(0x05A) /* RC Calibration Control 1 */
+#define B2063_RC_CALIB_CTL2			B43_LP_RADIO(0x05B) /* RC Calibration Control 2 */
+#define B2063_RC_CALIB_CTL3			B43_LP_RADIO(0x05C) /* RC Calibration Control 3 */
+#define B2063_RC_CALIB_CTL4			B43_LP_RADIO(0x05D) /* RC Calibration Control 4 */
+#define B2063_RC_CALIB_CTL5			B43_LP_RADIO(0x05E) /* RC Calibration Control 5 */
+#define B2063_RC_CALIB_CTL6			B43_LP_RADIO(0x05F) /* RC Calibration Control 6 */
+#define B2063_RC_CALIB_CTL7			B43_LP_RADIO(0x060) /* RC Calibration Control 7 */
+#define B2063_RC_CALIB_CTL8			B43_LP_RADIO(0x061) /* RC Calibration Control 8 */
+#define B2063_RC_CALIB_CTL9			B43_LP_RADIO(0x062) /* RC Calibration Control 9 */
+#define B2063_RC_CALIB_CTL10			B43_LP_RADIO(0x063) /* RC Calibration Control 10 */
+#define B2063_PLL_JTAG_CALNRST			B43_LP_RADIO(0x064) /* PLL JTAG CALNRST */
+#define B2063_PLL_JTAG_IN_PLL1			B43_LP_RADIO(0x065) /* PLL JTAG IN PLL 1 */
+#define B2063_PLL_JTAG_IN_PLL2			B43_LP_RADIO(0x066) /* PLL JTAG IN PLL 2 */
+#define B2063_PLL_JTAG_PLL_CP1			B43_LP_RADIO(0x067) /* PLL JTAG PLL CP 1 */
+#define B2063_PLL_JTAG_PLL_CP2			B43_LP_RADIO(0x068) /* PLL JTAG PLL CP 2 */
+#define B2063_PLL_JTAG_PLL_CP3			B43_LP_RADIO(0x069) /* PLL JTAG PLL CP 3 */
+#define B2063_PLL_JTAG_PLL_CP4			B43_LP_RADIO(0x06A) /* PLL JTAG PLL CP 4 */
+#define B2063_PLL_JTAG_PLL_CTL1			B43_LP_RADIO(0x06B) /* PLL JTAG PLL Control 1 */
+#define B2063_PLL_JTAG_PLL_LF1			B43_LP_RADIO(0x06C) /* PLL JTAG PLL LF 1 */
+#define B2063_PLL_JTAG_PLL_LF2			B43_LP_RADIO(0x06D) /* PLL JTAG PLL LF 2 */
+#define B2063_PLL_JTAG_PLL_LF3			B43_LP_RADIO(0x06E) /* PLL JTAG PLL LF 3 */
+#define B2063_PLL_JTAG_PLL_LF4			B43_LP_RADIO(0x06F) /* PLL JTAG PLL LF 4 */
+#define B2063_PLL_JTAG_PLL_SG1			B43_LP_RADIO(0x070) /* PLL JTAG PLL SG 1 */
+#define B2063_PLL_JTAG_PLL_SG2			B43_LP_RADIO(0x071) /* PLL JTAG PLL SG 2 */
+#define B2063_PLL_JTAG_PLL_SG3			B43_LP_RADIO(0x072) /* PLL JTAG PLL SG 3 */
+#define B2063_PLL_JTAG_PLL_SG4			B43_LP_RADIO(0x073) /* PLL JTAG PLL SG 4 */
+#define B2063_PLL_JTAG_PLL_SG5			B43_LP_RADIO(0x074) /* PLL JTAG PLL SG 5 */
+#define B2063_PLL_JTAG_PLL_VCO1			B43_LP_RADIO(0x075) /* PLL JTAG PLL VCO 1 */
+#define B2063_PLL_JTAG_PLL_VCO2			B43_LP_RADIO(0x076) /* PLL JTAG PLL VCO 2 */
+#define B2063_PLL_JTAG_PLL_VCO_CALIB1		B43_LP_RADIO(0x077) /* PLL JTAG PLL VCO Calibration 1 */
+#define B2063_PLL_JTAG_PLL_VCO_CALIB2		B43_LP_RADIO(0x078) /* PLL JTAG PLL VCO Calibration 2 */
+#define B2063_PLL_JTAG_PLL_VCO_CALIB3		B43_LP_RADIO(0x079) /* PLL JTAG PLL VCO Calibration 3 */
+#define B2063_PLL_JTAG_PLL_VCO_CALIB4		B43_LP_RADIO(0x07A) /* PLL JTAG PLL VCO Calibration 4 */
+#define B2063_PLL_JTAG_PLL_VCO_CALIB5		B43_LP_RADIO(0x07B) /* PLL JTAG PLL VCO Calibration 5 */
+#define B2063_PLL_JTAG_PLL_VCO_CALIB6		B43_LP_RADIO(0x07C) /* PLL JTAG PLL VCO Calibration 6 */
+#define B2063_PLL_JTAG_PLL_VCO_CALIB7		B43_LP_RADIO(0x07D) /* PLL JTAG PLL VCO Calibration 7 */
+#define B2063_PLL_JTAG_PLL_VCO_CALIB8		B43_LP_RADIO(0x07E) /* PLL JTAG PLL VCO Calibration 8 */
+#define B2063_PLL_JTAG_PLL_VCO_CALIB9		B43_LP_RADIO(0x07F) /* PLL JTAG PLL VCO Calibration 9 */
+#define B2063_PLL_JTAG_PLL_VCO_CALIB10		B43_LP_RADIO(0x080) /* PLL JTAG PLL VCO Calibration 10 */
+#define B2063_PLL_JTAG_PLL_XTAL_12		B43_LP_RADIO(0x081) /* PLL JTAG PLL XTAL 1 2 */
+#define B2063_PLL_JTAG_PLL_XTAL3		B43_LP_RADIO(0x082) /* PLL JTAG PLL XTAL 3 */
+#define B2063_LOGEN_ACL1			B43_LP_RADIO(0x083) /* LOGEN ACL 1 */
+#define B2063_LOGEN_ACL2			B43_LP_RADIO(0x084) /* LOGEN ACL 2 */
+#define B2063_LOGEN_ACL3			B43_LP_RADIO(0x085) /* LOGEN ACL 3 */
+#define B2063_LOGEN_ACL4			B43_LP_RADIO(0x086) /* LOGEN ACL 4 */
+#define B2063_LOGEN_ACL5			B43_LP_RADIO(0x087) /* LOGEN ACL 5 */
+#define B2063_LO_CALIB_INPUTS			B43_LP_RADIO(0x088) /* LO Calibration INPUTS */
+#define B2063_LO_CALIB_CTL1			B43_LP_RADIO(0x089) /* LO Calibration Control 1 */
+#define B2063_LO_CALIB_CTL2			B43_LP_RADIO(0x08A) /* LO Calibration Control 2 */
+#define B2063_LO_CALIB_CTL3			B43_LP_RADIO(0x08B) /* LO Calibration Control 3 */
+#define B2063_LO_CALIB_WAITCNT			B43_LP_RADIO(0x08C) /* LO Calibration WAITCNT */
+#define B2063_LO_CALIB_OVR1			B43_LP_RADIO(0x08D) /* LO Calibration OVR 1 */
+#define B2063_LO_CALIB_OVR2			B43_LP_RADIO(0x08E) /* LO Calibration OVR 2 */
+#define B2063_LO_CALIB_OVAL1			B43_LP_RADIO(0x08F) /* LO Calibration OVAL 1 */
+#define B2063_LO_CALIB_OVAL2			B43_LP_RADIO(0x090) /* LO Calibration OVAL 2 */
+#define B2063_LO_CALIB_OVAL3			B43_LP_RADIO(0x091) /* LO Calibration OVAL 3 */
+#define B2063_LO_CALIB_OVAL4			B43_LP_RADIO(0x092) /* LO Calibration OVAL 4 */
+#define B2063_LO_CALIB_OVAL5			B43_LP_RADIO(0x093) /* LO Calibration OVAL 5 */
+#define B2063_LO_CALIB_OVAL6			B43_LP_RADIO(0x094) /* LO Calibration OVAL 6 */
+#define B2063_LO_CALIB_OVAL7			B43_LP_RADIO(0x095) /* LO Calibration OVAL 7 */
+#define B2063_LO_CALIB_CALVLD1			B43_LP_RADIO(0x096) /* LO Calibration CALVLD 1 */
+#define B2063_LO_CALIB_CALVLD2			B43_LP_RADIO(0x097) /* LO Calibration CALVLD 2 */
+#define B2063_LO_CALIB_CVAL1			B43_LP_RADIO(0x098) /* LO Calibration CVAL 1 */
+#define B2063_LO_CALIB_CVAL2			B43_LP_RADIO(0x099) /* LO Calibration CVAL 2 */
+#define B2063_LO_CALIB_CVAL3			B43_LP_RADIO(0x09A) /* LO Calibration CVAL 3 */
+#define B2063_LO_CALIB_CVAL4			B43_LP_RADIO(0x09B) /* LO Calibration CVAL 4 */
+#define B2063_LO_CALIB_CVAL5			B43_LP_RADIO(0x09C) /* LO Calibration CVAL 5 */
+#define B2063_LO_CALIB_CVAL6			B43_LP_RADIO(0x09D) /* LO Calibration CVAL 6 */
+#define B2063_LO_CALIB_CVAL7			B43_LP_RADIO(0x09E) /* LO Calibration CVAL 7 */
+#define B2063_LOGEN_CALIB_EN			B43_LP_RADIO(0x09F) /* LOGEN Calibration EN */
+#define B2063_LOGEN_PEAKDET1			B43_LP_RADIO(0x0A0) /* LOGEN PEAKDET 1 */
+#define B2063_LOGEN_RCCR1			B43_LP_RADIO(0x0A1) /* LOGEN RCCR 1 */
+#define B2063_LOGEN_VCOBUF1			B43_LP_RADIO(0x0A2) /* LOGEN VCOBUF 1 */
+#define B2063_LOGEN_MIXER1			B43_LP_RADIO(0x0A3) /* LOGEN MIXER 1 */
+#define B2063_LOGEN_MIXER2			B43_LP_RADIO(0x0A4) /* LOGEN MIXER 2 */
+#define B2063_LOGEN_BUF1			B43_LP_RADIO(0x0A5) /* LOGEN BUF 1 */
+#define B2063_LOGEN_BUF2			B43_LP_RADIO(0x0A6) /* LOGEN BUF 2 */
+#define B2063_LOGEN_DIV1			B43_LP_RADIO(0x0A7) /* LOGEN DIV 1 */
+#define B2063_LOGEN_DIV2			B43_LP_RADIO(0x0A8) /* LOGEN DIV 2 */
+#define B2063_LOGEN_DIV3			B43_LP_RADIO(0x0A9) /* LOGEN DIV 3 */
+#define B2063_LOGEN_CBUFRX1			B43_LP_RADIO(0x0AA) /* LOGEN CBUFRX 1 */
+#define B2063_LOGEN_CBUFRX2			B43_LP_RADIO(0x0AB) /* LOGEN CBUFRX 2 */
+#define B2063_LOGEN_CBUFTX1			B43_LP_RADIO(0x0AC) /* LOGEN CBUFTX 1 */
+#define B2063_LOGEN_CBUFTX2			B43_LP_RADIO(0x0AD) /* LOGEN CBUFTX 2 */
+#define B2063_LOGEN_IDAC1			B43_LP_RADIO(0x0AE) /* LOGEN IDAC 1 */
+#define B2063_LOGEN_SPARE1			B43_LP_RADIO(0x0AF) /* LOGEN SPARE 1 */
+#define B2063_LOGEN_SPARE2			B43_LP_RADIO(0x0B0) /* LOGEN SPARE 2 */
+#define B2063_LOGEN_SPARE3			B43_LP_RADIO(0x0B1) /* LOGEN SPARE 3 */
+#define B2063_G_RX_1ST1				B43_LP_RADIO(0x0B2) /* G RX 1ST 1 */
+#define B2063_G_RX_1ST2				B43_LP_RADIO(0x0B3) /* G RX 1ST 2 */
+#define B2063_G_RX_1ST3				B43_LP_RADIO(0x0B4) /* G RX 1ST 3 */
+#define B2063_G_RX_2ND1				B43_LP_RADIO(0x0B5) /* G RX 2ND 1 */
+#define B2063_G_RX_2ND2				B43_LP_RADIO(0x0B6) /* G RX 2ND 2 */
+#define B2063_G_RX_2ND3				B43_LP_RADIO(0x0B7) /* G RX 2ND 3 */
+#define B2063_G_RX_2ND4				B43_LP_RADIO(0x0B8) /* G RX 2ND 4 */
+#define B2063_G_RX_2ND5				B43_LP_RADIO(0x0B9) /* G RX 2ND 5 */
+#define B2063_G_RX_2ND6				B43_LP_RADIO(0x0BA) /* G RX 2ND 6 */
+#define B2063_G_RX_2ND7				B43_LP_RADIO(0x0BB) /* G RX 2ND 7 */
+#define B2063_G_RX_2ND8				B43_LP_RADIO(0x0BC) /* G RX 2ND 8 */
+#define B2063_G_RX_PS1				B43_LP_RADIO(0x0BD) /* G RX PS 1 */
+#define B2063_G_RX_PS2				B43_LP_RADIO(0x0BE) /* G RX PS 2 */
+#define B2063_G_RX_PS3				B43_LP_RADIO(0x0BF) /* G RX PS 3 */
+#define B2063_G_RX_PS4				B43_LP_RADIO(0x0C0) /* G RX PS 4 */
+#define B2063_G_RX_PS5				B43_LP_RADIO(0x0C1) /* G RX PS 5 */
+#define B2063_G_RX_MIX1				B43_LP_RADIO(0x0C2) /* G RX MIX 1 */
+#define B2063_G_RX_MIX2				B43_LP_RADIO(0x0C3) /* G RX MIX 2 */
+#define B2063_G_RX_MIX3				B43_LP_RADIO(0x0C4) /* G RX MIX 3 */
+#define B2063_G_RX_MIX4				B43_LP_RADIO(0x0C5) /* G RX MIX 4 */
+#define B2063_G_RX_MIX5				B43_LP_RADIO(0x0C6) /* G RX MIX 5 */
+#define B2063_G_RX_MIX6				B43_LP_RADIO(0x0C7) /* G RX MIX 6 */
+#define B2063_G_RX_MIX7				B43_LP_RADIO(0x0C8) /* G RX MIX 7 */
+#define B2063_G_RX_MIX8				B43_LP_RADIO(0x0C9) /* G RX MIX 8 */
+#define B2063_G_RX_PDET1			B43_LP_RADIO(0x0CA) /* G RX PDET 1 */
+#define B2063_G_RX_SPARES1			B43_LP_RADIO(0x0CB) /* G RX SPARES 1 */
+#define B2063_G_RX_SPARES2			B43_LP_RADIO(0x0CC) /* G RX SPARES 2 */
+#define B2063_G_RX_SPARES3			B43_LP_RADIO(0x0CD) /* G RX SPARES 3 */
+#define B2063_A_RX_1ST1				B43_LP_RADIO(0x0CE) /* A RX 1ST 1 */
+#define B2063_A_RX_1ST2				B43_LP_RADIO(0x0CF) /* A RX 1ST 2 */
+#define B2063_A_RX_1ST3				B43_LP_RADIO(0x0D0) /* A RX 1ST 3 */
+#define B2063_A_RX_1ST4				B43_LP_RADIO(0x0D1) /* A RX 1ST 4 */
+#define B2063_A_RX_1ST5				B43_LP_RADIO(0x0D2) /* A RX 1ST 5 */
+#define B2063_A_RX_2ND1				B43_LP_RADIO(0x0D3) /* A RX 2ND 1 */
+#define B2063_A_RX_2ND2				B43_LP_RADIO(0x0D4) /* A RX 2ND 2 */
+#define B2063_A_RX_2ND3				B43_LP_RADIO(0x0D5) /* A RX 2ND 3 */
+#define B2063_A_RX_2ND4				B43_LP_RADIO(0x0D6) /* A RX 2ND 4 */
+#define B2063_A_RX_2ND5				B43_LP_RADIO(0x0D7) /* A RX 2ND 5 */
+#define B2063_A_RX_2ND6				B43_LP_RADIO(0x0D8) /* A RX 2ND 6 */
+#define B2063_A_RX_2ND7				B43_LP_RADIO(0x0D9) /* A RX 2ND 7 */
+#define B2063_A_RX_PS1				B43_LP_RADIO(0x0DA) /* A RX PS 1 */
+#define B2063_A_RX_PS2				B43_LP_RADIO(0x0DB) /* A RX PS 2 */
+#define B2063_A_RX_PS3				B43_LP_RADIO(0x0DC) /* A RX PS 3 */
+#define B2063_A_RX_PS4				B43_LP_RADIO(0x0DD) /* A RX PS 4 */
+#define B2063_A_RX_PS5				B43_LP_RADIO(0x0DE) /* A RX PS 5 */
+#define B2063_A_RX_PS6				B43_LP_RADIO(0x0DF) /* A RX PS 6 */
+#define B2063_A_RX_MIX1				B43_LP_RADIO(0x0E0) /* A RX MIX 1 */
+#define B2063_A_RX_MIX2				B43_LP_RADIO(0x0E1) /* A RX MIX 2 */
+#define B2063_A_RX_MIX3				B43_LP_RADIO(0x0E2) /* A RX MIX 3 */
+#define B2063_A_RX_MIX4				B43_LP_RADIO(0x0E3) /* A RX MIX 4 */
+#define B2063_A_RX_MIX5				B43_LP_RADIO(0x0E4) /* A RX MIX 5 */
+#define B2063_A_RX_MIX6				B43_LP_RADIO(0x0E5) /* A RX MIX 6 */
+#define B2063_A_RX_MIX7				B43_LP_RADIO(0x0E6) /* A RX MIX 7 */
+#define B2063_A_RX_MIX8				B43_LP_RADIO(0x0E7) /* A RX MIX 8 */
+#define B2063_A_RX_PWRDET1			B43_LP_RADIO(0x0E8) /* A RX PWRDET 1 */
+#define B2063_A_RX_SPARE1			B43_LP_RADIO(0x0E9) /* A RX SPARE 1 */
+#define B2063_A_RX_SPARE2			B43_LP_RADIO(0x0EA) /* A RX SPARE 2 */
+#define B2063_A_RX_SPARE3			B43_LP_RADIO(0x0EB) /* A RX SPARE 3 */
+#define B2063_RX_TIA_CTL1			B43_LP_RADIO(0x0EC) /* RX TIA Control 1 */
+#define B2063_RX_TIA_CTL2			B43_LP_RADIO(0x0ED) /* RX TIA Control 2 */
+#define B2063_RX_TIA_CTL3			B43_LP_RADIO(0x0EE) /* RX TIA Control 3 */
+#define B2063_RX_TIA_CTL4			B43_LP_RADIO(0x0EF) /* RX TIA Control 4 */
+#define B2063_RX_TIA_CTL5			B43_LP_RADIO(0x0F0) /* RX TIA Control 5 */
+#define B2063_RX_TIA_CTL6			B43_LP_RADIO(0x0F1) /* RX TIA Control 6 */
+#define B2063_RX_BB_CTL1			B43_LP_RADIO(0x0F2) /* RX BB Control 1 */
+#define B2063_RX_BB_CTL2			B43_LP_RADIO(0x0F3) /* RX BB Control 2 */
+#define B2063_RX_BB_CTL3			B43_LP_RADIO(0x0F4) /* RX BB Control 3 */
+#define B2063_RX_BB_CTL4			B43_LP_RADIO(0x0F5) /* RX BB Control 4 */
+#define B2063_RX_BB_CTL5			B43_LP_RADIO(0x0F6) /* RX BB Control 5 */
+#define B2063_RX_BB_CTL6			B43_LP_RADIO(0x0F7) /* RX BB Control 6 */
+#define B2063_RX_BB_CTL7			B43_LP_RADIO(0x0F8) /* RX BB Control 7 */
+#define B2063_RX_BB_CTL8			B43_LP_RADIO(0x0F9) /* RX BB Control 8 */
+#define B2063_RX_BB_CTL9			B43_LP_RADIO(0x0FA) /* RX BB Control 9 */
+#define B2063_TX_RF_CTL1			B43_LP_RADIO(0x0FB) /* TX RF Control 1 */
+#define B2063_TX_RF_IDAC_LO_RF_I		B43_LP_RADIO(0x0FC) /* TX RF IDAC LO RF I */
+#define B2063_TX_RF_IDAC_LO_RF_Q		B43_LP_RADIO(0x0FD) /* TX RF IDAC LO RF Q */
+#define B2063_TX_RF_IDAC_LO_BB_I		B43_LP_RADIO(0x0FE) /* TX RF IDAC LO BB I */
+#define B2063_TX_RF_IDAC_LO_BB_Q		B43_LP_RADIO(0x0FF) /* TX RF IDAC LO BB Q */
+#define B2063_TX_RF_CTL2			B43_LP_RADIO(0x100) /* TX RF Control 2 */
+#define B2063_TX_RF_CTL3			B43_LP_RADIO(0x101) /* TX RF Control 3 */
+#define B2063_TX_RF_CTL4			B43_LP_RADIO(0x102) /* TX RF Control 4 */
+#define B2063_TX_RF_CTL5			B43_LP_RADIO(0x103) /* TX RF Control 5 */
+#define B2063_TX_RF_CTL6			B43_LP_RADIO(0x104) /* TX RF Control 6 */
+#define B2063_TX_RF_CTL7			B43_LP_RADIO(0x105) /* TX RF Control 7 */
+#define B2063_TX_RF_CTL8			B43_LP_RADIO(0x106) /* TX RF Control 8 */
+#define B2063_TX_RF_CTL9			B43_LP_RADIO(0x107) /* TX RF Control 9 */
+#define B2063_TX_RF_CTL10			B43_LP_RADIO(0x108) /* TX RF Control 10 */
+#define B2063_TX_RF_CTL14			B43_LP_RADIO(0x109) /* TX RF Control 14 */
+#define B2063_TX_RF_CTL15			B43_LP_RADIO(0x10A) /* TX RF Control 15 */
+#define B2063_PA_CTL1				B43_LP_RADIO(0x10B) /* PA Control 1 */
+#define B2063_PA_CTL2				B43_LP_RADIO(0x10C) /* PA Control 2 */
+#define B2063_PA_CTL3				B43_LP_RADIO(0x10D) /* PA Control 3 */
+#define B2063_PA_CTL4				B43_LP_RADIO(0x10E) /* PA Control 4 */
+#define B2063_PA_CTL5				B43_LP_RADIO(0x10F) /* PA Control 5 */
+#define B2063_PA_CTL6				B43_LP_RADIO(0x110) /* PA Control 6 */
+#define B2063_PA_CTL7				B43_LP_RADIO(0x111) /* PA Control 7 */
+#define B2063_PA_CTL8				B43_LP_RADIO(0x112) /* PA Control 8 */
+#define B2063_PA_CTL9				B43_LP_RADIO(0x113) /* PA Control 9 */
+#define B2063_PA_CTL10				B43_LP_RADIO(0x114) /* PA Control 10 */
+#define B2063_PA_CTL11				B43_LP_RADIO(0x115) /* PA Control 11 */
+#define B2063_PA_CTL12				B43_LP_RADIO(0x116) /* PA Control 12 */
+#define B2063_PA_CTL13				B43_LP_RADIO(0x117) /* PA Control 13 */
+#define B2063_TX_BB_CTL1			B43_LP_RADIO(0x118) /* TX BB Control 1 */
+#define B2063_TX_BB_CTL2			B43_LP_RADIO(0x119) /* TX BB Control 2 */
+#define B2063_TX_BB_CTL3			B43_LP_RADIO(0x11A) /* TX BB Control 3 */
+#define B2063_TX_BB_CTL4			B43_LP_RADIO(0x11B) /* TX BB Control 4 */
+#define B2063_GPIO_CTL1				B43_LP_RADIO(0x11C) /* GPIO Control 1 */
+#define B2063_VREG_CTL1				B43_LP_RADIO(0x11D) /* VREG Control 1 */
+#define B2063_AMUX_CTL1				B43_LP_RADIO(0x11E) /* AMUX Control 1 */
+#define B2063_IQ_CALIB_GVAR			B43_LP_RADIO(0x11F) /* IQ Calibration GVAR */
+#define B2063_IQ_CALIB_CTL1			B43_LP_RADIO(0x120) /* IQ Calibration Control 1 */
+#define B2063_IQ_CALIB_CTL2			B43_LP_RADIO(0x121) /* IQ Calibration Control 2 */
+#define B2063_TEMPSENSE_CTL1			B43_LP_RADIO(0x122) /* TEMPSENSE Control 1 */
+#define B2063_TEMPSENSE_CTL2			B43_LP_RADIO(0x123) /* TEMPSENSE Control 2 */
+#define B2063_TX_RX_LOOPBACK1			B43_LP_RADIO(0x124) /* TX/RX LOOPBACK 1 */
+#define B2063_TX_RX_LOOPBACK2			B43_LP_RADIO(0x125) /* TX/RX LOOPBACK 2 */
+#define B2063_EXT_TSSI_CTL1			B43_LP_RADIO(0x126) /* EXT TSSI Control 1 */
+#define B2063_EXT_TSSI_CTL2			B43_LP_RADIO(0x127) /* EXT TSSI Control 2 */
+#define B2063_AFE_CTL				B43_LP_RADIO(0x128) /* AFE Control */
+
+
+
+enum b43_lpphy_txpctl_mode {
+	B43_LPPHY_TXPCTL_UNKNOWN = 0,
+	B43_LPPHY_TXPCTL_OFF,	/* TX power control is OFF */
+	B43_LPPHY_TXPCTL_SW,	/* TX power control is set to Software */
+	B43_LPPHY_TXPCTL_HW,	/* TX power control is set to Hardware */
+};
+
+struct b43_phy_lp {
+	/* Current TX power control mode. */
+	enum b43_lpphy_txpctl_mode txpctl_mode;
+
+	/* Transmit isolation medium band */
+	u8 tx_isolation_med_band;
+	/* Transmit isolation low band */
+	u8 tx_isolation_low_band;
+	/* Transmit isolation high band */
+	u8 tx_isolation_hi_band;
+
+	/* Max transmit power medium band */
+	u16 max_tx_pwr_med_band;
+	/* Max transmit power low band */
+	u16 max_tx_pwr_low_band;
+	/* Max transmit power high band */
+	u16 max_tx_pwr_hi_band;
+
+	/* FIXME What are these used for? */
+	/* FIXME Is 15 the correct array size? */
+	u16 tx_max_rate[15];
+	u16 tx_max_ratel[15];
+	u16 tx_max_rateh[15];
+
+	/* Transmit power arrays */
+	s16 txpa[3], txpal[3], txpah[3];
+
+	/* Receive power offset */
+	u8 rx_pwr_offset;
+
+	/* TSSI transmit count */
+	u16 tssi_tx_count;
+	/* TSSI index */
+	u16 tssi_idx; /* FIXME initial value? */
+	/* TSSI npt */
+	u16 tssi_npt; /* FIXME initial value? */
+
+	/* Target TX frequency */
+	u16 tgt_tx_freq; /* FIXME initial value? */
+
+	/* Transmit power index override */
+	s8 tx_pwr_idx_over; /* FIXME initial value? */
+
+	/* RSSI vf */
+	u8 rssi_vf;
+	/* RSSI vc */
+	u8 rssi_vc;
+	/* RSSI gs */
+	u8 rssi_gs;
+
+	/* RC cap */
+	u8 rc_cap;
+	/* BX arch */
+	u8 bx_arch;
+
+	/* Full calibration channel */
+	u8 full_calib_chan;
+
+	/* Transmit iqlocal best coeffs */
+	bool tx_iqloc_best_coeffs_valid;
+	u8 tx_iqloc_best_coeffs[11];
+
+	/* Used for "Save/Restore Dig Filt State" */
+	u16 dig_flt_state[9];
+
+	bool crs_usr_disable, crs_sys_disable;
+
+	unsigned int pdiv;
+
+	/* The channel we are tuned to */
+	u8 channel;
+
+	/* The active antenna diversity mode */
+	int antenna;
+
+	/* Frequency of the active TX tone */
+	int tx_tone_freq;
+};
+
+enum tssi_mux_mode {
+	TSSI_MUX_PREPA,
+	TSSI_MUX_POSTPA,
+	TSSI_MUX_EXT,
+};
+
+struct b43_phy_operations;
+extern const struct b43_phy_operations b43_phyops_lp;
+
+#endif /* LINUX_B43_PHY_LP_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/phy_n.c b/drivers/net/wireless/broadcom/b43/phy_n.c
new file mode 100644
index 0000000..44ab080
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/phy_n.c
@@ -0,0 +1,6726 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11n PHY support
+
+  Copyright (c) 2008 Michael Buesch <m@bues.ch>
+  Copyright (c) 2010-2011 Rafał Miłecki <zajec5@gmail.com>
+
+  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/delay.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "b43.h"
+#include "phy_n.h"
+#include "tables_nphy.h"
+#include "radio_2055.h"
+#include "radio_2056.h"
+#include "radio_2057.h"
+#include "main.h"
+#include "ppr.h"
+
+struct nphy_txgains {
+	u16 tx_lpf[2];
+	u16 txgm[2];
+	u16 pga[2];
+	u16 pad[2];
+	u16 ipa[2];
+};
+
+struct nphy_iqcal_params {
+	u16 tx_lpf;
+	u16 txgm;
+	u16 pga;
+	u16 pad;
+	u16 ipa;
+	u16 cal_gain;
+	u16 ncorr[5];
+};
+
+struct nphy_iq_est {
+	s32 iq0_prod;
+	u32 i0_pwr;
+	u32 q0_pwr;
+	s32 iq1_prod;
+	u32 i1_pwr;
+	u32 q1_pwr;
+};
+
+enum b43_nphy_rf_sequence {
+	B43_RFSEQ_RX2TX,
+	B43_RFSEQ_TX2RX,
+	B43_RFSEQ_RESET2RX,
+	B43_RFSEQ_UPDATE_GAINH,
+	B43_RFSEQ_UPDATE_GAINL,
+	B43_RFSEQ_UPDATE_GAINU,
+};
+
+enum n_rf_ctl_over_cmd {
+	N_RF_CTL_OVER_CMD_RXRF_PU = 0,
+	N_RF_CTL_OVER_CMD_RX_PU = 1,
+	N_RF_CTL_OVER_CMD_TX_PU = 2,
+	N_RF_CTL_OVER_CMD_RX_GAIN = 3,
+	N_RF_CTL_OVER_CMD_TX_GAIN = 4,
+};
+
+enum n_intc_override {
+	N_INTC_OVERRIDE_OFF = 0,
+	N_INTC_OVERRIDE_TRSW = 1,
+	N_INTC_OVERRIDE_PA = 2,
+	N_INTC_OVERRIDE_EXT_LNA_PU = 3,
+	N_INTC_OVERRIDE_EXT_LNA_GAIN = 4,
+};
+
+enum n_rssi_type {
+	N_RSSI_W1 = 0,
+	N_RSSI_W2,
+	N_RSSI_NB,
+	N_RSSI_IQ,
+	N_RSSI_TSSI_2G,
+	N_RSSI_TSSI_5G,
+	N_RSSI_TBD,
+};
+
+enum n_rail_type {
+	N_RAIL_I = 0,
+	N_RAIL_Q = 1,
+};
+
+static inline bool b43_nphy_ipa(struct b43_wldev *dev)
+{
+	enum nl80211_band band = b43_current_band(dev->wl);
+	return ((dev->phy.n->ipa2g_on && band == NL80211_BAND_2GHZ) ||
+		(dev->phy.n->ipa5g_on && band == NL80211_BAND_5GHZ));
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreGetState */
+static u8 b43_nphy_get_rx_core_state(struct b43_wldev *dev)
+{
+	return (b43_phy_read(dev, B43_NPHY_RFSEQCA) & B43_NPHY_RFSEQCA_RXEN) >>
+		B43_NPHY_RFSEQCA_RXEN_SHIFT;
+}
+
+/**************************************************
+ * RF (just without b43_nphy_rf_ctl_intc_override)
+ **************************************************/
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */
+static void b43_nphy_force_rf_sequence(struct b43_wldev *dev,
+				       enum b43_nphy_rf_sequence seq)
+{
+	static const u16 trigger[] = {
+		[B43_RFSEQ_RX2TX]		= B43_NPHY_RFSEQTR_RX2TX,
+		[B43_RFSEQ_TX2RX]		= B43_NPHY_RFSEQTR_TX2RX,
+		[B43_RFSEQ_RESET2RX]		= B43_NPHY_RFSEQTR_RST2RX,
+		[B43_RFSEQ_UPDATE_GAINH]	= B43_NPHY_RFSEQTR_UPGH,
+		[B43_RFSEQ_UPDATE_GAINL]	= B43_NPHY_RFSEQTR_UPGL,
+		[B43_RFSEQ_UPDATE_GAINU]	= B43_NPHY_RFSEQTR_UPGU,
+	};
+	int i;
+	u16 seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);
+
+	B43_WARN_ON(seq >= ARRAY_SIZE(trigger));
+
+	b43_phy_set(dev, B43_NPHY_RFSEQMODE,
+		    B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER);
+	b43_phy_set(dev, B43_NPHY_RFSEQTR, trigger[seq]);
+	for (i = 0; i < 200; i++) {
+		if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & trigger[seq]))
+			goto ok;
+		msleep(1);
+	}
+	b43err(dev->wl, "RF sequence status timeout\n");
+ok:
+	b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
+}
+
+static void b43_nphy_rf_ctl_override_rev19(struct b43_wldev *dev, u16 field,
+					   u16 value, u8 core, bool off,
+					   u8 override_id)
+{
+	/* TODO */
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverrideRev7 */
+static void b43_nphy_rf_ctl_override_rev7(struct b43_wldev *dev, u16 field,
+					  u16 value, u8 core, bool off,
+					  u8 override)
+{
+	struct b43_phy *phy = &dev->phy;
+	const struct nphy_rf_control_override_rev7 *e;
+	u16 en_addrs[3][2] = {
+		{ 0x0E7, 0x0EC }, { 0x342, 0x343 }, { 0x346, 0x347 }
+	};
+	u16 en_addr;
+	u16 en_mask = field;
+	u16 val_addr;
+	u8 i;
+
+	if (phy->rev >= 19 || phy->rev < 3) {
+		B43_WARN_ON(1);
+		return;
+	}
+
+	/* Remember: we can get NULL! */
+	e = b43_nphy_get_rf_ctl_over_rev7(dev, field, override);
+
+	for (i = 0; i < 2; i++) {
+		if (override >= ARRAY_SIZE(en_addrs)) {
+			b43err(dev->wl, "Invalid override value %d\n", override);
+			return;
+		}
+		en_addr = en_addrs[override][i];
+
+		if (e)
+			val_addr = (i == 0) ? e->val_addr_core0 : e->val_addr_core1;
+
+		if (off) {
+			b43_phy_mask(dev, en_addr, ~en_mask);
+			if (e) /* Do it safer, better than wl */
+				b43_phy_mask(dev, val_addr, ~e->val_mask);
+		} else {
+			if (!core || (core & (1 << i))) {
+				b43_phy_set(dev, en_addr, en_mask);
+				if (e)
+					b43_phy_maskset(dev, val_addr, ~e->val_mask, (value << e->val_shift));
+			}
+		}
+	}
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverideOneToMany */
+static void b43_nphy_rf_ctl_override_one_to_many(struct b43_wldev *dev,
+						 enum n_rf_ctl_over_cmd cmd,
+						 u16 value, u8 core, bool off)
+{
+	struct b43_phy *phy = &dev->phy;
+	u16 tmp;
+
+	B43_WARN_ON(phy->rev < 7);
+
+	switch (cmd) {
+	case N_RF_CTL_OVER_CMD_RXRF_PU:
+		b43_nphy_rf_ctl_override_rev7(dev, 0x20, value, core, off, 1);
+		b43_nphy_rf_ctl_override_rev7(dev, 0x10, value, core, off, 1);
+		b43_nphy_rf_ctl_override_rev7(dev, 0x08, value, core, off, 1);
+		break;
+	case N_RF_CTL_OVER_CMD_RX_PU:
+		b43_nphy_rf_ctl_override_rev7(dev, 0x4, value, core, off, 1);
+		b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 1);
+		b43_nphy_rf_ctl_override_rev7(dev, 0x1, value, core, off, 1);
+		b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 2);
+		b43_nphy_rf_ctl_override_rev7(dev, 0x0800, 0, core, off, 1);
+		break;
+	case N_RF_CTL_OVER_CMD_TX_PU:
+		b43_nphy_rf_ctl_override_rev7(dev, 0x4, value, core, off, 0);
+		b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 1);
+		b43_nphy_rf_ctl_override_rev7(dev, 0x1, value, core, off, 2);
+		b43_nphy_rf_ctl_override_rev7(dev, 0x0800, 1, core, off, 1);
+		break;
+	case N_RF_CTL_OVER_CMD_RX_GAIN:
+		tmp = value & 0xFF;
+		b43_nphy_rf_ctl_override_rev7(dev, 0x0800, tmp, core, off, 0);
+		tmp = value >> 8;
+		b43_nphy_rf_ctl_override_rev7(dev, 0x6000, tmp, core, off, 0);
+		break;
+	case N_RF_CTL_OVER_CMD_TX_GAIN:
+		tmp = value & 0x7FFF;
+		b43_nphy_rf_ctl_override_rev7(dev, 0x1000, tmp, core, off, 0);
+		tmp = value >> 14;
+		b43_nphy_rf_ctl_override_rev7(dev, 0x4000, tmp, core, off, 0);
+		break;
+	}
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */
+static void b43_nphy_rf_ctl_override(struct b43_wldev *dev, u16 field,
+				     u16 value, u8 core, bool off)
+{
+	int i;
+	u8 index = fls(field);
+	u8 addr, en_addr, val_addr;
+	/* we expect only one bit set */
+	B43_WARN_ON(field & (~(1 << (index - 1))));
+
+	if (dev->phy.rev >= 3) {
+		const struct nphy_rf_control_override_rev3 *rf_ctrl;
+		for (i = 0; i < 2; i++) {
+			if (index == 0 || index == 16) {
+				b43err(dev->wl,
+					"Unsupported RF Ctrl Override call\n");
+				return;
+			}
+
+			rf_ctrl = &tbl_rf_control_override_rev3[index - 1];
+			en_addr = B43_PHY_N((i == 0) ?
+				rf_ctrl->en_addr0 : rf_ctrl->en_addr1);
+			val_addr = B43_PHY_N((i == 0) ?
+				rf_ctrl->val_addr0 : rf_ctrl->val_addr1);
+
+			if (off) {
+				b43_phy_mask(dev, en_addr, ~(field));
+				b43_phy_mask(dev, val_addr,
+						~(rf_ctrl->val_mask));
+			} else {
+				if (core == 0 || ((1 << i) & core)) {
+					b43_phy_set(dev, en_addr, field);
+					b43_phy_maskset(dev, val_addr,
+						~(rf_ctrl->val_mask),
+						(value << rf_ctrl->val_shift));
+				}
+			}
+		}
+	} else {
+		const struct nphy_rf_control_override_rev2 *rf_ctrl;
+		if (off) {
+			b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~(field));
+			value = 0;
+		} else {
+			b43_phy_set(dev, B43_NPHY_RFCTL_OVER, field);
+		}
+
+		for (i = 0; i < 2; i++) {
+			if (index <= 1 || index == 16) {
+				b43err(dev->wl,
+					"Unsupported RF Ctrl Override call\n");
+				return;
+			}
+
+			if (index == 2 || index == 10 ||
+			    (index >= 13 && index <= 15)) {
+				core = 1;
+			}
+
+			rf_ctrl = &tbl_rf_control_override_rev2[index - 2];
+			addr = B43_PHY_N((i == 0) ?
+				rf_ctrl->addr0 : rf_ctrl->addr1);
+
+			if ((1 << i) & core)
+				b43_phy_maskset(dev, addr, ~(rf_ctrl->bmask),
+						(value << rf_ctrl->shift));
+
+			b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x1);
+			b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
+					B43_NPHY_RFCTL_CMD_START);
+			udelay(1);
+			b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, 0xFFFE);
+		}
+	}
+}
+
+static void b43_nphy_rf_ctl_intc_override_rev7(struct b43_wldev *dev,
+					       enum n_intc_override intc_override,
+					       u16 value, u8 core_sel)
+{
+	u16 reg, tmp, tmp2, val;
+	int core;
+
+	/* TODO: What about rev19+? Revs 3+ and 7+ are a bit similar */
+
+	for (core = 0; core < 2; core++) {
+		if ((core_sel == 1 && core != 0) ||
+		    (core_sel == 2 && core != 1))
+			continue;
+
+		reg = (core == 0) ? B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2;
+
+		switch (intc_override) {
+		case N_INTC_OVERRIDE_OFF:
+			b43_phy_write(dev, reg, 0);
+			b43_phy_mask(dev, 0x2ff, ~0x2000);
+			b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
+			break;
+		case N_INTC_OVERRIDE_TRSW:
+			b43_phy_maskset(dev, reg, ~0xC0, value << 6);
+			b43_phy_set(dev, reg, 0x400);
+
+			b43_phy_mask(dev, 0x2ff, ~0xC000 & 0xFFFF);
+			b43_phy_set(dev, 0x2ff, 0x2000);
+			b43_phy_set(dev, 0x2ff, 0x0001);
+			break;
+		case N_INTC_OVERRIDE_PA:
+			tmp = 0x0030;
+			if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
+				val = value << 5;
+			else
+				val = value << 4;
+			b43_phy_maskset(dev, reg, ~tmp, val);
+			b43_phy_set(dev, reg, 0x1000);
+			break;
+		case N_INTC_OVERRIDE_EXT_LNA_PU:
+			if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
+				tmp = 0x0001;
+				tmp2 = 0x0004;
+				val = value;
+			} else {
+				tmp = 0x0004;
+				tmp2 = 0x0001;
+				val = value << 2;
+			}
+			b43_phy_maskset(dev, reg, ~tmp, val);
+			b43_phy_mask(dev, reg, ~tmp2);
+			break;
+		case N_INTC_OVERRIDE_EXT_LNA_GAIN:
+			if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
+				tmp = 0x0002;
+				tmp2 = 0x0008;
+				val = value << 1;
+			} else {
+				tmp = 0x0008;
+				tmp2 = 0x0002;
+				val = value << 3;
+			}
+			b43_phy_maskset(dev, reg, ~tmp, val);
+			b43_phy_mask(dev, reg, ~tmp2);
+			break;
+		}
+	}
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlIntcOverride */
+static void b43_nphy_rf_ctl_intc_override(struct b43_wldev *dev,
+					  enum n_intc_override intc_override,
+					  u16 value, u8 core)
+{
+	u8 i, j;
+	u16 reg, tmp, val;
+
+	if (dev->phy.rev >= 7) {
+		b43_nphy_rf_ctl_intc_override_rev7(dev, intc_override, value,
+						   core);
+		return;
+	}
+
+	B43_WARN_ON(dev->phy.rev < 3);
+
+	for (i = 0; i < 2; i++) {
+		if ((core == 1 && i == 1) || (core == 2 && !i))
+			continue;
+
+		reg = (i == 0) ?
+			B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2;
+		b43_phy_set(dev, reg, 0x400);
+
+		switch (intc_override) {
+		case N_INTC_OVERRIDE_OFF:
+			b43_phy_write(dev, reg, 0);
+			b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
+			break;
+		case N_INTC_OVERRIDE_TRSW:
+			if (!i) {
+				b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC1,
+						0xFC3F, (value << 6));
+				b43_phy_maskset(dev, B43_NPHY_TXF_40CO_B1S1,
+						0xFFFE, 1);
+				b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
+						B43_NPHY_RFCTL_CMD_START);
+				for (j = 0; j < 100; j++) {
+					if (!(b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_START)) {
+						j = 0;
+						break;
+					}
+					udelay(10);
+				}
+				if (j)
+					b43err(dev->wl,
+						"intc override timeout\n");
+				b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S1,
+						0xFFFE);
+			} else {
+				b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC2,
+						0xFC3F, (value << 6));
+				b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
+						0xFFFE, 1);
+				b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
+						B43_NPHY_RFCTL_CMD_RXTX);
+				for (j = 0; j < 100; j++) {
+					if (!(b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_RXTX)) {
+						j = 0;
+						break;
+					}
+					udelay(10);
+				}
+				if (j)
+					b43err(dev->wl,
+						"intc override timeout\n");
+				b43_phy_mask(dev, B43_NPHY_RFCTL_OVER,
+						0xFFFE);
+			}
+			break;
+		case N_INTC_OVERRIDE_PA:
+			if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
+				tmp = 0x0020;
+				val = value << 5;
+			} else {
+				tmp = 0x0010;
+				val = value << 4;
+			}
+			b43_phy_maskset(dev, reg, ~tmp, val);
+			break;
+		case N_INTC_OVERRIDE_EXT_LNA_PU:
+			if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
+				tmp = 0x0001;
+				val = value;
+			} else {
+				tmp = 0x0004;
+				val = value << 2;
+			}
+			b43_phy_maskset(dev, reg, ~tmp, val);
+			break;
+		case N_INTC_OVERRIDE_EXT_LNA_GAIN:
+			if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
+				tmp = 0x0002;
+				val = value << 1;
+			} else {
+				tmp = 0x0008;
+				val = value << 3;
+			}
+			b43_phy_maskset(dev, reg, ~tmp, val);
+			break;
+		}
+	}
+}
+
+/**************************************************
+ * Various PHY ops
+ **************************************************/
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
+static void b43_nphy_write_clip_detection(struct b43_wldev *dev,
+					  const u16 *clip_st)
+{
+	b43_phy_write(dev, B43_NPHY_C1_CLIP1THRES, clip_st[0]);
+	b43_phy_write(dev, B43_NPHY_C2_CLIP1THRES, clip_st[1]);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
+static void b43_nphy_read_clip_detection(struct b43_wldev *dev, u16 *clip_st)
+{
+	clip_st[0] = b43_phy_read(dev, B43_NPHY_C1_CLIP1THRES);
+	clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */
+static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)
+{
+	u16 tmp;
+
+	if (dev->dev->core_rev == 16)
+		b43_mac_suspend(dev);
+
+	tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL);
+	tmp &= (B43_NPHY_CLASSCTL_CCKEN | B43_NPHY_CLASSCTL_OFDMEN |
+		B43_NPHY_CLASSCTL_WAITEDEN);
+	tmp &= ~mask;
+	tmp |= (val & mask);
+	b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp);
+
+	if (dev->dev->core_rev == 16)
+		b43_mac_enable(dev);
+
+	return tmp;
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
+static void b43_nphy_reset_cca(struct b43_wldev *dev)
+{
+	u16 bbcfg;
+
+	b43_phy_force_clock(dev, 1);
+	bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG);
+	b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA);
+	udelay(1);
+	b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA);
+	b43_phy_force_clock(dev, 0);
+	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/carriersearch */
+static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = phy->n;
+
+	if (enable) {
+		static const u16 clip[] = { 0xFFFF, 0xFFFF };
+		if (nphy->deaf_count++ == 0) {
+			nphy->classifier_state = b43_nphy_classifier(dev, 0, 0);
+			b43_nphy_classifier(dev, 0x7,
+					    B43_NPHY_CLASSCTL_WAITEDEN);
+			b43_nphy_read_clip_detection(dev, nphy->clip_state);
+			b43_nphy_write_clip_detection(dev, clip);
+		}
+		b43_nphy_reset_cca(dev);
+	} else {
+		if (--nphy->deaf_count == 0) {
+			b43_nphy_classifier(dev, 0x7, nphy->classifier_state);
+			b43_nphy_write_clip_detection(dev, nphy->clip_state);
+		}
+	}
+}
+
+/* http://bcm-v4.sipsolutions.net/PHY/N/Read_Lpf_Bw_Ctl */
+static u16 b43_nphy_read_lpf_ctl(struct b43_wldev *dev, u16 offset)
+{
+	if (!offset)
+		offset = b43_is_40mhz(dev) ? 0x159 : 0x154;
+	return b43_ntab_read(dev, B43_NTAB16(7, offset)) & 0x7;
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */
+static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)
+{
+	struct b43_phy_n *nphy = dev->phy.n;
+
+	u8 i;
+	s16 tmp;
+	u16 data[4];
+	s16 gain[2];
+	u16 minmax[2];
+	static const u16 lna_gain[4] = { -2, 10, 19, 25 };
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, 1);
+
+	if (nphy->gain_boost) {
+		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+			gain[0] = 6;
+			gain[1] = 6;
+		} else {
+			tmp = 40370 - 315 * dev->phy.channel;
+			gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1));
+			tmp = 23242 - 224 * dev->phy.channel;
+			gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1));
+		}
+	} else {
+		gain[0] = 0;
+		gain[1] = 0;
+	}
+
+	for (i = 0; i < 2; i++) {
+		if (nphy->elna_gain_config) {
+			data[0] = 19 + gain[i];
+			data[1] = 25 + gain[i];
+			data[2] = 25 + gain[i];
+			data[3] = 25 + gain[i];
+		} else {
+			data[0] = lna_gain[0] + gain[i];
+			data[1] = lna_gain[1] + gain[i];
+			data[2] = lna_gain[2] + gain[i];
+			data[3] = lna_gain[3] + gain[i];
+		}
+		b43_ntab_write_bulk(dev, B43_NTAB16(i, 8), 4, data);
+
+		minmax[i] = 23 + gain[i];
+	}
+
+	b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN, ~B43_NPHY_C1_MINGAIN,
+				minmax[0] << B43_NPHY_C1_MINGAIN_SHIFT);
+	b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN, ~B43_NPHY_C2_MINGAIN,
+				minmax[1] << B43_NPHY_C2_MINGAIN_SHIFT);
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, 0);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRfSeq */
+static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
+					u8 *events, u8 *delays, u8 length)
+{
+	struct b43_phy_n *nphy = dev->phy.n;
+	u8 i;
+	u8 end = (dev->phy.rev >= 3) ? 0x1F : 0x0F;
+	u16 offset1 = cmd << 4;
+	u16 offset2 = offset1 + 0x80;
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, true);
+
+	b43_ntab_write_bulk(dev, B43_NTAB8(7, offset1), length, events);
+	b43_ntab_write_bulk(dev, B43_NTAB8(7, offset2), length, delays);
+
+	for (i = length; i < 16; i++) {
+		b43_ntab_write(dev, B43_NTAB8(7, offset1 + i), end);
+		b43_ntab_write(dev, B43_NTAB8(7, offset2 + i), 1);
+	}
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, false);
+}
+
+/**************************************************
+ * Radio 0x2057
+ **************************************************/
+
+static void b43_radio_2057_chantab_upload(struct b43_wldev *dev,
+					  const struct b43_nphy_chantabent_rev7 *e_r7,
+					  const struct b43_nphy_chantabent_rev7_2g *e_r7_2g)
+{
+	if (e_r7_2g) {
+		b43_radio_write(dev, R2057_VCOCAL_COUNTVAL0, e_r7_2g->radio_vcocal_countval0);
+		b43_radio_write(dev, R2057_VCOCAL_COUNTVAL1, e_r7_2g->radio_vcocal_countval1);
+		b43_radio_write(dev, R2057_RFPLL_REFMASTER_SPAREXTALSIZE, e_r7_2g->radio_rfpll_refmaster_sparextalsize);
+		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, e_r7_2g->radio_rfpll_loopfilter_r1);
+		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, e_r7_2g->radio_rfpll_loopfilter_c2);
+		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, e_r7_2g->radio_rfpll_loopfilter_c1);
+		b43_radio_write(dev, R2057_CP_KPD_IDAC, e_r7_2g->radio_cp_kpd_idac);
+		b43_radio_write(dev, R2057_RFPLL_MMD0, e_r7_2g->radio_rfpll_mmd0);
+		b43_radio_write(dev, R2057_RFPLL_MMD1, e_r7_2g->radio_rfpll_mmd1);
+		b43_radio_write(dev, R2057_VCOBUF_TUNE, e_r7_2g->radio_vcobuf_tune);
+		b43_radio_write(dev, R2057_LOGEN_MX2G_TUNE, e_r7_2g->radio_logen_mx2g_tune);
+		b43_radio_write(dev, R2057_LOGEN_INDBUF2G_TUNE, e_r7_2g->radio_logen_indbuf2g_tune);
+		b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, e_r7_2g->radio_txmix2g_tune_boost_pu_core0);
+		b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE0, e_r7_2g->radio_pad2g_tune_pus_core0);
+		b43_radio_write(dev, R2057_LNA2G_TUNE_CORE0, e_r7_2g->radio_lna2g_tune_core0);
+		b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, e_r7_2g->radio_txmix2g_tune_boost_pu_core1);
+		b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE1, e_r7_2g->radio_pad2g_tune_pus_core1);
+		b43_radio_write(dev, R2057_LNA2G_TUNE_CORE1, e_r7_2g->radio_lna2g_tune_core1);
+
+	} else {
+		b43_radio_write(dev, R2057_VCOCAL_COUNTVAL0, e_r7->radio_vcocal_countval0);
+		b43_radio_write(dev, R2057_VCOCAL_COUNTVAL1, e_r7->radio_vcocal_countval1);
+		b43_radio_write(dev, R2057_RFPLL_REFMASTER_SPAREXTALSIZE, e_r7->radio_rfpll_refmaster_sparextalsize);
+		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, e_r7->radio_rfpll_loopfilter_r1);
+		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, e_r7->radio_rfpll_loopfilter_c2);
+		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, e_r7->radio_rfpll_loopfilter_c1);
+		b43_radio_write(dev, R2057_CP_KPD_IDAC, e_r7->radio_cp_kpd_idac);
+		b43_radio_write(dev, R2057_RFPLL_MMD0, e_r7->radio_rfpll_mmd0);
+		b43_radio_write(dev, R2057_RFPLL_MMD1, e_r7->radio_rfpll_mmd1);
+		b43_radio_write(dev, R2057_VCOBUF_TUNE, e_r7->radio_vcobuf_tune);
+		b43_radio_write(dev, R2057_LOGEN_MX2G_TUNE, e_r7->radio_logen_mx2g_tune);
+		b43_radio_write(dev, R2057_LOGEN_MX5G_TUNE, e_r7->radio_logen_mx5g_tune);
+		b43_radio_write(dev, R2057_LOGEN_INDBUF2G_TUNE, e_r7->radio_logen_indbuf2g_tune);
+		b43_radio_write(dev, R2057_LOGEN_INDBUF5G_TUNE, e_r7->radio_logen_indbuf5g_tune);
+		b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, e_r7->radio_txmix2g_tune_boost_pu_core0);
+		b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE0, e_r7->radio_pad2g_tune_pus_core0);
+		b43_radio_write(dev, R2057_PGA_BOOST_TUNE_CORE0, e_r7->radio_pga_boost_tune_core0);
+		b43_radio_write(dev, R2057_TXMIX5G_BOOST_TUNE_CORE0, e_r7->radio_txmix5g_boost_tune_core0);
+		b43_radio_write(dev, R2057_PAD5G_TUNE_MISC_PUS_CORE0, e_r7->radio_pad5g_tune_misc_pus_core0);
+		b43_radio_write(dev, R2057_LNA2G_TUNE_CORE0, e_r7->radio_lna2g_tune_core0);
+		b43_radio_write(dev, R2057_LNA5G_TUNE_CORE0, e_r7->radio_lna5g_tune_core0);
+		b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, e_r7->radio_txmix2g_tune_boost_pu_core1);
+		b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE1, e_r7->radio_pad2g_tune_pus_core1);
+		b43_radio_write(dev, R2057_PGA_BOOST_TUNE_CORE1, e_r7->radio_pga_boost_tune_core1);
+		b43_radio_write(dev, R2057_TXMIX5G_BOOST_TUNE_CORE1, e_r7->radio_txmix5g_boost_tune_core1);
+		b43_radio_write(dev, R2057_PAD5G_TUNE_MISC_PUS_CORE1, e_r7->radio_pad5g_tune_misc_pus_core1);
+		b43_radio_write(dev, R2057_LNA2G_TUNE_CORE1, e_r7->radio_lna2g_tune_core1);
+		b43_radio_write(dev, R2057_LNA5G_TUNE_CORE1, e_r7->radio_lna5g_tune_core1);
+	}
+}
+
+static void b43_radio_2057_setup(struct b43_wldev *dev,
+				 const struct b43_nphy_chantabent_rev7 *tabent_r7,
+				 const struct b43_nphy_chantabent_rev7_2g *tabent_r7_2g)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	b43_radio_2057_chantab_upload(dev, tabent_r7, tabent_r7_2g);
+
+	switch (phy->radio_rev) {
+	case 0 ... 4:
+	case 6:
+		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x3f);
+			b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f);
+			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x8);
+			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x8);
+		} else {
+			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x1f);
+			b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f);
+			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x8);
+			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x8);
+		}
+		break;
+	case 9: /* e.g. PHY rev 16 */
+		b43_radio_write(dev, R2057_LOGEN_PTAT_RESETS, 0x20);
+		b43_radio_write(dev, R2057_VCOBUF_IDACS, 0x18);
+		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
+			b43_radio_write(dev, R2057_LOGEN_PTAT_RESETS, 0x38);
+			b43_radio_write(dev, R2057_VCOBUF_IDACS, 0x0f);
+
+			if (b43_is_40mhz(dev)) {
+				/* TODO */
+			} else {
+				b43_radio_write(dev,
+						R2057_PAD_BIAS_FILTER_BWS_CORE0,
+						0x3c);
+				b43_radio_write(dev,
+						R2057_PAD_BIAS_FILTER_BWS_CORE1,
+						0x3c);
+			}
+		}
+		break;
+	case 14: /* 2 GHz only */
+		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x1b);
+		b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f);
+		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x1f);
+		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x1f);
+		break;
+	}
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+		u16 txmix2g_tune_boost_pu = 0;
+		u16 pad2g_tune_pus = 0;
+
+		if (b43_nphy_ipa(dev)) {
+			switch (phy->radio_rev) {
+			case 9:
+				txmix2g_tune_boost_pu = 0x0041;
+				/* TODO */
+				break;
+			case 14:
+				txmix2g_tune_boost_pu = 0x21;
+				pad2g_tune_pus = 0x23;
+				break;
+			}
+		}
+
+		if (txmix2g_tune_boost_pu)
+			b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0,
+					txmix2g_tune_boost_pu);
+		if (pad2g_tune_pus)
+			b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE0,
+					pad2g_tune_pus);
+		if (txmix2g_tune_boost_pu)
+			b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1,
+					txmix2g_tune_boost_pu);
+		if (pad2g_tune_pus)
+			b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE1,
+					pad2g_tune_pus);
+	}
+
+	usleep_range(50, 100);
+
+	/* VCO calibration */
+	b43_radio_mask(dev, R2057_RFPLL_MISC_EN, ~0x01);
+	b43_radio_mask(dev, R2057_RFPLL_MISC_CAL_RESETN, ~0x04);
+	b43_radio_set(dev, R2057_RFPLL_MISC_CAL_RESETN, 0x4);
+	b43_radio_set(dev, R2057_RFPLL_MISC_EN, 0x01);
+	usleep_range(300, 600);
+}
+
+/* Calibrate resistors in LPF of PLL?
+ * http://bcm-v4.sipsolutions.net/PHY/radio205x_rcal
+ */
+static u8 b43_radio_2057_rcal(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	u16 saved_regs_phy[12];
+	u16 saved_regs_phy_rf[6];
+	u16 saved_regs_radio[2] = { };
+	static const u16 phy_to_store[] = {
+		B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2,
+		B43_NPHY_RFCTL_LUT_TRSW_LO1, B43_NPHY_RFCTL_LUT_TRSW_LO2,
+		B43_NPHY_RFCTL_RXG1, B43_NPHY_RFCTL_RXG2,
+		B43_NPHY_RFCTL_TXG1, B43_NPHY_RFCTL_TXG2,
+		B43_NPHY_REV7_RF_CTL_MISC_REG3, B43_NPHY_REV7_RF_CTL_MISC_REG4,
+		B43_NPHY_REV7_RF_CTL_MISC_REG5, B43_NPHY_REV7_RF_CTL_MISC_REG6,
+	};
+	static const u16 phy_to_store_rf[] = {
+		B43_NPHY_REV3_RFCTL_OVER0, B43_NPHY_REV3_RFCTL_OVER1,
+		B43_NPHY_REV7_RF_CTL_OVER3, B43_NPHY_REV7_RF_CTL_OVER4,
+		B43_NPHY_REV7_RF_CTL_OVER5, B43_NPHY_REV7_RF_CTL_OVER6,
+	};
+	u16 tmp;
+	int i;
+
+	/* Save */
+	for (i = 0; i < ARRAY_SIZE(phy_to_store); i++)
+		saved_regs_phy[i] = b43_phy_read(dev, phy_to_store[i]);
+	for (i = 0; i < ARRAY_SIZE(phy_to_store_rf); i++)
+		saved_regs_phy_rf[i] = b43_phy_read(dev, phy_to_store_rf[i]);
+
+	/* Set */
+	for (i = 0; i < ARRAY_SIZE(phy_to_store); i++)
+		b43_phy_write(dev, phy_to_store[i], 0);
+	b43_phy_write(dev, B43_NPHY_REV3_RFCTL_OVER0, 0x07ff);
+	b43_phy_write(dev, B43_NPHY_REV3_RFCTL_OVER1, 0x07ff);
+	b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x07ff);
+	b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER4, 0x07ff);
+	b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER5, 0x007f);
+	b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER6, 0x007f);
+
+	switch (phy->radio_rev) {
+	case 5:
+		b43_phy_mask(dev, B43_NPHY_REV7_RF_CTL_OVER3, ~0x2);
+		udelay(10);
+		b43_radio_set(dev, R2057_IQTEST_SEL_PU, 0x1);
+		b43_radio_maskset(dev, R2057v7_IQTEST_SEL_PU2, ~0x2, 0x1);
+		break;
+	case 9:
+		b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x2);
+		b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_MISC_REG3, 0x2);
+		saved_regs_radio[0] = b43_radio_read(dev, R2057_IQTEST_SEL_PU);
+		b43_radio_write(dev, R2057_IQTEST_SEL_PU, 0x11);
+		break;
+	case 14:
+		saved_regs_radio[0] = b43_radio_read(dev, R2057_IQTEST_SEL_PU);
+		saved_regs_radio[1] = b43_radio_read(dev, R2057v7_IQTEST_SEL_PU2);
+		b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_MISC_REG3, 0x2);
+		b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x2);
+		b43_radio_write(dev, R2057v7_IQTEST_SEL_PU2, 0x2);
+		b43_radio_write(dev, R2057_IQTEST_SEL_PU, 0x1);
+		break;
+	}
+
+	/* Enable */
+	b43_radio_set(dev, R2057_RCAL_CONFIG, 0x1);
+	udelay(10);
+
+	/* Start */
+	b43_radio_set(dev, R2057_RCAL_CONFIG, 0x2);
+	usleep_range(100, 200);
+
+	/* Stop */
+	b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x2);
+
+	/* Wait and check for result */
+	if (!b43_radio_wait_value(dev, R2057_RCAL_STATUS, 1, 1, 100, 1000000)) {
+		b43err(dev->wl, "Radio 0x2057 rcal timeout\n");
+		return 0;
+	}
+	tmp = b43_radio_read(dev, R2057_RCAL_STATUS) & 0x3E;
+
+	/* Disable */
+	b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x1);
+
+	/* Restore */
+	for (i = 0; i < ARRAY_SIZE(phy_to_store_rf); i++)
+		b43_phy_write(dev, phy_to_store_rf[i], saved_regs_phy_rf[i]);
+	for (i = 0; i < ARRAY_SIZE(phy_to_store); i++)
+		b43_phy_write(dev, phy_to_store[i], saved_regs_phy[i]);
+
+	switch (phy->radio_rev) {
+	case 0 ... 4:
+	case 6:
+		b43_radio_maskset(dev, R2057_TEMPSENSE_CONFIG, ~0x3C, tmp);
+		b43_radio_maskset(dev, R2057_BANDGAP_RCAL_TRIM, ~0xF0,
+				  tmp << 2);
+		break;
+	case 5:
+		b43_radio_mask(dev, R2057_IPA2G_CASCONV_CORE0, ~0x1);
+		b43_radio_mask(dev, R2057v7_IQTEST_SEL_PU2, ~0x2);
+		break;
+	case 9:
+		b43_radio_write(dev, R2057_IQTEST_SEL_PU, saved_regs_radio[0]);
+		break;
+	case 14:
+		b43_radio_write(dev, R2057_IQTEST_SEL_PU, saved_regs_radio[0]);
+		b43_radio_write(dev, R2057v7_IQTEST_SEL_PU2, saved_regs_radio[1]);
+		break;
+	}
+
+	return tmp & 0x3e;
+}
+
+/* Calibrate the internal RC oscillator?
+ * http://bcm-v4.sipsolutions.net/PHY/radio2057_rccal
+ */
+static u16 b43_radio_2057_rccal(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	bool special = (phy->radio_rev == 3 || phy->radio_rev == 4 ||
+			phy->radio_rev == 6);
+	u16 tmp;
+
+	/* Setup cal */
+	if (special) {
+		b43_radio_write(dev, R2057_RCCAL_MASTER, 0x61);
+		b43_radio_write(dev, R2057_RCCAL_TRC0, 0xC0);
+	} else {
+		b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x61);
+		b43_radio_write(dev, R2057_RCCAL_TRC0, 0xE9);
+	}
+	b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
+
+	/* Start, wait, stop */
+	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
+	if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500,
+				  5000000))
+		b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n");
+	usleep_range(35, 70);
+	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
+	usleep_range(70, 140);
+
+	/* Setup cal */
+	if (special) {
+		b43_radio_write(dev, R2057_RCCAL_MASTER, 0x69);
+		b43_radio_write(dev, R2057_RCCAL_TRC0, 0xB0);
+	} else {
+		b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x69);
+		b43_radio_write(dev, R2057_RCCAL_TRC0, 0xD5);
+	}
+	b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
+
+	/* Start, wait, stop */
+	usleep_range(35, 70);
+	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
+	usleep_range(70, 140);
+	if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500,
+				  5000000))
+		b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n");
+	usleep_range(35, 70);
+	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
+	usleep_range(70, 140);
+
+	/* Setup cal */
+	if (special) {
+		b43_radio_write(dev, R2057_RCCAL_MASTER, 0x73);
+		b43_radio_write(dev, R2057_RCCAL_X1, 0x28);
+		b43_radio_write(dev, R2057_RCCAL_TRC0, 0xB0);
+	} else {
+		b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x73);
+		b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
+		b43_radio_write(dev, R2057_RCCAL_TRC0, 0x99);
+	}
+
+	/* Start, wait, stop */
+	usleep_range(35, 70);
+	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
+	usleep_range(70, 140);
+	if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500,
+				  5000000)) {
+		b43err(dev->wl, "Radio 0x2057 rcal timeout\n");
+		return 0;
+	}
+	tmp = b43_radio_read(dev, R2057_RCCAL_DONE_OSCCAP);
+	usleep_range(35, 70);
+	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
+	usleep_range(70, 140);
+
+	if (special)
+		b43_radio_mask(dev, R2057_RCCAL_MASTER, ~0x1);
+	else
+		b43_radio_mask(dev, R2057v7_RCCAL_MASTER, ~0x1);
+
+	return tmp;
+}
+
+static void b43_radio_2057_init_pre(struct b43_wldev *dev)
+{
+	b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, ~B43_NPHY_RFCTL_CMD_CHIP0PU);
+	/* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */
+	b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_OEPORFORCE);
+	b43_phy_set(dev, B43_NPHY_RFCTL_CMD, ~B43_NPHY_RFCTL_CMD_OEPORFORCE);
+	b43_phy_set(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_CHIP0PU);
+}
+
+static void b43_radio_2057_init_post(struct b43_wldev *dev)
+{
+	b43_radio_set(dev, R2057_XTALPUOVR_PINCTRL, 0x1);
+
+	if (0) /* FIXME: Is this BCM43217 specific? */
+		b43_radio_set(dev, R2057_XTALPUOVR_PINCTRL, 0x2);
+
+	b43_radio_set(dev, R2057_RFPLL_MISC_CAL_RESETN, 0x78);
+	b43_radio_set(dev, R2057_XTAL_CONFIG2, 0x80);
+	usleep_range(2000, 3000);
+	b43_radio_mask(dev, R2057_RFPLL_MISC_CAL_RESETN, ~0x78);
+	b43_radio_mask(dev, R2057_XTAL_CONFIG2, ~0x80);
+
+	if (dev->phy.do_full_init) {
+		b43_radio_2057_rcal(dev);
+		b43_radio_2057_rccal(dev);
+	}
+	b43_radio_mask(dev, R2057_RFPLL_MASTER, ~0x8);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/Radio/2057/Init */
+static void b43_radio_2057_init(struct b43_wldev *dev)
+{
+	b43_radio_2057_init_pre(dev);
+	r2057_upload_inittabs(dev);
+	b43_radio_2057_init_post(dev);
+}
+
+/**************************************************
+ * Radio 0x2056
+ **************************************************/
+
+static void b43_chantab_radio_2056_upload(struct b43_wldev *dev,
+				const struct b43_nphy_channeltab_entry_rev3 *e)
+{
+	b43_radio_write(dev, B2056_SYN_PLL_VCOCAL1, e->radio_syn_pll_vcocal1);
+	b43_radio_write(dev, B2056_SYN_PLL_VCOCAL2, e->radio_syn_pll_vcocal2);
+	b43_radio_write(dev, B2056_SYN_PLL_REFDIV, e->radio_syn_pll_refdiv);
+	b43_radio_write(dev, B2056_SYN_PLL_MMD2, e->radio_syn_pll_mmd2);
+	b43_radio_write(dev, B2056_SYN_PLL_MMD1, e->radio_syn_pll_mmd1);
+	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1,
+					e->radio_syn_pll_loopfilter1);
+	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2,
+					e->radio_syn_pll_loopfilter2);
+	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER3,
+					e->radio_syn_pll_loopfilter3);
+	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4,
+					e->radio_syn_pll_loopfilter4);
+	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER5,
+					e->radio_syn_pll_loopfilter5);
+	b43_radio_write(dev, B2056_SYN_RESERVED_ADDR27,
+					e->radio_syn_reserved_addr27);
+	b43_radio_write(dev, B2056_SYN_RESERVED_ADDR28,
+					e->radio_syn_reserved_addr28);
+	b43_radio_write(dev, B2056_SYN_RESERVED_ADDR29,
+					e->radio_syn_reserved_addr29);
+	b43_radio_write(dev, B2056_SYN_LOGEN_VCOBUF1,
+					e->radio_syn_logen_vcobuf1);
+	b43_radio_write(dev, B2056_SYN_LOGEN_MIXER2, e->radio_syn_logen_mixer2);
+	b43_radio_write(dev, B2056_SYN_LOGEN_BUF3, e->radio_syn_logen_buf3);
+	b43_radio_write(dev, B2056_SYN_LOGEN_BUF4, e->radio_syn_logen_buf4);
+
+	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA_TUNE,
+					e->radio_rx0_lnaa_tune);
+	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG_TUNE,
+					e->radio_rx0_lnag_tune);
+
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAA_BOOST_TUNE,
+					e->radio_tx0_intpaa_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAG_BOOST_TUNE,
+					e->radio_tx0_intpag_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_PADA_BOOST_TUNE,
+					e->radio_tx0_pada_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_PADG_BOOST_TUNE,
+					e->radio_tx0_padg_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAA_BOOST_TUNE,
+					e->radio_tx0_pgaa_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAG_BOOST_TUNE,
+					e->radio_tx0_pgag_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXA_BOOST_TUNE,
+					e->radio_tx0_mixa_boost_tune);
+	b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXG_BOOST_TUNE,
+					e->radio_tx0_mixg_boost_tune);
+
+	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA_TUNE,
+					e->radio_rx1_lnaa_tune);
+	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG_TUNE,
+					e->radio_rx1_lnag_tune);
+
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAA_BOOST_TUNE,
+					e->radio_tx1_intpaa_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAG_BOOST_TUNE,
+					e->radio_tx1_intpag_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_PADA_BOOST_TUNE,
+					e->radio_tx1_pada_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_PADG_BOOST_TUNE,
+					e->radio_tx1_padg_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAA_BOOST_TUNE,
+					e->radio_tx1_pgaa_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAG_BOOST_TUNE,
+					e->radio_tx1_pgag_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXA_BOOST_TUNE,
+					e->radio_tx1_mixa_boost_tune);
+	b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXG_BOOST_TUNE,
+					e->radio_tx1_mixg_boost_tune);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2056Setup */
+static void b43_radio_2056_setup(struct b43_wldev *dev,
+				const struct b43_nphy_channeltab_entry_rev3 *e)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+	enum nl80211_band band = b43_current_band(dev->wl);
+	u16 offset;
+	u8 i;
+	u16 bias, cbias;
+	u16 pag_boost, padg_boost, pgag_boost, mixg_boost;
+	u16 paa_boost, pada_boost, pgaa_boost, mixa_boost;
+	bool is_pkg_fab_smic;
+
+	B43_WARN_ON(dev->phy.rev < 3);
+
+	is_pkg_fab_smic =
+		((dev->dev->chip_id == BCMA_CHIP_ID_BCM43224 ||
+		  dev->dev->chip_id == BCMA_CHIP_ID_BCM43225 ||
+		  dev->dev->chip_id == BCMA_CHIP_ID_BCM43421) &&
+		 dev->dev->chip_pkg == BCMA_PKG_ID_BCM43224_FAB_SMIC);
+
+	b43_chantab_radio_2056_upload(dev, e);
+	b2056_upload_syn_pll_cp2(dev, band == NL80211_BAND_5GHZ);
+
+	if (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
+	    b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
+		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F);
+		if (dev->dev->chip_id == BCMA_CHIP_ID_BCM4716 ||
+		    dev->dev->chip_id == BCMA_CHIP_ID_BCM47162) {
+			b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x14);
+			b43_radio_write(dev, B2056_SYN_PLL_CP2, 0);
+		} else {
+			b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x0B);
+			b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x14);
+		}
+	}
+	if (sprom->boardflags2_hi & B43_BFH2_GPLL_WAR2 &&
+	    b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1f);
+		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1f);
+		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x0b);
+		b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x20);
+	}
+	if (sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
+	    b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
+		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
+		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F);
+		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x05);
+		b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x0C);
+	}
+
+	if (dev->phy.n->ipa2g_on && band == NL80211_BAND_2GHZ) {
+		for (i = 0; i < 2; i++) {
+			offset = i ? B2056_TX1 : B2056_TX0;
+			if (dev->phy.rev >= 5) {
+				b43_radio_write(dev,
+					offset | B2056_TX_PADG_IDAC, 0xcc);
+
+				if (dev->dev->chip_id == BCMA_CHIP_ID_BCM4716 ||
+				    dev->dev->chip_id == BCMA_CHIP_ID_BCM47162) {
+					bias = 0x40;
+					cbias = 0x45;
+					pag_boost = 0x5;
+					pgag_boost = 0x33;
+					mixg_boost = 0x55;
+				} else {
+					bias = 0x25;
+					cbias = 0x20;
+					if (is_pkg_fab_smic) {
+						bias = 0x2a;
+						cbias = 0x38;
+					}
+					pag_boost = 0x4;
+					pgag_boost = 0x03;
+					mixg_boost = 0x65;
+				}
+				padg_boost = 0x77;
+
+				b43_radio_write(dev,
+					offset | B2056_TX_INTPAG_IMAIN_STAT,
+					bias);
+				b43_radio_write(dev,
+					offset | B2056_TX_INTPAG_IAUX_STAT,
+					bias);
+				b43_radio_write(dev,
+					offset | B2056_TX_INTPAG_CASCBIAS,
+					cbias);
+				b43_radio_write(dev,
+					offset | B2056_TX_INTPAG_BOOST_TUNE,
+					pag_boost);
+				b43_radio_write(dev,
+					offset | B2056_TX_PGAG_BOOST_TUNE,
+					pgag_boost);
+				b43_radio_write(dev,
+					offset | B2056_TX_PADG_BOOST_TUNE,
+					padg_boost);
+				b43_radio_write(dev,
+					offset | B2056_TX_MIXG_BOOST_TUNE,
+					mixg_boost);
+			} else {
+				bias = b43_is_40mhz(dev) ? 0x40 : 0x20;
+				b43_radio_write(dev,
+					offset | B2056_TX_INTPAG_IMAIN_STAT,
+					bias);
+				b43_radio_write(dev,
+					offset | B2056_TX_INTPAG_IAUX_STAT,
+					bias);
+				b43_radio_write(dev,
+					offset | B2056_TX_INTPAG_CASCBIAS,
+					0x30);
+			}
+			b43_radio_write(dev, offset | B2056_TX_PA_SPARE1, 0xee);
+		}
+	} else if (dev->phy.n->ipa5g_on && band == NL80211_BAND_5GHZ) {
+		u16 freq = phy->chandef->chan->center_freq;
+		if (freq < 5100) {
+			paa_boost = 0xA;
+			pada_boost = 0x77;
+			pgaa_boost = 0xF;
+			mixa_boost = 0xF;
+		} else if (freq < 5340) {
+			paa_boost = 0x8;
+			pada_boost = 0x77;
+			pgaa_boost = 0xFB;
+			mixa_boost = 0xF;
+		} else if (freq < 5650) {
+			paa_boost = 0x0;
+			pada_boost = 0x77;
+			pgaa_boost = 0xB;
+			mixa_boost = 0xF;
+		} else {
+			paa_boost = 0x0;
+			pada_boost = 0x77;
+			if (freq != 5825)
+				pgaa_boost = -(freq - 18) / 36 + 168;
+			else
+				pgaa_boost = 6;
+			mixa_boost = 0xF;
+		}
+
+		cbias = is_pkg_fab_smic ? 0x35 : 0x30;
+
+		for (i = 0; i < 2; i++) {
+			offset = i ? B2056_TX1 : B2056_TX0;
+
+			b43_radio_write(dev,
+				offset | B2056_TX_INTPAA_BOOST_TUNE, paa_boost);
+			b43_radio_write(dev,
+				offset | B2056_TX_PADA_BOOST_TUNE, pada_boost);
+			b43_radio_write(dev,
+				offset | B2056_TX_PGAA_BOOST_TUNE, pgaa_boost);
+			b43_radio_write(dev,
+				offset | B2056_TX_MIXA_BOOST_TUNE, mixa_boost);
+			b43_radio_write(dev,
+				offset | B2056_TX_TXSPARE1, 0x30);
+			b43_radio_write(dev,
+				offset | B2056_TX_PA_SPARE2, 0xee);
+			b43_radio_write(dev,
+				offset | B2056_TX_PADA_CASCBIAS, 0x03);
+			b43_radio_write(dev,
+				offset | B2056_TX_INTPAA_IAUX_STAT, 0x30);
+			b43_radio_write(dev,
+				offset | B2056_TX_INTPAA_IMAIN_STAT, 0x30);
+			b43_radio_write(dev,
+				offset | B2056_TX_INTPAA_CASCBIAS, cbias);
+		}
+	}
+
+	udelay(50);
+	/* VCO calibration */
+	b43_radio_write(dev, B2056_SYN_PLL_VCOCAL12, 0x00);
+	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38);
+	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x18);
+	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38);
+	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x39);
+	udelay(300);
+}
+
+static u8 b43_radio_2056_rcal(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	u16 mast2, tmp;
+
+	if (phy->rev != 3)
+		return 0;
+
+	mast2 = b43_radio_read(dev, B2056_SYN_PLL_MAST2);
+	b43_radio_write(dev, B2056_SYN_PLL_MAST2, mast2 | 0x7);
+
+	udelay(10);
+	b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x01);
+	udelay(10);
+	b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x09);
+
+	if (!b43_radio_wait_value(dev, B2056_SYN_RCAL_CODE_OUT, 0x80, 0x80, 100,
+				  1000000)) {
+		b43err(dev->wl, "Radio recalibration timeout\n");
+		return 0;
+	}
+
+	b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x01);
+	tmp = b43_radio_read(dev, B2056_SYN_RCAL_CODE_OUT);
+	b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x00);
+
+	b43_radio_write(dev, B2056_SYN_PLL_MAST2, mast2);
+
+	return tmp & 0x1f;
+}
+
+static void b43_radio_init2056_pre(struct b43_wldev *dev)
+{
+	b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
+		     ~B43_NPHY_RFCTL_CMD_CHIP0PU);
+	/* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */
+	b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
+		     B43_NPHY_RFCTL_CMD_OEPORFORCE);
+	b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
+		    ~B43_NPHY_RFCTL_CMD_OEPORFORCE);
+	b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
+		    B43_NPHY_RFCTL_CMD_CHIP0PU);
+}
+
+static void b43_radio_init2056_post(struct b43_wldev *dev)
+{
+	b43_radio_set(dev, B2056_SYN_COM_CTRL, 0xB);
+	b43_radio_set(dev, B2056_SYN_COM_PU, 0x2);
+	b43_radio_set(dev, B2056_SYN_COM_RESET, 0x2);
+	msleep(1);
+	b43_radio_mask(dev, B2056_SYN_COM_RESET, ~0x2);
+	b43_radio_mask(dev, B2056_SYN_PLL_MAST2, ~0xFC);
+	b43_radio_mask(dev, B2056_SYN_RCCAL_CTRL0, ~0x1);
+	if (dev->phy.do_full_init)
+		b43_radio_2056_rcal(dev);
+}
+
+/*
+ * Initialize a Broadcom 2056 N-radio
+ * http://bcm-v4.sipsolutions.net/802.11/Radio/2056/Init
+ */
+static void b43_radio_init2056(struct b43_wldev *dev)
+{
+	b43_radio_init2056_pre(dev);
+	b2056_upload_inittabs(dev, 0, 0);
+	b43_radio_init2056_post(dev);
+}
+
+/**************************************************
+ * Radio 0x2055
+ **************************************************/
+
+static void b43_chantab_radio_upload(struct b43_wldev *dev,
+				const struct b43_nphy_channeltab_entry_rev2 *e)
+{
+	b43_radio_write(dev, B2055_PLL_REF, e->radio_pll_ref);
+	b43_radio_write(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0);
+	b43_radio_write(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1);
+	b43_radio_write(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail);
+	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
+
+	b43_radio_write(dev, B2055_VCO_CAL1, e->radio_vco_cal1);
+	b43_radio_write(dev, B2055_VCO_CAL2, e->radio_vco_cal2);
+	b43_radio_write(dev, B2055_PLL_LFC1, e->radio_pll_lfc1);
+	b43_radio_write(dev, B2055_PLL_LFR1, e->radio_pll_lfr1);
+	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
+
+	b43_radio_write(dev, B2055_PLL_LFC2, e->radio_pll_lfc2);
+	b43_radio_write(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf);
+	b43_radio_write(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1);
+	b43_radio_write(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2);
+	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
+
+	b43_radio_write(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune);
+	b43_radio_write(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune);
+	b43_radio_write(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1);
+	b43_radio_write(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn);
+	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
+
+	b43_radio_write(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim);
+	b43_radio_write(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune);
+	b43_radio_write(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune);
+	b43_radio_write(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1);
+	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
+
+	b43_radio_write(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn);
+	b43_radio_write(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */
+static void b43_radio_2055_setup(struct b43_wldev *dev,
+				const struct b43_nphy_channeltab_entry_rev2 *e)
+{
+	B43_WARN_ON(dev->phy.rev >= 3);
+
+	b43_chantab_radio_upload(dev, e);
+	udelay(50);
+	b43_radio_write(dev, B2055_VCO_CAL10, 0x05);
+	b43_radio_write(dev, B2055_VCO_CAL10, 0x45);
+	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
+	b43_radio_write(dev, B2055_VCO_CAL10, 0x65);
+	udelay(300);
+}
+
+static void b43_radio_init2055_pre(struct b43_wldev *dev)
+{
+	b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
+		     ~B43_NPHY_RFCTL_CMD_PORFORCE);
+	b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
+		    B43_NPHY_RFCTL_CMD_CHIP0PU |
+		    B43_NPHY_RFCTL_CMD_OEPORFORCE);
+	b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
+		    B43_NPHY_RFCTL_CMD_PORFORCE);
+}
+
+static void b43_radio_init2055_post(struct b43_wldev *dev)
+{
+	struct b43_phy_n *nphy = dev->phy.n;
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+	bool workaround = false;
+
+	if (sprom->revision < 4)
+		workaround = (dev->dev->board_vendor != PCI_VENDOR_ID_BROADCOM
+			      && dev->dev->board_type == SSB_BOARD_CB2_4321
+			      && dev->dev->board_rev >= 0x41);
+	else
+		workaround =
+			!(sprom->boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS);
+
+	b43_radio_mask(dev, B2055_MASTER1, 0xFFF3);
+	if (workaround) {
+		b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F);
+		b43_radio_mask(dev, B2055_C2_RX_BB_REG, 0x7F);
+	}
+	b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0xFFC0, 0x2C);
+	b43_radio_write(dev, B2055_CAL_MISC, 0x3C);
+	b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE);
+	b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80);
+	b43_radio_set(dev, B2055_CAL_MISC, 0x1);
+	msleep(1);
+	b43_radio_set(dev, B2055_CAL_MISC, 0x40);
+	if (!b43_radio_wait_value(dev, B2055_CAL_COUT2, 0x80, 0x80, 10, 2000))
+		b43err(dev->wl, "radio post init timeout\n");
+	b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F);
+	b43_switch_channel(dev, dev->phy.channel);
+	b43_radio_write(dev, B2055_C1_RX_BB_LPF, 0x9);
+	b43_radio_write(dev, B2055_C2_RX_BB_LPF, 0x9);
+	b43_radio_write(dev, B2055_C1_RX_BB_MIDACHP, 0x83);
+	b43_radio_write(dev, B2055_C2_RX_BB_MIDACHP, 0x83);
+	b43_radio_maskset(dev, B2055_C1_LNA_GAINBST, 0xFFF8, 0x6);
+	b43_radio_maskset(dev, B2055_C2_LNA_GAINBST, 0xFFF8, 0x6);
+	if (!nphy->gain_boost) {
+		b43_radio_set(dev, B2055_C1_RX_RFSPC1, 0x2);
+		b43_radio_set(dev, B2055_C2_RX_RFSPC1, 0x2);
+	} else {
+		b43_radio_mask(dev, B2055_C1_RX_RFSPC1, 0xFFFD);
+		b43_radio_mask(dev, B2055_C2_RX_RFSPC1, 0xFFFD);
+	}
+	udelay(2);
+}
+
+/*
+ * Initialize a Broadcom 2055 N-radio
+ * http://bcm-v4.sipsolutions.net/802.11/Radio/2055/Init
+ */
+static void b43_radio_init2055(struct b43_wldev *dev)
+{
+	b43_radio_init2055_pre(dev);
+	if (b43_status(dev) < B43_STAT_INITIALIZED) {
+		/* Follow wl, not specs. Do not force uploading all regs */
+		b2055_upload_inittab(dev, 0, 0);
+	} else {
+		bool ghz5 = b43_current_band(dev->wl) == NL80211_BAND_5GHZ;
+		b2055_upload_inittab(dev, ghz5, 0);
+	}
+	b43_radio_init2055_post(dev);
+}
+
+/**************************************************
+ * Samples
+ **************************************************/
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/LoadSampleTable */
+static int b43_nphy_load_samples(struct b43_wldev *dev,
+					struct b43_c32 *samples, u16 len) {
+	struct b43_phy_n *nphy = dev->phy.n;
+	u16 i;
+	u32 *data;
+
+	data = kcalloc(len, sizeof(u32), GFP_KERNEL);
+	if (!data) {
+		b43err(dev->wl, "allocation for samples loading failed\n");
+		return -ENOMEM;
+	}
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, 1);
+
+	for (i = 0; i < len; i++) {
+		data[i] = (samples[i].i & 0x3FF << 10);
+		data[i] |= samples[i].q & 0x3FF;
+	}
+	b43_ntab_write_bulk(dev, B43_NTAB32(17, 0), len, data);
+
+	kfree(data);
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, 0);
+	return 0;
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GenLoadSamples */
+static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max,
+					bool test)
+{
+	int i;
+	u16 bw, len, rot, angle;
+	struct b43_c32 *samples;
+
+	bw = b43_is_40mhz(dev) ? 40 : 20;
+	len = bw << 3;
+
+	if (test) {
+		if (b43_phy_read(dev, B43_NPHY_BBCFG) & B43_NPHY_BBCFG_RSTRX)
+			bw = 82;
+		else
+			bw = 80;
+
+		if (b43_is_40mhz(dev))
+			bw <<= 1;
+
+		len = bw << 1;
+	}
+
+	samples = kcalloc(len, sizeof(struct b43_c32), GFP_KERNEL);
+	if (!samples) {
+		b43err(dev->wl, "allocation for samples generation failed\n");
+		return 0;
+	}
+	rot = (((freq * 36) / bw) << 16) / 100;
+	angle = 0;
+
+	for (i = 0; i < len; i++) {
+		samples[i] = b43_cordic(angle);
+		angle += rot;
+		samples[i].q = CORDIC_CONVERT(samples[i].q * max);
+		samples[i].i = CORDIC_CONVERT(samples[i].i * max);
+	}
+
+	i = b43_nphy_load_samples(dev, samples, len);
+	kfree(samples);
+	return (i < 0) ? 0 : len;
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */
+static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops,
+				 u16 wait, bool iqmode, bool dac_test,
+				 bool modify_bbmult)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = dev->phy.n;
+	int i;
+	u16 seq_mode;
+	u32 tmp;
+
+	b43_nphy_stay_in_carrier_search(dev, true);
+
+	if (phy->rev >= 7) {
+		bool lpf_bw3, lpf_bw4;
+
+		lpf_bw3 = b43_phy_read(dev, B43_NPHY_REV7_RF_CTL_OVER3) & 0x80;
+		lpf_bw4 = b43_phy_read(dev, B43_NPHY_REV7_RF_CTL_OVER4) & 0x80;
+
+		if (lpf_bw3 || lpf_bw4) {
+			/* TODO */
+		} else {
+			u16 value = b43_nphy_read_lpf_ctl(dev, 0);
+			if (phy->rev >= 19)
+				b43_nphy_rf_ctl_override_rev19(dev, 0x80, value,
+							       0, false, 1);
+			else
+				b43_nphy_rf_ctl_override_rev7(dev, 0x80, value,
+							      0, false, 1);
+			nphy->lpf_bw_overrode_for_sample_play = true;
+		}
+	}
+
+	if ((nphy->bb_mult_save & 0x80000000) == 0) {
+		tmp = b43_ntab_read(dev, B43_NTAB16(15, 87));
+		nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000;
+	}
+
+	if (modify_bbmult) {
+		tmp = !b43_is_40mhz(dev) ? 0x6464 : 0x4747;
+		b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
+	}
+
+	b43_phy_write(dev, B43_NPHY_SAMP_DEPCNT, (samps - 1));
+
+	if (loops != 0xFFFF)
+		b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, (loops - 1));
+	else
+		b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, loops);
+
+	b43_phy_write(dev, B43_NPHY_SAMP_WAITCNT, wait);
+
+	seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);
+
+	b43_phy_set(dev, B43_NPHY_RFSEQMODE, B43_NPHY_RFSEQMODE_CAOVER);
+	if (iqmode) {
+		b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
+		b43_phy_set(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8000);
+	} else {
+		tmp = dac_test ? 5 : 1;
+		b43_phy_write(dev, B43_NPHY_SAMP_CMD, tmp);
+	}
+	for (i = 0; i < 100; i++) {
+		if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & 1)) {
+			i = 0;
+			break;
+		}
+		udelay(10);
+	}
+	if (i)
+		b43err(dev->wl, "run samples timeout\n");
+
+	b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
+
+	b43_nphy_stay_in_carrier_search(dev, false);
+}
+
+/**************************************************
+ * RSSI
+ **************************************************/
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */
+static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale,
+					s8 offset, u8 core,
+					enum n_rail_type rail,
+					enum n_rssi_type rssi_type)
+{
+	u16 tmp;
+	bool core1or5 = (core == 1) || (core == 5);
+	bool core2or5 = (core == 2) || (core == 5);
+
+	offset = clamp_val(offset, -32, 31);
+	tmp = ((scale & 0x3F) << 8) | (offset & 0x3F);
+
+	switch (rssi_type) {
+	case N_RSSI_NB:
+		if (core1or5 && rail == N_RAIL_I)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp);
+		if (core1or5 && rail == N_RAIL_Q)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp);
+		if (core2or5 && rail == N_RAIL_I)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp);
+		if (core2or5 && rail == N_RAIL_Q)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp);
+		break;
+	case N_RSSI_W1:
+		if (core1or5 && rail == N_RAIL_I)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp);
+		if (core1or5 && rail == N_RAIL_Q)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp);
+		if (core2or5 && rail == N_RAIL_I)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp);
+		if (core2or5 && rail == N_RAIL_Q)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp);
+		break;
+	case N_RSSI_W2:
+		if (core1or5 && rail == N_RAIL_I)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp);
+		if (core1or5 && rail == N_RAIL_Q)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp);
+		if (core2or5 && rail == N_RAIL_I)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp);
+		if (core2or5 && rail == N_RAIL_Q)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp);
+		break;
+	case N_RSSI_TBD:
+		if (core1or5 && rail == N_RAIL_I)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp);
+		if (core1or5 && rail == N_RAIL_Q)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp);
+		if (core2or5 && rail == N_RAIL_I)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp);
+		if (core2or5 && rail == N_RAIL_Q)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp);
+		break;
+	case N_RSSI_IQ:
+		if (core1or5 && rail == N_RAIL_I)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp);
+		if (core1or5 && rail == N_RAIL_Q)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp);
+		if (core2or5 && rail == N_RAIL_I)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp);
+		if (core2or5 && rail == N_RAIL_Q)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp);
+		break;
+	case N_RSSI_TSSI_2G:
+		if (core1or5)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp);
+		if (core2or5)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp);
+		break;
+	case N_RSSI_TSSI_5G:
+		if (core1or5)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp);
+		if (core2or5)
+			b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp);
+		break;
+	}
+}
+
+static void b43_nphy_rssi_select_rev19(struct b43_wldev *dev, u8 code,
+				       enum n_rssi_type rssi_type)
+{
+	/* TODO */
+}
+
+static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code,
+				      enum n_rssi_type rssi_type)
+{
+	u8 i;
+	u16 reg, val;
+
+	if (code == 0) {
+		b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, 0xFDFF);
+		b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, 0xFDFF);
+		b43_phy_mask(dev, B43_NPHY_AFECTL_C1, 0xFCFF);
+		b43_phy_mask(dev, B43_NPHY_AFECTL_C2, 0xFCFF);
+		b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S0, 0xFFDF);
+		b43_phy_mask(dev, B43_NPHY_TXF_40CO_B32S1, 0xFFDF);
+		b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0xFFC3);
+		b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0xFFC3);
+	} else {
+		for (i = 0; i < 2; i++) {
+			if ((code == 1 && i == 1) || (code == 2 && !i))
+				continue;
+
+			reg = (i == 0) ?
+				B43_NPHY_AFECTL_OVER1 : B43_NPHY_AFECTL_OVER;
+			b43_phy_maskset(dev, reg, 0xFDFF, 0x0200);
+
+			if (rssi_type == N_RSSI_W1 ||
+			    rssi_type == N_RSSI_W2 ||
+			    rssi_type == N_RSSI_NB) {
+				reg = (i == 0) ?
+					B43_NPHY_AFECTL_C1 :
+					B43_NPHY_AFECTL_C2;
+				b43_phy_maskset(dev, reg, 0xFCFF, 0);
+
+				reg = (i == 0) ?
+					B43_NPHY_RFCTL_LUT_TRSW_UP1 :
+					B43_NPHY_RFCTL_LUT_TRSW_UP2;
+				b43_phy_maskset(dev, reg, 0xFFC3, 0);
+
+				if (rssi_type == N_RSSI_W1)
+					val = (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ? 4 : 8;
+				else if (rssi_type == N_RSSI_W2)
+					val = 16;
+				else
+					val = 32;
+				b43_phy_set(dev, reg, val);
+
+				reg = (i == 0) ?
+					B43_NPHY_TXF_40CO_B1S0 :
+					B43_NPHY_TXF_40CO_B32S1;
+				b43_phy_set(dev, reg, 0x0020);
+			} else {
+				if (rssi_type == N_RSSI_TBD)
+					val = 0x0100;
+				else if (rssi_type == N_RSSI_IQ)
+					val = 0x0200;
+				else
+					val = 0x0300;
+
+				reg = (i == 0) ?
+					B43_NPHY_AFECTL_C1 :
+					B43_NPHY_AFECTL_C2;
+
+				b43_phy_maskset(dev, reg, 0xFCFF, val);
+				b43_phy_maskset(dev, reg, 0xF3FF, val << 2);
+
+				if (rssi_type != N_RSSI_IQ &&
+				    rssi_type != N_RSSI_TBD) {
+					enum nl80211_band band =
+						b43_current_band(dev->wl);
+
+					if (dev->phy.rev < 7) {
+						if (b43_nphy_ipa(dev))
+							val = (band == NL80211_BAND_5GHZ) ? 0xC : 0xE;
+						else
+							val = 0x11;
+						reg = (i == 0) ? B2056_TX0 : B2056_TX1;
+						reg |= B2056_TX_TX_SSI_MUX;
+						b43_radio_write(dev, reg, val);
+					}
+
+					reg = (i == 0) ?
+						B43_NPHY_AFECTL_OVER1 :
+						B43_NPHY_AFECTL_OVER;
+					b43_phy_set(dev, reg, 0x0200);
+				}
+			}
+		}
+	}
+}
+
+static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code,
+				      enum n_rssi_type rssi_type)
+{
+	u16 val;
+	bool rssi_w1_w2_nb = false;
+
+	switch (rssi_type) {
+	case N_RSSI_W1:
+	case N_RSSI_W2:
+	case N_RSSI_NB:
+		val = 0;
+		rssi_w1_w2_nb = true;
+		break;
+	case N_RSSI_TBD:
+		val = 1;
+		break;
+	case N_RSSI_IQ:
+		val = 2;
+		break;
+	default:
+		val = 3;
+	}
+
+	val = (val << 12) | (val << 14);
+	b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val);
+	b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val);
+
+	if (rssi_w1_w2_nb) {
+		b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF,
+				(rssi_type + 1) << 4);
+		b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF,
+				(rssi_type + 1) << 4);
+	}
+
+	if (code == 0) {
+		b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x3000);
+		if (rssi_w1_w2_nb) {
+			b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
+				~(B43_NPHY_RFCTL_CMD_RXEN |
+				  B43_NPHY_RFCTL_CMD_CORESEL));
+			b43_phy_mask(dev, B43_NPHY_RFCTL_OVER,
+				~(0x1 << 12 |
+				  0x1 << 5 |
+				  0x1 << 1 |
+				  0x1));
+			b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
+				~B43_NPHY_RFCTL_CMD_START);
+			udelay(20);
+			b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1);
+		}
+	} else {
+		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x3000);
+		if (rssi_w1_w2_nb) {
+			b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
+				~(B43_NPHY_RFCTL_CMD_RXEN |
+				  B43_NPHY_RFCTL_CMD_CORESEL),
+				(B43_NPHY_RFCTL_CMD_RXEN |
+				 code << B43_NPHY_RFCTL_CMD_CORESEL_SHIFT));
+			b43_phy_set(dev, B43_NPHY_RFCTL_OVER,
+				(0x1 << 12 |
+				  0x1 << 5 |
+				  0x1 << 1 |
+				  0x1));
+			b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
+				B43_NPHY_RFCTL_CMD_START);
+			udelay(20);
+			b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1);
+		}
+	}
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */
+static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code,
+				 enum n_rssi_type type)
+{
+	if (dev->phy.rev >= 19)
+		b43_nphy_rssi_select_rev19(dev, code, type);
+	else if (dev->phy.rev >= 3)
+		b43_nphy_rev3_rssi_select(dev, code, type);
+	else
+		b43_nphy_rev2_rssi_select(dev, code, type);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */
+static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev,
+				       enum n_rssi_type rssi_type, u8 *buf)
+{
+	int i;
+	for (i = 0; i < 2; i++) {
+		if (rssi_type == N_RSSI_NB) {
+			if (i == 0) {
+				b43_radio_maskset(dev, B2055_C1_B0NB_RSSIVCM,
+						  0xFC, buf[0]);
+				b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
+						  0xFC, buf[1]);
+			} else {
+				b43_radio_maskset(dev, B2055_C2_B0NB_RSSIVCM,
+						  0xFC, buf[2 * i]);
+				b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
+						  0xFC, buf[2 * i + 1]);
+			}
+		} else {
+			if (i == 0)
+				b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
+						  0xF3, buf[0] << 2);
+			else
+				b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
+						  0xF3, buf[2 * i + 1] << 2);
+		}
+	}
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */
+static int b43_nphy_poll_rssi(struct b43_wldev *dev, enum n_rssi_type rssi_type,
+			      s32 *buf, u8 nsamp)
+{
+	int i;
+	int out;
+	u16 save_regs_phy[9];
+	u16 s[2];
+
+	/* TODO: rev7+ is treated like rev3+, what about rev19+? */
+
+	if (dev->phy.rev >= 3) {
+		save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
+		save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
+		save_regs_phy[2] = b43_phy_read(dev,
+						B43_NPHY_RFCTL_LUT_TRSW_UP1);
+		save_regs_phy[3] = b43_phy_read(dev,
+						B43_NPHY_RFCTL_LUT_TRSW_UP2);
+		save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
+		save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
+		save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0);
+		save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1);
+		save_regs_phy[8] = 0;
+	} else {
+		save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
+		save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
+		save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
+		save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_RFCTL_CMD);
+		save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER);
+		save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1);
+		save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2);
+		save_regs_phy[7] = 0;
+		save_regs_phy[8] = 0;
+	}
+
+	b43_nphy_rssi_select(dev, 5, rssi_type);
+
+	if (dev->phy.rev < 2) {
+		save_regs_phy[8] = b43_phy_read(dev, B43_NPHY_GPIO_SEL);
+		b43_phy_write(dev, B43_NPHY_GPIO_SEL, 5);
+	}
+
+	for (i = 0; i < 4; i++)
+		buf[i] = 0;
+
+	for (i = 0; i < nsamp; i++) {
+		if (dev->phy.rev < 2) {
+			s[0] = b43_phy_read(dev, B43_NPHY_GPIO_LOOUT);
+			s[1] = b43_phy_read(dev, B43_NPHY_GPIO_HIOUT);
+		} else {
+			s[0] = b43_phy_read(dev, B43_NPHY_RSSI1);
+			s[1] = b43_phy_read(dev, B43_NPHY_RSSI2);
+		}
+
+		buf[0] += ((s8)((s[0] & 0x3F) << 2)) >> 2;
+		buf[1] += ((s8)(((s[0] >> 8) & 0x3F) << 2)) >> 2;
+		buf[2] += ((s8)((s[1] & 0x3F) << 2)) >> 2;
+		buf[3] += ((s8)(((s[1] >> 8) & 0x3F) << 2)) >> 2;
+	}
+	out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 |
+		(buf[2] & 0xFF) << 8 | (buf[3] & 0xFF);
+
+	if (dev->phy.rev < 2)
+		b43_phy_write(dev, B43_NPHY_GPIO_SEL, save_regs_phy[8]);
+
+	if (dev->phy.rev >= 3) {
+		b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]);
+		b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]);
+		b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1,
+				save_regs_phy[2]);
+		b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2,
+				save_regs_phy[3]);
+		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, save_regs_phy[4]);
+		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]);
+		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]);
+		b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]);
+	} else {
+		b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]);
+		b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]);
+		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[2]);
+		b43_phy_write(dev, B43_NPHY_RFCTL_CMD, save_regs_phy[3]);
+		b43_phy_write(dev, B43_NPHY_RFCTL_OVER, save_regs_phy[4]);
+		b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, save_regs_phy[5]);
+		b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, save_regs_phy[6]);
+	}
+
+	return out;
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */
+static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = dev->phy.n;
+
+	u16 saved_regs_phy_rfctl[2];
+	u16 saved_regs_phy[22];
+	u16 regs_to_store_rev3[] = {
+		B43_NPHY_AFECTL_OVER1, B43_NPHY_AFECTL_OVER,
+		B43_NPHY_AFECTL_C1, B43_NPHY_AFECTL_C2,
+		B43_NPHY_TXF_40CO_B1S1, B43_NPHY_RFCTL_OVER,
+		B43_NPHY_TXF_40CO_B1S0, B43_NPHY_TXF_40CO_B32S1,
+		B43_NPHY_RFCTL_CMD,
+		B43_NPHY_RFCTL_LUT_TRSW_UP1, B43_NPHY_RFCTL_LUT_TRSW_UP2,
+		B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2
+	};
+	u16 regs_to_store_rev7[] = {
+		B43_NPHY_AFECTL_OVER1, B43_NPHY_AFECTL_OVER,
+		B43_NPHY_AFECTL_C1, B43_NPHY_AFECTL_C2,
+		B43_NPHY_TXF_40CO_B1S1, B43_NPHY_RFCTL_OVER,
+		B43_NPHY_REV7_RF_CTL_OVER3, B43_NPHY_REV7_RF_CTL_OVER4,
+		B43_NPHY_REV7_RF_CTL_OVER5, B43_NPHY_REV7_RF_CTL_OVER6,
+		0x2ff,
+		B43_NPHY_TXF_40CO_B1S0, B43_NPHY_TXF_40CO_B32S1,
+		B43_NPHY_RFCTL_CMD,
+		B43_NPHY_RFCTL_LUT_TRSW_UP1, B43_NPHY_RFCTL_LUT_TRSW_UP2,
+		B43_NPHY_REV7_RF_CTL_MISC_REG3, B43_NPHY_REV7_RF_CTL_MISC_REG4,
+		B43_NPHY_REV7_RF_CTL_MISC_REG5, B43_NPHY_REV7_RF_CTL_MISC_REG6,
+		B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2
+	};
+	u16 *regs_to_store;
+	int regs_amount;
+
+	u16 class;
+
+	u16 clip_state[2];
+	u16 clip_off[2] = { 0xFFFF, 0xFFFF };
+
+	u8 vcm_final = 0;
+	s32 offset[4];
+	s32 results[8][4] = { };
+	s32 results_min[4] = { };
+	s32 poll_results[4] = { };
+
+	u16 *rssical_radio_regs = NULL;
+	u16 *rssical_phy_regs = NULL;
+
+	u16 r; /* routing */
+	u8 rx_core_state;
+	int core, i, j, vcm;
+
+	if (dev->phy.rev >= 7) {
+		regs_to_store = regs_to_store_rev7;
+		regs_amount = ARRAY_SIZE(regs_to_store_rev7);
+	} else {
+		regs_to_store = regs_to_store_rev3;
+		regs_amount = ARRAY_SIZE(regs_to_store_rev3);
+	}
+	BUG_ON(regs_amount > ARRAY_SIZE(saved_regs_phy));
+
+	class = b43_nphy_classifier(dev, 0, 0);
+	b43_nphy_classifier(dev, 7, 4);
+	b43_nphy_read_clip_detection(dev, clip_state);
+	b43_nphy_write_clip_detection(dev, clip_off);
+
+	saved_regs_phy_rfctl[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
+	saved_regs_phy_rfctl[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
+	for (i = 0; i < regs_amount; i++)
+		saved_regs_phy[i] = b43_phy_read(dev, regs_to_store[i]);
+
+	b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_OFF, 0, 7);
+	b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 1, 7);
+
+	if (dev->phy.rev >= 7) {
+		b43_nphy_rf_ctl_override_one_to_many(dev,
+						     N_RF_CTL_OVER_CMD_RXRF_PU,
+						     0, 0, false);
+		b43_nphy_rf_ctl_override_one_to_many(dev,
+						     N_RF_CTL_OVER_CMD_RX_PU,
+						     1, 0, false);
+		b43_nphy_rf_ctl_override_rev7(dev, 0x80, 1, 0, false, 0);
+		b43_nphy_rf_ctl_override_rev7(dev, 0x40, 1, 0, false, 0);
+		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
+			b43_nphy_rf_ctl_override_rev7(dev, 0x20, 0, 0, false,
+						      0);
+			b43_nphy_rf_ctl_override_rev7(dev, 0x10, 1, 0, false,
+						      0);
+		} else {
+			b43_nphy_rf_ctl_override_rev7(dev, 0x10, 0, 0, false,
+						      0);
+			b43_nphy_rf_ctl_override_rev7(dev, 0x20, 1, 0, false,
+						      0);
+		}
+	} else {
+		b43_nphy_rf_ctl_override(dev, 0x1, 0, 0, false);
+		b43_nphy_rf_ctl_override(dev, 0x2, 1, 0, false);
+		b43_nphy_rf_ctl_override(dev, 0x80, 1, 0, false);
+		b43_nphy_rf_ctl_override(dev, 0x40, 1, 0, false);
+		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
+			b43_nphy_rf_ctl_override(dev, 0x20, 0, 0, false);
+			b43_nphy_rf_ctl_override(dev, 0x10, 1, 0, false);
+		} else {
+			b43_nphy_rf_ctl_override(dev, 0x10, 0, 0, false);
+			b43_nphy_rf_ctl_override(dev, 0x20, 1, 0, false);
+		}
+	}
+
+	rx_core_state = b43_nphy_get_rx_core_state(dev);
+	for (core = 0; core < 2; core++) {
+		if (!(rx_core_state & (1 << core)))
+			continue;
+		r = core ? B2056_RX1 : B2056_RX0;
+		b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, N_RAIL_I,
+					   N_RSSI_NB);
+		b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, N_RAIL_Q,
+					   N_RSSI_NB);
+
+		/* Grab RSSI results for every possible VCM */
+		for (vcm = 0; vcm < 8; vcm++) {
+			if (dev->phy.rev >= 7)
+				b43_radio_maskset(dev,
+						  core ? R2057_NB_MASTER_CORE1 :
+							 R2057_NB_MASTER_CORE0,
+						  ~R2057_VCM_MASK, vcm);
+			else
+				b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC,
+						  0xE3, vcm << 2);
+			b43_nphy_poll_rssi(dev, N_RSSI_NB, results[vcm], 8);
+		}
+
+		/* Find out which VCM got the best results */
+		for (i = 0; i < 4; i += 2) {
+			s32 currd;
+			s32 mind = 0x100000;
+			s32 minpoll = 249;
+			u8 minvcm = 0;
+			if (2 * core != i)
+				continue;
+			for (vcm = 0; vcm < 8; vcm++) {
+				currd = results[vcm][i] * results[vcm][i] +
+					results[vcm][i + 1] * results[vcm][i];
+				if (currd < mind) {
+					mind = currd;
+					minvcm = vcm;
+				}
+				if (results[vcm][i] < minpoll)
+					minpoll = results[vcm][i];
+			}
+			vcm_final = minvcm;
+			results_min[i] = minpoll;
+		}
+
+		/* Select the best VCM */
+		if (dev->phy.rev >= 7)
+			b43_radio_maskset(dev,
+					  core ? R2057_NB_MASTER_CORE1 :
+						 R2057_NB_MASTER_CORE0,
+					  ~R2057_VCM_MASK, vcm);
+		else
+			b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC,
+					  0xE3, vcm_final << 2);
+
+		for (i = 0; i < 4; i++) {
+			if (core != i / 2)
+				continue;
+			offset[i] = -results[vcm_final][i];
+			if (offset[i] < 0)
+				offset[i] = -((abs(offset[i]) + 4) / 8);
+			else
+				offset[i] = (offset[i] + 4) / 8;
+			if (results_min[i] == 248)
+				offset[i] = -32;
+			b43_nphy_scale_offset_rssi(dev, 0, offset[i],
+						   (i / 2 == 0) ? 1 : 2,
+						   (i % 2 == 0) ? N_RAIL_I : N_RAIL_Q,
+						   N_RSSI_NB);
+		}
+	}
+
+	for (core = 0; core < 2; core++) {
+		if (!(rx_core_state & (1 << core)))
+			continue;
+		for (i = 0; i < 2; i++) {
+			b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1,
+						   N_RAIL_I, i);
+			b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1,
+						   N_RAIL_Q, i);
+			b43_nphy_poll_rssi(dev, i, poll_results, 8);
+			for (j = 0; j < 4; j++) {
+				if (j / 2 == core) {
+					offset[j] = 232 - poll_results[j];
+					if (offset[j] < 0)
+						offset[j] = -(abs(offset[j] + 4) / 8);
+					else
+						offset[j] = (offset[j] + 4) / 8;
+					b43_nphy_scale_offset_rssi(dev, 0,
+						offset[2 * core], core + 1, j % 2, i);
+				}
+			}
+		}
+	}
+
+	b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, saved_regs_phy_rfctl[0]);
+	b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, saved_regs_phy_rfctl[1]);
+
+	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
+
+	b43_phy_set(dev, B43_NPHY_TXF_40CO_B1S1, 0x1);
+	b43_phy_set(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_START);
+	b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S1, ~0x1);
+
+	b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x1);
+	b43_phy_set(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_RXTX);
+	b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1);
+
+	for (i = 0; i < regs_amount; i++)
+		b43_phy_write(dev, regs_to_store[i], saved_regs_phy[i]);
+
+	/* Store for future configuration */
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+		rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G;
+		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G;
+	} else {
+		rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G;
+		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
+	}
+	if (dev->phy.rev >= 7) {
+		rssical_radio_regs[0] = b43_radio_read(dev,
+						       R2057_NB_MASTER_CORE0);
+		rssical_radio_regs[1] = b43_radio_read(dev,
+						       R2057_NB_MASTER_CORE1);
+	} else {
+		rssical_radio_regs[0] = b43_radio_read(dev, B2056_RX0 |
+						       B2056_RX_RSSI_MISC);
+		rssical_radio_regs[1] = b43_radio_read(dev, B2056_RX1 |
+						       B2056_RX_RSSI_MISC);
+	}
+	rssical_phy_regs[0] = b43_phy_read(dev, B43_NPHY_RSSIMC_0I_RSSI_Z);
+	rssical_phy_regs[1] = b43_phy_read(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z);
+	rssical_phy_regs[2] = b43_phy_read(dev, B43_NPHY_RSSIMC_1I_RSSI_Z);
+	rssical_phy_regs[3] = b43_phy_read(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z);
+	rssical_phy_regs[4] = b43_phy_read(dev, B43_NPHY_RSSIMC_0I_RSSI_X);
+	rssical_phy_regs[5] = b43_phy_read(dev, B43_NPHY_RSSIMC_0Q_RSSI_X);
+	rssical_phy_regs[6] = b43_phy_read(dev, B43_NPHY_RSSIMC_1I_RSSI_X);
+	rssical_phy_regs[7] = b43_phy_read(dev, B43_NPHY_RSSIMC_1Q_RSSI_X);
+	rssical_phy_regs[8] = b43_phy_read(dev, B43_NPHY_RSSIMC_0I_RSSI_Y);
+	rssical_phy_regs[9] = b43_phy_read(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y);
+	rssical_phy_regs[10] = b43_phy_read(dev, B43_NPHY_RSSIMC_1I_RSSI_Y);
+	rssical_phy_regs[11] = b43_phy_read(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y);
+
+	/* Remember for which channel we store configuration */
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+		nphy->rssical_chanspec_2G.center_freq = phy->chandef->chan->center_freq;
+	else
+		nphy->rssical_chanspec_5G.center_freq = phy->chandef->chan->center_freq;
+
+	/* End of calibration, restore configuration */
+	b43_nphy_classifier(dev, 7, class);
+	b43_nphy_write_clip_detection(dev, clip_state);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */
+static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, enum n_rssi_type type)
+{
+	int i, j, vcm;
+	u8 state[4];
+	u8 code, val;
+	u16 class, override;
+	u8 regs_save_radio[2];
+	u16 regs_save_phy[2];
+
+	s32 offset[4];
+	u8 core;
+	u8 rail;
+
+	u16 clip_state[2];
+	u16 clip_off[2] = { 0xFFFF, 0xFFFF };
+	s32 results_min[4] = { };
+	u8 vcm_final[4] = { };
+	s32 results[4][4] = { };
+	s32 miniq[4][2] = { };
+
+	if (type == N_RSSI_NB) {
+		code = 0;
+		val = 6;
+	} else if (type == N_RSSI_W1 || type == N_RSSI_W2) {
+		code = 25;
+		val = 4;
+	} else {
+		B43_WARN_ON(1);
+		return;
+	}
+
+	class = b43_nphy_classifier(dev, 0, 0);
+	b43_nphy_classifier(dev, 7, 4);
+	b43_nphy_read_clip_detection(dev, clip_state);
+	b43_nphy_write_clip_detection(dev, clip_off);
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
+		override = 0x140;
+	else
+		override = 0x110;
+
+	regs_save_phy[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
+	regs_save_radio[0] = b43_radio_read(dev, B2055_C1_PD_RXTX);
+	b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, override);
+	b43_radio_write(dev, B2055_C1_PD_RXTX, val);
+
+	regs_save_phy[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
+	regs_save_radio[1] = b43_radio_read(dev, B2055_C2_PD_RXTX);
+	b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, override);
+	b43_radio_write(dev, B2055_C2_PD_RXTX, val);
+
+	state[0] = b43_radio_read(dev, B2055_C1_PD_RSSIMISC) & 0x07;
+	state[1] = b43_radio_read(dev, B2055_C2_PD_RSSIMISC) & 0x07;
+	b43_radio_mask(dev, B2055_C1_PD_RSSIMISC, 0xF8);
+	b43_radio_mask(dev, B2055_C2_PD_RSSIMISC, 0xF8);
+	state[2] = b43_radio_read(dev, B2055_C1_SP_RSSI) & 0x07;
+	state[3] = b43_radio_read(dev, B2055_C2_SP_RSSI) & 0x07;
+
+	b43_nphy_rssi_select(dev, 5, type);
+	b43_nphy_scale_offset_rssi(dev, 0, 0, 5, N_RAIL_I, type);
+	b43_nphy_scale_offset_rssi(dev, 0, 0, 5, N_RAIL_Q, type);
+
+	for (vcm = 0; vcm < 4; vcm++) {
+		u8 tmp[4];
+		for (j = 0; j < 4; j++)
+			tmp[j] = vcm;
+		if (type != N_RSSI_W2)
+			b43_nphy_set_rssi_2055_vcm(dev, type, tmp);
+		b43_nphy_poll_rssi(dev, type, results[vcm], 8);
+		if (type == N_RSSI_W1 || type == N_RSSI_W2)
+			for (j = 0; j < 2; j++)
+				miniq[vcm][j] = min(results[vcm][2 * j],
+						    results[vcm][2 * j + 1]);
+	}
+
+	for (i = 0; i < 4; i++) {
+		s32 mind = 0x100000;
+		u8 minvcm = 0;
+		s32 minpoll = 249;
+		s32 currd;
+		for (vcm = 0; vcm < 4; vcm++) {
+			if (type == N_RSSI_NB)
+				currd = abs(results[vcm][i] - code * 8);
+			else
+				currd = abs(miniq[vcm][i / 2] - code * 8);
+
+			if (currd < mind) {
+				mind = currd;
+				minvcm = vcm;
+			}
+
+			if (results[vcm][i] < minpoll)
+				minpoll = results[vcm][i];
+		}
+		results_min[i] = minpoll;
+		vcm_final[i] = minvcm;
+	}
+
+	if (type != N_RSSI_W2)
+		b43_nphy_set_rssi_2055_vcm(dev, type, vcm_final);
+
+	for (i = 0; i < 4; i++) {
+		offset[i] = (code * 8) - results[vcm_final[i]][i];
+
+		if (offset[i] < 0)
+			offset[i] = -((abs(offset[i]) + 4) / 8);
+		else
+			offset[i] = (offset[i] + 4) / 8;
+
+		if (results_min[i] == 248)
+			offset[i] = code - 32;
+
+		core = (i / 2) ? 2 : 1;
+		rail = (i % 2) ? N_RAIL_Q : N_RAIL_I;
+
+		b43_nphy_scale_offset_rssi(dev, 0, offset[i], core, rail,
+						type);
+	}
+
+	b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[0]);
+	b43_radio_maskset(dev, B2055_C2_PD_RSSIMISC, 0xF8, state[1]);
+
+	switch (state[2]) {
+	case 1:
+		b43_nphy_rssi_select(dev, 1, N_RSSI_NB);
+		break;
+	case 4:
+		b43_nphy_rssi_select(dev, 1, N_RSSI_W1);
+		break;
+	case 2:
+		b43_nphy_rssi_select(dev, 1, N_RSSI_W2);
+		break;
+	default:
+		b43_nphy_rssi_select(dev, 1, N_RSSI_W2);
+		break;
+	}
+
+	switch (state[3]) {
+	case 1:
+		b43_nphy_rssi_select(dev, 2, N_RSSI_NB);
+		break;
+	case 4:
+		b43_nphy_rssi_select(dev, 2, N_RSSI_W1);
+		break;
+	default:
+		b43_nphy_rssi_select(dev, 2, N_RSSI_W2);
+		break;
+	}
+
+	b43_nphy_rssi_select(dev, 0, type);
+
+	b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs_save_phy[0]);
+	b43_radio_write(dev, B2055_C1_PD_RXTX, regs_save_radio[0]);
+	b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs_save_phy[1]);
+	b43_radio_write(dev, B2055_C2_PD_RXTX, regs_save_radio[1]);
+
+	b43_nphy_classifier(dev, 7, class);
+	b43_nphy_write_clip_detection(dev, clip_state);
+	/* Specs don't say about reset here, but it makes wl and b43 dumps
+	   identical, it really seems wl performs this */
+	b43_nphy_reset_cca(dev);
+}
+
+/*
+ * RSSI Calibration
+ * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal
+ */
+static void b43_nphy_rssi_cal(struct b43_wldev *dev)
+{
+	if (dev->phy.rev >= 19) {
+		/* TODO */
+	} else if (dev->phy.rev >= 3) {
+		b43_nphy_rev3_rssi_cal(dev);
+	} else {
+		b43_nphy_rev2_rssi_cal(dev, N_RSSI_NB);
+		b43_nphy_rev2_rssi_cal(dev, N_RSSI_W1);
+		b43_nphy_rev2_rssi_cal(dev, N_RSSI_W2);
+	}
+}
+
+/**************************************************
+ * Workarounds
+ **************************************************/
+
+static void b43_nphy_gain_ctl_workarounds_rev19(struct b43_wldev *dev)
+{
+	/* TODO */
+}
+
+static void b43_nphy_gain_ctl_workarounds_rev7(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	switch (phy->rev) {
+	/* TODO */
+	}
+}
+
+static void b43_nphy_gain_ctl_workarounds_rev3(struct b43_wldev *dev)
+{
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+
+	bool ghz5;
+	bool ext_lna;
+	u16 rssi_gain;
+	struct nphy_gain_ctl_workaround_entry *e;
+	u8 lpf_gain[6] = { 0x00, 0x06, 0x0C, 0x12, 0x12, 0x12 };
+	u8 lpf_bits[6] = { 0, 1, 2, 3, 3, 3 };
+
+	/* Prepare values */
+	ghz5 = b43_phy_read(dev, B43_NPHY_BANDCTL)
+		& B43_NPHY_BANDCTL_5GHZ;
+	ext_lna = ghz5 ? sprom->boardflags_hi & B43_BFH_EXTLNA_5GHZ :
+		sprom->boardflags_lo & B43_BFL_EXTLNA;
+	e = b43_nphy_get_gain_ctl_workaround_ent(dev, ghz5, ext_lna);
+	if (ghz5 && dev->phy.rev >= 5)
+		rssi_gain = 0x90;
+	else
+		rssi_gain = 0x50;
+
+	b43_phy_set(dev, B43_NPHY_RXCTL, 0x0040);
+
+	/* Set Clip 2 detect */
+	b43_phy_set(dev, B43_NPHY_C1_CGAINI, B43_NPHY_C1_CGAINI_CL2DETECT);
+	b43_phy_set(dev, B43_NPHY_C2_CGAINI, B43_NPHY_C2_CGAINI_CL2DETECT);
+
+	b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAG1_IDAC,
+			0x17);
+	b43_radio_write(dev, B2056_RX1 | B2056_RX_BIASPOLE_LNAG1_IDAC,
+			0x17);
+	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG2_IDAC, 0xF0);
+	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG2_IDAC, 0xF0);
+	b43_radio_write(dev, B2056_RX0 | B2056_RX_RSSI_POLE, 0x00);
+	b43_radio_write(dev, B2056_RX1 | B2056_RX_RSSI_POLE, 0x00);
+	b43_radio_write(dev, B2056_RX0 | B2056_RX_RSSI_GAIN,
+			rssi_gain);
+	b43_radio_write(dev, B2056_RX1 | B2056_RX_RSSI_GAIN,
+			rssi_gain);
+	b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAA1_IDAC,
+			0x17);
+	b43_radio_write(dev, B2056_RX1 | B2056_RX_BIASPOLE_LNAA1_IDAC,
+			0x17);
+	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA2_IDAC, 0xFF);
+	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA2_IDAC, 0xFF);
+
+	b43_ntab_write_bulk(dev, B43_NTAB8(0, 8), 4, e->lna1_gain);
+	b43_ntab_write_bulk(dev, B43_NTAB8(1, 8), 4, e->lna1_gain);
+	b43_ntab_write_bulk(dev, B43_NTAB8(0, 16), 4, e->lna2_gain);
+	b43_ntab_write_bulk(dev, B43_NTAB8(1, 16), 4, e->lna2_gain);
+	b43_ntab_write_bulk(dev, B43_NTAB8(0, 32), 10, e->gain_db);
+	b43_ntab_write_bulk(dev, B43_NTAB8(1, 32), 10, e->gain_db);
+	b43_ntab_write_bulk(dev, B43_NTAB8(2, 32), 10, e->gain_bits);
+	b43_ntab_write_bulk(dev, B43_NTAB8(3, 32), 10, e->gain_bits);
+	b43_ntab_write_bulk(dev, B43_NTAB8(0, 0x40), 6, lpf_gain);
+	b43_ntab_write_bulk(dev, B43_NTAB8(1, 0x40), 6, lpf_gain);
+	b43_ntab_write_bulk(dev, B43_NTAB8(2, 0x40), 6, lpf_bits);
+	b43_ntab_write_bulk(dev, B43_NTAB8(3, 0x40), 6, lpf_bits);
+
+	b43_phy_write(dev, B43_NPHY_REV3_C1_INITGAIN_A, e->init_gain);
+	b43_phy_write(dev, B43_NPHY_REV3_C2_INITGAIN_A, e->init_gain);
+
+	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x106), 2,
+				e->rfseq_init);
+
+	b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_HIGAIN_A, e->cliphi_gain);
+	b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_HIGAIN_A, e->cliphi_gain);
+	b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_MEDGAIN_A, e->clipmd_gain);
+	b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_MEDGAIN_A, e->clipmd_gain);
+	b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_LOGAIN_A, e->cliplo_gain);
+	b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_LOGAIN_A, e->cliplo_gain);
+
+	b43_phy_maskset(dev, B43_NPHY_CRSMINPOWER0, 0xFF00, e->crsmin);
+	b43_phy_maskset(dev, B43_NPHY_CRSMINPOWERL0, 0xFF00, e->crsminl);
+	b43_phy_maskset(dev, B43_NPHY_CRSMINPOWERU0, 0xFF00, e->crsminu);
+	b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, e->nbclip);
+	b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, e->nbclip);
+	b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
+			~B43_NPHY_C1_CLIPWBTHRES_CLIP2, e->wlclip);
+	b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
+			~B43_NPHY_C2_CLIPWBTHRES_CLIP2, e->wlclip);
+	b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);
+}
+
+static void b43_nphy_gain_ctl_workarounds_rev1_2(struct b43_wldev *dev)
+{
+	struct b43_phy_n *nphy = dev->phy.n;
+
+	u8 i, j;
+	u8 code;
+	u16 tmp;
+	u8 rfseq_events[3] = { 6, 8, 7 };
+	u8 rfseq_delays[3] = { 10, 30, 1 };
+
+	/* Set Clip 2 detect */
+	b43_phy_set(dev, B43_NPHY_C1_CGAINI, B43_NPHY_C1_CGAINI_CL2DETECT);
+	b43_phy_set(dev, B43_NPHY_C2_CGAINI, B43_NPHY_C2_CGAINI_CL2DETECT);
+
+	/* Set narrowband clip threshold */
+	b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 0x84);
+	b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 0x84);
+
+	if (!b43_is_40mhz(dev)) {
+		/* Set dwell lengths */
+		b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 0x002B);
+		b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 0x002B);
+		b43_phy_write(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 0x0009);
+		b43_phy_write(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 0x0009);
+	}
+
+	/* Set wideband clip 2 threshold */
+	b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
+			~B43_NPHY_C1_CLIPWBTHRES_CLIP2, 21);
+	b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
+			~B43_NPHY_C2_CLIPWBTHRES_CLIP2, 21);
+
+	if (!b43_is_40mhz(dev)) {
+		b43_phy_maskset(dev, B43_NPHY_C1_CGAINI,
+			~B43_NPHY_C1_CGAINI_GAINBKOFF, 0x1);
+		b43_phy_maskset(dev, B43_NPHY_C2_CGAINI,
+			~B43_NPHY_C2_CGAINI_GAINBKOFF, 0x1);
+		b43_phy_maskset(dev, B43_NPHY_C1_CCK_CGAINI,
+			~B43_NPHY_C1_CCK_CGAINI_GAINBKOFF, 0x1);
+		b43_phy_maskset(dev, B43_NPHY_C2_CCK_CGAINI,
+			~B43_NPHY_C2_CCK_CGAINI_GAINBKOFF, 0x1);
+	}
+
+	b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);
+
+	if (nphy->gain_boost) {
+		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ &&
+		    b43_is_40mhz(dev))
+			code = 4;
+		else
+			code = 5;
+	} else {
+		code = b43_is_40mhz(dev) ? 6 : 7;
+	}
+
+	/* Set HPVGA2 index */
+	b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN, ~B43_NPHY_C1_INITGAIN_HPVGA2,
+			code << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT);
+	b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN, ~B43_NPHY_C2_INITGAIN_HPVGA2,
+			code << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT);
+
+	b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
+	/* specs say about 2 loops, but wl does 4 */
+	for (i = 0; i < 4; i++)
+		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, (code << 8 | 0x7C));
+
+	b43_nphy_adjust_lna_gain_table(dev);
+
+	if (nphy->elna_gain_config) {
+		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0808);
+		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0);
+		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
+		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
+		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
+
+		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0C08);
+		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0);
+		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
+		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
+		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
+
+		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
+		/* specs say about 2 loops, but wl does 4 */
+		for (i = 0; i < 4; i++)
+			b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
+						(code << 8 | 0x74));
+	}
+
+	if (dev->phy.rev == 2) {
+		for (i = 0; i < 4; i++) {
+			b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
+					(0x0400 * i) + 0x0020);
+			for (j = 0; j < 21; j++) {
+				tmp = j * (i < 2 ? 3 : 1);
+				b43_phy_write(dev,
+					B43_NPHY_TABLE_DATALO, tmp);
+			}
+		}
+	}
+
+	b43_nphy_set_rf_sequence(dev, 5, rfseq_events, rfseq_delays, 3);
+	b43_phy_maskset(dev, B43_NPHY_OVER_DGAIN1,
+		~B43_NPHY_OVER_DGAIN_CCKDGECV & 0xFFFF,
+		0x5A << B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT);
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+		b43_phy_maskset(dev, B43_PHY_N(0xC5D), 0xFF80, 4);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */
+static void b43_nphy_gain_ctl_workarounds(struct b43_wldev *dev)
+{
+	if (dev->phy.rev >= 19)
+		b43_nphy_gain_ctl_workarounds_rev19(dev);
+	else if (dev->phy.rev >= 7)
+		b43_nphy_gain_ctl_workarounds_rev7(dev);
+	else if (dev->phy.rev >= 3)
+		b43_nphy_gain_ctl_workarounds_rev3(dev);
+	else
+		b43_nphy_gain_ctl_workarounds_rev1_2(dev);
+}
+
+static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
+{
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+	struct b43_phy *phy = &dev->phy;
+
+	/* TX to RX */
+	u8 tx2rx_events[7] = { 4, 3, 5, 2, 1, 8, 31, };
+	u8 tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1, };
+	/* RX to TX */
+	u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
+					0x1F };
+	u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
+
+	static const u16 ntab7_15e_16e[] = { 0, 0x10f, 0x10f };
+	u8 ntab7_138_146[] = { 0x11, 0x11 };
+	u8 ntab7_133[] = { 0x77, 0x11, 0x11 };
+
+	u16 lpf_ofdm_20mhz[2], lpf_ofdm_40mhz[2], lpf_11b[2];
+	u16 bcap_val;
+	s16 bcap_val_11b[2], bcap_val_11n_20[2], bcap_val_11n_40[2];
+	u16 scap_val;
+	s16 scap_val_11b[2], scap_val_11n_20[2], scap_val_11n_40[2];
+	bool rccal_ovrd = false;
+
+	u16 bias, conv, filt;
+
+	u32 noise_tbl[2];
+
+	u32 tmp32;
+	u8 core;
+
+	b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);
+	b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01b3);
+	b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);
+	b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016e);
+	b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00cd);
+	b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
+
+	if (phy->rev == 7) {
+		b43_phy_set(dev, B43_NPHY_FINERX2_CGC, 0x10);
+		b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0xFF80, 0x0020);
+		b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0x80FF, 0x2700);
+		b43_phy_maskset(dev, B43_NPHY_FREQGAIN1, 0xFF80, 0x002E);
+		b43_phy_maskset(dev, B43_NPHY_FREQGAIN1, 0x80FF, 0x3300);
+		b43_phy_maskset(dev, B43_NPHY_FREQGAIN2, 0xFF80, 0x0037);
+		b43_phy_maskset(dev, B43_NPHY_FREQGAIN2, 0x80FF, 0x3A00);
+		b43_phy_maskset(dev, B43_NPHY_FREQGAIN3, 0xFF80, 0x003C);
+		b43_phy_maskset(dev, B43_NPHY_FREQGAIN3, 0x80FF, 0x3E00);
+		b43_phy_maskset(dev, B43_NPHY_FREQGAIN4, 0xFF80, 0x003E);
+		b43_phy_maskset(dev, B43_NPHY_FREQGAIN4, 0x80FF, 0x3F00);
+		b43_phy_maskset(dev, B43_NPHY_FREQGAIN5, 0xFF80, 0x0040);
+		b43_phy_maskset(dev, B43_NPHY_FREQGAIN5, 0x80FF, 0x4000);
+		b43_phy_maskset(dev, B43_NPHY_FREQGAIN6, 0xFF80, 0x0040);
+		b43_phy_maskset(dev, B43_NPHY_FREQGAIN6, 0x80FF, 0x4000);
+		b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0xFF80, 0x0040);
+		b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0x80FF, 0x4000);
+	}
+
+	if (phy->rev >= 16) {
+		b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x7ff);
+		b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x7ff);
+	} else if (phy->rev <= 8) {
+		b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1B0);
+		b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1B0);
+	}
+
+	if (phy->rev >= 16)
+		b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0xa0);
+	else if (phy->rev >= 8)
+		b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0x72);
+
+	b43_ntab_write(dev, B43_NTAB16(8, 0x00), 2);
+	b43_ntab_write(dev, B43_NTAB16(8, 0x10), 2);
+	tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
+	tmp32 &= 0xffffff;
+	b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
+	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x15d), 3, ntab7_15e_16e);
+	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16d), 3, ntab7_15e_16e);
+
+	b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays,
+				 ARRAY_SIZE(tx2rx_events));
+	if (b43_nphy_ipa(dev))
+		b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa,
+				rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa));
+
+	b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_0, 0x3FFF, 0x4000);
+	b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_1, 0x3FFF, 0x4000);
+
+	for (core = 0; core < 2; core++) {
+		lpf_ofdm_20mhz[core] = b43_nphy_read_lpf_ctl(dev, 0x154 + core * 0x10);
+		lpf_ofdm_40mhz[core] = b43_nphy_read_lpf_ctl(dev, 0x159 + core * 0x10);
+		lpf_11b[core] = b43_nphy_read_lpf_ctl(dev, 0x152 + core * 0x10);
+	}
+
+	bcap_val = b43_radio_read(dev, R2057_RCCAL_BCAP_VAL);
+	scap_val = b43_radio_read(dev, R2057_RCCAL_SCAP_VAL);
+
+	if (b43_nphy_ipa(dev)) {
+		bool ghz2 = b43_current_band(dev->wl) == NL80211_BAND_2GHZ;
+
+		switch (phy->radio_rev) {
+		case 5:
+			/* Check radio version (to be 0) by PHY rev for now */
+			if (phy->rev == 8 && b43_is_40mhz(dev)) {
+				for (core = 0; core < 2; core++) {
+					scap_val_11b[core] = scap_val;
+					bcap_val_11b[core] = bcap_val;
+					scap_val_11n_20[core] = scap_val;
+					bcap_val_11n_20[core] = bcap_val;
+					scap_val_11n_40[core] = 0xc;
+					bcap_val_11n_40[core] = 0xc;
+				}
+
+				rccal_ovrd = true;
+			}
+			if (phy->rev == 9) {
+				/* TODO: Radio version 1 (e.g. BCM5357B0) */
+			}
+			break;
+		case 7:
+		case 8:
+			for (core = 0; core < 2; core++) {
+				scap_val_11b[core] = scap_val;
+				bcap_val_11b[core] = bcap_val;
+				lpf_ofdm_20mhz[core] = 4;
+				lpf_11b[core] = 1;
+				if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+					scap_val_11n_20[core] = 0xc;
+					bcap_val_11n_20[core] = 0xc;
+					scap_val_11n_40[core] = 0xa;
+					bcap_val_11n_40[core] = 0xa;
+				} else {
+					scap_val_11n_20[core] = 0x14;
+					bcap_val_11n_20[core] = 0x14;
+					scap_val_11n_40[core] = 0xf;
+					bcap_val_11n_40[core] = 0xf;
+				}
+			}
+
+			rccal_ovrd = true;
+			break;
+		case 9:
+			for (core = 0; core < 2; core++) {
+				bcap_val_11b[core] = bcap_val;
+				scap_val_11b[core] = scap_val;
+				lpf_11b[core] = 1;
+
+				if (ghz2) {
+					bcap_val_11n_20[core] = bcap_val + 13;
+					scap_val_11n_20[core] = scap_val + 15;
+				} else {
+					bcap_val_11n_20[core] = bcap_val + 14;
+					scap_val_11n_20[core] = scap_val + 15;
+				}
+				lpf_ofdm_20mhz[core] = 4;
+
+				if (ghz2) {
+					bcap_val_11n_40[core] = bcap_val - 7;
+					scap_val_11n_40[core] = scap_val - 5;
+				} else {
+					bcap_val_11n_40[core] = bcap_val + 2;
+					scap_val_11n_40[core] = scap_val + 4;
+				}
+				lpf_ofdm_40mhz[core] = 4;
+			}
+
+			rccal_ovrd = true;
+			break;
+		case 14:
+			for (core = 0; core < 2; core++) {
+				bcap_val_11b[core] = bcap_val;
+				scap_val_11b[core] = scap_val;
+				lpf_11b[core] = 1;
+			}
+
+			bcap_val_11n_20[0] = bcap_val + 20;
+			scap_val_11n_20[0] = scap_val + 20;
+			lpf_ofdm_20mhz[0] = 3;
+
+			bcap_val_11n_20[1] = bcap_val + 16;
+			scap_val_11n_20[1] = scap_val + 16;
+			lpf_ofdm_20mhz[1] = 3;
+
+			bcap_val_11n_40[0] = bcap_val + 20;
+			scap_val_11n_40[0] = scap_val + 20;
+			lpf_ofdm_40mhz[0] = 4;
+
+			bcap_val_11n_40[1] = bcap_val + 10;
+			scap_val_11n_40[1] = scap_val + 10;
+			lpf_ofdm_40mhz[1] = 4;
+
+			rccal_ovrd = true;
+			break;
+		}
+	} else {
+		if (phy->radio_rev == 5) {
+			for (core = 0; core < 2; core++) {
+				lpf_ofdm_20mhz[core] = 1;
+				lpf_ofdm_40mhz[core] = 3;
+				scap_val_11b[core] = scap_val;
+				bcap_val_11b[core] = bcap_val;
+				scap_val_11n_20[core] = 0x11;
+				scap_val_11n_40[core] = 0x11;
+				bcap_val_11n_20[core] = 0x13;
+				bcap_val_11n_40[core] = 0x13;
+			}
+
+			rccal_ovrd = true;
+		}
+	}
+	if (rccal_ovrd) {
+		u16 rx2tx_lut_20_11b[2], rx2tx_lut_20_11n[2], rx2tx_lut_40_11n[2];
+		u8 rx2tx_lut_extra = 1;
+
+		for (core = 0; core < 2; core++) {
+			bcap_val_11b[core] = clamp_val(bcap_val_11b[core], 0, 0x1f);
+			scap_val_11b[core] = clamp_val(scap_val_11b[core], 0, 0x1f);
+			bcap_val_11n_20[core] = clamp_val(bcap_val_11n_20[core], 0, 0x1f);
+			scap_val_11n_20[core] = clamp_val(scap_val_11n_20[core], 0, 0x1f);
+			bcap_val_11n_40[core] = clamp_val(bcap_val_11n_40[core], 0, 0x1f);
+			scap_val_11n_40[core] = clamp_val(scap_val_11n_40[core], 0, 0x1f);
+
+			rx2tx_lut_20_11b[core] = (rx2tx_lut_extra << 13) |
+						 (bcap_val_11b[core] << 8) |
+						 (scap_val_11b[core] << 3) |
+						 lpf_11b[core];
+			rx2tx_lut_20_11n[core] = (rx2tx_lut_extra << 13) |
+						 (bcap_val_11n_20[core] << 8) |
+						 (scap_val_11n_20[core] << 3) |
+						 lpf_ofdm_20mhz[core];
+			rx2tx_lut_40_11n[core] = (rx2tx_lut_extra << 13) |
+						 (bcap_val_11n_40[core] << 8) |
+						 (scap_val_11n_40[core] << 3) |
+						 lpf_ofdm_40mhz[core];
+		}
+
+		for (core = 0; core < 2; core++) {
+			b43_ntab_write(dev, B43_NTAB16(7, 0x152 + core * 16),
+				       rx2tx_lut_20_11b[core]);
+			b43_ntab_write(dev, B43_NTAB16(7, 0x153 + core * 16),
+				       rx2tx_lut_20_11n[core]);
+			b43_ntab_write(dev, B43_NTAB16(7, 0x154 + core * 16),
+				       rx2tx_lut_20_11n[core]);
+			b43_ntab_write(dev, B43_NTAB16(7, 0x155 + core * 16),
+				       rx2tx_lut_40_11n[core]);
+			b43_ntab_write(dev, B43_NTAB16(7, 0x156 + core * 16),
+				       rx2tx_lut_40_11n[core]);
+			b43_ntab_write(dev, B43_NTAB16(7, 0x157 + core * 16),
+				       rx2tx_lut_40_11n[core]);
+			b43_ntab_write(dev, B43_NTAB16(7, 0x158 + core * 16),
+				       rx2tx_lut_40_11n[core]);
+			b43_ntab_write(dev, B43_NTAB16(7, 0x159 + core * 16),
+				       rx2tx_lut_40_11n[core]);
+		}
+	}
+
+	b43_phy_write(dev, 0x32F, 0x3);
+
+	if (phy->radio_rev == 4 || phy->radio_rev == 6)
+		b43_nphy_rf_ctl_override_rev7(dev, 4, 1, 3, false, 0);
+
+	if (phy->radio_rev == 3 || phy->radio_rev == 4 || phy->radio_rev == 6) {
+		if (sprom->revision &&
+		    sprom->boardflags2_hi & B43_BFH2_IPALVLSHIFT_3P3) {
+			b43_radio_write(dev, 0x5, 0x05);
+			b43_radio_write(dev, 0x6, 0x30);
+			b43_radio_write(dev, 0x7, 0x00);
+			b43_radio_set(dev, 0x4f, 0x1);
+			b43_radio_set(dev, 0xd4, 0x1);
+			bias = 0x1f;
+			conv = 0x6f;
+			filt = 0xaa;
+		} else {
+			bias = 0x2b;
+			conv = 0x7f;
+			filt = 0xee;
+		}
+		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+			for (core = 0; core < 2; core++) {
+				if (core == 0) {
+					b43_radio_write(dev, 0x5F, bias);
+					b43_radio_write(dev, 0x64, conv);
+					b43_radio_write(dev, 0x66, filt);
+				} else {
+					b43_radio_write(dev, 0xE8, bias);
+					b43_radio_write(dev, 0xE9, conv);
+					b43_radio_write(dev, 0xEB, filt);
+				}
+			}
+		}
+	}
+
+	if (b43_nphy_ipa(dev)) {
+		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+			if (phy->radio_rev == 3 || phy->radio_rev == 4 ||
+			    phy->radio_rev == 6) {
+				for (core = 0; core < 2; core++) {
+					if (core == 0)
+						b43_radio_write(dev, 0x51,
+								0x7f);
+					else
+						b43_radio_write(dev, 0xd6,
+								0x7f);
+				}
+			}
+			switch (phy->radio_rev) {
+			case 3:
+				for (core = 0; core < 2; core++) {
+					if (core == 0) {
+						b43_radio_write(dev, 0x64,
+								0x13);
+						b43_radio_write(dev, 0x5F,
+								0x1F);
+						b43_radio_write(dev, 0x66,
+								0xEE);
+						b43_radio_write(dev, 0x59,
+								0x8A);
+						b43_radio_write(dev, 0x80,
+								0x3E);
+					} else {
+						b43_radio_write(dev, 0x69,
+								0x13);
+						b43_radio_write(dev, 0xE8,
+								0x1F);
+						b43_radio_write(dev, 0xEB,
+								0xEE);
+						b43_radio_write(dev, 0xDE,
+								0x8A);
+						b43_radio_write(dev, 0x105,
+								0x3E);
+					}
+				}
+				break;
+			case 7:
+			case 8:
+				if (!b43_is_40mhz(dev)) {
+					b43_radio_write(dev, 0x5F, 0x14);
+					b43_radio_write(dev, 0xE8, 0x12);
+				} else {
+					b43_radio_write(dev, 0x5F, 0x16);
+					b43_radio_write(dev, 0xE8, 0x16);
+				}
+				break;
+			case 14:
+				for (core = 0; core < 2; core++) {
+					int o = core ? 0x85 : 0;
+
+					b43_radio_write(dev, o + R2057_IPA2G_CASCONV_CORE0, 0x13);
+					b43_radio_write(dev, o + R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, 0x21);
+					b43_radio_write(dev, o + R2057_IPA2G_BIAS_FILTER_CORE0, 0xff);
+					b43_radio_write(dev, o + R2057_PAD2G_IDACS_CORE0, 0x88);
+					b43_radio_write(dev, o + R2057_PAD2G_TUNE_PUS_CORE0, 0x23);
+					b43_radio_write(dev, o + R2057_IPA2G_IMAIN_CORE0, 0x16);
+					b43_radio_write(dev, o + R2057_PAD_BIAS_FILTER_BWS_CORE0, 0x3e);
+					b43_radio_write(dev, o + R2057_BACKUP1_CORE0, 0x10);
+				}
+				break;
+			}
+		} else {
+			u16 freq = phy->chandef->chan->center_freq;
+			if ((freq >= 5180 && freq <= 5230) ||
+			    (freq >= 5745 && freq <= 5805)) {
+				b43_radio_write(dev, 0x7D, 0xFF);
+				b43_radio_write(dev, 0xFE, 0xFF);
+			}
+		}
+	} else {
+		if (phy->radio_rev != 5) {
+			for (core = 0; core < 2; core++) {
+				if (core == 0) {
+					b43_radio_write(dev, 0x5c, 0x61);
+					b43_radio_write(dev, 0x51, 0x70);
+				} else {
+					b43_radio_write(dev, 0xe1, 0x61);
+					b43_radio_write(dev, 0xd6, 0x70);
+				}
+			}
+		}
+	}
+
+	if (phy->radio_rev == 4) {
+		b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0x20);
+		b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0x20);
+		for (core = 0; core < 2; core++) {
+			if (core == 0) {
+				b43_radio_write(dev, 0x1a1, 0x00);
+				b43_radio_write(dev, 0x1a2, 0x3f);
+				b43_radio_write(dev, 0x1a6, 0x3f);
+			} else {
+				b43_radio_write(dev, 0x1a7, 0x00);
+				b43_radio_write(dev, 0x1ab, 0x3f);
+				b43_radio_write(dev, 0x1ac, 0x3f);
+			}
+		}
+	} else {
+		b43_phy_set(dev, B43_NPHY_AFECTL_C1, 0x4);
+		b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x4);
+		b43_phy_set(dev, B43_NPHY_AFECTL_C2, 0x4);
+		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4);
+
+		b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x1);
+		b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x1);
+		b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x1);
+		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x1);
+		b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0);
+		b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0);
+
+		b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x4);
+		b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x4);
+		b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x4);
+		b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4);
+	}
+
+	b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, 0x2);
+
+	b43_ntab_write(dev, B43_NTAB32(16, 0x100), 20);
+	b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x138), 2, ntab7_138_146);
+	b43_ntab_write(dev, B43_NTAB16(7, 0x141), 0x77);
+	b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x133), 3, ntab7_133);
+	b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x146), 2, ntab7_138_146);
+	b43_ntab_write(dev, B43_NTAB16(7, 0x123), 0x77);
+	b43_ntab_write(dev, B43_NTAB16(7, 0x12A), 0x77);
+
+	b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x02), 1, noise_tbl);
+	noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D;
+	b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x02), 2, noise_tbl);
+
+	b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x7E), 1, noise_tbl);
+	noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D;
+	b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x7E), 2, noise_tbl);
+
+	b43_nphy_gain_ctl_workarounds(dev);
+
+	/* TODO
+	b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4,
+			    aux_adc_vmid_rev7_core0);
+	b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4,
+			    aux_adc_vmid_rev7_core1);
+	b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0C), 4,
+			    aux_adc_gain_rev7);
+	b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1C), 4,
+			    aux_adc_gain_rev7);
+	*/
+}
+
+static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
+{
+	struct b43_phy_n *nphy = dev->phy.n;
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+
+	/* TX to RX */
+	u8 tx2rx_events[7] = { 0x4, 0x3, 0x5, 0x2, 0x1, 0x8, 0x1F };
+	u8 tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1 };
+	/* RX to TX */
+	u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
+					0x1F };
+	u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
+	u8 rx2tx_events[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0x3, 0x4, 0x1F };
+	u8 rx2tx_delays[9] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 };
+
+	u16 vmids[5][4] = {
+		{ 0xa2, 0xb4, 0xb4, 0x89, }, /* 0 */
+		{ 0xb4, 0xb4, 0xb4, 0x24, }, /* 1 */
+		{ 0xa2, 0xb4, 0xb4, 0x74, }, /* 2 */
+		{ 0xa2, 0xb4, 0xb4, 0x270, }, /* 3 */
+		{ 0xa2, 0xb4, 0xb4, 0x00, }, /* 4 and 5 */
+	};
+	u16 gains[5][4] = {
+		{ 0x02, 0x02, 0x02, 0x00, }, /* 0 */
+		{ 0x02, 0x02, 0x02, 0x02, }, /* 1 */
+		{ 0x02, 0x02, 0x02, 0x04, }, /* 2 */
+		{ 0x02, 0x02, 0x02, 0x00, }, /* 3 */
+		{ 0x02, 0x02, 0x02, 0x00, }, /* 4 and 5 */
+	};
+	u16 *vmid, *gain;
+
+	u8 pdet_range;
+	u16 tmp16;
+	u32 tmp32;
+
+	b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1f8);
+	b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1f8);
+
+	tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
+	tmp32 &= 0xffffff;
+	b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
+
+	b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);
+	b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01B3);
+	b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);
+	b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016E);
+	b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00CD);
+	b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
+
+	b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_LOGAIN_B, 0x000C);
+	b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_LOGAIN_B, 0x000C);
+
+	/* TX to RX */
+	b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays,
+				 ARRAY_SIZE(tx2rx_events));
+
+	/* RX to TX */
+	if (b43_nphy_ipa(dev))
+		b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa,
+				rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa));
+	if (nphy->hw_phyrxchain != 3 &&
+	    nphy->hw_phyrxchain != nphy->hw_phytxchain) {
+		if (b43_nphy_ipa(dev)) {
+			rx2tx_delays[5] = 59;
+			rx2tx_delays[6] = 1;
+			rx2tx_events[7] = 0x1F;
+		}
+		b43_nphy_set_rf_sequence(dev, 0, rx2tx_events, rx2tx_delays,
+					 ARRAY_SIZE(rx2tx_events));
+	}
+
+	tmp16 = (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) ?
+		0x2 : 0x9C40;
+	b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16);
+
+	b43_phy_maskset(dev, B43_NPHY_SGILTRNOFFSET, 0xF0FF, 0x0700);
+
+	if (!b43_is_40mhz(dev)) {
+		b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
+		b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);
+	} else {
+		b43_ntab_write(dev, B43_NTAB32(16, 3), 0x14D);
+		b43_ntab_write(dev, B43_NTAB32(16, 127), 0x14D);
+	}
+
+	b43_nphy_gain_ctl_workarounds(dev);
+
+	b43_ntab_write(dev, B43_NTAB16(8, 0), 2);
+	b43_ntab_write(dev, B43_NTAB16(8, 16), 2);
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+		pdet_range = sprom->fem.ghz2.pdet_range;
+	else
+		pdet_range = sprom->fem.ghz5.pdet_range;
+	vmid = vmids[min_t(u16, pdet_range, 4)];
+	gain = gains[min_t(u16, pdet_range, 4)];
+	switch (pdet_range) {
+	case 3:
+		if (!(dev->phy.rev >= 4 &&
+		      b43_current_band(dev->wl) == NL80211_BAND_2GHZ))
+			break;
+		/* FALL THROUGH */
+	case 0:
+	case 1:
+		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4, vmid);
+		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4, vmid);
+		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0c), 4, gain);
+		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1c), 4, gain);
+		break;
+	case 2:
+		if (dev->phy.rev >= 6) {
+			if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+				vmid[3] = 0x94;
+			else
+				vmid[3] = 0x8e;
+			gain[3] = 3;
+		} else if (dev->phy.rev == 5) {
+			vmid[3] = 0x84;
+			gain[3] = 2;
+		}
+		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4, vmid);
+		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4, vmid);
+		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0c), 4, gain);
+		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1c), 4, gain);
+		break;
+	case 4:
+	case 5:
+		if (b43_current_band(dev->wl) != NL80211_BAND_2GHZ) {
+			if (pdet_range == 4) {
+				vmid[3] = 0x8e;
+				tmp16 = 0x96;
+				gain[3] = 0x2;
+			} else {
+				vmid[3] = 0x89;
+				tmp16 = 0x89;
+				gain[3] = 0;
+			}
+		} else {
+			if (pdet_range == 4) {
+				vmid[3] = 0x89;
+				tmp16 = 0x8b;
+				gain[3] = 0x2;
+			} else {
+				vmid[3] = 0x74;
+				tmp16 = 0x70;
+				gain[3] = 0;
+			}
+		}
+		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4, vmid);
+		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0c), 4, gain);
+		vmid[3] = tmp16;
+		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4, vmid);
+		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1c), 4, gain);
+		break;
+	}
+
+	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_MAST_BIAS, 0x00);
+	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_MAST_BIAS, 0x00);
+	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
+	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
+	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_AUX, 0x07);
+	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07);
+	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88);
+	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88);
+	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_CMFB_IDAC, 0x00);
+	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_CMFB_IDAC, 0x00);
+	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
+	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
+
+	/* N PHY WAR TX Chain Update with hw_phytxchain as argument */
+
+	if ((sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
+	     b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ||
+	    (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
+	     b43_current_band(dev->wl) == NL80211_BAND_2GHZ))
+		tmp32 = 0x00088888;
+	else
+		tmp32 = 0x88888888;
+	b43_ntab_write(dev, B43_NTAB32(30, 1), tmp32);
+	b43_ntab_write(dev, B43_NTAB32(30, 2), tmp32);
+	b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32);
+
+	if (dev->phy.rev == 4 &&
+	    b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
+		b43_radio_write(dev, B2056_TX0 | B2056_TX_GMBB_IDAC,
+				0x70);
+		b43_radio_write(dev, B2056_TX1 | B2056_TX_GMBB_IDAC,
+				0x70);
+	}
+
+	/* Dropped probably-always-true condition */
+	b43_phy_write(dev, B43_NPHY_ED_CRS40ASSERTTHRESH0, 0x03eb);
+	b43_phy_write(dev, B43_NPHY_ED_CRS40ASSERTTHRESH1, 0x03eb);
+	b43_phy_write(dev, B43_NPHY_ED_CRS40DEASSERTTHRESH0, 0x0341);
+	b43_phy_write(dev, B43_NPHY_ED_CRS40DEASSERTTHRESH1, 0x0341);
+	b43_phy_write(dev, B43_NPHY_ED_CRS20LASSERTTHRESH0, 0x042b);
+	b43_phy_write(dev, B43_NPHY_ED_CRS20LASSERTTHRESH1, 0x042b);
+	b43_phy_write(dev, B43_NPHY_ED_CRS20LDEASSERTTHRESH0, 0x0381);
+	b43_phy_write(dev, B43_NPHY_ED_CRS20LDEASSERTTHRESH1, 0x0381);
+	b43_phy_write(dev, B43_NPHY_ED_CRS20UASSERTTHRESH0, 0x042b);
+	b43_phy_write(dev, B43_NPHY_ED_CRS20UASSERTTHRESH1, 0x042b);
+	b43_phy_write(dev, B43_NPHY_ED_CRS20UDEASSERTTHRESH0, 0x0381);
+	b43_phy_write(dev, B43_NPHY_ED_CRS20UDEASSERTTHRESH1, 0x0381);
+
+	if (dev->phy.rev >= 6 && sprom->boardflags2_lo & B43_BFL2_SINGLEANT_CCK)
+		; /* TODO: 0x0080000000000000 HF */
+}
+
+static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
+{
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = phy->n;
+
+	u8 events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 };
+	u8 delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 };
+
+	u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 };
+	u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
+
+	if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD ||
+	    dev->dev->board_type == BCMA_BOARD_TYPE_BCM943224M93) {
+		delays1[0] = 0x1;
+		delays1[5] = 0x14;
+	}
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ &&
+	    nphy->band5g_pwrgain) {
+		b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8);
+		b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8);
+	} else {
+		b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8);
+		b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8);
+	}
+
+	b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A);
+	b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A);
+	if (dev->phy.rev < 3) {
+		b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
+		b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
+	}
+
+	if (dev->phy.rev < 2) {
+		b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000);
+		b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0x0000);
+		b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB);
+		b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB);
+		b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x0800);
+		b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x0800);
+	}
+
+	b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
+	b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
+	b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
+	b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
+
+	b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);
+	b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);
+
+	b43_nphy_gain_ctl_workarounds(dev);
+
+	if (dev->phy.rev < 2) {
+		if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2)
+			b43_hf_write(dev, b43_hf_read(dev) |
+					B43_HF_MLADVW);
+	} else if (dev->phy.rev == 2) {
+		b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0);
+		b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0);
+	}
+
+	if (dev->phy.rev < 2)
+		b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL,
+				~B43_NPHY_SCRAM_SIGCTL_SCM);
+
+	/* Set phase track alpha and beta */
+	b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125);
+	b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3);
+	b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105);
+	b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E);
+	b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);
+	b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
+
+	if (dev->phy.rev < 3) {
+		b43_phy_mask(dev, B43_NPHY_PIL_DW1,
+			     ~B43_NPHY_PIL_DW_64QAM & 0xFFFF);
+		b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5);
+		b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4);
+		b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00);
+	}
+
+	if (dev->phy.rev == 2)
+		b43_phy_set(dev, B43_NPHY_FINERX2_CGC,
+				B43_NPHY_FINERX2_CGC_DECGC);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */
+static void b43_nphy_workarounds(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = phy->n;
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
+		b43_nphy_classifier(dev, 1, 0);
+	else
+		b43_nphy_classifier(dev, 1, 1);
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, 1);
+
+	b43_phy_set(dev, B43_NPHY_IQFLIP,
+		    B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
+
+	/* TODO: rev19+ */
+	if (dev->phy.rev >= 7)
+		b43_nphy_workarounds_rev7plus(dev);
+	else if (dev->phy.rev >= 3)
+		b43_nphy_workarounds_rev3plus(dev);
+	else
+		b43_nphy_workarounds_rev1_2(dev);
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, 0);
+}
+
+/**************************************************
+ * Tx/Rx common
+ **************************************************/
+
+/*
+ * Transmits a known value for LO calibration
+ * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone
+ */
+static int b43_nphy_tx_tone(struct b43_wldev *dev, u32 freq, u16 max_val,
+			    bool iqmode, bool dac_test, bool modify_bbmult)
+{
+	u16 samp = b43_nphy_gen_load_samples(dev, freq, max_val, dac_test);
+	if (samp == 0)
+		return -1;
+	b43_nphy_run_samples(dev, samp, 0xFFFF, 0, iqmode, dac_test,
+			     modify_bbmult);
+	return 0;
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */
+static void b43_nphy_update_txrx_chain(struct b43_wldev *dev)
+{
+	struct b43_phy_n *nphy = dev->phy.n;
+
+	bool override = false;
+	u16 chain = 0x33;
+
+	if (nphy->txrx_chain == 0) {
+		chain = 0x11;
+		override = true;
+	} else if (nphy->txrx_chain == 1) {
+		chain = 0x22;
+		override = true;
+	}
+
+	b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
+			~(B43_NPHY_RFSEQCA_TXEN | B43_NPHY_RFSEQCA_RXEN),
+			chain);
+
+	if (override)
+		b43_phy_set(dev, B43_NPHY_RFSEQMODE,
+				B43_NPHY_RFSEQMODE_CAOVER);
+	else
+		b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
+				~B43_NPHY_RFSEQMODE_CAOVER);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */
+static void b43_nphy_stop_playback(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = dev->phy.n;
+	u16 tmp;
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, 1);
+
+	tmp = b43_phy_read(dev, B43_NPHY_SAMP_STAT);
+	if (tmp & 0x1)
+		b43_phy_set(dev, B43_NPHY_SAMP_CMD, B43_NPHY_SAMP_CMD_STOP);
+	else if (tmp & 0x2)
+		b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
+
+	b43_phy_mask(dev, B43_NPHY_SAMP_CMD, ~0x0004);
+
+	if (nphy->bb_mult_save & 0x80000000) {
+		tmp = nphy->bb_mult_save & 0xFFFF;
+		b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
+		nphy->bb_mult_save = 0;
+	}
+
+	if (phy->rev >= 7 && nphy->lpf_bw_overrode_for_sample_play) {
+		if (phy->rev >= 19)
+			b43_nphy_rf_ctl_override_rev19(dev, 0x80, 0, 0, true,
+						       1);
+		else
+			b43_nphy_rf_ctl_override_rev7(dev, 0x80, 0, 0, true, 1);
+		nphy->lpf_bw_overrode_for_sample_play = false;
+	}
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, 0);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IqCalGainParams */
+static void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core,
+					struct nphy_txgains target,
+					struct nphy_iqcal_params *params)
+{
+	struct b43_phy *phy = &dev->phy;
+	int i, j, indx;
+	u16 gain;
+
+	if (dev->phy.rev >= 3) {
+		params->tx_lpf = target.tx_lpf[core]; /* Rev 7+ */
+		params->txgm = target.txgm[core];
+		params->pga = target.pga[core];
+		params->pad = target.pad[core];
+		params->ipa = target.ipa[core];
+		if (phy->rev >= 19) {
+			/* TODO */
+		} else if (phy->rev >= 7) {
+			params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 3) | (params->ipa) | (params->tx_lpf << 15);
+		} else {
+			params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 4) | (params->ipa);
+		}
+		for (j = 0; j < 5; j++)
+			params->ncorr[j] = 0x79;
+	} else {
+		gain = (target.pad[core]) | (target.pga[core] << 4) |
+			(target.txgm[core] << 8);
+
+		indx = (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ?
+			1 : 0;
+		for (i = 0; i < 9; i++)
+			if (tbl_iqcal_gainparams[indx][i][0] == gain)
+				break;
+		i = min(i, 8);
+
+		params->txgm = tbl_iqcal_gainparams[indx][i][1];
+		params->pga = tbl_iqcal_gainparams[indx][i][2];
+		params->pad = tbl_iqcal_gainparams[indx][i][3];
+		params->cal_gain = (params->txgm << 7) | (params->pga << 4) |
+					(params->pad << 2);
+		for (j = 0; j < 4; j++)
+			params->ncorr[j] = tbl_iqcal_gainparams[indx][i][4 + j];
+	}
+}
+
+/**************************************************
+ * Tx and Rx
+ **************************************************/
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */
+static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = dev->phy.n;
+	u8 i;
+	u16 bmask, val, tmp;
+	enum nl80211_band band = b43_current_band(dev->wl);
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, 1);
+
+	nphy->txpwrctrl = enable;
+	if (!enable) {
+		if (dev->phy.rev >= 3 &&
+		    (b43_phy_read(dev, B43_NPHY_TXPCTL_CMD) &
+		     (B43_NPHY_TXPCTL_CMD_COEFF |
+		      B43_NPHY_TXPCTL_CMD_HWPCTLEN |
+		      B43_NPHY_TXPCTL_CMD_PCTLEN))) {
+			/* We disable enabled TX pwr ctl, save it's state */
+			nphy->tx_pwr_idx[0] = b43_phy_read(dev,
+						B43_NPHY_C1_TXPCTL_STAT) & 0x7f;
+			nphy->tx_pwr_idx[1] = b43_phy_read(dev,
+						B43_NPHY_C2_TXPCTL_STAT) & 0x7f;
+		}
+
+		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6840);
+		for (i = 0; i < 84; i++)
+			b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0);
+
+		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6C40);
+		for (i = 0; i < 84; i++)
+			b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0);
+
+		tmp = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN;
+		if (dev->phy.rev >= 3)
+			tmp |= B43_NPHY_TXPCTL_CMD_PCTLEN;
+		b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD, ~tmp);
+
+		if (dev->phy.rev >= 3) {
+			b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100);
+			b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100);
+		} else {
+			b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000);
+		}
+
+		if (dev->phy.rev == 2)
+			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
+				~B43_NPHY_BPHY_CTL3_SCALE, 0x53);
+		else if (dev->phy.rev < 2)
+			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
+				~B43_NPHY_BPHY_CTL3_SCALE, 0x5A);
+
+		if (dev->phy.rev < 2 && b43_is_40mhz(dev))
+			b43_hf_write(dev, b43_hf_read(dev) | B43_HF_TSSIRPSMW);
+	} else {
+		b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84,
+				    nphy->adj_pwr_tbl);
+		b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84,
+				    nphy->adj_pwr_tbl);
+
+		bmask = B43_NPHY_TXPCTL_CMD_COEFF |
+			B43_NPHY_TXPCTL_CMD_HWPCTLEN;
+		/* wl does useless check for "enable" param here */
+		val = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN;
+		if (dev->phy.rev >= 3) {
+			bmask |= B43_NPHY_TXPCTL_CMD_PCTLEN;
+			if (val)
+				val |= B43_NPHY_TXPCTL_CMD_PCTLEN;
+		}
+		b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, ~(bmask), val);
+
+		if (band == NL80211_BAND_5GHZ) {
+			if (phy->rev >= 19) {
+				/* TODO */
+			} else if (phy->rev >= 7) {
+				b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
+						~B43_NPHY_TXPCTL_CMD_INIT,
+						0x32);
+				b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,
+						~B43_NPHY_TXPCTL_INIT_PIDXI1,
+						0x32);
+			} else {
+				b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
+						~B43_NPHY_TXPCTL_CMD_INIT,
+						0x64);
+				if (phy->rev > 1)
+					b43_phy_maskset(dev,
+							B43_NPHY_TXPCTL_INIT,
+							~B43_NPHY_TXPCTL_INIT_PIDXI1,
+							0x64);
+			}
+		}
+
+		if (dev->phy.rev >= 3) {
+			if (nphy->tx_pwr_idx[0] != 128 &&
+			    nphy->tx_pwr_idx[1] != 128) {
+				/* Recover TX pwr ctl state */
+				b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
+						~B43_NPHY_TXPCTL_CMD_INIT,
+						nphy->tx_pwr_idx[0]);
+				if (dev->phy.rev > 1)
+					b43_phy_maskset(dev,
+						B43_NPHY_TXPCTL_INIT,
+						~0xff, nphy->tx_pwr_idx[1]);
+			}
+		}
+
+		if (phy->rev >= 7) {
+			/* TODO */
+		}
+
+		if (dev->phy.rev >= 3) {
+			b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x100);
+			b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x100);
+		} else {
+			b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4000);
+		}
+
+		if (dev->phy.rev == 2)
+			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x3b);
+		else if (dev->phy.rev < 2)
+			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x40);
+
+		if (dev->phy.rev < 2 && b43_is_40mhz(dev))
+			b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_TSSIRPSMW);
+
+		if (b43_nphy_ipa(dev)) {
+			b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x4);
+			b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x4);
+		}
+	}
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, 0);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrFix */
+static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = dev->phy.n;
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+
+	u8 txpi[2], bbmult, i;
+	u16 tmp, radio_gain, dac_gain;
+	u16 freq = phy->chandef->chan->center_freq;
+	u32 txgain;
+	/* u32 gaintbl; rev3+ */
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, 1);
+
+	/* TODO: rev19+ */
+	if (dev->phy.rev >= 7) {
+		txpi[0] = txpi[1] = 30;
+	} else if (dev->phy.rev >= 3) {
+		txpi[0] = 40;
+		txpi[1] = 40;
+	} else if (sprom->revision < 4) {
+		txpi[0] = 72;
+		txpi[1] = 72;
+	} else {
+		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+			txpi[0] = sprom->txpid2g[0];
+			txpi[1] = sprom->txpid2g[1];
+		} else if (freq >= 4900 && freq < 5100) {
+			txpi[0] = sprom->txpid5gl[0];
+			txpi[1] = sprom->txpid5gl[1];
+		} else if (freq >= 5100 && freq < 5500) {
+			txpi[0] = sprom->txpid5g[0];
+			txpi[1] = sprom->txpid5g[1];
+		} else if (freq >= 5500) {
+			txpi[0] = sprom->txpid5gh[0];
+			txpi[1] = sprom->txpid5gh[1];
+		} else {
+			txpi[0] = 91;
+			txpi[1] = 91;
+		}
+	}
+	if (dev->phy.rev < 7 &&
+	    (txpi[0] < 40 || txpi[0] > 100 || txpi[1] < 40 || txpi[1] > 100))
+		txpi[0] = txpi[1] = 91;
+
+	/*
+	for (i = 0; i < 2; i++) {
+		nphy->txpwrindex[i].index_internal = txpi[i];
+		nphy->txpwrindex[i].index_internal_save = txpi[i];
+	}
+	*/
+
+	for (i = 0; i < 2; i++) {
+		const u32 *table = b43_nphy_get_tx_gain_table(dev);
+
+		if (!table)
+			break;
+		txgain = *(table + txpi[i]);
+
+		if (dev->phy.rev >= 3)
+			radio_gain = (txgain >> 16) & 0x1FFFF;
+		else
+			radio_gain = (txgain >> 16) & 0x1FFF;
+
+		if (dev->phy.rev >= 7)
+			dac_gain = (txgain >> 8) & 0x7;
+		else
+			dac_gain = (txgain >> 8) & 0x3F;
+		bbmult = txgain & 0xFF;
+
+		if (dev->phy.rev >= 3) {
+			if (i == 0)
+				b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100);
+			else
+				b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100);
+		} else {
+			b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000);
+		}
+
+		if (i == 0)
+			b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN1, dac_gain);
+		else
+			b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN2, dac_gain);
+
+		b43_ntab_write(dev, B43_NTAB16(0x7, 0x110 + i), radio_gain);
+
+		tmp = b43_ntab_read(dev, B43_NTAB16(0xF, 0x57));
+		if (i == 0)
+			tmp = (tmp & 0x00FF) | (bbmult << 8);
+		else
+			tmp = (tmp & 0xFF00) | bbmult;
+		b43_ntab_write(dev, B43_NTAB16(0xF, 0x57), tmp);
+
+		if (b43_nphy_ipa(dev)) {
+			u32 tmp32;
+			u16 reg = (i == 0) ?
+				B43_NPHY_PAPD_EN0 : B43_NPHY_PAPD_EN1;
+			tmp32 = b43_ntab_read(dev, B43_NTAB32(26 + i,
+							      576 + txpi[i]));
+			b43_phy_maskset(dev, reg, 0xE00F, (u32) tmp32 << 4);
+			b43_phy_set(dev, reg, 0x4);
+		}
+	}
+
+	b43_phy_mask(dev, B43_NPHY_BPHY_CTL2, ~B43_NPHY_BPHY_CTL2_LUT);
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, 0);
+}
+
+static void b43_nphy_ipa_internal_tssi_setup(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	u8 core;
+	u16 r; /* routing */
+
+	if (phy->rev >= 19) {
+		/* TODO */
+	} else if (phy->rev >= 7) {
+		for (core = 0; core < 2; core++) {
+			r = core ? 0x190 : 0x170;
+			if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+				b43_radio_write(dev, r + 0x5, 0x5);
+				b43_radio_write(dev, r + 0x9, 0xE);
+				if (phy->rev != 5)
+					b43_radio_write(dev, r + 0xA, 0);
+				if (phy->rev != 7)
+					b43_radio_write(dev, r + 0xB, 1);
+				else
+					b43_radio_write(dev, r + 0xB, 0x31);
+			} else {
+				b43_radio_write(dev, r + 0x5, 0x9);
+				b43_radio_write(dev, r + 0x9, 0xC);
+				b43_radio_write(dev, r + 0xB, 0x0);
+				if (phy->rev != 5)
+					b43_radio_write(dev, r + 0xA, 1);
+				else
+					b43_radio_write(dev, r + 0xA, 0x31);
+			}
+			b43_radio_write(dev, r + 0x6, 0);
+			b43_radio_write(dev, r + 0x7, 0);
+			b43_radio_write(dev, r + 0x8, 3);
+			b43_radio_write(dev, r + 0xC, 0);
+		}
+	} else {
+		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+			b43_radio_write(dev, B2056_SYN_RESERVED_ADDR31, 0x128);
+		else
+			b43_radio_write(dev, B2056_SYN_RESERVED_ADDR31, 0x80);
+		b43_radio_write(dev, B2056_SYN_RESERVED_ADDR30, 0);
+		b43_radio_write(dev, B2056_SYN_GPIO_MASTER1, 0x29);
+
+		for (core = 0; core < 2; core++) {
+			r = core ? B2056_TX1 : B2056_TX0;
+
+			b43_radio_write(dev, r | B2056_TX_IQCAL_VCM_HG, 0);
+			b43_radio_write(dev, r | B2056_TX_IQCAL_IDAC, 0);
+			b43_radio_write(dev, r | B2056_TX_TSSI_VCM, 3);
+			b43_radio_write(dev, r | B2056_TX_TX_AMP_DET, 0);
+			b43_radio_write(dev, r | B2056_TX_TSSI_MISC1, 8);
+			b43_radio_write(dev, r | B2056_TX_TSSI_MISC2, 0);
+			b43_radio_write(dev, r | B2056_TX_TSSI_MISC3, 0);
+			if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+				b43_radio_write(dev, r | B2056_TX_TX_SSI_MASTER,
+						0x5);
+				if (phy->rev != 5)
+					b43_radio_write(dev, r | B2056_TX_TSSIA,
+							0x00);
+				if (phy->rev >= 5)
+					b43_radio_write(dev, r | B2056_TX_TSSIG,
+							0x31);
+				else
+					b43_radio_write(dev, r | B2056_TX_TSSIG,
+							0x11);
+				b43_radio_write(dev, r | B2056_TX_TX_SSI_MUX,
+						0xE);
+			} else {
+				b43_radio_write(dev, r | B2056_TX_TX_SSI_MASTER,
+						0x9);
+				b43_radio_write(dev, r | B2056_TX_TSSIA, 0x31);
+				b43_radio_write(dev, r | B2056_TX_TSSIG, 0x0);
+				b43_radio_write(dev, r | B2056_TX_TX_SSI_MUX,
+						0xC);
+			}
+		}
+	}
+}
+
+/*
+ * Stop radio and transmit known signal. Then check received signal strength to
+ * get TSSI (Transmit Signal Strength Indicator).
+ * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlIdleTssi
+ */
+static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = dev->phy.n;
+
+	u32 tmp;
+	s32 rssi[4] = { };
+
+	if (phy->chandef->chan->flags & IEEE80211_CHAN_NO_IR)
+		return;
+
+	if (b43_nphy_ipa(dev))
+		b43_nphy_ipa_internal_tssi_setup(dev);
+
+	if (phy->rev >= 19)
+		b43_nphy_rf_ctl_override_rev19(dev, 0x1000, 0, 3, false, 0);
+	else if (phy->rev >= 7)
+		b43_nphy_rf_ctl_override_rev7(dev, 0x1000, 0, 3, false, 0);
+	else if (phy->rev >= 3)
+		b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, false);
+
+	b43_nphy_stop_playback(dev);
+	b43_nphy_tx_tone(dev, 4000, 0, false, false, false);
+	udelay(20);
+	tmp = b43_nphy_poll_rssi(dev, N_RSSI_TSSI_2G, rssi, 1);
+	b43_nphy_stop_playback(dev);
+
+	b43_nphy_rssi_select(dev, 0, N_RSSI_W1);
+
+	if (phy->rev >= 19)
+		b43_nphy_rf_ctl_override_rev19(dev, 0x1000, 0, 3, true, 0);
+	else if (phy->rev >= 7)
+		b43_nphy_rf_ctl_override_rev7(dev, 0x1000, 0, 3, true, 0);
+	else if (phy->rev >= 3)
+		b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, true);
+
+	if (phy->rev >= 19) {
+		/* TODO */
+		return;
+	} else if (phy->rev >= 3) {
+		nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 24) & 0xFF;
+		nphy->pwr_ctl_info[1].idle_tssi_5g = (tmp >> 8) & 0xFF;
+	} else {
+		nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 16) & 0xFF;
+		nphy->pwr_ctl_info[1].idle_tssi_5g = tmp & 0xFF;
+	}
+	nphy->pwr_ctl_info[0].idle_tssi_2g = (tmp >> 24) & 0xFF;
+	nphy->pwr_ctl_info[1].idle_tssi_2g = (tmp >> 8) & 0xFF;
+}
+
+/* http://bcm-v4.sipsolutions.net/PHY/N/TxPwrLimitToTbl */
+static void b43_nphy_tx_prepare_adjusted_power_table(struct b43_wldev *dev)
+{
+	struct b43_phy_n *nphy = dev->phy.n;
+
+	u8 idx, delta;
+	u8 i, stf_mode;
+
+	/* Array adj_pwr_tbl corresponds to the hardware table. It consists of
+	 * 21 groups, each containing 4 entries.
+	 *
+	 * First group has entries for CCK modulation.
+	 * The rest of groups has 1 entry per modulation (SISO, CDD, STBC, SDM).
+	 *
+	 * Group 0 is for CCK
+	 * Groups 1..4 use BPSK (group per coding rate)
+	 * Groups 5..8 use QPSK (group per coding rate)
+	 * Groups 9..12 use 16-QAM (group per coding rate)
+	 * Groups 13..16 use 64-QAM (group per coding rate)
+	 * Groups 17..20 are unknown
+	 */
+
+	for (i = 0; i < 4; i++)
+		nphy->adj_pwr_tbl[i] = nphy->tx_power_offset[i];
+
+	for (stf_mode = 0; stf_mode < 4; stf_mode++) {
+		delta = 0;
+		switch (stf_mode) {
+		case 0:
+			if (b43_is_40mhz(dev) && dev->phy.rev >= 5) {
+				idx = 68;
+			} else {
+				delta = 1;
+				idx = b43_is_40mhz(dev) ? 52 : 4;
+			}
+			break;
+		case 1:
+			idx = b43_is_40mhz(dev) ? 76 : 28;
+			break;
+		case 2:
+			idx = b43_is_40mhz(dev) ? 84 : 36;
+			break;
+		case 3:
+			idx = b43_is_40mhz(dev) ? 92 : 44;
+			break;
+		}
+
+		for (i = 0; i < 20; i++) {
+			nphy->adj_pwr_tbl[4 + 4 * i + stf_mode] =
+				nphy->tx_power_offset[idx];
+			if (i == 0)
+				idx += delta;
+			if (i == 14)
+				idx += 1 - delta;
+			if (i == 3 || i == 4 || i == 7 || i == 8 || i == 11 ||
+			    i == 13)
+				idx += 1;
+		}
+	}
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlSetup */
+static void b43_nphy_tx_power_ctl_setup(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = dev->phy.n;
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+
+	s16 a1[2], b0[2], b1[2];
+	u8 idle[2];
+	u8 ppr_max;
+	s8 target[2];
+	s32 num, den, pwr;
+	u32 regval[64];
+
+	u16 freq = phy->chandef->chan->center_freq;
+	u16 tmp;
+	u16 r; /* routing */
+	u8 i, c;
+
+	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) {
+		b43_maskset32(dev, B43_MMIO_MACCTL, ~0, 0x200000);
+		b43_read32(dev, B43_MMIO_MACCTL);
+		udelay(1);
+	}
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, true);
+
+	b43_phy_set(dev, B43_NPHY_TSSIMODE, B43_NPHY_TSSIMODE_EN);
+	if (dev->phy.rev >= 3)
+		b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD,
+			     ~B43_NPHY_TXPCTL_CMD_PCTLEN & 0xFFFF);
+	else
+		b43_phy_set(dev, B43_NPHY_TXPCTL_CMD,
+			    B43_NPHY_TXPCTL_CMD_PCTLEN);
+
+	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12)
+		b43_maskset32(dev, B43_MMIO_MACCTL, ~0x200000, 0);
+
+	if (sprom->revision < 4) {
+		idle[0] = nphy->pwr_ctl_info[0].idle_tssi_2g;
+		idle[1] = nphy->pwr_ctl_info[1].idle_tssi_2g;
+		target[0] = target[1] = 52;
+		a1[0] = a1[1] = -424;
+		b0[0] = b0[1] = 5612;
+		b1[0] = b1[1] = -1393;
+	} else {
+		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+			for (c = 0; c < 2; c++) {
+				idle[c] = nphy->pwr_ctl_info[c].idle_tssi_2g;
+				target[c] = sprom->core_pwr_info[c].maxpwr_2g;
+				a1[c] = sprom->core_pwr_info[c].pa_2g[0];
+				b0[c] = sprom->core_pwr_info[c].pa_2g[1];
+				b1[c] = sprom->core_pwr_info[c].pa_2g[2];
+			}
+		} else if (freq >= 4900 && freq < 5100) {
+			for (c = 0; c < 2; c++) {
+				idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g;
+				target[c] = sprom->core_pwr_info[c].maxpwr_5gl;
+				a1[c] = sprom->core_pwr_info[c].pa_5gl[0];
+				b0[c] = sprom->core_pwr_info[c].pa_5gl[1];
+				b1[c] = sprom->core_pwr_info[c].pa_5gl[2];
+			}
+		} else if (freq >= 5100 && freq < 5500) {
+			for (c = 0; c < 2; c++) {
+				idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g;
+				target[c] = sprom->core_pwr_info[c].maxpwr_5g;
+				a1[c] = sprom->core_pwr_info[c].pa_5g[0];
+				b0[c] = sprom->core_pwr_info[c].pa_5g[1];
+				b1[c] = sprom->core_pwr_info[c].pa_5g[2];
+			}
+		} else if (freq >= 5500) {
+			for (c = 0; c < 2; c++) {
+				idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g;
+				target[c] = sprom->core_pwr_info[c].maxpwr_5gh;
+				a1[c] = sprom->core_pwr_info[c].pa_5gh[0];
+				b0[c] = sprom->core_pwr_info[c].pa_5gh[1];
+				b1[c] = sprom->core_pwr_info[c].pa_5gh[2];
+			}
+		} else {
+			idle[0] = nphy->pwr_ctl_info[0].idle_tssi_5g;
+			idle[1] = nphy->pwr_ctl_info[1].idle_tssi_5g;
+			target[0] = target[1] = 52;
+			a1[0] = a1[1] = -424;
+			b0[0] = b0[1] = 5612;
+			b1[0] = b1[1] = -1393;
+		}
+	}
+
+	ppr_max = b43_ppr_get_max(dev, &nphy->tx_pwr_max_ppr);
+	if (ppr_max) {
+		target[0] = ppr_max;
+		target[1] = ppr_max;
+	}
+
+	if (dev->phy.rev >= 3) {
+		if (sprom->fem.ghz2.tssipos)
+			b43_phy_set(dev, B43_NPHY_TXPCTL_ITSSI, 0x4000);
+		if (dev->phy.rev >= 7) {
+			for (c = 0; c < 2; c++) {
+				r = c ? 0x190 : 0x170;
+				if (b43_nphy_ipa(dev))
+					b43_radio_write(dev, r + 0x9, (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) ? 0xE : 0xC);
+			}
+		} else {
+			if (b43_nphy_ipa(dev)) {
+				tmp = (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ? 0xC : 0xE;
+				b43_radio_write(dev,
+					B2056_TX0 | B2056_TX_TX_SSI_MUX, tmp);
+				b43_radio_write(dev,
+					B2056_TX1 | B2056_TX_TX_SSI_MUX, tmp);
+			} else {
+				b43_radio_write(dev,
+					B2056_TX0 | B2056_TX_TX_SSI_MUX, 0x11);
+				b43_radio_write(dev,
+					B2056_TX1 | B2056_TX_TX_SSI_MUX, 0x11);
+			}
+		}
+	}
+
+	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) {
+		b43_maskset32(dev, B43_MMIO_MACCTL, ~0, 0x200000);
+		b43_read32(dev, B43_MMIO_MACCTL);
+		udelay(1);
+	}
+
+	if (phy->rev >= 19) {
+		/* TODO */
+	} else if (phy->rev >= 7) {
+		b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
+				~B43_NPHY_TXPCTL_CMD_INIT, 0x19);
+		b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,
+				~B43_NPHY_TXPCTL_INIT_PIDXI1, 0x19);
+	} else {
+		b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
+				~B43_NPHY_TXPCTL_CMD_INIT, 0x40);
+		if (dev->phy.rev > 1)
+			b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,
+				~B43_NPHY_TXPCTL_INIT_PIDXI1, 0x40);
+	}
+
+	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12)
+		b43_maskset32(dev, B43_MMIO_MACCTL, ~0x200000, 0);
+
+	b43_phy_write(dev, B43_NPHY_TXPCTL_N,
+		      0xF0 << B43_NPHY_TXPCTL_N_TSSID_SHIFT |
+		      3 << B43_NPHY_TXPCTL_N_NPTIL2_SHIFT);
+	b43_phy_write(dev, B43_NPHY_TXPCTL_ITSSI,
+		      idle[0] << B43_NPHY_TXPCTL_ITSSI_0_SHIFT |
+		      idle[1] << B43_NPHY_TXPCTL_ITSSI_1_SHIFT |
+		      B43_NPHY_TXPCTL_ITSSI_BINF);
+	b43_phy_write(dev, B43_NPHY_TXPCTL_TPWR,
+		      target[0] << B43_NPHY_TXPCTL_TPWR_0_SHIFT |
+		      target[1] << B43_NPHY_TXPCTL_TPWR_1_SHIFT);
+
+	for (c = 0; c < 2; c++) {
+		for (i = 0; i < 64; i++) {
+			num = 8 * (16 * b0[c] + b1[c] * i);
+			den = 32768 + a1[c] * i;
+			pwr = max((4 * num + den / 2) / den, -8);
+			if (dev->phy.rev < 3 && (i <= (31 - idle[c] + 1)))
+				pwr = max(pwr, target[c] + 1);
+			regval[i] = pwr;
+		}
+		b43_ntab_write_bulk(dev, B43_NTAB32(26 + c, 0), 64, regval);
+	}
+
+	b43_nphy_tx_prepare_adjusted_power_table(dev);
+	b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84, nphy->adj_pwr_tbl);
+	b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84, nphy->adj_pwr_tbl);
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, false);
+}
+
+static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	const u32 *table = NULL;
+	u32 rfpwr_offset;
+	u8 pga_gain, pad_gain;
+	int i;
+	const s16 *uninitialized_var(rf_pwr_offset_table);
+
+	table = b43_nphy_get_tx_gain_table(dev);
+	if (!table)
+		return;
+
+	b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table);
+	b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table);
+
+	if (phy->rev < 3)
+		return;
+
+#if 0
+	nphy->gmval = (table[0] >> 16) & 0x7000;
+#endif
+
+	if (phy->rev >= 19) {
+		return;
+	} else if (phy->rev >= 7) {
+		rf_pwr_offset_table = b43_ntab_get_rf_pwr_offset_table(dev);
+		if (!rf_pwr_offset_table)
+			return;
+		/* TODO: Enable this once we have gains configured */
+		return;
+	}
+
+	for (i = 0; i < 128; i++) {
+		if (phy->rev >= 19) {
+			/* TODO */
+			return;
+		} else if (phy->rev >= 7) {
+			pga_gain = (table[i] >> 24) & 0xf;
+			pad_gain = (table[i] >> 19) & 0x1f;
+			if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+				rfpwr_offset = rf_pwr_offset_table[pad_gain];
+			else
+				rfpwr_offset = rf_pwr_offset_table[pga_gain];
+		} else {
+			pga_gain = (table[i] >> 24) & 0xF;
+			if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+				rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain];
+			else
+				rfpwr_offset = 0; /* FIXME */
+		}
+
+		b43_ntab_write(dev, B43_NTAB32(26, 576 + i), rfpwr_offset);
+		b43_ntab_write(dev, B43_NTAB32(27, 576 + i), rfpwr_offset);
+	}
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */
+static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable)
+{
+	struct b43_phy_n *nphy = dev->phy.n;
+	enum nl80211_band band;
+	u16 tmp;
+
+	if (!enable) {
+		nphy->rfctrl_intc1_save = b43_phy_read(dev,
+						       B43_NPHY_RFCTL_INTC1);
+		nphy->rfctrl_intc2_save = b43_phy_read(dev,
+						       B43_NPHY_RFCTL_INTC2);
+		band = b43_current_band(dev->wl);
+		if (dev->phy.rev >= 7) {
+			tmp = 0x1480;
+		} else if (dev->phy.rev >= 3) {
+			if (band == NL80211_BAND_5GHZ)
+				tmp = 0x600;
+			else
+				tmp = 0x480;
+		} else {
+			if (band == NL80211_BAND_5GHZ)
+				tmp = 0x180;
+			else
+				tmp = 0x120;
+		}
+		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp);
+		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp);
+	} else {
+		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1,
+				nphy->rfctrl_intc1_save);
+		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2,
+				nphy->rfctrl_intc2_save);
+	}
+}
+
+/*
+ * TX low-pass filter bandwidth setup
+ * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw
+ */
+static void b43_nphy_tx_lpf_bw(struct b43_wldev *dev)
+{
+	u16 tmp;
+
+	if (dev->phy.rev < 3 || dev->phy.rev >= 7)
+		return;
+
+	if (b43_nphy_ipa(dev))
+		tmp = b43_is_40mhz(dev) ? 5 : 4;
+	else
+		tmp = b43_is_40mhz(dev) ? 3 : 1;
+	b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2,
+		      (tmp << 9) | (tmp << 6) | (tmp << 3) | tmp);
+
+	if (b43_nphy_ipa(dev)) {
+		tmp = b43_is_40mhz(dev) ? 4 : 1;
+		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S2,
+			      (tmp << 9) | (tmp << 6) | (tmp << 3) | tmp);
+	}
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */
+static void b43_nphy_rx_iq_est(struct b43_wldev *dev, struct nphy_iq_est *est,
+				u16 samps, u8 time, bool wait)
+{
+	int i;
+	u16 tmp;
+
+	b43_phy_write(dev, B43_NPHY_IQEST_SAMCNT, samps);
+	b43_phy_maskset(dev, B43_NPHY_IQEST_WT, ~B43_NPHY_IQEST_WT_VAL, time);
+	if (wait)
+		b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_MODE);
+	else
+		b43_phy_mask(dev, B43_NPHY_IQEST_CMD, ~B43_NPHY_IQEST_CMD_MODE);
+
+	b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_START);
+
+	for (i = 1000; i; i--) {
+		tmp = b43_phy_read(dev, B43_NPHY_IQEST_CMD);
+		if (!(tmp & B43_NPHY_IQEST_CMD_START)) {
+			est->i0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI0) << 16) |
+					b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO0);
+			est->q0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI0) << 16) |
+					b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO0);
+			est->iq0_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI0) << 16) |
+					b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO0);
+
+			est->i1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI1) << 16) |
+					b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO1);
+			est->q1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI1) << 16) |
+					b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO1);
+			est->iq1_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI1) << 16) |
+					b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO1);
+			return;
+		}
+		udelay(10);
+	}
+	memset(est, 0, sizeof(*est));
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */
+static void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write,
+					struct b43_phy_n_iq_comp *pcomp)
+{
+	if (write) {
+		b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPA0, pcomp->a0);
+		b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPB0, pcomp->b0);
+		b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPA1, pcomp->a1);
+		b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPB1, pcomp->b1);
+	} else {
+		pcomp->a0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPA0);
+		pcomp->b0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPB0);
+		pcomp->a1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPA1);
+		pcomp->b1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPB1);
+	}
+}
+
+#if 0
+/* Ready but not used anywhere */
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */
+static void b43_nphy_rx_cal_phy_cleanup(struct b43_wldev *dev, u8 core)
+{
+	u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
+
+	b43_phy_write(dev, B43_NPHY_RFSEQCA, regs[0]);
+	if (core == 0) {
+		b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[1]);
+		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]);
+	} else {
+		b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]);
+		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]);
+	}
+	b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[3]);
+	b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[4]);
+	b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, regs[5]);
+	b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, regs[6]);
+	b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, regs[7]);
+	b43_phy_write(dev, B43_NPHY_RFCTL_OVER, regs[8]);
+	b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]);
+	b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhySetup */
+static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core)
+{
+	u8 rxval, txval;
+	u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
+
+	regs[0] = b43_phy_read(dev, B43_NPHY_RFSEQCA);
+	if (core == 0) {
+		regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
+		regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
+	} else {
+		regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
+		regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
+	}
+	regs[3] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
+	regs[4] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
+	regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1);
+	regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2);
+	regs[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S1);
+	regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER);
+	regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);
+	regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
+
+	b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
+	b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
+
+	b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
+			~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF,
+			((1 - core) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));
+	b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN,
+			((1 - core) << B43_NPHY_RFSEQCA_TXEN_SHIFT));
+	b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN,
+			(core << B43_NPHY_RFSEQCA_RXEN_SHIFT));
+	b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXDIS,
+			(core << B43_NPHY_RFSEQCA_TXDIS_SHIFT));
+
+	if (core == 0) {
+		b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x0007);
+		b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0007);
+	} else {
+		b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x0007);
+		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0007);
+	}
+
+	b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA, 0, 3);
+	b43_nphy_rf_ctl_override(dev, 8, 0, 3, false);
+	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
+
+	if (core == 0) {
+		rxval = 1;
+		txval = 8;
+	} else {
+		rxval = 4;
+		txval = 2;
+	}
+	b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, rxval,
+				      core + 1);
+	b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, txval,
+				      2 - core);
+}
+#endif
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */
+static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask)
+{
+	int i;
+	s32 iq;
+	u32 ii;
+	u32 qq;
+	int iq_nbits, qq_nbits;
+	int arsh, brsh;
+	u16 tmp, a, b;
+
+	struct nphy_iq_est est;
+	struct b43_phy_n_iq_comp old;
+	struct b43_phy_n_iq_comp new = { };
+	bool error = false;
+
+	if (mask == 0)
+		return;
+
+	b43_nphy_rx_iq_coeffs(dev, false, &old);
+	b43_nphy_rx_iq_coeffs(dev, true, &new);
+	b43_nphy_rx_iq_est(dev, &est, 0x4000, 32, false);
+	new = old;
+
+	for (i = 0; i < 2; i++) {
+		if (i == 0 && (mask & 1)) {
+			iq = est.iq0_prod;
+			ii = est.i0_pwr;
+			qq = est.q0_pwr;
+		} else if (i == 1 && (mask & 2)) {
+			iq = est.iq1_prod;
+			ii = est.i1_pwr;
+			qq = est.q1_pwr;
+		} else {
+			continue;
+		}
+
+		if (ii + qq < 2) {
+			error = true;
+			break;
+		}
+
+		iq_nbits = fls(abs(iq));
+		qq_nbits = fls(qq);
+
+		arsh = iq_nbits - 20;
+		if (arsh >= 0) {
+			a = -((iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
+			tmp = ii >> arsh;
+		} else {
+			a = -((iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
+			tmp = ii << -arsh;
+		}
+		if (tmp == 0) {
+			error = true;
+			break;
+		}
+		a /= tmp;
+
+		brsh = qq_nbits - 11;
+		if (brsh >= 0) {
+			b = (qq << (31 - qq_nbits));
+			tmp = ii >> brsh;
+		} else {
+			b = (qq << (31 - qq_nbits));
+			tmp = ii << -brsh;
+		}
+		if (tmp == 0) {
+			error = true;
+			break;
+		}
+		b = int_sqrt(b / tmp - a * a) - (1 << 10);
+
+		if (i == 0 && (mask & 0x1)) {
+			if (dev->phy.rev >= 3) {
+				new.a0 = a & 0x3FF;
+				new.b0 = b & 0x3FF;
+			} else {
+				new.a0 = b & 0x3FF;
+				new.b0 = a & 0x3FF;
+			}
+		} else if (i == 1 && (mask & 0x2)) {
+			if (dev->phy.rev >= 3) {
+				new.a1 = a & 0x3FF;
+				new.b1 = b & 0x3FF;
+			} else {
+				new.a1 = b & 0x3FF;
+				new.b1 = a & 0x3FF;
+			}
+		}
+	}
+
+	if (error)
+		new = old;
+
+	b43_nphy_rx_iq_coeffs(dev, true, &new);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */
+static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev)
+{
+	u16 array[4];
+	b43_ntab_read_bulk(dev, B43_NTAB16(0xF, 0x50), 4, array);
+
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW0, array[0]);
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW1, array[1]);
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW2, array[2]);
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW3, array[3]);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SpurWar */
+static void b43_nphy_spur_workaround(struct b43_wldev *dev)
+{
+	struct b43_phy_n *nphy = dev->phy.n;
+
+	u8 channel = dev->phy.channel;
+	int tone[2] = { 57, 58 };
+	u32 noise[2] = { 0x3FF, 0x3FF };
+
+	B43_WARN_ON(dev->phy.rev < 3);
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, 1);
+
+	if (nphy->gband_spurwar_en) {
+		/* TODO: N PHY Adjust Analog Pfbw (7) */
+		if (channel == 11 && b43_is_40mhz(dev))
+			; /* TODO: N PHY Adjust Min Noise Var(2, tone, noise)*/
+		else
+			; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/
+		/* TODO: N PHY Adjust CRS Min Power (0x1E) */
+	}
+
+	if (nphy->aband_spurwar_en) {
+		if (channel == 54) {
+			tone[0] = 0x20;
+			noise[0] = 0x25F;
+		} else if (channel == 38 || channel == 102 || channel == 118) {
+			if (0 /* FIXME */) {
+				tone[0] = 0x20;
+				noise[0] = 0x21F;
+			} else {
+				tone[0] = 0;
+				noise[0] = 0;
+			}
+		} else if (channel == 134) {
+			tone[0] = 0x20;
+			noise[0] = 0x21F;
+		} else if (channel == 151) {
+			tone[0] = 0x10;
+			noise[0] = 0x23F;
+		} else if (channel == 153 || channel == 161) {
+			tone[0] = 0x30;
+			noise[0] = 0x23F;
+		} else {
+			tone[0] = 0;
+			noise[0] = 0;
+		}
+
+		if (!tone[0] && !noise[0])
+			; /* TODO: N PHY Adjust Min Noise Var(1, tone, noise)*/
+		else
+			; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/
+	}
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, 0);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */
+static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev)
+{
+	struct b43_phy_n *nphy = dev->phy.n;
+	int i, j;
+	u32 tmp;
+	u32 cur_real, cur_imag, real_part, imag_part;
+
+	u16 buffer[7];
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, true);
+
+	b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
+
+	for (i = 0; i < 2; i++) {
+		tmp = ((buffer[i * 2] & 0x3FF) << 10) |
+			(buffer[i * 2 + 1] & 0x3FF);
+		b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
+				(((i + 26) << 10) | 320));
+		for (j = 0; j < 128; j++) {
+			b43_phy_write(dev, B43_NPHY_TABLE_DATAHI,
+					((tmp >> 16) & 0xFFFF));
+			b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
+					(tmp & 0xFFFF));
+		}
+	}
+
+	for (i = 0; i < 2; i++) {
+		tmp = buffer[5 + i];
+		real_part = (tmp >> 8) & 0xFF;
+		imag_part = (tmp & 0xFF);
+		b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
+				(((i + 26) << 10) | 448));
+
+		if (dev->phy.rev >= 3) {
+			cur_real = real_part;
+			cur_imag = imag_part;
+			tmp = ((cur_real & 0xFF) << 8) | (cur_imag & 0xFF);
+		}
+
+		for (j = 0; j < 128; j++) {
+			if (dev->phy.rev < 3) {
+				cur_real = (real_part * loscale[j] + 128) >> 8;
+				cur_imag = (imag_part * loscale[j] + 128) >> 8;
+				tmp = ((cur_real & 0xFF) << 8) |
+					(cur_imag & 0xFF);
+			}
+			b43_phy_write(dev, B43_NPHY_TABLE_DATAHI,
+					((tmp >> 16) & 0xFFFF));
+			b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
+					(tmp & 0xFFFF));
+		}
+	}
+
+	if (dev->phy.rev >= 3) {
+		b43_shm_write16(dev, B43_SHM_SHARED,
+				B43_SHM_SH_NPHY_TXPWR_INDX0, 0xFFFF);
+		b43_shm_write16(dev, B43_SHM_SHARED,
+				B43_SHM_SH_NPHY_TXPWR_INDX1, 0xFFFF);
+	}
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, false);
+}
+
+/*
+ * Restore RSSI Calibration
+ * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal
+ */
+static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev)
+{
+	struct b43_phy_n *nphy = dev->phy.n;
+
+	u16 *rssical_radio_regs = NULL;
+	u16 *rssical_phy_regs = NULL;
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+		if (!nphy->rssical_chanspec_2G.center_freq)
+			return;
+		rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G;
+		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G;
+	} else {
+		if (!nphy->rssical_chanspec_5G.center_freq)
+			return;
+		rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G;
+		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
+	}
+
+	if (dev->phy.rev >= 19) {
+		/* TODO */
+	} else if (dev->phy.rev >= 7) {
+		b43_radio_maskset(dev, R2057_NB_MASTER_CORE0, ~R2057_VCM_MASK,
+				  rssical_radio_regs[0]);
+		b43_radio_maskset(dev, R2057_NB_MASTER_CORE1, ~R2057_VCM_MASK,
+				  rssical_radio_regs[1]);
+	} else {
+		b43_radio_maskset(dev, B2056_RX0 | B2056_RX_RSSI_MISC, 0xE3,
+				  rssical_radio_regs[0]);
+		b43_radio_maskset(dev, B2056_RX1 | B2056_RX_RSSI_MISC, 0xE3,
+				  rssical_radio_regs[1]);
+	}
+
+	b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, rssical_phy_regs[0]);
+	b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, rssical_phy_regs[1]);
+	b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, rssical_phy_regs[2]);
+	b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, rssical_phy_regs[3]);
+
+	b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, rssical_phy_regs[4]);
+	b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, rssical_phy_regs[5]);
+	b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, rssical_phy_regs[6]);
+	b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, rssical_phy_regs[7]);
+
+	b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, rssical_phy_regs[8]);
+	b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, rssical_phy_regs[9]);
+	b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, rssical_phy_regs[10]);
+	b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]);
+}
+
+static void b43_nphy_tx_cal_radio_setup_rev19(struct b43_wldev *dev)
+{
+	/* TODO */
+}
+
+static void b43_nphy_tx_cal_radio_setup_rev7(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = dev->phy.n;
+	u16 *save = nphy->tx_rx_cal_radio_saveregs;
+	int core, off;
+	u16 r, tmp;
+
+	for (core = 0; core < 2; core++) {
+		r = core ? 0x20 : 0;
+		off = core * 11;
+
+		save[off + 0] = b43_radio_read(dev, r + R2057_TX0_TX_SSI_MASTER);
+		save[off + 1] = b43_radio_read(dev, r + R2057_TX0_IQCAL_VCM_HG);
+		save[off + 2] = b43_radio_read(dev, r + R2057_TX0_IQCAL_IDAC);
+		save[off + 3] = b43_radio_read(dev, r + R2057_TX0_TSSI_VCM);
+		save[off + 4] = 0;
+		save[off + 5] = b43_radio_read(dev, r + R2057_TX0_TX_SSI_MUX);
+		if (phy->radio_rev != 5)
+			save[off + 6] = b43_radio_read(dev, r + R2057_TX0_TSSIA);
+		save[off + 7] = b43_radio_read(dev, r + R2057_TX0_TSSIG);
+		save[off + 8] = b43_radio_read(dev, r + R2057_TX0_TSSI_MISC1);
+
+		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
+			b43_radio_write(dev, r + R2057_TX0_TX_SSI_MASTER, 0xA);
+			b43_radio_write(dev, r + R2057_TX0_IQCAL_VCM_HG, 0x43);
+			b43_radio_write(dev, r + R2057_TX0_IQCAL_IDAC, 0x55);
+			b43_radio_write(dev, r + R2057_TX0_TSSI_VCM, 0);
+			b43_radio_write(dev, r + R2057_TX0_TSSIG, 0);
+			if (nphy->use_int_tx_iq_lo_cal) {
+				b43_radio_write(dev, r + R2057_TX0_TX_SSI_MUX, 0x4);
+				tmp = true ? 0x31 : 0x21; /* TODO */
+				b43_radio_write(dev, r + R2057_TX0_TSSIA, tmp);
+			}
+			b43_radio_write(dev, r + R2057_TX0_TSSI_MISC1, 0x00);
+		} else {
+			b43_radio_write(dev, r + R2057_TX0_TX_SSI_MASTER, 0x6);
+			b43_radio_write(dev, r + R2057_TX0_IQCAL_VCM_HG, 0x43);
+			b43_radio_write(dev, r + R2057_TX0_IQCAL_IDAC, 0x55);
+			b43_radio_write(dev, r + R2057_TX0_TSSI_VCM, 0);
+
+			if (phy->radio_rev != 5)
+				b43_radio_write(dev, r + R2057_TX0_TSSIA, 0);
+			if (nphy->use_int_tx_iq_lo_cal) {
+				b43_radio_write(dev, r + R2057_TX0_TX_SSI_MUX, 0x6);
+				tmp = true ? 0x31 : 0x21; /* TODO */
+				b43_radio_write(dev, r + R2057_TX0_TSSIG, tmp);
+			}
+			b43_radio_write(dev, r + R2057_TX0_TSSI_MISC1, 0);
+		}
+	}
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */
+static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = dev->phy.n;
+	u16 *save = nphy->tx_rx_cal_radio_saveregs;
+	u16 tmp;
+	u8 offset, i;
+
+	if (phy->rev >= 19) {
+		b43_nphy_tx_cal_radio_setup_rev19(dev);
+	} else if (phy->rev >= 7) {
+		b43_nphy_tx_cal_radio_setup_rev7(dev);
+	} else if (phy->rev >= 3) {
+	    for (i = 0; i < 2; i++) {
+		tmp = (i == 0) ? 0x2000 : 0x3000;
+		offset = i * 11;
+
+		save[offset + 0] = b43_radio_read(dev, B2055_CAL_RVARCTL);
+		save[offset + 1] = b43_radio_read(dev, B2055_CAL_LPOCTL);
+		save[offset + 2] = b43_radio_read(dev, B2055_CAL_TS);
+		save[offset + 3] = b43_radio_read(dev, B2055_CAL_RCCALRTS);
+		save[offset + 4] = b43_radio_read(dev, B2055_CAL_RCALRTS);
+		save[offset + 5] = b43_radio_read(dev, B2055_PADDRV);
+		save[offset + 6] = b43_radio_read(dev, B2055_XOCTL1);
+		save[offset + 7] = b43_radio_read(dev, B2055_XOCTL2);
+		save[offset + 8] = b43_radio_read(dev, B2055_XOREGUL);
+		save[offset + 9] = b43_radio_read(dev, B2055_XOMISC);
+		save[offset + 10] = b43_radio_read(dev, B2055_PLL_LFC1);
+
+		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
+			b43_radio_write(dev, tmp | B2055_CAL_RVARCTL, 0x0A);
+			b43_radio_write(dev, tmp | B2055_CAL_LPOCTL, 0x40);
+			b43_radio_write(dev, tmp | B2055_CAL_TS, 0x55);
+			b43_radio_write(dev, tmp | B2055_CAL_RCCALRTS, 0);
+			b43_radio_write(dev, tmp | B2055_CAL_RCALRTS, 0);
+			if (nphy->ipa5g_on) {
+				b43_radio_write(dev, tmp | B2055_PADDRV, 4);
+				b43_radio_write(dev, tmp | B2055_XOCTL1, 1);
+			} else {
+				b43_radio_write(dev, tmp | B2055_PADDRV, 0);
+				b43_radio_write(dev, tmp | B2055_XOCTL1, 0x2F);
+			}
+			b43_radio_write(dev, tmp | B2055_XOCTL2, 0);
+		} else {
+			b43_radio_write(dev, tmp | B2055_CAL_RVARCTL, 0x06);
+			b43_radio_write(dev, tmp | B2055_CAL_LPOCTL, 0x40);
+			b43_radio_write(dev, tmp | B2055_CAL_TS, 0x55);
+			b43_radio_write(dev, tmp | B2055_CAL_RCCALRTS, 0);
+			b43_radio_write(dev, tmp | B2055_CAL_RCALRTS, 0);
+			b43_radio_write(dev, tmp | B2055_XOCTL1, 0);
+			if (nphy->ipa2g_on) {
+				b43_radio_write(dev, tmp | B2055_PADDRV, 6);
+				b43_radio_write(dev, tmp | B2055_XOCTL2,
+					(dev->phy.rev < 5) ? 0x11 : 0x01);
+			} else {
+				b43_radio_write(dev, tmp | B2055_PADDRV, 0);
+				b43_radio_write(dev, tmp | B2055_XOCTL2, 0);
+			}
+		}
+		b43_radio_write(dev, tmp | B2055_XOREGUL, 0);
+		b43_radio_write(dev, tmp | B2055_XOMISC, 0);
+		b43_radio_write(dev, tmp | B2055_PLL_LFC1, 0);
+	    }
+	} else {
+		save[0] = b43_radio_read(dev, B2055_C1_TX_RF_IQCAL1);
+		b43_radio_write(dev, B2055_C1_TX_RF_IQCAL1, 0x29);
+
+		save[1] = b43_radio_read(dev, B2055_C1_TX_RF_IQCAL2);
+		b43_radio_write(dev, B2055_C1_TX_RF_IQCAL2, 0x54);
+
+		save[2] = b43_radio_read(dev, B2055_C2_TX_RF_IQCAL1);
+		b43_radio_write(dev, B2055_C2_TX_RF_IQCAL1, 0x29);
+
+		save[3] = b43_radio_read(dev, B2055_C2_TX_RF_IQCAL2);
+		b43_radio_write(dev, B2055_C2_TX_RF_IQCAL2, 0x54);
+
+		save[3] = b43_radio_read(dev, B2055_C1_PWRDET_RXTX);
+		save[4] = b43_radio_read(dev, B2055_C2_PWRDET_RXTX);
+
+		if (!(b43_phy_read(dev, B43_NPHY_BANDCTL) &
+		    B43_NPHY_BANDCTL_5GHZ)) {
+			b43_radio_write(dev, B2055_C1_PWRDET_RXTX, 0x04);
+			b43_radio_write(dev, B2055_C2_PWRDET_RXTX, 0x04);
+		} else {
+			b43_radio_write(dev, B2055_C1_PWRDET_RXTX, 0x20);
+			b43_radio_write(dev, B2055_C2_PWRDET_RXTX, 0x20);
+		}
+
+		if (dev->phy.rev < 2) {
+			b43_radio_set(dev, B2055_C1_TX_BB_MXGM, 0x20);
+			b43_radio_set(dev, B2055_C2_TX_BB_MXGM, 0x20);
+		} else {
+			b43_radio_mask(dev, B2055_C1_TX_BB_MXGM, ~0x20);
+			b43_radio_mask(dev, B2055_C2_TX_BB_MXGM, ~0x20);
+		}
+	}
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */
+static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core)
+{
+	struct b43_phy_n *nphy = dev->phy.n;
+	int i;
+	u16 scale, entry;
+
+	u16 tmp = nphy->txcal_bbmult;
+	if (core == 0)
+		tmp >>= 8;
+	tmp &= 0xff;
+
+	for (i = 0; i < 18; i++) {
+		scale = (ladder_lo[i].percent * tmp) / 100;
+		entry = ((scale & 0xFF) << 8) | ladder_lo[i].g_env;
+		b43_ntab_write(dev, B43_NTAB16(15, i), entry);
+
+		scale = (ladder_iq[i].percent * tmp) / 100;
+		entry = ((scale & 0xFF) << 8) | ladder_iq[i].g_env;
+		b43_ntab_write(dev, B43_NTAB16(15, i + 32), entry);
+	}
+}
+
+static void b43_nphy_pa_set_tx_dig_filter(struct b43_wldev *dev, u16 offset,
+					  const s16 *filter)
+{
+	int i;
+
+	offset = B43_PHY_N(offset);
+
+	for (i = 0; i < 15; i++, offset++)
+		b43_phy_write(dev, offset, filter[i]);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */
+static void b43_nphy_ext_pa_set_tx_dig_filters(struct b43_wldev *dev)
+{
+	b43_nphy_pa_set_tx_dig_filter(dev, 0x2C5,
+				      tbl_tx_filter_coef_rev4[2]);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */
+static void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev)
+{
+	/* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */
+	static const u16 offset[] = { 0x186, 0x195, 0x2C5 };
+	static const s16 dig_filter_phy_rev16[] = {
+		-375, 136, -407, 208, -1527,
+		956, 93, 186, 93, 230,
+		-44, 230, 201, -191, 201,
+	};
+	int i;
+
+	for (i = 0; i < 3; i++)
+		b43_nphy_pa_set_tx_dig_filter(dev, offset[i],
+					      tbl_tx_filter_coef_rev4[i]);
+
+	/* Verified with BCM43227 and BCM43228 */
+	if (dev->phy.rev == 16)
+		b43_nphy_pa_set_tx_dig_filter(dev, 0x186, dig_filter_phy_rev16);
+
+	/* Verified with BCM43131 and BCM43217 */
+	if (dev->phy.rev == 17) {
+		b43_nphy_pa_set_tx_dig_filter(dev, 0x186, dig_filter_phy_rev16);
+		b43_nphy_pa_set_tx_dig_filter(dev, 0x195,
+					      tbl_tx_filter_coef_rev4[1]);
+	}
+
+	if (b43_is_40mhz(dev)) {
+		b43_nphy_pa_set_tx_dig_filter(dev, 0x186,
+					      tbl_tx_filter_coef_rev4[3]);
+	} else {
+		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
+			b43_nphy_pa_set_tx_dig_filter(dev, 0x186,
+						      tbl_tx_filter_coef_rev4[5]);
+		if (dev->phy.channel == 14)
+			b43_nphy_pa_set_tx_dig_filter(dev, 0x186,
+						      tbl_tx_filter_coef_rev4[6]);
+	}
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */
+static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev)
+{
+	struct b43_phy_n *nphy = dev->phy.n;
+
+	u16 curr_gain[2];
+	struct nphy_txgains target;
+	const u32 *table = NULL;
+
+	if (!nphy->txpwrctrl) {
+		int i;
+
+		if (nphy->hang_avoid)
+			b43_nphy_stay_in_carrier_search(dev, true);
+		b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, curr_gain);
+		if (nphy->hang_avoid)
+			b43_nphy_stay_in_carrier_search(dev, false);
+
+		for (i = 0; i < 2; ++i) {
+			if (dev->phy.rev >= 7) {
+				target.ipa[i] = curr_gain[i] & 0x0007;
+				target.pad[i] = (curr_gain[i] & 0x00F8) >> 3;
+				target.pga[i] = (curr_gain[i] & 0x0F00) >> 8;
+				target.txgm[i] = (curr_gain[i] & 0x7000) >> 12;
+				target.tx_lpf[i] = (curr_gain[i] & 0x8000) >> 15;
+			} else if (dev->phy.rev >= 3) {
+				target.ipa[i] = curr_gain[i] & 0x000F;
+				target.pad[i] = (curr_gain[i] & 0x00F0) >> 4;
+				target.pga[i] = (curr_gain[i] & 0x0F00) >> 8;
+				target.txgm[i] = (curr_gain[i] & 0x7000) >> 12;
+			} else {
+				target.ipa[i] = curr_gain[i] & 0x0003;
+				target.pad[i] = (curr_gain[i] & 0x000C) >> 2;
+				target.pga[i] = (curr_gain[i] & 0x0070) >> 4;
+				target.txgm[i] = (curr_gain[i] & 0x0380) >> 7;
+			}
+		}
+	} else {
+		int i;
+		u16 index[2];
+		index[0] = (b43_phy_read(dev, B43_NPHY_C1_TXPCTL_STAT) &
+			B43_NPHY_TXPCTL_STAT_BIDX) >>
+			B43_NPHY_TXPCTL_STAT_BIDX_SHIFT;
+		index[1] = (b43_phy_read(dev, B43_NPHY_C2_TXPCTL_STAT) &
+			B43_NPHY_TXPCTL_STAT_BIDX) >>
+			B43_NPHY_TXPCTL_STAT_BIDX_SHIFT;
+
+		for (i = 0; i < 2; ++i) {
+			table = b43_nphy_get_tx_gain_table(dev);
+			if (!table)
+				break;
+
+			if (dev->phy.rev >= 7) {
+				target.ipa[i] = (table[index[i]] >> 16) & 0x7;
+				target.pad[i] = (table[index[i]] >> 19) & 0x1F;
+				target.pga[i] = (table[index[i]] >> 24) & 0xF;
+				target.txgm[i] = (table[index[i]] >> 28) & 0x7;
+				target.tx_lpf[i] = (table[index[i]] >> 31) & 0x1;
+			} else if (dev->phy.rev >= 3) {
+				target.ipa[i] = (table[index[i]] >> 16) & 0xF;
+				target.pad[i] = (table[index[i]] >> 20) & 0xF;
+				target.pga[i] = (table[index[i]] >> 24) & 0xF;
+				target.txgm[i] = (table[index[i]] >> 28) & 0xF;
+			} else {
+				target.ipa[i] = (table[index[i]] >> 16) & 0x3;
+				target.pad[i] = (table[index[i]] >> 18) & 0x3;
+				target.pga[i] = (table[index[i]] >> 20) & 0x7;
+				target.txgm[i] = (table[index[i]] >> 23) & 0x7;
+			}
+		}
+	}
+
+	return target;
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhyCleanup */
+static void b43_nphy_tx_cal_phy_cleanup(struct b43_wldev *dev)
+{
+	u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
+
+	if (dev->phy.rev >= 3) {
+		b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[0]);
+		b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]);
+		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]);
+		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[3]);
+		b43_phy_write(dev, B43_NPHY_BBCFG, regs[4]);
+		b43_ntab_write(dev, B43_NTAB16(8, 3), regs[5]);
+		b43_ntab_write(dev, B43_NTAB16(8, 19), regs[6]);
+		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[7]);
+		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[8]);
+		b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]);
+		b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]);
+		b43_nphy_reset_cca(dev);
+	} else {
+		b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, regs[0]);
+		b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, regs[1]);
+		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]);
+		b43_ntab_write(dev, B43_NTAB16(8, 2), regs[3]);
+		b43_ntab_write(dev, B43_NTAB16(8, 18), regs[4]);
+		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[5]);
+		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[6]);
+	}
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */
+static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = dev->phy.n;
+	u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
+	u16 tmp;
+
+	regs[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
+	regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
+	if (dev->phy.rev >= 3) {
+		b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0xF0FF, 0x0A00);
+		b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0xF0FF, 0x0A00);
+
+		tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
+		regs[2] = tmp;
+		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, tmp | 0x0600);
+
+		tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
+		regs[3] = tmp;
+		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x0600);
+
+		regs[4] = b43_phy_read(dev, B43_NPHY_BBCFG);
+		b43_phy_mask(dev, B43_NPHY_BBCFG,
+			     ~B43_NPHY_BBCFG_RSTRX & 0xFFFF);
+
+		tmp = b43_ntab_read(dev, B43_NTAB16(8, 3));
+		regs[5] = tmp;
+		b43_ntab_write(dev, B43_NTAB16(8, 3), 0);
+
+		tmp = b43_ntab_read(dev, B43_NTAB16(8, 19));
+		regs[6] = tmp;
+		b43_ntab_write(dev, B43_NTAB16(8, 19), 0);
+		regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
+		regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
+
+		if (!nphy->use_int_tx_iq_lo_cal)
+			b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA,
+						      1, 3);
+		else
+			b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA,
+						      0, 3);
+		b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 2, 1);
+		b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 8, 2);
+
+		regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);
+		regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
+		b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
+		b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
+
+		tmp = b43_nphy_read_lpf_ctl(dev, 0);
+		if (phy->rev >= 19)
+			b43_nphy_rf_ctl_override_rev19(dev, 0x80, tmp, 0, false,
+						       1);
+		else if (phy->rev >= 7)
+			b43_nphy_rf_ctl_override_rev7(dev, 0x80, tmp, 0, false,
+						      1);
+
+		if (nphy->use_int_tx_iq_lo_cal && true /* FIXME */) {
+			if (phy->rev >= 19) {
+				b43_nphy_rf_ctl_override_rev19(dev, 0x8, 0, 0x3,
+							       false, 0);
+			} else if (phy->rev >= 8) {
+				b43_nphy_rf_ctl_override_rev7(dev, 0x8, 0, 0x3,
+							      false, 0);
+			} else if (phy->rev == 7) {
+				b43_radio_maskset(dev, R2057_OVR_REG0, 1 << 4, 1 << 4);
+				if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+					b43_radio_maskset(dev, R2057_PAD2G_TUNE_PUS_CORE0, ~1, 0);
+					b43_radio_maskset(dev, R2057_PAD2G_TUNE_PUS_CORE1, ~1, 0);
+				} else {
+					b43_radio_maskset(dev, R2057_IPA5G_CASCOFFV_PU_CORE0, ~1, 0);
+					b43_radio_maskset(dev, R2057_IPA5G_CASCOFFV_PU_CORE1, ~1, 0);
+				}
+			}
+		}
+	} else {
+		b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, 0xA000);
+		b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, 0xA000);
+		tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
+		regs[2] = tmp;
+		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x3000);
+		tmp = b43_ntab_read(dev, B43_NTAB16(8, 2));
+		regs[3] = tmp;
+		tmp |= 0x2000;
+		b43_ntab_write(dev, B43_NTAB16(8, 2), tmp);
+		tmp = b43_ntab_read(dev, B43_NTAB16(8, 18));
+		regs[4] = tmp;
+		tmp |= 0x2000;
+		b43_ntab_write(dev, B43_NTAB16(8, 18), tmp);
+		regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
+		regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
+		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
+			tmp = 0x0180;
+		else
+			tmp = 0x0120;
+		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp);
+		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp);
+	}
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */
+static void b43_nphy_save_cal(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = dev->phy.n;
+
+	struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
+	u16 *txcal_radio_regs = NULL;
+	struct b43_chanspec *iqcal_chanspec;
+	u16 *table = NULL;
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, 1);
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G;
+		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G;
+		iqcal_chanspec = &nphy->iqcal_chanspec_2G;
+		table = nphy->cal_cache.txcal_coeffs_2G;
+	} else {
+		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G;
+		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G;
+		iqcal_chanspec = &nphy->iqcal_chanspec_5G;
+		table = nphy->cal_cache.txcal_coeffs_5G;
+	}
+
+	b43_nphy_rx_iq_coeffs(dev, false, rxcal_coeffs);
+	/* TODO use some definitions */
+	if (phy->rev >= 19) {
+		/* TODO */
+	} else if (phy->rev >= 7) {
+		txcal_radio_regs[0] = b43_radio_read(dev,
+						     R2057_TX0_LOFT_FINE_I);
+		txcal_radio_regs[1] = b43_radio_read(dev,
+						     R2057_TX0_LOFT_FINE_Q);
+		txcal_radio_regs[4] = b43_radio_read(dev,
+						     R2057_TX0_LOFT_COARSE_I);
+		txcal_radio_regs[5] = b43_radio_read(dev,
+						     R2057_TX0_LOFT_COARSE_Q);
+		txcal_radio_regs[2] = b43_radio_read(dev,
+						     R2057_TX1_LOFT_FINE_I);
+		txcal_radio_regs[3] = b43_radio_read(dev,
+						     R2057_TX1_LOFT_FINE_Q);
+		txcal_radio_regs[6] = b43_radio_read(dev,
+						     R2057_TX1_LOFT_COARSE_I);
+		txcal_radio_regs[7] = b43_radio_read(dev,
+						     R2057_TX1_LOFT_COARSE_Q);
+	} else if (phy->rev >= 3) {
+		txcal_radio_regs[0] = b43_radio_read(dev, 0x2021);
+		txcal_radio_regs[1] = b43_radio_read(dev, 0x2022);
+		txcal_radio_regs[2] = b43_radio_read(dev, 0x3021);
+		txcal_radio_regs[3] = b43_radio_read(dev, 0x3022);
+		txcal_radio_regs[4] = b43_radio_read(dev, 0x2023);
+		txcal_radio_regs[5] = b43_radio_read(dev, 0x2024);
+		txcal_radio_regs[6] = b43_radio_read(dev, 0x3023);
+		txcal_radio_regs[7] = b43_radio_read(dev, 0x3024);
+	} else {
+		txcal_radio_regs[0] = b43_radio_read(dev, 0x8B);
+		txcal_radio_regs[1] = b43_radio_read(dev, 0xBA);
+		txcal_radio_regs[2] = b43_radio_read(dev, 0x8D);
+		txcal_radio_regs[3] = b43_radio_read(dev, 0xBC);
+	}
+	iqcal_chanspec->center_freq = dev->phy.chandef->chan->center_freq;
+	iqcal_chanspec->channel_type =
+				cfg80211_get_chandef_type(dev->phy.chandef);
+	b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 8, table);
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, 0);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */
+static void b43_nphy_restore_cal(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = dev->phy.n;
+
+	u16 coef[4];
+	u16 *loft = NULL;
+	u16 *table = NULL;
+
+	int i;
+	u16 *txcal_radio_regs = NULL;
+	struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+		if (!nphy->iqcal_chanspec_2G.center_freq)
+			return;
+		table = nphy->cal_cache.txcal_coeffs_2G;
+		loft = &nphy->cal_cache.txcal_coeffs_2G[5];
+	} else {
+		if (!nphy->iqcal_chanspec_5G.center_freq)
+			return;
+		table = nphy->cal_cache.txcal_coeffs_5G;
+		loft = &nphy->cal_cache.txcal_coeffs_5G[5];
+	}
+
+	b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4, table);
+
+	for (i = 0; i < 4; i++) {
+		if (dev->phy.rev >= 3)
+			table[i] = coef[i];
+		else
+			coef[i] = 0;
+	}
+
+	b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, coef);
+	b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, loft);
+	b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2, loft);
+
+	if (dev->phy.rev < 2)
+		b43_nphy_tx_iq_workaround(dev);
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G;
+		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G;
+	} else {
+		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G;
+		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G;
+	}
+
+	/* TODO use some definitions */
+	if (phy->rev >= 19) {
+		/* TODO */
+	} else if (phy->rev >= 7) {
+		b43_radio_write(dev, R2057_TX0_LOFT_FINE_I,
+				txcal_radio_regs[0]);
+		b43_radio_write(dev, R2057_TX0_LOFT_FINE_Q,
+				txcal_radio_regs[1]);
+		b43_radio_write(dev, R2057_TX0_LOFT_COARSE_I,
+				txcal_radio_regs[4]);
+		b43_radio_write(dev, R2057_TX0_LOFT_COARSE_Q,
+				txcal_radio_regs[5]);
+		b43_radio_write(dev, R2057_TX1_LOFT_FINE_I,
+				txcal_radio_regs[2]);
+		b43_radio_write(dev, R2057_TX1_LOFT_FINE_Q,
+				txcal_radio_regs[3]);
+		b43_radio_write(dev, R2057_TX1_LOFT_COARSE_I,
+				txcal_radio_regs[6]);
+		b43_radio_write(dev, R2057_TX1_LOFT_COARSE_Q,
+				txcal_radio_regs[7]);
+	} else if (phy->rev >= 3) {
+		b43_radio_write(dev, 0x2021, txcal_radio_regs[0]);
+		b43_radio_write(dev, 0x2022, txcal_radio_regs[1]);
+		b43_radio_write(dev, 0x3021, txcal_radio_regs[2]);
+		b43_radio_write(dev, 0x3022, txcal_radio_regs[3]);
+		b43_radio_write(dev, 0x2023, txcal_radio_regs[4]);
+		b43_radio_write(dev, 0x2024, txcal_radio_regs[5]);
+		b43_radio_write(dev, 0x3023, txcal_radio_regs[6]);
+		b43_radio_write(dev, 0x3024, txcal_radio_regs[7]);
+	} else {
+		b43_radio_write(dev, 0x8B, txcal_radio_regs[0]);
+		b43_radio_write(dev, 0xBA, txcal_radio_regs[1]);
+		b43_radio_write(dev, 0x8D, txcal_radio_regs[2]);
+		b43_radio_write(dev, 0xBC, txcal_radio_regs[3]);
+	}
+	b43_nphy_rx_iq_coeffs(dev, true, rxcal_coeffs);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalTxIqlo */
+static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
+				struct nphy_txgains target,
+				bool full, bool mphase)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = dev->phy.n;
+	int i;
+	int error = 0;
+	int freq;
+	bool avoid = false;
+	u8 length;
+	u16 tmp, core, type, count, max, numb, last = 0, cmd;
+	const u16 *table;
+	bool phy6or5x;
+
+	u16 buffer[11];
+	u16 diq_start = 0;
+	u16 save[2];
+	u16 gain[2];
+	struct nphy_iqcal_params params[2];
+	bool updated[2] = { };
+
+	b43_nphy_stay_in_carrier_search(dev, true);
+
+	if (dev->phy.rev >= 4) {
+		avoid = nphy->hang_avoid;
+		nphy->hang_avoid = false;
+	}
+
+	b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, save);
+
+	for (i = 0; i < 2; i++) {
+		b43_nphy_iq_cal_gain_params(dev, i, target, &params[i]);
+		gain[i] = params[i].cal_gain;
+	}
+
+	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain);
+
+	b43_nphy_tx_cal_radio_setup(dev);
+	b43_nphy_tx_cal_phy_setup(dev);
+
+	phy6or5x = dev->phy.rev >= 6 ||
+		(dev->phy.rev == 5 && nphy->ipa2g_on &&
+		b43_current_band(dev->wl) == NL80211_BAND_2GHZ);
+	if (phy6or5x) {
+		if (b43_is_40mhz(dev)) {
+			b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18,
+					tbl_tx_iqlo_cal_loft_ladder_40);
+			b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18,
+					tbl_tx_iqlo_cal_iqimb_ladder_40);
+		} else {
+			b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18,
+					tbl_tx_iqlo_cal_loft_ladder_20);
+			b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18,
+					tbl_tx_iqlo_cal_iqimb_ladder_20);
+		}
+	}
+
+	if (phy->rev >= 19) {
+		/* TODO */
+	} else if (phy->rev >= 7) {
+		b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AD9);
+	} else {
+		b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9);
+	}
+
+	if (!b43_is_40mhz(dev))
+		freq = 2500;
+	else
+		freq = 5000;
+
+	if (nphy->mphase_cal_phase_id > 2)
+		b43_nphy_run_samples(dev, (b43_is_40mhz(dev) ? 40 : 20) * 8,
+				     0xFFFF, 0, true, false, false);
+	else
+		error = b43_nphy_tx_tone(dev, freq, 250, true, false, false);
+
+	if (error == 0) {
+		if (nphy->mphase_cal_phase_id > 2) {
+			table = nphy->mphase_txcal_bestcoeffs;
+			length = 11;
+			if (dev->phy.rev < 3)
+				length -= 2;
+		} else {
+			if (!full && nphy->txiqlocal_coeffsvalid) {
+				table = nphy->txiqlocal_bestc;
+				length = 11;
+				if (dev->phy.rev < 3)
+					length -= 2;
+			} else {
+				full = true;
+				if (dev->phy.rev >= 3) {
+					table = tbl_tx_iqlo_cal_startcoefs_nphyrev3;
+					length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3;
+				} else {
+					table = tbl_tx_iqlo_cal_startcoefs;
+					length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS;
+				}
+			}
+		}
+
+		b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length, table);
+
+		if (full) {
+			if (dev->phy.rev >= 3)
+				max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3;
+			else
+				max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL;
+		} else {
+			if (dev->phy.rev >= 3)
+				max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3;
+			else
+				max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL;
+		}
+
+		if (mphase) {
+			count = nphy->mphase_txcal_cmdidx;
+			numb = min(max,
+				(u16)(count + nphy->mphase_txcal_numcmds));
+		} else {
+			count = 0;
+			numb = max;
+		}
+
+		for (; count < numb; count++) {
+			if (full) {
+				if (dev->phy.rev >= 3)
+					cmd = tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[count];
+				else
+					cmd = tbl_tx_iqlo_cal_cmds_fullcal[count];
+			} else {
+				if (dev->phy.rev >= 3)
+					cmd = tbl_tx_iqlo_cal_cmds_recal_nphyrev3[count];
+				else
+					cmd = tbl_tx_iqlo_cal_cmds_recal[count];
+			}
+
+			core = (cmd & 0x3000) >> 12;
+			type = (cmd & 0x0F00) >> 8;
+
+			if (phy6or5x && updated[core] == 0) {
+				b43_nphy_update_tx_cal_ladder(dev, core);
+				updated[core] = true;
+			}
+
+			tmp = (params[core].ncorr[type] << 8) | 0x66;
+			b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDNNUM, tmp);
+
+			if (type == 1 || type == 3 || type == 4) {
+				buffer[0] = b43_ntab_read(dev,
+						B43_NTAB16(15, 69 + core));
+				diq_start = buffer[0];
+				buffer[0] = 0;
+				b43_ntab_write(dev, B43_NTAB16(15, 69 + core),
+						0);
+			}
+
+			b43_phy_write(dev, B43_NPHY_IQLOCAL_CMD, cmd);
+			for (i = 0; i < 2000; i++) {
+				tmp = b43_phy_read(dev, B43_NPHY_IQLOCAL_CMD);
+				if (tmp & 0xC000)
+					break;
+				udelay(10);
+			}
+
+			b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
+						buffer);
+			b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length,
+						buffer);
+
+			if (type == 1 || type == 3 || type == 4)
+				buffer[0] = diq_start;
+		}
+
+		if (mphase)
+			nphy->mphase_txcal_cmdidx = (numb >= max) ? 0 : numb;
+
+		last = (dev->phy.rev < 3) ? 6 : 7;
+
+		if (!mphase || nphy->mphase_cal_phase_id == last) {
+			b43_ntab_write_bulk(dev, B43_NTAB16(15, 96), 4, buffer);
+			b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 4, buffer);
+			if (dev->phy.rev < 3) {
+				buffer[0] = 0;
+				buffer[1] = 0;
+				buffer[2] = 0;
+				buffer[3] = 0;
+			}
+			b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4,
+						buffer);
+			b43_ntab_read_bulk(dev, B43_NTAB16(15, 101), 2,
+						buffer);
+			b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2,
+						buffer);
+			b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2,
+						buffer);
+			length = 11;
+			if (dev->phy.rev < 3)
+				length -= 2;
+			b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
+						nphy->txiqlocal_bestc);
+			nphy->txiqlocal_coeffsvalid = true;
+			nphy->txiqlocal_chanspec.center_freq =
+						phy->chandef->chan->center_freq;
+			nphy->txiqlocal_chanspec.channel_type =
+					cfg80211_get_chandef_type(phy->chandef);
+		} else {
+			length = 11;
+			if (dev->phy.rev < 3)
+				length -= 2;
+			b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
+						nphy->mphase_txcal_bestcoeffs);
+		}
+
+		b43_nphy_stop_playback(dev);
+		b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0);
+	}
+
+	b43_nphy_tx_cal_phy_cleanup(dev);
+	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, save);
+
+	if (dev->phy.rev < 2 && (!mphase || nphy->mphase_cal_phase_id == last))
+		b43_nphy_tx_iq_workaround(dev);
+
+	if (dev->phy.rev >= 4)
+		nphy->hang_avoid = avoid;
+
+	b43_nphy_stay_in_carrier_search(dev, false);
+
+	return error;
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ReapplyTxCalCoeffs */
+static void b43_nphy_reapply_tx_cal_coeffs(struct b43_wldev *dev)
+{
+	struct b43_phy_n *nphy = dev->phy.n;
+	u8 i;
+	u16 buffer[7];
+	bool equal = true;
+
+	if (!nphy->txiqlocal_coeffsvalid ||
+	    nphy->txiqlocal_chanspec.center_freq != dev->phy.chandef->chan->center_freq ||
+	    nphy->txiqlocal_chanspec.channel_type != cfg80211_get_chandef_type(dev->phy.chandef))
+		return;
+
+	b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
+	for (i = 0; i < 4; i++) {
+		if (buffer[i] != nphy->txiqlocal_bestc[i]) {
+			equal = false;
+			break;
+		}
+	}
+
+	if (!equal) {
+		b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4,
+					nphy->txiqlocal_bestc);
+		for (i = 0; i < 4; i++)
+			buffer[i] = 0;
+		b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4,
+					buffer);
+		b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2,
+					&nphy->txiqlocal_bestc[5]);
+		b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2,
+					&nphy->txiqlocal_bestc[5]);
+	}
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIqRev2 */
+static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,
+			struct nphy_txgains target, u8 type, bool debug)
+{
+	struct b43_phy_n *nphy = dev->phy.n;
+	int i, j, index;
+	u8 rfctl[2];
+	u8 afectl_core;
+	u16 tmp[6];
+	u16 uninitialized_var(cur_hpf1), uninitialized_var(cur_hpf2), cur_lna;
+	u32 real, imag;
+	enum nl80211_band band;
+
+	u8 use;
+	u16 cur_hpf;
+	u16 lna[3] = { 3, 3, 1 };
+	u16 hpf1[3] = { 7, 2, 0 };
+	u16 hpf2[3] = { 2, 0, 0 };
+	u32 power[3] = { };
+	u16 gain_save[2];
+	u16 cal_gain[2];
+	struct nphy_iqcal_params cal_params[2];
+	struct nphy_iq_est est;
+	int ret = 0;
+	bool playtone = true;
+	int desired = 13;
+
+	b43_nphy_stay_in_carrier_search(dev, 1);
+
+	if (dev->phy.rev < 2)
+		b43_nphy_reapply_tx_cal_coeffs(dev);
+	b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save);
+	for (i = 0; i < 2; i++) {
+		b43_nphy_iq_cal_gain_params(dev, i, target, &cal_params[i]);
+		cal_gain[i] = cal_params[i].cal_gain;
+	}
+	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, cal_gain);
+
+	for (i = 0; i < 2; i++) {
+		if (i == 0) {
+			rfctl[0] = B43_NPHY_RFCTL_INTC1;
+			rfctl[1] = B43_NPHY_RFCTL_INTC2;
+			afectl_core = B43_NPHY_AFECTL_C1;
+		} else {
+			rfctl[0] = B43_NPHY_RFCTL_INTC2;
+			rfctl[1] = B43_NPHY_RFCTL_INTC1;
+			afectl_core = B43_NPHY_AFECTL_C2;
+		}
+
+		tmp[1] = b43_phy_read(dev, B43_NPHY_RFSEQCA);
+		tmp[2] = b43_phy_read(dev, afectl_core);
+		tmp[3] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
+		tmp[4] = b43_phy_read(dev, rfctl[0]);
+		tmp[5] = b43_phy_read(dev, rfctl[1]);
+
+		b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
+				~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF,
+				((1 - i) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));
+		b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN,
+				(1 - i));
+		b43_phy_set(dev, afectl_core, 0x0006);
+		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0006);
+
+		band = b43_current_band(dev->wl);
+
+		if (nphy->rxcalparams & 0xFF000000) {
+			if (band == NL80211_BAND_5GHZ)
+				b43_phy_write(dev, rfctl[0], 0x140);
+			else
+				b43_phy_write(dev, rfctl[0], 0x110);
+		} else {
+			if (band == NL80211_BAND_5GHZ)
+				b43_phy_write(dev, rfctl[0], 0x180);
+			else
+				b43_phy_write(dev, rfctl[0], 0x120);
+		}
+
+		if (band == NL80211_BAND_5GHZ)
+			b43_phy_write(dev, rfctl[1], 0x148);
+		else
+			b43_phy_write(dev, rfctl[1], 0x114);
+
+		if (nphy->rxcalparams & 0x10000) {
+			b43_radio_maskset(dev, B2055_C1_GENSPARE2, 0xFC,
+					(i + 1));
+			b43_radio_maskset(dev, B2055_C2_GENSPARE2, 0xFC,
+					(2 - i));
+		}
+
+		for (j = 0; j < 4; j++) {
+			if (j < 3) {
+				cur_lna = lna[j];
+				cur_hpf1 = hpf1[j];
+				cur_hpf2 = hpf2[j];
+			} else {
+				if (power[1] > 10000) {
+					use = 1;
+					cur_hpf = cur_hpf1;
+					index = 2;
+				} else {
+					if (power[0] > 10000) {
+						use = 1;
+						cur_hpf = cur_hpf1;
+						index = 1;
+					} else {
+						index = 0;
+						use = 2;
+						cur_hpf = cur_hpf2;
+					}
+				}
+				cur_lna = lna[index];
+				cur_hpf1 = hpf1[index];
+				cur_hpf2 = hpf2[index];
+				cur_hpf += desired - hweight32(power[index]);
+				cur_hpf = clamp_val(cur_hpf, 0, 10);
+				if (use == 1)
+					cur_hpf1 = cur_hpf;
+				else
+					cur_hpf2 = cur_hpf;
+			}
+
+			tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) |
+					(cur_lna << 2));
+			b43_nphy_rf_ctl_override(dev, 0x400, tmp[0], 3,
+									false);
+			b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
+			b43_nphy_stop_playback(dev);
+
+			if (playtone) {
+				ret = b43_nphy_tx_tone(dev, 4000,
+						(nphy->rxcalparams & 0xFFFF),
+						false, false, true);
+				playtone = false;
+			} else {
+				b43_nphy_run_samples(dev, 160, 0xFFFF, 0, false,
+						     false, true);
+			}
+
+			if (ret == 0) {
+				if (j < 3) {
+					b43_nphy_rx_iq_est(dev, &est, 1024, 32,
+									false);
+					if (i == 0) {
+						real = est.i0_pwr;
+						imag = est.q0_pwr;
+					} else {
+						real = est.i1_pwr;
+						imag = est.q1_pwr;
+					}
+					power[i] = ((real + imag) / 1024) + 1;
+				} else {
+					b43_nphy_calc_rx_iq_comp(dev, 1 << i);
+				}
+				b43_nphy_stop_playback(dev);
+			}
+
+			if (ret != 0)
+				break;
+		}
+
+		b43_radio_mask(dev, B2055_C1_GENSPARE2, 0xFC);
+		b43_radio_mask(dev, B2055_C2_GENSPARE2, 0xFC);
+		b43_phy_write(dev, rfctl[1], tmp[5]);
+		b43_phy_write(dev, rfctl[0], tmp[4]);
+		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp[3]);
+		b43_phy_write(dev, afectl_core, tmp[2]);
+		b43_phy_write(dev, B43_NPHY_RFSEQCA, tmp[1]);
+
+		if (ret != 0)
+			break;
+	}
+
+	b43_nphy_rf_ctl_override(dev, 0x400, 0, 3, true);
+	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
+	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save);
+
+	b43_nphy_stay_in_carrier_search(dev, 0);
+
+	return ret;
+}
+
+static int b43_nphy_rev3_cal_rx_iq(struct b43_wldev *dev,
+			struct nphy_txgains target, u8 type, bool debug)
+{
+	return -1;
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIq */
+static int b43_nphy_cal_rx_iq(struct b43_wldev *dev,
+			struct nphy_txgains target, u8 type, bool debug)
+{
+	if (dev->phy.rev >= 7)
+		type = 0;
+
+	if (dev->phy.rev >= 3)
+		return b43_nphy_rev3_cal_rx_iq(dev, target, type, debug);
+	else
+		return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */
+static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = phy->n;
+	/* u16 buf[16]; it's rev3+ */
+
+	nphy->phyrxchain = mask;
+
+	if (0 /* FIXME clk */)
+		return;
+
+	b43_mac_suspend(dev);
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, true);
+
+	b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN,
+			(mask & 0x3) << B43_NPHY_RFSEQCA_RXEN_SHIFT);
+
+	if ((mask & 0x3) != 0x3) {
+		b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 1);
+		if (dev->phy.rev >= 3) {
+			/* TODO */
+		}
+	} else {
+		b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 0x1E);
+		if (dev->phy.rev >= 3) {
+			/* TODO */
+		}
+	}
+
+	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
+
+	if (nphy->hang_avoid)
+		b43_nphy_stay_in_carrier_search(dev, false);
+
+	b43_mac_enable(dev);
+}
+
+static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev,
+							bool ignore_tssi)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = dev->phy.n;
+	struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan;
+	struct b43_ppr *ppr = &nphy->tx_pwr_max_ppr;
+	u8 max; /* qdBm */
+	bool tx_pwr_state;
+
+	if (nphy->tx_pwr_last_recalc_freq == channel->center_freq &&
+	    nphy->tx_pwr_last_recalc_limit == phy->desired_txpower)
+		return B43_TXPWR_RES_DONE;
+
+	/* Make sure we have a clean PPR */
+	b43_ppr_clear(dev, ppr);
+
+	/* HW limitations */
+	b43_ppr_load_max_from_sprom(dev, ppr, B43_BAND_2G);
+
+	/* Regulatory & user settings */
+	max = INT_TO_Q52(phy->chandef->chan->max_power);
+	if (phy->desired_txpower)
+		max = min_t(u8, max, INT_TO_Q52(phy->desired_txpower));
+	b43_ppr_apply_max(dev, ppr, max);
+	if (b43_debug(dev, B43_DBG_XMITPOWER))
+		b43dbg(dev->wl, "Calculated TX power: " Q52_FMT "\n",
+		       Q52_ARG(b43_ppr_get_max(dev, ppr)));
+
+	/* TODO: Enable this once we get gains working */
+#if 0
+	/* Some extra gains */
+	hw_gain = 6; /* N-PHY specific */
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+		hw_gain += sprom->antenna_gain.a0;
+	else
+		hw_gain += sprom->antenna_gain.a1;
+	b43_ppr_add(dev, ppr, -hw_gain);
+#endif
+
+	/* Make sure we didn't go too low */
+	b43_ppr_apply_min(dev, ppr, INT_TO_Q52(8));
+
+	/* Apply */
+	tx_pwr_state = nphy->txpwrctrl;
+	b43_mac_suspend(dev);
+	b43_nphy_tx_power_ctl_setup(dev);
+	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) {
+		b43_maskset32(dev, B43_MMIO_MACCTL, ~0, B43_MACCTL_PHY_LOCK);
+		b43_read32(dev, B43_MMIO_MACCTL);
+		udelay(1);
+	}
+	b43_nphy_tx_power_ctrl(dev, nphy->txpwrctrl);
+	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12)
+		b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_PHY_LOCK, 0);
+	b43_mac_enable(dev);
+
+	nphy->tx_pwr_last_recalc_freq = channel->center_freq;
+	nphy->tx_pwr_last_recalc_limit = phy->desired_txpower;
+
+	return B43_TXPWR_RES_DONE;
+}
+
+/**************************************************
+ * N-PHY init
+ **************************************************/
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */
+static void b43_nphy_update_mimo_config(struct b43_wldev *dev, s32 preamble)
+{
+	u16 mimocfg = b43_phy_read(dev, B43_NPHY_MIMOCFG);
+
+	mimocfg |= B43_NPHY_MIMOCFG_AUTO;
+	if (preamble == 1)
+		mimocfg |= B43_NPHY_MIMOCFG_GFMIX;
+	else
+		mimocfg &= ~B43_NPHY_MIMOCFG_GFMIX;
+
+	b43_phy_write(dev, B43_NPHY_MIMOCFG, mimocfg);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BPHYInit */
+static void b43_nphy_bphy_init(struct b43_wldev *dev)
+{
+	unsigned int i;
+	u16 val;
+
+	val = 0x1E1F;
+	for (i = 0; i < 16; i++) {
+		b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val);
+		val -= 0x202;
+	}
+	val = 0x3E3F;
+	for (i = 0; i < 16; i++) {
+		b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val);
+		val -= 0x202;
+	}
+	b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */
+static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init)
+{
+	if (dev->phy.rev >= 7)
+		return;
+
+	if (dev->phy.rev >= 3) {
+		if (!init)
+			return;
+		if (0 /* FIXME */) {
+			b43_ntab_write(dev, B43_NTAB16(9, 2), 0x211);
+			b43_ntab_write(dev, B43_NTAB16(9, 3), 0x222);
+			b43_ntab_write(dev, B43_NTAB16(9, 8), 0x144);
+			b43_ntab_write(dev, B43_NTAB16(9, 12), 0x188);
+		}
+	} else {
+		b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0);
+		b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0);
+
+		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_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0);
+		b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, 0xFC00);
+		b43_maskset16(dev, B43_MMIO_GPIO_CONTROL, (~0xFC00 & 0xFFFF),
+			      0);
+
+		if (init) {
+			b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
+			b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
+			b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
+			b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
+		}
+	}
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N */
+static int b43_phy_initn(struct b43_wldev *dev)
+{
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = phy->n;
+	u8 tx_pwr_state;
+	struct nphy_txgains target;
+	u16 tmp;
+	enum nl80211_band tmp2;
+	bool do_rssi_cal;
+
+	u16 clip[2];
+	bool do_cal = false;
+
+	if ((dev->phy.rev >= 3) &&
+	   (sprom->boardflags_lo & B43_BFL_EXTLNA) &&
+	   (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)) {
+		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->use_int_tx_iq_lo_cal = b43_nphy_ipa(dev) ||
+		phy->rev >= 7 ||
+		(phy->rev >= 5 &&
+		 sprom->boardflags2_hi & B43_BFH2_INTERNDET_TXIQCAL);
+	nphy->deaf_count = 0;
+	b43_nphy_tables_init(dev);
+	nphy->crsminpwr_adjusted = false;
+	nphy->noisevars_adjusted = false;
+
+	/* Clear all overrides */
+	if (dev->phy.rev >= 3) {
+		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, 0);
+		b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
+		if (phy->rev >= 7) {
+			b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0);
+			b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER4, 0);
+			b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER5, 0);
+			b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER6, 0);
+		}
+		if (phy->rev >= 19) {
+			/* TODO */
+		}
+
+		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, 0);
+		b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, 0);
+	} else {
+		b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
+	}
+	b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 0);
+	b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 0);
+	if (dev->phy.rev < 6) {
+		b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0);
+		b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0);
+	}
+	b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
+		     ~(B43_NPHY_RFSEQMODE_CAOVER |
+		       B43_NPHY_RFSEQMODE_TROVER));
+	if (dev->phy.rev >= 3)
+		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, 0);
+	b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 0);
+
+	if (dev->phy.rev <= 2) {
+		tmp = (dev->phy.rev == 2) ? 0x3B : 0x40;
+		b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
+				~B43_NPHY_BPHY_CTL3_SCALE,
+				tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT);
+	}
+	b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20);
+	b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20);
+
+	if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD ||
+	    (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&
+	     dev->dev->board_type == BCMA_BOARD_TYPE_BCM943224M93))
+		b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0);
+	else
+		b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8);
+	b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 0xC8);
+	b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50);
+	b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30);
+
+	if (phy->rev < 8)
+		b43_nphy_update_mimo_config(dev, nphy->preamble_override);
+
+	b43_nphy_update_txrx_chain(dev);
+
+	if (phy->rev < 2) {
+		b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8);
+		b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4);
+	}
+
+	tmp2 = b43_current_band(dev->wl);
+	if (b43_nphy_ipa(dev)) {
+		b43_phy_set(dev, B43_NPHY_PAPD_EN0, 0x1);
+		b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ0, 0x007F,
+				nphy->papd_epsilon_offset[0] << 7);
+		b43_phy_set(dev, B43_NPHY_PAPD_EN1, 0x1);
+		b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ1, 0x007F,
+				nphy->papd_epsilon_offset[1] << 7);
+		b43_nphy_int_pa_set_tx_dig_filters(dev);
+	} else if (phy->rev >= 5) {
+		b43_nphy_ext_pa_set_tx_dig_filters(dev);
+	}
+
+	b43_nphy_workarounds(dev);
+
+	/* Reset CCA, in init code it differs a little from standard way */
+	b43_phy_force_clock(dev, 1);
+	tmp = b43_phy_read(dev, B43_NPHY_BBCFG);
+	b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA);
+	b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA);
+	b43_phy_force_clock(dev, 0);
+
+	b43_mac_phy_clock_set(dev, true);
+
+	if (phy->rev < 7) {
+		b43_nphy_pa_override(dev, false);
+		b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
+		b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
+		b43_nphy_pa_override(dev, true);
+	}
+
+	b43_nphy_classifier(dev, 0, 0);
+	b43_nphy_read_clip_detection(dev, clip);
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+		b43_nphy_bphy_init(dev);
+
+	tx_pwr_state = nphy->txpwrctrl;
+	b43_nphy_tx_power_ctrl(dev, false);
+	b43_nphy_tx_power_fix(dev);
+	b43_nphy_tx_power_ctl_idle_tssi(dev);
+	b43_nphy_tx_power_ctl_setup(dev);
+	b43_nphy_tx_gain_table_upload(dev);
+
+	if (nphy->phyrxchain != 3)
+		b43_nphy_set_rx_core_state(dev, nphy->phyrxchain);
+	if (nphy->mphase_cal_phase_id > 0)
+		;/* TODO PHY Periodic Calibration Multi-Phase Restart */
+
+	do_rssi_cal = false;
+	if (phy->rev >= 3) {
+		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+			do_rssi_cal = !nphy->rssical_chanspec_2G.center_freq;
+		else
+			do_rssi_cal = !nphy->rssical_chanspec_5G.center_freq;
+
+		if (do_rssi_cal)
+			b43_nphy_rssi_cal(dev);
+		else
+			b43_nphy_restore_rssi_cal(dev);
+	} else {
+		b43_nphy_rssi_cal(dev);
+	}
+
+	if (!((nphy->measure_hold & 0x6) != 0)) {
+		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+			do_cal = !nphy->iqcal_chanspec_2G.center_freq;
+		else
+			do_cal = !nphy->iqcal_chanspec_5G.center_freq;
+
+		if (nphy->mute)
+			do_cal = false;
+
+		if (do_cal) {
+			target = b43_nphy_get_tx_gains(dev);
+
+			if (nphy->antsel_type == 2)
+				b43_nphy_superswitch_init(dev, true);
+			if (nphy->perical != 2) {
+				b43_nphy_rssi_cal(dev);
+				if (phy->rev >= 3) {
+					nphy->cal_orig_pwr_idx[0] =
+					    nphy->txpwrindex[0].index_internal;
+					nphy->cal_orig_pwr_idx[1] =
+					    nphy->txpwrindex[1].index_internal;
+					/* TODO N PHY Pre Calibrate TX Gain */
+					target = b43_nphy_get_tx_gains(dev);
+				}
+				if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false))
+					if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0)
+						b43_nphy_save_cal(dev);
+			} else if (nphy->mphase_cal_phase_id == 0)
+				;/* N PHY Periodic Calibration with arg 3 */
+		} else {
+			b43_nphy_restore_cal(dev);
+		}
+	}
+
+	b43_nphy_tx_pwr_ctrl_coef_setup(dev);
+	b43_nphy_tx_power_ctrl(dev, tx_pwr_state);
+	b43_phy_write(dev, B43_NPHY_TXMACIF_HOLDOFF, 0x0015);
+	b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320);
+	if (phy->rev >= 3 && phy->rev <= 6)
+		b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x0032);
+	b43_nphy_tx_lpf_bw(dev);
+	if (phy->rev >= 3)
+		b43_nphy_spur_workaround(dev);
+
+	return 0;
+}
+
+/**************************************************
+ * Channel switching ops.
+ **************************************************/
+
+static void b43_chantab_phy_upload(struct b43_wldev *dev,
+				   const struct b43_phy_n_sfo_cfg *e)
+{
+	b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a);
+	b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2);
+	b43_phy_write(dev, B43_NPHY_BW3, e->phy_bw3);
+	b43_phy_write(dev, B43_NPHY_BW4, e->phy_bw4);
+	b43_phy_write(dev, B43_NPHY_BW5, e->phy_bw5);
+	b43_phy_write(dev, B43_NPHY_BW6, e->phy_bw6);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PmuSpurAvoid */
+static void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid)
+{
+	switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+	case B43_BUS_BCMA:
+		bcma_pmu_spuravoid_pllupdate(&dev->dev->bdev->bus->drv_cc,
+					     avoid);
+		break;
+#endif
+#ifdef CONFIG_B43_SSB
+	case B43_BUS_SSB:
+		ssb_pmu_spuravoid_pllupdate(&dev->dev->sdev->bus->chipco,
+					    avoid);
+		break;
+#endif
+	}
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */
+static void b43_nphy_channel_setup(struct b43_wldev *dev,
+				const struct b43_phy_n_sfo_cfg *e,
+				struct ieee80211_channel *new_channel)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = dev->phy.n;
+	int ch = new_channel->hw_value;
+	u16 tmp16;
+
+	if (new_channel->band == NL80211_BAND_5GHZ) {
+		/* Switch to 2 GHz for a moment to access B43_PHY_B_BBCFG */
+		b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
+
+		tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR);
+		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4);
+		/* Put BPHY in the reset */
+		b43_phy_set(dev, B43_PHY_B_BBCFG,
+			    B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX);
+		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16);
+		b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ);
+	} else if (new_channel->band == NL80211_BAND_2GHZ) {
+		b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
+		tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR);
+		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4);
+		/* Take BPHY out of the reset */
+		b43_phy_mask(dev, B43_PHY_B_BBCFG,
+			     (u16)~(B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX));
+		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16);
+	}
+
+	b43_chantab_phy_upload(dev, e);
+
+	if (new_channel->hw_value == 14) {
+		b43_nphy_classifier(dev, 2, 0);
+		b43_phy_set(dev, B43_PHY_B_TEST, 0x0800);
+	} else {
+		b43_nphy_classifier(dev, 2, 2);
+		if (new_channel->band == NL80211_BAND_2GHZ)
+			b43_phy_mask(dev, B43_PHY_B_TEST, ~0x840);
+	}
+
+	if (!nphy->txpwrctrl)
+		b43_nphy_tx_power_fix(dev);
+
+	if (dev->phy.rev < 3)
+		b43_nphy_adjust_lna_gain_table(dev);
+
+	b43_nphy_tx_lpf_bw(dev);
+
+	if (dev->phy.rev >= 3 &&
+	    dev->phy.n->spur_avoid != B43_SPUR_AVOID_DISABLE) {
+		u8 spuravoid = 0;
+
+		if (dev->phy.n->spur_avoid == B43_SPUR_AVOID_FORCE) {
+			spuravoid = 1;
+		} else if (phy->rev >= 19) {
+			/* TODO */
+		} else if (phy->rev >= 18) {
+			/* TODO */
+		} else if (phy->rev >= 17) {
+			/* TODO: Off for channels 1-11, but check 12-14! */
+		} else if (phy->rev >= 16) {
+			/* TODO: Off for 2 GHz, but check 5 GHz! */
+		} else if (phy->rev >= 7) {
+			if (!b43_is_40mhz(dev)) { /* 20MHz */
+				if (ch == 13 || ch == 14 || ch == 153)
+					spuravoid = 1;
+			} else { /* 40 MHz */
+				if (ch == 54)
+					spuravoid = 1;
+			}
+		} else {
+			if (!b43_is_40mhz(dev)) { /* 20MHz */
+				if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14)
+					spuravoid = 1;
+			} else { /* 40MHz */
+				if (nphy->aband_spurwar_en &&
+				    (ch == 38 || ch == 102 || ch == 118))
+					spuravoid = dev->dev->chip_id == 0x4716;
+			}
+		}
+
+		b43_nphy_pmu_spur_avoid(dev, spuravoid);
+
+		b43_mac_switch_freq(dev, spuravoid);
+
+		if (dev->phy.rev == 3 || dev->phy.rev == 4)
+			b43_wireless_core_phy_pll_reset(dev);
+
+		if (spuravoid)
+			b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTRX);
+		else
+			b43_phy_mask(dev, B43_NPHY_BBCFG,
+				     ~B43_NPHY_BBCFG_RSTRX & 0xFFFF);
+
+		b43_nphy_reset_cca(dev);
+
+		/* wl sets useless phy_isspuravoid here */
+	}
+
+	b43_phy_write(dev, B43_NPHY_NDATAT_DUP40, 0x3830);
+
+	if (phy->rev >= 3)
+		b43_nphy_spur_workaround(dev);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */
+static int b43_nphy_set_channel(struct b43_wldev *dev,
+				struct ieee80211_channel *channel,
+				enum nl80211_channel_type channel_type)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	const struct b43_nphy_channeltab_entry_rev2 *tabent_r2 = NULL;
+	const struct b43_nphy_channeltab_entry_rev3 *tabent_r3 = NULL;
+	const struct b43_nphy_chantabent_rev7 *tabent_r7 = NULL;
+	const struct b43_nphy_chantabent_rev7_2g *tabent_r7_2g = NULL;
+
+	u8 tmp;
+
+	if (phy->rev >= 19) {
+		return -ESRCH;
+		/* TODO */
+	} else if (phy->rev >= 7) {
+		r2057_get_chantabent_rev7(dev, channel->center_freq,
+					  &tabent_r7, &tabent_r7_2g);
+		if (!tabent_r7 && !tabent_r7_2g)
+			return -ESRCH;
+	} else if (phy->rev >= 3) {
+		tabent_r3 = b43_nphy_get_chantabent_rev3(dev,
+							channel->center_freq);
+		if (!tabent_r3)
+			return -ESRCH;
+	} else {
+		tabent_r2 = b43_nphy_get_chantabent_rev2(dev,
+							channel->hw_value);
+		if (!tabent_r2)
+			return -ESRCH;
+	}
+
+	/* Channel is set later in common code, but we need to set it on our
+	   own to let this function's subcalls work properly. */
+	phy->channel = channel->hw_value;
+
+#if 0
+	if (b43_channel_type_is_40mhz(phy->channel_type) !=
+		b43_channel_type_is_40mhz(channel_type))
+		; /* TODO: BMAC BW Set (channel_type) */
+#endif
+
+	if (channel_type == NL80211_CHAN_HT40PLUS) {
+		b43_phy_set(dev, B43_NPHY_RXCTL, B43_NPHY_RXCTL_BSELU20);
+		if (phy->rev >= 7)
+			b43_phy_set(dev, 0x310, 0x8000);
+	} else if (channel_type == NL80211_CHAN_HT40MINUS) {
+		b43_phy_mask(dev, B43_NPHY_RXCTL, ~B43_NPHY_RXCTL_BSELU20);
+		if (phy->rev >= 7)
+			b43_phy_mask(dev, 0x310, (u16)~0x8000);
+	}
+
+	if (phy->rev >= 19) {
+		/* TODO */
+	} else if (phy->rev >= 7) {
+		const struct b43_phy_n_sfo_cfg *phy_regs = tabent_r7 ?
+			&(tabent_r7->phy_regs) : &(tabent_r7_2g->phy_regs);
+
+		if (phy->radio_rev <= 4 || phy->radio_rev == 6) {
+			tmp = (channel->band == NL80211_BAND_5GHZ) ? 2 : 0;
+			b43_radio_maskset(dev, R2057_TIA_CONFIG_CORE0, ~2, tmp);
+			b43_radio_maskset(dev, R2057_TIA_CONFIG_CORE1, ~2, tmp);
+		}
+
+		b43_radio_2057_setup(dev, tabent_r7, tabent_r7_2g);
+		b43_nphy_channel_setup(dev, phy_regs, channel);
+	} else if (phy->rev >= 3) {
+		tmp = (channel->band == NL80211_BAND_5GHZ) ? 4 : 0;
+		b43_radio_maskset(dev, 0x08, 0xFFFB, tmp);
+		b43_radio_2056_setup(dev, tabent_r3);
+		b43_nphy_channel_setup(dev, &(tabent_r3->phy_regs), channel);
+	} else {
+		tmp = (channel->band == NL80211_BAND_5GHZ) ? 0x0020 : 0x0050;
+		b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp);
+		b43_radio_2055_setup(dev, tabent_r2);
+		b43_nphy_channel_setup(dev, &(tabent_r2->phy_regs), channel);
+	}
+
+	return 0;
+}
+
+/**************************************************
+ * Basic PHY ops.
+ **************************************************/
+
+static int b43_nphy_op_allocate(struct b43_wldev *dev)
+{
+	struct b43_phy_n *nphy;
+
+	nphy = kzalloc(sizeof(*nphy), GFP_KERNEL);
+	if (!nphy)
+		return -ENOMEM;
+
+	dev->phy.n = nphy;
+
+	return 0;
+}
+
+static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = phy->n;
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+
+	memset(nphy, 0, sizeof(*nphy));
+
+	nphy->hang_avoid = (phy->rev == 3 || phy->rev == 4);
+	nphy->spur_avoid = (phy->rev >= 3) ?
+				B43_SPUR_AVOID_AUTO : B43_SPUR_AVOID_DISABLE;
+	nphy->gain_boost = true; /* this way we follow wl, assume it is true */
+	nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */
+	nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */
+	nphy->perical = 2; /* avoid additional rssi cal on init (like wl) */
+	/* 128 can mean disabled-by-default state of TX pwr ctl. Max value is
+	 * 0x7f == 127 and we check for 128 when restoring TX pwr ctl. */
+	nphy->tx_pwr_idx[0] = 128;
+	nphy->tx_pwr_idx[1] = 128;
+
+	/* Hardware TX power control and 5GHz power gain */
+	nphy->txpwrctrl = false;
+	nphy->pwg_gain_5ghz = false;
+	if (dev->phy.rev >= 3 ||
+	    (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&
+	     (dev->dev->core_rev == 11 || dev->dev->core_rev == 12))) {
+		nphy->txpwrctrl = true;
+		nphy->pwg_gain_5ghz = true;
+	} else if (sprom->revision >= 4) {
+		if (dev->phy.rev >= 2 &&
+		    (sprom->boardflags2_lo & B43_BFL2_TXPWRCTRL_EN)) {
+			nphy->txpwrctrl = true;
+#ifdef CONFIG_B43_SSB
+			if (dev->dev->bus_type == B43_BUS_SSB &&
+			    dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI) {
+				struct pci_dev *pdev =
+					dev->dev->sdev->bus->host_pci;
+				if (pdev->device == 0x4328 ||
+				    pdev->device == 0x432a)
+					nphy->pwg_gain_5ghz = true;
+			}
+#endif
+		} else if (sprom->boardflags2_lo & B43_BFL2_5G_PWRGAIN) {
+			nphy->pwg_gain_5ghz = true;
+		}
+	}
+
+	if (dev->phy.rev >= 3) {
+		nphy->ipa2g_on = sprom->fem.ghz2.extpa_gain == 2;
+		nphy->ipa5g_on = sprom->fem.ghz5.extpa_gain == 2;
+	}
+}
+
+static void b43_nphy_op_free(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_n *nphy = phy->n;
+
+	kfree(nphy);
+	phy->n = NULL;
+}
+
+static int b43_nphy_op_init(struct b43_wldev *dev)
+{
+	return b43_phy_initn(dev);
+}
+
+static inline void check_phyreg(struct b43_wldev *dev, u16 offset)
+{
+#if B43_DEBUG
+	if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) {
+		/* OFDM registers are onnly available on A/G-PHYs */
+		b43err(dev->wl, "Invalid OFDM PHY access at "
+		       "0x%04X on N-PHY\n", offset);
+		dump_stack();
+	}
+	if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) {
+		/* Ext-G registers are only available on G-PHYs */
+		b43err(dev->wl, "Invalid EXT-G PHY access at "
+		       "0x%04X on N-PHY\n", offset);
+		dump_stack();
+	}
+#endif /* B43_DEBUG */
+}
+
+static void b43_nphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
+				 u16 set)
+{
+	check_phyreg(dev, reg);
+	b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
+	b43_maskset16(dev, B43_MMIO_PHY_DATA, mask, set);
+	dev->phy.writes_counter = 1;
+}
+
+static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg)
+{
+	/* Register 1 is a 32-bit register. */
+	B43_WARN_ON(dev->phy.rev < 7 && reg == 1);
+
+	if (dev->phy.rev >= 7)
+		reg |= 0x200; /* Radio 0x2057 */
+	else
+		reg |= 0x100;
+
+	b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);
+	return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
+}
+
+static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+	/* Register 1 is a 32-bit register. */
+	B43_WARN_ON(dev->phy.rev < 7 && reg == 1);
+
+	b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);
+	b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */
+static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
+					bool blocked)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
+		b43err(dev->wl, "MAC not suspended\n");
+
+	if (blocked) {
+		if (phy->rev >= 19) {
+			/* TODO */
+		} else if (phy->rev >= 8) {
+			b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
+				     ~B43_NPHY_RFCTL_CMD_CHIP0PU);
+		} else if (phy->rev >= 7) {
+			/* Nothing needed */
+		} else if (phy->rev >= 3) {
+			b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
+				     ~B43_NPHY_RFCTL_CMD_CHIP0PU);
+
+			b43_radio_mask(dev, 0x09, ~0x2);
+
+			b43_radio_write(dev, 0x204D, 0);
+			b43_radio_write(dev, 0x2053, 0);
+			b43_radio_write(dev, 0x2058, 0);
+			b43_radio_write(dev, 0x205E, 0);
+			b43_radio_mask(dev, 0x2062, ~0xF0);
+			b43_radio_write(dev, 0x2064, 0);
+
+			b43_radio_write(dev, 0x304D, 0);
+			b43_radio_write(dev, 0x3053, 0);
+			b43_radio_write(dev, 0x3058, 0);
+			b43_radio_write(dev, 0x305E, 0);
+			b43_radio_mask(dev, 0x3062, ~0xF0);
+			b43_radio_write(dev, 0x3064, 0);
+		}
+	} else {
+		if (phy->rev >= 19) {
+			/* TODO */
+		} else if (phy->rev >= 7) {
+			if (!dev->phy.radio_on)
+				b43_radio_2057_init(dev);
+			b43_switch_channel(dev, dev->phy.channel);
+		} else if (phy->rev >= 3) {
+			if (!dev->phy.radio_on)
+				b43_radio_init2056(dev);
+			b43_switch_channel(dev, dev->phy.channel);
+		} else {
+			b43_radio_init2055(dev);
+		}
+	}
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */
+static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
+{
+	struct b43_phy *phy = &dev->phy;
+	u16 override = on ? 0x0 : 0x7FFF;
+	u16 core = on ? 0xD : 0x00FD;
+
+	if (phy->rev >= 19) {
+		/* TODO */
+	} else if (phy->rev >= 3) {
+		if (on) {
+			b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
+			b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
+			b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);
+			b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
+		} else {
+			b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
+			b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
+			b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
+			b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);
+		}
+	} else {
+		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
+	}
+}
+
+static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
+				      unsigned int new_channel)
+{
+	struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan;
+	enum nl80211_channel_type channel_type =
+		cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef);
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+		if ((new_channel < 1) || (new_channel > 14))
+			return -EINVAL;
+	} else {
+		if (new_channel > 200)
+			return -EINVAL;
+	}
+
+	return b43_nphy_set_channel(dev, channel, channel_type);
+}
+
+static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev)
+{
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+		return 1;
+	return 36;
+}
+
+const struct b43_phy_operations b43_phyops_n = {
+	.allocate		= b43_nphy_op_allocate,
+	.free			= b43_nphy_op_free,
+	.prepare_structs	= b43_nphy_op_prepare_structs,
+	.init			= b43_nphy_op_init,
+	.phy_maskset		= b43_nphy_op_maskset,
+	.radio_read		= b43_nphy_op_radio_read,
+	.radio_write		= b43_nphy_op_radio_write,
+	.software_rfkill	= b43_nphy_op_software_rfkill,
+	.switch_analog		= b43_nphy_op_switch_analog,
+	.switch_channel		= b43_nphy_op_switch_channel,
+	.get_default_chan	= b43_nphy_op_get_default_chan,
+	.recalc_txpower		= b43_nphy_op_recalc_txpower,
+};
diff --git a/drivers/net/wireless/broadcom/b43/phy_n.h b/drivers/net/wireless/broadcom/b43/phy_n.h
new file mode 100644
index 0000000..b96ded0
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/phy_n.h
@@ -0,0 +1,1008 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_NPHY_H_
+#define B43_NPHY_H_
+
+#include "phy_common.h"
+#include "ppr.h"
+
+
+/* N-PHY registers. */
+
+#define B43_NPHY_BBCFG				B43_PHY_N(0x001) /* BB config */
+#define  B43_NPHY_BBCFG_RSTCCA			0x4000 /* Reset CCA */
+#define  B43_NPHY_BBCFG_RSTRX			0x8000 /* Reset RX */
+#define B43_NPHY_CHANNEL			B43_PHY_N(0x005) /* Channel */
+#define B43_NPHY_TXERR				B43_PHY_N(0x007) /* TX error */
+#define B43_NPHY_BANDCTL			B43_PHY_N(0x009) /* Band control */
+#define  B43_NPHY_BANDCTL_5GHZ			0x0001 /* Use the 5GHz band */
+#define B43_NPHY_4WI_ADDR			B43_PHY_N(0x00B) /* Four-wire bus address */
+#define B43_NPHY_4WI_DATAHI			B43_PHY_N(0x00C) /* Four-wire bus data high */
+#define B43_NPHY_4WI_DATALO			B43_PHY_N(0x00D) /* Four-wire bus data low */
+#define B43_NPHY_BIST_STAT0			B43_PHY_N(0x00E) /* Built-in self test status 0 */
+#define B43_NPHY_BIST_STAT1			B43_PHY_N(0x00F) /* Built-in self test status 1 */
+
+#define B43_NPHY_C1_DESPWR			B43_PHY_N(0x018) /* Core 1 desired power */
+#define B43_NPHY_C1_CCK_DESPWR			B43_PHY_N(0x019) /* Core 1 CCK desired power */
+#define B43_NPHY_C1_BCLIPBKOFF			B43_PHY_N(0x01A) /* Core 1 barely clip backoff */
+#define B43_NPHY_C1_CCK_BCLIPBKOFF		B43_PHY_N(0x01B) /* Core 1 CCK barely clip backoff */
+#define B43_NPHY_C1_CGAINI			B43_PHY_N(0x01C) /* Core 1 compute gain info */
+#define  B43_NPHY_C1_CGAINI_GAINBKOFF		0x001F /* Gain backoff */
+#define  B43_NPHY_C1_CGAINI_GAINBKOFF_SHIFT	0
+#define  B43_NPHY_C1_CGAINI_CLIPGBKOFF		0x03E0 /* Clip gain backoff */
+#define  B43_NPHY_C1_CGAINI_CLIPGBKOFF_SHIFT	5
+#define  B43_NPHY_C1_CGAINI_GAINSTEP		0x1C00 /* Gain step */
+#define  B43_NPHY_C1_CGAINI_GAINSTEP_SHIFT	10
+#define  B43_NPHY_C1_CGAINI_CL2DETECT		0x2000 /* Clip 2 detect mask */
+#define B43_NPHY_C1_CCK_CGAINI			B43_PHY_N(0x01D) /* Core 1 CCK compute gain info */
+#define  B43_NPHY_C1_CCK_CGAINI_GAINBKOFF	0x001F /* Gain backoff */
+#define  B43_NPHY_C1_CCK_CGAINI_CLIPGBKOFF	0x01E0 /* CCK barely clip gain backoff */
+#define B43_NPHY_C1_MINMAX_GAIN			B43_PHY_N(0x01E) /* Core 1 min/max gain */
+#define  B43_NPHY_C1_MINGAIN			0x00FF /* Minimum gain */
+#define  B43_NPHY_C1_MINGAIN_SHIFT		0
+#define  B43_NPHY_C1_MAXGAIN			0xFF00 /* Maximum gain */
+#define  B43_NPHY_C1_MAXGAIN_SHIFT		8
+#define B43_NPHY_C1_CCK_MINMAX_GAIN		B43_PHY_N(0x01F) /* Core 1 CCK min/max gain */
+#define  B43_NPHY_C1_CCK_MINGAIN		0x00FF /* Minimum gain */
+#define  B43_NPHY_C1_CCK_MINGAIN_SHIFT		0
+#define  B43_NPHY_C1_CCK_MAXGAIN		0xFF00 /* Maximum gain */
+#define  B43_NPHY_C1_CCK_MAXGAIN_SHIFT		8
+#define B43_NPHY_C1_INITGAIN			B43_PHY_N(0x020) /* Core 1 initial gain code */
+#define  B43_NPHY_C1_INITGAIN_EXTLNA		0x0001 /* External LNA index */
+#define  B43_NPHY_C1_INITGAIN_LNA		0x0006 /* LNA index */
+#define  B43_NPHY_C1_INITGAIN_LNAIDX_SHIFT	1
+#define  B43_NPHY_C1_INITGAIN_HPVGA1		0x0078 /* HPVGA1 index */
+#define  B43_NPHY_C1_INITGAIN_HPVGA1_SHIFT	3
+#define  B43_NPHY_C1_INITGAIN_HPVGA2		0x0F80 /* HPVGA2 index */
+#define  B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT	7
+#define  B43_NPHY_C1_INITGAIN_TRRX		0x1000 /* TR RX index */
+#define  B43_NPHY_C1_INITGAIN_TRTX		0x2000 /* TR TX index */
+#define B43_NPHY_REV3_C1_INITGAIN_A		B43_PHY_N(0x020)
+#define B43_NPHY_C1_CLIP1_HIGAIN		B43_PHY_N(0x021) /* Core 1 clip1 high gain code */
+#define B43_NPHY_REV3_C1_INITGAIN_B		B43_PHY_N(0x021)
+#define B43_NPHY_C1_CLIP1_MEDGAIN		B43_PHY_N(0x022) /* Core 1 clip1 medium gain code */
+#define B43_NPHY_REV3_C1_CLIP_HIGAIN_A		B43_PHY_N(0x022)
+#define B43_NPHY_C1_CLIP1_LOGAIN		B43_PHY_N(0x023) /* Core 1 clip1 low gain code */
+#define B43_NPHY_REV3_C1_CLIP_HIGAIN_B		B43_PHY_N(0x023)
+#define B43_NPHY_C1_CLIP2_GAIN			B43_PHY_N(0x024) /* Core 1 clip2 gain code */
+#define B43_NPHY_REV3_C1_CLIP_MEDGAIN_A		B43_PHY_N(0x024)
+#define B43_NPHY_C1_FILTERGAIN			B43_PHY_N(0x025) /* Core 1 filter gain */
+#define B43_NPHY_C1_LPF_QHPF_BW			B43_PHY_N(0x026) /* Core 1 LPF Q HP F bandwidth */
+#define B43_NPHY_C1_CLIPWBTHRES			B43_PHY_N(0x027) /* Core 1 clip wideband threshold */
+#define  B43_NPHY_C1_CLIPWBTHRES_CLIP2		0x003F /* Clip 2 */
+#define  B43_NPHY_C1_CLIPWBTHRES_CLIP2_SHIFT	0
+#define  B43_NPHY_C1_CLIPWBTHRES_CLIP1		0x0FC0 /* Clip 1 */
+#define  B43_NPHY_C1_CLIPWBTHRES_CLIP1_SHIFT	6
+#define B43_NPHY_C1_W1THRES			B43_PHY_N(0x028) /* Core 1 W1 threshold */
+#define B43_NPHY_C1_EDTHRES			B43_PHY_N(0x029) /* Core 1 ED threshold */
+#define B43_NPHY_C1_SMSIGTHRES			B43_PHY_N(0x02A) /* Core 1 small sig threshold */
+#define B43_NPHY_C1_NBCLIPTHRES			B43_PHY_N(0x02B) /* Core 1 NB clip threshold */
+#define B43_NPHY_C1_CLIP1THRES			B43_PHY_N(0x02C) /* Core 1 clip1 threshold */
+#define B43_NPHY_C1_CLIP2THRES			B43_PHY_N(0x02D) /* Core 1 clip2 threshold */
+
+#define B43_NPHY_C2_DESPWR			B43_PHY_N(0x02E) /* Core 2 desired power */
+#define B43_NPHY_C2_CCK_DESPWR			B43_PHY_N(0x02F) /* Core 2 CCK desired power */
+#define B43_NPHY_C2_BCLIPBKOFF			B43_PHY_N(0x030) /* Core 2 barely clip backoff */
+#define B43_NPHY_C2_CCK_BCLIPBKOFF		B43_PHY_N(0x031) /* Core 2 CCK barely clip backoff */
+#define B43_NPHY_C2_CGAINI			B43_PHY_N(0x032) /* Core 2 compute gain info */
+#define  B43_NPHY_C2_CGAINI_GAINBKOFF		0x001F /* Gain backoff */
+#define  B43_NPHY_C2_CGAINI_GAINBKOFF_SHIFT	0
+#define  B43_NPHY_C2_CGAINI_CLIPGBKOFF		0x03E0 /* Clip gain backoff */
+#define  B43_NPHY_C2_CGAINI_CLIPGBKOFF_SHIFT	5
+#define  B43_NPHY_C2_CGAINI_GAINSTEP		0x1C00 /* Gain step */
+#define  B43_NPHY_C2_CGAINI_GAINSTEP_SHIFT	10
+#define  B43_NPHY_C2_CGAINI_CL2DETECT		0x2000 /* Clip 2 detect mask */
+#define B43_NPHY_C2_CCK_CGAINI			B43_PHY_N(0x033) /* Core 2 CCK compute gain info */
+#define  B43_NPHY_C2_CCK_CGAINI_GAINBKOFF	0x001F /* Gain backoff */
+#define  B43_NPHY_C2_CCK_CGAINI_CLIPGBKOFF	0x01E0 /* CCK barely clip gain backoff */
+#define B43_NPHY_C2_MINMAX_GAIN			B43_PHY_N(0x034) /* Core 2 min/max gain */
+#define  B43_NPHY_C2_MINGAIN			0x00FF /* Minimum gain */
+#define  B43_NPHY_C2_MINGAIN_SHIFT		0
+#define  B43_NPHY_C2_MAXGAIN			0xFF00 /* Maximum gain */
+#define  B43_NPHY_C2_MAXGAIN_SHIFT		8
+#define B43_NPHY_C2_CCK_MINMAX_GAIN		B43_PHY_N(0x035) /* Core 2 CCK min/max gain */
+#define  B43_NPHY_C2_CCK_MINGAIN		0x00FF /* Minimum gain */
+#define  B43_NPHY_C2_CCK_MINGAIN_SHIFT		0
+#define  B43_NPHY_C2_CCK_MAXGAIN		0xFF00 /* Maximum gain */
+#define  B43_NPHY_C2_CCK_MAXGAIN_SHIFT		8
+#define B43_NPHY_C2_INITGAIN			B43_PHY_N(0x036) /* Core 2 initial gain code */
+#define  B43_NPHY_C2_INITGAIN_EXTLNA		0x0001 /* External LNA index */
+#define  B43_NPHY_C2_INITGAIN_LNA		0x0006 /* LNA index */
+#define  B43_NPHY_C2_INITGAIN_LNAIDX_SHIFT	1
+#define  B43_NPHY_C2_INITGAIN_HPVGA1		0x0078 /* HPVGA1 index */
+#define  B43_NPHY_C2_INITGAIN_HPVGA1_SHIFT	3
+#define  B43_NPHY_C2_INITGAIN_HPVGA2		0x0F80 /* HPVGA2 index */
+#define  B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT	7
+#define  B43_NPHY_C2_INITGAIN_TRRX		0x1000 /* TR RX index */
+#define  B43_NPHY_C2_INITGAIN_TRTX		0x2000 /* TR TX index */
+#define B43_NPHY_REV3_C1_CLIP_MEDGAIN_B		B43_PHY_N(0x036)
+#define B43_NPHY_C2_CLIP1_HIGAIN		B43_PHY_N(0x037) /* Core 2 clip1 high gain code */
+#define B43_NPHY_REV3_C1_CLIP_LOGAIN_A		B43_PHY_N(0x037)
+#define B43_NPHY_C2_CLIP1_MEDGAIN		B43_PHY_N(0x038) /* Core 2 clip1 medium gain code */
+#define B43_NPHY_REV3_C1_CLIP_LOGAIN_B		B43_PHY_N(0x038)
+#define B43_NPHY_C2_CLIP1_LOGAIN		B43_PHY_N(0x039) /* Core 2 clip1 low gain code */
+#define B43_NPHY_REV3_C1_CLIP2_GAIN_A		B43_PHY_N(0x039)
+#define B43_NPHY_C2_CLIP2_GAIN			B43_PHY_N(0x03A) /* Core 2 clip2 gain code */
+#define B43_NPHY_REV3_C1_CLIP2_GAIN_B		B43_PHY_N(0x03A)
+#define B43_NPHY_C2_FILTERGAIN			B43_PHY_N(0x03B) /* Core 2 filter gain */
+#define B43_NPHY_C2_LPF_QHPF_BW			B43_PHY_N(0x03C) /* Core 2 LPF Q HP F bandwidth */
+#define B43_NPHY_C2_CLIPWBTHRES			B43_PHY_N(0x03D) /* Core 2 clip wideband threshold */
+#define  B43_NPHY_C2_CLIPWBTHRES_CLIP2		0x003F /* Clip 2 */
+#define  B43_NPHY_C2_CLIPWBTHRES_CLIP2_SHIFT	0
+#define  B43_NPHY_C2_CLIPWBTHRES_CLIP1		0x0FC0 /* Clip 1 */
+#define  B43_NPHY_C2_CLIPWBTHRES_CLIP1_SHIFT	6
+#define B43_NPHY_C2_W1THRES			B43_PHY_N(0x03E) /* Core 2 W1 threshold */
+#define B43_NPHY_C2_EDTHRES			B43_PHY_N(0x03F) /* Core 2 ED threshold */
+#define B43_NPHY_C2_SMSIGTHRES			B43_PHY_N(0x040) /* Core 2 small sig threshold */
+#define B43_NPHY_C2_NBCLIPTHRES			B43_PHY_N(0x041) /* Core 2 NB clip threshold */
+#define B43_NPHY_C2_CLIP1THRES			B43_PHY_N(0x042) /* Core 2 clip1 threshold */
+#define B43_NPHY_C2_CLIP2THRES			B43_PHY_N(0x043) /* Core 2 clip2 threshold */
+
+#define B43_NPHY_CRS_THRES1			B43_PHY_N(0x044) /* CRS threshold 1 */
+#define B43_NPHY_CRS_THRES2			B43_PHY_N(0x045) /* CRS threshold 2 */
+#define B43_NPHY_CRS_THRES3			B43_PHY_N(0x046) /* CRS threshold 3 */
+#define B43_NPHY_CRSCTL				B43_PHY_N(0x047) /* CRS control */
+#define B43_NPHY_DCFADDR			B43_PHY_N(0x048) /* DC filter address */
+#define B43_NPHY_RXF20_NUM0			B43_PHY_N(0x049) /* RX filter 20 numerator 0 */
+#define B43_NPHY_RXF20_NUM1			B43_PHY_N(0x04A) /* RX filter 20 numerator 1 */
+#define B43_NPHY_RXF20_NUM2			B43_PHY_N(0x04B) /* RX filter 20 numerator 2 */
+#define B43_NPHY_RXF20_DENOM0			B43_PHY_N(0x04C) /* RX filter 20 denominator 0 */
+#define B43_NPHY_RXF20_DENOM1			B43_PHY_N(0x04D) /* RX filter 20 denominator 1 */
+#define B43_NPHY_RXF20_NUM10			B43_PHY_N(0x04E) /* RX filter 20 numerator 10 */
+#define B43_NPHY_RXF20_NUM11			B43_PHY_N(0x04F) /* RX filter 20 numerator 11 */
+#define B43_NPHY_RXF20_NUM12			B43_PHY_N(0x050) /* RX filter 20 numerator 12 */
+#define B43_NPHY_RXF20_DENOM10			B43_PHY_N(0x051) /* RX filter 20 denominator 10 */
+#define B43_NPHY_RXF20_DENOM11			B43_PHY_N(0x052) /* RX filter 20 denominator 11 */
+#define B43_NPHY_RXF40_NUM0			B43_PHY_N(0x053) /* RX filter 40 numerator 0 */
+#define B43_NPHY_RXF40_NUM1			B43_PHY_N(0x054) /* RX filter 40 numerator 1 */
+#define B43_NPHY_RXF40_NUM2			B43_PHY_N(0x055) /* RX filter 40 numerator 2 */
+#define B43_NPHY_RXF40_DENOM0			B43_PHY_N(0x056) /* RX filter 40 denominator 0 */
+#define B43_NPHY_RXF40_DENOM1			B43_PHY_N(0x057) /* RX filter 40 denominator 1 */
+#define B43_NPHY_RXF40_NUM10			B43_PHY_N(0x058) /* RX filter 40 numerator 10 */
+#define B43_NPHY_RXF40_NUM11			B43_PHY_N(0x059) /* RX filter 40 numerator 11 */
+#define B43_NPHY_RXF40_NUM12			B43_PHY_N(0x05A) /* RX filter 40 numerator 12 */
+#define B43_NPHY_RXF40_DENOM10			B43_PHY_N(0x05B) /* RX filter 40 denominator 10 */
+#define B43_NPHY_RXF40_DENOM11			B43_PHY_N(0x05C) /* RX filter 40 denominator 11 */
+#define B43_NPHY_PPROC_RSTLEN			B43_PHY_N(0x060) /* Packet processing reset length */
+#define B43_NPHY_INITCARR_DLEN			B43_PHY_N(0x061) /* Initial carrier detection length */
+#define B43_NPHY_CLIP1CARR_DLEN			B43_PHY_N(0x062) /* Clip1 carrier detection length */
+#define B43_NPHY_CLIP2CARR_DLEN			B43_PHY_N(0x063) /* Clip2 carrier detection length */
+#define B43_NPHY_INITGAIN_SLEN			B43_PHY_N(0x064) /* Initial gain settle length */
+#define B43_NPHY_CLIP1GAIN_SLEN			B43_PHY_N(0x065) /* Clip1 gain settle length */
+#define B43_NPHY_CLIP2GAIN_SLEN			B43_PHY_N(0x066) /* Clip2 gain settle length */
+#define B43_NPHY_PACKGAIN_SLEN			B43_PHY_N(0x067) /* Packet gain settle length */
+#define B43_NPHY_CARRSRC_TLEN			B43_PHY_N(0x068) /* Carrier search timeout length */
+#define B43_NPHY_TISRC_TLEN			B43_PHY_N(0x069) /* Timing search timeout length */
+#define B43_NPHY_ENDROP_TLEN			B43_PHY_N(0x06A) /* Energy drop timeout length */
+#define B43_NPHY_CLIP1_NBDWELL_LEN		B43_PHY_N(0x06B) /* Clip1 NB dwell length */
+#define B43_NPHY_CLIP2_NBDWELL_LEN		B43_PHY_N(0x06C) /* Clip2 NB dwell length */
+#define B43_NPHY_W1CLIP1_DWELL_LEN		B43_PHY_N(0x06D) /* W1 clip1 dwell length */
+#define B43_NPHY_W1CLIP2_DWELL_LEN		B43_PHY_N(0x06E) /* W1 clip2 dwell length */
+#define B43_NPHY_W2CLIP1_DWELL_LEN		B43_PHY_N(0x06F) /* W2 clip1 dwell length */
+#define B43_NPHY_PLOAD_CSENSE_EXTLEN		B43_PHY_N(0x070) /* Payload carrier sense extension length */
+#define B43_NPHY_EDROP_CSENSE_EXTLEN		B43_PHY_N(0x071) /* Energy drop carrier sense extension length */
+#define B43_NPHY_TABLE_ADDR			B43_PHY_N(0x072) /* Table address */
+#define B43_NPHY_TABLE_DATALO			B43_PHY_N(0x073) /* Table data low */
+#define B43_NPHY_TABLE_DATAHI			B43_PHY_N(0x074) /* Table data high */
+#define B43_NPHY_WWISE_LENIDX			B43_PHY_N(0x075) /* WWiSE length index */
+#define B43_NPHY_TGNSYNC_LENIDX			B43_PHY_N(0x076) /* TGNsync length index */
+#define B43_NPHY_TXMACIF_HOLDOFF		B43_PHY_N(0x077) /* TX MAC IF Hold off */
+#define B43_NPHY_RFCTL_CMD			B43_PHY_N(0x078) /* RF control (command) */
+#define  B43_NPHY_RFCTL_CMD_START		0x0001 /* Start sequence */
+#define  B43_NPHY_RFCTL_CMD_RXTX		0x0002 /* RX/TX */
+#define  B43_NPHY_RFCTL_CMD_CORESEL		0x0038 /* Core select */
+#define  B43_NPHY_RFCTL_CMD_CORESEL_SHIFT	3
+#define  B43_NPHY_RFCTL_CMD_PORFORCE		0x0040 /* POR force */
+#define  B43_NPHY_RFCTL_CMD_OEPORFORCE		0x0080 /* OE POR force */
+#define  B43_NPHY_RFCTL_CMD_RXEN		0x0100 /* RX enable */
+#define  B43_NPHY_RFCTL_CMD_TXEN		0x0200 /* TX enable */
+#define  B43_NPHY_RFCTL_CMD_CHIP0PU		0x0400 /* Chip0 PU */
+#define  B43_NPHY_RFCTL_CMD_EN			0x0800 /* Radio enabled */
+#define  B43_NPHY_RFCTL_CMD_SEQENCORE		0xF000 /* Seq en core */
+#define  B43_NPHY_RFCTL_CMD_SEQENCORE_SHIFT	12
+#define B43_NPHY_RFCTL_RSSIO1			B43_PHY_N(0x07A) /* RF control (RSSI others 1) */
+#define  B43_NPHY_RFCTL_RSSIO1_RXPD		0x0001 /* RX PD */
+#define  B43_NPHY_RFCTL_RSSIO1_TXPD		0x0002 /* TX PD */
+#define  B43_NPHY_RFCTL_RSSIO1_PAPD		0x0004 /* PA PD */
+#define  B43_NPHY_RFCTL_RSSIO1_RSSICTL		0x0030 /* RSSI control */
+#define  B43_NPHY_RFCTL_RSSIO1_LPFBW		0x00C0 /* LPF bandwidth */
+#define  B43_NPHY_RFCTL_RSSIO1_HPFBWHI		0x0100 /* HPF bandwidth high */
+#define  B43_NPHY_RFCTL_RSSIO1_HIQDISCO		0x0200 /* HIQ dis core */
+#define B43_NPHY_RFCTL_RXG1			B43_PHY_N(0x07B) /* RF control (RX gain 1) */
+#define B43_NPHY_RFCTL_TXG1			B43_PHY_N(0x07C) /* RF control (TX gain 1) */
+#define B43_NPHY_RFCTL_RSSIO2			B43_PHY_N(0x07D) /* RF control (RSSI others 2) */
+#define  B43_NPHY_RFCTL_RSSIO2_RXPD		0x0001 /* RX PD */
+#define  B43_NPHY_RFCTL_RSSIO2_TXPD		0x0002 /* TX PD */
+#define  B43_NPHY_RFCTL_RSSIO2_PAPD		0x0004 /* PA PD */
+#define  B43_NPHY_RFCTL_RSSIO2_RSSICTL		0x0030 /* RSSI control */
+#define  B43_NPHY_RFCTL_RSSIO2_LPFBW		0x00C0 /* LPF bandwidth */
+#define  B43_NPHY_RFCTL_RSSIO2_HPFBWHI		0x0100 /* HPF bandwidth high */
+#define  B43_NPHY_RFCTL_RSSIO2_HIQDISCO		0x0200 /* HIQ dis core */
+#define B43_NPHY_RFCTL_RXG2			B43_PHY_N(0x07E) /* RF control (RX gain 2) */
+#define B43_NPHY_RFCTL_TXG2			B43_PHY_N(0x07F) /* RF control (TX gain 2) */
+#define B43_NPHY_RFCTL_RSSIO3			B43_PHY_N(0x080) /* RF control (RSSI others 3) */
+#define  B43_NPHY_RFCTL_RSSIO3_RXPD		0x0001 /* RX PD */
+#define  B43_NPHY_RFCTL_RSSIO3_TXPD		0x0002 /* TX PD */
+#define  B43_NPHY_RFCTL_RSSIO3_PAPD		0x0004 /* PA PD */
+#define  B43_NPHY_RFCTL_RSSIO3_RSSICTL		0x0030 /* RSSI control */
+#define  B43_NPHY_RFCTL_RSSIO3_LPFBW		0x00C0 /* LPF bandwidth */
+#define  B43_NPHY_RFCTL_RSSIO3_HPFBWHI		0x0100 /* HPF bandwidth high */
+#define  B43_NPHY_RFCTL_RSSIO3_HIQDISCO		0x0200 /* HIQ dis core */
+#define B43_NPHY_RFCTL_RXG3			B43_PHY_N(0x081) /* RF control (RX gain 3) */
+#define B43_NPHY_RFCTL_TXG3			B43_PHY_N(0x082) /* RF control (TX gain 3) */
+#define B43_NPHY_RFCTL_RSSIO4			B43_PHY_N(0x083) /* RF control (RSSI others 4) */
+#define  B43_NPHY_RFCTL_RSSIO4_RXPD		0x0001 /* RX PD */
+#define  B43_NPHY_RFCTL_RSSIO4_TXPD		0x0002 /* TX PD */
+#define  B43_NPHY_RFCTL_RSSIO4_PAPD		0x0004 /* PA PD */
+#define  B43_NPHY_RFCTL_RSSIO4_RSSICTL		0x0030 /* RSSI control */
+#define  B43_NPHY_RFCTL_RSSIO4_LPFBW		0x00C0 /* LPF bandwidth */
+#define  B43_NPHY_RFCTL_RSSIO4_HPFBWHI		0x0100 /* HPF bandwidth high */
+#define  B43_NPHY_RFCTL_RSSIO4_HIQDISCO		0x0200 /* HIQ dis core */
+#define B43_NPHY_RFCTL_RXG4			B43_PHY_N(0x084) /* RF control (RX gain 4) */
+#define B43_NPHY_RFCTL_TXG4			B43_PHY_N(0x085) /* RF control (TX gain 4) */
+#define B43_NPHY_C1_TXIQ_COMP_OFF		B43_PHY_N(0x087) /* Core 1 TX I/Q comp offset */
+#define B43_NPHY_C2_TXIQ_COMP_OFF		B43_PHY_N(0x088) /* Core 2 TX I/Q comp offset */
+#define B43_NPHY_C1_TXCTL			B43_PHY_N(0x08B) /* Core 1 TX control */
+#define B43_NPHY_C2_TXCTL			B43_PHY_N(0x08C) /* Core 2 TX control */
+#define B43_NPHY_AFECTL_OVER1			B43_PHY_N(0x08F) /* AFE control override 1 */
+#define B43_NPHY_SCRAM_SIGCTL			B43_PHY_N(0x090) /* Scram signal control */
+#define  B43_NPHY_SCRAM_SIGCTL_INITST		0x007F /* Initial state value */
+#define  B43_NPHY_SCRAM_SIGCTL_INITST_SHIFT	0
+#define  B43_NPHY_SCRAM_SIGCTL_SCM		0x0080 /* Scram control mode */
+#define  B43_NPHY_SCRAM_SIGCTL_SICE		0x0100 /* Scram index control enable */
+#define  B43_NPHY_SCRAM_SIGCTL_START		0xFE00 /* Scram start bit */
+#define  B43_NPHY_SCRAM_SIGCTL_START_SHIFT	9
+#define B43_NPHY_RFCTL_INTC1			B43_PHY_N(0x091) /* RF control (intc 1) */
+#define B43_NPHY_RFCTL_INTC2			B43_PHY_N(0x092) /* RF control (intc 2) */
+#define B43_NPHY_RFCTL_INTC3			B43_PHY_N(0x093) /* RF control (intc 3) */
+#define B43_NPHY_RFCTL_INTC4			B43_PHY_N(0x094) /* RF control (intc 4) */
+#define B43_NPHY_NRDTO_WWISE			B43_PHY_N(0x095) /* # datatones WWiSE */
+#define B43_NPHY_NRDTO_TGNSYNC			B43_PHY_N(0x096) /* # datatones TGNsync */
+#define B43_NPHY_SIGFMOD_WWISE			B43_PHY_N(0x097) /* Signal field mod WWiSE */
+#define B43_NPHY_LEG_SIGFMOD_11N		B43_PHY_N(0x098) /* Legacy signal field mod 11n */
+#define B43_NPHY_HT_SIGFMOD_11N			B43_PHY_N(0x099) /* HT signal field mod 11n */
+#define B43_NPHY_C1_RXIQ_COMPA0			B43_PHY_N(0x09A) /* Core 1 RX I/Q comp A0 */
+#define B43_NPHY_C1_RXIQ_COMPB0			B43_PHY_N(0x09B) /* Core 1 RX I/Q comp B0 */
+#define B43_NPHY_C2_RXIQ_COMPA1			B43_PHY_N(0x09C) /* Core 2 RX I/Q comp A1 */
+#define B43_NPHY_C2_RXIQ_COMPB1			B43_PHY_N(0x09D) /* Core 2 RX I/Q comp B1 */
+#define B43_NPHY_RXCTL				B43_PHY_N(0x0A0) /* RX control */
+#define  B43_NPHY_RXCTL_BSELU20			0x0010 /* Band select upper 20 */
+#define  B43_NPHY_RXCTL_RIFSEN			0x0080 /* RIFS enable */
+#define B43_NPHY_RFSEQMODE			B43_PHY_N(0x0A1) /* RF seq mode */
+#define  B43_NPHY_RFSEQMODE_CAOVER		0x0001 /* Core active override */
+#define  B43_NPHY_RFSEQMODE_TROVER		0x0002 /* Trigger override */
+#define B43_NPHY_RFSEQCA			B43_PHY_N(0x0A2) /* RF seq core active */
+#define  B43_NPHY_RFSEQCA_TXEN			0x000F /* TX enable */
+#define  B43_NPHY_RFSEQCA_TXEN_SHIFT		0
+#define  B43_NPHY_RFSEQCA_RXEN			0x00F0 /* RX enable */
+#define  B43_NPHY_RFSEQCA_RXEN_SHIFT		4
+#define  B43_NPHY_RFSEQCA_TXDIS			0x0F00 /* TX disable */
+#define  B43_NPHY_RFSEQCA_TXDIS_SHIFT		8
+#define  B43_NPHY_RFSEQCA_RXDIS			0xF000 /* RX disable */
+#define  B43_NPHY_RFSEQCA_RXDIS_SHIFT		12
+#define B43_NPHY_RFSEQTR			B43_PHY_N(0x0A3) /* RF seq trigger */
+#define  B43_NPHY_RFSEQTR_RX2TX			0x0001 /* RX2TX */
+#define  B43_NPHY_RFSEQTR_TX2RX			0x0002 /* TX2RX */
+#define  B43_NPHY_RFSEQTR_UPGH			0x0004 /* Update gain H */
+#define  B43_NPHY_RFSEQTR_UPGL			0x0008 /* Update gain L */
+#define  B43_NPHY_RFSEQTR_UPGU			0x0010 /* Update gain U */
+#define  B43_NPHY_RFSEQTR_RST2RX		0x0020 /* Reset to RX */
+#define B43_NPHY_RFSEQST			B43_PHY_N(0x0A4) /* RF seq status. Values same as trigger. */
+#define B43_NPHY_AFECTL_OVER			B43_PHY_N(0x0A5) /* AFE control override */
+#define B43_NPHY_AFECTL_C1			B43_PHY_N(0x0A6) /* AFE control core 1 */
+#define B43_NPHY_AFECTL_C2			B43_PHY_N(0x0A7) /* AFE control core 2 */
+#define B43_NPHY_AFECTL_C3			B43_PHY_N(0x0A8) /* AFE control core 3 */
+#define B43_NPHY_AFECTL_C4			B43_PHY_N(0x0A9) /* AFE control core 4 */
+#define B43_NPHY_AFECTL_DACGAIN1		B43_PHY_N(0x0AA) /* AFE control DAC gain 1 */
+#define B43_NPHY_AFECTL_DACGAIN2		B43_PHY_N(0x0AB) /* AFE control DAC gain 2 */
+#define B43_NPHY_AFECTL_DACGAIN3		B43_PHY_N(0x0AC) /* AFE control DAC gain 3 */
+#define B43_NPHY_AFECTL_DACGAIN4		B43_PHY_N(0x0AD) /* AFE control DAC gain 4 */
+#define B43_NPHY_STR_ADDR1			B43_PHY_N(0x0AE) /* STR address 1 */
+#define B43_NPHY_STR_ADDR2			B43_PHY_N(0x0AF) /* STR address 2 */
+#define B43_NPHY_CLASSCTL			B43_PHY_N(0x0B0) /* Classifier control */
+#define  B43_NPHY_CLASSCTL_CCKEN		0x0001 /* CCK enable */
+#define  B43_NPHY_CLASSCTL_OFDMEN		0x0002 /* OFDM enable */
+#define  B43_NPHY_CLASSCTL_WAITEDEN		0x0004 /* Waited enable */
+#define B43_NPHY_IQFLIP				B43_PHY_N(0x0B1) /* I/Q flip */
+#define  B43_NPHY_IQFLIP_ADC1			0x0001 /* ADC1 */
+#define  B43_NPHY_IQFLIP_ADC2			0x0010 /* ADC2 */
+#define B43_NPHY_SISO_SNR_THRES			B43_PHY_N(0x0B2) /* SISO SNR threshold */
+#define B43_NPHY_SIGMA_N_MULT			B43_PHY_N(0x0B3) /* Sigma N multiplier */
+#define B43_NPHY_TXMACDELAY			B43_PHY_N(0x0B4) /* TX MAC delay */
+#define B43_NPHY_TXFRAMEDELAY			B43_PHY_N(0x0B5) /* TX frame delay */
+#define B43_NPHY_MLPARM				B43_PHY_N(0x0B6) /* ML parameters */
+#define B43_NPHY_MLCTL				B43_PHY_N(0x0B7) /* ML control */
+#define B43_NPHY_WWISE_20NCYCDAT		B43_PHY_N(0x0B8) /* WWiSE 20 N cyc data */
+#define B43_NPHY_WWISE_40NCYCDAT		B43_PHY_N(0x0B9) /* WWiSE 40 N cyc data */
+#define B43_NPHY_TGNSYNC_20NCYCDAT		B43_PHY_N(0x0BA) /* TGNsync 20 N cyc data */
+#define B43_NPHY_TGNSYNC_40NCYCDAT		B43_PHY_N(0x0BB) /* TGNsync 40 N cyc data */
+#define B43_NPHY_INITSWIZP			B43_PHY_N(0x0BC) /* Initial swizzle pattern */
+#define B43_NPHY_TXTAILCNT			B43_PHY_N(0x0BD) /* TX tail count value */
+#define B43_NPHY_BPHY_CTL1			B43_PHY_N(0x0BE) /* B PHY control 1 */
+#define B43_NPHY_BPHY_CTL2			B43_PHY_N(0x0BF) /* B PHY control 2 */
+#define  B43_NPHY_BPHY_CTL2_LUT			0x001F /* LUT index */
+#define  B43_NPHY_BPHY_CTL2_LUT_SHIFT		0
+#define  B43_NPHY_BPHY_CTL2_MACDEL		0x7FE0 /* MAC delay */
+#define  B43_NPHY_BPHY_CTL2_MACDEL_SHIFT	5
+#define B43_NPHY_IQLOCAL_CMD			B43_PHY_N(0x0C0) /* I/Q LO cal command */
+#define  B43_NPHY_IQLOCAL_CMD_EN		0x8000
+#define B43_NPHY_IQLOCAL_CMDNNUM		B43_PHY_N(0x0C1) /* I/Q LO cal command N num */
+#define B43_NPHY_IQLOCAL_CMDGCTL		B43_PHY_N(0x0C2) /* I/Q LO cal command G control */
+#define B43_NPHY_SAMP_CMD			B43_PHY_N(0x0C3) /* Sample command */
+#define  B43_NPHY_SAMP_CMD_STOP			0x0002 /* Stop */
+#define B43_NPHY_SAMP_LOOPCNT			B43_PHY_N(0x0C4) /* Sample loop count */
+#define B43_NPHY_SAMP_WAITCNT			B43_PHY_N(0x0C5) /* Sample wait count */
+#define B43_NPHY_SAMP_DEPCNT			B43_PHY_N(0x0C6) /* Sample depth count */
+#define B43_NPHY_SAMP_STAT			B43_PHY_N(0x0C7) /* Sample status */
+#define B43_NPHY_GPIO_LOOEN			B43_PHY_N(0x0C8) /* GPIO low out enable */
+#define B43_NPHY_GPIO_HIOEN			B43_PHY_N(0x0C9) /* GPIO high out enable */
+#define B43_NPHY_GPIO_SEL			B43_PHY_N(0x0CA) /* GPIO select */
+#define B43_NPHY_GPIO_CLKCTL			B43_PHY_N(0x0CB) /* GPIO clock control */
+#define B43_NPHY_TXF_20CO_AS0			B43_PHY_N(0x0CC) /* TX filter 20 coeff A stage 0 */
+#define B43_NPHY_TXF_20CO_AS1			B43_PHY_N(0x0CD) /* TX filter 20 coeff A stage 1 */
+#define B43_NPHY_TXF_20CO_AS2			B43_PHY_N(0x0CE) /* TX filter 20 coeff A stage 2 */
+#define B43_NPHY_TXF_20CO_B32S0			B43_PHY_N(0x0CF) /* TX filter 20 coeff B32 stage 0 */
+#define B43_NPHY_TXF_20CO_B1S0			B43_PHY_N(0x0D0) /* TX filter 20 coeff B1 stage 0 */
+#define B43_NPHY_TXF_20CO_B32S1			B43_PHY_N(0x0D1) /* TX filter 20 coeff B32 stage 1 */
+#define B43_NPHY_TXF_20CO_B1S1			B43_PHY_N(0x0D2) /* TX filter 20 coeff B1 stage 1 */
+#define B43_NPHY_TXF_20CO_B32S2			B43_PHY_N(0x0D3) /* TX filter 20 coeff B32 stage 2 */
+#define B43_NPHY_TXF_20CO_B1S2			B43_PHY_N(0x0D4) /* TX filter 20 coeff B1 stage 2 */
+#define B43_NPHY_SIGFLDTOL			B43_PHY_N(0x0D5) /* Signal fld tolerance */
+#define B43_NPHY_TXSERFLD			B43_PHY_N(0x0D6) /* TX service field */
+#define B43_NPHY_AFESEQ_RX2TX_PUD		B43_PHY_N(0x0D7) /* AFE seq RX2TX power up/down delay */
+#define B43_NPHY_AFESEQ_TX2RX_PUD		B43_PHY_N(0x0D8) /* AFE seq TX2RX power up/down delay */
+#define B43_NPHY_TGNSYNC_SCRAMI0		B43_PHY_N(0x0D9) /* TGNsync scram init 0 */
+#define B43_NPHY_TGNSYNC_SCRAMI1		B43_PHY_N(0x0DA) /* TGNsync scram init 1 */
+#define B43_NPHY_INITSWIZPATTLEG		B43_PHY_N(0x0DB) /* Initial swizzle pattern leg */
+#define B43_NPHY_BPHY_CTL3			B43_PHY_N(0x0DC) /* B PHY control 3 */
+#define  B43_NPHY_BPHY_CTL3_SCALE		0x00FF /* Scale */
+#define  B43_NPHY_BPHY_CTL3_SCALE_SHIFT		0
+#define  B43_NPHY_BPHY_CTL3_FSC			0xFF00 /* Frame start count value */
+#define  B43_NPHY_BPHY_CTL3_FSC_SHIFT		8
+#define B43_NPHY_BPHY_CTL4			B43_PHY_N(0x0DD) /* B PHY control 4 */
+#define B43_NPHY_C1_TXBBMULT			B43_PHY_N(0x0DE) /* Core 1 TX BB multiplier */
+#define B43_NPHY_C2_TXBBMULT			B43_PHY_N(0x0DF) /* Core 2 TX BB multiplier */
+#define B43_NPHY_TXF_40CO_AS0			B43_PHY_N(0x0E1) /* TX filter 40 coeff A stage 0 */
+#define B43_NPHY_TXF_40CO_AS1			B43_PHY_N(0x0E2) /* TX filter 40 coeff A stage 1 */
+#define B43_NPHY_TXF_40CO_AS2			B43_PHY_N(0x0E3) /* TX filter 40 coeff A stage 2 */
+#define B43_NPHY_TXF_40CO_B32S0			B43_PHY_N(0x0E4) /* TX filter 40 coeff B32 stage 0 */
+#define B43_NPHY_TXF_40CO_B1S0			B43_PHY_N(0x0E5) /* TX filter 40 coeff B1 stage 0 */
+#define B43_NPHY_TXF_40CO_B32S1			B43_PHY_N(0x0E6) /* TX filter 40 coeff B32 stage 1 */
+#define B43_NPHY_TXF_40CO_B1S1			B43_PHY_N(0x0E7) /* TX filter 40 coeff B1 stage 1 */
+#define B43_NPHY_REV3_RFCTL_OVER0		B43_PHY_N(0x0E7)
+#define B43_NPHY_TXF_40CO_B32S2			B43_PHY_N(0x0E8) /* TX filter 40 coeff B32 stage 2 */
+#define B43_NPHY_TXF_40CO_B1S2			B43_PHY_N(0x0E9) /* TX filter 40 coeff B1 stage 2 */
+#define B43_NPHY_BIST_STAT2			B43_PHY_N(0x0EA) /* BIST status 2 */
+#define B43_NPHY_BIST_STAT3			B43_PHY_N(0x0EB) /* BIST status 3 */
+#define B43_NPHY_RFCTL_OVER			B43_PHY_N(0x0EC) /* RF control override */
+#define B43_NPHY_REV3_RFCTL_OVER1		B43_PHY_N(0x0EC)
+#define B43_NPHY_MIMOCFG			B43_PHY_N(0x0ED) /* MIMO config */
+#define  B43_NPHY_MIMOCFG_GFMIX			0x0004 /* Greenfield or mixed mode */
+#define  B43_NPHY_MIMOCFG_AUTO			0x0100 /* Greenfield/mixed mode auto */
+#define B43_NPHY_RADAR_BLNKCTL			B43_PHY_N(0x0EE) /* Radar blank control */
+#define B43_NPHY_A0RADAR_FIFOCTL		B43_PHY_N(0x0EF) /* Antenna 0 radar FIFO control */
+#define B43_NPHY_A1RADAR_FIFOCTL		B43_PHY_N(0x0F0) /* Antenna 1 radar FIFO control */
+#define B43_NPHY_A0RADAR_FIFODAT		B43_PHY_N(0x0F1) /* Antenna 0 radar FIFO data */
+#define B43_NPHY_A1RADAR_FIFODAT		B43_PHY_N(0x0F2) /* Antenna 1 radar FIFO data */
+#define B43_NPHY_RADAR_THRES0			B43_PHY_N(0x0F3) /* Radar threshold 0 */
+#define B43_NPHY_RADAR_THRES1			B43_PHY_N(0x0F4) /* Radar threshold 1 */
+#define B43_NPHY_RADAR_THRES0R			B43_PHY_N(0x0F5) /* Radar threshold 0R */
+#define B43_NPHY_RADAR_THRES1R			B43_PHY_N(0x0F6) /* Radar threshold 1R */
+#define B43_NPHY_CSEN_20IN40_DLEN		B43_PHY_N(0x0F7) /* Carrier sense 20 in 40 dwell length */
+#define B43_NPHY_RFCTL_LUT_TRSW_LO1		B43_PHY_N(0x0F8) /* RF control LUT TRSW lower 1 */
+#define B43_NPHY_RFCTL_LUT_TRSW_UP1		B43_PHY_N(0x0F9) /* RF control LUT TRSW upper 1 */
+#define B43_NPHY_RFCTL_LUT_TRSW_LO2		B43_PHY_N(0x0FA) /* RF control LUT TRSW lower 2 */
+#define B43_NPHY_RFCTL_LUT_TRSW_UP2		B43_PHY_N(0x0FB) /* RF control LUT TRSW upper 2 */
+#define B43_NPHY_RFCTL_LUT_TRSW_LO3		B43_PHY_N(0x0FC) /* RF control LUT TRSW lower 3 */
+#define B43_NPHY_RFCTL_LUT_TRSW_UP3		B43_PHY_N(0x0FD) /* RF control LUT TRSW upper 3 */
+#define B43_NPHY_RFCTL_LUT_TRSW_LO4		B43_PHY_N(0x0FE) /* RF control LUT TRSW lower 4 */
+#define B43_NPHY_RFCTL_LUT_TRSW_UP4		B43_PHY_N(0x0FF) /* RF control LUT TRSW upper 4 */
+#define B43_NPHY_RFCTL_LUT_LNAPA1		B43_PHY_N(0x100) /* RF control LUT LNA PA 1 */
+#define B43_NPHY_RFCTL_LUT_LNAPA2		B43_PHY_N(0x101) /* RF control LUT LNA PA 2 */
+#define B43_NPHY_RFCTL_LUT_LNAPA3		B43_PHY_N(0x102) /* RF control LUT LNA PA 3 */
+#define B43_NPHY_RFCTL_LUT_LNAPA4		B43_PHY_N(0x103) /* RF control LUT LNA PA 4 */
+#define B43_NPHY_TGNSYNC_CRCM0			B43_PHY_N(0x104) /* TGNsync CRC mask 0 */
+#define B43_NPHY_TGNSYNC_CRCM1			B43_PHY_N(0x105) /* TGNsync CRC mask 1 */
+#define B43_NPHY_TGNSYNC_CRCM2			B43_PHY_N(0x106) /* TGNsync CRC mask 2 */
+#define B43_NPHY_TGNSYNC_CRCM3			B43_PHY_N(0x107) /* TGNsync CRC mask 3 */
+#define B43_NPHY_TGNSYNC_CRCM4			B43_PHY_N(0x108) /* TGNsync CRC mask 4 */
+#define B43_NPHY_CRCPOLY			B43_PHY_N(0x109) /* CRC polynomial */
+#define B43_NPHY_SIGCNT				B43_PHY_N(0x10A) /* # sig count */
+#define B43_NPHY_SIGSTARTBIT_CTL		B43_PHY_N(0x10B) /* Sig start bit control */
+#define B43_NPHY_CRCPOLY_ORDER			B43_PHY_N(0x10C) /* CRC polynomial order */
+#define B43_NPHY_RFCTL_CST0			B43_PHY_N(0x10D) /* RF control core swap table 0 */
+#define B43_NPHY_RFCTL_CST1			B43_PHY_N(0x10E) /* RF control core swap table 1 */
+#define B43_NPHY_RFCTL_CST2O			B43_PHY_N(0x10F) /* RF control core swap table 2 + others */
+#define B43_NPHY_BPHY_CTL5			B43_PHY_N(0x111) /* B PHY control 5 */
+#define B43_NPHY_RFSEQ_LPFBW			B43_PHY_N(0x112) /* RF seq LPF bandwidth */
+#define B43_NPHY_TSSIBIAS1			B43_PHY_N(0x114) /* TSSI bias val 1 */
+#define B43_NPHY_TSSIBIAS2			B43_PHY_N(0x115) /* TSSI bias val 2 */
+#define  B43_NPHY_TSSIBIAS_BIAS			0x00FF /* Bias */
+#define  B43_NPHY_TSSIBIAS_BIAS_SHIFT		0
+#define  B43_NPHY_TSSIBIAS_VAL			0xFF00 /* Value */
+#define  B43_NPHY_TSSIBIAS_VAL_SHIFT		8
+#define B43_NPHY_ESTPWR1			B43_PHY_N(0x118) /* Estimated power 1 */
+#define B43_NPHY_ESTPWR2			B43_PHY_N(0x119) /* Estimated power 2 */
+#define  B43_NPHY_ESTPWR_PWR			0x00FF /* Estimated power */
+#define  B43_NPHY_ESTPWR_PWR_SHIFT		0
+#define  B43_NPHY_ESTPWR_VALID			0x0100 /* Estimated power valid */
+#define B43_NPHY_TSSI_MAXTXFDT			B43_PHY_N(0x11C) /* TSSI max TX frame delay time */
+#define  B43_NPHY_TSSI_MAXTXFDT_VAL		0x00FF /* max TX frame delay time */
+#define  B43_NPHY_TSSI_MAXTXFDT_VAL_SHIFT	0
+#define B43_NPHY_TSSI_MAXTDT			B43_PHY_N(0x11D) /* TSSI max TSSI delay time */
+#define  B43_NPHY_TSSI_MAXTDT_VAL		0x00FF /* max TSSI delay time */
+#define  B43_NPHY_TSSI_MAXTDT_VAL_SHIFT		0
+#define B43_NPHY_ITSSI1				B43_PHY_N(0x11E) /* TSSI idle 1 */
+#define B43_NPHY_ITSSI2				B43_PHY_N(0x11F) /* TSSI idle 2 */
+#define  B43_NPHY_ITSSI_VAL			0x00FF /* Idle TSSI */
+#define  B43_NPHY_ITSSI_VAL_SHIFT		0
+#define B43_NPHY_TSSIMODE			B43_PHY_N(0x122) /* TSSI mode */
+#define  B43_NPHY_TSSIMODE_EN			0x0001 /* TSSI enable */
+#define  B43_NPHY_TSSIMODE_PDEN			0x0002 /* Power det enable */
+#define B43_NPHY_RXMACIFM			B43_PHY_N(0x123) /* RX Macif mode */
+#define B43_NPHY_CRSIT_COCNT_LO			B43_PHY_N(0x124) /* CRS idle time CRS-on count (low) */
+#define B43_NPHY_CRSIT_COCNT_HI			B43_PHY_N(0x125) /* CRS idle time CRS-on count (high) */
+#define B43_NPHY_CRSIT_MTCNT_LO			B43_PHY_N(0x126) /* CRS idle time measure time count (low) */
+#define B43_NPHY_CRSIT_MTCNT_HI			B43_PHY_N(0x127) /* CRS idle time measure time count (high) */
+#define B43_NPHY_SAMTWC				B43_PHY_N(0x128) /* Sample tail wait count */
+#define B43_NPHY_IQEST_CMD			B43_PHY_N(0x129) /* I/Q estimate command */
+#define  B43_NPHY_IQEST_CMD_START		0x0001 /* Start */
+#define  B43_NPHY_IQEST_CMD_MODE		0x0002 /* Mode */
+#define B43_NPHY_IQEST_WT			B43_PHY_N(0x12A) /* I/Q estimate wait time */
+#define  B43_NPHY_IQEST_WT_VAL			0x00FF /* Wait time */
+#define  B43_NPHY_IQEST_WT_VAL_SHIFT		0
+#define B43_NPHY_IQEST_SAMCNT			B43_PHY_N(0x12B) /* I/Q estimate sample count */
+#define B43_NPHY_IQEST_IQACC_LO0		B43_PHY_N(0x12C) /* I/Q estimate I/Q acc lo 0 */
+#define B43_NPHY_IQEST_IQACC_HI0		B43_PHY_N(0x12D) /* I/Q estimate I/Q acc hi 0 */
+#define B43_NPHY_IQEST_IPACC_LO0		B43_PHY_N(0x12E) /* I/Q estimate I power acc lo 0 */
+#define B43_NPHY_IQEST_IPACC_HI0		B43_PHY_N(0x12F) /* I/Q estimate I power acc hi 0 */
+#define B43_NPHY_IQEST_QPACC_LO0		B43_PHY_N(0x130) /* I/Q estimate Q power acc lo 0 */
+#define B43_NPHY_IQEST_QPACC_HI0		B43_PHY_N(0x131) /* I/Q estimate Q power acc hi 0 */
+#define B43_NPHY_IQEST_IQACC_LO1		B43_PHY_N(0x134) /* I/Q estimate I/Q acc lo 1 */
+#define B43_NPHY_IQEST_IQACC_HI1		B43_PHY_N(0x135) /* I/Q estimate I/Q acc hi 1 */
+#define B43_NPHY_IQEST_IPACC_LO1		B43_PHY_N(0x136) /* I/Q estimate I power acc lo 1 */
+#define B43_NPHY_IQEST_IPACC_HI1		B43_PHY_N(0x137) /* I/Q estimate I power acc hi 1 */
+#define B43_NPHY_IQEST_QPACC_LO1		B43_PHY_N(0x138) /* I/Q estimate Q power acc lo 1 */
+#define B43_NPHY_IQEST_QPACC_HI1		B43_PHY_N(0x139) /* I/Q estimate Q power acc hi 1 */
+#define B43_NPHY_MIMO_CRSTXEXT			B43_PHY_N(0x13A) /* MIMO PHY CRS TX extension */
+#define B43_NPHY_PWRDET1			B43_PHY_N(0x13B) /* Power det 1 */
+#define B43_NPHY_PWRDET2			B43_PHY_N(0x13C) /* Power det 2 */
+#define B43_NPHY_MAXRSSI_DTIME			B43_PHY_N(0x13F) /* RSSI max RSSI delay time */
+#define B43_NPHY_PIL_DW0			B43_PHY_N(0x141) /* Pilot data weight 0 */
+#define B43_NPHY_PIL_DW1			B43_PHY_N(0x142) /* Pilot data weight 1 */
+#define B43_NPHY_PIL_DW2			B43_PHY_N(0x143) /* Pilot data weight 2 */
+#define  B43_NPHY_PIL_DW_BPSK			0x000F /* BPSK */
+#define  B43_NPHY_PIL_DW_BPSK_SHIFT		0
+#define  B43_NPHY_PIL_DW_QPSK			0x00F0 /* QPSK */
+#define  B43_NPHY_PIL_DW_QPSK_SHIFT		4
+#define  B43_NPHY_PIL_DW_16QAM			0x0F00 /* 16-QAM */
+#define  B43_NPHY_PIL_DW_16QAM_SHIFT		8
+#define  B43_NPHY_PIL_DW_64QAM			0xF000 /* 64-QAM */
+#define  B43_NPHY_PIL_DW_64QAM_SHIFT		12
+#define B43_NPHY_FMDEM_CFG			B43_PHY_N(0x144) /* FM demodulation config */
+#define B43_NPHY_PHASETR_A0			B43_PHY_N(0x145) /* Phase track alpha 0 */
+#define B43_NPHY_PHASETR_A1			B43_PHY_N(0x146) /* Phase track alpha 1 */
+#define B43_NPHY_PHASETR_A2			B43_PHY_N(0x147) /* Phase track alpha 2 */
+#define B43_NPHY_PHASETR_B0			B43_PHY_N(0x148) /* Phase track beta 0 */
+#define B43_NPHY_PHASETR_B1			B43_PHY_N(0x149) /* Phase track beta 1 */
+#define B43_NPHY_PHASETR_B2			B43_PHY_N(0x14A) /* Phase track beta 2 */
+#define B43_NPHY_PHASETR_CHG0			B43_PHY_N(0x14B) /* Phase track change 0 */
+#define B43_NPHY_PHASETR_CHG1			B43_PHY_N(0x14C) /* Phase track change 1 */
+#define B43_NPHY_PHASETW_OFF			B43_PHY_N(0x14D) /* Phase track offset */
+#define B43_NPHY_RFCTL_DBG			B43_PHY_N(0x14E) /* RF control debug */
+#define B43_NPHY_CCK_SHIFTB_REF			B43_PHY_N(0x150) /* CCK shiftbits reference var */
+#define B43_NPHY_OVER_DGAIN0			B43_PHY_N(0x152) /* Override digital gain 0 */
+#define B43_NPHY_OVER_DGAIN1			B43_PHY_N(0x153) /* Override digital gain 1 */
+#define  B43_NPHY_OVER_DGAIN_FDGV		0x0007 /* Force digital gain value */
+#define  B43_NPHY_OVER_DGAIN_FDGV_SHIFT		0
+#define  B43_NPHY_OVER_DGAIN_FDGEN		0x0008 /* Force digital gain enable */
+#define  B43_NPHY_OVER_DGAIN_CCKDGECV		0xFF00 /* CCK digital gain enable count value */
+#define  B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT	8
+#define B43_NPHY_BIST_STAT4			B43_PHY_N(0x156) /* BIST status 4 */
+#define B43_NPHY_RADAR_MAL			B43_PHY_N(0x157) /* Radar MA length */
+#define B43_NPHY_RADAR_SRCCTL			B43_PHY_N(0x158) /* Radar search control */
+#define B43_NPHY_VLD_DTSIG			B43_PHY_N(0x159) /* VLD data tones sig */
+#define B43_NPHY_VLD_DTDAT			B43_PHY_N(0x15A) /* VLD data tones data */
+#define B43_NPHY_C1_BPHY_RXIQCA0		B43_PHY_N(0x15B) /* Core 1 B PHY RX I/Q comp A0 */
+#define B43_NPHY_C1_BPHY_RXIQCB0		B43_PHY_N(0x15C) /* Core 1 B PHY RX I/Q comp B0 */
+#define B43_NPHY_C2_BPHY_RXIQCA1		B43_PHY_N(0x15D) /* Core 2 B PHY RX I/Q comp A1 */
+#define B43_NPHY_C2_BPHY_RXIQCB1		B43_PHY_N(0x15E) /* Core 2 B PHY RX I/Q comp B1 */
+#define B43_NPHY_FREQGAIN0			B43_PHY_N(0x160) /* Frequency gain 0 */
+#define B43_NPHY_FREQGAIN1			B43_PHY_N(0x161) /* Frequency gain 1 */
+#define B43_NPHY_FREQGAIN2			B43_PHY_N(0x162) /* Frequency gain 2 */
+#define B43_NPHY_FREQGAIN3			B43_PHY_N(0x163) /* Frequency gain 3 */
+#define B43_NPHY_FREQGAIN4			B43_PHY_N(0x164) /* Frequency gain 4 */
+#define B43_NPHY_FREQGAIN5			B43_PHY_N(0x165) /* Frequency gain 5 */
+#define B43_NPHY_FREQGAIN6			B43_PHY_N(0x166) /* Frequency gain 6 */
+#define B43_NPHY_FREQGAIN7			B43_PHY_N(0x167) /* Frequency gain 7 */
+#define B43_NPHY_FREQGAIN_BYPASS		B43_PHY_N(0x168) /* Frequency gain bypass */
+#define B43_NPHY_TRLOSS				B43_PHY_N(0x169) /* TR loss value */
+#define B43_NPHY_C1_ADCCLIP			B43_PHY_N(0x16A) /* Core 1 ADC clip */
+#define B43_NPHY_C2_ADCCLIP			B43_PHY_N(0x16B) /* Core 2 ADC clip */
+#define B43_NPHY_LTRN_OFFGAIN			B43_PHY_N(0x16F) /* LTRN offset gain */
+#define B43_NPHY_LTRN_OFF			B43_PHY_N(0x170) /* LTRN offset */
+#define B43_NPHY_NRDATAT_WWISE20SIG		B43_PHY_N(0x171) /* # data tones WWiSE 20 sig */
+#define B43_NPHY_NRDATAT_WWISE40SIG		B43_PHY_N(0x172) /* # data tones WWiSE 40 sig */
+#define B43_NPHY_NRDATAT_TGNSYNC20SIG		B43_PHY_N(0x173) /* # data tones TGNsync 20 sig */
+#define B43_NPHY_NRDATAT_TGNSYNC40SIG		B43_PHY_N(0x174) /* # data tones TGNsync 40 sig */
+#define B43_NPHY_WWISE_CRCM0			B43_PHY_N(0x175) /* WWiSE CRC mask 0 */
+#define B43_NPHY_WWISE_CRCM1			B43_PHY_N(0x176) /* WWiSE CRC mask 1 */
+#define B43_NPHY_WWISE_CRCM2			B43_PHY_N(0x177) /* WWiSE CRC mask 2 */
+#define B43_NPHY_WWISE_CRCM3			B43_PHY_N(0x178) /* WWiSE CRC mask 3 */
+#define B43_NPHY_WWISE_CRCM4			B43_PHY_N(0x179) /* WWiSE CRC mask 4 */
+#define B43_NPHY_CHANEST_CDDSH			B43_PHY_N(0x17A) /* Channel estimate CDD shift */
+#define B43_NPHY_HTAGC_WCNT			B43_PHY_N(0x17B) /* HT ADC wait counters */
+#define B43_NPHY_SQPARM				B43_PHY_N(0x17C) /* SQ params */
+#define B43_NPHY_MCSDUP6M			B43_PHY_N(0x17D) /* MCS dup 6M */
+#define B43_NPHY_NDATAT_DUP40			B43_PHY_N(0x17E) /* # data tones dup 40 */
+#define B43_NPHY_DUP40_TGNSYNC_CYCD		B43_PHY_N(0x17F) /* Dup40 TGNsync cycle data */
+#define B43_NPHY_DUP40_GFBL			B43_PHY_N(0x180) /* Dup40 GF format BL address */
+#define B43_NPHY_DUP40_BL			B43_PHY_N(0x181) /* Dup40 format BL address */
+#define B43_NPHY_LEGDUP_FTA			B43_PHY_N(0x182) /* Legacy dup frm table address */
+#define B43_NPHY_PACPROC_DBG			B43_PHY_N(0x183) /* Packet processing debug */
+#define B43_NPHY_PIL_CYC1			B43_PHY_N(0x184) /* Pilot cycle counter 1 */
+#define B43_NPHY_PIL_CYC2			B43_PHY_N(0x185) /* Pilot cycle counter 2 */
+#define B43_NPHY_TXF_20CO_S0A1			B43_PHY_N(0x186) /* TX filter 20 coeff stage 0 A1 */
+#define B43_NPHY_TXF_20CO_S0A2			B43_PHY_N(0x187) /* TX filter 20 coeff stage 0 A2 */
+#define B43_NPHY_TXF_20CO_S1A1			B43_PHY_N(0x188) /* TX filter 20 coeff stage 1 A1 */
+#define B43_NPHY_TXF_20CO_S1A2			B43_PHY_N(0x189) /* TX filter 20 coeff stage 1 A2 */
+#define B43_NPHY_TXF_20CO_S2A1			B43_PHY_N(0x18A) /* TX filter 20 coeff stage 2 A1 */
+#define B43_NPHY_TXF_20CO_S2A2			B43_PHY_N(0x18B) /* TX filter 20 coeff stage 2 A2 */
+#define B43_NPHY_TXF_20CO_S0B1			B43_PHY_N(0x18C) /* TX filter 20 coeff stage 0 B1 */
+#define B43_NPHY_TXF_20CO_S0B2			B43_PHY_N(0x18D) /* TX filter 20 coeff stage 0 B2 */
+#define B43_NPHY_TXF_20CO_S0B3			B43_PHY_N(0x18E) /* TX filter 20 coeff stage 0 B3 */
+#define B43_NPHY_TXF_20CO_S1B1			B43_PHY_N(0x18F) /* TX filter 20 coeff stage 1 B1 */
+#define B43_NPHY_TXF_20CO_S1B2			B43_PHY_N(0x190) /* TX filter 20 coeff stage 1 B2 */
+#define B43_NPHY_TXF_20CO_S1B3			B43_PHY_N(0x191) /* TX filter 20 coeff stage 1 B3 */
+#define B43_NPHY_TXF_20CO_S2B1			B43_PHY_N(0x192) /* TX filter 20 coeff stage 2 B1 */
+#define B43_NPHY_TXF_20CO_S2B2			B43_PHY_N(0x193) /* TX filter 20 coeff stage 2 B2 */
+#define B43_NPHY_TXF_20CO_S2B3			B43_PHY_N(0x194) /* TX filter 20 coeff stage 2 B3 */
+#define B43_NPHY_TXF_40CO_S0A1			B43_PHY_N(0x195) /* TX filter 40 coeff stage 0 A1 */
+#define B43_NPHY_TXF_40CO_S0A2			B43_PHY_N(0x196) /* TX filter 40 coeff stage 0 A2 */
+#define B43_NPHY_TXF_40CO_S1A1			B43_PHY_N(0x197) /* TX filter 40 coeff stage 1 A1 */
+#define B43_NPHY_TXF_40CO_S1A2			B43_PHY_N(0x198) /* TX filter 40 coeff stage 1 A2 */
+#define B43_NPHY_TXF_40CO_S2A1			B43_PHY_N(0x199) /* TX filter 40 coeff stage 2 A1 */
+#define B43_NPHY_TXF_40CO_S2A2			B43_PHY_N(0x19A) /* TX filter 40 coeff stage 2 A2 */
+#define B43_NPHY_TXF_40CO_S0B1			B43_PHY_N(0x19B) /* TX filter 40 coeff stage 0 B1 */
+#define B43_NPHY_TXF_40CO_S0B2			B43_PHY_N(0x19C) /* TX filter 40 coeff stage 0 B2 */
+#define B43_NPHY_TXF_40CO_S0B3			B43_PHY_N(0x19D) /* TX filter 40 coeff stage 0 B3 */
+#define B43_NPHY_TXF_40CO_S1B1			B43_PHY_N(0x19E) /* TX filter 40 coeff stage 1 B1 */
+#define B43_NPHY_TXF_40CO_S1B2			B43_PHY_N(0x19F) /* TX filter 40 coeff stage 1 B2 */
+#define B43_NPHY_TXF_40CO_S1B3			B43_PHY_N(0x1A0) /* TX filter 40 coeff stage 1 B3 */
+#define B43_NPHY_TXF_40CO_S2B1			B43_PHY_N(0x1A1) /* TX filter 40 coeff stage 2 B1 */
+#define B43_NPHY_TXF_40CO_S2B2			B43_PHY_N(0x1A2) /* TX filter 40 coeff stage 2 B2 */
+#define B43_NPHY_TXF_40CO_S2B3			B43_PHY_N(0x1A3) /* TX filter 40 coeff stage 2 B3 */
+#define B43_NPHY_RSSIMC_0I_RSSI_X		B43_PHY_N(0x1A4) /* RSSI multiplication coefficient 0 I RSSI X */
+#define B43_NPHY_RSSIMC_0I_RSSI_Y		B43_PHY_N(0x1A5) /* RSSI multiplication coefficient 0 I RSSI Y */
+#define B43_NPHY_RSSIMC_0I_RSSI_Z		B43_PHY_N(0x1A6) /* RSSI multiplication coefficient 0 I RSSI Z */
+#define B43_NPHY_RSSIMC_0I_TBD			B43_PHY_N(0x1A7) /* RSSI multiplication coefficient 0 I TBD */
+#define B43_NPHY_RSSIMC_0I_PWRDET		B43_PHY_N(0x1A8) /* RSSI multiplication coefficient 0 I power det */
+#define B43_NPHY_RSSIMC_0I_TSSI			B43_PHY_N(0x1A9) /* RSSI multiplication coefficient 0 I TSSI */
+#define B43_NPHY_RSSIMC_0Q_RSSI_X		B43_PHY_N(0x1AA) /* RSSI multiplication coefficient 0 Q RSSI X */
+#define B43_NPHY_RSSIMC_0Q_RSSI_Y		B43_PHY_N(0x1AB) /* RSSI multiplication coefficient 0 Q RSSI Y */
+#define B43_NPHY_RSSIMC_0Q_RSSI_Z		B43_PHY_N(0x1AC) /* RSSI multiplication coefficient 0 Q RSSI Z */
+#define B43_NPHY_RSSIMC_0Q_TBD			B43_PHY_N(0x1AD) /* RSSI multiplication coefficient 0 Q TBD */
+#define B43_NPHY_RSSIMC_0Q_PWRDET		B43_PHY_N(0x1AE) /* RSSI multiplication coefficient 0 Q power det */
+#define B43_NPHY_RSSIMC_0Q_TSSI			B43_PHY_N(0x1AF) /* RSSI multiplication coefficient 0 Q TSSI */
+#define B43_NPHY_RSSIMC_1I_RSSI_X		B43_PHY_N(0x1B0) /* RSSI multiplication coefficient 1 I RSSI X */
+#define B43_NPHY_RSSIMC_1I_RSSI_Y		B43_PHY_N(0x1B1) /* RSSI multiplication coefficient 1 I RSSI Y */
+#define B43_NPHY_RSSIMC_1I_RSSI_Z		B43_PHY_N(0x1B2) /* RSSI multiplication coefficient 1 I RSSI Z */
+#define B43_NPHY_RSSIMC_1I_TBD			B43_PHY_N(0x1B3) /* RSSI multiplication coefficient 1 I TBD */
+#define B43_NPHY_RSSIMC_1I_PWRDET		B43_PHY_N(0x1B4) /* RSSI multiplication coefficient 1 I power det */
+#define B43_NPHY_RSSIMC_1I_TSSI			B43_PHY_N(0x1B5) /* RSSI multiplication coefficient 1 I TSSI */
+#define B43_NPHY_RSSIMC_1Q_RSSI_X		B43_PHY_N(0x1B6) /* RSSI multiplication coefficient 1 Q RSSI X */
+#define B43_NPHY_RSSIMC_1Q_RSSI_Y		B43_PHY_N(0x1B7) /* RSSI multiplication coefficient 1 Q RSSI Y */
+#define B43_NPHY_RSSIMC_1Q_RSSI_Z		B43_PHY_N(0x1B8) /* RSSI multiplication coefficient 1 Q RSSI Z */
+#define B43_NPHY_RSSIMC_1Q_TBD			B43_PHY_N(0x1B9) /* RSSI multiplication coefficient 1 Q TBD */
+#define B43_NPHY_RSSIMC_1Q_PWRDET		B43_PHY_N(0x1BA) /* RSSI multiplication coefficient 1 Q power det */
+#define B43_NPHY_RSSIMC_1Q_TSSI			B43_PHY_N(0x1BB) /* RSSI multiplication coefficient 1 Q TSSI */
+#define B43_NPHY_SAMC_WCNT			B43_PHY_N(0x1BC) /* Sample collect wait counter */
+#define B43_NPHY_PTHROUGH_CNT			B43_PHY_N(0x1BD) /* Pass-through counter */
+#define B43_NPHY_LTRN_OFF_G20L			B43_PHY_N(0x1C4) /* LTRN offset gain 20L */
+#define B43_NPHY_LTRN_OFF_20L			B43_PHY_N(0x1C5) /* LTRN offset 20L */
+#define B43_NPHY_LTRN_OFF_G20U			B43_PHY_N(0x1C6) /* LTRN offset gain 20U */
+#define B43_NPHY_LTRN_OFF_20U			B43_PHY_N(0x1C7) /* LTRN offset 20U */
+#define B43_NPHY_DSSSCCK_GAINSL			B43_PHY_N(0x1C8) /* DSSS/CCK gain settle length */
+#define B43_NPHY_GPIO_LOOUT			B43_PHY_N(0x1C9) /* GPIO low out */
+#define B43_NPHY_GPIO_HIOUT			B43_PHY_N(0x1CA) /* GPIO high out */
+#define B43_NPHY_CRS_CHECK			B43_PHY_N(0x1CB) /* CRS check */
+#define B43_NPHY_ML_LOGSS_RAT			B43_PHY_N(0x1CC) /* ML/logss ratio */
+#define B43_NPHY_DUPSCALE			B43_PHY_N(0x1CD) /* Dup scale */
+#define B43_NPHY_BW1A				B43_PHY_N(0x1CE) /* BW 1A */
+#define B43_NPHY_BW2				B43_PHY_N(0x1CF) /* BW 2 */
+#define B43_NPHY_BW3				B43_PHY_N(0x1D0) /* BW 3 */
+#define B43_NPHY_BW4				B43_PHY_N(0x1D1) /* BW 4 */
+#define B43_NPHY_BW5				B43_PHY_N(0x1D2) /* BW 5 */
+#define B43_NPHY_BW6				B43_PHY_N(0x1D3) /* BW 6 */
+#define B43_NPHY_COALEN0			B43_PHY_N(0x1D4) /* Coarse length 0 */
+#define B43_NPHY_COALEN1			B43_PHY_N(0x1D5) /* Coarse length 1 */
+#define B43_NPHY_CRSTHRES_1U			B43_PHY_N(0x1D6) /* CRS threshold 1 U */
+#define B43_NPHY_CRSTHRES_2U			B43_PHY_N(0x1D7) /* CRS threshold 2 U */
+#define B43_NPHY_CRSTHRES_3U			B43_PHY_N(0x1D8) /* CRS threshold 3 U */
+#define B43_NPHY_CRSCTL_U			B43_PHY_N(0x1D9) /* CRS control U */
+#define B43_NPHY_CRSTHRES_1L			B43_PHY_N(0x1DA) /* CRS threshold 1 L */
+#define B43_NPHY_CRSTHRES_2L			B43_PHY_N(0x1DB) /* CRS threshold 2 L */
+#define B43_NPHY_CRSTHRES_3L			B43_PHY_N(0x1DC) /* CRS threshold 3 L */
+#define B43_NPHY_CRSCTL_L			B43_PHY_N(0x1DD) /* CRS control L */
+#define B43_NPHY_STRA_1U			B43_PHY_N(0x1DE) /* STR address 1 U */
+#define B43_NPHY_STRA_2U			B43_PHY_N(0x1DF) /* STR address 2 U */
+#define B43_NPHY_STRA_1L			B43_PHY_N(0x1E0) /* STR address 1 L */
+#define B43_NPHY_STRA_2L			B43_PHY_N(0x1E1) /* STR address 2 L */
+#define B43_NPHY_CRSCHECK1			B43_PHY_N(0x1E2) /* CRS check 1 */
+#define B43_NPHY_CRSCHECK2			B43_PHY_N(0x1E3) /* CRS check 2 */
+#define B43_NPHY_CRSCHECK3			B43_PHY_N(0x1E4) /* CRS check 3 */
+#define B43_NPHY_JMPSTP0			B43_PHY_N(0x1E5) /* Jump step 0 */
+#define B43_NPHY_JMPSTP1			B43_PHY_N(0x1E6) /* Jump step 1 */
+#define B43_NPHY_TXPCTL_CMD			B43_PHY_N(0x1E7) /* TX power control command */
+#define  B43_NPHY_TXPCTL_CMD_INIT		0x007F /* Init */
+#define  B43_NPHY_TXPCTL_CMD_INIT_SHIFT		0
+#define  B43_NPHY_TXPCTL_CMD_COEFF		0x2000 /* Power control coefficients */
+#define  B43_NPHY_TXPCTL_CMD_HWPCTLEN		0x4000 /* Hardware TX power control enable */
+#define  B43_NPHY_TXPCTL_CMD_PCTLEN		0x8000 /* TX power control enable */
+#define B43_NPHY_TXPCTL_N			B43_PHY_N(0x1E8) /* TX power control N num */
+#define  B43_NPHY_TXPCTL_N_TSSID		0x00FF /* N TSSI delay */
+#define  B43_NPHY_TXPCTL_N_TSSID_SHIFT		0
+#define  B43_NPHY_TXPCTL_N_NPTIL2		0x0700 /* N PT integer log2 */
+#define  B43_NPHY_TXPCTL_N_NPTIL2_SHIFT		8
+#define B43_NPHY_TXPCTL_ITSSI			B43_PHY_N(0x1E9) /* TX power control idle TSSI */
+#define  B43_NPHY_TXPCTL_ITSSI_0		0x003F /* Idle TSSI 0 */
+#define  B43_NPHY_TXPCTL_ITSSI_0_SHIFT		0
+#define  B43_NPHY_TXPCTL_ITSSI_1		0x3F00 /* Idle TSSI 1 */
+#define  B43_NPHY_TXPCTL_ITSSI_1_SHIFT		8
+#define  B43_NPHY_TXPCTL_ITSSI_BINF		0x8000 /* Raw TSSI offset bin format */
+#define B43_NPHY_TXPCTL_TPWR			B43_PHY_N(0x1EA) /* TX power control target power */
+#define  B43_NPHY_TXPCTL_TPWR_0			0x00FF /* Power 0 */
+#define  B43_NPHY_TXPCTL_TPWR_0_SHIFT		0
+#define  B43_NPHY_TXPCTL_TPWR_1			0xFF00 /* Power 1 */
+#define  B43_NPHY_TXPCTL_TPWR_1_SHIFT		8
+#define B43_NPHY_TXPCTL_BIDX			B43_PHY_N(0x1EB) /* TX power control base index */
+#define  B43_NPHY_TXPCTL_BIDX_0			0x007F /* uC base index 0 */
+#define  B43_NPHY_TXPCTL_BIDX_0_SHIFT		0
+#define  B43_NPHY_TXPCTL_BIDX_1			0x7F00 /* uC base index 1 */
+#define  B43_NPHY_TXPCTL_BIDX_1_SHIFT		8
+#define  B43_NPHY_TXPCTL_BIDX_LOAD		0x8000 /* Load base index */
+#define B43_NPHY_TXPCTL_PIDX			B43_PHY_N(0x1EC) /* TX power control power index */
+#define  B43_NPHY_TXPCTL_PIDX_0			0x007F /* uC power index 0 */
+#define  B43_NPHY_TXPCTL_PIDX_0_SHIFT		0
+#define  B43_NPHY_TXPCTL_PIDX_1			0x7F00 /* uC power index 1 */
+#define  B43_NPHY_TXPCTL_PIDX_1_SHIFT		8
+#define B43_NPHY_C1_TXPCTL_STAT			B43_PHY_N(0x1ED) /* Core 1 TX power control status */
+#define B43_NPHY_C2_TXPCTL_STAT			B43_PHY_N(0x1EE) /* Core 2 TX power control status */
+#define  B43_NPHY_TXPCTL_STAT_EST		0x00FF /* Estimated power */
+#define  B43_NPHY_TXPCTL_STAT_EST_SHIFT		0
+#define  B43_NPHY_TXPCTL_STAT_BIDX		0x7F00 /* Base index */
+#define  B43_NPHY_TXPCTL_STAT_BIDX_SHIFT	8
+#define  B43_NPHY_TXPCTL_STAT_ESTVALID		0x8000 /* Estimated power valid */
+#define B43_NPHY_SMALLSGS_LEN			B43_PHY_N(0x1EF) /* Small sig gain settle length */
+#define B43_NPHY_PHYSTAT_GAIN0			B43_PHY_N(0x1F0) /* PHY stats gain info 0 */
+#define B43_NPHY_PHYSTAT_GAIN1			B43_PHY_N(0x1F1) /* PHY stats gain info 1 */
+#define B43_NPHY_PHYSTAT_FREQEST		B43_PHY_N(0x1F2) /* PHY stats frequency estimate */
+#define B43_NPHY_PHYSTAT_ADVRET			B43_PHY_N(0x1F3) /* PHY stats ADV retard */
+#define B43_NPHY_PHYLB_MODE			B43_PHY_N(0x1F4) /* PHY loopback mode */
+#define B43_NPHY_TONE_MIDX20_1			B43_PHY_N(0x1F5) /* Tone map index 20/1 */
+#define B43_NPHY_TONE_MIDX20_2			B43_PHY_N(0x1F6) /* Tone map index 20/2 */
+#define B43_NPHY_TONE_MIDX20_3			B43_PHY_N(0x1F7) /* Tone map index 20/3 */
+#define B43_NPHY_TONE_MIDX40_1			B43_PHY_N(0x1F8) /* Tone map index 40/1 */
+#define B43_NPHY_TONE_MIDX40_2			B43_PHY_N(0x1F9) /* Tone map index 40/2 */
+#define B43_NPHY_TONE_MIDX40_3			B43_PHY_N(0x1FA) /* Tone map index 40/3 */
+#define B43_NPHY_TONE_MIDX40_4			B43_PHY_N(0x1FB) /* Tone map index 40/4 */
+#define B43_NPHY_PILTONE_MIDX1			B43_PHY_N(0x1FC) /* Pilot tone map index 1 */
+#define B43_NPHY_PILTONE_MIDX2			B43_PHY_N(0x1FD) /* Pilot tone map index 2 */
+#define B43_NPHY_PILTONE_MIDX3			B43_PHY_N(0x1FE) /* Pilot tone map index 3 */
+#define B43_NPHY_TXRIFS_FRDEL			B43_PHY_N(0x1FF) /* TX RIFS frame delay */
+#define B43_NPHY_AFESEQ_RX2TX_PUD_40M		B43_PHY_N(0x200) /* AFE seq rx2tx power up/down delay 40M */
+#define B43_NPHY_AFESEQ_TX2RX_PUD_40M		B43_PHY_N(0x201) /* AFE seq tx2rx power up/down delay 40M */
+#define B43_NPHY_AFESEQ_RX2TX_PUD_20M		B43_PHY_N(0x202) /* AFE seq rx2tx power up/down delay 20M */
+#define B43_NPHY_AFESEQ_TX2RX_PUD_20M		B43_PHY_N(0x203) /* AFE seq tx2rx power up/down delay 20M */
+#define B43_NPHY_RX_SIGCTL			B43_PHY_N(0x204) /* RX signal control */
+#define B43_NPHY_RXPIL_CYCNT0			B43_PHY_N(0x205) /* RX pilot cycle counter 0 */
+#define B43_NPHY_RXPIL_CYCNT1			B43_PHY_N(0x206) /* RX pilot cycle counter 1 */
+#define B43_NPHY_RXPIL_CYCNT2			B43_PHY_N(0x207) /* RX pilot cycle counter 2 */
+#define B43_NPHY_AFESEQ_RX2TX_PUD_10M		B43_PHY_N(0x208) /* AFE seq rx2tx power up/down delay 10M */
+#define B43_NPHY_AFESEQ_TX2RX_PUD_10M		B43_PHY_N(0x209) /* AFE seq tx2rx power up/down delay 10M */
+#define B43_NPHY_DSSSCCK_CRSEXTL		B43_PHY_N(0x20A) /* DSSS/CCK CRS extension length */
+#define B43_NPHY_ML_LOGSS_RATSLOPE		B43_PHY_N(0x20B) /* ML/logss ratio slope */
+#define B43_NPHY_RIFS_SRCTL			B43_PHY_N(0x20C) /* RIFS search timeout length */
+#define B43_NPHY_TXREALFD			B43_PHY_N(0x20D) /* TX real frame delay */
+#define B43_NPHY_HPANT_SWTHRES			B43_PHY_N(0x20E) /* High power antenna switch threshold */
+#define B43_NPHY_EDCRS_ASSTHRES0		B43_PHY_N(0x210) /* ED CRS assert threshold 0 */
+#define B43_NPHY_EDCRS_ASSTHRES1		B43_PHY_N(0x211) /* ED CRS assert threshold 1 */
+#define B43_NPHY_EDCRS_DEASSTHRES0		B43_PHY_N(0x212) /* ED CRS deassert threshold 0 */
+#define B43_NPHY_EDCRS_DEASSTHRES1		B43_PHY_N(0x213) /* ED CRS deassert threshold 1 */
+#define B43_NPHY_STR_WTIME20U			B43_PHY_N(0x214) /* STR wait time 20U */
+#define B43_NPHY_STR_WTIME20L			B43_PHY_N(0x215) /* STR wait time 20L */
+#define B43_NPHY_TONE_MIDX657M			B43_PHY_N(0x216) /* Tone map index 657M */
+#define B43_NPHY_HTSIGTONES			B43_PHY_N(0x217) /* HT signal tones */
+#define B43_NPHY_RSSI1				B43_PHY_N(0x219) /* RSSI value 1 */
+#define B43_NPHY_RSSI2				B43_PHY_N(0x21A) /* RSSI value 2 */
+#define B43_NPHY_CHAN_ESTHANG			B43_PHY_N(0x21D) /* Channel estimate hang */
+#define B43_NPHY_FINERX2_CGC			B43_PHY_N(0x221) /* Fine RX 2 clock gate control */
+#define  B43_NPHY_FINERX2_CGC_DECGC		0x0008 /* Decode gated clocks */
+#define B43_NPHY_TXPCTL_INIT			B43_PHY_N(0x222) /* TX power control init */
+#define  B43_NPHY_TXPCTL_INIT_PIDXI1		0x00FF /* Power index init 1 */
+#define  B43_NPHY_TXPCTL_INIT_PIDXI1_SHIFT	0
+#define B43_NPHY_ED_CRSEN			B43_PHY_N(0x223)
+#define B43_NPHY_ED_CRS40ASSERTTHRESH0		B43_PHY_N(0x224)
+#define B43_NPHY_ED_CRS40ASSERTTHRESH1		B43_PHY_N(0x225)
+#define B43_NPHY_ED_CRS40DEASSERTTHRESH0	B43_PHY_N(0x226)
+#define B43_NPHY_ED_CRS40DEASSERTTHRESH1	B43_PHY_N(0x227)
+#define B43_NPHY_ED_CRS20LASSERTTHRESH0		B43_PHY_N(0x228)
+#define B43_NPHY_ED_CRS20LASSERTTHRESH1		B43_PHY_N(0x229)
+#define B43_NPHY_ED_CRS20LDEASSERTTHRESH0	B43_PHY_N(0x22A)
+#define B43_NPHY_ED_CRS20LDEASSERTTHRESH1	B43_PHY_N(0x22B)
+#define B43_NPHY_ED_CRS20UASSERTTHRESH0		B43_PHY_N(0x22C)
+#define B43_NPHY_ED_CRS20UASSERTTHRESH1		B43_PHY_N(0x22D)
+#define B43_NPHY_ED_CRS20UDEASSERTTHRESH0	B43_PHY_N(0x22E)
+#define B43_NPHY_ED_CRS20UDEASSERTTHRESH1	B43_PHY_N(0x22F)
+#define B43_NPHY_ED_CRS				B43_PHY_N(0x230)
+#define B43_NPHY_TIMEOUTEN			B43_PHY_N(0x231)
+#define B43_NPHY_OFDMPAYDECODETIMEOUTLEN	B43_PHY_N(0x232)
+#define B43_NPHY_CCKPAYDECODETIMEOUTLEN		B43_PHY_N(0x233)
+#define B43_NPHY_NONPAYDECODETIMEOUTLEN		B43_PHY_N(0x234)
+#define B43_NPHY_TIMEOUTSTATUS			B43_PHY_N(0x235)
+#define B43_NPHY_RFCTRLCORE0GPIO0		B43_PHY_N(0x236)
+#define B43_NPHY_RFCTRLCORE0GPIO1		B43_PHY_N(0x237)
+#define B43_NPHY_RFCTRLCORE0GPIO2		B43_PHY_N(0x238)
+#define B43_NPHY_RFCTRLCORE0GPIO3		B43_PHY_N(0x239)
+#define B43_NPHY_RFCTRLCORE1GPIO0		B43_PHY_N(0x23A)
+#define B43_NPHY_RFCTRLCORE1GPIO1		B43_PHY_N(0x23B)
+#define B43_NPHY_RFCTRLCORE1GPIO2		B43_PHY_N(0x23C)
+#define B43_NPHY_RFCTRLCORE1GPIO3		B43_PHY_N(0x23D)
+#define B43_NPHY_BPHYTESTCONTROL		B43_PHY_N(0x23E)
+/* REV3+ */
+#define B43_NPHY_FORCEFRONT0			B43_PHY_N(0x23F)
+#define B43_NPHY_FORCEFRONT1			B43_PHY_N(0x240)
+#define B43_NPHY_NORMVARHYSTTH			B43_PHY_N(0x241)
+#define B43_NPHY_TXCCKERROR			B43_PHY_N(0x242)
+#define B43_NPHY_AFESEQINITDACGAIN		B43_PHY_N(0x243)
+#define B43_NPHY_TXANTSWLUT			B43_PHY_N(0x244)
+#define B43_NPHY_CORECONFIG			B43_PHY_N(0x245)
+#define B43_NPHY_ANTENNADIVDWELLTIME		B43_PHY_N(0x246)
+#define B43_NPHY_ANTENNACCKDIVDWELLTIME		B43_PHY_N(0x247)
+#define B43_NPHY_ANTENNADIVBACKOFFGAIN		B43_PHY_N(0x248)
+#define B43_NPHY_ANTENNADIVMINGAIN		B43_PHY_N(0x249)
+#define B43_NPHY_BRDSEL_NORMVARHYSTTH		B43_PHY_N(0x24A)
+#define B43_NPHY_RXANTSWITCHCTRL		B43_PHY_N(0x24B)
+#define B43_NPHY_ENERGYDROPTIMEOUTLEN2		B43_PHY_N(0x24C)
+#define B43_NPHY_ML_LOG_TXEVM0			B43_PHY_N(0x250)
+#define B43_NPHY_ML_LOG_TXEVM1			B43_PHY_N(0x251)
+#define B43_NPHY_ML_LOG_TXEVM2			B43_PHY_N(0x252)
+#define B43_NPHY_ML_LOG_TXEVM3			B43_PHY_N(0x253)
+#define B43_NPHY_ML_LOG_TXEVM4			B43_PHY_N(0x254)
+#define B43_NPHY_ML_LOG_TXEVM5			B43_PHY_N(0x255)
+#define B43_NPHY_ML_LOG_TXEVM6			B43_PHY_N(0x256)
+#define B43_NPHY_ML_LOG_TXEVM7			B43_PHY_N(0x257)
+#define B43_NPHY_ML_SCALE_TWEAK			B43_PHY_N(0x258)
+#define B43_NPHY_MLUA				B43_PHY_N(0x259)
+#define B43_NPHY_ZFUA				B43_PHY_N(0x25A)
+#define B43_NPHY_CHANUPSYM01			B43_PHY_N(0x25B)
+#define B43_NPHY_CHANUPSYM2			B43_PHY_N(0x25C)
+#define B43_NPHY_RXSTRNFILT20NUM00		B43_PHY_N(0x25D)
+#define B43_NPHY_RXSTRNFILT20NUM01		B43_PHY_N(0x25E)
+#define B43_NPHY_RXSTRNFILT20NUM02		B43_PHY_N(0x25F)
+#define B43_NPHY_RXSTRNFILT20DEN00		B43_PHY_N(0x260)
+#define B43_NPHY_RXSTRNFILT20DEN01		B43_PHY_N(0x261)
+#define B43_NPHY_RXSTRNFILT20NUM10		B43_PHY_N(0x262)
+#define B43_NPHY_RXSTRNFILT20NUM11		B43_PHY_N(0x263)
+#define B43_NPHY_RXSTRNFILT20NUM12		B43_PHY_N(0x264)
+#define B43_NPHY_RXSTRNFILT20DEN10		B43_PHY_N(0x265)
+#define B43_NPHY_RXSTRNFILT20DEN11		B43_PHY_N(0x266)
+#define B43_NPHY_RXSTRNFILT40NUM00		B43_PHY_N(0x267)
+#define B43_NPHY_RXSTRNFILT40NUM01		B43_PHY_N(0x268)
+#define B43_NPHY_RXSTRNFILT40NUM02		B43_PHY_N(0x269)
+#define B43_NPHY_RXSTRNFILT40DEN00		B43_PHY_N(0x26A)
+#define B43_NPHY_RXSTRNFILT40DEN01		B43_PHY_N(0x26B)
+#define B43_NPHY_RXSTRNFILT40NUM10		B43_PHY_N(0x26C)
+#define B43_NPHY_RXSTRNFILT40NUM11		B43_PHY_N(0x26D)
+#define B43_NPHY_RXSTRNFILT40NUM12		B43_PHY_N(0x26E)
+#define B43_NPHY_RXSTRNFILT40DEN10		B43_PHY_N(0x26F)
+#define B43_NPHY_RXSTRNFILT40DEN11		B43_PHY_N(0x270)
+#define B43_NPHY_CRSHIGHPOWTHRESHOLD1		B43_PHY_N(0x271)
+#define B43_NPHY_CRSHIGHPOWTHRESHOLD2		B43_PHY_N(0x272)
+#define B43_NPHY_CRSHIGHLOWPOWTHRESHOLD		B43_PHY_N(0x273)
+#define B43_NPHY_CRSHIGHPOWTHRESHOLD1L		B43_PHY_N(0x274)
+#define B43_NPHY_CRSHIGHPOWTHRESHOLD2L		B43_PHY_N(0x275)
+#define B43_NPHY_CRSHIGHLOWPOWTHRESHOLDL	B43_PHY_N(0x276)
+#define B43_NPHY_CRSHIGHPOWTHRESHOLD1U		B43_PHY_N(0x277)
+#define B43_NPHY_CRSHIGHPOWTHRESHOLD2U		B43_PHY_N(0x278)
+#define B43_NPHY_CRSHIGHLOWPOWTHRESHOLDU	B43_PHY_N(0x279)
+#define B43_NPHY_CRSACIDETECTTHRESH		B43_PHY_N(0x27A)
+#define B43_NPHY_CRSACIDETECTTHRESHL		B43_PHY_N(0x27B)
+#define B43_NPHY_CRSACIDETECTTHRESHU		B43_PHY_N(0x27C)
+#define B43_NPHY_CRSMINPOWER0			B43_PHY_N(0x27D)
+#define B43_NPHY_CRSMINPOWER1			B43_PHY_N(0x27E)
+#define B43_NPHY_CRSMINPOWER2			B43_PHY_N(0x27F)
+#define B43_NPHY_CRSMINPOWERL0			B43_PHY_N(0x280)
+#define B43_NPHY_CRSMINPOWERL1			B43_PHY_N(0x281)
+#define B43_NPHY_CRSMINPOWERL2			B43_PHY_N(0x282)
+#define B43_NPHY_CRSMINPOWERU0			B43_PHY_N(0x283)
+#define B43_NPHY_CRSMINPOWERU1			B43_PHY_N(0x284)
+#define B43_NPHY_CRSMINPOWERU2			B43_PHY_N(0x285)
+#define B43_NPHY_STRPARAM			B43_PHY_N(0x286)
+#define B43_NPHY_STRPARAML			B43_PHY_N(0x287)
+#define B43_NPHY_STRPARAMU			B43_PHY_N(0x288)
+#define B43_NPHY_BPHYCRSMINPOWER0		B43_PHY_N(0x289)
+#define B43_NPHY_BPHYCRSMINPOWER1		B43_PHY_N(0x28A)
+#define B43_NPHY_BPHYCRSMINPOWER2		B43_PHY_N(0x28B)
+#define B43_NPHY_BPHYFILTDEN0COEF		B43_PHY_N(0x28C)
+#define B43_NPHY_BPHYFILTDEN1COEF		B43_PHY_N(0x28D)
+#define B43_NPHY_BPHYFILTDEN2COEF		B43_PHY_N(0x28E)
+#define B43_NPHY_BPHYFILTNUM0COEF		B43_PHY_N(0x28F)
+#define B43_NPHY_BPHYFILTNUM1COEF		B43_PHY_N(0x290)
+#define B43_NPHY_BPHYFILTNUM2COEF		B43_PHY_N(0x291)
+#define B43_NPHY_BPHYFILTNUM01COEF2		B43_PHY_N(0x292)
+#define B43_NPHY_BPHYFILTBYPASS			B43_PHY_N(0x293)
+#define B43_NPHY_SGILTRNOFFSET			B43_PHY_N(0x294)
+#define B43_NPHY_RADAR_T2_MIN			B43_PHY_N(0x295)
+#define B43_NPHY_TXPWRCTRLDAMPING		B43_PHY_N(0x296)
+#define B43_NPHY_PAPD_EN0			B43_PHY_N(0x297) /* PAPD Enable0 TBD */
+#define B43_NPHY_EPS_TABLE_ADJ0			B43_PHY_N(0x298) /* EPS Table Adj0 TBD */
+#define B43_NPHY_EPS_OVERRIDEI_0		B43_PHY_N(0x299)
+#define B43_NPHY_EPS_OVERRIDEQ_0		B43_PHY_N(0x29A)
+#define B43_NPHY_PAPD_EN1			B43_PHY_N(0x29B) /* PAPD Enable1 TBD */
+#define B43_NPHY_EPS_TABLE_ADJ1			B43_PHY_N(0x29C) /* EPS Table Adj1 TBD */
+#define B43_NPHY_EPS_OVERRIDEI_1		B43_PHY_N(0x29D)
+#define B43_NPHY_EPS_OVERRIDEQ_1		B43_PHY_N(0x29E)
+#define B43_NPHY_PAPD_CAL_ADDRESS		B43_PHY_N(0x29F)
+#define B43_NPHY_PAPD_CAL_YREFEPSILON		B43_PHY_N(0x2A0)
+#define B43_NPHY_PAPD_CAL_SETTLE		B43_PHY_N(0x2A1)
+#define B43_NPHY_PAPD_CAL_CORRELATE		B43_PHY_N(0x2A2)
+#define B43_NPHY_PAPD_CAL_SHIFTS0		B43_PHY_N(0x2A3)
+#define B43_NPHY_PAPD_CAL_SHIFTS1		B43_PHY_N(0x2A4)
+#define B43_NPHY_SAMPLE_START_ADDR		B43_PHY_N(0x2A5)
+#define B43_NPHY_RADAR_ADC_TO_DBM		B43_PHY_N(0x2A6)
+#define B43_NPHY_REV3_C2_INITGAIN_A		B43_PHY_N(0x2A7)
+#define B43_NPHY_REV3_C2_INITGAIN_B		B43_PHY_N(0x2A8)
+#define B43_NPHY_REV3_C2_CLIP_HIGAIN_A		B43_PHY_N(0x2A9)
+#define B43_NPHY_REV3_C2_CLIP_HIGAIN_B		B43_PHY_N(0x2AA)
+#define B43_NPHY_REV3_C2_CLIP_MEDGAIN_A		B43_PHY_N(0x2AB)
+#define B43_NPHY_REV3_C2_CLIP_MEDGAIN_B		B43_PHY_N(0x2AC)
+#define B43_NPHY_REV3_C2_CLIP_LOGAIN_A		B43_PHY_N(0x2AD)
+#define B43_NPHY_REV3_C2_CLIP_LOGAIN_B		B43_PHY_N(0x2AE)
+#define B43_NPHY_REV3_C2_CLIP2_GAIN_A		B43_PHY_N(0x2AF)
+#define B43_NPHY_REV3_C2_CLIP2_GAIN_B		B43_PHY_N(0x2B0)
+
+#define B43_NPHY_REV7_RF_CTL_MISC_REG3		B43_PHY_N(0x340)
+#define B43_NPHY_REV7_RF_CTL_MISC_REG4		B43_PHY_N(0x341)
+#define B43_NPHY_REV7_RF_CTL_OVER3		B43_PHY_N(0x342)
+#define B43_NPHY_REV7_RF_CTL_OVER4		B43_PHY_N(0x343)
+#define B43_NPHY_REV7_RF_CTL_MISC_REG5		B43_PHY_N(0x344)
+#define B43_NPHY_REV7_RF_CTL_MISC_REG6		B43_PHY_N(0x345)
+#define B43_NPHY_REV7_RF_CTL_OVER5		B43_PHY_N(0x346)
+#define B43_NPHY_REV7_RF_CTL_OVER6		B43_PHY_N(0x347)
+
+#define B43_PHY_B_BBCFG				B43_PHY_N_BMODE(0x001) /* BB config */
+#define  B43_PHY_B_BBCFG_RSTCCA			0x4000 /* Reset CCA */
+#define  B43_PHY_B_BBCFG_RSTRX			0x8000 /* Reset RX */
+#define B43_PHY_B_TEST				B43_PHY_N_BMODE(0x00A)
+
+struct b43_wldev;
+
+enum b43_nphy_spur_avoid {
+	B43_SPUR_AVOID_DISABLE,
+	B43_SPUR_AVOID_AUTO,
+	B43_SPUR_AVOID_FORCE,
+};
+
+struct b43_chanspec {
+	u16 center_freq;
+	enum nl80211_channel_type channel_type;
+};
+
+struct b43_phy_n_iq_comp {
+	s16 a0;
+	s16 b0;
+	s16 a1;
+	s16 b1;
+};
+
+struct b43_phy_n_rssical_cache {
+	u16 rssical_radio_regs_2G[2];
+	u16 rssical_phy_regs_2G[12];
+
+	u16 rssical_radio_regs_5G[2];
+	u16 rssical_phy_regs_5G[12];
+};
+
+struct b43_phy_n_cal_cache {
+	u16 txcal_radio_regs_2G[8];
+	u16 txcal_coeffs_2G[8];
+	struct b43_phy_n_iq_comp rxcal_coeffs_2G;
+
+	u16 txcal_radio_regs_5G[8];
+	u16 txcal_coeffs_5G[8];
+	struct b43_phy_n_iq_comp rxcal_coeffs_5G;
+};
+
+struct b43_phy_n_txpwrindex {
+	s8 index;
+	s8 index_internal;
+	s8 index_internal_save;
+	u16 AfectrlOverride;
+	u16 AfeCtrlDacGain;
+	u16 rad_gain;
+	u8 bbmult;
+	u16 iqcomp_a;
+	u16 iqcomp_b;
+	u16 locomp;
+};
+
+struct b43_phy_n_pwr_ctl_info {
+	u8 idle_tssi_2g;
+	u8 idle_tssi_5g;
+};
+
+struct b43_phy_n {
+	u8 antsel_type;
+	u8 cal_orig_pwr_idx[2];
+	u8 measure_hold;
+	u8 phyrxchain;
+	u8 hw_phyrxchain;
+	u8 hw_phytxchain;
+	u8 perical;
+	u32 deaf_count;
+	u32 rxcalparams;
+	bool hang_avoid;
+	bool mute;
+	u16 papd_epsilon_offset[2];
+	s32 preamble_override;
+	u32 bb_mult_save;
+
+	bool gain_boost;
+	bool elna_gain_config;
+	bool band5g_pwrgain;
+	bool use_int_tx_iq_lo_cal;
+	bool lpf_bw_overrode_for_sample_play;
+
+	u8 mphase_cal_phase_id;
+	u16 mphase_txcal_cmdidx;
+	u16 mphase_txcal_numcmds;
+	u16 mphase_txcal_bestcoeffs[11];
+
+	bool txpwrctrl;
+	bool pwg_gain_5ghz;
+	u8 tx_pwr_idx[2];
+	s8 tx_power_offset[101];
+	u16 adj_pwr_tbl[84];
+	u16 txcal_bbmult;
+	u16 txiqlocal_bestc[11];
+	bool txiqlocal_coeffsvalid;
+	struct b43_phy_n_txpwrindex txpwrindex[2];
+	struct b43_phy_n_pwr_ctl_info pwr_ctl_info[2];
+	struct b43_chanspec txiqlocal_chanspec;
+	struct b43_ppr tx_pwr_max_ppr;
+	u16 tx_pwr_last_recalc_freq;
+	int tx_pwr_last_recalc_limit;
+
+	u8 txrx_chain;
+	u16 tx_rx_cal_phy_saveregs[11];
+	u16 tx_rx_cal_radio_saveregs[22];
+
+	u16 rfctrl_intc1_save;
+	u16 rfctrl_intc2_save;
+
+	u16 classifier_state;
+	u16 clip_state[2];
+
+	enum b43_nphy_spur_avoid spur_avoid;
+	bool aband_spurwar_en;
+	bool gband_spurwar_en;
+
+	bool ipa2g_on;
+	struct b43_chanspec iqcal_chanspec_2G;
+	struct b43_chanspec rssical_chanspec_2G;
+
+	bool ipa5g_on;
+	struct b43_chanspec iqcal_chanspec_5G;
+	struct b43_chanspec rssical_chanspec_5G;
+
+	struct b43_phy_n_rssical_cache rssical_cache;
+	struct b43_phy_n_cal_cache cal_cache;
+	bool crsminpwr_adjusted;
+	bool noisevars_adjusted;
+};
+
+
+struct b43_phy_operations;
+extern const struct b43_phy_operations b43_phyops_n;
+
+#endif /* B43_NPHY_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/pio.c b/drivers/net/wireless/broadcom/b43/pio.c
new file mode 100644
index 0000000..a4ff5e2
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/pio.c
@@ -0,0 +1,834 @@
+/*
+
+  Broadcom B43 wireless driver
+
+  PIO data transfer
+
+  Copyright (c) 2005-2008 Michael Buesch <m@bues.ch>
+
+  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 "pio.h"
+#include "dma.h"
+#include "main.h"
+#include "xmit.h"
+
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+
+static u16 generate_cookie(struct b43_pio_txqueue *q,
+			   struct b43_pio_txpacket *pack)
+{
+	u16 cookie;
+
+	/* Use the upper 4 bits of the cookie as
+	 * PIO controller ID and store the packet index number
+	 * in the lower 12 bits.
+	 * Note that the cookie must never be 0, as this
+	 * is a special value used in RX path.
+	 * It can also not be 0xFFFF because that is special
+	 * for multicast frames.
+	 */
+	cookie = (((u16)q->index + 1) << 12);
+	cookie |= pack->index;
+
+	return cookie;
+}
+
+static
+struct b43_pio_txqueue *parse_cookie(struct b43_wldev *dev,
+				     u16 cookie,
+				      struct b43_pio_txpacket **pack)
+{
+	struct b43_pio *pio = &dev->pio;
+	struct b43_pio_txqueue *q = NULL;
+	unsigned int pack_index;
+
+	switch (cookie & 0xF000) {
+	case 0x1000:
+		q = pio->tx_queue_AC_BK;
+		break;
+	case 0x2000:
+		q = pio->tx_queue_AC_BE;
+		break;
+	case 0x3000:
+		q = pio->tx_queue_AC_VI;
+		break;
+	case 0x4000:
+		q = pio->tx_queue_AC_VO;
+		break;
+	case 0x5000:
+		q = pio->tx_queue_mcast;
+		break;
+	}
+	if (B43_WARN_ON(!q))
+		return NULL;
+	pack_index = (cookie & 0x0FFF);
+	if (B43_WARN_ON(pack_index >= ARRAY_SIZE(q->packets)))
+		return NULL;
+	*pack = &q->packets[pack_index];
+
+	return q;
+}
+
+static u16 index_to_pioqueue_base(struct b43_wldev *dev,
+				  unsigned int index)
+{
+	static const u16 bases[] = {
+		B43_MMIO_PIO_BASE0,
+		B43_MMIO_PIO_BASE1,
+		B43_MMIO_PIO_BASE2,
+		B43_MMIO_PIO_BASE3,
+		B43_MMIO_PIO_BASE4,
+		B43_MMIO_PIO_BASE5,
+		B43_MMIO_PIO_BASE6,
+		B43_MMIO_PIO_BASE7,
+	};
+	static const u16 bases_rev11[] = {
+		B43_MMIO_PIO11_BASE0,
+		B43_MMIO_PIO11_BASE1,
+		B43_MMIO_PIO11_BASE2,
+		B43_MMIO_PIO11_BASE3,
+		B43_MMIO_PIO11_BASE4,
+		B43_MMIO_PIO11_BASE5,
+	};
+
+	if (dev->dev->core_rev >= 11) {
+		B43_WARN_ON(index >= ARRAY_SIZE(bases_rev11));
+		return bases_rev11[index];
+	}
+	B43_WARN_ON(index >= ARRAY_SIZE(bases));
+	return bases[index];
+}
+
+static u16 pio_txqueue_offset(struct b43_wldev *dev)
+{
+	if (dev->dev->core_rev >= 11)
+		return 0x18;
+	return 0;
+}
+
+static u16 pio_rxqueue_offset(struct b43_wldev *dev)
+{
+	if (dev->dev->core_rev >= 11)
+		return 0x38;
+	return 8;
+}
+
+static struct b43_pio_txqueue *b43_setup_pioqueue_tx(struct b43_wldev *dev,
+						     unsigned int index)
+{
+	struct b43_pio_txqueue *q;
+	struct b43_pio_txpacket *p;
+	unsigned int i;
+
+	q = kzalloc(sizeof(*q), GFP_KERNEL);
+	if (!q)
+		return NULL;
+	q->dev = dev;
+	q->rev = dev->dev->core_rev;
+	q->mmio_base = index_to_pioqueue_base(dev, index) +
+		       pio_txqueue_offset(dev);
+	q->index = index;
+
+	q->free_packet_slots = B43_PIO_MAX_NR_TXPACKETS;
+	if (q->rev >= 8) {
+		q->buffer_size = 1920; //FIXME this constant is wrong.
+	} else {
+		q->buffer_size = b43_piotx_read16(q, B43_PIO_TXQBUFSIZE);
+		q->buffer_size -= 80;
+	}
+
+	INIT_LIST_HEAD(&q->packets_list);
+	for (i = 0; i < ARRAY_SIZE(q->packets); i++) {
+		p = &(q->packets[i]);
+		INIT_LIST_HEAD(&p->list);
+		p->index = i;
+		p->queue = q;
+		list_add(&p->list, &q->packets_list);
+	}
+
+	return q;
+}
+
+static struct b43_pio_rxqueue *b43_setup_pioqueue_rx(struct b43_wldev *dev,
+						     unsigned int index)
+{
+	struct b43_pio_rxqueue *q;
+
+	q = kzalloc(sizeof(*q), GFP_KERNEL);
+	if (!q)
+		return NULL;
+	q->dev = dev;
+	q->rev = dev->dev->core_rev;
+	q->mmio_base = index_to_pioqueue_base(dev, index) +
+		       pio_rxqueue_offset(dev);
+
+	/* Enable Direct FIFO RX (PIO) on the engine. */
+	b43_dma_direct_fifo_rx(dev, index, 1);
+
+	return q;
+}
+
+static void b43_pio_cancel_tx_packets(struct b43_pio_txqueue *q)
+{
+	struct b43_pio_txpacket *pack;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(q->packets); i++) {
+		pack = &(q->packets[i]);
+		if (pack->skb) {
+			ieee80211_free_txskb(q->dev->wl->hw, pack->skb);
+			pack->skb = NULL;
+		}
+	}
+}
+
+static void b43_destroy_pioqueue_tx(struct b43_pio_txqueue *q,
+				    const char *name)
+{
+	if (!q)
+		return;
+	b43_pio_cancel_tx_packets(q);
+	kfree(q);
+}
+
+static void b43_destroy_pioqueue_rx(struct b43_pio_rxqueue *q,
+				    const char *name)
+{
+	if (!q)
+		return;
+	kfree(q);
+}
+
+#define destroy_queue_tx(pio, queue) do {				\
+	b43_destroy_pioqueue_tx((pio)->queue, __stringify(queue));	\
+	(pio)->queue = NULL;						\
+  } while (0)
+
+#define destroy_queue_rx(pio, queue) do {				\
+	b43_destroy_pioqueue_rx((pio)->queue, __stringify(queue));	\
+	(pio)->queue = NULL;						\
+  } while (0)
+
+void b43_pio_free(struct b43_wldev *dev)
+{
+	struct b43_pio *pio;
+
+	if (!b43_using_pio_transfers(dev))
+		return;
+	pio = &dev->pio;
+
+	destroy_queue_rx(pio, rx_queue);
+	destroy_queue_tx(pio, tx_queue_mcast);
+	destroy_queue_tx(pio, tx_queue_AC_VO);
+	destroy_queue_tx(pio, tx_queue_AC_VI);
+	destroy_queue_tx(pio, tx_queue_AC_BE);
+	destroy_queue_tx(pio, tx_queue_AC_BK);
+}
+
+int b43_pio_init(struct b43_wldev *dev)
+{
+	struct b43_pio *pio = &dev->pio;
+	int err = -ENOMEM;
+
+	b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
+		    & ~B43_MACCTL_BE);
+	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_RXPADOFF, 0);
+
+	pio->tx_queue_AC_BK = b43_setup_pioqueue_tx(dev, 0);
+	if (!pio->tx_queue_AC_BK)
+		goto out;
+
+	pio->tx_queue_AC_BE = b43_setup_pioqueue_tx(dev, 1);
+	if (!pio->tx_queue_AC_BE)
+		goto err_destroy_bk;
+
+	pio->tx_queue_AC_VI = b43_setup_pioqueue_tx(dev, 2);
+	if (!pio->tx_queue_AC_VI)
+		goto err_destroy_be;
+
+	pio->tx_queue_AC_VO = b43_setup_pioqueue_tx(dev, 3);
+	if (!pio->tx_queue_AC_VO)
+		goto err_destroy_vi;
+
+	pio->tx_queue_mcast = b43_setup_pioqueue_tx(dev, 4);
+	if (!pio->tx_queue_mcast)
+		goto err_destroy_vo;
+
+	pio->rx_queue = b43_setup_pioqueue_rx(dev, 0);
+	if (!pio->rx_queue)
+		goto err_destroy_mcast;
+
+	b43dbg(dev->wl, "PIO initialized\n");
+	err = 0;
+out:
+	return err;
+
+err_destroy_mcast:
+	destroy_queue_tx(pio, tx_queue_mcast);
+err_destroy_vo:
+	destroy_queue_tx(pio, tx_queue_AC_VO);
+err_destroy_vi:
+	destroy_queue_tx(pio, tx_queue_AC_VI);
+err_destroy_be:
+	destroy_queue_tx(pio, tx_queue_AC_BE);
+err_destroy_bk:
+	destroy_queue_tx(pio, tx_queue_AC_BK);
+	return err;
+}
+
+/* Static mapping of mac80211's queues (priorities) to b43 PIO queues. */
+static struct b43_pio_txqueue *select_queue_by_priority(struct b43_wldev *dev,
+							u8 queue_prio)
+{
+	struct b43_pio_txqueue *q;
+
+	if (dev->qos_enabled) {
+		/* 0 = highest priority */
+		switch (queue_prio) {
+		default:
+			B43_WARN_ON(1);
+			/* fallthrough */
+		case 0:
+			q = dev->pio.tx_queue_AC_VO;
+			break;
+		case 1:
+			q = dev->pio.tx_queue_AC_VI;
+			break;
+		case 2:
+			q = dev->pio.tx_queue_AC_BE;
+			break;
+		case 3:
+			q = dev->pio.tx_queue_AC_BK;
+			break;
+		}
+	} else
+		q = dev->pio.tx_queue_AC_BE;
+
+	return q;
+}
+
+static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
+				u16 ctl,
+				const void *_data,
+				unsigned int data_len)
+{
+	struct b43_wldev *dev = q->dev;
+	struct b43_wl *wl = dev->wl;
+	const u8 *data = _data;
+
+	ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI;
+	b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
+
+	b43_block_write(dev, data, (data_len & ~1),
+			q->mmio_base + B43_PIO_TXDATA,
+			sizeof(u16));
+	if (data_len & 1) {
+		u8 *tail = wl->pio_tailspace;
+		BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2);
+
+		/* Write the last byte. */
+		ctl &= ~B43_PIO_TXCTL_WRITEHI;
+		b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
+		tail[0] = data[data_len - 1];
+		tail[1] = 0;
+		b43_block_write(dev, tail, 2,
+				q->mmio_base + B43_PIO_TXDATA,
+				sizeof(u16));
+	}
+
+	return ctl;
+}
+
+static void pio_tx_frame_2byte_queue(struct b43_pio_txpacket *pack,
+				     const u8 *hdr, unsigned int hdrlen)
+{
+	struct b43_pio_txqueue *q = pack->queue;
+	const char *frame = pack->skb->data;
+	unsigned int frame_len = pack->skb->len;
+	u16 ctl;
+
+	ctl = b43_piotx_read16(q, B43_PIO_TXCTL);
+	ctl |= B43_PIO_TXCTL_FREADY;
+	ctl &= ~B43_PIO_TXCTL_EOF;
+
+	/* Transfer the header data. */
+	ctl = tx_write_2byte_queue(q, ctl, hdr, hdrlen);
+	/* Transfer the frame data. */
+	ctl = tx_write_2byte_queue(q, ctl, frame, frame_len);
+
+	ctl |= B43_PIO_TXCTL_EOF;
+	b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
+}
+
+static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
+				u32 ctl,
+				const void *_data,
+				unsigned int data_len)
+{
+	struct b43_wldev *dev = q->dev;
+	struct b43_wl *wl = dev->wl;
+	const u8 *data = _data;
+
+	ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 |
+	       B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31;
+	b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
+
+	b43_block_write(dev, data, (data_len & ~3),
+			q->mmio_base + B43_PIO8_TXDATA,
+			sizeof(u32));
+	if (data_len & 3) {
+		u8 *tail = wl->pio_tailspace;
+		BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4);
+
+		memset(tail, 0, 4);
+		/* Write the last few bytes. */
+		ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 |
+			 B43_PIO8_TXCTL_24_31);
+		switch (data_len & 3) {
+		case 3:
+			ctl |= B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_8_15;
+			tail[0] = data[data_len - 3];
+			tail[1] = data[data_len - 2];
+			tail[2] = data[data_len - 1];
+			break;
+		case 2:
+			ctl |= B43_PIO8_TXCTL_8_15;
+			tail[0] = data[data_len - 2];
+			tail[1] = data[data_len - 1];
+			break;
+		case 1:
+			tail[0] = data[data_len - 1];
+			break;
+		}
+		b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
+		b43_block_write(dev, tail, 4,
+				q->mmio_base + B43_PIO8_TXDATA,
+				sizeof(u32));
+	}
+
+	return ctl;
+}
+
+static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack,
+				     const u8 *hdr, unsigned int hdrlen)
+{
+	struct b43_pio_txqueue *q = pack->queue;
+	const char *frame = pack->skb->data;
+	unsigned int frame_len = pack->skb->len;
+	u32 ctl;
+
+	ctl = b43_piotx_read32(q, B43_PIO8_TXCTL);
+	ctl |= B43_PIO8_TXCTL_FREADY;
+	ctl &= ~B43_PIO8_TXCTL_EOF;
+
+	/* Transfer the header data. */
+	ctl = tx_write_4byte_queue(q, ctl, hdr, hdrlen);
+	/* Transfer the frame data. */
+	ctl = tx_write_4byte_queue(q, ctl, frame, frame_len);
+
+	ctl |= B43_PIO8_TXCTL_EOF;
+	b43_piotx_write32(q, B43_PIO_TXCTL, ctl);
+}
+
+static int pio_tx_frame(struct b43_pio_txqueue *q,
+			struct sk_buff *skb)
+{
+	struct b43_wldev *dev = q->dev;
+	struct b43_wl *wl = dev->wl;
+	struct b43_pio_txpacket *pack;
+	u16 cookie;
+	int err;
+	unsigned int hdrlen;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct b43_txhdr *txhdr = (struct b43_txhdr *)wl->pio_scratchspace;
+
+	B43_WARN_ON(list_empty(&q->packets_list));
+	pack = list_entry(q->packets_list.next,
+			  struct b43_pio_txpacket, list);
+
+	cookie = generate_cookie(q, pack);
+	hdrlen = b43_txhdr_size(dev);
+	BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(struct b43_txhdr));
+	B43_WARN_ON(sizeof(wl->pio_scratchspace) < hdrlen);
+	err = b43_generate_txhdr(dev, (u8 *)txhdr, skb,
+				 info, cookie);
+	if (err)
+		return err;
+
+	if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
+		/* Tell the firmware about the cookie of the last
+		 * mcast frame, so it can clear the more-data bit in it. */
+		b43_shm_write16(dev, B43_SHM_SHARED,
+				B43_SHM_SH_MCASTCOOKIE, cookie);
+	}
+
+	pack->skb = skb;
+	if (q->rev >= 8)
+		pio_tx_frame_4byte_queue(pack, (const u8 *)txhdr, hdrlen);
+	else
+		pio_tx_frame_2byte_queue(pack, (const u8 *)txhdr, hdrlen);
+
+	/* Remove it from the list of available packet slots.
+	 * It will be put back when we receive the status report. */
+	list_del(&pack->list);
+
+	/* Update the queue statistics. */
+	q->buffer_used += roundup(skb->len + hdrlen, 4);
+	q->free_packet_slots -= 1;
+
+	return 0;
+}
+
+int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb)
+{
+	struct b43_pio_txqueue *q;
+	struct ieee80211_hdr *hdr;
+	unsigned int hdrlen, total_len;
+	int err = 0;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+	hdr = (struct ieee80211_hdr *)skb->data;
+
+	if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
+		/* The multicast queue will be sent after the DTIM. */
+		q = dev->pio.tx_queue_mcast;
+		/* Set the frame More-Data bit. Ucode will clear it
+		 * for us on the last frame. */
+		hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+	} else {
+		/* Decide by priority where to put this frame. */
+		q = select_queue_by_priority(dev, skb_get_queue_mapping(skb));
+	}
+
+	hdrlen = b43_txhdr_size(dev);
+	total_len = roundup(skb->len + hdrlen, 4);
+
+	if (unlikely(total_len > q->buffer_size)) {
+		err = -ENOBUFS;
+		b43dbg(dev->wl, "PIO: TX packet longer than queue.\n");
+		goto out;
+	}
+	if (unlikely(q->free_packet_slots == 0)) {
+		err = -ENOBUFS;
+		b43warn(dev->wl, "PIO: TX packet overflow.\n");
+		goto out;
+	}
+	B43_WARN_ON(q->buffer_used > q->buffer_size);
+
+	if (total_len > (q->buffer_size - q->buffer_used)) {
+		/* Not enough memory on the queue. */
+		err = -EBUSY;
+		ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb));
+		q->stopped = true;
+		goto out;
+	}
+
+	/* Assign the queue number to the ring (if not already done before)
+	 * so TX status handling can use it. The mac80211-queue to b43-queue
+	 * mapping is static, so we don't need to store it per frame. */
+	q->queue_prio = skb_get_queue_mapping(skb);
+
+	err = pio_tx_frame(q, skb);
+	if (unlikely(err == -ENOKEY)) {
+		/* Drop this packet, as we don't have the encryption key
+		 * anymore and must not transmit it unencrypted. */
+		ieee80211_free_txskb(dev->wl->hw, skb);
+		err = 0;
+		goto out;
+	}
+	if (unlikely(err)) {
+		b43err(dev->wl, "PIO transmission failure\n");
+		goto out;
+	}
+
+	B43_WARN_ON(q->buffer_used > q->buffer_size);
+	if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) ||
+	    (q->free_packet_slots == 0)) {
+		/* The queue is full. */
+		ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb));
+		q->stopped = true;
+	}
+
+out:
+	return err;
+}
+
+void b43_pio_handle_txstatus(struct b43_wldev *dev,
+			     const struct b43_txstatus *status)
+{
+	struct b43_pio_txqueue *q;
+	struct b43_pio_txpacket *pack = NULL;
+	unsigned int total_len;
+	struct ieee80211_tx_info *info;
+
+	q = parse_cookie(dev, status->cookie, &pack);
+	if (unlikely(!q))
+		return;
+	B43_WARN_ON(!pack);
+
+	info = IEEE80211_SKB_CB(pack->skb);
+
+	b43_fill_txstatus_report(dev, info, status);
+
+	total_len = pack->skb->len + b43_txhdr_size(dev);
+	total_len = roundup(total_len, 4);
+	q->buffer_used -= total_len;
+	q->free_packet_slots += 1;
+
+	ieee80211_tx_status(dev->wl->hw, pack->skb);
+	pack->skb = NULL;
+	list_add(&pack->list, &q->packets_list);
+
+	if (q->stopped) {
+		ieee80211_wake_queue(dev->wl->hw, q->queue_prio);
+		q->stopped = false;
+	}
+}
+
+/* Returns whether we should fetch another frame. */
+static bool pio_rx_frame(struct b43_pio_rxqueue *q)
+{
+	struct b43_wldev *dev = q->dev;
+	struct b43_wl *wl = dev->wl;
+	u16 len;
+	u32 macstat = 0;
+	unsigned int i, padding;
+	struct sk_buff *skb;
+	const char *err_msg = NULL;
+	struct b43_rxhdr_fw4 *rxhdr =
+		(struct b43_rxhdr_fw4 *)wl->pio_scratchspace;
+	size_t rxhdr_size = sizeof(*rxhdr);
+
+	BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(*rxhdr));
+	switch (dev->fw.hdr_format) {
+	case B43_FW_HDR_410:
+	case B43_FW_HDR_351:
+		rxhdr_size -= sizeof(rxhdr->format_598) -
+			sizeof(rxhdr->format_351);
+		break;
+	case B43_FW_HDR_598:
+		break;
+	}
+	memset(rxhdr, 0, rxhdr_size);
+
+	/* Check if we have data and wait for it to get ready. */
+	if (q->rev >= 8) {
+		u32 ctl;
+
+		ctl = b43_piorx_read32(q, B43_PIO8_RXCTL);
+		if (!(ctl & B43_PIO8_RXCTL_FRAMERDY))
+			return false;
+		b43_piorx_write32(q, B43_PIO8_RXCTL,
+				  B43_PIO8_RXCTL_FRAMERDY);
+		for (i = 0; i < 10; i++) {
+			ctl = b43_piorx_read32(q, B43_PIO8_RXCTL);
+			if (ctl & B43_PIO8_RXCTL_DATARDY)
+				goto data_ready;
+			udelay(10);
+		}
+	} else {
+		u16 ctl;
+
+		ctl = b43_piorx_read16(q, B43_PIO_RXCTL);
+		if (!(ctl & B43_PIO_RXCTL_FRAMERDY))
+			return false;
+		b43_piorx_write16(q, B43_PIO_RXCTL,
+				  B43_PIO_RXCTL_FRAMERDY);
+		for (i = 0; i < 10; i++) {
+			ctl = b43_piorx_read16(q, B43_PIO_RXCTL);
+			if (ctl & B43_PIO_RXCTL_DATARDY)
+				goto data_ready;
+			udelay(10);
+		}
+	}
+	b43dbg(q->dev->wl, "PIO RX timed out\n");
+	return true;
+data_ready:
+
+	/* Get the preamble (RX header) */
+	if (q->rev >= 8) {
+		b43_block_read(dev, rxhdr, rxhdr_size,
+			       q->mmio_base + B43_PIO8_RXDATA,
+			       sizeof(u32));
+	} else {
+		b43_block_read(dev, rxhdr, rxhdr_size,
+			       q->mmio_base + B43_PIO_RXDATA,
+			       sizeof(u16));
+	}
+	/* Sanity checks. */
+	len = le16_to_cpu(rxhdr->frame_len);
+	if (unlikely(len > 0x700)) {
+		err_msg = "len > 0x700";
+		goto rx_error;
+	}
+	if (unlikely(len == 0)) {
+		err_msg = "len == 0";
+		goto rx_error;
+	}
+
+	switch (dev->fw.hdr_format) {
+	case B43_FW_HDR_598:
+		macstat = le32_to_cpu(rxhdr->format_598.mac_status);
+		break;
+	case B43_FW_HDR_410:
+	case B43_FW_HDR_351:
+		macstat = le32_to_cpu(rxhdr->format_351.mac_status);
+		break;
+	}
+	if (macstat & B43_RX_MAC_FCSERR) {
+		if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) {
+			/* Drop frames with failed FCS. */
+			err_msg = "Frame FCS error";
+			goto rx_error;
+		}
+	}
+
+	/* We always pad 2 bytes, as that's what upstream code expects
+	 * due to the RX-header being 30 bytes. In case the frame is
+	 * unaligned, we pad another 2 bytes. */
+	padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0;
+	skb = dev_alloc_skb(len + padding + 2);
+	if (unlikely(!skb)) {
+		err_msg = "Out of memory";
+		goto rx_error;
+	}
+	skb_reserve(skb, 2);
+	skb_put(skb, len + padding);
+	if (q->rev >= 8) {
+		b43_block_read(dev, skb->data + padding, (len & ~3),
+			       q->mmio_base + B43_PIO8_RXDATA,
+			       sizeof(u32));
+		if (len & 3) {
+			u8 *tail = wl->pio_tailspace;
+			BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4);
+
+			/* Read the last few bytes. */
+			b43_block_read(dev, tail, 4,
+				       q->mmio_base + B43_PIO8_RXDATA,
+				       sizeof(u32));
+			switch (len & 3) {
+			case 3:
+				skb->data[len + padding - 3] = tail[0];
+				skb->data[len + padding - 2] = tail[1];
+				skb->data[len + padding - 1] = tail[2];
+				break;
+			case 2:
+				skb->data[len + padding - 2] = tail[0];
+				skb->data[len + padding - 1] = tail[1];
+				break;
+			case 1:
+				skb->data[len + padding - 1] = tail[0];
+				break;
+			}
+		}
+	} else {
+		b43_block_read(dev, skb->data + padding, (len & ~1),
+			       q->mmio_base + B43_PIO_RXDATA,
+			       sizeof(u16));
+		if (len & 1) {
+			u8 *tail = wl->pio_tailspace;
+			BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2);
+
+			/* Read the last byte. */
+			b43_block_read(dev, tail, 2,
+				       q->mmio_base + B43_PIO_RXDATA,
+				       sizeof(u16));
+			skb->data[len + padding - 1] = tail[0];
+		}
+	}
+
+	b43_rx(q->dev, skb, rxhdr);
+
+	return true;
+
+rx_error:
+	if (err_msg)
+		b43dbg(q->dev->wl, "PIO RX error: %s\n", err_msg);
+	if (q->rev >= 8)
+		b43_piorx_write32(q, B43_PIO8_RXCTL, B43_PIO8_RXCTL_DATARDY);
+	else
+		b43_piorx_write16(q, B43_PIO_RXCTL, B43_PIO_RXCTL_DATARDY);
+
+	return true;
+}
+
+void b43_pio_rx(struct b43_pio_rxqueue *q)
+{
+	unsigned int count = 0;
+	bool stop;
+
+	while (1) {
+		stop = (pio_rx_frame(q) == 0);
+		if (stop)
+			break;
+		cond_resched();
+		if (WARN_ON_ONCE(++count > 10000))
+			break;
+	}
+}
+
+static void b43_pio_tx_suspend_queue(struct b43_pio_txqueue *q)
+{
+	if (q->rev >= 8) {
+		b43_piotx_write32(q, B43_PIO8_TXCTL,
+				  b43_piotx_read32(q, B43_PIO8_TXCTL)
+				  | B43_PIO8_TXCTL_SUSPREQ);
+	} else {
+		b43_piotx_write16(q, B43_PIO_TXCTL,
+				  b43_piotx_read16(q, B43_PIO_TXCTL)
+				  | B43_PIO_TXCTL_SUSPREQ);
+	}
+}
+
+static void b43_pio_tx_resume_queue(struct b43_pio_txqueue *q)
+{
+	if (q->rev >= 8) {
+		b43_piotx_write32(q, B43_PIO8_TXCTL,
+				  b43_piotx_read32(q, B43_PIO8_TXCTL)
+				  & ~B43_PIO8_TXCTL_SUSPREQ);
+	} else {
+		b43_piotx_write16(q, B43_PIO_TXCTL,
+				  b43_piotx_read16(q, B43_PIO_TXCTL)
+				  & ~B43_PIO_TXCTL_SUSPREQ);
+	}
+}
+
+void b43_pio_tx_suspend(struct b43_wldev *dev)
+{
+	b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
+	b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_BK);
+	b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_BE);
+	b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_VI);
+	b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_VO);
+	b43_pio_tx_suspend_queue(dev->pio.tx_queue_mcast);
+}
+
+void b43_pio_tx_resume(struct b43_wldev *dev)
+{
+	b43_pio_tx_resume_queue(dev->pio.tx_queue_mcast);
+	b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_VO);
+	b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_VI);
+	b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_BE);
+	b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_BK);
+	b43_power_saving_ctl_bits(dev, 0);
+}
diff --git a/drivers/net/wireless/broadcom/b43/pio.h b/drivers/net/wireless/broadcom/b43/pio.h
new file mode 100644
index 0000000..ffbfec6
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/pio.h
@@ -0,0 +1,166 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_PIO_H_
+#define B43_PIO_H_
+
+#include "b43.h"
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/skbuff.h>
+
+
+/*** Registers for PIO queues up to revision 7. ***/
+/* TX queue. */
+#define B43_PIO_TXCTL			0x00
+#define  B43_PIO_TXCTL_WRITELO		0x0001
+#define  B43_PIO_TXCTL_WRITEHI		0x0002
+#define  B43_PIO_TXCTL_EOF		0x0004
+#define  B43_PIO_TXCTL_FREADY		0x0008
+#define  B43_PIO_TXCTL_FLUSHREQ		0x0020
+#define  B43_PIO_TXCTL_FLUSHPEND	0x0040
+#define  B43_PIO_TXCTL_SUSPREQ		0x0080
+#define  B43_PIO_TXCTL_QSUSP		0x0100
+#define  B43_PIO_TXCTL_COMMCNT		0xFC00
+#define  B43_PIO_TXCTL_COMMCNT_SHIFT	10
+#define B43_PIO_TXDATA			0x02
+#define B43_PIO_TXQBUFSIZE		0x04
+/* RX queue. */
+#define B43_PIO_RXCTL			0x00
+#define  B43_PIO_RXCTL_FRAMERDY		0x0001
+#define  B43_PIO_RXCTL_DATARDY		0x0002
+#define B43_PIO_RXDATA			0x02
+
+/*** Registers for PIO queues revision 8 and later. ***/
+/* TX queue */
+#define B43_PIO8_TXCTL			0x00
+#define  B43_PIO8_TXCTL_0_7		0x00000001
+#define  B43_PIO8_TXCTL_8_15		0x00000002
+#define  B43_PIO8_TXCTL_16_23		0x00000004
+#define  B43_PIO8_TXCTL_24_31		0x00000008
+#define  B43_PIO8_TXCTL_EOF		0x00000010
+#define  B43_PIO8_TXCTL_FREADY		0x00000080
+#define  B43_PIO8_TXCTL_SUSPREQ		0x00000100
+#define  B43_PIO8_TXCTL_QSUSP		0x00000200
+#define  B43_PIO8_TXCTL_FLUSHREQ	0x00000400
+#define  B43_PIO8_TXCTL_FLUSHPEND	0x00000800
+#define B43_PIO8_TXDATA			0x04
+/* RX queue */
+#define B43_PIO8_RXCTL			0x00
+#define  B43_PIO8_RXCTL_FRAMERDY	0x00000001
+#define  B43_PIO8_RXCTL_DATARDY		0x00000002
+#define B43_PIO8_RXDATA			0x04
+
+
+/* The maximum number of TX-packets the HW can handle. */
+#define B43_PIO_MAX_NR_TXPACKETS	32
+
+
+struct b43_pio_txpacket {
+	/* Pointer to the TX queue we belong to. */
+	struct b43_pio_txqueue *queue;
+	/* The TX data packet. */
+	struct sk_buff *skb;
+	/* Index in the (struct b43_pio_txqueue)->packets array. */
+	u8 index;
+
+	struct list_head list;
+};
+
+struct b43_pio_txqueue {
+	struct b43_wldev *dev;
+	u16 mmio_base;
+
+	/* The device queue buffer size in bytes. */
+	u16 buffer_size;
+	/* The number of used bytes in the device queue buffer. */
+	u16 buffer_used;
+	/* The number of packets that can still get queued.
+	 * This is decremented on queueing a packet and incremented
+	 * after receiving the transmit status. */
+	u16 free_packet_slots;
+
+	/* True, if the mac80211 queue was stopped due to overflow at TX. */
+	bool stopped;
+	/* Our b43 queue index number */
+	u8 index;
+	/* The mac80211 QoS queue priority. */
+	u8 queue_prio;
+
+	/* Buffer for TX packet meta data. */
+	struct b43_pio_txpacket packets[B43_PIO_MAX_NR_TXPACKETS];
+	struct list_head packets_list;
+
+	/* Shortcut to the 802.11 core revision. This is to
+	 * avoid horrible pointer dereferencing in the fastpaths. */
+	u8 rev;
+};
+
+struct b43_pio_rxqueue {
+	struct b43_wldev *dev;
+	u16 mmio_base;
+
+	/* Shortcut to the 802.11 core revision. This is to
+	 * avoid horrible pointer dereferencing in the fastpaths. */
+	u8 rev;
+};
+
+
+static inline u16 b43_piotx_read16(struct b43_pio_txqueue *q, u16 offset)
+{
+	return b43_read16(q->dev, q->mmio_base + offset);
+}
+
+static inline u32 b43_piotx_read32(struct b43_pio_txqueue *q, u16 offset)
+{
+	return b43_read32(q->dev, q->mmio_base + offset);
+}
+
+static inline void b43_piotx_write16(struct b43_pio_txqueue *q,
+				     u16 offset, u16 value)
+{
+	b43_write16(q->dev, q->mmio_base + offset, value);
+}
+
+static inline void b43_piotx_write32(struct b43_pio_txqueue *q,
+				     u16 offset, u32 value)
+{
+	b43_write32(q->dev, q->mmio_base + offset, value);
+}
+
+
+static inline u16 b43_piorx_read16(struct b43_pio_rxqueue *q, u16 offset)
+{
+	return b43_read16(q->dev, q->mmio_base + offset);
+}
+
+static inline u32 b43_piorx_read32(struct b43_pio_rxqueue *q, u16 offset)
+{
+	return b43_read32(q->dev, q->mmio_base + offset);
+}
+
+static inline void b43_piorx_write16(struct b43_pio_rxqueue *q,
+				     u16 offset, u16 value)
+{
+	b43_write16(q->dev, q->mmio_base + offset, value);
+}
+
+static inline void b43_piorx_write32(struct b43_pio_rxqueue *q,
+				     u16 offset, u32 value)
+{
+	b43_write32(q->dev, q->mmio_base + offset, value);
+}
+
+
+int b43_pio_init(struct b43_wldev *dev);
+void b43_pio_free(struct b43_wldev *dev);
+
+int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb);
+void b43_pio_handle_txstatus(struct b43_wldev *dev,
+			     const struct b43_txstatus *status);
+void b43_pio_rx(struct b43_pio_rxqueue *q);
+
+void b43_pio_tx_suspend(struct b43_wldev *dev);
+void b43_pio_tx_resume(struct b43_wldev *dev);
+
+#endif /* B43_PIO_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/ppr.c b/drivers/net/wireless/broadcom/b43/ppr.c
new file mode 100644
index 0000000..9a77027
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/ppr.c
@@ -0,0 +1,199 @@
+/*
+ * Broadcom B43 wireless driver
+ * PPR (Power Per Rate) management
+ *
+ * Copyright (c) 2014 Rafał Miłecki <zajec5@gmail.com>
+ *
+ * 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.
+ */
+
+#include "ppr.h"
+#include "b43.h"
+
+#define ppr_for_each_entry(ppr, i, entry)				\
+	for (i = 0, entry = &(ppr)->__all_rates[i];			\
+	     i < B43_PPR_RATES_NUM;					\
+	     i++, entry++)
+
+void b43_ppr_clear(struct b43_wldev *dev, struct b43_ppr *ppr)
+{
+	memset(ppr, 0, sizeof(*ppr));
+
+	/* Compile-time PPR check */
+	BUILD_BUG_ON(sizeof(struct b43_ppr) != B43_PPR_RATES_NUM * sizeof(u8));
+}
+
+void b43_ppr_add(struct b43_wldev *dev, struct b43_ppr *ppr, int diff)
+{
+	int i;
+	u8 *rate;
+
+	ppr_for_each_entry(ppr, i, rate) {
+		*rate = clamp_val(*rate + diff, 0, 127);
+	}
+}
+
+void b43_ppr_apply_max(struct b43_wldev *dev, struct b43_ppr *ppr, u8 max)
+{
+	int i;
+	u8 *rate;
+
+	ppr_for_each_entry(ppr, i, rate) {
+		*rate = min(*rate, max);
+	}
+}
+
+void b43_ppr_apply_min(struct b43_wldev *dev, struct b43_ppr *ppr, u8 min)
+{
+	int i;
+	u8 *rate;
+
+	ppr_for_each_entry(ppr, i, rate) {
+		*rate = max(*rate, min);
+	}
+}
+
+u8 b43_ppr_get_max(struct b43_wldev *dev, struct b43_ppr *ppr)
+{
+	u8 res = 0;
+	int i;
+	u8 *rate;
+
+	ppr_for_each_entry(ppr, i, rate) {
+		res = max(*rate, res);
+	}
+
+	return res;
+}
+
+bool b43_ppr_load_max_from_sprom(struct b43_wldev *dev, struct b43_ppr *ppr,
+				 enum b43_band band)
+{
+	struct b43_ppr_rates *rates = &ppr->rates;
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+	struct b43_phy *phy = &dev->phy;
+	u8 maxpwr, off;
+	u32 sprom_ofdm_po;
+	u16 *sprom_mcs_po;
+	u8 extra_cdd_po, extra_stbc_po;
+	int i;
+
+	switch (band) {
+	case B43_BAND_2G:
+		maxpwr = min(sprom->core_pwr_info[0].maxpwr_2g,
+			     sprom->core_pwr_info[1].maxpwr_2g);
+		sprom_ofdm_po = sprom->ofdm2gpo;
+		sprom_mcs_po = sprom->mcs2gpo;
+		extra_cdd_po = (sprom->cddpo >> 0) & 0xf;
+		extra_stbc_po = (sprom->stbcpo >> 0) & 0xf;
+		break;
+	case B43_BAND_5G_LO:
+		maxpwr = min(sprom->core_pwr_info[0].maxpwr_5gl,
+			     sprom->core_pwr_info[1].maxpwr_5gl);
+		sprom_ofdm_po = sprom->ofdm5glpo;
+		sprom_mcs_po = sprom->mcs5glpo;
+		extra_cdd_po = (sprom->cddpo >> 8) & 0xf;
+		extra_stbc_po = (sprom->stbcpo >> 8) & 0xf;
+		break;
+	case B43_BAND_5G_MI:
+		maxpwr = min(sprom->core_pwr_info[0].maxpwr_5g,
+			     sprom->core_pwr_info[1].maxpwr_5g);
+		sprom_ofdm_po = sprom->ofdm5gpo;
+		sprom_mcs_po = sprom->mcs5gpo;
+		extra_cdd_po = (sprom->cddpo >> 4) & 0xf;
+		extra_stbc_po = (sprom->stbcpo >> 4) & 0xf;
+		break;
+	case B43_BAND_5G_HI:
+		maxpwr = min(sprom->core_pwr_info[0].maxpwr_5gh,
+			     sprom->core_pwr_info[1].maxpwr_5gh);
+		sprom_ofdm_po = sprom->ofdm5ghpo;
+		sprom_mcs_po = sprom->mcs5ghpo;
+		extra_cdd_po = (sprom->cddpo >> 12) & 0xf;
+		extra_stbc_po = (sprom->stbcpo >> 12) & 0xf;
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		return false;
+	}
+
+	if (band == B43_BAND_2G) {
+		for (i = 0; i < 4; i++) {
+			off = ((sprom->cck2gpo >> (i * 4)) & 0xf) * 2;
+			rates->cck[i] = maxpwr - off;
+		}
+	}
+
+	/* OFDM */
+	for (i = 0; i < 8; i++) {
+		off = ((sprom_ofdm_po >> (i * 4)) & 0xf) * 2;
+		rates->ofdm[i] = maxpwr - off;
+	}
+
+	/* MCS 20 SISO */
+	rates->mcs_20[0] = rates->ofdm[0];
+	rates->mcs_20[1] = rates->ofdm[2];
+	rates->mcs_20[2] = rates->ofdm[3];
+	rates->mcs_20[3] = rates->ofdm[4];
+	rates->mcs_20[4] = rates->ofdm[5];
+	rates->mcs_20[5] = rates->ofdm[6];
+	rates->mcs_20[6] = rates->ofdm[7];
+	rates->mcs_20[7] = rates->ofdm[7];
+
+	/* MCS 20 CDD */
+	for (i = 0; i < 4; i++) {
+		off = ((sprom_mcs_po[0] >> (i * 4)) & 0xf) * 2;
+		rates->mcs_20_cdd[i] = maxpwr - off;
+		if (phy->type == B43_PHYTYPE_N && phy->rev >= 3)
+			rates->mcs_20_cdd[i] -= extra_cdd_po;
+	}
+	for (i = 0; i < 4; i++) {
+		off = ((sprom_mcs_po[1] >> (i * 4)) & 0xf) * 2;
+		rates->mcs_20_cdd[4 + i] = maxpwr - off;
+		if (phy->type == B43_PHYTYPE_N && phy->rev >= 3)
+			rates->mcs_20_cdd[4 + i] -= extra_cdd_po;
+	}
+
+	/* OFDM 20 CDD */
+	rates->ofdm_20_cdd[0] = rates->mcs_20_cdd[0];
+	rates->ofdm_20_cdd[1] = rates->mcs_20_cdd[0];
+	rates->ofdm_20_cdd[2] = rates->mcs_20_cdd[1];
+	rates->ofdm_20_cdd[3] = rates->mcs_20_cdd[2];
+	rates->ofdm_20_cdd[4] = rates->mcs_20_cdd[3];
+	rates->ofdm_20_cdd[5] = rates->mcs_20_cdd[4];
+	rates->ofdm_20_cdd[6] = rates->mcs_20_cdd[5];
+	rates->ofdm_20_cdd[7] = rates->mcs_20_cdd[6];
+
+	/* MCS 20 STBC */
+	for (i = 0; i < 4; i++) {
+		off = ((sprom_mcs_po[0] >> (i * 4)) & 0xf) * 2;
+		rates->mcs_20_stbc[i] = maxpwr - off;
+		if (phy->type == B43_PHYTYPE_N && phy->rev >= 3)
+			rates->mcs_20_stbc[i] -= extra_stbc_po;
+	}
+	for (i = 0; i < 4; i++) {
+		off = ((sprom_mcs_po[1] >> (i * 4)) & 0xf) * 2;
+		rates->mcs_20_stbc[4 + i] = maxpwr - off;
+		if (phy->type == B43_PHYTYPE_N && phy->rev >= 3)
+			rates->mcs_20_stbc[4 + i] -= extra_stbc_po;
+	}
+
+	/* MCS 20 SDM */
+	for (i = 0; i < 4; i++) {
+		off = ((sprom_mcs_po[2] >> (i * 4)) & 0xf) * 2;
+		rates->mcs_20_sdm[i] = maxpwr - off;
+	}
+	for (i = 0; i < 4; i++) {
+		off = ((sprom_mcs_po[3] >> (i * 4)) & 0xf) * 2;
+		rates->mcs_20_sdm[4 + i] = maxpwr - off;
+	}
+
+	return true;
+}
diff --git a/drivers/net/wireless/broadcom/b43/ppr.h b/drivers/net/wireless/broadcom/b43/ppr.h
new file mode 100644
index 0000000..094389f
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/ppr.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef LINUX_B43_PPR_H_
+#define LINUX_B43_PPR_H_
+
+#include <linux/types.h>
+
+#define B43_PPR_CCK_RATES_NUM		4
+#define B43_PPR_OFDM_RATES_NUM		8
+#define B43_PPR_MCS_RATES_NUM		8
+
+#define B43_PPR_RATES_NUM	(B43_PPR_CCK_RATES_NUM +	\
+				 B43_PPR_OFDM_RATES_NUM * 2 +	\
+				 B43_PPR_MCS_RATES_NUM * 4)
+
+struct b43_ppr_rates {
+	u8 cck[B43_PPR_CCK_RATES_NUM];
+	u8 ofdm[B43_PPR_OFDM_RATES_NUM];
+	u8 ofdm_20_cdd[B43_PPR_OFDM_RATES_NUM];
+	u8 mcs_20[B43_PPR_MCS_RATES_NUM]; /* SISO */
+	u8 mcs_20_cdd[B43_PPR_MCS_RATES_NUM];
+	u8 mcs_20_stbc[B43_PPR_MCS_RATES_NUM];
+	u8 mcs_20_sdm[B43_PPR_MCS_RATES_NUM];
+};
+
+struct b43_ppr {
+	/* All powers are in qdbm (Q5.2) */
+	union {
+		u8 __all_rates[B43_PPR_RATES_NUM];
+		struct b43_ppr_rates rates;
+	};
+};
+
+struct b43_wldev;
+enum b43_band;
+
+void b43_ppr_clear(struct b43_wldev *dev, struct b43_ppr *ppr);
+
+void b43_ppr_add(struct b43_wldev *dev, struct b43_ppr *ppr, int diff);
+void b43_ppr_apply_max(struct b43_wldev *dev, struct b43_ppr *ppr, u8 max);
+void b43_ppr_apply_min(struct b43_wldev *dev, struct b43_ppr *ppr, u8 min);
+u8 b43_ppr_get_max(struct b43_wldev *dev, struct b43_ppr *ppr);
+
+bool b43_ppr_load_max_from_sprom(struct b43_wldev *dev, struct b43_ppr *ppr,
+				 enum b43_band band);
+
+#endif /* LINUX_B43_PPR_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/radio_2055.c b/drivers/net/wireless/broadcom/b43/radio_2055.c
new file mode 100644
index 0000000..5289a18
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/radio_2055.c
@@ -0,0 +1,1335 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11n PHY and radio device data tables
+
+  Copyright (c) 2008 Michael Buesch <m@bues.ch>
+  Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
+
+  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 "radio_2055.h"
+#include "phy_common.h"
+
+struct b2055_inittab_entry {
+	/* Value to write if we use the 5GHz band. */
+	u16 ghz5;
+	/* Value to write if we use the 2.4GHz band. */
+	u16 ghz2;
+	/* Flags */
+	u8 flags;
+#define B2055_INITTAB_ENTRY_OK	0x01
+#define B2055_INITTAB_UPLOAD	0x02
+};
+#define UPLOAD		.flags = B2055_INITTAB_ENTRY_OK | B2055_INITTAB_UPLOAD
+#define NOUPLOAD	.flags = B2055_INITTAB_ENTRY_OK
+
+static const struct b2055_inittab_entry b2055_inittab [] = {
+  [B2055_SP_PINPD]		= { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, },
+  [B2055_C1_SP_RSSI]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C1_SP_PDMISC]		= { .ghz5 = 0x0027, .ghz2 = 0x0027, NOUPLOAD, },
+  [B2055_C2_SP_RSSI]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C2_SP_PDMISC]		= { .ghz5 = 0x0027, .ghz2 = 0x0027, NOUPLOAD, },
+  [B2055_C1_SP_RXGC1]		= { .ghz5 = 0x007F, .ghz2 = 0x007F, UPLOAD, },
+  [B2055_C1_SP_RXGC2]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+  [B2055_C2_SP_RXGC1]		= { .ghz5 = 0x007F, .ghz2 = 0x007F, UPLOAD, },
+  [B2055_C2_SP_RXGC2]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+  [B2055_C1_SP_LPFBWSEL]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+  [B2055_C2_SP_LPFBWSEL]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+  [B2055_C1_SP_TXGC1]		= { .ghz5 = 0x004F, .ghz2 = 0x004F, UPLOAD, },
+  [B2055_C1_SP_TXGC2]		= { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, },
+  [B2055_C2_SP_TXGC1]		= { .ghz5 = 0x004F, .ghz2 = 0x004F, UPLOAD, },
+  [B2055_C2_SP_TXGC2]		= { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, },
+  [B2055_MASTER1]		= { .ghz5 = 0x00D0, .ghz2 = 0x00D0, NOUPLOAD, },
+  [B2055_MASTER2]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+  [B2055_PD_LGEN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_PD_PLLTS]		= { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, },
+  [B2055_C1_PD_LGBUF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C1_PD_TX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C1_PD_RXTX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C1_PD_RSSIMISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C2_PD_LGBUF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C2_PD_TX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C2_PD_RXTX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C2_PD_RSSIMISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_PWRDET_LGEN]		= { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, },
+  [B2055_C1_PWRDET_LGBUF]	= { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
+  [B2055_C1_PWRDET_RXTX]	= { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, },
+  [B2055_C2_PWRDET_LGBUF]	= { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
+  [B2055_C2_PWRDET_RXTX]	= { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, },
+  [B2055_RRCCAL_CS]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_RRCCAL_NOPTSEL]	= { .ghz5 = 0x002C, .ghz2 = 0x002C, NOUPLOAD, },
+  [B2055_CAL_MISC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_CAL_COUT]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_CAL_COUT2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_CAL_CVARCTL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_CAL_RVARCTL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_CAL_LPOCTL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_CAL_TS]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_CAL_RCCALRTS]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_CAL_RCALRTS]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_PADDRV]		= { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, },
+  [B2055_XOCTL1]		= { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, },
+  [B2055_XOCTL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_XOREGUL]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, },
+  [B2055_XOMISC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_PLL_LFC1]		= { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
+  [B2055_PLL_CALVTH]		= { .ghz5 = 0x0087, .ghz2 = 0x0087, NOUPLOAD, },
+  [B2055_PLL_LFC2]		= { .ghz5 = 0x0009, .ghz2 = 0x0009, NOUPLOAD, },
+  [B2055_PLL_REF]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+  [B2055_PLL_LFR1]		= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+  [B2055_PLL_PFDCP]		= { .ghz5 = 0x0018, .ghz2 = 0x0018, UPLOAD, },
+  [B2055_PLL_IDAC_CPOPAMP]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+  [B2055_PLL_CPREG]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, },
+  [B2055_PLL_RCAL]		= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+  [B2055_RF_PLLMOD0]		= { .ghz5 = 0x009E, .ghz2 = 0x009E, NOUPLOAD, },
+  [B2055_RF_PLLMOD1]		= { .ghz5 = 0x0009, .ghz2 = 0x0009, NOUPLOAD, },
+  [B2055_RF_MMDIDAC1]		= { .ghz5 = 0x00C8, .ghz2 = 0x00C8, UPLOAD, },
+  [B2055_RF_MMDIDAC0]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [B2055_RF_MMDSP]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_VCO_CAL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_VCO_CAL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_VCO_CAL3]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+  [B2055_VCO_CAL4]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+  [B2055_VCO_CAL5]		= { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, },
+  [B2055_VCO_CAL6]		= { .ghz5 = 0x003E, .ghz2 = 0x003E, NOUPLOAD, },
+  [B2055_VCO_CAL7]		= { .ghz5 = 0x003E, .ghz2 = 0x003E, NOUPLOAD, },
+  [B2055_VCO_CAL8]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+  [B2055_VCO_CAL9]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+  [B2055_VCO_CAL10]		= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+  [B2055_VCO_CAL11]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+  [B2055_VCO_CAL12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_VCO_CAL13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_VCO_CAL14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_VCO_CAL15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_VCO_CAL16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_VCO_KVCO]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+  [B2055_VCO_CAPTAIL]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+  [B2055_VCO_IDACVCO]		= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+  [B2055_VCO_REG]		= { .ghz5 = 0x0084, .ghz2 = 0x0084, UPLOAD, },
+  [B2055_PLL_RFVTH]		= { .ghz5 = 0x00C3, .ghz2 = 0x00C3, NOUPLOAD, },
+  [B2055_LGBUF_CENBUF]		= { .ghz5 = 0x008F, .ghz2 = 0x008F, NOUPLOAD, },
+  [B2055_LGEN_TUNE1]		= { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
+  [B2055_LGEN_TUNE2]		= { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
+  [B2055_LGEN_IDAC1]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [B2055_LGEN_IDAC2]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [B2055_LGEN_BIASC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_LGEN_BIASIDAC]		= { .ghz5 = 0x00CC, .ghz2 = 0x00CC, NOUPLOAD, },
+  [B2055_LGEN_RCAL]		= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+  [B2055_LGEN_DIV]		= { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, },
+  [B2055_LGEN_SPARE2]		= { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, },
+  [B2055_C1_LGBUF_ATUNE]	= { .ghz5 = 0x00F8, .ghz2 = 0x00F8, NOUPLOAD, },
+  [B2055_C1_LGBUF_GTUNE]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [B2055_C1_LGBUF_DIV]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [B2055_C1_LGBUF_AIDAC]	= { .ghz5 = 0x0088, .ghz2 = 0x0008, UPLOAD, },
+  [B2055_C1_LGBUF_GIDAC]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [B2055_C1_LGBUF_IDACFO]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C1_LGBUF_SPARE]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, UPLOAD, },
+  [B2055_C1_RX_RFSPC1]		= { .ghz5 = 0x008A, .ghz2 = 0x008A, NOUPLOAD, },
+  [B2055_C1_RX_RFR1]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+  [B2055_C1_RX_RFR2]		= { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
+  [B2055_C1_RX_RFRCAL]		= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+  [B2055_C1_RX_BB_BLCMP]	= { .ghz5 = 0x00A0, .ghz2 = 0x00A0, NOUPLOAD, },
+  [B2055_C1_RX_BB_LPF]		= { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
+  [B2055_C1_RX_BB_MIDACHP]	= { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
+  [B2055_C1_RX_BB_VGA1IDAC]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+  [B2055_C1_RX_BB_VGA2IDAC]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+  [B2055_C1_RX_BB_VGA3IDAC]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+  [B2055_C1_RX_BB_BUFOCTL]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+  [B2055_C1_RX_BB_RCCALCTL]	= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+  [B2055_C1_RX_BB_RSSICTL1]	= { .ghz5 = 0x006A, .ghz2 = 0x006A, UPLOAD, },
+  [B2055_C1_RX_BB_RSSICTL2]	= { .ghz5 = 0x00AB, .ghz2 = 0x00AB, UPLOAD, },
+  [B2055_C1_RX_BB_RSSICTL3]	= { .ghz5 = 0x0013, .ghz2 = 0x0013, UPLOAD, },
+  [B2055_C1_RX_BB_RSSICTL4]	= { .ghz5 = 0x00C1, .ghz2 = 0x00C1, UPLOAD, },
+  [B2055_C1_RX_BB_RSSICTL5]	= { .ghz5 = 0x00AA, .ghz2 = 0x00AA, UPLOAD, },
+  [B2055_C1_RX_BB_REG]		= { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
+  [B2055_C1_RX_BB_SPARE1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C1_RX_TXBBRCAL]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+  [B2055_C1_TX_RF_SPGA]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+  [B2055_C1_TX_RF_SPAD]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+  [B2055_C1_TX_RF_CNTPGA1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+  [B2055_C1_TX_RF_CNTPAD1]	= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+  [B2055_C1_TX_RF_PGAIDAC]	= { .ghz5 = 0x0097, .ghz2 = 0x0097, UPLOAD, },
+  [B2055_C1_TX_PGAPADTN]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+  [B2055_C1_TX_PADIDAC1]	= { .ghz5 = 0x0014, .ghz2 = 0x0014, UPLOAD, },
+  [B2055_C1_TX_PADIDAC2]	= { .ghz5 = 0x0033, .ghz2 = 0x0033, NOUPLOAD, },
+  [B2055_C1_TX_MXBGTRIM]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [B2055_C1_TX_RF_RCAL]		= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+  [B2055_C1_TX_RF_PADTSSI1]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
+  [B2055_C1_TX_RF_PADTSSI2]	= { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
+  [B2055_C1_TX_RF_SPARE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
+  [B2055_C1_TX_RF_IQCAL1]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+  [B2055_C1_TX_RF_IQCAL2]	= { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, },
+  [B2055_C1_TXBB_RCCAL]		= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+  [B2055_C1_TXBB_LPF1]		= { .ghz5 = 0x0028, .ghz2 = 0x0028, NOUPLOAD, },
+  [B2055_C1_TX_VOSCNCL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C1_TX_LPF_MXGMIDAC]	= { .ghz5 = 0x004A, .ghz2 = 0x004A, NOUPLOAD, },
+  [B2055_C1_TX_BB_MXGM]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C2_LGBUF_ATUNE]	= { .ghz5 = 0x00F8, .ghz2 = 0x00F8, NOUPLOAD, },
+  [B2055_C2_LGBUF_GTUNE]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [B2055_C2_LGBUF_DIV]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [B2055_C2_LGBUF_AIDAC]	= { .ghz5 = 0x0088, .ghz2 = 0x0008, UPLOAD, },
+  [B2055_C2_LGBUF_GIDAC]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [B2055_C2_LGBUF_IDACFO]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C2_LGBUF_SPARE]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, UPLOAD, },
+  [B2055_C2_RX_RFSPC1]		= { .ghz5 = 0x008A, .ghz2 = 0x008A, NOUPLOAD, },
+  [B2055_C2_RX_RFR1]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+  [B2055_C2_RX_RFR2]		= { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
+  [B2055_C2_RX_RFRCAL]		= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+  [B2055_C2_RX_BB_BLCMP]	= { .ghz5 = 0x00A0, .ghz2 = 0x00A0, NOUPLOAD, },
+  [B2055_C2_RX_BB_LPF]		= { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
+  [B2055_C2_RX_BB_MIDACHP]	= { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
+  [B2055_C2_RX_BB_VGA1IDAC]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+  [B2055_C2_RX_BB_VGA2IDAC]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+  [B2055_C2_RX_BB_VGA3IDAC]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+  [B2055_C2_RX_BB_BUFOCTL]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+  [B2055_C2_RX_BB_RCCALCTL]	= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+  [B2055_C2_RX_BB_RSSICTL1]	= { .ghz5 = 0x006A, .ghz2 = 0x006A, UPLOAD, },
+  [B2055_C2_RX_BB_RSSICTL2]	= { .ghz5 = 0x00AB, .ghz2 = 0x00AB, UPLOAD, },
+  [B2055_C2_RX_BB_RSSICTL3]	= { .ghz5 = 0x0013, .ghz2 = 0x0013, UPLOAD, },
+  [B2055_C2_RX_BB_RSSICTL4]	= { .ghz5 = 0x00C1, .ghz2 = 0x00C1, UPLOAD, },
+  [B2055_C2_RX_BB_RSSICTL5]	= { .ghz5 = 0x00AA, .ghz2 = 0x00AA, UPLOAD, },
+  [B2055_C2_RX_BB_REG]		= { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
+  [B2055_C2_RX_BB_SPARE1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C2_RX_TXBBRCAL]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+  [B2055_C2_TX_RF_SPGA]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+  [B2055_C2_TX_RF_SPAD]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+  [B2055_C2_TX_RF_CNTPGA1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+  [B2055_C2_TX_RF_CNTPAD1]	= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+  [B2055_C2_TX_RF_PGAIDAC]	= { .ghz5 = 0x0097, .ghz2 = 0x0097, UPLOAD, },
+  [B2055_C2_TX_PGAPADTN]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+  [B2055_C2_TX_PADIDAC1]	= { .ghz5 = 0x0014, .ghz2 = 0x0014, UPLOAD, },
+  [B2055_C2_TX_PADIDAC2]	= { .ghz5 = 0x0033, .ghz2 = 0x0033, NOUPLOAD, },
+  [B2055_C2_TX_MXBGTRIM]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [B2055_C2_TX_RF_RCAL]		= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+  [B2055_C2_TX_RF_PADTSSI1]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
+  [B2055_C2_TX_RF_PADTSSI2]	= { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
+  [B2055_C2_TX_RF_SPARE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
+  [B2055_C2_TX_RF_IQCAL1]	= { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+  [B2055_C2_TX_RF_IQCAL2]	= { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, },
+  [B2055_C2_TXBB_RCCAL]		= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+  [B2055_C2_TXBB_LPF1]		= { .ghz5 = 0x0028, .ghz2 = 0x0028, NOUPLOAD, },
+  [B2055_C2_TX_VOSCNCL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C2_TX_LPF_MXGMIDAC]	= { .ghz5 = 0x004A, .ghz2 = 0x004A, NOUPLOAD, },
+  [B2055_C2_TX_BB_MXGM]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_PRG_GCHP21]		= { .ghz5 = 0x0071, .ghz2 = 0x0071, NOUPLOAD, },
+  [B2055_PRG_GCHP22]		= { .ghz5 = 0x0072, .ghz2 = 0x0072, NOUPLOAD, },
+  [B2055_PRG_GCHP23]		= { .ghz5 = 0x0073, .ghz2 = 0x0073, NOUPLOAD, },
+  [B2055_PRG_GCHP24]		= { .ghz5 = 0x0074, .ghz2 = 0x0074, NOUPLOAD, },
+  [B2055_PRG_GCHP25]		= { .ghz5 = 0x0075, .ghz2 = 0x0075, NOUPLOAD, },
+  [B2055_PRG_GCHP26]		= { .ghz5 = 0x0076, .ghz2 = 0x0076, NOUPLOAD, },
+  [B2055_PRG_GCHP27]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+  [B2055_PRG_GCHP28]		= { .ghz5 = 0x0078, .ghz2 = 0x0078, NOUPLOAD, },
+  [B2055_PRG_GCHP29]		= { .ghz5 = 0x0079, .ghz2 = 0x0079, NOUPLOAD, },
+  [B2055_PRG_GCHP30]		= { .ghz5 = 0x007A, .ghz2 = 0x007A, NOUPLOAD, },
+  [0xC7]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xC8]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xC9]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xCA]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xCB]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xCC]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C1_LNA_GAINBST]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xCE]			= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+  [0xCF]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xD0]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xD1]			= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+  [B2055_C1_B0NB_RSSIVCM]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [0xD3]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xD4]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xD5]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C1_GENSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xD7]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xD8]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C2_LNA_GAINBST]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xDA]			= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+  [0xDB]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xDC]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xDD]			= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+  [B2055_C2_B0NB_RSSIVCM]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+  [0xDF]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xE0]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xE1]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [B2055_C2_GENSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+#define RADIOREGS(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, \
+		  r12, r13, r14, r15, r16, r17, r18, r19, r20, r21) \
+	.radio_pll_ref		= r0,	\
+	.radio_rf_pllmod0	= r1,	\
+	.radio_rf_pllmod1	= r2,	\
+	.radio_vco_captail	= r3,	\
+	.radio_vco_cal1		= r4,	\
+	.radio_vco_cal2		= r5,	\
+	.radio_pll_lfc1		= r6,	\
+	.radio_pll_lfr1		= r7,	\
+	.radio_pll_lfc2		= r8,	\
+	.radio_lgbuf_cenbuf	= r9,	\
+	.radio_lgen_tune1	= r10,	\
+	.radio_lgen_tune2	= r11,	\
+	.radio_c1_lgbuf_atune	= r12,	\
+	.radio_c1_lgbuf_gtune	= r13,	\
+	.radio_c1_rx_rfr1	= r14,	\
+	.radio_c1_tx_pgapadtn	= r15,	\
+	.radio_c1_tx_mxbgtrim	= r16,	\
+	.radio_c2_lgbuf_atune	= r17,	\
+	.radio_c2_lgbuf_gtune	= r18,	\
+	.radio_c2_rx_rfr1	= r19,	\
+	.radio_c2_tx_pgapadtn	= r20,	\
+	.radio_c2_tx_mxbgtrim	= r21
+
+#define PHYREGS(r0, r1, r2, r3, r4, r5)	\
+	.phy_regs.phy_bw1a	= r0,	\
+	.phy_regs.phy_bw2	= r1,	\
+	.phy_regs.phy_bw3	= r2,	\
+	.phy_regs.phy_bw4	= r3,	\
+	.phy_regs.phy_bw5	= r4,	\
+	.phy_regs.phy_bw6	= r5
+
+static const struct b43_nphy_channeltab_entry_rev2 b43_nphy_channeltab_rev2[] = {
+  {	.channel		= 184,
+	.freq			= 4920, /* MHz */
+	.unk2			= 3280,
+	RADIOREGS(0x71, 0xEC, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0x07B4, 0x07B0, 0x07AC, 0x0214, 0x0215, 0x0216),
+  },
+  {	.channel		= 186,
+	.freq			= 4930, /* MHz */
+	.unk2			= 3287,
+	RADIOREGS(0x71, 0xED, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0x07B8, 0x07B4, 0x07B0, 0x0213, 0x0214, 0x0215),
+  },
+  {	.channel		= 188,
+	.freq			= 4940, /* MHz */
+	.unk2			= 3293,
+	RADIOREGS(0x71, 0xEE, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0x07BC, 0x07B8, 0x07B4, 0x0212, 0x0213, 0x0214),
+  },
+  {	.channel		= 190,
+	.freq			= 4950, /* MHz */
+	.unk2			= 3300,
+	RADIOREGS(0x71, 0xEF, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0x07C0, 0x07BC, 0x07B8, 0x0211, 0x0212, 0x0213),
+  },
+  {	.channel		= 192,
+	.freq			= 4960, /* MHz */
+	.unk2			= 3307,
+	RADIOREGS(0x71, 0xF0, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0x07C4, 0x07C0, 0x07BC, 0x020F, 0x0211, 0x0212),
+  },
+  {	.channel		= 194,
+	.freq			= 4970, /* MHz */
+	.unk2			= 3313,
+	RADIOREGS(0x71, 0xF1, 0x01, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0x07C8, 0x07C4, 0x07C0, 0x020E, 0x020F, 0x0211),
+  },
+  {	.channel		= 196,
+	.freq			= 4980, /* MHz */
+	.unk2			= 3320,
+	RADIOREGS(0x71, 0xF2, 0x01, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0x07CC, 0x07C8, 0x07C4, 0x020D, 0x020E, 0x020F),
+  },
+  {	.channel		= 198,
+	.freq			= 4990, /* MHz */
+	.unk2			= 3327,
+	RADIOREGS(0x71, 0xF3, 0x01, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0x07D0, 0x07CC, 0x07C8, 0x020C, 0x020D, 0x020E),
+  },
+  {	.channel		= 200,
+	.freq			= 5000, /* MHz */
+	.unk2			= 3333,
+	RADIOREGS(0x71, 0xF4, 0x01, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0x07D4, 0x07D0, 0x07CC, 0x020B, 0x020C, 0x020D),
+  },
+  {	.channel		= 202,
+	.freq			= 5010, /* MHz */
+	.unk2			= 3340,
+	RADIOREGS(0x71, 0xF5, 0x01, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0x07D8, 0x07D4, 0x07D0, 0x020A, 0x020B, 0x020C),
+  },
+  {	.channel		= 204,
+	.freq			= 5020, /* MHz */
+	.unk2			= 3347,
+	RADIOREGS(0x71, 0xF6, 0x01, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0x07DC, 0x07D8, 0x07D4, 0x0209, 0x020A, 0x020B),
+  },
+  {	.channel		= 206,
+	.freq			= 5030, /* MHz */
+	.unk2			= 3353,
+	RADIOREGS(0x71, 0xF7, 0x01, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0x07E0, 0x07DC, 0x07D8, 0x0208, 0x0209, 0x020A),
+  },
+  {	.channel		= 208,
+	.freq			= 5040, /* MHz */
+	.unk2			= 3360,
+	RADIOREGS(0x71, 0xF8, 0x01, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0x07E4, 0x07E0, 0x07DC, 0x0207, 0x0208, 0x0209),
+  },
+  {	.channel		= 210,
+	.freq			= 5050, /* MHz */
+	.unk2			= 3367,
+	RADIOREGS(0x71, 0xF9, 0x01, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
+		  0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+	PHYREGS(0x07E8, 0x07E4, 0x07E0, 0x0206, 0x0207, 0x0208),
+  },
+  {	.channel		= 212,
+	.freq			= 5060, /* MHz */
+	.unk2			= 3373,
+	RADIOREGS(0x71, 0xFA, 0x01, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F,
+		  0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E),
+	PHYREGS(0x07EC, 0x07E8, 0x07E4, 0x0205, 0x0206, 0x0207),
+  },
+  {	.channel		= 214,
+	.freq			= 5070, /* MHz */
+	.unk2			= 3380,
+	RADIOREGS(0x71, 0xFB, 0x01, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
+		  0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F,
+		  0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E),
+	PHYREGS(0x07F0, 0x07EC, 0x07E8, 0x0204, 0x0205, 0x0206),
+  },
+  {	.channel		= 216,
+	.freq			= 5080, /* MHz */
+	.unk2			= 3387,
+	RADIOREGS(0x71, 0xFC, 0x01, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
+		  0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F,
+		  0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D),
+	PHYREGS(0x07F4, 0x07F0, 0x07EC, 0x0203, 0x0204, 0x0205),
+  },
+  {	.channel		= 218,
+	.freq			= 5090, /* MHz */
+	.unk2			= 3393,
+	RADIOREGS(0x71, 0xFD, 0x01, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
+		  0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F,
+		  0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D),
+	PHYREGS(0x07F8, 0x07F4, 0x07F0, 0x0202, 0x0203, 0x0204),
+  },
+  {	.channel		= 220,
+	.freq			= 5100, /* MHz */
+	.unk2			= 3400,
+	RADIOREGS(0x71, 0xFE, 0x01, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
+		  0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F,
+		  0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D),
+	PHYREGS(0x07FC, 0x07F8, 0x07F4, 0x0201, 0x0202, 0x0203),
+  },
+  {	.channel		= 222,
+	.freq			= 5110, /* MHz */
+	.unk2			= 3407,
+	RADIOREGS(0x71, 0xFF, 0x01, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
+		  0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F,
+		  0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D),
+	PHYREGS(0x0800, 0x07FC, 0x07F8, 0x0200, 0x0201, 0x0202),
+  },
+  {	.channel		= 224,
+	.freq			= 5120, /* MHz */
+	.unk2			= 3413,
+	RADIOREGS(0x71, 0x00, 0x02, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
+		  0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F,
+		  0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C),
+	PHYREGS(0x0804, 0x0800, 0x07FC, 0x01FF, 0x0200, 0x0201),
+  },
+  {	.channel		= 226,
+	.freq			= 5130, /* MHz */
+	.unk2			= 3420,
+	RADIOREGS(0x71, 0x01, 0x02, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
+		  0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F,
+		  0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C),
+	PHYREGS(0x0808, 0x0804, 0x0800, 0x01FE, 0x01FF, 0x0200),
+  },
+  {	.channel		= 228,
+	.freq			= 5140, /* MHz */
+	.unk2			= 3427,
+	RADIOREGS(0x71, 0x02, 0x02, 0x0C, 0xC6, 0x01, 0x04, 0x0A,
+		  0x00, 0x8D, 0x99, 0x99, 0xDD, 0x00, 0x0C, 0x0E,
+		  0x8B, 0xDD, 0x00, 0x0C, 0x0E, 0x8B),
+	PHYREGS(0x080C, 0x0808, 0x0804, 0x01FD, 0x01FE, 0x01FF),
+  },
+  {	.channel		= 32,
+	.freq			= 5160, /* MHz */
+	.unk2			= 3440,
+	RADIOREGS(0x71, 0x04, 0x02, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
+		  0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D,
+		  0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A),
+	PHYREGS(0x0814, 0x0810, 0x080C, 0x01FB, 0x01FC, 0x01FD),
+  },
+  {	.channel		= 34,
+	.freq			= 5170, /* MHz */
+	.unk2			= 3447,
+	RADIOREGS(0x71, 0x05, 0x02, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
+		  0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D,
+		  0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A),
+	PHYREGS(0x0818, 0x0814, 0x0810, 0x01FA, 0x01FB, 0x01FC),
+  },
+  {	.channel		= 36,
+	.freq			= 5180, /* MHz */
+	.unk2			= 3453,
+	RADIOREGS(0x71, 0x06, 0x02, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
+		  0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C,
+		  0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89),
+	PHYREGS(0x081C, 0x0818, 0x0814, 0x01F9, 0x01FA, 0x01FB),
+  },
+  {	.channel		= 38,
+	.freq			= 5190, /* MHz */
+	.unk2			= 3460,
+	RADIOREGS(0x71, 0x07, 0x02, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
+		  0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C,
+		  0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89),
+	PHYREGS(0x0820, 0x081C, 0x0818, 0x01F8, 0x01F9, 0x01FA),
+  },
+  {	.channel		= 40,
+	.freq			= 5200, /* MHz */
+	.unk2			= 3467,
+	RADIOREGS(0x71, 0x08, 0x02, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B,
+		  0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89),
+	PHYREGS(0x0824, 0x0820, 0x081C, 0x01F7, 0x01F8, 0x01F9),
+  },
+  {	.channel		= 42,
+	.freq			= 5210, /* MHz */
+	.unk2			= 3473,
+	RADIOREGS(0x71, 0x09, 0x02, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
+		  0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B,
+		  0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89),
+	PHYREGS(0x0828, 0x0824, 0x0820, 0x01F6, 0x01F7, 0x01F8),
+  },
+  {	.channel		= 44,
+	.freq			= 5220, /* MHz */
+	.unk2			= 3480,
+	RADIOREGS(0x71, 0x0A, 0x02, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
+		  0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A,
+		  0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88),
+	PHYREGS(0x082C, 0x0828, 0x0824, 0x01F5, 0x01F6, 0x01F7),
+  },
+  {	.channel		= 46,
+	.freq			= 5230, /* MHz */
+	.unk2			= 3487,
+	RADIOREGS(0x71, 0x0B, 0x02, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
+		  0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A,
+		  0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88),
+	PHYREGS(0x0830, 0x082C, 0x0828, 0x01F4, 0x01F5, 0x01F6),
+  },
+  {	.channel		= 48,
+	.freq			= 5240, /* MHz */
+	.unk2			= 3493,
+	RADIOREGS(0x71, 0x0C, 0x02, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
+		  0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A,
+		  0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87),
+	PHYREGS(0x0834, 0x0830, 0x082C, 0x01F3, 0x01F4, 0x01F5),
+  },
+  {	.channel		= 50,
+	.freq			= 5250, /* MHz */
+	.unk2			= 3500,
+	RADIOREGS(0x71, 0x0D, 0x02, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
+		  0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A,
+		  0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87),
+	PHYREGS(0x0838, 0x0834, 0x0830, 0x01F2, 0x01F3, 0x01F4),
+  },
+  {	.channel		= 52,
+	.freq			= 5260, /* MHz */
+	.unk2			= 3507,
+	RADIOREGS(0x71, 0x0E, 0x02, 0x0A, 0x98, 0x01, 0x04, 0x0A,
+		  0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09,
+		  0x87, 0xAA, 0x00, 0x08, 0x09, 0x87),
+	PHYREGS(0x083C, 0x0838, 0x0834, 0x01F1, 0x01F2, 0x01F3),
+  },
+  {	.channel		= 54,
+	.freq			= 5270, /* MHz */
+	.unk2			= 3513,
+	RADIOREGS(0x71, 0x0F, 0x02, 0x0A, 0x98, 0x01, 0x04, 0x0A,
+		  0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09,
+		  0x87, 0xAA, 0x00, 0x08, 0x09, 0x87),
+	PHYREGS(0x0840, 0x083C, 0x0838, 0x01F0, 0x01F1, 0x01F2),
+  },
+  {	.channel		= 56,
+	.freq			= 5280, /* MHz */
+	.unk2			= 3520,
+	RADIOREGS(0x71, 0x10, 0x02, 0x09, 0x91, 0x01, 0x04, 0x0A,
+		  0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08,
+		  0x86, 0x99, 0x00, 0x08, 0x08, 0x86),
+	PHYREGS(0x0844, 0x0840, 0x083C, 0x01F0, 0x01F0, 0x01F1),
+  },
+  {	.channel		= 58,
+	.freq			= 5290, /* MHz */
+	.unk2			= 3527,
+	RADIOREGS(0x71, 0x11, 0x02, 0x09, 0x91, 0x01, 0x04, 0x0A,
+		  0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08,
+		  0x86, 0x99, 0x00, 0x08, 0x08, 0x86),
+	PHYREGS(0x0848, 0x0844, 0x0840, 0x01EF, 0x01F0, 0x01F0),
+  },
+  {	.channel		= 60,
+	.freq			= 5300, /* MHz */
+	.unk2			= 3533,
+	RADIOREGS(0x71, 0x12, 0x02, 0x09, 0x8A, 0x01, 0x04, 0x0A,
+		  0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07,
+		  0x85, 0x99, 0x00, 0x08, 0x07, 0x85),
+	PHYREGS(0x084C, 0x0848, 0x0844, 0x01EE, 0x01EF, 0x01F0),
+  },
+  {	.channel		= 62,
+	.freq			= 5310, /* MHz */
+	.unk2			= 3540,
+	RADIOREGS(0x71, 0x13, 0x02, 0x09, 0x8A, 0x01, 0x04, 0x0A,
+		  0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07,
+		  0x85, 0x99, 0x00, 0x08, 0x07, 0x85),
+	PHYREGS(0x0850, 0x084C, 0x0848, 0x01ED, 0x01EE, 0x01EF),
+  },
+  {	.channel		= 64,
+	.freq			= 5320, /* MHz */
+	.unk2			= 3547,
+	RADIOREGS(0x71, 0x14, 0x02, 0x09, 0x83, 0x01, 0x04, 0x0A,
+		  0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07,
+		  0x84, 0x88, 0x00, 0x07, 0x07, 0x84),
+	PHYREGS(0x0854, 0x0850, 0x084C, 0x01EC, 0x01ED, 0x01EE),
+  },
+  {	.channel		= 66,
+	.freq			= 5330, /* MHz */
+	.unk2			= 3553,
+	RADIOREGS(0x71, 0x15, 0x02, 0x09, 0x83, 0x01, 0x04, 0x0A,
+		  0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07,
+		  0x84, 0x88, 0x00, 0x07, 0x07, 0x84),
+	PHYREGS(0x0858, 0x0854, 0x0850, 0x01EB, 0x01EC, 0x01ED),
+  },
+  {	.channel		= 68,
+	.freq			= 5340, /* MHz */
+	.unk2			= 3560,
+	RADIOREGS(0x71, 0x16, 0x02, 0x08, 0x7C, 0x01, 0x04, 0x0A,
+		  0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06,
+		  0x84, 0x88, 0x00, 0x07, 0x06, 0x84),
+	PHYREGS(0x085C, 0x0858, 0x0854, 0x01EA, 0x01EB, 0x01EC),
+  },
+  {	.channel		= 70,
+	.freq			= 5350, /* MHz */
+	.unk2			= 3567,
+	RADIOREGS(0x71, 0x17, 0x02, 0x08, 0x7C, 0x01, 0x04, 0x0A,
+		  0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06,
+		  0x84, 0x88, 0x00, 0x07, 0x06, 0x84),
+	PHYREGS(0x0860, 0x085C, 0x0858, 0x01E9, 0x01EA, 0x01EB),
+  },
+  {	.channel		= 72,
+	.freq			= 5360, /* MHz */
+	.unk2			= 3573,
+	RADIOREGS(0x71, 0x18, 0x02, 0x08, 0x75, 0x01, 0x04, 0x0A,
+		  0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05,
+		  0x83, 0x77, 0x00, 0x06, 0x05, 0x83),
+	PHYREGS(0x0864, 0x0860, 0x085C, 0x01E8, 0x01E9, 0x01EA),
+  },
+  {	.channel		= 74,
+	.freq			= 5370, /* MHz */
+	.unk2			= 3580,
+	RADIOREGS(0x71, 0x19, 0x02, 0x08, 0x75, 0x01, 0x04, 0x0A,
+		  0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05,
+		  0x83, 0x77, 0x00, 0x06, 0x05, 0x83),
+	PHYREGS(0x0868, 0x0864, 0x0860, 0x01E7, 0x01E8, 0x01E9),
+  },
+  {	.channel		= 76,
+	.freq			= 5380, /* MHz */
+	.unk2			= 3587,
+	RADIOREGS(0x71, 0x1A, 0x02, 0x08, 0x6E, 0x01, 0x04, 0x0A,
+		  0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04,
+		  0x82, 0x77, 0x00, 0x06, 0x04, 0x82),
+	PHYREGS(0x086C, 0x0868, 0x0864, 0x01E6, 0x01E7, 0x01E8),
+  },
+  {	.channel		= 78,
+	.freq			= 5390, /* MHz */
+	.unk2			= 3593,
+	RADIOREGS(0x71, 0x1B, 0x02, 0x08, 0x6E, 0x01, 0x04, 0x0A,
+		  0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04,
+		  0x82, 0x77, 0x00, 0x06, 0x04, 0x82),
+	PHYREGS(0x0870, 0x086C, 0x0868, 0x01E5, 0x01E6, 0x01E7),
+  },
+  {	.channel		= 80,
+	.freq			= 5400, /* MHz */
+	.unk2			= 3600,
+	RADIOREGS(0x71, 0x1C, 0x02, 0x07, 0x67, 0x01, 0x04, 0x0A,
+		  0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04,
+		  0x81, 0x66, 0x00, 0x05, 0x04, 0x81),
+	PHYREGS(0x0874, 0x0870, 0x086C, 0x01E5, 0x01E5, 0x01E6),
+  },
+  {	.channel		= 82,
+	.freq			= 5410, /* MHz */
+	.unk2			= 3607,
+	RADIOREGS(0x71, 0x1D, 0x02, 0x07, 0x67, 0x01, 0x04, 0x0A,
+		  0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04,
+		  0x81, 0x66, 0x00, 0x05, 0x04, 0x81),
+	PHYREGS(0x0878, 0x0874, 0x0870, 0x01E4, 0x01E5, 0x01E5),
+  },
+  {	.channel		= 84,
+	.freq			= 5420, /* MHz */
+	.unk2			= 3613,
+	RADIOREGS(0x71, 0x1E, 0x02, 0x07, 0x61, 0x01, 0x04, 0x0A,
+		  0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03,
+		  0x80, 0x66, 0x00, 0x05, 0x03, 0x80),
+	PHYREGS(0x087C, 0x0878, 0x0874, 0x01E3, 0x01E4, 0x01E5),
+  },
+  {	.channel		= 86,
+	.freq			= 5430, /* MHz */
+	.unk2			= 3620,
+	RADIOREGS(0x71, 0x1F, 0x02, 0x07, 0x61, 0x01, 0x04, 0x0A,
+		  0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03,
+		  0x80, 0x66, 0x00, 0x05, 0x03, 0x80),
+	PHYREGS(0x0880, 0x087C, 0x0878, 0x01E2, 0x01E3, 0x01E4),
+  },
+  {	.channel		= 88,
+	.freq			= 5440, /* MHz */
+	.unk2			= 3627,
+	RADIOREGS(0x71, 0x20, 0x02, 0x07, 0x5A, 0x01, 0x04, 0x0A,
+		  0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02,
+		  0x80, 0x55, 0x00, 0x04, 0x02, 0x80),
+	PHYREGS(0x0884, 0x0880, 0x087C, 0x01E1, 0x01E2, 0x01E3),
+  },
+  {	.channel		= 90,
+	.freq			= 5450, /* MHz */
+	.unk2			= 3633,
+	RADIOREGS(0x71, 0x21, 0x02, 0x07, 0x5A, 0x01, 0x04, 0x0A,
+		  0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02,
+		  0x80, 0x55, 0x00, 0x04, 0x02, 0x80),
+	PHYREGS(0x0888, 0x0884, 0x0880, 0x01E0, 0x01E1, 0x01E2),
+  },
+  {	.channel		= 92,
+	.freq			= 5460, /* MHz */
+	.unk2			= 3640,
+	RADIOREGS(0x71, 0x22, 0x02, 0x06, 0x53, 0x01, 0x04, 0x0A,
+		  0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01,
+		  0x80, 0x55, 0x00, 0x04, 0x01, 0x80),
+	PHYREGS(0x088C, 0x0888, 0x0884, 0x01DF, 0x01E0, 0x01E1),
+  },
+  {	.channel		= 94,
+	.freq			= 5470, /* MHz */
+	.unk2			= 3647,
+	RADIOREGS(0x71, 0x23, 0x02, 0x06, 0x53, 0x01, 0x04, 0x0A,
+		  0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01,
+		  0x80, 0x55, 0x00, 0x04, 0x01, 0x80),
+	PHYREGS(0x0890, 0x088C, 0x0888, 0x01DE, 0x01DF, 0x01E0),
+  },
+  {	.channel		= 96,
+	.freq			= 5480, /* MHz */
+	.unk2			= 3653,
+	RADIOREGS(0x71, 0x24, 0x02, 0x06, 0x4D, 0x01, 0x04, 0x0A,
+		  0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00,
+		  0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
+	PHYREGS(0x0894, 0x0890, 0x088C, 0x01DD, 0x01DE, 0x01DF),
+  },
+  {	.channel		= 98,
+	.freq			= 5490, /* MHz */
+	.unk2			= 3660,
+	RADIOREGS(0x71, 0x25, 0x02, 0x06, 0x4D, 0x01, 0x04, 0x0A,
+		  0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00,
+		  0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
+	PHYREGS(0x0898, 0x0894, 0x0890, 0x01DD, 0x01DD, 0x01DE),
+  },
+  {	.channel		= 100,
+	.freq			= 5500, /* MHz */
+	.unk2			= 3667,
+	RADIOREGS(0x71, 0x26, 0x02, 0x06, 0x47, 0x01, 0x04, 0x0A,
+		  0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00,
+		  0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
+	PHYREGS(0x089C, 0x0898, 0x0894, 0x01DC, 0x01DD, 0x01DD),
+  },
+  {	.channel		= 102,
+	.freq			= 5510, /* MHz */
+	.unk2			= 3673,
+	RADIOREGS(0x71, 0x27, 0x02, 0x06, 0x47, 0x01, 0x04, 0x0A,
+		  0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00,
+		  0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
+	PHYREGS(0x08A0, 0x089C, 0x0898, 0x01DB, 0x01DC, 0x01DD),
+  },
+  {	.channel		= 104,
+	.freq			= 5520, /* MHz */
+	.unk2			= 3680,
+	RADIOREGS(0x71, 0x28, 0x02, 0x05, 0x40, 0x01, 0x04, 0x0A,
+		  0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
+		  0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
+	PHYREGS(0x08A4, 0x08A0, 0x089C, 0x01DA, 0x01DB, 0x01DC),
+  },
+  {	.channel		= 106,
+	.freq			= 5530, /* MHz */
+	.unk2			= 3687,
+	RADIOREGS(0x71, 0x29, 0x02, 0x05, 0x40, 0x01, 0x04, 0x0A,
+		  0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
+		  0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
+	PHYREGS(0x08A8, 0x08A4, 0x08A0, 0x01D9, 0x01DA, 0x01DB),
+  },
+  {	.channel		= 108,
+	.freq			= 5540, /* MHz */
+	.unk2			= 3693,
+	RADIOREGS(0x71, 0x2A, 0x02, 0x05, 0x3A, 0x01, 0x04, 0x0A,
+		  0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
+		  0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
+	PHYREGS(0x08AC, 0x08A8, 0x08A4, 0x01D8, 0x01D9, 0x01DA),
+  },
+  {	.channel		= 110,
+	.freq			= 5550, /* MHz */
+	.unk2			= 3700,
+	RADIOREGS(0x71, 0x2B, 0x02, 0x05, 0x3A, 0x01, 0x04, 0x0A,
+		  0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
+		  0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
+	PHYREGS(0x08B0, 0x08AC, 0x08A8, 0x01D7, 0x01D8, 0x01D9),
+  },
+  {	.channel		= 112,
+	.freq			= 5560, /* MHz */
+	.unk2			= 3707,
+	RADIOREGS(0x71, 0x2C, 0x02, 0x05, 0x34, 0x01, 0x04, 0x0A,
+		  0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
+		  0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
+	PHYREGS(0x08B4, 0x08B0, 0x08AC, 0x01D7, 0x01D7, 0x01D8),
+  },
+  {	.channel		= 114,
+	.freq			= 5570, /* MHz */
+	.unk2			= 3713,
+	RADIOREGS(0x71, 0x2D, 0x02, 0x05, 0x34, 0x01, 0x04, 0x0A,
+		  0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
+		  0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
+	PHYREGS(0x08B8, 0x08B4, 0x08B0, 0x01D6, 0x01D7, 0x01D7),
+  },
+  {	.channel		= 116,
+	.freq			= 5580, /* MHz */
+	.unk2			= 3720,
+	RADIOREGS(0x71, 0x2E, 0x02, 0x04, 0x2E, 0x01, 0x04, 0x0A,
+		  0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
+		  0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
+	PHYREGS(0x08BC, 0x08B8, 0x08B4, 0x01D5, 0x01D6, 0x01D7),
+  },
+  {	.channel		= 118,
+	.freq			= 5590, /* MHz */
+	.unk2			= 3727,
+	RADIOREGS(0x71, 0x2F, 0x02, 0x04, 0x2E, 0x01, 0x04, 0x0A,
+		  0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
+		  0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
+	PHYREGS(0x08C0, 0x08BC, 0x08B8, 0x01D4, 0x01D5, 0x01D6),
+  },
+  {	.channel		= 120,
+	.freq			= 5600, /* MHz */
+	.unk2			= 3733,
+	RADIOREGS(0x71, 0x30, 0x02, 0x04, 0x28, 0x01, 0x04, 0x0A,
+		  0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00,
+		  0x80, 0x11, 0x00, 0x01, 0x00, 0x80),
+	PHYREGS(0x08C4, 0x08C0, 0x08BC, 0x01D3, 0x01D4, 0x01D5),
+  },
+  {	.channel		= 122,
+	.freq			= 5610, /* MHz */
+	.unk2			= 3740,
+	RADIOREGS(0x71, 0x31, 0x02, 0x04, 0x28, 0x01, 0x04, 0x0A,
+		  0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00,
+		  0x80, 0x11, 0x00, 0x01, 0x00, 0x80),
+	PHYREGS(0x08C8, 0x08C4, 0x08C0, 0x01D2, 0x01D3, 0x01D4),
+  },
+  {	.channel		= 124,
+	.freq			= 5620, /* MHz */
+	.unk2			= 3747,
+	RADIOREGS(0x71, 0x32, 0x02, 0x04, 0x21, 0x01, 0x04, 0x0A,
+		  0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+		  0x80, 0x11, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x08CC, 0x08C8, 0x08C4, 0x01D2, 0x01D2, 0x01D3),
+  },
+  {	.channel		= 126,
+	.freq			= 5630, /* MHz */
+	.unk2			= 3753,
+	RADIOREGS(0x71, 0x33, 0x02, 0x04, 0x21, 0x01, 0x04, 0x0A,
+		  0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+		  0x80, 0x11, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x08D0, 0x08CC, 0x08C8, 0x01D1, 0x01D2, 0x01D2),
+  },
+  {	.channel		= 128,
+	.freq			= 5640, /* MHz */
+	.unk2			= 3760,
+	RADIOREGS(0x71, 0x34, 0x02, 0x03, 0x1C, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x08D4, 0x08D0, 0x08CC, 0x01D0, 0x01D1, 0x01D2),
+  },
+  {	.channel		= 130,
+	.freq			= 5650, /* MHz */
+	.unk2			= 3767,
+	RADIOREGS(0x71, 0x35, 0x02, 0x03, 0x1C, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x08D8, 0x08D4, 0x08D0, 0x01CF, 0x01D0, 0x01D1),
+  },
+  {	.channel		= 132,
+	.freq			= 5660, /* MHz */
+	.unk2			= 3773,
+	RADIOREGS(0x71, 0x36, 0x02, 0x03, 0x16, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x08DC, 0x08D8, 0x08D4, 0x01CE, 0x01CF, 0x01D0),
+  },
+  {	.channel		= 134,
+	.freq			= 5670, /* MHz */
+	.unk2			= 3780,
+	RADIOREGS(0x71, 0x37, 0x02, 0x03, 0x16, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x08E0, 0x08DC, 0x08D8, 0x01CE, 0x01CE, 0x01CF),
+  },
+  {	.channel		= 136,
+	.freq			= 5680, /* MHz */
+	.unk2			= 3787,
+	RADIOREGS(0x71, 0x38, 0x02, 0x03, 0x10, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x08E4, 0x08E0, 0x08DC, 0x01CD, 0x01CE, 0x01CE),
+  },
+  {	.channel		= 138,
+	.freq			= 5690, /* MHz */
+	.unk2			= 3793,
+	RADIOREGS(0x71, 0x39, 0x02, 0x03, 0x10, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x08E8, 0x08E4, 0x08E0, 0x01CC, 0x01CD, 0x01CE),
+  },
+  {	.channel		= 140,
+	.freq			= 5700, /* MHz */
+	.unk2			= 3800,
+	RADIOREGS(0x71, 0x3A, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x08EC, 0x08E8, 0x08E4, 0x01CB, 0x01CC, 0x01CD),
+  },
+  {	.channel		= 142,
+	.freq			= 5710, /* MHz */
+	.unk2			= 3807,
+	RADIOREGS(0x71, 0x3B, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x08F0, 0x08EC, 0x08E8, 0x01CA, 0x01CB, 0x01CC),
+  },
+  {	.channel		= 144,
+	.freq			= 5720, /* MHz */
+	.unk2			= 3813,
+	RADIOREGS(0x71, 0x3C, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x08F4, 0x08F0, 0x08EC, 0x01C9, 0x01CA, 0x01CB),
+  },
+  {	.channel		= 145,
+	.freq			= 5725, /* MHz */
+	.unk2			= 3817,
+	RADIOREGS(0x72, 0x79, 0x04, 0x02, 0x03, 0x01, 0x03, 0x14,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x08F6, 0x08F2, 0x08EE, 0x01C9, 0x01CA, 0x01CB),
+  },
+  {	.channel		= 146,
+	.freq			= 5730, /* MHz */
+	.unk2			= 3820,
+	RADIOREGS(0x71, 0x3D, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x08F8, 0x08F4, 0x08F0, 0x01C9, 0x01C9, 0x01CA),
+  },
+  {	.channel		= 147,
+	.freq			= 5735, /* MHz */
+	.unk2			= 3823,
+	RADIOREGS(0x72, 0x7B, 0x04, 0x02, 0x03, 0x01, 0x03, 0x14,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x08FA, 0x08F6, 0x08F2, 0x01C8, 0x01C9, 0x01CA),
+  },
+  {	.channel		= 148,
+	.freq			= 5740, /* MHz */
+	.unk2			= 3827,
+	RADIOREGS(0x71, 0x3E, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x08FC, 0x08F8, 0x08F4, 0x01C8, 0x01C9, 0x01C9),
+  },
+  {	.channel		= 149,
+	.freq			= 5745, /* MHz */
+	.unk2			= 3830,
+	RADIOREGS(0x72, 0x7D, 0x04, 0x02, 0xFE, 0x00, 0x03, 0x14,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x08FE, 0x08FA, 0x08F6, 0x01C8, 0x01C8, 0x01C9),
+  },
+  {	.channel		= 150,
+	.freq			= 5750, /* MHz */
+	.unk2			= 3833,
+	RADIOREGS(0x71, 0x3F, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0900, 0x08FC, 0x08F8, 0x01C7, 0x01C8, 0x01C9),
+  },
+  {	.channel		= 151,
+	.freq			= 5755, /* MHz */
+	.unk2			= 3837,
+	RADIOREGS(0x72, 0x7F, 0x04, 0x02, 0xFE, 0x00, 0x03, 0x14,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0902, 0x08FE, 0x08FA, 0x01C7, 0x01C8, 0x01C8),
+  },
+  {	.channel		= 152,
+	.freq			= 5760, /* MHz */
+	.unk2			= 3840,
+	RADIOREGS(0x71, 0x40, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0904, 0x0900, 0x08FC, 0x01C6, 0x01C7, 0x01C8),
+  },
+  {	.channel		= 153,
+	.freq			= 5765, /* MHz */
+	.unk2			= 3843,
+	RADIOREGS(0x72, 0x81, 0x04, 0x02, 0xF8, 0x00, 0x03, 0x14,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0906, 0x0902, 0x08FE, 0x01C6, 0x01C7, 0x01C8),
+  },
+  {	.channel		= 154,
+	.freq			= 5770, /* MHz */
+	.unk2			= 3847,
+	RADIOREGS(0x71, 0x41, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0908, 0x0904, 0x0900, 0x01C6, 0x01C6, 0x01C7),
+  },
+  {	.channel		= 155,
+	.freq			= 5775, /* MHz */
+	.unk2			= 3850,
+	RADIOREGS(0x72, 0x83, 0x04, 0x02, 0xF8, 0x00, 0x03, 0x14,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x090A, 0x0906, 0x0902, 0x01C5, 0x01C6, 0x01C7),
+  },
+  {	.channel		= 156,
+	.freq			= 5780, /* MHz */
+	.unk2			= 3853,
+	RADIOREGS(0x71, 0x42, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x090C, 0x0908, 0x0904, 0x01C5, 0x01C6, 0x01C6),
+  },
+  {	.channel		= 157,
+	.freq			= 5785, /* MHz */
+	.unk2			= 3857,
+	RADIOREGS(0x72, 0x85, 0x04, 0x02, 0xF2, 0x00, 0x03, 0x14,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x090E, 0x090A, 0x0906, 0x01C4, 0x01C5, 0x01C6),
+  },
+  {	.channel		= 158,
+	.freq			= 5790, /* MHz */
+	.unk2			= 3860,
+	RADIOREGS(0x71, 0x43, 0x02, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0910, 0x090C, 0x0908, 0x01C4, 0x01C5, 0x01C6),
+  },
+  {	.channel		= 159,
+	.freq			= 5795, /* MHz */
+	.unk2			= 3863,
+	RADIOREGS(0x72, 0x87, 0x04, 0x02, 0xF2, 0x00, 0x03, 0x14,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0912, 0x090E, 0x090A, 0x01C4, 0x01C4, 0x01C5),
+  },
+  {	.channel		= 160,
+	.freq			= 5800, /* MHz */
+	.unk2			= 3867,
+	RADIOREGS(0x71, 0x44, 0x02, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0914, 0x0910, 0x090C, 0x01C3, 0x01C4, 0x01C5),
+  },
+  {	.channel		= 161,
+	.freq			= 5805, /* MHz */
+	.unk2			= 3870,
+	RADIOREGS(0x72, 0x89, 0x04, 0x01, 0xED, 0x00, 0x03, 0x14,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0916, 0x0912, 0x090E, 0x01C3, 0x01C4, 0x01C4),
+  },
+  {	.channel		= 162,
+	.freq			= 5810, /* MHz */
+	.unk2			= 3873,
+	RADIOREGS(0x71, 0x45, 0x02, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0918, 0x0914, 0x0910, 0x01C2, 0x01C3, 0x01C4),
+  },
+  {	.channel		= 163,
+	.freq			= 5815, /* MHz */
+	.unk2			= 3877,
+	RADIOREGS(0x72, 0x8B, 0x04, 0x01, 0xED, 0x00, 0x03, 0x14,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x091A, 0x0916, 0x0912, 0x01C2, 0x01C3, 0x01C4),
+  },
+  {	.channel		= 164,
+	.freq			= 5820, /* MHz */
+	.unk2			= 3880,
+	RADIOREGS(0x71, 0x46, 0x02, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x091C, 0x0918, 0x0914, 0x01C2, 0x01C2, 0x01C3),
+  },
+  {	.channel		= 165,
+	.freq			= 5825, /* MHz */
+	.unk2			= 3883,
+	RADIOREGS(0x72, 0x8D, 0x04, 0x01, 0xED, 0x00, 0x03, 0x14,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x091E, 0x091A, 0x0916, 0x01C1, 0x01C2, 0x01C3),
+  },
+  {	.channel		= 166,
+	.freq			= 5830, /* MHz */
+	.unk2			= 3887,
+	RADIOREGS(0x71, 0x47, 0x02, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0920, 0x091C, 0x0918, 0x01C1, 0x01C2, 0x01C2),
+  },
+  {	.channel		= 168,
+	.freq			= 5840, /* MHz */
+	.unk2			= 3893,
+	RADIOREGS(0x71, 0x48, 0x02, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0924, 0x0920, 0x091C, 0x01C0, 0x01C1, 0x01C2),
+  },
+  {	.channel		= 170,
+	.freq			= 5850, /* MHz */
+	.unk2			= 3900,
+	RADIOREGS(0x71, 0x49, 0x02, 0x01, 0xE0, 0x00, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0928, 0x0924, 0x0920, 0x01BF, 0x01C0, 0x01C1),
+  },
+  {	.channel		= 172,
+	.freq			= 5860, /* MHz */
+	.unk2			= 3907,
+	RADIOREGS(0x71, 0x4A, 0x02, 0x01, 0xDE, 0x00, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x092C, 0x0928, 0x0924, 0x01BF, 0x01BF, 0x01C0),
+  },
+  {	.channel		= 174,
+	.freq			= 5870, /* MHz */
+	.unk2			= 3913,
+	RADIOREGS(0x71, 0x4B, 0x02, 0x00, 0xDB, 0x00, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0930, 0x092C, 0x0928, 0x01BE, 0x01BF, 0x01BF),
+  },
+  {	.channel		= 176,
+	.freq			= 5880, /* MHz */
+	.unk2			= 3920,
+	RADIOREGS(0x71, 0x4C, 0x02, 0x00, 0xD8, 0x00, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0934, 0x0930, 0x092C, 0x01BD, 0x01BE, 0x01BF),
+  },
+  {	.channel		= 178,
+	.freq			= 5890, /* MHz */
+	.unk2			= 3927,
+	RADIOREGS(0x71, 0x4D, 0x02, 0x00, 0xD6, 0x00, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0938, 0x0934, 0x0930, 0x01BC, 0x01BD, 0x01BE),
+  },
+  {	.channel		= 180,
+	.freq			= 5900, /* MHz */
+	.unk2			= 3933,
+	RADIOREGS(0x71, 0x4E, 0x02, 0x00, 0xD3, 0x00, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x093C, 0x0938, 0x0934, 0x01BC, 0x01BC, 0x01BD),
+  },
+  {	.channel		= 182,
+	.freq			= 5910, /* MHz */
+	.unk2			= 3940,
+	RADIOREGS(0x71, 0x4F, 0x02, 0x00, 0xD6, 0x00, 0x04, 0x0A,
+		  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		  0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+	PHYREGS(0x0940, 0x093C, 0x0938, 0x01BB, 0x01BC, 0x01BC),
+  },
+  {	.channel		= 1,
+	.freq			= 2412, /* MHz */
+	.unk2			= 3216,
+	RADIOREGS(0x73, 0x6C, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0D, 0x0C,
+		  0x80, 0xFF, 0x88, 0x0D, 0x0C, 0x80),
+	PHYREGS(0x03C9, 0x03C5, 0x03C1, 0x043A, 0x043F, 0x0443),
+  },
+  {	.channel		= 2,
+	.freq			= 2417, /* MHz */
+	.unk2			= 3223,
+	RADIOREGS(0x73, 0x71, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0B,
+		  0x80, 0xFF, 0x88, 0x0C, 0x0B, 0x80),
+	PHYREGS(0x03CB, 0x03C7, 0x03C3, 0x0438, 0x043D, 0x0441),
+  },
+  {	.channel		= 3,
+	.freq			= 2422, /* MHz */
+	.unk2			= 3229,
+	RADIOREGS(0x73, 0x76, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A,
+		  0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80),
+	PHYREGS(0x03CD, 0x03C9, 0x03C5, 0x0436, 0x043A, 0x043F),
+  },
+  {	.channel		= 4,
+	.freq			= 2427, /* MHz */
+	.unk2			= 3236,
+	RADIOREGS(0x73, 0x7B, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A,
+		  0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80),
+	PHYREGS(0x03CF, 0x03CB, 0x03C7, 0x0434, 0x0438, 0x043D),
+  },
+  {	.channel		= 5,
+	.freq			= 2432, /* MHz */
+	.unk2			= 3243,
+	RADIOREGS(0x73, 0x80, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x09,
+		  0x80, 0xFF, 0x88, 0x0C, 0x09, 0x80),
+	PHYREGS(0x03D1, 0x03CD, 0x03C9, 0x0431, 0x0436, 0x043A),
+  },
+  {	.channel		= 6,
+	.freq			= 2437, /* MHz */
+	.unk2			= 3249,
+	RADIOREGS(0x73, 0x85, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0B, 0x08,
+		  0x80, 0xFF, 0x88, 0x0B, 0x08, 0x80),
+	PHYREGS(0x03D3, 0x03CF, 0x03CB, 0x042F, 0x0434, 0x0438),
+  },
+  {	.channel		= 7,
+	.freq			= 2442, /* MHz */
+	.unk2			= 3256,
+	RADIOREGS(0x73, 0x8A, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x07,
+		  0x80, 0xFF, 0x88, 0x0A, 0x07, 0x80),
+	PHYREGS(0x03D5, 0x03D1, 0x03CD, 0x042D, 0x0431, 0x0436),
+  },
+  {	.channel		= 8,
+	.freq			= 2447, /* MHz */
+	.unk2			= 3263,
+	RADIOREGS(0x73, 0x8F, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x06,
+		  0x80, 0xFF, 0x88, 0x0A, 0x06, 0x80),
+	PHYREGS(0x03D7, 0x03D3, 0x03CF, 0x042B, 0x042F, 0x0434),
+  },
+  {	.channel		= 9,
+	.freq			= 2452, /* MHz */
+	.unk2			= 3269,
+	RADIOREGS(0x73, 0x94, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x09, 0x06,
+		  0x80, 0xFF, 0x88, 0x09, 0x06, 0x80),
+	PHYREGS(0x03D9, 0x03D5, 0x03D1, 0x0429, 0x042D, 0x0431),
+  },
+  {	.channel		= 10,
+	.freq			= 2457, /* MHz */
+	.unk2			= 3276,
+	RADIOREGS(0x73, 0x99, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x05,
+		  0x80, 0xFF, 0x88, 0x08, 0x05, 0x80),
+	PHYREGS(0x03DB, 0x03D7, 0x03D3, 0x0427, 0x042B, 0x042F),
+  },
+  {	.channel		= 11,
+	.freq			= 2462, /* MHz */
+	.unk2			= 3283,
+	RADIOREGS(0x73, 0x9E, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x04,
+		  0x80, 0xFF, 0x88, 0x08, 0x04, 0x80),
+	PHYREGS(0x03DD, 0x03D9, 0x03D5, 0x0424, 0x0429, 0x042D),
+  },
+  {	.channel		= 12,
+	.freq			= 2467, /* MHz */
+	.unk2			= 3289,
+	RADIOREGS(0x73, 0xA3, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x03,
+		  0x80, 0xFF, 0x88, 0x08, 0x03, 0x80),
+	PHYREGS(0x03DF, 0x03DB, 0x03D7, 0x0422, 0x0427, 0x042B),
+  },
+  {	.channel		= 13,
+	.freq			= 2472, /* MHz */
+	.unk2			= 3296,
+	RADIOREGS(0x73, 0xA8, 0x09, 0x0F, 0x00, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x03,
+		  0x80, 0xFF, 0x88, 0x07, 0x03, 0x80),
+	PHYREGS(0x03E1, 0x03DD, 0x03D9, 0x0420, 0x0424, 0x0429),
+  },
+  {	.channel		= 14,
+	.freq			= 2484, /* MHz */
+	.unk2			= 3312,
+	RADIOREGS(0x73, 0xB4, 0x09, 0x0F, 0xFF, 0x01, 0x07, 0x15,
+		  0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x01,
+		  0x80, 0xFF, 0x88, 0x07, 0x01, 0x80),
+	PHYREGS(0x03E6, 0x03E2, 0x03DE, 0x041B, 0x041F, 0x0424),
+  },
+};
+
+void b2055_upload_inittab(struct b43_wldev *dev,
+			  bool ghz5, bool ignore_uploadflag)
+{
+	const struct b2055_inittab_entry *e;
+	unsigned int i, writes = 0;
+	u16 value;
+
+	for (i = 0; i < ARRAY_SIZE(b2055_inittab); i++) {
+		e = &(b2055_inittab[i]);
+		if (!(e->flags & B2055_INITTAB_ENTRY_OK))
+			continue;
+		if ((e->flags & B2055_INITTAB_UPLOAD) || ignore_uploadflag) {
+			if (ghz5)
+				value = e->ghz5;
+			else
+				value = e->ghz2;
+			b43_radio_write16(dev, i, value);
+			if (++writes % 4 == 0)
+				b43_read32(dev, B43_MMIO_MACCTL); /* flush */
+		}
+	}
+}
+
+const struct b43_nphy_channeltab_entry_rev2 *
+b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel)
+{
+	const struct b43_nphy_channeltab_entry_rev2 *e;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab_rev2); i++) {
+		e = &(b43_nphy_channeltab_rev2[i]);
+		if (e->channel == channel)
+			return e;
+	}
+
+	return NULL;
+}
diff --git a/drivers/net/wireless/broadcom/b43/radio_2055.h b/drivers/net/wireless/broadcom/b43/radio_2055.h
new file mode 100644
index 0000000..ad7271c
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/radio_2055.h
@@ -0,0 +1,260 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_RADIO_2055_H_
+#define B43_RADIO_2055_H_
+
+#include <linux/types.h>
+
+#include "tables_nphy.h"
+
+#define B2055_GEN_SPARE			0x00 /* GEN spare */
+#define B2055_SP_PINPD			0x02 /* SP PIN PD */
+#define B2055_C1_SP_RSSI		0x03 /* SP RSSI Core 1 */
+#define B2055_C1_SP_PDMISC		0x04 /* SP PD MISC Core 1 */
+#define B2055_C2_SP_RSSI		0x05 /* SP RSSI Core 2 */
+#define B2055_C2_SP_PDMISC		0x06 /* SP PD MISC Core 2 */
+#define B2055_C1_SP_RXGC1		0x07 /* SP RX GC1 Core 1 */
+#define B2055_C1_SP_RXGC2		0x08 /* SP RX GC2 Core 1 */
+#define B2055_C2_SP_RXGC1		0x09 /* SP RX GC1 Core 2 */
+#define B2055_C2_SP_RXGC2		0x0A /* SP RX GC2 Core 2 */
+#define B2055_C1_SP_LPFBWSEL		0x0B /* SP LPF BW select Core 1 */
+#define B2055_C2_SP_LPFBWSEL		0x0C /* SP LPF BW select Core 2 */
+#define B2055_C1_SP_TXGC1		0x0D /* SP TX GC1 Core 1 */
+#define B2055_C1_SP_TXGC2		0x0E /* SP TX GC2 Core 1 */
+#define B2055_C2_SP_TXGC1		0x0F /* SP TX GC1 Core 2 */
+#define B2055_C2_SP_TXGC2		0x10 /* SP TX GC2 Core 2 */
+#define B2055_MASTER1			0x11 /* Master control 1 */
+#define B2055_MASTER2			0x12 /* Master control 2 */
+#define B2055_PD_LGEN			0x13 /* PD LGEN */
+#define B2055_PD_PLLTS			0x14 /* PD PLL TS */
+#define B2055_C1_PD_LGBUF		0x15 /* PD Core 1 LGBUF */
+#define B2055_C1_PD_TX			0x16 /* PD Core 1 TX */
+#define B2055_C1_PD_RXTX		0x17 /* PD Core 1 RXTX */
+#define B2055_C1_PD_RSSIMISC		0x18 /* PD Core 1 RSSI MISC */
+#define B2055_C2_PD_LGBUF		0x19 /* PD Core 2 LGBUF */
+#define B2055_C2_PD_TX			0x1A /* PD Core 2 TX */
+#define B2055_C2_PD_RXTX		0x1B /* PD Core 2 RXTX */
+#define B2055_C2_PD_RSSIMISC		0x1C /* PD Core 2 RSSI MISC */
+#define B2055_PWRDET_LGEN		0x1D /* PWRDET LGEN */
+#define B2055_C1_PWRDET_LGBUF		0x1E /* PWRDET LGBUF Core 1 */
+#define B2055_C1_PWRDET_RXTX		0x1F /* PWRDET RXTX Core 1 */
+#define B2055_C2_PWRDET_LGBUF		0x20 /* PWRDET LGBUF Core 2 */
+#define B2055_C2_PWRDET_RXTX		0x21 /* PWRDET RXTX Core 2 */
+#define B2055_RRCCAL_CS			0x22 /* RRCCAL Control spare */
+#define B2055_RRCCAL_NOPTSEL		0x23 /* RRCCAL N OPT SEL */
+#define B2055_CAL_MISC			0x24 /* CAL MISC */
+#define B2055_CAL_COUT			0x25 /* CAL Counter out */
+#define B2055_CAL_COUT2			0x26 /* CAL Counter out 2 */
+#define B2055_CAL_CVARCTL		0x27 /* CAL CVAR Control */
+#define B2055_CAL_RVARCTL		0x28 /* CAL RVAR Control */
+#define B2055_CAL_LPOCTL		0x29 /* CAL LPO Control */
+#define B2055_CAL_TS			0x2A /* CAL TS */
+#define B2055_CAL_RCCALRTS		0x2B /* CAL RCCAL READ TS */
+#define B2055_CAL_RCALRTS		0x2C /* CAL RCAL READ TS */
+#define B2055_PADDRV			0x2D /* PAD driver */
+#define B2055_XOCTL1			0x2E /* XO Control 1 */
+#define B2055_XOCTL2			0x2F /* XO Control 2 */
+#define B2055_XOREGUL			0x30 /* XO Regulator */
+#define B2055_XOMISC			0x31 /* XO misc */
+#define B2055_PLL_LFC1			0x32 /* PLL LF C1 */
+#define B2055_PLL_CALVTH		0x33 /* PLL CAL VTH */
+#define B2055_PLL_LFC2			0x34 /* PLL LF C2 */
+#define B2055_PLL_REF			0x35 /* PLL reference */
+#define B2055_PLL_LFR1			0x36 /* PLL LF R1 */
+#define B2055_PLL_PFDCP			0x37 /* PLL PFD CP */
+#define B2055_PLL_IDAC_CPOPAMP		0x38 /* PLL IDAC CPOPAMP */
+#define B2055_PLL_CPREG			0x39 /* PLL CP Regulator */
+#define B2055_PLL_RCAL			0x3A /* PLL RCAL */
+#define B2055_RF_PLLMOD0		0x3B /* RF PLL MOD0 */
+#define B2055_RF_PLLMOD1		0x3C /* RF PLL MOD1 */
+#define B2055_RF_MMDIDAC1		0x3D /* RF MMD IDAC 1 */
+#define B2055_RF_MMDIDAC0		0x3E /* RF MMD IDAC 0 */
+#define B2055_RF_MMDSP			0x3F /* RF MMD spare */
+#define B2055_VCO_CAL1			0x40 /* VCO cal 1 */
+#define B2055_VCO_CAL2			0x41 /* VCO cal 2 */
+#define B2055_VCO_CAL3			0x42 /* VCO cal 3 */
+#define B2055_VCO_CAL4			0x43 /* VCO cal 4 */
+#define B2055_VCO_CAL5			0x44 /* VCO cal 5 */
+#define B2055_VCO_CAL6			0x45 /* VCO cal 6 */
+#define B2055_VCO_CAL7			0x46 /* VCO cal 7 */
+#define B2055_VCO_CAL8			0x47 /* VCO cal 8 */
+#define B2055_VCO_CAL9			0x48 /* VCO cal 9 */
+#define B2055_VCO_CAL10			0x49 /* VCO cal 10 */
+#define B2055_VCO_CAL11			0x4A /* VCO cal 11 */
+#define B2055_VCO_CAL12			0x4B /* VCO cal 12 */
+#define B2055_VCO_CAL13			0x4C /* VCO cal 13 */
+#define B2055_VCO_CAL14			0x4D /* VCO cal 14 */
+#define B2055_VCO_CAL15			0x4E /* VCO cal 15 */
+#define B2055_VCO_CAL16			0x4F /* VCO cal 16 */
+#define B2055_VCO_KVCO			0x50 /* VCO KVCO */
+#define B2055_VCO_CAPTAIL		0x51 /* VCO CAP TAIL */
+#define B2055_VCO_IDACVCO		0x52 /* VCO IDAC VCO */
+#define B2055_VCO_REG			0x53 /* VCO Regulator */
+#define B2055_PLL_RFVTH			0x54 /* PLL RF VTH */
+#define B2055_LGBUF_CENBUF		0x55 /* LGBUF CEN BUF */
+#define B2055_LGEN_TUNE1		0x56 /* LGEN tune 1 */
+#define B2055_LGEN_TUNE2		0x57 /* LGEN tune 2 */
+#define B2055_LGEN_IDAC1		0x58 /* LGEN IDAC 1 */
+#define B2055_LGEN_IDAC2		0x59 /* LGEN IDAC 2 */
+#define B2055_LGEN_BIASC		0x5A /* LGEN BIAS counter */
+#define B2055_LGEN_BIASIDAC		0x5B /* LGEN BIAS IDAC */
+#define B2055_LGEN_RCAL			0x5C /* LGEN RCAL */
+#define B2055_LGEN_DIV			0x5D /* LGEN div */
+#define B2055_LGEN_SPARE2		0x5E /* LGEN spare 2 */
+#define B2055_C1_LGBUF_ATUNE		0x5F /* Core 1 LGBUF A tune */
+#define B2055_C1_LGBUF_GTUNE		0x60 /* Core 1 LGBUF G tune */
+#define B2055_C1_LGBUF_DIV		0x61 /* Core 1 LGBUF div */
+#define B2055_C1_LGBUF_AIDAC		0x62 /* Core 1 LGBUF A IDAC */
+#define B2055_C1_LGBUF_GIDAC		0x63 /* Core 1 LGBUF G IDAC */
+#define B2055_C1_LGBUF_IDACFO		0x64 /* Core 1 LGBUF IDAC filter override */
+#define B2055_C1_LGBUF_SPARE		0x65 /* Core 1 LGBUF spare */
+#define B2055_C1_RX_RFSPC1		0x66 /* Core 1 RX RF SPC1 */
+#define B2055_C1_RX_RFR1		0x67 /* Core 1 RX RF reg 1 */
+#define B2055_C1_RX_RFR2		0x68 /* Core 1 RX RF reg 2 */
+#define B2055_C1_RX_RFRCAL		0x69 /* Core 1 RX RF RCAL */
+#define B2055_C1_RX_BB_BLCMP		0x6A /* Core 1 RX Baseband BUFI LPF CMP */
+#define B2055_C1_RX_BB_LPF		0x6B /* Core 1 RX Baseband LPF */
+#define B2055_C1_RX_BB_MIDACHP		0x6C /* Core 1 RX Baseband MIDAC High-pass */
+#define B2055_C1_RX_BB_VGA1IDAC		0x6D /* Core 1 RX Baseband VGA1 IDAC */
+#define B2055_C1_RX_BB_VGA2IDAC		0x6E /* Core 1 RX Baseband VGA2 IDAC */
+#define B2055_C1_RX_BB_VGA3IDAC		0x6F /* Core 1 RX Baseband VGA3 IDAC */
+#define B2055_C1_RX_BB_BUFOCTL		0x70 /* Core 1 RX Baseband BUFO Control */
+#define B2055_C1_RX_BB_RCCALCTL		0x71 /* Core 1 RX Baseband RCCAL Control */
+#define B2055_C1_RX_BB_RSSICTL1		0x72 /* Core 1 RX Baseband RSSI Control 1 */
+#define B2055_C1_RX_BB_RSSICTL2		0x73 /* Core 1 RX Baseband RSSI Control 2 */
+#define B2055_C1_RX_BB_RSSICTL3		0x74 /* Core 1 RX Baseband RSSI Control 3 */
+#define B2055_C1_RX_BB_RSSICTL4		0x75 /* Core 1 RX Baseband RSSI Control 4 */
+#define B2055_C1_RX_BB_RSSICTL5		0x76 /* Core 1 RX Baseband RSSI Control 5 */
+#define B2055_C1_RX_BB_REG		0x77 /* Core 1 RX Baseband Regulator */
+#define B2055_C1_RX_BB_SPARE1		0x78 /* Core 1 RX Baseband spare 1 */
+#define B2055_C1_RX_TXBBRCAL		0x79 /* Core 1 RX TX BB RCAL */
+#define B2055_C1_TX_RF_SPGA		0x7A /* Core 1 TX RF SGM PGA */
+#define B2055_C1_TX_RF_SPAD		0x7B /* Core 1 TX RF SGM PAD */
+#define B2055_C1_TX_RF_CNTPGA1		0x7C /* Core 1 TX RF counter PGA 1 */
+#define B2055_C1_TX_RF_CNTPAD1		0x7D /* Core 1 TX RF counter PAD 1 */
+#define B2055_C1_TX_RF_PGAIDAC		0x7E /* Core 1 TX RF PGA IDAC */
+#define B2055_C1_TX_PGAPADTN		0x7F /* Core 1 TX PGA PAD TN */
+#define B2055_C1_TX_PADIDAC1		0x80 /* Core 1 TX PAD IDAC 1 */
+#define B2055_C1_TX_PADIDAC2		0x81 /* Core 1 TX PAD IDAC 2 */
+#define B2055_C1_TX_MXBGTRIM		0x82 /* Core 1 TX MX B/G TRIM */
+#define B2055_C1_TX_RF_RCAL		0x83 /* Core 1 TX RF RCAL */
+#define B2055_C1_TX_RF_PADTSSI1		0x84 /* Core 1 TX RF PAD TSSI1 */
+#define B2055_C1_TX_RF_PADTSSI2		0x85 /* Core 1 TX RF PAD TSSI2 */
+#define B2055_C1_TX_RF_SPARE		0x86 /* Core 1 TX RF spare */
+#define B2055_C1_TX_RF_IQCAL1		0x87 /* Core 1 TX RF I/Q CAL 1 */
+#define B2055_C1_TX_RF_IQCAL2		0x88 /* Core 1 TX RF I/Q CAL 2 */
+#define B2055_C1_TXBB_RCCAL		0x89 /* Core 1 TXBB RC CAL Control */
+#define B2055_C1_TXBB_LPF1		0x8A /* Core 1 TXBB LPF 1 */
+#define B2055_C1_TX_VOSCNCL		0x8B /* Core 1 TX VOS CNCL */
+#define B2055_C1_TX_LPF_MXGMIDAC	0x8C /* Core 1 TX LPF MXGM IDAC */
+#define B2055_C1_TX_BB_MXGM		0x8D /* Core 1 TX BB MXGM */
+#define B2055_C2_LGBUF_ATUNE		0x8E /* Core 2 LGBUF A tune */
+#define B2055_C2_LGBUF_GTUNE		0x8F /* Core 2 LGBUF G tune */
+#define B2055_C2_LGBUF_DIV		0x90 /* Core 2 LGBUF div */
+#define B2055_C2_LGBUF_AIDAC		0x91 /* Core 2 LGBUF A IDAC */
+#define B2055_C2_LGBUF_GIDAC		0x92 /* Core 2 LGBUF G IDAC */
+#define B2055_C2_LGBUF_IDACFO		0x93 /* Core 2 LGBUF IDAC filter override */
+#define B2055_C2_LGBUF_SPARE		0x94 /* Core 2 LGBUF spare */
+#define B2055_C2_RX_RFSPC1		0x95 /* Core 2 RX RF SPC1 */
+#define B2055_C2_RX_RFR1		0x96 /* Core 2 RX RF reg 1 */
+#define B2055_C2_RX_RFR2		0x97 /* Core 2 RX RF reg 2 */
+#define B2055_C2_RX_RFRCAL		0x98 /* Core 2 RX RF RCAL */
+#define B2055_C2_RX_BB_BLCMP		0x99 /* Core 2 RX Baseband BUFI LPF CMP */
+#define B2055_C2_RX_BB_LPF		0x9A /* Core 2 RX Baseband LPF */
+#define B2055_C2_RX_BB_MIDACHP		0x9B /* Core 2 RX Baseband MIDAC High-pass */
+#define B2055_C2_RX_BB_VGA1IDAC		0x9C /* Core 2 RX Baseband VGA1 IDAC */
+#define B2055_C2_RX_BB_VGA2IDAC		0x9D /* Core 2 RX Baseband VGA2 IDAC */
+#define B2055_C2_RX_BB_VGA3IDAC		0x9E /* Core 2 RX Baseband VGA3 IDAC */
+#define B2055_C2_RX_BB_BUFOCTL		0x9F /* Core 2 RX Baseband BUFO Control */
+#define B2055_C2_RX_BB_RCCALCTL		0xA0 /* Core 2 RX Baseband RCCAL Control */
+#define B2055_C2_RX_BB_RSSICTL1		0xA1 /* Core 2 RX Baseband RSSI Control 1 */
+#define B2055_C2_RX_BB_RSSICTL2		0xA2 /* Core 2 RX Baseband RSSI Control 2 */
+#define B2055_C2_RX_BB_RSSICTL3		0xA3 /* Core 2 RX Baseband RSSI Control 3 */
+#define B2055_C2_RX_BB_RSSICTL4		0xA4 /* Core 2 RX Baseband RSSI Control 4 */
+#define B2055_C2_RX_BB_RSSICTL5		0xA5 /* Core 2 RX Baseband RSSI Control 5 */
+#define B2055_C2_RX_BB_REG		0xA6 /* Core 2 RX Baseband Regulator */
+#define B2055_C2_RX_BB_SPARE1		0xA7 /* Core 2 RX Baseband spare 1 */
+#define B2055_C2_RX_TXBBRCAL		0xA8 /* Core 2 RX TX BB RCAL */
+#define B2055_C2_TX_RF_SPGA		0xA9 /* Core 2 TX RF SGM PGA */
+#define B2055_C2_TX_RF_SPAD		0xAA /* Core 2 TX RF SGM PAD */
+#define B2055_C2_TX_RF_CNTPGA1		0xAB /* Core 2 TX RF counter PGA 1 */
+#define B2055_C2_TX_RF_CNTPAD1		0xAC /* Core 2 TX RF counter PAD 1 */
+#define B2055_C2_TX_RF_PGAIDAC		0xAD /* Core 2 TX RF PGA IDAC */
+#define B2055_C2_TX_PGAPADTN		0xAE /* Core 2 TX PGA PAD TN */
+#define B2055_C2_TX_PADIDAC1		0xAF /* Core 2 TX PAD IDAC 1 */
+#define B2055_C2_TX_PADIDAC2		0xB0 /* Core 2 TX PAD IDAC 2 */
+#define B2055_C2_TX_MXBGTRIM		0xB1 /* Core 2 TX MX B/G TRIM */
+#define B2055_C2_TX_RF_RCAL		0xB2 /* Core 2 TX RF RCAL */
+#define B2055_C2_TX_RF_PADTSSI1		0xB3 /* Core 2 TX RF PAD TSSI1 */
+#define B2055_C2_TX_RF_PADTSSI2		0xB4 /* Core 2 TX RF PAD TSSI2 */
+#define B2055_C2_TX_RF_SPARE		0xB5 /* Core 2 TX RF spare */
+#define B2055_C2_TX_RF_IQCAL1		0xB6 /* Core 2 TX RF I/Q CAL 1 */
+#define B2055_C2_TX_RF_IQCAL2		0xB7 /* Core 2 TX RF I/Q CAL 2 */
+#define B2055_C2_TXBB_RCCAL		0xB8 /* Core 2 TXBB RC CAL Control */
+#define B2055_C2_TXBB_LPF1		0xB9 /* Core 2 TXBB LPF 1 */
+#define B2055_C2_TX_VOSCNCL		0xBA /* Core 2 TX VOS CNCL */
+#define B2055_C2_TX_LPF_MXGMIDAC	0xBB /* Core 2 TX LPF MXGM IDAC */
+#define B2055_C2_TX_BB_MXGM		0xBC /* Core 2 TX BB MXGM */
+#define B2055_PRG_GCHP21		0xBD /* PRG GC HPVGA23 21 */
+#define B2055_PRG_GCHP22		0xBE /* PRG GC HPVGA23 22 */
+#define B2055_PRG_GCHP23		0xBF /* PRG GC HPVGA23 23 */
+#define B2055_PRG_GCHP24		0xC0 /* PRG GC HPVGA23 24 */
+#define B2055_PRG_GCHP25		0xC1 /* PRG GC HPVGA23 25 */
+#define B2055_PRG_GCHP26		0xC2 /* PRG GC HPVGA23 26 */
+#define B2055_PRG_GCHP27		0xC3 /* PRG GC HPVGA23 27 */
+#define B2055_PRG_GCHP28		0xC4 /* PRG GC HPVGA23 28 */
+#define B2055_PRG_GCHP29		0xC5 /* PRG GC HPVGA23 29 */
+#define B2055_PRG_GCHP30		0xC6 /* PRG GC HPVGA23 30 */
+#define B2055_C1_LNA_GAINBST		0xCD /* Core 1 LNA GAINBST */
+#define B2055_C1_B0NB_RSSIVCM		0xD2 /* Core 1 B0 narrow-band RSSI VCM */
+#define B2055_C1_GENSPARE2		0xD6 /* Core 1 GEN spare 2 */
+#define B2055_C2_LNA_GAINBST		0xD9 /* Core 2 LNA GAINBST */
+#define B2055_C2_B0NB_RSSIVCM		0xDE /* Core 2 B0 narrow-band RSSI VCM */
+#define B2055_C2_GENSPARE2		0xE2 /* Core 2 GEN spare 2 */
+
+struct b43_nphy_channeltab_entry_rev2 {
+	/* The channel number */
+	u8 channel;
+	/* The channel frequency in MHz */
+	u16 freq;
+	/* An unknown value */
+	u16 unk2;
+	/* Radio register values on channelswitch */
+	u8 radio_pll_ref;
+	u8 radio_rf_pllmod0;
+	u8 radio_rf_pllmod1;
+	u8 radio_vco_captail;
+	u8 radio_vco_cal1;
+	u8 radio_vco_cal2;
+	u8 radio_pll_lfc1;
+	u8 radio_pll_lfr1;
+	u8 radio_pll_lfc2;
+	u8 radio_lgbuf_cenbuf;
+	u8 radio_lgen_tune1;
+	u8 radio_lgen_tune2;
+	u8 radio_c1_lgbuf_atune;
+	u8 radio_c1_lgbuf_gtune;
+	u8 radio_c1_rx_rfr1;
+	u8 radio_c1_tx_pgapadtn;
+	u8 radio_c1_tx_mxbgtrim;
+	u8 radio_c2_lgbuf_atune;
+	u8 radio_c2_lgbuf_gtune;
+	u8 radio_c2_rx_rfr1;
+	u8 radio_c2_tx_pgapadtn;
+	u8 radio_c2_tx_mxbgtrim;
+	/* PHY register values on channelswitch */
+	struct b43_phy_n_sfo_cfg phy_regs;
+};
+
+/* Upload the default register value table.
+ * If "ghz5" is true, we upload the 5Ghz table. Otherwise the 2.4Ghz
+ * table is uploaded. If "ignore_uploadflag" is true, we upload any value
+ * and ignore the "UPLOAD" flag. */
+void b2055_upload_inittab(struct b43_wldev *dev,
+			  bool ghz5, bool ignore_uploadflag);
+
+/* Get the NPHY Channel Switch Table entry for a channel.
+ * Returns NULL on failure to find an entry. */
+const struct b43_nphy_channeltab_entry_rev2 *
+b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel);
+
+#endif /* B43_RADIO_2055_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/radio_2056.c b/drivers/net/wireless/broadcom/b43/radio_2056.c
new file mode 100644
index 0000000..2ce2560
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/radio_2056.c
@@ -0,0 +1,10318 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11n 2056 radio device data tables
+
+  Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
+
+  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 "radio_2056.h"
+#include "phy_common.h"
+
+struct b2056_inittab_entry {
+	/* Value to write if we use the 5GHz band. */
+	u16 ghz5;
+	/* Value to write if we use the 2.4GHz band. */
+	u16 ghz2;
+	/* Flags */
+	u8 flags;
+};
+#define B2056_INITTAB_ENTRY_OK	0x01
+#define B2056_INITTAB_UPLOAD	0x02
+#define UPLOAD		.flags = B2056_INITTAB_ENTRY_OK | B2056_INITTAB_UPLOAD
+#define NOUPLOAD	.flags = B2056_INITTAB_ENTRY_OK
+
+struct b2056_inittabs_pts {
+	const struct b2056_inittab_entry *syn;
+	unsigned int syn_length;
+	const struct b2056_inittab_entry *tx;
+	unsigned int tx_length;
+	const struct b2056_inittab_entry *rx;
+	unsigned int rx_length;
+};
+
+static const struct b2056_inittab_entry b2056_inittab_phy_rev3_syn[] = {
+	[B2056_SYN_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_PU]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_TXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXHPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_MASTER]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_RCAL]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_AFEREG]		= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSE]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSEIDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSERCAL]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LPO]			= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_STATUS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_CODE_OUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL0]		= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL1]		= { .ghz5 = 0x001f, .ghz2 = 0x001f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL2]		= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL3]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL11]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST1]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST2]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST3]		= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+	[B2056_SYN_PLL_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL1]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL3]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL5]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL6]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_REFDIV]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_PFD]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_CP1]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_CP2]		= { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+	[B2056_SYN_PLL_CP3]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER1]	= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER2]	= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER3]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER4]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER5]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD1]		= { .ghz5 = 0x001c, .ghz2 = 0x001c, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD2]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO1]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO2]		= { .ghz5 = 0x00f7, .ghz2 = 0x00f7, UPLOAD, },
+	[B2056_SYN_PLL_MONITOR1]	= { .ghz5 = 0x00b4, .ghz2 = 0x00b4, NOUPLOAD, },
+	[B2056_SYN_PLL_MONITOR2]	= { .ghz5 = 0x00d2, .ghz2 = 0x00d2, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL4]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL5]		= { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL6]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL7]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL8]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL9]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL11]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL12]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+	[B2056_SYN_PLL_VCOCAL13]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_SYN_PLL_VREG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU2]		= { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU8]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RCCR1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF1]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER1]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER2]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF1]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGENBUF2]		= { .ghz5 = 0x008f, .ghz2 = 0x008f, UPLOAD, },
+	[B2056_SYN_LOGEN_BUF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF4]		= { .ghz5 = 0x00cc, .ghz2 = 0x00cc, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV1]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV2]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV3]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLOUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_CALEN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PEAKDET1]	= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2_OVRVAL]= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL_WAITCNT]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_VALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_phy_rev3_tx[] = {
+	[B2056_TX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_GAIN_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_I]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_Q]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_I]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_Q]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER1]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RXIQCAL_TXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_VCM_HG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_IQCAL_IDAC]		= { .ghz5 = 0x0037, .ghz2 = 0x0037, NOUPLOAD, },
+	[B2056_TX_TSSI_VCM]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_AMP_DET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MUX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSIA]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSIG]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PA_SPARE1]		= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_TX_PA_SPARE2]		= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_TX_INTPAA_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAA_IAUX_STAT]	= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_TX_INTPAA_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_STAT]	= { .ghz5 = 0x002d, .ghz2 = 0x002d, NOUPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAA_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAA_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_STAT]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_STAT]	= { .ghz5 = 0x001e, .ghz2 = 0x001e, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAG_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAG_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PADA_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_BOOST_TUNE]	= { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, },
+	[B2056_TX_PADA_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PADG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PADG_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PADG_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PGAA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PGAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAA_BOOST_TUNE]	= { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
+	[B2056_TX_PGAA_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAA_MISC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PGAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PGAG_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAG_MISC]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_MIXA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXA_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_MIXG]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXG_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_BB_GM_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_GM]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC]		= { .ghz5 = 0x0074, .ghz2 = 0x0074, UPLOAD, },
+	[B2056_TX_TXLPF_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF0]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_BW]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_TXLPF_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_0]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_1]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_2]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_3]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_4]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_5]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_6]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_OPAMP_IDAC]	= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_TX_TXLPF_MISC]		= { .ghz5 = 0x005b, .ghz2 = 0x005b, NOUPLOAD, },
+	[B2056_TX_TXSPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_INTPA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PAD_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PGA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_GM_TXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_phy_rev3_rx[] = {
+	[B2056_RX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXIQCAL_RXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_RX_RSSI_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_SEL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_GAIN]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_RSSI_NB_IDAC]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_POLE]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_RSSI_WB1_IDAC]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_RSSI_MISC]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_LNAA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAA_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAA_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_A_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAA1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAA2_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_RX_LNA1A_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_LNAG_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAG_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAG_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_G_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAG1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAG2_IDAC]		= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_RX_LNA1G_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_MIXA_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXA_VCM]		= { .ghz5 = 0x0099, .ghz2 = 0x0099, NOUPLOAD, },
+	[B2056_RX_MIXA_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_LOB_BIAS]	= { .ghz5 = 0x0044, .ghz2 = 0x0044, UPLOAD, },
+	[B2056_RX_MIXA_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_CMFB_IDAC]	= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_MIXA_BIAS_AUX]	= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_MIXA_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXA_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXA_MAST_BIAS]	= { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, },
+	[B2056_RX_MIXG_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXG_VCM]		= { .ghz5 = 0x0099, .ghz2 = 0x0099, NOUPLOAD, },
+	[B2056_RX_MIXG_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_LOB_BIAS]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_MIXG_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_CMFB_IDAC]	= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_AUX]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXG_MAST_BIAS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_IOPAMP]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_RX_TIA_QOPAMP]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_RX_TIA_IMISC]		= { .ghz5 = 0x0057, .ghz2 = 0x0057, NOUPLOAD, },
+	[B2056_RX_TIA_QMISC]		= { .ghz5 = 0x0057, .ghz2 = 0x0057, NOUPLOAD, },
+	[B2056_RX_TIA_GAIN]		= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_BB_LPF_MASTER]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_AACI_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_RXLPF_IDAC]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_LOWQ]	= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_HIGHQ]= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_BIAS_DCCANCEL]	= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_RX_RXLPF_OUTVCM]		= { .ghz5 = 0x0023, .ghz2 = 0x0023, NOUPLOAD, },
+	[B2056_RX_RXLPF_INVCM_BODY]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_CC_OP]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RXLPF_GAIN]		= { .ghz5 = 0x0023, .ghz2 = 0x0023, NOUPLOAD, },
+	[B2056_RX_RXLPF_Q_BW]		= { .ghz5 = 0x0041, .ghz2 = 0x0041, NOUPLOAD, },
+	[B2056_RX_RXLPF_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_HPC]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_LPC]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_UNUSED]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_VGA_MASTER]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS_DCCANCEL]	= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_RX_VGA_GAIN]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_VGA_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_VGABUF_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGABUF_GAIN_BW]	= { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_A]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_G]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAG_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_MIXTIA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_VGA_BUF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_Q]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_BUF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_VGA_HPC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_HPC_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_phy_rev4_syn[] = {
+	[B2056_SYN_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_PU]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_TXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXHPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_MASTER]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_RCAL]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_AFEREG]		= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSE]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSEIDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSERCAL]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LPO]			= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_STATUS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_CODE_OUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL0]		= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL1]		= { .ghz5 = 0x001f, .ghz2 = 0x001f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL2]		= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL3]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL11]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST1]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST2]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST3]		= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+	[B2056_SYN_PLL_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL1]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL3]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL5]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL6]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_REFDIV]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_PFD]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_CP1]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_CP2]		= { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+	[B2056_SYN_PLL_CP3]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER1]	= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER2]	= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER3]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER4]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER5]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD1]		= { .ghz5 = 0x001c, .ghz2 = 0x001c, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD2]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO1]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO2]		= { .ghz5 = 0x00f7, .ghz2 = 0x00f7, UPLOAD, },
+	[B2056_SYN_PLL_MONITOR1]	= { .ghz5 = 0x00b4, .ghz2 = 0x00b4, NOUPLOAD, },
+	[B2056_SYN_PLL_MONITOR2]	= { .ghz5 = 0x00d2, .ghz2 = 0x00d2, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL4]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL5]		= { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL6]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL7]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL8]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL9]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL11]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL12]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+	[B2056_SYN_PLL_VCOCAL13]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_SYN_PLL_VREG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU2]		= { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU8]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RCCR1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF1]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER1]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER2]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF1]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGENBUF2]		= { .ghz5 = 0x008f, .ghz2 = 0x008f, UPLOAD, },
+	[B2056_SYN_LOGEN_BUF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF4]		= { .ghz5 = 0x00cc, .ghz2 = 0x00cc, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV1]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV2]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV3]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLOUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_CALEN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PEAKDET1]	= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2_OVRVAL]= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL_WAITCNT]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_VALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_phy_rev4_tx[] = {
+	[B2056_TX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_GAIN_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_I]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_Q]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_I]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_Q]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER1]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RXIQCAL_TXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_VCM_HG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_IQCAL_IDAC]		= { .ghz5 = 0x0037, .ghz2 = 0x0037, NOUPLOAD, },
+	[B2056_TX_TSSI_VCM]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_AMP_DET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MUX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSIA]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSIG]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PA_SPARE1]		= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_TX_PA_SPARE2]		= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_TX_INTPAA_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAA_IAUX_STAT]	= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_TX_INTPAA_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_STAT]	= { .ghz5 = 0x002d, .ghz2 = 0x002d, NOUPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAA_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAA_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_STAT]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_STAT]	= { .ghz5 = 0x001e, .ghz2 = 0x001e, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAG_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAG_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PADA_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_BOOST_TUNE]	= { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, },
+	[B2056_TX_PADA_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PADG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PADG_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PADG_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PGAA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PGAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAA_BOOST_TUNE]	= { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
+	[B2056_TX_PGAA_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAA_MISC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PGAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PGAG_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAG_MISC]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_MIXA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXA_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_MIXG]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXG_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_BB_GM_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_GM]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC]		= { .ghz5 = 0x0072, .ghz2 = 0x0072, UPLOAD, },
+	[B2056_TX_TXLPF_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF0]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_BW]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_TXLPF_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_0]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_1]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_2]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_3]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_4]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_5]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_6]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_OPAMP_IDAC]	= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_TX_TXLPF_MISC]		= { .ghz5 = 0x005b, .ghz2 = 0x005b, NOUPLOAD, },
+	[B2056_TX_TXSPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_INTPA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PAD_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PGA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_GM_TXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_phy_rev4_rx[] = {
+	[B2056_RX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXIQCAL_RXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_RX_RSSI_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_SEL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_GAIN]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_RSSI_NB_IDAC]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_POLE]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_RSSI_WB1_IDAC]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_RSSI_MISC]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_LNAA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAA_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAA_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_A_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAA1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAA2_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_RX_LNA1A_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_LNAG_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAG_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAG_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_G_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAG1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAG2_IDAC]		= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_RX_LNA1G_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_MIXA_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXA_VCM]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, },
+	[B2056_RX_MIXA_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_LOB_BIAS]	= { .ghz5 = 0x0044, .ghz2 = 0x0044, UPLOAD, },
+	[B2056_RX_MIXA_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_CMFB_IDAC]	= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_MIXA_BIAS_AUX]	= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_MIXA_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXA_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXA_MAST_BIAS]	= { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, },
+	[B2056_RX_MIXG_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXG_VCM]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, },
+	[B2056_RX_MIXG_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_LOB_BIAS]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_MIXG_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_CMFB_IDAC]	= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_AUX]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXG_MAST_BIAS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_IOPAMP]		= { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, },
+	[B2056_RX_TIA_QOPAMP]		= { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, },
+	[B2056_RX_TIA_IMISC]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_TIA_QMISC]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_TIA_GAIN]		= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_BB_LPF_MASTER]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_AACI_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_RXLPF_IDAC]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_LOWQ]	= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_HIGHQ]= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_BIAS_DCCANCEL]	= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_RX_RXLPF_OUTVCM]		= { .ghz5 = 0x002f, .ghz2 = 0x002f, UPLOAD, },
+	[B2056_RX_RXLPF_INVCM_BODY]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_CC_OP]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RXLPF_GAIN]		= { .ghz5 = 0x0023, .ghz2 = 0x0023, NOUPLOAD, },
+	[B2056_RX_RXLPF_Q_BW]		= { .ghz5 = 0x0041, .ghz2 = 0x0041, NOUPLOAD, },
+	[B2056_RX_RXLPF_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_HPC]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_LPC]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_UNUSED]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_VGA_MASTER]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS_DCCANCEL]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_RX_VGA_GAIN]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_VGA_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_VGABUF_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGABUF_GAIN_BW]	= { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_A]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_G]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAG_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_MIXTIA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_VGA_BUF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_Q]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_BUF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_VGA_HPC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_HPC_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_radio_rev5_syn[] = {
+	[B2056_SYN_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_PU]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_TXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXHPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_MASTER]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_RCAL]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_AFEREG]		= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSE]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSEIDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSERCAL]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LPO]			= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_STATUS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_CODE_OUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL1]		= { .ghz5 = 0x001f, .ghz2 = 0x001f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL2]		= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL3]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL11]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST1]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST2]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST3]		= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+	[B2056_SYN_PLL_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL1]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL3]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL5]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL6]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_REFDIV]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_PFD]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_CP1]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_CP2]		= { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+	[B2056_SYN_PLL_CP3]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER1]	= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER2]	= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER3]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER4]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER5]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD1]		= { .ghz5 = 0x001c, .ghz2 = 0x001c, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD2]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO1]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO2]		= { .ghz5 = 0x00f7, .ghz2 = 0x00f7, UPLOAD, },
+	[B2056_SYN_PLL_MONITOR1]	= { .ghz5 = 0x00b4, .ghz2 = 0x00b4, NOUPLOAD, },
+	[B2056_SYN_PLL_MONITOR2]	= { .ghz5 = 0x00d2, .ghz2 = 0x00d2, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL4]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL5]		= { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL6]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL7]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL8]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL9]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL11]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL12]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+	[B2056_SYN_PLL_VCOCAL13]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_SYN_PLL_VREG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU2]		= { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU8]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RCCR1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF1]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER1]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER2]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF1]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGENBUF2]		= { .ghz5 = 0x008f, .ghz2 = 0x008f, UPLOAD, },
+	[B2056_SYN_LOGEN_BUF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF4]		= { .ghz5 = 0x00cc, .ghz2 = 0x00cc, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV1]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV2]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV3]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLOUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_CALEN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PEAKDET1]	= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2_OVRVAL]= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL_WAITCNT]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_VALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_radio_rev5_tx[] = {
+	[B2056_TX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_GAIN_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_I]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_Q]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_I]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_Q]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER1]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RXIQCAL_TXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_VCM_HG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_IQCAL_IDAC]		= { .ghz5 = 0x0037, .ghz2 = 0x0037, NOUPLOAD, },
+	[B2056_TX_TSSI_VCM]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_AMP_DET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MUX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSIA]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSIG]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PA_SPARE1]		= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_TX_PA_SPARE2]		= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_TX_INTPAA_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAA_IAUX_STAT]	= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_TX_INTPAA_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_STAT]	= { .ghz5 = 0x002d, .ghz2 = 0x002d, NOUPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAA_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAA_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_STAT]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_STAT]	= { .ghz5 = 0x001e, .ghz2 = 0x001e, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAG_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAG_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PADA_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_BOOST_TUNE]	= { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, },
+	[B2056_TX_PADA_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PADG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PADG_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PADG_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PGAA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PGAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAA_BOOST_TUNE]	= { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
+	[B2056_TX_PGAA_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAA_MISC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PGAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PGAG_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAG_MISC]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_MIXA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXA_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_MIXG]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXG_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_BB_GM_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_GM]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_TX_TXLPF_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF0]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_BW]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_TXLPF_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_0]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_1]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_2]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_3]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_4]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_5]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_6]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_OPAMP_IDAC]	= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_TX_TXLPF_MISC]		= { .ghz5 = 0x005b, .ghz2 = 0x005b, NOUPLOAD, },
+	[B2056_TX_TXSPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_INTPA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PAD_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PGA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_GM_TXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC0]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC1]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC2]		= { .ghz5 = 0x0071, .ghz2 = 0x0071, UPLOAD, },
+	[B2056_TX_GMBB_IDAC3]		= { .ghz5 = 0x0071, .ghz2 = 0x0071, UPLOAD, },
+	[B2056_TX_GMBB_IDAC4]		= { .ghz5 = 0x0072, .ghz2 = 0x0072, UPLOAD, },
+	[B2056_TX_GMBB_IDAC5]		= { .ghz5 = 0x0073, .ghz2 = 0x0073, UPLOAD, },
+	[B2056_TX_GMBB_IDAC6]		= { .ghz5 = 0x0074, .ghz2 = 0x0074, UPLOAD, },
+	[B2056_TX_GMBB_IDAC7]		= { .ghz5 = 0x0075, .ghz2 = 0x0075, UPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_radio_rev5_rx[] = {
+	[B2056_RX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXIQCAL_RXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_RX_RSSI_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_SEL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_GAIN]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_RSSI_NB_IDAC]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_POLE]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_RSSI_WB1_IDAC]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_RSSI_MISC]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_LNAA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAA_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAA_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_A_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAA1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAA2_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_RX_LNA1A_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_LNAG_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAG_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAG_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_G_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAG1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAG2_IDAC]		= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_RX_LNA1G_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_MIXA_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXA_VCM]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, },
+	[B2056_RX_MIXA_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_LOB_BIAS]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, UPLOAD, },
+	[B2056_RX_MIXA_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_CMFB_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_RX_MIXA_BIAS_AUX]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+	[B2056_RX_MIXA_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXA_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXA_MAST_BIAS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXG_VCM]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, },
+	[B2056_RX_MIXG_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_LOB_BIAS]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_MIXG_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_CMFB_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_RX_MIXG_BIAS_AUX]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXG_MAST_BIAS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_IOPAMP]		= { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, },
+	[B2056_RX_TIA_QOPAMP]		= { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, },
+	[B2056_RX_TIA_IMISC]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_TIA_QMISC]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_TIA_GAIN]		= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_BB_LPF_MASTER]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_AACI_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_RXLPF_IDAC]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_LOWQ]	= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_HIGHQ]= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_BIAS_DCCANCEL]	= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_RX_RXLPF_OUTVCM]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, },
+	[B2056_RX_RXLPF_INVCM_BODY]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_CC_OP]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RXLPF_GAIN]		= { .ghz5 = 0x0023, .ghz2 = 0x0023, NOUPLOAD, },
+	[B2056_RX_RXLPF_Q_BW]		= { .ghz5 = 0x0041, .ghz2 = 0x0041, NOUPLOAD, },
+	[B2056_RX_RXLPF_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_HPC]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_LPC]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_UNUSED]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_VGA_MASTER]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS_DCCANCEL]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_RX_VGA_GAIN]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_VGA_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_VGABUF_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGABUF_GAIN_BW]	= { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_A]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_G]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAG_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_MIXTIA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_VGA_BUF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_Q]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_BUF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_VGA_HPC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_HPC_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_radio_rev6_syn[] = {
+	[B2056_SYN_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_PU]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_TXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXHPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_MASTER]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_RCAL]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_AFEREG]		= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSE]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSEIDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSERCAL]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LPO]			= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_STATUS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_CODE_OUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL1]		= { .ghz5 = 0x001f, .ghz2 = 0x001f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL2]		= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL3]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL11]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST1]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST2]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST3]		= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+	[B2056_SYN_PLL_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL1]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL3]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL5]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL6]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_REFDIV]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_PFD]		= { .ghz5 = 0x0006, .ghz2 = 0x0006, UPLOAD, },
+	[B2056_SYN_PLL_CP1]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_CP2]		= { .ghz5 = 0x003f, .ghz2 = 0x003f, UPLOAD, },
+	[B2056_SYN_PLL_CP3]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER1]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, UPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER2]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, UPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER3]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER4]	= { .ghz5 = 0x002b, .ghz2 = 0x002b, UPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER5]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD1]		= { .ghz5 = 0x001c, .ghz2 = 0x001c, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD2]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO1]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO2]		= { .ghz5 = 0x00f7, .ghz2 = 0x00f7, UPLOAD, },
+	[B2056_SYN_PLL_MONITOR1]	= { .ghz5 = 0x00b4, .ghz2 = 0x00b4, NOUPLOAD, },
+	[B2056_SYN_PLL_MONITOR2]	= { .ghz5 = 0x00d2, .ghz2 = 0x00d2, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL4]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL5]		= { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL6]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL7]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL8]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL9]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL11]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL12]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+	[B2056_SYN_PLL_VCOCAL13]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_SYN_PLL_VREG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU2]		= { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU8]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RCCR1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF1]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER1]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER2]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF1]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGENBUF2]		= { .ghz5 = 0x008f, .ghz2 = 0x008f, UPLOAD, },
+	[B2056_SYN_LOGEN_BUF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF4]		= { .ghz5 = 0x00cc, .ghz2 = 0x00cc, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV1]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV2]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV3]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLOUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_CALEN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PEAKDET1]	= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2_OVRVAL]= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL_WAITCNT]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_VALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_radio_rev6_tx[] = {
+	[B2056_TX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_GAIN_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_I]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_Q]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_I]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_Q]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER1]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RXIQCAL_TXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_VCM_HG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_IQCAL_IDAC]		= { .ghz5 = 0x0037, .ghz2 = 0x0037, NOUPLOAD, },
+	[B2056_TX_TSSI_VCM]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_AMP_DET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MUX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSIA]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSIG]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PA_SPARE1]		= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_TX_PA_SPARE2]		= { .ghz5 = 0x00ee, .ghz2 = 0x00ee, UPLOAD, },
+	[B2056_TX_INTPAA_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAA_IAUX_STAT]	= { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, },
+	[B2056_TX_INTPAA_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_STAT]	= { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAA_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAA_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_STAT]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_STAT]	= { .ghz5 = 0x001e, .ghz2 = 0x001e, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAG_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAG_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PADA_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_BOOST_TUNE]	= { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, },
+	[B2056_TX_PADA_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PADG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PADG_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PADG_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PGAA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PGAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAA_BOOST_TUNE]	= { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
+	[B2056_TX_PGAA_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAA_MISC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PGAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PGAG_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAG_MISC]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_MIXA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXA_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_MIXG]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXG_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_BB_GM_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_GM]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_TX_TXLPF_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF0]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_BW]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_TXLPF_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_0]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_1]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_2]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_3]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_4]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_5]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_6]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_OPAMP_IDAC]	= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_TX_TXLPF_MISC]		= { .ghz5 = 0x005b, .ghz2 = 0x005b, NOUPLOAD, },
+	[B2056_TX_TXSPARE1]		= { .ghz5 = 0x0030, .ghz2 = 0x0030, UPLOAD, },
+	[B2056_TX_TXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_INTPA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PAD_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PGA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_GM_TXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC0]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC1]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC2]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC3]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC4]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC5]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC6]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC7]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_radio_rev6_rx[] = {
+	[B2056_RX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXIQCAL_RXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_RX_RSSI_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_SEL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_GAIN]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_RSSI_NB_IDAC]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_POLE]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_RSSI_WB1_IDAC]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_RSSI_MISC]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_LNAA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAA_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAA_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_A_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAA1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAA2_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_RX_LNA1A_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_LNAG_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAG_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAG_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_G_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAG1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAG2_IDAC]		= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_RX_LNA1G_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_MIXA_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXA_VCM]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, },
+	[B2056_RX_MIXA_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_LOB_BIAS]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, UPLOAD, },
+	[B2056_RX_MIXA_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_CMFB_IDAC]	= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_MIXA_BIAS_AUX]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+	[B2056_RX_MIXA_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXA_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXA_MAST_BIAS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXG_VCM]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, },
+	[B2056_RX_MIXG_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_LOB_BIAS]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_MIXG_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_CMFB_IDAC]	= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_AUX]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXG_MAST_BIAS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_IOPAMP]		= { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, },
+	[B2056_RX_TIA_QOPAMP]		= { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, },
+	[B2056_RX_TIA_IMISC]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_TIA_QMISC]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_TIA_GAIN]		= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_BB_LPF_MASTER]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_AACI_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_RXLPF_IDAC]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_LOWQ]	= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_HIGHQ]= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_BIAS_DCCANCEL]	= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_RX_RXLPF_OUTVCM]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, },
+	[B2056_RX_RXLPF_INVCM_BODY]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_CC_OP]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RXLPF_GAIN]		= { .ghz5 = 0x0023, .ghz2 = 0x0023, NOUPLOAD, },
+	[B2056_RX_RXLPF_Q_BW]		= { .ghz5 = 0x0041, .ghz2 = 0x0041, NOUPLOAD, },
+	[B2056_RX_RXLPF_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_HPC]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_LPC]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_UNUSED]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_VGA_MASTER]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS_DCCANCEL]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_RX_VGA_GAIN]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_VGA_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_VGABUF_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGABUF_GAIN_BW]	= { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_A]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_G]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE3]		= { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, },
+	[B2056_RX_RXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAG_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_MIXTIA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_VGA_BUF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_Q]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_BUF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_VGA_HPC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_HPC_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_radio_rev7_9_syn[] = {
+	[B2056_SYN_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_PU]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_TXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXHPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_MASTER]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_RCAL]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_AFEREG]		= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSE]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSEIDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSERCAL]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LPO]			= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_STATUS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_CODE_OUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL1]		= { .ghz5 = 0x001f, .ghz2 = 0x001f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL2]		= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL3]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL11]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST1]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST2]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST3]		= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+	[B2056_SYN_PLL_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL1]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL3]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL5]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL6]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_REFDIV]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_PFD]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_CP1]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_CP2]		= { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+	[B2056_SYN_PLL_CP3]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER1]	= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER2]	= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER3]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER4]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER5]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD1]		= { .ghz5 = 0x001c, .ghz2 = 0x001c, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD2]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO1]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO2]		= { .ghz5 = 0x00f7, .ghz2 = 0x00f7, UPLOAD, },
+	[B2056_SYN_PLL_MONITOR1]	= { .ghz5 = 0x00b4, .ghz2 = 0x00b4, NOUPLOAD, },
+	[B2056_SYN_PLL_MONITOR2]	= { .ghz5 = 0x00d2, .ghz2 = 0x00d2, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL4]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL5]		= { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL6]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL7]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL8]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL9]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL11]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL12]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+	[B2056_SYN_PLL_VCOCAL13]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_SYN_PLL_VREG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU2]		= { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU8]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RCCR1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF1]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER1]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER2]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF1]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGENBUF2]		= { .ghz5 = 0x008f, .ghz2 = 0x008f, UPLOAD, },
+	[B2056_SYN_LOGEN_BUF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF4]		= { .ghz5 = 0x00cc, .ghz2 = 0x00cc, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV1]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV2]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV3]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLOUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_CALEN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PEAKDET1]	= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2_OVRVAL]= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL_WAITCNT]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_VALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_radio_rev7_9_tx[] = {
+	[B2056_TX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_GAIN_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_I]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_Q]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_I]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_Q]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER1]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RXIQCAL_TXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_VCM_HG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_IQCAL_IDAC]		= { .ghz5 = 0x0037, .ghz2 = 0x0037, NOUPLOAD, },
+	[B2056_TX_TSSI_VCM]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_AMP_DET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MUX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSIA]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSIG]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PA_SPARE1]		= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_TX_PA_SPARE2]		= { .ghz5 = 0x00ee, .ghz2 = 0x00ee, UPLOAD, },
+	[B2056_TX_INTPAA_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAA_IAUX_STAT]	= { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, },
+	[B2056_TX_INTPAA_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_STAT]	= { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAA_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAA_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_STAT]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_STAT]	= { .ghz5 = 0x001e, .ghz2 = 0x001e, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAG_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAG_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PADA_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_BOOST_TUNE]	= { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, },
+	[B2056_TX_PADA_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PADG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PADG_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PADG_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PGAA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PGAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAA_BOOST_TUNE]	= { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
+	[B2056_TX_PGAA_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAA_MISC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PGAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PGAG_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAG_MISC]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_MIXA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXA_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_MIXG]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXG_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_BB_GM_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_GM]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_TX_TXLPF_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF0]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_BW]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_TXLPF_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_0]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_1]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_2]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_3]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_4]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_5]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_6]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_OPAMP_IDAC]	= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_TX_TXLPF_MISC]		= { .ghz5 = 0x005b, .ghz2 = 0x005b, NOUPLOAD, },
+	[B2056_TX_TXSPARE1]		= { .ghz5 = 0x0030, .ghz2 = 0x0030, UPLOAD, },
+	[B2056_TX_TXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_INTPA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PAD_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PGA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_GM_TXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC0]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC1]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC2]		= { .ghz5 = 0x0071, .ghz2 = 0x0071, UPLOAD, },
+	[B2056_TX_GMBB_IDAC3]		= { .ghz5 = 0x0071, .ghz2 = 0x0071, UPLOAD, },
+	[B2056_TX_GMBB_IDAC4]		= { .ghz5 = 0x0072, .ghz2 = 0x0072, UPLOAD, },
+	[B2056_TX_GMBB_IDAC5]		= { .ghz5 = 0x0073, .ghz2 = 0x0073, UPLOAD, },
+	[B2056_TX_GMBB_IDAC6]		= { .ghz5 = 0x0074, .ghz2 = 0x0074, UPLOAD, },
+	[B2056_TX_GMBB_IDAC7]		= { .ghz5 = 0x0075, .ghz2 = 0x0075, UPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_radio_rev7_9_rx[] = {
+	[B2056_RX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXIQCAL_RXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_RX_RSSI_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_SEL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_GAIN]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_RSSI_NB_IDAC]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_POLE]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_RSSI_WB1_IDAC]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_RSSI_MISC]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_LNAA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAA_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAA_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_A_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAA1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAA2_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_RX_LNA1A_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_LNAG_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAG_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAG_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_G_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAG1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAG2_IDAC]		= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_RX_LNA1G_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_MIXA_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXA_VCM]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, },
+	[B2056_RX_MIXA_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_LOB_BIAS]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, UPLOAD, },
+	[B2056_RX_MIXA_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_CMFB_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_RX_MIXA_BIAS_AUX]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+	[B2056_RX_MIXA_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXA_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXA_MAST_BIAS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXG_VCM]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, },
+	[B2056_RX_MIXG_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_LOB_BIAS]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_MIXG_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_CMFB_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_RX_MIXG_BIAS_AUX]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXG_MAST_BIAS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_IOPAMP]		= { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, },
+	[B2056_RX_TIA_QOPAMP]		= { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, },
+	[B2056_RX_TIA_IMISC]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_TIA_QMISC]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_TIA_GAIN]		= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_BB_LPF_MASTER]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_AACI_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_RXLPF_IDAC]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_LOWQ]	= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_HIGHQ]= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_BIAS_DCCANCEL]	= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_RX_RXLPF_OUTVCM]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, },
+	[B2056_RX_RXLPF_INVCM_BODY]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_CC_OP]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RXLPF_GAIN]		= { .ghz5 = 0x0023, .ghz2 = 0x0023, NOUPLOAD, },
+	[B2056_RX_RXLPF_Q_BW]		= { .ghz5 = 0x0041, .ghz2 = 0x0041, NOUPLOAD, },
+	[B2056_RX_RXLPF_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_HPC]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_LPC]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_UNUSED]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_VGA_MASTER]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS_DCCANCEL]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_RX_VGA_GAIN]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_VGA_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_VGABUF_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGABUF_GAIN_BW]	= { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_A]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_G]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAG_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_MIXTIA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_VGA_BUF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_Q]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_BUF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_VGA_HPC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_HPC_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_radio_rev8_syn[] = {
+	[B2056_SYN_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_PU]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_TXLPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_COM_RC_RXHPF]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_GPIO_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_MASTER]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_TOPBIAS_RCAL]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_AFEREG]		= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSE]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSEIDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_TEMPPROCSENSERCAL]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LPO]			= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_VDDCAL_STATUS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCAL_CODE_OUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL1]		= { .ghz5 = 0x001f, .ghz2 = 0x001f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL2]		= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL3]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_RCCAL_CTRL11]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_ZCAL_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST1]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST2]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_MAST3]		= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+	[B2056_SYN_PLL_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL1]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL3]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL5]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_SYN_PLL_XTAL6]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_REFDIV]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_PFD]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_CP1]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
+	[B2056_SYN_PLL_CP2]		= { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+	[B2056_SYN_PLL_CP3]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER1]	= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER2]	= { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER3]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER4]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER5]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD1]		= { .ghz5 = 0x001c, .ghz2 = 0x001c, NOUPLOAD, },
+	[B2056_SYN_PLL_MMD2]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO1]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCO2]		= { .ghz5 = 0x00f7, .ghz2 = 0x00f7, UPLOAD, },
+	[B2056_SYN_PLL_MONITOR1]	= { .ghz5 = 0x00b4, .ghz2 = 0x00b4, NOUPLOAD, },
+	[B2056_SYN_PLL_MONITOR2]	= { .ghz5 = 0x00d2, .ghz2 = 0x00d2, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL4]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL5]		= { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL6]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL7]		= { .ghz5 = 0x003e, .ghz2 = 0x003e, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL8]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL9]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL10]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL11]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_SYN_PLL_VCOCAL12]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+	[B2056_SYN_PLL_VCOCAL13]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_SYN_PLL_VREG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_PLL_STATUS3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU2]		= { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PU8]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BIAS_RESET]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RCCR1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF1]	= { .ghz5 = 0x0060, .ghz2 = 0x0060, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER1]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER2]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF1]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGENBUF2]		= { .ghz5 = 0x008f, .ghz2 = 0x008f, UPLOAD, },
+	[B2056_SYN_LOGEN_BUF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF4]		= { .ghz5 = 0x00cc, .ghz2 = 0x00cc, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV1]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV2]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_DIV3]		= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLOUT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACLCAL3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_CALEN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_PEAKDET1]	= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_DIFF_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_ACL_OVR]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_VCOBUF2_OVRVAL]= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_SYN_LOGEN_MIXER3_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF5_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_BUF6_OVRVAL]	= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CBUFTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSRX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX1_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX2_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX3_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CMOSTX4_OVRVAL]= { .ghz5 = 0x0066, .ghz2 = 0x0066, NOUPLOAD, },
+	[B2056_SYN_LOGEN_ACL_WAITCNT]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_SYN_LOGEN_CORE_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_RX_CMOS_CALVALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_SYN_LOGEN_TX_CMOS_VALID]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_radio_rev8_tx[] = {
+	[B2056_TX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_GAIN_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_I]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_FINE_Q]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_I]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_LOFT_COARSE_Q]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER1]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_TX_COM_MASTER2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_RXIQCAL_TXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_IQCAL_VCM_HG]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_IQCAL_IDAC]		= { .ghz5 = 0x0037, .ghz2 = 0x0037, NOUPLOAD, },
+	[B2056_TX_TSSI_VCM]		= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_TX_AMP_DET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TX_SSI_MUX]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSIA]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSIG]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TSSI_MISC3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PA_SPARE1]		= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_TX_PA_SPARE2]		= { .ghz5 = 0x00ee, .ghz2 = 0x00ee, UPLOAD, },
+	[B2056_TX_INTPAA_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAA_IAUX_STAT]	= { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, },
+	[B2056_TX_INTPAA_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_STAT]	= { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAA_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAA_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAA_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_MASTER]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_BOOST_TUNE]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_STAT]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_TX_INTPAG_IAUX_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_STAT]	= { .ghz5 = 0x001e, .ghz2 = 0x001e, NOUPLOAD, },
+	[B2056_TX_INTPAG_IMAIN_DYN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_INTPAG_CASCBIAS]	= { .ghz5 = 0x006e, .ghz2 = 0x006e, NOUPLOAD, },
+	[B2056_TX_INTPAG_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAG_PA_MISC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PADA_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADA_BOOST_TUNE]	= { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, },
+	[B2056_TX_PADA_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PADG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PADG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PADG_CASCBIAS]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_TX_PADG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PADG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PADG_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PGAA_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PGAA_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAA_BOOST_TUNE]	= { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
+	[B2056_TX_PGAA_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAA_MISC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_MASTER]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_PGAG_IDAC]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_TX_PGAG_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_PGAG_BOOST_TUNE]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_TX_PGAG_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAG_MISC]		= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_TX_MIXA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXA_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_MIXG]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_MIXG_BOOST_TUNE]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_TX_BB_GM_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_GM]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_TX_TXLPF_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF0]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF1]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_RCCAL_OFF6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_BW]		= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_TX_TXLPF_GAIN]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_0]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_1]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_2]		= { .ghz5 = 0x000e, .ghz2 = 0x000e, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_3]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_4]		= { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_5]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_IDAC_6]		= { .ghz5 = 0x001b, .ghz2 = 0x001b, NOUPLOAD, },
+	[B2056_TX_TXLPF_OPAMP_IDAC]	= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_TX_TXLPF_MISC]		= { .ghz5 = 0x005b, .ghz2 = 0x005b, NOUPLOAD, },
+	[B2056_TX_TXSPARE1]		= { .ghz5 = 0x0030, .ghz2 = 0x0030, UPLOAD, },
+	[B2056_TX_TXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_TXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_INTPA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PAD_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_PGA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_GM_TXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_STATUS_TXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC0]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC1]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC2]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC3]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC4]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC5]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC6]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+	[B2056_TX_GMBB_IDAC7]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_radio_rev8_rx[] = {
+	[B2056_RX_RESERVED_ADDR2]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR3]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR4]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR5]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR6]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR7]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_CTRL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_OVR]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RESET]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RCAL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_TXLPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_COM_RC_RXHPF]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR16]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR17]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR18]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR19]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR20]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR21]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR22]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR23]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR24]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR25]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR26]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR27]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR28]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR29]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR30]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RESERVED_ADDR31]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXIQCAL_RXMUX]	= { .ghz5 = 0x0003, .ghz2 = 0x0003, NOUPLOAD, },
+	[B2056_RX_RSSI_PU]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_SEL]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RSSI_GAIN]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_RSSI_NB_IDAC]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2I_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_1]	= { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+	[B2056_RX_RSSI_WB2Q_IDAC_2]	= { .ghz5 = 0x0005, .ghz2 = 0x0005, NOUPLOAD, },
+	[B2056_RX_RSSI_POLE]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_RSSI_WB1_IDAC]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_RSSI_MISC]		= { .ghz5 = 0x0090, .ghz2 = 0x0090, NOUPLOAD, },
+	[B2056_RX_LNAA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAA_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAA_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_A_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAA1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAA2_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_RX_LNA1A_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_LNAG_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_LNAG_TUNE]		= { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+	[B2056_RX_LNAG_GAIN]		= { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
+	[B2056_RX_LNA_G_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+	[B2056_RX_BIASPOLE_LNAG1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAG2_IDAC]		= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_RX_LNA1G_MISC]		= { .ghz5 = 0x0020, .ghz2 = 0x0020, NOUPLOAD, },
+	[B2056_RX_MIXA_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXA_VCM]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, },
+	[B2056_RX_MIXA_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_LOB_BIAS]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, UPLOAD, },
+	[B2056_RX_MIXA_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXA_CMFB_IDAC]	= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_MIXA_BIAS_AUX]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+	[B2056_RX_MIXA_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXA_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXA_MAST_BIAS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_MIXG_VCM]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, },
+	[B2056_RX_MIXG_CTRLPTAT]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_LOB_BIAS]	= { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+	[B2056_RX_MIXG_CORE_IDAC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_MIXG_CMFB_IDAC]	= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_AUX]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MAIN]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+	[B2056_RX_MIXG_BIAS_MISC]	= { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
+	[B2056_RX_MIXG_MAST_BIAS]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_MASTER]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_IOPAMP]		= { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, },
+	[B2056_RX_TIA_QOPAMP]		= { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, },
+	[B2056_RX_TIA_IMISC]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_TIA_QMISC]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_TIA_GAIN]		= { .ghz5 = 0x0044, .ghz2 = 0x0044, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TIA_SPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_BB_LPF_MASTER]	= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_AACI_MASTER]		= { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+	[B2056_RX_RXLPF_IDAC]		= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_LOWQ]	= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_OPAMPBIAS_HIGHQ]= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_RXLPF_BIAS_DCCANCEL]	= { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+	[B2056_RX_RXLPF_OUTVCM]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, },
+	[B2056_RX_RXLPF_INVCM_BODY]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+	[B2056_RX_RXLPF_CC_OP]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+	[B2056_RX_RXLPF_GAIN]		= { .ghz5 = 0x0023, .ghz2 = 0x0023, NOUPLOAD, },
+	[B2056_RX_RXLPF_Q_BW]		= { .ghz5 = 0x0041, .ghz2 = 0x0041, NOUPLOAD, },
+	[B2056_RX_RXLPF_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_HPC]	= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXHPF_OFF7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_RCCAL_LPC]	= { .ghz5 = 0x000c, .ghz2 = 0x000c, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_0]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_3]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXLPF_OFF_4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_UNUSED]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_VGA_MASTER]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGA_BIAS_DCCANCEL]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_RX_VGA_GAIN]		= { .ghz5 = 0x000a, .ghz2 = 0x000a, NOUPLOAD, },
+	[B2056_RX_VGA_HP_CORNER_BW]	= { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+	[B2056_RX_VGABUF_BIAS]		= { .ghz5 = 0x0022, .ghz2 = 0x0022, NOUPLOAD, },
+	[B2056_RX_VGABUF_GAIN_BW]	= { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_A]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_TXFBMIX_G]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE1]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE2]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE3]		= { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, },
+	[B2056_RX_RXSPARE4]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE5]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE6]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE7]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE8]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE9]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE10]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE11]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE12]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE13]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE14]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE15]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_RXSPARE16]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_LNAG_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_MIXTIA_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_VGA_BUF_GAIN]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_Q]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_BUF_BW]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_VGA_HPC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_RXLPF_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+	[B2056_RX_STATUS_HPC_RC]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_radio_rev11_syn[] = {
+	[B2056_SYN_PLL_PFD]		= { .ghz5 = 0x0006, .ghz2 = 0x0006, UPLOAD, },
+	[B2056_SYN_PLL_CP2]		= { .ghz5 = 0x003f, .ghz2 = 0x003f, UPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER1]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, UPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER2]	= { .ghz5 = 0x0006, .ghz2 = 0x0006, UPLOAD, },
+	[B2056_SYN_PLL_LOOPFILTER4]	= { .ghz5 = 0x002b, .ghz2 = 0x002b, UPLOAD, },
+	[B2056_SYN_PLL_VCO2]		= { .ghz5 = 0x00f7, .ghz2 = 0x00f7, UPLOAD, },
+	[B2056_SYN_PLL_VCOCAL12]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+	[B2056_SYN_LOGENBUF2]		= { .ghz5 = 0x008f, .ghz2 = 0x008f, UPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_radio_rev11_tx[] = {
+	[B2056_TX_PA_SPARE2]		= { .ghz5 = 0x00ee, .ghz2 = 0x00ee, UPLOAD, },
+	[B2056_TX_INTPAA_IAUX_STAT]	= { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, },
+	[B2056_TX_INTPAA_IMAIN_STAT]	= { .ghz5 = 0x0050, .ghz2 = 0x0050, UPLOAD, },
+	[B2056_TX_INTPAA_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_INTPAG_PASLOPE]	= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_TX_PADA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PADA_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PADG_SLOPE]		= { .ghz5 = 0x0070, .ghz2 = 0x0070, UPLOAD, },
+	[B2056_TX_PGAA_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_TX_PGAA_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_PGAG_SLOPE]		= { .ghz5 = 0x0077, .ghz2 = 0x0077, UPLOAD, },
+	[B2056_TX_GMBB_IDAC]		= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_TX_TXSPARE1]		= { .ghz5 = 0x0030, .ghz2 = 0x0030, UPLOAD, },
+};
+
+static const struct b2056_inittab_entry b2056_inittab_radio_rev11_rx[] = {
+	[B2056_RX_BIASPOLE_LNAA1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAA2_IDAC]		= { .ghz5 = 0x00ff, .ghz2 = 0x00ff, UPLOAD, },
+	[B2056_RX_BIASPOLE_LNAG1_IDAC]	= { .ghz5 = 0x0017, .ghz2 = 0x0017, UPLOAD, },
+	[B2056_RX_LNAG2_IDAC]		= { .ghz5 = 0x00f0, .ghz2 = 0x00f0, UPLOAD, },
+	[B2056_RX_MIXA_VCM]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, },
+	[B2056_RX_MIXA_LOB_BIAS]	= { .ghz5 = 0x0088, .ghz2 = 0x0088, UPLOAD, },
+	[B2056_RX_MIXA_BIAS_AUX]	= { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+	[B2056_RX_MIXG_VCM]		= { .ghz5 = 0x0055, .ghz2 = 0x0055, UPLOAD, },
+	[B2056_RX_TIA_IOPAMP]		= { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, },
+	[B2056_RX_TIA_QOPAMP]		= { .ghz5 = 0x0026, .ghz2 = 0x0026, UPLOAD, },
+	[B2056_RX_TIA_IMISC]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_TIA_QMISC]		= { .ghz5 = 0x000f, .ghz2 = 0x000f, UPLOAD, },
+	[B2056_RX_RXLPF_OUTVCM]		= { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, },
+	[B2056_RX_VGA_BIAS_DCCANCEL]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, UPLOAD, },
+	[B2056_RX_RXSPARE3]		= { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, },
+};
+
+#define INITTABSPTS(prefix) \
+	static const struct b2056_inittabs_pts prefix = {	\
+		.syn		= prefix##_syn,			\
+		.syn_length	= ARRAY_SIZE(prefix##_syn),	\
+		.tx		= prefix##_tx,			\
+		.tx_length	= ARRAY_SIZE(prefix##_tx),	\
+		.rx		= prefix##_rx,			\
+		.rx_length	= ARRAY_SIZE(prefix##_rx),	\
+	}
+
+INITTABSPTS(b2056_inittab_phy_rev3);
+INITTABSPTS(b2056_inittab_phy_rev4);
+INITTABSPTS(b2056_inittab_radio_rev5);
+INITTABSPTS(b2056_inittab_radio_rev6);
+INITTABSPTS(b2056_inittab_radio_rev7_9);
+INITTABSPTS(b2056_inittab_radio_rev8);
+INITTABSPTS(b2056_inittab_radio_rev11);
+
+#define RADIOREGS3(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, r29, \
+		   r30, r31, r32, r33, r34, r35, r36) \
+	.radio_syn_pll_vcocal1		= r00,	\
+	.radio_syn_pll_vcocal2		= r01,	\
+	.radio_syn_pll_refdiv		= r02,	\
+	.radio_syn_pll_mmd2		= r03,	\
+	.radio_syn_pll_mmd1		= r04,	\
+	.radio_syn_pll_loopfilter1	= r05,	\
+	.radio_syn_pll_loopfilter2	= r06,	\
+	.radio_syn_pll_loopfilter3	= r07,	\
+	.radio_syn_pll_loopfilter4	= r08,	\
+	.radio_syn_pll_loopfilter5	= r09,	\
+	.radio_syn_reserved_addr27	= r10,	\
+	.radio_syn_reserved_addr28	= r11,	\
+	.radio_syn_reserved_addr29	= r12,	\
+	.radio_syn_logen_vcobuf1	= r13,	\
+	.radio_syn_logen_mixer2		= r14,	\
+	.radio_syn_logen_buf3		= r15,	\
+	.radio_syn_logen_buf4		= r16,	\
+	.radio_rx0_lnaa_tune		= r17,	\
+	.radio_rx0_lnag_tune		= r18,	\
+	.radio_tx0_intpaa_boost_tune	= r19,	\
+	.radio_tx0_intpag_boost_tune	= r20,	\
+	.radio_tx0_pada_boost_tune	= r21,	\
+	.radio_tx0_padg_boost_tune	= r22,	\
+	.radio_tx0_pgaa_boost_tune	= r23,	\
+	.radio_tx0_pgag_boost_tune	= r24,	\
+	.radio_tx0_mixa_boost_tune	= r25,	\
+	.radio_tx0_mixg_boost_tune	= r26,	\
+	.radio_rx1_lnaa_tune		= r27,	\
+	.radio_rx1_lnag_tune		= r28,	\
+	.radio_tx1_intpaa_boost_tune	= r29,	\
+	.radio_tx1_intpag_boost_tune	= r30,	\
+	.radio_tx1_pada_boost_tune	= r31,	\
+	.radio_tx1_padg_boost_tune	= r32,	\
+	.radio_tx1_pgaa_boost_tune	= r33,	\
+	.radio_tx1_pgag_boost_tune	= r34,	\
+	.radio_tx1_mixa_boost_tune	= r35,	\
+	.radio_tx1_mixg_boost_tune	= r36
+
+#define PHYREGS(r0, r1, r2, r3, r4, r5)	\
+	.phy_regs.phy_bw1a	= r0,	\
+	.phy_regs.phy_bw2	= r1,	\
+	.phy_regs.phy_bw3	= r2,	\
+	.phy_regs.phy_bw4	= r3,	\
+	.phy_regs.phy_bw5	= r4,	\
+	.phy_regs.phy_bw6	= r5
+
+/* http://bcm-v4.sipsolutions.net/802.11/Radio/2056/ChannelTable */
+static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_phy_rev3[] = {
+  {	.freq			= 4920,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216),
+  },
+  {	.freq			= 4930,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215),
+  },
+  {	.freq			= 4940,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214),
+  },
+  {	.freq			= 4950,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213),
+  },
+  {	.freq			= 4960,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212),
+  },
+  {	.freq			= 4970,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211),
+  },
+  {	.freq			= 4980,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f),
+  },
+  {	.freq			= 4990,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e),
+  },
+  {	.freq			= 5000,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d),
+  },
+  {	.freq			= 5010,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c),
+  },
+  {	.freq			= 5020,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b),
+  },
+  {	.freq			= 5030,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a),
+  },
+  {	.freq			= 5040,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209),
+  },
+  {	.freq			= 5050,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208),
+  },
+  {	.freq			= 5060,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207),
+  },
+  {	.freq			= 5070,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206),
+  },
+  {	.freq			= 5080,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205),
+  },
+  {	.freq			= 5090,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204),
+  },
+  {	.freq			= 5100,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xff, 0x00),
+	PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203),
+  },
+  {	.freq			= 5110,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202),
+  },
+  {	.freq			= 5120,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201),
+  },
+  {	.freq			= 5130,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200),
+  },
+  {	.freq			= 5140,
+	RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xfc, 0x00),
+	PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff),
+  },
+  {	.freq			= 5160,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd),
+  },
+  {	.freq			= 5170,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc),
+  },
+  {	.freq			= 5180,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xfc, 0x00),
+	PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb),
+  },
+  {	.freq			= 5190,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa),
+  },
+  {	.freq			= 5200,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xef, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xfc, 0x00, 0xef, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9),
+  },
+  {	.freq			= 5210,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8),
+  },
+  {	.freq			= 5220,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xfc, 0x00),
+	PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7),
+  },
+  {	.freq			= 5230,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6),
+  },
+  {	.freq			= 5240,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5),
+  },
+  {	.freq			= 5250,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4),
+  },
+  {	.freq			= 5260,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xfc, 0x00),
+	PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3),
+  },
+  {	.freq			= 5270,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00,
+		   0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2),
+  },
+  {	.freq			= 5280,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00,
+		   0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1),
+  },
+  {	.freq			= 5290,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00,
+		   0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0),
+  },
+  {	.freq			= 5300,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xfc, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xfc, 0x00),
+	PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0),
+  },
+  {	.freq			= 5310,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef),
+  },
+  {	.freq			= 5320,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee),
+  },
+  {	.freq			= 5330,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed),
+  },
+  {	.freq			= 5340,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xfa, 0x00),
+	PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec),
+  },
+  {	.freq			= 5350,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb),
+  },
+  {	.freq			= 5360,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea),
+  },
+  {	.freq			= 5370,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9),
+  },
+  {	.freq			= 5380,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xfa, 0x00),
+	PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8),
+  },
+  {	.freq			= 5390,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x8f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xfa, 0x00, 0x8f, 0x00, 0x05, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7),
+  },
+  {	.freq			= 5400,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+		   0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x08, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6),
+  },
+  {	.freq			= 5410,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+		   0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x08, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5),
+  },
+  {	.freq			= 5420,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+		   0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x08, 0x00, 0xfa, 0x00),
+	PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5),
+  },
+  {	.freq			= 5430,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+		   0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x08, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4),
+  },
+  {	.freq			= 5440,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x7e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+		   0x00, 0xfa, 0x00, 0x7e, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x08, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3),
+  },
+  {	.freq			= 5450,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x7d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+		   0x00, 0xfa, 0x00, 0x7d, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x08, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2),
+  },
+  {	.freq			= 5460,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+		   0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x08, 0x00, 0xf8, 0x00),
+	PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1),
+  },
+  {	.freq			= 5470,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+		   0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x08, 0x00, 0xf8, 0x00),
+	PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0),
+  },
+  {	.freq			= 5480,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x5d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+		   0x00, 0xf8, 0x00, 0x5d, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x08, 0x00, 0xf8, 0x00),
+	PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df),
+  },
+  {	.freq			= 5490,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x5c, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+		   0x00, 0xf8, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x08, 0x00, 0xf8, 0x00),
+	PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de),
+  },
+  {	.freq			= 5500,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x5c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x5c, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd),
+  },
+  {	.freq			= 5510,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd),
+  },
+  {	.freq			= 5520,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc),
+  },
+  {	.freq			= 5530,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db),
+  },
+  {	.freq			= 5540,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da),
+  },
+  {	.freq			= 5550,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9),
+  },
+  {	.freq			= 5560,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x2b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x2b, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8),
+  },
+  {	.freq			= 5570,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x2a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x2a, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7),
+  },
+  {	.freq			= 5580,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7),
+  },
+  {	.freq			= 5590,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6),
+  },
+  {	.freq			= 5600,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5),
+  },
+  {	.freq			= 5610,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4),
+  },
+  {	.freq			= 5620,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3),
+  },
+  {	.freq			= 5630,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2),
+  },
+  {	.freq			= 5640,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2),
+  },
+  {	.freq			= 5650,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf8, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf8, 0x00),
+	PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1),
+  },
+  {	.freq			= 5660,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0),
+  },
+  {	.freq			= 5670,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf),
+  },
+  {	.freq			= 5680,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce),
+  },
+  {	.freq			= 5690,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf6, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce),
+  },
+  {	.freq			= 5700,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf6, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd),
+  },
+  {	.freq			= 5710,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc),
+  },
+  {	.freq			= 5720,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5725,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5730,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5735,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5740,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9),
+  },
+  {	.freq			= 5745,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5750,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5755,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8),
+  },
+  {	.freq			= 5760,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5765,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5770,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5775,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5780,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6),
+  },
+  {	.freq			= 5785,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00,
+		   0x40, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5790,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00,
+		   0x40, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5795,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00,
+		   0x40, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5800,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5805,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4),
+  },
+  {	.freq			= 5810,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5815,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5820,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5825,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5830,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2),
+  },
+  {	.freq			= 5840,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2),
+  },
+  {	.freq			= 5850,
+	RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf4, 0x00),
+	PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1),
+  },
+  {	.freq			= 5860,
+	RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf2, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf2, 0x00),
+	PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0),
+  },
+  {	.freq			= 5870,
+	RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf2, 0x00),
+	PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf),
+  },
+  {	.freq			= 5880,
+	RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf2, 0x00),
+	PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf),
+  },
+  {	.freq			= 5890,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+		   0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x06, 0x00, 0xf2, 0x00),
+	PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be),
+  },
+  {	.freq			= 5900,
+	RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00,
+		   0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05,
+		   0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x05, 0x00, 0xf2, 0x00),
+	PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd),
+  },
+  {	.freq			= 5910,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00,
+		   0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05,
+		   0x00, 0xf2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x05, 0x00, 0xf2, 0x00),
+	PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc),
+  },
+  {	.freq			= 2412,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0f),
+	PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+  },
+  {	.freq			= 2417,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0f),
+	PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+  },
+  {	.freq			= 2422,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0f),
+	PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+  },
+  {	.freq			= 2427,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xfd, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0f, 0x00, 0xfd, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0f),
+	PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+  },
+  {	.freq			= 2432,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xfb, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0f, 0x00, 0xfb, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0f),
+	PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+  },
+  {	.freq			= 2437,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xfa, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0f),
+	PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+  },
+  {	.freq			= 2442,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf8, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0f),
+	PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+  },
+  {	.freq			= 2447,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf7, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0f, 0x00, 0xf7, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0f),
+	PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+  },
+  {	.freq			= 2452,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf6, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0f, 0x00, 0xf6, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0f),
+	PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+  },
+  {	.freq			= 2457,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf5, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0d, 0x00, 0xf5, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0d),
+	PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+  },
+  {	.freq			= 2462,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0d, 0x00, 0xf4, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0d),
+	PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+  },
+  {	.freq			= 2467,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf3, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0d, 0x00, 0xf3, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0d),
+	PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
+  },
+  {	.freq			= 2472,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0d, 0x00, 0xf2, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0d),
+	PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
+  },
+  {	.freq			= 2484,
+	RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf0, 0x00, 0x05, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0d, 0x00, 0xf0, 0x00, 0x05, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0d),
+	PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424),
+  },
+};
+
+static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_phy_rev4[] = {
+  {	.freq			= 4920,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216),
+  },
+  {	.freq			= 4930,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215),
+  },
+  {	.freq			= 4940,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214),
+  },
+  {	.freq			= 4950,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213),
+  },
+  {	.freq			= 4960,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212),
+  },
+  {	.freq			= 4970,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211),
+  },
+  {	.freq			= 4980,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f),
+  },
+  {	.freq			= 4990,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e),
+  },
+  {	.freq			= 5000,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d),
+  },
+  {	.freq			= 5010,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c),
+  },
+  {	.freq			= 5020,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b),
+  },
+  {	.freq			= 5030,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a),
+  },
+  {	.freq			= 5040,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209),
+  },
+  {	.freq			= 5050,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208),
+  },
+  {	.freq			= 5060,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207),
+  },
+  {	.freq			= 5070,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206),
+  },
+  {	.freq			= 5080,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205),
+  },
+  {	.freq			= 5090,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xff, 0x00),
+	PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204),
+  },
+  {	.freq			= 5100,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfe, 0x00),
+	PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203),
+  },
+  {	.freq			= 5110,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfe, 0x00),
+	PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202),
+  },
+  {	.freq			= 5120,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfe, 0x00),
+	PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201),
+  },
+  {	.freq			= 5130,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfe, 0x00),
+	PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200),
+  },
+  {	.freq			= 5140,
+	RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfe, 0x00),
+	PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff),
+  },
+  {	.freq			= 5160,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfe, 0x00),
+	PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd),
+  },
+  {	.freq			= 5170,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfe, 0x00),
+	PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc),
+  },
+  {	.freq			= 5180,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfe, 0x00),
+	PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb),
+  },
+  {	.freq			= 5190,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfe, 0x00),
+	PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa),
+  },
+  {	.freq			= 5200,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xef, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfc, 0x00, 0xef, 0x00, 0x0a, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9),
+  },
+  {	.freq			= 5210,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8),
+  },
+  {	.freq			= 5220,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfc, 0x00),
+	PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7),
+  },
+  {	.freq			= 5230,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6),
+  },
+  {	.freq			= 5240,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5),
+  },
+  {	.freq			= 5250,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4),
+  },
+  {	.freq			= 5260,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfc, 0x00),
+	PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3),
+  },
+  {	.freq			= 5270,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00,
+		   0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2),
+  },
+  {	.freq			= 5280,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00,
+		   0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1),
+  },
+  {	.freq			= 5290,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00,
+		   0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfc, 0x00),
+	PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0),
+  },
+  {	.freq			= 5300,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfa, 0x00),
+	PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0),
+  },
+  {	.freq			= 5310,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef),
+  },
+  {	.freq			= 5320,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee),
+  },
+  {	.freq			= 5330,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed),
+  },
+  {	.freq			= 5340,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfa, 0x00),
+	PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec),
+  },
+  {	.freq			= 5350,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb),
+  },
+  {	.freq			= 5360,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea),
+  },
+  {	.freq			= 5370,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9),
+  },
+  {	.freq			= 5380,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfa, 0x00),
+	PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8),
+  },
+  {	.freq			= 5390,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x8f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xfa, 0x00, 0x8f, 0x00, 0x08, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xfa, 0x00),
+	PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7),
+  },
+  {	.freq			= 5400,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xf8, 0x00),
+	PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6),
+  },
+  {	.freq			= 5410,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xf8, 0x00),
+	PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5),
+  },
+  {	.freq			= 5420,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xf8, 0x00),
+	PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5),
+  },
+  {	.freq			= 5430,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xf8, 0x00),
+	PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4),
+  },
+  {	.freq			= 5440,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x7e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xf8, 0x00, 0x7e, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xf8, 0x00),
+	PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3),
+  },
+  {	.freq			= 5450,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x7d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xf8, 0x00, 0x7d, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xf8, 0x00),
+	PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2),
+  },
+  {	.freq			= 5460,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xf8, 0x00),
+	PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1),
+  },
+  {	.freq			= 5470,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xf8, 0x00),
+	PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0),
+  },
+  {	.freq			= 5480,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x5d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xf8, 0x00, 0x5d, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xf8, 0x00),
+	PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df),
+  },
+  {	.freq			= 5490,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x5c, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+		   0x00, 0xf8, 0x00, 0x5c, 0x00, 0x07, 0x00, 0x7f,
+		   0x00, 0x0f, 0x00, 0xf8, 0x00),
+	PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de),
+  },
+  {	.freq			= 5500,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x5c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+		   0x00, 0xf6, 0x00, 0x5c, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0d, 0x00, 0xf6, 0x00),
+	PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd),
+  },
+  {	.freq			= 5510,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+		   0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0d, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd),
+  },
+  {	.freq			= 5520,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+		   0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0d, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc),
+  },
+  {	.freq			= 5530,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+		   0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0d, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db),
+  },
+  {	.freq			= 5540,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+		   0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0d, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da),
+  },
+  {	.freq			= 5550,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+		   0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0d, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9),
+  },
+  {	.freq			= 5560,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x2b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+		   0x00, 0xf6, 0x00, 0x2b, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0d, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8),
+  },
+  {	.freq			= 5570,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x2a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+		   0x00, 0xf6, 0x00, 0x2a, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0d, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7),
+  },
+  {	.freq			= 5580,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+		   0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0d, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7),
+  },
+  {	.freq			= 5590,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+		   0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f,
+		   0x00, 0x0d, 0x00, 0xf6, 0x00),
+	PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6),
+  },
+  {	.freq			= 5600,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x1a, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xf4, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5),
+  },
+  {	.freq			= 5610,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4),
+  },
+  {	.freq			= 5620,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3),
+  },
+  {	.freq			= 5630,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2),
+  },
+  {	.freq			= 5640,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2),
+  },
+  {	.freq			= 5650,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1),
+  },
+  {	.freq			= 5660,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0),
+  },
+  {	.freq			= 5670,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf),
+  },
+  {	.freq			= 5680,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce),
+  },
+  {	.freq			= 5690,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x07, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+		   0x00, 0xf4, 0x00, 0x07, 0x00, 0x04, 0x00, 0x7f,
+		   0x00, 0x0b, 0x00, 0xf4, 0x00),
+	PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce),
+  },
+  {	.freq			= 5700,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd),
+  },
+  {	.freq			= 5710,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc),
+  },
+  {	.freq			= 5720,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5725,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5730,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5735,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5740,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9),
+  },
+  {	.freq			= 5745,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5750,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5755,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8),
+  },
+  {	.freq			= 5760,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5765,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5770,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5775,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5780,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6),
+  },
+  {	.freq			= 5785,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00,
+		   0x40, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5790,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00,
+		   0x40, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5795,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00,
+		   0x40, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+		   0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f,
+		   0x00, 0x0a, 0x00, 0xf2, 0x00),
+	PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5800,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5805,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4),
+  },
+  {	.freq			= 5810,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5815,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5820,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5825,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5830,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2),
+  },
+  {	.freq			= 5840,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2),
+  },
+  {	.freq			= 5850,
+	RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1),
+  },
+  {	.freq			= 5860,
+	RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0),
+  },
+  {	.freq			= 5870,
+	RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf),
+  },
+  {	.freq			= 5880,
+	RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf),
+  },
+  {	.freq			= 5890,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+		   0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f,
+		   0x00, 0x09, 0x00, 0xf0, 0x00),
+	PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be),
+  },
+  {	.freq			= 5900,
+	RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00,
+		   0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf0, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf0, 0x00),
+	PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd),
+  },
+  {	.freq			= 5910,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00,
+		   0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07,
+		   0x00, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f,
+		   0x00, 0x07, 0x00, 0xf0, 0x00),
+	PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc),
+  },
+  {	.freq			= 2412,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+  },
+  {	.freq			= 2417,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+  },
+  {	.freq			= 2422,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+  },
+  {	.freq			= 2427,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xfd, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xfd, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+  },
+  {	.freq			= 2432,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xfb, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xfb, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+  },
+  {	.freq			= 2437,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xfa, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+  },
+  {	.freq			= 2442,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf8, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xf8, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+  },
+  {	.freq			= 2447,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf7, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xf7, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+  },
+  {	.freq			= 2452,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf6, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xf6, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+  },
+  {	.freq			= 2457,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf5, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xf5, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+  },
+  {	.freq			= 2462,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xf4, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+  },
+  {	.freq			= 2467,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf3, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xf3, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
+  },
+  {	.freq			= 2472,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xf2, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
+  },
+  {	.freq			= 2484,
+	RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0e, 0x00, 0xf0, 0x00, 0x04, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0e),
+	PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424),
+  },
+};
+
+static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev5[] = {
+  {	.freq			= 4920,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216),
+  },
+  {	.freq			= 4930,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215),
+  },
+  {	.freq			= 4940,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214),
+  },
+  {	.freq			= 4950,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213),
+  },
+  {	.freq			= 4960,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212),
+  },
+  {	.freq			= 4970,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211),
+  },
+  {	.freq			= 4980,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f),
+  },
+  {	.freq			= 4990,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e),
+  },
+  {	.freq			= 5000,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d),
+  },
+  {	.freq			= 5010,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c),
+  },
+  {	.freq			= 5020,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b),
+  },
+  {	.freq			= 5030,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a),
+  },
+  {	.freq			= 5040,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+		   0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209),
+  },
+  {	.freq			= 5050,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+		   0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208),
+  },
+  {	.freq			= 5060,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+		   0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207),
+  },
+  {	.freq			= 5070,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206),
+  },
+  {	.freq			= 5080,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205),
+  },
+  {	.freq			= 5090,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204),
+  },
+  {	.freq			= 5100,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203),
+  },
+  {	.freq			= 5110,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202),
+  },
+  {	.freq			= 5120,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201),
+  },
+  {	.freq			= 5130,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a,
+		   0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200),
+  },
+  {	.freq			= 5140,
+	RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a,
+		   0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff),
+  },
+  {	.freq			= 5160,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd),
+  },
+  {	.freq			= 5170,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc),
+  },
+  {	.freq			= 5180,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb),
+  },
+  {	.freq			= 5190,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa),
+  },
+  {	.freq			= 5200,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9),
+  },
+  {	.freq			= 5210,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8),
+  },
+  {	.freq			= 5220,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7),
+  },
+  {	.freq			= 5230,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08,
+		   0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x08, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6),
+  },
+  {	.freq			= 5240,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+		   0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70,
+		   0x00, 0x08, 0x00, 0x6d, 0x00),
+	PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5),
+  },
+  {	.freq			= 5250,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+		   0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70,
+		   0x00, 0x08, 0x00, 0x6d, 0x00),
+	PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4),
+  },
+  {	.freq			= 5260,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+		   0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70,
+		   0x00, 0x08, 0x00, 0x6d, 0x00),
+	PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3),
+  },
+  {	.freq			= 5270,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00,
+		   0xff, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2),
+  },
+  {	.freq			= 5280,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00,
+		   0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1),
+  },
+  {	.freq			= 5290,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00,
+		   0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0),
+  },
+  {	.freq			= 5300,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0),
+  },
+  {	.freq			= 5310,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef),
+  },
+  {	.freq			= 5320,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee),
+  },
+  {	.freq			= 5330,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed),
+  },
+  {	.freq			= 5340,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6b, 0x00),
+	PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec),
+  },
+  {	.freq			= 5350,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb),
+  },
+  {	.freq			= 5360,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea),
+  },
+  {	.freq			= 5370,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x5b, 0x00),
+	PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9),
+  },
+  {	.freq			= 5380,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x5a, 0x00),
+	PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8),
+  },
+  {	.freq			= 5390,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00,
+		   0xff, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x5a, 0x00),
+	PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7),
+  },
+  {	.freq			= 5400,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x5a, 0x00),
+	PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6),
+  },
+  {	.freq			= 5410,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+		   0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x05, 0x00, 0x5a, 0x00),
+	PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5),
+  },
+  {	.freq			= 5420,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+		   0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x05, 0x00, 0x5a, 0x00),
+	PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5),
+  },
+  {	.freq			= 5430,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+		   0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70,
+		   0x00, 0x05, 0x00, 0x59, 0x00),
+	PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4),
+  },
+  {	.freq			= 5440,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+		   0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70,
+		   0x00, 0x05, 0x00, 0x59, 0x00),
+	PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3),
+  },
+  {	.freq			= 5450,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+		   0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70,
+		   0x00, 0x05, 0x00, 0x59, 0x00),
+	PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2),
+  },
+  {	.freq			= 5460,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x69, 0x00),
+	PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1),
+  },
+  {	.freq			= 5470,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x69, 0x00),
+	PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0),
+  },
+  {	.freq			= 5480,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df),
+  },
+  {	.freq			= 5490,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00,
+		   0xc8, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de),
+  },
+  {	.freq			= 5500,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x78, 0x00),
+	PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd),
+  },
+  {	.freq			= 5510,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x78, 0x00),
+	PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd),
+  },
+  {	.freq			= 5520,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x78, 0x00),
+	PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc),
+  },
+  {	.freq			= 5530,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03,
+		   0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x03, 0x00, 0x78, 0x00),
+	PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db),
+  },
+  {	.freq			= 5540,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+		   0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x03, 0x00, 0x77, 0x00),
+	PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da),
+  },
+  {	.freq			= 5550,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+		   0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x03, 0x00, 0x77, 0x00),
+	PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9),
+  },
+  {	.freq			= 5560,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+		   0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x03, 0x00, 0x77, 0x00),
+	PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8),
+  },
+  {	.freq			= 5570,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x76, 0x00),
+	PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7),
+  },
+  {	.freq			= 5580,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x76, 0x00),
+	PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7),
+  },
+  {	.freq			= 5590,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00,
+		   0x84, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x76, 0x00),
+	PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6),
+  },
+  {	.freq			= 5600,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x76, 0x00),
+	PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5),
+  },
+  {	.freq			= 5610,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x76, 0x00),
+	PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4),
+  },
+  {	.freq			= 5620,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x76, 0x00),
+	PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3),
+  },
+  {	.freq			= 5630,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x76, 0x00),
+	PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2),
+  },
+  {	.freq			= 5640,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x75, 0x00),
+	PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2),
+  },
+  {	.freq			= 5650,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x75, 0x00),
+	PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1),
+  },
+  {	.freq			= 5660,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x75, 0x00),
+	PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0),
+  },
+  {	.freq			= 5670,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x74, 0x00),
+	PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf),
+  },
+  {	.freq			= 5680,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x74, 0x00),
+	PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce),
+  },
+  {	.freq			= 5690,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00,
+		   0x70, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x74, 0x00),
+	PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce),
+  },
+  {	.freq			= 5700,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x74, 0x00),
+	PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd),
+  },
+  {	.freq			= 5710,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x74, 0x00),
+	PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc),
+  },
+  {	.freq			= 5720,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x74, 0x00),
+	PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5725,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x74, 0x00),
+	PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5730,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x84, 0x00),
+	PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5735,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x83, 0x00),
+	PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5740,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x83, 0x00),
+	PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9),
+  },
+  {	.freq			= 5745,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x83, 0x00),
+	PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5750,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x83, 0x00),
+	PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5755,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x83, 0x00),
+	PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8),
+  },
+  {	.freq			= 5760,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x83, 0x00),
+	PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5765,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5770,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5775,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5780,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00,
+		   0x40, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6),
+  },
+  {	.freq			= 5785,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00,
+		   0x40, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5790,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00,
+		   0x40, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5795,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00,
+		   0x40, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5800,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5805,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4),
+  },
+  {	.freq			= 5810,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5815,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5820,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5825,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x82, 0x00),
+	PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5830,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x72, 0x00),
+	PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2),
+  },
+  {	.freq			= 5840,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x72, 0x00),
+	PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2),
+  },
+  {	.freq			= 5850,
+	RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x72, 0x00),
+	PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1),
+  },
+  {	.freq			= 5860,
+	RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x72, 0x00),
+	PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0),
+  },
+  {	.freq			= 5870,
+	RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x71, 0x00),
+	PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf),
+  },
+  {	.freq			= 5880,
+	RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x71, 0x00),
+	PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf),
+  },
+  {	.freq			= 5890,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x88, 0x04, 0x00,
+		   0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x71, 0x00),
+	PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be),
+  },
+  {	.freq			= 5900,
+	RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x71, 0x00),
+	PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd),
+  },
+  {	.freq			= 5910,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x87, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x71, 0x00),
+	PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc),
+  },
+  {	.freq			= 2412,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0b, 0x00, 0x1f, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0b),
+	PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+  },
+  {	.freq			= 2417,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0a, 0x00, 0x1f, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0a),
+	PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+  },
+  {	.freq			= 2422,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0a),
+	PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+  },
+  {	.freq			= 2427,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x0d, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x0a),
+	PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+  },
+  {	.freq			= 2432,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x0a),
+	PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+  },
+  {	.freq			= 2437,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x0b, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x0a),
+	PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+  },
+  {	.freq			= 2442,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x09, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x0a),
+	PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+  },
+  {	.freq			= 2447,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x09, 0x00, 0x08, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x09),
+	PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+  },
+  {	.freq			= 2452,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x07, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x09, 0x00, 0x07, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x09),
+	PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+  },
+  {	.freq			= 2457,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0d, 0x00, 0x09, 0x00, 0x06, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0d, 0x00, 0x09),
+	PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+  },
+  {	.freq			= 2462,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x05, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0d, 0x00, 0x09, 0x00, 0x05, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0d, 0x00, 0x09),
+	PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+  },
+  {	.freq			= 2467,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0d, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0d, 0x00, 0x08),
+	PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
+  },
+  {	.freq			= 2472,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0d, 0x00, 0x08, 0x00, 0x03, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0d, 0x00, 0x08),
+	PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
+  },
+  {	.freq			= 2484,
+	RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0d, 0x00, 0x08),
+	PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424),
+  },
+};
+
+static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev6[] = {
+  {	.freq			= 4920,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216),
+  },
+  {	.freq			= 4930,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215),
+  },
+  {	.freq			= 4940,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214),
+  },
+  {	.freq			= 4950,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213),
+  },
+  {	.freq			= 4960,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212),
+  },
+  {	.freq			= 4970,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211),
+  },
+  {	.freq			= 4980,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f),
+  },
+  {	.freq			= 4990,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e),
+  },
+  {	.freq			= 5000,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d),
+  },
+  {	.freq			= 5010,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c),
+  },
+  {	.freq			= 5020,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b),
+  },
+  {	.freq			= 5030,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a),
+  },
+  {	.freq			= 5040,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209),
+  },
+  {	.freq			= 5050,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208),
+  },
+  {	.freq			= 5060,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207),
+  },
+  {	.freq			= 5070,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206),
+  },
+  {	.freq			= 5080,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205),
+  },
+  {	.freq			= 5090,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204),
+  },
+  {	.freq			= 5100,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203),
+  },
+  {	.freq			= 5110,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202),
+  },
+  {	.freq			= 5120,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201),
+  },
+  {	.freq			= 5130,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200),
+  },
+  {	.freq			= 5140,
+	RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff),
+  },
+  {	.freq			= 5160,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+		   0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd),
+  },
+  {	.freq			= 5170,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+		   0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc),
+  },
+  {	.freq			= 5180,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e,
+		   0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb),
+  },
+  {	.freq			= 5190,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa),
+  },
+  {	.freq			= 5200,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9),
+  },
+  {	.freq			= 5210,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8),
+  },
+  {	.freq			= 5220,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7),
+  },
+  {	.freq			= 5230,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xee, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6),
+  },
+  {	.freq			= 5240,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xee, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5),
+  },
+  {	.freq			= 5250,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xed, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4),
+  },
+  {	.freq			= 5260,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00,
+		   0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3),
+  },
+  {	.freq			= 5270,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00,
+		   0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2),
+  },
+  {	.freq			= 5280,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1),
+  },
+  {	.freq			= 5290,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0),
+  },
+  {	.freq			= 5300,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0),
+  },
+  {	.freq			= 5310,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef),
+  },
+  {	.freq			= 5320,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee),
+  },
+  {	.freq			= 5330,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+		   0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed),
+  },
+  {	.freq			= 5340,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+		   0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec),
+  },
+  {	.freq			= 5350,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+		   0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+		   0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb),
+  },
+  {	.freq			= 5360,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+		   0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea),
+  },
+  {	.freq			= 5370,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+		   0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9),
+  },
+  {	.freq			= 5380,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb8, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8),
+  },
+  {	.freq			= 5390,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7),
+  },
+  {	.freq			= 5400,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6),
+  },
+  {	.freq			= 5410,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb7, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5),
+  },
+  {	.freq			= 5420,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xa7, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5),
+  },
+  {	.freq			= 5430,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00,
+		   0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4),
+  },
+  {	.freq			= 5440,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3),
+  },
+  {	.freq			= 5450,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0x95, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2),
+  },
+  {	.freq			= 5460,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0x95, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1),
+  },
+  {	.freq			= 5470,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0x94, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0),
+  },
+  {	.freq			= 5480,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x84, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df),
+  },
+  {	.freq			= 5490,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x83, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de),
+  },
+  {	.freq			= 5500,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x82, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd),
+  },
+  {	.freq			= 5510,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x82, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd),
+  },
+  {	.freq			= 5520,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x72, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc),
+  },
+  {	.freq			= 5530,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00,
+		   0x72, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db),
+  },
+  {	.freq			= 5540,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00,
+		   0x71, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da),
+  },
+  {	.freq			= 5550,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+		   0x61, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9),
+  },
+  {	.freq			= 5560,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+		   0x61, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8),
+  },
+  {	.freq			= 5570,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+		   0x61, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7),
+  },
+  {	.freq			= 5580,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00,
+		   0x60, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+		   0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x08, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7),
+  },
+  {	.freq			= 5590,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00,
+		   0x50, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+		   0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x08, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6),
+  },
+  {	.freq			= 5600,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+		   0x50, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+		   0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x08, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5),
+  },
+  {	.freq			= 5610,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+		   0x50, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+		   0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x08, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4),
+  },
+  {	.freq			= 5620,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+		   0x50, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+		   0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x07, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3),
+  },
+  {	.freq			= 5630,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x50, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+		   0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x07, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2),
+  },
+  {	.freq			= 5640,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+		   0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x07, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2),
+  },
+  {	.freq			= 5650,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+		   0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x07, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1),
+  },
+  {	.freq			= 5660,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0),
+  },
+  {	.freq			= 5670,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf),
+  },
+  {	.freq			= 5680,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce),
+  },
+  {	.freq			= 5690,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce),
+  },
+  {	.freq			= 5700,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6e, 0x00),
+	PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd),
+  },
+  {	.freq			= 5710,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6e, 0x00),
+	PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc),
+  },
+  {	.freq			= 5720,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6e, 0x00),
+	PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5725,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6e, 0x00),
+	PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5730,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6e, 0x00),
+	PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5735,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6d, 0x00),
+	PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5740,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6d, 0x00),
+	PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9),
+  },
+  {	.freq			= 5745,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6d, 0x00),
+	PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5750,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6d, 0x00),
+	PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5755,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x10, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8),
+  },
+  {	.freq			= 5760,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00,
+		   0x10, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5765,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00,
+		   0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5770,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+		   0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5775,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+		   0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5780,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+		   0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6),
+  },
+  {	.freq			= 5785,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5790,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5795,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5800,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5805,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6a, 0x00),
+	PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4),
+  },
+  {	.freq			= 5810,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6a, 0x00),
+	PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5815,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6a, 0x00),
+	PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5820,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6a, 0x00),
+	PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5825,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x69, 0x00),
+	PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5830,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x69, 0x00),
+	PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2),
+  },
+  {	.freq			= 5840,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x69, 0x00),
+	PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2),
+  },
+  {	.freq			= 5850,
+	RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x69, 0x00),
+	PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1),
+  },
+  {	.freq			= 5860,
+	RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x69, 0x00),
+	PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0),
+  },
+  {	.freq			= 5870,
+	RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf),
+  },
+  {	.freq			= 5880,
+	RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf),
+  },
+  {	.freq			= 5890,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be),
+  },
+  {	.freq			= 5900,
+	RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd),
+  },
+  {	.freq			= 5910,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc),
+  },
+  {	.freq			= 2412,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0b, 0x00, 0x0a),
+	PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+  },
+  {	.freq			= 2417,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0b, 0x00, 0x0a),
+	PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+  },
+  {	.freq			= 2422,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x67, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0b, 0x00, 0x0a, 0x00, 0x67, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0b, 0x00, 0x0a),
+	PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+  },
+  {	.freq			= 2427,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x57, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x0a, 0x00, 0x57, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x0a),
+	PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+  },
+  {	.freq			= 2432,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x56, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x0a, 0x00, 0x56, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x0a),
+	PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+  },
+  {	.freq			= 2437,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x46, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x0a, 0x00, 0x46, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x0a),
+	PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+  },
+  {	.freq			= 2442,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x0a, 0x00, 0x45, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x0a),
+	PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+  },
+  {	.freq			= 2447,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x09),
+	PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+  },
+  {	.freq			= 2452,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x23, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x09, 0x00, 0x23, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x09),
+	PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+  },
+  {	.freq			= 2457,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x12, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x09, 0x00, 0x12, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x09),
+	PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+  },
+  {	.freq			= 2462,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x09, 0x00, 0x09, 0x00, 0x02, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x09, 0x00, 0x09),
+	PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+  },
+  {	.freq			= 2467,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x09, 0x00, 0x09),
+	PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
+  },
+  {	.freq			= 2472,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x09, 0x00, 0x09),
+	PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
+  },
+  {	.freq			= 2484,
+	RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x09, 0x00, 0x09),
+	PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424),
+  },
+};
+
+static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev7_9[] = {
+  {	.freq			= 4920,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216),
+  },
+  {	.freq			= 4930,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215),
+  },
+  {	.freq			= 4940,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214),
+  },
+  {	.freq			= 4950,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213),
+  },
+  {	.freq			= 4960,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212),
+  },
+  {	.freq			= 4970,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211),
+  },
+  {	.freq			= 4980,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f),
+  },
+  {	.freq			= 4990,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e),
+  },
+  {	.freq			= 5000,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d),
+  },
+  {	.freq			= 5010,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c),
+  },
+  {	.freq			= 5020,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b),
+  },
+  {	.freq			= 5030,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+		   0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a),
+  },
+  {	.freq			= 5040,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+		   0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209),
+  },
+  {	.freq			= 5050,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+		   0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208),
+  },
+  {	.freq			= 5060,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+		   0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207),
+  },
+  {	.freq			= 5070,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206),
+  },
+  {	.freq			= 5080,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205),
+  },
+  {	.freq			= 5090,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204),
+  },
+  {	.freq			= 5100,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203),
+  },
+  {	.freq			= 5110,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202),
+  },
+  {	.freq			= 5120,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+		   0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201),
+  },
+  {	.freq			= 5130,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a,
+		   0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200),
+  },
+  {	.freq			= 5140,
+	RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a,
+		   0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff),
+  },
+  {	.freq			= 5160,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd),
+  },
+  {	.freq			= 5170,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc),
+  },
+  {	.freq			= 5180,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb),
+  },
+  {	.freq			= 5190,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa),
+  },
+  {	.freq			= 5200,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9),
+  },
+  {	.freq			= 5210,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8),
+  },
+  {	.freq			= 5220,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xfe, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+		   0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x09, 0x00, 0x6e, 0x00),
+	PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7),
+  },
+  {	.freq			= 5230,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xee, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08,
+		   0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70,
+		   0x00, 0x08, 0x00, 0x6e, 0x00),
+	PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6),
+  },
+  {	.freq			= 5240,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xee, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+		   0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70,
+		   0x00, 0x08, 0x00, 0x6d, 0x00),
+	PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5),
+  },
+  {	.freq			= 5250,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xed, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+		   0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70,
+		   0x00, 0x08, 0x00, 0x6d, 0x00),
+	PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4),
+  },
+  {	.freq			= 5260,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00,
+		   0xed, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+		   0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70,
+		   0x00, 0x08, 0x00, 0x6d, 0x00),
+	PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3),
+  },
+  {	.freq			= 5270,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00,
+		   0xed, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2),
+  },
+  {	.freq			= 5280,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1),
+  },
+  {	.freq			= 5290,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0),
+  },
+  {	.freq			= 5300,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0),
+  },
+  {	.freq			= 5310,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef),
+  },
+  {	.freq			= 5320,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdb, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee),
+  },
+  {	.freq			= 5330,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xcb, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed),
+  },
+  {	.freq			= 5340,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xca, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07,
+		   0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x07, 0x00, 0x6b, 0x00),
+	PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec),
+  },
+  {	.freq			= 5350,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+		   0xca, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb),
+  },
+  {	.freq			= 5360,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+		   0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea),
+  },
+  {	.freq			= 5370,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+		   0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x7b, 0x00),
+	PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9),
+  },
+  {	.freq			= 5380,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb8, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x7a, 0x00),
+	PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8),
+  },
+  {	.freq			= 5390,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb8, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x7a, 0x00),
+	PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7),
+  },
+  {	.freq			= 5400,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb8, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+		   0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x06, 0x00, 0x7a, 0x00),
+	PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6),
+  },
+  {	.freq			= 5410,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb7, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+		   0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x05, 0x00, 0x7a, 0x00),
+	PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5),
+  },
+  {	.freq			= 5420,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xa7, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+		   0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70,
+		   0x00, 0x05, 0x00, 0x7a, 0x00),
+	PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5),
+  },
+  {	.freq			= 5430,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00,
+		   0xa6, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+		   0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70,
+		   0x00, 0x05, 0x00, 0x79, 0x00),
+	PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4),
+  },
+  {	.freq			= 5440,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0xa6, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+		   0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70,
+		   0x00, 0x05, 0x00, 0x79, 0x00),
+	PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3),
+  },
+  {	.freq			= 5450,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0x95, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+		   0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70,
+		   0x00, 0x05, 0x00, 0x79, 0x00),
+	PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2),
+  },
+  {	.freq			= 5460,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0x95, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x79, 0x00),
+	PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1),
+  },
+  {	.freq			= 5470,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0x94, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x79, 0x00),
+	PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0),
+  },
+  {	.freq			= 5480,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x84, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x78, 0x00),
+	PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df),
+  },
+  {	.freq			= 5490,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x83, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x78, 0x00),
+	PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de),
+  },
+  {	.freq			= 5500,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x82, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x78, 0x00),
+	PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd),
+  },
+  {	.freq			= 5510,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x82, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x78, 0x00),
+	PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd),
+  },
+  {	.freq			= 5520,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x72, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+		   0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x04, 0x00, 0x78, 0x00),
+	PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc),
+  },
+  {	.freq			= 5530,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00,
+		   0x72, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03,
+		   0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70,
+		   0x00, 0x03, 0x00, 0x78, 0x00),
+	PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db),
+  },
+  {	.freq			= 5540,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00,
+		   0x71, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+		   0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x03, 0x00, 0x77, 0x00),
+	PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da),
+  },
+  {	.freq			= 5550,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+		   0x61, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+		   0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x03, 0x00, 0x77, 0x00),
+	PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9),
+  },
+  {	.freq			= 5560,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+		   0x61, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+		   0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x03, 0x00, 0x77, 0x00),
+	PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8),
+  },
+  {	.freq			= 5570,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+		   0x61, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x76, 0x00),
+	PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7),
+  },
+  {	.freq			= 5580,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00,
+		   0x60, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x86, 0x00),
+	PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7),
+  },
+  {	.freq			= 5590,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00,
+		   0x50, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x86, 0x00),
+	PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6),
+  },
+  {	.freq			= 5600,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+		   0x50, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x86, 0x00),
+	PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5),
+  },
+  {	.freq			= 5610,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+		   0x50, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x86, 0x00),
+	PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4),
+  },
+  {	.freq			= 5620,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+		   0x50, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x86, 0x00),
+	PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3),
+  },
+  {	.freq			= 5630,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x50, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x86, 0x00),
+	PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2),
+  },
+  {	.freq			= 5640,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+		   0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x02, 0x00, 0x85, 0x00),
+	PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2),
+  },
+  {	.freq			= 5650,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x85, 0x00),
+	PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1),
+  },
+  {	.freq			= 5660,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x85, 0x00),
+	PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0),
+  },
+  {	.freq			= 5670,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x84, 0x00),
+	PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf),
+  },
+  {	.freq			= 5680,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x84, 0x00),
+	PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce),
+  },
+  {	.freq			= 5690,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x94, 0x00),
+	PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce),
+  },
+  {	.freq			= 5700,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x94, 0x00),
+	PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd),
+  },
+  {	.freq			= 5710,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x94, 0x00),
+	PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc),
+  },
+  {	.freq			= 5720,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x94, 0x00),
+	PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5725,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x94, 0x00),
+	PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5730,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+		   0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x01, 0x00, 0x94, 0x00),
+	PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5735,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x93, 0x00),
+	PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5740,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x93, 0x00),
+	PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9),
+  },
+  {	.freq			= 5745,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x93, 0x00),
+	PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5750,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x93, 0x00),
+	PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5755,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x10, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x93, 0x00),
+	PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8),
+  },
+  {	.freq			= 5760,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00,
+		   0x10, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x93, 0x00),
+	PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5765,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00,
+		   0x10, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5770,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+		   0x10, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5775,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+		   0x10, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5780,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+		   0x10, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6),
+  },
+  {	.freq			= 5785,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5790,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5795,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5800,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5805,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4),
+  },
+  {	.freq			= 5810,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5815,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5820,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5825,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5830,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2),
+  },
+  {	.freq			= 5840,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2),
+  },
+  {	.freq			= 5850,
+	RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1),
+  },
+  {	.freq			= 5860,
+	RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x92, 0x00),
+	PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0),
+  },
+  {	.freq			= 5870,
+	RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x91, 0x00),
+	PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf),
+  },
+  {	.freq			= 5880,
+	RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x91, 0x00),
+	PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf),
+  },
+  {	.freq			= 5890,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x91, 0x00),
+	PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be),
+  },
+  {	.freq			= 5900,
+	RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x91, 0x00),
+	PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd),
+  },
+  {	.freq			= 5910,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+		   0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+		   0x00, 0x00, 0x00, 0x91, 0x00),
+	PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc),
+  },
+  {	.freq			= 2412,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0b, 0x00, 0x89, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0b),
+	PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+  },
+  {	.freq			= 2417,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0a),
+	PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+  },
+  {	.freq			= 2422,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0f, 0x00, 0x0a),
+	PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+  },
+  {	.freq			= 2427,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x0a),
+	PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+  },
+  {	.freq			= 2432,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x0a),
+	PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+  },
+  {	.freq			= 2437,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x0a),
+	PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+  },
+  {	.freq			= 2442,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x66, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x0a),
+	PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+  },
+  {	.freq			= 2447,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x09),
+	PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+  },
+  {	.freq			= 2452,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0e, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0e, 0x00, 0x09),
+	PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+  },
+  {	.freq			= 2457,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0d, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0d, 0x00, 0x09),
+	PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+  },
+  {	.freq			= 2462,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0d, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0d, 0x00, 0x09),
+	PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+  },
+  {	.freq			= 2467,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0d, 0x00, 0x08, 0x00, 0x22, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0d, 0x00, 0x08),
+	PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
+  },
+  {	.freq			= 2472,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0d, 0x00, 0x08, 0x00, 0x11, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0d, 0x00, 0x08),
+	PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
+  },
+  {	.freq			= 2484,
+	RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0d, 0x00, 0x08),
+	PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424),
+  },
+};
+
+static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev8[] = {
+  {	.freq			= 4920,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216),
+  },
+  {	.freq			= 4930,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215),
+  },
+  {	.freq			= 4940,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214),
+  },
+  {	.freq			= 4950,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213),
+  },
+  {	.freq			= 4960,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212),
+  },
+  {	.freq			= 4970,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211),
+  },
+  {	.freq			= 4980,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f),
+  },
+  {	.freq			= 4990,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e),
+  },
+  {	.freq			= 5000,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d),
+  },
+  {	.freq			= 5010,
+	RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c),
+  },
+  {	.freq			= 5020,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b),
+  },
+  {	.freq			= 5030,
+	RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a),
+  },
+  {	.freq			= 5040,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209),
+  },
+  {	.freq			= 5050,
+	RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208),
+  },
+  {	.freq			= 5060,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207),
+  },
+  {	.freq			= 5070,
+	RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206),
+  },
+  {	.freq			= 5080,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205),
+  },
+  {	.freq			= 5090,
+	RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204),
+  },
+  {	.freq			= 5100,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203),
+  },
+  {	.freq			= 5110,
+	RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202),
+  },
+  {	.freq			= 5120,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201),
+  },
+  {	.freq			= 5130,
+	RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200),
+  },
+  {	.freq			= 5140,
+	RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+		   0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77,
+		   0x00, 0x0f, 0x00, 0x6f, 0x00),
+	PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff),
+  },
+  {	.freq			= 5160,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+		   0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd),
+  },
+  {	.freq			= 5170,
+	RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+		   0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc),
+  },
+  {	.freq			= 5180,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e,
+		   0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77,
+		   0x00, 0x0e, 0x00, 0x6f, 0x00),
+	PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb),
+  },
+  {	.freq			= 5190,
+	RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa),
+  },
+  {	.freq			= 5200,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9),
+  },
+  {	.freq			= 5210,
+	RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+		   0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8),
+  },
+  {	.freq			= 5220,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7),
+  },
+  {	.freq			= 5230,
+	RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xee, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6),
+  },
+  {	.freq			= 5240,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xee, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5),
+  },
+  {	.freq			= 5250,
+	RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+		   0xed, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4),
+  },
+  {	.freq			= 5260,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00,
+		   0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
+		   0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77,
+		   0x00, 0x0d, 0x00, 0x6f, 0x00),
+	PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3),
+  },
+  {	.freq			= 5270,
+	RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00,
+		   0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2),
+  },
+  {	.freq			= 5280,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1),
+  },
+  {	.freq			= 5290,
+	RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0),
+  },
+  {	.freq			= 5300,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0),
+  },
+  {	.freq			= 5310,
+	RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef),
+  },
+  {	.freq			= 5320,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+		   0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+		   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0c, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee),
+  },
+  {	.freq			= 5330,
+	RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+		   0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed),
+  },
+  {	.freq			= 5340,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+		   0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+		   0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec),
+  },
+  {	.freq			= 5350,
+	RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+		   0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+		   0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0b, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb),
+  },
+  {	.freq			= 5360,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+		   0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea),
+  },
+  {	.freq			= 5370,
+	RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+		   0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9),
+  },
+  {	.freq			= 5380,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb8, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8),
+  },
+  {	.freq			= 5390,
+	RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7),
+  },
+  {	.freq			= 5400,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6),
+  },
+  {	.freq			= 5410,
+	RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xb7, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5),
+  },
+  {	.freq			= 5420,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+		   0xa7, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5),
+  },
+  {	.freq			= 5430,
+	RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00,
+		   0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+		   0x00, 0x0a, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4),
+  },
+  {	.freq			= 5440,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3),
+  },
+  {	.freq			= 5450,
+	RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0x95, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2),
+  },
+  {	.freq			= 5460,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0x95, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1),
+  },
+  {	.freq			= 5470,
+	RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+		   0x94, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0),
+  },
+  {	.freq			= 5480,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x84, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df),
+  },
+  {	.freq			= 5490,
+	RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x83, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de),
+  },
+  {	.freq			= 5500,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x82, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd),
+  },
+  {	.freq			= 5510,
+	RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x82, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd),
+  },
+  {	.freq			= 5520,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+		   0x72, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc),
+  },
+  {	.freq			= 5530,
+	RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00,
+		   0x72, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db),
+  },
+  {	.freq			= 5540,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00,
+		   0x71, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da),
+  },
+  {	.freq			= 5550,
+	RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+		   0x61, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9),
+  },
+  {	.freq			= 5560,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+		   0x61, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8),
+  },
+  {	.freq			= 5570,
+	RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+		   0x61, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+		   0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x09, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7),
+  },
+  {	.freq			= 5580,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00,
+		   0x60, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+		   0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x08, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7),
+  },
+  {	.freq			= 5590,
+	RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00,
+		   0x50, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+		   0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x08, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6),
+  },
+  {	.freq			= 5600,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+		   0x50, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+		   0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x08, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5),
+  },
+  {	.freq			= 5610,
+	RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+		   0x50, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+		   0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x08, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4),
+  },
+  {	.freq			= 5620,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+		   0x50, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+		   0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x07, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3),
+  },
+  {	.freq			= 5630,
+	RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x50, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+		   0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x07, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2),
+  },
+  {	.freq			= 5640,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+		   0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x07, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2),
+  },
+  {	.freq			= 5650,
+	RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+		   0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x07, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1),
+  },
+  {	.freq			= 5660,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0),
+  },
+  {	.freq			= 5670,
+	RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+		   0x40, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf),
+  },
+  {	.freq			= 5680,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce),
+  },
+  {	.freq			= 5690,
+	RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6f, 0x00),
+	PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce),
+  },
+  {	.freq			= 5700,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6e, 0x00),
+	PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd),
+  },
+  {	.freq			= 5710,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6e, 0x00),
+	PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc),
+  },
+  {	.freq			= 5720,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6e, 0x00),
+	PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5725,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+		   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6e, 0x00),
+	PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb),
+  },
+  {	.freq			= 5730,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6e, 0x00),
+	PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5735,
+	RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6d, 0x00),
+	PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca),
+  },
+  {	.freq			= 5740,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6d, 0x00),
+	PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9),
+  },
+  {	.freq			= 5745,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+		   0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x06, 0x00, 0x6d, 0x00),
+	PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5750,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x20, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6d, 0x00),
+	PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9),
+  },
+  {	.freq			= 5755,
+	RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+		   0x10, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8),
+  },
+  {	.freq			= 5760,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00,
+		   0x10, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5765,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00,
+		   0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6c, 0x00),
+	PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8),
+  },
+  {	.freq			= 5770,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+		   0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5775,
+	RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+		   0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7),
+  },
+  {	.freq			= 5780,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+		   0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6),
+  },
+  {	.freq			= 5785,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5790,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6),
+  },
+  {	.freq			= 5795,
+	RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5800,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6b, 0x00),
+	PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5),
+  },
+  {	.freq			= 5805,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6a, 0x00),
+	PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4),
+  },
+  {	.freq			= 5810,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6a, 0x00),
+	PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5815,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6a, 0x00),
+	PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4),
+  },
+  {	.freq			= 5820,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x6a, 0x00),
+	PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5825,
+	RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04,
+		   0x10, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x69, 0x00),
+	PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3),
+  },
+  {	.freq			= 5830,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+		   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x05, 0x00, 0x69, 0x00),
+	PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2),
+  },
+  {	.freq			= 5840,
+	RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x69, 0x00),
+	PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2),
+  },
+  {	.freq			= 5850,
+	RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x69, 0x00),
+	PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1),
+  },
+  {	.freq			= 5860,
+	RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x69, 0x00),
+	PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0),
+  },
+  {	.freq			= 5870,
+	RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf),
+  },
+  {	.freq			= 5880,
+	RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf),
+  },
+  {	.freq			= 5890,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be),
+  },
+  {	.freq			= 5900,
+	RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd),
+  },
+  {	.freq			= 5910,
+	RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04,
+		   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+		   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+		   0x00, 0x04, 0x00, 0x68, 0x00),
+	PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc),
+  },
+  {	.freq			= 2412,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0b, 0x00, 0x0a),
+	PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+  },
+  {	.freq			= 2417,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0b, 0x00, 0x0a),
+	PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+  },
+  {	.freq			= 2422,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x67, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0b, 0x00, 0x0a),
+	PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+  },
+  {	.freq			= 2427,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x57, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x0a),
+	PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+  },
+  {	.freq			= 2432,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x56, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x0a),
+	PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+  },
+  {	.freq			= 2437,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x46, 0x00, 0x03, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x0a),
+	PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+  },
+  {	.freq			= 2442,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x0a),
+	PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+  },
+  {	.freq			= 2447,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x09),
+	PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+  },
+  {	.freq			= 2452,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x23, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x09),
+	PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+  },
+  {	.freq			= 2457,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x12, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x0a, 0x00, 0x09),
+	PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+  },
+  {	.freq			= 2462,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x09, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x09, 0x00, 0x09),
+	PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+  },
+  {	.freq			= 2467,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x09, 0x00, 0x09, 0x00, 0x22, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x09, 0x00, 0x09),
+	PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
+  },
+  {	.freq			= 2472,
+	RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00,
+		   0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x09, 0x00, 0x09),
+	PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
+  },
+  {	.freq			= 2484,
+	RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04,
+		   0x16, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00,
+		   0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+		   0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00,
+		   0x70, 0x00, 0x09, 0x00, 0x09),
+	PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424),
+  },
+};
+
+static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev11[] = {
+	{
+		.freq			= 4920,
+		RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+			   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+			   0x00, 0x0f, 0x00, 0x6f, 0x00),
+		PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216),
+	},
+	{
+		.freq			= 4930,
+		RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+			   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+			   0x00, 0x0f, 0x00, 0x6f, 0x00),
+		PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215),
+	},
+	{
+		.freq			= 4940,
+		RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+			   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+			   0x00, 0x0f, 0x00, 0x6f, 0x00),
+		PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214),
+	},
+	{
+		.freq			= 4950,
+		RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+			   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+			   0x00, 0x0f, 0x00, 0x6f, 0x00),
+		PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213),
+	},
+	{
+		.freq			= 4960,
+		RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+			   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+			   0x00, 0x0f, 0x00, 0x6f, 0x00),
+		PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212),
+	},
+	{
+		.freq			= 4970,
+		RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+			   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+			   0x00, 0x0f, 0x00, 0x6f, 0x00),
+		PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211),
+	},
+	{
+		.freq			= 4980,
+		RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+			   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+			   0x00, 0x0f, 0x00, 0x6f, 0x00),
+		PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f),
+	},
+	{
+		.freq			= 4990,
+		RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+			   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+			   0x00, 0x0f, 0x00, 0x6f, 0x00),
+		PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e),
+	},
+	{
+		.freq			= 5000,
+		RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+			   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+			   0x00, 0x0f, 0x00, 0x6f, 0x00),
+		PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d),
+	},
+	{
+		.freq			= 5010,
+		RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+			   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+			   0x00, 0x0f, 0x00, 0x6f, 0x00),
+		PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c),
+	},
+	{
+		.freq			= 5020,
+		RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+			   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+			   0x00, 0x0f, 0x00, 0x6f, 0x00),
+		PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b),
+	},
+	{
+		.freq			= 5030,
+		RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+			   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+			   0x00, 0x0f, 0x00, 0x6f, 0x00),
+		PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a),
+	},
+	{
+		.freq			= 5040,
+		RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+			   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+			   0x00, 0x0f, 0x00, 0x6f, 0x00),
+		PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209),
+	},
+	{
+		.freq			= 5050,
+		RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+			   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+			   0x00, 0x0f, 0x00, 0x6f, 0x00),
+		PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208),
+	},
+	{
+		.freq			= 5060,
+		RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+			   0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+			   0x00, 0x0f, 0x00, 0x6f, 0x00),
+		PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207),
+	},
+	{
+		.freq			= 5070,
+		RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+			   0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77,
+			   0x00, 0x0f, 0x00, 0x6f, 0x00),
+		PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206),
+	},
+	{
+		.freq			= 5080,
+		RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+			   0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77,
+			   0x00, 0x0f, 0x00, 0x6f, 0x00),
+		PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205),
+	},
+	{
+		.freq			= 5090,
+		RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+			   0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77,
+			   0x00, 0x0f, 0x00, 0x6f, 0x00),
+		PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204),
+	},
+	{
+		.freq			= 5100,
+		RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+			   0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77,
+			   0x00, 0x0f, 0x00, 0x6f, 0x00),
+		PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203),
+	},
+	{
+		.freq			= 5110,
+		RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+			   0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77,
+			   0x00, 0x0f, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202),
+	},
+	{
+		.freq			= 5120,
+		RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+			   0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77,
+			   0x00, 0x0f, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201),
+	},
+	{
+		.freq			= 5130,
+		RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+			   0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77,
+			   0x00, 0x0f, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200),
+	},
+	{
+		.freq			= 5140,
+		RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+			   0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77,
+			   0x00, 0x0f, 0x00, 0x6f, 0x00),
+		PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff),
+	},
+	{
+		.freq			= 5160,
+		RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+			   0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77,
+			   0x00, 0x0e, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd),
+	},
+	{
+		.freq			= 5170,
+		RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+			   0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+			   0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77,
+			   0x00, 0x0e, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc),
+	},
+	{
+		.freq			= 5180,
+		RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+			   0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e,
+			   0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77,
+			   0x00, 0x0e, 0x00, 0x6f, 0x00),
+		PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb),
+	},
+	{
+		.freq			= 5190,
+		RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+			   0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
+			   0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77,
+			   0x00, 0x0d, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa),
+	},
+	{
+		.freq			= 5200,
+		RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+			   0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+			   0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77,
+			   0x00, 0x0d, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9),
+	},
+	{
+		.freq			= 5210,
+		RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+			   0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+			   0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77,
+			   0x00, 0x0d, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8),
+	},
+	{
+		.freq			= 5220,
+		RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+			   0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+			   0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77,
+			   0x00, 0x0d, 0x00, 0x6f, 0x00),
+		PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7),
+	},
+	{
+		.freq			= 5230,
+		RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+			   0xee, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+			   0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77,
+			   0x00, 0x0d, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6),
+	},
+	{
+		.freq			= 5240,
+		RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+			   0xee, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+			   0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77,
+			   0x00, 0x0d, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5),
+	},
+	{
+		.freq			= 5250,
+		RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+			   0xed, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+			   0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77,
+			   0x00, 0x0d, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4),
+	},
+	{
+		.freq			= 5260,
+		RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00,
+			   0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
+			   0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77,
+			   0x00, 0x0d, 0x00, 0x6f, 0x00),
+		PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3),
+	},
+	{
+		.freq			= 5270,
+		RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00,
+			   0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
+			   0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77,
+			   0x00, 0x0c, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2),
+	},
+	{
+		.freq			= 5280,
+		RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+			   0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+			   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+			   0x00, 0x0c, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1),
+	},
+	{
+		.freq			= 5290,
+		RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+			   0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+			   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+			   0x00, 0x0c, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0),
+	},
+	{
+		.freq			= 5300,
+		RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+			   0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+			   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+			   0x00, 0x0c, 0x00, 0x6f, 0x00),
+		PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0),
+	},
+	{
+		.freq			= 5310,
+		RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+			   0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+			   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+			   0x00, 0x0c, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef),
+	},
+	{
+		.freq			= 5320,
+		RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+			   0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+			   0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+			   0x00, 0x0c, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee),
+	},
+	{
+		.freq			= 5330,
+		RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+			   0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+			   0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77,
+			   0x00, 0x0b, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed),
+	},
+	{
+		.freq			= 5340,
+		RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+			   0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+			   0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77,
+			   0x00, 0x0b, 0x00, 0x6f, 0x00),
+		PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec),
+	},
+	{
+		.freq			= 5350,
+		RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+			   0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+			   0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77,
+			   0x00, 0x0b, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb),
+	},
+	{
+		.freq			= 5360,
+		RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+			   0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+			   0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77,
+			   0x00, 0x0a, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea),
+	},
+	{
+		.freq			= 5370,
+		RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+			   0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+			   0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77,
+			   0x00, 0x0a, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9),
+	},
+	{
+		.freq			= 5380,
+		RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+			   0xb8, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+			   0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77,
+			   0x00, 0x0a, 0x00, 0x6f, 0x00),
+		PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8),
+	},
+	{
+		.freq			= 5390,
+		RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+			   0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+			   0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77,
+			   0x00, 0x0a, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7),
+	},
+	{
+		.freq			= 5400,
+		RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+			   0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+			   0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77,
+			   0x00, 0x0a, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6),
+	},
+	{
+		.freq			= 5410,
+		RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+			   0xb7, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+			   0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+			   0x00, 0x0a, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5),
+	},
+	{
+		.freq			= 5420,
+		RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+			   0xa7, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+			   0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+			   0x00, 0x0a, 0x00, 0x6f, 0x00),
+		PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5),
+	},
+	{
+		.freq			= 5430,
+		RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00,
+			   0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+			   0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+			   0x00, 0x0a, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4),
+	},
+	{
+		.freq			= 5440,
+		RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+			   0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
+			   0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+			   0x00, 0x09, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3),
+	},
+	{
+		.freq			= 5450,
+		RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+			   0x95, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+			   0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77,
+			   0x00, 0x09, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2),
+	},
+	{
+		.freq			= 5460,
+		RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+			   0x95, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+			   0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77,
+			   0x00, 0x09, 0x00, 0x6f, 0x00),
+		PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1),
+	},
+	{
+		.freq			= 5470,
+		RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+			   0x94, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+			   0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77,
+			   0x00, 0x09, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0),
+	},
+	{
+		.freq			= 5480,
+		RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+			   0x84, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+			   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x09, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df),
+	},
+	{
+		.freq			= 5490,
+		RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+			   0x83, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+			   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x09, 0x00, 0x6f, 0x00),
+		PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de),
+	},
+	{
+		.freq			= 5500,
+		RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+			   0x82, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+			   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x09, 0x00, 0x6f, 0x00),
+		PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd),
+	},
+	{
+		.freq			= 5510,
+		RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+			   0x82, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+			   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x09, 0x00, 0x6f, 0x00),
+		PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd),
+	},
+	{
+		.freq			= 5520,
+		RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+			   0x72, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+			   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x09, 0x00, 0x6f, 0x00),
+		PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc),
+	},
+	{
+		.freq			= 5530,
+		RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00,
+			   0x72, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+			   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x09, 0x00, 0x6f, 0x00),
+		PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db),
+	},
+	{
+		.freq			= 5540,
+		RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00,
+			   0x71, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+			   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x09, 0x00, 0x6f, 0x00),
+		PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da),
+	},
+	{
+		.freq			= 5550,
+		RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+			   0x61, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+			   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x09, 0x00, 0x6f, 0x00),
+		PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9),
+	},
+	{
+		.freq			= 5560,
+		RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+			   0x61, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+			   0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x09, 0x00, 0x6f, 0x00),
+		PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8),
+	},
+	{
+		.freq			= 5570,
+		RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+			   0x61, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+			   0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x09, 0x00, 0x6f, 0x00),
+		PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7),
+	},
+	{
+		.freq			= 5580,
+		RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00,
+			   0x60, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+			   0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x08, 0x00, 0x6f, 0x00),
+		PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7),
+	},
+	{
+		.freq			= 5590,
+		RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00,
+			   0x50, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+			   0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x08, 0x00, 0x6f, 0x00),
+		PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6),
+	},
+	{
+		.freq			= 5600,
+		RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+			   0x50, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+			   0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x08, 0x00, 0x6f, 0x00),
+		PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5),
+	},
+	{
+		.freq			= 5610,
+		RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+			   0x50, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+			   0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x08, 0x00, 0x6f, 0x00),
+		PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4),
+	},
+	{
+		.freq			= 5620,
+		RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+			   0x50, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+			   0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x07, 0x00, 0x6f, 0x00),
+		PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3),
+	},
+	{
+		.freq			= 5630,
+		RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+			   0x50, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+			   0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x07, 0x00, 0x6f, 0x00),
+		PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2),
+	},
+	{
+		.freq			= 5640,
+		RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+			   0x40, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+			   0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x07, 0x00, 0x6f, 0x00),
+		PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2),
+	},
+	{
+		.freq			= 5650,
+		RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+			   0x40, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+			   0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x07, 0x00, 0x6f, 0x00),
+		PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1),
+	},
+	{
+		.freq			= 5660,
+		RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+			   0x40, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+			   0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x06, 0x00, 0x6f, 0x00),
+		PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0),
+	},
+	{
+		.freq			= 5670,
+		RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+			   0x40, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+			   0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x06, 0x00, 0x6f, 0x00),
+		PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf),
+	},
+	{
+		.freq			= 5680,
+		RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+			   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+			   0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x06, 0x00, 0x6f, 0x00),
+		PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce),
+	},
+	{
+		.freq			= 5690,
+		RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+			   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+			   0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x06, 0x00, 0x6f, 0x00),
+		PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce),
+	},
+	{
+		.freq			= 5700,
+		RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+			   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+			   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x06, 0x00, 0x6e, 0x00),
+		PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd),
+	},
+	{
+		.freq			= 5710,
+		RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+			   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+			   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x06, 0x00, 0x6e, 0x00),
+		PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc),
+	},
+	{
+		.freq			= 5720,
+		RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+			   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+			   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x06, 0x00, 0x6e, 0x00),
+		PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb),
+	},
+	{
+		.freq			= 5725,
+		RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x05, 0x05, 0x02,
+			   0x15, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+			   0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+			   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x06, 0x00, 0x6e, 0x00),
+		PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb),
+	},
+	{
+		.freq			= 5730,
+		RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+			   0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+			   0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x06, 0x00, 0x6e, 0x00),
+		PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca),
+	},
+	{
+		.freq			= 5735,
+		RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x05, 0x05, 0x02,
+			   0x15, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+			   0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+			   0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x06, 0x00, 0x6d, 0x00),
+		PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca),
+	},
+	{
+		.freq			= 5740,
+		RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+			   0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+			   0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x06, 0x00, 0x6d, 0x00),
+		PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9),
+	},
+	{
+		.freq			= 5745,
+		RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x05, 0x05, 0x02,
+			   0x15, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+			   0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+			   0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x06, 0x00, 0x6d, 0x00),
+		PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9),
+	},
+	{
+		.freq			= 5750,
+		RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+			   0x20, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+			   0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x05, 0x00, 0x6d, 0x00),
+		PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9),
+	},
+	{
+		.freq			= 5755,
+		RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x05, 0x05, 0x02,
+			   0x15, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+			   0x10, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+			   0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x05, 0x00, 0x6c, 0x00),
+		PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8),
+	},
+	{
+		.freq			= 5760,
+		RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00,
+			   0x10, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+			   0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x05, 0x00, 0x6c, 0x00),
+		PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8),
+	},
+	{
+		.freq			= 5765,
+		RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x05, 0x05, 0x02,
+			   0x15, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00,
+			   0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+			   0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x05, 0x00, 0x6c, 0x00),
+		PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8),
+	},
+	{
+		.freq			= 5770,
+		RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+			   0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+			   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x05, 0x00, 0x6b, 0x00),
+		PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7),
+	},
+	{
+		.freq			= 5775,
+		RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x05, 0x05, 0x02,
+			   0x15, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+			   0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+			   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x05, 0x00, 0x6b, 0x00),
+		PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7),
+	},
+	{
+		.freq			= 5780,
+		RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+			   0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+			   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x05, 0x00, 0x6b, 0x00),
+		PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6),
+	},
+	{
+		.freq			= 5785,
+		RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x05, 0x05, 0x02,
+			   0x15, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+			   0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+			   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x05, 0x00, 0x6b, 0x00),
+		PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6),
+	},
+	{
+		.freq			= 5790,
+		RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+			   0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+			   0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x05, 0x00, 0x6b, 0x00),
+		PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6),
+	},
+	{
+		.freq			= 5795,
+		RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x05, 0x05, 0x02,
+			   0x15, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+			   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+			   0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x05, 0x00, 0x6b, 0x00),
+		PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5),
+	},
+	{
+		.freq			= 5800,
+		RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+			   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+			   0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x05, 0x00, 0x6b, 0x00),
+		PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5),
+	},
+	{
+		.freq			= 5805,
+		RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x05, 0x05, 0x02,
+			   0x15, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+			   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+			   0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x05, 0x00, 0x6a, 0x00),
+		PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4),
+	},
+	{
+		.freq			= 5810,
+		RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+			   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+			   0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x05, 0x00, 0x6a, 0x00),
+		PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4),
+	},
+	{
+		.freq			= 5815,
+		RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x05, 0x05, 0x02,
+			   0x15, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+			   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+			   0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x05, 0x00, 0x6a, 0x00),
+		PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4),
+	},
+	{
+		.freq			= 5820,
+		RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+			   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+			   0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x05, 0x00, 0x6a, 0x00),
+		PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3),
+	},
+	{
+		.freq			= 5825,
+		RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x05, 0x05, 0x02,
+			   0x15, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+			   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+			   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x05, 0x00, 0x69, 0x00),
+		PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3),
+	},
+	{
+		.freq			= 5830,
+		RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+			   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+			   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x05, 0x00, 0x69, 0x00),
+		PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2),
+	},
+	{
+		.freq			= 5840,
+		RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+			   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+			   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x04, 0x00, 0x69, 0x00),
+		PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2),
+	},
+	{
+		.freq			= 5850,
+		RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+			   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+			   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x04, 0x00, 0x69, 0x00),
+		PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1),
+	},
+	{
+		.freq			= 5860,
+		RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+			   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+			   0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x04, 0x00, 0x69, 0x00),
+		PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0),
+	},
+	{
+		.freq			= 5870,
+		RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+			   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+			   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x04, 0x00, 0x68, 0x00),
+		PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf),
+	},
+	{
+		.freq			= 5880,
+		RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+			   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+			   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x04, 0x00, 0x68, 0x00),
+		PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf),
+	},
+	{
+		.freq			= 5890,
+		RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+			   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+			   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x04, 0x00, 0x68, 0x00),
+		PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be),
+	},
+	{
+		.freq			= 5900,
+		RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+			   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+			   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x04, 0x00, 0x68, 0x00),
+		PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd),
+	},
+	{
+		.freq			= 5910,
+		RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x02,
+			   0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+			   0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+			   0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+			   0x00, 0x04, 0x00, 0x68, 0x00),
+		PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc),
+	},
+	{
+		.freq			= 2412,
+		RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x06, 0x06, 0x04,
+			   0x2b, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00,
+			   0x00, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+			   0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00,
+			   0x70, 0x00, 0x0b, 0x00, 0x0a),
+		PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+	},
+	{
+		.freq			= 2417,
+		RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x71, 0x06, 0x06, 0x04,
+			   0x2b, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+			   0x00, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+			   0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00,
+			   0x70, 0x00, 0x0b, 0x00, 0x0a),
+		PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+	},
+	{
+		.freq			= 2422,
+		RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x76, 0x06, 0x06, 0x04,
+			   0x2b, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+			   0x00, 0x00, 0x67, 0x00, 0x03, 0x00, 0x70, 0x00,
+			   0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00,
+			   0x70, 0x00, 0x0b, 0x00, 0x0a),
+		PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+	},
+	{
+		.freq			= 2427,
+		RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x7b, 0x06, 0x06, 0x04,
+			   0x2b, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+			   0x00, 0x00, 0x57, 0x00, 0x03, 0x00, 0x70, 0x00,
+			   0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00,
+			   0x70, 0x00, 0x0a, 0x00, 0x0a),
+		PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+	},
+	{
+		.freq			= 2432,
+		RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x80, 0x06, 0x06, 0x04,
+			   0x2b, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+			   0x00, 0x00, 0x56, 0x00, 0x03, 0x00, 0x70, 0x00,
+			   0x0a, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00,
+			   0x70, 0x00, 0x0a, 0x00, 0x0a),
+		PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+	},
+	{
+		.freq			= 2437,
+		RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x85, 0x06, 0x06, 0x04,
+			   0x2b, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+			   0x00, 0x00, 0x46, 0x00, 0x03, 0x00, 0x70, 0x00,
+			   0x0a, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00,
+			   0x70, 0x00, 0x0a, 0x00, 0x0a),
+		PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+	},
+	{
+		.freq			= 2442,
+		RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8a, 0x06, 0x06, 0x04,
+			   0x2b, 0x01, 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00,
+			   0x00, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
+			   0x0a, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x02, 0x00,
+			   0x70, 0x00, 0x0a, 0x00, 0x0a),
+		PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+	},
+	{
+		.freq			= 2447,
+		RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x8f, 0x06, 0x06, 0x04,
+			   0x2b, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+			   0x00, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
+			   0x0a, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00,
+			   0x70, 0x00, 0x0a, 0x00, 0x09),
+		PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+	},
+	{
+		.freq			= 2452,
+		RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x94, 0x06, 0x06, 0x04,
+			   0x2b, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+			   0x00, 0x00, 0x23, 0x00, 0x02, 0x00, 0x70, 0x00,
+			   0x0a, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00,
+			   0x70, 0x00, 0x0a, 0x00, 0x09),
+		PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+	},
+	{
+		.freq			= 2457,
+		RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x99, 0x06, 0x06, 0x04,
+			   0x2b, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+			   0x00, 0x00, 0x12, 0x00, 0x02, 0x00, 0x70, 0x00,
+			   0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00,
+			   0x70, 0x00, 0x0a, 0x00, 0x09),
+		PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+	},
+	{
+		.freq			= 2462,
+		RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x9e, 0x06, 0x06, 0x04,
+			   0x2b, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+			   0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x70, 0x00,
+			   0x09, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00,
+			   0x70, 0x00, 0x09, 0x00, 0x09),
+		PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+	},
+	{
+		.freq			= 2467,
+		RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa3, 0x06, 0x06, 0x04,
+			   0x2b, 0x01, 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00,
+			   0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00,
+			   0x09, 0x00, 0x09, 0x00, 0x22, 0x00, 0x02, 0x00,
+			   0x70, 0x00, 0x09, 0x00, 0x09),
+		PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
+	},
+	{
+		.freq			= 2472,
+		RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0xa8, 0x06, 0x06, 0x04,
+			   0x2b, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00,
+			   0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00,
+			   0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x02, 0x00,
+			   0x70, 0x00, 0x09, 0x00, 0x09),
+		PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
+	},
+	{
+		.freq			= 2484,
+		RADIOREGS3(0xff, 0x01, 0x03, 0x09, 0xb4, 0x06, 0x06, 0x04,
+			   0x2b, 0x01, 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00,
+			   0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+			   0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00,
+			   0x70, 0x00, 0x09, 0x00, 0x09),
+		PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424),
+	},
+};
+
+static const struct b2056_inittabs_pts
+*b43_nphy_get_inittabs_rev3(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	switch (dev->phy.rev) {
+	case 3:
+		return &b2056_inittab_phy_rev3;
+	case 4:
+		return &b2056_inittab_phy_rev4;
+	default:
+		switch (phy->radio_rev) {
+		case 5:
+			return &b2056_inittab_radio_rev5;
+		case 6:
+			return &b2056_inittab_radio_rev6;
+		case 7:
+		case 9:
+			return &b2056_inittab_radio_rev7_9;
+		case 8:
+			return &b2056_inittab_radio_rev8;
+		case 11:
+			return &b2056_inittab_radio_rev11;
+		}
+	}
+
+	return NULL;
+}
+
+static void b2056_upload_inittab(struct b43_wldev *dev, bool ghz5,
+				 bool ignore_uploadflag, u16 routing,
+				 const struct b2056_inittab_entry *e,
+				 unsigned int length)
+{
+	unsigned int i;
+	u16 value;
+
+	for (i = 0; i < length; i++, e++) {
+		if (!(e->flags & B2056_INITTAB_ENTRY_OK))
+			continue;
+		if ((e->flags & B2056_INITTAB_UPLOAD) || ignore_uploadflag) {
+			if (ghz5)
+				value = e->ghz5;
+			else
+				value = e->ghz2;
+			b43_radio_write(dev, routing | i, value);
+		}
+	}
+}
+
+void b2056_upload_inittabs(struct b43_wldev *dev,
+			   bool ghz5, bool ignore_uploadflag)
+{
+	const struct b2056_inittabs_pts *pts;
+
+	pts = b43_nphy_get_inittabs_rev3(dev);
+	if (!pts) {
+		B43_WARN_ON(1);
+		return;
+	}
+
+	b2056_upload_inittab(dev, ghz5, ignore_uploadflag,
+				B2056_SYN, pts->syn, pts->syn_length);
+	b2056_upload_inittab(dev, ghz5, ignore_uploadflag,
+				B2056_TX0, pts->tx, pts->tx_length);
+	b2056_upload_inittab(dev, ghz5, ignore_uploadflag,
+				B2056_TX1, pts->tx, pts->tx_length);
+	b2056_upload_inittab(dev, ghz5, ignore_uploadflag,
+				B2056_RX0, pts->rx, pts->rx_length);
+	b2056_upload_inittab(dev, ghz5, ignore_uploadflag,
+				B2056_RX1, pts->rx, pts->rx_length);
+}
+
+void b2056_upload_syn_pll_cp2(struct b43_wldev *dev, bool ghz5)
+{
+	const struct b2056_inittabs_pts *pts;
+	const struct b2056_inittab_entry *e;
+
+	pts = b43_nphy_get_inittabs_rev3(dev);
+	if (!pts) {
+		B43_WARN_ON(1);
+		return;
+	}
+
+	e = &pts->syn[B2056_SYN_PLL_CP2];
+
+	b43_radio_write(dev, B2056_SYN_PLL_CP2, ghz5 ? e->ghz5 : e->ghz2);
+}
+
+const struct b43_nphy_channeltab_entry_rev3 *
+b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq)
+{
+	struct b43_phy *phy = &dev->phy;
+	const struct b43_nphy_channeltab_entry_rev3 *e;
+	unsigned int length, i;
+
+	switch (phy->rev) {
+	case 3:
+		e = b43_nphy_channeltab_phy_rev3;
+		length = ARRAY_SIZE(b43_nphy_channeltab_phy_rev3);
+		break;
+	case 4:
+		e = b43_nphy_channeltab_phy_rev4;
+		length = ARRAY_SIZE(b43_nphy_channeltab_phy_rev4);
+		break;
+	default:
+		switch (phy->radio_rev) {
+		case 5:
+			e = b43_nphy_channeltab_radio_rev5;
+			length = ARRAY_SIZE(b43_nphy_channeltab_radio_rev5);
+			break;
+		case 6:
+			e = b43_nphy_channeltab_radio_rev6;
+			length = ARRAY_SIZE(b43_nphy_channeltab_radio_rev6);
+			break;
+		case 7:
+		case 9:
+			e = b43_nphy_channeltab_radio_rev7_9;
+			length = ARRAY_SIZE(b43_nphy_channeltab_radio_rev7_9);
+			break;
+		case 8:
+			e = b43_nphy_channeltab_radio_rev8;
+			length = ARRAY_SIZE(b43_nphy_channeltab_radio_rev8);
+			break;
+		case 11:
+			e = b43_nphy_channeltab_radio_rev11;
+			length = ARRAY_SIZE(b43_nphy_channeltab_radio_rev11);
+			break;
+		default:
+			B43_WARN_ON(1);
+			return NULL;
+		}
+	}
+
+	for (i = 0; i < length; i++, e++) {
+		if (e->freq == freq)
+			return e;
+	}
+
+	return NULL;
+}
diff --git a/drivers/net/wireless/broadcom/b43/radio_2056.h b/drivers/net/wireless/broadcom/b43/radio_2056.h
new file mode 100644
index 0000000..59297fd
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/radio_2056.h
@@ -0,0 +1,1101 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_RADIO_2056_H_
+#define B43_RADIO_2056_H_
+
+#include <linux/types.h>
+
+#include "tables_nphy.h"
+
+#define B2056_SYN			(0x0 << 12)
+#define B2056_TX0			(0x2 << 12)
+#define B2056_TX1			(0x3 << 12)
+#define B2056_RX0			(0x6 << 12)
+#define B2056_RX1			(0x7 << 12)
+#define B2056_ALLTX			(0xE << 12)
+#define B2056_ALLRX			(0xF << 12)
+
+#define B2056_SYN_RESERVED_ADDR0	0x00
+#define B2056_SYN_IDCODE		0x01
+#define B2056_SYN_RESERVED_ADDR2	0x02
+#define B2056_SYN_RESERVED_ADDR3	0x03
+#define B2056_SYN_RESERVED_ADDR4	0x04
+#define B2056_SYN_RESERVED_ADDR5	0x05
+#define B2056_SYN_RESERVED_ADDR6	0x06
+#define B2056_SYN_RESERVED_ADDR7	0x07
+#define B2056_SYN_COM_CTRL		0x08
+#define B2056_SYN_COM_PU		0x09
+#define B2056_SYN_COM_OVR		0x0A
+#define B2056_SYN_COM_RESET		0x0B
+#define B2056_SYN_COM_RCAL		0x0C
+#define B2056_SYN_COM_RC_RXLPF		0x0D
+#define B2056_SYN_COM_RC_TXLPF		0x0E
+#define B2056_SYN_COM_RC_RXHPF		0x0F
+#define B2056_SYN_RESERVED_ADDR16	0x10
+#define B2056_SYN_RESERVED_ADDR17	0x11
+#define B2056_SYN_RESERVED_ADDR18	0x12
+#define B2056_SYN_RESERVED_ADDR19	0x13
+#define B2056_SYN_RESERVED_ADDR20	0x14
+#define B2056_SYN_RESERVED_ADDR21	0x15
+#define B2056_SYN_RESERVED_ADDR22	0x16
+#define B2056_SYN_RESERVED_ADDR23	0x17
+#define B2056_SYN_RESERVED_ADDR24	0x18
+#define B2056_SYN_RESERVED_ADDR25	0x19
+#define B2056_SYN_RESERVED_ADDR26	0x1A
+#define B2056_SYN_RESERVED_ADDR27	0x1B
+#define B2056_SYN_RESERVED_ADDR28	0x1C
+#define B2056_SYN_RESERVED_ADDR29	0x1D
+#define B2056_SYN_RESERVED_ADDR30	0x1E
+#define B2056_SYN_RESERVED_ADDR31	0x1F
+#define B2056_SYN_GPIO_MASTER1		0x20
+#define B2056_SYN_GPIO_MASTER2		0x21
+#define B2056_SYN_TOPBIAS_MASTER	0x22
+#define B2056_SYN_TOPBIAS_RCAL		0x23
+#define B2056_SYN_AFEREG		0x24
+#define B2056_SYN_TEMPPROCSENSE		0x25
+#define B2056_SYN_TEMPPROCSENSEIDAC	0x26
+#define B2056_SYN_TEMPPROCSENSERCAL	0x27
+#define B2056_SYN_LPO			0x28
+#define B2056_SYN_VDDCAL_MASTER		0x29
+#define B2056_SYN_VDDCAL_IDAC		0x2A
+#define B2056_SYN_VDDCAL_STATUS		0x2B
+#define B2056_SYN_RCAL_MASTER		0x2C
+#define B2056_SYN_RCAL_CODE_OUT		0x2D
+#define B2056_SYN_RCCAL_CTRL0		0x2E
+#define B2056_SYN_RCCAL_CTRL1		0x2F
+#define B2056_SYN_RCCAL_CTRL2		0x30
+#define B2056_SYN_RCCAL_CTRL3		0x31
+#define B2056_SYN_RCCAL_CTRL4		0x32
+#define B2056_SYN_RCCAL_CTRL5		0x33
+#define B2056_SYN_RCCAL_CTRL6		0x34
+#define B2056_SYN_RCCAL_CTRL7		0x35
+#define B2056_SYN_RCCAL_CTRL8		0x36
+#define B2056_SYN_RCCAL_CTRL9		0x37
+#define B2056_SYN_RCCAL_CTRL10		0x38
+#define B2056_SYN_RCCAL_CTRL11		0x39
+#define B2056_SYN_ZCAL_SPARE1		0x3A
+#define B2056_SYN_ZCAL_SPARE2		0x3B
+#define B2056_SYN_PLL_MAST1		0x3C
+#define B2056_SYN_PLL_MAST2		0x3D
+#define B2056_SYN_PLL_MAST3		0x3E
+#define B2056_SYN_PLL_BIAS_RESET	0x3F
+#define B2056_SYN_PLL_XTAL0		0x40
+#define B2056_SYN_PLL_XTAL1		0x41
+#define B2056_SYN_PLL_XTAL3		0x42
+#define B2056_SYN_PLL_XTAL4		0x43
+#define B2056_SYN_PLL_XTAL5		0x44
+#define B2056_SYN_PLL_XTAL6		0x45
+#define B2056_SYN_PLL_REFDIV		0x46
+#define B2056_SYN_PLL_PFD		0x47
+#define B2056_SYN_PLL_CP1		0x48
+#define B2056_SYN_PLL_CP2		0x49
+#define B2056_SYN_PLL_CP3		0x4A
+#define B2056_SYN_PLL_LOOPFILTER1	0x4B
+#define B2056_SYN_PLL_LOOPFILTER2	0x4C
+#define B2056_SYN_PLL_LOOPFILTER3	0x4D
+#define B2056_SYN_PLL_LOOPFILTER4	0x4E
+#define B2056_SYN_PLL_LOOPFILTER5	0x4F
+#define B2056_SYN_PLL_MMD1		0x50
+#define B2056_SYN_PLL_MMD2		0x51
+#define B2056_SYN_PLL_VCO1		0x52
+#define B2056_SYN_PLL_VCO2		0x53
+#define B2056_SYN_PLL_MONITOR1		0x54
+#define B2056_SYN_PLL_MONITOR2		0x55
+#define B2056_SYN_PLL_VCOCAL1		0x56
+#define B2056_SYN_PLL_VCOCAL2		0x57
+#define B2056_SYN_PLL_VCOCAL4		0x58
+#define B2056_SYN_PLL_VCOCAL5		0x59
+#define B2056_SYN_PLL_VCOCAL6		0x5A
+#define B2056_SYN_PLL_VCOCAL7		0x5B
+#define B2056_SYN_PLL_VCOCAL8		0x5C
+#define B2056_SYN_PLL_VCOCAL9		0x5D
+#define B2056_SYN_PLL_VCOCAL10		0x5E
+#define B2056_SYN_PLL_VCOCAL11		0x5F
+#define B2056_SYN_PLL_VCOCAL12		0x60
+#define B2056_SYN_PLL_VCOCAL13		0x61
+#define B2056_SYN_PLL_VREG		0x62
+#define B2056_SYN_PLL_STATUS1		0x63
+#define B2056_SYN_PLL_STATUS2		0x64
+#define B2056_SYN_PLL_STATUS3		0x65
+#define B2056_SYN_LOGEN_PU0		0x66
+#define B2056_SYN_LOGEN_PU1		0x67
+#define B2056_SYN_LOGEN_PU2		0x68
+#define B2056_SYN_LOGEN_PU3		0x69
+#define B2056_SYN_LOGEN_PU5		0x6A
+#define B2056_SYN_LOGEN_PU6		0x6B
+#define B2056_SYN_LOGEN_PU7		0x6C
+#define B2056_SYN_LOGEN_PU8		0x6D
+#define B2056_SYN_LOGEN_BIAS_RESET	0x6E
+#define B2056_SYN_LOGEN_RCCR1		0x6F
+#define B2056_SYN_LOGEN_VCOBUF1		0x70
+#define B2056_SYN_LOGEN_MIXER1		0x71
+#define B2056_SYN_LOGEN_MIXER2		0x72
+#define B2056_SYN_LOGEN_BUF1		0x73
+#define B2056_SYN_LOGENBUF2		0x74
+#define B2056_SYN_LOGEN_BUF3		0x75
+#define B2056_SYN_LOGEN_BUF4		0x76
+#define B2056_SYN_LOGEN_DIV1		0x77
+#define B2056_SYN_LOGEN_DIV2		0x78
+#define B2056_SYN_LOGEN_DIV3		0x79
+#define B2056_SYN_LOGEN_ACL1		0x7A
+#define B2056_SYN_LOGEN_ACL2		0x7B
+#define B2056_SYN_LOGEN_ACL3		0x7C
+#define B2056_SYN_LOGEN_ACL4		0x7D
+#define B2056_SYN_LOGEN_ACL5		0x7E
+#define B2056_SYN_LOGEN_ACL6		0x7F
+#define B2056_SYN_LOGEN_ACLOUT		0x80
+#define B2056_SYN_LOGEN_ACLCAL1		0x81
+#define B2056_SYN_LOGEN_ACLCAL2		0x82
+#define B2056_SYN_LOGEN_ACLCAL3		0x83
+#define B2056_SYN_CALEN			0x84
+#define B2056_SYN_LOGEN_PEAKDET1	0x85
+#define B2056_SYN_LOGEN_CORE_ACL_OVR	0x86
+#define B2056_SYN_LOGEN_RX_DIFF_ACL_OVR	0x87
+#define B2056_SYN_LOGEN_TX_DIFF_ACL_OVR	0x88
+#define B2056_SYN_LOGEN_RX_CMOS_ACL_OVR	0x89
+#define B2056_SYN_LOGEN_TX_CMOS_ACL_OVR	0x8A
+#define B2056_SYN_LOGEN_VCOBUF2		0x8B
+#define B2056_SYN_LOGEN_MIXER3		0x8C
+#define B2056_SYN_LOGEN_BUF5		0x8D
+#define B2056_SYN_LOGEN_BUF6		0x8E
+#define B2056_SYN_LOGEN_CBUFRX1		0x8F
+#define B2056_SYN_LOGEN_CBUFRX2		0x90
+#define B2056_SYN_LOGEN_CBUFRX3		0x91
+#define B2056_SYN_LOGEN_CBUFRX4		0x92
+#define B2056_SYN_LOGEN_CBUFTX1		0x93
+#define B2056_SYN_LOGEN_CBUFTX2		0x94
+#define B2056_SYN_LOGEN_CBUFTX3		0x95
+#define B2056_SYN_LOGEN_CBUFTX4		0x96
+#define B2056_SYN_LOGEN_CMOSRX1		0x97
+#define B2056_SYN_LOGEN_CMOSRX2		0x98
+#define B2056_SYN_LOGEN_CMOSRX3		0x99
+#define B2056_SYN_LOGEN_CMOSRX4		0x9A
+#define B2056_SYN_LOGEN_CMOSTX1		0x9B
+#define B2056_SYN_LOGEN_CMOSTX2		0x9C
+#define B2056_SYN_LOGEN_CMOSTX3		0x9D
+#define B2056_SYN_LOGEN_CMOSTX4		0x9E
+#define B2056_SYN_LOGEN_VCOBUF2_OVRVAL	0x9F
+#define B2056_SYN_LOGEN_MIXER3_OVRVAL	0xA0
+#define B2056_SYN_LOGEN_BUF5_OVRVAL	0xA1
+#define B2056_SYN_LOGEN_BUF6_OVRVAL	0xA2
+#define B2056_SYN_LOGEN_CBUFRX1_OVRVAL	0xA3
+#define B2056_SYN_LOGEN_CBUFRX2_OVRVAL	0xA4
+#define B2056_SYN_LOGEN_CBUFRX3_OVRVAL	0xA5
+#define B2056_SYN_LOGEN_CBUFRX4_OVRVAL	0xA6
+#define B2056_SYN_LOGEN_CBUFTX1_OVRVAL	0xA7
+#define B2056_SYN_LOGEN_CBUFTX2_OVRVAL	0xA8
+#define B2056_SYN_LOGEN_CBUFTX3_OVRVAL	0xA9
+#define B2056_SYN_LOGEN_CBUFTX4_OVRVAL	0xAA
+#define B2056_SYN_LOGEN_CMOSRX1_OVRVAL	0xAB
+#define B2056_SYN_LOGEN_CMOSRX2_OVRVAL	0xAC
+#define B2056_SYN_LOGEN_CMOSRX3_OVRVAL	0xAD
+#define B2056_SYN_LOGEN_CMOSRX4_OVRVAL	0xAE
+#define B2056_SYN_LOGEN_CMOSTX1_OVRVAL	0xAF
+#define B2056_SYN_LOGEN_CMOSTX2_OVRVAL	0xB0
+#define B2056_SYN_LOGEN_CMOSTX3_OVRVAL	0xB1
+#define B2056_SYN_LOGEN_CMOSTX4_OVRVAL	0xB2
+#define B2056_SYN_LOGEN_ACL_WAITCNT	0xB3
+#define B2056_SYN_LOGEN_CORE_CALVALID	0xB4
+#define B2056_SYN_LOGEN_RX_CMOS_CALVALID	0xB5
+#define B2056_SYN_LOGEN_TX_CMOS_VALID	0xB6
+
+#define B2056_TX_RESERVED_ADDR0		0x00
+#define B2056_TX_IDCODE			0x01
+#define B2056_TX_RESERVED_ADDR2		0x02
+#define B2056_TX_RESERVED_ADDR3		0x03
+#define B2056_TX_RESERVED_ADDR4		0x04
+#define B2056_TX_RESERVED_ADDR5		0x05
+#define B2056_TX_RESERVED_ADDR6		0x06
+#define B2056_TX_RESERVED_ADDR7		0x07
+#define B2056_TX_COM_CTRL		0x08
+#define B2056_TX_COM_PU			0x09
+#define B2056_TX_COM_OVR		0x0A
+#define B2056_TX_COM_RESET		0x0B
+#define B2056_TX_COM_RCAL		0x0C
+#define B2056_TX_COM_RC_RXLPF		0x0D
+#define B2056_TX_COM_RC_TXLPF		0x0E
+#define B2056_TX_COM_RC_RXHPF		0x0F
+#define B2056_TX_RESERVED_ADDR16	0x10
+#define B2056_TX_RESERVED_ADDR17	0x11
+#define B2056_TX_RESERVED_ADDR18	0x12
+#define B2056_TX_RESERVED_ADDR19	0x13
+#define B2056_TX_RESERVED_ADDR20	0x14
+#define B2056_TX_RESERVED_ADDR21	0x15
+#define B2056_TX_RESERVED_ADDR22	0x16
+#define B2056_TX_RESERVED_ADDR23	0x17
+#define B2056_TX_RESERVED_ADDR24	0x18
+#define B2056_TX_RESERVED_ADDR25	0x19
+#define B2056_TX_RESERVED_ADDR26	0x1A
+#define B2056_TX_RESERVED_ADDR27	0x1B
+#define B2056_TX_RESERVED_ADDR28	0x1C
+#define B2056_TX_RESERVED_ADDR29	0x1D
+#define B2056_TX_RESERVED_ADDR30	0x1E
+#define B2056_TX_RESERVED_ADDR31	0x1F
+#define B2056_TX_IQCAL_GAIN_BW		0x20
+#define B2056_TX_LOFT_FINE_I		0x21
+#define B2056_TX_LOFT_FINE_Q		0x22
+#define B2056_TX_LOFT_COARSE_I		0x23
+#define B2056_TX_LOFT_COARSE_Q		0x24
+#define B2056_TX_TX_COM_MASTER1		0x25
+#define B2056_TX_TX_COM_MASTER2		0x26
+#define B2056_TX_RXIQCAL_TXMUX		0x27
+#define B2056_TX_TX_SSI_MASTER		0x28
+#define B2056_TX_IQCAL_VCM_HG		0x29
+#define B2056_TX_IQCAL_IDAC		0x2A
+#define B2056_TX_TSSI_VCM		0x2B
+#define B2056_TX_TX_AMP_DET		0x2C
+#define B2056_TX_TX_SSI_MUX		0x2D
+#define B2056_TX_TSSIA			0x2E
+#define B2056_TX_TSSIG			0x2F
+#define B2056_TX_TSSI_MISC1		0x30
+#define B2056_TX_TSSI_MISC2		0x31
+#define B2056_TX_TSSI_MISC3		0x32
+#define B2056_TX_PA_SPARE1		0x33
+#define B2056_TX_PA_SPARE2		0x34
+#define B2056_TX_INTPAA_MASTER		0x35
+#define B2056_TX_INTPAA_GAIN		0x36
+#define B2056_TX_INTPAA_BOOST_TUNE	0x37
+#define B2056_TX_INTPAA_IAUX_STAT	0x38
+#define B2056_TX_INTPAA_IAUX_DYN	0x39
+#define B2056_TX_INTPAA_IMAIN_STAT	0x3A
+#define B2056_TX_INTPAA_IMAIN_DYN	0x3B
+#define B2056_TX_INTPAA_CASCBIAS	0x3C
+#define B2056_TX_INTPAA_PASLOPE		0x3D
+#define B2056_TX_INTPAA_PA_MISC		0x3E
+#define B2056_TX_INTPAG_MASTER		0x3F
+#define B2056_TX_INTPAG_GAIN		0x40
+#define B2056_TX_INTPAG_BOOST_TUNE	0x41
+#define B2056_TX_INTPAG_IAUX_STAT	0x42
+#define B2056_TX_INTPAG_IAUX_DYN	0x43
+#define B2056_TX_INTPAG_IMAIN_STAT	0x44
+#define B2056_TX_INTPAG_IMAIN_DYN	0x45
+#define B2056_TX_INTPAG_CASCBIAS	0x46
+#define B2056_TX_INTPAG_PASLOPE		0x47
+#define B2056_TX_INTPAG_PA_MISC		0x48
+#define B2056_TX_PADA_MASTER		0x49
+#define B2056_TX_PADA_IDAC		0x4A
+#define B2056_TX_PADA_CASCBIAS		0x4B
+#define B2056_TX_PADA_GAIN		0x4C
+#define B2056_TX_PADA_BOOST_TUNE	0x4D
+#define B2056_TX_PADA_SLOPE		0x4E
+#define B2056_TX_PADG_MASTER		0x4F
+#define B2056_TX_PADG_IDAC		0x50
+#define B2056_TX_PADG_CASCBIAS		0x51
+#define B2056_TX_PADG_GAIN		0x52
+#define B2056_TX_PADG_BOOST_TUNE	0x53
+#define B2056_TX_PADG_SLOPE		0x54
+#define B2056_TX_PGAA_MASTER		0x55
+#define B2056_TX_PGAA_IDAC		0x56
+#define B2056_TX_PGAA_GAIN		0x57
+#define B2056_TX_PGAA_BOOST_TUNE	0x58
+#define B2056_TX_PGAA_SLOPE		0x59
+#define B2056_TX_PGAA_MISC		0x5A
+#define B2056_TX_PGAG_MASTER		0x5B
+#define B2056_TX_PGAG_IDAC		0x5C
+#define B2056_TX_PGAG_GAIN		0x5D
+#define B2056_TX_PGAG_BOOST_TUNE	0x5E
+#define B2056_TX_PGAG_SLOPE		0x5F
+#define B2056_TX_PGAG_MISC		0x60
+#define B2056_TX_MIXA_MASTER		0x61
+#define B2056_TX_MIXA_BOOST_TUNE	0x62
+#define B2056_TX_MIXG			0x63
+#define B2056_TX_MIXG_BOOST_TUNE	0x64
+#define B2056_TX_BB_GM_MASTER		0x65
+#define B2056_TX_GMBB_GM		0x66
+#define B2056_TX_GMBB_IDAC		0x67
+#define B2056_TX_TXLPF_MASTER		0x68
+#define B2056_TX_TXLPF_RCCAL		0x69
+#define B2056_TX_TXLPF_RCCAL_OFF0	0x6A
+#define B2056_TX_TXLPF_RCCAL_OFF1	0x6B
+#define B2056_TX_TXLPF_RCCAL_OFF2	0x6C
+#define B2056_TX_TXLPF_RCCAL_OFF3	0x6D
+#define B2056_TX_TXLPF_RCCAL_OFF4	0x6E
+#define B2056_TX_TXLPF_RCCAL_OFF5	0x6F
+#define B2056_TX_TXLPF_RCCAL_OFF6	0x70
+#define B2056_TX_TXLPF_BW		0x71
+#define B2056_TX_TXLPF_GAIN		0x72
+#define B2056_TX_TXLPF_IDAC		0x73
+#define B2056_TX_TXLPF_IDAC_0		0x74
+#define B2056_TX_TXLPF_IDAC_1		0x75
+#define B2056_TX_TXLPF_IDAC_2		0x76
+#define B2056_TX_TXLPF_IDAC_3		0x77
+#define B2056_TX_TXLPF_IDAC_4		0x78
+#define B2056_TX_TXLPF_IDAC_5		0x79
+#define B2056_TX_TXLPF_IDAC_6		0x7A
+#define B2056_TX_TXLPF_OPAMP_IDAC	0x7B
+#define B2056_TX_TXLPF_MISC		0x7C
+#define B2056_TX_TXSPARE1		0x7D
+#define B2056_TX_TXSPARE2		0x7E
+#define B2056_TX_TXSPARE3		0x7F
+#define B2056_TX_TXSPARE4		0x80
+#define B2056_TX_TXSPARE5		0x81
+#define B2056_TX_TXSPARE6		0x82
+#define B2056_TX_TXSPARE7		0x83
+#define B2056_TX_TXSPARE8		0x84
+#define B2056_TX_TXSPARE9		0x85
+#define B2056_TX_TXSPARE10		0x86
+#define B2056_TX_TXSPARE11		0x87
+#define B2056_TX_TXSPARE12		0x88
+#define B2056_TX_TXSPARE13		0x89
+#define B2056_TX_TXSPARE14		0x8A
+#define B2056_TX_TXSPARE15		0x8B
+#define B2056_TX_TXSPARE16		0x8C
+#define B2056_TX_STATUS_INTPA_GAIN	0x8D
+#define B2056_TX_STATUS_PAD_GAIN	0x8E
+#define B2056_TX_STATUS_PGA_GAIN	0x8F
+#define B2056_TX_STATUS_GM_TXLPF_GAIN	0x90
+#define B2056_TX_STATUS_TXLPF_BW	0x91
+#define B2056_TX_STATUS_TXLPF_RC	0x92
+#define B2056_TX_GMBB_IDAC0		0x93
+#define B2056_TX_GMBB_IDAC1		0x94
+#define B2056_TX_GMBB_IDAC2		0x95
+#define B2056_TX_GMBB_IDAC3		0x96
+#define B2056_TX_GMBB_IDAC4		0x97
+#define B2056_TX_GMBB_IDAC5		0x98
+#define B2056_TX_GMBB_IDAC6		0x99
+#define B2056_TX_GMBB_IDAC7		0x9A
+
+#define B2056_RX_RESERVED_ADDR0		0x00
+#define B2056_RX_IDCODE			0x01
+#define B2056_RX_RESERVED_ADDR2		0x02
+#define B2056_RX_RESERVED_ADDR3		0x03
+#define B2056_RX_RESERVED_ADDR4		0x04
+#define B2056_RX_RESERVED_ADDR5		0x05
+#define B2056_RX_RESERVED_ADDR6		0x06
+#define B2056_RX_RESERVED_ADDR7		0x07
+#define B2056_RX_COM_CTRL		0x08
+#define B2056_RX_COM_PU			0x09
+#define B2056_RX_COM_OVR		0x0A
+#define B2056_RX_COM_RESET		0x0B
+#define B2056_RX_COM_RCAL		0x0C
+#define B2056_RX_COM_RC_RXLPF		0x0D
+#define B2056_RX_COM_RC_TXLPF		0x0E
+#define B2056_RX_COM_RC_RXHPF		0x0F
+#define B2056_RX_RESERVED_ADDR16	0x10
+#define B2056_RX_RESERVED_ADDR17	0x11
+#define B2056_RX_RESERVED_ADDR18	0x12
+#define B2056_RX_RESERVED_ADDR19	0x13
+#define B2056_RX_RESERVED_ADDR20	0x14
+#define B2056_RX_RESERVED_ADDR21	0x15
+#define B2056_RX_RESERVED_ADDR22	0x16
+#define B2056_RX_RESERVED_ADDR23	0x17
+#define B2056_RX_RESERVED_ADDR24	0x18
+#define B2056_RX_RESERVED_ADDR25	0x19
+#define B2056_RX_RESERVED_ADDR26	0x1A
+#define B2056_RX_RESERVED_ADDR27	0x1B
+#define B2056_RX_RESERVED_ADDR28	0x1C
+#define B2056_RX_RESERVED_ADDR29	0x1D
+#define B2056_RX_RESERVED_ADDR30	0x1E
+#define B2056_RX_RESERVED_ADDR31	0x1F
+#define B2056_RX_RXIQCAL_RXMUX		0x20
+#define B2056_RX_RSSI_PU		0x21
+#define B2056_RX_RSSI_SEL		0x22
+#define B2056_RX_RSSI_GAIN		0x23
+#define B2056_RX_RSSI_NB_IDAC		0x24
+#define B2056_RX_RSSI_WB2I_IDAC_1	0x25
+#define B2056_RX_RSSI_WB2I_IDAC_2	0x26
+#define B2056_RX_RSSI_WB2Q_IDAC_1	0x27
+#define B2056_RX_RSSI_WB2Q_IDAC_2	0x28
+#define B2056_RX_RSSI_POLE		0x29
+#define B2056_RX_RSSI_WB1_IDAC		0x2A
+#define B2056_RX_RSSI_MISC		0x2B
+#define B2056_RX_LNAA_MASTER		0x2C
+#define B2056_RX_LNAA_TUNE		0x2D
+#define B2056_RX_LNAA_GAIN		0x2E
+#define B2056_RX_LNA_A_SLOPE		0x2F
+#define B2056_RX_BIASPOLE_LNAA1_IDAC	0x30
+#define B2056_RX_LNAA2_IDAC		0x31
+#define B2056_RX_LNA1A_MISC		0x32
+#define B2056_RX_LNAG_MASTER		0x33
+#define B2056_RX_LNAG_TUNE		0x34
+#define B2056_RX_LNAG_GAIN		0x35
+#define B2056_RX_LNA_G_SLOPE		0x36
+#define B2056_RX_BIASPOLE_LNAG1_IDAC	0x37
+#define B2056_RX_LNAG2_IDAC		0x38
+#define B2056_RX_LNA1G_MISC		0x39
+#define B2056_RX_MIXA_MASTER		0x3A
+#define B2056_RX_MIXA_VCM		0x3B
+#define B2056_RX_MIXA_CTRLPTAT		0x3C
+#define B2056_RX_MIXA_LOB_BIAS		0x3D
+#define B2056_RX_MIXA_CORE_IDAC		0x3E
+#define B2056_RX_MIXA_CMFB_IDAC		0x3F
+#define B2056_RX_MIXA_BIAS_AUX		0x40
+#define B2056_RX_MIXA_BIAS_MAIN		0x41
+#define B2056_RX_MIXA_BIAS_MISC		0x42
+#define B2056_RX_MIXA_MAST_BIAS		0x43
+#define B2056_RX_MIXG_MASTER		0x44
+#define B2056_RX_MIXG_VCM		0x45
+#define B2056_RX_MIXG_CTRLPTAT		0x46
+#define B2056_RX_MIXG_LOB_BIAS		0x47
+#define B2056_RX_MIXG_CORE_IDAC		0x48
+#define B2056_RX_MIXG_CMFB_IDAC		0x49
+#define B2056_RX_MIXG_BIAS_AUX		0x4A
+#define B2056_RX_MIXG_BIAS_MAIN		0x4B
+#define B2056_RX_MIXG_BIAS_MISC		0x4C
+#define B2056_RX_MIXG_MAST_BIAS		0x4D
+#define B2056_RX_TIA_MASTER		0x4E
+#define B2056_RX_TIA_IOPAMP		0x4F
+#define B2056_RX_TIA_QOPAMP		0x50
+#define B2056_RX_TIA_IMISC		0x51
+#define B2056_RX_TIA_QMISC		0x52
+#define B2056_RX_TIA_GAIN		0x53
+#define B2056_RX_TIA_SPARE1		0x54
+#define B2056_RX_TIA_SPARE2		0x55
+#define B2056_RX_BB_LPF_MASTER		0x56
+#define B2056_RX_AACI_MASTER		0x57
+#define B2056_RX_RXLPF_IDAC		0x58
+#define B2056_RX_RXLPF_OPAMPBIAS_LOWQ	0x59
+#define B2056_RX_RXLPF_OPAMPBIAS_HIGHQ	0x5A
+#define B2056_RX_RXLPF_BIAS_DCCANCEL	0x5B
+#define B2056_RX_RXLPF_OUTVCM		0x5C
+#define B2056_RX_RXLPF_INVCM_BODY	0x5D
+#define B2056_RX_RXLPF_CC_OP		0x5E
+#define B2056_RX_RXLPF_GAIN		0x5F
+#define B2056_RX_RXLPF_Q_BW		0x60
+#define B2056_RX_RXLPF_HP_CORNER_BW	0x61
+#define B2056_RX_RXLPF_RCCAL_HPC	0x62
+#define B2056_RX_RXHPF_OFF0		0x63
+#define B2056_RX_RXHPF_OFF1		0x64
+#define B2056_RX_RXHPF_OFF2		0x65
+#define B2056_RX_RXHPF_OFF3		0x66
+#define B2056_RX_RXHPF_OFF4		0x67
+#define B2056_RX_RXHPF_OFF5		0x68
+#define B2056_RX_RXHPF_OFF6		0x69
+#define B2056_RX_RXHPF_OFF7		0x6A
+#define B2056_RX_RXLPF_RCCAL_LPC	0x6B
+#define B2056_RX_RXLPF_OFF_0		0x6C
+#define B2056_RX_RXLPF_OFF_1		0x6D
+#define B2056_RX_RXLPF_OFF_2		0x6E
+#define B2056_RX_RXLPF_OFF_3		0x6F
+#define B2056_RX_RXLPF_OFF_4		0x70
+#define B2056_RX_UNUSED			0x71
+#define B2056_RX_VGA_MASTER		0x72
+#define B2056_RX_VGA_BIAS		0x73
+#define B2056_RX_VGA_BIAS_DCCANCEL	0x74
+#define B2056_RX_VGA_GAIN		0x75
+#define B2056_RX_VGA_HP_CORNER_BW	0x76
+#define B2056_RX_VGABUF_BIAS		0x77
+#define B2056_RX_VGABUF_GAIN_BW		0x78
+#define B2056_RX_TXFBMIX_A		0x79
+#define B2056_RX_TXFBMIX_G		0x7A
+#define B2056_RX_RXSPARE1		0x7B
+#define B2056_RX_RXSPARE2		0x7C
+#define B2056_RX_RXSPARE3		0x7D
+#define B2056_RX_RXSPARE4		0x7E
+#define B2056_RX_RXSPARE5		0x7F
+#define B2056_RX_RXSPARE6		0x80
+#define B2056_RX_RXSPARE7		0x81
+#define B2056_RX_RXSPARE8		0x82
+#define B2056_RX_RXSPARE9		0x83
+#define B2056_RX_RXSPARE10		0x84
+#define B2056_RX_RXSPARE11		0x85
+#define B2056_RX_RXSPARE12		0x86
+#define B2056_RX_RXSPARE13		0x87
+#define B2056_RX_RXSPARE14		0x88
+#define B2056_RX_RXSPARE15		0x89
+#define B2056_RX_RXSPARE16		0x8A
+#define B2056_RX_STATUS_LNAA_GAIN	0x8B
+#define B2056_RX_STATUS_LNAG_GAIN	0x8C
+#define B2056_RX_STATUS_MIXTIA_GAIN	0x8D
+#define B2056_RX_STATUS_RXLPF_GAIN	0x8E
+#define B2056_RX_STATUS_VGA_BUF_GAIN	0x8F
+#define B2056_RX_STATUS_RXLPF_Q		0x90
+#define B2056_RX_STATUS_RXLPF_BUF_BW	0x91
+#define B2056_RX_STATUS_RXLPF_VGA_HPC	0x92
+#define B2056_RX_STATUS_RXLPF_RC	0x93
+#define B2056_RX_STATUS_HPC_RC		0x94
+
+#define B2056_LNA1_A_PU			0x01
+#define B2056_LNA2_A_PU			0x02
+#define B2056_LNA1_G_PU			0x01
+#define B2056_LNA2_G_PU			0x02
+#define B2056_MIXA_PU_I			0x01
+#define B2056_MIXA_PU_Q			0x02
+#define B2056_MIXA_PU_GM		0x10
+#define B2056_MIXG_PU_I			0x01
+#define B2056_MIXG_PU_Q			0x02
+#define B2056_MIXG_PU_GM		0x10
+#define B2056_TIA_PU			0x01
+#define B2056_BB_LPF_PU			0x20
+#define B2056_W1_PU			0x02
+#define B2056_W2_PU			0x04
+#define B2056_NB_PU			0x08
+#define B2056_RSSI_W1_SEL		0x02
+#define B2056_RSSI_W2_SEL		0x04
+#define B2056_RSSI_NB_SEL		0x08
+#define B2056_VCM_MASK			0x1C
+#define B2056_RSSI_VCM_SHIFT		0x02
+
+#define B2056_SYN			(0x0 << 12)
+#define B2056_TX0			(0x2 << 12)
+#define B2056_TX1			(0x3 << 12)
+#define B2056_RX0			(0x6 << 12)
+#define B2056_RX1			(0x7 << 12)
+#define B2056_ALLTX			(0xE << 12)
+#define B2056_ALLRX			(0xF << 12)
+
+#define B2056_SYN_RESERVED_ADDR0	0x00
+#define B2056_SYN_IDCODE		0x01
+#define B2056_SYN_RESERVED_ADDR2	0x02
+#define B2056_SYN_RESERVED_ADDR3	0x03
+#define B2056_SYN_RESERVED_ADDR4	0x04
+#define B2056_SYN_RESERVED_ADDR5	0x05
+#define B2056_SYN_RESERVED_ADDR6	0x06
+#define B2056_SYN_RESERVED_ADDR7	0x07
+#define B2056_SYN_COM_CTRL		0x08
+#define B2056_SYN_COM_PU		0x09
+#define B2056_SYN_COM_OVR		0x0A
+#define B2056_SYN_COM_RESET		0x0B
+#define B2056_SYN_COM_RCAL		0x0C
+#define B2056_SYN_COM_RC_RXLPF		0x0D
+#define B2056_SYN_COM_RC_TXLPF		0x0E
+#define B2056_SYN_COM_RC_RXHPF		0x0F
+#define B2056_SYN_RESERVED_ADDR16	0x10
+#define B2056_SYN_RESERVED_ADDR17	0x11
+#define B2056_SYN_RESERVED_ADDR18	0x12
+#define B2056_SYN_RESERVED_ADDR19	0x13
+#define B2056_SYN_RESERVED_ADDR20	0x14
+#define B2056_SYN_RESERVED_ADDR21	0x15
+#define B2056_SYN_RESERVED_ADDR22	0x16
+#define B2056_SYN_RESERVED_ADDR23	0x17
+#define B2056_SYN_RESERVED_ADDR24	0x18
+#define B2056_SYN_RESERVED_ADDR25	0x19
+#define B2056_SYN_RESERVED_ADDR26	0x1A
+#define B2056_SYN_RESERVED_ADDR27	0x1B
+#define B2056_SYN_RESERVED_ADDR28	0x1C
+#define B2056_SYN_RESERVED_ADDR29	0x1D
+#define B2056_SYN_RESERVED_ADDR30	0x1E
+#define B2056_SYN_RESERVED_ADDR31	0x1F
+#define B2056_SYN_GPIO_MASTER1		0x20
+#define B2056_SYN_GPIO_MASTER2		0x21
+#define B2056_SYN_TOPBIAS_MASTER	0x22
+#define B2056_SYN_TOPBIAS_RCAL		0x23
+#define B2056_SYN_AFEREG		0x24
+#define B2056_SYN_TEMPPROCSENSE		0x25
+#define B2056_SYN_TEMPPROCSENSEIDAC	0x26
+#define B2056_SYN_TEMPPROCSENSERCAL	0x27
+#define B2056_SYN_LPO			0x28
+#define B2056_SYN_VDDCAL_MASTER		0x29
+#define B2056_SYN_VDDCAL_IDAC		0x2A
+#define B2056_SYN_VDDCAL_STATUS		0x2B
+#define B2056_SYN_RCAL_MASTER		0x2C
+#define B2056_SYN_RCAL_CODE_OUT		0x2D
+#define B2056_SYN_RCCAL_CTRL0		0x2E
+#define B2056_SYN_RCCAL_CTRL1		0x2F
+#define B2056_SYN_RCCAL_CTRL2		0x30
+#define B2056_SYN_RCCAL_CTRL3		0x31
+#define B2056_SYN_RCCAL_CTRL4		0x32
+#define B2056_SYN_RCCAL_CTRL5		0x33
+#define B2056_SYN_RCCAL_CTRL6		0x34
+#define B2056_SYN_RCCAL_CTRL7		0x35
+#define B2056_SYN_RCCAL_CTRL8		0x36
+#define B2056_SYN_RCCAL_CTRL9		0x37
+#define B2056_SYN_RCCAL_CTRL10		0x38
+#define B2056_SYN_RCCAL_CTRL11		0x39
+#define B2056_SYN_ZCAL_SPARE1		0x3A
+#define B2056_SYN_ZCAL_SPARE2		0x3B
+#define B2056_SYN_PLL_MAST1		0x3C
+#define B2056_SYN_PLL_MAST2		0x3D
+#define B2056_SYN_PLL_MAST3		0x3E
+#define B2056_SYN_PLL_BIAS_RESET	0x3F
+#define B2056_SYN_PLL_XTAL0		0x40
+#define B2056_SYN_PLL_XTAL1		0x41
+#define B2056_SYN_PLL_XTAL3		0x42
+#define B2056_SYN_PLL_XTAL4		0x43
+#define B2056_SYN_PLL_XTAL5		0x44
+#define B2056_SYN_PLL_XTAL6		0x45
+#define B2056_SYN_PLL_REFDIV		0x46
+#define B2056_SYN_PLL_PFD		0x47
+#define B2056_SYN_PLL_CP1		0x48
+#define B2056_SYN_PLL_CP2		0x49
+#define B2056_SYN_PLL_CP3		0x4A
+#define B2056_SYN_PLL_LOOPFILTER1	0x4B
+#define B2056_SYN_PLL_LOOPFILTER2	0x4C
+#define B2056_SYN_PLL_LOOPFILTER3	0x4D
+#define B2056_SYN_PLL_LOOPFILTER4	0x4E
+#define B2056_SYN_PLL_LOOPFILTER5	0x4F
+#define B2056_SYN_PLL_MMD1		0x50
+#define B2056_SYN_PLL_MMD2		0x51
+#define B2056_SYN_PLL_VCO1		0x52
+#define B2056_SYN_PLL_VCO2		0x53
+#define B2056_SYN_PLL_MONITOR1		0x54
+#define B2056_SYN_PLL_MONITOR2		0x55
+#define B2056_SYN_PLL_VCOCAL1		0x56
+#define B2056_SYN_PLL_VCOCAL2		0x57
+#define B2056_SYN_PLL_VCOCAL4		0x58
+#define B2056_SYN_PLL_VCOCAL5		0x59
+#define B2056_SYN_PLL_VCOCAL6		0x5A
+#define B2056_SYN_PLL_VCOCAL7		0x5B
+#define B2056_SYN_PLL_VCOCAL8		0x5C
+#define B2056_SYN_PLL_VCOCAL9		0x5D
+#define B2056_SYN_PLL_VCOCAL10		0x5E
+#define B2056_SYN_PLL_VCOCAL11		0x5F
+#define B2056_SYN_PLL_VCOCAL12		0x60
+#define B2056_SYN_PLL_VCOCAL13		0x61
+#define B2056_SYN_PLL_VREG		0x62
+#define B2056_SYN_PLL_STATUS1		0x63
+#define B2056_SYN_PLL_STATUS2		0x64
+#define B2056_SYN_PLL_STATUS3		0x65
+#define B2056_SYN_LOGEN_PU0		0x66
+#define B2056_SYN_LOGEN_PU1		0x67
+#define B2056_SYN_LOGEN_PU2		0x68
+#define B2056_SYN_LOGEN_PU3		0x69
+#define B2056_SYN_LOGEN_PU5		0x6A
+#define B2056_SYN_LOGEN_PU6		0x6B
+#define B2056_SYN_LOGEN_PU7		0x6C
+#define B2056_SYN_LOGEN_PU8		0x6D
+#define B2056_SYN_LOGEN_BIAS_RESET	0x6E
+#define B2056_SYN_LOGEN_RCCR1		0x6F
+#define B2056_SYN_LOGEN_VCOBUF1		0x70
+#define B2056_SYN_LOGEN_MIXER1		0x71
+#define B2056_SYN_LOGEN_MIXER2		0x72
+#define B2056_SYN_LOGEN_BUF1		0x73
+#define B2056_SYN_LOGENBUF2		0x74
+#define B2056_SYN_LOGEN_BUF3		0x75
+#define B2056_SYN_LOGEN_BUF4		0x76
+#define B2056_SYN_LOGEN_DIV1		0x77
+#define B2056_SYN_LOGEN_DIV2		0x78
+#define B2056_SYN_LOGEN_DIV3		0x79
+#define B2056_SYN_LOGEN_ACL1		0x7A
+#define B2056_SYN_LOGEN_ACL2		0x7B
+#define B2056_SYN_LOGEN_ACL3		0x7C
+#define B2056_SYN_LOGEN_ACL4		0x7D
+#define B2056_SYN_LOGEN_ACL5		0x7E
+#define B2056_SYN_LOGEN_ACL6		0x7F
+#define B2056_SYN_LOGEN_ACLOUT		0x80
+#define B2056_SYN_LOGEN_ACLCAL1		0x81
+#define B2056_SYN_LOGEN_ACLCAL2		0x82
+#define B2056_SYN_LOGEN_ACLCAL3		0x83
+#define B2056_SYN_CALEN			0x84
+#define B2056_SYN_LOGEN_PEAKDET1	0x85
+#define B2056_SYN_LOGEN_CORE_ACL_OVR	0x86
+#define B2056_SYN_LOGEN_RX_DIFF_ACL_OVR	0x87
+#define B2056_SYN_LOGEN_TX_DIFF_ACL_OVR	0x88
+#define B2056_SYN_LOGEN_RX_CMOS_ACL_OVR	0x89
+#define B2056_SYN_LOGEN_TX_CMOS_ACL_OVR	0x8A
+#define B2056_SYN_LOGEN_VCOBUF2		0x8B
+#define B2056_SYN_LOGEN_MIXER3		0x8C
+#define B2056_SYN_LOGEN_BUF5		0x8D
+#define B2056_SYN_LOGEN_BUF6		0x8E
+#define B2056_SYN_LOGEN_CBUFRX1		0x8F
+#define B2056_SYN_LOGEN_CBUFRX2		0x90
+#define B2056_SYN_LOGEN_CBUFRX3		0x91
+#define B2056_SYN_LOGEN_CBUFRX4		0x92
+#define B2056_SYN_LOGEN_CBUFTX1		0x93
+#define B2056_SYN_LOGEN_CBUFTX2		0x94
+#define B2056_SYN_LOGEN_CBUFTX3		0x95
+#define B2056_SYN_LOGEN_CBUFTX4		0x96
+#define B2056_SYN_LOGEN_CMOSRX1		0x97
+#define B2056_SYN_LOGEN_CMOSRX2		0x98
+#define B2056_SYN_LOGEN_CMOSRX3		0x99
+#define B2056_SYN_LOGEN_CMOSRX4		0x9A
+#define B2056_SYN_LOGEN_CMOSTX1		0x9B
+#define B2056_SYN_LOGEN_CMOSTX2		0x9C
+#define B2056_SYN_LOGEN_CMOSTX3		0x9D
+#define B2056_SYN_LOGEN_CMOSTX4		0x9E
+#define B2056_SYN_LOGEN_VCOBUF2_OVRVAL	0x9F
+#define B2056_SYN_LOGEN_MIXER3_OVRVAL	0xA0
+#define B2056_SYN_LOGEN_BUF5_OVRVAL	0xA1
+#define B2056_SYN_LOGEN_BUF6_OVRVAL	0xA2
+#define B2056_SYN_LOGEN_CBUFRX1_OVRVAL	0xA3
+#define B2056_SYN_LOGEN_CBUFRX2_OVRVAL	0xA4
+#define B2056_SYN_LOGEN_CBUFRX3_OVRVAL	0xA5
+#define B2056_SYN_LOGEN_CBUFRX4_OVRVAL	0xA6
+#define B2056_SYN_LOGEN_CBUFTX1_OVRVAL	0xA7
+#define B2056_SYN_LOGEN_CBUFTX2_OVRVAL	0xA8
+#define B2056_SYN_LOGEN_CBUFTX3_OVRVAL	0xA9
+#define B2056_SYN_LOGEN_CBUFTX4_OVRVAL	0xAA
+#define B2056_SYN_LOGEN_CMOSRX1_OVRVAL	0xAB
+#define B2056_SYN_LOGEN_CMOSRX2_OVRVAL	0xAC
+#define B2056_SYN_LOGEN_CMOSRX3_OVRVAL	0xAD
+#define B2056_SYN_LOGEN_CMOSRX4_OVRVAL	0xAE
+#define B2056_SYN_LOGEN_CMOSTX1_OVRVAL	0xAF
+#define B2056_SYN_LOGEN_CMOSTX2_OVRVAL	0xB0
+#define B2056_SYN_LOGEN_CMOSTX3_OVRVAL	0xB1
+#define B2056_SYN_LOGEN_CMOSTX4_OVRVAL	0xB2
+#define B2056_SYN_LOGEN_ACL_WAITCNT	0xB3
+#define B2056_SYN_LOGEN_CORE_CALVALID	0xB4
+#define B2056_SYN_LOGEN_RX_CMOS_CALVALID	0xB5
+#define B2056_SYN_LOGEN_TX_CMOS_VALID	0xB6
+
+#define B2056_TX_RESERVED_ADDR0		0x00
+#define B2056_TX_IDCODE			0x01
+#define B2056_TX_RESERVED_ADDR2		0x02
+#define B2056_TX_RESERVED_ADDR3		0x03
+#define B2056_TX_RESERVED_ADDR4		0x04
+#define B2056_TX_RESERVED_ADDR5		0x05
+#define B2056_TX_RESERVED_ADDR6		0x06
+#define B2056_TX_RESERVED_ADDR7		0x07
+#define B2056_TX_COM_CTRL		0x08
+#define B2056_TX_COM_PU			0x09
+#define B2056_TX_COM_OVR		0x0A
+#define B2056_TX_COM_RESET		0x0B
+#define B2056_TX_COM_RCAL		0x0C
+#define B2056_TX_COM_RC_RXLPF		0x0D
+#define B2056_TX_COM_RC_TXLPF		0x0E
+#define B2056_TX_COM_RC_RXHPF		0x0F
+#define B2056_TX_RESERVED_ADDR16	0x10
+#define B2056_TX_RESERVED_ADDR17	0x11
+#define B2056_TX_RESERVED_ADDR18	0x12
+#define B2056_TX_RESERVED_ADDR19	0x13
+#define B2056_TX_RESERVED_ADDR20	0x14
+#define B2056_TX_RESERVED_ADDR21	0x15
+#define B2056_TX_RESERVED_ADDR22	0x16
+#define B2056_TX_RESERVED_ADDR23	0x17
+#define B2056_TX_RESERVED_ADDR24	0x18
+#define B2056_TX_RESERVED_ADDR25	0x19
+#define B2056_TX_RESERVED_ADDR26	0x1A
+#define B2056_TX_RESERVED_ADDR27	0x1B
+#define B2056_TX_RESERVED_ADDR28	0x1C
+#define B2056_TX_RESERVED_ADDR29	0x1D
+#define B2056_TX_RESERVED_ADDR30	0x1E
+#define B2056_TX_RESERVED_ADDR31	0x1F
+#define B2056_TX_IQCAL_GAIN_BW		0x20
+#define B2056_TX_LOFT_FINE_I		0x21
+#define B2056_TX_LOFT_FINE_Q		0x22
+#define B2056_TX_LOFT_COARSE_I		0x23
+#define B2056_TX_LOFT_COARSE_Q		0x24
+#define B2056_TX_TX_COM_MASTER1		0x25
+#define B2056_TX_TX_COM_MASTER2		0x26
+#define B2056_TX_RXIQCAL_TXMUX		0x27
+#define B2056_TX_TX_SSI_MASTER		0x28
+#define B2056_TX_IQCAL_VCM_HG		0x29
+#define B2056_TX_IQCAL_IDAC		0x2A
+#define B2056_TX_TSSI_VCM		0x2B
+#define B2056_TX_TX_AMP_DET		0x2C
+#define B2056_TX_TX_SSI_MUX		0x2D
+#define B2056_TX_TSSIA			0x2E
+#define B2056_TX_TSSIG			0x2F
+#define B2056_TX_TSSI_MISC1		0x30
+#define B2056_TX_TSSI_MISC2		0x31
+#define B2056_TX_TSSI_MISC3		0x32
+#define B2056_TX_PA_SPARE1		0x33
+#define B2056_TX_PA_SPARE2		0x34
+#define B2056_TX_INTPAA_MASTER		0x35
+#define B2056_TX_INTPAA_GAIN		0x36
+#define B2056_TX_INTPAA_BOOST_TUNE	0x37
+#define B2056_TX_INTPAA_IAUX_STAT	0x38
+#define B2056_TX_INTPAA_IAUX_DYN	0x39
+#define B2056_TX_INTPAA_IMAIN_STAT	0x3A
+#define B2056_TX_INTPAA_IMAIN_DYN	0x3B
+#define B2056_TX_INTPAA_CASCBIAS	0x3C
+#define B2056_TX_INTPAA_PASLOPE		0x3D
+#define B2056_TX_INTPAA_PA_MISC		0x3E
+#define B2056_TX_INTPAG_MASTER		0x3F
+#define B2056_TX_INTPAG_GAIN		0x40
+#define B2056_TX_INTPAG_BOOST_TUNE	0x41
+#define B2056_TX_INTPAG_IAUX_STAT	0x42
+#define B2056_TX_INTPAG_IAUX_DYN	0x43
+#define B2056_TX_INTPAG_IMAIN_STAT	0x44
+#define B2056_TX_INTPAG_IMAIN_DYN	0x45
+#define B2056_TX_INTPAG_CASCBIAS	0x46
+#define B2056_TX_INTPAG_PASLOPE		0x47
+#define B2056_TX_INTPAG_PA_MISC		0x48
+#define B2056_TX_PADA_MASTER		0x49
+#define B2056_TX_PADA_IDAC		0x4A
+#define B2056_TX_PADA_CASCBIAS		0x4B
+#define B2056_TX_PADA_GAIN		0x4C
+#define B2056_TX_PADA_BOOST_TUNE	0x4D
+#define B2056_TX_PADA_SLOPE		0x4E
+#define B2056_TX_PADG_MASTER		0x4F
+#define B2056_TX_PADG_IDAC		0x50
+#define B2056_TX_PADG_CASCBIAS		0x51
+#define B2056_TX_PADG_GAIN		0x52
+#define B2056_TX_PADG_BOOST_TUNE	0x53
+#define B2056_TX_PADG_SLOPE		0x54
+#define B2056_TX_PGAA_MASTER		0x55
+#define B2056_TX_PGAA_IDAC		0x56
+#define B2056_TX_PGAA_GAIN		0x57
+#define B2056_TX_PGAA_BOOST_TUNE	0x58
+#define B2056_TX_PGAA_SLOPE		0x59
+#define B2056_TX_PGAA_MISC		0x5A
+#define B2056_TX_PGAG_MASTER		0x5B
+#define B2056_TX_PGAG_IDAC		0x5C
+#define B2056_TX_PGAG_GAIN		0x5D
+#define B2056_TX_PGAG_BOOST_TUNE	0x5E
+#define B2056_TX_PGAG_SLOPE		0x5F
+#define B2056_TX_PGAG_MISC		0x60
+#define B2056_TX_MIXA_MASTER		0x61
+#define B2056_TX_MIXA_BOOST_TUNE	0x62
+#define B2056_TX_MIXG			0x63
+#define B2056_TX_MIXG_BOOST_TUNE	0x64
+#define B2056_TX_BB_GM_MASTER		0x65
+#define B2056_TX_GMBB_GM		0x66
+#define B2056_TX_GMBB_IDAC		0x67
+#define B2056_TX_TXLPF_MASTER		0x68
+#define B2056_TX_TXLPF_RCCAL		0x69
+#define B2056_TX_TXLPF_RCCAL_OFF0	0x6A
+#define B2056_TX_TXLPF_RCCAL_OFF1	0x6B
+#define B2056_TX_TXLPF_RCCAL_OFF2	0x6C
+#define B2056_TX_TXLPF_RCCAL_OFF3	0x6D
+#define B2056_TX_TXLPF_RCCAL_OFF4	0x6E
+#define B2056_TX_TXLPF_RCCAL_OFF5	0x6F
+#define B2056_TX_TXLPF_RCCAL_OFF6	0x70
+#define B2056_TX_TXLPF_BW		0x71
+#define B2056_TX_TXLPF_GAIN		0x72
+#define B2056_TX_TXLPF_IDAC		0x73
+#define B2056_TX_TXLPF_IDAC_0		0x74
+#define B2056_TX_TXLPF_IDAC_1		0x75
+#define B2056_TX_TXLPF_IDAC_2		0x76
+#define B2056_TX_TXLPF_IDAC_3		0x77
+#define B2056_TX_TXLPF_IDAC_4		0x78
+#define B2056_TX_TXLPF_IDAC_5		0x79
+#define B2056_TX_TXLPF_IDAC_6		0x7A
+#define B2056_TX_TXLPF_OPAMP_IDAC	0x7B
+#define B2056_TX_TXLPF_MISC		0x7C
+#define B2056_TX_TXSPARE1		0x7D
+#define B2056_TX_TXSPARE2		0x7E
+#define B2056_TX_TXSPARE3		0x7F
+#define B2056_TX_TXSPARE4		0x80
+#define B2056_TX_TXSPARE5		0x81
+#define B2056_TX_TXSPARE6		0x82
+#define B2056_TX_TXSPARE7		0x83
+#define B2056_TX_TXSPARE8		0x84
+#define B2056_TX_TXSPARE9		0x85
+#define B2056_TX_TXSPARE10		0x86
+#define B2056_TX_TXSPARE11		0x87
+#define B2056_TX_TXSPARE12		0x88
+#define B2056_TX_TXSPARE13		0x89
+#define B2056_TX_TXSPARE14		0x8A
+#define B2056_TX_TXSPARE15		0x8B
+#define B2056_TX_TXSPARE16		0x8C
+#define B2056_TX_STATUS_INTPA_GAIN	0x8D
+#define B2056_TX_STATUS_PAD_GAIN	0x8E
+#define B2056_TX_STATUS_PGA_GAIN	0x8F
+#define B2056_TX_STATUS_GM_TXLPF_GAIN	0x90
+#define B2056_TX_STATUS_TXLPF_BW	0x91
+#define B2056_TX_STATUS_TXLPF_RC	0x92
+#define B2056_TX_GMBB_IDAC0		0x93
+#define B2056_TX_GMBB_IDAC1		0x94
+#define B2056_TX_GMBB_IDAC2		0x95
+#define B2056_TX_GMBB_IDAC3		0x96
+#define B2056_TX_GMBB_IDAC4		0x97
+#define B2056_TX_GMBB_IDAC5		0x98
+#define B2056_TX_GMBB_IDAC6		0x99
+#define B2056_TX_GMBB_IDAC7		0x9A
+
+#define B2056_RX_RESERVED_ADDR0		0x00
+#define B2056_RX_IDCODE			0x01
+#define B2056_RX_RESERVED_ADDR2		0x02
+#define B2056_RX_RESERVED_ADDR3		0x03
+#define B2056_RX_RESERVED_ADDR4		0x04
+#define B2056_RX_RESERVED_ADDR5		0x05
+#define B2056_RX_RESERVED_ADDR6		0x06
+#define B2056_RX_RESERVED_ADDR7		0x07
+#define B2056_RX_COM_CTRL		0x08
+#define B2056_RX_COM_PU			0x09
+#define B2056_RX_COM_OVR		0x0A
+#define B2056_RX_COM_RESET		0x0B
+#define B2056_RX_COM_RCAL		0x0C
+#define B2056_RX_COM_RC_RXLPF		0x0D
+#define B2056_RX_COM_RC_TXLPF		0x0E
+#define B2056_RX_COM_RC_RXHPF		0x0F
+#define B2056_RX_RESERVED_ADDR16	0x10
+#define B2056_RX_RESERVED_ADDR17	0x11
+#define B2056_RX_RESERVED_ADDR18	0x12
+#define B2056_RX_RESERVED_ADDR19	0x13
+#define B2056_RX_RESERVED_ADDR20	0x14
+#define B2056_RX_RESERVED_ADDR21	0x15
+#define B2056_RX_RESERVED_ADDR22	0x16
+#define B2056_RX_RESERVED_ADDR23	0x17
+#define B2056_RX_RESERVED_ADDR24	0x18
+#define B2056_RX_RESERVED_ADDR25	0x19
+#define B2056_RX_RESERVED_ADDR26	0x1A
+#define B2056_RX_RESERVED_ADDR27	0x1B
+#define B2056_RX_RESERVED_ADDR28	0x1C
+#define B2056_RX_RESERVED_ADDR29	0x1D
+#define B2056_RX_RESERVED_ADDR30	0x1E
+#define B2056_RX_RESERVED_ADDR31	0x1F
+#define B2056_RX_RXIQCAL_RXMUX		0x20
+#define B2056_RX_RSSI_PU		0x21
+#define B2056_RX_RSSI_SEL		0x22
+#define B2056_RX_RSSI_GAIN		0x23
+#define B2056_RX_RSSI_NB_IDAC		0x24
+#define B2056_RX_RSSI_WB2I_IDAC_1	0x25
+#define B2056_RX_RSSI_WB2I_IDAC_2	0x26
+#define B2056_RX_RSSI_WB2Q_IDAC_1	0x27
+#define B2056_RX_RSSI_WB2Q_IDAC_2	0x28
+#define B2056_RX_RSSI_POLE		0x29
+#define B2056_RX_RSSI_WB1_IDAC		0x2A
+#define B2056_RX_RSSI_MISC		0x2B
+#define B2056_RX_LNAA_MASTER		0x2C
+#define B2056_RX_LNAA_TUNE		0x2D
+#define B2056_RX_LNAA_GAIN		0x2E
+#define B2056_RX_LNA_A_SLOPE		0x2F
+#define B2056_RX_BIASPOLE_LNAA1_IDAC	0x30
+#define B2056_RX_LNAA2_IDAC		0x31
+#define B2056_RX_LNA1A_MISC		0x32
+#define B2056_RX_LNAG_MASTER		0x33
+#define B2056_RX_LNAG_TUNE		0x34
+#define B2056_RX_LNAG_GAIN		0x35
+#define B2056_RX_LNA_G_SLOPE		0x36
+#define B2056_RX_BIASPOLE_LNAG1_IDAC	0x37
+#define B2056_RX_LNAG2_IDAC		0x38
+#define B2056_RX_LNA1G_MISC		0x39
+#define B2056_RX_MIXA_MASTER		0x3A
+#define B2056_RX_MIXA_VCM		0x3B
+#define B2056_RX_MIXA_CTRLPTAT		0x3C
+#define B2056_RX_MIXA_LOB_BIAS		0x3D
+#define B2056_RX_MIXA_CORE_IDAC		0x3E
+#define B2056_RX_MIXA_CMFB_IDAC		0x3F
+#define B2056_RX_MIXA_BIAS_AUX		0x40
+#define B2056_RX_MIXA_BIAS_MAIN		0x41
+#define B2056_RX_MIXA_BIAS_MISC		0x42
+#define B2056_RX_MIXA_MAST_BIAS		0x43
+#define B2056_RX_MIXG_MASTER		0x44
+#define B2056_RX_MIXG_VCM		0x45
+#define B2056_RX_MIXG_CTRLPTAT		0x46
+#define B2056_RX_MIXG_LOB_BIAS		0x47
+#define B2056_RX_MIXG_CORE_IDAC		0x48
+#define B2056_RX_MIXG_CMFB_IDAC		0x49
+#define B2056_RX_MIXG_BIAS_AUX		0x4A
+#define B2056_RX_MIXG_BIAS_MAIN		0x4B
+#define B2056_RX_MIXG_BIAS_MISC		0x4C
+#define B2056_RX_MIXG_MAST_BIAS		0x4D
+#define B2056_RX_TIA_MASTER		0x4E
+#define B2056_RX_TIA_IOPAMP		0x4F
+#define B2056_RX_TIA_QOPAMP		0x50
+#define B2056_RX_TIA_IMISC		0x51
+#define B2056_RX_TIA_QMISC		0x52
+#define B2056_RX_TIA_GAIN		0x53
+#define B2056_RX_TIA_SPARE1		0x54
+#define B2056_RX_TIA_SPARE2		0x55
+#define B2056_RX_BB_LPF_MASTER		0x56
+#define B2056_RX_AACI_MASTER		0x57
+#define B2056_RX_RXLPF_IDAC		0x58
+#define B2056_RX_RXLPF_OPAMPBIAS_LOWQ	0x59
+#define B2056_RX_RXLPF_OPAMPBIAS_HIGHQ	0x5A
+#define B2056_RX_RXLPF_BIAS_DCCANCEL	0x5B
+#define B2056_RX_RXLPF_OUTVCM		0x5C
+#define B2056_RX_RXLPF_INVCM_BODY	0x5D
+#define B2056_RX_RXLPF_CC_OP		0x5E
+#define B2056_RX_RXLPF_GAIN		0x5F
+#define B2056_RX_RXLPF_Q_BW		0x60
+#define B2056_RX_RXLPF_HP_CORNER_BW	0x61
+#define B2056_RX_RXLPF_RCCAL_HPC	0x62
+#define B2056_RX_RXHPF_OFF0		0x63
+#define B2056_RX_RXHPF_OFF1		0x64
+#define B2056_RX_RXHPF_OFF2		0x65
+#define B2056_RX_RXHPF_OFF3		0x66
+#define B2056_RX_RXHPF_OFF4		0x67
+#define B2056_RX_RXHPF_OFF5		0x68
+#define B2056_RX_RXHPF_OFF6		0x69
+#define B2056_RX_RXHPF_OFF7		0x6A
+#define B2056_RX_RXLPF_RCCAL_LPC	0x6B
+#define B2056_RX_RXLPF_OFF_0		0x6C
+#define B2056_RX_RXLPF_OFF_1		0x6D
+#define B2056_RX_RXLPF_OFF_2		0x6E
+#define B2056_RX_RXLPF_OFF_3		0x6F
+#define B2056_RX_RXLPF_OFF_4		0x70
+#define B2056_RX_UNUSED			0x71
+#define B2056_RX_VGA_MASTER		0x72
+#define B2056_RX_VGA_BIAS		0x73
+#define B2056_RX_VGA_BIAS_DCCANCEL	0x74
+#define B2056_RX_VGA_GAIN		0x75
+#define B2056_RX_VGA_HP_CORNER_BW	0x76
+#define B2056_RX_VGABUF_BIAS		0x77
+#define B2056_RX_VGABUF_GAIN_BW		0x78
+#define B2056_RX_TXFBMIX_A		0x79
+#define B2056_RX_TXFBMIX_G		0x7A
+#define B2056_RX_RXSPARE1		0x7B
+#define B2056_RX_RXSPARE2		0x7C
+#define B2056_RX_RXSPARE3		0x7D
+#define B2056_RX_RXSPARE4		0x7E
+#define B2056_RX_RXSPARE5		0x7F
+#define B2056_RX_RXSPARE6		0x80
+#define B2056_RX_RXSPARE7		0x81
+#define B2056_RX_RXSPARE8		0x82
+#define B2056_RX_RXSPARE9		0x83
+#define B2056_RX_RXSPARE10		0x84
+#define B2056_RX_RXSPARE11		0x85
+#define B2056_RX_RXSPARE12		0x86
+#define B2056_RX_RXSPARE13		0x87
+#define B2056_RX_RXSPARE14		0x88
+#define B2056_RX_RXSPARE15		0x89
+#define B2056_RX_RXSPARE16		0x8A
+#define B2056_RX_STATUS_LNAA_GAIN	0x8B
+#define B2056_RX_STATUS_LNAG_GAIN	0x8C
+#define B2056_RX_STATUS_MIXTIA_GAIN	0x8D
+#define B2056_RX_STATUS_RXLPF_GAIN	0x8E
+#define B2056_RX_STATUS_VGA_BUF_GAIN	0x8F
+#define B2056_RX_STATUS_RXLPF_Q		0x90
+#define B2056_RX_STATUS_RXLPF_BUF_BW	0x91
+#define B2056_RX_STATUS_RXLPF_VGA_HPC	0x92
+#define B2056_RX_STATUS_RXLPF_RC	0x93
+#define B2056_RX_STATUS_HPC_RC		0x94
+
+#define B2056_LNA1_A_PU			0x01
+#define B2056_LNA2_A_PU			0x02
+#define B2056_LNA1_G_PU			0x01
+#define B2056_LNA2_G_PU			0x02
+#define B2056_MIXA_PU_I			0x01
+#define B2056_MIXA_PU_Q			0x02
+#define B2056_MIXA_PU_GM		0x10
+#define B2056_MIXG_PU_I			0x01
+#define B2056_MIXG_PU_Q			0x02
+#define B2056_MIXG_PU_GM		0x10
+#define B2056_TIA_PU			0x01
+#define B2056_BB_LPF_PU			0x20
+#define B2056_W1_PU			0x02
+#define B2056_W2_PU			0x04
+#define B2056_NB_PU			0x08
+#define B2056_RSSI_W1_SEL		0x02
+#define B2056_RSSI_W2_SEL		0x04
+#define B2056_RSSI_NB_SEL		0x08
+#define B2056_VCM_MASK			0x1C
+#define B2056_RSSI_VCM_SHIFT		0x02
+
+struct b43_nphy_channeltab_entry_rev3 {
+	/* The channel frequency in MHz */
+	u16 freq;
+	/* Radio register values on channelswitch */
+	u8 radio_syn_pll_vcocal1;
+	u8 radio_syn_pll_vcocal2;
+	u8 radio_syn_pll_refdiv;
+	u8 radio_syn_pll_mmd2;
+	u8 radio_syn_pll_mmd1;
+	u8 radio_syn_pll_loopfilter1;
+	u8 radio_syn_pll_loopfilter2;
+	u8 radio_syn_pll_loopfilter3;
+	u8 radio_syn_pll_loopfilter4;
+	u8 radio_syn_pll_loopfilter5;
+	u8 radio_syn_reserved_addr27;
+	u8 radio_syn_reserved_addr28;
+	u8 radio_syn_reserved_addr29;
+	u8 radio_syn_logen_vcobuf1;
+	u8 radio_syn_logen_mixer2;
+	u8 radio_syn_logen_buf3;
+	u8 radio_syn_logen_buf4;
+	u8 radio_rx0_lnaa_tune;
+	u8 radio_rx0_lnag_tune;
+	u8 radio_tx0_intpaa_boost_tune;
+	u8 radio_tx0_intpag_boost_tune;
+	u8 radio_tx0_pada_boost_tune;
+	u8 radio_tx0_padg_boost_tune;
+	u8 radio_tx0_pgaa_boost_tune;
+	u8 radio_tx0_pgag_boost_tune;
+	u8 radio_tx0_mixa_boost_tune;
+	u8 radio_tx0_mixg_boost_tune;
+	u8 radio_rx1_lnaa_tune;
+	u8 radio_rx1_lnag_tune;
+	u8 radio_tx1_intpaa_boost_tune;
+	u8 radio_tx1_intpag_boost_tune;
+	u8 radio_tx1_pada_boost_tune;
+	u8 radio_tx1_padg_boost_tune;
+	u8 radio_tx1_pgaa_boost_tune;
+	u8 radio_tx1_pgag_boost_tune;
+	u8 radio_tx1_mixa_boost_tune;
+	u8 radio_tx1_mixg_boost_tune;
+	/* PHY register values on channelswitch */
+	struct b43_phy_n_sfo_cfg phy_regs;
+};
+
+void b2056_upload_inittabs(struct b43_wldev *dev,
+			   bool ghz5, bool ignore_uploadflag);
+void b2056_upload_syn_pll_cp2(struct b43_wldev *dev, bool ghz5);
+
+/* Get the NPHY Channel Switch Table entry for a channel.
+ * Returns NULL on failure to find an entry. */
+const struct b43_nphy_channeltab_entry_rev3 *
+b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq);
+
+#endif /* B43_RADIO_2056_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/radio_2057.c b/drivers/net/wireless/broadcom/b43/radio_2057.c
new file mode 100644
index 0000000..ff1e026
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/radio_2057.c
@@ -0,0 +1,637 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11n 2057 radio device data tables
+
+  Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
+
+  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 "radio_2057.h"
+#include "phy_common.h"
+
+static u16 r2057_rev4_init[][2] = {
+	{ 0x0E, 0x20 }, { 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 },
+	{ 0x35, 0x26 }, { 0x3C, 0xff }, { 0x3D, 0xff }, { 0x3E, 0xff },
+	{ 0x3F, 0xff }, { 0x62, 0x33 }, { 0x8A, 0xf0 }, { 0x8B, 0x10 },
+	{ 0x8C, 0xf0 }, { 0x91, 0x3f }, { 0x92, 0x36 }, { 0xA4, 0x8c },
+	{ 0xA8, 0x55 }, { 0xAF, 0x01 }, { 0x10F, 0xf0 }, { 0x110, 0x10 },
+	{ 0x111, 0xf0 }, { 0x116, 0x3f }, { 0x117, 0x36 }, { 0x129, 0x8c },
+	{ 0x12D, 0x55 }, { 0x134, 0x01 }, { 0x15E, 0x00 }, { 0x15F, 0x00 },
+	{ 0x160, 0x00 }, { 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 },
+	{ 0x169, 0x02 }, { 0x16A, 0x00 }, { 0x16B, 0x00 }, { 0x16C, 0x00 },
+	{ 0x1A4, 0x00 }, { 0x1A5, 0x00 }, { 0x1A6, 0x00 }, { 0x1AA, 0x00 },
+	{ 0x1AB, 0x00 }, { 0x1AC, 0x00 },
+};
+
+static u16 r2057_rev5_init[][2] = {
+	{ 0x00, 0x00 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x23, 0x6 },
+	{ 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 },
+	{ 0x59, 0x88 }, { 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f },
+	{ 0x64, 0x0f }, { 0x81, 0x01 }, { 0x91, 0x3f }, { 0x92, 0x36 },
+	{ 0xA1, 0x20 }, { 0xD6, 0x70 }, { 0xDE, 0x88 }, { 0xE1, 0x20 },
+	{ 0xE8, 0x0f }, { 0xE9, 0x0f }, { 0x106, 0x01 }, { 0x116, 0x3f },
+	{ 0x117, 0x36 }, { 0x126, 0x20 }, { 0x15E, 0x00 }, { 0x15F, 0x00 },
+	{ 0x160, 0x00 }, { 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 },
+	{ 0x16A, 0x00 }, { 0x16B, 0x00 }, { 0x16C, 0x00 }, { 0x1A4, 0x00 },
+	{ 0x1A5, 0x00 }, { 0x1A6, 0x00 }, { 0x1AA, 0x00 }, { 0x1AB, 0x00 },
+	{ 0x1AC, 0x00 }, { 0x1B7, 0x0c }, { 0x1C1, 0x01 }, { 0x1C2, 0x80 },
+};
+
+static u16 r2057_rev5a_init[][2] = {
+	{ 0x00, 0x15 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x23, 0x6 },
+	{ 0x31, 0x00 }, { 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 },
+	{ 0x59, 0x88 }, { 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f },
+	{ 0x64, 0x0f }, { 0x81, 0x01 }, { 0x91, 0x3f }, { 0x92, 0x36 },
+	{ 0xC9, 0x01 }, { 0xD6, 0x70 }, { 0xDE, 0x88 }, { 0xE1, 0x20 },
+	{ 0xE8, 0x0f }, { 0xE9, 0x0f }, { 0x106, 0x01 }, { 0x116, 0x3f },
+	{ 0x117, 0x36 }, { 0x126, 0x20 }, { 0x14E, 0x01 }, { 0x15E, 0x00 },
+	{ 0x15F, 0x00 }, { 0x160, 0x00 }, { 0x161, 0x00 }, { 0x162, 0x00 },
+	{ 0x163, 0x00 }, { 0x16A, 0x00 }, { 0x16B, 0x00 }, { 0x16C, 0x00 },
+	{ 0x1A4, 0x00 }, { 0x1A5, 0x00 }, { 0x1A6, 0x00 }, { 0x1AA, 0x00 },
+	{ 0x1AB, 0x00 }, { 0x1AC, 0x00 }, { 0x1B7, 0x0c }, { 0x1C1, 0x01 },
+	{ 0x1C2, 0x80 },
+};
+
+static u16 r2057_rev7_init[][2] = {
+	{ 0x00, 0x00 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x31, 0x00 },
+	{ 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 }, { 0x59, 0x88 },
+	{ 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f }, { 0x64, 0x13 },
+	{ 0x66, 0xee }, { 0x6E, 0x58 }, { 0x75, 0x13 }, { 0x7B, 0x13 },
+	{ 0x7C, 0x14 }, { 0x7D, 0xee }, { 0x81, 0x01 }, { 0x91, 0x3f },
+	{ 0x92, 0x36 }, { 0xA1, 0x20 }, { 0xD6, 0x70 }, { 0xDE, 0x88 },
+	{ 0xE1, 0x20 }, { 0xE8, 0x0f }, { 0xE9, 0x13 }, { 0xEB, 0xee },
+	{ 0xF3, 0x58 }, { 0xFA, 0x13 }, { 0x100, 0x13 }, { 0x101, 0x14 },
+	{ 0x102, 0xee }, { 0x106, 0x01 }, { 0x116, 0x3f }, { 0x117, 0x36 },
+	{ 0x126, 0x20 }, { 0x15E, 0x00 }, { 0x15F, 0x00 }, { 0x160, 0x00 },
+	{ 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 }, { 0x16A, 0x00 },
+	{ 0x16B, 0x00 }, { 0x16C, 0x00 }, { 0x1A4, 0x00 }, { 0x1A5, 0x00 },
+	{ 0x1A6, 0x00 }, { 0x1AA, 0x00 }, { 0x1AB, 0x00 }, { 0x1AC, 0x00 },
+	{ 0x1B7, 0x05 }, { 0x1C2, 0xa0 },
+};
+
+/* TODO: Which devices should use it?
+static u16 r2057_rev8_init[][2] = {
+	{ 0x00, 0x08 }, { 0x01, 0x57 }, { 0x02, 0x20 }, { 0x31, 0x00 },
+	{ 0x32, 0x00 }, { 0x33, 0x00 }, { 0x51, 0x70 }, { 0x59, 0x88 },
+	{ 0x5C, 0x20 }, { 0x62, 0x33 }, { 0x63, 0x0f }, { 0x64, 0x0f },
+	{ 0x6E, 0x58 }, { 0x75, 0x13 }, { 0x7B, 0x13 }, { 0x7C, 0x0f },
+	{ 0x7D, 0xee }, { 0x81, 0x01 }, { 0x91, 0x3f }, { 0x92, 0x36 },
+	{ 0xA1, 0x20 }, { 0xC9, 0x01 }, { 0xD6, 0x70 }, { 0xDE, 0x88 },
+	{ 0xE1, 0x20 }, { 0xE8, 0x0f }, { 0xE9, 0x0f }, { 0xF3, 0x58 },
+	{ 0xFA, 0x13 }, { 0x100, 0x13 }, { 0x101, 0x0f }, { 0x102, 0xee },
+	{ 0x106, 0x01 }, { 0x116, 0x3f }, { 0x117, 0x36 }, { 0x126, 0x20 },
+	{ 0x14E, 0x01 }, { 0x15E, 0x00 }, { 0x15F, 0x00 }, { 0x160, 0x00 },
+	{ 0x161, 0x00 }, { 0x162, 0x00 }, { 0x163, 0x00 }, { 0x16A, 0x00 },
+	{ 0x16B, 0x00 }, { 0x16C, 0x00 }, { 0x1A4, 0x00 }, { 0x1A5, 0x00 },
+	{ 0x1A6, 0x00 }, { 0x1AA, 0x00 }, { 0x1AB, 0x00 }, { 0x1AC, 0x00 },
+	{ 0x1B7, 0x05 }, { 0x1C2, 0xa0 },
+};
+*/
+
+/* Extracted from MMIO dump of 6.30.223.141 */
+static u16 r2057_rev9_init[][2] = {
+	{ 0x27, 0x1f }, { 0x28, 0x0a }, { 0x29, 0x2f }, { 0x42, 0x1f },
+	{ 0x48, 0x3f }, { 0x5c, 0x41 }, { 0x63, 0x14 }, { 0x64, 0x12 },
+	{ 0x66, 0xff }, { 0x74, 0xa3 }, { 0x7b, 0x14 }, { 0x7c, 0x14 },
+	{ 0x7d, 0xee }, { 0x86, 0xc0 }, { 0xc4, 0x10 }, { 0xc9, 0x01 },
+	{ 0xe1, 0x41 }, { 0xe8, 0x14 }, { 0xe9, 0x12 }, { 0xeb, 0xff },
+	{ 0xf5, 0x0a }, { 0xf8, 0x09 }, { 0xf9, 0xa3 }, { 0x100, 0x14 },
+	{ 0x101, 0x10 }, { 0x102, 0xee }, { 0x10b, 0xc0 }, { 0x149, 0x10 },
+	{ 0x14e, 0x01 }, { 0x1b7, 0x05 }, { 0x1c2, 0xa0 },
+};
+
+/* Extracted from MMIO dump of 6.30.223.248 */
+static u16 r2057_rev14_init[][2] = {
+	{ 0x011, 0xfc }, { 0x030, 0x24 }, { 0x040, 0x1c }, { 0x082, 0x08 },
+	{ 0x0b4, 0x44 }, { 0x0c8, 0x01 }, { 0x0c9, 0x01 }, { 0x107, 0x08 },
+	{ 0x14d, 0x01 }, { 0x14e, 0x01 }, { 0x1af, 0x40 }, { 0x1b0, 0x40 },
+	{ 0x1cc, 0x01 }, { 0x1cf, 0x10 }, { 0x1d0, 0x0f }, { 0x1d3, 0x10 },
+	{ 0x1d4, 0x0f },
+};
+
+#define RADIOREGS7(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) \
+	.radio_vcocal_countval0			= r00,	\
+	.radio_vcocal_countval1			= r01,	\
+	.radio_rfpll_refmaster_sparextalsize	= r02,	\
+	.radio_rfpll_loopfilter_r1		= r03,	\
+	.radio_rfpll_loopfilter_c2		= r04,	\
+	.radio_rfpll_loopfilter_c1		= r05,	\
+	.radio_cp_kpd_idac			= r06,	\
+	.radio_rfpll_mmd0			= r07,	\
+	.radio_rfpll_mmd1			= r08,	\
+	.radio_vcobuf_tune			= r09,	\
+	.radio_logen_mx2g_tune			= r10,	\
+	.radio_logen_mx5g_tune			= r11,	\
+	.radio_logen_indbuf2g_tune		= r12,	\
+	.radio_logen_indbuf5g_tune		= r13,	\
+	.radio_txmix2g_tune_boost_pu_core0	= r14,	\
+	.radio_pad2g_tune_pus_core0		= r15,	\
+	.radio_pga_boost_tune_core0		= r16,	\
+	.radio_txmix5g_boost_tune_core0		= r17,	\
+	.radio_pad5g_tune_misc_pus_core0	= r18,	\
+	.radio_lna2g_tune_core0			= r19,	\
+	.radio_lna5g_tune_core0			= r20,	\
+	.radio_txmix2g_tune_boost_pu_core1	= r21,	\
+	.radio_pad2g_tune_pus_core1		= r22,	\
+	.radio_pga_boost_tune_core1		= r23,	\
+	.radio_txmix5g_boost_tune_core1		= r24,	\
+	.radio_pad5g_tune_misc_pus_core1	= r25,	\
+	.radio_lna2g_tune_core1			= r26,	\
+	.radio_lna5g_tune_core1			= r27
+
+#define RADIOREGS7_2G(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
+		      r10, r11, r12, r13, r14, r15, r16, r17) \
+	.radio_vcocal_countval0			= r00,	\
+	.radio_vcocal_countval1			= r01,	\
+	.radio_rfpll_refmaster_sparextalsize	= r02,	\
+	.radio_rfpll_loopfilter_r1		= r03,	\
+	.radio_rfpll_loopfilter_c2		= r04,	\
+	.radio_rfpll_loopfilter_c1		= r05,	\
+	.radio_cp_kpd_idac			= r06,	\
+	.radio_rfpll_mmd0			= r07,	\
+	.radio_rfpll_mmd1			= r08,	\
+	.radio_vcobuf_tune			= r09,	\
+	.radio_logen_mx2g_tune			= r10,	\
+	.radio_logen_indbuf2g_tune		= r11,	\
+	.radio_txmix2g_tune_boost_pu_core0	= r12,	\
+	.radio_pad2g_tune_pus_core0		= r13,	\
+	.radio_lna2g_tune_core0			= r14,	\
+	.radio_txmix2g_tune_boost_pu_core1	= r15,	\
+	.radio_pad2g_tune_pus_core1		= r16,	\
+	.radio_lna2g_tune_core1			= r17
+
+#define PHYREGS(r0, r1, r2, r3, r4, r5)	\
+	.phy_regs.phy_bw1a	= r0,	\
+	.phy_regs.phy_bw2	= r1,	\
+	.phy_regs.phy_bw3	= r2,	\
+	.phy_regs.phy_bw4	= r3,	\
+	.phy_regs.phy_bw5	= r4,	\
+	.phy_regs.phy_bw6	= r5
+
+/* Copied from brcmsmac (5.75.11): chan_info_nphyrev8_2057_rev5 */
+static const struct b43_nphy_chantabent_rev7_2g b43_nphy_chantab_phy_rev8_radio_rev5[] = {
+	{
+		.freq			= 2412,
+		RADIOREGS7_2G(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
+			      0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61,
+			      0x03, 0xff),
+		PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+	},
+	{
+		.freq			= 2417,
+		RADIOREGS7_2G(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
+			      0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61,
+			      0x03, 0xff),
+		PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+	},
+	{
+		.freq			= 2422,
+		RADIOREGS7_2G(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
+			      0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61,
+			      0x03, 0xef),
+		PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+	},
+	{
+		.freq			= 2427,
+		RADIOREGS7_2G(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
+			      0x09, 0x0c, 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61,
+			      0x03, 0xdf),
+		PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+	},
+	{
+		.freq			= 2432,
+		RADIOREGS7_2G(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
+			      0x09, 0x0c, 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61,
+			      0x03, 0xcf),
+		PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+	},
+	{
+		.freq			= 2437,
+		RADIOREGS7_2G(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
+			      0x09, 0x0c, 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61,
+			      0x03, 0xbf),
+		PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+	},
+	{
+		.freq			= 2442,
+		RADIOREGS7_2G(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
+			      0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61,
+			      0x03, 0xaf),
+		PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+	},
+	{
+		.freq			= 2447,
+		RADIOREGS7_2G(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
+			      0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61,
+			      0x03, 0x9f),
+		PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+	},
+	{
+		.freq			= 2452,
+		RADIOREGS7_2G(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
+			      0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61,
+			      0x03, 0x8f),
+		PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+	},
+	{
+		.freq			= 2457,
+		RADIOREGS7_2G(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
+			      0x09, 0x0b, 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61,
+			      0x03, 0x7f),
+		PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+	},
+	{
+		.freq			= 2462,
+		RADIOREGS7_2G(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
+			      0x09, 0x0b, 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61,
+			      0x03, 0x6f),
+		PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+	},
+	{
+		.freq			= 2467,
+		RADIOREGS7_2G(0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3,
+			      0x09, 0x0b, 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61,
+			      0x03, 0x5f),
+		PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
+	},
+	{
+		.freq			= 2472,
+		RADIOREGS7_2G(0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8,
+			      0x09, 0x0a, 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61,
+			      0x03, 0x4f),
+		PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
+	},
+	{
+		.freq			= 2484,
+		RADIOREGS7_2G(0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4,
+			      0x09, 0x0a, 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61,
+			      0x03, 0x3f),
+		PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424),
+	}
+};
+
+/* Extracted from MMIO dump of 6.30.223.248 */
+static const struct b43_nphy_chantabent_rev7_2g b43_nphy_chantab_phy_rev17_radio_rev14[] = {
+	{
+		.freq			= 2412,
+		RADIOREGS7_2G(0x48, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x6c,
+			      0x09, 0x0d, 0x09, 0x03, 0x21, 0x53, 0xff, 0x21,
+			      0x53, 0xff),
+		PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+	},
+	{
+		.freq			= 2417,
+		RADIOREGS7_2G(0x4b, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x71,
+			      0x09, 0x0d, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
+			      0x53, 0xff),
+		PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+	},
+	{
+		.freq			= 2422,
+		RADIOREGS7_2G(0x4e, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x76,
+			      0x09, 0x0d, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
+			      0x53, 0xff),
+		PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+	},
+	{
+		.freq			= 2427,
+		RADIOREGS7_2G(0x52, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x7b,
+			      0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
+			      0x53, 0xff),
+		PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+	},
+	{
+		.freq			= 2432,
+		RADIOREGS7_2G(0x55, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x80,
+			      0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
+			      0x53, 0xff),
+		PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+	},
+	{
+		.freq			= 2437,
+		RADIOREGS7_2G(0x58, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x85,
+			      0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
+			      0x53, 0xff),
+		PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+	},
+	{
+		.freq			= 2442,
+		RADIOREGS7_2G(0x5c, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x8a,
+			      0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21,
+			      0x43, 0xff),
+		PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+	},
+	{
+		.freq			= 2447,
+		RADIOREGS7_2G(0x5f, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x8f,
+			      0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21,
+			      0x43, 0xff),
+		PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+	},
+	{
+		.freq			= 2452,
+		RADIOREGS7_2G(0x62, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x94,
+			      0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21,
+			      0x43, 0xff),
+		PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+	},
+	{
+		.freq			= 2457,
+		RADIOREGS7_2G(0x66, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x99,
+			      0x09, 0x0b, 0x07, 0x03, 0x21, 0x43, 0xff, 0x21,
+			      0x43, 0xff),
+		PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+	},
+	{
+		.freq			= 2462,
+		RADIOREGS7_2G(0x69, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x9e,
+			      0x09, 0x0b, 0x07, 0x03, 0x01, 0x43, 0xff, 0x01,
+			      0x43, 0xff),
+		PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+	},
+};
+
+/* Extracted from MMIO dump of 6.30.223.141 */
+static const struct b43_nphy_chantabent_rev7 b43_nphy_chantab_phy_rev16_radio_rev9[] = {
+	{
+		.freq			= 2412,
+		RADIOREGS7(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
+			   0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x41, 0x63,
+			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+			   0x00, 0x00, 0xf0, 0x00),
+		PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+	},
+	{
+		.freq			= 2417,
+		RADIOREGS7(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
+			   0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x41, 0x63,
+			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+			   0x00, 0x00, 0xf0, 0x00),
+		PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+	},
+	{
+		.freq			= 2422,
+		RADIOREGS7(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
+			   0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x41, 0x63,
+			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+			   0x00, 0x00, 0xf0, 0x00),
+		PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+	},
+	{
+		.freq			= 2427,
+		RADIOREGS7(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
+			   0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x41, 0x63,
+			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+			   0x00, 0x00, 0xf0, 0x00),
+		PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+	},
+	{
+		.freq			= 2432,
+		RADIOREGS7(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
+			   0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x41, 0x63,
+			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+			   0x00, 0x00, 0xf0, 0x00),
+		PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+	},
+	{
+		.freq			= 2437,
+		RADIOREGS7(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
+			   0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x41, 0x63,
+			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+			   0x00, 0x00, 0xf0, 0x00),
+		PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+	},
+	{
+		.freq			= 2442,
+		RADIOREGS7(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
+			   0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63,
+			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+			   0x00, 0x00, 0xf0, 0x00),
+		PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+	},
+	{
+		.freq			= 2447,
+		RADIOREGS7(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
+			   0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63,
+			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+			   0x00, 0x00, 0xf0, 0x00),
+		PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+	},
+	{
+		.freq			= 2452,
+		RADIOREGS7(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
+			   0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63,
+			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+			   0x00, 0x00, 0xf0, 0x00),
+		PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+	},
+	{
+		.freq			= 2457,
+		RADIOREGS7(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
+			   0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x41, 0x63,
+			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+			   0x00, 0x00, 0xf0, 0x00),
+		PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+	},
+	{
+		.freq			= 2462,
+		RADIOREGS7(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
+			   0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x41, 0x63,
+			   0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
+			   0x00, 0x00, 0xf0, 0x00),
+		PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
+	},
+	{
+		.freq			= 5180,
+		RADIOREGS7(0xbe, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x06,
+			   0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00,
+			   0x9f, 0x2f, 0xa3, 0x00, 0xfc, 0x00, 0x00, 0x4f,
+			   0x3a, 0x83, 0x00, 0xfc),
+		PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb),
+	},
+	{
+		.freq			= 5200,
+		RADIOREGS7(0xc5, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x08,
+			   0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00,
+			   0x7f, 0x2f, 0x83, 0x00, 0xf8, 0x00, 0x00, 0x4c,
+			   0x4a, 0x83, 0x00, 0xf8),
+		PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9),
+	},
+	{
+		.freq			= 5220,
+		RADIOREGS7(0xcc, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x0a,
+			   0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00,
+			   0x6d, 0x3d, 0x83, 0x00, 0xf8, 0x00, 0x00, 0x2d,
+			   0x2a, 0x73, 0x00, 0xf8),
+		PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7),
+	},
+	{
+		.freq			= 5240,
+		RADIOREGS7(0xd2, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x0c,
+			   0x02, 0x0d, 0x00, 0x0d, 0x00, 0x8d, 0x00, 0x00,
+			   0x4d, 0x1c, 0x73, 0x00, 0xf8, 0x00, 0x00, 0x4d,
+			   0x2b, 0x73, 0x00, 0xf8),
+		PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5),
+	},
+	{
+		.freq			= 5745,
+		RADIOREGS7(0x7b, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x7d,
+			   0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00,
+			   0x08, 0x03, 0x03, 0x00, 0x30, 0x00, 0x00, 0x06,
+			   0x02, 0x03, 0x00, 0x30),
+		PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9),
+	},
+	{
+		.freq			= 5765,
+		RADIOREGS7(0x81, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x81,
+			   0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00,
+			   0x06, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05,
+			   0x02, 0x03, 0x00, 0x00),
+		PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8),
+	},
+	{
+		.freq			= 5785,
+		RADIOREGS7(0x88, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x85,
+			   0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00,
+			   0x08, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05,
+			   0x21, 0x03, 0x00, 0x00),
+		PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6),
+	},
+	{
+		.freq			= 5805,
+		RADIOREGS7(0x8f, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x89,
+			   0x04, 0x07, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00,
+			   0x06, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03,
+			   0x00, 0x03, 0x00, 0x00),
+		PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4),
+	},
+	{
+		.freq			= 5825,
+		RADIOREGS7(0x95, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x8d,
+			   0x04, 0x07, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00,
+			   0x05, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03,
+			   0x00, 0x03, 0x00, 0x00),
+		PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3),
+	},
+};
+
+void r2057_upload_inittabs(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	u16 *table = NULL;
+	u16 size, i;
+
+	switch (phy->rev) {
+	case 7:
+		table = r2057_rev4_init[0];
+		size = ARRAY_SIZE(r2057_rev4_init);
+		break;
+	case 8:
+		if (phy->radio_rev == 5) {
+			table = r2057_rev5_init[0];
+			size = ARRAY_SIZE(r2057_rev5_init);
+		} else if (phy->radio_rev == 7) {
+			table = r2057_rev7_init[0];
+			size = ARRAY_SIZE(r2057_rev7_init);
+		}
+		break;
+	case 9:
+		if (phy->radio_rev == 5) {
+			table = r2057_rev5a_init[0];
+			size = ARRAY_SIZE(r2057_rev5a_init);
+		}
+		break;
+	case 16:
+		if (phy->radio_rev == 9) {
+			table = r2057_rev9_init[0];
+			size = ARRAY_SIZE(r2057_rev9_init);
+		}
+		break;
+	case 17:
+		if (phy->radio_rev == 14) {
+			table = r2057_rev14_init[0];
+			size = ARRAY_SIZE(r2057_rev14_init);
+		}
+		break;
+	}
+
+	B43_WARN_ON(!table);
+
+	if (table) {
+		for (i = 0; i < size; i++, table += 2)
+			b43_radio_write(dev, table[0], table[1]);
+	}
+}
+
+void r2057_get_chantabent_rev7(struct b43_wldev *dev, u16 freq,
+			       const struct b43_nphy_chantabent_rev7 **tabent_r7,
+			       const struct b43_nphy_chantabent_rev7_2g **tabent_r7_2g)
+{
+	struct b43_phy *phy = &dev->phy;
+	const struct b43_nphy_chantabent_rev7 *e_r7 = NULL;
+	const struct b43_nphy_chantabent_rev7_2g *e_r7_2g = NULL;
+	unsigned int len, i;
+
+	*tabent_r7 = NULL;
+	*tabent_r7_2g = NULL;
+
+	switch (phy->rev) {
+	case 8:
+		if (phy->radio_rev == 5) {
+			e_r7_2g = b43_nphy_chantab_phy_rev8_radio_rev5;
+			len = ARRAY_SIZE(b43_nphy_chantab_phy_rev8_radio_rev5);
+		}
+		break;
+	case 16:
+		if (phy->radio_rev == 9) {
+			e_r7 = b43_nphy_chantab_phy_rev16_radio_rev9;
+			len = ARRAY_SIZE(b43_nphy_chantab_phy_rev16_radio_rev9);
+		}
+		break;
+	case 17:
+		if (phy->radio_rev == 14) {
+			e_r7_2g = b43_nphy_chantab_phy_rev17_radio_rev14;
+			len = ARRAY_SIZE(b43_nphy_chantab_phy_rev17_radio_rev14);
+		}
+		break;
+	default:
+		break;
+	}
+
+	if (e_r7) {
+		for (i = 0; i < len; i++, e_r7++) {
+			if (e_r7->freq == freq) {
+				*tabent_r7 = e_r7;
+				return;
+			}
+		}
+	} else if (e_r7_2g) {
+		for (i = 0; i < len; i++, e_r7_2g++) {
+			if (e_r7_2g->freq == freq) {
+				*tabent_r7_2g = e_r7_2g;
+				return;
+			}
+		}
+	} else {
+		B43_WARN_ON(1);
+	}
+}
diff --git a/drivers/net/wireless/broadcom/b43/radio_2057.h b/drivers/net/wireless/broadcom/b43/radio_2057.h
new file mode 100644
index 0000000..d7959da
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/radio_2057.h
@@ -0,0 +1,507 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_RADIO_2057_H_
+#define B43_RADIO_2057_H_
+
+#include <linux/types.h>
+
+#include "tables_nphy.h"
+
+#define R2057_DACBUF_VINCM_CORE0		0x000
+#define R2057_IDCODE				0x001
+#define R2057_RCCAL_MASTER			0x002
+#define R2057_RCCAL_CAP_SIZE			0x003
+#define R2057_RCAL_CONFIG			0x004
+#define R2057_GPAIO_CONFIG			0x005
+#define R2057_GPAIO_SEL1			0x006
+#define R2057_GPAIO_SEL0			0x007
+#define R2057_CLPO_CONFIG			0x008
+#define R2057_BANDGAP_CONFIG			0x009
+#define R2057_BANDGAP_RCAL_TRIM			0x00a
+#define R2057_AFEREG_CONFIG			0x00b
+#define R2057_TEMPSENSE_CONFIG			0x00c
+#define R2057_XTAL_CONFIG1			0x00d
+#define R2057_XTAL_ICORE_SIZE			0x00e
+#define R2057_XTAL_BUF_SIZE			0x00f
+#define R2057_XTAL_PULLCAP_SIZE			0x010
+#define R2057_RFPLL_MASTER			0x011
+#define R2057_VCOMONITOR_VTH_L			0x012
+#define R2057_VCOMONITOR_VTH_H			0x013
+#define R2057_VCOCAL_BIASRESET_RFPLLREG_VOUT	0x014
+#define R2057_VCO_VARCSIZE_IDAC			0x015
+#define R2057_VCOCAL_COUNTVAL0			0x016
+#define R2057_VCOCAL_COUNTVAL1			0x017
+#define R2057_VCOCAL_INTCLK_COUNT		0x018
+#define R2057_VCOCAL_MASTER			0x019
+#define R2057_VCOCAL_NUMCAPCHANGE		0x01a
+#define R2057_VCOCAL_WINSIZE			0x01b
+#define R2057_VCOCAL_DELAY_AFTER_REFRESH	0x01c
+#define R2057_VCOCAL_DELAY_AFTER_CLOSELOOP	0x01d
+#define R2057_VCOCAL_DELAY_AFTER_OPENLOOP	0x01e
+#define R2057_VCOCAL_DELAY_BEFORE_OPENLOOP	0x01f
+#define R2057_VCO_FORCECAPEN_FORCECAP1		0x020
+#define R2057_VCO_FORCECAP0			0x021
+#define R2057_RFPLL_REFMASTER_SPAREXTALSIZE	0x022
+#define R2057_RFPLL_PFD_RESET_PW		0x023
+#define R2057_RFPLL_LOOPFILTER_R2		0x024
+#define R2057_RFPLL_LOOPFILTER_R1		0x025
+#define R2057_RFPLL_LOOPFILTER_C3		0x026
+#define R2057_RFPLL_LOOPFILTER_C2		0x027
+#define R2057_RFPLL_LOOPFILTER_C1		0x028
+#define R2057_CP_KPD_IDAC			0x029
+#define R2057_RFPLL_IDACS			0x02a
+#define R2057_RFPLL_MISC_EN			0x02b
+#define R2057_RFPLL_MMD0			0x02c
+#define R2057_RFPLL_MMD1			0x02d
+#define R2057_RFPLL_MISC_CAL_RESETN		0x02e
+#define R2057_JTAGXTAL_SIZE_CPBIAS_FILTRES	0x02f
+#define R2057_VCO_ALCREF_BBPLLXTAL_SIZE		0x030
+#define R2057_VCOCAL_READCAP0			0x031
+#define R2057_VCOCAL_READCAP1			0x032
+#define R2057_VCOCAL_STATUS			0x033
+#define R2057_LOGEN_PUS				0x034
+#define R2057_LOGEN_PTAT_RESETS			0x035
+#define R2057_VCOBUF_IDACS			0x036
+#define R2057_VCOBUF_TUNE			0x037
+#define R2057_CMOSBUF_TX2GQ_IDACS		0x038
+#define R2057_CMOSBUF_TX2GI_IDACS		0x039
+#define R2057_CMOSBUF_TX5GQ_IDACS		0x03a
+#define R2057_CMOSBUF_TX5GI_IDACS		0x03b
+#define R2057_CMOSBUF_RX2GQ_IDACS		0x03c
+#define R2057_CMOSBUF_RX2GI_IDACS		0x03d
+#define R2057_CMOSBUF_RX5GQ_IDACS		0x03e
+#define R2057_CMOSBUF_RX5GI_IDACS		0x03f
+#define R2057_LOGEN_MX2G_IDACS			0x040
+#define R2057_LOGEN_MX2G_TUNE			0x041
+#define R2057_LOGEN_MX5G_IDACS			0x042
+#define R2057_LOGEN_MX5G_TUNE			0x043
+#define R2057_LOGEN_MX5G_RCCR			0x044
+#define R2057_LOGEN_INDBUF2G_IDAC		0x045
+#define R2057_LOGEN_INDBUF2G_IBOOST		0x046
+#define R2057_LOGEN_INDBUF2G_TUNE		0x047
+#define R2057_LOGEN_INDBUF5G_IDAC		0x048
+#define R2057_LOGEN_INDBUF5G_IBOOST		0x049
+#define R2057_LOGEN_INDBUF5G_TUNE		0x04a
+#define R2057_CMOSBUF_TX_RCCR			0x04b
+#define R2057_CMOSBUF_RX_RCCR			0x04c
+#define R2057_LOGEN_SEL_PKDET			0x04d
+#define R2057_CMOSBUF_SHAREIQ_PTAT		0x04e
+
+/* MISC core 0 */
+#define R2057_RXTXBIAS_CONFIG_CORE0		0x04f
+#define R2057_TXGM_TXRF_PUS_CORE0		0x050
+#define R2057_TXGM_IDAC_BLEED_CORE0		0x051
+#define R2057_TXGM_GAIN_CORE0			0x056
+#define R2057_TXGM2G_PKDET_PUS_CORE0		0x057
+#define R2057_PAD2G_PTATS_CORE0			0x058
+#define R2057_PAD2G_IDACS_CORE0			0x059
+#define R2057_PAD2G_BOOST_PU_CORE0		0x05a
+#define R2057_PAD2G_CASCV_GAIN_CORE0		0x05b
+#define R2057_TXMIX2G_TUNE_BOOST_PU_CORE0	0x05c
+#define R2057_TXMIX2G_LODC_CORE0		0x05d
+#define R2057_PAD2G_TUNE_PUS_CORE0		0x05e
+#define R2057_IPA2G_GAIN_CORE0			0x05f
+#define R2057_TSSI2G_SPARE1_CORE0		0x060
+#define R2057_TSSI2G_SPARE2_CORE0		0x061
+#define R2057_IPA2G_TUNEV_CASCV_PTAT_CORE0	0x062
+#define R2057_IPA2G_IMAIN_CORE0			0x063
+#define R2057_IPA2G_CASCONV_CORE0		0x064
+#define R2057_IPA2G_CASCOFFV_CORE0		0x065
+#define R2057_IPA2G_BIAS_FILTER_CORE0		0x066
+#define R2057_TX5G_PKDET_CORE0			0x069
+#define R2057_PGA_PTAT_TXGM5G_PU_CORE0		0x06a
+#define R2057_PAD5G_PTATS1_CORE0		0x06b
+#define R2057_PAD5G_CLASS_PTATS2_CORE0		0x06c
+#define R2057_PGA_BOOSTPTAT_IMAIN_CORE0		0x06d
+#define R2057_PAD5G_CASCV_IMAIN_CORE0		0x06e
+#define R2057_TXMIX5G_IBOOST_PAD_IAUX_CORE0	0x06f
+#define R2057_PGA_BOOST_TUNE_CORE0		0x070
+#define R2057_PGA_GAIN_CORE0			0x071
+#define R2057_PAD5G_CASCOFFV_GAIN_PUS_CORE0	0x072
+#define R2057_TXMIX5G_BOOST_TUNE_CORE0		0x073
+#define R2057_PAD5G_TUNE_MISC_PUS_CORE0		0x074
+#define R2057_IPA5G_IAUX_CORE0			0x075
+#define R2057_IPA5G_GAIN_CORE0			0x076
+#define R2057_TSSI5G_SPARE1_CORE0		0x077
+#define R2057_TSSI5G_SPARE2_CORE0		0x078
+#define R2057_IPA5G_CASCOFFV_PU_CORE0		0x079
+#define R2057_IPA5G_PTAT_CORE0			0x07a
+#define R2057_IPA5G_IMAIN_CORE0			0x07b
+#define R2057_IPA5G_CASCONV_CORE0		0x07c
+#define R2057_IPA5G_BIAS_FILTER_CORE0		0x07d
+#define R2057_PAD_BIAS_FILTER_BWS_CORE0		0x080
+#define R2057_TR2G_CONFIG1_CORE0_NU		0x081
+#define R2057_TR2G_CONFIG2_CORE0_NU		0x082
+#define R2057_LNA5G_RFEN_CORE0			0x083
+#define R2057_TR5G_CONFIG2_CORE0_NU		0x084
+#define R2057_RXRFBIAS_IBOOST_PU_CORE0		0x085
+#define R2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE0	0x086
+#define R2057_RXGM_CMFBITAIL_AUXPTAT_CORE0	0x087
+#define R2057_RXMIX_ICORE_RXGM_IAUX_CORE0	0x088
+#define R2057_RXMIX_CMFBITAIL_PU_CORE0		0x089
+#define R2057_LNA2_IMAIN_PTAT_PU_CORE0		0x08a
+#define R2057_LNA2_IAUX_PTAT_CORE0		0x08b
+#define R2057_LNA1_IMAIN_PTAT_PU_CORE0		0x08c
+#define R2057_LNA15G_INPUT_MATCH_TUNE_CORE0	0x08d
+#define R2057_RXRFBIAS_BANDSEL_CORE0		0x08e
+#define R2057_TIA_CONFIG_CORE0			0x08f
+#define R2057_TIA_IQGAIN_CORE0			0x090
+#define R2057_TIA_IBIAS2_CORE0			0x091
+#define R2057_TIA_IBIAS1_CORE0			0x092
+#define R2057_TIA_SPARE_Q_CORE0			0x093
+#define R2057_TIA_SPARE_I_CORE0			0x094
+#define R2057_RXMIX2G_PUS_CORE0			0x095
+#define R2057_RXMIX2G_VCMREFS_CORE0		0x096
+#define R2057_RXMIX2G_LODC_QI_CORE0		0x097
+#define R2057_W12G_BW_LNA2G_PUS_CORE0		0x098
+#define R2057_LNA2G_GAIN_CORE0			0x099
+#define R2057_LNA2G_TUNE_CORE0			0x09a
+#define R2057_RXMIX5G_PUS_CORE0			0x09b
+#define R2057_RXMIX5G_VCMREFS_CORE0		0x09c
+#define R2057_RXMIX5G_LODC_QI_CORE0		0x09d
+#define R2057_W15G_BW_LNA5G_PUS_CORE0		0x09e
+#define R2057_LNA5G_GAIN_CORE0			0x09f
+#define R2057_LNA5G_TUNE_CORE0			0x0a0
+#define R2057_LPFSEL_TXRX_RXBB_PUS_CORE0	0x0a1
+#define R2057_RXBB_BIAS_MASTER_CORE0		0x0a2
+#define R2057_RXBB_VGABUF_IDACS_CORE0		0x0a3
+#define R2057_LPF_VCMREF_TXBUF_VCMREF_CORE0	0x0a4
+#define R2057_TXBUF_VINCM_CORE0			0x0a5
+#define R2057_TXBUF_IDACS_CORE0			0x0a6
+#define R2057_LPF_RESP_RXBUF_BW_CORE0		0x0a7
+#define R2057_RXBB_CC_CORE0			0x0a8
+#define R2057_RXBB_SPARE3_CORE0			0x0a9
+#define R2057_RXBB_RCCAL_HPC_CORE0		0x0aa
+#define R2057_LPF_IDACS_CORE0			0x0ab
+#define R2057_LPFBYP_DCLOOP_BYP_IDAC_CORE0	0x0ac
+#define R2057_TXBUF_GAIN_CORE0			0x0ad
+#define R2057_AFELOOPBACK_AACI_RESP_CORE0	0x0ae
+#define R2057_RXBUF_DEGEN_CORE0			0x0af
+#define R2057_RXBB_SPARE2_CORE0			0x0b0
+#define R2057_RXBB_SPARE1_CORE0			0x0b1
+#define R2057_RSSI_MASTER_CORE0			0x0b2
+#define R2057_W2_MASTER_CORE0			0x0b3
+#define R2057_NB_MASTER_CORE0			0x0b4
+#define R2057_W2_IDACS0_Q_CORE0			0x0b5
+#define R2057_W2_IDACS1_Q_CORE0			0x0b6
+#define R2057_W2_IDACS0_I_CORE0			0x0b7
+#define R2057_W2_IDACS1_I_CORE0			0x0b8
+#define R2057_RSSI_GPAIOSEL_W1_IDACS_CORE0	0x0b9
+#define R2057_NB_IDACS_Q_CORE0			0x0ba
+#define R2057_NB_IDACS_I_CORE0			0x0bb
+#define R2057_BACKUP4_CORE0			0x0c1
+#define R2057_BACKUP3_CORE0			0x0c2
+#define R2057_BACKUP2_CORE0			0x0c3
+#define R2057_BACKUP1_CORE0			0x0c4
+#define R2057_SPARE16_CORE0			0x0c5
+#define R2057_SPARE15_CORE0			0x0c6
+#define R2057_SPARE14_CORE0			0x0c7
+#define R2057_SPARE13_CORE0			0x0c8
+#define R2057_SPARE12_CORE0			0x0c9
+#define R2057_SPARE11_CORE0			0x0ca
+#define R2057_TX2G_BIAS_RESETS_CORE0		0x0cb
+#define R2057_TX5G_BIAS_RESETS_CORE0		0x0cc
+#define R2057_IQTEST_SEL_PU			0x0cd
+#define R2057_XTAL_CONFIG2			0x0ce
+#define R2057_BUFS_MISC_LPFBW_CORE0		0x0cf
+#define R2057_TXLPF_RCCAL_CORE0			0x0d0
+#define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE0	0x0d1
+#define R2057_LPF_GAIN_CORE0			0x0d2
+#define R2057_DACBUF_IDACS_BW_CORE0		0x0d3
+
+/* MISC core 1 */
+#define R2057_RXTXBIAS_CONFIG_CORE1		0x0d4
+#define R2057_TXGM_TXRF_PUS_CORE1		0x0d5
+#define R2057_TXGM_IDAC_BLEED_CORE1		0x0d6
+#define R2057_TXGM_GAIN_CORE1			0x0db
+#define R2057_TXGM2G_PKDET_PUS_CORE1		0x0dc
+#define R2057_PAD2G_PTATS_CORE1			0x0dd
+#define R2057_PAD2G_IDACS_CORE1			0x0de
+#define R2057_PAD2G_BOOST_PU_CORE1		0x0df
+#define R2057_PAD2G_CASCV_GAIN_CORE1		0x0e0
+#define R2057_TXMIX2G_TUNE_BOOST_PU_CORE1	0x0e1
+#define R2057_TXMIX2G_LODC_CORE1		0x0e2
+#define R2057_PAD2G_TUNE_PUS_CORE1		0x0e3
+#define R2057_IPA2G_GAIN_CORE1			0x0e4
+#define R2057_TSSI2G_SPARE1_CORE1		0x0e5
+#define R2057_TSSI2G_SPARE2_CORE1		0x0e6
+#define R2057_IPA2G_TUNEV_CASCV_PTAT_CORE1	0x0e7
+#define R2057_IPA2G_IMAIN_CORE1			0x0e8
+#define R2057_IPA2G_CASCONV_CORE1		0x0e9
+#define R2057_IPA2G_CASCOFFV_CORE1		0x0ea
+#define R2057_IPA2G_BIAS_FILTER_CORE1		0x0eb
+#define R2057_TX5G_PKDET_CORE1			0x0ee
+#define R2057_PGA_PTAT_TXGM5G_PU_CORE1		0x0ef
+#define R2057_PAD5G_PTATS1_CORE1		0x0f0
+#define R2057_PAD5G_CLASS_PTATS2_CORE1		0x0f1
+#define R2057_PGA_BOOSTPTAT_IMAIN_CORE1		0x0f2
+#define R2057_PAD5G_CASCV_IMAIN_CORE1		0x0f3
+#define R2057_TXMIX5G_IBOOST_PAD_IAUX_CORE1	0x0f4
+#define R2057_PGA_BOOST_TUNE_CORE1		0x0f5
+#define R2057_PGA_GAIN_CORE1			0x0f6
+#define R2057_PAD5G_CASCOFFV_GAIN_PUS_CORE1	0x0f7
+#define R2057_TXMIX5G_BOOST_TUNE_CORE1		0x0f8
+#define R2057_PAD5G_TUNE_MISC_PUS_CORE1		0x0f9
+#define R2057_IPA5G_IAUX_CORE1			0x0fa
+#define R2057_IPA5G_GAIN_CORE1			0x0fb
+#define R2057_TSSI5G_SPARE1_CORE1		0x0fc
+#define R2057_TSSI5G_SPARE2_CORE1		0x0fd
+#define R2057_IPA5G_CASCOFFV_PU_CORE1		0x0fe
+#define R2057_IPA5G_PTAT_CORE1			0x0ff
+#define R2057_IPA5G_IMAIN_CORE1			0x100
+#define R2057_IPA5G_CASCONV_CORE1		0x101
+#define R2057_IPA5G_BIAS_FILTER_CORE1		0x102
+#define R2057_PAD_BIAS_FILTER_BWS_CORE1		0x105
+#define R2057_TR2G_CONFIG1_CORE1_NU		0x106
+#define R2057_TR2G_CONFIG2_CORE1_NU		0x107
+#define R2057_LNA5G_RFEN_CORE1			0x108
+#define R2057_TR5G_CONFIG2_CORE1_NU		0x109
+#define R2057_RXRFBIAS_IBOOST_PU_CORE1		0x10a
+#define R2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE1	0x10b
+#define R2057_RXGM_CMFBITAIL_AUXPTAT_CORE1	0x10c
+#define R2057_RXMIX_ICORE_RXGM_IAUX_CORE1	0x10d
+#define R2057_RXMIX_CMFBITAIL_PU_CORE1		0x10e
+#define R2057_LNA2_IMAIN_PTAT_PU_CORE1		0x10f
+#define R2057_LNA2_IAUX_PTAT_CORE1		0x110
+#define R2057_LNA1_IMAIN_PTAT_PU_CORE1		0x111
+#define R2057_LNA15G_INPUT_MATCH_TUNE_CORE1	0x112
+#define R2057_RXRFBIAS_BANDSEL_CORE1		0x113
+#define R2057_TIA_CONFIG_CORE1			0x114
+#define R2057_TIA_IQGAIN_CORE1			0x115
+#define R2057_TIA_IBIAS2_CORE1			0x116
+#define R2057_TIA_IBIAS1_CORE1			0x117
+#define R2057_TIA_SPARE_Q_CORE1			0x118
+#define R2057_TIA_SPARE_I_CORE1			0x119
+#define R2057_RXMIX2G_PUS_CORE1			0x11a
+#define R2057_RXMIX2G_VCMREFS_CORE1		0x11b
+#define R2057_RXMIX2G_LODC_QI_CORE1		0x11c
+#define R2057_W12G_BW_LNA2G_PUS_CORE1		0x11d
+#define R2057_LNA2G_GAIN_CORE1			0x11e
+#define R2057_LNA2G_TUNE_CORE1			0x11f
+#define R2057_RXMIX5G_PUS_CORE1			0x120
+#define R2057_RXMIX5G_VCMREFS_CORE1		0x121
+#define R2057_RXMIX5G_LODC_QI_CORE1		0x122
+#define R2057_W15G_BW_LNA5G_PUS_CORE1		0x123
+#define R2057_LNA5G_GAIN_CORE1			0x124
+#define R2057_LNA5G_TUNE_CORE1			0x125
+#define R2057_LPFSEL_TXRX_RXBB_PUS_CORE1	0x126
+#define R2057_RXBB_BIAS_MASTER_CORE1		0x127
+#define R2057_RXBB_VGABUF_IDACS_CORE1		0x128
+#define R2057_LPF_VCMREF_TXBUF_VCMREF_CORE1	0x129
+#define R2057_TXBUF_VINCM_CORE1			0x12a
+#define R2057_TXBUF_IDACS_CORE1			0x12b
+#define R2057_LPF_RESP_RXBUF_BW_CORE1		0x12c
+#define R2057_RXBB_CC_CORE1			0x12d
+#define R2057_RXBB_SPARE3_CORE1			0x12e
+#define R2057_RXBB_RCCAL_HPC_CORE1		0x12f
+#define R2057_LPF_IDACS_CORE1			0x130
+#define R2057_LPFBYP_DCLOOP_BYP_IDAC_CORE1	0x131
+#define R2057_TXBUF_GAIN_CORE1			0x132
+#define R2057_AFELOOPBACK_AACI_RESP_CORE1	0x133
+#define R2057_RXBUF_DEGEN_CORE1			0x134
+#define R2057_RXBB_SPARE2_CORE1			0x135
+#define R2057_RXBB_SPARE1_CORE1			0x136
+#define R2057_RSSI_MASTER_CORE1			0x137
+#define R2057_W2_MASTER_CORE1			0x138
+#define R2057_NB_MASTER_CORE1			0x139
+#define R2057_W2_IDACS0_Q_CORE1			0x13a
+#define R2057_W2_IDACS1_Q_CORE1			0x13b
+#define R2057_W2_IDACS0_I_CORE1			0x13c
+#define R2057_W2_IDACS1_I_CORE1			0x13d
+#define R2057_RSSI_GPAIOSEL_W1_IDACS_CORE1	0x13e
+#define R2057_NB_IDACS_Q_CORE1			0x13f
+#define R2057_NB_IDACS_I_CORE1			0x140
+#define R2057_BACKUP4_CORE1			0x146
+#define R2057_BACKUP3_CORE1			0x147
+#define R2057_BACKUP2_CORE1			0x148
+#define R2057_BACKUP1_CORE1			0x149
+#define R2057_SPARE16_CORE1			0x14a
+#define R2057_SPARE15_CORE1			0x14b
+#define R2057_SPARE14_CORE1			0x14c
+#define R2057_SPARE13_CORE1			0x14d
+#define R2057_SPARE12_CORE1			0x14e
+#define R2057_SPARE11_CORE1			0x14f
+#define R2057_TX2G_BIAS_RESETS_CORE1		0x150
+#define R2057_TX5G_BIAS_RESETS_CORE1		0x151
+#define R2057_SPARE8_CORE1			0x152
+#define R2057_SPARE7_CORE1			0x153
+#define R2057_BUFS_MISC_LPFBW_CORE1		0x154
+#define R2057_TXLPF_RCCAL_CORE1			0x155
+#define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE1	0x156
+#define R2057_LPF_GAIN_CORE1			0x157
+#define R2057_DACBUF_IDACS_BW_CORE1		0x158
+
+#define R2057_DACBUF_VINCM_CORE1		0x159
+#define R2057_RCCAL_START_R1_Q1_P1		0x15a
+#define R2057_RCCAL_X1				0x15b
+#define R2057_RCCAL_TRC0			0x15c
+#define R2057_RCCAL_TRC1			0x15d
+#define R2057_RCCAL_DONE_OSCCAP			0x15e
+#define R2057_RCCAL_N0_0			0x15f
+#define R2057_RCCAL_N0_1			0x160
+#define R2057_RCCAL_N1_0			0x161
+#define R2057_RCCAL_N1_1			0x162
+#define R2057_RCAL_STATUS			0x163
+#define R2057_XTALPUOVR_PINCTRL			0x164
+#define R2057_OVR_REG0				0x165
+#define R2057_OVR_REG1				0x166
+#define R2057_OVR_REG2				0x167
+#define R2057_OVR_REG3				0x168
+#define R2057_OVR_REG4				0x169
+#define R2057_RCCAL_SCAP_VAL			0x16a
+#define R2057_RCCAL_BCAP_VAL			0x16b
+#define R2057_RCCAL_HPC_VAL			0x16c
+#define R2057_RCCAL_OVERRIDES			0x16d
+
+/* TX core 0 */
+#define R2057_TX0_IQCAL_GAIN_BW			0x170
+#define R2057_TX0_LOFT_FINE_I			0x171
+#define R2057_TX0_LOFT_FINE_Q			0x172
+#define R2057_TX0_LOFT_COARSE_I			0x173
+#define R2057_TX0_LOFT_COARSE_Q			0x174
+#define R2057_TX0_TX_SSI_MASTER			0x175
+#define R2057_TX0_IQCAL_VCM_HG			0x176
+#define R2057_TX0_IQCAL_IDAC			0x177
+#define R2057_TX0_TSSI_VCM			0x178
+#define R2057_TX0_TX_SSI_MUX			0x179
+#define R2057_TX0_TSSIA				0x17a
+#define R2057_TX0_TSSIG				0x17b
+#define R2057_TX0_TSSI_MISC1			0x17c
+#define R2057_TX0_TXRXCOUPLE_2G_ATTEN		0x17d
+#define R2057_TX0_TXRXCOUPLE_2G_PWRUP		0x17e
+#define R2057_TX0_TXRXCOUPLE_5G_ATTEN		0x17f
+#define R2057_TX0_TXRXCOUPLE_5G_PWRUP		0x180
+
+/* TX core 1 */
+#define R2057_TX1_IQCAL_GAIN_BW			0x190
+#define R2057_TX1_LOFT_FINE_I			0x191
+#define R2057_TX1_LOFT_FINE_Q			0x192
+#define R2057_TX1_LOFT_COARSE_I			0x193
+#define R2057_TX1_LOFT_COARSE_Q			0x194
+#define R2057_TX1_TX_SSI_MASTER			0x195
+#define R2057_TX1_IQCAL_VCM_HG			0x196
+#define R2057_TX1_IQCAL_IDAC			0x197
+#define R2057_TX1_TSSI_VCM			0x198
+#define R2057_TX1_TX_SSI_MUX			0x199
+#define R2057_TX1_TSSIA				0x19a
+#define R2057_TX1_TSSIG				0x19b
+#define R2057_TX1_TSSI_MISC1			0x19c
+#define R2057_TX1_TXRXCOUPLE_2G_ATTEN		0x19d
+#define R2057_TX1_TXRXCOUPLE_2G_PWRUP		0x19e
+#define R2057_TX1_TXRXCOUPLE_5G_ATTEN		0x19f
+#define R2057_TX1_TXRXCOUPLE_5G_PWRUP		0x1a0
+
+#define R2057_AFE_VCM_CAL_MASTER_CORE0		0x1a1
+#define R2057_AFE_SET_VCM_I_CORE0		0x1a2
+#define R2057_AFE_SET_VCM_Q_CORE0		0x1a3
+#define R2057_AFE_STATUS_VCM_IQADC_CORE0	0x1a4
+#define R2057_AFE_STATUS_VCM_I_CORE0		0x1a5
+#define R2057_AFE_STATUS_VCM_Q_CORE0		0x1a6
+#define R2057_AFE_VCM_CAL_MASTER_CORE1		0x1a7
+#define R2057_AFE_SET_VCM_I_CORE1		0x1a8
+#define R2057_AFE_SET_VCM_Q_CORE1		0x1a9
+#define R2057_AFE_STATUS_VCM_IQADC_CORE1	0x1aa
+#define R2057_AFE_STATUS_VCM_I_CORE1		0x1ab
+#define R2057_AFE_STATUS_VCM_Q_CORE1		0x1ac
+
+#define R2057v7_DACBUF_VINCM_CORE0		0x1ad
+#define R2057v7_RCCAL_MASTER			0x1ae
+#define R2057v7_TR2G_CONFIG3_CORE0_NU		0x1af
+#define R2057v7_TR2G_CONFIG3_CORE1_NU		0x1b0
+#define R2057v7_LOGEN_PUS1			0x1b1
+#define R2057v7_OVR_REG5			0x1b2
+#define R2057v7_OVR_REG6			0x1b3
+#define R2057v7_OVR_REG7			0x1b4
+#define R2057v7_OVR_REG8			0x1b5
+#define R2057v7_OVR_REG9			0x1b6
+#define R2057v7_OVR_REG10			0x1b7
+#define R2057v7_OVR_REG11			0x1b8
+#define R2057v7_OVR_REG12			0x1b9
+#define R2057v7_OVR_REG13			0x1ba
+#define R2057v7_OVR_REG14			0x1bb
+#define R2057v7_OVR_REG15			0x1bc
+#define R2057v7_OVR_REG16			0x1bd
+#define R2057v7_OVR_REG1			0x1be
+#define R2057v7_OVR_REG18			0x1bf
+#define R2057v7_OVR_REG19			0x1c0
+#define R2057v7_OVR_REG20			0x1c1
+#define R2057v7_OVR_REG21			0x1c2
+#define R2057v7_OVR_REG2			0x1c3
+#define R2057v7_OVR_REG23			0x1c4
+#define R2057v7_OVR_REG24			0x1c5
+#define R2057v7_OVR_REG25			0x1c6
+#define R2057v7_OVR_REG26			0x1c7
+#define R2057v7_OVR_REG27			0x1c8
+#define R2057v7_OVR_REG28			0x1c9
+#define R2057v7_IQTEST_SEL_PU2			0x1ca
+
+#define R2057_VCM_MASK				0x7
+
+struct b43_nphy_chantabent_rev7 {
+	/* The channel frequency in MHz */
+	u16 freq;
+	/* Radio regs values on channelswitch */
+	u8 radio_vcocal_countval0;
+	u8 radio_vcocal_countval1;
+	u8 radio_rfpll_refmaster_sparextalsize;
+	u8 radio_rfpll_loopfilter_r1;
+	u8 radio_rfpll_loopfilter_c2;
+	u8 radio_rfpll_loopfilter_c1;
+	u8 radio_cp_kpd_idac;
+	u8 radio_rfpll_mmd0;
+	u8 radio_rfpll_mmd1;
+	u8 radio_vcobuf_tune;
+	u8 radio_logen_mx2g_tune;
+	u8 radio_logen_mx5g_tune;
+	u8 radio_logen_indbuf2g_tune;
+	u8 radio_logen_indbuf5g_tune;
+	u8 radio_txmix2g_tune_boost_pu_core0;
+	u8 radio_pad2g_tune_pus_core0;
+	u8 radio_pga_boost_tune_core0;
+	u8 radio_txmix5g_boost_tune_core0;
+	u8 radio_pad5g_tune_misc_pus_core0;
+	u8 radio_lna2g_tune_core0;
+	u8 radio_lna5g_tune_core0;
+	u8 radio_txmix2g_tune_boost_pu_core1;
+	u8 radio_pad2g_tune_pus_core1;
+	u8 radio_pga_boost_tune_core1;
+	u8 radio_txmix5g_boost_tune_core1;
+	u8 radio_pad5g_tune_misc_pus_core1;
+	u8 radio_lna2g_tune_core1;
+	u8 radio_lna5g_tune_core1;
+	/* PHY res values on channelswitch */
+	struct b43_phy_n_sfo_cfg phy_regs;
+};
+
+struct b43_nphy_chantabent_rev7_2g {
+	/* The channel frequency in MHz */
+	u16 freq;
+	/* Radio regs values on channelswitch */
+	u8 radio_vcocal_countval0;
+	u8 radio_vcocal_countval1;
+	u8 radio_rfpll_refmaster_sparextalsize;
+	u8 radio_rfpll_loopfilter_r1;
+	u8 radio_rfpll_loopfilter_c2;
+	u8 radio_rfpll_loopfilter_c1;
+	u8 radio_cp_kpd_idac;
+	u8 radio_rfpll_mmd0;
+	u8 radio_rfpll_mmd1;
+	u8 radio_vcobuf_tune;
+	u8 radio_logen_mx2g_tune;
+	u8 radio_logen_indbuf2g_tune;
+	u8 radio_txmix2g_tune_boost_pu_core0;
+	u8 radio_pad2g_tune_pus_core0;
+	u8 radio_lna2g_tune_core0;
+	u8 radio_txmix2g_tune_boost_pu_core1;
+	u8 radio_pad2g_tune_pus_core1;
+	u8 radio_lna2g_tune_core1;
+	/* PHY regs values on channelswitch */
+	struct b43_phy_n_sfo_cfg phy_regs;
+};
+
+void r2057_upload_inittabs(struct b43_wldev *dev);
+
+void r2057_get_chantabent_rev7(struct b43_wldev *dev, u16 freq,
+			       const struct b43_nphy_chantabent_rev7 **tabent_r7,
+			       const struct b43_nphy_chantabent_rev7_2g **tabent_r7_2g);
+
+#endif /* B43_RADIO_2057_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/radio_2059.c b/drivers/net/wireless/broadcom/b43/radio_2059.c
new file mode 100644
index 0000000..a3cf9ef
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/radio_2059.c
@@ -0,0 +1,364 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11n 2059 radio device data tables
+
+  Copyright (c) 2011 Rafał Miłecki <zajec5@gmail.com>
+
+  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 "radio_2059.h"
+
+/* Extracted from MMIO dump of 6.30.223.141 */
+static u16 r2059_phy_rev1_init[][2] = {
+	{ 0x051, 0x70 }, { 0x05a, 0x03 }, { 0x079, 0x01 }, { 0x082, 0x70 },
+	{ 0x083, 0x00 }, { 0x084, 0x70 }, { 0x09a, 0x7f }, { 0x0b6, 0x10 },
+	{ 0x188, 0x05 },
+};
+
+#define RADIOREGS(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
+		  r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \
+		  r20) \
+	.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_rxtx4a			= r13,	\
+	.radio_rxtx58			= r14,	\
+	.radio_rxtx5a			= r15,	\
+	.radio_rxtx6a			= r16,	\
+	.radio_rxtx6d			= r17,	\
+	.radio_rxtx6e			= r18,	\
+	.radio_rxtx92			= r19,	\
+	.radio_rxtx98			= r20
+
+#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
+
+/* Extracted from MMIO dump of 6.30.223.141
+ * TODO: Values for channels 12 & 13 are outdated (from some old 5.x driver)!
+ */
+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, 0x73,
+			  0x00, 0x00, 0x00, 0xd0, 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, 0x73,
+			  0x00, 0x00, 0x00, 0xd0, 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, 0x73,
+			  0x00, 0x00, 0x00, 0xd0, 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, 0x73,
+			  0x00, 0x00, 0x00, 0xa0, 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, 0x73,
+			  0x00, 0x00, 0x00, 0xa0, 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, 0x73,
+			  0x00, 0x00, 0x00, 0xa0, 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, 0x73,
+			  0x00, 0x00, 0x00, 0x80, 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, 0x73,
+			  0x00, 0x00, 0x00, 0x80, 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, 0x73,
+			  0x00, 0x00, 0x00, 0x80, 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, 0x73,
+			  0x00, 0x00, 0x00, 0x60, 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, 0x73,
+			  0x00, 0x00, 0x00, 0x60, 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),
+	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),
+	PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
+  },
+	{
+		.freq			= 5180,
+		RADIOREGS(0xbe, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x06,
+			  0x02, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x00,
+			  0x0f, 0x4f, 0xa3, 0x00, 0xfc),
+		PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb),
+	},
+	{
+		.freq			= 5200,
+		RADIOREGS(0xc5, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x08,
+			  0x02, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x00,
+			  0x0f, 0x4f, 0x93, 0x00, 0xfb),
+		PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9),
+	},
+	{
+		.freq			= 5220,
+		RADIOREGS(0xcc, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x0a,
+			  0x02, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x00,
+			  0x0f, 0x4f, 0x93, 0x00, 0xea),
+		PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7),
+	},
+	{
+		.freq			= 5240,
+		RADIOREGS(0xd2, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x0c,
+			  0x02, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x00,
+			  0x0f, 0x4f, 0x93, 0x00, 0xda),
+		PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5),
+	},
+	{
+		.freq			= 5260,
+		RADIOREGS(0xd9, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x0e,
+			  0x02, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x00,
+			  0x0f, 0x4f, 0x93, 0x00, 0xca),
+		PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3),
+	},
+	{
+		.freq			= 5280,
+		RADIOREGS(0xe0, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x10,
+			  0x02, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x00,
+			  0x0f, 0x4f, 0x93, 0x00, 0xb9),
+		PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1),
+	},
+	{
+		.freq			= 5300,
+		RADIOREGS(0xe6, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x12,
+			  0x02, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x00,
+			  0x0f, 0x4c, 0x83, 0x00, 0xb8),
+		PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0),
+	},
+	{
+		.freq			= 5320,
+		RADIOREGS(0xed, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x14,
+			  0x02, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x00,
+			  0x0f, 0x4c, 0x83, 0x00, 0xa8),
+		PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee),
+	},
+	{
+		.freq			= 5500,
+		RADIOREGS(0x29, 0x17, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x26,
+			  0x02, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00,
+			  0x0a, 0x46, 0x43, 0x00, 0x75),
+		PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd),
+	},
+	{
+		.freq			= 5520,
+		RADIOREGS(0x30, 0x17, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x28,
+			  0x02, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00,
+			  0x0a, 0x46, 0x43, 0x00, 0x75),
+		PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc),
+	},
+	{
+		.freq			= 5540,
+		RADIOREGS(0x36, 0x17, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x2a,
+			  0x02, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00,
+			  0x0a, 0x46, 0x43, 0x00, 0x75),
+		PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da),
+	},
+	{
+		.freq			= 5560,
+		RADIOREGS(0x3d, 0x17, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x2c,
+			  0x02, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00,
+			  0x0a, 0x46, 0x43, 0x00, 0x75),
+		PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8),
+	},
+	{
+		.freq			= 5580,
+		RADIOREGS(0x44, 0x17, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x2e,
+			  0x02, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00,
+			  0x0a, 0x46, 0x43, 0x00, 0x74),
+		PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7),
+	},
+	{
+		.freq			= 5600,
+		RADIOREGS(0x4a, 0x17, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x30,
+			  0x02, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00,
+			  0x09, 0x44, 0x23, 0x00, 0x54),
+		PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5),
+	},
+	{
+		.freq			= 5620,
+		RADIOREGS(0x51, 0x17, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x32,
+			  0x02, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00,
+			  0x09, 0x44, 0x23, 0x00, 0x54),
+		PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3),
+	},
+	{
+		.freq			= 5640,
+		RADIOREGS(0x58, 0x17, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x34,
+			  0x02, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00,
+			  0x09, 0x44, 0x23, 0x00, 0x43),
+		PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2),
+	},
+	{
+		.freq			= 5660,
+		RADIOREGS(0x5e, 0x17, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x36,
+			  0x02, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00,
+			  0x09, 0x43, 0x23, 0x00, 0x43),
+		PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0),
+	},
+	{
+		.freq			= 5680,
+		RADIOREGS(0x65, 0x17, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x38,
+			  0x02, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00,
+			  0x09, 0x42, 0x23, 0x00, 0x43),
+		PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce),
+	},
+	{
+		.freq			= 5700,
+		RADIOREGS(0x6c, 0x17, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x3a,
+			  0x02, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00,
+			  0x08, 0x42, 0x13, 0x00, 0x32),
+		PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd),
+	},
+	{
+		.freq			= 5745,
+		RADIOREGS(0x7b, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x7d,
+			  0x04, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00,
+			  0x08, 0x42, 0x13, 0x00, 0x21),
+		PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9),
+	},
+	{
+		.freq			= 5765,
+		RADIOREGS(0x81, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x81,
+			  0x04, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00,
+			  0x08, 0x42, 0x13, 0x00, 0x11),
+		PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8),
+	},
+	{
+		.freq			= 5785,
+		RADIOREGS(0x88, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x85,
+			  0x04, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x00,
+			  0x08, 0x42, 0x13, 0x00, 0x00),
+		PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6),
+	},
+	{
+		.freq			= 5805,
+		RADIOREGS(0x8f, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x89,
+			  0x04, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x00,
+			  0x06, 0x41, 0x03, 0x00, 0x00),
+		PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4),
+	},
+	{
+		.freq			= 5825,
+		RADIOREGS(0x95, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x8d,
+			  0x04, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x00,
+			  0x06, 0x41, 0x03, 0x00, 0x00),
+		PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3),
+	},
+};
+
+void r2059_upload_inittabs(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	u16 *table = NULL;
+	u16 size, i;
+
+	switch (phy->rev) {
+	case 1:
+		table = r2059_phy_rev1_init[0];
+		size = ARRAY_SIZE(r2059_phy_rev1_init);
+		break;
+	default:
+		B43_WARN_ON(1);
+		return;
+	}
+
+	for (i = 0; i < size; i++, table += 2)
+		b43_radio_write(dev, R2059_ALL | table[0], table[1]);
+}
+
+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;
+}
diff --git a/drivers/net/wireless/broadcom/b43/radio_2059.h b/drivers/net/wireless/broadcom/b43/radio_2059.h
new file mode 100644
index 0000000..32c0025
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/radio_2059.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_RADIO_2059_H_
+#define B43_RADIO_2059_H_
+
+#include <linux/types.h>
+
+#include "phy_ht.h"
+
+#define R2059_C1			0x000
+#define R2059_C2			0x400
+#define R2059_C3			0x800
+#define R2059_ALL			0xC00
+
+#define R2059_RCAL_CONFIG			0x004
+#define R2059_RFPLL_MASTER			0x011
+#define R2059_RFPLL_MISC_EN			0x02b
+#define R2059_RFPLL_MISC_CAL_RESETN		0x02e
+#define R2059_XTAL_CONFIG2			0x0c0
+#define R2059_RCCAL_START_R1_Q1_P1		0x13c
+#define R2059_RCCAL_X1				0x13d
+#define R2059_RCCAL_TRC0			0x13e
+#define R2059_RCCAL_DONE_OSCCAP			0x140
+#define R2059_RCAL_STATUS			0x145
+#define R2059_RCCAL_MASTER			0x17f
+
+/* Values for various registers uploaded on channel switching */
+struct b43_phy_ht_channeltab_e_radio2059 {
+	/* The channel frequency in MHz */
+	u16 freq;
+	/* Values for radio registers */
+	u8 radio_syn16;
+	u8 radio_syn17;
+	u8 radio_syn22;
+	u8 radio_syn25;
+	u8 radio_syn27;
+	u8 radio_syn28;
+	u8 radio_syn29;
+	u8 radio_syn2c;
+	u8 radio_syn2d;
+	u8 radio_syn37;
+	u8 radio_syn41;
+	u8 radio_syn43;
+	u8 radio_syn47;
+	u8 radio_rxtx4a;
+	u8 radio_rxtx58;
+	u8 radio_rxtx5a;
+	u8 radio_rxtx6a;
+	u8 radio_rxtx6d;
+	u8 radio_rxtx6e;
+	u8 radio_rxtx92;
+	u8 radio_rxtx98;
+	/* Values for PHY registers */
+	struct b43_phy_ht_channeltab_e_phy phy_regs;
+};
+
+void r2059_upload_inittabs(struct b43_wldev *dev);
+
+const struct b43_phy_ht_channeltab_e_radio2059
+*b43_phy_ht_get_channeltab_e_r2059(struct b43_wldev *dev, u16 freq);
+
+#endif /* B43_RADIO_2059_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/rfkill.c b/drivers/net/wireless/broadcom/b43/rfkill.c
new file mode 100644
index 0000000..70c2fce
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/rfkill.c
@@ -0,0 +1,70 @@
+/*
+
+  Broadcom B43 wireless driver
+  RFKILL support
+
+  Copyright (c) 2007 Michael Buesch <m@bues.ch>
+
+  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"
+
+
+/* Returns TRUE, if the radio is enabled in hardware. */
+bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
+{
+	return !(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI)
+		& B43_MMIO_RADIO_HWENABLED_HI_MASK);
+}
+
+/* The poll callback for the hardware button. */
+void b43_rfkill_poll(struct ieee80211_hw *hw)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+	struct b43_wldev *dev = wl->current_dev;
+	bool enabled;
+	bool brought_up = false;
+
+	mutex_lock(&wl->mutex);
+	if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) {
+		if (b43_bus_powerup(dev, 0)) {
+			mutex_unlock(&wl->mutex);
+			return;
+		}
+		b43_device_enable(dev, 0);
+		brought_up = true;
+	}
+
+	enabled = b43_is_hw_radio_enabled(dev);
+
+	if (unlikely(enabled != dev->radio_hw_enable)) {
+		dev->radio_hw_enable = enabled;
+		b43info(wl, "Radio hardware status changed to %s\n",
+			enabled ? "ENABLED" : "DISABLED");
+		wiphy_rfkill_set_hw_state(hw->wiphy, !enabled);
+		if (enabled != dev->phy.radio_on)
+			b43_software_rfkill(dev, !enabled);
+	}
+
+	if (brought_up) {
+		b43_device_disable(dev, 0);
+		b43_bus_may_powerdown(dev);
+	}
+
+	mutex_unlock(&wl->mutex);
+}
diff --git a/drivers/net/wireless/broadcom/b43/rfkill.h b/drivers/net/wireless/broadcom/b43/rfkill.h
new file mode 100644
index 0000000..8682ac5
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/rfkill.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_RFKILL_H_
+#define B43_RFKILL_H_
+
+struct ieee80211_hw;
+struct b43_wldev;
+
+void b43_rfkill_poll(struct ieee80211_hw *hw);
+
+bool b43_is_hw_radio_enabled(struct b43_wldev *dev);
+
+#endif /* B43_RFKILL_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/sdio.c b/drivers/net/wireless/broadcom/b43/sdio.c
new file mode 100644
index 0000000..59a5218
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/sdio.c
@@ -0,0 +1,207 @@
+/*
+ * Broadcom B43 wireless driver
+ *
+ * SDIO over Sonics Silicon Backplane bus glue for b43.
+ *
+ * Copyright (C) 2009 Albert Herranz
+ * Copyright (C) 2009 Michael Buesch <m@bues.ch>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/slab.h>
+#include <linux/ssb/ssb.h>
+
+#include "sdio.h"
+#include "b43.h"
+
+
+#define HNBU_CHIPID		0x01	/* vendor & device id */
+
+#define B43_SDIO_BLOCK_SIZE	64	/* rx fifo max size in bytes */
+
+
+static const struct b43_sdio_quirk {
+	u16 vendor;
+	u16 device;
+	unsigned int quirks;
+} b43_sdio_quirks[] = {
+	{ 0x14E4, 0x4318, SSB_QUIRK_SDIO_READ_AFTER_WRITE32, },
+	{ },
+};
+
+
+static unsigned int b43_sdio_get_quirks(u16 vendor, u16 device)
+{
+	const struct b43_sdio_quirk *q;
+
+	for (q = b43_sdio_quirks; q->quirks; q++) {
+		if (vendor == q->vendor && device == q->device)
+			return q->quirks;
+	}
+
+	return 0;
+}
+
+static void b43_sdio_interrupt_dispatcher(struct sdio_func *func)
+{
+	struct b43_sdio *sdio = sdio_get_drvdata(func);
+	struct b43_wldev *dev = sdio->irq_handler_opaque;
+
+	if (unlikely(b43_status(dev) < B43_STAT_STARTED))
+		return;
+
+	sdio_release_host(func);
+	sdio->irq_handler(dev);
+	sdio_claim_host(func);
+}
+
+int b43_sdio_request_irq(struct b43_wldev *dev,
+			 void (*handler)(struct b43_wldev *dev))
+{
+	struct ssb_bus *bus = dev->dev->sdev->bus;
+	struct sdio_func *func = bus->host_sdio;
+	struct b43_sdio *sdio = sdio_get_drvdata(func);
+	int err;
+
+	sdio->irq_handler_opaque = dev;
+	sdio->irq_handler = handler;
+	sdio_claim_host(func);
+	err = sdio_claim_irq(func, b43_sdio_interrupt_dispatcher);
+	sdio_release_host(func);
+
+	return err;
+}
+
+void b43_sdio_free_irq(struct b43_wldev *dev)
+{
+	struct ssb_bus *bus = dev->dev->sdev->bus;
+	struct sdio_func *func = bus->host_sdio;
+	struct b43_sdio *sdio = sdio_get_drvdata(func);
+
+	sdio_claim_host(func);
+	sdio_release_irq(func);
+	sdio_release_host(func);
+	sdio->irq_handler_opaque = NULL;
+	sdio->irq_handler = NULL;
+}
+
+static int b43_sdio_probe(struct sdio_func *func,
+				    const struct sdio_device_id *id)
+{
+	struct b43_sdio *sdio;
+	struct sdio_func_tuple *tuple;
+	u16 vendor = 0, device = 0;
+	int error;
+
+	/* Look for the card chip identifier. */
+	tuple = func->tuples;
+	while (tuple) {
+		switch (tuple->code) {
+		case 0x80:
+			switch (tuple->data[0]) {
+			case HNBU_CHIPID:
+				if (tuple->size != 5)
+					break;
+				vendor = tuple->data[1] | (tuple->data[2]<<8);
+				device = tuple->data[3] | (tuple->data[4]<<8);
+				dev_info(&func->dev, "Chip ID %04x:%04x\n",
+					 vendor, device);
+				break;
+			default:
+				break;
+			}
+			break;
+		default:
+			break;
+		}
+		tuple = tuple->next;
+	}
+	if (!vendor || !device) {
+		error = -ENODEV;
+		goto out;
+	}
+
+	sdio_claim_host(func);
+	error = sdio_set_block_size(func, B43_SDIO_BLOCK_SIZE);
+	if (error) {
+		dev_err(&func->dev, "failed to set block size to %u bytes,"
+			" error %d\n", B43_SDIO_BLOCK_SIZE, error);
+		goto err_release_host;
+	}
+	error = sdio_enable_func(func);
+	if (error) {
+		dev_err(&func->dev, "failed to enable func, error %d\n", error);
+		goto err_release_host;
+	}
+	sdio_release_host(func);
+
+	sdio = kzalloc(sizeof(*sdio), GFP_KERNEL);
+	if (!sdio) {
+		error = -ENOMEM;
+		dev_err(&func->dev, "failed to allocate ssb bus\n");
+		goto err_disable_func;
+	}
+	error = ssb_bus_sdiobus_register(&sdio->ssb, func,
+					 b43_sdio_get_quirks(vendor, device));
+	if (error) {
+		dev_err(&func->dev, "failed to register ssb sdio bus,"
+			" error %d\n", error);
+		goto err_free_ssb;
+	}
+	sdio_set_drvdata(func, sdio);
+
+	return 0;
+
+err_free_ssb:
+	kfree(sdio);
+err_disable_func:
+	sdio_claim_host(func);
+	sdio_disable_func(func);
+err_release_host:
+	sdio_release_host(func);
+out:
+	return error;
+}
+
+static void b43_sdio_remove(struct sdio_func *func)
+{
+	struct b43_sdio *sdio = sdio_get_drvdata(func);
+
+	ssb_bus_unregister(&sdio->ssb);
+	sdio_claim_host(func);
+	sdio_disable_func(func);
+	sdio_release_host(func);
+	kfree(sdio);
+	sdio_set_drvdata(func, NULL);
+}
+
+static const struct sdio_device_id b43_sdio_ids[] = {
+	{ SDIO_DEVICE(0x02d0, 0x044b) }, /* Nintendo Wii WLAN daughter card */
+	{ SDIO_DEVICE(0x0092, 0x0004) }, /* C-guys, Inc. EW-CG1102GC */
+	{ },
+};
+
+static struct sdio_driver b43_sdio_driver = {
+	.name		= "b43-sdio",
+	.id_table	= b43_sdio_ids,
+	.probe		= b43_sdio_probe,
+	.remove		= b43_sdio_remove,
+};
+
+int b43_sdio_init(void)
+{
+	return sdio_register_driver(&b43_sdio_driver);
+}
+
+void b43_sdio_exit(void)
+{
+	sdio_unregister_driver(&b43_sdio_driver);
+}
diff --git a/drivers/net/wireless/broadcom/b43/sdio.h b/drivers/net/wireless/broadcom/b43/sdio.h
new file mode 100644
index 0000000..aa5693b
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/sdio.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_SDIO_H_
+#define B43_SDIO_H_
+
+#include <linux/ssb/ssb.h>
+
+struct b43_wldev;
+
+
+#ifdef CONFIG_B43_SDIO
+
+struct b43_sdio {
+	struct ssb_bus ssb;
+	void *irq_handler_opaque;
+	void (*irq_handler)(struct b43_wldev *dev);
+};
+
+int b43_sdio_request_irq(struct b43_wldev *dev,
+			 void (*handler)(struct b43_wldev *dev));
+void b43_sdio_free_irq(struct b43_wldev *dev);
+
+int b43_sdio_init(void);
+void b43_sdio_exit(void);
+
+
+#else /* CONFIG_B43_SDIO */
+
+
+static inline int b43_sdio_request_irq(struct b43_wldev *dev,
+			 void (*handler)(struct b43_wldev *dev))
+{
+	return -ENODEV;
+}
+static inline void b43_sdio_free_irq(struct b43_wldev *dev)
+{
+}
+static inline int b43_sdio_init(void)
+{
+	return 0;
+}
+static inline void b43_sdio_exit(void)
+{
+}
+
+#endif /* CONFIG_B43_SDIO */
+#endif /* B43_SDIO_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/sysfs.c b/drivers/net/wireless/broadcom/b43/sysfs.c
new file mode 100644
index 0000000..3190493
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/sysfs.c
@@ -0,0 +1,155 @@
+/*
+
+  Broadcom B43 wireless driver
+
+  SYSFS support routines
+
+  Copyright (c) 2006 Michael Buesch <m@bues.ch>
+
+  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/capability.h>
+#include <linux/io.h>
+
+#include "b43.h"
+#include "sysfs.h"
+#include "main.h"
+#include "phy_common.h"
+
+#define GENERIC_FILESIZE	64
+
+static int get_integer(const char *buf, size_t count)
+{
+	char tmp[10 + 1] = { 0 };
+	int ret = -EINVAL;
+
+	if (count == 0)
+		goto out;
+	count = min_t(size_t, count, 10);
+	memcpy(tmp, buf, count);
+	ret = simple_strtol(tmp, NULL, 10);
+      out:
+	return ret;
+}
+
+static ssize_t b43_attr_interfmode_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct b43_wldev *wldev = dev_to_b43_wldev(dev);
+	ssize_t count = 0;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	mutex_lock(&wldev->wl->mutex);
+
+	if (wldev->phy.type != B43_PHYTYPE_G) {
+		mutex_unlock(&wldev->wl->mutex);
+		return -ENOSYS;
+	}
+
+	switch (wldev->phy.g->interfmode) {
+	case B43_INTERFMODE_NONE:
+		count =
+		    snprintf(buf, PAGE_SIZE,
+			     "0 (No Interference Mitigation)\n");
+		break;
+	case B43_INTERFMODE_NONWLAN:
+		count =
+		    snprintf(buf, PAGE_SIZE,
+			     "1 (Non-WLAN Interference Mitigation)\n");
+		break;
+	case B43_INTERFMODE_MANUALWLAN:
+		count =
+		    snprintf(buf, PAGE_SIZE,
+			     "2 (WLAN Interference Mitigation)\n");
+		break;
+	default:
+		B43_WARN_ON(1);
+	}
+
+	mutex_unlock(&wldev->wl->mutex);
+
+	return count;
+}
+
+static ssize_t b43_attr_interfmode_store(struct device *dev,
+					 struct device_attribute *attr,
+					 const char *buf, size_t count)
+{
+	struct b43_wldev *wldev = dev_to_b43_wldev(dev);
+	int err;
+	int mode;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	mode = get_integer(buf, count);
+	switch (mode) {
+	case 0:
+		mode = B43_INTERFMODE_NONE;
+		break;
+	case 1:
+		mode = B43_INTERFMODE_NONWLAN;
+		break;
+	case 2:
+		mode = B43_INTERFMODE_MANUALWLAN;
+		break;
+	case 3:
+		mode = B43_INTERFMODE_AUTOWLAN;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	mutex_lock(&wldev->wl->mutex);
+
+	if (wldev->phy.ops->interf_mitigation) {
+		err = wldev->phy.ops->interf_mitigation(wldev, mode);
+		if (err) {
+			b43err(wldev->wl, "Interference Mitigation not "
+			       "supported by device\n");
+		}
+	} else
+		err = -ENOSYS;
+
+	mmiowb();
+	mutex_unlock(&wldev->wl->mutex);
+
+	return err ? err : count;
+}
+
+static DEVICE_ATTR(interference, 0644,
+		   b43_attr_interfmode_show, b43_attr_interfmode_store);
+
+int b43_sysfs_register(struct b43_wldev *wldev)
+{
+	struct device *dev = wldev->dev->dev;
+
+	B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED);
+
+	return device_create_file(dev, &dev_attr_interference);
+}
+
+void b43_sysfs_unregister(struct b43_wldev *wldev)
+{
+	struct device *dev = wldev->dev->dev;
+
+	device_remove_file(dev, &dev_attr_interference);
+}
diff --git a/drivers/net/wireless/broadcom/b43/sysfs.h b/drivers/net/wireless/broadcom/b43/sysfs.h
new file mode 100644
index 0000000..e70e6cf
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/sysfs.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_SYSFS_H_
+#define B43_SYSFS_H_
+
+struct b43_wldev;
+
+int b43_sysfs_register(struct b43_wldev *dev);
+void b43_sysfs_unregister(struct b43_wldev *dev);
+
+#endif /* B43_SYSFS_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/tables.c b/drivers/net/wireless/broadcom/b43/tables.c
new file mode 100644
index 0000000..ea288df
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/tables.c
@@ -0,0 +1,466 @@
+/*
+
+  Broadcom B43 wireless driver
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+  Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
+  Copyright (c) 2006, 2006 Michael Buesch <m@bues.ch>
+  Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
+  Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+  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.h"
+#include "phy_g.h"
+
+
+const u32 b43_tab_rotor[] = {
+	0xFEB93FFD, 0xFEC63FFD,	/* 0 */
+	0xFED23FFD, 0xFEDF3FFD,
+	0xFEEC3FFE, 0xFEF83FFE,
+	0xFF053FFE, 0xFF113FFE,
+	0xFF1E3FFE, 0xFF2A3FFF,	/* 8 */
+	0xFF373FFF, 0xFF443FFF,
+	0xFF503FFF, 0xFF5D3FFF,
+	0xFF693FFF, 0xFF763FFF,
+	0xFF824000, 0xFF8F4000,	/* 16 */
+	0xFF9B4000, 0xFFA84000,
+	0xFFB54000, 0xFFC14000,
+	0xFFCE4000, 0xFFDA4000,
+	0xFFE74000, 0xFFF34000,	/* 24 */
+	0x00004000, 0x000D4000,
+	0x00194000, 0x00264000,
+	0x00324000, 0x003F4000,
+	0x004B4000, 0x00584000,	/* 32 */
+	0x00654000, 0x00714000,
+	0x007E4000, 0x008A3FFF,
+	0x00973FFF, 0x00A33FFF,
+	0x00B03FFF, 0x00BC3FFF,	/* 40 */
+	0x00C93FFF, 0x00D63FFF,
+	0x00E23FFE, 0x00EF3FFE,
+	0x00FB3FFE, 0x01083FFE,
+	0x01143FFE, 0x01213FFD,	/* 48 */
+	0x012E3FFD, 0x013A3FFD,
+	0x01473FFD,
+};
+
+const u32 b43_tab_retard[] = {
+	0xDB93CB87, 0xD666CF64,	/* 0 */
+	0xD1FDD358, 0xCDA6D826,
+	0xCA38DD9F, 0xC729E2B4,
+	0xC469E88E, 0xC26AEE2B,
+	0xC0DEF46C, 0xC073FA62,	/* 8 */
+	0xC01D00D5, 0xC0760743,
+	0xC1560D1E, 0xC2E51369,
+	0xC4ED18FF, 0xC7AC1ED7,
+	0xCB2823B2, 0xCEFA28D9,	/* 16 */
+	0xD2F62D3F, 0xD7BB3197,
+	0xDCE53568, 0xE1FE3875,
+	0xE7D13B35, 0xED663D35,
+	0xF39B3EC4, 0xF98E3FA7,	/* 24 */
+	0x00004000, 0x06723FA7,
+	0x0C653EC4, 0x129A3D35,
+	0x182F3B35, 0x1E023875,
+	0x231B3568, 0x28453197,	/* 32 */
+	0x2D0A2D3F, 0x310628D9,
+	0x34D823B2, 0x38541ED7,
+	0x3B1318FF, 0x3D1B1369,
+	0x3EAA0D1E, 0x3F8A0743,	/* 40 */
+	0x3FE300D5, 0x3F8DFA62,
+	0x3F22F46C, 0x3D96EE2B,
+	0x3B97E88E, 0x38D7E2B4,
+	0x35C8DD9F, 0x325AD826,	/* 48 */
+	0x2E03D358, 0x299ACF64,
+	0x246DCB87,
+};
+
+const u16 b43_tab_finefreqa[] = {
+	0x0082, 0x0082, 0x0102, 0x0182,	/* 0 */
+	0x0202, 0x0282, 0x0302, 0x0382,
+	0x0402, 0x0482, 0x0502, 0x0582,
+	0x05E2, 0x0662, 0x06E2, 0x0762,
+	0x07E2, 0x0842, 0x08C2, 0x0942,	/* 16 */
+	0x09C2, 0x0A22, 0x0AA2, 0x0B02,
+	0x0B82, 0x0BE2, 0x0C62, 0x0CC2,
+	0x0D42, 0x0DA2, 0x0E02, 0x0E62,
+	0x0EE2, 0x0F42, 0x0FA2, 0x1002,	/* 32 */
+	0x1062, 0x10C2, 0x1122, 0x1182,
+	0x11E2, 0x1242, 0x12A2, 0x12E2,
+	0x1342, 0x13A2, 0x1402, 0x1442,
+	0x14A2, 0x14E2, 0x1542, 0x1582,	/* 48 */
+	0x15E2, 0x1622, 0x1662, 0x16C1,
+	0x1701, 0x1741, 0x1781, 0x17E1,
+	0x1821, 0x1861, 0x18A1, 0x18E1,
+	0x1921, 0x1961, 0x19A1, 0x19E1,	/* 64 */
+	0x1A21, 0x1A61, 0x1AA1, 0x1AC1,
+	0x1B01, 0x1B41, 0x1B81, 0x1BA1,
+	0x1BE1, 0x1C21, 0x1C41, 0x1C81,
+	0x1CA1, 0x1CE1, 0x1D01, 0x1D41,	/* 80 */
+	0x1D61, 0x1DA1, 0x1DC1, 0x1E01,
+	0x1E21, 0x1E61, 0x1E81, 0x1EA1,
+	0x1EE1, 0x1F01, 0x1F21, 0x1F41,
+	0x1F81, 0x1FA1, 0x1FC1, 0x1FE1,	/* 96 */
+	0x2001, 0x2041, 0x2061, 0x2081,
+	0x20A1, 0x20C1, 0x20E1, 0x2101,
+	0x2121, 0x2141, 0x2161, 0x2181,
+	0x21A1, 0x21C1, 0x21E1, 0x2201,	/* 112 */
+	0x2221, 0x2241, 0x2261, 0x2281,
+	0x22A1, 0x22C1, 0x22C1, 0x22E1,
+	0x2301, 0x2321, 0x2341, 0x2361,
+	0x2361, 0x2381, 0x23A1, 0x23C1,	/* 128 */
+	0x23E1, 0x23E1, 0x2401, 0x2421,
+	0x2441, 0x2441, 0x2461, 0x2481,
+	0x2481, 0x24A1, 0x24C1, 0x24C1,
+	0x24E1, 0x2501, 0x2501, 0x2521,	/* 144 */
+	0x2541, 0x2541, 0x2561, 0x2561,
+	0x2581, 0x25A1, 0x25A1, 0x25C1,
+	0x25C1, 0x25E1, 0x2601, 0x2601,
+	0x2621, 0x2621, 0x2641, 0x2641,	/* 160 */
+	0x2661, 0x2661, 0x2681, 0x2681,
+	0x26A1, 0x26A1, 0x26C1, 0x26C1,
+	0x26E1, 0x26E1, 0x2701, 0x2701,
+	0x2721, 0x2721, 0x2740, 0x2740,	/* 176 */
+	0x2760, 0x2760, 0x2780, 0x2780,
+	0x2780, 0x27A0, 0x27A0, 0x27C0,
+	0x27C0, 0x27E0, 0x27E0, 0x27E0,
+	0x2800, 0x2800, 0x2820, 0x2820,	/* 192 */
+	0x2820, 0x2840, 0x2840, 0x2840,
+	0x2860, 0x2860, 0x2880, 0x2880,
+	0x2880, 0x28A0, 0x28A0, 0x28A0,
+	0x28C0, 0x28C0, 0x28C0, 0x28E0,	/* 208 */
+	0x28E0, 0x28E0, 0x2900, 0x2900,
+	0x2900, 0x2920, 0x2920, 0x2920,
+	0x2940, 0x2940, 0x2940, 0x2960,
+	0x2960, 0x2960, 0x2960, 0x2980,	/* 224 */
+	0x2980, 0x2980, 0x29A0, 0x29A0,
+	0x29A0, 0x29A0, 0x29C0, 0x29C0,
+	0x29C0, 0x29E0, 0x29E0, 0x29E0,
+	0x29E0, 0x2A00, 0x2A00, 0x2A00,	/* 240 */
+	0x2A00, 0x2A20, 0x2A20, 0x2A20,
+	0x2A20, 0x2A40, 0x2A40, 0x2A40,
+	0x2A40, 0x2A60, 0x2A60, 0x2A60,
+};
+
+const u16 b43_tab_finefreqg[] = {
+	0x0089, 0x02E9, 0x0409, 0x04E9,	/* 0 */
+	0x05A9, 0x0669, 0x0709, 0x0789,
+	0x0829, 0x08A9, 0x0929, 0x0989,
+	0x0A09, 0x0A69, 0x0AC9, 0x0B29,
+	0x0BA9, 0x0BE9, 0x0C49, 0x0CA9,	/* 16 */
+	0x0D09, 0x0D69, 0x0DA9, 0x0E09,
+	0x0E69, 0x0EA9, 0x0F09, 0x0F49,
+	0x0FA9, 0x0FE9, 0x1029, 0x1089,
+	0x10C9, 0x1109, 0x1169, 0x11A9,	/* 32 */
+	0x11E9, 0x1229, 0x1289, 0x12C9,
+	0x1309, 0x1349, 0x1389, 0x13C9,
+	0x1409, 0x1449, 0x14A9, 0x14E9,
+	0x1529, 0x1569, 0x15A9, 0x15E9,	/* 48 */
+	0x1629, 0x1669, 0x16A9, 0x16E8,
+	0x1728, 0x1768, 0x17A8, 0x17E8,
+	0x1828, 0x1868, 0x18A8, 0x18E8,
+	0x1928, 0x1968, 0x19A8, 0x19E8,	/* 64 */
+	0x1A28, 0x1A68, 0x1AA8, 0x1AE8,
+	0x1B28, 0x1B68, 0x1BA8, 0x1BE8,
+	0x1C28, 0x1C68, 0x1CA8, 0x1CE8,
+	0x1D28, 0x1D68, 0x1DC8, 0x1E08,	/* 80 */
+	0x1E48, 0x1E88, 0x1EC8, 0x1F08,
+	0x1F48, 0x1F88, 0x1FE8, 0x2028,
+	0x2068, 0x20A8, 0x2108, 0x2148,
+	0x2188, 0x21C8, 0x2228, 0x2268,	/* 96 */
+	0x22C8, 0x2308, 0x2348, 0x23A8,
+	0x23E8, 0x2448, 0x24A8, 0x24E8,
+	0x2548, 0x25A8, 0x2608, 0x2668,
+	0x26C8, 0x2728, 0x2787, 0x27E7,	/* 112 */
+	0x2847, 0x28C7, 0x2947, 0x29A7,
+	0x2A27, 0x2AC7, 0x2B47, 0x2BE7,
+	0x2CA7, 0x2D67, 0x2E47, 0x2F67,
+	0x3247, 0x3526, 0x3646, 0x3726,	/* 128 */
+	0x3806, 0x38A6, 0x3946, 0x39E6,
+	0x3A66, 0x3AE6, 0x3B66, 0x3BC6,
+	0x3C45, 0x3CA5, 0x3D05, 0x3D85,
+	0x3DE5, 0x3E45, 0x3EA5, 0x3EE5,	/* 144 */
+	0x3F45, 0x3FA5, 0x4005, 0x4045,
+	0x40A5, 0x40E5, 0x4145, 0x4185,
+	0x41E5, 0x4225, 0x4265, 0x42C5,
+	0x4305, 0x4345, 0x43A5, 0x43E5,	/* 160 */
+	0x4424, 0x4464, 0x44C4, 0x4504,
+	0x4544, 0x4584, 0x45C4, 0x4604,
+	0x4644, 0x46A4, 0x46E4, 0x4724,
+	0x4764, 0x47A4, 0x47E4, 0x4824,	/* 176 */
+	0x4864, 0x48A4, 0x48E4, 0x4924,
+	0x4964, 0x49A4, 0x49E4, 0x4A24,
+	0x4A64, 0x4AA4, 0x4AE4, 0x4B23,
+	0x4B63, 0x4BA3, 0x4BE3, 0x4C23,	/* 192 */
+	0x4C63, 0x4CA3, 0x4CE3, 0x4D23,
+	0x4D63, 0x4DA3, 0x4DE3, 0x4E23,
+	0x4E63, 0x4EA3, 0x4EE3, 0x4F23,
+	0x4F63, 0x4FC3, 0x5003, 0x5043,	/* 208 */
+	0x5083, 0x50C3, 0x5103, 0x5143,
+	0x5183, 0x51E2, 0x5222, 0x5262,
+	0x52A2, 0x52E2, 0x5342, 0x5382,
+	0x53C2, 0x5402, 0x5462, 0x54A2,	/* 224 */
+	0x5502, 0x5542, 0x55A2, 0x55E2,
+	0x5642, 0x5682, 0x56E2, 0x5722,
+	0x5782, 0x57E1, 0x5841, 0x58A1,
+	0x5901, 0x5961, 0x59C1, 0x5A21,	/* 240 */
+	0x5AA1, 0x5B01, 0x5B81, 0x5BE1,
+	0x5C61, 0x5D01, 0x5D80, 0x5E20,
+	0x5EE0, 0x5FA0, 0x6080, 0x61C0,
+};
+
+const u16 b43_tab_noisea2[] = {
+	0x0001, 0x0001, 0x0001, 0xFFFE,
+	0xFFFE, 0x3FFF, 0x1000, 0x0393,
+};
+
+const u16 b43_tab_noisea3[] = {
+	0x5E5E, 0x5E5E, 0x5E5E, 0x3F48,
+	0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
+};
+
+const u16 b43_tab_noiseg1[] = {
+	0x013C, 0x01F5, 0x031A, 0x0631,
+	0x0001, 0x0001, 0x0001, 0x0001,
+};
+
+const u16 b43_tab_noiseg2[] = {
+	0x5484, 0x3C40, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+const u16 b43_tab_noisescalea2[] = {
+	0x6767, 0x6767, 0x6767, 0x6767, /* 0 */
+	0x6767, 0x6767, 0x6767, 0x6767,
+	0x6767, 0x6767, 0x6767, 0x6767,
+	0x6767, 0x6700, 0x6767, 0x6767,
+	0x6767, 0x6767, 0x6767, 0x6767, /* 16 */
+	0x6767, 0x6767, 0x6767, 0x6767,
+	0x6767, 0x6767, 0x0067,
+};
+
+const u16 b43_tab_noisescalea3[] = {
+	0x2323, 0x2323, 0x2323, 0x2323, /* 0 */
+	0x2323, 0x2323, 0x2323, 0x2323,
+	0x2323, 0x2323, 0x2323, 0x2323,
+	0x2323, 0x2300, 0x2323, 0x2323,
+	0x2323, 0x2323, 0x2323, 0x2323, /* 16 */
+	0x2323, 0x2323, 0x2323, 0x2323,
+	0x2323, 0x2323, 0x0023,
+};
+
+const u16 b43_tab_noisescaleg1[] = {
+	0x6C77, 0x5162, 0x3B40, 0x3335,	/* 0 */
+	0x2F2D, 0x2A2A, 0x2527, 0x1F21,
+	0x1A1D, 0x1719, 0x1616, 0x1414,
+	0x1414, 0x1400, 0x1414, 0x1614,
+	0x1716, 0x1A19, 0x1F1D, 0x2521,	/* 16 */
+	0x2A27, 0x2F2A, 0x332D, 0x3B35,
+	0x5140, 0x6C62, 0x0077,
+};
+
+const u16 b43_tab_noisescaleg2[] = {
+	0xD8DD, 0xCBD4, 0xBCC0, 0xB6B7,	/* 0 */
+	0xB2B0, 0xADAD, 0xA7A9, 0x9FA1,
+	0x969B, 0x9195, 0x8F8F, 0x8A8A,
+	0x8A8A, 0x8A00, 0x8A8A, 0x8F8A,
+	0x918F, 0x9695, 0x9F9B, 0xA7A1,	/* 16 */
+	0xADA9, 0xB2AD, 0xB6B0, 0xBCB7,
+	0xCBC0, 0xD8D4, 0x00DD,
+};
+
+const u16 b43_tab_noisescaleg3[] = {
+	0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,	/* 0 */
+	0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
+	0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
+	0xA4A4, 0xA400, 0xA4A4, 0xA4A4,
+	0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,	/* 16 */
+	0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
+	0xA4A4, 0xA4A4, 0x00A4,
+};
+
+const u16 b43_tab_sigmasqr1[] = {
+	0x007A, 0x0075, 0x0071, 0x006C,	/* 0 */
+	0x0067, 0x0063, 0x005E, 0x0059,
+	0x0054, 0x0050, 0x004B, 0x0046,
+	0x0042, 0x003D, 0x003D, 0x003D,
+	0x003D, 0x003D, 0x003D, 0x003D,	/* 16 */
+	0x003D, 0x003D, 0x003D, 0x003D,
+	0x003D, 0x003D, 0x0000, 0x003D,
+	0x003D, 0x003D, 0x003D, 0x003D,
+	0x003D, 0x003D, 0x003D, 0x003D,	/* 32 */
+	0x003D, 0x003D, 0x003D, 0x003D,
+	0x0042, 0x0046, 0x004B, 0x0050,
+	0x0054, 0x0059, 0x005E, 0x0063,
+	0x0067, 0x006C, 0x0071, 0x0075,	/* 48 */
+	0x007A,
+};
+
+const u16 b43_tab_sigmasqr2[] = {
+	0x00DE, 0x00DC, 0x00DA, 0x00D8,	/* 0 */
+	0x00D6, 0x00D4, 0x00D2, 0x00CF,
+	0x00CD, 0x00CA, 0x00C7, 0x00C4,
+	0x00C1, 0x00BE, 0x00BE, 0x00BE,
+	0x00BE, 0x00BE, 0x00BE, 0x00BE,	/* 16 */
+	0x00BE, 0x00BE, 0x00BE, 0x00BE,
+	0x00BE, 0x00BE, 0x0000, 0x00BE,
+	0x00BE, 0x00BE, 0x00BE, 0x00BE,
+	0x00BE, 0x00BE, 0x00BE, 0x00BE,	/* 32 */
+	0x00BE, 0x00BE, 0x00BE, 0x00BE,
+	0x00C1, 0x00C4, 0x00C7, 0x00CA,
+	0x00CD, 0x00CF, 0x00D2, 0x00D4,
+	0x00D6, 0x00D8, 0x00DA, 0x00DC,	/* 48 */
+	0x00DE,
+};
+
+const u16 b43_tab_rssiagc1[] = {
+	0xFFF8, 0xFFF8, 0xFFF8, 0xFFF8, /* 0 */
+	0xFFF8, 0xFFF9, 0xFFFC, 0xFFFE,
+	0xFFF8, 0xFFF8, 0xFFF8, 0xFFF8,
+	0xFFF8, 0xFFF8, 0xFFF8, 0xFFF8,
+};
+
+const u16 b43_tab_rssiagc2[] = {
+	0x0820, 0x0820, 0x0920, 0x0C38, /* 0 */
+	0x0820, 0x0820, 0x0820, 0x0820,
+	0x0820, 0x0820, 0x0920, 0x0A38,
+	0x0820, 0x0820, 0x0820, 0x0820,
+	0x0820, 0x0820, 0x0920, 0x0A38, /* 16 */
+	0x0820, 0x0820, 0x0820, 0x0820,
+	0x0820, 0x0820, 0x0920, 0x0A38,
+	0x0820, 0x0820, 0x0820, 0x0820,
+	0x0820, 0x0820, 0x0920, 0x0A38, /* 32 */
+	0x0820, 0x0820, 0x0820, 0x0820,
+	0x0820, 0x0820, 0x0920, 0x0A38,
+	0x0820, 0x0820, 0x0820, 0x0820,
+};
+
+static inline void assert_sizes(void)
+{
+	BUILD_BUG_ON(B43_TAB_ROTOR_SIZE != ARRAY_SIZE(b43_tab_rotor));
+	BUILD_BUG_ON(B43_TAB_RETARD_SIZE != ARRAY_SIZE(b43_tab_retard));
+	BUILD_BUG_ON(B43_TAB_FINEFREQA_SIZE != ARRAY_SIZE(b43_tab_finefreqa));
+	BUILD_BUG_ON(B43_TAB_FINEFREQG_SIZE != ARRAY_SIZE(b43_tab_finefreqg));
+	BUILD_BUG_ON(B43_TAB_NOISEA2_SIZE != ARRAY_SIZE(b43_tab_noisea2));
+	BUILD_BUG_ON(B43_TAB_NOISEA3_SIZE != ARRAY_SIZE(b43_tab_noisea3));
+	BUILD_BUG_ON(B43_TAB_NOISEG1_SIZE != ARRAY_SIZE(b43_tab_noiseg1));
+	BUILD_BUG_ON(B43_TAB_NOISEG2_SIZE != ARRAY_SIZE(b43_tab_noiseg2));
+	BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE !=
+		     ARRAY_SIZE(b43_tab_noisescalea2));
+	BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE !=
+		     ARRAY_SIZE(b43_tab_noisescalea3));
+	BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE !=
+		     ARRAY_SIZE(b43_tab_noisescaleg1));
+	BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE !=
+		     ARRAY_SIZE(b43_tab_noisescaleg2));
+	BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE !=
+		     ARRAY_SIZE(b43_tab_noisescaleg3));
+	BUILD_BUG_ON(B43_TAB_SIGMASQR_SIZE != ARRAY_SIZE(b43_tab_sigmasqr1));
+	BUILD_BUG_ON(B43_TAB_SIGMASQR_SIZE != ARRAY_SIZE(b43_tab_sigmasqr2));
+	BUILD_BUG_ON(B43_TAB_RSSIAGC1_SIZE != ARRAY_SIZE(b43_tab_rssiagc1));
+	BUILD_BUG_ON(B43_TAB_RSSIAGC2_SIZE != ARRAY_SIZE(b43_tab_rssiagc2));
+}
+
+u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset)
+{
+	struct b43_phy_g *gphy = dev->phy.g;
+	u16 addr;
+
+	addr = table + offset;
+	if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) ||
+	    (addr - 1 != gphy->ofdmtab_addr)) {
+		/* The hardware has a different address in memory. Update it. */
+		b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
+		gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ;
+	}
+	gphy->ofdmtab_addr = addr;
+
+	return b43_phy_read(dev, B43_PHY_OTABLEI);
+
+	/* Some compiletime assertions... */
+	assert_sizes();
+}
+
+void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table,
+			 u16 offset, u16 value)
+{
+	struct b43_phy_g *gphy = dev->phy.g;
+	u16 addr;
+
+	addr = table + offset;
+	if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) ||
+	    (addr - 1 != gphy->ofdmtab_addr)) {
+		/* The hardware has a different address in memory. Update it. */
+		b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
+		gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE;
+	}
+	gphy->ofdmtab_addr = addr;
+	b43_phy_write(dev, B43_PHY_OTABLEI, value);
+}
+
+u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset)
+{
+	struct b43_phy_g *gphy = dev->phy.g;
+	u32 ret;
+	u16 addr;
+
+	addr = table + offset;
+	if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) ||
+	    (addr - 1 != gphy->ofdmtab_addr)) {
+		/* The hardware has a different address in memory. Update it. */
+		b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
+		gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ;
+	}
+	gphy->ofdmtab_addr = addr;
+	ret = b43_phy_read(dev, B43_PHY_OTABLEQ);
+	ret <<= 16;
+	ret |= b43_phy_read(dev, B43_PHY_OTABLEI);
+
+	return ret;
+}
+
+void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table,
+			 u16 offset, u32 value)
+{
+	struct b43_phy_g *gphy = dev->phy.g;
+	u16 addr;
+
+	addr = table + offset;
+	if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) ||
+	    (addr - 1 != gphy->ofdmtab_addr)) {
+		/* The hardware has a different address in memory. Update it. */
+		b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
+		gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE;
+	}
+	gphy->ofdmtab_addr = addr;
+
+	b43_phy_write(dev, B43_PHY_OTABLEI, value);
+	b43_phy_write(dev, B43_PHY_OTABLEQ, (value >> 16));
+}
+
+u16 b43_gtab_read(struct b43_wldev *dev, u16 table, u16 offset)
+{
+	b43_phy_write(dev, B43_PHY_GTABCTL, table + offset);
+	return b43_phy_read(dev, B43_PHY_GTABDATA);
+}
+
+void b43_gtab_write(struct b43_wldev *dev, u16 table, u16 offset, u16 value)
+{
+	b43_phy_write(dev, B43_PHY_GTABCTL, table + offset);
+	b43_phy_write(dev, B43_PHY_GTABDATA, value);
+}
diff --git a/drivers/net/wireless/broadcom/b43/tables.h b/drivers/net/wireless/broadcom/b43/tables.h
new file mode 100644
index 0000000..3b0777f
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/tables.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_TABLES_H_
+#define B43_TABLES_H_
+
+#define B43_TAB_ROTOR_SIZE	53
+extern const u32 b43_tab_rotor[];
+#define B43_TAB_RETARD_SIZE	53
+extern const u32 b43_tab_retard[];
+#define B43_TAB_FINEFREQA_SIZE	256
+extern const u16 b43_tab_finefreqa[];
+#define B43_TAB_FINEFREQG_SIZE	256
+extern const u16 b43_tab_finefreqg[];
+#define B43_TAB_NOISEA2_SIZE	8
+extern const u16 b43_tab_noisea2[];
+#define B43_TAB_NOISEA3_SIZE	8
+extern const u16 b43_tab_noisea3[];
+#define B43_TAB_NOISEG1_SIZE	8
+extern const u16 b43_tab_noiseg1[];
+#define B43_TAB_NOISEG2_SIZE	8
+extern const u16 b43_tab_noiseg2[];
+#define B43_TAB_NOISESCALE_SIZE	27
+extern const u16 b43_tab_noisescalea2[];
+extern const u16 b43_tab_noisescalea3[];
+extern const u16 b43_tab_noisescaleg1[];
+extern const u16 b43_tab_noisescaleg2[];
+extern const u16 b43_tab_noisescaleg3[];
+#define B43_TAB_SIGMASQR_SIZE	53
+extern const u16 b43_tab_sigmasqr1[];
+extern const u16 b43_tab_sigmasqr2[];
+#define B43_TAB_RSSIAGC1_SIZE	16
+extern const u16 b43_tab_rssiagc1[];
+#define B43_TAB_RSSIAGC2_SIZE	48
+extern const u16 b43_tab_rssiagc2[];
+
+#endif /* B43_TABLES_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/tables_lpphy.c b/drivers/net/wireless/broadcom/b43/tables_lpphy.c
new file mode 100644
index 0000000..ce01e16
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/tables_lpphy.c
@@ -0,0 +1,2456 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11a/g LP-PHY and radio device data tables
+
+  Copyright (c) 2009 Michael Buesch <m@bues.ch>
+  Copyright (c) 2009 Gábor Stefanik <netrolller.3d@gmail.com>
+
+  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_lpphy.h"
+#include "phy_common.h"
+#include "phy_lp.h"
+
+
+/* Entry of the 2062/2063 radio init table */
+struct b206x_init_tab_entry {
+	u16 offset;
+	u16 value_a;
+	u16 value_g;
+	u8 flags;
+};
+#define B206X_FLAG_A	0x01 /* Flag: Init in A mode */
+#define B206X_FLAG_G	0x02 /* Flag: Init in G mode */
+
+static const struct b206x_init_tab_entry b2062_init_tab[] = {
+	/* { .offset = B2062_N_COMM1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = 0x0001, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_COMM2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_COMM3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2062_N_COMM4, .value_a = 0x0001, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2062_N_COMM5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_COMM6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_COMM7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_COMM8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_COMM9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_COMM10, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_COMM11, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_COMM12, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_COMM13, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_COMM14, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_COMM15, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_PDN_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2062_N_PDN_CTL1, .value_a = 0x0000, .value_g = 0x00CA, .flags = B206X_FLAG_G, },
+	/* { .offset = B2062_N_PDN_CTL2, .value_a = 0x0018, .value_g = 0x0018, .flags = 0, }, */
+	{ .offset = B2062_N_PDN_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2062_N_PDN_CTL4, .value_a = 0x0015, .value_g = 0x002A, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2062_N_GEN_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_IQ_CALIB, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
+	{ .offset = B2062_N_LGENC, .value_a = 0x00DB, .value_g = 0x00FF, .flags = B206X_FLAG_A, },
+	/* { .offset = B2062_N_LGENA_LPF, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
+	/* { .offset = B2062_N_LGENA_BIAS0, .value_a = 0x0041, .value_g = 0x0041, .flags = 0, }, */
+	/* { .offset = B2062_N_LGNEA_BIAS1, .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */
+	/* { .offset = B2062_N_LGENA_CTL0, .value_a = 0x0032, .value_g = 0x0032, .flags = 0, }, */
+	/* { .offset = B2062_N_LGENA_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_LGENA_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2062_N_LGENA_TUNE0, .value_a = 0x00DD, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2062_N_LGENA_TUNE1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2062_N_LGENA_TUNE2, .value_a = 0x00DD, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2062_N_LGENA_TUNE3, .value_a = 0x0077, .value_g = 0x00B5, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2062_N_LGENA_CTL3, .value_a = 0x0000, .value_g = 0x00FF, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2062_N_LGENA_CTL4, .value_a = 0x001F, .value_g = 0x001F, .flags = 0, }, */
+	/* { .offset = B2062_N_LGENA_CTL5, .value_a = 0x0032, .value_g = 0x0032, .flags = 0, }, */
+	/* { .offset = B2062_N_LGENA_CTL6, .value_a = 0x0032, .value_g = 0x0032, .flags = 0, }, */
+	{ .offset = B2062_N_LGENA_CTL7, .value_a = 0x0033, .value_g = 0x0033, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2062_N_RXA_CTL0, .value_a = 0x0009, .value_g = 0x0009, .flags = 0, }, */
+	{ .offset = B2062_N_RXA_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
+	/* { .offset = B2062_N_RXA_CTL2, .value_a = 0x0018, .value_g = 0x0018, .flags = 0, }, */
+	/* { .offset = B2062_N_RXA_CTL3, .value_a = 0x0027, .value_g = 0x0027, .flags = 0, }, */
+	/* { .offset = B2062_N_RXA_CTL4, .value_a = 0x0028, .value_g = 0x0028, .flags = 0, }, */
+	/* { .offset = B2062_N_RXA_CTL5, .value_a = 0x0007, .value_g = 0x0007, .flags = 0, }, */
+	/* { .offset = B2062_N_RXA_CTL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_RXA_CTL7, .value_a = 0x0008, .value_g = 0x0008, .flags = 0, }, */
+	{ .offset = B2062_N_RXBB_CTL0, .value_a = 0x0082, .value_g = 0x0080, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2062_N_RXBB_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_RXBB_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_RXBB_GAIN0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2062_N_RXBB_GAIN1, .value_a = 0x0004, .value_g = 0x0004, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2062_N_RXBB_GAIN2, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2062_N_RXBB_GAIN3, .value_a = 0x0011, .value_g = 0x0011, .flags = 0, }, */
+	/* { .offset = B2062_N_RXBB_RSSI0, .value_a = 0x0043, .value_g = 0x0043, .flags = 0, }, */
+	/* { .offset = B2062_N_RXBB_RSSI1, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
+	/* { .offset = B2062_N_RXBB_CALIB0, .value_a = 0x0010, .value_g = 0x0010, .flags = 0, }, */
+	/* { .offset = B2062_N_RXBB_CALIB1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_RXBB_CALIB2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_RXBB_BIAS0, .value_a = 0x0006, .value_g = 0x0006, .flags = 0, }, */
+	/* { .offset = B2062_N_RXBB_BIAS1, .value_a = 0x002A, .value_g = 0x002A, .flags = 0, }, */
+	/* { .offset = B2062_N_RXBB_BIAS2, .value_a = 0x00AA, .value_g = 0x00AA, .flags = 0, }, */
+	/* { .offset = B2062_N_RXBB_BIAS3, .value_a = 0x0021, .value_g = 0x0021, .flags = 0, }, */
+	/* { .offset = B2062_N_RXBB_BIAS4, .value_a = 0x00AA, .value_g = 0x00AA, .flags = 0, }, */
+	/* { .offset = B2062_N_RXBB_BIAS5, .value_a = 0x0022, .value_g = 0x0022, .flags = 0, }, */
+	/* { .offset = B2062_N_RXBB_RSSI2, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
+	/* { .offset = B2062_N_RXBB_RSSI3, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
+	/* { .offset = B2062_N_RXBB_RSSI4, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
+	/* { .offset = B2062_N_RXBB_RSSI5, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
+	/* { .offset = B2062_N_TX_CTL0, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
+	/* { .offset = B2062_N_TX_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_TX_CTL2, .value_a = 0x0084, .value_g = 0x0084, .flags = 0, }, */
+	/* { .offset = B2062_N_TX_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2062_N_TX_CTL4, .value_a = 0x0003, .value_g = 0x0003, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2062_N_TX_CTL5, .value_a = 0x0002, .value_g = 0x0002, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2062_N_TX_CTL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_TX_CTL7, .value_a = 0x0058, .value_g = 0x0058, .flags = 0, }, */
+	/* { .offset = B2062_N_TX_CTL8, .value_a = 0x0082, .value_g = 0x0082, .flags = 0, }, */
+	/* { .offset = B2062_N_TX_CTL9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_TX_CTL_A, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_TX_GC2G, .value_a = 0x00FF, .value_g = 0x00FF, .flags = 0, }, */
+	/* { .offset = B2062_N_TX_GC5G, .value_a = 0x00FF, .value_g = 0x00FF, .flags = 0, }, */
+	{ .offset = B2062_N_TX_TUNE, .value_a = 0x0088, .value_g = 0x001B, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2062_N_TX_PAD, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
+	/* { .offset = B2062_N_TX_PGA, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
+	/* { .offset = B2062_N_TX_PADAUX, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
+	/* { .offset = B2062_N_TX_PGAAUX, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
+	/* { .offset = B2062_N_TSSI_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_TSSI_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_TSSI_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_IQ_CALIB_CTL0, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
+	/* { .offset = B2062_N_IQ_CALIB_CTL1, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
+	/* { .offset = B2062_N_IQ_CALIB_CTL2, .value_a = 0x0032, .value_g = 0x0032, .flags = 0, }, */
+	/* { .offset = B2062_N_CALIB_TS, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_CALIB_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_CALIB_CTL1, .value_a = 0x0015, .value_g = 0x0015, .flags = 0, }, */
+	/* { .offset = B2062_N_CALIB_CTL2, .value_a = 0x000F, .value_g = 0x000F, .flags = 0, }, */
+	/* { .offset = B2062_N_CALIB_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_CALIB_CTL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_CALIB_DBG0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_CALIB_DBG1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_CALIB_DBG2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_CALIB_DBG3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_PSENSE_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_PSENSE_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_PSENSE_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_N_TEST_BUF0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_COMM1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_RADIO_ID_CODE, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_COMM2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_COMM3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2062_S_COMM4, .value_a = 0x0001, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2062_S_COMM5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_COMM6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_COMM7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_COMM8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_COMM9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_COMM10, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_COMM11, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_COMM12, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_COMM13, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_COMM14, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_COMM15, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2062_S_PDS_CTL0, .value_a = 0x00FF, .value_g = 0x00FF, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2062_S_PDS_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_PDS_CTL2, .value_a = 0x008E, .value_g = 0x008E, .flags = 0, }, */
+	/* { .offset = B2062_S_PDS_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_BG_CTL0, .value_a = 0x0006, .value_g = 0x0006, .flags = 0, }, */
+	/* { .offset = B2062_S_BG_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_BG_CTL2, .value_a = 0x0011, .value_g = 0x0011, .flags = 0, }, */
+	{ .offset = B2062_S_LGENG_CTL0, .value_a = 0x00F8, .value_g = 0x00D8, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2062_S_LGENG_CTL1, .value_a = 0x003C, .value_g = 0x0024, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2062_S_LGENG_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_LGENG_CTL3, .value_a = 0x0041, .value_g = 0x0041, .flags = 0, }, */
+	/* { .offset = B2062_S_LGENG_CTL4, .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */
+	/* { .offset = B2062_S_LGENG_CTL5, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
+	/* { .offset = B2062_S_LGENG_CTL6, .value_a = 0x0022, .value_g = 0x0022, .flags = 0, }, */
+	/* { .offset = B2062_S_LGENG_CTL7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2062_S_LGENG_CTL8, .value_a = 0x0088, .value_g = 0x0080, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2062_S_LGENG_CTL9, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
+	{ .offset = B2062_S_LGENG_CTL10, .value_a = 0x0088, .value_g = 0x0080, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2062_S_LGENG_CTL11, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_REFPLL_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_REFPLL_CTL1, .value_a = 0x0007, .value_g = 0x0007, .flags = 0, }, */
+	/* { .offset = B2062_S_REFPLL_CTL2, .value_a = 0x00AF, .value_g = 0x00AF, .flags = 0, }, */
+	/* { .offset = B2062_S_REFPLL_CTL3, .value_a = 0x0012, .value_g = 0x0012, .flags = 0, }, */
+	/* { .offset = B2062_S_REFPLL_CTL4, .value_a = 0x000B, .value_g = 0x000B, .flags = 0, }, */
+	/* { .offset = B2062_S_REFPLL_CTL5, .value_a = 0x005F, .value_g = 0x005F, .flags = 0, }, */
+	/* { .offset = B2062_S_REFPLL_CTL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_REFPLL_CTL7, .value_a = 0x0040, .value_g = 0x0040, .flags = 0, }, */
+	/* { .offset = B2062_S_REFPLL_CTL8, .value_a = 0x0052, .value_g = 0x0052, .flags = 0, }, */
+	/* { .offset = B2062_S_REFPLL_CTL9, .value_a = 0x0026, .value_g = 0x0026, .flags = 0, }, */
+	/* { .offset = B2062_S_REFPLL_CTL10, .value_a = 0x0003, .value_g = 0x0003, .flags = 0, }, */
+	/* { .offset = B2062_S_REFPLL_CTL11, .value_a = 0x0036, .value_g = 0x0036, .flags = 0, }, */
+	/* { .offset = B2062_S_REFPLL_CTL12, .value_a = 0x0057, .value_g = 0x0057, .flags = 0, }, */
+	/* { .offset = B2062_S_REFPLL_CTL13, .value_a = 0x0011, .value_g = 0x0011, .flags = 0, }, */
+	/* { .offset = B2062_S_REFPLL_CTL14, .value_a = 0x0075, .value_g = 0x0075, .flags = 0, }, */
+	/* { .offset = B2062_S_REFPLL_CTL15, .value_a = 0x00B4, .value_g = 0x00B4, .flags = 0, }, */
+	/* { .offset = B2062_S_REFPLL_CTL16, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2062_S_RFPLL_CTL0, .value_a = 0x0098, .value_g = 0x0098, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2062_S_RFPLL_CTL1, .value_a = 0x0010, .value_g = 0x0010, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2062_S_RFPLL_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_RFPLL_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_RFPLL_CTL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2062_S_RFPLL_CTL5, .value_a = 0x0043, .value_g = 0x0043, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2062_S_RFPLL_CTL6, .value_a = 0x0047, .value_g = 0x0047, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2062_S_RFPLL_CTL7, .value_a = 0x000C, .value_g = 0x000C, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2062_S_RFPLL_CTL8, .value_a = 0x0011, .value_g = 0x0011, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2062_S_RFPLL_CTL9, .value_a = 0x0011, .value_g = 0x0011, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2062_S_RFPLL_CTL10, .value_a = 0x000E, .value_g = 0x000E, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2062_S_RFPLL_CTL11, .value_a = 0x0008, .value_g = 0x0008, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2062_S_RFPLL_CTL12, .value_a = 0x0033, .value_g = 0x0033, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2062_S_RFPLL_CTL13, .value_a = 0x000A, .value_g = 0x000A, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2062_S_RFPLL_CTL14, .value_a = 0x0006, .value_g = 0x0006, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2062_S_RFPLL_CTL15, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_RFPLL_CTL16, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_RFPLL_CTL17, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2062_S_RFPLL_CTL18, .value_a = 0x003E, .value_g = 0x003E, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2062_S_RFPLL_CTL19, .value_a = 0x0013, .value_g = 0x0013, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2062_S_RFPLL_CTL20, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2062_S_RFPLL_CTL21, .value_a = 0x0062, .value_g = 0x0062, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2062_S_RFPLL_CTL22, .value_a = 0x0007, .value_g = 0x0007, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2062_S_RFPLL_CTL23, .value_a = 0x0016, .value_g = 0x0016, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2062_S_RFPLL_CTL24, .value_a = 0x005C, .value_g = 0x005C, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2062_S_RFPLL_CTL25, .value_a = 0x0095, .value_g = 0x0095, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2062_S_RFPLL_CTL26, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_RFPLL_CTL27, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_RFPLL_CTL28, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_RFPLL_CTL29, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2062_S_RFPLL_CTL30, .value_a = 0x00A0, .value_g = 0x00A0, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2062_S_RFPLL_CTL31, .value_a = 0x0004, .value_g = 0x0004, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2062_S_RFPLL_CTL32, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2062_S_RFPLL_CTL33, .value_a = 0x00CC, .value_g = 0x00CC, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2062_S_RFPLL_CTL34, .value_a = 0x0007, .value_g = 0x0007, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2062_S_RXG_CNT0, .value_a = 0x0010, .value_g = 0x0010, .flags = 0, }, */
+	/* { .offset = B2062_S_RXG_CNT1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_RXG_CNT2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_RXG_CNT3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_RXG_CNT4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_RXG_CNT5, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
+	/* { .offset = B2062_S_RXG_CNT6, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
+	/* { .offset = B2062_S_RXG_CNT7, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */
+	{ .offset = B2062_S_RXG_CNT8, .value_a = 0x000F, .value_g = 0x000F, .flags = B206X_FLAG_A, },
+	/* { .offset = B2062_S_RXG_CNT9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_RXG_CNT10, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
+	/* { .offset = B2062_S_RXG_CNT11, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+	/* { .offset = B2062_S_RXG_CNT12, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
+	/* { .offset = B2062_S_RXG_CNT13, .value_a = 0x0044, .value_g = 0x0044, .flags = 0, }, */
+	/* { .offset = B2062_S_RXG_CNT14, .value_a = 0x00A0, .value_g = 0x00A0, .flags = 0, }, */
+	/* { .offset = B2062_S_RXG_CNT15, .value_a = 0x0004, .value_g = 0x0004, .flags = 0, }, */
+	/* { .offset = B2062_S_RXG_CNT16, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2062_S_RXG_CNT17, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
+};
+
+static const struct b206x_init_tab_entry b2063_init_tab[] = {
+	{ .offset = B2063_COMM1, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
+	/* { .offset = B2063_COMM2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_COMM3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_COMM4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_COMM5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_COMM6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_COMM7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_COMM8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_COMM9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2063_COMM10, .value_a = 0x0001, .value_g = 0x0000, .flags = B206X_FLAG_A, },
+	/* { .offset = B2063_COMM11, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_COMM12, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_COMM13, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_COMM14, .value_a = 0x0006, .value_g = 0x0006, .flags = 0, }, */
+	/* { .offset = B2063_COMM15, .value_a = 0x000f, .value_g = 0x000f, .flags = 0, }, */
+	{ .offset = B2063_COMM16, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
+	{ .offset = B2063_COMM17, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
+	{ .offset = B2063_COMM18, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
+	{ .offset = B2063_COMM19, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
+	{ .offset = B2063_COMM20, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
+	{ .offset = B2063_COMM21, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
+	{ .offset = B2063_COMM22, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
+	{ .offset = B2063_COMM23, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
+	{ .offset = B2063_COMM24, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
+	/* { .offset = B2063_PWR_SWITCH_CTL, .value_a = 0x007f, .value_g = 0x007f, .flags = 0, }, */
+	/* { .offset = B2063_PLL_SP1, .value_a = 0x003f, .value_g = 0x003f, .flags = 0, }, */
+	/* { .offset = B2063_PLL_SP2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2063_LOGEN_SP1, .value_a = 0x00e8, .value_g = 0x00d4, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2063_LOGEN_SP2, .value_a = 0x00a7, .value_g = 0x0053, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2063_LOGEN_SP3, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
+	{ .offset = B2063_LOGEN_SP4, .value_a = 0x00f0, .value_g = 0x000f, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2063_LOGEN_SP5, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
+	{ .offset = B2063_G_RX_SP1, .value_a = 0x001f, .value_g = 0x005e, .flags = B206X_FLAG_G, },
+	{ .offset = B2063_G_RX_SP2, .value_a = 0x007f, .value_g = 0x007e, .flags = B206X_FLAG_G, },
+	{ .offset = B2063_G_RX_SP3, .value_a = 0x0030, .value_g = 0x00f0, .flags = B206X_FLAG_G, },
+	/* { .offset = B2063_G_RX_SP4, .value_a = 0x0035, .value_g = 0x0035, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_SP5, .value_a = 0x003f, .value_g = 0x003f, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_SP6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2063_G_RX_SP7, .value_a = 0x007f, .value_g = 0x007f, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2063_G_RX_SP8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_SP9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2063_G_RX_SP10, .value_a = 0x000c, .value_g = 0x000c, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2063_G_RX_SP11, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2063_A_RX_SP1, .value_a = 0x003c, .value_g = 0x003f, .flags = B206X_FLAG_A, },
+	{ .offset = B2063_A_RX_SP2, .value_a = 0x00fc, .value_g = 0x00fe, .flags = B206X_FLAG_A, },
+	/* { .offset = B2063_A_RX_SP3, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_SP4, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_SP5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_SP6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2063_A_RX_SP7, .value_a = 0x0008, .value_g = 0x0008, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2063_RX_BB_SP1, .value_a = 0x000f, .value_g = 0x000f, .flags = 0, }, */
+	/* { .offset = B2063_RX_BB_SP2, .value_a = 0x0022, .value_g = 0x0022, .flags = 0, }, */
+	/* { .offset = B2063_RX_BB_SP3, .value_a = 0x00a8, .value_g = 0x00a8, .flags = 0, }, */
+	{ .offset = B2063_RX_BB_SP4, .value_a = 0x0060, .value_g = 0x0060, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2063_RX_BB_SP5, .value_a = 0x0011, .value_g = 0x0011, .flags = 0, }, */
+	/* { .offset = B2063_RX_BB_SP6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_RX_BB_SP7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2063_RX_BB_SP8, .value_a = 0x0030, .value_g = 0x0030, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2063_TX_RF_SP1, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_SP2, .value_a = 0x0003, .value_g = 0x0003, .flags = 0, }, */
+	{ .offset = B2063_TX_RF_SP3, .value_a = 0x000c, .value_g = 0x000b, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2063_TX_RF_SP4, .value_a = 0x0010, .value_g = 0x000f, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2063_TX_RF_SP5, .value_a = 0x000f, .value_g = 0x000f, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_SP6, .value_a = 0x0080, .value_g = 0x0080, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_SP7, .value_a = 0x0068, .value_g = 0x0068, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_SP8, .value_a = 0x0068, .value_g = 0x0068, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_SP9, .value_a = 0x0080, .value_g = 0x0080, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_SP10, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_SP11, .value_a = 0x0003, .value_g = 0x0003, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_SP12, .value_a = 0x0038, .value_g = 0x0038, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_SP13, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_SP14, .value_a = 0x0038, .value_g = 0x0038, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_SP15, .value_a = 0x00c0, .value_g = 0x00c0, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_SP16, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_SP17, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
+	{ .offset = B2063_PA_SP1, .value_a = 0x003d, .value_g = 0x00fd, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2063_PA_SP2, .value_a = 0x000c, .value_g = 0x000c, .flags = 0, }, */
+	/* { .offset = B2063_PA_SP3, .value_a = 0x0096, .value_g = 0x0096, .flags = 0, }, */
+	/* { .offset = B2063_PA_SP4, .value_a = 0x005a, .value_g = 0x005a, .flags = 0, }, */
+	/* { .offset = B2063_PA_SP5, .value_a = 0x007f, .value_g = 0x007f, .flags = 0, }, */
+	/* { .offset = B2063_PA_SP6, .value_a = 0x007f, .value_g = 0x007f, .flags = 0, }, */
+	/* { .offset = B2063_PA_SP7, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
+	{ .offset = B2063_TX_BB_SP1, .value_a = 0x0002, .value_g = 0x0002, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2063_TX_BB_SP2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_TX_BB_SP3, .value_a = 0x0030, .value_g = 0x0030, .flags = 0, }, */
+	/* { .offset = B2063_REG_SP1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2063_BANDGAP_CTL1, .value_a = 0x0056, .value_g = 0x0056, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2063_BANDGAP_CTL2, .value_a = 0x0006, .value_g = 0x0006, .flags = 0, }, */
+	/* { .offset = B2063_LPO_CTL1, .value_a = 0x000e, .value_g = 0x000e, .flags = 0, }, */
+	/* { .offset = B2063_RC_CALIB_CTL1, .value_a = 0x007e, .value_g = 0x007e, .flags = 0, }, */
+	/* { .offset = B2063_RC_CALIB_CTL2, .value_a = 0x0015, .value_g = 0x0015, .flags = 0, }, */
+	/* { .offset = B2063_RC_CALIB_CTL3, .value_a = 0x000f, .value_g = 0x000f, .flags = 0, }, */
+	/* { .offset = B2063_RC_CALIB_CTL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_RC_CALIB_CTL5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_RC_CALIB_CTL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_RC_CALIB_CTL7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_RC_CALIB_CTL8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_RC_CALIB_CTL9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_RC_CALIB_CTL10, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_CALNRST, .value_a = 0x0004, .value_g = 0x0004, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_IN_PLL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_IN_PLL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_CP1, .value_a = 0x00cf, .value_g = 0x00cf, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_CP2, .value_a = 0x0059, .value_g = 0x0059, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_CP3, .value_a = 0x0007, .value_g = 0x0007, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_CP4, .value_a = 0x0042, .value_g = 0x0042, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_LF1, .value_a = 0x00db, .value_g = 0x00db, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_LF2, .value_a = 0x0094, .value_g = 0x0094, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_LF3, .value_a = 0x0028, .value_g = 0x0028, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_LF4, .value_a = 0x0063, .value_g = 0x0063, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_SG1, .value_a = 0x0007, .value_g = 0x0007, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_SG2, .value_a = 0x00d3, .value_g = 0x00d3, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_SG3, .value_a = 0x00b1, .value_g = 0x00b1, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_SG4, .value_a = 0x003b, .value_g = 0x003b, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_SG5, .value_a = 0x0006, .value_g = 0x0006, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_VCO1, .value_a = 0x0058, .value_g = 0x0058, .flags = 0, }, */
+	{ .offset = B2063_PLL_JTAG_PLL_VCO2, .value_a = 0x00f7, .value_g = 0x00f7, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB3, .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB5, .value_a = 0x0009, .value_g = 0x0009, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB6, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB7, .value_a = 0x0016, .value_g = 0x0016, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB8, .value_a = 0x006b, .value_g = 0x006b, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB10, .value_a = 0x00b3, .value_g = 0x00b3, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_XTAL_12, .value_a = 0x0004, .value_g = 0x0004, .flags = 0, }, */
+	/* { .offset = B2063_PLL_JTAG_PLL_XTAL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_ACL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_ACL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_ACL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_ACL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_ACL5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LO_CALIB_INPUTS, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LO_CALIB_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LO_CALIB_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LO_CALIB_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LO_CALIB_WAITCNT, .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */
+	/* { .offset = B2063_LO_CALIB_OVR1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LO_CALIB_OVR2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LO_CALIB_OVAL1, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+	/* { .offset = B2063_LO_CALIB_OVAL2, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+	/* { .offset = B2063_LO_CALIB_OVAL3, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+	/* { .offset = B2063_LO_CALIB_OVAL4, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+	/* { .offset = B2063_LO_CALIB_OVAL5, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+	/* { .offset = B2063_LO_CALIB_OVAL6, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+	/* { .offset = B2063_LO_CALIB_OVAL7, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+	/* { .offset = B2063_LO_CALIB_CALVLD1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LO_CALIB_CALVLD2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LO_CALIB_CVAL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LO_CALIB_CVAL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LO_CALIB_CVAL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LO_CALIB_CVAL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LO_CALIB_CVAL5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LO_CALIB_CVAL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LO_CALIB_CVAL7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_CALIB_EN, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_PEAKDET1, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_RCCR1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_VCOBUF1, .value_a = 0x0060, .value_g = 0x0060, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_MIXER1, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_MIXER2, .value_a = 0x000c, .value_g = 0x000c, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_BUF1, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_BUF2, .value_a = 0x000c, .value_g = 0x000c, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_DIV1, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_DIV2, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_DIV3, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_CBUFRX1, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_CBUFRX2, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_CBUFTX1, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_CBUFTX2, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_IDAC1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_SPARE1, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_SPARE2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_LOGEN_SPARE3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_1ST1, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_1ST2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_1ST3, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_2ND1, .value_a = 0x0030, .value_g = 0x0030, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_2ND2, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_2ND3, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_2ND4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_2ND5, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_2ND6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_2ND7, .value_a = 0x0035, .value_g = 0x0035, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_2ND8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_PS1, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_PS2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_PS3, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_PS4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_PS5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_MIX1, .value_a = 0x0044, .value_g = 0x0044, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_MIX2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2063_G_RX_MIX3, .value_a = 0x0071, .value_g = 0x0071, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2063_G_RX_MIX4, .value_a = 0x0071, .value_g = 0x0071, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2063_G_RX_MIX5, .value_a = 0x0003, .value_g = 0x0003, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_MIX6, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_MIX7, .value_a = 0x0044, .value_g = 0x0044, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_MIX8, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_PDET1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_SPARES1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_SPARES2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_G_RX_SPARES3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_1ST1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2063_A_RX_1ST2, .value_a = 0x00f0, .value_g = 0x0030, .flags = B206X_FLAG_A, },
+	/* { .offset = B2063_A_RX_1ST3, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_1ST4, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_1ST5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_2ND1, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_2ND2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_2ND3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_2ND4, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_2ND5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_2ND6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_2ND7, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_PS1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_PS2, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_PS3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_PS4, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_PS5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2063_A_RX_PS6, .value_a = 0x0077, .value_g = 0x0077, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2063_A_RX_MIX1, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_MIX2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_MIX3, .value_a = 0x0044, .value_g = 0x0044, .flags = 0, }, */
+	{ .offset = B2063_A_RX_MIX4, .value_a = 0x0003, .value_g = 0x0003, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2063_A_RX_MIX5, .value_a = 0x000f, .value_g = 0x000f, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	{ .offset = B2063_A_RX_MIX6, .value_a = 0x000f, .value_g = 0x000f, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2063_A_RX_MIX7, .value_a = 0x0044, .value_g = 0x0044, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_MIX8, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_PWRDET1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_SPARE1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_SPARE2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_A_RX_SPARE3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2063_RX_TIA_CTL1, .value_a = 0x0077, .value_g = 0x0077, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2063_RX_TIA_CTL2, .value_a = 0x0058, .value_g = 0x0058, .flags = 0, }, */
+	{ .offset = B2063_RX_TIA_CTL3, .value_a = 0x0077, .value_g = 0x0077, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2063_RX_TIA_CTL4, .value_a = 0x0058, .value_g = 0x0058, .flags = 0, }, */
+	/* { .offset = B2063_RX_TIA_CTL5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_RX_TIA_CTL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_RX_BB_CTL1, .value_a = 0x0074, .value_g = 0x0074, .flags = 0, }, */
+	{ .offset = B2063_RX_BB_CTL2, .value_a = 0x0004, .value_g = 0x0004, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2063_RX_BB_CTL3, .value_a = 0x00a2, .value_g = 0x00a2, .flags = 0, }, */
+	/* { .offset = B2063_RX_BB_CTL4, .value_a = 0x00aa, .value_g = 0x00aa, .flags = 0, }, */
+	/* { .offset = B2063_RX_BB_CTL5, .value_a = 0x0024, .value_g = 0x0024, .flags = 0, }, */
+	/* { .offset = B2063_RX_BB_CTL6, .value_a = 0x00a9, .value_g = 0x00a9, .flags = 0, }, */
+	/* { .offset = B2063_RX_BB_CTL7, .value_a = 0x0028, .value_g = 0x0028, .flags = 0, }, */
+	/* { .offset = B2063_RX_BB_CTL8, .value_a = 0x0010, .value_g = 0x0010, .flags = 0, }, */
+	/* { .offset = B2063_RX_BB_CTL9, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_CTL1, .value_a = 0x0080, .value_g = 0x0080, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_IDAC_LO_RF_I, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_IDAC_LO_RF_Q, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_IDAC_LO_BB_I, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_IDAC_LO_BB_Q, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_CTL2, .value_a = 0x0080, .value_g = 0x0080, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_CTL3, .value_a = 0x0038, .value_g = 0x0038, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_CTL4, .value_a = 0x00b8, .value_g = 0x00b8, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_CTL5, .value_a = 0x0080, .value_g = 0x0080, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_CTL6, .value_a = 0x0038, .value_g = 0x0038, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_CTL7, .value_a = 0x0078, .value_g = 0x0078, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_CTL8, .value_a = 0x00c0, .value_g = 0x00c0, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_CTL9, .value_a = 0x0003, .value_g = 0x0003, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_CTL10, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_CTL14, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_TX_RF_CTL15, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2063_PA_CTL1, .value_a = 0x0000, .value_g = 0x0004, .flags = B206X_FLAG_A, },
+	/* { .offset = B2063_PA_CTL2, .value_a = 0x000c, .value_g = 0x000c, .flags = 0, }, */
+	/* { .offset = B2063_PA_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_PA_CTL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_PA_CTL5, .value_a = 0x0096, .value_g = 0x0096, .flags = 0, }, */
+	/* { .offset = B2063_PA_CTL6, .value_a = 0x0077, .value_g = 0x0077, .flags = 0, }, */
+	/* { .offset = B2063_PA_CTL7, .value_a = 0x005a, .value_g = 0x005a, .flags = 0, }, */
+	/* { .offset = B2063_PA_CTL8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_PA_CTL9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_PA_CTL10, .value_a = 0x0021, .value_g = 0x0021, .flags = 0, }, */
+	/* { .offset = B2063_PA_CTL11, .value_a = 0x0070, .value_g = 0x0070, .flags = 0, }, */
+	/* { .offset = B2063_PA_CTL12, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_PA_CTL13, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_TX_BB_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_TX_BB_CTL2, .value_a = 0x00b3, .value_g = 0x00b3, .flags = 0, }, */
+	/* { .offset = B2063_TX_BB_CTL3, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
+	/* { .offset = B2063_TX_BB_CTL4, .value_a = 0x000b, .value_g = 0x000b, .flags = 0, }, */
+	/* { .offset = B2063_GPIO_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	{ .offset = B2063_VREG_CTL1, .value_a = 0x0003, .value_g = 0x0003, .flags = B206X_FLAG_A | B206X_FLAG_G, },
+	/* { .offset = B2063_AMUX_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_IQ_CALIB_GVAR, .value_a = 0x00b3, .value_g = 0x00b3, .flags = 0, }, */
+	/* { .offset = B2063_IQ_CALIB_CTL1, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
+	/* { .offset = B2063_IQ_CALIB_CTL2, .value_a = 0x0030, .value_g = 0x0030, .flags = 0, }, */
+	/* { .offset = B2063_TEMPSENSE_CTL1, .value_a = 0x0046, .value_g = 0x0046, .flags = 0, }, */
+	/* { .offset = B2063_TEMPSENSE_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_TX_RX_LOOPBACK1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_TX_RX_LOOPBACK2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
+	/* { .offset = B2063_EXT_TSSI_CTL1, .value_a = 0x0021, .value_g = 0x0021, .flags = 0, }, */
+	/* { .offset = B2063_EXT_TSSI_CTL2, .value_a = 0x0023, .value_g = 0x0023, .flags = 0, }, */
+	/* { .offset = B2063_AFE_CTL , .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */
+};
+
+void b2062_upload_init_table(struct b43_wldev *dev)
+{
+	const struct b206x_init_tab_entry *e;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(b2062_init_tab); i++) {
+		e = &b2062_init_tab[i];
+		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+			if (!(e->flags & B206X_FLAG_G))
+				continue;
+			b43_radio_write(dev, e->offset, e->value_g);
+		} else {
+			if (!(e->flags & B206X_FLAG_A))
+				continue;
+			b43_radio_write(dev, e->offset, e->value_a);
+		}
+	}
+}
+
+void b2063_upload_init_table(struct b43_wldev *dev)
+{
+	const struct b206x_init_tab_entry *e;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(b2063_init_tab); i++) {
+		e = &b2063_init_tab[i];
+		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+			if (!(e->flags & B206X_FLAG_G))
+				continue;
+			b43_radio_write(dev, e->offset, e->value_g);
+		} else {
+			if (!(e->flags & B206X_FLAG_A))
+				continue;
+			b43_radio_write(dev, e->offset, e->value_a);
+		}
+	}
+}
+
+u32 b43_lptab_read(struct b43_wldev *dev, u32 offset)
+{
+	u32 type, value;
+
+	type = offset & B43_LPTAB_TYPEMASK;
+	offset &= ~B43_LPTAB_TYPEMASK;
+	B43_WARN_ON(offset > 0xFFFF);
+
+	switch (type) {
+	case B43_LPTAB_8BIT:
+		b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset);
+		value = b43_phy_read(dev, B43_LPPHY_TABLEDATALO) & 0xFF;
+		break;
+	case B43_LPTAB_16BIT:
+		b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset);
+		value = b43_phy_read(dev, B43_LPPHY_TABLEDATALO);
+		break;
+	case B43_LPTAB_32BIT:
+		b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset);
+		value = b43_phy_read(dev, B43_LPPHY_TABLEDATAHI);
+		value <<= 16;
+		value |= b43_phy_read(dev, B43_LPPHY_TABLEDATALO);
+		break;
+	default:
+		B43_WARN_ON(1);
+		value = 0;
+	}
+
+	return value;
+}
+
+void b43_lptab_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_LPTAB_TYPEMASK;
+	offset &= ~B43_LPTAB_TYPEMASK;
+	B43_WARN_ON(offset > 0xFFFF);
+
+	b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset);
+
+	for (i = 0; i < nr_elements; i++) {
+		switch (type) {
+		case B43_LPTAB_8BIT:
+			*data = b43_phy_read(dev, B43_LPPHY_TABLEDATALO) & 0xFF;
+			data++;
+			break;
+		case B43_LPTAB_16BIT:
+			*((u16 *)data) = b43_phy_read(dev, B43_LPPHY_TABLEDATALO);
+			data += 2;
+			break;
+		case B43_LPTAB_32BIT:
+			*((u32 *)data) = b43_phy_read(dev, B43_LPPHY_TABLEDATAHI);
+			*((u32 *)data) <<= 16;
+			*((u32 *)data) |= b43_phy_read(dev, B43_LPPHY_TABLEDATALO);
+			data += 4;
+			break;
+		default:
+			B43_WARN_ON(1);
+		}
+	}
+}
+
+void b43_lptab_write(struct b43_wldev *dev, u32 offset, u32 value)
+{
+	u32 type;
+
+	type = offset & B43_LPTAB_TYPEMASK;
+	offset &= ~B43_LPTAB_TYPEMASK;
+	B43_WARN_ON(offset > 0xFFFF);
+
+	switch (type) {
+	case B43_LPTAB_8BIT:
+		B43_WARN_ON(value & ~0xFF);
+		b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset);
+		b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value);
+		break;
+	case B43_LPTAB_16BIT:
+		B43_WARN_ON(value & ~0xFFFF);
+		b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset);
+		b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value);
+		break;
+	case B43_LPTAB_32BIT:
+		b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset);
+		b43_phy_write(dev, B43_LPPHY_TABLEDATAHI, value >> 16);
+		b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value);
+		break;
+	default:
+		B43_WARN_ON(1);
+	}
+}
+
+void b43_lptab_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_LPTAB_TYPEMASK;
+	offset &= ~B43_LPTAB_TYPEMASK;
+	B43_WARN_ON(offset > 0xFFFF);
+
+	b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset);
+
+	for (i = 0; i < nr_elements; i++) {
+		switch (type) {
+		case B43_LPTAB_8BIT:
+			value = *data;
+			data++;
+			B43_WARN_ON(value & ~0xFF);
+			b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value);
+			break;
+		case B43_LPTAB_16BIT:
+			value = *((u16 *)data);
+			data += 2;
+			B43_WARN_ON(value & ~0xFFFF);
+			b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value);
+			break;
+		case B43_LPTAB_32BIT:
+			value = *((u32 *)data);
+			data += 4;
+			b43_phy_write(dev, B43_LPPHY_TABLEDATAHI, value >> 16);
+			b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value);
+			break;
+		default:
+			B43_WARN_ON(1);
+		}
+	}
+}
+
+static const u8 lpphy_min_sig_sq_table[] = {
+	0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
+	0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
+	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
+	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
+	0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
+	0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
+};
+
+static const u16 lpphy_rev01_noise_scale_table[] = {
+	0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
+	0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
+	0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0x00a4,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4c00, 0x2d36,
+	0x0000, 0x0000, 0x4c00, 0x2d36,
+};
+
+static const u16 lpphy_rev2plus_noise_scale_table[] = {
+	0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
+	0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
+	0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x0000,
+	0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
+	0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
+	0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
+	0x00a4,
+};
+
+static const u16 lpphy_crs_gain_nft_table[] = {
+	0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f, 0x036f,
+	0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381, 0x0374, 0x0381,
+	0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f, 0x0040, 0x005e, 0x007f,
+	0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d, 0x013d,
+};
+
+static const u16 lpphy_rev01_filter_control_table[] = {
+	0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077, 0xff53,
+	0x0127,
+};
+
+static const u32 lpphy_rev2plus_filter_control_table[] = {
+	0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27, 0x0000217f,
+	0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f,
+};
+
+static const u32 lpphy_rev01_ps_control_table[] = {
+	0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101, 0x00000080,
+	0x08080101, 0x00000040, 0x08080101, 0x000000c0, 0x08a81501, 0x000000c0,
+	0x0fe8fd01, 0x000000c0, 0x08300105, 0x000000c0, 0x08080201, 0x000000c0,
+	0x08280205, 0x000000c0, 0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0,
+	0x08080202, 0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
+	0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106, 0x000000c0,
+	0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
+};
+
+static const u32 lpphy_rev2plus_ps_control_table[] = {
+	0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000, 0x00002080,
+	0x00006180, 0x00003002, 0x00000040, 0x00002042, 0x00180047, 0x00080043,
+	0x00000041, 0x000020c1, 0x00046006, 0x00042002, 0x00040000, 0x00002003,
+	0x00180006, 0x00080002,
+};
+
+static const u8 lpphy_pll_fraction_table[] = {
+	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
+	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+};
+
+static const u16 lpphy_iqlo_cal_table[] = {
+	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
+	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
+	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
+	0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+static const u16 lpphy_rev0_ofdm_cck_gain_table[] = {
+	0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001, 0x5001,
+	0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055, 0x2065, 0x2075,
+	0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d, 0x135d, 0x055d, 0x155d,
+	0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d, 0x755d,
+};
+
+static const u16 lpphy_rev1_ofdm_cck_gain_table[] = {
+	0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001, 0x5001,
+	0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055, 0x2065, 0x2075,
+	0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d, 0x135d, 0x055d, 0x155d,
+	0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d, 0x755d,
+};
+
+static const u16 lpphy_gain_delta_table[] = {
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+static const u32 lpphy_tx_power_control_table[] = {
+	0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c, 0x0000004b,
+	0x0000004a, 0x00000049, 0x00000048, 0x00000047, 0x00000046, 0x00000045,
+	0x00000044, 0x00000043, 0x00000042, 0x00000041, 0x00000040, 0x0000003f,
+	0x0000003e, 0x0000003d, 0x0000003c, 0x0000003b, 0x0000003a, 0x00000039,
+	0x00000038, 0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
+	0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e, 0x0000002d,
+	0x0000002c, 0x0000002b, 0x0000002a, 0x00000029, 0x00000028, 0x00000027,
+	0x00000026, 0x00000025, 0x00000024, 0x00000023, 0x00000022, 0x00000021,
+	0x00000020, 0x0000001f, 0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b,
+	0x0000001a, 0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
+	0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x000075a0, 0x000075a0, 0x000075a1, 0x000075a1, 0x000075a2, 0x000075a2,
+	0x000075a3, 0x000075a3, 0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1,
+	0x000074b2, 0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
+	0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23, 0x00006d23,
+	0x00004660, 0x00004660, 0x00004661, 0x00004661, 0x00004662, 0x00004662,
+	0x00004663, 0x00004663, 0x00003e60, 0x00003e60, 0x00003e61, 0x00003e61,
+	0x00003e62, 0x00003e62, 0x00003e63, 0x00003e63, 0x00003660, 0x00003660,
+	0x00003661, 0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
+	0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62, 0x00002e62,
+	0x00002e63, 0x00002e63, 0x00002660, 0x00002660, 0x00002661, 0x00002661,
+	0x00002662, 0x00002662, 0x00002663, 0x00002663, 0x000025e0, 0x000025e0,
+	0x000025e1, 0x000025e1, 0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3,
+	0x00001de0, 0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
+	0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61, 0x00001d61,
+	0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63, 0x00001560, 0x00001560,
+	0x00001561, 0x00001561, 0x00001562, 0x00001562, 0x00001563, 0x00001563,
+	0x00000d60, 0x00000d60, 0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62,
+	0x00000d63, 0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
+	0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10, 0x00000e10,
+	0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12, 0x00000e13, 0x00000e13,
+	0x00000bf0, 0x00000bf0, 0x00000bf1, 0x00000bf1, 0x00000bf2, 0x00000bf2,
+	0x00000bf3, 0x00000bf3, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+	0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+	0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+	0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+	0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+	0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+	0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+	0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+	0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+	0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+	0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+	0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+	0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+	0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+	0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+	0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+	0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+	0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+	0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+	0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+	0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
+	0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
+	0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04, 0x0000fcff,
+	0x000005fb, 0x0000fd01, 0x00000401, 0x00000006, 0x0000ff03, 0x000007fc,
+	0x0000fc08, 0x00000203, 0x0000fffb, 0x00000600, 0x0000fa01, 0x0000fc03,
+	0x0000fe06, 0x0000fe00, 0x00000102, 0x000007fd, 0x000004fb, 0x000006ff,
+	0x000004fd, 0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
+	0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa, 0x00000700,
+	0x00000305, 0x000004ff, 0x00000801, 0x00000503, 0x000005f9, 0x00000404,
+	0x0000fb08, 0x000005fd, 0x00000501, 0x00000405, 0x0000fb03, 0x000007fc,
+	0x00000403, 0x00000303, 0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd,
+	0x0000fe01, 0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
+	0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa, 0x000003fe,
+	0x00000304, 0x000004f9, 0x00000100, 0x0000fd06, 0x000008fc, 0x00000701,
+	0x00000504, 0x0000fdfe, 0x0000fdfc, 0x000003fe, 0x00000704, 0x000002fc,
+	0x000004f9, 0x0000fdfd, 0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb,
+	0x000004f9, 0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
+	0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa, 0x00000305,
+	0x000008fc, 0x00000102, 0x000001fd, 0x000004fc, 0x0000fe03, 0x00000701,
+	0x000001fb, 0x000001f9, 0x00000206, 0x000006fd, 0x00000508, 0x00000700,
+	0x00000304, 0x000005fe, 0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb,
+	0x000007f9, 0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
+	0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb, 0x00000702,
+};
+
+static const u32 lpphy_gain_idx_table[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x10000001, 0x00000000, 0x20000082, 0x00000000, 0x40000104, 0x00000000,
+	0x60004207, 0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
+	0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
+	0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711, 0x00000001,
+	0xb0a18612, 0x00000010, 0xe1024794, 0x00000010, 0x11630915, 0x00000011,
+	0x31c3ca1b, 0x00000011, 0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018,
+	0x22468e21, 0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
+	0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
+	0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c, 0x0000001a,
+	0x64ca55ad, 0x0000001a, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082, 0x00000000,
+	0x40000104, 0x00000000, 0x60004207, 0x00000001, 0x7000838a, 0x00000001,
+	0xd021050d, 0x00000001, 0xe041c683, 0x00000001, 0x50828805, 0x00000000,
+	0x80e34288, 0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
+	0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
+	0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c, 0x00000018,
+	0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019, 0x4286d023, 0x00000019,
+	0xa347d0a4, 0x00000019, 0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019,
+	0x0408d329, 0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
+	0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a,
+};
+
+static const u16 lpphy_aux_gain_idx_table[] = {
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0004, 0x0016,
+};
+
+static const u32 lpphy_gain_value_table[] = {
+	0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb, 0x00000004,
+	0x00000008, 0x0000000d, 0x00000001, 0x00000004, 0x00000007, 0x0000000a,
+	0x0000000d, 0x00000010, 0x00000012, 0x00000015, 0x00000000, 0x00000006,
+	0x0000000c, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000,
+	0x00000000, 0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x0000001e, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000003, 0x00000006, 0x00000009, 0x0000000c, 0x0000000f,
+	0x00000012, 0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009, 0x000000f1,
+	0x00000000, 0x00000000,
+};
+
+static const u16 lpphy_gain_table[] = {
+	0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808, 0x080a,
+	0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813, 0x0814, 0x0816,
+	0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824, 0x0830, 0x0834, 0x0837,
+	0x083b, 0x083f, 0x0840, 0x0844, 0x0857, 0x085b, 0x085f, 0x08d7, 0x08db,
+	0x08df, 0x0957, 0x095b, 0x095f, 0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f,
+	0x175f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	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 lpphy_a0_gain_idx_table[] = {
+	0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060, 0x00511065,
+	0x004c806b, 0x0047d072, 0x00444078, 0x00400080, 0x003ca087, 0x0039408f,
+	0x0035e098, 0x0032e0a1, 0x003030aa, 0x002d80b4, 0x002ae0bf, 0x002880ca,
+	0x002640d6, 0x002410e3, 0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e,
+	0x001b012f, 0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
+	0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a, 0x000e523a,
+	0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd, 0x000ac2f8, 0x000a2325,
+	0x00099355, 0x00091387, 0x000883bd, 0x000813f5, 0x0007a432, 0x00073471,
+	0x0006c4b5, 0x000664fc, 0x00061547, 0x0005b598, 0x000565ec, 0x00051646,
+	0x0004d6a5, 0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
+	0x00036963, 0x000339f2, 0x00030a89, 0x0002db28,
+};
+
+static const u16 lpphy_a0_aux_gain_idx_table[] = {
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0014,
+};
+
+static const u32 lpphy_a0_gain_value_table[] = {
+	0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb, 0x00000004,
+	0x00000008, 0x0000000d, 0x00000001, 0x00000004, 0x00000007, 0x0000000a,
+	0x0000000d, 0x00000010, 0x00000012, 0x00000015, 0x00000000, 0x00000006,
+	0x0000000c, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000,
+	0x00000000, 0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x0000001e, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000003, 0x00000006, 0x00000009, 0x0000000c, 0x0000000f,
+	0x00000012, 0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f, 0x000000f7,
+	0x00000000, 0x00000000,
+};
+
+static const u16 lpphy_a0_gain_table[] = {
+	0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b, 0x000c,
+	0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016, 0x0017, 0x001a,
+	0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034, 0x0037, 0x003b, 0x003f,
+	0x0040, 0x0044, 0x0057, 0x005b, 0x005f, 0x00d7, 0x00db, 0x00df, 0x0157,
+	0x015b, 0x015f, 0x0357, 0x035b, 0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	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 lpphy_sw_control_table[] = {
+	0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028, 0x0128,
+	0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028, 0x0009, 0x0009,
+	0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0018, 0x0018, 0x0018,
+	0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0128, 0x0128, 0x0009, 0x0009,
+	0x0028, 0x0028, 0x0028, 0x0028, 0x0128, 0x0128, 0x0009, 0x0009, 0x0028,
+	0x0028, 0x0028, 0x0028, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
+	0x0009, 0x0009, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
+	0x0018,
+};
+
+static const u8 lpphy_hf_table[] = {
+	0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
+	0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17,
+};
+
+static const u32 lpphy_papd_eps_table[] = {
+	0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9, 0x00021fdf,
+	0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7, 0x0004efc2, 0x00055fb5,
+	0x0005cfb0, 0x00063fa8, 0x00068fa3, 0x00071f98, 0x0007ef92, 0x00084f8b,
+	0x0008df82, 0x00097f77, 0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c,
+	0x000bff41, 0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
+	0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15, 0x00143f1c,
+	0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f, 0x001e6f7e, 0x0021cfa4,
+	0x0025bfd2, 0x002a2008, 0x002fb047, 0x00360090, 0x003d40e0, 0x0045c135,
+	0x004fb189, 0x005ae1d7, 0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf,
+	0x007ff2e3, 0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
+	0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506,
+};
+
+static const u32 lpphy_papd_mult_table[] = {
+	0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060, 0x00511065,
+	0x004c806b, 0x0047d072, 0x00444078, 0x00400080, 0x003ca087, 0x0039408f,
+	0x0035e098, 0x0032e0a1, 0x003030aa, 0x002d80b4, 0x002ae0bf, 0x002880ca,
+	0x002640d6, 0x002410e3, 0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e,
+	0x001b012f, 0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
+	0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a, 0x000e523a,
+	0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd, 0x000ac2f8, 0x000a2325,
+	0x00099355, 0x00091387, 0x000883bd, 0x000813f5, 0x0007a432, 0x00073471,
+	0x0006c4b5, 0x000664fc, 0x00061547, 0x0005b598, 0x000565ec, 0x00051646,
+	0x0004d6a5, 0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
+	0x00036963, 0x000339f2, 0x00030a89, 0x0002db28,
+};
+
+static struct lpphy_tx_gain_table_entry lpphy_rev0_nopa_tx_gain_table[] = {
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 152, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 147, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 143, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 139, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 135, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 131, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 128, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 124, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 121, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 117, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 114, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 111, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 107, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 104, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 101, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 99, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 96, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 93, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 90, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 88, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 85, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 83, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 81, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 78, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 76, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 74, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 72, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 72, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 71, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 69, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 67, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 65, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 58, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 65, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 58, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 71, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 69, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 67, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 65, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 58, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 56, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 72, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 72, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 72, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 72, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 73, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 71, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 69, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 67, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 65, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 72, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 65, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 73, },
+	{ .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 71, },
+};
+
+static struct lpphy_tx_gain_table_entry lpphy_rev0_2ghz_tx_gain_table[] = {
+	{ .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, },
+	{ .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, },
+	{ .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 60, },
+	{ .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 72, },
+	{ .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 70, },
+	{ .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 64, },
+	{ .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 62, },
+	{ .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 60, },
+	{ .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 72, },
+	{ .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, },
+	{ .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, },
+	{ .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, },
+	{ .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, },
+	{ .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, },
+	{ .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 72, },
+	{ .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, },
+	{ .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, },
+	{ .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, },
+	{ .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, },
+	{ .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 72, },
+	{ .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, },
+	{ .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, },
+	{ .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, },
+	{ .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, },
+	{ .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 73, },
+	{ .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 71, },
+	{ .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 69, },
+	{ .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 67, },
+	{ .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 65, },
+	{ .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 63, },
+	{ .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, },
+	{ .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 72, },
+	{ .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, },
+	{ .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 65, },
+	{ .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 63, },
+	{ .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, },
+	{ .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 73, },
+	{ .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 71, },
+	{ .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 69, },
+	{ .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 67, },
+	{ .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 65, },
+	{ .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 63, },
+	{ .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 61, },
+	{ .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 60, },
+	{ .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 72, },
+	{ .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 70, },
+	{ .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 64, },
+	{ .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 62, },
+	{ .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 60, },
+	{ .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 72, },
+	{ .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 70, },
+	{ .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 64, },
+	{ .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 62, },
+	{ .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 60, },
+	{ .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 70, },
+	{ .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 64, },
+	{ .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 63, },
+	{ .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 61, },
+	{ .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 71, },
+	{ .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 69, },
+	{ .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 67, },
+	{ .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 65, },
+	{ .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 63, },
+	{ .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 62, },
+	{ .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 60, },
+	{ .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 58, },
+	{ .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 70, },
+	{ .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 65, },
+	{ .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 63, },
+	{ .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 61, },
+	{ .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 64, },
+	{ .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 62, },
+	{ .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 61, },
+	{ .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 67, },
+	{ .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 65, },
+	{ .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 63, },
+	{ .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 62, },
+	{ .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 60, },
+	{ .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 65, },
+	{ .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 63, },
+	{ .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 61, },
+	{ .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 60, },
+	{ .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 58, },
+	{ .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 64, },
+	{ .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 62, },
+	{ .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 60, },
+	{ .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 57, },
+	{ .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 83, },
+	{ .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 81, },
+	{ .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 78, },
+	{ .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 76, },
+	{ .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 74, },
+	{ .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 72, },
+};
+
+static struct lpphy_tx_gain_table_entry lpphy_rev0_5ghz_tx_gain_table[] = {
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 99, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 96, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 93, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 90, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 88, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 85, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 83, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 81, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 78, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 76, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 74, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 72, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 55, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 72, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 58, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 56, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 55, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 71, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 69, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 67, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 65, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 58, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 56, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 72, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 73, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 71, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 69, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 67, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 65, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 58, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 71, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 69, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 67, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 65, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 58, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 56, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 65, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 58, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 69, },
+	{ .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 67, },
+	{ .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 65, },
+	{ .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 60, },
+};
+
+static struct lpphy_tx_gain_table_entry lpphy_rev1_nopa_tx_gain_table[] = {
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 152, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 147, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 143, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 139, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 135, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 131, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 128, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 124, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 121, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 117, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 114, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 111, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 107, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 104, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 101, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 99, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 96, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 93, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 90, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 88, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 85, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 83, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 81, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 78, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 76, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 74, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 72, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 72, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 72, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 71, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 69, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 67, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 65, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 58, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 65, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 58, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 71, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 69, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 67, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 65, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 58, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 56, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 72, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 72, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 72, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 72, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 73, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 71, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 69, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 67, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 65, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 72, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 65, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 73, },
+	{ .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 71, },
+};
+
+static struct lpphy_tx_gain_table_entry lpphy_rev1_2ghz_tx_gain_table[] = {
+	{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 90, },
+	{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 88, },
+	{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 85, },
+	{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 83, },
+	{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 81, },
+	{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 78, },
+	{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 76, },
+	{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 74, },
+	{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 72, },
+	{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 70, },
+	{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 64, },
+	{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 62, },
+	{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 60, },
+	{ .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 72, },
+	{ .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 70, },
+	{ .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 64, },
+	{ .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 62, },
+	{ .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 60, },
+	{ .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 72, },
+	{ .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 70, },
+	{ .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 64, },
+	{ .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 62, },
+	{ .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 60, },
+	{ .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 72, },
+	{ .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 70, },
+	{ .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 64, },
+	{ .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 62, },
+	{ .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 60, },
+	{ .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 72, },
+	{ .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 70, },
+	{ .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 64, },
+	{ .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 62, },
+	{ .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 60, },
+	{ .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 72, },
+	{ .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 70, },
+	{ .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 64, },
+	{ .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 62, },
+	{ .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 60, },
+	{ .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 72, },
+	{ .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 70, },
+	{ .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, },
+	{ .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, },
+	{ .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 60, },
+	{ .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 72, },
+	{ .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 70, },
+	{ .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 64, },
+	{ .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 62, },
+	{ .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 60, },
+	{ .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 72, },
+	{ .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, },
+	{ .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, },
+	{ .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, },
+	{ .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, },
+	{ .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, },
+	{ .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 72, },
+	{ .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, },
+	{ .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, },
+	{ .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, },
+	{ .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, },
+	{ .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 72, },
+	{ .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, },
+	{ .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, },
+	{ .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, },
+	{ .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, },
+	{ .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 73, },
+	{ .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 71, },
+	{ .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 69, },
+	{ .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 67, },
+	{ .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 65, },
+	{ .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 63, },
+	{ .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, },
+	{ .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 72, },
+	{ .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, },
+	{ .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 65, },
+	{ .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 63, },
+	{ .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, },
+	{ .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, },
+	{ .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 73, },
+	{ .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 71, },
+	{ .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 69, },
+	{ .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 67, },
+	{ .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 65, },
+	{ .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 63, },
+	{ .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 61, },
+	{ .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 60, },
+	{ .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 72, },
+	{ .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 70, },
+	{ .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 68, },
+	{ .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 66, },
+	{ .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 64, },
+	{ .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 62, },
+	{ .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 60, },
+};
+
+static struct lpphy_tx_gain_table_entry lpphy_rev1_5ghz_tx_gain_table[] = {
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 99, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 96, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 93, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 90, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 88, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 85, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 83, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 81, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 78, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 76, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 74, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 72, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 55, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 72, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 58, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 56, },
+	{ .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 55, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 71, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 69, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 67, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 65, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 58, },
+	{ .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 56, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 72, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 73, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 71, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 69, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 67, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 65, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 58, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 71, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 69, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 67, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 65, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 58, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 56, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 65, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 58, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, },
+	{ .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 57, },
+	{ .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 69, },
+	{ .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 67, },
+	{ .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 65, },
+	{ .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 63, },
+	{ .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 62, },
+	{ .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 60, },
+};
+
+static struct lpphy_tx_gain_table_entry lpphy_rev2_nopa_tx_gain_table[] = {
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 152, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 147, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 143, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 139, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 135, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 131, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 128, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 124, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 121, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 117, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 114, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 111, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 107, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 104, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 101, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 99, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 96, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 93, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 90, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 88, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 85, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 83, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 81, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 78, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 76, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 74, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 72, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 70, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 68, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 66, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 197, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 192, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 186, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 181, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 176, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 171, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 166, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 161, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 157, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 152, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 148, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 144, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 140, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 136, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 132, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 128, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 124, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 121, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 117, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 114, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 111, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 108, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 105, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 102, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 99, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 96, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 93, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 91, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 88, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 86, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 83, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 81, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 79, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 76, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 74, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 72, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 70, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 68, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 66, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 64, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 248, .pad = 64, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 248, .pad = 62, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 241, .pad = 62, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 241, .pad = 60, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 234, .pad = 60, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 234, .pad = 59, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 227, .pad = 59, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 227, .pad = 57, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 221, .pad = 57, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 221, .pad = 55, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 215, .pad = 55, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 215, .pad = 54, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 208, .pad = 54, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 208, .pad = 52, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 203, .pad = 52, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 203, .pad = 51, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 197, .pad = 51, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 197, .pad = 49, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 191, .pad = 49, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 191, .pad = 48, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 186, .pad = 48, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 186, .pad = 47, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 181, .pad = 47, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 181, .pad = 45, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 175, .pad = 45, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 175, .pad = 44, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 170, .pad = 44, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 170, .pad = 43, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 166, .pad = 43, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 166, .pad = 42, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 161, .pad = 42, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 161, .pad = 40, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 156, .pad = 40, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 156, .pad = 39, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 152, .pad = 39, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 152, .pad = 38, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 148, .pad = 38, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 148, .pad = 37, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 143, .pad = 37, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 143, .pad = 36, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 139, .pad = 36, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 139, .pad = 35, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 135, .pad = 35, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 135, .pad = 34, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 132, .pad = 34, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 132, .pad = 33, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 128, .pad = 33, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 128, .pad = 32, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 124, .pad = 32, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 124, .pad = 31, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 121, .pad = 31, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 121, .pad = 30, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 117, .pad = 30, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 117, .pad = 29, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 114, .pad = 29, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 114, .pad = 29, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 111, .pad = 29, .dac = 0, .bb_mult = 64, },
+};
+
+static struct lpphy_tx_gain_table_entry lpphy_rev2_2ghz_tx_gain_table[] = {
+	{ .gm = 7, .pga = 99, .pad = 255, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 96, .pad = 255, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 93, .pad = 255, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 90, .pad = 255, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 88, .pad = 255, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 85, .pad = 255, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 83, .pad = 255, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 81, .pad = 255, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 78, .pad = 255, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 76, .pad = 255, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 74, .pad = 255, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 72, .pad = 255, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 70, .pad = 255, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 68, .pad = 255, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 66, .pad = 255, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 64, .pad = 255, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 64, .pad = 255, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 62, .pad = 255, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 62, .pad = 248, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 60, .pad = 248, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 60, .pad = 241, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 59, .pad = 241, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 59, .pad = 234, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 57, .pad = 234, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 57, .pad = 227, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 55, .pad = 227, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 55, .pad = 221, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 54, .pad = 221, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 54, .pad = 215, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 52, .pad = 215, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 52, .pad = 208, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 51, .pad = 208, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 51, .pad = 203, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 49, .pad = 203, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 49, .pad = 197, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 48, .pad = 197, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 48, .pad = 191, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 47, .pad = 191, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 47, .pad = 186, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 45, .pad = 186, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 45, .pad = 181, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 44, .pad = 181, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 44, .pad = 175, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 43, .pad = 175, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 43, .pad = 170, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 42, .pad = 170, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 42, .pad = 166, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 40, .pad = 166, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 40, .pad = 161, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 39, .pad = 161, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 39, .pad = 156, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 38, .pad = 156, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 38, .pad = 152, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 37, .pad = 152, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 37, .pad = 148, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 36, .pad = 148, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 36, .pad = 143, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 35, .pad = 143, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 35, .pad = 139, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 34, .pad = 139, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 34, .pad = 135, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 33, .pad = 135, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 33, .pad = 132, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 32, .pad = 132, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 32, .pad = 128, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 31, .pad = 128, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 31, .pad = 124, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 30, .pad = 124, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 30, .pad = 121, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 29, .pad = 121, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 29, .pad = 117, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 29, .pad = 117, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 29, .pad = 114, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 28, .pad = 114, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 28, .pad = 111, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 27, .pad = 111, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 27, .pad = 108, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 26, .pad = 108, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 26, .pad = 104, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 25, .pad = 104, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 25, .pad = 102, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 25, .pad = 102, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 25, .pad = 99, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 24, .pad = 99, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 24, .pad = 96, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 23, .pad = 96, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 23, .pad = 93, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 23, .pad = 93, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 23, .pad = 90, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 22, .pad = 90, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 22, .pad = 88, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 21, .pad = 88, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 21, .pad = 85, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 21, .pad = 85, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 21, .pad = 83, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 20, .pad = 83, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 20, .pad = 81, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 20, .pad = 81, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 20, .pad = 78, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 19, .pad = 78, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 19, .pad = 76, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 19, .pad = 76, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 19, .pad = 74, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 18, .pad = 74, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 18, .pad = 72, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 18, .pad = 72, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 18, .pad = 70, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 17, .pad = 70, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 17, .pad = 68, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 17, .pad = 68, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 17, .pad = 66, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 16, .pad = 66, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 16, .pad = 64, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 16, .pad = 64, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 16, .pad = 62, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 15, .pad = 62, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 15, .pad = 60, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 15, .pad = 60, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 15, .pad = 59, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 14, .pad = 59, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 14, .pad = 57, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 14, .pad = 57, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 14, .pad = 55, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 14, .pad = 55, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 14, .pad = 54, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 13, .pad = 54, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 13, .pad = 52, .dac = 0, .bb_mult = 64, },
+	{ .gm = 7, .pga = 13, .pad = 52, .dac = 0, .bb_mult = 64, },
+};
+
+static struct lpphy_tx_gain_table_entry lpphy_rev2_5ghz_tx_gain_table[] = {
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 152, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 147, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 143, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 139, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 135, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 131, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 128, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 124, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 121, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 117, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 114, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 111, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 107, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 104, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 101, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 99, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 96, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 93, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 90, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 88, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 85, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 83, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 81, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 78, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 76, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 74, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 72, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 70, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 68, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 66, },
+	{ .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 248, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 241, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 234, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 227, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 221, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 215, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 208, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 197, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 191, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 186, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 181, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 175, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 170, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 166, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 161, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 156, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 152, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 148, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 143, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 139, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 135, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 132, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 128, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 124, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 121, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 117, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 114, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 111, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 108, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 104, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 102, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 99, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 96, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 93, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 90, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 88, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 85, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 83, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 81, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 78, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 76, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 74, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 72, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 70, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 68, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 66, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 64, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 64, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 255, .pad = 62, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 248, .pad = 62, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 248, .pad = 60, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 241, .pad = 60, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 241, .pad = 59, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 234, .pad = 59, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 234, .pad = 57, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 227, .pad = 57, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 227, .pad = 55, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 221, .pad = 55, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 221, .pad = 54, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 215, .pad = 54, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 215, .pad = 52, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 208, .pad = 52, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 208, .pad = 51, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 203, .pad = 51, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 203, .pad = 49, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 197, .pad = 49, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 197, .pad = 48, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 191, .pad = 48, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 191, .pad = 47, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 186, .pad = 47, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 186, .pad = 45, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 181, .pad = 45, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 181, .pad = 44, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 175, .pad = 44, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 175, .pad = 43, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 170, .pad = 43, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 170, .pad = 42, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 166, .pad = 42, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 166, .pad = 40, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 161, .pad = 40, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 161, .pad = 39, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 156, .pad = 39, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 156, .pad = 38, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 152, .pad = 38, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 152, .pad = 37, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 148, .pad = 37, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 148, .pad = 36, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 143, .pad = 36, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 143, .pad = 35, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 139, .pad = 35, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 139, .pad = 34, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 135, .pad = 34, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 135, .pad = 33, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 132, .pad = 33, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 132, .pad = 32, .dac = 0, .bb_mult = 64, },
+	{ .gm = 255, .pga = 128, .pad = 32, .dac = 0, .bb_mult = 64, },
+};
+
+void lpphy_rev0_1_table_init(struct b43_wldev *dev)
+{
+	B43_WARN_ON(dev->phy.rev >= 2);
+
+	b43_lptab_write_bulk(dev, B43_LPTAB8(2, 0),
+		ARRAY_SIZE(lpphy_min_sig_sq_table), lpphy_min_sig_sq_table);
+	b43_lptab_write_bulk(dev, B43_LPTAB16(1, 0),
+		ARRAY_SIZE(lpphy_rev01_noise_scale_table), lpphy_rev01_noise_scale_table);
+	b43_lptab_write_bulk(dev, B43_LPTAB16(14, 0),
+		ARRAY_SIZE(lpphy_crs_gain_nft_table), lpphy_crs_gain_nft_table);
+	b43_lptab_write_bulk(dev, B43_LPTAB16(8, 0),
+		ARRAY_SIZE(lpphy_rev01_filter_control_table), lpphy_rev01_filter_control_table);
+	b43_lptab_write_bulk(dev, B43_LPTAB32(9, 0),
+		ARRAY_SIZE(lpphy_rev01_ps_control_table), lpphy_rev01_ps_control_table);
+	b43_lptab_write_bulk(dev, B43_LPTAB8(6, 0),
+		ARRAY_SIZE(lpphy_pll_fraction_table), lpphy_pll_fraction_table);
+	b43_lptab_write_bulk(dev, B43_LPTAB16(0, 0),
+		ARRAY_SIZE(lpphy_iqlo_cal_table), lpphy_iqlo_cal_table);
+	if (dev->phy.rev == 0) {
+		b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0),
+			ARRAY_SIZE(lpphy_rev0_ofdm_cck_gain_table), lpphy_rev0_ofdm_cck_gain_table);
+		b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0),
+			ARRAY_SIZE(lpphy_rev0_ofdm_cck_gain_table), lpphy_rev0_ofdm_cck_gain_table);
+	} else {
+		b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0),
+			ARRAY_SIZE(lpphy_rev1_ofdm_cck_gain_table), lpphy_rev1_ofdm_cck_gain_table);
+		b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0),
+			ARRAY_SIZE(lpphy_rev1_ofdm_cck_gain_table), lpphy_rev1_ofdm_cck_gain_table);
+}
+	b43_lptab_write_bulk(dev, B43_LPTAB16(15, 0),
+		ARRAY_SIZE(lpphy_gain_delta_table), lpphy_gain_delta_table);
+	b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0),
+		ARRAY_SIZE(lpphy_tx_power_control_table), lpphy_tx_power_control_table);
+}
+
+void lpphy_rev2plus_table_init(struct b43_wldev *dev)
+{
+	int i;
+
+	B43_WARN_ON(dev->phy.rev < 2);
+
+	for (i = 0; i < 704; i++)
+		b43_lptab_write(dev, B43_LPTAB32(7, i), 0);
+
+	b43_lptab_write_bulk(dev, B43_LPTAB8(2, 0),
+		ARRAY_SIZE(lpphy_min_sig_sq_table), lpphy_min_sig_sq_table);
+	b43_lptab_write_bulk(dev, B43_LPTAB16(1, 0),
+		ARRAY_SIZE(lpphy_rev2plus_noise_scale_table), lpphy_rev2plus_noise_scale_table);
+	b43_lptab_write_bulk(dev, B43_LPTAB32(11, 0),
+		ARRAY_SIZE(lpphy_rev2plus_filter_control_table), lpphy_rev2plus_filter_control_table);
+	b43_lptab_write_bulk(dev, B43_LPTAB32(12, 0),
+		ARRAY_SIZE(lpphy_rev2plus_ps_control_table), lpphy_rev2plus_ps_control_table);
+	b43_lptab_write_bulk(dev, B43_LPTAB32(13, 0),
+		ARRAY_SIZE(lpphy_gain_idx_table), lpphy_gain_idx_table);
+	b43_lptab_write_bulk(dev, B43_LPTAB16(14, 0),
+		ARRAY_SIZE(lpphy_aux_gain_idx_table), lpphy_aux_gain_idx_table);
+	b43_lptab_write_bulk(dev, B43_LPTAB16(15, 0),
+		ARRAY_SIZE(lpphy_sw_control_table), lpphy_sw_control_table);
+	b43_lptab_write_bulk(dev, B43_LPTAB8(16, 0),
+		ARRAY_SIZE(lpphy_hf_table), lpphy_hf_table);
+	b43_lptab_write_bulk(dev, B43_LPTAB32(17, 0),
+		ARRAY_SIZE(lpphy_gain_value_table), lpphy_gain_value_table);
+	b43_lptab_write_bulk(dev, B43_LPTAB16(18, 0),
+		ARRAY_SIZE(lpphy_gain_table), lpphy_gain_table);
+	b43_lptab_write_bulk(dev, B43_LPTAB8(6, 0),
+		ARRAY_SIZE(lpphy_pll_fraction_table), lpphy_pll_fraction_table);
+	b43_lptab_write_bulk(dev, B43_LPTAB16(0, 0),
+		ARRAY_SIZE(lpphy_iqlo_cal_table), lpphy_iqlo_cal_table);
+	b43_lptab_write_bulk(dev, B43_LPTAB32(9, 0),
+		ARRAY_SIZE(lpphy_papd_eps_table), lpphy_papd_eps_table);
+	b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0),
+		ARRAY_SIZE(lpphy_papd_mult_table), lpphy_papd_mult_table);
+
+	if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
+		b43_lptab_write_bulk(dev, B43_LPTAB32(13, 0),
+			ARRAY_SIZE(lpphy_a0_gain_idx_table), lpphy_a0_gain_idx_table);
+		b43_lptab_write_bulk(dev, B43_LPTAB16(14, 0),
+			ARRAY_SIZE(lpphy_a0_aux_gain_idx_table), lpphy_a0_aux_gain_idx_table);
+		b43_lptab_write_bulk(dev, B43_LPTAB32(17, 0),
+			ARRAY_SIZE(lpphy_a0_gain_value_table), lpphy_a0_gain_value_table);
+		b43_lptab_write_bulk(dev, B43_LPTAB16(18, 0),
+			ARRAY_SIZE(lpphy_a0_gain_table), lpphy_a0_gain_table);
+	}
+}
+
+static void lpphy_rev0_1_write_gain_table(struct b43_wldev *dev, int offset,
+				struct lpphy_tx_gain_table_entry data)
+{
+	u32 tmp;
+
+	B43_WARN_ON(dev->phy.rev >= 2);
+
+	tmp  = data.pad << 11;
+	tmp |= data.pga << 7;
+	tmp |= data.gm  << 4;
+	tmp |= data.dac;
+	b43_lptab_write(dev, B43_LPTAB32(10, 0xC0 + offset), tmp);
+	tmp  = data.bb_mult << 20;
+	b43_lptab_write(dev, B43_LPTAB32(10, 0x140 + offset), tmp);
+}
+
+static void lpphy_rev2plus_write_gain_table(struct b43_wldev *dev, int offset,
+				struct lpphy_tx_gain_table_entry data)
+{
+	u32 tmp;
+
+	B43_WARN_ON(dev->phy.rev < 2);
+
+	tmp  = data.pad << 16;
+	tmp |= data.pga << 8;
+	tmp |= data.gm;
+	if (dev->phy.rev >= 3) {
+		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
+			tmp |= 0x10 << 24;
+		else
+			tmp |= 0x70 << 24;
+	} else {
+		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
+			tmp |= 0x14 << 24;
+		else
+			tmp |= 0x7F << 24;
+	}
+	b43_lptab_write(dev, B43_LPTAB32(7, 0xC0 + offset), tmp);
+	tmp  = data.bb_mult << 20;
+	tmp |= data.dac << 28;
+	b43_lptab_write(dev, B43_LPTAB32(7, 0x140 + offset), tmp);
+}
+
+void lpphy_write_gain_table(struct b43_wldev *dev, int offset,
+			    struct lpphy_tx_gain_table_entry data)
+{
+	if (dev->phy.rev >= 2)
+		lpphy_rev2plus_write_gain_table(dev, offset, data);
+	else
+		lpphy_rev0_1_write_gain_table(dev, offset, data);
+}
+
+void lpphy_write_gain_table_bulk(struct b43_wldev *dev, int offset, int count,
+				 struct lpphy_tx_gain_table_entry *table)
+{
+	int i;
+
+	for (i = offset; i < count; i++)
+		lpphy_write_gain_table(dev, i, table[i]);
+}
+
+void lpphy_init_tx_gain_table(struct b43_wldev *dev)
+{
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+
+	switch (dev->phy.rev) {
+	case 0:
+		if ((sprom->boardflags_hi & B43_BFH_NOPA) ||
+		    (sprom->boardflags_lo & B43_BFL_HGPA))
+			lpphy_write_gain_table_bulk(dev, 0, 128,
+					lpphy_rev0_nopa_tx_gain_table);
+		else if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+			lpphy_write_gain_table_bulk(dev, 0, 128,
+					lpphy_rev0_2ghz_tx_gain_table);
+		else
+			lpphy_write_gain_table_bulk(dev, 0, 128,
+					lpphy_rev0_5ghz_tx_gain_table);
+		break;
+	case 1:
+		if ((sprom->boardflags_hi & B43_BFH_NOPA) ||
+		    (sprom->boardflags_lo & B43_BFL_HGPA))
+			lpphy_write_gain_table_bulk(dev, 0, 128,
+					lpphy_rev1_nopa_tx_gain_table);
+		else if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+			lpphy_write_gain_table_bulk(dev, 0, 128,
+					lpphy_rev1_2ghz_tx_gain_table);
+		else
+			lpphy_write_gain_table_bulk(dev, 0, 128,
+					lpphy_rev1_5ghz_tx_gain_table);
+		break;
+	default:
+		if (sprom->boardflags_hi & B43_BFH_NOPA)
+			lpphy_write_gain_table_bulk(dev, 0, 128,
+					lpphy_rev2_nopa_tx_gain_table);
+		else if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
+			lpphy_write_gain_table_bulk(dev, 0, 128,
+					lpphy_rev2_2ghz_tx_gain_table);
+		else
+			lpphy_write_gain_table_bulk(dev, 0, 128,
+					lpphy_rev2_5ghz_tx_gain_table);
+	}
+}
diff --git a/drivers/net/wireless/broadcom/b43/tables_lpphy.h b/drivers/net/wireless/broadcom/b43/tables_lpphy.h
new file mode 100644
index 0000000..6200209
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/tables_lpphy.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_TABLES_LPPHY_H_
+#define B43_TABLES_LPPHY_H_
+
+
+#define B43_LPTAB_TYPEMASK		0xF0000000
+#define B43_LPTAB_8BIT			0x10000000
+#define B43_LPTAB_16BIT			0x20000000
+#define B43_LPTAB_32BIT			0x30000000
+#define B43_LPTAB8(table, offset)	(((table) << 10) | (offset) | B43_LPTAB_8BIT)
+#define B43_LPTAB16(table, offset)	(((table) << 10) | (offset) | B43_LPTAB_16BIT)
+#define B43_LPTAB32(table, offset)	(((table) << 10) | (offset) | B43_LPTAB_32BIT)
+
+/* Table definitions */
+#define B43_LPTAB_TXPWR_R2PLUS		B43_LPTAB32(0x07, 0) /* TX power lookup table (rev >= 2) */
+#define B43_LPTAB_TXPWR_R0_1		B43_LPTAB32(0xA0, 0) /* TX power lookup table (rev < 2) */
+
+u32 b43_lptab_read(struct b43_wldev *dev, u32 offset);
+void b43_lptab_write(struct b43_wldev *dev, u32 offset, u32 value);
+
+/* Bulk table access. Note that these functions return the bulk data in
+ * host endianness! The returned data is _not_ a bytearray, but an array
+ * consisting of nr_elements of the data type. */
+void b43_lptab_read_bulk(struct b43_wldev *dev, u32 offset,
+			 unsigned int nr_elements, void *data);
+void b43_lptab_write_bulk(struct b43_wldev *dev, u32 offset,
+			  unsigned int nr_elements, const void *data);
+
+void b2062_upload_init_table(struct b43_wldev *dev);
+void b2063_upload_init_table(struct b43_wldev *dev);
+
+struct lpphy_tx_gain_table_entry {
+	u8 gm,  pga,  pad,  dac,  bb_mult;
+};
+
+void lpphy_write_gain_table(struct b43_wldev *dev, int offset,
+			    struct lpphy_tx_gain_table_entry data);
+void lpphy_write_gain_table_bulk(struct b43_wldev *dev, int offset, int count,
+				 struct lpphy_tx_gain_table_entry *table);
+
+void lpphy_rev0_1_table_init(struct b43_wldev *dev);
+void lpphy_rev2plus_table_init(struct b43_wldev *dev);
+void lpphy_init_tx_gain_table(struct b43_wldev *dev);
+
+#endif /* B43_TABLES_LPPHY_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/tables_nphy.c b/drivers/net/wireless/broadcom/b43/tables_nphy.c
new file mode 100644
index 0000000..44e0957
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/tables_nphy.c
@@ -0,0 +1,3878 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11n PHY data tables
+
+  Copyright (c) 2008 Michael Buesch <m@bues.ch>
+  Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
+
+  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_nphy.h"
+#include "phy_common.h"
+#include "phy_n.h"
+
+static const u8 b43_ntab_adjustpower0[] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const u8 b43_ntab_adjustpower1[] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const u16 b43_ntab_bdi[] = {
+	0x0070, 0x0126, 0x012C, 0x0246, 0x048D, 0x04D2,
+};
+
+static const u32 b43_ntab_channelest[] = {
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+};
+
+static const u8 b43_ntab_estimatepowerlt0[] = {
+	0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49,
+	0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41,
+	0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39,
+	0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31,
+	0x30, 0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29,
+	0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21,
+	0x20, 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19,
+	0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11,
+};
+
+static const u8 b43_ntab_estimatepowerlt1[] = {
+	0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49,
+	0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41,
+	0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39,
+	0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31,
+	0x30, 0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29,
+	0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21,
+	0x20, 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19,
+	0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11,
+};
+
+static const u8 b43_ntab_framelookup[] = {
+	0x02, 0x04, 0x14, 0x14, 0x03, 0x05, 0x16, 0x16,
+	0x0A, 0x0C, 0x1C, 0x1C, 0x0B, 0x0D, 0x1E, 0x1E,
+	0x06, 0x08, 0x18, 0x18, 0x07, 0x09, 0x1A, 0x1A,
+	0x0E, 0x10, 0x20, 0x28, 0x0F, 0x11, 0x22, 0x2A,
+};
+
+static const u32 b43_ntab_framestruct[] = {
+	0x08004A04, 0x00100000, 0x01000A05, 0x00100020,
+	0x09804506, 0x00100030, 0x09804507, 0x00100030,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x08004A0C, 0x00100004, 0x01000A0D, 0x00100024,
+	0x0980450E, 0x00100034, 0x0980450F, 0x00100034,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000A04, 0x00100000, 0x11008A05, 0x00100020,
+	0x1980C506, 0x00100030, 0x21810506, 0x00100030,
+	0x21810506, 0x00100030, 0x01800504, 0x00100030,
+	0x11808505, 0x00100030, 0x29814507, 0x01100030,
+	0x00000A04, 0x00100000, 0x11008A05, 0x00100020,
+	0x21810506, 0x00100030, 0x21810506, 0x00100030,
+	0x29814507, 0x01100030, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000A0C, 0x00100008, 0x11008A0D, 0x00100028,
+	0x1980C50E, 0x00100038, 0x2181050E, 0x00100038,
+	0x2181050E, 0x00100038, 0x0180050C, 0x00100038,
+	0x1180850D, 0x00100038, 0x2981450F, 0x01100038,
+	0x00000A0C, 0x00100008, 0x11008A0D, 0x00100028,
+	0x2181050E, 0x00100038, 0x2181050E, 0x00100038,
+	0x2981450F, 0x01100038, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x08004A04, 0x00100000, 0x01000A05, 0x00100020,
+	0x1980C506, 0x00100030, 0x1980C506, 0x00100030,
+	0x11808504, 0x00100030, 0x3981CA05, 0x00100030,
+	0x29814507, 0x01100030, 0x00000000, 0x00000000,
+	0x10008A04, 0x00100000, 0x3981CA05, 0x00100030,
+	0x1980C506, 0x00100030, 0x29814507, 0x01100030,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x08004A0C, 0x00100008, 0x01000A0D, 0x00100028,
+	0x1980C50E, 0x00100038, 0x1980C50E, 0x00100038,
+	0x1180850C, 0x00100038, 0x3981CA0D, 0x00100038,
+	0x2981450F, 0x01100038, 0x00000000, 0x00000000,
+	0x10008A0C, 0x00100008, 0x3981CA0D, 0x00100038,
+	0x1980C50E, 0x00100038, 0x2981450F, 0x01100038,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x40021404, 0x00100000, 0x02001405, 0x00100040,
+	0x0B004A06, 0x01900060, 0x13008A06, 0x01900060,
+	0x13008A06, 0x01900060, 0x43020A04, 0x00100060,
+	0x1B00CA05, 0x00100060, 0x23010A07, 0x01500060,
+	0x40021404, 0x00100000, 0x1A00D405, 0x00100040,
+	0x13008A06, 0x01900060, 0x13008A06, 0x01900060,
+	0x23010A07, 0x01500060, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140C, 0x00100010, 0x0200140D, 0x00100050,
+	0x0B004A0E, 0x01900070, 0x13008A0E, 0x01900070,
+	0x13008A0E, 0x01900070, 0x43020A0C, 0x00100070,
+	0x1B00CA0D, 0x00100070, 0x23010A0F, 0x01500070,
+	0x4002140C, 0x00100010, 0x1A00D40D, 0x00100050,
+	0x13008A0E, 0x01900070, 0x13008A0E, 0x01900070,
+	0x23010A0F, 0x01500070, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x50029404, 0x00100000, 0x32019405, 0x00100040,
+	0x0B004A06, 0x01900060, 0x0B004A06, 0x01900060,
+	0x5B02CA04, 0x00100060, 0x3B01D405, 0x00100060,
+	0x23010A07, 0x01500060, 0x00000000, 0x00000000,
+	0x5802D404, 0x00100000, 0x3B01D405, 0x00100060,
+	0x0B004A06, 0x01900060, 0x23010A07, 0x01500060,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x5002940C, 0x00100010, 0x3201940D, 0x00100050,
+	0x0B004A0E, 0x01900070, 0x0B004A0E, 0x01900070,
+	0x5B02CA0C, 0x00100070, 0x3B01D40D, 0x00100070,
+	0x23010A0F, 0x01500070, 0x00000000, 0x00000000,
+	0x5802D40C, 0x00100010, 0x3B01D40D, 0x00100070,
+	0x0B004A0E, 0x01900070, 0x23010A0F, 0x01500070,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x40021404, 0x000F4800, 0x62031405, 0x00100040,
+	0x53028A06, 0x01900060, 0x53028A07, 0x01900060,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140C, 0x000F4808, 0x6203140D, 0x00100048,
+	0x53028A0E, 0x01900068, 0x53028A0F, 0x01900068,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000A0C, 0x00100004, 0x11008A0D, 0x00100024,
+	0x1980C50E, 0x00100034, 0x2181050E, 0x00100034,
+	0x2181050E, 0x00100034, 0x0180050C, 0x00100038,
+	0x1180850D, 0x00100038, 0x1181850D, 0x00100038,
+	0x2981450F, 0x01100038, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000A0C, 0x00100008, 0x11008A0D, 0x00100028,
+	0x2181050E, 0x00100038, 0x2181050E, 0x00100038,
+	0x1181850D, 0x00100038, 0x2981450F, 0x01100038,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x08004A04, 0x00100000, 0x01000A05, 0x00100020,
+	0x0180C506, 0x00100030, 0x0180C506, 0x00100030,
+	0x2180C50C, 0x00100030, 0x49820A0D, 0x0016A130,
+	0x41824A0D, 0x0016A130, 0x2981450F, 0x01100030,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x2000CA0C, 0x00100000, 0x49820A0D, 0x0016A130,
+	0x1980C50E, 0x00100030, 0x41824A0D, 0x0016A130,
+	0x2981450F, 0x01100030, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140C, 0x00100008, 0x0200140D, 0x00100048,
+	0x0B004A0E, 0x01900068, 0x13008A0E, 0x01900068,
+	0x13008A0E, 0x01900068, 0x43020A0C, 0x00100070,
+	0x1B00CA0D, 0x00100070, 0x1B014A0D, 0x00100070,
+	0x23010A0F, 0x01500070, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140C, 0x00100010, 0x1A00D40D, 0x00100050,
+	0x13008A0E, 0x01900070, 0x13008A0E, 0x01900070,
+	0x1B014A0D, 0x00100070, 0x23010A0F, 0x01500070,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x50029404, 0x00100000, 0x32019405, 0x00100040,
+	0x03004A06, 0x01900060, 0x03004A06, 0x01900060,
+	0x6B030A0C, 0x00100060, 0x4B02140D, 0x0016A160,
+	0x4302540D, 0x0016A160, 0x23010A0F, 0x01500060,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x6B03140C, 0x00100060, 0x4B02140D, 0x0016A160,
+	0x0B004A0E, 0x01900060, 0x4302540D, 0x0016A160,
+	0x23010A0F, 0x01500060, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x40021404, 0x00100000, 0x1A00D405, 0x00100040,
+	0x53028A06, 0x01900060, 0x5B02CA06, 0x01900060,
+	0x5B02CA06, 0x01900060, 0x43020A04, 0x00100060,
+	0x1B00CA05, 0x00100060, 0x53028A07, 0x0190C060,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140C, 0x00100010, 0x1A00D40D, 0x00100050,
+	0x53028A0E, 0x01900070, 0x5B02CA0E, 0x01900070,
+	0x5B02CA0E, 0x01900070, 0x43020A0C, 0x00100070,
+	0x1B00CA0D, 0x00100070, 0x53028A0F, 0x0190C070,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x40021404, 0x00100000, 0x1A00D405, 0x00100040,
+	0x5B02CA06, 0x01900060, 0x5B02CA06, 0x01900060,
+	0x53028A07, 0x0190C060, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140C, 0x00100010, 0x1A00D40D, 0x00100050,
+	0x5B02CA0E, 0x01900070, 0x5B02CA0E, 0x01900070,
+	0x53028A0F, 0x0190C070, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	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_ntab_gainctl0[] = {
+	0x03CC2B44, 0x03CC2B42, 0x03CC2B40, 0x03CC2B3E,
+	0x03CC2B3D, 0x03CC2B3B, 0x03C82B44, 0x03C82B42,
+	0x03C82B40, 0x03C82B3E, 0x03C82B3D, 0x03C82B3B,
+	0x03C82B39, 0x03C82B38, 0x03C82B36, 0x03C82B34,
+	0x03C42B44, 0x03C42B42, 0x03C42B40, 0x03C42B3E,
+	0x03C42B3D, 0x03C42B3B, 0x03C42B39, 0x03C42B38,
+	0x03C42B36, 0x03C42B34, 0x03C42B33, 0x03C42B32,
+	0x03C42B30, 0x03C42B2F, 0x03C42B2D, 0x03C02B44,
+	0x03C02B42, 0x03C02B40, 0x03C02B3E, 0x03C02B3D,
+	0x03C02B3B, 0x03C02B39, 0x03C02B38, 0x03C02B36,
+	0x03C02B34, 0x03B02B44, 0x03B02B42, 0x03B02B40,
+	0x03B02B3E, 0x03B02B3D, 0x03B02B3B, 0x03B02B39,
+	0x03B02B38, 0x03B02B36, 0x03B02B34, 0x03B02B33,
+	0x03B02B32, 0x03B02B30, 0x03B02B2F, 0x03B02B2D,
+	0x03A02B44, 0x03A02B42, 0x03A02B40, 0x03A02B3E,
+	0x03A02B3D, 0x03A02B3B, 0x03A02B39, 0x03A02B38,
+	0x03A02B36, 0x03A02B34, 0x03902B44, 0x03902B42,
+	0x03902B40, 0x03902B3E, 0x03902B3D, 0x03902B3B,
+	0x03902B39, 0x03902B38, 0x03902B36, 0x03902B34,
+	0x03902B33, 0x03902B32, 0x03902B30, 0x03802B44,
+	0x03802B42, 0x03802B40, 0x03802B3E, 0x03802B3D,
+	0x03802B3B, 0x03802B39, 0x03802B38, 0x03802B36,
+	0x03802B34, 0x03802B33, 0x03802B32, 0x03802B30,
+	0x03802B2F, 0x03802B2D, 0x03802B2C, 0x03802B2B,
+	0x03802B2A, 0x03802B29, 0x03802B27, 0x03802B26,
+	0x03802B25, 0x03802B24, 0x03802B23, 0x03802B22,
+	0x03802B21, 0x03802B20, 0x03802B1F, 0x03802B1E,
+	0x03802B1E, 0x03802B1D, 0x03802B1C, 0x03802B1B,
+	0x03802B1A, 0x03802B1A, 0x03802B19, 0x03802B18,
+	0x03802B18, 0x03802B18, 0x03802B18, 0x03802B18,
+	0x03802B18, 0x03802B18, 0x03802B18, 0x03802B18,
+	0x03802B18, 0x03802B18, 0x03802B18, 0x00002B00,
+};
+
+static const u32 b43_ntab_gainctl1[] = {
+	0x03CC2B44, 0x03CC2B42, 0x03CC2B40, 0x03CC2B3E,
+	0x03CC2B3D, 0x03CC2B3B, 0x03C82B44, 0x03C82B42,
+	0x03C82B40, 0x03C82B3E, 0x03C82B3D, 0x03C82B3B,
+	0x03C82B39, 0x03C82B38, 0x03C82B36, 0x03C82B34,
+	0x03C42B44, 0x03C42B42, 0x03C42B40, 0x03C42B3E,
+	0x03C42B3D, 0x03C42B3B, 0x03C42B39, 0x03C42B38,
+	0x03C42B36, 0x03C42B34, 0x03C42B33, 0x03C42B32,
+	0x03C42B30, 0x03C42B2F, 0x03C42B2D, 0x03C02B44,
+	0x03C02B42, 0x03C02B40, 0x03C02B3E, 0x03C02B3D,
+	0x03C02B3B, 0x03C02B39, 0x03C02B38, 0x03C02B36,
+	0x03C02B34, 0x03B02B44, 0x03B02B42, 0x03B02B40,
+	0x03B02B3E, 0x03B02B3D, 0x03B02B3B, 0x03B02B39,
+	0x03B02B38, 0x03B02B36, 0x03B02B34, 0x03B02B33,
+	0x03B02B32, 0x03B02B30, 0x03B02B2F, 0x03B02B2D,
+	0x03A02B44, 0x03A02B42, 0x03A02B40, 0x03A02B3E,
+	0x03A02B3D, 0x03A02B3B, 0x03A02B39, 0x03A02B38,
+	0x03A02B36, 0x03A02B34, 0x03902B44, 0x03902B42,
+	0x03902B40, 0x03902B3E, 0x03902B3D, 0x03902B3B,
+	0x03902B39, 0x03902B38, 0x03902B36, 0x03902B34,
+	0x03902B33, 0x03902B32, 0x03902B30, 0x03802B44,
+	0x03802B42, 0x03802B40, 0x03802B3E, 0x03802B3D,
+	0x03802B3B, 0x03802B39, 0x03802B38, 0x03802B36,
+	0x03802B34, 0x03802B33, 0x03802B32, 0x03802B30,
+	0x03802B2F, 0x03802B2D, 0x03802B2C, 0x03802B2B,
+	0x03802B2A, 0x03802B29, 0x03802B27, 0x03802B26,
+	0x03802B25, 0x03802B24, 0x03802B23, 0x03802B22,
+	0x03802B21, 0x03802B20, 0x03802B1F, 0x03802B1E,
+	0x03802B1E, 0x03802B1D, 0x03802B1C, 0x03802B1B,
+	0x03802B1A, 0x03802B1A, 0x03802B19, 0x03802B18,
+	0x03802B18, 0x03802B18, 0x03802B18, 0x03802B18,
+	0x03802B18, 0x03802B18, 0x03802B18, 0x03802B18,
+	0x03802B18, 0x03802B18, 0x03802B18, 0x00002B00,
+};
+
+static const u32 b43_ntab_intlevel[] = {
+	0x00802070, 0x0671188D, 0x0A60192C, 0x0A300E46,
+	0x00C1188D, 0x080024D2, 0x00000070,
+};
+
+static const u32 b43_ntab_iqlt0[] = {
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+};
+
+static const u32 b43_ntab_iqlt1[] = {
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+	0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+};
+
+static const u16 b43_ntab_loftlt0[] = {
+	0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+	0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+	0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+	0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+	0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+	0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+	0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+	0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+	0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+	0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+	0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+	0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+	0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+	0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+	0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+	0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+	0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+	0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+	0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+	0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+	0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+	0x0002, 0x0103,
+};
+
+static const u16 b43_ntab_loftlt1[] = {
+	0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+	0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+	0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+	0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+	0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+	0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+	0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+	0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+	0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+	0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+	0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+	0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+	0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+	0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+	0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+	0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+	0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+	0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+	0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+	0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+	0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+	0x0002, 0x0103,
+};
+
+static const u8 b43_ntab_mcs[] = {
+	0x00, 0x08, 0x0A, 0x10, 0x12, 0x19, 0x1A, 0x1C,
+	0x40, 0x48, 0x4A, 0x50, 0x52, 0x59, 0x5A, 0x5C,
+	0x80, 0x88, 0x8A, 0x90, 0x92, 0x99, 0x9A, 0x9C,
+	0xC0, 0xC8, 0xCA, 0xD0, 0xD2, 0xD9, 0xDA, 0xDC,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x01, 0x02, 0x04, 0x08, 0x09, 0x0A, 0x0C,
+	0x10, 0x11, 0x12, 0x14, 0x18, 0x19, 0x1A, 0x1C,
+	0x20, 0x21, 0x22, 0x24, 0x40, 0x41, 0x42, 0x44,
+	0x48, 0x49, 0x4A, 0x4C, 0x50, 0x51, 0x52, 0x54,
+	0x58, 0x59, 0x5A, 0x5C, 0x60, 0x61, 0x62, 0x64,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const u32 b43_ntab_noisevar10[] = {
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+};
+
+static const u32 b43_ntab_noisevar11[] = {
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+	0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+};
+
+static const u16 b43_ntab_pilot[] = {
+	0xFF08, 0xFF08, 0xFF08, 0xFF08, 0xFF08, 0xFF08,
+	0xFF08, 0xFF08, 0x80D5, 0x80D5, 0x80D5, 0x80D5,
+	0x80D5, 0x80D5, 0x80D5, 0x80D5, 0xFF0A, 0xFF82,
+	0xFFA0, 0xFF28, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+	0xFF82, 0xFFA0, 0xFF28, 0xFF0A, 0xFFFF, 0xFFFF,
+	0xFFFF, 0xFFFF, 0xF83F, 0xFA1F, 0xFA97, 0xFAB5,
+	0xF2BD, 0xF0BF, 0xFFFF, 0xFFFF, 0xF017, 0xF815,
+	0xF215, 0xF095, 0xF035, 0xF01D, 0xFFFF, 0xFFFF,
+	0xFF08, 0xFF02, 0xFF80, 0xFF20, 0xFF08, 0xFF02,
+	0xFF80, 0xFF20, 0xF01F, 0xF817, 0xFA15, 0xF295,
+	0xF0B5, 0xF03D, 0xFFFF, 0xFFFF, 0xF82A, 0xFA0A,
+	0xFA82, 0xFAA0, 0xF2A8, 0xF0AA, 0xFFFF, 0xFFFF,
+	0xF002, 0xF800, 0xF200, 0xF080, 0xF020, 0xF008,
+	0xFFFF, 0xFFFF, 0xF00A, 0xF802, 0xFA00, 0xF280,
+	0xF0A0, 0xF028, 0xFFFF, 0xFFFF,
+};
+
+static const u32 b43_ntab_pilotlt[] = {
+	0x76540123, 0x62407351, 0x76543201, 0x76540213,
+	0x76540123, 0x76430521,
+};
+
+static const u32 b43_ntab_tdi20a0[] = {
+	0x00091226, 0x000A1429, 0x000B56AD, 0x000C58B0,
+	0x000D5AB3, 0x000E9CB6, 0x000F9EBA, 0x0000C13D,
+	0x00020301, 0x00030504, 0x00040708, 0x0005090B,
+	0x00064B8E, 0x00095291, 0x000A5494, 0x000B9718,
+	0x000C9927, 0x000D9B2A, 0x000EDD2E, 0x000FDF31,
+	0x000101B4, 0x000243B7, 0x000345BB, 0x000447BE,
+	0x00058982, 0x00068C05, 0x00099309, 0x000A950C,
+	0x000BD78F, 0x000CD992, 0x000DDB96, 0x000F1D99,
+	0x00005FA8, 0x0001422C, 0x0002842F, 0x00038632,
+	0x00048835, 0x0005CA38, 0x0006CCBC, 0x0009D3BF,
+	0x000B1603, 0x000C1806, 0x000D1A0A, 0x000E1C0D,
+	0x000F5E10, 0x00008093, 0x00018297, 0x0002C49A,
+	0x0003C680, 0x0004C880, 0x00060B00, 0x00070D00,
+	0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_ntab_tdi20a1[] = {
+	0x00014B26, 0x00028D29, 0x000393AD, 0x00049630,
+	0x0005D833, 0x0006DA36, 0x00099C3A, 0x000A9E3D,
+	0x000BC081, 0x000CC284, 0x000DC488, 0x000F068B,
+	0x0000488E, 0x00018B91, 0x0002D214, 0x0003D418,
+	0x0004D6A7, 0x000618AA, 0x00071AAE, 0x0009DCB1,
+	0x000B1EB4, 0x000C0137, 0x000D033B, 0x000E053E,
+	0x000F4702, 0x00008905, 0x00020C09, 0x0003128C,
+	0x0004148F, 0x00051712, 0x00065916, 0x00091B19,
+	0x000A1D28, 0x000B5F2C, 0x000C41AF, 0x000D43B2,
+	0x000E85B5, 0x000F87B8, 0x0000C9BC, 0x00024CBF,
+	0x00035303, 0x00045506, 0x0005978A, 0x0006998D,
+	0x00095B90, 0x000A5D93, 0x000B9F97, 0x000C821A,
+	0x000D8400, 0x000EC600, 0x000FC800, 0x00010A00,
+	0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_ntab_tdi40a0[] = {
+	0x0011A346, 0x00136CCF, 0x0014F5D9, 0x001641E2,
+	0x0017CB6B, 0x00195475, 0x001B2383, 0x001CAD0C,
+	0x001E7616, 0x0000821F, 0x00020BA8, 0x0003D4B2,
+	0x00056447, 0x00072DD0, 0x0008B6DA, 0x000A02E3,
+	0x000B8C6C, 0x000D15F6, 0x0011E484, 0x0013AE0D,
+	0x00153717, 0x00168320, 0x00180CA9, 0x00199633,
+	0x001B6548, 0x001CEED1, 0x001EB7DB, 0x0000C3E4,
+	0x00024D6D, 0x000416F7, 0x0005A585, 0x00076F0F,
+	0x0008F818, 0x000A4421, 0x000BCDAB, 0x000D9734,
+	0x00122649, 0x0013EFD2, 0x001578DC, 0x0016C4E5,
+	0x00184E6E, 0x001A17F8, 0x001BA686, 0x001D3010,
+	0x001EF999, 0x00010522, 0x00028EAC, 0x00045835,
+	0x0005E74A, 0x0007B0D3, 0x00093A5D, 0x000A85E6,
+	0x000C0F6F, 0x000DD8F9, 0x00126787, 0x00143111,
+	0x0015BA9A, 0x00170623, 0x00188FAD, 0x001A5936,
+	0x001BE84B, 0x001DB1D4, 0x001F3B5E, 0x000146E7,
+	0x00031070, 0x000499FA, 0x00062888, 0x0007F212,
+	0x00097B9B, 0x000AC7A4, 0x000C50AE, 0x000E1A37,
+	0x0012A94C, 0x001472D5, 0x0015FC5F, 0x00174868,
+	0x0018D171, 0x001A9AFB, 0x001C2989, 0x001DF313,
+	0x001F7C9C, 0x000188A5, 0x000351AF, 0x0004DB38,
+	0x0006AA4D, 0x000833D7, 0x0009BD60, 0x000B0969,
+	0x000C9273, 0x000E5BFC, 0x00132A8A, 0x0014B414,
+	0x00163D9D, 0x001789A6, 0x001912B0, 0x001ADC39,
+	0x001C6BCE, 0x001E34D8, 0x001FBE61, 0x0001CA6A,
+	0x00039374, 0x00051CFD, 0x0006EC0B, 0x00087515,
+	0x0009FE9E, 0x000B4AA7, 0x000CD3B1, 0x000E9D3A,
+	0x00000000, 0x00000000,
+};
+
+static const u32 b43_ntab_tdi40a1[] = {
+	0x001EDB36, 0x000129CA, 0x0002B353, 0x00047CDD,
+	0x0005C8E6, 0x000791EF, 0x00091BF9, 0x000AAA07,
+	0x000C3391, 0x000DFD1A, 0x00120923, 0x0013D22D,
+	0x00155C37, 0x0016EACB, 0x00187454, 0x001A3DDE,
+	0x001B89E7, 0x001D12F0, 0x001F1CFA, 0x00016B88,
+	0x00033492, 0x0004BE1B, 0x00060A24, 0x0007D32E,
+	0x00095D38, 0x000AEC4C, 0x000C7555, 0x000E3EDF,
+	0x00124AE8, 0x001413F1, 0x0015A37B, 0x00172C89,
+	0x0018B593, 0x001A419C, 0x001BCB25, 0x001D942F,
+	0x001F63B9, 0x0001AD4D, 0x00037657, 0x0004C260,
+	0x00068BE9, 0x000814F3, 0x0009A47C, 0x000B2D8A,
+	0x000CB694, 0x000E429D, 0x00128C26, 0x001455B0,
+	0x0015E4BA, 0x00176E4E, 0x0018F758, 0x001A8361,
+	0x001C0CEA, 0x001DD674, 0x001FA57D, 0x0001EE8B,
+	0x0003B795, 0x0005039E, 0x0006CD27, 0x000856B1,
+	0x0009E5C6, 0x000B6F4F, 0x000CF859, 0x000E8462,
+	0x00130DEB, 0x00149775, 0x00162603, 0x0017AF8C,
+	0x00193896, 0x001AC49F, 0x001C4E28, 0x001E17B2,
+	0x0000A6C7, 0x00023050, 0x0003F9DA, 0x00054563,
+	0x00070EEC, 0x00089876, 0x000A2704, 0x000BB08D,
+	0x000D3A17, 0x001185A0, 0x00134F29, 0x0014D8B3,
+	0x001667C8, 0x0017F151, 0x00197ADB, 0x001B0664,
+	0x001C8FED, 0x001E5977, 0x0000E805, 0x0002718F,
+	0x00043B18, 0x000586A1, 0x0007502B, 0x0008D9B4,
+	0x000A68C9, 0x000BF252, 0x000DBBDC, 0x0011C7E5,
+	0x001390EE, 0x00151A78, 0x0016A906, 0x00183290,
+	0x0019BC19, 0x001B4822, 0x001CD12C, 0x001E9AB5,
+	0x00000000, 0x00000000,
+};
+
+static const u32 b43_ntab_tdtrn[] = {
+	0x061C061C, 0x0050EE68, 0xF592FE36, 0xFE5212F6,
+	0x00000C38, 0xFE5212F6, 0xF592FE36, 0x0050EE68,
+	0x061C061C, 0xEE680050, 0xFE36F592, 0x12F6FE52,
+	0x0C380000, 0x12F6FE52, 0xFE36F592, 0xEE680050,
+	0x061C061C, 0x0050EE68, 0xF592FE36, 0xFE5212F6,
+	0x00000C38, 0xFE5212F6, 0xF592FE36, 0x0050EE68,
+	0x061C061C, 0xEE680050, 0xFE36F592, 0x12F6FE52,
+	0x0C380000, 0x12F6FE52, 0xFE36F592, 0xEE680050,
+	0x05E305E3, 0x004DEF0C, 0xF5F3FE47, 0xFE611246,
+	0x00000BC7, 0xFE611246, 0xF5F3FE47, 0x004DEF0C,
+	0x05E305E3, 0xEF0C004D, 0xFE47F5F3, 0x1246FE61,
+	0x0BC70000, 0x1246FE61, 0xFE47F5F3, 0xEF0C004D,
+	0x05E305E3, 0x004DEF0C, 0xF5F3FE47, 0xFE611246,
+	0x00000BC7, 0xFE611246, 0xF5F3FE47, 0x004DEF0C,
+	0x05E305E3, 0xEF0C004D, 0xFE47F5F3, 0x1246FE61,
+	0x0BC70000, 0x1246FE61, 0xFE47F5F3, 0xEF0C004D,
+	0xFA58FA58, 0xF895043B, 0xFF4C09C0, 0xFBC6FFA8,
+	0xFB84F384, 0x0798F6F9, 0x05760122, 0x058409F6,
+	0x0B500000, 0x05B7F542, 0x08860432, 0x06DDFEE7,
+	0xFB84F384, 0xF9D90664, 0xF7E8025C, 0x00FFF7BD,
+	0x05A805A8, 0xF7BD00FF, 0x025CF7E8, 0x0664F9D9,
+	0xF384FB84, 0xFEE706DD, 0x04320886, 0xF54205B7,
+	0x00000B50, 0x09F60584, 0x01220576, 0xF6F90798,
+	0xF384FB84, 0xFFA8FBC6, 0x09C0FF4C, 0x043BF895,
+	0x02D402D4, 0x07DE0270, 0xFC96079C, 0xF90AFE94,
+	0xFE00FF2C, 0x02D4065D, 0x092A0096, 0x0014FBB8,
+	0xFD2CFD2C, 0x076AFB3C, 0x0096F752, 0xF991FD87,
+	0xFB2C0200, 0xFEB8F960, 0x08E0FC96, 0x049802A8,
+	0xFD2CFD2C, 0x02A80498, 0xFC9608E0, 0xF960FEB8,
+	0x0200FB2C, 0xFD87F991, 0xF7520096, 0xFB3C076A,
+	0xFD2CFD2C, 0xFBB80014, 0x0096092A, 0x065D02D4,
+	0xFF2CFE00, 0xFE94F90A, 0x079CFC96, 0x027007DE,
+	0x02D402D4, 0x027007DE, 0x079CFC96, 0xFE94F90A,
+	0xFF2CFE00, 0x065D02D4, 0x0096092A, 0xFBB80014,
+	0xFD2CFD2C, 0xFB3C076A, 0xF7520096, 0xFD87F991,
+	0x0200FB2C, 0xF960FEB8, 0xFC9608E0, 0x02A80498,
+	0xFD2CFD2C, 0x049802A8, 0x08E0FC96, 0xFEB8F960,
+	0xFB2C0200, 0xF991FD87, 0x0096F752, 0x076AFB3C,
+	0xFD2CFD2C, 0x0014FBB8, 0x092A0096, 0x02D4065D,
+	0xFE00FF2C, 0xF90AFE94, 0xFC96079C, 0x07DE0270,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x062A0000, 0xFEFA0759, 0x08B80908, 0xF396FC2D,
+	0xF9D6045C, 0xFC4EF608, 0xF748F596, 0x07B207BF,
+	0x062A062A, 0xF84EF841, 0xF748F596, 0x03B209F8,
+	0xF9D6045C, 0x0C6A03D3, 0x08B80908, 0x0106F8A7,
+	0x062A0000, 0xFEFAF8A7, 0x08B8F6F8, 0xF39603D3,
+	0xF9D6FBA4, 0xFC4E09F8, 0xF7480A6A, 0x07B2F841,
+	0x062AF9D6, 0xF84E07BF, 0xF7480A6A, 0x03B2F608,
+	0xF9D6FBA4, 0x0C6AFC2D, 0x08B8F6F8, 0x01060759,
+	0x062A0000, 0xFEFA0759, 0x08B80908, 0xF396FC2D,
+	0xF9D6045C, 0xFC4EF608, 0xF748F596, 0x07B207BF,
+	0x062A062A, 0xF84EF841, 0xF748F596, 0x03B209F8,
+	0xF9D6045C, 0x0C6A03D3, 0x08B80908, 0x0106F8A7,
+	0x062A0000, 0xFEFAF8A7, 0x08B8F6F8, 0xF39603D3,
+	0xF9D6FBA4, 0xFC4E09F8, 0xF7480A6A, 0x07B2F841,
+	0x062AF9D6, 0xF84E07BF, 0xF7480A6A, 0x03B2F608,
+	0xF9D6FBA4, 0x0C6AFC2D, 0x08B8F6F8, 0x01060759,
+	0x061C061C, 0xFF30009D, 0xFFB21141, 0xFD87FB54,
+	0xF65DFE59, 0x02EEF99E, 0x0166F03C, 0xFFF809B6,
+	0x000008A4, 0x000AF42B, 0x00EFF577, 0xFA840BF2,
+	0xFC02FF51, 0x08260F67, 0xFFF0036F, 0x0842F9C3,
+	0x00000000, 0x063DF7BE, 0xFC910010, 0xF099F7DA,
+	0x00AF03FE, 0xF40E057C, 0x0A89FF11, 0x0BD5FFF6,
+	0xF75C0000, 0xF64A0008, 0x0FC4FE9A, 0x0662FD12,
+	0x01A709A3, 0x04AC0279, 0xEEBF004E, 0xFF6300D0,
+	0xF9E4F9E4, 0x00D0FF63, 0x004EEEBF, 0x027904AC,
+	0x09A301A7, 0xFD120662, 0xFE9A0FC4, 0x0008F64A,
+	0x0000F75C, 0xFFF60BD5, 0xFF110A89, 0x057CF40E,
+	0x03FE00AF, 0xF7DAF099, 0x0010FC91, 0xF7BE063D,
+	0x00000000, 0xF9C30842, 0x036FFFF0, 0x0F670826,
+	0xFF51FC02, 0x0BF2FA84, 0xF57700EF, 0xF42B000A,
+	0x08A40000, 0x09B6FFF8, 0xF03C0166, 0xF99E02EE,
+	0xFE59F65D, 0xFB54FD87, 0x1141FFB2, 0x009DFF30,
+	0x05E30000, 0xFF060705, 0x085408A0, 0xF425FC59,
+	0xFA1D042A, 0xFC78F67A, 0xF7ACF60E, 0x075A0766,
+	0x05E305E3, 0xF8A6F89A, 0xF7ACF60E, 0x03880986,
+	0xFA1D042A, 0x0BDB03A7, 0x085408A0, 0x00FAF8FB,
+	0x05E30000, 0xFF06F8FB, 0x0854F760, 0xF42503A7,
+	0xFA1DFBD6, 0xFC780986, 0xF7AC09F2, 0x075AF89A,
+	0x05E3FA1D, 0xF8A60766, 0xF7AC09F2, 0x0388F67A,
+	0xFA1DFBD6, 0x0BDBFC59, 0x0854F760, 0x00FA0705,
+	0x05E30000, 0xFF060705, 0x085408A0, 0xF425FC59,
+	0xFA1D042A, 0xFC78F67A, 0xF7ACF60E, 0x075A0766,
+	0x05E305E3, 0xF8A6F89A, 0xF7ACF60E, 0x03880986,
+	0xFA1D042A, 0x0BDB03A7, 0x085408A0, 0x00FAF8FB,
+	0x05E30000, 0xFF06F8FB, 0x0854F760, 0xF42503A7,
+	0xFA1DFBD6, 0xFC780986, 0xF7AC09F2, 0x075AF89A,
+	0x05E3FA1D, 0xF8A60766, 0xF7AC09F2, 0x0388F67A,
+	0xFA1DFBD6, 0x0BDBFC59, 0x0854F760, 0x00FA0705,
+	0xFA58FA58, 0xF8F0FE00, 0x0448073D, 0xFDC9FE46,
+	0xF9910258, 0x089D0407, 0xFD5CF71A, 0x02AFFDE0,
+	0x083E0496, 0xFF5A0740, 0xFF7AFD97, 0x00FE01F1,
+	0x0009082E, 0xFA94FF75, 0xFECDF8EA, 0xFFB0F693,
+	0xFD2CFA58, 0x0433FF16, 0xFBA405DD, 0xFA610341,
+	0x06A606CB, 0x0039FD2D, 0x0677FA97, 0x01FA05E0,
+	0xF896003E, 0x075A068B, 0x012CFC3E, 0xFA23F98D,
+	0xFC7CFD43, 0xFF90FC0D, 0x01C10982, 0x00C601D6,
+	0xFD2CFD2C, 0x01D600C6, 0x098201C1, 0xFC0DFF90,
+	0xFD43FC7C, 0xF98DFA23, 0xFC3E012C, 0x068B075A,
+	0x003EF896, 0x05E001FA, 0xFA970677, 0xFD2D0039,
+	0x06CB06A6, 0x0341FA61, 0x05DDFBA4, 0xFF160433,
+	0xFA58FD2C, 0xF693FFB0, 0xF8EAFECD, 0xFF75FA94,
+	0x082E0009, 0x01F100FE, 0xFD97FF7A, 0x0740FF5A,
+	0x0496083E, 0xFDE002AF, 0xF71AFD5C, 0x0407089D,
+	0x0258F991, 0xFE46FDC9, 0x073D0448, 0xFE00F8F0,
+	0xFD2CFD2C, 0xFCE00500, 0xFC09FDDC, 0xFE680157,
+	0x04C70571, 0xFC3AFF21, 0xFCD70228, 0x056D0277,
+	0x0200FE00, 0x0022F927, 0xFE3C032B, 0xFC44FF3C,
+	0x03E9FBDB, 0x04570313, 0x04C9FF5C, 0x000D03B8,
+	0xFA580000, 0xFBE900D2, 0xF9D0FE0B, 0x0125FDF9,
+	0x042501BF, 0x0328FA2B, 0xFFA902F0, 0xFA250157,
+	0x0200FE00, 0x03740438, 0xFF0405FD, 0x030CFE52,
+	0x0037FB39, 0xFF6904C5, 0x04F8FD23, 0xFD31FC1B,
+	0xFD2CFD2C, 0xFC1BFD31, 0xFD2304F8, 0x04C5FF69,
+	0xFB390037, 0xFE52030C, 0x05FDFF04, 0x04380374,
+	0xFE000200, 0x0157FA25, 0x02F0FFA9, 0xFA2B0328,
+	0x01BF0425, 0xFDF90125, 0xFE0BF9D0, 0x00D2FBE9,
+	0x0000FA58, 0x03B8000D, 0xFF5C04C9, 0x03130457,
+	0xFBDB03E9, 0xFF3CFC44, 0x032BFE3C, 0xF9270022,
+	0xFE000200, 0x0277056D, 0x0228FCD7, 0xFF21FC3A,
+	0x057104C7, 0x0157FE68, 0xFDDCFC09, 0x0500FCE0,
+	0xFD2CFD2C, 0x0500FCE0, 0xFDDCFC09, 0x0157FE68,
+	0x057104C7, 0xFF21FC3A, 0x0228FCD7, 0x0277056D,
+	0xFE000200, 0xF9270022, 0x032BFE3C, 0xFF3CFC44,
+	0xFBDB03E9, 0x03130457, 0xFF5C04C9, 0x03B8000D,
+	0x0000FA58, 0x00D2FBE9, 0xFE0BF9D0, 0xFDF90125,
+	0x01BF0425, 0xFA2B0328, 0x02F0FFA9, 0x0157FA25,
+	0xFE000200, 0x04380374, 0x05FDFF04, 0xFE52030C,
+	0xFB390037, 0x04C5FF69, 0xFD2304F8, 0xFC1BFD31,
+	0xFD2CFD2C, 0xFD31FC1B, 0x04F8FD23, 0xFF6904C5,
+	0x0037FB39, 0x030CFE52, 0xFF0405FD, 0x03740438,
+	0x0200FE00, 0xFA250157, 0xFFA902F0, 0x0328FA2B,
+	0x042501BF, 0x0125FDF9, 0xF9D0FE0B, 0xFBE900D2,
+	0xFA580000, 0x000D03B8, 0x04C9FF5C, 0x04570313,
+	0x03E9FBDB, 0xFC44FF3C, 0xFE3C032B, 0x0022F927,
+	0x0200FE00, 0x056D0277, 0xFCD70228, 0xFC3AFF21,
+	0x04C70571, 0xFE680157, 0xFC09FDDC, 0xFCE00500,
+	0x05A80000, 0xFF1006BE, 0x0800084A, 0xF49CFC7E,
+	0xFA580400, 0xFC9CF6DA, 0xF800F672, 0x0710071C,
+	0x05A805A8, 0xF8F0F8E4, 0xF800F672, 0x03640926,
+	0xFA580400, 0x0B640382, 0x0800084A, 0x00F0F942,
+	0x05A80000, 0xFF10F942, 0x0800F7B6, 0xF49C0382,
+	0xFA58FC00, 0xFC9C0926, 0xF800098E, 0x0710F8E4,
+	0x05A8FA58, 0xF8F0071C, 0xF800098E, 0x0364F6DA,
+	0xFA58FC00, 0x0B64FC7E, 0x0800F7B6, 0x00F006BE,
+	0x05A80000, 0xFF1006BE, 0x0800084A, 0xF49CFC7E,
+	0xFA580400, 0xFC9CF6DA, 0xF800F672, 0x0710071C,
+	0x05A805A8, 0xF8F0F8E4, 0xF800F672, 0x03640926,
+	0xFA580400, 0x0B640382, 0x0800084A, 0x00F0F942,
+	0x05A80000, 0xFF10F942, 0x0800F7B6, 0xF49C0382,
+	0xFA58FC00, 0xFC9C0926, 0xF800098E, 0x0710F8E4,
+	0x05A8FA58, 0xF8F0071C, 0xF800098E, 0x0364F6DA,
+	0xFA58FC00, 0x0B64FC7E, 0x0800F7B6, 0x00F006BE,
+};
+
+static const u32 b43_ntab_tmap[] = {
+	0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888,
+	0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+	0xF1111110, 0x11111111, 0x11F11111, 0x00000111,
+	0x11000000, 0x1111F111, 0x11111111, 0x111111F1,
+	0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x000AA888,
+	0x88880000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+	0xA1111110, 0x11111111, 0x11C11111, 0x00000111,
+	0x11000000, 0x1111A111, 0x11111111, 0x111111A1,
+	0xA2222220, 0x22222222, 0x22C22222, 0x00000222,
+	0x22000000, 0x2222A222, 0x22222222, 0x222222A2,
+	0xF1111110, 0x11111111, 0x11F11111, 0x00011111,
+	0x11110000, 0x1111F111, 0x11111111, 0x111111F1,
+	0xA8AA88A0, 0xA88888A8, 0xA8A8A88A, 0x00088AAA,
+	0xAAAA0000, 0xA8A8AA88, 0xA88AAAAA, 0xAAAA8A8A,
+	0xAAA8AAA0, 0x8AAA8AAA, 0xAA8A8A8A, 0x000AAA88,
+	0x8AAA0000, 0xAAA8A888, 0x8AA88A8A, 0x8A88A888,
+	0x08080A00, 0x0A08080A, 0x080A0A08, 0x00080808,
+	0x080A0000, 0x080A0808, 0x080A0808, 0x0A0A0A08,
+	0xA0A0A0A0, 0x80A0A080, 0x8080A0A0, 0x00008080,
+	0x80A00000, 0x80A080A0, 0xA080A0A0, 0x8080A0A0,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x99999000, 0x9B9B99BB, 0x9BB99999, 0x9999B9B9,
+	0x9B99BB90, 0x9BBBBB9B, 0x9B9B9BB9, 0x00000999,
+	0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+	0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00AAA888,
+	0x22000000, 0x2222B222, 0x22222222, 0x222222B2,
+	0xB2222220, 0x22222222, 0x22D22222, 0x00000222,
+	0x11000000, 0x1111A111, 0x11111111, 0x111111A1,
+	0xA1111110, 0x11111111, 0x11C11111, 0x00000111,
+	0x33000000, 0x3333B333, 0x33333333, 0x333333B3,
+	0xB3333330, 0x33333333, 0x33D33333, 0x00000333,
+	0x22000000, 0x2222A222, 0x22222222, 0x222222A2,
+	0xA2222220, 0x22222222, 0x22C22222, 0x00000222,
+	0x99B99B00, 0x9B9B99BB, 0x9BB99999, 0x9999B9B9,
+	0x9B99BB99, 0x9BBBBB9B, 0x9B9B9BB9, 0x00000999,
+	0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+	0x8A88AA88, 0x8AAAAA8A, 0x8A8A8AA8, 0x08AAA888,
+	0x22222200, 0x2222F222, 0x22222222, 0x222222F2,
+	0x22222222, 0x22222222, 0x22F22222, 0x00000222,
+	0x11000000, 0x1111F111, 0x11111111, 0x11111111,
+	0xF1111111, 0x11111111, 0x11F11111, 0x01111111,
+	0xBB9BB900, 0xB9B9BB99, 0xB99BBBBB, 0xBBBB9B9B,
+	0xB9BB99BB, 0xB99999B9, 0xB9B9B99B, 0x00000BBB,
+	0xAA000000, 0xA8A8AA88, 0xA88AAAAA, 0xAAAA8A8A,
+	0xA8AA88AA, 0xA88888A8, 0xA8A8A88A, 0x0A888AAA,
+	0xAA000000, 0xA8A8AA88, 0xA88AAAAA, 0xAAAA8A8A,
+	0xA8AA88A0, 0xA88888A8, 0xA8A8A88A, 0x00000AAA,
+	0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+	0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888,
+	0xBBBBBB00, 0x999BBBBB, 0x9BB99B9B, 0xB9B9B9BB,
+	0xB9B99BBB, 0xB9B9B9BB, 0xB9BB9B99, 0x00000999,
+	0x8A000000, 0xAA88A888, 0xA88888AA, 0xA88A8A88,
+	0xA88AA88A, 0x88A8AAAA, 0xA8AA8AAA, 0x0888A88A,
+	0x0B0B0B00, 0x090B0B0B, 0x0B090B0B, 0x0909090B,
+	0x09090B0B, 0x09090B0B, 0x09090B09, 0x00000909,
+	0x0A000000, 0x0A080808, 0x080A080A, 0x080A0A08,
+	0x080A080A, 0x0808080A, 0x0A0A0A08, 0x0808080A,
+	0xB0B0B000, 0x9090B0B0, 0x90B09090, 0xB0B0B090,
+	0xB0B090B0, 0x90B0B0B0, 0xB0B09090, 0x00000090,
+	0x80000000, 0xA080A080, 0xA08080A0, 0xA0808080,
+	0xA080A080, 0x80A0A0A0, 0xA0A080A0, 0x00A0A0A0,
+	0x22000000, 0x2222F222, 0x22222222, 0x222222F2,
+	0xF2222220, 0x22222222, 0x22F22222, 0x00000222,
+	0x11000000, 0x1111F111, 0x11111111, 0x111111F1,
+	0xF1111110, 0x11111111, 0x11F11111, 0x00000111,
+	0x33000000, 0x3333F333, 0x33333333, 0x333333F3,
+	0xF3333330, 0x33333333, 0x33F33333, 0x00000333,
+	0x22000000, 0x2222F222, 0x22222222, 0x222222F2,
+	0xF2222220, 0x22222222, 0x22F22222, 0x00000222,
+	0x99000000, 0x9B9B99BB, 0x9BB99999, 0x9999B9B9,
+	0x9B99BB90, 0x9BBBBB9B, 0x9B9B9BB9, 0x00000999,
+	0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+	0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888,
+	0x88888000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+	0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888,
+	0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+	0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00AAA888,
+	0x88A88A00, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+	0x8A88AA88, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888,
+	0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+	0x8A88AA88, 0x8AAAAA8A, 0x8A8A8AA8, 0x08AAA888,
+	0x11000000, 0x1111A111, 0x11111111, 0x111111A1,
+	0xA1111110, 0x11111111, 0x11C11111, 0x00000111,
+	0x11000000, 0x1111A111, 0x11111111, 0x111111A1,
+	0xA1111110, 0x11111111, 0x11C11111, 0x00000111,
+	0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+	0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888,
+	0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+	0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	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 tables, PHY revision >= 3 */
+static const u32 b43_ntab_framestruct_r3[] = {
+	0x08004a04, 0x00100000, 0x01000a05, 0x00100020,
+	0x09804506, 0x00100030, 0x09804507, 0x00100030,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x08004a0c, 0x00100004, 0x01000a0d, 0x00100024,
+	0x0980450e, 0x00100034, 0x0980450f, 0x00100034,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000a04, 0x00100000, 0x11008a05, 0x00100020,
+	0x1980c506, 0x00100030, 0x21810506, 0x00100030,
+	0x21810506, 0x00100030, 0x01800504, 0x00100030,
+	0x11808505, 0x00100030, 0x29814507, 0x01100030,
+	0x00000a04, 0x00100000, 0x11008a05, 0x00100020,
+	0x21810506, 0x00100030, 0x21810506, 0x00100030,
+	0x29814507, 0x01100030, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000a0c, 0x00100008, 0x11008a0d, 0x00100028,
+	0x1980c50e, 0x00100038, 0x2181050e, 0x00100038,
+	0x2181050e, 0x00100038, 0x0180050c, 0x00100038,
+	0x1180850d, 0x00100038, 0x2981450f, 0x01100038,
+	0x00000a0c, 0x00100008, 0x11008a0d, 0x00100028,
+	0x2181050e, 0x00100038, 0x2181050e, 0x00100038,
+	0x2981450f, 0x01100038, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x08004a04, 0x00100000, 0x01000a05, 0x00100020,
+	0x1980c506, 0x00100030, 0x1980c506, 0x00100030,
+	0x11808504, 0x00100030, 0x3981ca05, 0x00100030,
+	0x29814507, 0x01100030, 0x00000000, 0x00000000,
+	0x10008a04, 0x00100000, 0x3981ca05, 0x00100030,
+	0x1980c506, 0x00100030, 0x29814507, 0x01100030,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x08004a0c, 0x00100008, 0x01000a0d, 0x00100028,
+	0x1980c50e, 0x00100038, 0x1980c50e, 0x00100038,
+	0x1180850c, 0x00100038, 0x3981ca0d, 0x00100038,
+	0x2981450f, 0x01100038, 0x00000000, 0x00000000,
+	0x10008a0c, 0x00100008, 0x3981ca0d, 0x00100038,
+	0x1980c50e, 0x00100038, 0x2981450f, 0x01100038,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x40021404, 0x00100000, 0x02001405, 0x00100040,
+	0x0b004a06, 0x01900060, 0x13008a06, 0x01900060,
+	0x13008a06, 0x01900060, 0x43020a04, 0x00100060,
+	0x1b00ca05, 0x00100060, 0x23010a07, 0x01500060,
+	0x40021404, 0x00100000, 0x1a00d405, 0x00100040,
+	0x13008a06, 0x01900060, 0x13008a06, 0x01900060,
+	0x23010a07, 0x01500060, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140c, 0x00100010, 0x0200140d, 0x00100050,
+	0x0b004a0e, 0x01900070, 0x13008a0e, 0x01900070,
+	0x13008a0e, 0x01900070, 0x43020a0c, 0x00100070,
+	0x1b00ca0d, 0x00100070, 0x23010a0f, 0x01500070,
+	0x4002140c, 0x00100010, 0x1a00d40d, 0x00100050,
+	0x13008a0e, 0x01900070, 0x13008a0e, 0x01900070,
+	0x23010a0f, 0x01500070, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x50029404, 0x00100000, 0x32019405, 0x00100040,
+	0x0b004a06, 0x01900060, 0x0b004a06, 0x01900060,
+	0x5b02ca04, 0x00100060, 0x3b01d405, 0x00100060,
+	0x23010a07, 0x01500060, 0x00000000, 0x00000000,
+	0x5802d404, 0x00100000, 0x3b01d405, 0x00100060,
+	0x0b004a06, 0x01900060, 0x23010a07, 0x01500060,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x5002940c, 0x00100010, 0x3201940d, 0x00100050,
+	0x0b004a0e, 0x01900070, 0x0b004a0e, 0x01900070,
+	0x5b02ca0c, 0x00100070, 0x3b01d40d, 0x00100070,
+	0x23010a0f, 0x01500070, 0x00000000, 0x00000000,
+	0x5802d40c, 0x00100010, 0x3b01d40d, 0x00100070,
+	0x0b004a0e, 0x01900070, 0x23010a0f, 0x01500070,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x40021404, 0x000f4800, 0x62031405, 0x00100040,
+	0x53028a06, 0x01900060, 0x53028a07, 0x01900060,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140c, 0x000f4808, 0x6203140d, 0x00100048,
+	0x53028a0e, 0x01900068, 0x53028a0f, 0x01900068,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000a0c, 0x00100004, 0x11008a0d, 0x00100024,
+	0x1980c50e, 0x00100034, 0x2181050e, 0x00100034,
+	0x2181050e, 0x00100034, 0x0180050c, 0x00100038,
+	0x1180850d, 0x00100038, 0x1181850d, 0x00100038,
+	0x2981450f, 0x01100038, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000a0c, 0x00100008, 0x11008a0d, 0x00100028,
+	0x2181050e, 0x00100038, 0x2181050e, 0x00100038,
+	0x1181850d, 0x00100038, 0x2981450f, 0x01100038,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x08004a04, 0x00100000, 0x01000a05, 0x00100020,
+	0x0180c506, 0x00100030, 0x0180c506, 0x00100030,
+	0x2180c50c, 0x00100030, 0x49820a0d, 0x0016a130,
+	0x41824a0d, 0x0016a130, 0x2981450f, 0x01100030,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x2000ca0c, 0x00100000, 0x49820a0d, 0x0016a130,
+	0x1980c50e, 0x00100030, 0x41824a0d, 0x0016a130,
+	0x2981450f, 0x01100030, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140c, 0x00100008, 0x0200140d, 0x00100048,
+	0x0b004a0e, 0x01900068, 0x13008a0e, 0x01900068,
+	0x13008a0e, 0x01900068, 0x43020a0c, 0x00100070,
+	0x1b00ca0d, 0x00100070, 0x1b014a0d, 0x00100070,
+	0x23010a0f, 0x01500070, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140c, 0x00100010, 0x1a00d40d, 0x00100050,
+	0x13008a0e, 0x01900070, 0x13008a0e, 0x01900070,
+	0x1b014a0d, 0x00100070, 0x23010a0f, 0x01500070,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x50029404, 0x00100000, 0x32019405, 0x00100040,
+	0x03004a06, 0x01900060, 0x03004a06, 0x01900060,
+	0x6b030a0c, 0x00100060, 0x4b02140d, 0x0016a160,
+	0x4302540d, 0x0016a160, 0x23010a0f, 0x01500060,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x6b03140c, 0x00100060, 0x4b02140d, 0x0016a160,
+	0x0b004a0e, 0x01900060, 0x4302540d, 0x0016a160,
+	0x23010a0f, 0x01500060, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x40021404, 0x00100000, 0x1a00d405, 0x00100040,
+	0x53028a06, 0x01900060, 0x5b02ca06, 0x01900060,
+	0x5b02ca06, 0x01900060, 0x43020a04, 0x00100060,
+	0x1b00ca05, 0x00100060, 0x53028a07, 0x0190c060,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140c, 0x00100010, 0x1a00d40d, 0x00100050,
+	0x53028a0e, 0x01900070, 0x5b02ca0e, 0x01900070,
+	0x5b02ca0e, 0x01900070, 0x43020a0c, 0x00100070,
+	0x1b00ca0d, 0x00100070, 0x53028a0f, 0x0190c070,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x40021404, 0x00100000, 0x1a00d405, 0x00100040,
+	0x5b02ca06, 0x01900060, 0x5b02ca06, 0x01900060,
+	0x53028a07, 0x0190c060, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140c, 0x00100010, 0x1a00d40d, 0x00100050,
+	0x5b02ca0e, 0x01900070, 0x5b02ca0e, 0x01900070,
+	0x53028a0f, 0x0190c070, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	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_ntab_pilot_r3[] = {
+	0xff08, 0xff08, 0xff08, 0xff08, 0xff08, 0xff08,
+	0xff08, 0xff08, 0x80d5, 0x80d5, 0x80d5, 0x80d5,
+	0x80d5, 0x80d5, 0x80d5, 0x80d5, 0xff0a, 0xff82,
+	0xffa0, 0xff28, 0xffff, 0xffff, 0xffff, 0xffff,
+	0xff82, 0xffa0, 0xff28, 0xff0a, 0xffff, 0xffff,
+	0xffff, 0xffff, 0xf83f, 0xfa1f, 0xfa97, 0xfab5,
+	0xf2bd, 0xf0bf, 0xffff, 0xffff, 0xf017, 0xf815,
+	0xf215, 0xf095, 0xf035, 0xf01d, 0xffff, 0xffff,
+	0xff08, 0xff02, 0xff80, 0xff20, 0xff08, 0xff02,
+	0xff80, 0xff20, 0xf01f, 0xf817, 0xfa15, 0xf295,
+	0xf0b5, 0xf03d, 0xffff, 0xffff, 0xf82a, 0xfa0a,
+	0xfa82, 0xfaa0, 0xf2a8, 0xf0aa, 0xffff, 0xffff,
+	0xf002, 0xf800, 0xf200, 0xf080, 0xf020, 0xf008,
+	0xffff, 0xffff, 0xf00a, 0xf802, 0xfa00, 0xf280,
+	0xf0a0, 0xf028, 0xffff, 0xffff,
+};
+
+static const u32 b43_ntab_tmap_r3[] = {
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0xf1111110, 0x11111111, 0x11f11111, 0x00000111,
+	0x11000000, 0x1111f111, 0x11111111, 0x111111f1,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x000aa888,
+	0x88880000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+	0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+	0xa2222220, 0x22222222, 0x22c22222, 0x00000222,
+	0x22000000, 0x2222a222, 0x22222222, 0x222222a2,
+	0xf1111110, 0x11111111, 0x11f11111, 0x00011111,
+	0x11110000, 0x1111f111, 0x11111111, 0x111111f1,
+	0xa8aa88a0, 0xa88888a8, 0xa8a8a88a, 0x00088aaa,
+	0xaaaa0000, 0xa8a8aa88, 0xa88aaaaa, 0xaaaa8a8a,
+	0xaaa8aaa0, 0x8aaa8aaa, 0xaa8a8a8a, 0x000aaa88,
+	0x8aaa0000, 0xaaa8a888, 0x8aa88a8a, 0x8a88a888,
+	0x08080a00, 0x0a08080a, 0x080a0a08, 0x00080808,
+	0x080a0000, 0x080a0808, 0x080a0808, 0x0a0a0a08,
+	0xa0a0a0a0, 0x80a0a080, 0x8080a0a0, 0x00008080,
+	0x80a00000, 0x80a080a0, 0xa080a0a0, 0x8080a0a0,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x99999000, 0x9b9b99bb, 0x9bb99999, 0x9999b9b9,
+	0x9b99bb90, 0x9bbbbb9b, 0x9b9b9bb9, 0x00000999,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00aaa888,
+	0x22000000, 0x2222b222, 0x22222222, 0x222222b2,
+	0xb2222220, 0x22222222, 0x22d22222, 0x00000222,
+	0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+	0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+	0x33000000, 0x3333b333, 0x33333333, 0x333333b3,
+	0xb3333330, 0x33333333, 0x33d33333, 0x00000333,
+	0x22000000, 0x2222a222, 0x22222222, 0x222222a2,
+	0xa2222220, 0x22222222, 0x22c22222, 0x00000222,
+	0x99b99b00, 0x9b9b99bb, 0x9bb99999, 0x9999b9b9,
+	0x9b99bb99, 0x9bbbbb9b, 0x9b9b9bb9, 0x00000999,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa88, 0x8aaaaa8a, 0x8a8a8aa8, 0x08aaa888,
+	0x22222200, 0x2222f222, 0x22222222, 0x222222f2,
+	0x22222222, 0x22222222, 0x22f22222, 0x00000222,
+	0x11000000, 0x1111f111, 0x11111111, 0x11111111,
+	0xf1111111, 0x11111111, 0x11f11111, 0x01111111,
+	0xbb9bb900, 0xb9b9bb99, 0xb99bbbbb, 0xbbbb9b9b,
+	0xb9bb99bb, 0xb99999b9, 0xb9b9b99b, 0x00000bbb,
+	0xaa000000, 0xa8a8aa88, 0xa88aaaaa, 0xaaaa8a8a,
+	0xa8aa88aa, 0xa88888a8, 0xa8a8a88a, 0x0a888aaa,
+	0xaa000000, 0xa8a8aa88, 0xa88aaaaa, 0xaaaa8a8a,
+	0xa8aa88a0, 0xa88888a8, 0xa8a8a88a, 0x00000aaa,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0xbbbbbb00, 0x999bbbbb, 0x9bb99b9b, 0xb9b9b9bb,
+	0xb9b99bbb, 0xb9b9b9bb, 0xb9bb9b99, 0x00000999,
+	0x8a000000, 0xaa88a888, 0xa88888aa, 0xa88a8a88,
+	0xa88aa88a, 0x88a8aaaa, 0xa8aa8aaa, 0x0888a88a,
+	0x0b0b0b00, 0x090b0b0b, 0x0b090b0b, 0x0909090b,
+	0x09090b0b, 0x09090b0b, 0x09090b09, 0x00000909,
+	0x0a000000, 0x0a080808, 0x080a080a, 0x080a0a08,
+	0x080a080a, 0x0808080a, 0x0a0a0a08, 0x0808080a,
+	0xb0b0b000, 0x9090b0b0, 0x90b09090, 0xb0b0b090,
+	0xb0b090b0, 0x90b0b0b0, 0xb0b09090, 0x00000090,
+	0x80000000, 0xa080a080, 0xa08080a0, 0xa0808080,
+	0xa080a080, 0x80a0a0a0, 0xa0a080a0, 0x00a0a0a0,
+	0x22000000, 0x2222f222, 0x22222222, 0x222222f2,
+	0xf2222220, 0x22222222, 0x22f22222, 0x00000222,
+	0x11000000, 0x1111f111, 0x11111111, 0x111111f1,
+	0xf1111110, 0x11111111, 0x11f11111, 0x00000111,
+	0x33000000, 0x3333f333, 0x33333333, 0x333333f3,
+	0xf3333330, 0x33333333, 0x33f33333, 0x00000333,
+	0x22000000, 0x2222f222, 0x22222222, 0x222222f2,
+	0xf2222220, 0x22222222, 0x22f22222, 0x00000222,
+	0x99000000, 0x9b9b99bb, 0x9bb99999, 0x9999b9b9,
+	0x9b99bb90, 0x9bbbbb9b, 0x9b9b9bb9, 0x00000999,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x88888000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00aaa888,
+	0x88a88a00, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa88, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa88, 0x8aaaaa8a, 0x8a8a8aa8, 0x08aaa888,
+	0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+	0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+	0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+	0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	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_ntab_intlevel_r3[] = {
+	0x00802070, 0x0671188d, 0x0a60192c, 0x0a300e46,
+	0x00c1188d, 0x080024d2, 0x00000070,
+};
+
+static const u32 b43_ntab_tdtrn_r3[] = {
+	0x061c061c, 0x0050ee68, 0xf592fe36, 0xfe5212f6,
+	0x00000c38, 0xfe5212f6, 0xf592fe36, 0x0050ee68,
+	0x061c061c, 0xee680050, 0xfe36f592, 0x12f6fe52,
+	0x0c380000, 0x12f6fe52, 0xfe36f592, 0xee680050,
+	0x061c061c, 0x0050ee68, 0xf592fe36, 0xfe5212f6,
+	0x00000c38, 0xfe5212f6, 0xf592fe36, 0x0050ee68,
+	0x061c061c, 0xee680050, 0xfe36f592, 0x12f6fe52,
+	0x0c380000, 0x12f6fe52, 0xfe36f592, 0xee680050,
+	0x05e305e3, 0x004def0c, 0xf5f3fe47, 0xfe611246,
+	0x00000bc7, 0xfe611246, 0xf5f3fe47, 0x004def0c,
+	0x05e305e3, 0xef0c004d, 0xfe47f5f3, 0x1246fe61,
+	0x0bc70000, 0x1246fe61, 0xfe47f5f3, 0xef0c004d,
+	0x05e305e3, 0x004def0c, 0xf5f3fe47, 0xfe611246,
+	0x00000bc7, 0xfe611246, 0xf5f3fe47, 0x004def0c,
+	0x05e305e3, 0xef0c004d, 0xfe47f5f3, 0x1246fe61,
+	0x0bc70000, 0x1246fe61, 0xfe47f5f3, 0xef0c004d,
+	0xfa58fa58, 0xf895043b, 0xff4c09c0, 0xfbc6ffa8,
+	0xfb84f384, 0x0798f6f9, 0x05760122, 0x058409f6,
+	0x0b500000, 0x05b7f542, 0x08860432, 0x06ddfee7,
+	0xfb84f384, 0xf9d90664, 0xf7e8025c, 0x00fff7bd,
+	0x05a805a8, 0xf7bd00ff, 0x025cf7e8, 0x0664f9d9,
+	0xf384fb84, 0xfee706dd, 0x04320886, 0xf54205b7,
+	0x00000b50, 0x09f60584, 0x01220576, 0xf6f90798,
+	0xf384fb84, 0xffa8fbc6, 0x09c0ff4c, 0x043bf895,
+	0x02d402d4, 0x07de0270, 0xfc96079c, 0xf90afe94,
+	0xfe00ff2c, 0x02d4065d, 0x092a0096, 0x0014fbb8,
+	0xfd2cfd2c, 0x076afb3c, 0x0096f752, 0xf991fd87,
+	0xfb2c0200, 0xfeb8f960, 0x08e0fc96, 0x049802a8,
+	0xfd2cfd2c, 0x02a80498, 0xfc9608e0, 0xf960feb8,
+	0x0200fb2c, 0xfd87f991, 0xf7520096, 0xfb3c076a,
+	0xfd2cfd2c, 0xfbb80014, 0x0096092a, 0x065d02d4,
+	0xff2cfe00, 0xfe94f90a, 0x079cfc96, 0x027007de,
+	0x02d402d4, 0x027007de, 0x079cfc96, 0xfe94f90a,
+	0xff2cfe00, 0x065d02d4, 0x0096092a, 0xfbb80014,
+	0xfd2cfd2c, 0xfb3c076a, 0xf7520096, 0xfd87f991,
+	0x0200fb2c, 0xf960feb8, 0xfc9608e0, 0x02a80498,
+	0xfd2cfd2c, 0x049802a8, 0x08e0fc96, 0xfeb8f960,
+	0xfb2c0200, 0xf991fd87, 0x0096f752, 0x076afb3c,
+	0xfd2cfd2c, 0x0014fbb8, 0x092a0096, 0x02d4065d,
+	0xfe00ff2c, 0xf90afe94, 0xfc96079c, 0x07de0270,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x062a0000, 0xfefa0759, 0x08b80908, 0xf396fc2d,
+	0xf9d6045c, 0xfc4ef608, 0xf748f596, 0x07b207bf,
+	0x062a062a, 0xf84ef841, 0xf748f596, 0x03b209f8,
+	0xf9d6045c, 0x0c6a03d3, 0x08b80908, 0x0106f8a7,
+	0x062a0000, 0xfefaf8a7, 0x08b8f6f8, 0xf39603d3,
+	0xf9d6fba4, 0xfc4e09f8, 0xf7480a6a, 0x07b2f841,
+	0x062af9d6, 0xf84e07bf, 0xf7480a6a, 0x03b2f608,
+	0xf9d6fba4, 0x0c6afc2d, 0x08b8f6f8, 0x01060759,
+	0x062a0000, 0xfefa0759, 0x08b80908, 0xf396fc2d,
+	0xf9d6045c, 0xfc4ef608, 0xf748f596, 0x07b207bf,
+	0x062a062a, 0xf84ef841, 0xf748f596, 0x03b209f8,
+	0xf9d6045c, 0x0c6a03d3, 0x08b80908, 0x0106f8a7,
+	0x062a0000, 0xfefaf8a7, 0x08b8f6f8, 0xf39603d3,
+	0xf9d6fba4, 0xfc4e09f8, 0xf7480a6a, 0x07b2f841,
+	0x062af9d6, 0xf84e07bf, 0xf7480a6a, 0x03b2f608,
+	0xf9d6fba4, 0x0c6afc2d, 0x08b8f6f8, 0x01060759,
+	0x061c061c, 0xff30009d, 0xffb21141, 0xfd87fb54,
+	0xf65dfe59, 0x02eef99e, 0x0166f03c, 0xfff809b6,
+	0x000008a4, 0x000af42b, 0x00eff577, 0xfa840bf2,
+	0xfc02ff51, 0x08260f67, 0xfff0036f, 0x0842f9c3,
+	0x00000000, 0x063df7be, 0xfc910010, 0xf099f7da,
+	0x00af03fe, 0xf40e057c, 0x0a89ff11, 0x0bd5fff6,
+	0xf75c0000, 0xf64a0008, 0x0fc4fe9a, 0x0662fd12,
+	0x01a709a3, 0x04ac0279, 0xeebf004e, 0xff6300d0,
+	0xf9e4f9e4, 0x00d0ff63, 0x004eeebf, 0x027904ac,
+	0x09a301a7, 0xfd120662, 0xfe9a0fc4, 0x0008f64a,
+	0x0000f75c, 0xfff60bd5, 0xff110a89, 0x057cf40e,
+	0x03fe00af, 0xf7daf099, 0x0010fc91, 0xf7be063d,
+	0x00000000, 0xf9c30842, 0x036ffff0, 0x0f670826,
+	0xff51fc02, 0x0bf2fa84, 0xf57700ef, 0xf42b000a,
+	0x08a40000, 0x09b6fff8, 0xf03c0166, 0xf99e02ee,
+	0xfe59f65d, 0xfb54fd87, 0x1141ffb2, 0x009dff30,
+	0x05e30000, 0xff060705, 0x085408a0, 0xf425fc59,
+	0xfa1d042a, 0xfc78f67a, 0xf7acf60e, 0x075a0766,
+	0x05e305e3, 0xf8a6f89a, 0xf7acf60e, 0x03880986,
+	0xfa1d042a, 0x0bdb03a7, 0x085408a0, 0x00faf8fb,
+	0x05e30000, 0xff06f8fb, 0x0854f760, 0xf42503a7,
+	0xfa1dfbd6, 0xfc780986, 0xf7ac09f2, 0x075af89a,
+	0x05e3fa1d, 0xf8a60766, 0xf7ac09f2, 0x0388f67a,
+	0xfa1dfbd6, 0x0bdbfc59, 0x0854f760, 0x00fa0705,
+	0x05e30000, 0xff060705, 0x085408a0, 0xf425fc59,
+	0xfa1d042a, 0xfc78f67a, 0xf7acf60e, 0x075a0766,
+	0x05e305e3, 0xf8a6f89a, 0xf7acf60e, 0x03880986,
+	0xfa1d042a, 0x0bdb03a7, 0x085408a0, 0x00faf8fb,
+	0x05e30000, 0xff06f8fb, 0x0854f760, 0xf42503a7,
+	0xfa1dfbd6, 0xfc780986, 0xf7ac09f2, 0x075af89a,
+	0x05e3fa1d, 0xf8a60766, 0xf7ac09f2, 0x0388f67a,
+	0xfa1dfbd6, 0x0bdbfc59, 0x0854f760, 0x00fa0705,
+	0xfa58fa58, 0xf8f0fe00, 0x0448073d, 0xfdc9fe46,
+	0xf9910258, 0x089d0407, 0xfd5cf71a, 0x02affde0,
+	0x083e0496, 0xff5a0740, 0xff7afd97, 0x00fe01f1,
+	0x0009082e, 0xfa94ff75, 0xfecdf8ea, 0xffb0f693,
+	0xfd2cfa58, 0x0433ff16, 0xfba405dd, 0xfa610341,
+	0x06a606cb, 0x0039fd2d, 0x0677fa97, 0x01fa05e0,
+	0xf896003e, 0x075a068b, 0x012cfc3e, 0xfa23f98d,
+	0xfc7cfd43, 0xff90fc0d, 0x01c10982, 0x00c601d6,
+	0xfd2cfd2c, 0x01d600c6, 0x098201c1, 0xfc0dff90,
+	0xfd43fc7c, 0xf98dfa23, 0xfc3e012c, 0x068b075a,
+	0x003ef896, 0x05e001fa, 0xfa970677, 0xfd2d0039,
+	0x06cb06a6, 0x0341fa61, 0x05ddfba4, 0xff160433,
+	0xfa58fd2c, 0xf693ffb0, 0xf8eafecd, 0xff75fa94,
+	0x082e0009, 0x01f100fe, 0xfd97ff7a, 0x0740ff5a,
+	0x0496083e, 0xfde002af, 0xf71afd5c, 0x0407089d,
+	0x0258f991, 0xfe46fdc9, 0x073d0448, 0xfe00f8f0,
+	0xfd2cfd2c, 0xfce00500, 0xfc09fddc, 0xfe680157,
+	0x04c70571, 0xfc3aff21, 0xfcd70228, 0x056d0277,
+	0x0200fe00, 0x0022f927, 0xfe3c032b, 0xfc44ff3c,
+	0x03e9fbdb, 0x04570313, 0x04c9ff5c, 0x000d03b8,
+	0xfa580000, 0xfbe900d2, 0xf9d0fe0b, 0x0125fdf9,
+	0x042501bf, 0x0328fa2b, 0xffa902f0, 0xfa250157,
+	0x0200fe00, 0x03740438, 0xff0405fd, 0x030cfe52,
+	0x0037fb39, 0xff6904c5, 0x04f8fd23, 0xfd31fc1b,
+	0xfd2cfd2c, 0xfc1bfd31, 0xfd2304f8, 0x04c5ff69,
+	0xfb390037, 0xfe52030c, 0x05fdff04, 0x04380374,
+	0xfe000200, 0x0157fa25, 0x02f0ffa9, 0xfa2b0328,
+	0x01bf0425, 0xfdf90125, 0xfe0bf9d0, 0x00d2fbe9,
+	0x0000fa58, 0x03b8000d, 0xff5c04c9, 0x03130457,
+	0xfbdb03e9, 0xff3cfc44, 0x032bfe3c, 0xf9270022,
+	0xfe000200, 0x0277056d, 0x0228fcd7, 0xff21fc3a,
+	0x057104c7, 0x0157fe68, 0xfddcfc09, 0x0500fce0,
+	0xfd2cfd2c, 0x0500fce0, 0xfddcfc09, 0x0157fe68,
+	0x057104c7, 0xff21fc3a, 0x0228fcd7, 0x0277056d,
+	0xfe000200, 0xf9270022, 0x032bfe3c, 0xff3cfc44,
+	0xfbdb03e9, 0x03130457, 0xff5c04c9, 0x03b8000d,
+	0x0000fa58, 0x00d2fbe9, 0xfe0bf9d0, 0xfdf90125,
+	0x01bf0425, 0xfa2b0328, 0x02f0ffa9, 0x0157fa25,
+	0xfe000200, 0x04380374, 0x05fdff04, 0xfe52030c,
+	0xfb390037, 0x04c5ff69, 0xfd2304f8, 0xfc1bfd31,
+	0xfd2cfd2c, 0xfd31fc1b, 0x04f8fd23, 0xff6904c5,
+	0x0037fb39, 0x030cfe52, 0xff0405fd, 0x03740438,
+	0x0200fe00, 0xfa250157, 0xffa902f0, 0x0328fa2b,
+	0x042501bf, 0x0125fdf9, 0xf9d0fe0b, 0xfbe900d2,
+	0xfa580000, 0x000d03b8, 0x04c9ff5c, 0x04570313,
+	0x03e9fbdb, 0xfc44ff3c, 0xfe3c032b, 0x0022f927,
+	0x0200fe00, 0x056d0277, 0xfcd70228, 0xfc3aff21,
+	0x04c70571, 0xfe680157, 0xfc09fddc, 0xfce00500,
+	0x05a80000, 0xff1006be, 0x0800084a, 0xf49cfc7e,
+	0xfa580400, 0xfc9cf6da, 0xf800f672, 0x0710071c,
+	0x05a805a8, 0xf8f0f8e4, 0xf800f672, 0x03640926,
+	0xfa580400, 0x0b640382, 0x0800084a, 0x00f0f942,
+	0x05a80000, 0xff10f942, 0x0800f7b6, 0xf49c0382,
+	0xfa58fc00, 0xfc9c0926, 0xf800098e, 0x0710f8e4,
+	0x05a8fa58, 0xf8f0071c, 0xf800098e, 0x0364f6da,
+	0xfa58fc00, 0x0b64fc7e, 0x0800f7b6, 0x00f006be,
+	0x05a80000, 0xff1006be, 0x0800084a, 0xf49cfc7e,
+	0xfa580400, 0xfc9cf6da, 0xf800f672, 0x0710071c,
+	0x05a805a8, 0xf8f0f8e4, 0xf800f672, 0x03640926,
+	0xfa580400, 0x0b640382, 0x0800084a, 0x00f0f942,
+	0x05a80000, 0xff10f942, 0x0800f7b6, 0xf49c0382,
+	0xfa58fc00, 0xfc9c0926, 0xf800098e, 0x0710f8e4,
+	0x05a8fa58, 0xf8f0071c, 0xf800098e, 0x0364f6da,
+	0xfa58fc00, 0x0b64fc7e, 0x0800f7b6, 0x00f006be,
+};
+
+static const u32 b43_ntab_noisevar_r3[] = {
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+};
+
+static const u16 b43_ntab_mcs_r3[] = {
+	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 u32 b43_ntab_tdi20a0_r3[] = {
+	0x00091226, 0x000a1429, 0x000b56ad, 0x000c58b0,
+	0x000d5ab3, 0x000e9cb6, 0x000f9eba, 0x0000c13d,
+	0x00020301, 0x00030504, 0x00040708, 0x0005090b,
+	0x00064b8e, 0x00095291, 0x000a5494, 0x000b9718,
+	0x000c9927, 0x000d9b2a, 0x000edd2e, 0x000fdf31,
+	0x000101b4, 0x000243b7, 0x000345bb, 0x000447be,
+	0x00058982, 0x00068c05, 0x00099309, 0x000a950c,
+	0x000bd78f, 0x000cd992, 0x000ddb96, 0x000f1d99,
+	0x00005fa8, 0x0001422c, 0x0002842f, 0x00038632,
+	0x00048835, 0x0005ca38, 0x0006ccbc, 0x0009d3bf,
+	0x000b1603, 0x000c1806, 0x000d1a0a, 0x000e1c0d,
+	0x000f5e10, 0x00008093, 0x00018297, 0x0002c49a,
+	0x0003c680, 0x0004c880, 0x00060b00, 0x00070d00,
+	0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_ntab_tdi20a1_r3[] = {
+	0x00014b26, 0x00028d29, 0x000393ad, 0x00049630,
+	0x0005d833, 0x0006da36, 0x00099c3a, 0x000a9e3d,
+	0x000bc081, 0x000cc284, 0x000dc488, 0x000f068b,
+	0x0000488e, 0x00018b91, 0x0002d214, 0x0003d418,
+	0x0004d6a7, 0x000618aa, 0x00071aae, 0x0009dcb1,
+	0x000b1eb4, 0x000c0137, 0x000d033b, 0x000e053e,
+	0x000f4702, 0x00008905, 0x00020c09, 0x0003128c,
+	0x0004148f, 0x00051712, 0x00065916, 0x00091b19,
+	0x000a1d28, 0x000b5f2c, 0x000c41af, 0x000d43b2,
+	0x000e85b5, 0x000f87b8, 0x0000c9bc, 0x00024cbf,
+	0x00035303, 0x00045506, 0x0005978a, 0x0006998d,
+	0x00095b90, 0x000a5d93, 0x000b9f97, 0x000c821a,
+	0x000d8400, 0x000ec600, 0x000fc800, 0x00010a00,
+	0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_ntab_tdi40a0_r3[] = {
+	0x0011a346, 0x00136ccf, 0x0014f5d9, 0x001641e2,
+	0x0017cb6b, 0x00195475, 0x001b2383, 0x001cad0c,
+	0x001e7616, 0x0000821f, 0x00020ba8, 0x0003d4b2,
+	0x00056447, 0x00072dd0, 0x0008b6da, 0x000a02e3,
+	0x000b8c6c, 0x000d15f6, 0x0011e484, 0x0013ae0d,
+	0x00153717, 0x00168320, 0x00180ca9, 0x00199633,
+	0x001b6548, 0x001ceed1, 0x001eb7db, 0x0000c3e4,
+	0x00024d6d, 0x000416f7, 0x0005a585, 0x00076f0f,
+	0x0008f818, 0x000a4421, 0x000bcdab, 0x000d9734,
+	0x00122649, 0x0013efd2, 0x001578dc, 0x0016c4e5,
+	0x00184e6e, 0x001a17f8, 0x001ba686, 0x001d3010,
+	0x001ef999, 0x00010522, 0x00028eac, 0x00045835,
+	0x0005e74a, 0x0007b0d3, 0x00093a5d, 0x000a85e6,
+	0x000c0f6f, 0x000dd8f9, 0x00126787, 0x00143111,
+	0x0015ba9a, 0x00170623, 0x00188fad, 0x001a5936,
+	0x001be84b, 0x001db1d4, 0x001f3b5e, 0x000146e7,
+	0x00031070, 0x000499fa, 0x00062888, 0x0007f212,
+	0x00097b9b, 0x000ac7a4, 0x000c50ae, 0x000e1a37,
+	0x0012a94c, 0x001472d5, 0x0015fc5f, 0x00174868,
+	0x0018d171, 0x001a9afb, 0x001c2989, 0x001df313,
+	0x001f7c9c, 0x000188a5, 0x000351af, 0x0004db38,
+	0x0006aa4d, 0x000833d7, 0x0009bd60, 0x000b0969,
+	0x000c9273, 0x000e5bfc, 0x00132a8a, 0x0014b414,
+	0x00163d9d, 0x001789a6, 0x001912b0, 0x001adc39,
+	0x001c6bce, 0x001e34d8, 0x001fbe61, 0x0001ca6a,
+	0x00039374, 0x00051cfd, 0x0006ec0b, 0x00087515,
+	0x0009fe9e, 0x000b4aa7, 0x000cd3b1, 0x000e9d3a,
+	0x00000000, 0x00000000,
+};
+
+static const u32 b43_ntab_tdi40a1_r3[] = {
+	0x001edb36, 0x000129ca, 0x0002b353, 0x00047cdd,
+	0x0005c8e6, 0x000791ef, 0x00091bf9, 0x000aaa07,
+	0x000c3391, 0x000dfd1a, 0x00120923, 0x0013d22d,
+	0x00155c37, 0x0016eacb, 0x00187454, 0x001a3dde,
+	0x001b89e7, 0x001d12f0, 0x001f1cfa, 0x00016b88,
+	0x00033492, 0x0004be1b, 0x00060a24, 0x0007d32e,
+	0x00095d38, 0x000aec4c, 0x000c7555, 0x000e3edf,
+	0x00124ae8, 0x001413f1, 0x0015a37b, 0x00172c89,
+	0x0018b593, 0x001a419c, 0x001bcb25, 0x001d942f,
+	0x001f63b9, 0x0001ad4d, 0x00037657, 0x0004c260,
+	0x00068be9, 0x000814f3, 0x0009a47c, 0x000b2d8a,
+	0x000cb694, 0x000e429d, 0x00128c26, 0x001455b0,
+	0x0015e4ba, 0x00176e4e, 0x0018f758, 0x001a8361,
+	0x001c0cea, 0x001dd674, 0x001fa57d, 0x0001ee8b,
+	0x0003b795, 0x0005039e, 0x0006cd27, 0x000856b1,
+	0x0009e5c6, 0x000b6f4f, 0x000cf859, 0x000e8462,
+	0x00130deb, 0x00149775, 0x00162603, 0x0017af8c,
+	0x00193896, 0x001ac49f, 0x001c4e28, 0x001e17b2,
+	0x0000a6c7, 0x00023050, 0x0003f9da, 0x00054563,
+	0x00070eec, 0x00089876, 0x000a2704, 0x000bb08d,
+	0x000d3a17, 0x001185a0, 0x00134f29, 0x0014d8b3,
+	0x001667c8, 0x0017f151, 0x00197adb, 0x001b0664,
+	0x001c8fed, 0x001e5977, 0x0000e805, 0x0002718f,
+	0x00043b18, 0x000586a1, 0x0007502b, 0x0008d9b4,
+	0x000a68c9, 0x000bf252, 0x000dbbdc, 0x0011c7e5,
+	0x001390ee, 0x00151a78, 0x0016a906, 0x00183290,
+	0x0019bc19, 0x001b4822, 0x001cd12c, 0x001e9ab5,
+	0x00000000, 0x00000000,
+};
+
+static const u32 b43_ntab_pilotlt_r3[] = {
+	0x76540213, 0x62407351, 0x76543210, 0x76540213,
+	0x76540213, 0x76430521,
+};
+
+static const u32 b43_ntab_channelest_r3[] = {
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+};
+
+static const u8 b43_ntab_framelookup_r3[] = {
+	0x02, 0x04, 0x14, 0x14, 0x03, 0x05, 0x16, 0x16,
+	0x0a, 0x0c, 0x1c, 0x1c, 0x0b, 0x0d, 0x1e, 0x1e,
+	0x06, 0x08, 0x18, 0x18, 0x07, 0x09, 0x1a, 0x1a,
+	0x0e, 0x10, 0x20, 0x28, 0x0f, 0x11, 0x22, 0x2a,
+};
+
+static const u8 b43_ntab_estimatepowerlt0_r3[] = {
+	0x55, 0x54, 0x54, 0x53, 0x52, 0x52, 0x51, 0x51,
+	0x50, 0x4f, 0x4f, 0x4e, 0x4e, 0x4d, 0x4c, 0x4c,
+	0x4b, 0x4a, 0x49, 0x49, 0x48, 0x47, 0x46, 0x46,
+	0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x40, 0x3f,
+	0x3e, 0x3d, 0x3c, 0x3a, 0x39, 0x38, 0x37, 0x36,
+	0x35, 0x33, 0x32, 0x31, 0x2f, 0x2e, 0x2c, 0x2b,
+	0x29, 0x27, 0x25, 0x23, 0x21, 0x1f, 0x1d, 0x1a,
+	0x18, 0x15, 0x12, 0x0e, 0x0b, 0x07, 0x02, 0xfd,
+};
+
+static const u8 b43_ntab_estimatepowerlt1_r3[] = {
+	0x55, 0x54, 0x54, 0x53, 0x52, 0x52, 0x51, 0x51,
+	0x50, 0x4f, 0x4f, 0x4e, 0x4e, 0x4d, 0x4c, 0x4c,
+	0x4b, 0x4a, 0x49, 0x49, 0x48, 0x47, 0x46, 0x46,
+	0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x40, 0x3f,
+	0x3e, 0x3d, 0x3c, 0x3a, 0x39, 0x38, 0x37, 0x36,
+	0x35, 0x33, 0x32, 0x31, 0x2f, 0x2e, 0x2c, 0x2b,
+	0x29, 0x27, 0x25, 0x23, 0x21, 0x1f, 0x1d, 0x1a,
+	0x18, 0x15, 0x12, 0x0e, 0x0b, 0x07, 0x02, 0xfd,
+};
+
+static const u8 b43_ntab_adjustpower0_r3[] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const u8 b43_ntab_adjustpower1_r3[] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const u32 b43_ntab_gainctl0_r3[] = {
+	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_ntab_gainctl1_r3[] = {
+	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_ntab_iqlt0_r3[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	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_ntab_iqlt1_r3[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	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_ntab_loftlt0_r3[] = {
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 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_ntab_loftlt1_r3[] = {
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000,
+};
+
+/* volatile  tables, PHY revision >= 3 */
+
+/* indexed by antswctl2g */
+static const u16 b43_ntab_antswctl_r3[4][32] = {
+	{
+		0x0082, 0x0082, 0x0211, 0x0222, 0x0328,
+		0x0000, 0x0000, 0x0000, 0x0144, 0x0000,
+		0x0000, 0x0000, 0x0188, 0x0000, 0x0000,
+		0x0000, 0x0082, 0x0082, 0x0211, 0x0222,
+		0x0328, 0x0000, 0x0000, 0x0000, 0x0144,
+		0x0000, 0x0000, 0x0000, 0x0188, 0x0000,
+		0x0000, 0x0000,
+	},
+	{
+		0x0022, 0x0022, 0x0011, 0x0022, 0x0022,
+		0x0000, 0x0000, 0x0000, 0x0011, 0x0000,
+		0x0000, 0x0000, 0x0022, 0x0000, 0x0000,
+		0x0000, 0x0022, 0x0022, 0x0011, 0x0022,
+		0x0022, 0x0000, 0x0000, 0x0000, 0x0011,
+		0x0000, 0x0000, 0x0000, 0x0022, 0x0000,
+		0x0000, 0x0000,
+	},
+	{
+		0x0088, 0x0088, 0x0044, 0x0088, 0x0088,
+		0x0000, 0x0000, 0x0000, 0x0044, 0x0000,
+		0x0000, 0x0000, 0x0088, 0x0000, 0x0000,
+		0x0000, 0x0088, 0x0088, 0x0044, 0x0088,
+		0x0088, 0x0000, 0x0000, 0x0000, 0x0044,
+		0x0000, 0x0000, 0x0000, 0x0088, 0x0000,
+		0x0000, 0x0000,
+	},
+	{
+		0x0022, 0x0022, 0x0011, 0x0022, 0x0000,
+		0x0000, 0x0000, 0x0000, 0x0011, 0x0000,
+		0x0000, 0x0000, 0x0022, 0x0000, 0x0000,
+		0x03cc, 0x0022, 0x0022, 0x0011, 0x0022,
+		0x0000, 0x0000, 0x0000, 0x0000, 0x0011,
+		0x0000, 0x0000, 0x0000, 0x0022, 0x0000,
+		0x0000, 0x03cc,
+	}
+};
+
+/* static tables, PHY revision >= 7 */
+
+/* Copied from brcmsmac (5.75.11) */
+static const u32 b43_ntab_tmap_r7[] = {
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0xf1111110, 0x11111111, 0x11f11111, 0x00000111,
+	0x11000000, 0x1111f111, 0x11111111, 0x111111f1,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x000aa888,
+	0x88880000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+	0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+	0xa2222220, 0x22222222, 0x22c22222, 0x00000222,
+	0x22000000, 0x2222a222, 0x22222222, 0x222222a2,
+	0xf1111110, 0x11111111, 0x11f11111, 0x00011111,
+	0x11110000, 0x1111f111, 0x11111111, 0x111111f1,
+	0xa8aa88a0, 0xa88888a8, 0xa8a8a88a, 0x00088aaa,
+	0xaaaa0000, 0xa8a8aa88, 0xa88aaaaa, 0xaaaa8a8a,
+	0xaaa8aaa0, 0x8aaa8aaa, 0xaa8a8a8a, 0x000aaa88,
+	0x8aaa0000, 0xaaa8a888, 0x8aa88a8a, 0x8a88a888,
+	0x08080a00, 0x0a08080a, 0x080a0a08, 0x00080808,
+	0x080a0000, 0x080a0808, 0x080a0808, 0x0a0a0a08,
+	0xa0a0a0a0, 0x80a0a080, 0x8080a0a0, 0x00008080,
+	0x80a00000, 0x80a080a0, 0xa080a0a0, 0x8080a0a0,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x99999000, 0x9b9b99bb, 0x9bb99999, 0x9999b9b9,
+	0x9b99bb90, 0x9bbbbb9b, 0x9b9b9bb9, 0x00000999,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00aaa888,
+	0x22000000, 0x2222b222, 0x22222222, 0x222222b2,
+	0xb2222220, 0x22222222, 0x22d22222, 0x00000222,
+	0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+	0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+	0x33000000, 0x3333b333, 0x33333333, 0x333333b3,
+	0xb3333330, 0x33333333, 0x33d33333, 0x00000333,
+	0x22000000, 0x2222a222, 0x22222222, 0x222222a2,
+	0xa2222220, 0x22222222, 0x22c22222, 0x00000222,
+	0x99b99b00, 0x9b9b99bb, 0x9bb99999, 0x9999b9b9,
+	0x9b99bb99, 0x9bbbbb9b, 0x9b9b9bb9, 0x00000999,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa88, 0x8aaaaa8a, 0x8a8a8aa8, 0x08aaa888,
+	0x22222200, 0x2222f222, 0x22222222, 0x222222f2,
+	0x22222222, 0x22222222, 0x22f22222, 0x00000222,
+	0x11000000, 0x1111f111, 0x11111111, 0x11111111,
+	0xf1111111, 0x11111111, 0x11f11111, 0x01111111,
+	0xbb9bb900, 0xb9b9bb99, 0xb99bbbbb, 0xbbbb9b9b,
+	0xb9bb99bb, 0xb99999b9, 0xb9b9b99b, 0x00000bbb,
+	0xaa000000, 0xa8a8aa88, 0xa88aaaaa, 0xaaaa8a8a,
+	0xa8aa88aa, 0xa88888a8, 0xa8a8a88a, 0x0a888aaa,
+	0xaa000000, 0xa8a8aa88, 0xa88aaaaa, 0xaaaa8a8a,
+	0xa8aa88a0, 0xa88888a8, 0xa8a8a88a, 0x00000aaa,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0xbbbbbb00, 0x999bbbbb, 0x9bb99b9b, 0xb9b9b9bb,
+	0xb9b99bbb, 0xb9b9b9bb, 0xb9bb9b99, 0x00000999,
+	0x8a000000, 0xaa88a888, 0xa88888aa, 0xa88a8a88,
+	0xa88aa88a, 0x88a8aaaa, 0xa8aa8aaa, 0x0888a88a,
+	0x0b0b0b00, 0x090b0b0b, 0x0b090b0b, 0x0909090b,
+	0x09090b0b, 0x09090b0b, 0x09090b09, 0x00000909,
+	0x0a000000, 0x0a080808, 0x080a080a, 0x080a0a08,
+	0x080a080a, 0x0808080a, 0x0a0a0a08, 0x0808080a,
+	0xb0b0b000, 0x9090b0b0, 0x90b09090, 0xb0b0b090,
+	0xb0b090b0, 0x90b0b0b0, 0xb0b09090, 0x00000090,
+	0x80000000, 0xa080a080, 0xa08080a0, 0xa0808080,
+	0xa080a080, 0x80a0a0a0, 0xa0a080a0, 0x00a0a0a0,
+	0x22000000, 0x2222f222, 0x22222222, 0x222222f2,
+	0xf2222220, 0x22222222, 0x22f22222, 0x00000222,
+	0x11000000, 0x1111f111, 0x11111111, 0x111111f1,
+	0xf1111110, 0x11111111, 0x11f11111, 0x00000111,
+	0x33000000, 0x3333f333, 0x33333333, 0x333333f3,
+	0xf3333330, 0x33333333, 0x33f33333, 0x00000333,
+	0x22000000, 0x2222f222, 0x22222222, 0x222222f2,
+	0xf2222220, 0x22222222, 0x22f22222, 0x00000222,
+	0x99000000, 0x9b9b99bb, 0x9bb99999, 0x9999b9b9,
+	0x9b99bb90, 0x9bbbbb9b, 0x9b9b9bb9, 0x00000999,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x88888000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00aaa888,
+	0x88a88a00, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa88, 0x8aaaaa8a, 0x8a8a8aa8, 0x000aa888,
+	0x88880000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa88, 0x8aaaaa8a, 0x8a8a8aa8, 0x08aaa888,
+	0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+	0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+	0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+	0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+/* Extracted from MMIO dump of 6.30.223.141 */
+static const u32 b43_ntab_noisevar_r7[] = {
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+	0x020c020c, 0x0000014d, 0x020c020c, 0x0000014d,
+};
+
+/**************************************************
+ * TX gain tables
+ **************************************************/
+
+static const u32 b43_ntab_tx_gain_rev0_1_2[] = {
+	0x03cc2b44, 0x03cc2b42, 0x03cc2a44, 0x03cc2a42,
+	0x03cc2944, 0x03c82b44, 0x03c82b42, 0x03c82a44,
+	0x03c82a42, 0x03c82944, 0x03c82942, 0x03c82844,
+	0x03c82842, 0x03c42b44, 0x03c42b42, 0x03c42a44,
+	0x03c42a42, 0x03c42944, 0x03c42942, 0x03c42844,
+	0x03c42842, 0x03c42744, 0x03c42742, 0x03c42644,
+	0x03c42642, 0x03c42544, 0x03c42542, 0x03c42444,
+	0x03c42442, 0x03c02b44, 0x03c02b42, 0x03c02a44,
+	0x03c02a42, 0x03c02944, 0x03c02942, 0x03c02844,
+	0x03c02842, 0x03c02744, 0x03c02742, 0x03b02b44,
+	0x03b02b42, 0x03b02a44, 0x03b02a42, 0x03b02944,
+	0x03b02942, 0x03b02844, 0x03b02842, 0x03b02744,
+	0x03b02742, 0x03b02644, 0x03b02642, 0x03b02544,
+	0x03b02542, 0x03a02b44, 0x03a02b42, 0x03a02a44,
+	0x03a02a42, 0x03a02944, 0x03a02942, 0x03a02844,
+	0x03a02842, 0x03a02744, 0x03a02742, 0x03902b44,
+	0x03902b42, 0x03902a44, 0x03902a42, 0x03902944,
+	0x03902942, 0x03902844, 0x03902842, 0x03902744,
+	0x03902742, 0x03902644, 0x03902642, 0x03902544,
+	0x03902542, 0x03802b44, 0x03802b42, 0x03802a44,
+	0x03802a42, 0x03802944, 0x03802942, 0x03802844,
+	0x03802842, 0x03802744, 0x03802742, 0x03802644,
+	0x03802642, 0x03802544, 0x03802542, 0x03802444,
+	0x03802442, 0x03802344, 0x03802342, 0x03802244,
+	0x03802242, 0x03802144, 0x03802142, 0x03802044,
+	0x03802042, 0x03801f44, 0x03801f42, 0x03801e44,
+	0x03801e42, 0x03801d44, 0x03801d42, 0x03801c44,
+	0x03801c42, 0x03801b44, 0x03801b42, 0x03801a44,
+	0x03801a42, 0x03801944, 0x03801942, 0x03801844,
+	0x03801842, 0x03801744, 0x03801742, 0x03801644,
+	0x03801642, 0x03801544, 0x03801542, 0x03801444,
+	0x03801442, 0x03801344, 0x03801342, 0x00002b00,
+};
+
+/* EPA 2 GHz */
+
+static const u32 b43_ntab_tx_gain_epa_rev3_2g[] = {
+	0x1f410044, 0x1f410042, 0x1f410040, 0x1f41003e,
+	0x1f41003c, 0x1f41003b, 0x1f410039, 0x1f410037,
+	0x1e410044, 0x1e410042, 0x1e410040, 0x1e41003e,
+	0x1e41003c, 0x1e41003b, 0x1e410039, 0x1e410037,
+	0x1d410044, 0x1d410042, 0x1d410040, 0x1d41003e,
+	0x1d41003c, 0x1d41003b, 0x1d410039, 0x1d410037,
+	0x1c410044, 0x1c410042, 0x1c410040, 0x1c41003e,
+	0x1c41003c, 0x1c41003b, 0x1c410039, 0x1c410037,
+	0x1b410044, 0x1b410042, 0x1b410040, 0x1b41003e,
+	0x1b41003c, 0x1b41003b, 0x1b410039, 0x1b410037,
+	0x1a410044, 0x1a410042, 0x1a410040, 0x1a41003e,
+	0x1a41003c, 0x1a41003b, 0x1a410039, 0x1a410037,
+	0x19410044, 0x19410042, 0x19410040, 0x1941003e,
+	0x1941003c, 0x1941003b, 0x19410039, 0x19410037,
+	0x18410044, 0x18410042, 0x18410040, 0x1841003e,
+	0x1841003c, 0x1841003b, 0x18410039, 0x18410037,
+	0x17410044, 0x17410042, 0x17410040, 0x1741003e,
+	0x1741003c, 0x1741003b, 0x17410039, 0x17410037,
+	0x16410044, 0x16410042, 0x16410040, 0x1641003e,
+	0x1641003c, 0x1641003b, 0x16410039, 0x16410037,
+	0x15410044, 0x15410042, 0x15410040, 0x1541003e,
+	0x1541003c, 0x1541003b, 0x15410039, 0x15410037,
+	0x14410044, 0x14410042, 0x14410040, 0x1441003e,
+	0x1441003c, 0x1441003b, 0x14410039, 0x14410037,
+	0x13410044, 0x13410042, 0x13410040, 0x1341003e,
+	0x1341003c, 0x1341003b, 0x13410039, 0x13410037,
+	0x12410044, 0x12410042, 0x12410040, 0x1241003e,
+	0x1241003c, 0x1241003b, 0x12410039, 0x12410037,
+	0x11410044, 0x11410042, 0x11410040, 0x1141003e,
+	0x1141003c, 0x1141003b, 0x11410039, 0x11410037,
+	0x10410044, 0x10410042, 0x10410040, 0x1041003e,
+	0x1041003c, 0x1041003b, 0x10410039, 0x10410037,
+};
+
+static const u32 b43_ntab_tx_gain_epa_rev3_hi_pwr_2g[] = {
+	0x0f410044, 0x0f410042, 0x0f410040, 0x0f41003e,
+	0x0f41003c, 0x0f41003b, 0x0f410039, 0x0f410037,
+	0x0e410044, 0x0e410042, 0x0e410040, 0x0e41003e,
+	0x0e41003c, 0x0e41003b, 0x0e410039, 0x0e410037,
+	0x0d410044, 0x0d410042, 0x0d410040, 0x0d41003e,
+	0x0d41003c, 0x0d41003b, 0x0d410039, 0x0d410037,
+	0x0c410044, 0x0c410042, 0x0c410040, 0x0c41003e,
+	0x0c41003c, 0x0c41003b, 0x0c410039, 0x0c410037,
+	0x0b410044, 0x0b410042, 0x0b410040, 0x0b41003e,
+	0x0b41003c, 0x0b41003b, 0x0b410039, 0x0b410037,
+	0x0a410044, 0x0a410042, 0x0a410040, 0x0a41003e,
+	0x0a41003c, 0x0a41003b, 0x0a410039, 0x0a410037,
+	0x09410044, 0x09410042, 0x09410040, 0x0941003e,
+	0x0941003c, 0x0941003b, 0x09410039, 0x09410037,
+	0x08410044, 0x08410042, 0x08410040, 0x0841003e,
+	0x0841003c, 0x0841003b, 0x08410039, 0x08410037,
+	0x07410044, 0x07410042, 0x07410040, 0x0741003e,
+	0x0741003c, 0x0741003b, 0x07410039, 0x07410037,
+	0x06410044, 0x06410042, 0x06410040, 0x0641003e,
+	0x0641003c, 0x0641003b, 0x06410039, 0x06410037,
+	0x05410044, 0x05410042, 0x05410040, 0x0541003e,
+	0x0541003c, 0x0541003b, 0x05410039, 0x05410037,
+	0x04410044, 0x04410042, 0x04410040, 0x0441003e,
+	0x0441003c, 0x0441003b, 0x04410039, 0x04410037,
+	0x03410044, 0x03410042, 0x03410040, 0x0341003e,
+	0x0341003c, 0x0341003b, 0x03410039, 0x03410037,
+	0x02410044, 0x02410042, 0x02410040, 0x0241003e,
+	0x0241003c, 0x0241003b, 0x02410039, 0x02410037,
+	0x01410044, 0x01410042, 0x01410040, 0x0141003e,
+	0x0141003c, 0x0141003b, 0x01410039, 0x01410037,
+	0x00410044, 0x00410042, 0x00410040, 0x0041003e,
+	0x0041003c, 0x0041003b, 0x00410039, 0x00410037
+};
+
+/* EPA 5 GHz */
+
+static const u32 b43_ntab_tx_gain_epa_rev3_5g[] = {
+	0xcff70044, 0xcff70042, 0xcff70040, 0xcff7003e,
+	0xcff7003c, 0xcff7003b, 0xcff70039, 0xcff70037,
+	0xcef70044, 0xcef70042, 0xcef70040, 0xcef7003e,
+	0xcef7003c, 0xcef7003b, 0xcef70039, 0xcef70037,
+	0xcdf70044, 0xcdf70042, 0xcdf70040, 0xcdf7003e,
+	0xcdf7003c, 0xcdf7003b, 0xcdf70039, 0xcdf70037,
+	0xccf70044, 0xccf70042, 0xccf70040, 0xccf7003e,
+	0xccf7003c, 0xccf7003b, 0xccf70039, 0xccf70037,
+	0xcbf70044, 0xcbf70042, 0xcbf70040, 0xcbf7003e,
+	0xcbf7003c, 0xcbf7003b, 0xcbf70039, 0xcbf70037,
+	0xcaf70044, 0xcaf70042, 0xcaf70040, 0xcaf7003e,
+	0xcaf7003c, 0xcaf7003b, 0xcaf70039, 0xcaf70037,
+	0xc9f70044, 0xc9f70042, 0xc9f70040, 0xc9f7003e,
+	0xc9f7003c, 0xc9f7003b, 0xc9f70039, 0xc9f70037,
+	0xc8f70044, 0xc8f70042, 0xc8f70040, 0xc8f7003e,
+	0xc8f7003c, 0xc8f7003b, 0xc8f70039, 0xc8f70037,
+	0xc7f70044, 0xc7f70042, 0xc7f70040, 0xc7f7003e,
+	0xc7f7003c, 0xc7f7003b, 0xc7f70039, 0xc7f70037,
+	0xc6f70044, 0xc6f70042, 0xc6f70040, 0xc6f7003e,
+	0xc6f7003c, 0xc6f7003b, 0xc6f70039, 0xc6f70037,
+	0xc5f70044, 0xc5f70042, 0xc5f70040, 0xc5f7003e,
+	0xc5f7003c, 0xc5f7003b, 0xc5f70039, 0xc5f70037,
+	0xc4f70044, 0xc4f70042, 0xc4f70040, 0xc4f7003e,
+	0xc4f7003c, 0xc4f7003b, 0xc4f70039, 0xc4f70037,
+	0xc3f70044, 0xc3f70042, 0xc3f70040, 0xc3f7003e,
+	0xc3f7003c, 0xc3f7003b, 0xc3f70039, 0xc3f70037,
+	0xc2f70044, 0xc2f70042, 0xc2f70040, 0xc2f7003e,
+	0xc2f7003c, 0xc2f7003b, 0xc2f70039, 0xc2f70037,
+	0xc1f70044, 0xc1f70042, 0xc1f70040, 0xc1f7003e,
+	0xc1f7003c, 0xc1f7003b, 0xc1f70039, 0xc1f70037,
+	0xc0f70044, 0xc0f70042, 0xc0f70040, 0xc0f7003e,
+	0xc0f7003c, 0xc0f7003b, 0xc0f70039, 0xc0f70037,
+};
+
+static const u32 b43_ntab_tx_gain_epa_rev4_5g[] = {
+	0x2ff20044, 0x2ff20042, 0x2ff20040, 0x2ff2003e,
+	0x2ff2003c, 0x2ff2003b, 0x2ff20039, 0x2ff20037,
+	0x2ef20044, 0x2ef20042, 0x2ef20040, 0x2ef2003e,
+	0x2ef2003c, 0x2ef2003b, 0x2ef20039, 0x2ef20037,
+	0x2df20044, 0x2df20042, 0x2df20040, 0x2df2003e,
+	0x2df2003c, 0x2df2003b, 0x2df20039, 0x2df20037,
+	0x2cf20044, 0x2cf20042, 0x2cf20040, 0x2cf2003e,
+	0x2cf2003c, 0x2cf2003b, 0x2cf20039, 0x2cf20037,
+	0x2bf20044, 0x2bf20042, 0x2bf20040, 0x2bf2003e,
+	0x2bf2003c, 0x2bf2003b, 0x2bf20039, 0x2bf20037,
+	0x2af20044, 0x2af20042, 0x2af20040, 0x2af2003e,
+	0x2af2003c, 0x2af2003b, 0x2af20039, 0x2af20037,
+	0x29f20044, 0x29f20042, 0x29f20040, 0x29f2003e,
+	0x29f2003c, 0x29f2003b, 0x29f20039, 0x29f20037,
+	0x28f20044, 0x28f20042, 0x28f20040, 0x28f2003e,
+	0x28f2003c, 0x28f2003b, 0x28f20039, 0x28f20037,
+	0x27f20044, 0x27f20042, 0x27f20040, 0x27f2003e,
+	0x27f2003c, 0x27f2003b, 0x27f20039, 0x27f20037,
+	0x26f20044, 0x26f20042, 0x26f20040, 0x26f2003e,
+	0x26f2003c, 0x26f2003b, 0x26f20039, 0x26f20037,
+	0x25f20044, 0x25f20042, 0x25f20040, 0x25f2003e,
+	0x25f2003c, 0x25f2003b, 0x25f20039, 0x25f20037,
+	0x24f20044, 0x24f20042, 0x24f20040, 0x24f2003e,
+	0x24f2003c, 0x24f2003b, 0x24f20039, 0x24f20038,
+	0x23f20041, 0x23f20040, 0x23f2003f, 0x23f2003e,
+	0x23f2003c, 0x23f2003b, 0x23f20039, 0x23f20037,
+	0x22f20044, 0x22f20042, 0x22f20040, 0x22f2003e,
+	0x22f2003c, 0x22f2003b, 0x22f20039, 0x22f20037,
+	0x21f20044, 0x21f20042, 0x21f20040, 0x21f2003e,
+	0x21f2003c, 0x21f2003b, 0x21f20039, 0x21f20037,
+	0x20d20043, 0x20d20041, 0x20d2003e, 0x20d2003c,
+	0x20d2003a, 0x20d20038, 0x20d20036, 0x20d20034,
+};
+
+static const u32 b43_ntab_tx_gain_epa_rev4_hi_pwr_5g[] = {
+	0x2ff10044, 0x2ff10042, 0x2ff10040, 0x2ff1003e,
+	0x2ff1003c, 0x2ff1003b, 0x2ff10039, 0x2ff10037,
+	0x2ef10044, 0x2ef10042, 0x2ef10040, 0x2ef1003e,
+	0x2ef1003c, 0x2ef1003b, 0x2ef10039, 0x2ef10037,
+	0x2df10044, 0x2df10042, 0x2df10040, 0x2df1003e,
+	0x2df1003c, 0x2df1003b, 0x2df10039, 0x2df10037,
+	0x2cf10044, 0x2cf10042, 0x2cf10040, 0x2cf1003e,
+	0x2cf1003c, 0x2cf1003b, 0x2cf10039, 0x2cf10037,
+	0x2bf10044, 0x2bf10042, 0x2bf10040, 0x2bf1003e,
+	0x2bf1003c, 0x2bf1003b, 0x2bf10039, 0x2bf10037,
+	0x2af10044, 0x2af10042, 0x2af10040, 0x2af1003e,
+	0x2af1003c, 0x2af1003b, 0x2af10039, 0x2af10037,
+	0x29f10044, 0x29f10042, 0x29f10040, 0x29f1003e,
+	0x29f1003c, 0x29f1003b, 0x29f10039, 0x29f10037,
+	0x28f10044, 0x28f10042, 0x28f10040, 0x28f1003e,
+	0x28f1003c, 0x28f1003b, 0x28f10039, 0x28f10037,
+	0x27f10044, 0x27f10042, 0x27f10040, 0x27f1003e,
+	0x27f1003c, 0x27f1003b, 0x27f10039, 0x27f10037,
+	0x26f10044, 0x26f10042, 0x26f10040, 0x26f1003e,
+	0x26f1003c, 0x26f1003b, 0x26f10039, 0x26f10037,
+	0x25f10044, 0x25f10042, 0x25f10040, 0x25f1003e,
+	0x25f1003c, 0x25f1003b, 0x25f10039, 0x25f10037,
+	0x24f10044, 0x24f10042, 0x24f10040, 0x24f1003e,
+	0x24f1003c, 0x24f1003b, 0x24f10039, 0x24f10038,
+	0x23f10041, 0x23f10040, 0x23f1003f, 0x23f1003e,
+	0x23f1003c, 0x23f1003b, 0x23f10039, 0x23f10037,
+	0x22f10044, 0x22f10042, 0x22f10040, 0x22f1003e,
+	0x22f1003c, 0x22f1003b, 0x22f10039, 0x22f10037,
+	0x21f10044, 0x21f10042, 0x21f10040, 0x21f1003e,
+	0x21f1003c, 0x21f1003b, 0x21f10039, 0x21f10037,
+	0x20d10043, 0x20d10041, 0x20d1003e, 0x20d1003c,
+	0x20d1003a, 0x20d10038, 0x20d10036, 0x20d10034
+};
+
+static const u32 b43_ntab_tx_gain_epa_rev5_5g[] = {
+	0x0f62004a, 0x0f620048, 0x0f620046, 0x0f620044,
+	0x0f620042, 0x0f620040, 0x0f62003e, 0x0f62003c,
+	0x0e620044, 0x0e620042, 0x0e620040, 0x0e62003e,
+	0x0e62003c, 0x0e62003d, 0x0e62003b, 0x0e62003a,
+	0x0d620043, 0x0d620041, 0x0d620040, 0x0d62003e,
+	0x0d62003d, 0x0d62003c, 0x0d62003b, 0x0d62003a,
+	0x0c620041, 0x0c620040, 0x0c62003f, 0x0c62003e,
+	0x0c62003c, 0x0c62003b, 0x0c620039, 0x0c620037,
+	0x0b620046, 0x0b620044, 0x0b620042, 0x0b620040,
+	0x0b62003e, 0x0b62003c, 0x0b62003b, 0x0b62003a,
+	0x0a620041, 0x0a620040, 0x0a62003e, 0x0a62003c,
+	0x0a62003b, 0x0a62003a, 0x0a620039, 0x0a620038,
+	0x0962003e, 0x0962003d, 0x0962003c, 0x0962003b,
+	0x09620039, 0x09620037, 0x09620035, 0x09620033,
+	0x08620044, 0x08620042, 0x08620040, 0x0862003e,
+	0x0862003c, 0x0862003b, 0x0862003a, 0x08620039,
+	0x07620043, 0x07620042, 0x07620040, 0x0762003f,
+	0x0762003d, 0x0762003b, 0x0762003a, 0x07620039,
+	0x0662003e, 0x0662003d, 0x0662003c, 0x0662003b,
+	0x06620039, 0x06620037, 0x06620035, 0x06620033,
+	0x05620046, 0x05620044, 0x05620042, 0x05620040,
+	0x0562003e, 0x0562003c, 0x0562003b, 0x05620039,
+	0x04620044, 0x04620042, 0x04620040, 0x0462003e,
+	0x0462003c, 0x0462003b, 0x04620039, 0x04620038,
+	0x0362003c, 0x0362003b, 0x0362003a, 0x03620039,
+	0x03620038, 0x03620037, 0x03620035, 0x03620033,
+	0x0262004c, 0x0262004a, 0x02620048, 0x02620047,
+	0x02620046, 0x02620044, 0x02620043, 0x02620042,
+	0x0162004a, 0x01620048, 0x01620046, 0x01620044,
+	0x01620043, 0x01620042, 0x01620041, 0x01620040,
+	0x00620042, 0x00620040, 0x0062003e, 0x0062003c,
+	0x0062003b, 0x00620039, 0x00620037, 0x00620035,
+};
+
+/* IPA 2 GHz */
+
+static const u32 b43_ntab_tx_gain_ipa_rev3_2g[] = {
+	0x5ff7002d, 0x5ff7002b, 0x5ff7002a, 0x5ff70029,
+	0x5ff70028, 0x5ff70027, 0x5ff70026, 0x5ff70025,
+	0x5ef7002d, 0x5ef7002b, 0x5ef7002a, 0x5ef70029,
+	0x5ef70028, 0x5ef70027, 0x5ef70026, 0x5ef70025,
+	0x5df7002d, 0x5df7002b, 0x5df7002a, 0x5df70029,
+	0x5df70028, 0x5df70027, 0x5df70026, 0x5df70025,
+	0x5cf7002d, 0x5cf7002b, 0x5cf7002a, 0x5cf70029,
+	0x5cf70028, 0x5cf70027, 0x5cf70026, 0x5cf70025,
+	0x5bf7002d, 0x5bf7002b, 0x5bf7002a, 0x5bf70029,
+	0x5bf70028, 0x5bf70027, 0x5bf70026, 0x5bf70025,
+	0x5af7002d, 0x5af7002b, 0x5af7002a, 0x5af70029,
+	0x5af70028, 0x5af70027, 0x5af70026, 0x5af70025,
+	0x59f7002d, 0x59f7002b, 0x59f7002a, 0x59f70029,
+	0x59f70028, 0x59f70027, 0x59f70026, 0x59f70025,
+	0x58f7002d, 0x58f7002b, 0x58f7002a, 0x58f70029,
+	0x58f70028, 0x58f70027, 0x58f70026, 0x58f70025,
+	0x57f7002d, 0x57f7002b, 0x57f7002a, 0x57f70029,
+	0x57f70028, 0x57f70027, 0x57f70026, 0x57f70025,
+	0x56f7002d, 0x56f7002b, 0x56f7002a, 0x56f70029,
+	0x56f70028, 0x56f70027, 0x56f70026, 0x56f70025,
+	0x55f7002d, 0x55f7002b, 0x55f7002a, 0x55f70029,
+	0x55f70028, 0x55f70027, 0x55f70026, 0x55f70025,
+	0x54f7002d, 0x54f7002b, 0x54f7002a, 0x54f70029,
+	0x54f70028, 0x54f70027, 0x54f70026, 0x54f70025,
+	0x53f7002d, 0x53f7002b, 0x53f7002a, 0x53f70029,
+	0x53f70028, 0x53f70027, 0x53f70026, 0x53f70025,
+	0x52f7002d, 0x52f7002b, 0x52f7002a, 0x52f70029,
+	0x52f70028, 0x52f70027, 0x52f70026, 0x52f70025,
+	0x51f7002d, 0x51f7002b, 0x51f7002a, 0x51f70029,
+	0x51f70028, 0x51f70027, 0x51f70026, 0x51f70025,
+	0x50f7002d, 0x50f7002b, 0x50f7002a, 0x50f70029,
+	0x50f70028, 0x50f70027, 0x50f70026, 0x50f70025,
+};
+
+static const u32 b43_ntab_tx_gain_ipa_rev5_2g[] = {
+	0x1ff7002d, 0x1ff7002b, 0x1ff7002a, 0x1ff70029,
+	0x1ff70028, 0x1ff70027, 0x1ff70026, 0x1ff70025,
+	0x1ef7002d, 0x1ef7002b, 0x1ef7002a, 0x1ef70029,
+	0x1ef70028, 0x1ef70027, 0x1ef70026, 0x1ef70025,
+	0x1df7002d, 0x1df7002b, 0x1df7002a, 0x1df70029,
+	0x1df70028, 0x1df70027, 0x1df70026, 0x1df70025,
+	0x1cf7002d, 0x1cf7002b, 0x1cf7002a, 0x1cf70029,
+	0x1cf70028, 0x1cf70027, 0x1cf70026, 0x1cf70025,
+	0x1bf7002d, 0x1bf7002b, 0x1bf7002a, 0x1bf70029,
+	0x1bf70028, 0x1bf70027, 0x1bf70026, 0x1bf70025,
+	0x1af7002d, 0x1af7002b, 0x1af7002a, 0x1af70029,
+	0x1af70028, 0x1af70027, 0x1af70026, 0x1af70025,
+	0x19f7002d, 0x19f7002b, 0x19f7002a, 0x19f70029,
+	0x19f70028, 0x19f70027, 0x19f70026, 0x19f70025,
+	0x18f7002d, 0x18f7002b, 0x18f7002a, 0x18f70029,
+	0x18f70028, 0x18f70027, 0x18f70026, 0x18f70025,
+	0x17f7002d, 0x17f7002b, 0x17f7002a, 0x17f70029,
+	0x17f70028, 0x17f70027, 0x17f70026, 0x17f70025,
+	0x16f7002d, 0x16f7002b, 0x16f7002a, 0x16f70029,
+	0x16f70028, 0x16f70027, 0x16f70026, 0x16f70025,
+	0x15f7002d, 0x15f7002b, 0x15f7002a, 0x15f70029,
+	0x15f70028, 0x15f70027, 0x15f70026, 0x15f70025,
+	0x14f7002d, 0x14f7002b, 0x14f7002a, 0x14f70029,
+	0x14f70028, 0x14f70027, 0x14f70026, 0x14f70025,
+	0x13f7002d, 0x13f7002b, 0x13f7002a, 0x13f70029,
+	0x13f70028, 0x13f70027, 0x13f70026, 0x13f70025,
+	0x12f7002d, 0x12f7002b, 0x12f7002a, 0x12f70029,
+	0x12f70028, 0x12f70027, 0x12f70026, 0x12f70025,
+	0x11f7002d, 0x11f7002b, 0x11f7002a, 0x11f70029,
+	0x11f70028, 0x11f70027, 0x11f70026, 0x11f70025,
+	0x10f7002d, 0x10f7002b, 0x10f7002a, 0x10f70029,
+	0x10f70028, 0x10f70027, 0x10f70026, 0x10f70025,
+};
+
+static const u32 b43_ntab_tx_gain_ipa_rev6_2g[] = {
+	0x0ff7002d, 0x0ff7002b, 0x0ff7002a, 0x0ff70029,
+	0x0ff70028, 0x0ff70027, 0x0ff70026, 0x0ff70025,
+	0x0ef7002d, 0x0ef7002b, 0x0ef7002a, 0x0ef70029,
+	0x0ef70028, 0x0ef70027, 0x0ef70026, 0x0ef70025,
+	0x0df7002d, 0x0df7002b, 0x0df7002a, 0x0df70029,
+	0x0df70028, 0x0df70027, 0x0df70026, 0x0df70025,
+	0x0cf7002d, 0x0cf7002b, 0x0cf7002a, 0x0cf70029,
+	0x0cf70028, 0x0cf70027, 0x0cf70026, 0x0cf70025,
+	0x0bf7002d, 0x0bf7002b, 0x0bf7002a, 0x0bf70029,
+	0x0bf70028, 0x0bf70027, 0x0bf70026, 0x0bf70025,
+	0x0af7002d, 0x0af7002b, 0x0af7002a, 0x0af70029,
+	0x0af70028, 0x0af70027, 0x0af70026, 0x0af70025,
+	0x09f7002d, 0x09f7002b, 0x09f7002a, 0x09f70029,
+	0x09f70028, 0x09f70027, 0x09f70026, 0x09f70025,
+	0x08f7002d, 0x08f7002b, 0x08f7002a, 0x08f70029,
+	0x08f70028, 0x08f70027, 0x08f70026, 0x08f70025,
+	0x07f7002d, 0x07f7002b, 0x07f7002a, 0x07f70029,
+	0x07f70028, 0x07f70027, 0x07f70026, 0x07f70025,
+	0x06f7002d, 0x06f7002b, 0x06f7002a, 0x06f70029,
+	0x06f70028, 0x06f70027, 0x06f70026, 0x06f70025,
+	0x05f7002d, 0x05f7002b, 0x05f7002a, 0x05f70029,
+	0x05f70028, 0x05f70027, 0x05f70026, 0x05f70025,
+	0x04f7002d, 0x04f7002b, 0x04f7002a, 0x04f70029,
+	0x04f70028, 0x04f70027, 0x04f70026, 0x04f70025,
+	0x03f7002d, 0x03f7002b, 0x03f7002a, 0x03f70029,
+	0x03f70028, 0x03f70027, 0x03f70026, 0x03f70025,
+	0x02f7002d, 0x02f7002b, 0x02f7002a, 0x02f70029,
+	0x02f70028, 0x02f70027, 0x02f70026, 0x02f70025,
+	0x01f7002d, 0x01f7002b, 0x01f7002a, 0x01f70029,
+	0x01f70028, 0x01f70027, 0x01f70026, 0x01f70025,
+	0x00f7002d, 0x00f7002b, 0x00f7002a, 0x00f70029,
+	0x00f70028, 0x00f70027, 0x00f70026, 0x00f70025,
+};
+
+/* Copied from brcmsmac (5.75.11): nphy_tpc_txgain_ipa_2g_2057rev5 */
+static const u32 b43_ntab_tx_gain_ipa_2057_rev5_2g[] = {
+	0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e,
+	0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033,
+	0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e,
+	0x3067002e, 0x305f002f, 0x30570030, 0x3057002d,
+	0x304f002e, 0x30470031, 0x3047002e, 0x3047002c,
+	0x30470029, 0x303f002c, 0x303f0029, 0x3037002d,
+	0x3037002a, 0x30370028, 0x302f002c, 0x302f002a,
+	0x302f0028, 0x302f0026, 0x3027002c, 0x30270029,
+	0x30270027, 0x30270025, 0x30270023, 0x301f002c,
+	0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024,
+	0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b,
+	0x30170028, 0x30170026, 0x30170024, 0x30170022,
+	0x30170020, 0x3017001e, 0x3017001d, 0x3017001b,
+	0x3017001a, 0x30170018, 0x30170017, 0x30170015,
+	0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024,
+	0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d,
+	0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017,
+	0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215,
+	0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+};
+
+/* Extracted from MMIO dump of 6.30.223.141 */
+static const u32 b43_ntab_tx_gain_ipa_2057_rev9_2g[] = {
+	0x60ff0031, 0x60e7002c, 0x60cf002a, 0x60c70029,
+	0x60b70029, 0x60a70029, 0x609f002a, 0x6097002b,
+	0x6087002e, 0x60770031, 0x606f0032, 0x60670034,
+	0x60670031, 0x605f0033, 0x605f0031, 0x60570033,
+	0x60570030, 0x6057002d, 0x6057002b, 0x604f002d,
+	0x604f002b, 0x604f0029, 0x604f0026, 0x60470029,
+	0x60470027, 0x603f0029, 0x603f0027, 0x603f0025,
+	0x60370029, 0x60370027, 0x60370024, 0x602f002a,
+	0x602f0028, 0x602f0026, 0x602f0024, 0x6027002a,
+	0x60270028, 0x60270026, 0x60270024, 0x60270022,
+	0x601f002b, 0x601f0029, 0x601f0027, 0x601f0024,
+	0x601f0022, 0x601f0020, 0x601f001f, 0x601f001d,
+	0x60170029, 0x60170027, 0x60170025, 0x60170023,
+	0x60170021, 0x6017001f, 0x6017001d, 0x6017001c,
+	0x6017001a, 0x60170018, 0x60170018, 0x60170016,
+	0x60170015, 0x600f0029, 0x600f0027, 0x600f0025,
+	0x600f0023, 0x600f0021, 0x600f001f, 0x600f001d,
+	0x600f001c, 0x600f001a, 0x600f0019, 0x600f0018,
+	0x600f0016, 0x600f0015, 0x600f0115, 0x600f0215,
+	0x600f0315, 0x600f0415, 0x600f0515, 0x600f0615,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+	0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
+};
+
+/* Extracted from MMIO dump of 6.30.223.248 */
+static const u32 b43_ntab_tx_gain_ipa_2057_rev14_2g[] = {
+	0x50df002e, 0x50cf002d, 0x50bf002c, 0x50b7002b,
+	0x50af002a, 0x50a70029, 0x509f0029, 0x50970028,
+	0x508f0027, 0x50870027, 0x507f0027, 0x50770027,
+	0x506f0027, 0x50670027, 0x505f0028, 0x50570029,
+	0x504f002b, 0x5047002e, 0x5047002b, 0x50470029,
+	0x503f002c, 0x503f0029, 0x5037002c, 0x5037002a,
+	0x50370028, 0x502f002d, 0x502f002b, 0x502f0028,
+	0x502f0026, 0x5027002d, 0x5027002a, 0x50270028,
+	0x50270026, 0x50270024, 0x501f002e, 0x501f002b,
+	0x501f0029, 0x501f0027, 0x501f0024, 0x501f0022,
+	0x501f0020, 0x501f001f, 0x5017002c, 0x50170029,
+	0x50170027, 0x50170024, 0x50170022, 0x50170021,
+	0x5017001f, 0x5017001d, 0x5017001b, 0x5017001a,
+	0x50170018, 0x50170017, 0x50170015, 0x500f002c,
+	0x500f002a, 0x500f0027, 0x500f0025, 0x500f0023,
+	0x500f0022, 0x500f001f, 0x500f001e, 0x500f001c,
+	0x500f001a, 0x500f0019, 0x500f0018, 0x500f0016,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+	0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
+};
+
+/* IPA 2 5Hz */
+
+static const u32 b43_ntab_tx_gain_ipa_rev3_5g[] = {
+	0x7ff70035, 0x7ff70033, 0x7ff70032, 0x7ff70031,
+	0x7ff7002f, 0x7ff7002e, 0x7ff7002d, 0x7ff7002b,
+	0x7ff7002a, 0x7ff70029, 0x7ff70028, 0x7ff70027,
+	0x7ff70026, 0x7ff70024, 0x7ff70023, 0x7ff70022,
+	0x7ef70028, 0x7ef70027, 0x7ef70026, 0x7ef70025,
+	0x7ef70024, 0x7ef70023, 0x7df70028, 0x7df70027,
+	0x7df70026, 0x7df70025, 0x7df70024, 0x7df70023,
+	0x7df70022, 0x7cf70029, 0x7cf70028, 0x7cf70027,
+	0x7cf70026, 0x7cf70025, 0x7cf70023, 0x7cf70022,
+	0x7bf70029, 0x7bf70028, 0x7bf70026, 0x7bf70025,
+	0x7bf70024, 0x7bf70023, 0x7bf70022, 0x7bf70021,
+	0x7af70029, 0x7af70028, 0x7af70027, 0x7af70026,
+	0x7af70025, 0x7af70024, 0x7af70023, 0x7af70022,
+	0x79f70029, 0x79f70028, 0x79f70027, 0x79f70026,
+	0x79f70025, 0x79f70024, 0x79f70023, 0x79f70022,
+	0x78f70029, 0x78f70028, 0x78f70027, 0x78f70026,
+	0x78f70025, 0x78f70024, 0x78f70023, 0x78f70022,
+	0x77f70029, 0x77f70028, 0x77f70027, 0x77f70026,
+	0x77f70025, 0x77f70024, 0x77f70023, 0x77f70022,
+	0x76f70029, 0x76f70028, 0x76f70027, 0x76f70026,
+	0x76f70024, 0x76f70023, 0x76f70022, 0x76f70021,
+	0x75f70029, 0x75f70028, 0x75f70027, 0x75f70026,
+	0x75f70025, 0x75f70024, 0x75f70023, 0x74f70029,
+	0x74f70028, 0x74f70026, 0x74f70025, 0x74f70024,
+	0x74f70023, 0x74f70022, 0x73f70029, 0x73f70027,
+	0x73f70026, 0x73f70025, 0x73f70024, 0x73f70023,
+	0x73f70022, 0x72f70028, 0x72f70027, 0x72f70026,
+	0x72f70025, 0x72f70024, 0x72f70023, 0x72f70022,
+	0x71f70028, 0x71f70027, 0x71f70026, 0x71f70025,
+	0x71f70024, 0x71f70023, 0x70f70028, 0x70f70027,
+	0x70f70026, 0x70f70024, 0x70f70023, 0x70f70022,
+	0x70f70021, 0x70f70020, 0x70f70020, 0x70f7001f,
+};
+
+/* Extracted from MMIO dump of 6.30.223.141 */
+static const u32 b43_ntab_tx_gain_ipa_2057_rev9_5g[] = {
+	0x7f7f0053, 0x7f7f004b, 0x7f7f0044, 0x7f7f003f,
+	0x7f7f0039, 0x7f7f0035, 0x7f7f0032, 0x7f7f0030,
+	0x7f7f002d, 0x7e7f0030, 0x7e7f002d, 0x7d7f0032,
+	0x7d7f002f, 0x7d7f002c, 0x7c7f0032, 0x7c7f0030,
+	0x7c7f002d, 0x7b7f0030, 0x7b7f002e, 0x7b7f002b,
+	0x7a7f0032, 0x7a7f0030, 0x7a7f002d, 0x7a7f002b,
+	0x797f0030, 0x797f002e, 0x797f002b, 0x797f0029,
+	0x787f0030, 0x787f002d, 0x787f002b, 0x777f0032,
+	0x777f0030, 0x777f002d, 0x777f002b, 0x767f0031,
+	0x767f002f, 0x767f002c, 0x767f002a, 0x757f0031,
+	0x757f002f, 0x757f002c, 0x757f002a, 0x747f0030,
+	0x747f002d, 0x747f002b, 0x737f0032, 0x737f002f,
+	0x737f002c, 0x737f002a, 0x727f0030, 0x727f002d,
+	0x727f002b, 0x727f0029, 0x717f0030, 0x717f002d,
+	0x717f002b, 0x707f0031, 0x707f002f, 0x707f002c,
+	0x707f002a, 0x707f0027, 0x707f0025, 0x707f0023,
+	0x707f0021, 0x707f001f, 0x707f001d, 0x707f001c,
+	0x707f001a, 0x707f0019, 0x707f0017, 0x707f0016,
+	0x707f0015, 0x707f0014, 0x707f0012, 0x707f0012,
+	0x707f0011, 0x707f0010, 0x707f000f, 0x707f000e,
+	0x707f000d, 0x707f000d, 0x707f000c, 0x707f000b,
+	0x707f000a, 0x707f000a, 0x707f0009, 0x707f0008,
+	0x707f0008, 0x707f0008, 0x707f0008, 0x707f0007,
+	0x707f0007, 0x707f0006, 0x707f0006, 0x707f0006,
+	0x707f0005, 0x707f0005, 0x707f0005, 0x707f0004,
+	0x707f0004, 0x707f0004, 0x707f0003, 0x707f0003,
+	0x707f0003, 0x707f0003, 0x707f0003, 0x707f0003,
+	0x707f0003, 0x707f0003, 0x707f0003, 0x707f0003,
+	0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002,
+	0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002,
+	0x707f0002, 0x707f0001, 0x707f0001, 0x707f0001,
+	0x707f0001, 0x707f0001, 0x707f0001, 0x707f0001,
+};
+
+const s8 b43_ntab_papd_pga_gain_delta_ipa_2g[] = {
+	-114, -108, -98, -91, -84, -78, -70, -62,
+	-54, -46, -39, -31, -23, -15, -8, 0
+};
+
+/* Extracted from MMIO dump of 6.30.223.248
+ * Entries: 0, 15, 17, 21, 24, 26, 27, 29, 30 were guessed
+ */
+static const s16 b43_ntab_rf_pwr_offset_2057_rev9_2g[] = {
+	-133, -133, -107, -92, -81,
+	-73, -66, -61, -56, -52,
+	-48, -44, -41, -37, -34,
+	-31, -28, -25, -22, -19,
+	-17, -14, -12, -10, -9,
+	-7, -5, -4, -3, -2,
+	-1, 0,
+};
+
+/* Extracted from MMIO dump of 6.30.223.248 */
+static const s16 b43_ntab_rf_pwr_offset_2057_rev9_5g[] = {
+	-101, -94, -86, -79, -72,
+	-65, -57, -50, -42, -35,
+	-28, -21, -16, -9, -4,
+	0,
+};
+
+/* Extracted from MMIO dump of 6.30.223.248
+ * Entries: 0, 26, 28, 29, 30, 31 were guessed
+ */
+static const s16 b43_ntab_rf_pwr_offset_2057_rev14_2g[] = {
+	-111, -111, -111, -84, -70,
+	-59, -52, -45, -40, -36,
+	-32, -29, -26, -23, -21,
+	-18, -16, -15, -13, -11,
+	-10, -8, -7, -6, -5,
+	-4, -4, -3, -3, -2,
+	-2, -1,
+};
+
+const u16 tbl_iqcal_gainparams[2][9][8] = {
+	{
+		{ 0x000, 0, 0, 2, 0x69, 0x69, 0x69, 0x69 },
+		{ 0x700, 7, 0, 0, 0x69, 0x69, 0x69, 0x69 },
+		{ 0x710, 7, 1, 0, 0x68, 0x68, 0x68, 0x68 },
+		{ 0x720, 7, 2, 0, 0x67, 0x67, 0x67, 0x67 },
+		{ 0x730, 7, 3, 0, 0x66, 0x66, 0x66, 0x66 },
+		{ 0x740, 7, 4, 0, 0x65, 0x65, 0x65, 0x65 },
+		{ 0x741, 7, 4, 1, 0x65, 0x65, 0x65, 0x65 },
+		{ 0x742, 7, 4, 2, 0x65, 0x65, 0x65, 0x65 },
+		{ 0x743, 7, 4, 3, 0x65, 0x65, 0x65, 0x65 }
+	},
+	{
+		{ 0x000, 7, 0, 0, 0x79, 0x79, 0x79, 0x79 },
+		{ 0x700, 7, 0, 0, 0x79, 0x79, 0x79, 0x79 },
+		{ 0x710, 7, 1, 0, 0x79, 0x79, 0x79, 0x79 },
+		{ 0x720, 7, 2, 0, 0x78, 0x78, 0x78, 0x78 },
+		{ 0x730, 7, 3, 0, 0x78, 0x78, 0x78, 0x78 },
+		{ 0x740, 7, 4, 0, 0x78, 0x78, 0x78, 0x78 },
+		{ 0x741, 7, 4, 1, 0x78, 0x78, 0x78, 0x78 },
+		{ 0x742, 7, 4, 2, 0x78, 0x78, 0x78, 0x78 },
+		{ 0x743, 7, 4, 3, 0x78, 0x78, 0x78, 0x78 }
+	}
+};
+
+const struct nphy_txiqcal_ladder ladder_lo[] = {
+	{ 3, 0 },
+	{ 4, 0 },
+	{ 6, 0 },
+	{ 9, 0 },
+	{ 13, 0 },
+	{ 18, 0 },
+	{ 25, 0 },
+	{ 25, 1 },
+	{ 25, 2 },
+	{ 25, 3 },
+	{ 25, 4 },
+	{ 25, 5 },
+	{ 25, 6 },
+	{ 25, 7 },
+	{ 35, 7 },
+	{ 50, 7 },
+	{ 71, 7 },
+	{ 100, 7 }
+};
+
+const struct nphy_txiqcal_ladder ladder_iq[] = {
+	{ 3, 0 },
+	{ 4, 0 },
+	{ 6, 0 },
+	{ 9, 0 },
+	{ 13, 0 },
+	{ 18, 0 },
+	{ 25, 0 },
+	{ 35, 0 },
+	{ 50, 0 },
+	{ 71, 0 },
+	{ 100, 0 },
+	{ 100, 1 },
+	{ 100, 2 },
+	{ 100, 3 },
+	{ 100, 4 },
+	{ 100, 5 },
+	{ 100, 6 },
+	{ 100, 7 }
+};
+
+const u16 loscale[] = {
+	256, 256, 271, 271,
+	287, 256, 256, 271,
+	271, 287, 287, 304,
+	304, 256, 256, 271,
+	271, 287, 287, 304,
+	304, 322, 322, 341,
+	341, 362, 362, 383,
+	383, 256, 256, 271,
+	271, 287, 287, 304,
+	304, 322, 322, 256,
+	256, 271, 271, 287,
+	287, 304, 304, 322,
+	322, 341, 341, 362,
+	362, 256, 256, 271,
+	271, 287, 287, 304,
+	304, 322, 322, 256,
+	256, 271, 271, 287,
+	287, 304, 304, 322,
+	322, 341, 341, 362,
+	362, 256, 256, 271,
+	271, 287, 287, 304,
+	304, 322, 322, 341,
+	341, 362, 362, 383,
+	383, 406, 406, 430,
+	430, 455, 455, 482,
+	482, 511, 511, 541,
+	541, 573, 573, 607,
+	607, 643, 643, 681,
+	681, 722, 722, 764,
+	764, 810, 810, 858,
+	858, 908, 908, 962,
+	962, 1019, 1019, 256
+};
+
+const u16 tbl_tx_iqlo_cal_loft_ladder_40[] = {
+	0x0200, 0x0300, 0x0400, 0x0700,
+	0x0900, 0x0c00, 0x1200, 0x1201,
+	0x1202, 0x1203, 0x1204, 0x1205,
+	0x1206, 0x1207, 0x1907, 0x2307,
+	0x3207, 0x4707
+};
+
+const u16 tbl_tx_iqlo_cal_loft_ladder_20[] = {
+	0x0300, 0x0500, 0x0700, 0x0900,
+	0x0d00, 0x1100, 0x1900, 0x1901,
+	0x1902, 0x1903, 0x1904, 0x1905,
+	0x1906, 0x1907, 0x2407, 0x3207,
+	0x4607, 0x6407
+};
+
+const u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = {
+	0x0100, 0x0200, 0x0400, 0x0700,
+	0x0900, 0x0c00, 0x1200, 0x1900,
+	0x2300, 0x3200, 0x4700, 0x4701,
+	0x4702, 0x4703, 0x4704, 0x4705,
+	0x4706, 0x4707
+};
+
+const u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = {
+	0x0200, 0x0300, 0x0600, 0x0900,
+	0x0d00, 0x1100, 0x1900, 0x2400,
+	0x3200, 0x4600, 0x6400, 0x6401,
+	0x6402, 0x6403, 0x6404, 0x6405,
+	0x6406, 0x6407
+};
+
+const u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3] = { };
+
+const u16 tbl_tx_iqlo_cal_startcoefs[B43_NTAB_TX_IQLO_CAL_STARTCOEFS] = { };
+
+const u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = {
+	0x8423, 0x8323, 0x8073, 0x8256,
+	0x8045, 0x8223, 0x9423, 0x9323,
+	0x9073, 0x9256, 0x9045, 0x9223
+};
+
+const u16 tbl_tx_iqlo_cal_cmds_recal[] = {
+	0x8101, 0x8253, 0x8053, 0x8234,
+	0x8034, 0x9101, 0x9253, 0x9053,
+	0x9234, 0x9034
+};
+
+const u16 tbl_tx_iqlo_cal_cmds_fullcal[] = {
+	0x8123, 0x8264, 0x8086, 0x8245,
+	0x8056, 0x9123, 0x9264, 0x9086,
+	0x9245, 0x9056
+};
+
+const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = {
+	0x8434, 0x8334, 0x8084, 0x8267,
+	0x8056, 0x8234, 0x9434, 0x9334,
+	0x9084, 0x9267, 0x9056, 0x9234
+};
+
+const s16 tbl_tx_filter_coef_rev4[7][15] = {
+	{  -377,   137,  -407,   208, -1527,
+	    956,    93,   186,    93,   230,
+	    -44,   230,   201,  -191,   201 },
+	{   -77,    20,   -98,    49,   -93,
+	     60,    56,   111,    56,    26,
+	     -5,    26,    34,   -32,    34 },
+	{  -360,   164,  -376,   164, -1533,
+	    576,   308,  -314,   308,   121,
+	    -73,   121,    91,   124,    91 },
+	{  -295,   200,  -363,   142, -1391,
+	    826,   151,   301,   151,   151,
+	    301,   151,   602,  -752,   602 },
+	{   -92,    58,   -96,    49,  -104,
+	     44,    17,    35,    17,    12,
+	     25,    12,    13,    27,    13 },
+	{  -375,   136,  -399,   209, -1479,
+	    949,   130,   260,   130,   230,
+	    -44,   230,   201,  -191,   201 },
+	{ 0xed9,  0xc8, 0xe95,  0x8e, 0xa91,
+	  0x33a,  0x97, 0x12d,  0x97,  0x97,
+	  0x12d,  0x97, 0x25a, 0xd10, 0x25a }
+};
+
+/* addr0,  addr1,  bmask,  shift */
+const struct nphy_rf_control_override_rev2 tbl_rf_control_override_rev2[] = {
+	{ 0x78, 0x78, 0x0038,  3 }, /* for field == 0x0002 (fls == 2) */
+	{ 0x7A, 0x7D, 0x0001,  0 }, /* for field == 0x0004 (fls == 3) */
+	{ 0x7A, 0x7D, 0x0002,  1 }, /* for field == 0x0008 (fls == 4) */
+	{ 0x7A, 0x7D, 0x0004,  2 }, /* for field == 0x0010 (fls == 5) */
+	{ 0x7A, 0x7D, 0x0030,  4 }, /* for field == 0x0020 (fls == 6) */
+	{ 0x7A, 0x7D, 0x00C0,  6 }, /* for field == 0x0040 (fls == 7) */
+	{ 0x7A, 0x7D, 0x0100,  8 }, /* for field == 0x0080 (fls == 8) */
+	{ 0x7A, 0x7D, 0x0200,  9 }, /* for field == 0x0100 (fls == 9) */
+	{ 0x78, 0x78, 0x0004,  2 }, /* for field == 0x0200 (fls == 10) */
+	{ 0x7B, 0x7E, 0x01FF,  0 }, /* for field == 0x0400 (fls == 11) */
+	{ 0x7C, 0x7F, 0x01FF,  0 }, /* for field == 0x0800 (fls == 12) */
+	{ 0x78, 0x78, 0x0100,  8 }, /* for field == 0x1000 (fls == 13) */
+	{ 0x78, 0x78, 0x0200,  9 }, /* for field == 0x2000 (fls == 14) */
+	{ 0x78, 0x78, 0xF000, 12 }  /* for field == 0x4000 (fls == 15) */
+};
+
+/* val_mask, val_shift, en_addr0, val_addr0, en_addr1, val_addr1 */
+const struct nphy_rf_control_override_rev3 tbl_rf_control_override_rev3[] = {
+	{ 0x8000, 15, 0xE5, 0xF9, 0xE6, 0xFB }, /* field == 0x0001 (fls 1) */
+	{ 0x0001,  0, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0002 (fls 2) */
+	{ 0x0002,  1, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0004 (fls 3) */
+	{ 0x0004,  2, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0008 (fls 4) */
+	{ 0x0010,  4, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0010 (fls 5) */
+	{ 0x0020,  5, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0020 (fls 6) */
+	{ 0x0040,  6, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0040 (fls 7) */
+	{ 0x0080,  7, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0080 (fls 8) */
+	{ 0x0100,  8, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0100 (fls 9) */
+	{ 0x0007,  0, 0xE7, 0xF8, 0xEC, 0xFA }, /* field == 0x0200 (fls 10) */
+	{ 0x0070,  4, 0xE7, 0xF8, 0xEC, 0xFA }, /* field == 0x0400 (fls 11) */
+	{ 0xE000, 13, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0800 (fls 12) */
+	{ 0xFFFF,  0, 0xE7, 0x7B, 0xEC, 0x7E }, /* field == 0x1000 (fls 13) */
+	{ 0xFFFF,  0, 0xE7, 0x7C, 0xEC, 0x7F }, /* field == 0x2000 (fls 14) */
+	{ 0x00C0,  6, 0xE7, 0xF9, 0xEC, 0xFB }  /* field == 0x4000 (fls 15) */
+};
+
+/* field, val_addr_core0, val_addr_core1, val_mask, val_shift */
+static const struct nphy_rf_control_override_rev7
+			tbl_rf_control_override_rev7_over0[] = {
+	{ 0x0004, 0x07A, 0x07D, 0x0002, 1 },
+	{ 0x0008, 0x07A, 0x07D, 0x0004, 2 },
+	{ 0x0010, 0x07A, 0x07D, 0x0010, 4 },
+	{ 0x0020, 0x07A, 0x07D, 0x0020, 5 },
+	{ 0x0040, 0x07A, 0x07D, 0x0040, 6 },
+	{ 0x0080, 0x07A, 0x07D, 0x0080, 7 },
+	{ 0x0400, 0x0F8, 0x0FA, 0x0070, 4 },
+	{ 0x0800, 0x07B, 0x07E, 0xFFFF, 0 },
+	{ 0x1000, 0x07C, 0x07F, 0xFFFF, 0 },
+	{ 0x6000, 0x348, 0x349, 0x00FF, 0 },
+	{ 0x2000, 0x348, 0x349, 0x000F, 0 },
+};
+
+/* field, val_addr_core0, val_addr_core1, val_mask, val_shift */
+static const struct nphy_rf_control_override_rev7
+			tbl_rf_control_override_rev7_over1[] = {
+	{ 0x0002, 0x340, 0x341, 0x0002, 1 },
+	{ 0x0008, 0x340, 0x341, 0x0008, 3 },
+	{ 0x0020, 0x340, 0x341, 0x0020, 5 },
+	{ 0x0010, 0x340, 0x341, 0x0010, 4 },
+	{ 0x0004, 0x340, 0x341, 0x0004, 2 },
+	{ 0x0080, 0x340, 0x341, 0x0700, 8 },
+	{ 0x0800, 0x340, 0x341, 0x4000, 14 },
+	{ 0x0400, 0x340, 0x341, 0x2000, 13 },
+	{ 0x0200, 0x340, 0x341, 0x0800, 12 },
+	{ 0x0100, 0x340, 0x341, 0x0100, 11 },
+	{ 0x0040, 0x340, 0x341, 0x0040, 6 },
+	{ 0x0001, 0x340, 0x341, 0x0001, 0 },
+};
+
+/* field, val_addr_core0, val_addr_core1, val_mask, val_shift */
+static const struct nphy_rf_control_override_rev7
+			tbl_rf_control_override_rev7_over2[] = {
+	{ 0x0008, 0x344, 0x345, 0x0008, 3 },
+	{ 0x0002, 0x344, 0x345, 0x0002, 1 },
+	{ 0x0001, 0x344, 0x345, 0x0001, 0 },
+	{ 0x0004, 0x344, 0x345, 0x0004, 2 },
+	{ 0x0010, 0x344, 0x345, 0x0010, 4 },
+};
+
+static struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_wa_phy6_radio11_ghz2 = {
+	{ 10, 14, 19, 27 },
+	{ -5, 6, 10, 15 },
+	{ 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA },
+	{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
+	0x427E,
+	{ 0x413F, 0x413F, 0x413F, 0x413F },
+	0x007E, 0x0066, 0x1074,
+	0x18, 0x18, 0x18,
+	0x01D0, 0x5,
+};
+static struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_workaround[2][4] = {
+	{ /* 2GHz */
+		{ /* PHY rev 3 */
+			{ 7, 11, 16, 23 },
+			{ -5, 6, 10, 14 },
+			{ 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA },
+			{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
+			0x627E,
+			{ 0x613F, 0x613F, 0x613F, 0x613F },
+			0x107E, 0x0066, 0x0074,
+			0x18, 0x18, 0x18,
+			0x020D, 0x5,
+		},
+		{ /* PHY rev 4 */
+			{ 8, 12, 17, 25 },
+			{ -5, 6, 10, 14 },
+			{ 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA },
+			{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
+			0x527E,
+			{ 0x513F, 0x513F, 0x513F, 0x513F },
+			0x007E, 0x0066, 0x0074,
+			0x18, 0x18, 0x18,
+			0x01A1, 0x5,
+		},
+		{ /* PHY rev 5 */
+			{ 9, 13, 18, 26 },
+			{ -3, 7, 11, 16 },
+			{ 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA },
+			{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
+			0x427E, /* invalid for external LNA! */
+			{ 0x413F, 0x413F, 0x413F, 0x413F }, /* invalid for external LNA! */
+			0x1076, 0x0066, 0x0000, /* low is invalid (the last one) */
+			0x18, 0x18, 0x18,
+			0x01D0, 0x9,
+		},
+		{ /* PHY rev 6+ */
+			{ 8, 13, 18, 25 },
+			{ -5, 6, 10, 14 },
+			{ 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA },
+			{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
+			0x527E, /* invalid for external LNA! */
+			{ 0x513F, 0x513F, 0x513F, 0x513F }, /* invalid for external LNA! */
+			0x007E, 0x0066, 0x0000, /* low is invalid (the last one) */
+			0x18, 0x18, 0x18,
+			0x01D0, 0x5,
+		},
+	},
+	{ /* 5GHz */
+		{ /* PHY rev 3 */
+			{ 7, 11, 17, 23 },
+			{ -6, 2, 6, 10 },
+			{ 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 },
+			{ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 },
+			0x52DE,
+			{ 0x516F, 0x516F, 0x516F, 0x516F },
+			0x00DE, 0x00CA, 0x00CC,
+			0x1E, 0x1E, 0x1E,
+			0x01A1, 25,
+		},
+		{ /* PHY rev 4 */
+			{ 8, 12, 18, 23 },
+			{ -5, 2, 6, 10 },
+			{ 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD },
+			{ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 },
+			0x629E,
+			{ 0x614F, 0x614F, 0x614F, 0x614F },
+			0x029E, 0x1084, 0x0086,
+			0x24, 0x24, 0x24,
+			0x0107, 25,
+		},
+		{ /* PHY rev 5 */
+			{ 6, 10, 16, 21 },
+			{ -7, 0, 4, 8 },
+			{ 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD },
+			{ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 },
+			0x729E,
+			{ 0x714F, 0x714F, 0x714F, 0x714F },
+			0x029E, 0x2084, 0x2086,
+			0x24, 0x24, 0x24,
+			0x00A9, 25,
+		},
+		{ /* PHY rev 6+ */
+			{ 6, 10, 16, 21 },
+			{ -7, 0, 4, 8 },
+			{ 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD },
+			{ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 },
+			0x729E,
+			{ 0x714F, 0x714F, 0x714F, 0x714F },
+			0x029E, 0x2084, 0x2086,
+			0x24, 0x24, 0x24, /* low is invalid for radio rev 11! */
+			0x00F0, 25,
+		},
+	},
+};
+
+static inline void assert_ntab_array_sizes(void)
+{
+#undef check
+#define check(table, size)	\
+	BUILD_BUG_ON(ARRAY_SIZE(b43_ntab_##table) != B43_NTAB_##size##_SIZE)
+
+	check(adjustpower0, C0_ADJPLT);
+	check(adjustpower1, C1_ADJPLT);
+	check(bdi, BDI);
+	check(channelest, CHANEST);
+	check(estimatepowerlt0, C0_ESTPLT);
+	check(estimatepowerlt1, C1_ESTPLT);
+	check(framelookup, FRAMELT);
+	check(framestruct, FRAMESTRUCT);
+	check(gainctl0, C0_GAINCTL);
+	check(gainctl1, C1_GAINCTL);
+	check(intlevel, INTLEVEL);
+	check(iqlt0, C0_IQLT);
+	check(iqlt1, C1_IQLT);
+	check(loftlt0, C0_LOFEEDTH);
+	check(loftlt1, C1_LOFEEDTH);
+	check(mcs, MCS);
+	check(noisevar10, NOISEVAR10);
+	check(noisevar11, NOISEVAR11);
+	check(pilot, PILOT);
+	check(pilotlt, PILOTLT);
+	check(tdi20a0, TDI20A0);
+	check(tdi20a1, TDI20A1);
+	check(tdi40a0, TDI40A0);
+	check(tdi40a1, TDI40A1);
+	check(tdtrn, TDTRN);
+	check(tmap, TMAP);
+
+#undef check
+}
+
+u32 b43_ntab_read(struct b43_wldev *dev, u32 offset)
+{
+	u32 type, value;
+
+	type = offset & B43_NTAB_TYPEMASK;
+	offset &= ~B43_NTAB_TYPEMASK;
+	B43_WARN_ON(offset > 0xFFFF);
+
+	switch (type) {
+	case B43_NTAB_8BIT:
+		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
+		value = b43_phy_read(dev, B43_NPHY_TABLE_DATALO) & 0xFF;
+		break;
+	case B43_NTAB_16BIT:
+		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
+		value = b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
+		break;
+	case B43_NTAB_32BIT:
+		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
+		value = b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
+		value |= b43_phy_read(dev, B43_NPHY_TABLE_DATAHI) << 16;
+		break;
+	default:
+		B43_WARN_ON(1);
+		value = 0;
+	}
+
+	return value;
+}
+
+void b43_ntab_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_NTAB_TYPEMASK;
+	offset &= ~B43_NTAB_TYPEMASK;
+	B43_WARN_ON(offset > 0xFFFF);
+
+	b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
+
+	for (i = 0; i < nr_elements; i++) {
+		/* Auto increment broken + caching issue on BCM43224? */
+		if (dev->dev->chip_id == 43224 && dev->dev->chip_rev == 1) {
+			b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
+			b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset + i);
+		}
+
+		switch (type) {
+		case B43_NTAB_8BIT:
+			*data = b43_phy_read(dev, B43_NPHY_TABLE_DATALO) & 0xFF;
+			data++;
+			break;
+		case B43_NTAB_16BIT:
+			*((u16 *)data) = b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
+			data += 2;
+			break;
+		case B43_NTAB_32BIT:
+			*((u32 *)data) =
+				b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
+			*((u32 *)data) |=
+				b43_phy_read(dev, B43_NPHY_TABLE_DATAHI) << 16;
+			data += 4;
+			break;
+		default:
+			B43_WARN_ON(1);
+		}
+	}
+}
+
+void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value)
+{
+	u32 type;
+
+	type = offset & B43_NTAB_TYPEMASK;
+	offset &= 0xFFFF;
+
+	switch (type) {
+	case B43_NTAB_8BIT:
+		B43_WARN_ON(value & ~0xFF);
+		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
+		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, value);
+		break;
+	case B43_NTAB_16BIT:
+		B43_WARN_ON(value & ~0xFFFF);
+		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
+		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, value);
+		break;
+	case B43_NTAB_32BIT:
+		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
+		b43_phy_write(dev, B43_NPHY_TABLE_DATAHI, value >> 16);
+		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, value & 0xFFFF);
+		break;
+	default:
+		B43_WARN_ON(1);
+	}
+
+	return;
+
+	/* Some compiletime assertions... */
+	assert_ntab_array_sizes();
+}
+
+void b43_ntab_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_NTAB_TYPEMASK;
+	offset &= ~B43_NTAB_TYPEMASK;
+	B43_WARN_ON(offset > 0xFFFF);
+
+	b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
+
+	for (i = 0; i < nr_elements; i++) {
+		/* Auto increment broken + caching issue on BCM43224? */
+		if ((offset >> 10) == 9 && dev->dev->chip_id == 43224 &&
+		    dev->dev->chip_rev == 1) {
+			b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
+			b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset + i);
+		}
+
+		switch (type) {
+		case B43_NTAB_8BIT:
+			value = *data;
+			data++;
+			B43_WARN_ON(value & ~0xFF);
+			b43_phy_write(dev, B43_NPHY_TABLE_DATALO, value);
+			break;
+		case B43_NTAB_16BIT:
+			value = *((u16 *)data);
+			data += 2;
+			B43_WARN_ON(value & ~0xFFFF);
+			b43_phy_write(dev, B43_NPHY_TABLE_DATALO, value);
+			break;
+		case B43_NTAB_32BIT:
+			value = *((u32 *)data);
+			data += 4;
+			b43_phy_write(dev, B43_NPHY_TABLE_DATAHI, value >> 16);
+			b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
+					value & 0xFFFF);
+			break;
+		default:
+			B43_WARN_ON(1);
+		}
+	}
+}
+
+#define ntab_upload(dev, offset, data) do { \
+		b43_ntab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
+	} while (0)
+
+static void b43_nphy_tables_init_shared_lut(struct b43_wldev *dev)
+{
+	ntab_upload(dev, B43_NTAB_C0_ESTPLT_R3, b43_ntab_estimatepowerlt0_r3);
+	ntab_upload(dev, B43_NTAB_C1_ESTPLT_R3, b43_ntab_estimatepowerlt1_r3);
+	ntab_upload(dev, B43_NTAB_C0_ADJPLT_R3, b43_ntab_adjustpower0_r3);
+	ntab_upload(dev, B43_NTAB_C1_ADJPLT_R3, b43_ntab_adjustpower1_r3);
+	ntab_upload(dev, B43_NTAB_C0_GAINCTL_R3, b43_ntab_gainctl0_r3);
+	ntab_upload(dev, B43_NTAB_C1_GAINCTL_R3, b43_ntab_gainctl1_r3);
+	ntab_upload(dev, B43_NTAB_C0_IQLT_R3, b43_ntab_iqlt0_r3);
+	ntab_upload(dev, B43_NTAB_C1_IQLT_R3, b43_ntab_iqlt1_r3);
+	ntab_upload(dev, B43_NTAB_C0_LOFEEDTH_R3, b43_ntab_loftlt0_r3);
+	ntab_upload(dev, B43_NTAB_C1_LOFEEDTH_R3, b43_ntab_loftlt1_r3);
+}
+
+static void b43_nphy_tables_init_rev7_volatile(struct b43_wldev *dev)
+{
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+	u8 antswlut;
+	int core, offset, i;
+
+	const int antswlut0_offsets[] = { 0, 4, 8, }; /* Offsets for values */
+	const u8 antswlut0_values[][3] = {
+		{ 0x2, 0x12, 0x8 }, /* Core 0 */
+		{ 0x2, 0x18, 0x2 }, /* Core 1 */
+	};
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
+		antswlut = sprom->fem.ghz5.antswlut;
+	else
+		antswlut = sprom->fem.ghz2.antswlut;
+
+	switch (antswlut) {
+	case 0:
+		for (core = 0; core < 2; core++) {
+			for (i = 0; i < ARRAY_SIZE(antswlut0_values[0]); i++) {
+				offset = core ? 0x20 : 0x00;
+				offset += antswlut0_offsets[i];
+				b43_ntab_write(dev, B43_NTAB8(9, offset),
+					       antswlut0_values[core][i]);
+			}
+		}
+		break;
+	default:
+		b43err(dev->wl, "Unsupported antswlut: %d\n", antswlut);
+		break;
+	}
+}
+
+static void b43_nphy_tables_init_rev16(struct b43_wldev *dev)
+{
+	/* Static tables */
+	if (dev->phy.do_full_init) {
+		ntab_upload(dev, B43_NTAB_NOISEVAR_R7, b43_ntab_noisevar_r7);
+		b43_nphy_tables_init_shared_lut(dev);
+	}
+
+	/* Volatile tables */
+	b43_nphy_tables_init_rev7_volatile(dev);
+}
+
+static void b43_nphy_tables_init_rev7(struct b43_wldev *dev)
+{
+	/* Static tables */
+	if (dev->phy.do_full_init) {
+		ntab_upload(dev, B43_NTAB_FRAMESTRUCT_R3, b43_ntab_framestruct_r3);
+		ntab_upload(dev, B43_NTAB_PILOT_R3, b43_ntab_pilot_r3);
+		ntab_upload(dev, B43_NTAB_TMAP_R7, b43_ntab_tmap_r7);
+		ntab_upload(dev, B43_NTAB_INTLEVEL_R3, b43_ntab_intlevel_r3);
+		ntab_upload(dev, B43_NTAB_TDTRN_R3, b43_ntab_tdtrn_r3);
+		ntab_upload(dev, B43_NTAB_NOISEVAR_R7, b43_ntab_noisevar_r7);
+		ntab_upload(dev, B43_NTAB_MCS_R3, b43_ntab_mcs_r3);
+		ntab_upload(dev, B43_NTAB_TDI20A0_R3, b43_ntab_tdi20a0_r3);
+		ntab_upload(dev, B43_NTAB_TDI20A1_R3, b43_ntab_tdi20a1_r3);
+		ntab_upload(dev, B43_NTAB_TDI40A0_R3, b43_ntab_tdi40a0_r3);
+		ntab_upload(dev, B43_NTAB_TDI40A1_R3, b43_ntab_tdi40a1_r3);
+		ntab_upload(dev, B43_NTAB_PILOTLT_R3, b43_ntab_pilotlt_r3);
+		ntab_upload(dev, B43_NTAB_CHANEST_R3, b43_ntab_channelest_r3);
+		ntab_upload(dev, B43_NTAB_FRAMELT_R3, b43_ntab_framelookup_r3);
+		b43_nphy_tables_init_shared_lut(dev);
+	}
+
+	/* Volatile tables */
+	b43_nphy_tables_init_rev7_volatile(dev);
+}
+
+static void b43_nphy_tables_init_rev3(struct b43_wldev *dev)
+{
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+	u8 antswlut;
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
+		antswlut = sprom->fem.ghz5.antswlut;
+	else
+		antswlut = sprom->fem.ghz2.antswlut;
+
+	/* Static tables */
+	if (dev->phy.do_full_init) {
+		ntab_upload(dev, B43_NTAB_FRAMESTRUCT_R3, b43_ntab_framestruct_r3);
+		ntab_upload(dev, B43_NTAB_PILOT_R3, b43_ntab_pilot_r3);
+		ntab_upload(dev, B43_NTAB_TMAP_R3, b43_ntab_tmap_r3);
+		ntab_upload(dev, B43_NTAB_INTLEVEL_R3, b43_ntab_intlevel_r3);
+		ntab_upload(dev, B43_NTAB_TDTRN_R3, b43_ntab_tdtrn_r3);
+		ntab_upload(dev, B43_NTAB_NOISEVAR_R3, b43_ntab_noisevar_r3);
+		ntab_upload(dev, B43_NTAB_MCS_R3, b43_ntab_mcs_r3);
+		ntab_upload(dev, B43_NTAB_TDI20A0_R3, b43_ntab_tdi20a0_r3);
+		ntab_upload(dev, B43_NTAB_TDI20A1_R3, b43_ntab_tdi20a1_r3);
+		ntab_upload(dev, B43_NTAB_TDI40A0_R3, b43_ntab_tdi40a0_r3);
+		ntab_upload(dev, B43_NTAB_TDI40A1_R3, b43_ntab_tdi40a1_r3);
+		ntab_upload(dev, B43_NTAB_PILOTLT_R3, b43_ntab_pilotlt_r3);
+		ntab_upload(dev, B43_NTAB_CHANEST_R3, b43_ntab_channelest_r3);
+		ntab_upload(dev, B43_NTAB_FRAMELT_R3, b43_ntab_framelookup_r3);
+		b43_nphy_tables_init_shared_lut(dev);
+	}
+
+	/* Volatile tables */
+	if (antswlut < ARRAY_SIZE(b43_ntab_antswctl_r3))
+		ntab_upload(dev, B43_NTAB_ANT_SW_CTL_R3,
+			    b43_ntab_antswctl_r3[antswlut]);
+	else
+		B43_WARN_ON(1);
+}
+
+static void b43_nphy_tables_init_rev0(struct b43_wldev *dev)
+{
+	/* Static tables */
+	if (dev->phy.do_full_init) {
+		ntab_upload(dev, B43_NTAB_FRAMESTRUCT, b43_ntab_framestruct);
+		ntab_upload(dev, B43_NTAB_FRAMELT, b43_ntab_framelookup);
+		ntab_upload(dev, B43_NTAB_TMAP, b43_ntab_tmap);
+		ntab_upload(dev, B43_NTAB_TDTRN, b43_ntab_tdtrn);
+		ntab_upload(dev, B43_NTAB_INTLEVEL, b43_ntab_intlevel);
+		ntab_upload(dev, B43_NTAB_PILOT, b43_ntab_pilot);
+		ntab_upload(dev, B43_NTAB_TDI20A0, b43_ntab_tdi20a0);
+		ntab_upload(dev, B43_NTAB_TDI20A1, b43_ntab_tdi20a1);
+		ntab_upload(dev, B43_NTAB_TDI40A0, b43_ntab_tdi40a0);
+		ntab_upload(dev, B43_NTAB_TDI40A1, b43_ntab_tdi40a1);
+		ntab_upload(dev, B43_NTAB_CHANEST, b43_ntab_channelest);
+		ntab_upload(dev, B43_NTAB_MCS, b43_ntab_mcs);
+		ntab_upload(dev, B43_NTAB_NOISEVAR10, b43_ntab_noisevar10);
+		ntab_upload(dev, B43_NTAB_NOISEVAR11, b43_ntab_noisevar11);
+	}
+
+	/* Volatile tables */
+	ntab_upload(dev, B43_NTAB_BDI, b43_ntab_bdi);
+	ntab_upload(dev, B43_NTAB_PILOTLT, b43_ntab_pilotlt);
+	ntab_upload(dev, B43_NTAB_C0_GAINCTL, b43_ntab_gainctl0);
+	ntab_upload(dev, B43_NTAB_C1_GAINCTL, b43_ntab_gainctl1);
+	ntab_upload(dev, B43_NTAB_C0_ESTPLT, b43_ntab_estimatepowerlt0);
+	ntab_upload(dev, B43_NTAB_C1_ESTPLT, b43_ntab_estimatepowerlt1);
+	ntab_upload(dev, B43_NTAB_C0_ADJPLT, b43_ntab_adjustpower0);
+	ntab_upload(dev, B43_NTAB_C1_ADJPLT, b43_ntab_adjustpower1);
+	ntab_upload(dev, B43_NTAB_C0_IQLT, b43_ntab_iqlt0);
+	ntab_upload(dev, B43_NTAB_C1_IQLT, b43_ntab_iqlt1);
+	ntab_upload(dev, B43_NTAB_C0_LOFEEDTH, b43_ntab_loftlt0);
+	ntab_upload(dev, B43_NTAB_C1_LOFEEDTH, b43_ntab_loftlt1);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables */
+void b43_nphy_tables_init(struct b43_wldev *dev)
+{
+	if (dev->phy.rev >= 16)
+		b43_nphy_tables_init_rev16(dev);
+	else if (dev->phy.rev >= 7)
+		b43_nphy_tables_init_rev7(dev);
+	else if (dev->phy.rev >= 3)
+		b43_nphy_tables_init_rev3(dev);
+	else
+		b43_nphy_tables_init_rev0(dev);
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetIpaGainTbl */
+static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+		switch (phy->rev) {
+		case 17:
+			if (phy->radio_rev == 14)
+				return b43_ntab_tx_gain_ipa_2057_rev14_2g;
+			break;
+		case 16:
+			if (phy->radio_rev == 9)
+				return b43_ntab_tx_gain_ipa_2057_rev9_2g;
+			break;
+		case 8:
+			if (phy->radio_rev == 5)
+				return b43_ntab_tx_gain_ipa_2057_rev5_2g;
+			break;
+		case 6:
+			if (dev->dev->chip_id == BCMA_CHIP_ID_BCM47162)
+				return b43_ntab_tx_gain_ipa_rev5_2g;
+			return b43_ntab_tx_gain_ipa_rev6_2g;
+		case 5:
+			return b43_ntab_tx_gain_ipa_rev5_2g;
+		case 4:
+		case 3:
+			return b43_ntab_tx_gain_ipa_rev3_2g;
+		}
+
+		b43err(dev->wl,
+		       "No 2GHz IPA gain table available for this device\n");
+		return NULL;
+	} else {
+		switch (phy->rev) {
+		case 16:
+			if (phy->radio_rev == 9)
+				return b43_ntab_tx_gain_ipa_2057_rev9_5g;
+			break;
+		case 3 ... 6:
+			return b43_ntab_tx_gain_ipa_rev3_5g;
+		}
+
+		b43err(dev->wl,
+		       "No 5GHz IPA gain table available for this device\n");
+		return NULL;
+	}
+}
+
+const u32 *b43_nphy_get_tx_gain_table(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	enum nl80211_band band = b43_current_band(dev->wl);
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+
+	if (dev->phy.rev < 3)
+		return b43_ntab_tx_gain_rev0_1_2;
+
+	/* rev 3+ */
+	if ((dev->phy.n->ipa2g_on && band == NL80211_BAND_2GHZ) ||
+	    (dev->phy.n->ipa5g_on && band == NL80211_BAND_5GHZ)) {
+		return b43_nphy_get_ipa_gain_table(dev);
+	} else if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
+		switch (phy->rev) {
+		case 6:
+		case 5:
+			return b43_ntab_tx_gain_epa_rev5_5g;
+		case 4:
+			return sprom->fem.ghz5.extpa_gain == 3 ?
+				b43_ntab_tx_gain_epa_rev4_5g :
+				b43_ntab_tx_gain_epa_rev4_hi_pwr_5g;
+		case 3:
+			return b43_ntab_tx_gain_epa_rev3_5g;
+		default:
+			b43err(dev->wl,
+			       "No 5GHz EPA gain table available for this device\n");
+			return NULL;
+		}
+	} else {
+		switch (phy->rev) {
+		case 6:
+		case 5:
+			if (sprom->fem.ghz2.extpa_gain == 3)
+				return b43_ntab_tx_gain_epa_rev3_hi_pwr_2g;
+			/* fall through */
+		case 4:
+		case 3:
+			return b43_ntab_tx_gain_epa_rev3_2g;
+		default:
+			b43err(dev->wl,
+			       "No 2GHz EPA gain table available for this device\n");
+			return NULL;
+		}
+	}
+}
+
+const s16 *b43_ntab_get_rf_pwr_offset_table(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+		switch (phy->rev) {
+		case 17:
+			if (phy->radio_rev == 14)
+				return b43_ntab_rf_pwr_offset_2057_rev14_2g;
+			break;
+		case 16:
+			if (phy->radio_rev == 9)
+				return b43_ntab_rf_pwr_offset_2057_rev9_2g;
+			break;
+		}
+
+		b43err(dev->wl,
+		       "No 2GHz RF power table available for this device\n");
+		return NULL;
+	} else {
+		switch (phy->rev) {
+		case 16:
+			if (phy->radio_rev == 9)
+				return b43_ntab_rf_pwr_offset_2057_rev9_5g;
+			break;
+		}
+
+		b43err(dev->wl,
+		       "No 5GHz RF power table available for this device\n");
+		return NULL;
+	}
+}
+
+struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
+	struct b43_wldev *dev, bool ghz5, bool ext_lna)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct nphy_gain_ctl_workaround_entry *e;
+	u8 phy_idx;
+
+	if (!ghz5 && dev->phy.rev >= 6 && dev->phy.radio_rev == 11)
+		return &nphy_gain_ctl_wa_phy6_radio11_ghz2;
+
+	B43_WARN_ON(dev->phy.rev < 3);
+	if (dev->phy.rev >= 6)
+		phy_idx = 3;
+	else if (dev->phy.rev == 5)
+		phy_idx = 2;
+	else if (dev->phy.rev == 4)
+		phy_idx = 1;
+	else
+		phy_idx = 0;
+	e = &nphy_gain_ctl_workaround[ghz5][phy_idx];
+
+	/* Some workarounds to the workarounds... */
+	if (!ghz5) {
+		u8 tr_iso = dev->dev->bus_sprom->fem.ghz2.tr_iso;
+
+		if (tr_iso > 7)
+			tr_iso = 3;
+
+		if (phy->rev >= 6) {
+			static const int gain_data[] = { 0x106a, 0x106c, 0x1074,
+							 0x107c, 0x007e, 0x107e,
+							 0x207e, 0x307e, };
+
+			e->cliplo_gain = gain_data[tr_iso];
+		} else if (phy->rev == 5) {
+			static const int gain_data[] = { 0x0062, 0x0064, 0x006a,
+							 0x106a, 0x106c, 0x1074,
+							 0x107c, 0x207c, };
+
+			e->cliplo_gain = gain_data[tr_iso];
+		}
+
+		if (phy->rev >= 5 && ext_lna) {
+			e->rfseq_init[0] &= ~0x4000;
+			e->rfseq_init[1] &= ~0x4000;
+			e->rfseq_init[2] &= ~0x4000;
+			e->rfseq_init[3] &= ~0x4000;
+			e->init_gain &= ~0x4000;
+		}
+	} else {
+		if (phy->rev >= 6) {
+			if (phy->radio_rev == 11 && !b43_is_40mhz(dev))
+				e->crsminu = 0x2d;
+		} else if (phy->rev == 4 && ext_lna) {
+			e->rfseq_init[0] &= ~0x4000;
+			e->rfseq_init[1] &= ~0x4000;
+			e->rfseq_init[2] &= ~0x4000;
+			e->rfseq_init[3] &= ~0x4000;
+			e->init_gain &= ~0x4000;
+			e->rfseq_init[0] |= 0x1000;
+			e->rfseq_init[1] |= 0x1000;
+			e->rfseq_init[2] |= 0x1000;
+			e->rfseq_init[3] |= 0x1000;
+			e->init_gain |= 0x1000;
+		}
+	}
+
+	return e;
+}
+
+const struct nphy_rf_control_override_rev7 *b43_nphy_get_rf_ctl_over_rev7(
+	struct b43_wldev *dev, u16 field, u8 override)
+{
+	const struct nphy_rf_control_override_rev7 *e;
+	u8 size, i;
+
+	switch (override) {
+	case 0:
+		e = tbl_rf_control_override_rev7_over0;
+		size = ARRAY_SIZE(tbl_rf_control_override_rev7_over0);
+		break;
+	case 1:
+		e = tbl_rf_control_override_rev7_over1;
+		size = ARRAY_SIZE(tbl_rf_control_override_rev7_over1);
+		break;
+	case 2:
+		e = tbl_rf_control_override_rev7_over2;
+		size = ARRAY_SIZE(tbl_rf_control_override_rev7_over2);
+		break;
+	default:
+		b43err(dev->wl, "Invalid override value %d\n", override);
+		return NULL;
+	}
+
+	for (i = 0; i < size; i++) {
+		if (e[i].field == field)
+			return &e[i];
+	}
+
+	return NULL;
+}
diff --git a/drivers/net/wireless/broadcom/b43/tables_nphy.h b/drivers/net/wireless/broadcom/b43/tables_nphy.h
new file mode 100644
index 0000000..3876786
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/tables_nphy.h
@@ -0,0 +1,223 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_TABLES_NPHY_H_
+#define B43_TABLES_NPHY_H_
+
+#include <linux/types.h>
+
+struct b43_phy_n_sfo_cfg {
+	u16 phy_bw1a;
+	u16 phy_bw2;
+	u16 phy_bw3;
+	u16 phy_bw4;
+	u16 phy_bw5;
+	u16 phy_bw6;
+};
+
+struct b43_wldev;
+
+struct nphy_txiqcal_ladder {
+	u8 percent;
+	u8 g_env;
+};
+
+struct nphy_rf_control_override_rev2 {
+	u8 addr0;
+	u8 addr1;
+	u16 bmask;
+	u8 shift;
+};
+
+struct nphy_rf_control_override_rev3 {
+	u16 val_mask;
+	u8 val_shift;
+	u8 en_addr0;
+	u8 val_addr0;
+	u8 en_addr1;
+	u8 val_addr1;
+};
+
+struct nphy_rf_control_override_rev7 {
+	u16 field;
+	u16 val_addr_core0;
+	u16 val_addr_core1;
+	u16 val_mask;
+	u8 val_shift;
+};
+
+struct nphy_gain_ctl_workaround_entry {
+	s8 lna1_gain[4];
+	s8 lna2_gain[4];
+	u8 gain_db[10];
+	u8 gain_bits[10];
+
+	u16 init_gain;
+	u16 rfseq_init[4];
+
+	u16 cliphi_gain;
+	u16 clipmd_gain;
+	u16 cliplo_gain;
+
+	u16 crsmin;
+	u16 crsminl;
+	u16 crsminu;
+
+	u16 nbclip;
+	u16 wlclip;
+};
+
+/* Get entry with workaround values for gain ctl. Does not return NULL. */
+struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
+	struct b43_wldev *dev, bool ghz5, bool ext_lna);
+
+
+/* The N-PHY tables. */
+#define B43_NTAB_TYPEMASK		0xF0000000
+#define B43_NTAB_8BIT			0x10000000
+#define B43_NTAB_16BIT			0x20000000
+#define B43_NTAB_32BIT			0x30000000
+#define B43_NTAB8(table, offset)	(((table) << 10) | (offset) | B43_NTAB_8BIT)
+#define B43_NTAB16(table, offset)	(((table) << 10) | (offset) | B43_NTAB_16BIT)
+#define B43_NTAB32(table, offset)	(((table) << 10) | (offset) | B43_NTAB_32BIT)
+
+/* Static N-PHY tables */
+#define B43_NTAB_FRAMESTRUCT		B43_NTAB32(0x0A, 0x000) /* Frame Struct Table */
+#define B43_NTAB_FRAMESTRUCT_SIZE	832
+#define B43_NTAB_FRAMELT		B43_NTAB8 (0x18, 0x000) /* Frame Lookup Table */
+#define B43_NTAB_FRAMELT_SIZE		32
+#define B43_NTAB_TMAP			B43_NTAB32(0x0C, 0x000) /* T Map Table */
+#define B43_NTAB_TMAP_SIZE		448
+#define B43_NTAB_TDTRN			B43_NTAB32(0x0E, 0x000) /* TDTRN Table */
+#define B43_NTAB_TDTRN_SIZE		704
+#define B43_NTAB_INTLEVEL		B43_NTAB32(0x0D, 0x000) /* Int Level Table */
+#define B43_NTAB_INTLEVEL_SIZE		7
+#define B43_NTAB_PILOT			B43_NTAB16(0x0B, 0x000) /* Pilot Table */
+#define B43_NTAB_PILOT_SIZE		88
+#define B43_NTAB_PILOTLT		B43_NTAB32(0x14, 0x000) /* Pilot Lookup Table */
+#define B43_NTAB_PILOTLT_SIZE		6
+#define B43_NTAB_TDI20A0		B43_NTAB32(0x13, 0x080) /* TDI Table 20 Antenna 0 */
+#define B43_NTAB_TDI20A0_SIZE		55
+#define B43_NTAB_TDI20A1		B43_NTAB32(0x13, 0x100) /* TDI Table 20 Antenna 1 */
+#define B43_NTAB_TDI20A1_SIZE		55
+#define B43_NTAB_TDI40A0		B43_NTAB32(0x13, 0x280) /* TDI Table 40 Antenna 0 */
+#define B43_NTAB_TDI40A0_SIZE		110
+#define B43_NTAB_TDI40A1		B43_NTAB32(0x13, 0x300) /* TDI Table 40 Antenna 1 */
+#define B43_NTAB_TDI40A1_SIZE		110
+#define B43_NTAB_BDI			B43_NTAB16(0x15, 0x000) /* BDI Table */
+#define B43_NTAB_BDI_SIZE		6
+#define B43_NTAB_CHANEST		B43_NTAB32(0x16, 0x000) /* Channel Estimate Table */
+#define B43_NTAB_CHANEST_SIZE		96
+#define B43_NTAB_MCS			B43_NTAB8 (0x12, 0x000) /* MCS Table */
+#define B43_NTAB_MCS_SIZE		128
+
+/* Volatile N-PHY tables */
+#define B43_NTAB_NOISEVAR10		B43_NTAB32(0x10, 0x000) /* Noise Var Table 10 */
+#define B43_NTAB_NOISEVAR10_SIZE	256
+#define B43_NTAB_NOISEVAR11		B43_NTAB32(0x10, 0x080) /* Noise Var Table 11 */
+#define B43_NTAB_NOISEVAR11_SIZE	256
+#define B43_NTAB_C0_ESTPLT		B43_NTAB8 (0x1A, 0x000) /* Estimate Power Lookup Table Core 0 */
+#define B43_NTAB_C0_ESTPLT_SIZE		64
+#define B43_NTAB_C0_ADJPLT		B43_NTAB8 (0x1A, 0x040) /* Adjust Power Lookup Table Core 0 */
+#define B43_NTAB_C0_ADJPLT_SIZE		128
+#define B43_NTAB_C0_GAINCTL		B43_NTAB32(0x1A, 0x0C0) /* Gain Control Lookup Table Core 0 */
+#define B43_NTAB_C0_GAINCTL_SIZE	128
+#define B43_NTAB_C0_IQLT		B43_NTAB32(0x1A, 0x140) /* IQ Lookup Table Core 0 */
+#define B43_NTAB_C0_IQLT_SIZE		128
+#define B43_NTAB_C0_LOFEEDTH		B43_NTAB16(0x1A, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 0 */
+#define B43_NTAB_C0_LOFEEDTH_SIZE	128
+#define B43_NTAB_C1_ESTPLT		B43_NTAB8 (0x1B, 0x000) /* Estimate Power Lookup Table Core 1 */
+#define B43_NTAB_C1_ESTPLT_SIZE		64
+#define B43_NTAB_C1_ADJPLT		B43_NTAB8 (0x1B, 0x040) /* Adjust Power Lookup Table Core 1 */
+#define B43_NTAB_C1_ADJPLT_SIZE		128
+#define B43_NTAB_C1_GAINCTL		B43_NTAB32(0x1B, 0x0C0) /* Gain Control Lookup Table Core 1 */
+#define B43_NTAB_C1_GAINCTL_SIZE	128
+#define B43_NTAB_C1_IQLT		B43_NTAB32(0x1B, 0x140) /* IQ Lookup Table Core 1 */
+#define B43_NTAB_C1_IQLT_SIZE		128
+#define B43_NTAB_C1_LOFEEDTH		B43_NTAB16(0x1B, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 1 */
+#define B43_NTAB_C1_LOFEEDTH_SIZE	128
+
+/* Volatile N-PHY tables, PHY revision >= 3 */
+#define B43_NTAB_ANT_SW_CTL_R3		B43_NTAB16( 9,   0) /* antenna software control */
+
+/* Static N-PHY tables, PHY revision >= 3 */
+#define B43_NTAB_FRAMESTRUCT_R3		B43_NTAB32(10,   0) /* frame struct  */
+#define B43_NTAB_PILOT_R3		B43_NTAB16(11,   0) /* pilot  */
+#define B43_NTAB_TMAP_R3		B43_NTAB32(12,   0) /* TM AP  */
+#define B43_NTAB_INTLEVEL_R3		B43_NTAB32(13,   0) /* INT LV  */
+#define B43_NTAB_TDTRN_R3		B43_NTAB32(14,   0) /* TD TRN  */
+#define B43_NTAB_NOISEVAR_R3		B43_NTAB32(16,   0) /* noise variance */
+#define B43_NTAB_MCS_R3			B43_NTAB16(18,   0) /* MCS  */
+#define B43_NTAB_TDI20A0_R3		B43_NTAB32(19, 128) /* TDI 20/0  */
+#define B43_NTAB_TDI20A1_R3		B43_NTAB32(19, 256) /* TDI 20/1  */
+#define B43_NTAB_TDI40A0_R3		B43_NTAB32(19, 640) /* TDI 40/0  */
+#define B43_NTAB_TDI40A1_R3		B43_NTAB32(19, 768) /* TDI 40/1  */
+#define B43_NTAB_PILOTLT_R3		B43_NTAB32(20,   0) /* PLT lookup  */
+#define B43_NTAB_CHANEST_R3		B43_NTAB32(22,   0) /* channel estimate  */
+#define B43_NTAB_FRAMELT_R3		 B43_NTAB8(24,   0) /* frame lookup  */
+#define B43_NTAB_C0_ESTPLT_R3		 B43_NTAB8(26,   0) /* estimated power lookup 0  */
+#define B43_NTAB_C0_ADJPLT_R3		 B43_NTAB8(26,  64) /* adjusted power lookup 0  */
+#define B43_NTAB_C0_GAINCTL_R3		B43_NTAB32(26, 192) /* gain control lookup 0  */
+#define B43_NTAB_C0_IQLT_R3		B43_NTAB32(26, 320) /* I/Q lookup 0  */
+#define B43_NTAB_C0_LOFEEDTH_R3		B43_NTAB16(26, 448) /* Local Oscillator Feed Through lookup 0  */
+#define B43_NTAB_C0_PAPD_COMP_R3	B43_NTAB16(26, 576)
+#define B43_NTAB_C1_ESTPLT_R3		 B43_NTAB8(27,   0) /* estimated power lookup 1  */
+#define B43_NTAB_C1_ADJPLT_R3		 B43_NTAB8(27,  64) /* adjusted power lookup 1  */
+#define B43_NTAB_C1_GAINCTL_R3		B43_NTAB32(27, 192) /* gain control lookup 1  */
+#define B43_NTAB_C1_IQLT_R3		B43_NTAB32(27, 320) /* I/Q lookup 1  */
+#define B43_NTAB_C1_LOFEEDTH_R3		B43_NTAB16(27, 448) /* Local Oscillator Feed Through lookup 1 */
+#define B43_NTAB_C1_PAPD_COMP_R3	B43_NTAB16(27, 576)
+
+/* Static N-PHY tables, PHY revision >= 7 */
+#define B43_NTAB_TMAP_R7		B43_NTAB32(12,   0) /* TM AP */
+#define B43_NTAB_NOISEVAR_R7		B43_NTAB32(16,   0) /* noise variance */
+
+#define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_40_SIZE	18
+#define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_20_SIZE	18
+#define B43_NTAB_TX_IQLO_CAL_IQIMB_LADDER_40_SIZE	18
+#define B43_NTAB_TX_IQLO_CAL_IQIMB_LADDER_20_SIZE	18
+#define B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3		11
+#define B43_NTAB_TX_IQLO_CAL_STARTCOEFS			9
+#define B43_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3		12
+#define B43_NTAB_TX_IQLO_CAL_CMDS_RECAL			10
+#define B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL		10
+#define B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3		12
+
+u32 b43_ntab_read(struct b43_wldev *dev, u32 offset);
+void b43_ntab_read_bulk(struct b43_wldev *dev, u32 offset,
+			 unsigned int nr_elements, void *_data);
+void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value);
+void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset,
+			  unsigned int nr_elements, const void *_data);
+
+void b43_nphy_tables_init(struct b43_wldev *dev);
+
+const u32 *b43_nphy_get_tx_gain_table(struct b43_wldev *dev);
+
+const s16 *b43_ntab_get_rf_pwr_offset_table(struct b43_wldev *dev);
+
+extern const s8 b43_ntab_papd_pga_gain_delta_ipa_2g[];
+
+extern const u16 tbl_iqcal_gainparams[2][9][8];
+extern const struct nphy_txiqcal_ladder ladder_lo[];
+extern const struct nphy_txiqcal_ladder ladder_iq[];
+extern const u16 loscale[];
+
+extern const u16 tbl_tx_iqlo_cal_loft_ladder_40[];
+extern const u16 tbl_tx_iqlo_cal_loft_ladder_20[];
+extern const u16 tbl_tx_iqlo_cal_iqimb_ladder_40[];
+extern const u16 tbl_tx_iqlo_cal_iqimb_ladder_20[];
+extern const u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[];
+extern const u16 tbl_tx_iqlo_cal_startcoefs[];
+extern const u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[];
+extern const u16 tbl_tx_iqlo_cal_cmds_recal[];
+extern const u16 tbl_tx_iqlo_cal_cmds_fullcal[];
+extern const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[];
+extern const s16 tbl_tx_filter_coef_rev4[7][15];
+
+extern const struct nphy_rf_control_override_rev2
+	tbl_rf_control_override_rev2[];
+extern const struct nphy_rf_control_override_rev3
+	tbl_rf_control_override_rev3[];
+const struct nphy_rf_control_override_rev7 *b43_nphy_get_rf_ctl_over_rev7(
+	struct b43_wldev *dev, u16 field, u8 override);
+
+#endif /* B43_TABLES_NPHY_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/tables_phy_ht.c b/drivers/net/wireless/broadcom/b43/tables_phy_ht.c
new file mode 100644
index 0000000..176c49d
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/tables_phy_ht.c
@@ -0,0 +1,836 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11n HT-PHY data tables
+
+  Copyright (c) 2011 Rafał Miłecki <zajec5@gmail.com>
+
+  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,
+};
+
+/* Some late-init table */
+const u32 b43_httab_0x1a_0xc0_late[] = {
+	0x10f90040, 0x10e10040, 0x10e1003c, 0x10c9003d,
+	0x10b9003c, 0x10a9003d, 0x10a1003c, 0x1099003b,
+	0x1091003b, 0x1089003a, 0x1081003a, 0x10790039,
+	0x10710039, 0x1069003a, 0x1061003b, 0x1059003d,
+	0x1051003f, 0x10490042, 0x1049003e, 0x1049003b,
+	0x1041003e, 0x1041003b, 0x1039003e, 0x1039003b,
+	0x10390038, 0x10390035, 0x1031003a, 0x10310036,
+	0x10310033, 0x1029003a, 0x10290037, 0x10290034,
+	0x10290031, 0x10210039, 0x10210036, 0x10210033,
+	0x10210030, 0x1019003c, 0x10190039, 0x10190036,
+	0x10190033, 0x10190030, 0x1019002d, 0x1019002b,
+	0x10190028, 0x1011003a, 0x10110036, 0x10110033,
+	0x10110030, 0x1011002e, 0x1011002b, 0x10110029,
+	0x10110027, 0x10110024, 0x10110022, 0x10110020,
+	0x1011001f, 0x1011001d, 0x1009003a, 0x10090037,
+	0x10090034, 0x10090031, 0x1009002e, 0x1009002c,
+	0x10090029, 0x10090027, 0x10090025, 0x10090023,
+	0x10090021, 0x1009001f, 0x1009001d, 0x1009001b,
+	0x1009001a, 0x10090018, 0x10090017, 0x10090016,
+	0x10090015, 0x10090013, 0x10090012, 0x10090011,
+	0x10090010, 0x1009000f, 0x1009000f, 0x1009000e,
+	0x1009000d, 0x1009000c, 0x1009000c, 0x1009000b,
+	0x1009000a, 0x1009000a, 0x10090009, 0x10090009,
+	0x10090008, 0x10090008, 0x10090007, 0x10090007,
+	0x10090007, 0x10090006, 0x10090006, 0x10090005,
+	0x10090005, 0x10090005, 0x10090005, 0x10090004,
+	0x10090004, 0x10090004, 0x10090004, 0x10090003,
+	0x10090003, 0x10090003, 0x10090003, 0x10090003,
+	0x10090003, 0x10090002, 0x10090002, 0x10090002,
+	0x10090002, 0x10090002, 0x10090002, 0x10090002,
+	0x10090002, 0x10090002, 0x10090001, 0x10090001,
+	0x10090001, 0x10090001, 0x10090001, 0x10090001,
+};
+
+/**************************************************
+ * 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_few(struct b43_wldev *dev, u32 offset, size_t num, ...)
+{
+	va_list args;
+	u32 type, value;
+	unsigned int i;
+
+	type = offset & B43_HTTAB_TYPEMASK;
+	offset &= 0xFFFF;
+
+	va_start(args, num);
+	switch (type) {
+	case B43_HTTAB_8BIT:
+		b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+		for (i = 0; i < num; i++) {
+			value = va_arg(args, int);
+			B43_WARN_ON(value & ~0xFF);
+			b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
+		}
+		break;
+	case B43_HTTAB_16BIT:
+		b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
+		for (i = 0; i < num; i++) {
+			value = va_arg(args, int);
+			B43_WARN_ON(value & ~0xFFFF);
+			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);
+		for (i = 0; i < num; i++) {
+			value = va_arg(args, int);
+			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);
+	}
+	va_end(args);
+
+	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)
+{
+	BUILD_BUG_ON(ARRAY_SIZE(b43_httab_0x1a_0xc0_late) !=
+			B43_HTTAB_1A_C0_LATE_SIZE);
+
+	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);
+}
diff --git a/drivers/net/wireless/broadcom/b43/tables_phy_ht.h b/drivers/net/wireless/broadcom/b43/tables_phy_ht.h
new file mode 100644
index 0000000..7ed0571
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/tables_phy_ht.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#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_few(struct b43_wldev *dev, u32 offset, size_t num, ...);
+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);
+
+#define B43_HTTAB_1A_C0_LATE_SIZE		128
+extern const u32 b43_httab_0x1a_0xc0_late[];
+
+#endif /* B43_TABLES_PHY_HT_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/tables_phy_lcn.c b/drivers/net/wireless/broadcom/b43/tables_phy_lcn.c
new file mode 100644
index 0000000..704ef1b
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/tables_phy_lcn.c
@@ -0,0 +1,724 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11n LCN-PHY data tables
+
+  Copyright (c) 2011 Rafał Miłecki <zajec5@gmail.com>
+
+  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"
+
+struct b43_lcntab_tx_gain_tbl_entry {
+	u8 gm;
+	u8 pga;
+	u8 pad;
+	u8 dac;
+	u8 bb_mult;
+};
+
+/**************************************************
+ * Static tables.
+ **************************************************/
+
+static const u16 b43_lcntab_0x02[] = {
+	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
+	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
+	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
+	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
+	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
+	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
+	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
+	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
+	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
+	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d,
+	0x014d, 0x014d, 0x014d, 0x014d,
+};
+
+static const u16 b43_lcntab_0x01[] = {
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 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_lcntab_0x0b[] = {
+	0x000141f8, 0x000021f8, 0x000021fb, 0x000041fb,
+	0x0001fedb, 0x0000217b, 0x00002133, 0x000040eb,
+	0x0001fea3, 0x0000024b,
+};
+
+static const u32 b43_lcntab_0x0c[] = {
+	0x00100001, 0x00200010, 0x00300001, 0x00400010,
+	0x00500022, 0x00600122, 0x00700222, 0x00800322,
+	0x00900422, 0x00a00522, 0x00b00622, 0x00c00722,
+	0x00d00822, 0x00f00922, 0x00100a22, 0x00200b22,
+	0x00300c22, 0x00400d22, 0x00500e22, 0x00600f22,
+};
+
+static const u32 b43_lcntab_0x0d[] = {
+	0x00000000, 0x00000000, 0x10000000, 0x00000000,
+	0x20000000, 0x00000000, 0x30000000, 0x00000000,
+	0x40000000, 0x00000000, 0x50000000, 0x00000000,
+	0x60000000, 0x00000000, 0x70000000, 0x00000000,
+	0x80000000, 0x00000000, 0x90000000, 0x00000008,
+	0xa0000000, 0x00000008, 0xb0000000, 0x00000008,
+	0xc0000000, 0x00000008, 0xd0000000, 0x00000008,
+	0xe0000000, 0x00000008, 0xf0000000, 0x00000008,
+	0x00000000, 0x00000009, 0x10000000, 0x00000009,
+	0x20000000, 0x00000019, 0x30000000, 0x00000019,
+	0x40000000, 0x00000019, 0x50000000, 0x00000019,
+	0x60000000, 0x00000019, 0x70000000, 0x00000019,
+	0x80000000, 0x00000019, 0x90000000, 0x00000019,
+	0xa0000000, 0x00000019, 0xb0000000, 0x00000019,
+	0xc0000000, 0x00000019, 0xd0000000, 0x00000019,
+	0xe0000000, 0x00000019, 0xf0000000, 0x00000019,
+	0x00000000, 0x0000001a, 0x10000000, 0x0000001a,
+	0x20000000, 0x0000001a, 0x30000000, 0x0000001a,
+	0x40000000, 0x0000001a, 0x50000000, 0x00000002,
+	0x60000000, 0x00000002, 0x70000000, 0x00000002,
+	0x80000000, 0x00000002, 0x90000000, 0x00000002,
+	0xa0000000, 0x00000002, 0xb0000000, 0x00000002,
+	0xc0000000, 0x0000000a, 0xd0000000, 0x0000000a,
+	0xe0000000, 0x0000000a, 0xf0000000, 0x0000000a,
+	0x00000000, 0x0000000b, 0x10000000, 0x0000000b,
+	0x20000000, 0x0000000b, 0x30000000, 0x0000000b,
+	0x40000000, 0x0000000b, 0x50000000, 0x0000001b,
+	0x60000000, 0x0000001b, 0x70000000, 0x0000001b,
+	0x80000000, 0x0000001b, 0x90000000, 0x0000001b,
+	0xa0000000, 0x0000001b, 0xb0000000, 0x0000001b,
+	0xc0000000, 0x0000001b, 0xd0000000, 0x0000001b,
+	0xe0000000, 0x0000001b, 0xf0000000, 0x0000001b,
+	0x00000000, 0x0000001c, 0x10000000, 0x0000001c,
+	0x20000000, 0x0000001c, 0x30000000, 0x0000001c,
+	0x40000000, 0x0000001c, 0x50000000, 0x0000001c,
+	0x60000000, 0x0000001c, 0x70000000, 0x0000001c,
+	0x80000000, 0x0000001c, 0x90000000, 0x0000001c,
+};
+
+static const u16 b43_lcntab_0x0e[] = {
+	0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406,
+	0x0407, 0x0408, 0x0409, 0x040a, 0x058b, 0x058c,
+	0x058d, 0x058e, 0x058f, 0x0090, 0x0091, 0x0092,
+	0x0193, 0x0194, 0x0195, 0x0196, 0x0197, 0x0198,
+	0x0199, 0x019a, 0x019b, 0x019c, 0x019d, 0x019e,
+	0x019f, 0x01a0, 0x01a1, 0x01a2, 0x01a3, 0x01a4,
+	0x01a5, 0x0000,
+};
+
+static const u16 b43_lcntab_0x0f[] = {
+	0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009,
+	0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005,
+	0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009,
+	0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005,
+	0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009,
+	0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005,
+	0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009,
+	0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005,
+	0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009,
+	0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005,
+	0x000a, 0x0009, 0x0006, 0x0005,
+};
+
+static const u16 b43_lcntab_0x10[] = {
+	0x005f, 0x0036, 0x0029, 0x001f, 0x005f, 0x0036,
+	0x0029, 0x001f, 0x005f, 0x0036, 0x0029, 0x001f,
+	0x005f, 0x0036, 0x0029, 0x001f,
+};
+
+static const u16 b43_lcntab_0x11[] = {
+	0x0009, 0x000f, 0x0014, 0x0018, 0x00fe, 0x0007,
+	0x000b, 0x000f, 0x00fb, 0x00fe, 0x0001, 0x0005,
+	0x0008, 0x000b, 0x000e, 0x0011, 0x0014, 0x0017,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0003, 0x0006, 0x0009, 0x000c, 0x000f,
+	0x0012, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0003,
+	0x0006, 0x0009, 0x000c, 0x000f, 0x0012, 0x0015,
+	0x0018, 0x001b, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0003, 0x00eb, 0x0000, 0x0000,
+};
+
+static const u32 b43_lcntab_0x12[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000004, 0x00000000, 0x00000004, 0x00000008,
+	0x00000001, 0x00000005, 0x00000009, 0x0000000d,
+	0x0000004d, 0x0000008d, 0x0000000d, 0x0000004d,
+	0x0000008d, 0x000000cd, 0x0000004f, 0x0000008f,
+	0x000000cf, 0x000000d3, 0x00000113, 0x00000513,
+	0x00000913, 0x00000953, 0x00000d53, 0x00001153,
+	0x00001193, 0x00005193, 0x00009193, 0x0000d193,
+	0x00011193, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000004,
+	0x00000000, 0x00000004, 0x00000008, 0x00000001,
+	0x00000005, 0x00000009, 0x0000000d, 0x0000004d,
+	0x0000008d, 0x0000000d, 0x0000004d, 0x0000008d,
+	0x000000cd, 0x0000004f, 0x0000008f, 0x000000cf,
+	0x000000d3, 0x00000113, 0x00000513, 0x00000913,
+	0x00000953, 0x00000d53, 0x00001153, 0x00005153,
+	0x00009153, 0x0000d153, 0x00011153, 0x00015153,
+	0x00019153, 0x0001d153, 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_lcntab_0x14[] = {
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+	0x0002, 0x0003, 0x0001, 0x0003, 0x0002, 0x0001,
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0002, 0x0003,
+	0x0001, 0x0003, 0x0002, 0x0001, 0x0001, 0x0001,
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+	0x0001, 0x0001,
+};
+
+static const u16 b43_lcntab_0x17[] = {
+	0x001a, 0x0034, 0x004e, 0x0068, 0x009c, 0x00d0,
+	0x00ea, 0x0104, 0x0034, 0x0068, 0x009c, 0x00d0,
+	0x0138, 0x01a0, 0x01d4, 0x0208, 0x004e, 0x009c,
+	0x00ea, 0x0138, 0x01d4, 0x0270, 0x02be, 0x030c,
+	0x0068, 0x00d0, 0x0138, 0x01a0, 0x0270, 0x0340,
+	0x03a8, 0x0410, 0x0018, 0x009c, 0x00d0, 0x0104,
+	0x00ea, 0x0138, 0x0186, 0x00d0, 0x0104, 0x0104,
+	0x0138, 0x016c, 0x016c, 0x01a0, 0x0138, 0x0186,
+	0x0186, 0x01d4, 0x0222, 0x0222, 0x0270, 0x0104,
+	0x0138, 0x016c, 0x0138, 0x016c, 0x01a0, 0x01d4,
+	0x01a0, 0x01d4, 0x0208, 0x0208, 0x023c, 0x0186,
+	0x01d4, 0x0222, 0x01d4, 0x0222, 0x0270, 0x02be,
+	0x0270, 0x02be, 0x030c, 0x030c, 0x035a, 0x0036,
+	0x006c, 0x00a2, 0x00d8, 0x0144, 0x01b0, 0x01e6,
+	0x021c, 0x006c, 0x00d8, 0x0144, 0x01b0, 0x0288,
+	0x0360, 0x03cc, 0x0438, 0x00a2, 0x0144, 0x01e6,
+	0x0288, 0x03cc, 0x0510, 0x05b2, 0x0654, 0x00d8,
+	0x01b0, 0x0288, 0x0360, 0x0510, 0x06c0, 0x0798,
+	0x0870, 0x0018, 0x0144, 0x01b0, 0x021c, 0x01e6,
+	0x0288, 0x032a, 0x01b0, 0x021c, 0x021c, 0x0288,
+	0x02f4, 0x02f4, 0x0360, 0x0288, 0x032a, 0x032a,
+	0x03cc, 0x046e, 0x046e, 0x0510, 0x021c, 0x0288,
+	0x02f4, 0x0288, 0x02f4, 0x0360, 0x03cc, 0x0360,
+	0x03cc, 0x0438, 0x0438, 0x04a4, 0x032a, 0x03cc,
+	0x046e, 0x03cc, 0x046e, 0x0510, 0x05b2, 0x0510,
+	0x05b2, 0x0654, 0x0654, 0x06f6,
+};
+
+static const u16 b43_lcntab_0x00[] = {
+	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00,
+	0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005,
+	0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
+	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003,
+	0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007,
+	0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+static const u32 b43_lcntab_0x18[] = {
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+	0x00080000, 0x00080000, 0x00080000, 0x00080000,
+};
+
+/**************************************************
+ * TX gain.
+ **************************************************/
+
+static const struct b43_lcntab_tx_gain_tbl_entry
+	b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0[B43_LCNTAB_TX_GAIN_SIZE] = {
+	{ 0x03, 0x00, 0x1f, 0x0, 0x48 },
+	{ 0x03, 0x00, 0x1f, 0x0, 0x46 },
+	{ 0x03, 0x00, 0x1f, 0x0, 0x44 },
+	{ 0x03, 0x00, 0x1e, 0x0, 0x43 },
+	{ 0x03, 0x00, 0x1d, 0x0, 0x44 },
+	{ 0x03, 0x00, 0x1c, 0x0, 0x44 },
+	{ 0x03, 0x00, 0x1b, 0x0, 0x45 },
+	{ 0x03, 0x00, 0x1a, 0x0, 0x46 },
+	{ 0x03, 0x00, 0x19, 0x0, 0x46 },
+	{ 0x03, 0x00, 0x18, 0x0, 0x47 },
+	{ 0x03, 0x00, 0x17, 0x0, 0x48 },
+	{ 0x03, 0x00, 0x17, 0x0, 0x46 },
+	{ 0x03, 0x00, 0x16, 0x0, 0x47 },
+	{ 0x03, 0x00, 0x15, 0x0, 0x48 },
+	{ 0x03, 0x00, 0x15, 0x0, 0x46 },
+	{ 0x03, 0x00, 0x15, 0x0, 0x44 },
+	{ 0x03, 0x00, 0x15, 0x0, 0x42 },
+	{ 0x03, 0x00, 0x15, 0x0, 0x40 },
+	{ 0x03, 0x00, 0x15, 0x0, 0x3f },
+	{ 0x03, 0x00, 0x14, 0x0, 0x40 },
+	{ 0x03, 0x00, 0x13, 0x0, 0x41 },
+	{ 0x03, 0x00, 0x13, 0x0, 0x40 },
+	{ 0x03, 0x00, 0x12, 0x0, 0x41 },
+	{ 0x03, 0x00, 0x12, 0x0, 0x40 },
+	{ 0x03, 0x00, 0x11, 0x0, 0x41 },
+	{ 0x03, 0x00, 0x11, 0x0, 0x40 },
+	{ 0x03, 0x00, 0x10, 0x0, 0x41 },
+	{ 0x03, 0x00, 0x10, 0x0, 0x40 },
+	{ 0x03, 0x00, 0x10, 0x0, 0x3e },
+	{ 0x03, 0x00, 0x10, 0x0, 0x3c },
+	{ 0x03, 0x00, 0x10, 0x0, 0x3a },
+	{ 0x03, 0x00, 0x0f, 0x0, 0x3d },
+	{ 0x03, 0x00, 0x0f, 0x0, 0x3b },
+	{ 0x03, 0x00, 0x0e, 0x0, 0x3d },
+	{ 0x03, 0x00, 0x0e, 0x0, 0x3c },
+	{ 0x03, 0x00, 0x0e, 0x0, 0x3a },
+	{ 0x03, 0x00, 0x0d, 0x0, 0x3c },
+	{ 0x03, 0x00, 0x0d, 0x0, 0x3b },
+	{ 0x03, 0x00, 0x0c, 0x0, 0x3e },
+	{ 0x03, 0x00, 0x0c, 0x0, 0x3c },
+	{ 0x03, 0x00, 0x0c, 0x0, 0x3a },
+	{ 0x03, 0x00, 0x0b, 0x0, 0x3e },
+	{ 0x03, 0x00, 0x0b, 0x0, 0x3c },
+	{ 0x03, 0x00, 0x0b, 0x0, 0x3b },
+	{ 0x03, 0x00, 0x0b, 0x0, 0x39 },
+	{ 0x03, 0x00, 0x0a, 0x0, 0x3d },
+	{ 0x03, 0x00, 0x0a, 0x0, 0x3b },
+	{ 0x03, 0x00, 0x0a, 0x0, 0x39 },
+	{ 0x03, 0x00, 0x09, 0x0, 0x3e },
+	{ 0x03, 0x00, 0x09, 0x0, 0x3c },
+	{ 0x03, 0x00, 0x09, 0x0, 0x3a },
+	{ 0x03, 0x00, 0x09, 0x0, 0x39 },
+	{ 0x03, 0x00, 0x08, 0x0, 0x3e },
+	{ 0x03, 0x00, 0x08, 0x0, 0x3c },
+	{ 0x03, 0x00, 0x08, 0x0, 0x3a },
+	{ 0x03, 0x00, 0x08, 0x0, 0x39 },
+	{ 0x03, 0x00, 0x08, 0x0, 0x37 },
+	{ 0x03, 0x00, 0x07, 0x0, 0x3d },
+	{ 0x03, 0x00, 0x07, 0x0, 0x3c },
+	{ 0x03, 0x00, 0x07, 0x0, 0x3a },
+	{ 0x03, 0x00, 0x07, 0x0, 0x38 },
+	{ 0x03, 0x00, 0x07, 0x0, 0x37 },
+	{ 0x03, 0x00, 0x06, 0x0, 0x3e },
+	{ 0x03, 0x00, 0x06, 0x0, 0x3c },
+	{ 0x03, 0x00, 0x06, 0x0, 0x3a },
+	{ 0x03, 0x00, 0x06, 0x0, 0x39 },
+	{ 0x03, 0x00, 0x06, 0x0, 0x37 },
+	{ 0x03, 0x00, 0x06, 0x0, 0x36 },
+	{ 0x03, 0x00, 0x06, 0x0, 0x34 },
+	{ 0x03, 0x00, 0x05, 0x0, 0x3d },
+	{ 0x03, 0x00, 0x05, 0x0, 0x3b },
+	{ 0x03, 0x00, 0x05, 0x0, 0x39 },
+	{ 0x03, 0x00, 0x05, 0x0, 0x38 },
+	{ 0x03, 0x00, 0x05, 0x0, 0x36 },
+	{ 0x03, 0x00, 0x05, 0x0, 0x35 },
+	{ 0x03, 0x00, 0x05, 0x0, 0x33 },
+	{ 0x03, 0x00, 0x04, 0x0, 0x3e },
+	{ 0x03, 0x00, 0x04, 0x0, 0x3c },
+	{ 0x03, 0x00, 0x04, 0x0, 0x3a },
+	{ 0x03, 0x00, 0x04, 0x0, 0x39 },
+	{ 0x03, 0x00, 0x04, 0x0, 0x37 },
+	{ 0x03, 0x00, 0x04, 0x0, 0x36 },
+	{ 0x03, 0x00, 0x04, 0x0, 0x34 },
+	{ 0x03, 0x00, 0x04, 0x0, 0x33 },
+	{ 0x03, 0x00, 0x04, 0x0, 0x31 },
+	{ 0x03, 0x00, 0x04, 0x0, 0x30 },
+	{ 0x03, 0x00, 0x04, 0x0, 0x2e },
+	{ 0x03, 0x00, 0x03, 0x0, 0x3c },
+	{ 0x03, 0x00, 0x03, 0x0, 0x3a },
+	{ 0x03, 0x00, 0x03, 0x0, 0x39 },
+	{ 0x03, 0x00, 0x03, 0x0, 0x37 },
+	{ 0x03, 0x00, 0x03, 0x0, 0x36 },
+	{ 0x03, 0x00, 0x03, 0x0, 0x34 },
+	{ 0x03, 0x00, 0x03, 0x0, 0x33 },
+	{ 0x03, 0x00, 0x03, 0x0, 0x31 },
+	{ 0x03, 0x00, 0x03, 0x0, 0x30 },
+	{ 0x03, 0x00, 0x03, 0x0, 0x2e },
+	{ 0x03, 0x00, 0x03, 0x0, 0x2d },
+	{ 0x03, 0x00, 0x03, 0x0, 0x2c },
+	{ 0x03, 0x00, 0x03, 0x0, 0x2b },
+	{ 0x03, 0x00, 0x03, 0x0, 0x29 },
+	{ 0x03, 0x00, 0x02, 0x0, 0x3d },
+	{ 0x03, 0x00, 0x02, 0x0, 0x3b },
+	{ 0x03, 0x00, 0x02, 0x0, 0x39 },
+	{ 0x03, 0x00, 0x02, 0x0, 0x38 },
+	{ 0x03, 0x00, 0x02, 0x0, 0x36 },
+	{ 0x03, 0x00, 0x02, 0x0, 0x35 },
+	{ 0x03, 0x00, 0x02, 0x0, 0x33 },
+	{ 0x03, 0x00, 0x02, 0x0, 0x32 },
+	{ 0x03, 0x00, 0x02, 0x0, 0x30 },
+	{ 0x03, 0x00, 0x02, 0x0, 0x2f },
+	{ 0x03, 0x00, 0x02, 0x0, 0x2e },
+	{ 0x03, 0x00, 0x02, 0x0, 0x2c },
+	{ 0x03, 0x00, 0x02, 0x0, 0x2b },
+	{ 0x03, 0x00, 0x02, 0x0, 0x2a },
+	{ 0x03, 0x00, 0x02, 0x0, 0x29 },
+	{ 0x03, 0x00, 0x02, 0x0, 0x27 },
+	{ 0x03, 0x00, 0x02, 0x0, 0x26 },
+	{ 0x03, 0x00, 0x02, 0x0, 0x25 },
+	{ 0x03, 0x00, 0x02, 0x0, 0x24 },
+	{ 0x03, 0x00, 0x02, 0x0, 0x23 },
+	{ 0x03, 0x00, 0x02, 0x0, 0x22 },
+	{ 0x03, 0x00, 0x02, 0x0, 0x21 },
+	{ 0x03, 0x00, 0x02, 0x0, 0x20 },
+	{ 0x03, 0x00, 0x01, 0x0, 0x3f },
+	{ 0x03, 0x00, 0x01, 0x0, 0x3d },
+	{ 0x03, 0x00, 0x01, 0x0, 0x3b },
+	{ 0x03, 0x00, 0x01, 0x0, 0x39 },
+};
+
+/**************************************************
+ * SW control.
+ **************************************************/
+
+static const u16 b43_lcntab_sw_ctl_4313_epa_rev0[] = {
+	0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
+	0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
+	0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
+	0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
+	0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
+	0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
+	0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
+	0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
+	0x0002, 0x0008, 0x0004, 0x0001, 0x0002, 0x0008,
+	0x0004, 0x0001, 0x0002, 0x0008, 0x0004, 0x0001,
+	0x0002, 0x0008, 0x0004, 0x0001,
+};
+
+/**************************************************
+ * R/W ops.
+ **************************************************/
+
+u32 b43_lcntab_read(struct b43_wldev *dev, u32 offset)
+{
+	u32 type, value;
+
+	type = offset & B43_LCNTAB_TYPEMASK;
+	offset &= ~B43_LCNTAB_TYPEMASK;
+	B43_WARN_ON(offset > 0xFFFF);
+
+	switch (type) {
+	case B43_LCNTAB_8BIT:
+		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
+		value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO) & 0xFF;
+		break;
+	case B43_LCNTAB_16BIT:
+		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
+		value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO);
+		break;
+	case B43_LCNTAB_32BIT:
+		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
+		value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO);
+		value |= (b43_phy_read(dev, B43_PHY_LCN_TABLE_DATAHI) << 16);
+		break;
+	default:
+		B43_WARN_ON(1);
+		value = 0;
+	}
+
+	return value;
+}
+
+void b43_lcntab_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_LCNTAB_TYPEMASK;
+	offset &= ~B43_LCNTAB_TYPEMASK;
+	B43_WARN_ON(offset > 0xFFFF);
+
+	b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
+
+	for (i = 0; i < nr_elements; i++) {
+		switch (type) {
+		case B43_LCNTAB_8BIT:
+			*data = b43_phy_read(dev,
+					     B43_PHY_LCN_TABLE_DATALO) & 0xFF;
+			data++;
+			break;
+		case B43_LCNTAB_16BIT:
+			*((u16 *)data) = b43_phy_read(dev,
+						      B43_PHY_LCN_TABLE_DATALO);
+			data += 2;
+			break;
+		case B43_LCNTAB_32BIT:
+			*((u32 *)data) = b43_phy_read(dev,
+						B43_PHY_LCN_TABLE_DATALO);
+			*((u32 *)data) |= (b43_phy_read(dev,
+					   B43_PHY_LCN_TABLE_DATAHI) << 16);
+			data += 4;
+			break;
+		default:
+			B43_WARN_ON(1);
+		}
+	}
+}
+
+void b43_lcntab_write(struct b43_wldev *dev, u32 offset, u32 value)
+{
+	u32 type;
+
+	type = offset & B43_LCNTAB_TYPEMASK;
+	offset &= 0xFFFF;
+
+	switch (type) {
+	case B43_LCNTAB_8BIT:
+		B43_WARN_ON(value & ~0xFF);
+		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
+		b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value);
+		break;
+	case B43_LCNTAB_16BIT:
+		B43_WARN_ON(value & ~0xFFFF);
+		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
+		b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value);
+		break;
+	case B43_LCNTAB_32BIT:
+		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
+		b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, value >> 16);
+		b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value & 0xFFFF);
+		break;
+	default:
+		B43_WARN_ON(1);
+	}
+
+	return;
+}
+
+void b43_lcntab_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_LCNTAB_TYPEMASK;
+	offset &= ~B43_LCNTAB_TYPEMASK;
+	B43_WARN_ON(offset > 0xFFFF);
+
+	b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset);
+
+	for (i = 0; i < nr_elements; i++) {
+		switch (type) {
+		case B43_LCNTAB_8BIT:
+			value = *data;
+			data++;
+			B43_WARN_ON(value & ~0xFF);
+			b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value);
+			break;
+		case B43_LCNTAB_16BIT:
+			value = *((u16 *)data);
+			data += 2;
+			B43_WARN_ON(value & ~0xFFFF);
+			b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value);
+			break;
+		case B43_LCNTAB_32BIT:
+			value = *((u32 *)data);
+			data += 4;
+			b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI,
+				      value >> 16);
+			b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO,
+				      value & 0xFFFF);
+			break;
+		default:
+			B43_WARN_ON(1);
+		}
+	}
+}
+
+/**************************************************
+ * Tables ops.
+ **************************************************/
+
+#define lcntab_upload(dev, offset, data) do { \
+		b43_lcntab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
+	} while (0)
+static void b43_phy_lcn_upload_static_tables(struct b43_wldev *dev)
+{
+	lcntab_upload(dev, B43_LCNTAB16(0x02, 0), b43_lcntab_0x02);
+	lcntab_upload(dev, B43_LCNTAB16(0x01, 0), b43_lcntab_0x01);
+	lcntab_upload(dev, B43_LCNTAB32(0x0b, 0), b43_lcntab_0x0b);
+	lcntab_upload(dev, B43_LCNTAB32(0x0c, 0), b43_lcntab_0x0c);
+	lcntab_upload(dev, B43_LCNTAB32(0x0d, 0), b43_lcntab_0x0d);
+	lcntab_upload(dev, B43_LCNTAB16(0x0e, 0), b43_lcntab_0x0e);
+	lcntab_upload(dev, B43_LCNTAB16(0x0f, 0), b43_lcntab_0x0f);
+	lcntab_upload(dev, B43_LCNTAB16(0x10, 0), b43_lcntab_0x10);
+	lcntab_upload(dev, B43_LCNTAB16(0x11, 0), b43_lcntab_0x11);
+	lcntab_upload(dev, B43_LCNTAB32(0x12, 0), b43_lcntab_0x12);
+	lcntab_upload(dev, B43_LCNTAB16(0x14, 0), b43_lcntab_0x14);
+	lcntab_upload(dev, B43_LCNTAB16(0x17, 0), b43_lcntab_0x17);
+	lcntab_upload(dev, B43_LCNTAB16(0x00, 0), b43_lcntab_0x00);
+	lcntab_upload(dev, B43_LCNTAB32(0x18, 0), b43_lcntab_0x18);
+}
+
+static void b43_phy_lcn_load_tx_gain_tab(struct b43_wldev *dev,
+			const struct b43_lcntab_tx_gain_tbl_entry *gain_table)
+{
+	u32 i;
+	u32 val;
+
+	u16 pa_gain = 0x70;
+	if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_FEM)
+		pa_gain = 0x10;
+
+	for (i = 0; i < B43_LCNTAB_TX_GAIN_SIZE; i++) {
+		val = ((pa_gain << 24) |
+		       (gain_table[i].pad << 16) |
+		       (gain_table[i].pga << 8) |
+			gain_table[i].gm);
+		b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0xc0 + i), val);
+
+		/* brcmsmac doesn't maskset, we follow newer wl here */
+		val = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x140 + i));
+		val &= 0x000fffff;
+		val |= ((gain_table[i].dac << 28) |
+			(gain_table[i].bb_mult << 20));
+		b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x140 + i), val);
+	}
+}
+
+/* wlc_lcnphy_load_rfpower */
+static void b43_phy_lcn_load_rfpower(struct b43_wldev *dev)
+{
+	u32 bbmult, rfgain;
+	u8 i;
+
+	for (i = 0; i < 128; i++) {
+		bbmult = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x140 + i));
+		bbmult >>= 20;
+		rfgain = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0xc0 + i));
+
+		/* TODO: calculate value for 0x240 + i table offset
+		 * b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x240 + i), val);
+		 */
+	}
+}
+
+/* Not implemented in brcmsmac, noticed in wl in MMIO dump */
+static void b43_phy_lcn_rewrite_rfpower_table(struct b43_wldev *dev)
+{
+	int i;
+	u32 tmp;
+	for (i = 0; i < 128; i++) {
+		tmp = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x240 + i));
+		b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x240 + i), tmp);
+	}
+}
+
+/* wlc_lcnphy_clear_papd_comptable */
+static void b43_phy_lcn_clean_papd_comp_table(struct b43_wldev *dev)
+{
+	u8 i;
+
+	for (i = 0; i < 0x80; i++)
+		b43_lcntab_write(dev, B43_LCNTAB32(0x18, i), 0x80000);
+}
+
+/* wlc_lcnphy_tbl_init */
+void b43_phy_lcn_tables_init(struct b43_wldev *dev)
+{
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+
+	b43_phy_lcn_upload_static_tables(dev);
+
+	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
+		if (sprom->boardflags_lo & B43_BFL_FEM)
+			b43_phy_lcn_load_tx_gain_tab(dev,
+				b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0);
+		else
+			b43err(dev->wl,
+			       "TX gain table unknown for this card\n");
+	}
+
+	if (sprom->boardflags_lo & B43_BFL_FEM &&
+	    !(sprom->boardflags_hi & B43_BFH_FEM_BT))
+		b43_lcntab_write_bulk(dev, B43_LCNTAB16(0xf, 0),
+			ARRAY_SIZE(b43_lcntab_sw_ctl_4313_epa_rev0),
+			b43_lcntab_sw_ctl_4313_epa_rev0);
+	else
+		b43err(dev->wl, "SW ctl table is unknown for this card\n");
+
+	b43_phy_lcn_load_rfpower(dev);
+	b43_phy_lcn_rewrite_rfpower_table(dev);
+	b43_phy_lcn_clean_papd_comp_table(dev);
+}
diff --git a/drivers/net/wireless/broadcom/b43/tables_phy_lcn.h b/drivers/net/wireless/broadcom/b43/tables_phy_lcn.h
new file mode 100644
index 0000000..5ea6c15
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/tables_phy_lcn.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_TABLES_PHY_LCN_H_
+#define B43_TABLES_PHY_LCN_H_
+
+/* The LCN-PHY tables. */
+#define B43_LCNTAB_TYPEMASK		0xF0000000
+#define B43_LCNTAB_8BIT			0x10000000
+#define B43_LCNTAB_16BIT		0x20000000
+#define B43_LCNTAB_32BIT		0x30000000
+#define B43_LCNTAB8(table, offset)	(((table) << 10) | (offset) | B43_LCNTAB_8BIT)
+#define B43_LCNTAB16(table, offset)	(((table) << 10) | (offset) | B43_LCNTAB_16BIT)
+#define B43_LCNTAB32(table, offset)	(((table) << 10) | (offset) | B43_LCNTAB_32BIT)
+
+#define B43_LCNTAB_TX_GAIN_SIZE		128
+
+u32 b43_lcntab_read(struct b43_wldev *dev, u32 offset);
+void b43_lcntab_read_bulk(struct b43_wldev *dev, u32 offset,
+			  unsigned int nr_elements, void *_data);
+void b43_lcntab_write(struct b43_wldev *dev, u32 offset, u32 value);
+void b43_lcntab_write_bulk(struct b43_wldev *dev, u32 offset,
+			   unsigned int nr_elements, const void *_data);
+
+void b43_phy_lcn_tables_init(struct b43_wldev *dev);
+
+#endif /* B43_TABLES_PHY_LCN_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/wa.c b/drivers/net/wireless/broadcom/b43/wa.c
new file mode 100644
index 0000000..0e96c08
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/wa.c
@@ -0,0 +1,389 @@
+/*
+
+  Broadcom B43 wireless driver
+
+  PHY workarounds.
+
+  Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
+  Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
+
+  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 "main.h"
+#include "tables.h"
+#include "phy_common.h"
+#include "wa.h"
+
+void b43_wa_initgains(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	b43_phy_write(dev, B43_PHY_LNAHPFCTL, 0x1FF9);
+	b43_phy_mask(dev, B43_PHY_LPFGAINCTL, 0xFF0F);
+	if (phy->rev <= 2)
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_LPFGAIN, 0, 0x1FBF);
+	b43_radio_write16(dev, 0x0002, 0x1FBF);
+
+	b43_phy_write(dev, 0x0024, 0x4680);
+	b43_phy_write(dev, 0x0020, 0x0003);
+	b43_phy_write(dev, 0x001D, 0x0F40);
+	b43_phy_write(dev, 0x001F, 0x1C00);
+	if (phy->rev <= 3)
+		b43_phy_maskset(dev, 0x002A, 0x00FF, 0x0400);
+	else if (phy->rev == 5) {
+		b43_phy_maskset(dev, 0x002A, 0x00FF, 0x1A00);
+		b43_phy_write(dev, 0x00CC, 0x2121);
+	}
+	if (phy->rev >= 3)
+		b43_phy_write(dev, 0x00BA, 0x3ED5);
+}
+
+static void b43_wa_rssi_lt(struct b43_wldev *dev) /* RSSI lookup table */
+{
+	int i;
+
+	if (0 /* FIXME: For APHY.rev=2 this might be needed */) {
+		for (i = 0; i < 8; i++)
+			b43_ofdmtab_write16(dev, B43_OFDMTAB_RSSI, i, i + 8);
+		for (i = 8; i < 16; i++)
+			b43_ofdmtab_write16(dev, B43_OFDMTAB_RSSI, i, i - 8);
+	} else {
+		for (i = 0; i < 64; i++)
+			b43_ofdmtab_write16(dev, B43_OFDMTAB_RSSI, i, i);
+	}
+}
+
+static void b43_wa_analog(struct b43_wldev *dev)
+{
+	u16 ofdmrev;
+
+	ofdmrev = b43_phy_read(dev, B43_PHY_VERSION_OFDM) & B43_PHYVER_VERSION;
+	if (ofdmrev > 2) {
+		b43_phy_write(dev, B43_PHY_PWRDOWN, 0x1000);
+	} else {
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 3, 0x1044);
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 4, 0x7201);
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 6, 0x0040);
+	}
+}
+
+static void b43_wa_fft(struct b43_wldev *dev) /* Fine frequency table */
+{
+	int i;
+
+	for (i = 0; i < B43_TAB_FINEFREQG_SIZE; i++)
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_DACRFPABB, i,
+				    b43_tab_finefreqg[i]);
+}
+
+static void b43_wa_nft(struct b43_wldev *dev) /* Noise figure table */
+{
+	struct b43_phy *phy = &dev->phy;
+	int i;
+
+	if (phy->rev == 1)
+		for (i = 0; i < B43_TAB_NOISEG1_SIZE; i++)
+			b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, i,
+					    b43_tab_noiseg1[i]);
+	else
+		for (i = 0; i < B43_TAB_NOISEG2_SIZE; i++)
+			b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, i,
+					    b43_tab_noiseg2[i]);
+}
+
+static void b43_wa_rt(struct b43_wldev *dev) /* Rotor table */
+{
+	int i;
+
+	for (i = 0; i < B43_TAB_ROTOR_SIZE; i++)
+		b43_ofdmtab_write32(dev, B43_OFDMTAB_ROTOR, i, b43_tab_rotor[i]);
+}
+
+static void b43_write_nst(struct b43_wldev *dev, const u16 *nst)
+{
+	int i;
+
+	for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE, i, nst[i]);
+}
+
+static void b43_wa_nst(struct b43_wldev *dev) /* Noise scale table */
+{
+	struct b43_phy *phy = &dev->phy;
+
+	if (phy->rev >= 6) {
+		if (b43_phy_read(dev, B43_PHY_ENCORE) & B43_PHY_ENCORE_EN)
+			b43_write_nst(dev, b43_tab_noisescaleg3);
+		else
+			b43_write_nst(dev, b43_tab_noisescaleg2);
+	} else {
+		b43_write_nst(dev, b43_tab_noisescaleg1);
+	}
+}
+
+static void b43_wa_art(struct b43_wldev *dev) /* ADV retard table */
+{
+	int i;
+
+	for (i = 0; i < B43_TAB_RETARD_SIZE; i++)
+			b43_ofdmtab_write32(dev, B43_OFDMTAB_ADVRETARD,
+				i, b43_tab_retard[i]);
+}
+
+static void b43_wa_msst(struct b43_wldev *dev) /* Min sigma square table */
+{
+	struct b43_phy *phy = &dev->phy;
+	int i;
+	const u16 *tab;
+
+	if (phy->type == B43_PHYTYPE_G) {
+		tab = b43_tab_sigmasqr2;
+	} else {
+		B43_WARN_ON(1);
+		return;
+	}
+
+	for (i = 0; i < B43_TAB_SIGMASQR_SIZE; i++) {
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_MINSIGSQ,
+					i, tab[i]);
+	}
+}
+
+static void b43_wa_crs_ed(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	if (phy->rev == 1) {
+		b43_phy_write(dev, B43_PHY_CRSTHRES1_R1, 0x4F19);
+	} else if (phy->rev == 2) {
+		b43_phy_write(dev, B43_PHY_CRSTHRES1, 0x1861);
+		b43_phy_write(dev, B43_PHY_CRSTHRES2, 0x0271);
+		b43_phy_set(dev, B43_PHY_ANTDWELL, 0x0800);
+	} else {
+		b43_phy_write(dev, B43_PHY_CRSTHRES1, 0x0098);
+		b43_phy_write(dev, B43_PHY_CRSTHRES2, 0x0070);
+		b43_phy_write(dev, B43_PHY_OFDM(0xC9), 0x0080);
+		b43_phy_set(dev, B43_PHY_ANTDWELL, 0x0800);
+	}
+}
+
+static void b43_wa_crs_thr(struct b43_wldev *dev)
+{
+	b43_phy_maskset(dev, B43_PHY_CRS0, ~0x03C0, 0xD000);
+}
+
+static void b43_wa_crs_blank(struct b43_wldev *dev)
+{
+	b43_phy_write(dev, B43_PHY_OFDM(0x2C), 0x005A);
+}
+
+static void b43_wa_cck_shiftbits(struct b43_wldev *dev)
+{
+	b43_phy_write(dev, B43_PHY_CCKSHIFTBITS, 0x0026);
+}
+
+static void b43_wa_wrssi_offset(struct b43_wldev *dev)
+{
+	int i;
+
+	if (dev->phy.rev == 1) {
+		for (i = 0; i < 16; i++) {
+			b43_ofdmtab_write16(dev, B43_OFDMTAB_WRSSI_R1,
+						i, 0x0020);
+		}
+	} else {
+		for (i = 0; i < 32; i++) {
+			b43_ofdmtab_write16(dev, B43_OFDMTAB_WRSSI,
+						i, 0x0820);
+		}
+	}
+}
+
+static void b43_wa_txpuoff_rxpuon(struct b43_wldev *dev)
+{
+	b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_0F, 2, 15);
+	b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_0F, 3, 20);
+}
+
+static void b43_wa_altagc(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	if (phy->rev == 1) {
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 0, 254);
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 1, 13);
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 2, 19);
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 3, 25);
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, 0, 0x2710);
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, 1, 0x9B83);
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, 2, 0x9B83);
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, 3, 0x0F8D);
+		b43_phy_write(dev, B43_PHY_LMS, 4);
+	} else {
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0, 254);
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 1, 13);
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 2, 19);
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 3, 25);
+	}
+
+	b43_phy_maskset(dev, B43_PHY_CCKSHIFTBITS_WA, 0x00FF, 0x5700);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0x1A), ~0x007F, 0x000F);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0x1A), ~0x3F80, 0x2B80);
+	b43_phy_maskset(dev, B43_PHY_ANTWRSETT, 0xF0FF, 0x0300);
+	b43_radio_set(dev, 0x7A, 0x0008);
+	b43_phy_maskset(dev, B43_PHY_N1P1GAIN, ~0x000F, 0x0008);
+	b43_phy_maskset(dev, B43_PHY_P1P2GAIN, ~0x0F00, 0x0600);
+	b43_phy_maskset(dev, B43_PHY_N1N2GAIN, ~0x0F00, 0x0700);
+	b43_phy_maskset(dev, B43_PHY_N1P1GAIN, ~0x0F00, 0x0100);
+	if (phy->rev == 1) {
+		b43_phy_maskset(dev, B43_PHY_N1N2GAIN, ~0x000F, 0x0007);
+	}
+	b43_phy_maskset(dev, B43_PHY_OFDM(0x88), ~0x00FF, 0x001C);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0x88), ~0x3F00, 0x0200);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0x96), ~0x00FF, 0x001C);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0x89), ~0x00FF, 0x0020);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0x89), ~0x3F00, 0x0200);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0x82), ~0x00FF, 0x002E);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0x96), 0x00FF, 0x1A00);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0x81), ~0x00FF, 0x0028);
+	b43_phy_maskset(dev, B43_PHY_OFDM(0x81), 0x00FF, 0x2C00);
+	if (phy->rev == 1) {
+		b43_phy_write(dev, B43_PHY_PEAK_COUNT, 0x092B);
+		b43_phy_maskset(dev, B43_PHY_OFDM(0x1B), ~0x001E, 0x0002);
+	} else {
+		b43_phy_mask(dev, B43_PHY_OFDM(0x1B), ~0x001E);
+		b43_phy_write(dev, B43_PHY_OFDM(0x1F), 0x287A);
+		b43_phy_maskset(dev, B43_PHY_LPFGAINCTL, ~0x000F, 0x0004);
+		if (phy->rev >= 6) {
+			b43_phy_write(dev, B43_PHY_OFDM(0x22), 0x287A);
+			b43_phy_maskset(dev, B43_PHY_LPFGAINCTL, 0x0FFF, 0x3000);
+		}
+	}
+	b43_phy_maskset(dev, B43_PHY_DIVSRCHIDX, 0x8080, 0x7874);
+	b43_phy_write(dev, B43_PHY_OFDM(0x8E), 0x1C00);
+	if (phy->rev == 1) {
+		b43_phy_maskset(dev, B43_PHY_DIVP1P2GAIN, ~0x0F00, 0x0600);
+		b43_phy_write(dev, B43_PHY_OFDM(0x8B), 0x005E);
+		b43_phy_maskset(dev, B43_PHY_ANTWRSETT, ~0x00FF, 0x001E);
+		b43_phy_write(dev, B43_PHY_OFDM(0x8D), 0x0002);
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3_R1, 0, 0);
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3_R1, 1, 7);
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3_R1, 2, 16);
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3_R1, 3, 28);
+	} else {
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3, 0, 0);
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3, 1, 7);
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3, 2, 16);
+		b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3, 3, 28);
+	}
+	if (phy->rev >= 6) {
+		b43_phy_mask(dev, B43_PHY_OFDM(0x26), ~0x0003);
+		b43_phy_mask(dev, B43_PHY_OFDM(0x26), ~0x1000);
+	}
+	b43_phy_read(dev, B43_PHY_VERSION_OFDM); /* Dummy read */
+}
+
+static void b43_wa_tr_ltov(struct b43_wldev *dev) /* TR Lookup Table Original Values */
+{
+	b43_gtab_write(dev, B43_GTAB_ORIGTR, 0, 0x7654);
+}
+
+static void b43_wa_cpll_nonpilot(struct b43_wldev *dev)
+{
+	b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_11, 0, 0);
+	b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_11, 1, 0);
+}
+
+static void b43_wa_boards_g(struct b43_wldev *dev)
+{
+	struct ssb_sprom *sprom = dev->dev->bus_sprom;
+	struct b43_phy *phy = &dev->phy;
+
+	if (dev->dev->board_vendor != SSB_BOARDVENDOR_BCM ||
+	    dev->dev->board_type != SSB_BOARD_BU4306 ||
+	    dev->dev->board_rev != 0x17) {
+		if (phy->rev < 2) {
+			b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX_R1, 1, 0x0002);
+			b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX_R1, 2, 0x0001);
+		} else {
+			b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 1, 0x0002);
+			b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 2, 0x0001);
+			if ((sprom->boardflags_lo & B43_BFL_EXTLNA) &&
+			    (phy->rev >= 7)) {
+				b43_phy_mask(dev, B43_PHY_EXTG(0x11), 0xF7FF);
+				b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0020, 0x0001);
+				b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0021, 0x0001);
+				b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0022, 0x0001);
+				b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0023, 0x0000);
+				b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0000, 0x0000);
+				b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0003, 0x0002);
+			}
+		}
+	}
+	if (sprom->boardflags_lo & B43_BFL_FEM) {
+		b43_phy_write(dev, B43_PHY_GTABCTL, 0x3120);
+		b43_phy_write(dev, B43_PHY_GTABDATA, 0xC480);
+	}
+}
+
+void b43_wa_all(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+
+	if (phy->type == B43_PHYTYPE_G) {
+		switch (phy->rev) {
+		case 1://XXX review rev1
+			b43_wa_crs_ed(dev);
+			b43_wa_crs_thr(dev);
+			b43_wa_crs_blank(dev);
+			b43_wa_cck_shiftbits(dev);
+			b43_wa_fft(dev);
+			b43_wa_nft(dev);
+			b43_wa_rt(dev);
+			b43_wa_nst(dev);
+			b43_wa_art(dev);
+			b43_wa_wrssi_offset(dev);
+			b43_wa_altagc(dev);
+			break;
+		case 2:
+		case 6:
+		case 7:
+		case 8:
+		case 9:
+			b43_wa_tr_ltov(dev);
+			b43_wa_crs_ed(dev);
+			b43_wa_rssi_lt(dev);
+			b43_wa_nft(dev);
+			b43_wa_nst(dev);
+			b43_wa_msst(dev);
+			b43_wa_wrssi_offset(dev);
+			b43_wa_altagc(dev);
+			b43_wa_analog(dev);
+			b43_wa_txpuoff_rxpuon(dev);
+			break;
+		default:
+			B43_WARN_ON(1);
+		}
+		b43_wa_boards_g(dev);
+	} else { /* No N PHY support so far, LP PHY is in phy_lp.c */
+		B43_WARN_ON(1);
+	}
+
+	b43_wa_cpll_nonpilot(dev);
+}
diff --git a/drivers/net/wireless/broadcom/b43/wa.h b/drivers/net/wireless/broadcom/b43/wa.h
new file mode 100644
index 0000000..f3459b9
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/wa.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_WA_H_
+#define B43_WA_H_
+
+void b43_wa_initgains(struct b43_wldev *dev);
+void b43_wa_all(struct b43_wldev *dev);
+
+#endif /* B43_WA_H_ */
diff --git a/drivers/net/wireless/broadcom/b43/xmit.c b/drivers/net/wireless/broadcom/b43/xmit.c
new file mode 100644
index 0000000..1b9c191
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/xmit.c
@@ -0,0 +1,939 @@
+/*
+
+  Broadcom B43 wireless driver
+
+  Transmission (TX/RX) related functions.
+
+  Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
+  Copyright (C) 2005 Stefano Brivio <stefano.brivio@polimi.it>
+  Copyright (C) 2005, 2006 Michael Buesch <m@bues.ch>
+  Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
+  Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+  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 "xmit.h"
+#include "phy_common.h"
+#include "dma.h"
+#include "pio.h"
+
+static const struct b43_tx_legacy_rate_phy_ctl_entry b43_tx_legacy_rate_phy_ctl[] = {
+	{ B43_CCK_RATE_1MB,	0x0,			0x0 },
+	{ B43_CCK_RATE_2MB,	0x0,			0x1 },
+	{ B43_CCK_RATE_5MB,	0x0,			0x2 },
+	{ B43_CCK_RATE_11MB,	0x0,			0x3 },
+	{ B43_OFDM_RATE_6MB,	B43_TXH_PHY1_CRATE_1_2,	B43_TXH_PHY1_MODUL_BPSK },
+	{ B43_OFDM_RATE_9MB,	B43_TXH_PHY1_CRATE_3_4,	B43_TXH_PHY1_MODUL_BPSK },
+	{ B43_OFDM_RATE_12MB,	B43_TXH_PHY1_CRATE_1_2,	B43_TXH_PHY1_MODUL_QPSK },
+	{ B43_OFDM_RATE_18MB,	B43_TXH_PHY1_CRATE_3_4,	B43_TXH_PHY1_MODUL_QPSK },
+	{ B43_OFDM_RATE_24MB,	B43_TXH_PHY1_CRATE_1_2,	B43_TXH_PHY1_MODUL_QAM16 },
+	{ B43_OFDM_RATE_36MB,	B43_TXH_PHY1_CRATE_3_4,	B43_TXH_PHY1_MODUL_QAM16 },
+	{ B43_OFDM_RATE_48MB,	B43_TXH_PHY1_CRATE_2_3,	B43_TXH_PHY1_MODUL_QAM64 },
+	{ B43_OFDM_RATE_54MB,	B43_TXH_PHY1_CRATE_3_4,	B43_TXH_PHY1_MODUL_QAM64 },
+};
+
+static const struct b43_tx_legacy_rate_phy_ctl_entry *
+b43_tx_legacy_rate_phy_ctl_ent(u8 bitrate)
+{
+	const struct b43_tx_legacy_rate_phy_ctl_entry *e;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(b43_tx_legacy_rate_phy_ctl); i++) {
+		e = &(b43_tx_legacy_rate_phy_ctl[i]);
+		if (e->bitrate == bitrate)
+			return e;
+	}
+
+	B43_WARN_ON(1);
+	return NULL;
+}
+
+/* Extract the bitrate index out of a CCK PLCP header. */
+static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp)
+{
+	switch (plcp->raw[0]) {
+	case 0x0A:
+		return 0;
+	case 0x14:
+		return 1;
+	case 0x37:
+		return 2;
+	case 0x6E:
+		return 3;
+	}
+	return -1;
+}
+
+/* Extract the bitrate index out of an OFDM PLCP header. */
+static int b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool ghz5)
+{
+	/* For 2 GHz band first OFDM rate is at index 4, see main.c */
+	int base = ghz5 ? 0 : 4;
+
+	switch (plcp->raw[0] & 0xF) {
+	case 0xB:
+		return base + 0;
+	case 0xF:
+		return base + 1;
+	case 0xA:
+		return base + 2;
+	case 0xE:
+		return base + 3;
+	case 0x9:
+		return base + 4;
+	case 0xD:
+		return base + 5;
+	case 0x8:
+		return base + 6;
+	case 0xC:
+		return base + 7;
+	}
+	return -1;
+}
+
+u8 b43_plcp_get_ratecode_cck(const u8 bitrate)
+{
+	switch (bitrate) {
+	case B43_CCK_RATE_1MB:
+		return 0x0A;
+	case B43_CCK_RATE_2MB:
+		return 0x14;
+	case B43_CCK_RATE_5MB:
+		return 0x37;
+	case B43_CCK_RATE_11MB:
+		return 0x6E;
+	}
+	B43_WARN_ON(1);
+	return 0;
+}
+
+u8 b43_plcp_get_ratecode_ofdm(const u8 bitrate)
+{
+	switch (bitrate) {
+	case B43_OFDM_RATE_6MB:
+		return 0xB;
+	case B43_OFDM_RATE_9MB:
+		return 0xF;
+	case B43_OFDM_RATE_12MB:
+		return 0xA;
+	case B43_OFDM_RATE_18MB:
+		return 0xE;
+	case B43_OFDM_RATE_24MB:
+		return 0x9;
+	case B43_OFDM_RATE_36MB:
+		return 0xD;
+	case B43_OFDM_RATE_48MB:
+		return 0x8;
+	case B43_OFDM_RATE_54MB:
+		return 0xC;
+	}
+	B43_WARN_ON(1);
+	return 0;
+}
+
+void b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp,
+			   const u16 octets, const u8 bitrate)
+{
+	__u8 *raw = plcp->raw;
+
+	if (b43_is_ofdm_rate(bitrate)) {
+		u32 d;
+
+		d = b43_plcp_get_ratecode_ofdm(bitrate);
+		B43_WARN_ON(octets & 0xF000);
+		d |= (octets << 5);
+		plcp->data = cpu_to_le32(d);
+	} else {
+		u32 plen;
+
+		plen = octets * 16 / bitrate;
+		if ((octets * 16 % bitrate) > 0) {
+			plen++;
+			if ((bitrate == B43_CCK_RATE_11MB)
+			    && ((octets * 8 % 11) < 4)) {
+				raw[1] = 0x84;
+			} else
+				raw[1] = 0x04;
+		} else
+			raw[1] = 0x04;
+		plcp->data |= cpu_to_le32(plen << 16);
+		raw[0] = b43_plcp_get_ratecode_cck(bitrate);
+	}
+}
+
+/* TODO: verify if needed for SSLPN or LCN  */
+static u16 b43_generate_tx_phy_ctl1(struct b43_wldev *dev, u8 bitrate)
+{
+	const struct b43_phy *phy = &dev->phy;
+	const struct b43_tx_legacy_rate_phy_ctl_entry *e;
+	u16 control = 0;
+	u16 bw;
+
+	if (phy->type == B43_PHYTYPE_LP)
+		bw = B43_TXH_PHY1_BW_20;
+	else /* FIXME */
+		bw = B43_TXH_PHY1_BW_20;
+
+	if (0) { /* FIXME: MIMO */
+	} else if (b43_is_cck_rate(bitrate) && phy->type != B43_PHYTYPE_LP) {
+		control = bw;
+	} else {
+		control = bw;
+		e = b43_tx_legacy_rate_phy_ctl_ent(bitrate);
+		if (e) {
+			control |= e->coding_rate;
+			control |= e->modulation;
+		}
+		control |= B43_TXH_PHY1_MODE_SISO;
+	}
+
+	return control;
+}
+
+static u8 b43_calc_fallback_rate(u8 bitrate, int gmode)
+{
+	switch (bitrate) {
+	case B43_CCK_RATE_1MB:
+		return B43_CCK_RATE_1MB;
+	case B43_CCK_RATE_2MB:
+		return B43_CCK_RATE_1MB;
+	case B43_CCK_RATE_5MB:
+		return B43_CCK_RATE_2MB;
+	case B43_CCK_RATE_11MB:
+		return B43_CCK_RATE_5MB;
+	/*
+	 * Don't just fallback to CCK; it may be in 5GHz operation
+	 * and falling back to CCK won't work out very well.
+	 */
+	case B43_OFDM_RATE_6MB:
+		if (gmode)
+			return B43_CCK_RATE_5MB;
+		else
+			return B43_OFDM_RATE_6MB;
+	case B43_OFDM_RATE_9MB:
+		return B43_OFDM_RATE_6MB;
+	case B43_OFDM_RATE_12MB:
+		return B43_OFDM_RATE_9MB;
+	case B43_OFDM_RATE_18MB:
+		return B43_OFDM_RATE_12MB;
+	case B43_OFDM_RATE_24MB:
+		return B43_OFDM_RATE_18MB;
+	case B43_OFDM_RATE_36MB:
+		return B43_OFDM_RATE_24MB;
+	case B43_OFDM_RATE_48MB:
+		return B43_OFDM_RATE_36MB;
+	case B43_OFDM_RATE_54MB:
+		return B43_OFDM_RATE_48MB;
+	}
+	B43_WARN_ON(1);
+	return 0;
+}
+
+/* Generate a TX data header. */
+int b43_generate_txhdr(struct b43_wldev *dev,
+		       u8 *_txhdr,
+		       struct sk_buff *skb_frag,
+		       struct ieee80211_tx_info *info,
+		       u16 cookie)
+{
+	const unsigned char *fragment_data = skb_frag->data;
+	unsigned int fragment_len = skb_frag->len;
+	struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr;
+	const struct b43_phy *phy = &dev->phy;
+	const struct ieee80211_hdr *wlhdr =
+	    (const struct ieee80211_hdr *)fragment_data;
+	int use_encryption = !!info->control.hw_key;
+	__le16 fctl = wlhdr->frame_control;
+	struct ieee80211_rate *fbrate;
+	u8 rate, rate_fb;
+	int rate_ofdm, rate_fb_ofdm;
+	unsigned int plcp_fragment_len;
+	u32 mac_ctl = 0;
+	u16 phy_ctl = 0;
+	bool fill_phy_ctl1 = (phy->type == B43_PHYTYPE_LP ||
+			      phy->type == B43_PHYTYPE_N ||
+			      phy->type == B43_PHYTYPE_HT);
+	u8 extra_ft = 0;
+	struct ieee80211_rate *txrate;
+	struct ieee80211_tx_rate *rates;
+
+	memset(txhdr, 0, sizeof(*txhdr));
+
+	txrate = ieee80211_get_tx_rate(dev->wl->hw, info);
+	rate = txrate ? txrate->hw_value : B43_CCK_RATE_1MB;
+	rate_ofdm = b43_is_ofdm_rate(rate);
+	fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : txrate;
+	rate_fb = fbrate->hw_value;
+	rate_fb_ofdm = b43_is_ofdm_rate(rate_fb);
+
+	if (rate_ofdm)
+		txhdr->phy_rate = b43_plcp_get_ratecode_ofdm(rate);
+	else
+		txhdr->phy_rate = b43_plcp_get_ratecode_cck(rate);
+	txhdr->mac_frame_ctl = wlhdr->frame_control;
+	memcpy(txhdr->tx_receiver, wlhdr->addr1, ETH_ALEN);
+
+	/* Calculate duration for fallback rate */
+	if ((rate_fb == rate) ||
+	    (wlhdr->duration_id & cpu_to_le16(0x8000)) ||
+	    (wlhdr->duration_id == cpu_to_le16(0))) {
+		/* If the fallback rate equals the normal rate or the
+		 * dur_id field contains an AID, CFP magic or 0,
+		 * use the original dur_id field. */
+		txhdr->dur_fb = wlhdr->duration_id;
+	} else {
+		txhdr->dur_fb = ieee80211_generic_frame_duration(
+			dev->wl->hw, info->control.vif, info->band,
+			fragment_len, fbrate);
+	}
+
+	plcp_fragment_len = fragment_len + FCS_LEN;
+	if (use_encryption) {
+		u8 key_idx = info->control.hw_key->hw_key_idx;
+		struct b43_key *key;
+		int wlhdr_len;
+		size_t iv_len;
+
+		B43_WARN_ON(key_idx >= ARRAY_SIZE(dev->key));
+		key = &(dev->key[key_idx]);
+
+		if (unlikely(!key->keyconf)) {
+			/* This key is invalid. This might only happen
+			 * in a short timeframe after machine resume before
+			 * we were able to reconfigure keys.
+			 * Drop this packet completely. Do not transmit it
+			 * unencrypted to avoid leaking information. */
+			return -ENOKEY;
+		}
+
+		/* Hardware appends ICV. */
+		plcp_fragment_len += info->control.hw_key->icv_len;
+
+		key_idx = b43_kidx_to_fw(dev, key_idx);
+		mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) &
+			   B43_TXH_MAC_KEYIDX;
+		mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) &
+			   B43_TXH_MAC_KEYALG;
+		wlhdr_len = ieee80211_hdrlen(fctl);
+		if (key->algorithm == B43_SEC_ALGO_TKIP) {
+			u16 phase1key[5];
+			int i;
+			/* we give the phase1key and iv16 here, the key is stored in
+			 * shm. With that the hardware can do phase 2 and encryption.
+			 */
+			ieee80211_get_tkip_p1k(info->control.hw_key, skb_frag, phase1key);
+			/* phase1key is in host endian. Copy to little-endian txhdr->iv. */
+			for (i = 0; i < 5; i++) {
+				txhdr->iv[i * 2 + 0] = phase1key[i];
+				txhdr->iv[i * 2 + 1] = phase1key[i] >> 8;
+			}
+			/* iv16 */
+			memcpy(txhdr->iv + 10, ((u8 *) wlhdr) + wlhdr_len, 3);
+		} else {
+			iv_len = min_t(size_t, info->control.hw_key->iv_len,
+				     ARRAY_SIZE(txhdr->iv));
+			memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
+		}
+	}
+	switch (dev->fw.hdr_format) {
+	case B43_FW_HDR_598:
+		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_598.plcp),
+				      plcp_fragment_len, rate);
+		break;
+	case B43_FW_HDR_351:
+		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_351.plcp),
+				      plcp_fragment_len, rate);
+		break;
+	case B43_FW_HDR_410:
+		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_410.plcp),
+				      plcp_fragment_len, rate);
+		break;
+	}
+	b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb),
+			      plcp_fragment_len, rate_fb);
+
+	/* Extra Frame Types */
+	if (rate_fb_ofdm)
+		extra_ft |= B43_TXH_EFT_FB_OFDM;
+	else
+		extra_ft |= B43_TXH_EFT_FB_CCK;
+
+	/* Set channel radio code. Note that the micrcode ORs 0x100 to
+	 * this value before comparing it to the value in SHM, if this
+	 * is a 5Ghz packet.
+	 */
+	txhdr->chan_radio_code = phy->channel;
+
+	/* PHY TX Control word */
+	if (rate_ofdm)
+		phy_ctl |= B43_TXH_PHY_ENC_OFDM;
+	else
+		phy_ctl |= B43_TXH_PHY_ENC_CCK;
+	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+		phy_ctl |= B43_TXH_PHY_SHORTPRMBL;
+
+	switch (b43_ieee80211_antenna_sanitize(dev, 0)) {
+	case 0: /* Default */
+		phy_ctl |= B43_TXH_PHY_ANT01AUTO;
+		break;
+	case 1: /* Antenna 0 */
+		phy_ctl |= B43_TXH_PHY_ANT0;
+		break;
+	case 2: /* Antenna 1 */
+		phy_ctl |= B43_TXH_PHY_ANT1;
+		break;
+	case 3: /* Antenna 2 */
+		phy_ctl |= B43_TXH_PHY_ANT2;
+		break;
+	case 4: /* Antenna 3 */
+		phy_ctl |= B43_TXH_PHY_ANT3;
+		break;
+	default:
+		B43_WARN_ON(1);
+	}
+
+	rates = info->control.rates;
+	/* MAC control */
+	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
+		mac_ctl |= B43_TXH_MAC_ACK;
+	/* use hardware sequence counter as the non-TID counter */
+	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
+		mac_ctl |= B43_TXH_MAC_HWSEQ;
+	if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
+		mac_ctl |= B43_TXH_MAC_STMSDU;
+	if (!phy->gmode)
+		mac_ctl |= B43_TXH_MAC_5GHZ;
+
+	/* Overwrite rates[0].count to make the retry calculation
+	 * in the tx status easier. need the actual retry limit to
+	 * detect whether the fallback rate was used.
+	 */
+	if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
+	    (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) {
+		rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count;
+		mac_ctl |= B43_TXH_MAC_LONGFRAME;
+	} else {
+		rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count;
+	}
+
+	/* Generate the RTS or CTS-to-self frame */
+	if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
+	    (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) {
+		unsigned int len;
+		struct ieee80211_hdr *uninitialized_var(hdr);
+		int rts_rate, rts_rate_fb;
+		int rts_rate_ofdm, rts_rate_fb_ofdm;
+		struct b43_plcp_hdr6 *uninitialized_var(plcp);
+		struct ieee80211_rate *rts_cts_rate;
+
+		rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info);
+
+		rts_rate = rts_cts_rate ? rts_cts_rate->hw_value : B43_CCK_RATE_1MB;
+		rts_rate_ofdm = b43_is_ofdm_rate(rts_rate);
+		rts_rate_fb = b43_calc_fallback_rate(rts_rate, phy->gmode);
+		rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
+
+		if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+			struct ieee80211_cts *uninitialized_var(cts);
+
+			switch (dev->fw.hdr_format) {
+			case B43_FW_HDR_598:
+				cts = (struct ieee80211_cts *)
+					(txhdr->format_598.rts_frame);
+				break;
+			case B43_FW_HDR_351:
+				cts = (struct ieee80211_cts *)
+					(txhdr->format_351.rts_frame);
+				break;
+			case B43_FW_HDR_410:
+				cts = (struct ieee80211_cts *)
+					(txhdr->format_410.rts_frame);
+				break;
+			}
+			ieee80211_ctstoself_get(dev->wl->hw, info->control.vif,
+						fragment_data, fragment_len,
+						info, cts);
+			mac_ctl |= B43_TXH_MAC_SENDCTS;
+			len = sizeof(struct ieee80211_cts);
+		} else {
+			struct ieee80211_rts *uninitialized_var(rts);
+
+			switch (dev->fw.hdr_format) {
+			case B43_FW_HDR_598:
+				rts = (struct ieee80211_rts *)
+					(txhdr->format_598.rts_frame);
+				break;
+			case B43_FW_HDR_351:
+				rts = (struct ieee80211_rts *)
+					(txhdr->format_351.rts_frame);
+				break;
+			case B43_FW_HDR_410:
+				rts = (struct ieee80211_rts *)
+					(txhdr->format_410.rts_frame);
+				break;
+			}
+			ieee80211_rts_get(dev->wl->hw, info->control.vif,
+					  fragment_data, fragment_len,
+					  info, rts);
+			mac_ctl |= B43_TXH_MAC_SENDRTS;
+			len = sizeof(struct ieee80211_rts);
+		}
+		len += FCS_LEN;
+
+		/* Generate the PLCP headers for the RTS/CTS frame */
+		switch (dev->fw.hdr_format) {
+		case B43_FW_HDR_598:
+			plcp = &txhdr->format_598.rts_plcp;
+			break;
+		case B43_FW_HDR_351:
+			plcp = &txhdr->format_351.rts_plcp;
+			break;
+		case B43_FW_HDR_410:
+			plcp = &txhdr->format_410.rts_plcp;
+			break;
+		}
+		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,
+				      len, rts_rate);
+		plcp = &txhdr->rts_plcp_fb;
+		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,
+				      len, rts_rate_fb);
+
+		switch (dev->fw.hdr_format) {
+		case B43_FW_HDR_598:
+			hdr = (struct ieee80211_hdr *)
+				(&txhdr->format_598.rts_frame);
+			break;
+		case B43_FW_HDR_351:
+			hdr = (struct ieee80211_hdr *)
+				(&txhdr->format_351.rts_frame);
+			break;
+		case B43_FW_HDR_410:
+			hdr = (struct ieee80211_hdr *)
+				(&txhdr->format_410.rts_frame);
+			break;
+		}
+		txhdr->rts_dur_fb = hdr->duration_id;
+
+		if (rts_rate_ofdm) {
+			extra_ft |= B43_TXH_EFT_RTS_OFDM;
+			txhdr->phy_rate_rts =
+			    b43_plcp_get_ratecode_ofdm(rts_rate);
+		} else {
+			extra_ft |= B43_TXH_EFT_RTS_CCK;
+			txhdr->phy_rate_rts =
+			    b43_plcp_get_ratecode_cck(rts_rate);
+		}
+		if (rts_rate_fb_ofdm)
+			extra_ft |= B43_TXH_EFT_RTSFB_OFDM;
+		else
+			extra_ft |= B43_TXH_EFT_RTSFB_CCK;
+
+		if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS &&
+		    fill_phy_ctl1) {
+			txhdr->phy_ctl1_rts = cpu_to_le16(
+				b43_generate_tx_phy_ctl1(dev, rts_rate));
+			txhdr->phy_ctl1_rts_fb = cpu_to_le16(
+				b43_generate_tx_phy_ctl1(dev, rts_rate_fb));
+		}
+	}
+
+	/* Magic cookie */
+	switch (dev->fw.hdr_format) {
+	case B43_FW_HDR_598:
+		txhdr->format_598.cookie = cpu_to_le16(cookie);
+		break;
+	case B43_FW_HDR_351:
+		txhdr->format_351.cookie = cpu_to_le16(cookie);
+		break;
+	case B43_FW_HDR_410:
+		txhdr->format_410.cookie = cpu_to_le16(cookie);
+		break;
+	}
+
+	if (fill_phy_ctl1) {
+		txhdr->phy_ctl1 =
+			cpu_to_le16(b43_generate_tx_phy_ctl1(dev, rate));
+		txhdr->phy_ctl1_fb =
+			cpu_to_le16(b43_generate_tx_phy_ctl1(dev, rate_fb));
+	}
+
+	/* Apply the bitfields */
+	txhdr->mac_ctl = cpu_to_le32(mac_ctl);
+	txhdr->phy_ctl = cpu_to_le16(phy_ctl);
+	txhdr->extra_ft = extra_ft;
+
+	return 0;
+}
+
+static s8 b43_rssi_postprocess(struct b43_wldev *dev,
+			       u8 in_rssi, int ofdm,
+			       int adjust_2053, int adjust_2050)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_g *gphy = phy->g;
+	s32 tmp;
+
+	switch (phy->radio_ver) {
+	case 0x2050:
+		if (ofdm) {
+			tmp = in_rssi;
+			if (tmp > 127)
+				tmp -= 256;
+			tmp *= 73;
+			tmp /= 64;
+			if (adjust_2050)
+				tmp += 25;
+			else
+				tmp -= 3;
+		} else {
+			if (dev->dev->bus_sprom->
+			    boardflags_lo & B43_BFL_RSSI) {
+				if (in_rssi > 63)
+					in_rssi = 63;
+				B43_WARN_ON(phy->type != B43_PHYTYPE_G);
+				tmp = gphy->nrssi_lt[in_rssi];
+				tmp = 31 - tmp;
+				tmp *= -131;
+				tmp /= 128;
+				tmp -= 57;
+			} else {
+				tmp = in_rssi;
+				tmp = 31 - tmp;
+				tmp *= -149;
+				tmp /= 128;
+				tmp -= 68;
+			}
+			if (phy->type == B43_PHYTYPE_G && adjust_2050)
+				tmp += 25;
+		}
+		break;
+	case 0x2060:
+		if (in_rssi > 127)
+			tmp = in_rssi - 256;
+		else
+			tmp = in_rssi;
+		break;
+	default:
+		tmp = in_rssi;
+		tmp -= 11;
+		tmp *= 103;
+		tmp /= 64;
+		if (adjust_2053)
+			tmp -= 109;
+		else
+			tmp -= 83;
+	}
+
+	return (s8) tmp;
+}
+
+//TODO
+#if 0
+static s8 b43_rssinoise_postprocess(struct b43_wldev *dev, u8 in_rssi)
+{
+	struct b43_phy *phy = &dev->phy;
+	s8 ret;
+
+	ret = b43_rssi_postprocess(dev, in_rssi, 0, 1, 1);
+
+	return ret;
+}
+#endif
+
+void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
+{
+	struct ieee80211_rx_status status;
+	struct b43_plcp_hdr6 *plcp;
+	struct ieee80211_hdr *wlhdr;
+	const struct b43_rxhdr_fw4 *rxhdr = _rxhdr;
+	__le16 fctl;
+	u16 phystat0, phystat3;
+	u16 uninitialized_var(chanstat), uninitialized_var(mactime);
+	u32 uninitialized_var(macstat);
+	u16 chanid;
+	int padding, rate_idx;
+
+	memset(&status, 0, sizeof(status));
+
+	/* Get metadata about the frame from the header. */
+	phystat0 = le16_to_cpu(rxhdr->phy_status0);
+	phystat3 = le16_to_cpu(rxhdr->phy_status3);
+	switch (dev->fw.hdr_format) {
+	case B43_FW_HDR_598:
+		macstat = le32_to_cpu(rxhdr->format_598.mac_status);
+		mactime = le16_to_cpu(rxhdr->format_598.mac_time);
+		chanstat = le16_to_cpu(rxhdr->format_598.channel);
+		break;
+	case B43_FW_HDR_410:
+	case B43_FW_HDR_351:
+		macstat = le32_to_cpu(rxhdr->format_351.mac_status);
+		mactime = le16_to_cpu(rxhdr->format_351.mac_time);
+		chanstat = le16_to_cpu(rxhdr->format_351.channel);
+		break;
+	}
+
+	if (unlikely(macstat & B43_RX_MAC_FCSERR)) {
+		dev->wl->ieee_stats.dot11FCSErrorCount++;
+		status.flag |= RX_FLAG_FAILED_FCS_CRC;
+	}
+	if (unlikely(phystat0 & (B43_RX_PHYST0_PLCPHCF | B43_RX_PHYST0_PLCPFV)))
+		status.flag |= RX_FLAG_FAILED_PLCP_CRC;
+	if (phystat0 & B43_RX_PHYST0_SHORTPRMBL)
+		status.enc_flags |= RX_ENC_FLAG_SHORTPRE;
+	if (macstat & B43_RX_MAC_DECERR) {
+		/* Decryption with the given key failed.
+		 * Drop the packet. We also won't be able to decrypt it with
+		 * the key in software. */
+		goto drop;
+	}
+
+	/* Skip PLCP and padding */
+	padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0;
+	if (unlikely(skb->len < (sizeof(struct b43_plcp_hdr6) + padding))) {
+		b43dbg(dev->wl, "RX: Packet size underrun (1)\n");
+		goto drop;
+	}
+	plcp = (struct b43_plcp_hdr6 *)(skb->data + padding);
+	skb_pull(skb, sizeof(struct b43_plcp_hdr6) + padding);
+	/* The skb contains the Wireless Header + payload data now */
+	if (unlikely(skb->len < (2 + 2 + 6 /*minimum hdr */  + FCS_LEN))) {
+		b43dbg(dev->wl, "RX: Packet size underrun (2)\n");
+		goto drop;
+	}
+	wlhdr = (struct ieee80211_hdr *)(skb->data);
+	fctl = wlhdr->frame_control;
+
+	if (macstat & B43_RX_MAC_DEC) {
+		unsigned int keyidx;
+		int wlhdr_len;
+
+		keyidx = ((macstat & B43_RX_MAC_KEYIDX)
+			  >> B43_RX_MAC_KEYIDX_SHIFT);
+		/* We must adjust the key index here. We want the "physical"
+		 * key index, but the ucode passed it slightly different.
+		 */
+		keyidx = b43_kidx_to_raw(dev, keyidx);
+		B43_WARN_ON(keyidx >= ARRAY_SIZE(dev->key));
+
+		if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) {
+			wlhdr_len = ieee80211_hdrlen(fctl);
+			if (unlikely(skb->len < (wlhdr_len + 3))) {
+				b43dbg(dev->wl,
+				       "RX: Packet size underrun (3)\n");
+				goto drop;
+			}
+			status.flag |= RX_FLAG_DECRYPTED;
+		}
+	}
+
+	/* Link quality statistics */
+	switch (chanstat & B43_RX_CHAN_PHYTYPE) {
+	case B43_PHYTYPE_HT:
+		/* TODO: is max the right choice? */
+		status.signal = max_t(__s8,
+			max(rxhdr->phy_ht_power0, rxhdr->phy_ht_power1),
+			rxhdr->phy_ht_power2);
+		break;
+	case B43_PHYTYPE_N:
+		/* Broadcom has code for min and avg, but always uses max */
+		if (rxhdr->power0 == 16 || rxhdr->power0 == 32)
+			status.signal = max(rxhdr->power1, rxhdr->power2);
+		else
+			status.signal = max(rxhdr->power0, rxhdr->power1);
+		break;
+	case B43_PHYTYPE_B:
+	case B43_PHYTYPE_G:
+	case B43_PHYTYPE_LP:
+		status.signal = b43_rssi_postprocess(dev, rxhdr->jssi,
+						  (phystat0 & B43_RX_PHYST0_OFDM),
+						  (phystat0 & B43_RX_PHYST0_GAINCTL),
+						  (phystat3 & B43_RX_PHYST3_TRSTATE));
+		break;
+	}
+
+	if (phystat0 & B43_RX_PHYST0_OFDM)
+		rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp,
+					!!(chanstat & B43_RX_CHAN_5GHZ));
+	else
+		rate_idx = b43_plcp_get_bitrate_idx_cck(plcp);
+	if (unlikely(rate_idx == -1)) {
+		/* PLCP seems to be corrupted.
+		 * Drop the frame, if we are not interested in corrupted frames. */
+		if (!(dev->wl->filter_flags & FIF_PLCPFAIL))
+			goto drop;
+	}
+	status.rate_idx = rate_idx;
+	status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT);
+
+	/*
+	 * All frames on monitor interfaces and beacons always need a full
+	 * 64-bit timestamp. Monitor interfaces need it for diagnostic
+	 * purposes and beacons for IBSS merging.
+	 * This code assumes we get to process the packet within 16 bits
+	 * of timestamp, i.e. about 65 milliseconds after the PHY received
+	 * the first symbol.
+	 */
+	if (ieee80211_is_beacon(fctl) || dev->wl->radiotap_enabled) {
+		u16 low_mactime_now;
+
+		b43_tsf_read(dev, &status.mactime);
+		low_mactime_now = status.mactime;
+		status.mactime = status.mactime & ~0xFFFFULL;
+		status.mactime += mactime;
+		if (low_mactime_now <= mactime)
+			status.mactime -= 0x10000;
+		status.flag |= RX_FLAG_MACTIME_START;
+	}
+
+	chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT;
+	switch (chanstat & B43_RX_CHAN_PHYTYPE) {
+	case B43_PHYTYPE_G:
+		status.band = NL80211_BAND_2GHZ;
+		/* Somewhere between 478.104 and 508.1084 firmware for G-PHY
+		 * has been modified to be compatible with N-PHY and others.
+		 */
+		if (dev->fw.rev >= 508)
+			status.freq = ieee80211_channel_to_frequency(chanid, status.band);
+		else
+			status.freq = chanid + 2400;
+		break;
+	case B43_PHYTYPE_N:
+	case B43_PHYTYPE_LP:
+	case B43_PHYTYPE_HT:
+		/* chanid is the SHM channel cookie. Which is the plain
+		 * channel number in b43. */
+		if (chanstat & B43_RX_CHAN_5GHZ)
+			status.band = NL80211_BAND_5GHZ;
+		else
+			status.band = NL80211_BAND_2GHZ;
+		status.freq =
+			ieee80211_channel_to_frequency(chanid, status.band);
+		break;
+	default:
+		B43_WARN_ON(1);
+		goto drop;
+	}
+
+	memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
+	ieee80211_rx_ni(dev->wl->hw, skb);
+
+#if B43_DEBUG
+	dev->rx_count++;
+#endif
+	return;
+drop:
+	dev_kfree_skb_any(skb);
+}
+
+void b43_handle_txstatus(struct b43_wldev *dev,
+			 const struct b43_txstatus *status)
+{
+	b43_debugfs_log_txstat(dev, status);
+
+	if (status->intermediate)
+		return;
+	if (status->for_ampdu)
+		return;
+	if (!status->acked)
+		dev->wl->ieee_stats.dot11ACKFailureCount++;
+	if (status->rts_count) {
+		if (status->rts_count == 0xF)	//FIXME
+			dev->wl->ieee_stats.dot11RTSFailureCount++;
+		else
+			dev->wl->ieee_stats.dot11RTSSuccessCount++;
+	}
+
+	if (b43_using_pio_transfers(dev))
+		b43_pio_handle_txstatus(dev, status);
+	else
+		b43_dma_handle_txstatus(dev, status);
+
+	b43_phy_txpower_check(dev, 0);
+}
+
+/* Fill out the mac80211 TXstatus report based on the b43-specific
+ * txstatus report data. This returns a boolean whether the frame was
+ * successfully transmitted. */
+bool b43_fill_txstatus_report(struct b43_wldev *dev,
+			      struct ieee80211_tx_info *report,
+			      const struct b43_txstatus *status)
+{
+	bool frame_success = true;
+	int retry_limit;
+
+	/* preserve the confiured retry limit before clearing the status
+	 * The xmit function has overwritten the rc's value with the actual
+	 * retry limit done by the hardware */
+	retry_limit = report->status.rates[0].count;
+	ieee80211_tx_info_clear_status(report);
+
+	if (status->acked) {
+		/* The frame was ACKed. */
+		report->flags |= IEEE80211_TX_STAT_ACK;
+	} else {
+		/* The frame was not ACKed... */
+		if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) {
+			/* ...but we expected an ACK. */
+			frame_success = false;
+		}
+	}
+	if (status->frame_count == 0) {
+		/* The frame was not transmitted at all. */
+		report->status.rates[0].count = 0;
+	} else if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) {
+		/*
+		 * If the short retries (RTS, not data frame) have exceeded
+		 * the limit, the hw will not have tried the selected rate,
+		 * but will have used the fallback rate instead.
+		 * Don't let the rate control count attempts for the selected
+		 * rate in this case, otherwise the statistics will be off.
+		 */
+		report->status.rates[0].count = 0;
+		report->status.rates[1].count = status->frame_count;
+	} else {
+		if (status->frame_count > retry_limit) {
+			report->status.rates[0].count = retry_limit;
+			report->status.rates[1].count = status->frame_count -
+					retry_limit;
+
+		} else {
+			report->status.rates[0].count = status->frame_count;
+			report->status.rates[1].idx = -1;
+		}
+	}
+
+	return frame_success;
+}
+
+/* Stop any TX operation on the device (suspend the hardware queues) */
+void b43_tx_suspend(struct b43_wldev *dev)
+{
+	if (b43_using_pio_transfers(dev))
+		b43_pio_tx_suspend(dev);
+	else
+		b43_dma_tx_suspend(dev);
+}
+
+/* Resume any TX operation on the device (resume the hardware queues) */
+void b43_tx_resume(struct b43_wldev *dev)
+{
+	if (b43_using_pio_transfers(dev))
+		b43_pio_tx_resume(dev);
+	else
+		b43_dma_tx_resume(dev);
+}
diff --git a/drivers/net/wireless/broadcom/b43/xmit.h b/drivers/net/wireless/broadcom/b43/xmit.h
new file mode 100644
index 0000000..6524a75
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/xmit.h
@@ -0,0 +1,417 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_XMIT_H_
+#define B43_XMIT_H_
+
+#include "main.h"
+#include <net/mac80211.h>
+
+
+#define _b43_declare_plcp_hdr(size) \
+	struct b43_plcp_hdr##size {		\
+		union {				\
+			__le32 data;		\
+			__u8 raw[size];		\
+		} __packed;	\
+	} __packed
+
+/* struct b43_plcp_hdr4 */
+_b43_declare_plcp_hdr(4);
+/* struct b43_plcp_hdr6 */
+_b43_declare_plcp_hdr(6);
+
+#undef _b43_declare_plcp_hdr
+
+/* TX header for v4 firmware */
+struct b43_txhdr {
+	__le32 mac_ctl;			/* MAC TX control */
+	__le16 mac_frame_ctl;		/* Copy of the FrameControl field */
+	__le16 tx_fes_time_norm;	/* TX FES Time Normal */
+	__le16 phy_ctl;			/* PHY TX control */
+	__le16 phy_ctl1;		/* PHY TX control word 1 */
+	__le16 phy_ctl1_fb;		/* PHY TX control word 1 for fallback rates */
+	__le16 phy_ctl1_rts;		/* PHY TX control word 1 RTS */
+	__le16 phy_ctl1_rts_fb;		/* PHY TX control word 1 RTS for fallback rates */
+	__u8 phy_rate;			/* PHY rate */
+	__u8 phy_rate_rts;		/* PHY rate for RTS/CTS */
+	__u8 extra_ft;			/* Extra Frame Types */
+	__u8 chan_radio_code;		/* Channel Radio Code */
+	__u8 iv[16];			/* Encryption IV */
+	__u8 tx_receiver[6];		/* TX Frame Receiver address */
+	__le16 tx_fes_time_fb;		/* TX FES Time Fallback */
+	struct b43_plcp_hdr6 rts_plcp_fb; /* RTS fallback PLCP header */
+	__le16 rts_dur_fb;		/* RTS fallback duration */
+	struct b43_plcp_hdr6 plcp_fb;	/* Fallback PLCP header */
+	__le16 dur_fb;			/* Fallback duration */
+	__le16 mimo_modelen;		/* MIMO mode length */
+	__le16 mimo_ratelen_fb;		/* MIMO fallback rate length */
+	__le32 timeout;			/* Timeout */
+
+	union {
+		/* Tested with 598.314, 644.1001 and 666.2 */
+		struct {
+			__le16 mimo_antenna;            /* MIMO antenna select */
+			__le16 preload_size;            /* Preload size */
+			PAD_BYTES(2);
+			__le16 cookie;                  /* TX frame cookie */
+			__le16 tx_status;               /* TX status */
+			__le16 max_n_mpdus;
+			__le16 max_a_bytes_mrt;
+			__le16 max_a_bytes_fbr;
+			__le16 min_m_bytes;
+			struct b43_plcp_hdr6 rts_plcp;  /* RTS PLCP header */
+			__u8 rts_frame[16];             /* The RTS frame (if used) */
+			PAD_BYTES(2);
+			struct b43_plcp_hdr6 plcp;      /* Main PLCP header */
+		} format_598 __packed;
+
+		/* Tested with 410.2160, 478.104 and 508.* */
+		struct {
+			__le16 mimo_antenna;		/* MIMO antenna select */
+			__le16 preload_size;		/* Preload size */
+			PAD_BYTES(2);
+			__le16 cookie;			/* TX frame cookie */
+			__le16 tx_status;		/* TX status */
+			struct b43_plcp_hdr6 rts_plcp;	/* RTS PLCP header */
+			__u8 rts_frame[16];		/* The RTS frame (if used) */
+			PAD_BYTES(2);
+			struct b43_plcp_hdr6 plcp;	/* Main PLCP header */
+		} format_410 __packed;
+
+		/* Tested with 351.126 */
+		struct {
+			PAD_BYTES(2);
+			__le16 cookie;			/* TX frame cookie */
+			__le16 tx_status;		/* TX status */
+			struct b43_plcp_hdr6 rts_plcp;	/* RTS PLCP header */
+			__u8 rts_frame[16];		/* The RTS frame (if used) */
+			PAD_BYTES(2);
+			struct b43_plcp_hdr6 plcp;	/* Main PLCP header */
+		} format_351 __packed;
+
+	} __packed;
+} __packed;
+
+struct b43_tx_legacy_rate_phy_ctl_entry {
+	u8 bitrate;
+	u16 coding_rate;
+	u16 modulation;
+};
+
+/* MAC TX control */
+#define B43_TXH_MAC_RTS_FB_SHORTPRMBL	0x80000000 /* RTS fallback preamble */
+#define B43_TXH_MAC_RTS_SHORTPRMBL	0x40000000 /* RTS main rate preamble */
+#define B43_TXH_MAC_FB_SHORTPRMBL	0x20000000 /* Main fallback preamble */
+#define B43_TXH_MAC_USEFBR		0x10000000 /* Use fallback rate for this AMPDU */
+#define B43_TXH_MAC_KEYIDX		0x0FF00000 /* Security key index */
+#define B43_TXH_MAC_KEYIDX_SHIFT	20
+#define B43_TXH_MAC_ALT_TXPWR		0x00080000 /* Use alternate txpwr defined at loc. M_ALT_TXPWR_IDX */
+#define B43_TXH_MAC_KEYALG		0x00070000 /* Security key algorithm */
+#define B43_TXH_MAC_KEYALG_SHIFT	16
+#define B43_TXH_MAC_AMIC		0x00008000 /* AMIC */
+#define B43_TXH_MAC_RIFS		0x00004000 /* Use RIFS */
+#define B43_TXH_MAC_LIFETIME		0x00002000 /* Lifetime */
+#define B43_TXH_MAC_FRAMEBURST		0x00001000 /* Frameburst */
+#define B43_TXH_MAC_SENDCTS		0x00000800 /* Send CTS-to-self */
+#define B43_TXH_MAC_AMPDU		0x00000600 /* AMPDU status */
+#define  B43_TXH_MAC_AMPDU_MPDU		0x00000000 /* Regular MPDU, not an AMPDU */
+#define  B43_TXH_MAC_AMPDU_FIRST	0x00000200 /* First MPDU or AMPDU */
+#define  B43_TXH_MAC_AMPDU_INTER	0x00000400 /* Intermediate MPDU or AMPDU */
+#define  B43_TXH_MAC_AMPDU_LAST		0x00000600 /* Last (or only) MPDU of AMPDU */
+#define B43_TXH_MAC_40MHZ		0x00000100 /* Use 40 MHz bandwidth */
+#define B43_TXH_MAC_5GHZ		0x00000080 /* 5GHz band */
+#define B43_TXH_MAC_DFCS		0x00000040 /* DFCS */
+#define B43_TXH_MAC_IGNPMQ		0x00000020 /* Ignore PMQ */
+#define B43_TXH_MAC_HWSEQ		0x00000010 /* Use Hardware Sequence Number */
+#define B43_TXH_MAC_STMSDU		0x00000008 /* Start MSDU */
+#define B43_TXH_MAC_SENDRTS		0x00000004 /* Send RTS */
+#define B43_TXH_MAC_LONGFRAME		0x00000002 /* Long frame */
+#define B43_TXH_MAC_ACK			0x00000001 /* Immediate ACK */
+
+/* Extra Frame Types */
+#define B43_TXH_EFT_FB			0x03 /* Data frame fallback encoding */
+#define  B43_TXH_EFT_FB_CCK		0x00 /* CCK */
+#define  B43_TXH_EFT_FB_OFDM		0x01 /* OFDM */
+#define  B43_TXH_EFT_FB_HT		0x02 /* HT */
+#define  B43_TXH_EFT_FB_VHT		0x03 /* VHT */
+#define B43_TXH_EFT_RTS			0x0C /* RTS/CTS encoding */
+#define  B43_TXH_EFT_RTS_CCK		0x00 /* CCK */
+#define  B43_TXH_EFT_RTS_OFDM		0x04 /* OFDM */
+#define  B43_TXH_EFT_RTS_HT		0x08 /* HT */
+#define  B43_TXH_EFT_RTS_VHT		0x0C /* VHT */
+#define B43_TXH_EFT_RTSFB		0x30 /* RTS/CTS fallback encoding */
+#define  B43_TXH_EFT_RTSFB_CCK		0x00 /* CCK */
+#define  B43_TXH_EFT_RTSFB_OFDM		0x10 /* OFDM */
+#define  B43_TXH_EFT_RTSFB_HT		0x20 /* HT */
+#define  B43_TXH_EFT_RTSFB_VHT		0x30 /* VHT */
+
+/* PHY TX control word */
+#define B43_TXH_PHY_ENC			0x0003 /* Data frame encoding */
+#define  B43_TXH_PHY_ENC_CCK		0x0000 /* CCK */
+#define  B43_TXH_PHY_ENC_OFDM		0x0001 /* OFDM */
+#define  B43_TXH_PHY_ENC_HT		0x0002 /* HT */
+#define  B43_TXH_PHY_ENC_VHT		0x0003 /* VHT */
+#define B43_TXH_PHY_SHORTPRMBL		0x0010 /* Use short preamble */
+#define B43_TXH_PHY_ANT			0x03C0 /* Antenna selection */
+#define  B43_TXH_PHY_ANT0		0x0000 /* Use antenna 0 */
+#define  B43_TXH_PHY_ANT1		0x0040 /* Use antenna 1 */
+#define  B43_TXH_PHY_ANT01AUTO		0x00C0 /* Use antenna 0/1 auto */
+#define  B43_TXH_PHY_ANT2		0x0100 /* Use antenna 2 */
+#define  B43_TXH_PHY_ANT3		0x0200 /* Use antenna 3 */
+#define B43_TXH_PHY_TXPWR		0xFC00 /* TX power */
+#define B43_TXH_PHY_TXPWR_SHIFT		10
+
+/* PHY TX control word 1 */
+#define B43_TXH_PHY1_BW			0x0007 /* Bandwidth */
+#define  B43_TXH_PHY1_BW_10		0x0000 /* 10 MHz */
+#define  B43_TXH_PHY1_BW_10U		0x0001 /* 10 MHz upper */
+#define  B43_TXH_PHY1_BW_20		0x0002 /* 20 MHz */
+#define  B43_TXH_PHY1_BW_20U		0x0003 /* 20 MHz upper */
+#define  B43_TXH_PHY1_BW_40		0x0004 /* 40 MHz */
+#define  B43_TXH_PHY1_BW_40DUP		0x0005 /* 40 MHz duplicate */
+#define B43_TXH_PHY1_MODE		0x0038 /* Mode */
+#define  B43_TXH_PHY1_MODE_SISO		0x0000 /* SISO */
+#define  B43_TXH_PHY1_MODE_CDD		0x0008 /* CDD */
+#define  B43_TXH_PHY1_MODE_STBC		0x0010 /* STBC */
+#define  B43_TXH_PHY1_MODE_SDM		0x0018 /* SDM */
+#define B43_TXH_PHY1_CRATE		0x0700 /* Coding rate */
+#define  B43_TXH_PHY1_CRATE_1_2		0x0000 /* 1/2 */
+#define  B43_TXH_PHY1_CRATE_2_3		0x0100 /* 2/3 */
+#define  B43_TXH_PHY1_CRATE_3_4		0x0200 /* 3/4 */
+#define  B43_TXH_PHY1_CRATE_4_5		0x0300 /* 4/5 */
+#define  B43_TXH_PHY1_CRATE_5_6		0x0400 /* 5/6 */
+#define  B43_TXH_PHY1_CRATE_7_8		0x0600 /* 7/8 */
+#define B43_TXH_PHY1_MODUL		0x3800 /* Modulation scheme */
+#define  B43_TXH_PHY1_MODUL_BPSK	0x0000 /* BPSK */
+#define  B43_TXH_PHY1_MODUL_QPSK	0x0800 /* QPSK */
+#define  B43_TXH_PHY1_MODUL_QAM16	0x1000 /* QAM16 */
+#define  B43_TXH_PHY1_MODUL_QAM64	0x1800 /* QAM64 */
+#define  B43_TXH_PHY1_MODUL_QAM256	0x2000 /* QAM256 */
+
+
+static inline
+size_t b43_txhdr_size(struct b43_wldev *dev)
+{
+	switch (dev->fw.hdr_format) {
+	case B43_FW_HDR_598:
+		return 112 + sizeof(struct b43_plcp_hdr6);
+	case B43_FW_HDR_410:
+		return 104 + sizeof(struct b43_plcp_hdr6);
+	case B43_FW_HDR_351:
+		return 100 + sizeof(struct b43_plcp_hdr6);
+	}
+	return 0;
+}
+
+
+int b43_generate_txhdr(struct b43_wldev *dev,
+		       u8 * txhdr,
+		       struct sk_buff *skb_frag,
+		       struct ieee80211_tx_info *txctl, u16 cookie);
+
+/* Transmit Status */
+struct b43_txstatus {
+	u16 cookie;		/* The cookie from the txhdr */
+	u16 seq;		/* Sequence number */
+	u8 phy_stat;		/* PHY TX status */
+	u8 frame_count;		/* Frame transmit count */
+	u8 rts_count;		/* RTS transmit count */
+	u8 supp_reason;		/* Suppression reason */
+	/* flags */
+	u8 pm_indicated;	/* PM mode indicated to AP */
+	u8 intermediate;	/* Intermediate status notification (not final) */
+	u8 for_ampdu;		/* Status is for an AMPDU (afterburner) */
+	u8 acked;		/* Wireless ACK received */
+};
+
+/* txstatus supp_reason values */
+enum {
+	B43_TXST_SUPP_NONE,	/* Not suppressed */
+	B43_TXST_SUPP_PMQ,	/* Suppressed due to PMQ entry */
+	B43_TXST_SUPP_FLUSH,	/* Suppressed due to flush request */
+	B43_TXST_SUPP_PREV,	/* Previous fragment failed */
+	B43_TXST_SUPP_CHAN,	/* Channel mismatch */
+	B43_TXST_SUPP_LIFE,	/* Lifetime expired */
+	B43_TXST_SUPP_UNDER,	/* Buffer underflow */
+	B43_TXST_SUPP_ABNACK,	/* Afterburner NACK */
+};
+
+/* Receive header for v4 firmware. */
+struct b43_rxhdr_fw4 {
+	__le16 frame_len;	/* Frame length */
+	 PAD_BYTES(2);
+	__le16 phy_status0;	/* PHY RX Status 0 */
+	union {
+		/* RSSI for A/B/G-PHYs */
+		struct {
+			__u8 jssi;	/* PHY RX Status 1: JSSI */
+			__u8 sig_qual;	/* PHY RX Status 1: Signal Quality */
+		} __packed;
+
+		/* RSSI for N-PHYs */
+		struct {
+			__s8 power0;	/* PHY RX Status 1: Power 0 */
+			__s8 power1;	/* PHY RX Status 1: Power 1 */
+		} __packed;
+	} __packed;
+	union {
+		/* HT-PHY */
+		struct {
+			PAD_BYTES(1);
+			__s8 phy_ht_power0;
+		} __packed;
+
+		/* RSSI for N-PHYs */
+		struct {
+			__s8 power2;
+			PAD_BYTES(1);
+		} __packed;
+
+		__le16 phy_status2;	/* PHY RX Status 2 */
+	} __packed;
+	union {
+		/* HT-PHY */
+		struct {
+			__s8 phy_ht_power1;
+			__s8 phy_ht_power2;
+		} __packed;
+
+		__le16 phy_status3;	/* PHY RX Status 3 */
+	} __packed;
+	union {
+		/* Tested with 598.314, 644.1001 and 666.2 */
+		struct {
+			__le16 phy_status4;	/* PHY RX Status 4 */
+			__le16 phy_status5;	/* PHY RX Status 5 */
+			__le32 mac_status;	/* MAC RX status */
+			__le16 mac_time;
+			__le16 channel;
+		} format_598 __packed;
+
+		/* Tested with 351.126, 410.2160, 478.104 and 508.* */
+		struct {
+			__le32 mac_status;	/* MAC RX status */
+			__le16 mac_time;
+			__le16 channel;
+		} format_351 __packed;
+	} __packed;
+} __packed;
+
+/* PHY RX Status 0 */
+#define B43_RX_PHYST0_GAINCTL		0x4000 /* Gain Control */
+#define B43_RX_PHYST0_PLCPHCF		0x0200
+#define B43_RX_PHYST0_PLCPFV		0x0100
+#define B43_RX_PHYST0_SHORTPRMBL	0x0080 /* Received with Short Preamble */
+#define B43_RX_PHYST0_LCRS		0x0040
+#define B43_RX_PHYST0_ANT		0x0020 /* Antenna */
+#define B43_RX_PHYST0_UNSRATE		0x0010
+#define B43_RX_PHYST0_CLIP		0x000C
+#define B43_RX_PHYST0_CLIP_SHIFT	2
+#define B43_RX_PHYST0_FTYPE		0x0003 /* Frame type */
+#define  B43_RX_PHYST0_CCK		0x0000 /* Frame type: CCK */
+#define  B43_RX_PHYST0_OFDM		0x0001 /* Frame type: OFDM */
+#define  B43_RX_PHYST0_PRE_N		0x0002 /* Pre-standard N-PHY frame */
+#define  B43_RX_PHYST0_STD_N		0x0003 /* Standard N-PHY frame */
+
+/* PHY RX Status 2 */
+#define B43_RX_PHYST2_LNAG		0xC000 /* LNA Gain */
+#define B43_RX_PHYST2_LNAG_SHIFT	14
+#define B43_RX_PHYST2_PNAG		0x3C00 /* PNA Gain */
+#define B43_RX_PHYST2_PNAG_SHIFT	10
+#define B43_RX_PHYST2_FOFF		0x03FF /* F offset */
+
+/* PHY RX Status 3 */
+#define B43_RX_PHYST3_DIGG		0x1800 /* DIG Gain */
+#define B43_RX_PHYST3_DIGG_SHIFT	11
+#define B43_RX_PHYST3_TRSTATE		0x0400 /* TR state */
+
+/* MAC RX Status */
+#define B43_RX_MAC_RXST_VALID		0x01000000 /* PHY RXST valid */
+#define B43_RX_MAC_TKIP_MICERR		0x00100000 /* TKIP MIC error */
+#define B43_RX_MAC_TKIP_MICATT		0x00080000 /* TKIP MIC attempted */
+#define B43_RX_MAC_AGGTYPE		0x00060000 /* Aggregation type */
+#define B43_RX_MAC_AGGTYPE_SHIFT	17
+#define B43_RX_MAC_AMSDU		0x00010000 /* A-MSDU mask */
+#define B43_RX_MAC_BEACONSENT		0x00008000 /* Beacon sent flag */
+#define B43_RX_MAC_KEYIDX		0x000007E0 /* Key index */
+#define B43_RX_MAC_KEYIDX_SHIFT		5
+#define B43_RX_MAC_DECERR		0x00000010 /* Decrypt error */
+#define B43_RX_MAC_DEC			0x00000008 /* Decryption attempted */
+#define B43_RX_MAC_PADDING		0x00000004 /* Pad bytes present */
+#define B43_RX_MAC_RESP			0x00000002 /* Response frame transmitted */
+#define B43_RX_MAC_FCSERR		0x00000001 /* FCS error */
+
+/* RX channel */
+#define B43_RX_CHAN_40MHZ		0x1000 /* 40 Mhz channel width */
+#define B43_RX_CHAN_5GHZ		0x0800 /* 5 Ghz band */
+#define B43_RX_CHAN_ID			0x07F8 /* Channel ID */
+#define B43_RX_CHAN_ID_SHIFT		3
+#define B43_RX_CHAN_PHYTYPE		0x0007 /* PHY type */
+
+
+u8 b43_plcp_get_ratecode_cck(const u8 bitrate);
+u8 b43_plcp_get_ratecode_ofdm(const u8 bitrate);
+
+void b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp,
+			   const u16 octets, const u8 bitrate);
+
+void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr);
+
+void b43_handle_txstatus(struct b43_wldev *dev,
+			 const struct b43_txstatus *status);
+bool b43_fill_txstatus_report(struct b43_wldev *dev,
+			      struct ieee80211_tx_info *report,
+			      const struct b43_txstatus *status);
+
+void b43_tx_suspend(struct b43_wldev *dev);
+void b43_tx_resume(struct b43_wldev *dev);
+
+
+/* Helper functions for converting the key-table index from "firmware-format"
+ * to "raw-format" and back. The firmware API changed for this at some revision.
+ * We need to account for that here. */
+static inline int b43_new_kidx_api(struct b43_wldev *dev)
+{
+	/* FIXME: Not sure the change was at rev 351 */
+	return (dev->fw.rev >= 351);
+}
+static inline u8 b43_kidx_to_fw(struct b43_wldev *dev, u8 raw_kidx)
+{
+	u8 firmware_kidx;
+	if (b43_new_kidx_api(dev)) {
+		firmware_kidx = raw_kidx;
+	} else {
+		if (raw_kidx >= 4)	/* Is per STA key? */
+			firmware_kidx = raw_kidx - 4;
+		else
+			firmware_kidx = raw_kidx;	/* TX default key */
+	}
+	return firmware_kidx;
+}
+static inline u8 b43_kidx_to_raw(struct b43_wldev *dev, u8 firmware_kidx)
+{
+	u8 raw_kidx;
+	if (b43_new_kidx_api(dev))
+		raw_kidx = firmware_kidx;
+	else
+		raw_kidx = firmware_kidx + 4;	/* RX default keys or per STA keys */
+	return raw_kidx;
+}
+
+/* struct b43_private_tx_info - TX info private to b43.
+ * The structure is placed in (struct ieee80211_tx_info *)->rate_driver_data
+ *
+ * @bouncebuffer: DMA Bouncebuffer (if used)
+ */
+struct b43_private_tx_info {
+	void *bouncebuffer;
+};
+
+static inline struct b43_private_tx_info *
+b43_get_priv_tx_info(struct ieee80211_tx_info *info)
+{
+	BUILD_BUG_ON(sizeof(struct b43_private_tx_info) >
+		     sizeof(info->rate_driver_data));
+	return (struct b43_private_tx_info *)info->rate_driver_data;
+}
+
+#endif /* B43_XMIT_H_ */
diff --git a/drivers/net/wireless/broadcom/b43legacy/Kconfig b/drivers/net/wireless/broadcom/b43legacy/Kconfig
new file mode 100644
index 0000000..1ffa288
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/Kconfig
@@ -0,0 +1,104 @@
+config B43LEGACY
+	tristate "Broadcom 43xx-legacy wireless support (mac80211 stack)"
+	depends on SSB_POSSIBLE && MAC80211 && HAS_DMA
+	select SSB
+	select FW_LOADER
+	---help---
+	  b43legacy is a driver for 802.11b devices from Broadcom (BCM4301 and
+	  BCM4303) and early model 802.11g chips (BCM4306 Ver. 2) used in the
+	  Linksys WPC54G V1 PCMCIA devices.
+
+	  Newer 802.11g and 802.11a devices need b43.
+
+	  It is safe to include both b43 and b43legacy as the underlying glue
+	  layer will automatically load the correct version for your device.
+
+	  This driver uses V3 firmware, which must be installed separately using
+	  b43-fwcutter.
+
+	  This driver can be built as a module (recommended) that will be
+	  called "b43legacy". If unsure, say M.
+
+# Auto-select SSB PCI-HOST support, if possible
+config B43LEGACY_PCI_AUTOSELECT
+	bool
+	depends on B43LEGACY && SSB_PCIHOST_POSSIBLE
+	select SSB_PCIHOST
+	select SSB_B43_PCI_BRIDGE
+	default y
+
+# Auto-select SSB PCICORE driver, if possible
+config B43LEGACY_PCICORE_AUTOSELECT
+	bool
+	depends on B43LEGACY && SSB_DRIVER_PCICORE_POSSIBLE
+	select SSB_DRIVER_PCICORE
+	default y
+
+# LED support
+# This config option automatically enables b43legacy LEDS support,
+# if it's possible.
+config B43LEGACY_LEDS
+	bool
+	depends on B43LEGACY && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = B43LEGACY)
+	default y
+
+# This config option automatically enables b43 HW-RNG support,
+# if the HW-RNG core is enabled.
+config B43LEGACY_HWRNG
+	bool
+	depends on B43LEGACY && (HW_RANDOM = y || HW_RANDOM = B43LEGACY)
+	default y
+
+config B43LEGACY_DEBUG
+	bool "Broadcom 43xx-legacy debugging"
+	depends on B43LEGACY
+	default y
+	---help---
+	  Say Y, because this information will help you get the driver running.
+	  This option generates a minimum of log output.
+
+config B43LEGACY_DMA
+	bool
+	depends on B43LEGACY
+
+config B43LEGACY_PIO
+	bool
+	depends on B43LEGACY
+
+choice
+	prompt "Broadcom 43xx-legacy data transfer mode"
+	depends on B43LEGACY
+	default B43LEGACY_DMA_AND_PIO_MODE
+
+config B43LEGACY_DMA_AND_PIO_MODE
+	bool "DMA + PIO"
+	select B43LEGACY_DMA
+	select B43LEGACY_PIO
+	---help---
+	  Include both, Direct Memory Access (DMA) and Programmed I/O (PIO)
+	  data transfer modes. The mode actually used is selectable through
+	  the module parameter "pio". With pio=0 as a module parameter, the
+	  default DMA is used, otherwise PIO is used.
+
+	  If unsure, choose this option.
+
+config B43LEGACY_DMA_MODE
+	bool "DMA (Direct Memory Access) only"
+	select B43LEGACY_DMA
+	---help---
+	  Only include Direct Memory Access (DMA).
+	  This reduces the size of the driver module, by omitting the PIO code.
+
+config B43LEGACY_PIO_MODE
+	bool "PIO (Programmed I/O) only"
+	select B43LEGACY_PIO
+	---help---
+	  Only include Programmed I/O (PIO).
+	  This reduces the size of the driver module, by omitting the DMA code.
+	  Please note that PIO transfers are slow (compared to DMA).
+
+	  Also note that not all devices of the b43legacy series support PIO.
+
+	  You should use PIO only if DMA does not work for you.
+
+endchoice
diff --git a/drivers/net/wireless/broadcom/b43legacy/Makefile b/drivers/net/wireless/broadcom/b43legacy/Makefile
new file mode 100644
index 0000000..f8b392f
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/Makefile
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: GPL-2.0
+# b43legacy core
+b43legacy-y				+= main.o
+b43legacy-y				+= ilt.o
+b43legacy-y				+= phy.o
+b43legacy-y				+= radio.o
+b43legacy-y				+= sysfs.o
+b43legacy-y				+= xmit.o
+# b43 RFKILL button support
+b43legacy-y				+= rfkill.o
+# b43legacy LED support
+b43legacy-$(CONFIG_B43LEGACY_LEDS)	+= leds.o
+# b43legacy debugging
+b43legacy-$(CONFIG_B43LEGACY_DEBUG)	+= debugfs.o
+# b43legacy DMA and PIO
+b43legacy-$(CONFIG_B43LEGACY_DMA)	+= dma.o
+b43legacy-$(CONFIG_B43LEGACY_PIO)	+= pio.o
+
+obj-$(CONFIG_B43LEGACY)			+= b43legacy.o
+
diff --git a/drivers/net/wireless/broadcom/b43legacy/b43legacy.h b/drivers/net/wireless/broadcom/b43legacy/b43legacy.h
new file mode 100644
index 0000000..6b0cec4
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/b43legacy.h
@@ -0,0 +1,859 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43legacy_H_
+#define B43legacy_H_
+
+#include <linux/hw_random.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/stringify.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/atomic.h>
+#include <linux/io.h>
+
+#include <linux/ssb/ssb.h>
+#include <linux/ssb/ssb_driver_chipcommon.h>
+#include <linux/completion.h>
+
+#include <net/mac80211.h>
+
+#include "debugfs.h"
+#include "leds.h"
+#include "rfkill.h"
+#include "phy.h"
+
+
+#define B43legacy_IRQWAIT_MAX_RETRIES	20
+
+/* MMIO offsets */
+#define B43legacy_MMIO_DMA0_REASON	0x20
+#define B43legacy_MMIO_DMA0_IRQ_MASK	0x24
+#define B43legacy_MMIO_DMA1_REASON	0x28
+#define B43legacy_MMIO_DMA1_IRQ_MASK	0x2C
+#define B43legacy_MMIO_DMA2_REASON	0x30
+#define B43legacy_MMIO_DMA2_IRQ_MASK	0x34
+#define B43legacy_MMIO_DMA3_REASON	0x38
+#define B43legacy_MMIO_DMA3_IRQ_MASK	0x3C
+#define B43legacy_MMIO_DMA4_REASON	0x40
+#define B43legacy_MMIO_DMA4_IRQ_MASK	0x44
+#define B43legacy_MMIO_DMA5_REASON	0x48
+#define B43legacy_MMIO_DMA5_IRQ_MASK	0x4C
+#define B43legacy_MMIO_MACCTL		0x120	/* MAC control */
+#define B43legacy_MMIO_MACCMD		0x124	/* MAC command */
+#define B43legacy_MMIO_GEN_IRQ_REASON	0x128
+#define B43legacy_MMIO_GEN_IRQ_MASK	0x12C
+#define B43legacy_MMIO_RAM_CONTROL	0x130
+#define B43legacy_MMIO_RAM_DATA		0x134
+#define B43legacy_MMIO_PS_STATUS		0x140
+#define B43legacy_MMIO_RADIO_HWENABLED_HI	0x158
+#define B43legacy_MMIO_SHM_CONTROL	0x160
+#define B43legacy_MMIO_SHM_DATA		0x164
+#define B43legacy_MMIO_SHM_DATA_UNALIGNED	0x166
+#define B43legacy_MMIO_XMITSTAT_0		0x170
+#define B43legacy_MMIO_XMITSTAT_1		0x174
+#define B43legacy_MMIO_REV3PLUS_TSF_LOW	0x180 /* core rev >= 3 only */
+#define B43legacy_MMIO_REV3PLUS_TSF_HIGH	0x184 /* core rev >= 3 only */
+#define B43legacy_MMIO_TSF_CFP_REP	0x188
+#define B43legacy_MMIO_TSF_CFP_START	0x18C
+/* 32-bit DMA */
+#define B43legacy_MMIO_DMA32_BASE0	0x200
+#define B43legacy_MMIO_DMA32_BASE1	0x220
+#define B43legacy_MMIO_DMA32_BASE2	0x240
+#define B43legacy_MMIO_DMA32_BASE3	0x260
+#define B43legacy_MMIO_DMA32_BASE4	0x280
+#define B43legacy_MMIO_DMA32_BASE5	0x2A0
+/* 64-bit DMA */
+#define B43legacy_MMIO_DMA64_BASE0	0x200
+#define B43legacy_MMIO_DMA64_BASE1	0x240
+#define B43legacy_MMIO_DMA64_BASE2	0x280
+#define B43legacy_MMIO_DMA64_BASE3	0x2C0
+#define B43legacy_MMIO_DMA64_BASE4	0x300
+#define B43legacy_MMIO_DMA64_BASE5	0x340
+/* PIO */
+#define B43legacy_MMIO_PIO1_BASE		0x300
+#define B43legacy_MMIO_PIO2_BASE		0x310
+#define B43legacy_MMIO_PIO3_BASE		0x320
+#define B43legacy_MMIO_PIO4_BASE		0x330
+
+#define B43legacy_MMIO_PHY_VER		0x3E0
+#define B43legacy_MMIO_PHY_RADIO		0x3E2
+#define B43legacy_MMIO_PHY0		0x3E6
+#define B43legacy_MMIO_ANTENNA		0x3E8
+#define B43legacy_MMIO_CHANNEL		0x3F0
+#define B43legacy_MMIO_CHANNEL_EXT	0x3F4
+#define B43legacy_MMIO_RADIO_CONTROL	0x3F6
+#define B43legacy_MMIO_RADIO_DATA_HIGH	0x3F8
+#define B43legacy_MMIO_RADIO_DATA_LOW	0x3FA
+#define B43legacy_MMIO_PHY_CONTROL	0x3FC
+#define B43legacy_MMIO_PHY_DATA		0x3FE
+#define B43legacy_MMIO_MACFILTER_CONTROL	0x420
+#define B43legacy_MMIO_MACFILTER_DATA	0x422
+#define B43legacy_MMIO_RCMTA_COUNT	0x43C /* Receive Match Transmitter Addr */
+#define B43legacy_MMIO_RADIO_HWENABLED_LO	0x49A
+#define B43legacy_MMIO_GPIO_CONTROL	0x49C
+#define B43legacy_MMIO_GPIO_MASK		0x49E
+#define B43legacy_MMIO_TSF_CFP_PRETBTT	0x612
+#define B43legacy_MMIO_TSF_0		0x632 /* core rev < 3 only */
+#define B43legacy_MMIO_TSF_1		0x634 /* core rev < 3 only */
+#define B43legacy_MMIO_TSF_2		0x636 /* core rev < 3 only */
+#define B43legacy_MMIO_TSF_3		0x638 /* core rev < 3 only */
+#define B43legacy_MMIO_RNG		0x65A
+#define B43legacy_MMIO_POWERUP_DELAY	0x6A8
+
+/* SPROM boardflags_lo values */
+#define B43legacy_BFL_PACTRL		0x0002
+#define B43legacy_BFL_RSSI		0x0008
+#define B43legacy_BFL_EXTLNA		0x1000
+
+/* GPIO register offset, in both ChipCommon and PCI core. */
+#define B43legacy_GPIO_CONTROL		0x6c
+
+/* SHM Routing */
+#define	B43legacy_SHM_SHARED		0x0001
+#define	B43legacy_SHM_WIRELESS		0x0002
+#define	B43legacy_SHM_HW		0x0004
+#define	B43legacy_SHM_UCODE		0x0300
+
+/* SHM Routing modifiers */
+#define B43legacy_SHM_AUTOINC_R		0x0200 /* Read Auto-increment */
+#define B43legacy_SHM_AUTOINC_W		0x0100 /* Write Auto-increment */
+#define B43legacy_SHM_AUTOINC_RW	(B43legacy_SHM_AUTOINC_R | \
+					 B43legacy_SHM_AUTOINC_W)
+
+/* Misc SHM_SHARED offsets */
+#define B43legacy_SHM_SH_WLCOREREV	0x0016 /* 802.11 core revision */
+#define B43legacy_SHM_SH_HOSTFLO	0x005E /* Hostflags ucode opts (low) */
+#define B43legacy_SHM_SH_HOSTFHI	0x0060 /* Hostflags ucode opts (high) */
+/* SHM_SHARED crypto engine */
+#define B43legacy_SHM_SH_KEYIDXBLOCK	0x05D4 /* Key index/algorithm block */
+/* SHM_SHARED beacon/AP variables */
+#define B43legacy_SHM_SH_DTIMP		0x0012 /* DTIM period */
+#define B43legacy_SHM_SH_BTL0		0x0018 /* Beacon template length 0 */
+#define B43legacy_SHM_SH_BTL1		0x001A /* Beacon template length 1 */
+#define B43legacy_SHM_SH_BTSFOFF	0x001C /* Beacon TSF offset */
+#define B43legacy_SHM_SH_TIMPOS		0x001E /* TIM position in beacon */
+#define B43legacy_SHM_SH_BEACPHYCTL	0x0054 /* Beacon PHY TX control word */
+/* SHM_SHARED ACK/CTS control */
+#define B43legacy_SHM_SH_ACKCTSPHYCTL	0x0022 /* ACK/CTS PHY control word */
+/* SHM_SHARED probe response variables */
+#define B43legacy_SHM_SH_PRTLEN		0x004A /* Probe Response template length */
+#define B43legacy_SHM_SH_PRMAXTIME	0x0074 /* Probe Response max time */
+#define B43legacy_SHM_SH_PRPHYCTL	0x0188 /* Probe Resp PHY TX control */
+/* SHM_SHARED rate tables */
+#define B43legacy_SHM_SH_OFDMDIRECT	0x0480 /* Pointer to OFDM direct map */
+#define B43legacy_SHM_SH_OFDMBASIC	0x04A0 /* Pointer to OFDM basic rate map */
+#define B43legacy_SHM_SH_CCKDIRECT	0x04C0 /* Pointer to CCK direct map */
+#define B43legacy_SHM_SH_CCKBASIC	0x04E0 /* Pointer to CCK basic rate map */
+/* SHM_SHARED microcode soft registers */
+#define B43legacy_SHM_SH_UCODEREV	0x0000 /* Microcode revision */
+#define B43legacy_SHM_SH_UCODEPATCH	0x0002 /* Microcode patchlevel */
+#define B43legacy_SHM_SH_UCODEDATE	0x0004 /* Microcode date */
+#define B43legacy_SHM_SH_UCODETIME	0x0006 /* Microcode time */
+#define B43legacy_SHM_SH_SPUWKUP	0x0094 /* pre-wakeup for synth PU in us */
+#define B43legacy_SHM_SH_PRETBTT	0x0096 /* pre-TBTT in us */
+
+#define B43legacy_UCODEFLAGS_OFFSET     0x005E
+
+/* Hardware Radio Enable masks */
+#define B43legacy_MMIO_RADIO_HWENABLED_HI_MASK (1 << 16)
+#define B43legacy_MMIO_RADIO_HWENABLED_LO_MASK (1 << 4)
+
+/* HostFlags. See b43legacy_hf_read/write() */
+#define B43legacy_HF_SYMW		0x00000002 /* G-PHY SYM workaround */
+#define B43legacy_HF_GDCW		0x00000020 /* G-PHY DV cancel filter */
+#define B43legacy_HF_OFDMPABOOST	0x00000040 /* Enable PA boost OFDM */
+#define B43legacy_HF_EDCF		0x00000100 /* on if WME/MAC suspended */
+
+/* MacFilter offsets. */
+#define B43legacy_MACFILTER_SELF	0x0000
+#define B43legacy_MACFILTER_BSSID	0x0003
+#define B43legacy_MACFILTER_MAC		0x0010
+
+/* PHYVersioning */
+#define B43legacy_PHYTYPE_B		0x01
+#define B43legacy_PHYTYPE_G		0x02
+
+/* PHYRegisters */
+#define B43legacy_PHY_G_LO_CONTROL	0x0810
+#define B43legacy_PHY_ILT_G_CTRL	0x0472
+#define B43legacy_PHY_ILT_G_DATA1	0x0473
+#define B43legacy_PHY_ILT_G_DATA2	0x0474
+#define B43legacy_PHY_G_PCTL		0x0029
+#define B43legacy_PHY_RADIO_BITFIELD	0x0401
+#define B43legacy_PHY_G_CRS		0x0429
+#define B43legacy_PHY_NRSSILT_CTRL	0x0803
+#define B43legacy_PHY_NRSSILT_DATA	0x0804
+
+/* RadioRegisters */
+#define B43legacy_RADIOCTL_ID		0x01
+
+/* MAC Control bitfield */
+#define B43legacy_MACCTL_ENABLED	0x00000001 /* MAC Enabled */
+#define B43legacy_MACCTL_PSM_RUN	0x00000002 /* Run Microcode */
+#define B43legacy_MACCTL_PSM_JMP0	0x00000004 /* Microcode jump to 0 */
+#define B43legacy_MACCTL_SHM_ENABLED	0x00000100 /* SHM Enabled */
+#define B43legacy_MACCTL_IHR_ENABLED	0x00000400 /* IHR Region Enabled */
+#define B43legacy_MACCTL_BE		0x00010000 /* Big Endian mode */
+#define B43legacy_MACCTL_INFRA		0x00020000 /* Infrastructure mode */
+#define B43legacy_MACCTL_AP		0x00040000 /* AccessPoint mode */
+#define B43legacy_MACCTL_RADIOLOCK	0x00080000 /* Radio lock */
+#define B43legacy_MACCTL_BEACPROMISC	0x00100000 /* Beacon Promiscuous */
+#define B43legacy_MACCTL_KEEP_BADPLCP	0x00200000 /* Keep bad PLCP frames */
+#define B43legacy_MACCTL_KEEP_CTL	0x00400000 /* Keep control frames */
+#define B43legacy_MACCTL_KEEP_BAD	0x00800000 /* Keep bad frames (FCS) */
+#define B43legacy_MACCTL_PROMISC	0x01000000 /* Promiscuous mode */
+#define B43legacy_MACCTL_HWPS		0x02000000 /* Hardware Power Saving */
+#define B43legacy_MACCTL_AWAKE		0x04000000 /* Device is awake */
+#define B43legacy_MACCTL_TBTTHOLD	0x10000000 /* TBTT Hold */
+#define B43legacy_MACCTL_GMODE		0x80000000 /* G Mode */
+
+/* MAC Command bitfield */
+#define B43legacy_MACCMD_BEACON0_VALID	0x00000001 /* Beacon 0 in template RAM is busy/valid */
+#define B43legacy_MACCMD_BEACON1_VALID	0x00000002 /* Beacon 1 in template RAM is busy/valid */
+#define B43legacy_MACCMD_DFQ_VALID	0x00000004 /* Directed frame queue valid (IBSS PS mode, ATIM) */
+#define B43legacy_MACCMD_CCA		0x00000008 /* Clear channel assessment */
+#define B43legacy_MACCMD_BGNOISE	0x00000010 /* Background noise */
+
+/* 802.11 core specific TM State Low flags */
+#define B43legacy_TMSLOW_GMODE		0x20000000 /* G Mode Enable */
+#define B43legacy_TMSLOW_PLLREFSEL	0x00200000 /* PLL Freq Ref Select */
+#define B43legacy_TMSLOW_MACPHYCLKEN	0x00100000 /* MAC PHY Clock Ctrl Enbl */
+#define B43legacy_TMSLOW_PHYRESET	0x00080000 /* PHY Reset */
+#define B43legacy_TMSLOW_PHYCLKEN	0x00040000 /* PHY Clock Enable */
+
+/* 802.11 core specific TM State High flags */
+#define B43legacy_TMSHIGH_FCLOCK	0x00040000 /* Fast Clock Available */
+#define B43legacy_TMSHIGH_GPHY		0x00010000 /* G-PHY avail (rev >= 5) */
+
+#define B43legacy_UCODEFLAG_AUTODIV       0x0001
+
+/* Generic-Interrupt reasons. */
+#define B43legacy_IRQ_MAC_SUSPENDED	0x00000001
+#define B43legacy_IRQ_BEACON		0x00000002
+#define B43legacy_IRQ_TBTT_INDI		0x00000004 /* Target Beacon Transmit Time */
+#define B43legacy_IRQ_BEACON_TX_OK	0x00000008
+#define B43legacy_IRQ_BEACON_CANCEL	0x00000010
+#define B43legacy_IRQ_ATIM_END		0x00000020
+#define B43legacy_IRQ_PMQ		0x00000040
+#define B43legacy_IRQ_PIO_WORKAROUND	0x00000100
+#define B43legacy_IRQ_MAC_TXERR		0x00000200
+#define B43legacy_IRQ_PHY_TXERR		0x00000800
+#define B43legacy_IRQ_PMEVENT		0x00001000
+#define B43legacy_IRQ_TIMER0		0x00002000
+#define B43legacy_IRQ_TIMER1		0x00004000
+#define B43legacy_IRQ_DMA		0x00008000
+#define B43legacy_IRQ_TXFIFO_FLUSH_OK	0x00010000
+#define B43legacy_IRQ_CCA_MEASURE_OK	0x00020000
+#define B43legacy_IRQ_NOISESAMPLE_OK	0x00040000
+#define B43legacy_IRQ_UCODE_DEBUG	0x08000000
+#define B43legacy_IRQ_RFKILL		0x10000000
+#define B43legacy_IRQ_TX_OK		0x20000000
+#define B43legacy_IRQ_PHY_G_CHANGED	0x40000000
+#define B43legacy_IRQ_TIMEOUT		0x80000000
+
+#define B43legacy_IRQ_ALL		0xFFFFFFFF
+#define B43legacy_IRQ_MASKTEMPLATE	(B43legacy_IRQ_MAC_SUSPENDED |	\
+					 B43legacy_IRQ_TBTT_INDI |	\
+					 B43legacy_IRQ_ATIM_END |	\
+					 B43legacy_IRQ_PMQ |		\
+					 B43legacy_IRQ_MAC_TXERR |	\
+					 B43legacy_IRQ_PHY_TXERR |	\
+					 B43legacy_IRQ_DMA |		\
+					 B43legacy_IRQ_TXFIFO_FLUSH_OK | \
+					 B43legacy_IRQ_NOISESAMPLE_OK | \
+					 B43legacy_IRQ_UCODE_DEBUG |	\
+					 B43legacy_IRQ_RFKILL |		\
+					 B43legacy_IRQ_TX_OK)
+
+/* Device specific rate values.
+ * The actual values defined here are (rate_in_mbps * 2).
+ * Some code depends on this. Don't change it. */
+#define B43legacy_CCK_RATE_1MB		2
+#define B43legacy_CCK_RATE_2MB		4
+#define B43legacy_CCK_RATE_5MB		11
+#define B43legacy_CCK_RATE_11MB		22
+#define B43legacy_OFDM_RATE_6MB		12
+#define B43legacy_OFDM_RATE_9MB		18
+#define B43legacy_OFDM_RATE_12MB	24
+#define B43legacy_OFDM_RATE_18MB	36
+#define B43legacy_OFDM_RATE_24MB	48
+#define B43legacy_OFDM_RATE_36MB	72
+#define B43legacy_OFDM_RATE_48MB	96
+#define B43legacy_OFDM_RATE_54MB	108
+/* Convert a b43legacy rate value to a rate in 100kbps */
+#define B43legacy_RATE_TO_100KBPS(rate)	(((rate) * 10) / 2)
+
+
+#define B43legacy_DEFAULT_SHORT_RETRY_LIMIT	7
+#define B43legacy_DEFAULT_LONG_RETRY_LIMIT	4
+
+#define B43legacy_PHY_TX_BADNESS_LIMIT		1000
+
+/* Max size of a security key */
+#define B43legacy_SEC_KEYSIZE		16
+/* Security algorithms. */
+enum {
+	B43legacy_SEC_ALGO_NONE = 0, /* unencrypted, as of TX header. */
+	B43legacy_SEC_ALGO_WEP40,
+	B43legacy_SEC_ALGO_TKIP,
+	B43legacy_SEC_ALGO_AES,
+	B43legacy_SEC_ALGO_WEP104,
+	B43legacy_SEC_ALGO_AES_LEGACY,
+};
+
+/* Core Information Registers */
+#define B43legacy_CIR_BASE                0xf00
+#define B43legacy_CIR_SBTPSFLAG           (B43legacy_CIR_BASE + 0x18)
+#define B43legacy_CIR_SBIMSTATE           (B43legacy_CIR_BASE + 0x90)
+#define B43legacy_CIR_SBINTVEC            (B43legacy_CIR_BASE + 0x94)
+#define B43legacy_CIR_SBTMSTATELOW        (B43legacy_CIR_BASE + 0x98)
+#define B43legacy_CIR_SBTMSTATEHIGH       (B43legacy_CIR_BASE + 0x9c)
+#define B43legacy_CIR_SBIMCONFIGLOW       (B43legacy_CIR_BASE + 0xa8)
+#define B43legacy_CIR_SB_ID_HI            (B43legacy_CIR_BASE + 0xfc)
+
+/* sbtmstatehigh state flags */
+#define B43legacy_SBTMSTATEHIGH_SERROR		0x00000001
+#define B43legacy_SBTMSTATEHIGH_BUSY		0x00000004
+#define B43legacy_SBTMSTATEHIGH_TIMEOUT		0x00000020
+#define B43legacy_SBTMSTATEHIGH_G_PHY_AVAIL	0x00010000
+#define B43legacy_SBTMSTATEHIGH_COREFLAGS	0x1FFF0000
+#define B43legacy_SBTMSTATEHIGH_DMA64BIT	0x10000000
+#define B43legacy_SBTMSTATEHIGH_GATEDCLK	0x20000000
+#define B43legacy_SBTMSTATEHIGH_BISTFAILED	0x40000000
+#define B43legacy_SBTMSTATEHIGH_BISTCOMPLETE	0x80000000
+
+/* sbimstate flags */
+#define B43legacy_SBIMSTATE_IB_ERROR		0x20000
+#define B43legacy_SBIMSTATE_TIMEOUT		0x40000
+
+#define PFX		KBUILD_MODNAME ": "
+#ifdef assert
+# undef assert
+#endif
+#ifdef CONFIG_B43LEGACY_DEBUG
+# define B43legacy_WARN_ON(x)	WARN_ON(x)
+# define B43legacy_BUG_ON(expr)						\
+	do {								\
+		if (unlikely((expr))) {					\
+			printk(KERN_INFO PFX "Test (%s) failed\n",	\
+					      #expr);			\
+			BUG_ON(expr);					\
+		}							\
+	} while (0)
+# define B43legacy_DEBUG	1
+#else
+/* This will evaluate the argument even if debugging is disabled. */
+static inline bool __b43legacy_warn_on_dummy(bool x) { return x; }
+# define B43legacy_WARN_ON(x)	__b43legacy_warn_on_dummy(unlikely(!!(x)))
+# define B43legacy_BUG_ON(x)	do { /* nothing */ } while (0)
+# define B43legacy_DEBUG	0
+#endif
+
+
+struct net_device;
+struct pci_dev;
+struct b43legacy_dmaring;
+struct b43legacy_pioqueue;
+
+/* The firmware file header */
+#define B43legacy_FW_TYPE_UCODE	'u'
+#define B43legacy_FW_TYPE_PCM	'p'
+#define B43legacy_FW_TYPE_IV	'i'
+struct b43legacy_fw_header {
+	/* File type */
+	u8 type;
+	/* File format version */
+	u8 ver;
+	u8 __padding[2];
+	/* Size of the data. For ucode and PCM this is in bytes.
+	 * For IV this is number-of-ivs. */
+	__be32 size;
+} __packed;
+
+/* Initial Value file format */
+#define B43legacy_IV_OFFSET_MASK	0x7FFF
+#define B43legacy_IV_32BIT		0x8000
+struct b43legacy_iv {
+	__be16 offset_size;
+	union {
+		__be16 d16;
+		__be32 d32;
+	} data __packed;
+} __packed;
+
+#define B43legacy_PHYMODE(phytype)	(1 << (phytype))
+#define B43legacy_PHYMODE_B		B43legacy_PHYMODE	\
+					((B43legacy_PHYTYPE_B))
+#define B43legacy_PHYMODE_G		B43legacy_PHYMODE	\
+					((B43legacy_PHYTYPE_G))
+
+/* Value pair to measure the LocalOscillator. */
+struct b43legacy_lopair {
+	s8 low;
+	s8 high;
+	u8 used:1;
+};
+#define B43legacy_LO_COUNT	(14*4)
+
+struct b43legacy_phy {
+	/* Possible PHYMODEs on this PHY */
+	u8 possible_phymodes;
+	/* GMODE bit enabled in MACCTL? */
+	bool gmode;
+
+	/* Analog Type */
+	u8 analog;
+	/* B43legacy_PHYTYPE_ */
+	u8 type;
+	/* PHY revision number. */
+	u8 rev;
+
+	u16 antenna_diversity;
+	u16 savedpctlreg;
+	/* Radio versioning */
+	u16 radio_manuf;	/* Radio manufacturer */
+	u16 radio_ver;		/* Radio version */
+	u8 calibrated:1;
+	u8 radio_rev;		/* Radio revision */
+
+	bool dyn_tssi_tbl;	/* tssi2dbm is kmalloc()ed. */
+
+	/* ACI (adjacent channel interference) flags. */
+	bool aci_enable;
+	bool aci_wlan_automatic;
+	bool aci_hw_rssi;
+
+	/* Radio switched on/off */
+	bool radio_on;
+	struct {
+		/* Values saved when turning the radio off.
+		 * They are needed when turning it on again. */
+		bool valid;
+		u16 rfover;
+		u16 rfoverval;
+	} radio_off_context;
+
+	u16 minlowsig[2];
+	u16 minlowsigpos[2];
+
+	/* LO Measurement Data.
+	 * Use b43legacy_get_lopair() to get a value.
+	 */
+	struct b43legacy_lopair *_lo_pairs;
+	/* TSSI to dBm table in use */
+	const s8 *tssi2dbm;
+	/* idle TSSI value */
+	s8 idle_tssi;
+	/* Target idle TSSI */
+	int tgt_idle_tssi;
+	/* Current idle TSSI */
+	int cur_idle_tssi;
+
+	/* LocalOscillator control values. */
+	struct b43legacy_txpower_lo_control *lo_control;
+	/* Values from b43legacy_calc_loopback_gain() */
+	s16 max_lb_gain;	/* Maximum Loopback gain in hdB */
+	s16 trsw_rx_gain;	/* TRSW RX gain in hdB */
+	s16 lna_lod_gain;	/* LNA lod */
+	s16 lna_gain;		/* LNA */
+	s16 pga_gain;		/* PGA */
+
+	/* Desired TX power level (in dBm). This is set by the user and
+	 * adjusted in b43legacy_phy_xmitpower(). */
+	u8 power_level;
+
+	/* Values from b43legacy_calc_loopback_gain() */
+	u16 loopback_gain[2];
+
+	/* TX Power control values. */
+	/* B/G PHY */
+	struct {
+		/* Current Radio Attenuation for TXpower recalculation. */
+		u16 rfatt;
+		/* Current Baseband Attenuation for TXpower recalculation. */
+		u16 bbatt;
+		/* Current TXpower control value for TXpower recalculation. */
+		u16 txctl1;
+		u16 txctl2;
+	};
+	/* A PHY */
+	struct {
+		u16 txpwr_offset;
+	};
+
+	/* Current Interference Mitigation mode */
+	int interfmode;
+	/* Stack of saved values from the Interference Mitigation code.
+	 * Each value in the stack is laid out as follows:
+	 * bit 0-11:  offset
+	 * bit 12-15: register ID
+	 * bit 16-32: value
+	 * register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT
+	 */
+#define B43legacy_INTERFSTACK_SIZE	26
+	u32 interfstack[B43legacy_INTERFSTACK_SIZE];
+
+	/* Saved values from the NRSSI Slope calculation */
+	s16 nrssi[2];
+	s32 nrssislope;
+	/* In memory nrssi lookup table. */
+	s8 nrssi_lt[64];
+
+	/* current channel */
+	u8 channel;
+
+	u16 lofcal;
+
+	u16 initval;
+
+	/* PHY TX errors counter. */
+	atomic_t txerr_cnt;
+
+#if B43legacy_DEBUG
+	/* Manual TX-power control enabled? */
+	bool manual_txpower_control;
+	/* PHY registers locked by b43legacy_phy_lock()? */
+	bool phy_locked;
+#endif /* B43legacy_DEBUG */
+};
+
+/* Data structures for DMA transmission, per 80211 core. */
+struct b43legacy_dma {
+	struct b43legacy_dmaring *tx_ring0;
+	struct b43legacy_dmaring *tx_ring1;
+	struct b43legacy_dmaring *tx_ring2;
+	struct b43legacy_dmaring *tx_ring3;
+	struct b43legacy_dmaring *tx_ring4;
+	struct b43legacy_dmaring *tx_ring5;
+
+	struct b43legacy_dmaring *rx_ring0;
+	struct b43legacy_dmaring *rx_ring3; /* only on core.rev < 5 */
+
+	u32 translation; /* Routing bits */
+};
+
+/* Data structures for PIO transmission, per 80211 core. */
+struct b43legacy_pio {
+	struct b43legacy_pioqueue *queue0;
+	struct b43legacy_pioqueue *queue1;
+	struct b43legacy_pioqueue *queue2;
+	struct b43legacy_pioqueue *queue3;
+};
+
+/* Context information for a noise calculation (Link Quality). */
+struct b43legacy_noise_calculation {
+	u8 channel_at_start;
+	bool calculation_running;
+	u8 nr_samples;
+	s8 samples[8][4];
+};
+
+struct b43legacy_stats {
+	u8 link_noise;
+	/* Store the last TX/RX times here for updating the leds. */
+	unsigned long last_tx;
+	unsigned long last_rx;
+};
+
+struct b43legacy_key {
+	void *keyconf;
+	bool enabled;
+	u8 algorithm;
+};
+
+#define B43legacy_QOS_QUEUE_NUM	4
+
+struct b43legacy_wldev;
+
+/* QOS parameters for a queue. */
+struct b43legacy_qos_params {
+	/* The QOS parameters */
+	struct ieee80211_tx_queue_params p;
+};
+
+/* Data structure for the WLAN parts (802.11 cores) of the b43legacy chip. */
+struct b43legacy_wl {
+	/* Pointer to the active wireless device on this chip */
+	struct b43legacy_wldev *current_dev;
+	/* Pointer to the ieee80211 hardware data structure */
+	struct ieee80211_hw *hw;
+
+	spinlock_t irq_lock;		/* locks IRQ */
+	struct mutex mutex;		/* locks wireless core state */
+	spinlock_t leds_lock;		/* lock for leds */
+
+	/* firmware loading work */
+	struct work_struct firmware_load;
+
+	/* We can only have one operating interface (802.11 core)
+	 * at a time. General information about this interface follows.
+	 */
+
+	struct ieee80211_vif *vif;
+	/* MAC address (can be NULL). */
+	u8 mac_addr[ETH_ALEN];
+	/* Current BSSID (can be NULL). */
+	u8 bssid[ETH_ALEN];
+	/* Interface type. (IEEE80211_IF_TYPE_XXX) */
+	int if_type;
+	/* Is the card operating in AP, STA or IBSS mode? */
+	bool operating;
+	/* filter flags */
+	unsigned int filter_flags;
+	/* Stats about the wireless interface */
+	struct ieee80211_low_level_stats ieee_stats;
+
+#ifdef CONFIG_B43LEGACY_HWRNG
+	struct hwrng rng;
+	u8 rng_initialized;
+	char rng_name[30 + 1];
+#endif
+
+	/* List of all wireless devices on this chip */
+	struct list_head devlist;
+	u8 nr_devs;
+
+	bool radiotap_enabled;
+	bool radio_enabled;
+
+	/* The beacon we are currently using (AP or IBSS mode).
+	 * This beacon stuff is protected by the irq_lock. */
+	struct sk_buff *current_beacon;
+	bool beacon0_uploaded;
+	bool beacon1_uploaded;
+	bool beacon_templates_virgin; /* Never wrote the templates? */
+	struct work_struct beacon_update_trigger;
+	/* The current QOS parameters for the 4 queues. */
+	struct b43legacy_qos_params qos_params[B43legacy_QOS_QUEUE_NUM];
+
+	/* Packet transmit work */
+	struct work_struct tx_work;
+
+	/* Queue of packets to be transmitted. */
+	struct sk_buff_head tx_queue[B43legacy_QOS_QUEUE_NUM];
+
+	/* Flag that implement the queues stopping. */
+	bool tx_queue_stopped[B43legacy_QOS_QUEUE_NUM];
+
+};
+
+/* Pointers to the firmware data and meta information about it. */
+struct b43legacy_firmware {
+	/* Microcode */
+	const struct firmware *ucode;
+	/* PCM code */
+	const struct firmware *pcm;
+	/* Initial MMIO values for the firmware */
+	const struct firmware *initvals;
+	/* Initial MMIO values for the firmware, band-specific */
+	const struct firmware *initvals_band;
+	/* Firmware revision */
+	u16 rev;
+	/* Firmware patchlevel */
+	u16 patch;
+};
+
+/* Device (802.11 core) initialization status. */
+enum {
+	B43legacy_STAT_UNINIT		= 0, /* Uninitialized. */
+	B43legacy_STAT_INITIALIZED	= 1, /* Initialized, not yet started. */
+	B43legacy_STAT_STARTED	= 2, /* Up and running. */
+};
+#define b43legacy_status(wldev)	atomic_read(&(wldev)->__init_status)
+#define b43legacy_set_status(wldev, stat)	do {		\
+		atomic_set(&(wldev)->__init_status, (stat));	\
+		smp_wmb();					\
+					} while (0)
+
+/* *** ---   HOW LOCKING WORKS IN B43legacy   --- ***
+ *
+ * You should always acquire both, wl->mutex and wl->irq_lock unless:
+ * - You don't need to acquire wl->irq_lock, if the interface is stopped.
+ * - You don't need to acquire wl->mutex in the IRQ handler, IRQ tasklet
+ *   and packet TX path (and _ONLY_ there.)
+ */
+
+/* Data structure for one wireless device (802.11 core) */
+struct b43legacy_wldev {
+	struct ssb_device *dev;
+	struct b43legacy_wl *wl;
+
+	/* The device initialization status.
+	 * Use b43legacy_status() to query. */
+	atomic_t __init_status;
+	/* Saved init status for handling suspend. */
+	int suspend_init_status;
+
+	bool __using_pio;	/* Using pio rather than dma. */
+	bool bad_frames_preempt;/* Use "Bad Frames Preemption". */
+	bool dfq_valid;		/* Directed frame queue valid (IBSS PS mode, ATIM). */
+	bool short_preamble;	/* TRUE if using short preamble. */
+	bool radio_hw_enable;	/* State of radio hardware enable bit. */
+
+	/* PHY/Radio device. */
+	struct b43legacy_phy phy;
+	union {
+		/* DMA engines. */
+		struct b43legacy_dma dma;
+		/* PIO engines. */
+		struct b43legacy_pio pio;
+	};
+
+	/* Various statistics about the physical device. */
+	struct b43legacy_stats stats;
+
+	/* The device LEDs. */
+	struct b43legacy_led led_tx;
+	struct b43legacy_led led_rx;
+	struct b43legacy_led led_assoc;
+	struct b43legacy_led led_radio;
+
+	/* Reason code of the last interrupt. */
+	u32 irq_reason;
+	u32 dma_reason[6];
+	/* The currently active generic-interrupt mask. */
+	u32 irq_mask;
+	/* Link Quality calculation context. */
+	struct b43legacy_noise_calculation noisecalc;
+	/* if > 0 MAC is suspended. if == 0 MAC is enabled. */
+	int mac_suspended;
+
+	/* Interrupt Service Routine tasklet (bottom-half) */
+	struct tasklet_struct isr_tasklet;
+
+	/* Periodic tasks */
+	struct delayed_work periodic_work;
+	unsigned int periodic_state;
+
+	struct work_struct restart_work;
+
+	/* encryption/decryption */
+	u16 ktp; /* Key table pointer */
+	u8 max_nr_keys;
+	struct b43legacy_key key[58];
+
+	/* Firmware data */
+	struct b43legacy_firmware fw;
+	const struct firmware *fwp;	/* needed to pass fw pointer */
+
+	/* completion struct for firmware loading */
+	struct completion fw_load_complete;
+
+	/* Devicelist in struct b43legacy_wl (all 802.11 cores) */
+	struct list_head list;
+
+	/* Debugging stuff follows. */
+#ifdef CONFIG_B43LEGACY_DEBUG
+	struct b43legacy_dfsentry *dfsentry;
+#endif
+};
+
+
+static inline
+struct b43legacy_wl *hw_to_b43legacy_wl(struct ieee80211_hw *hw)
+{
+	return hw->priv;
+}
+
+/* Helper function, which returns a boolean.
+ * TRUE, if PIO is used; FALSE, if DMA is used.
+ */
+#if defined(CONFIG_B43LEGACY_DMA) && defined(CONFIG_B43LEGACY_PIO)
+static inline
+int b43legacy_using_pio(struct b43legacy_wldev *dev)
+{
+	return dev->__using_pio;
+}
+#elif defined(CONFIG_B43LEGACY_DMA)
+static inline
+int b43legacy_using_pio(struct b43legacy_wldev *dev)
+{
+	return 0;
+}
+#elif defined(CONFIG_B43LEGACY_PIO)
+static inline
+int b43legacy_using_pio(struct b43legacy_wldev *dev)
+{
+	return 1;
+}
+#else
+# error "Using neither DMA nor PIO? Confused..."
+#endif
+
+
+static inline
+struct b43legacy_wldev *dev_to_b43legacy_wldev(struct device *dev)
+{
+	struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
+	return ssb_get_drvdata(ssb_dev);
+}
+
+/* Is the device operating in a specified mode (IEEE80211_IF_TYPE_XXX). */
+static inline
+int b43legacy_is_mode(struct b43legacy_wl *wl, int type)
+{
+	return (wl->operating &&
+		wl->if_type == type);
+}
+
+static inline
+bool is_bcm_board_vendor(struct b43legacy_wldev *dev)
+{
+	return  (dev->dev->bus->boardinfo.vendor == PCI_VENDOR_ID_BROADCOM);
+}
+
+static inline
+u16 b43legacy_read16(struct b43legacy_wldev *dev, u16 offset)
+{
+	return ssb_read16(dev->dev, offset);
+}
+
+static inline
+void b43legacy_write16(struct b43legacy_wldev *dev, u16 offset, u16 value)
+{
+	ssb_write16(dev->dev, offset, value);
+}
+
+static inline
+u32 b43legacy_read32(struct b43legacy_wldev *dev, u16 offset)
+{
+	return ssb_read32(dev->dev, offset);
+}
+
+static inline
+void b43legacy_write32(struct b43legacy_wldev *dev, u16 offset, u32 value)
+{
+	ssb_write32(dev->dev, offset, value);
+}
+
+static inline
+struct b43legacy_lopair *b43legacy_get_lopair(struct b43legacy_phy *phy,
+					      u16 radio_attenuation,
+					      u16 baseband_attenuation)
+{
+	return phy->_lo_pairs + (radio_attenuation
+			+ 14 * (baseband_attenuation / 2));
+}
+
+
+
+/* Message printing */
+__printf(2, 3)
+void b43legacyinfo(struct b43legacy_wl *wl, const char *fmt, ...);
+__printf(2, 3)
+void b43legacyerr(struct b43legacy_wl *wl, const char *fmt, ...);
+__printf(2, 3)
+void b43legacywarn(struct b43legacy_wl *wl, const char *fmt, ...);
+#if B43legacy_DEBUG
+__printf(2, 3)
+void b43legacydbg(struct b43legacy_wl *wl, const char *fmt, ...);
+#else /* DEBUG */
+# define b43legacydbg(wl, fmt...) do { /* nothing */ } while (0)
+#endif /* DEBUG */
+
+/* Macros for printing a value in Q5.2 format */
+#define Q52_FMT		"%u.%u"
+#define Q52_ARG(q52)	((q52) / 4), (((q52) & 3) * 100 / 4)
+
+#endif /* B43legacy_H_ */
diff --git a/drivers/net/wireless/broadcom/b43legacy/debugfs.c b/drivers/net/wireless/broadcom/b43legacy/debugfs.c
new file mode 100644
index 0000000..82ef56e
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/debugfs.c
@@ -0,0 +1,502 @@
+/*
+
+  Broadcom B43legacy wireless driver
+
+  debugfs driver debugging code
+
+  Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
+
+  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/fs.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/mutex.h>
+
+#include "b43legacy.h"
+#include "main.h"
+#include "debugfs.h"
+#include "dma.h"
+#include "pio.h"
+#include "xmit.h"
+
+
+/* The root directory. */
+static struct dentry *rootdir;
+
+struct b43legacy_debugfs_fops {
+	ssize_t (*read)(struct b43legacy_wldev *dev, char *buf, size_t bufsize);
+	int (*write)(struct b43legacy_wldev *dev, const char *buf, size_t count);
+	struct file_operations fops;
+	/* Offset of struct b43legacy_dfs_file in struct b43legacy_dfsentry */
+	size_t file_struct_offset;
+	/* Take wl->irq_lock before calling read/write? */
+	bool take_irqlock;
+};
+
+static inline
+struct b43legacy_dfs_file * fops_to_dfs_file(struct b43legacy_wldev *dev,
+				       const struct b43legacy_debugfs_fops *dfops)
+{
+	void *p;
+
+	p = dev->dfsentry;
+	p += dfops->file_struct_offset;
+
+	return p;
+}
+
+
+#define fappend(fmt, x...)	\
+	do {							\
+		if (bufsize - count)				\
+			count += snprintf(buf + count,		\
+					  bufsize - count,	\
+					  fmt , ##x);		\
+		else						\
+			printk(KERN_ERR "b43legacy: fappend overflow\n"); \
+	} while (0)
+
+
+/* wl->irq_lock is locked */
+static ssize_t tsf_read_file(struct b43legacy_wldev *dev, char *buf, size_t bufsize)
+{
+	ssize_t count = 0;
+	u64 tsf;
+
+	b43legacy_tsf_read(dev, &tsf);
+	fappend("0x%08x%08x\n",
+		(unsigned int)((tsf & 0xFFFFFFFF00000000ULL) >> 32),
+		(unsigned int)(tsf & 0xFFFFFFFFULL));
+
+	return count;
+}
+
+/* wl->irq_lock is locked */
+static int tsf_write_file(struct b43legacy_wldev *dev, const char *buf, size_t count)
+{
+	u64 tsf;
+
+	if (sscanf(buf, "%llu", (unsigned long long *)(&tsf)) != 1)
+		return -EINVAL;
+	b43legacy_tsf_write(dev, tsf);
+
+	return 0;
+}
+
+/* wl->irq_lock is locked */
+static ssize_t ucode_regs_read_file(struct b43legacy_wldev *dev, char *buf, size_t bufsize)
+{
+	ssize_t count = 0;
+	int i;
+
+	for (i = 0; i < 64; i++) {
+		fappend("r%d = 0x%04x\n", i,
+			b43legacy_shm_read16(dev, B43legacy_SHM_WIRELESS, i));
+	}
+
+	return count;
+}
+
+/* wl->irq_lock is locked */
+static ssize_t shm_read_file(struct b43legacy_wldev *dev, char *buf, size_t bufsize)
+{
+	ssize_t count = 0;
+	int i;
+	u16 tmp;
+	__le16 *le16buf = (__le16 *)buf;
+
+	for (i = 0; i < 0x1000; i++) {
+		if (bufsize < sizeof(tmp))
+			break;
+		tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 2 * i);
+		le16buf[i] = cpu_to_le16(tmp);
+		count += sizeof(tmp);
+		bufsize -= sizeof(tmp);
+	}
+
+	return count;
+}
+
+static ssize_t txstat_read_file(struct b43legacy_wldev *dev, char *buf, size_t bufsize)
+{
+	struct b43legacy_txstatus_log *log = &dev->dfsentry->txstatlog;
+	ssize_t count = 0;
+	unsigned long flags;
+	int i, idx;
+	struct b43legacy_txstatus *stat;
+
+	spin_lock_irqsave(&log->lock, flags);
+	if (log->end < 0) {
+		fappend("Nothing transmitted, yet\n");
+		goto out_unlock;
+	}
+	fappend("b43legacy TX status reports:\n\n"
+		"index | cookie | seq | phy_stat | frame_count | "
+		"rts_count | supp_reason | pm_indicated | "
+		"intermediate | for_ampdu | acked\n" "---\n");
+	i = log->end + 1;
+	idx = 0;
+	while (1) {
+		if (i == B43legacy_NR_LOGGED_TXSTATUS)
+			i = 0;
+		stat = &(log->log[i]);
+		if (stat->cookie) {
+			fappend("%03d | "
+				"0x%04X | 0x%04X | 0x%02X | "
+				"0x%X | 0x%X | "
+				"%u | %u | "
+				"%u | %u | %u\n",
+				idx,
+				stat->cookie, stat->seq, stat->phy_stat,
+				stat->frame_count, stat->rts_count,
+				stat->supp_reason, stat->pm_indicated,
+				stat->intermediate, stat->for_ampdu,
+				stat->acked);
+			idx++;
+		}
+		if (i == log->end)
+			break;
+		i++;
+	}
+out_unlock:
+	spin_unlock_irqrestore(&log->lock, flags);
+
+	return count;
+}
+
+/* wl->irq_lock is locked */
+static int restart_write_file(struct b43legacy_wldev *dev, const char *buf, size_t count)
+{
+	int err = 0;
+
+	if (count > 0 && buf[0] == '1') {
+		b43legacy_controller_restart(dev, "manually restarted");
+	} else
+		err = -EINVAL;
+
+	return err;
+}
+
+#undef fappend
+
+static ssize_t b43legacy_debugfs_read(struct file *file, char __user *userbuf,
+				size_t count, loff_t *ppos)
+{
+	struct b43legacy_wldev *dev;
+	struct b43legacy_debugfs_fops *dfops;
+	struct b43legacy_dfs_file *dfile;
+	ssize_t uninitialized_var(ret);
+	char *buf;
+	const size_t bufsize = 1024 * 16; /* 16 KiB buffer */
+	const size_t buforder = get_order(bufsize);
+	int err = 0;
+
+	if (!count)
+		return 0;
+	dev = file->private_data;
+	if (!dev)
+		return -ENODEV;
+
+	mutex_lock(&dev->wl->mutex);
+	if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) {
+		err = -ENODEV;
+		goto out_unlock;
+	}
+
+	dfops = container_of(debugfs_real_fops(file),
+			     struct b43legacy_debugfs_fops, fops);
+	if (!dfops->read) {
+		err = -ENOSYS;
+		goto out_unlock;
+	}
+	dfile = fops_to_dfs_file(dev, dfops);
+
+	if (!dfile->buffer) {
+		buf = (char *)__get_free_pages(GFP_KERNEL, buforder);
+		if (!buf) {
+			err = -ENOMEM;
+			goto out_unlock;
+		}
+		memset(buf, 0, bufsize);
+		if (dfops->take_irqlock) {
+			spin_lock_irq(&dev->wl->irq_lock);
+			ret = dfops->read(dev, buf, bufsize);
+			spin_unlock_irq(&dev->wl->irq_lock);
+		} else
+			ret = dfops->read(dev, buf, bufsize);
+		if (ret <= 0) {
+			free_pages((unsigned long)buf, buforder);
+			err = ret;
+			goto out_unlock;
+		}
+		dfile->data_len = ret;
+		dfile->buffer = buf;
+	}
+
+	ret = simple_read_from_buffer(userbuf, count, ppos,
+				      dfile->buffer,
+				      dfile->data_len);
+	if (*ppos >= dfile->data_len) {
+		free_pages((unsigned long)dfile->buffer, buforder);
+		dfile->buffer = NULL;
+		dfile->data_len = 0;
+	}
+out_unlock:
+	mutex_unlock(&dev->wl->mutex);
+
+	return err ? err : ret;
+}
+
+static ssize_t b43legacy_debugfs_write(struct file *file,
+				 const char __user *userbuf,
+				 size_t count, loff_t *ppos)
+{
+	struct b43legacy_wldev *dev;
+	struct b43legacy_debugfs_fops *dfops;
+	char *buf;
+	int err = 0;
+
+	if (!count)
+		return 0;
+	if (count > PAGE_SIZE)
+		return -E2BIG;
+	dev = file->private_data;
+	if (!dev)
+		return -ENODEV;
+
+	mutex_lock(&dev->wl->mutex);
+	if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) {
+		err = -ENODEV;
+		goto out_unlock;
+	}
+
+	dfops = container_of(debugfs_real_fops(file),
+			     struct b43legacy_debugfs_fops, fops);
+	if (!dfops->write) {
+		err = -ENOSYS;
+		goto out_unlock;
+	}
+
+	buf = (char *)get_zeroed_page(GFP_KERNEL);
+	if (!buf) {
+		err = -ENOMEM;
+		goto out_unlock;
+	}
+	if (copy_from_user(buf, userbuf, count)) {
+		err = -EFAULT;
+		goto out_freepage;
+	}
+	if (dfops->take_irqlock) {
+		spin_lock_irq(&dev->wl->irq_lock);
+		err = dfops->write(dev, buf, count);
+		spin_unlock_irq(&dev->wl->irq_lock);
+	} else
+		err = dfops->write(dev, buf, count);
+	if (err)
+		goto out_freepage;
+
+out_freepage:
+	free_page((unsigned long)buf);
+out_unlock:
+	mutex_unlock(&dev->wl->mutex);
+
+	return err ? err : count;
+}
+
+
+#define B43legacy_DEBUGFS_FOPS(name, _read, _write, _take_irqlock)	\
+	static struct b43legacy_debugfs_fops fops_##name = {		\
+		.read	= _read,				\
+		.write	= _write,				\
+		.fops	= {					\
+			.open	= simple_open,				\
+			.read	= b43legacy_debugfs_read,		\
+			.write	= b43legacy_debugfs_write,		\
+			.llseek = generic_file_llseek,			\
+		},						\
+		.file_struct_offset = offsetof(struct b43legacy_dfsentry, \
+					       file_##name),	\
+		.take_irqlock	= _take_irqlock,		\
+	}
+
+B43legacy_DEBUGFS_FOPS(tsf, tsf_read_file, tsf_write_file, 1);
+B43legacy_DEBUGFS_FOPS(ucode_regs, ucode_regs_read_file, NULL, 1);
+B43legacy_DEBUGFS_FOPS(shm, shm_read_file, NULL, 1);
+B43legacy_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0);
+B43legacy_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1);
+
+
+int b43legacy_debug(struct b43legacy_wldev *dev, enum b43legacy_dyndbg feature)
+{
+	return !!(dev->dfsentry && dev->dfsentry->dyn_debug[feature]);
+}
+
+static void b43legacy_remove_dynamic_debug(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_dfsentry *e = dev->dfsentry;
+	int i;
+
+	for (i = 0; i < __B43legacy_NR_DYNDBG; i++)
+		debugfs_remove(e->dyn_debug_dentries[i]);
+}
+
+static void b43legacy_add_dynamic_debug(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_dfsentry *e = dev->dfsentry;
+	struct dentry *d;
+
+#define add_dyn_dbg(name, id, initstate) do {		\
+	e->dyn_debug[id] = (initstate);			\
+	d = debugfs_create_bool(name, 0600, e->subdir,	\
+				&(e->dyn_debug[id]));	\
+	if (!IS_ERR(d))					\
+		e->dyn_debug_dentries[id] = d;		\
+				} while (0)
+
+	add_dyn_dbg("debug_xmitpower", B43legacy_DBG_XMITPOWER, false);
+	add_dyn_dbg("debug_dmaoverflow", B43legacy_DBG_DMAOVERFLOW, false);
+	add_dyn_dbg("debug_dmaverbose", B43legacy_DBG_DMAVERBOSE, false);
+	add_dyn_dbg("debug_pwork_fast", B43legacy_DBG_PWORK_FAST, false);
+	add_dyn_dbg("debug_pwork_stop", B43legacy_DBG_PWORK_STOP, false);
+
+#undef add_dyn_dbg
+}
+
+void b43legacy_debugfs_add_device(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_dfsentry *e;
+	struct b43legacy_txstatus_log *log;
+	char devdir[16];
+
+	B43legacy_WARN_ON(!dev);
+	e = kzalloc(sizeof(*e), GFP_KERNEL);
+	if (!e) {
+		b43legacyerr(dev->wl, "debugfs: add device OOM\n");
+		return;
+	}
+	e->dev = dev;
+	log = &e->txstatlog;
+	log->log = kcalloc(B43legacy_NR_LOGGED_TXSTATUS,
+			   sizeof(struct b43legacy_txstatus), GFP_KERNEL);
+	if (!log->log) {
+		b43legacyerr(dev->wl, "debugfs: add device txstatus OOM\n");
+		kfree(e);
+		return;
+	}
+	log->end = -1;
+	spin_lock_init(&log->lock);
+
+	dev->dfsentry = e;
+
+	snprintf(devdir, sizeof(devdir), "%s", wiphy_name(dev->wl->hw->wiphy));
+	e->subdir = debugfs_create_dir(devdir, rootdir);
+	if (!e->subdir || IS_ERR(e->subdir)) {
+		if (e->subdir == ERR_PTR(-ENODEV)) {
+			b43legacydbg(dev->wl, "DebugFS (CONFIG_DEBUG_FS) not "
+			       "enabled in kernel config\n");
+		} else {
+			b43legacyerr(dev->wl, "debugfs: cannot create %s directory\n",
+			       devdir);
+		}
+		dev->dfsentry = NULL;
+		kfree(log->log);
+		kfree(e);
+		return;
+	}
+
+#define ADD_FILE(name, mode)	\
+	do {							\
+		struct dentry *d;				\
+		d = debugfs_create_file(__stringify(name),	\
+					mode, e->subdir, dev,	\
+					&fops_##name.fops);	\
+		e->file_##name.dentry = NULL;			\
+		if (!IS_ERR(d))					\
+			e->file_##name.dentry = d;		\
+	} while (0)
+
+
+	ADD_FILE(tsf, 0600);
+	ADD_FILE(ucode_regs, 0400);
+	ADD_FILE(shm, 0400);
+	ADD_FILE(txstat, 0400);
+	ADD_FILE(restart, 0200);
+
+#undef ADD_FILE
+
+	b43legacy_add_dynamic_debug(dev);
+}
+
+void b43legacy_debugfs_remove_device(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_dfsentry *e;
+
+	if (!dev)
+		return;
+	e = dev->dfsentry;
+	if (!e)
+		return;
+	b43legacy_remove_dynamic_debug(dev);
+
+	debugfs_remove(e->file_tsf.dentry);
+	debugfs_remove(e->file_ucode_regs.dentry);
+	debugfs_remove(e->file_shm.dentry);
+	debugfs_remove(e->file_txstat.dentry);
+	debugfs_remove(e->file_restart.dentry);
+
+	debugfs_remove(e->subdir);
+	kfree(e->txstatlog.log);
+	kfree(e);
+}
+
+void b43legacy_debugfs_log_txstat(struct b43legacy_wldev *dev,
+			    const struct b43legacy_txstatus *status)
+{
+	struct b43legacy_dfsentry *e = dev->dfsentry;
+	struct b43legacy_txstatus_log *log;
+	struct b43legacy_txstatus *cur;
+	int i;
+
+	if (!e)
+		return;
+	log = &e->txstatlog;
+	B43legacy_WARN_ON(!irqs_disabled());
+	spin_lock(&log->lock);
+	i = log->end + 1;
+	if (i == B43legacy_NR_LOGGED_TXSTATUS)
+		i = 0;
+	log->end = i;
+	cur = &(log->log[i]);
+	memcpy(cur, status, sizeof(*cur));
+	spin_unlock(&log->lock);
+}
+
+void b43legacy_debugfs_init(void)
+{
+	rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
+	if (IS_ERR(rootdir))
+		rootdir = NULL;
+}
+
+void b43legacy_debugfs_exit(void)
+{
+	debugfs_remove(rootdir);
+}
diff --git a/drivers/net/wireless/broadcom/b43legacy/debugfs.h b/drivers/net/wireless/broadcom/b43legacy/debugfs.h
new file mode 100644
index 0000000..7a37764
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/debugfs.h
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43legacy_DEBUGFS_H_
+#define B43legacy_DEBUGFS_H_
+
+struct b43legacy_wldev;
+struct b43legacy_txstatus;
+
+enum b43legacy_dyndbg { /* Dynamic debugging features */
+	B43legacy_DBG_XMITPOWER,
+	B43legacy_DBG_DMAOVERFLOW,
+	B43legacy_DBG_DMAVERBOSE,
+	B43legacy_DBG_PWORK_FAST,
+	B43legacy_DBG_PWORK_STOP,
+	__B43legacy_NR_DYNDBG,
+};
+
+
+#ifdef CONFIG_B43LEGACY_DEBUG
+
+struct dentry;
+
+#define B43legacy_NR_LOGGED_TXSTATUS	100
+
+struct b43legacy_txstatus_log {
+	struct b43legacy_txstatus *log;
+	int end;
+	spinlock_t lock;	/* lock for debugging */
+};
+
+struct b43legacy_dfs_file {
+	struct dentry *dentry;
+	char *buffer;
+	size_t data_len;
+};
+
+struct b43legacy_dfsentry {
+	struct b43legacy_wldev *dev;
+	struct dentry *subdir;
+
+	struct b43legacy_dfs_file file_tsf;
+	struct b43legacy_dfs_file file_ucode_regs;
+	struct b43legacy_dfs_file file_shm;
+	struct b43legacy_dfs_file file_txstat;
+	struct b43legacy_dfs_file file_txpower_g;
+	struct b43legacy_dfs_file file_restart;
+	struct b43legacy_dfs_file file_loctls;
+
+	struct b43legacy_txstatus_log txstatlog;
+
+	/* Enabled/Disabled list for the dynamic debugging features. */
+	bool dyn_debug[__B43legacy_NR_DYNDBG];
+	/* Dentries for the dynamic debugging entries. */
+	struct dentry *dyn_debug_dentries[__B43legacy_NR_DYNDBG];
+};
+
+int b43legacy_debug(struct b43legacy_wldev *dev,
+		    enum b43legacy_dyndbg feature);
+
+void b43legacy_debugfs_init(void);
+void b43legacy_debugfs_exit(void);
+void b43legacy_debugfs_add_device(struct b43legacy_wldev *dev);
+void b43legacy_debugfs_remove_device(struct b43legacy_wldev *dev);
+void b43legacy_debugfs_log_txstat(struct b43legacy_wldev *dev,
+				  const struct b43legacy_txstatus *status);
+
+#else /* CONFIG_B43LEGACY_DEBUG*/
+
+static inline
+int b43legacy_debug(struct b43legacy_wldev *dev,
+		    enum b43legacy_dyndbg feature)
+{
+	return 0;
+}
+
+static inline
+void b43legacy_debugfs_init(void) { }
+static inline
+void b43legacy_debugfs_exit(void) { }
+static inline
+void b43legacy_debugfs_add_device(struct b43legacy_wldev *dev) { }
+static inline
+void b43legacy_debugfs_remove_device(struct b43legacy_wldev *dev) { }
+static inline
+void b43legacy_debugfs_log_txstat(struct b43legacy_wldev *dev,
+				  const struct b43legacy_txstatus *status)
+				  { }
+
+#endif /* CONFIG_B43LEGACY_DEBUG*/
+
+#endif /* B43legacy_DEBUGFS_H_ */
diff --git a/drivers/net/wireless/broadcom/b43legacy/dma.c b/drivers/net/wireless/broadcom/b43legacy/dma.c
new file mode 100644
index 0000000..2f0c64c
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/dma.c
@@ -0,0 +1,1455 @@
+/*
+
+  Broadcom B43legacy wireless driver
+
+  DMA ringbuffer and descriptor allocation/management
+
+  Copyright (c) 2005, 2006 Michael Buesch <m@bues.ch>
+
+  Some code in this file is derived from the b44.c driver
+  Copyright (C) 2002 David S. Miller
+  Copyright (C) Pekka Pietikainen
+
+  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 "b43legacy.h"
+#include "dma.h"
+#include "main.h"
+#include "debugfs.h"
+#include "xmit.h"
+
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <net/dst.h>
+
+/* 32bit DMA ops. */
+static
+struct b43legacy_dmadesc32 *op32_idx2desc(struct b43legacy_dmaring *ring,
+					  int slot,
+					  struct b43legacy_dmadesc_meta **meta)
+{
+	struct b43legacy_dmadesc32 *desc;
+
+	*meta = &(ring->meta[slot]);
+	desc = ring->descbase;
+	desc = &(desc[slot]);
+
+	return desc;
+}
+
+static void op32_fill_descriptor(struct b43legacy_dmaring *ring,
+				 struct b43legacy_dmadesc32 *desc,
+				 dma_addr_t dmaaddr, u16 bufsize,
+				 int start, int end, int irq)
+{
+	struct b43legacy_dmadesc32 *descbase = ring->descbase;
+	int slot;
+	u32 ctl;
+	u32 addr;
+	u32 addrext;
+
+	slot = (int)(desc - descbase);
+	B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
+
+	addr = (u32)(dmaaddr & ~SSB_DMA_TRANSLATION_MASK);
+	addrext = (u32)(dmaaddr & SSB_DMA_TRANSLATION_MASK)
+		   >> SSB_DMA_TRANSLATION_SHIFT;
+	addr |= ring->dev->dma.translation;
+	ctl = (bufsize - ring->frameoffset)
+	      & B43legacy_DMA32_DCTL_BYTECNT;
+	if (slot == ring->nr_slots - 1)
+		ctl |= B43legacy_DMA32_DCTL_DTABLEEND;
+	if (start)
+		ctl |= B43legacy_DMA32_DCTL_FRAMESTART;
+	if (end)
+		ctl |= B43legacy_DMA32_DCTL_FRAMEEND;
+	if (irq)
+		ctl |= B43legacy_DMA32_DCTL_IRQ;
+	ctl |= (addrext << B43legacy_DMA32_DCTL_ADDREXT_SHIFT)
+	       & B43legacy_DMA32_DCTL_ADDREXT_MASK;
+
+	desc->control = cpu_to_le32(ctl);
+	desc->address = cpu_to_le32(addr);
+}
+
+static void op32_poke_tx(struct b43legacy_dmaring *ring, int slot)
+{
+	b43legacy_dma_write(ring, B43legacy_DMA32_TXINDEX,
+			    (u32)(slot * sizeof(struct b43legacy_dmadesc32)));
+}
+
+static void op32_tx_suspend(struct b43legacy_dmaring *ring)
+{
+	b43legacy_dma_write(ring, B43legacy_DMA32_TXCTL,
+			    b43legacy_dma_read(ring, B43legacy_DMA32_TXCTL)
+			    | B43legacy_DMA32_TXSUSPEND);
+}
+
+static void op32_tx_resume(struct b43legacy_dmaring *ring)
+{
+	b43legacy_dma_write(ring, B43legacy_DMA32_TXCTL,
+			    b43legacy_dma_read(ring, B43legacy_DMA32_TXCTL)
+			    & ~B43legacy_DMA32_TXSUSPEND);
+}
+
+static int op32_get_current_rxslot(struct b43legacy_dmaring *ring)
+{
+	u32 val;
+
+	val = b43legacy_dma_read(ring, B43legacy_DMA32_RXSTATUS);
+	val &= B43legacy_DMA32_RXDPTR;
+
+	return (val / sizeof(struct b43legacy_dmadesc32));
+}
+
+static void op32_set_current_rxslot(struct b43legacy_dmaring *ring,
+				    int slot)
+{
+	b43legacy_dma_write(ring, B43legacy_DMA32_RXINDEX,
+			    (u32)(slot * sizeof(struct b43legacy_dmadesc32)));
+}
+
+static inline int free_slots(struct b43legacy_dmaring *ring)
+{
+	return (ring->nr_slots - ring->used_slots);
+}
+
+static inline int next_slot(struct b43legacy_dmaring *ring, int slot)
+{
+	B43legacy_WARN_ON(!(slot >= -1 && slot <= ring->nr_slots - 1));
+	if (slot == ring->nr_slots - 1)
+		return 0;
+	return slot + 1;
+}
+
+static inline int prev_slot(struct b43legacy_dmaring *ring, int slot)
+{
+	B43legacy_WARN_ON(!(slot >= 0 && slot <= ring->nr_slots - 1));
+	if (slot == 0)
+		return ring->nr_slots - 1;
+	return slot - 1;
+}
+
+#ifdef CONFIG_B43LEGACY_DEBUG
+static void update_max_used_slots(struct b43legacy_dmaring *ring,
+				  int current_used_slots)
+{
+	if (current_used_slots <= ring->max_used_slots)
+		return;
+	ring->max_used_slots = current_used_slots;
+	if (b43legacy_debug(ring->dev, B43legacy_DBG_DMAVERBOSE))
+		b43legacydbg(ring->dev->wl,
+		       "max_used_slots increased to %d on %s ring %d\n",
+		       ring->max_used_slots,
+		       ring->tx ? "TX" : "RX",
+		       ring->index);
+}
+#else
+static inline
+void update_max_used_slots(struct b43legacy_dmaring *ring,
+			   int current_used_slots)
+{ }
+#endif /* DEBUG */
+
+/* Request a slot for usage. */
+static inline
+int request_slot(struct b43legacy_dmaring *ring)
+{
+	int slot;
+
+	B43legacy_WARN_ON(!ring->tx);
+	B43legacy_WARN_ON(ring->stopped);
+	B43legacy_WARN_ON(free_slots(ring) == 0);
+
+	slot = next_slot(ring, ring->current_slot);
+	ring->current_slot = slot;
+	ring->used_slots++;
+
+	update_max_used_slots(ring, ring->used_slots);
+
+	return slot;
+}
+
+/* Mac80211-queue to b43legacy-ring mapping */
+static struct b43legacy_dmaring *priority_to_txring(
+						struct b43legacy_wldev *dev,
+						int queue_priority)
+{
+	struct b43legacy_dmaring *ring;
+
+/*FIXME: For now we always run on TX-ring-1 */
+return dev->dma.tx_ring1;
+
+	/* 0 = highest priority */
+	switch (queue_priority) {
+	default:
+		B43legacy_WARN_ON(1);
+		/* fallthrough */
+	case 0:
+		ring = dev->dma.tx_ring3;
+		break;
+	case 1:
+		ring = dev->dma.tx_ring2;
+		break;
+	case 2:
+		ring = dev->dma.tx_ring1;
+		break;
+	case 3:
+		ring = dev->dma.tx_ring0;
+		break;
+	case 4:
+		ring = dev->dma.tx_ring4;
+		break;
+	case 5:
+		ring = dev->dma.tx_ring5;
+		break;
+	}
+
+	return ring;
+}
+
+/* Bcm4301-ring to mac80211-queue mapping */
+static inline int txring_to_priority(struct b43legacy_dmaring *ring)
+{
+	static const u8 idx_to_prio[] =
+		{ 3, 2, 1, 0, 4, 5, };
+
+/*FIXME: have only one queue, for now */
+return 0;
+
+	return idx_to_prio[ring->index];
+}
+
+
+static u16 b43legacy_dmacontroller_base(enum b43legacy_dmatype type,
+					int controller_idx)
+{
+	static const u16 map32[] = {
+		B43legacy_MMIO_DMA32_BASE0,
+		B43legacy_MMIO_DMA32_BASE1,
+		B43legacy_MMIO_DMA32_BASE2,
+		B43legacy_MMIO_DMA32_BASE3,
+		B43legacy_MMIO_DMA32_BASE4,
+		B43legacy_MMIO_DMA32_BASE5,
+	};
+
+	B43legacy_WARN_ON(!(controller_idx >= 0 &&
+			  controller_idx < ARRAY_SIZE(map32)));
+	return map32[controller_idx];
+}
+
+static inline
+dma_addr_t map_descbuffer(struct b43legacy_dmaring *ring,
+			  unsigned char *buf,
+			  size_t len,
+			  int tx)
+{
+	dma_addr_t dmaaddr;
+
+	if (tx)
+		dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
+					     buf, len,
+					     DMA_TO_DEVICE);
+	else
+		dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
+					     buf, len,
+					     DMA_FROM_DEVICE);
+
+	return dmaaddr;
+}
+
+static inline
+void unmap_descbuffer(struct b43legacy_dmaring *ring,
+		      dma_addr_t addr,
+		      size_t len,
+		      int tx)
+{
+	if (tx)
+		dma_unmap_single(ring->dev->dev->dma_dev,
+				     addr, len,
+				     DMA_TO_DEVICE);
+	else
+		dma_unmap_single(ring->dev->dev->dma_dev,
+				     addr, len,
+				     DMA_FROM_DEVICE);
+}
+
+static inline
+void sync_descbuffer_for_cpu(struct b43legacy_dmaring *ring,
+			     dma_addr_t addr,
+			     size_t len)
+{
+	B43legacy_WARN_ON(ring->tx);
+
+	dma_sync_single_for_cpu(ring->dev->dev->dma_dev,
+				addr, len, DMA_FROM_DEVICE);
+}
+
+static inline
+void sync_descbuffer_for_device(struct b43legacy_dmaring *ring,
+				dma_addr_t addr,
+				size_t len)
+{
+	B43legacy_WARN_ON(ring->tx);
+
+	dma_sync_single_for_device(ring->dev->dev->dma_dev,
+				   addr, len, DMA_FROM_DEVICE);
+}
+
+static inline
+void free_descriptor_buffer(struct b43legacy_dmaring *ring,
+			    struct b43legacy_dmadesc_meta *meta,
+			    int irq_context)
+{
+	if (meta->skb) {
+		if (irq_context)
+			dev_kfree_skb_irq(meta->skb);
+		else
+			dev_kfree_skb(meta->skb);
+		meta->skb = NULL;
+	}
+}
+
+static int alloc_ringmemory(struct b43legacy_dmaring *ring)
+{
+	/* GFP flags must match the flags in free_ringmemory()! */
+	ring->descbase = dma_zalloc_coherent(ring->dev->dev->dma_dev,
+					     B43legacy_DMA_RINGMEMSIZE,
+					     &(ring->dmabase), GFP_KERNEL);
+	if (!ring->descbase)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void free_ringmemory(struct b43legacy_dmaring *ring)
+{
+	dma_free_coherent(ring->dev->dev->dma_dev, B43legacy_DMA_RINGMEMSIZE,
+			  ring->descbase, ring->dmabase);
+}
+
+/* Reset the RX DMA channel */
+static int b43legacy_dmacontroller_rx_reset(struct b43legacy_wldev *dev,
+					    u16 mmio_base,
+					    enum b43legacy_dmatype type)
+{
+	int i;
+	u32 value;
+	u16 offset;
+
+	might_sleep();
+
+	offset = B43legacy_DMA32_RXCTL;
+	b43legacy_write32(dev, mmio_base + offset, 0);
+	for (i = 0; i < 10; i++) {
+		offset = B43legacy_DMA32_RXSTATUS;
+		value = b43legacy_read32(dev, mmio_base + offset);
+		value &= B43legacy_DMA32_RXSTATE;
+		if (value == B43legacy_DMA32_RXSTAT_DISABLED) {
+			i = -1;
+			break;
+		}
+		msleep(1);
+	}
+	if (i != -1) {
+		b43legacyerr(dev->wl, "DMA RX reset timed out\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+/* Reset the RX DMA channel */
+static int b43legacy_dmacontroller_tx_reset(struct b43legacy_wldev *dev,
+					    u16 mmio_base,
+					    enum b43legacy_dmatype type)
+{
+	int i;
+	u32 value;
+	u16 offset;
+
+	might_sleep();
+
+	for (i = 0; i < 10; i++) {
+		offset = B43legacy_DMA32_TXSTATUS;
+		value = b43legacy_read32(dev, mmio_base + offset);
+		value &= B43legacy_DMA32_TXSTATE;
+		if (value == B43legacy_DMA32_TXSTAT_DISABLED ||
+		    value == B43legacy_DMA32_TXSTAT_IDLEWAIT ||
+		    value == B43legacy_DMA32_TXSTAT_STOPPED)
+			break;
+		msleep(1);
+	}
+	offset = B43legacy_DMA32_TXCTL;
+	b43legacy_write32(dev, mmio_base + offset, 0);
+	for (i = 0; i < 10; i++) {
+		offset = B43legacy_DMA32_TXSTATUS;
+		value = b43legacy_read32(dev, mmio_base + offset);
+		value &= B43legacy_DMA32_TXSTATE;
+		if (value == B43legacy_DMA32_TXSTAT_DISABLED) {
+			i = -1;
+			break;
+		}
+		msleep(1);
+	}
+	if (i != -1) {
+		b43legacyerr(dev->wl, "DMA TX reset timed out\n");
+		return -ENODEV;
+	}
+	/* ensure the reset is completed. */
+	msleep(1);
+
+	return 0;
+}
+
+/* Check if a DMA mapping address is invalid. */
+static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring,
+					 dma_addr_t addr,
+					 size_t buffersize,
+					 bool dma_to_device)
+{
+	if (unlikely(dma_mapping_error(ring->dev->dev->dma_dev, addr)))
+		return true;
+
+	switch (ring->type) {
+	case B43legacy_DMA_30BIT:
+		if ((u64)addr + buffersize > (1ULL << 30))
+			goto address_error;
+		break;
+	case B43legacy_DMA_32BIT:
+		if ((u64)addr + buffersize > (1ULL << 32))
+			goto address_error;
+		break;
+	}
+
+	/* The address is OK. */
+	return false;
+
+address_error:
+	/* We can't support this address. Unmap it again. */
+	unmap_descbuffer(ring, addr, buffersize, dma_to_device);
+
+	return true;
+}
+
+static int setup_rx_descbuffer(struct b43legacy_dmaring *ring,
+			       struct b43legacy_dmadesc32 *desc,
+			       struct b43legacy_dmadesc_meta *meta,
+			       gfp_t gfp_flags)
+{
+	struct b43legacy_rxhdr_fw3 *rxhdr;
+	struct b43legacy_hwtxstatus *txstat;
+	dma_addr_t dmaaddr;
+	struct sk_buff *skb;
+
+	B43legacy_WARN_ON(ring->tx);
+
+	skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags);
+	if (unlikely(!skb))
+		return -ENOMEM;
+	dmaaddr = map_descbuffer(ring, skb->data,
+				 ring->rx_buffersize, 0);
+	if (b43legacy_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) {
+		/* ugh. try to realloc in zone_dma */
+		gfp_flags |= GFP_DMA;
+
+		dev_kfree_skb_any(skb);
+
+		skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags);
+		if (unlikely(!skb))
+			return -ENOMEM;
+		dmaaddr = map_descbuffer(ring, skb->data,
+					 ring->rx_buffersize, 0);
+	}
+
+	if (b43legacy_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) {
+		dev_kfree_skb_any(skb);
+		return -EIO;
+	}
+
+	meta->skb = skb;
+	meta->dmaaddr = dmaaddr;
+	op32_fill_descriptor(ring, desc, dmaaddr, ring->rx_buffersize, 0, 0, 0);
+
+	rxhdr = (struct b43legacy_rxhdr_fw3 *)(skb->data);
+	rxhdr->frame_len = 0;
+	txstat = (struct b43legacy_hwtxstatus *)(skb->data);
+	txstat->cookie = 0;
+
+	return 0;
+}
+
+/* Allocate the initial descbuffers.
+ * This is used for an RX ring only.
+ */
+static int alloc_initial_descbuffers(struct b43legacy_dmaring *ring)
+{
+	int i;
+	int err = -ENOMEM;
+	struct b43legacy_dmadesc32 *desc;
+	struct b43legacy_dmadesc_meta *meta;
+
+	for (i = 0; i < ring->nr_slots; i++) {
+		desc = op32_idx2desc(ring, i, &meta);
+
+		err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL);
+		if (err) {
+			b43legacyerr(ring->dev->wl,
+			       "Failed to allocate initial descbuffers\n");
+			goto err_unwind;
+		}
+	}
+	mb(); /* all descbuffer setup before next line */
+	ring->used_slots = ring->nr_slots;
+	err = 0;
+out:
+	return err;
+
+err_unwind:
+	for (i--; i >= 0; i--) {
+		desc = op32_idx2desc(ring, i, &meta);
+
+		unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0);
+		dev_kfree_skb(meta->skb);
+	}
+	goto out;
+}
+
+/* Do initial setup of the DMA controller.
+ * Reset the controller, write the ring busaddress
+ * and switch the "enable" bit on.
+ */
+static int dmacontroller_setup(struct b43legacy_dmaring *ring)
+{
+	int err = 0;
+	u32 value;
+	u32 addrext;
+	u32 trans = ring->dev->dma.translation;
+	u32 ringbase = (u32)(ring->dmabase);
+
+	if (ring->tx) {
+		addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
+			  >> SSB_DMA_TRANSLATION_SHIFT;
+		value = B43legacy_DMA32_TXENABLE;
+		value |= (addrext << B43legacy_DMA32_TXADDREXT_SHIFT)
+			& B43legacy_DMA32_TXADDREXT_MASK;
+		b43legacy_dma_write(ring, B43legacy_DMA32_TXCTL, value);
+		b43legacy_dma_write(ring, B43legacy_DMA32_TXRING,
+				    (ringbase & ~SSB_DMA_TRANSLATION_MASK)
+				    | trans);
+	} else {
+		err = alloc_initial_descbuffers(ring);
+		if (err)
+			goto out;
+
+		addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
+			  >> SSB_DMA_TRANSLATION_SHIFT;
+		value = (ring->frameoffset <<
+			 B43legacy_DMA32_RXFROFF_SHIFT);
+		value |= B43legacy_DMA32_RXENABLE;
+		value |= (addrext << B43legacy_DMA32_RXADDREXT_SHIFT)
+			 & B43legacy_DMA32_RXADDREXT_MASK;
+		b43legacy_dma_write(ring, B43legacy_DMA32_RXCTL, value);
+		b43legacy_dma_write(ring, B43legacy_DMA32_RXRING,
+				    (ringbase & ~SSB_DMA_TRANSLATION_MASK)
+				    | trans);
+		b43legacy_dma_write(ring, B43legacy_DMA32_RXINDEX, 200);
+	}
+
+out:
+	return err;
+}
+
+/* Shutdown the DMA controller. */
+static void dmacontroller_cleanup(struct b43legacy_dmaring *ring)
+{
+	if (ring->tx) {
+		b43legacy_dmacontroller_tx_reset(ring->dev, ring->mmio_base,
+						 ring->type);
+		b43legacy_dma_write(ring, B43legacy_DMA32_TXRING, 0);
+	} else {
+		b43legacy_dmacontroller_rx_reset(ring->dev, ring->mmio_base,
+						 ring->type);
+		b43legacy_dma_write(ring, B43legacy_DMA32_RXRING, 0);
+	}
+}
+
+static void free_all_descbuffers(struct b43legacy_dmaring *ring)
+{
+	struct b43legacy_dmadesc_meta *meta;
+	int i;
+
+	if (!ring->used_slots)
+		return;
+	for (i = 0; i < ring->nr_slots; i++) {
+		op32_idx2desc(ring, i, &meta);
+
+		if (!meta->skb) {
+			B43legacy_WARN_ON(!ring->tx);
+			continue;
+		}
+		if (ring->tx)
+			unmap_descbuffer(ring, meta->dmaaddr,
+					 meta->skb->len, 1);
+		else
+			unmap_descbuffer(ring, meta->dmaaddr,
+					 ring->rx_buffersize, 0);
+		free_descriptor_buffer(ring, meta, 0);
+	}
+}
+
+static u64 supported_dma_mask(struct b43legacy_wldev *dev)
+{
+	u32 tmp;
+	u16 mmio_base;
+
+	mmio_base = b43legacy_dmacontroller_base(0, 0);
+	b43legacy_write32(dev,
+			mmio_base + B43legacy_DMA32_TXCTL,
+			B43legacy_DMA32_TXADDREXT_MASK);
+	tmp = b43legacy_read32(dev, mmio_base +
+			       B43legacy_DMA32_TXCTL);
+	if (tmp & B43legacy_DMA32_TXADDREXT_MASK)
+		return DMA_BIT_MASK(32);
+
+	return DMA_BIT_MASK(30);
+}
+
+static enum b43legacy_dmatype dma_mask_to_engine_type(u64 dmamask)
+{
+	if (dmamask == DMA_BIT_MASK(30))
+		return B43legacy_DMA_30BIT;
+	if (dmamask == DMA_BIT_MASK(32))
+		return B43legacy_DMA_32BIT;
+	B43legacy_WARN_ON(1);
+	return B43legacy_DMA_30BIT;
+}
+
+/* Main initialization function. */
+static
+struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev,
+						  int controller_index,
+						  int for_tx,
+						  enum b43legacy_dmatype type)
+{
+	struct b43legacy_dmaring *ring;
+	int err;
+	int nr_slots;
+	dma_addr_t dma_test;
+
+	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
+	if (!ring)
+		goto out;
+	ring->type = type;
+	ring->dev = dev;
+
+	nr_slots = B43legacy_RXRING_SLOTS;
+	if (for_tx)
+		nr_slots = B43legacy_TXRING_SLOTS;
+
+	ring->meta = kcalloc(nr_slots, sizeof(struct b43legacy_dmadesc_meta),
+			     GFP_KERNEL);
+	if (!ring->meta)
+		goto err_kfree_ring;
+	if (for_tx) {
+		ring->txhdr_cache = kcalloc(nr_slots,
+					sizeof(struct b43legacy_txhdr_fw3),
+					GFP_KERNEL);
+		if (!ring->txhdr_cache)
+			goto err_kfree_meta;
+
+		/* test for ability to dma to txhdr_cache */
+		dma_test = dma_map_single(dev->dev->dma_dev, ring->txhdr_cache,
+					      sizeof(struct b43legacy_txhdr_fw3),
+					      DMA_TO_DEVICE);
+
+		if (b43legacy_dma_mapping_error(ring, dma_test,
+					sizeof(struct b43legacy_txhdr_fw3), 1)) {
+			/* ugh realloc */
+			kfree(ring->txhdr_cache);
+			ring->txhdr_cache = kcalloc(nr_slots,
+					sizeof(struct b43legacy_txhdr_fw3),
+					GFP_KERNEL | GFP_DMA);
+			if (!ring->txhdr_cache)
+				goto err_kfree_meta;
+
+			dma_test = dma_map_single(dev->dev->dma_dev,
+					ring->txhdr_cache,
+					sizeof(struct b43legacy_txhdr_fw3),
+					DMA_TO_DEVICE);
+
+			if (b43legacy_dma_mapping_error(ring, dma_test,
+					sizeof(struct b43legacy_txhdr_fw3), 1))
+				goto err_kfree_txhdr_cache;
+		}
+
+		dma_unmap_single(dev->dev->dma_dev, dma_test,
+				 sizeof(struct b43legacy_txhdr_fw3),
+				 DMA_TO_DEVICE);
+	}
+
+	ring->nr_slots = nr_slots;
+	ring->mmio_base = b43legacy_dmacontroller_base(type, controller_index);
+	ring->index = controller_index;
+	if (for_tx) {
+		ring->tx = true;
+		ring->current_slot = -1;
+	} else {
+		if (ring->index == 0) {
+			ring->rx_buffersize = B43legacy_DMA0_RX_BUFFERSIZE;
+			ring->frameoffset = B43legacy_DMA0_RX_FRAMEOFFSET;
+		} else if (ring->index == 3) {
+			ring->rx_buffersize = B43legacy_DMA3_RX_BUFFERSIZE;
+			ring->frameoffset = B43legacy_DMA3_RX_FRAMEOFFSET;
+		} else
+			B43legacy_WARN_ON(1);
+	}
+#ifdef CONFIG_B43LEGACY_DEBUG
+	ring->last_injected_overflow = jiffies;
+#endif
+
+	err = alloc_ringmemory(ring);
+	if (err)
+		goto err_kfree_txhdr_cache;
+	err = dmacontroller_setup(ring);
+	if (err)
+		goto err_free_ringmemory;
+
+out:
+	return ring;
+
+err_free_ringmemory:
+	free_ringmemory(ring);
+err_kfree_txhdr_cache:
+	kfree(ring->txhdr_cache);
+err_kfree_meta:
+	kfree(ring->meta);
+err_kfree_ring:
+	kfree(ring);
+	ring = NULL;
+	goto out;
+}
+
+/* Main cleanup function. */
+static void b43legacy_destroy_dmaring(struct b43legacy_dmaring *ring)
+{
+	if (!ring)
+		return;
+
+	b43legacydbg(ring->dev->wl, "DMA-%u 0x%04X (%s) max used slots:"
+		     " %d/%d\n", (unsigned int)(ring->type), ring->mmio_base,
+		     (ring->tx) ? "TX" : "RX", ring->max_used_slots,
+		     ring->nr_slots);
+	/* Device IRQs are disabled prior entering this function,
+	 * so no need to take care of concurrency with rx handler stuff.
+	 */
+	dmacontroller_cleanup(ring);
+	free_all_descbuffers(ring);
+	free_ringmemory(ring);
+
+	kfree(ring->txhdr_cache);
+	kfree(ring->meta);
+	kfree(ring);
+}
+
+void b43legacy_dma_free(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_dma *dma;
+
+	if (b43legacy_using_pio(dev))
+		return;
+	dma = &dev->dma;
+
+	b43legacy_destroy_dmaring(dma->rx_ring3);
+	dma->rx_ring3 = NULL;
+	b43legacy_destroy_dmaring(dma->rx_ring0);
+	dma->rx_ring0 = NULL;
+
+	b43legacy_destroy_dmaring(dma->tx_ring5);
+	dma->tx_ring5 = NULL;
+	b43legacy_destroy_dmaring(dma->tx_ring4);
+	dma->tx_ring4 = NULL;
+	b43legacy_destroy_dmaring(dma->tx_ring3);
+	dma->tx_ring3 = NULL;
+	b43legacy_destroy_dmaring(dma->tx_ring2);
+	dma->tx_ring2 = NULL;
+	b43legacy_destroy_dmaring(dma->tx_ring1);
+	dma->tx_ring1 = NULL;
+	b43legacy_destroy_dmaring(dma->tx_ring0);
+	dma->tx_ring0 = NULL;
+}
+
+static int b43legacy_dma_set_mask(struct b43legacy_wldev *dev, u64 mask)
+{
+	u64 orig_mask = mask;
+	bool fallback = false;
+	int err;
+
+	/* Try to set the DMA mask. If it fails, try falling back to a
+	 * lower mask, as we can always also support a lower one. */
+	while (1) {
+		err = dma_set_mask_and_coherent(dev->dev->dma_dev, mask);
+		if (!err)
+			break;
+		if (mask == DMA_BIT_MASK(64)) {
+			mask = DMA_BIT_MASK(32);
+			fallback = true;
+			continue;
+		}
+		if (mask == DMA_BIT_MASK(32)) {
+			mask = DMA_BIT_MASK(30);
+			fallback = true;
+			continue;
+		}
+		b43legacyerr(dev->wl, "The machine/kernel does not support "
+		       "the required %u-bit DMA mask\n",
+		       (unsigned int)dma_mask_to_engine_type(orig_mask));
+		return -EOPNOTSUPP;
+	}
+	if (fallback) {
+		b43legacyinfo(dev->wl, "DMA mask fallback from %u-bit to %u-"
+			"bit\n",
+			(unsigned int)dma_mask_to_engine_type(orig_mask),
+			(unsigned int)dma_mask_to_engine_type(mask));
+	}
+
+	return 0;
+}
+
+int b43legacy_dma_init(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_dma *dma = &dev->dma;
+	struct b43legacy_dmaring *ring;
+	int err;
+	u64 dmamask;
+	enum b43legacy_dmatype type;
+
+	dmamask = supported_dma_mask(dev);
+	type = dma_mask_to_engine_type(dmamask);
+	err = b43legacy_dma_set_mask(dev, dmamask);
+	if (err) {
+#ifdef CONFIG_B43LEGACY_PIO
+		b43legacywarn(dev->wl, "DMA for this device not supported. "
+			"Falling back to PIO\n");
+		dev->__using_pio = true;
+		return -EAGAIN;
+#else
+		b43legacyerr(dev->wl, "DMA for this device not supported and "
+		       "no PIO support compiled in\n");
+		return -EOPNOTSUPP;
+#endif
+	}
+	dma->translation = ssb_dma_translation(dev->dev);
+
+	err = -ENOMEM;
+	/* setup TX DMA channels. */
+	ring = b43legacy_setup_dmaring(dev, 0, 1, type);
+	if (!ring)
+		goto out;
+	dma->tx_ring0 = ring;
+
+	ring = b43legacy_setup_dmaring(dev, 1, 1, type);
+	if (!ring)
+		goto err_destroy_tx0;
+	dma->tx_ring1 = ring;
+
+	ring = b43legacy_setup_dmaring(dev, 2, 1, type);
+	if (!ring)
+		goto err_destroy_tx1;
+	dma->tx_ring2 = ring;
+
+	ring = b43legacy_setup_dmaring(dev, 3, 1, type);
+	if (!ring)
+		goto err_destroy_tx2;
+	dma->tx_ring3 = ring;
+
+	ring = b43legacy_setup_dmaring(dev, 4, 1, type);
+	if (!ring)
+		goto err_destroy_tx3;
+	dma->tx_ring4 = ring;
+
+	ring = b43legacy_setup_dmaring(dev, 5, 1, type);
+	if (!ring)
+		goto err_destroy_tx4;
+	dma->tx_ring5 = ring;
+
+	/* setup RX DMA channels. */
+	ring = b43legacy_setup_dmaring(dev, 0, 0, type);
+	if (!ring)
+		goto err_destroy_tx5;
+	dma->rx_ring0 = ring;
+
+	if (dev->dev->id.revision < 5) {
+		ring = b43legacy_setup_dmaring(dev, 3, 0, type);
+		if (!ring)
+			goto err_destroy_rx0;
+		dma->rx_ring3 = ring;
+	}
+
+	b43legacydbg(dev->wl, "%u-bit DMA initialized\n", (unsigned int)type);
+	err = 0;
+out:
+	return err;
+
+err_destroy_rx0:
+	b43legacy_destroy_dmaring(dma->rx_ring0);
+	dma->rx_ring0 = NULL;
+err_destroy_tx5:
+	b43legacy_destroy_dmaring(dma->tx_ring5);
+	dma->tx_ring5 = NULL;
+err_destroy_tx4:
+	b43legacy_destroy_dmaring(dma->tx_ring4);
+	dma->tx_ring4 = NULL;
+err_destroy_tx3:
+	b43legacy_destroy_dmaring(dma->tx_ring3);
+	dma->tx_ring3 = NULL;
+err_destroy_tx2:
+	b43legacy_destroy_dmaring(dma->tx_ring2);
+	dma->tx_ring2 = NULL;
+err_destroy_tx1:
+	b43legacy_destroy_dmaring(dma->tx_ring1);
+	dma->tx_ring1 = NULL;
+err_destroy_tx0:
+	b43legacy_destroy_dmaring(dma->tx_ring0);
+	dma->tx_ring0 = NULL;
+	goto out;
+}
+
+/* Generate a cookie for the TX header. */
+static u16 generate_cookie(struct b43legacy_dmaring *ring,
+			   int slot)
+{
+	u16 cookie = 0x1000;
+
+	/* Use the upper 4 bits of the cookie as
+	 * DMA controller ID and store the slot number
+	 * in the lower 12 bits.
+	 * Note that the cookie must never be 0, as this
+	 * is a special value used in RX path.
+	 */
+	switch (ring->index) {
+	case 0:
+		cookie = 0xA000;
+		break;
+	case 1:
+		cookie = 0xB000;
+		break;
+	case 2:
+		cookie = 0xC000;
+		break;
+	case 3:
+		cookie = 0xD000;
+		break;
+	case 4:
+		cookie = 0xE000;
+		break;
+	case 5:
+		cookie = 0xF000;
+		break;
+	}
+	B43legacy_WARN_ON(!(((u16)slot & 0xF000) == 0x0000));
+	cookie |= (u16)slot;
+
+	return cookie;
+}
+
+/* Inspect a cookie and find out to which controller/slot it belongs. */
+static
+struct b43legacy_dmaring *parse_cookie(struct b43legacy_wldev *dev,
+				      u16 cookie, int *slot)
+{
+	struct b43legacy_dma *dma = &dev->dma;
+	struct b43legacy_dmaring *ring = NULL;
+
+	switch (cookie & 0xF000) {
+	case 0xA000:
+		ring = dma->tx_ring0;
+		break;
+	case 0xB000:
+		ring = dma->tx_ring1;
+		break;
+	case 0xC000:
+		ring = dma->tx_ring2;
+		break;
+	case 0xD000:
+		ring = dma->tx_ring3;
+		break;
+	case 0xE000:
+		ring = dma->tx_ring4;
+		break;
+	case 0xF000:
+		ring = dma->tx_ring5;
+		break;
+	default:
+		B43legacy_WARN_ON(1);
+	}
+	*slot = (cookie & 0x0FFF);
+	B43legacy_WARN_ON(!(ring && *slot >= 0 && *slot < ring->nr_slots));
+
+	return ring;
+}
+
+static int dma_tx_fragment(struct b43legacy_dmaring *ring,
+			    struct sk_buff **in_skb)
+{
+	struct sk_buff *skb = *in_skb;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	u8 *header;
+	int slot, old_top_slot, old_used_slots;
+	int err;
+	struct b43legacy_dmadesc32 *desc;
+	struct b43legacy_dmadesc_meta *meta;
+	struct b43legacy_dmadesc_meta *meta_hdr;
+	struct sk_buff *bounce_skb;
+
+#define SLOTS_PER_PACKET  2
+	B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags != 0);
+
+	old_top_slot = ring->current_slot;
+	old_used_slots = ring->used_slots;
+
+	/* Get a slot for the header. */
+	slot = request_slot(ring);
+	desc = op32_idx2desc(ring, slot, &meta_hdr);
+	memset(meta_hdr, 0, sizeof(*meta_hdr));
+
+	header = &(ring->txhdr_cache[slot * sizeof(
+			       struct b43legacy_txhdr_fw3)]);
+	err = b43legacy_generate_txhdr(ring->dev, header,
+				 skb->data, skb->len, info,
+				 generate_cookie(ring, slot));
+	if (unlikely(err)) {
+		ring->current_slot = old_top_slot;
+		ring->used_slots = old_used_slots;
+		return err;
+	}
+
+	meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header,
+					   sizeof(struct b43legacy_txhdr_fw3), 1);
+	if (b43legacy_dma_mapping_error(ring, meta_hdr->dmaaddr,
+					sizeof(struct b43legacy_txhdr_fw3), 1)) {
+		ring->current_slot = old_top_slot;
+		ring->used_slots = old_used_slots;
+		return -EIO;
+	}
+	op32_fill_descriptor(ring, desc, meta_hdr->dmaaddr,
+			     sizeof(struct b43legacy_txhdr_fw3), 1, 0, 0);
+
+	/* Get a slot for the payload. */
+	slot = request_slot(ring);
+	desc = op32_idx2desc(ring, slot, &meta);
+	memset(meta, 0, sizeof(*meta));
+
+	meta->skb = skb;
+	meta->is_last_fragment = true;
+
+	meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
+	/* create a bounce buffer in zone_dma on mapping failure. */
+	if (b43legacy_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
+		bounce_skb = alloc_skb(skb->len, GFP_KERNEL | GFP_DMA);
+		if (!bounce_skb) {
+			ring->current_slot = old_top_slot;
+			ring->used_slots = old_used_slots;
+			err = -ENOMEM;
+			goto out_unmap_hdr;
+		}
+
+		skb_put_data(bounce_skb, skb->data, skb->len);
+		memcpy(bounce_skb->cb, skb->cb, sizeof(skb->cb));
+		bounce_skb->dev = skb->dev;
+		skb_set_queue_mapping(bounce_skb, skb_get_queue_mapping(skb));
+		info = IEEE80211_SKB_CB(bounce_skb);
+
+		dev_kfree_skb_any(skb);
+		skb = bounce_skb;
+		*in_skb = bounce_skb;
+		meta->skb = skb;
+		meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
+		if (b43legacy_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
+			ring->current_slot = old_top_slot;
+			ring->used_slots = old_used_slots;
+			err = -EIO;
+			goto out_free_bounce;
+		}
+	}
+
+	op32_fill_descriptor(ring, desc, meta->dmaaddr,
+			     skb->len, 0, 1, 1);
+
+	wmb();	/* previous stuff MUST be done */
+	/* Now transfer the whole frame. */
+	op32_poke_tx(ring, next_slot(ring, slot));
+	return 0;
+
+out_free_bounce:
+	dev_kfree_skb_any(skb);
+out_unmap_hdr:
+	unmap_descbuffer(ring, meta_hdr->dmaaddr,
+			 sizeof(struct b43legacy_txhdr_fw3), 1);
+	return err;
+}
+
+static inline
+int should_inject_overflow(struct b43legacy_dmaring *ring)
+{
+#ifdef CONFIG_B43LEGACY_DEBUG
+	if (unlikely(b43legacy_debug(ring->dev,
+				     B43legacy_DBG_DMAOVERFLOW))) {
+		/* Check if we should inject another ringbuffer overflow
+		 * to test handling of this situation in the stack. */
+		unsigned long next_overflow;
+
+		next_overflow = ring->last_injected_overflow + HZ;
+		if (time_after(jiffies, next_overflow)) {
+			ring->last_injected_overflow = jiffies;
+			b43legacydbg(ring->dev->wl,
+			       "Injecting TX ring overflow on "
+			       "DMA controller %d\n", ring->index);
+			return 1;
+		}
+	}
+#endif /* CONFIG_B43LEGACY_DEBUG */
+	return 0;
+}
+
+int b43legacy_dma_tx(struct b43legacy_wldev *dev,
+		     struct sk_buff *skb)
+{
+	struct b43legacy_dmaring *ring;
+	int err = 0;
+
+	ring = priority_to_txring(dev, skb_get_queue_mapping(skb));
+	B43legacy_WARN_ON(!ring->tx);
+
+	if (unlikely(ring->stopped)) {
+		/* We get here only because of a bug in mac80211.
+		 * Because of a race, one packet may be queued after
+		 * the queue is stopped, thus we got called when we shouldn't.
+		 * For now, just refuse the transmit. */
+		if (b43legacy_debug(dev, B43legacy_DBG_DMAVERBOSE))
+			b43legacyerr(dev->wl, "Packet after queue stopped\n");
+		return -ENOSPC;
+	}
+
+	if (unlikely(WARN_ON(free_slots(ring) < SLOTS_PER_PACKET))) {
+		/* If we get here, we have a real error with the queue
+		 * full, but queues not stopped. */
+		b43legacyerr(dev->wl, "DMA queue overflow\n");
+		return -ENOSPC;
+	}
+
+	/* dma_tx_fragment might reallocate the skb, so invalidate pointers pointing
+	 * into the skb data or cb now. */
+	err = dma_tx_fragment(ring, &skb);
+	if (unlikely(err == -ENOKEY)) {
+		/* Drop this packet, as we don't have the encryption key
+		 * anymore and must not transmit it unencrypted. */
+		dev_kfree_skb_any(skb);
+		return 0;
+	}
+	if (unlikely(err)) {
+		b43legacyerr(dev->wl, "DMA tx mapping failure\n");
+		return err;
+	}
+	if ((free_slots(ring) < SLOTS_PER_PACKET) ||
+	    should_inject_overflow(ring)) {
+		/* This TX ring is full. */
+		unsigned int skb_mapping = skb_get_queue_mapping(skb);
+		ieee80211_stop_queue(dev->wl->hw, skb_mapping);
+		dev->wl->tx_queue_stopped[skb_mapping] = 1;
+		ring->stopped = true;
+		if (b43legacy_debug(dev, B43legacy_DBG_DMAVERBOSE))
+			b43legacydbg(dev->wl, "Stopped TX ring %d\n",
+			       ring->index);
+	}
+	return err;
+}
+
+void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
+				 const struct b43legacy_txstatus *status)
+{
+	struct b43legacy_dmaring *ring;
+	struct b43legacy_dmadesc_meta *meta;
+	int retry_limit;
+	int slot;
+	int firstused;
+
+	ring = parse_cookie(dev, status->cookie, &slot);
+	if (unlikely(!ring))
+		return;
+	B43legacy_WARN_ON(!ring->tx);
+
+	/* Sanity check: TX packets are processed in-order on one ring.
+	 * Check if the slot deduced from the cookie really is the first
+	 * used slot. */
+	firstused = ring->current_slot - ring->used_slots + 1;
+	if (firstused < 0)
+		firstused = ring->nr_slots + firstused;
+	if (unlikely(slot != firstused)) {
+		/* This possibly is a firmware bug and will result in
+		 * malfunction, memory leaks and/or stall of DMA functionality.
+		 */
+		b43legacydbg(dev->wl, "Out of order TX status report on DMA "
+			     "ring %d. Expected %d, but got %d\n",
+			     ring->index, firstused, slot);
+		return;
+	}
+
+	while (1) {
+		B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
+		op32_idx2desc(ring, slot, &meta);
+
+		if (meta->skb)
+			unmap_descbuffer(ring, meta->dmaaddr,
+					 meta->skb->len, 1);
+		else
+			unmap_descbuffer(ring, meta->dmaaddr,
+					 sizeof(struct b43legacy_txhdr_fw3),
+					 1);
+
+		if (meta->is_last_fragment) {
+			struct ieee80211_tx_info *info;
+			BUG_ON(!meta->skb);
+			info = IEEE80211_SKB_CB(meta->skb);
+
+			/* preserve the confiured retry limit before clearing the status
+			 * The xmit function has overwritten the rc's value with the actual
+			 * retry limit done by the hardware */
+			retry_limit = info->status.rates[0].count;
+			ieee80211_tx_info_clear_status(info);
+
+			if (status->acked)
+				info->flags |= IEEE80211_TX_STAT_ACK;
+
+			if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) {
+				/*
+				 * If the short retries (RTS, not data frame) have exceeded
+				 * the limit, the hw will not have tried the selected rate,
+				 * but will have used the fallback rate instead.
+				 * Don't let the rate control count attempts for the selected
+				 * rate in this case, otherwise the statistics will be off.
+				 */
+				info->status.rates[0].count = 0;
+				info->status.rates[1].count = status->frame_count;
+			} else {
+				if (status->frame_count > retry_limit) {
+					info->status.rates[0].count = retry_limit;
+					info->status.rates[1].count = status->frame_count -
+							retry_limit;
+
+				} else {
+					info->status.rates[0].count = status->frame_count;
+					info->status.rates[1].idx = -1;
+				}
+			}
+
+			/* Call back to inform the ieee80211 subsystem about the
+			 * status of the transmission.
+			 * Some fields of txstat are already filled in dma_tx().
+			 */
+			ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb);
+			/* skb is freed by ieee80211_tx_status_irqsafe() */
+			meta->skb = NULL;
+		} else {
+			/* No need to call free_descriptor_buffer here, as
+			 * this is only the txhdr, which is not allocated.
+			 */
+			B43legacy_WARN_ON(meta->skb != NULL);
+		}
+
+		/* Everything unmapped and free'd. So it's not used anymore. */
+		ring->used_slots--;
+
+		if (meta->is_last_fragment)
+			break;
+		slot = next_slot(ring, slot);
+	}
+	dev->stats.last_tx = jiffies;
+	if (ring->stopped) {
+		B43legacy_WARN_ON(free_slots(ring) < SLOTS_PER_PACKET);
+		ring->stopped = false;
+	}
+
+	if (dev->wl->tx_queue_stopped[ring->queue_prio]) {
+		dev->wl->tx_queue_stopped[ring->queue_prio] = 0;
+	} else {
+		/* If the driver queue is running wake the corresponding
+		 * mac80211 queue. */
+		ieee80211_wake_queue(dev->wl->hw, ring->queue_prio);
+		if (b43legacy_debug(dev, B43legacy_DBG_DMAVERBOSE))
+			b43legacydbg(dev->wl, "Woke up TX ring %d\n",
+				     ring->index);
+	}
+	/* Add work to the queue. */
+	ieee80211_queue_work(dev->wl->hw, &dev->wl->tx_work);
+}
+
+static void dma_rx(struct b43legacy_dmaring *ring,
+		   int *slot)
+{
+	struct b43legacy_dmadesc32 *desc;
+	struct b43legacy_dmadesc_meta *meta;
+	struct b43legacy_rxhdr_fw3 *rxhdr;
+	struct sk_buff *skb;
+	u16 len;
+	int err;
+	dma_addr_t dmaaddr;
+
+	desc = op32_idx2desc(ring, *slot, &meta);
+
+	sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize);
+	skb = meta->skb;
+
+	if (ring->index == 3) {
+		/* We received an xmit status. */
+		struct b43legacy_hwtxstatus *hw =
+				(struct b43legacy_hwtxstatus *)skb->data;
+		int i = 0;
+
+		while (hw->cookie == 0) {
+			if (i > 100)
+				break;
+			i++;
+			udelay(2);
+			barrier();
+		}
+		b43legacy_handle_hwtxstatus(ring->dev, hw);
+		/* recycle the descriptor buffer. */
+		sync_descbuffer_for_device(ring, meta->dmaaddr,
+					   ring->rx_buffersize);
+
+		return;
+	}
+	rxhdr = (struct b43legacy_rxhdr_fw3 *)skb->data;
+	len = le16_to_cpu(rxhdr->frame_len);
+	if (len == 0) {
+		int i = 0;
+
+		do {
+			udelay(2);
+			barrier();
+			len = le16_to_cpu(rxhdr->frame_len);
+		} while (len == 0 && i++ < 5);
+		if (unlikely(len == 0)) {
+			/* recycle the descriptor buffer. */
+			sync_descbuffer_for_device(ring, meta->dmaaddr,
+						   ring->rx_buffersize);
+			goto drop;
+		}
+	}
+	if (unlikely(len > ring->rx_buffersize)) {
+		/* The data did not fit into one descriptor buffer
+		 * and is split over multiple buffers.
+		 * This should never happen, as we try to allocate buffers
+		 * big enough. So simply ignore this packet.
+		 */
+		int cnt = 0;
+		s32 tmp = len;
+
+		while (1) {
+			desc = op32_idx2desc(ring, *slot, &meta);
+			/* recycle the descriptor buffer. */
+			sync_descbuffer_for_device(ring, meta->dmaaddr,
+						   ring->rx_buffersize);
+			*slot = next_slot(ring, *slot);
+			cnt++;
+			tmp -= ring->rx_buffersize;
+			if (tmp <= 0)
+				break;
+		}
+		b43legacyerr(ring->dev->wl, "DMA RX buffer too small "
+		       "(len: %u, buffer: %u, nr-dropped: %d)\n",
+		       len, ring->rx_buffersize, cnt);
+		goto drop;
+	}
+
+	dmaaddr = meta->dmaaddr;
+	err = setup_rx_descbuffer(ring, desc, meta, GFP_ATOMIC);
+	if (unlikely(err)) {
+		b43legacydbg(ring->dev->wl, "DMA RX: setup_rx_descbuffer()"
+			     " failed\n");
+		sync_descbuffer_for_device(ring, dmaaddr,
+					   ring->rx_buffersize);
+		goto drop;
+	}
+
+	unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0);
+	skb_put(skb, len + ring->frameoffset);
+	skb_pull(skb, ring->frameoffset);
+
+	b43legacy_rx(ring->dev, skb, rxhdr);
+drop:
+	return;
+}
+
+void b43legacy_dma_rx(struct b43legacy_dmaring *ring)
+{
+	int slot;
+	int current_slot;
+	int used_slots = 0;
+
+	B43legacy_WARN_ON(ring->tx);
+	current_slot = op32_get_current_rxslot(ring);
+	B43legacy_WARN_ON(!(current_slot >= 0 && current_slot <
+			   ring->nr_slots));
+
+	slot = ring->current_slot;
+	for (; slot != current_slot; slot = next_slot(ring, slot)) {
+		dma_rx(ring, &slot);
+		update_max_used_slots(ring, ++used_slots);
+	}
+	op32_set_current_rxslot(ring, slot);
+	ring->current_slot = slot;
+}
+
+static void b43legacy_dma_tx_suspend_ring(struct b43legacy_dmaring *ring)
+{
+	B43legacy_WARN_ON(!ring->tx);
+	op32_tx_suspend(ring);
+}
+
+static void b43legacy_dma_tx_resume_ring(struct b43legacy_dmaring *ring)
+{
+	B43legacy_WARN_ON(!ring->tx);
+	op32_tx_resume(ring);
+}
+
+void b43legacy_dma_tx_suspend(struct b43legacy_wldev *dev)
+{
+	b43legacy_power_saving_ctl_bits(dev, -1, 1);
+	b43legacy_dma_tx_suspend_ring(dev->dma.tx_ring0);
+	b43legacy_dma_tx_suspend_ring(dev->dma.tx_ring1);
+	b43legacy_dma_tx_suspend_ring(dev->dma.tx_ring2);
+	b43legacy_dma_tx_suspend_ring(dev->dma.tx_ring3);
+	b43legacy_dma_tx_suspend_ring(dev->dma.tx_ring4);
+	b43legacy_dma_tx_suspend_ring(dev->dma.tx_ring5);
+}
+
+void b43legacy_dma_tx_resume(struct b43legacy_wldev *dev)
+{
+	b43legacy_dma_tx_resume_ring(dev->dma.tx_ring5);
+	b43legacy_dma_tx_resume_ring(dev->dma.tx_ring4);
+	b43legacy_dma_tx_resume_ring(dev->dma.tx_ring3);
+	b43legacy_dma_tx_resume_ring(dev->dma.tx_ring2);
+	b43legacy_dma_tx_resume_ring(dev->dma.tx_ring1);
+	b43legacy_dma_tx_resume_ring(dev->dma.tx_ring0);
+	b43legacy_power_saving_ctl_bits(dev, -1, -1);
+}
diff --git a/drivers/net/wireless/broadcom/b43legacy/dma.h b/drivers/net/wireless/broadcom/b43legacy/dma.h
new file mode 100644
index 0000000..b5c1a51
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/dma.h
@@ -0,0 +1,232 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43legacy_DMA_H_
+#define B43legacy_DMA_H_
+
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/linkage.h>
+#include <linux/atomic.h>
+
+#include "b43legacy.h"
+
+
+/* DMA-Interrupt reasons. */
+#define B43legacy_DMAIRQ_FATALMASK	((1 << 10) | (1 << 11) | (1 << 12) \
+					 | (1 << 14) | (1 << 15))
+#define B43legacy_DMAIRQ_NONFATALMASK	(1 << 13)
+#define B43legacy_DMAIRQ_RX_DONE		(1 << 16)
+
+
+/*** 32-bit DMA Engine. ***/
+
+/* 32-bit DMA controller registers. */
+#define B43legacy_DMA32_TXCTL				0x00
+#define		B43legacy_DMA32_TXENABLE		0x00000001
+#define		B43legacy_DMA32_TXSUSPEND		0x00000002
+#define		B43legacy_DMA32_TXLOOPBACK		0x00000004
+#define		B43legacy_DMA32_TXFLUSH			0x00000010
+#define		B43legacy_DMA32_TXADDREXT_MASK		0x00030000
+#define		B43legacy_DMA32_TXADDREXT_SHIFT		16
+#define B43legacy_DMA32_TXRING				0x04
+#define B43legacy_DMA32_TXINDEX				0x08
+#define B43legacy_DMA32_TXSTATUS			0x0C
+#define		B43legacy_DMA32_TXDPTR			0x00000FFF
+#define		B43legacy_DMA32_TXSTATE			0x0000F000
+#define			B43legacy_DMA32_TXSTAT_DISABLED	0x00000000
+#define			B43legacy_DMA32_TXSTAT_ACTIVE	0x00001000
+#define			B43legacy_DMA32_TXSTAT_IDLEWAIT	0x00002000
+#define			B43legacy_DMA32_TXSTAT_STOPPED	0x00003000
+#define			B43legacy_DMA32_TXSTAT_SUSP	0x00004000
+#define		B43legacy_DMA32_TXERROR			0x000F0000
+#define			B43legacy_DMA32_TXERR_NOERR	0x00000000
+#define			B43legacy_DMA32_TXERR_PROT	0x00010000
+#define			B43legacy_DMA32_TXERR_UNDERRUN	0x00020000
+#define			B43legacy_DMA32_TXERR_BUFREAD	0x00030000
+#define			B43legacy_DMA32_TXERR_DESCREAD	0x00040000
+#define		B43legacy_DMA32_TXACTIVE		0xFFF00000
+#define B43legacy_DMA32_RXCTL				0x10
+#define		B43legacy_DMA32_RXENABLE		0x00000001
+#define		B43legacy_DMA32_RXFROFF_MASK		0x000000FE
+#define		B43legacy_DMA32_RXFROFF_SHIFT		1
+#define		B43legacy_DMA32_RXDIRECTFIFO		0x00000100
+#define		B43legacy_DMA32_RXADDREXT_MASK		0x00030000
+#define		B43legacy_DMA32_RXADDREXT_SHIFT		16
+#define B43legacy_DMA32_RXRING				0x14
+#define B43legacy_DMA32_RXINDEX				0x18
+#define B43legacy_DMA32_RXSTATUS			0x1C
+#define		B43legacy_DMA32_RXDPTR			0x00000FFF
+#define		B43legacy_DMA32_RXSTATE			0x0000F000
+#define			B43legacy_DMA32_RXSTAT_DISABLED	0x00000000
+#define			B43legacy_DMA32_RXSTAT_ACTIVE	0x00001000
+#define			B43legacy_DMA32_RXSTAT_IDLEWAIT	0x00002000
+#define			B43legacy_DMA32_RXSTAT_STOPPED	0x00003000
+#define		B43legacy_DMA32_RXERROR			0x000F0000
+#define			B43legacy_DMA32_RXERR_NOERR	0x00000000
+#define			B43legacy_DMA32_RXERR_PROT	0x00010000
+#define			B43legacy_DMA32_RXERR_OVERFLOW	0x00020000
+#define			B43legacy_DMA32_RXERR_BUFWRITE	0x00030000
+#define			B43legacy_DMA32_RXERR_DESCREAD	0x00040000
+#define		B43legacy_DMA32_RXACTIVE		0xFFF00000
+
+/* 32-bit DMA descriptor. */
+struct b43legacy_dmadesc32 {
+	__le32 control;
+	__le32 address;
+} __packed;
+#define B43legacy_DMA32_DCTL_BYTECNT		0x00001FFF
+#define B43legacy_DMA32_DCTL_ADDREXT_MASK	0x00030000
+#define B43legacy_DMA32_DCTL_ADDREXT_SHIFT	16
+#define B43legacy_DMA32_DCTL_DTABLEEND		0x10000000
+#define B43legacy_DMA32_DCTL_IRQ		0x20000000
+#define B43legacy_DMA32_DCTL_FRAMEEND		0x40000000
+#define B43legacy_DMA32_DCTL_FRAMESTART		0x80000000
+
+
+/* Misc DMA constants */
+#define B43legacy_DMA_RINGMEMSIZE	PAGE_SIZE
+#define B43legacy_DMA0_RX_FRAMEOFFSET	30
+#define B43legacy_DMA3_RX_FRAMEOFFSET	0
+
+
+/* DMA engine tuning knobs */
+#define B43legacy_TXRING_SLOTS		128
+#define B43legacy_RXRING_SLOTS		64
+#define B43legacy_DMA0_RX_BUFFERSIZE	(2304 + 100)
+#define B43legacy_DMA3_RX_BUFFERSIZE	16
+
+
+
+#ifdef CONFIG_B43LEGACY_DMA
+
+
+struct sk_buff;
+struct b43legacy_private;
+struct b43legacy_txstatus;
+
+
+struct b43legacy_dmadesc_meta {
+	/* The kernel DMA-able buffer. */
+	struct sk_buff *skb;
+	/* DMA base bus-address of the descriptor buffer. */
+	dma_addr_t dmaaddr;
+	/* ieee80211 TX status. Only used once per 802.11 frag. */
+	bool is_last_fragment;
+};
+
+enum b43legacy_dmatype {
+	B43legacy_DMA_30BIT = 30,
+	B43legacy_DMA_32BIT = 32,
+};
+
+struct b43legacy_dmaring {
+	/* Kernel virtual base address of the ring memory. */
+	void *descbase;
+	/* Meta data about all descriptors. */
+	struct b43legacy_dmadesc_meta *meta;
+	/* Cache of TX headers for each slot.
+	 * This is to avoid an allocation on each TX.
+	 * This is NULL for an RX ring.
+	 */
+	u8 *txhdr_cache;
+	/* (Unadjusted) DMA base bus-address of the ring memory. */
+	dma_addr_t dmabase;
+	/* Number of descriptor slots in the ring. */
+	int nr_slots;
+	/* Number of used descriptor slots. */
+	int used_slots;
+	/* Currently used slot in the ring. */
+	int current_slot;
+	/* Frameoffset in octets. */
+	u32 frameoffset;
+	/* Descriptor buffer size. */
+	u16 rx_buffersize;
+	/* The MMIO base register of the DMA controller. */
+	u16 mmio_base;
+	/* DMA controller index number (0-5). */
+	int index;
+	/* Boolean. Is this a TX ring? */
+	bool tx;
+	/* The type of DMA engine used. */
+	enum b43legacy_dmatype type;
+	/* Boolean. Is this ring stopped at ieee80211 level? */
+	bool stopped;
+	/* The QOS priority assigned to this ring. Only used for TX rings.
+	 * This is the mac80211 "queue" value. */
+	u8 queue_prio;
+	struct b43legacy_wldev *dev;
+#ifdef CONFIG_B43LEGACY_DEBUG
+	/* Maximum number of used slots. */
+	int max_used_slots;
+	/* Last time we injected a ring overflow. */
+	unsigned long last_injected_overflow;
+#endif /* CONFIG_B43LEGACY_DEBUG*/
+};
+
+
+static inline
+u32 b43legacy_dma_read(struct b43legacy_dmaring *ring,
+		       u16 offset)
+{
+	return b43legacy_read32(ring->dev, ring->mmio_base + offset);
+}
+
+static inline
+void b43legacy_dma_write(struct b43legacy_dmaring *ring,
+			 u16 offset, u32 value)
+{
+	b43legacy_write32(ring->dev, ring->mmio_base + offset, value);
+}
+
+
+int b43legacy_dma_init(struct b43legacy_wldev *dev);
+void b43legacy_dma_free(struct b43legacy_wldev *dev);
+
+void b43legacy_dma_tx_suspend(struct b43legacy_wldev *dev);
+void b43legacy_dma_tx_resume(struct b43legacy_wldev *dev);
+
+int b43legacy_dma_tx(struct b43legacy_wldev *dev,
+		     struct sk_buff *skb);
+void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
+				   const struct b43legacy_txstatus *status);
+
+void b43legacy_dma_rx(struct b43legacy_dmaring *ring);
+
+#else /* CONFIG_B43LEGACY_DMA */
+
+
+static inline
+int b43legacy_dma_init(struct b43legacy_wldev *dev)
+{
+	return 0;
+}
+static inline
+void b43legacy_dma_free(struct b43legacy_wldev *dev)
+{
+}
+static inline
+int b43legacy_dma_tx(struct b43legacy_wldev *dev,
+		     struct sk_buff *skb)
+{
+	return 0;
+}
+static inline
+void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
+				   const struct b43legacy_txstatus *status)
+{
+}
+static inline
+void b43legacy_dma_rx(struct b43legacy_dmaring *ring)
+{
+}
+static inline
+void b43legacy_dma_tx_suspend(struct b43legacy_wldev *dev)
+{
+}
+static inline
+void b43legacy_dma_tx_resume(struct b43legacy_wldev *dev)
+{
+}
+
+#endif /* CONFIG_B43LEGACY_DMA */
+#endif /* B43legacy_DMA_H_ */
diff --git a/drivers/net/wireless/broadcom/b43legacy/ilt.c b/drivers/net/wireless/broadcom/b43legacy/ilt.c
new file mode 100644
index 0000000..ee5682e
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/ilt.c
@@ -0,0 +1,336 @@
+/*
+
+  Broadcom B43legacy wireless driver
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+		     Stefano Brivio <stefano.brivio@polimi.it>
+		     Michael Buesch <m@bues.ch>
+		     Danny van Dyk <kugelfang@gentoo.org>
+		     Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+  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 "b43legacy.h"
+#include "ilt.h"
+#include "phy.h"
+
+
+/**** Initial Internal Lookup Tables ****/
+
+const u32 b43legacy_ilt_rotor[B43legacy_ILT_ROTOR_SIZE] = {
+	0xFEB93FFD, 0xFEC63FFD, /* 0 */
+	0xFED23FFD, 0xFEDF3FFD,
+	0xFEEC3FFE, 0xFEF83FFE,
+	0xFF053FFE, 0xFF113FFE,
+	0xFF1E3FFE, 0xFF2A3FFF, /* 8 */
+	0xFF373FFF, 0xFF443FFF,
+	0xFF503FFF, 0xFF5D3FFF,
+	0xFF693FFF, 0xFF763FFF,
+	0xFF824000, 0xFF8F4000, /* 16 */
+	0xFF9B4000, 0xFFA84000,
+	0xFFB54000, 0xFFC14000,
+	0xFFCE4000, 0xFFDA4000,
+	0xFFE74000, 0xFFF34000, /* 24 */
+	0x00004000, 0x000D4000,
+	0x00194000, 0x00264000,
+	0x00324000, 0x003F4000,
+	0x004B4000, 0x00584000, /* 32 */
+	0x00654000, 0x00714000,
+	0x007E4000, 0x008A3FFF,
+	0x00973FFF, 0x00A33FFF,
+	0x00B03FFF, 0x00BC3FFF, /* 40 */
+	0x00C93FFF, 0x00D63FFF,
+	0x00E23FFE, 0x00EF3FFE,
+	0x00FB3FFE, 0x01083FFE,
+	0x01143FFE, 0x01213FFD, /* 48 */
+	0x012E3FFD, 0x013A3FFD,
+	0x01473FFD,
+};
+
+const u32 b43legacy_ilt_retard[B43legacy_ILT_RETARD_SIZE] = {
+	0xDB93CB87, 0xD666CF64, /* 0 */
+	0xD1FDD358, 0xCDA6D826,
+	0xCA38DD9F, 0xC729E2B4,
+	0xC469E88E, 0xC26AEE2B,
+	0xC0DEF46C, 0xC073FA62, /* 8 */
+	0xC01D00D5, 0xC0760743,
+	0xC1560D1E, 0xC2E51369,
+	0xC4ED18FF, 0xC7AC1ED7,
+	0xCB2823B2, 0xCEFA28D9, /* 16 */
+	0xD2F62D3F, 0xD7BB3197,
+	0xDCE53568, 0xE1FE3875,
+	0xE7D13B35, 0xED663D35,
+	0xF39B3EC4, 0xF98E3FA7, /* 24 */
+	0x00004000, 0x06723FA7,
+	0x0C653EC4, 0x129A3D35,
+	0x182F3B35, 0x1E023875,
+	0x231B3568, 0x28453197, /* 32 */
+	0x2D0A2D3F, 0x310628D9,
+	0x34D823B2, 0x38541ED7,
+	0x3B1318FF, 0x3D1B1369,
+	0x3EAA0D1E, 0x3F8A0743, /* 40 */
+	0x3FE300D5, 0x3F8DFA62,
+	0x3F22F46C, 0x3D96EE2B,
+	0x3B97E88E, 0x38D7E2B4,
+	0x35C8DD9F, 0x325AD826, /* 48 */
+	0x2E03D358, 0x299ACF64,
+	0x246DCB87,
+};
+
+const u16 b43legacy_ilt_finefreqa[B43legacy_ILT_FINEFREQA_SIZE] = {
+	0x0082, 0x0082, 0x0102, 0x0182, /* 0 */
+	0x0202, 0x0282, 0x0302, 0x0382,
+	0x0402, 0x0482, 0x0502, 0x0582,
+	0x05E2, 0x0662, 0x06E2, 0x0762,
+	0x07E2, 0x0842, 0x08C2, 0x0942, /* 16 */
+	0x09C2, 0x0A22, 0x0AA2, 0x0B02,
+	0x0B82, 0x0BE2, 0x0C62, 0x0CC2,
+	0x0D42, 0x0DA2, 0x0E02, 0x0E62,
+	0x0EE2, 0x0F42, 0x0FA2, 0x1002, /* 32 */
+	0x1062, 0x10C2, 0x1122, 0x1182,
+	0x11E2, 0x1242, 0x12A2, 0x12E2,
+	0x1342, 0x13A2, 0x1402, 0x1442,
+	0x14A2, 0x14E2, 0x1542, 0x1582, /* 48 */
+	0x15E2, 0x1622, 0x1662, 0x16C1,
+	0x1701, 0x1741, 0x1781, 0x17E1,
+	0x1821, 0x1861, 0x18A1, 0x18E1,
+	0x1921, 0x1961, 0x19A1, 0x19E1, /* 64 */
+	0x1A21, 0x1A61, 0x1AA1, 0x1AC1,
+	0x1B01, 0x1B41, 0x1B81, 0x1BA1,
+	0x1BE1, 0x1C21, 0x1C41, 0x1C81,
+	0x1CA1, 0x1CE1, 0x1D01, 0x1D41, /* 80 */
+	0x1D61, 0x1DA1, 0x1DC1, 0x1E01,
+	0x1E21, 0x1E61, 0x1E81, 0x1EA1,
+	0x1EE1, 0x1F01, 0x1F21, 0x1F41,
+	0x1F81, 0x1FA1, 0x1FC1, 0x1FE1, /* 96 */
+	0x2001, 0x2041, 0x2061, 0x2081,
+	0x20A1, 0x20C1, 0x20E1, 0x2101,
+	0x2121, 0x2141, 0x2161, 0x2181,
+	0x21A1, 0x21C1, 0x21E1, 0x2201, /* 112 */
+	0x2221, 0x2241, 0x2261, 0x2281,
+	0x22A1, 0x22C1, 0x22C1, 0x22E1,
+	0x2301, 0x2321, 0x2341, 0x2361,
+	0x2361, 0x2381, 0x23A1, 0x23C1, /* 128 */
+	0x23E1, 0x23E1, 0x2401, 0x2421,
+	0x2441, 0x2441, 0x2461, 0x2481,
+	0x2481, 0x24A1, 0x24C1, 0x24C1,
+	0x24E1, 0x2501, 0x2501, 0x2521, /* 144 */
+	0x2541, 0x2541, 0x2561, 0x2561,
+	0x2581, 0x25A1, 0x25A1, 0x25C1,
+	0x25C1, 0x25E1, 0x2601, 0x2601,
+	0x2621, 0x2621, 0x2641, 0x2641, /* 160 */
+	0x2661, 0x2661, 0x2681, 0x2681,
+	0x26A1, 0x26A1, 0x26C1, 0x26C1,
+	0x26E1, 0x26E1, 0x2701, 0x2701,
+	0x2721, 0x2721, 0x2740, 0x2740, /* 176 */
+	0x2760, 0x2760, 0x2780, 0x2780,
+	0x2780, 0x27A0, 0x27A0, 0x27C0,
+	0x27C0, 0x27E0, 0x27E0, 0x27E0,
+	0x2800, 0x2800, 0x2820, 0x2820, /* 192 */
+	0x2820, 0x2840, 0x2840, 0x2840,
+	0x2860, 0x2860, 0x2880, 0x2880,
+	0x2880, 0x28A0, 0x28A0, 0x28A0,
+	0x28C0, 0x28C0, 0x28C0, 0x28E0, /* 208 */
+	0x28E0, 0x28E0, 0x2900, 0x2900,
+	0x2900, 0x2920, 0x2920, 0x2920,
+	0x2940, 0x2940, 0x2940, 0x2960,
+	0x2960, 0x2960, 0x2960, 0x2980, /* 224 */
+	0x2980, 0x2980, 0x29A0, 0x29A0,
+	0x29A0, 0x29A0, 0x29C0, 0x29C0,
+	0x29C0, 0x29E0, 0x29E0, 0x29E0,
+	0x29E0, 0x2A00, 0x2A00, 0x2A00, /* 240 */
+	0x2A00, 0x2A20, 0x2A20, 0x2A20,
+	0x2A20, 0x2A40, 0x2A40, 0x2A40,
+	0x2A40, 0x2A60, 0x2A60, 0x2A60,
+};
+
+const u16 b43legacy_ilt_finefreqg[B43legacy_ILT_FINEFREQG_SIZE] = {
+	0x0089, 0x02E9, 0x0409, 0x04E9, /* 0 */
+	0x05A9, 0x0669, 0x0709, 0x0789,
+	0x0829, 0x08A9, 0x0929, 0x0989,
+	0x0A09, 0x0A69, 0x0AC9, 0x0B29,
+	0x0BA9, 0x0BE9, 0x0C49, 0x0CA9, /* 16 */
+	0x0D09, 0x0D69, 0x0DA9, 0x0E09,
+	0x0E69, 0x0EA9, 0x0F09, 0x0F49,
+	0x0FA9, 0x0FE9, 0x1029, 0x1089,
+	0x10C9, 0x1109, 0x1169, 0x11A9, /* 32 */
+	0x11E9, 0x1229, 0x1289, 0x12C9,
+	0x1309, 0x1349, 0x1389, 0x13C9,
+	0x1409, 0x1449, 0x14A9, 0x14E9,
+	0x1529, 0x1569, 0x15A9, 0x15E9, /* 48 */
+	0x1629, 0x1669, 0x16A9, 0x16E8,
+	0x1728, 0x1768, 0x17A8, 0x17E8,
+	0x1828, 0x1868, 0x18A8, 0x18E8,
+	0x1928, 0x1968, 0x19A8, 0x19E8, /* 64 */
+	0x1A28, 0x1A68, 0x1AA8, 0x1AE8,
+	0x1B28, 0x1B68, 0x1BA8, 0x1BE8,
+	0x1C28, 0x1C68, 0x1CA8, 0x1CE8,
+	0x1D28, 0x1D68, 0x1DC8, 0x1E08, /* 80 */
+	0x1E48, 0x1E88, 0x1EC8, 0x1F08,
+	0x1F48, 0x1F88, 0x1FE8, 0x2028,
+	0x2068, 0x20A8, 0x2108, 0x2148,
+	0x2188, 0x21C8, 0x2228, 0x2268, /* 96 */
+	0x22C8, 0x2308, 0x2348, 0x23A8,
+	0x23E8, 0x2448, 0x24A8, 0x24E8,
+	0x2548, 0x25A8, 0x2608, 0x2668,
+	0x26C8, 0x2728, 0x2787, 0x27E7, /* 112 */
+	0x2847, 0x28C7, 0x2947, 0x29A7,
+	0x2A27, 0x2AC7, 0x2B47, 0x2BE7,
+	0x2CA7, 0x2D67, 0x2E47, 0x2F67,
+	0x3247, 0x3526, 0x3646, 0x3726, /* 128 */
+	0x3806, 0x38A6, 0x3946, 0x39E6,
+	0x3A66, 0x3AE6, 0x3B66, 0x3BC6,
+	0x3C45, 0x3CA5, 0x3D05, 0x3D85,
+	0x3DE5, 0x3E45, 0x3EA5, 0x3EE5, /* 144 */
+	0x3F45, 0x3FA5, 0x4005, 0x4045,
+	0x40A5, 0x40E5, 0x4145, 0x4185,
+	0x41E5, 0x4225, 0x4265, 0x42C5,
+	0x4305, 0x4345, 0x43A5, 0x43E5, /* 160 */
+	0x4424, 0x4464, 0x44C4, 0x4504,
+	0x4544, 0x4584, 0x45C4, 0x4604,
+	0x4644, 0x46A4, 0x46E4, 0x4724,
+	0x4764, 0x47A4, 0x47E4, 0x4824, /* 176 */
+	0x4864, 0x48A4, 0x48E4, 0x4924,
+	0x4964, 0x49A4, 0x49E4, 0x4A24,
+	0x4A64, 0x4AA4, 0x4AE4, 0x4B23,
+	0x4B63, 0x4BA3, 0x4BE3, 0x4C23, /* 192 */
+	0x4C63, 0x4CA3, 0x4CE3, 0x4D23,
+	0x4D63, 0x4DA3, 0x4DE3, 0x4E23,
+	0x4E63, 0x4EA3, 0x4EE3, 0x4F23,
+	0x4F63, 0x4FC3, 0x5003, 0x5043, /* 208 */
+	0x5083, 0x50C3, 0x5103, 0x5143,
+	0x5183, 0x51E2, 0x5222, 0x5262,
+	0x52A2, 0x52E2, 0x5342, 0x5382,
+	0x53C2, 0x5402, 0x5462, 0x54A2, /* 224 */
+	0x5502, 0x5542, 0x55A2, 0x55E2,
+	0x5642, 0x5682, 0x56E2, 0x5722,
+	0x5782, 0x57E1, 0x5841, 0x58A1,
+	0x5901, 0x5961, 0x59C1, 0x5A21, /* 240 */
+	0x5AA1, 0x5B01, 0x5B81, 0x5BE1,
+	0x5C61, 0x5D01, 0x5D80, 0x5E20,
+	0x5EE0, 0x5FA0, 0x6080, 0x61C0,
+};
+
+const u16 b43legacy_ilt_noisea2[B43legacy_ILT_NOISEA2_SIZE] = {
+	0x0001, 0x0001, 0x0001, 0xFFFE,
+	0xFFFE, 0x3FFF, 0x1000, 0x0393,
+};
+
+const u16 b43legacy_ilt_noisea3[B43legacy_ILT_NOISEA3_SIZE] = {
+	0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
+	0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
+};
+
+const u16 b43legacy_ilt_noiseg1[B43legacy_ILT_NOISEG1_SIZE] = {
+	0x013C, 0x01F5, 0x031A, 0x0631,
+	0x0001, 0x0001, 0x0001, 0x0001,
+};
+
+const u16 b43legacy_ilt_noiseg2[B43legacy_ILT_NOISEG2_SIZE] = {
+	0x5484, 0x3C40, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+const u16 b43legacy_ilt_noisescaleg1[B43legacy_ILT_NOISESCALEG_SIZE] = {
+	0x6C77, 0x5162, 0x3B40, 0x3335, /* 0 */
+	0x2F2D, 0x2A2A, 0x2527, 0x1F21,
+	0x1A1D, 0x1719, 0x1616, 0x1414,
+	0x1414, 0x1400, 0x1414, 0x1614,
+	0x1716, 0x1A19, 0x1F1D, 0x2521, /* 16 */
+	0x2A27, 0x2F2A, 0x332D, 0x3B35,
+	0x5140, 0x6C62, 0x0077,
+};
+
+const u16 b43legacy_ilt_noisescaleg2[B43legacy_ILT_NOISESCALEG_SIZE] = {
+	0xD8DD, 0xCBD4, 0xBCC0, 0XB6B7, /* 0 */
+	0xB2B0, 0xADAD, 0xA7A9, 0x9FA1,
+	0x969B, 0x9195, 0x8F8F, 0x8A8A,
+	0x8A8A, 0x8A00, 0x8A8A, 0x8F8A,
+	0x918F, 0x9695, 0x9F9B, 0xA7A1, /* 16 */
+	0xADA9, 0xB2AD, 0xB6B0, 0xBCB7,
+	0xCBC0, 0xD8D4, 0x00DD,
+};
+
+const u16 b43legacy_ilt_noisescaleg3[B43legacy_ILT_NOISESCALEG_SIZE] = {
+	0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 0 */
+	0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
+	0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
+	0xA4A4, 0xA400, 0xA4A4, 0xA4A4,
+	0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 16 */
+	0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
+	0xA4A4, 0xA4A4, 0x00A4,
+};
+
+const u16 b43legacy_ilt_sigmasqr1[B43legacy_ILT_SIGMASQR_SIZE] = {
+	0x007A, 0x0075, 0x0071, 0x006C, /* 0 */
+	0x0067, 0x0063, 0x005E, 0x0059,
+	0x0054, 0x0050, 0x004B, 0x0046,
+	0x0042, 0x003D, 0x003D, 0x003D,
+	0x003D, 0x003D, 0x003D, 0x003D, /* 16 */
+	0x003D, 0x003D, 0x003D, 0x003D,
+	0x003D, 0x003D, 0x0000, 0x003D,
+	0x003D, 0x003D, 0x003D, 0x003D,
+	0x003D, 0x003D, 0x003D, 0x003D, /* 32 */
+	0x003D, 0x003D, 0x003D, 0x003D,
+	0x0042, 0x0046, 0x004B, 0x0050,
+	0x0054, 0x0059, 0x005E, 0x0063,
+	0x0067, 0x006C, 0x0071, 0x0075, /* 48 */
+	0x007A,
+};
+
+const u16 b43legacy_ilt_sigmasqr2[B43legacy_ILT_SIGMASQR_SIZE] = {
+	0x00DE, 0x00DC, 0x00DA, 0x00D8, /* 0 */
+	0x00D6, 0x00D4, 0x00D2, 0x00CF,
+	0x00CD, 0x00CA, 0x00C7, 0x00C4,
+	0x00C1, 0x00BE, 0x00BE, 0x00BE,
+	0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 16 */
+	0x00BE, 0x00BE, 0x00BE, 0x00BE,
+	0x00BE, 0x00BE, 0x0000, 0x00BE,
+	0x00BE, 0x00BE, 0x00BE, 0x00BE,
+	0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 32 */
+	0x00BE, 0x00BE, 0x00BE, 0x00BE,
+	0x00C1, 0x00C4, 0x00C7, 0x00CA,
+	0x00CD, 0x00CF, 0x00D2, 0x00D4,
+	0x00D6, 0x00D8, 0x00DA, 0x00DC, /* 48 */
+	0x00DE,
+};
+
+/**** Helper functions to access the device Internal Lookup Tables ****/
+
+void b43legacy_ilt_write(struct b43legacy_wldev *dev, u16 offset, u16 val)
+{
+	b43legacy_phy_write(dev, B43legacy_PHY_ILT_G_CTRL, offset);
+	mmiowb();
+	b43legacy_phy_write(dev, B43legacy_PHY_ILT_G_DATA1, val);
+}
+
+void b43legacy_ilt_write32(struct b43legacy_wldev *dev, u16 offset, u32 val)
+{
+	b43legacy_phy_write(dev, B43legacy_PHY_ILT_G_CTRL, offset);
+	mmiowb();
+	b43legacy_phy_write(dev, B43legacy_PHY_ILT_G_DATA2,
+			    (val & 0xFFFF0000) >> 16);
+	b43legacy_phy_write(dev, B43legacy_PHY_ILT_G_DATA1,
+			    val & 0x0000FFFF);
+}
+
+u16 b43legacy_ilt_read(struct b43legacy_wldev *dev, u16 offset)
+{
+	b43legacy_phy_write(dev, B43legacy_PHY_ILT_G_CTRL, offset);
+	return b43legacy_phy_read(dev, B43legacy_PHY_ILT_G_DATA1);
+}
diff --git a/drivers/net/wireless/broadcom/b43legacy/ilt.h b/drivers/net/wireless/broadcom/b43legacy/ilt.h
new file mode 100644
index 0000000..ce7a61e
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/ilt.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43legacy_ILT_H_
+#define B43legacy_ILT_H_
+
+#define B43legacy_ILT_ROTOR_SIZE	53
+extern const u32 b43legacy_ilt_rotor[B43legacy_ILT_ROTOR_SIZE];
+#define B43legacy_ILT_RETARD_SIZE	53
+extern const u32 b43legacy_ilt_retard[B43legacy_ILT_RETARD_SIZE];
+#define B43legacy_ILT_FINEFREQA_SIZE	256
+extern const u16 b43legacy_ilt_finefreqa[B43legacy_ILT_FINEFREQA_SIZE];
+#define B43legacy_ILT_FINEFREQG_SIZE	256
+extern const u16 b43legacy_ilt_finefreqg[B43legacy_ILT_FINEFREQG_SIZE];
+#define B43legacy_ILT_NOISEA2_SIZE	8
+extern const u16 b43legacy_ilt_noisea2[B43legacy_ILT_NOISEA2_SIZE];
+#define B43legacy_ILT_NOISEA3_SIZE	8
+extern const u16 b43legacy_ilt_noisea3[B43legacy_ILT_NOISEA3_SIZE];
+#define B43legacy_ILT_NOISEG1_SIZE	8
+extern const u16 b43legacy_ilt_noiseg1[B43legacy_ILT_NOISEG1_SIZE];
+#define B43legacy_ILT_NOISEG2_SIZE	8
+extern const u16 b43legacy_ilt_noiseg2[B43legacy_ILT_NOISEG2_SIZE];
+#define B43legacy_ILT_NOISESCALEG_SIZE	27
+extern const u16 b43legacy_ilt_noisescaleg1[B43legacy_ILT_NOISESCALEG_SIZE];
+extern const u16 b43legacy_ilt_noisescaleg2[B43legacy_ILT_NOISESCALEG_SIZE];
+extern const u16 b43legacy_ilt_noisescaleg3[B43legacy_ILT_NOISESCALEG_SIZE];
+#define B43legacy_ILT_SIGMASQR_SIZE	53
+extern const u16 b43legacy_ilt_sigmasqr1[B43legacy_ILT_SIGMASQR_SIZE];
+extern const u16 b43legacy_ilt_sigmasqr2[B43legacy_ILT_SIGMASQR_SIZE];
+
+
+void b43legacy_ilt_write(struct b43legacy_wldev *dev, u16 offset, u16 val);
+void b43legacy_ilt_write32(struct b43legacy_wldev *dev, u16 offset,
+			   u32 val);
+u16 b43legacy_ilt_read(struct b43legacy_wldev *dev, u16 offset);
+
+#endif /* B43legacy_ILT_H_ */
diff --git a/drivers/net/wireless/broadcom/b43legacy/leds.c b/drivers/net/wireless/broadcom/b43legacy/leds.c
new file mode 100644
index 0000000..bc92211
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/leds.c
@@ -0,0 +1,243 @@
+/*
+
+  Broadcom B43 wireless driver
+  LED control
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+  Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
+  Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
+  Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
+  Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+  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 "b43legacy.h"
+#include "leds.h"
+#include "rfkill.h"
+
+
+static void b43legacy_led_turn_on(struct b43legacy_wldev *dev, u8 led_index,
+			    bool activelow)
+{
+	struct b43legacy_wl *wl = dev->wl;
+	unsigned long flags;
+	u16 ctl;
+
+	spin_lock_irqsave(&wl->leds_lock, flags);
+	ctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
+	if (activelow)
+		ctl &= ~(1 << led_index);
+	else
+		ctl |= (1 << led_index);
+	b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ctl);
+	spin_unlock_irqrestore(&wl->leds_lock, flags);
+}
+
+static void b43legacy_led_turn_off(struct b43legacy_wldev *dev, u8 led_index,
+			     bool activelow)
+{
+	struct b43legacy_wl *wl = dev->wl;
+	unsigned long flags;
+	u16 ctl;
+
+	spin_lock_irqsave(&wl->leds_lock, flags);
+	ctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
+	if (activelow)
+		ctl |= (1 << led_index);
+	else
+		ctl &= ~(1 << led_index);
+	b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ctl);
+	spin_unlock_irqrestore(&wl->leds_lock, flags);
+}
+
+/* Callback from the LED subsystem. */
+static void b43legacy_led_brightness_set(struct led_classdev *led_dev,
+				   enum led_brightness brightness)
+{
+	struct b43legacy_led *led = container_of(led_dev, struct b43legacy_led,
+				    led_dev);
+	struct b43legacy_wldev *dev = led->dev;
+	bool radio_enabled;
+
+	/* Checking the radio-enabled status here is slightly racy,
+	 * but we want to avoid the locking overhead and we don't care
+	 * whether the LED has the wrong state for a second. */
+	radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable);
+
+	if (brightness == LED_OFF || !radio_enabled)
+		b43legacy_led_turn_off(dev, led->index, led->activelow);
+	else
+		b43legacy_led_turn_on(dev, led->index, led->activelow);
+}
+
+static int b43legacy_register_led(struct b43legacy_wldev *dev,
+				  struct b43legacy_led *led,
+				  const char *name,
+				  const char *default_trigger,
+				  u8 led_index, bool activelow)
+{
+	int err;
+
+	b43legacy_led_turn_off(dev, led_index, activelow);
+	if (led->dev)
+		return -EEXIST;
+	if (!default_trigger)
+		return -EINVAL;
+	led->dev = dev;
+	led->index = led_index;
+	led->activelow = activelow;
+	strlcpy(led->name, name, sizeof(led->name));
+
+	led->led_dev.name = led->name;
+	led->led_dev.default_trigger = default_trigger;
+	led->led_dev.brightness_set = b43legacy_led_brightness_set;
+
+	err = led_classdev_register(dev->dev->dev, &led->led_dev);
+	if (err) {
+		b43legacywarn(dev->wl, "LEDs: Failed to register %s\n", name);
+		led->dev = NULL;
+		return err;
+	}
+	return 0;
+}
+
+static void b43legacy_unregister_led(struct b43legacy_led *led)
+{
+	if (!led->dev)
+		return;
+	led_classdev_unregister(&led->led_dev);
+	b43legacy_led_turn_off(led->dev, led->index, led->activelow);
+	led->dev = NULL;
+}
+
+static void b43legacy_map_led(struct b43legacy_wldev *dev,
+			u8 led_index,
+			enum b43legacy_led_behaviour behaviour,
+			bool activelow)
+{
+	struct ieee80211_hw *hw = dev->wl->hw;
+	char name[B43legacy_LED_MAX_NAME_LEN + 1];
+
+	/* Map the b43 specific LED behaviour value to the
+	 * generic LED triggers. */
+	switch (behaviour) {
+	case B43legacy_LED_INACTIVE:
+		break;
+	case B43legacy_LED_OFF:
+		b43legacy_led_turn_off(dev, led_index, activelow);
+		break;
+	case B43legacy_LED_ON:
+		b43legacy_led_turn_on(dev, led_index, activelow);
+		break;
+	case B43legacy_LED_ACTIVITY:
+	case B43legacy_LED_TRANSFER:
+	case B43legacy_LED_APTRANSFER:
+		snprintf(name, sizeof(name),
+			 "b43legacy-%s::tx", wiphy_name(hw->wiphy));
+		b43legacy_register_led(dev, &dev->led_tx, name,
+				 ieee80211_get_tx_led_name(hw),
+				 led_index, activelow);
+		snprintf(name, sizeof(name),
+			 "b43legacy-%s::rx", wiphy_name(hw->wiphy));
+		b43legacy_register_led(dev, &dev->led_rx, name,
+				 ieee80211_get_rx_led_name(hw),
+				 led_index, activelow);
+		break;
+	case B43legacy_LED_RADIO_ALL:
+	case B43legacy_LED_RADIO_A:
+	case B43legacy_LED_RADIO_B:
+	case B43legacy_LED_MODE_BG:
+		snprintf(name, sizeof(name),
+			 "b43legacy-%s::radio", wiphy_name(hw->wiphy));
+		b43legacy_register_led(dev, &dev->led_radio, name,
+				 ieee80211_get_radio_led_name(hw),
+				 led_index, activelow);
+		/* Sync the RF-kill LED state with radio and switch states. */
+		if (dev->phy.radio_on && b43legacy_is_hw_radio_enabled(dev))
+			b43legacy_led_turn_on(dev, led_index, activelow);
+		break;
+	case B43legacy_LED_WEIRD:
+	case B43legacy_LED_ASSOC:
+		snprintf(name, sizeof(name),
+			 "b43legacy-%s::assoc", wiphy_name(hw->wiphy));
+		b43legacy_register_led(dev, &dev->led_assoc, name,
+				 ieee80211_get_assoc_led_name(hw),
+				 led_index, activelow);
+		break;
+	default:
+		b43legacywarn(dev->wl, "LEDs: Unknown behaviour 0x%02X\n",
+			behaviour);
+		break;
+	}
+}
+
+void b43legacy_leds_init(struct b43legacy_wldev *dev)
+{
+	struct ssb_bus *bus = dev->dev->bus;
+	u8 sprom[4];
+	int i;
+	enum b43legacy_led_behaviour behaviour;
+	bool activelow;
+
+	sprom[0] = bus->sprom.gpio0;
+	sprom[1] = bus->sprom.gpio1;
+	sprom[2] = bus->sprom.gpio2;
+	sprom[3] = bus->sprom.gpio3;
+
+	for (i = 0; i < 4; i++) {
+		if (sprom[i] == 0xFF) {
+			/* There is no LED information in the SPROM
+			 * for this LED. Hardcode it here. */
+			activelow = false;
+			switch (i) {
+			case 0:
+				behaviour = B43legacy_LED_ACTIVITY;
+				activelow = true;
+				if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ)
+					behaviour = B43legacy_LED_RADIO_ALL;
+				break;
+			case 1:
+				behaviour = B43legacy_LED_RADIO_B;
+				if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK)
+					behaviour = B43legacy_LED_ASSOC;
+				break;
+			case 2:
+				behaviour = B43legacy_LED_RADIO_A;
+				break;
+			case 3:
+				behaviour = B43legacy_LED_OFF;
+				break;
+			default:
+				B43legacy_WARN_ON(1);
+				return;
+			}
+		} else {
+			behaviour = sprom[i] & B43legacy_LED_BEHAVIOUR;
+			activelow = !!(sprom[i] & B43legacy_LED_ACTIVELOW);
+		}
+		b43legacy_map_led(dev, i, behaviour, activelow);
+	}
+}
+
+void b43legacy_leds_exit(struct b43legacy_wldev *dev)
+{
+	b43legacy_unregister_led(&dev->led_tx);
+	b43legacy_unregister_led(&dev->led_rx);
+	b43legacy_unregister_led(&dev->led_assoc);
+	b43legacy_unregister_led(&dev->led_radio);
+}
diff --git a/drivers/net/wireless/broadcom/b43legacy/leds.h b/drivers/net/wireless/broadcom/b43legacy/leds.h
new file mode 100644
index 0000000..389ae06
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/leds.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43legacy_LEDS_H_
+#define B43legacy_LEDS_H_
+
+struct b43legacy_wldev;
+
+#ifdef CONFIG_B43LEGACY_LEDS
+
+#include <linux/types.h>
+#include <linux/leds.h>
+
+
+#define B43legacy_LED_MAX_NAME_LEN	31
+
+struct b43legacy_led {
+	struct b43legacy_wldev *dev;
+	/* The LED class device */
+	struct led_classdev led_dev;
+	/* The index number of the LED. */
+	u8 index;
+	/* If activelow is true, the LED is ON if the
+	 * bit is switched off. */
+	bool activelow;
+	/* The unique name string for this LED device. */
+	char name[B43legacy_LED_MAX_NAME_LEN + 1];
+};
+
+#define B43legacy_LED_BEHAVIOUR		0x7F
+#define B43legacy_LED_ACTIVELOW		0x80
+/* LED behaviour values */
+enum b43legacy_led_behaviour {
+	B43legacy_LED_OFF,
+	B43legacy_LED_ON,
+	B43legacy_LED_ACTIVITY,
+	B43legacy_LED_RADIO_ALL,
+	B43legacy_LED_RADIO_A,
+	B43legacy_LED_RADIO_B,
+	B43legacy_LED_MODE_BG,
+	B43legacy_LED_TRANSFER,
+	B43legacy_LED_APTRANSFER,
+	B43legacy_LED_WEIRD,
+	B43legacy_LED_ASSOC,
+	B43legacy_LED_INACTIVE,
+};
+
+void b43legacy_leds_init(struct b43legacy_wldev *dev);
+void b43legacy_leds_exit(struct b43legacy_wldev *dev);
+
+#else /* CONFIG_B43LEGACY_LEDS */
+/* LED support disabled */
+
+struct b43legacy_led {
+	/* empty */
+};
+
+static inline void b43legacy_leds_init(struct b43legacy_wldev *dev)
+{
+}
+static inline void b43legacy_leds_exit(struct b43legacy_wldev *dev)
+{
+}
+#endif /* CONFIG_B43LEGACY_LEDS */
+
+#endif /* B43legacy_LEDS_H_ */
diff --git a/drivers/net/wireless/broadcom/b43legacy/main.c b/drivers/net/wireless/broadcom/b43legacy/main.c
new file mode 100644
index 0000000..55f4119
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/main.c
@@ -0,0 +1,4066 @@
+/*
+ *
+ *  Broadcom B43legacy wireless driver
+ *
+ *  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>
+ *  Copyright (c) 2005-2008 Stefano Brivio <stefano.brivio@polimi.it>
+ *  Copyright (c) 2005, 2006 Michael Buesch <m@bues.ch>
+ *  Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
+ *  Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
+ *  Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *  Some parts of the code in this file are derived from the ipw2200
+ *  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+
+ *  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/delay.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/if_arp.h>
+#include <linux/etherdevice.h>
+#include <linux/firmware.h>
+#include <linux/workqueue.h>
+#include <linux/sched/signal.h>
+#include <linux/skbuff.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <net/dst.h>
+#include <asm/unaligned.h>
+
+#include "b43legacy.h"
+#include "main.h"
+#include "debugfs.h"
+#include "phy.h"
+#include "dma.h"
+#include "pio.h"
+#include "sysfs.h"
+#include "xmit.h"
+#include "radio.h"
+
+
+MODULE_DESCRIPTION("Broadcom B43legacy wireless driver");
+MODULE_AUTHOR("Martin Langer");
+MODULE_AUTHOR("Stefano Brivio");
+MODULE_AUTHOR("Michael Buesch");
+MODULE_LICENSE("GPL");
+
+MODULE_FIRMWARE("b43legacy/ucode2.fw");
+MODULE_FIRMWARE("b43legacy/ucode4.fw");
+
+#if defined(CONFIG_B43LEGACY_DMA) && defined(CONFIG_B43LEGACY_PIO)
+static int modparam_pio;
+module_param_named(pio, modparam_pio, int, 0444);
+MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode");
+#elif defined(CONFIG_B43LEGACY_DMA)
+# define modparam_pio	0
+#elif defined(CONFIG_B43LEGACY_PIO)
+# define modparam_pio	1
+#endif
+
+static int modparam_bad_frames_preempt;
+module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
+MODULE_PARM_DESC(bad_frames_preempt, "enable(1) / disable(0) Bad Frames"
+		 " Preemption");
+
+static char modparam_fwpostfix[16];
+module_param_string(fwpostfix, modparam_fwpostfix, 16, 0444);
+MODULE_PARM_DESC(fwpostfix, "Postfix for the firmware files to load.");
+
+/* The following table supports BCM4301, BCM4303 and BCM4306/2 devices. */
+static const struct ssb_device_id b43legacy_ssb_tbl[] = {
+	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 2),
+	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 4),
+	{},
+};
+MODULE_DEVICE_TABLE(ssb, b43legacy_ssb_tbl);
+
+
+/* Channel and ratetables are shared for all devices.
+ * They can't be const, because ieee80211 puts some precalculated
+ * data in there. This data is the same for all devices, so we don't
+ * get concurrency issues */
+#define RATETAB_ENT(_rateid, _flags) \
+	{								\
+		.bitrate	= B43legacy_RATE_TO_100KBPS(_rateid),	\
+		.hw_value	= (_rateid),				\
+		.flags		= (_flags),				\
+	}
+/*
+ * NOTE: When changing this, sync with xmit.c's
+ *	 b43legacy_plcp_get_bitrate_idx_* functions!
+ */
+static struct ieee80211_rate __b43legacy_ratetable[] = {
+	RATETAB_ENT(B43legacy_CCK_RATE_1MB, 0),
+	RATETAB_ENT(B43legacy_CCK_RATE_2MB, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATETAB_ENT(B43legacy_CCK_RATE_5MB, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATETAB_ENT(B43legacy_CCK_RATE_11MB, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATETAB_ENT(B43legacy_OFDM_RATE_6MB, 0),
+	RATETAB_ENT(B43legacy_OFDM_RATE_9MB, 0),
+	RATETAB_ENT(B43legacy_OFDM_RATE_12MB, 0),
+	RATETAB_ENT(B43legacy_OFDM_RATE_18MB, 0),
+	RATETAB_ENT(B43legacy_OFDM_RATE_24MB, 0),
+	RATETAB_ENT(B43legacy_OFDM_RATE_36MB, 0),
+	RATETAB_ENT(B43legacy_OFDM_RATE_48MB, 0),
+	RATETAB_ENT(B43legacy_OFDM_RATE_54MB, 0),
+};
+#define b43legacy_b_ratetable		(__b43legacy_ratetable + 0)
+#define b43legacy_b_ratetable_size	4
+#define b43legacy_g_ratetable		(__b43legacy_ratetable + 0)
+#define b43legacy_g_ratetable_size	12
+
+#define CHANTAB_ENT(_chanid, _freq) \
+	{							\
+		.center_freq	= (_freq),			\
+		.hw_value	= (_chanid),			\
+	}
+static struct ieee80211_channel b43legacy_bg_chantable[] = {
+	CHANTAB_ENT(1, 2412),
+	CHANTAB_ENT(2, 2417),
+	CHANTAB_ENT(3, 2422),
+	CHANTAB_ENT(4, 2427),
+	CHANTAB_ENT(5, 2432),
+	CHANTAB_ENT(6, 2437),
+	CHANTAB_ENT(7, 2442),
+	CHANTAB_ENT(8, 2447),
+	CHANTAB_ENT(9, 2452),
+	CHANTAB_ENT(10, 2457),
+	CHANTAB_ENT(11, 2462),
+	CHANTAB_ENT(12, 2467),
+	CHANTAB_ENT(13, 2472),
+	CHANTAB_ENT(14, 2484),
+};
+
+static struct ieee80211_supported_band b43legacy_band_2GHz_BPHY = {
+	.channels = b43legacy_bg_chantable,
+	.n_channels = ARRAY_SIZE(b43legacy_bg_chantable),
+	.bitrates = b43legacy_b_ratetable,
+	.n_bitrates = b43legacy_b_ratetable_size,
+};
+
+static struct ieee80211_supported_band b43legacy_band_2GHz_GPHY = {
+	.channels = b43legacy_bg_chantable,
+	.n_channels = ARRAY_SIZE(b43legacy_bg_chantable),
+	.bitrates = b43legacy_g_ratetable,
+	.n_bitrates = b43legacy_g_ratetable_size,
+};
+
+static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev);
+static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev);
+static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev);
+static int b43legacy_wireless_core_start(struct b43legacy_wldev *dev);
+
+
+static int b43legacy_ratelimit(struct b43legacy_wl *wl)
+{
+	if (!wl || !wl->current_dev)
+		return 1;
+	if (b43legacy_status(wl->current_dev) < B43legacy_STAT_STARTED)
+		return 1;
+	/* We are up and running.
+	 * Ratelimit the messages to avoid DoS over the net. */
+	return net_ratelimit();
+}
+
+void b43legacyinfo(struct b43legacy_wl *wl, const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+
+	if (!b43legacy_ratelimit(wl))
+		return;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	printk(KERN_INFO "b43legacy-%s: %pV",
+	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
+	va_end(args);
+}
+
+void b43legacyerr(struct b43legacy_wl *wl, const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+
+	if (!b43legacy_ratelimit(wl))
+		return;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	printk(KERN_ERR "b43legacy-%s ERROR: %pV",
+	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
+	va_end(args);
+}
+
+void b43legacywarn(struct b43legacy_wl *wl, const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+
+	if (!b43legacy_ratelimit(wl))
+		return;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	printk(KERN_WARNING "b43legacy-%s warning: %pV",
+	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
+	va_end(args);
+}
+
+#if B43legacy_DEBUG
+void b43legacydbg(struct b43legacy_wl *wl, const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	printk(KERN_DEBUG "b43legacy-%s debug: %pV",
+	       (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
+	va_end(args);
+}
+#endif /* DEBUG */
+
+static void b43legacy_ram_write(struct b43legacy_wldev *dev, u16 offset,
+				u32 val)
+{
+	u32 status;
+
+	B43legacy_WARN_ON(offset % 4 != 0);
+
+	status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	if (status & B43legacy_MACCTL_BE)
+		val = swab32(val);
+
+	b43legacy_write32(dev, B43legacy_MMIO_RAM_CONTROL, offset);
+	mmiowb();
+	b43legacy_write32(dev, B43legacy_MMIO_RAM_DATA, val);
+}
+
+static inline
+void b43legacy_shm_control_word(struct b43legacy_wldev *dev,
+				u16 routing, u16 offset)
+{
+	u32 control;
+
+	/* "offset" is the WORD offset. */
+
+	control = routing;
+	control <<= 16;
+	control |= offset;
+	b43legacy_write32(dev, B43legacy_MMIO_SHM_CONTROL, control);
+}
+
+u32 b43legacy_shm_read32(struct b43legacy_wldev *dev,
+		       u16 routing, u16 offset)
+{
+	u32 ret;
+
+	if (routing == B43legacy_SHM_SHARED) {
+		B43legacy_WARN_ON((offset & 0x0001) != 0);
+		if (offset & 0x0003) {
+			/* Unaligned access */
+			b43legacy_shm_control_word(dev, routing, offset >> 2);
+			ret = b43legacy_read16(dev,
+				B43legacy_MMIO_SHM_DATA_UNALIGNED);
+			ret <<= 16;
+			b43legacy_shm_control_word(dev, routing,
+						     (offset >> 2) + 1);
+			ret |= b43legacy_read16(dev, B43legacy_MMIO_SHM_DATA);
+
+			return ret;
+		}
+		offset >>= 2;
+	}
+	b43legacy_shm_control_word(dev, routing, offset);
+	ret = b43legacy_read32(dev, B43legacy_MMIO_SHM_DATA);
+
+	return ret;
+}
+
+u16 b43legacy_shm_read16(struct b43legacy_wldev *dev,
+			   u16 routing, u16 offset)
+{
+	u16 ret;
+
+	if (routing == B43legacy_SHM_SHARED) {
+		B43legacy_WARN_ON((offset & 0x0001) != 0);
+		if (offset & 0x0003) {
+			/* Unaligned access */
+			b43legacy_shm_control_word(dev, routing, offset >> 2);
+			ret = b43legacy_read16(dev,
+					     B43legacy_MMIO_SHM_DATA_UNALIGNED);
+
+			return ret;
+		}
+		offset >>= 2;
+	}
+	b43legacy_shm_control_word(dev, routing, offset);
+	ret = b43legacy_read16(dev, B43legacy_MMIO_SHM_DATA);
+
+	return ret;
+}
+
+void b43legacy_shm_write32(struct b43legacy_wldev *dev,
+			   u16 routing, u16 offset,
+			   u32 value)
+{
+	if (routing == B43legacy_SHM_SHARED) {
+		B43legacy_WARN_ON((offset & 0x0001) != 0);
+		if (offset & 0x0003) {
+			/* Unaligned access */
+			b43legacy_shm_control_word(dev, routing, offset >> 2);
+			mmiowb();
+			b43legacy_write16(dev,
+					  B43legacy_MMIO_SHM_DATA_UNALIGNED,
+					  (value >> 16) & 0xffff);
+			mmiowb();
+			b43legacy_shm_control_word(dev, routing,
+						   (offset >> 2) + 1);
+			mmiowb();
+			b43legacy_write16(dev, B43legacy_MMIO_SHM_DATA,
+					  value & 0xffff);
+			return;
+		}
+		offset >>= 2;
+	}
+	b43legacy_shm_control_word(dev, routing, offset);
+	mmiowb();
+	b43legacy_write32(dev, B43legacy_MMIO_SHM_DATA, value);
+}
+
+void b43legacy_shm_write16(struct b43legacy_wldev *dev, u16 routing, u16 offset,
+			   u16 value)
+{
+	if (routing == B43legacy_SHM_SHARED) {
+		B43legacy_WARN_ON((offset & 0x0001) != 0);
+		if (offset & 0x0003) {
+			/* Unaligned access */
+			b43legacy_shm_control_word(dev, routing, offset >> 2);
+			mmiowb();
+			b43legacy_write16(dev,
+					  B43legacy_MMIO_SHM_DATA_UNALIGNED,
+					  value);
+			return;
+		}
+		offset >>= 2;
+	}
+	b43legacy_shm_control_word(dev, routing, offset);
+	mmiowb();
+	b43legacy_write16(dev, B43legacy_MMIO_SHM_DATA, value);
+}
+
+/* Read HostFlags */
+u32 b43legacy_hf_read(struct b43legacy_wldev *dev)
+{
+	u32 ret;
+
+	ret = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,
+				   B43legacy_SHM_SH_HOSTFHI);
+	ret <<= 16;
+	ret |= b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,
+				    B43legacy_SHM_SH_HOSTFLO);
+
+	return ret;
+}
+
+/* Write HostFlags */
+void b43legacy_hf_write(struct b43legacy_wldev *dev, u32 value)
+{
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+			      B43legacy_SHM_SH_HOSTFLO,
+			      (value & 0x0000FFFF));
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+			      B43legacy_SHM_SH_HOSTFHI,
+			      ((value & 0xFFFF0000) >> 16));
+}
+
+void b43legacy_tsf_read(struct b43legacy_wldev *dev, u64 *tsf)
+{
+	/* We need to be careful. As we read the TSF from multiple
+	 * registers, we should take care of register overflows.
+	 * In theory, the whole tsf read process should be atomic.
+	 * We try to be atomic here, by restaring the read process,
+	 * if any of the high registers changed (overflew).
+	 */
+	if (dev->dev->id.revision >= 3) {
+		u32 low;
+		u32 high;
+		u32 high2;
+
+		do {
+			high = b43legacy_read32(dev,
+					B43legacy_MMIO_REV3PLUS_TSF_HIGH);
+			low = b43legacy_read32(dev,
+					B43legacy_MMIO_REV3PLUS_TSF_LOW);
+			high2 = b43legacy_read32(dev,
+					B43legacy_MMIO_REV3PLUS_TSF_HIGH);
+		} while (unlikely(high != high2));
+
+		*tsf = high;
+		*tsf <<= 32;
+		*tsf |= low;
+	} else {
+		u64 tmp;
+		u16 v0;
+		u16 v1;
+		u16 v2;
+		u16 v3;
+		u16 test1;
+		u16 test2;
+		u16 test3;
+
+		do {
+			v3 = b43legacy_read16(dev, B43legacy_MMIO_TSF_3);
+			v2 = b43legacy_read16(dev, B43legacy_MMIO_TSF_2);
+			v1 = b43legacy_read16(dev, B43legacy_MMIO_TSF_1);
+			v0 = b43legacy_read16(dev, B43legacy_MMIO_TSF_0);
+
+			test3 = b43legacy_read16(dev, B43legacy_MMIO_TSF_3);
+			test2 = b43legacy_read16(dev, B43legacy_MMIO_TSF_2);
+			test1 = b43legacy_read16(dev, B43legacy_MMIO_TSF_1);
+		} while (v3 != test3 || v2 != test2 || v1 != test1);
+
+		*tsf = v3;
+		*tsf <<= 48;
+		tmp = v2;
+		tmp <<= 32;
+		*tsf |= tmp;
+		tmp = v1;
+		tmp <<= 16;
+		*tsf |= tmp;
+		*tsf |= v0;
+	}
+}
+
+static void b43legacy_time_lock(struct b43legacy_wldev *dev)
+{
+	u32 status;
+
+	status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	status |= B43legacy_MACCTL_TBTTHOLD;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status);
+	mmiowb();
+}
+
+static void b43legacy_time_unlock(struct b43legacy_wldev *dev)
+{
+	u32 status;
+
+	status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	status &= ~B43legacy_MACCTL_TBTTHOLD;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status);
+}
+
+static void b43legacy_tsf_write_locked(struct b43legacy_wldev *dev, u64 tsf)
+{
+	/* Be careful with the in-progress timer.
+	 * First zero out the low register, so we have a full
+	 * register-overflow duration to complete the operation.
+	 */
+	if (dev->dev->id.revision >= 3) {
+		u32 lo = (tsf & 0x00000000FFFFFFFFULL);
+		u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32;
+
+		b43legacy_write32(dev, B43legacy_MMIO_REV3PLUS_TSF_LOW, 0);
+		mmiowb();
+		b43legacy_write32(dev, B43legacy_MMIO_REV3PLUS_TSF_HIGH,
+				    hi);
+		mmiowb();
+		b43legacy_write32(dev, B43legacy_MMIO_REV3PLUS_TSF_LOW,
+				    lo);
+	} else {
+		u16 v0 = (tsf & 0x000000000000FFFFULL);
+		u16 v1 = (tsf & 0x00000000FFFF0000ULL) >> 16;
+		u16 v2 = (tsf & 0x0000FFFF00000000ULL) >> 32;
+		u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48;
+
+		b43legacy_write16(dev, B43legacy_MMIO_TSF_0, 0);
+		mmiowb();
+		b43legacy_write16(dev, B43legacy_MMIO_TSF_3, v3);
+		mmiowb();
+		b43legacy_write16(dev, B43legacy_MMIO_TSF_2, v2);
+		mmiowb();
+		b43legacy_write16(dev, B43legacy_MMIO_TSF_1, v1);
+		mmiowb();
+		b43legacy_write16(dev, B43legacy_MMIO_TSF_0, v0);
+	}
+}
+
+void b43legacy_tsf_write(struct b43legacy_wldev *dev, u64 tsf)
+{
+	b43legacy_time_lock(dev);
+	b43legacy_tsf_write_locked(dev, tsf);
+	b43legacy_time_unlock(dev);
+}
+
+static
+void b43legacy_macfilter_set(struct b43legacy_wldev *dev,
+			     u16 offset, const u8 *mac)
+{
+	static const u8 zero_addr[ETH_ALEN] = { 0 };
+	u16 data;
+
+	if (!mac)
+		mac = zero_addr;
+
+	offset |= 0x0020;
+	b43legacy_write16(dev, B43legacy_MMIO_MACFILTER_CONTROL, offset);
+
+	data = mac[0];
+	data |= mac[1] << 8;
+	b43legacy_write16(dev, B43legacy_MMIO_MACFILTER_DATA, data);
+	data = mac[2];
+	data |= mac[3] << 8;
+	b43legacy_write16(dev, B43legacy_MMIO_MACFILTER_DATA, data);
+	data = mac[4];
+	data |= mac[5] << 8;
+	b43legacy_write16(dev, B43legacy_MMIO_MACFILTER_DATA, data);
+}
+
+static void b43legacy_write_mac_bssid_templates(struct b43legacy_wldev *dev)
+{
+	static const u8 zero_addr[ETH_ALEN] = { 0 };
+	const u8 *mac = dev->wl->mac_addr;
+	const u8 *bssid = dev->wl->bssid;
+	u8 mac_bssid[ETH_ALEN * 2];
+	int i;
+	u32 tmp;
+
+	if (!bssid)
+		bssid = zero_addr;
+	if (!mac)
+		mac = zero_addr;
+
+	b43legacy_macfilter_set(dev, B43legacy_MACFILTER_BSSID, bssid);
+
+	memcpy(mac_bssid, mac, ETH_ALEN);
+	memcpy(mac_bssid + ETH_ALEN, bssid, ETH_ALEN);
+
+	/* Write our MAC address and BSSID to template ram */
+	for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32)) {
+		tmp =  (u32)(mac_bssid[i + 0]);
+		tmp |= (u32)(mac_bssid[i + 1]) << 8;
+		tmp |= (u32)(mac_bssid[i + 2]) << 16;
+		tmp |= (u32)(mac_bssid[i + 3]) << 24;
+		b43legacy_ram_write(dev, 0x20 + i, tmp);
+		b43legacy_ram_write(dev, 0x78 + i, tmp);
+		b43legacy_ram_write(dev, 0x478 + i, tmp);
+	}
+}
+
+static void b43legacy_upload_card_macaddress(struct b43legacy_wldev *dev)
+{
+	b43legacy_write_mac_bssid_templates(dev);
+	b43legacy_macfilter_set(dev, B43legacy_MACFILTER_SELF,
+				dev->wl->mac_addr);
+}
+
+static void b43legacy_set_slot_time(struct b43legacy_wldev *dev,
+				    u16 slot_time)
+{
+	/* slot_time is in usec. */
+	if (dev->phy.type != B43legacy_PHYTYPE_G)
+		return;
+	b43legacy_write16(dev, 0x684, 510 + slot_time);
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0010,
+			      slot_time);
+}
+
+static void b43legacy_short_slot_timing_enable(struct b43legacy_wldev *dev)
+{
+	b43legacy_set_slot_time(dev, 9);
+}
+
+static void b43legacy_short_slot_timing_disable(struct b43legacy_wldev *dev)
+{
+	b43legacy_set_slot_time(dev, 20);
+}
+
+/* Synchronize IRQ top- and bottom-half.
+ * IRQs must be masked before calling this.
+ * This must not be called with the irq_lock held.
+ */
+static void b43legacy_synchronize_irq(struct b43legacy_wldev *dev)
+{
+	synchronize_irq(dev->dev->irq);
+	tasklet_kill(&dev->isr_tasklet);
+}
+
+/* DummyTransmission function, as documented on
+ * http://bcm-specs.sipsolutions.net/DummyTransmission
+ */
+void b43legacy_dummy_transmission(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	unsigned int i;
+	unsigned int max_loop;
+	u16 value;
+	u32 buffer[5] = {
+		0x00000000,
+		0x00D40000,
+		0x00000000,
+		0x01000000,
+		0x00000000,
+	};
+
+	switch (phy->type) {
+	case B43legacy_PHYTYPE_B:
+	case B43legacy_PHYTYPE_G:
+		max_loop = 0xFA;
+		buffer[0] = 0x000B846E;
+		break;
+	default:
+		B43legacy_BUG_ON(1);
+		return;
+	}
+
+	for (i = 0; i < 5; i++)
+		b43legacy_ram_write(dev, i * 4, buffer[i]);
+
+	/* dummy read follows */
+	b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+
+	b43legacy_write16(dev, 0x0568, 0x0000);
+	b43legacy_write16(dev, 0x07C0, 0x0000);
+	b43legacy_write16(dev, 0x050C, 0x0000);
+	b43legacy_write16(dev, 0x0508, 0x0000);
+	b43legacy_write16(dev, 0x050A, 0x0000);
+	b43legacy_write16(dev, 0x054C, 0x0000);
+	b43legacy_write16(dev, 0x056A, 0x0014);
+	b43legacy_write16(dev, 0x0568, 0x0826);
+	b43legacy_write16(dev, 0x0500, 0x0000);
+	b43legacy_write16(dev, 0x0502, 0x0030);
+
+	if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5)
+		b43legacy_radio_write16(dev, 0x0051, 0x0017);
+	for (i = 0x00; i < max_loop; i++) {
+		value = b43legacy_read16(dev, 0x050E);
+		if (value & 0x0080)
+			break;
+		udelay(10);
+	}
+	for (i = 0x00; i < 0x0A; i++) {
+		value = b43legacy_read16(dev, 0x050E);
+		if (value & 0x0400)
+			break;
+		udelay(10);
+	}
+	for (i = 0x00; i < 0x0A; i++) {
+		value = b43legacy_read16(dev, 0x0690);
+		if (!(value & 0x0100))
+			break;
+		udelay(10);
+	}
+	if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5)
+		b43legacy_radio_write16(dev, 0x0051, 0x0037);
+}
+
+/* Turn the Analog ON/OFF */
+static void b43legacy_switch_analog(struct b43legacy_wldev *dev, int on)
+{
+	b43legacy_write16(dev, B43legacy_MMIO_PHY0, on ? 0 : 0xF4);
+}
+
+void b43legacy_wireless_core_reset(struct b43legacy_wldev *dev, u32 flags)
+{
+	u32 tmslow;
+	u32 macctl;
+
+	flags |= B43legacy_TMSLOW_PHYCLKEN;
+	flags |= B43legacy_TMSLOW_PHYRESET;
+	ssb_device_enable(dev->dev, flags);
+	msleep(2); /* Wait for the PLL to turn on. */
+
+	/* Now take the PHY out of Reset again */
+	tmslow = ssb_read32(dev->dev, SSB_TMSLOW);
+	tmslow |= SSB_TMSLOW_FGC;
+	tmslow &= ~B43legacy_TMSLOW_PHYRESET;
+	ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
+	ssb_read32(dev->dev, SSB_TMSLOW); /* flush */
+	msleep(1);
+	tmslow &= ~SSB_TMSLOW_FGC;
+	ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
+	ssb_read32(dev->dev, SSB_TMSLOW); /* flush */
+	msleep(1);
+
+	/* Turn Analog ON */
+	b43legacy_switch_analog(dev, 1);
+
+	macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	macctl &= ~B43legacy_MACCTL_GMODE;
+	if (flags & B43legacy_TMSLOW_GMODE) {
+		macctl |= B43legacy_MACCTL_GMODE;
+		dev->phy.gmode = true;
+	} else
+		dev->phy.gmode = false;
+	macctl |= B43legacy_MACCTL_IHR_ENABLED;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
+}
+
+static void handle_irq_transmit_status(struct b43legacy_wldev *dev)
+{
+	u32 v0;
+	u32 v1;
+	u16 tmp;
+	struct b43legacy_txstatus stat;
+
+	while (1) {
+		v0 = b43legacy_read32(dev, B43legacy_MMIO_XMITSTAT_0);
+		if (!(v0 & 0x00000001))
+			break;
+		v1 = b43legacy_read32(dev, B43legacy_MMIO_XMITSTAT_1);
+
+		stat.cookie = (v0 >> 16);
+		stat.seq = (v1 & 0x0000FFFF);
+		stat.phy_stat = ((v1 & 0x00FF0000) >> 16);
+		tmp = (v0 & 0x0000FFFF);
+		stat.frame_count = ((tmp & 0xF000) >> 12);
+		stat.rts_count = ((tmp & 0x0F00) >> 8);
+		stat.supp_reason = ((tmp & 0x001C) >> 2);
+		stat.pm_indicated = !!(tmp & 0x0080);
+		stat.intermediate = !!(tmp & 0x0040);
+		stat.for_ampdu = !!(tmp & 0x0020);
+		stat.acked = !!(tmp & 0x0002);
+
+		b43legacy_handle_txstatus(dev, &stat);
+	}
+}
+
+static void drain_txstatus_queue(struct b43legacy_wldev *dev)
+{
+	u32 dummy;
+
+	if (dev->dev->id.revision < 5)
+		return;
+	/* Read all entries from the microcode TXstatus FIFO
+	 * and throw them away.
+	 */
+	while (1) {
+		dummy = b43legacy_read32(dev, B43legacy_MMIO_XMITSTAT_0);
+		if (!(dummy & 0x00000001))
+			break;
+		dummy = b43legacy_read32(dev, B43legacy_MMIO_XMITSTAT_1);
+	}
+}
+
+static u32 b43legacy_jssi_read(struct b43legacy_wldev *dev)
+{
+	u32 val = 0;
+
+	val = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x40A);
+	val <<= 16;
+	val |= b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x408);
+
+	return val;
+}
+
+static void b43legacy_jssi_write(struct b43legacy_wldev *dev, u32 jssi)
+{
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x408,
+			      (jssi & 0x0000FFFF));
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x40A,
+			      (jssi & 0xFFFF0000) >> 16);
+}
+
+static void b43legacy_generate_noise_sample(struct b43legacy_wldev *dev)
+{
+	b43legacy_jssi_write(dev, 0x7F7F7F7F);
+	b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
+			  b43legacy_read32(dev, B43legacy_MMIO_MACCMD)
+			  | B43legacy_MACCMD_BGNOISE);
+	B43legacy_WARN_ON(dev->noisecalc.channel_at_start !=
+			    dev->phy.channel);
+}
+
+static void b43legacy_calculate_link_quality(struct b43legacy_wldev *dev)
+{
+	/* Top half of Link Quality calculation. */
+
+	if (dev->noisecalc.calculation_running)
+		return;
+	dev->noisecalc.channel_at_start = dev->phy.channel;
+	dev->noisecalc.calculation_running = true;
+	dev->noisecalc.nr_samples = 0;
+
+	b43legacy_generate_noise_sample(dev);
+}
+
+static void handle_irq_noise(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 tmp;
+	u8 noise[4];
+	u8 i;
+	u8 j;
+	s32 average;
+
+	/* Bottom half of Link Quality calculation. */
+
+	B43legacy_WARN_ON(!dev->noisecalc.calculation_running);
+	if (dev->noisecalc.channel_at_start != phy->channel)
+		goto drop_calculation;
+	*((__le32 *)noise) = cpu_to_le32(b43legacy_jssi_read(dev));
+	if (noise[0] == 0x7F || noise[1] == 0x7F ||
+	    noise[2] == 0x7F || noise[3] == 0x7F)
+		goto generate_new;
+
+	/* Get the noise samples. */
+	B43legacy_WARN_ON(dev->noisecalc.nr_samples >= 8);
+	i = dev->noisecalc.nr_samples;
+	noise[0] = clamp_val(noise[0], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+	noise[1] = clamp_val(noise[1], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+	noise[2] = clamp_val(noise[2], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+	noise[3] = clamp_val(noise[3], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+	dev->noisecalc.samples[i][0] = phy->nrssi_lt[noise[0]];
+	dev->noisecalc.samples[i][1] = phy->nrssi_lt[noise[1]];
+	dev->noisecalc.samples[i][2] = phy->nrssi_lt[noise[2]];
+	dev->noisecalc.samples[i][3] = phy->nrssi_lt[noise[3]];
+	dev->noisecalc.nr_samples++;
+	if (dev->noisecalc.nr_samples == 8) {
+		/* Calculate the Link Quality by the noise samples. */
+		average = 0;
+		for (i = 0; i < 8; i++) {
+			for (j = 0; j < 4; j++)
+				average += dev->noisecalc.samples[i][j];
+		}
+		average /= (8 * 4);
+		average *= 125;
+		average += 64;
+		average /= 128;
+		tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,
+					     0x40C);
+		tmp = (tmp / 128) & 0x1F;
+		if (tmp >= 8)
+			average += 2;
+		else
+			average -= 25;
+		if (tmp == 8)
+			average -= 72;
+		else
+			average -= 48;
+
+		dev->stats.link_noise = average;
+drop_calculation:
+		dev->noisecalc.calculation_running = false;
+		return;
+	}
+generate_new:
+	b43legacy_generate_noise_sample(dev);
+}
+
+static void handle_irq_tbtt_indication(struct b43legacy_wldev *dev)
+{
+	if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_AP)) {
+		/* TODO: PS TBTT */
+	} else {
+		if (1/*FIXME: the last PSpoll frame was sent successfully */)
+			b43legacy_power_saving_ctl_bits(dev, -1, -1);
+	}
+	if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_ADHOC))
+		dev->dfq_valid = true;
+}
+
+static void handle_irq_atim_end(struct b43legacy_wldev *dev)
+{
+	if (dev->dfq_valid) {
+		b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
+				  b43legacy_read32(dev, B43legacy_MMIO_MACCMD)
+				  | B43legacy_MACCMD_DFQ_VALID);
+		dev->dfq_valid = false;
+	}
+}
+
+static void handle_irq_pmq(struct b43legacy_wldev *dev)
+{
+	u32 tmp;
+
+	/* TODO: AP mode. */
+
+	while (1) {
+		tmp = b43legacy_read32(dev, B43legacy_MMIO_PS_STATUS);
+		if (!(tmp & 0x00000008))
+			break;
+	}
+	/* 16bit write is odd, but correct. */
+	b43legacy_write16(dev, B43legacy_MMIO_PS_STATUS, 0x0002);
+}
+
+static void b43legacy_write_template_common(struct b43legacy_wldev *dev,
+					    const u8 *data, u16 size,
+					    u16 ram_offset,
+					    u16 shm_size_offset, u8 rate)
+{
+	u32 i;
+	u32 tmp;
+	struct b43legacy_plcp_hdr4 plcp;
+
+	plcp.data = 0;
+	b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
+	b43legacy_ram_write(dev, ram_offset, le32_to_cpu(plcp.data));
+	ram_offset += sizeof(u32);
+	/* The PLCP is 6 bytes long, but we only wrote 4 bytes, yet.
+	 * So leave the first two bytes of the next write blank.
+	 */
+	tmp = (u32)(data[0]) << 16;
+	tmp |= (u32)(data[1]) << 24;
+	b43legacy_ram_write(dev, ram_offset, tmp);
+	ram_offset += sizeof(u32);
+	for (i = 2; i < size; i += sizeof(u32)) {
+		tmp = (u32)(data[i + 0]);
+		if (i + 1 < size)
+			tmp |= (u32)(data[i + 1]) << 8;
+		if (i + 2 < size)
+			tmp |= (u32)(data[i + 2]) << 16;
+		if (i + 3 < size)
+			tmp |= (u32)(data[i + 3]) << 24;
+		b43legacy_ram_write(dev, ram_offset + i - 2, tmp);
+	}
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, shm_size_offset,
+			      size + sizeof(struct b43legacy_plcp_hdr6));
+}
+
+/* Convert a b43legacy antenna number value to the PHY TX control value. */
+static u16 b43legacy_antenna_to_phyctl(int antenna)
+{
+	switch (antenna) {
+	case B43legacy_ANTENNA0:
+		return B43legacy_TX4_PHY_ANT0;
+	case B43legacy_ANTENNA1:
+		return B43legacy_TX4_PHY_ANT1;
+	}
+	return B43legacy_TX4_PHY_ANTLAST;
+}
+
+static void b43legacy_write_beacon_template(struct b43legacy_wldev *dev,
+					    u16 ram_offset,
+					    u16 shm_size_offset)
+{
+
+	unsigned int i, len, variable_len;
+	const struct ieee80211_mgmt *bcn;
+	const u8 *ie;
+	bool tim_found = false;
+	unsigned int rate;
+	u16 ctl;
+	int antenna;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(dev->wl->current_beacon);
+
+	bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data);
+	len = min_t(size_t, dev->wl->current_beacon->len,
+		  0x200 - sizeof(struct b43legacy_plcp_hdr6));
+	rate = ieee80211_get_tx_rate(dev->wl->hw, info)->hw_value;
+
+	b43legacy_write_template_common(dev, (const u8 *)bcn, len, ram_offset,
+					shm_size_offset, rate);
+
+	/* Write the PHY TX control parameters. */
+	antenna = B43legacy_ANTENNA_DEFAULT;
+	antenna = b43legacy_antenna_to_phyctl(antenna);
+	ctl = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,
+				   B43legacy_SHM_SH_BEACPHYCTL);
+	/* We can't send beacons with short preamble. Would get PHY errors. */
+	ctl &= ~B43legacy_TX4_PHY_SHORTPRMBL;
+	ctl &= ~B43legacy_TX4_PHY_ANT;
+	ctl &= ~B43legacy_TX4_PHY_ENC;
+	ctl |= antenna;
+	ctl |= B43legacy_TX4_PHY_ENC_CCK;
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+			      B43legacy_SHM_SH_BEACPHYCTL, ctl);
+
+	/* Find the position of the TIM and the DTIM_period value
+	 * and write them to SHM. */
+	ie = bcn->u.beacon.variable;
+	variable_len = len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
+	for (i = 0; i < variable_len - 2; ) {
+		uint8_t ie_id, ie_len;
+
+		ie_id = ie[i];
+		ie_len = ie[i + 1];
+		if (ie_id == 5) {
+			u16 tim_position;
+			u16 dtim_period;
+			/* This is the TIM Information Element */
+
+			/* Check whether the ie_len is in the beacon data range. */
+			if (variable_len < ie_len + 2 + i)
+				break;
+			/* A valid TIM is at least 4 bytes long. */
+			if (ie_len < 4)
+				break;
+			tim_found = true;
+
+			tim_position = sizeof(struct b43legacy_plcp_hdr6);
+			tim_position += offsetof(struct ieee80211_mgmt,
+						 u.beacon.variable);
+			tim_position += i;
+
+			dtim_period = ie[i + 3];
+
+			b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+					B43legacy_SHM_SH_TIMPOS, tim_position);
+			b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+					B43legacy_SHM_SH_DTIMP, dtim_period);
+			break;
+		}
+		i += ie_len + 2;
+	}
+	if (!tim_found) {
+		b43legacywarn(dev->wl, "Did not find a valid TIM IE in the "
+			      "beacon template packet. AP or IBSS operation "
+			      "may be broken.\n");
+	} else
+		b43legacydbg(dev->wl, "Updated beacon template\n");
+}
+
+static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev,
+					    u16 shm_offset, u16 size,
+					    struct ieee80211_rate *rate)
+{
+	struct b43legacy_plcp_hdr4 plcp;
+	u32 tmp;
+	__le16 dur;
+
+	plcp.data = 0;
+	b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->hw_value);
+	dur = ieee80211_generic_frame_duration(dev->wl->hw,
+					       dev->wl->vif,
+					       NL80211_BAND_2GHZ,
+					       size,
+					       rate);
+	/* Write PLCP in two parts and timing for packet transfer */
+	tmp = le32_to_cpu(plcp.data);
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, shm_offset,
+			      tmp & 0xFFFF);
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, shm_offset + 2,
+			      tmp >> 16);
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, shm_offset + 6,
+			      le16_to_cpu(dur));
+}
+
+/* Instead of using custom probe response template, this function
+ * just patches custom beacon template by:
+ * 1) Changing packet type
+ * 2) Patching duration field
+ * 3) Stripping TIM
+ */
+static const u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
+					       u16 *dest_size,
+					       struct ieee80211_rate *rate)
+{
+	const u8 *src_data;
+	u8 *dest_data;
+	u16 src_size, elem_size, src_pos, dest_pos;
+	__le16 dur;
+	struct ieee80211_hdr *hdr;
+	size_t ie_start;
+
+	src_size = dev->wl->current_beacon->len;
+	src_data = (const u8 *)dev->wl->current_beacon->data;
+
+	/* Get the start offset of the variable IEs in the packet. */
+	ie_start = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
+	B43legacy_WARN_ON(ie_start != offsetof(struct ieee80211_mgmt,
+					       u.beacon.variable));
+
+	if (B43legacy_WARN_ON(src_size < ie_start))
+		return NULL;
+
+	dest_data = kmalloc(src_size, GFP_ATOMIC);
+	if (unlikely(!dest_data))
+		return NULL;
+
+	/* Copy the static data and all Information Elements, except the TIM. */
+	memcpy(dest_data, src_data, ie_start);
+	src_pos = ie_start;
+	dest_pos = ie_start;
+	for ( ; src_pos < src_size - 2; src_pos += elem_size) {
+		elem_size = src_data[src_pos + 1] + 2;
+		if (src_data[src_pos] == 5) {
+			/* This is the TIM. */
+			continue;
+		}
+		memcpy(dest_data + dest_pos, src_data + src_pos, elem_size);
+		dest_pos += elem_size;
+	}
+	*dest_size = dest_pos;
+	hdr = (struct ieee80211_hdr *)dest_data;
+
+	/* Set the frame control. */
+	hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+					 IEEE80211_STYPE_PROBE_RESP);
+	dur = ieee80211_generic_frame_duration(dev->wl->hw,
+					       dev->wl->vif,
+					       NL80211_BAND_2GHZ,
+					       *dest_size,
+					       rate);
+	hdr->duration_id = dur;
+
+	return dest_data;
+}
+
+static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev,
+						u16 ram_offset,
+						u16 shm_size_offset,
+						struct ieee80211_rate *rate)
+{
+	const u8 *probe_resp_data;
+	u16 size;
+
+	size = dev->wl->current_beacon->len;
+	probe_resp_data = b43legacy_generate_probe_resp(dev, &size, rate);
+	if (unlikely(!probe_resp_data))
+		return;
+
+	/* Looks like PLCP headers plus packet timings are stored for
+	 * all possible basic rates
+	 */
+	b43legacy_write_probe_resp_plcp(dev, 0x31A, size,
+					&b43legacy_b_ratetable[0]);
+	b43legacy_write_probe_resp_plcp(dev, 0x32C, size,
+					&b43legacy_b_ratetable[1]);
+	b43legacy_write_probe_resp_plcp(dev, 0x33E, size,
+					&b43legacy_b_ratetable[2]);
+	b43legacy_write_probe_resp_plcp(dev, 0x350, size,
+					&b43legacy_b_ratetable[3]);
+
+	size = min_t(size_t, size,
+		   0x200 - sizeof(struct b43legacy_plcp_hdr6));
+	b43legacy_write_template_common(dev, probe_resp_data,
+					size, ram_offset,
+					shm_size_offset, rate->hw_value);
+	kfree(probe_resp_data);
+}
+
+static void b43legacy_upload_beacon0(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_wl *wl = dev->wl;
+
+	if (wl->beacon0_uploaded)
+		return;
+	b43legacy_write_beacon_template(dev, 0x68, 0x18);
+	/* FIXME: Probe resp upload doesn't really belong here,
+	 *        but we don't use that feature anyway. */
+	b43legacy_write_probe_resp_template(dev, 0x268, 0x4A,
+				      &__b43legacy_ratetable[3]);
+	wl->beacon0_uploaded = true;
+}
+
+static void b43legacy_upload_beacon1(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_wl *wl = dev->wl;
+
+	if (wl->beacon1_uploaded)
+		return;
+	b43legacy_write_beacon_template(dev, 0x468, 0x1A);
+	wl->beacon1_uploaded = true;
+}
+
+static void handle_irq_beacon(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_wl *wl = dev->wl;
+	u32 cmd, beacon0_valid, beacon1_valid;
+
+	if (!b43legacy_is_mode(wl, NL80211_IFTYPE_AP))
+		return;
+
+	/* This is the bottom half of the asynchronous beacon update. */
+
+	/* Ignore interrupt in the future. */
+	dev->irq_mask &= ~B43legacy_IRQ_BEACON;
+
+	cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
+	beacon0_valid = (cmd & B43legacy_MACCMD_BEACON0_VALID);
+	beacon1_valid = (cmd & B43legacy_MACCMD_BEACON1_VALID);
+
+	/* Schedule interrupt manually, if busy. */
+	if (beacon0_valid && beacon1_valid) {
+		b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, B43legacy_IRQ_BEACON);
+		dev->irq_mask |= B43legacy_IRQ_BEACON;
+		return;
+	}
+
+	if (unlikely(wl->beacon_templates_virgin)) {
+		/* We never uploaded a beacon before.
+		 * Upload both templates now, but only mark one valid. */
+		wl->beacon_templates_virgin = false;
+		b43legacy_upload_beacon0(dev);
+		b43legacy_upload_beacon1(dev);
+		cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
+		cmd |= B43legacy_MACCMD_BEACON0_VALID;
+		b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd);
+	} else {
+		if (!beacon0_valid) {
+			b43legacy_upload_beacon0(dev);
+			cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
+			cmd |= B43legacy_MACCMD_BEACON0_VALID;
+			b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd);
+		} else if (!beacon1_valid) {
+			b43legacy_upload_beacon1(dev);
+			cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
+			cmd |= B43legacy_MACCMD_BEACON1_VALID;
+			b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd);
+		}
+	}
+}
+
+static void b43legacy_beacon_update_trigger_work(struct work_struct *work)
+{
+	struct b43legacy_wl *wl = container_of(work, struct b43legacy_wl,
+					 beacon_update_trigger);
+	struct b43legacy_wldev *dev;
+
+	mutex_lock(&wl->mutex);
+	dev = wl->current_dev;
+	if (likely(dev && (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED))) {
+		spin_lock_irq(&wl->irq_lock);
+		/* Update beacon right away or defer to IRQ. */
+		handle_irq_beacon(dev);
+		/* The handler might have updated the IRQ mask. */
+		b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK,
+				  dev->irq_mask);
+		mmiowb();
+		spin_unlock_irq(&wl->irq_lock);
+	}
+	mutex_unlock(&wl->mutex);
+}
+
+/* Asynchronously update the packet templates in template RAM.
+ * Locking: Requires wl->irq_lock to be locked. */
+static void b43legacy_update_templates(struct b43legacy_wl *wl)
+{
+	struct sk_buff *beacon;
+	/* This is the top half of the ansynchronous beacon update. The bottom
+	 * half is the beacon IRQ. Beacon update must be asynchronous to avoid
+	 * sending an invalid beacon. This can happen for example, if the
+	 * firmware transmits a beacon while we are updating it. */
+
+	/* We could modify the existing beacon and set the aid bit in the TIM
+	 * field, but that would probably require resizing and moving of data
+	 * within the beacon template. Simply request a new beacon and let
+	 * mac80211 do the hard work. */
+	beacon = ieee80211_beacon_get(wl->hw, wl->vif);
+	if (unlikely(!beacon))
+		return;
+
+	if (wl->current_beacon)
+		dev_kfree_skb_any(wl->current_beacon);
+	wl->current_beacon = beacon;
+	wl->beacon0_uploaded = false;
+	wl->beacon1_uploaded = false;
+	ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger);
+}
+
+static void b43legacy_set_beacon_int(struct b43legacy_wldev *dev,
+				     u16 beacon_int)
+{
+	b43legacy_time_lock(dev);
+	if (dev->dev->id.revision >= 3) {
+		b43legacy_write32(dev, B43legacy_MMIO_TSF_CFP_REP,
+				 (beacon_int << 16));
+		b43legacy_write32(dev, B43legacy_MMIO_TSF_CFP_START,
+				 (beacon_int << 10));
+	} else {
+		b43legacy_write16(dev, 0x606, (beacon_int >> 6));
+		b43legacy_write16(dev, 0x610, beacon_int);
+	}
+	b43legacy_time_unlock(dev);
+	b43legacydbg(dev->wl, "Set beacon interval to %u\n", beacon_int);
+}
+
+static void handle_irq_ucode_debug(struct b43legacy_wldev *dev)
+{
+}
+
+/* Interrupt handler bottom-half */
+static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev)
+{
+	u32 reason;
+	u32 dma_reason[ARRAY_SIZE(dev->dma_reason)];
+	u32 merged_dma_reason = 0;
+	int i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->wl->irq_lock, flags);
+
+	B43legacy_WARN_ON(b43legacy_status(dev) <
+			  B43legacy_STAT_INITIALIZED);
+
+	reason = dev->irq_reason;
+	for (i = 0; i < ARRAY_SIZE(dma_reason); i++) {
+		dma_reason[i] = dev->dma_reason[i];
+		merged_dma_reason |= dma_reason[i];
+	}
+
+	if (unlikely(reason & B43legacy_IRQ_MAC_TXERR))
+		b43legacyerr(dev->wl, "MAC transmission error\n");
+
+	if (unlikely(reason & B43legacy_IRQ_PHY_TXERR)) {
+		b43legacyerr(dev->wl, "PHY transmission error\n");
+		rmb();
+		if (unlikely(atomic_dec_and_test(&dev->phy.txerr_cnt))) {
+			b43legacyerr(dev->wl, "Too many PHY TX errors, "
+					      "restarting the controller\n");
+			b43legacy_controller_restart(dev, "PHY TX errors");
+		}
+	}
+
+	if (unlikely(merged_dma_reason & (B43legacy_DMAIRQ_FATALMASK |
+					  B43legacy_DMAIRQ_NONFATALMASK))) {
+		if (merged_dma_reason & B43legacy_DMAIRQ_FATALMASK) {
+			b43legacyerr(dev->wl, "Fatal DMA error: "
+			       "0x%08X, 0x%08X, 0x%08X, "
+			       "0x%08X, 0x%08X, 0x%08X\n",
+			       dma_reason[0], dma_reason[1],
+			       dma_reason[2], dma_reason[3],
+			       dma_reason[4], dma_reason[5]);
+			b43legacy_controller_restart(dev, "DMA error");
+			mmiowb();
+			spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
+			return;
+		}
+		if (merged_dma_reason & B43legacy_DMAIRQ_NONFATALMASK)
+			b43legacyerr(dev->wl, "DMA error: "
+			       "0x%08X, 0x%08X, 0x%08X, "
+			       "0x%08X, 0x%08X, 0x%08X\n",
+			       dma_reason[0], dma_reason[1],
+			       dma_reason[2], dma_reason[3],
+			       dma_reason[4], dma_reason[5]);
+	}
+
+	if (unlikely(reason & B43legacy_IRQ_UCODE_DEBUG))
+		handle_irq_ucode_debug(dev);
+	if (reason & B43legacy_IRQ_TBTT_INDI)
+		handle_irq_tbtt_indication(dev);
+	if (reason & B43legacy_IRQ_ATIM_END)
+		handle_irq_atim_end(dev);
+	if (reason & B43legacy_IRQ_BEACON)
+		handle_irq_beacon(dev);
+	if (reason & B43legacy_IRQ_PMQ)
+		handle_irq_pmq(dev);
+	if (reason & B43legacy_IRQ_TXFIFO_FLUSH_OK)
+		;/*TODO*/
+	if (reason & B43legacy_IRQ_NOISESAMPLE_OK)
+		handle_irq_noise(dev);
+
+	/* Check the DMA reason registers for received data. */
+	if (dma_reason[0] & B43legacy_DMAIRQ_RX_DONE) {
+		if (b43legacy_using_pio(dev))
+			b43legacy_pio_rx(dev->pio.queue0);
+		else
+			b43legacy_dma_rx(dev->dma.rx_ring0);
+	}
+	B43legacy_WARN_ON(dma_reason[1] & B43legacy_DMAIRQ_RX_DONE);
+	B43legacy_WARN_ON(dma_reason[2] & B43legacy_DMAIRQ_RX_DONE);
+	if (dma_reason[3] & B43legacy_DMAIRQ_RX_DONE) {
+		if (b43legacy_using_pio(dev))
+			b43legacy_pio_rx(dev->pio.queue3);
+		else
+			b43legacy_dma_rx(dev->dma.rx_ring3);
+	}
+	B43legacy_WARN_ON(dma_reason[4] & B43legacy_DMAIRQ_RX_DONE);
+	B43legacy_WARN_ON(dma_reason[5] & B43legacy_DMAIRQ_RX_DONE);
+
+	if (reason & B43legacy_IRQ_TX_OK)
+		handle_irq_transmit_status(dev);
+
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask);
+	mmiowb();
+	spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
+}
+
+static void pio_irq_workaround(struct b43legacy_wldev *dev,
+			       u16 base, int queueidx)
+{
+	u16 rxctl;
+
+	rxctl = b43legacy_read16(dev, base + B43legacy_PIO_RXCTL);
+	if (rxctl & B43legacy_PIO_RXCTL_DATAAVAILABLE)
+		dev->dma_reason[queueidx] |= B43legacy_DMAIRQ_RX_DONE;
+	else
+		dev->dma_reason[queueidx] &= ~B43legacy_DMAIRQ_RX_DONE;
+}
+
+static void b43legacy_interrupt_ack(struct b43legacy_wldev *dev, u32 reason)
+{
+	if (b43legacy_using_pio(dev) &&
+	    (dev->dev->id.revision < 3) &&
+	    (!(reason & B43legacy_IRQ_PIO_WORKAROUND))) {
+		/* Apply a PIO specific workaround to the dma_reasons */
+		pio_irq_workaround(dev, B43legacy_MMIO_PIO1_BASE, 0);
+		pio_irq_workaround(dev, B43legacy_MMIO_PIO2_BASE, 1);
+		pio_irq_workaround(dev, B43legacy_MMIO_PIO3_BASE, 2);
+		pio_irq_workaround(dev, B43legacy_MMIO_PIO4_BASE, 3);
+	}
+
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, reason);
+
+	b43legacy_write32(dev, B43legacy_MMIO_DMA0_REASON,
+			  dev->dma_reason[0]);
+	b43legacy_write32(dev, B43legacy_MMIO_DMA1_REASON,
+			  dev->dma_reason[1]);
+	b43legacy_write32(dev, B43legacy_MMIO_DMA2_REASON,
+			  dev->dma_reason[2]);
+	b43legacy_write32(dev, B43legacy_MMIO_DMA3_REASON,
+			  dev->dma_reason[3]);
+	b43legacy_write32(dev, B43legacy_MMIO_DMA4_REASON,
+			  dev->dma_reason[4]);
+	b43legacy_write32(dev, B43legacy_MMIO_DMA5_REASON,
+			  dev->dma_reason[5]);
+}
+
+/* Interrupt handler top-half */
+static irqreturn_t b43legacy_interrupt_handler(int irq, void *dev_id)
+{
+	irqreturn_t ret = IRQ_NONE;
+	struct b43legacy_wldev *dev = dev_id;
+	u32 reason;
+
+	B43legacy_WARN_ON(!dev);
+
+	spin_lock(&dev->wl->irq_lock);
+
+	if (unlikely(b43legacy_status(dev) < B43legacy_STAT_STARTED))
+		/* This can only happen on shared IRQ lines. */
+		goto out;
+	reason = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
+	if (reason == 0xffffffff) /* shared IRQ */
+		goto out;
+	ret = IRQ_HANDLED;
+	reason &= dev->irq_mask;
+	if (!reason)
+		goto out;
+
+	dev->dma_reason[0] = b43legacy_read32(dev,
+					      B43legacy_MMIO_DMA0_REASON)
+					      & 0x0001DC00;
+	dev->dma_reason[1] = b43legacy_read32(dev,
+					      B43legacy_MMIO_DMA1_REASON)
+					      & 0x0000DC00;
+	dev->dma_reason[2] = b43legacy_read32(dev,
+					      B43legacy_MMIO_DMA2_REASON)
+					      & 0x0000DC00;
+	dev->dma_reason[3] = b43legacy_read32(dev,
+					      B43legacy_MMIO_DMA3_REASON)
+					      & 0x0001DC00;
+	dev->dma_reason[4] = b43legacy_read32(dev,
+					      B43legacy_MMIO_DMA4_REASON)
+					      & 0x0000DC00;
+	dev->dma_reason[5] = b43legacy_read32(dev,
+					      B43legacy_MMIO_DMA5_REASON)
+					      & 0x0000DC00;
+
+	b43legacy_interrupt_ack(dev, reason);
+	/* Disable all IRQs. They are enabled again in the bottom half. */
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
+	/* Save the reason code and call our bottom half. */
+	dev->irq_reason = reason;
+	tasklet_schedule(&dev->isr_tasklet);
+out:
+	mmiowb();
+	spin_unlock(&dev->wl->irq_lock);
+
+	return ret;
+}
+
+static void b43legacy_release_firmware(struct b43legacy_wldev *dev)
+{
+	release_firmware(dev->fw.ucode);
+	dev->fw.ucode = NULL;
+	release_firmware(dev->fw.pcm);
+	dev->fw.pcm = NULL;
+	release_firmware(dev->fw.initvals);
+	dev->fw.initvals = NULL;
+	release_firmware(dev->fw.initvals_band);
+	dev->fw.initvals_band = NULL;
+}
+
+static void b43legacy_print_fw_helptext(struct b43legacy_wl *wl)
+{
+	b43legacyerr(wl, "You must go to http://wireless.kernel.org/en/users/"
+		     "Drivers/b43#devicefirmware "
+		     "and download the correct firmware (version 3).\n");
+}
+
+static void b43legacy_fw_cb(const struct firmware *firmware, void *context)
+{
+	struct b43legacy_wldev *dev = context;
+
+	dev->fwp = firmware;
+	complete(&dev->fw_load_complete);
+}
+
+static int do_request_fw(struct b43legacy_wldev *dev,
+			 const char *name,
+			 const struct firmware **fw, bool async)
+{
+	char path[sizeof(modparam_fwpostfix) + 32];
+	struct b43legacy_fw_header *hdr;
+	u32 size;
+	int err;
+
+	if (!name)
+		return 0;
+
+	snprintf(path, ARRAY_SIZE(path),
+		 "b43legacy%s/%s.fw",
+		 modparam_fwpostfix, name);
+	b43legacyinfo(dev->wl, "Loading firmware %s\n", path);
+	if (async) {
+		init_completion(&dev->fw_load_complete);
+		err = request_firmware_nowait(THIS_MODULE, 1, path,
+					      dev->dev->dev, GFP_KERNEL,
+					      dev, b43legacy_fw_cb);
+		if (err) {
+			b43legacyerr(dev->wl, "Unable to load firmware\n");
+			return err;
+		}
+		/* stall here until fw ready */
+		wait_for_completion(&dev->fw_load_complete);
+		if (!dev->fwp)
+			err = -EINVAL;
+		*fw = dev->fwp;
+	} else {
+		err = request_firmware(fw, path, dev->dev->dev);
+	}
+	if (err) {
+		b43legacyerr(dev->wl, "Firmware file \"%s\" not found "
+		       "or load failed.\n", path);
+		return err;
+	}
+	if ((*fw)->size < sizeof(struct b43legacy_fw_header))
+		goto err_format;
+	hdr = (struct b43legacy_fw_header *)((*fw)->data);
+	switch (hdr->type) {
+	case B43legacy_FW_TYPE_UCODE:
+	case B43legacy_FW_TYPE_PCM:
+		size = be32_to_cpu(hdr->size);
+		if (size != (*fw)->size - sizeof(struct b43legacy_fw_header))
+			goto err_format;
+		/* fallthrough */
+	case B43legacy_FW_TYPE_IV:
+		if (hdr->ver != 1)
+			goto err_format;
+		break;
+	default:
+		goto err_format;
+	}
+
+	return err;
+
+err_format:
+	b43legacyerr(dev->wl, "Firmware file \"%s\" format error.\n", path);
+	return -EPROTO;
+}
+
+static int b43legacy_one_core_attach(struct ssb_device *dev,
+				     struct b43legacy_wl *wl);
+static void b43legacy_one_core_detach(struct ssb_device *dev);
+
+static void b43legacy_request_firmware(struct work_struct *work)
+{
+	struct b43legacy_wl *wl = container_of(work,
+				  struct b43legacy_wl, firmware_load);
+	struct b43legacy_wldev *dev = wl->current_dev;
+	struct b43legacy_firmware *fw = &dev->fw;
+	const u8 rev = dev->dev->id.revision;
+	const char *filename;
+	int err;
+
+	if (!fw->ucode) {
+		if (rev == 2)
+			filename = "ucode2";
+		else if (rev == 4)
+			filename = "ucode4";
+		else
+			filename = "ucode5";
+		err = do_request_fw(dev, filename, &fw->ucode, true);
+		if (err)
+			goto err_load;
+	}
+	if (!fw->pcm) {
+		if (rev < 5)
+			filename = "pcm4";
+		else
+			filename = "pcm5";
+		err = do_request_fw(dev, filename, &fw->pcm, false);
+		if (err)
+			goto err_load;
+	}
+	if (!fw->initvals) {
+		switch (dev->phy.type) {
+		case B43legacy_PHYTYPE_B:
+		case B43legacy_PHYTYPE_G:
+			if ((rev >= 5) && (rev <= 10))
+				filename = "b0g0initvals5";
+			else if (rev == 2 || rev == 4)
+				filename = "b0g0initvals2";
+			else
+				goto err_no_initvals;
+			break;
+		default:
+			goto err_no_initvals;
+		}
+		err = do_request_fw(dev, filename, &fw->initvals, false);
+		if (err)
+			goto err_load;
+	}
+	if (!fw->initvals_band) {
+		switch (dev->phy.type) {
+		case B43legacy_PHYTYPE_B:
+		case B43legacy_PHYTYPE_G:
+			if ((rev >= 5) && (rev <= 10))
+				filename = "b0g0bsinitvals5";
+			else if (rev >= 11)
+				filename = NULL;
+			else if (rev == 2 || rev == 4)
+				filename = NULL;
+			else
+				goto err_no_initvals;
+			break;
+		default:
+			goto err_no_initvals;
+		}
+		err = do_request_fw(dev, filename, &fw->initvals_band, false);
+		if (err)
+			goto err_load;
+	}
+	err = ieee80211_register_hw(wl->hw);
+	if (err)
+		goto err_one_core_detach;
+	return;
+
+err_one_core_detach:
+	b43legacy_one_core_detach(dev->dev);
+	goto error;
+
+err_load:
+	b43legacy_print_fw_helptext(dev->wl);
+	goto error;
+
+err_no_initvals:
+	err = -ENODEV;
+	b43legacyerr(dev->wl, "No Initial Values firmware file for PHY %u, "
+	       "core rev %u\n", dev->phy.type, rev);
+	goto error;
+
+error:
+	b43legacy_release_firmware(dev);
+	return;
+}
+
+static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
+{
+	struct wiphy *wiphy = dev->wl->hw->wiphy;
+	const size_t hdr_len = sizeof(struct b43legacy_fw_header);
+	const __be32 *data;
+	unsigned int i;
+	unsigned int len;
+	u16 fwrev;
+	u16 fwpatch;
+	u16 fwdate;
+	u16 fwtime;
+	u32 tmp, macctl;
+	int err = 0;
+
+	/* Jump the microcode PSM to offset 0 */
+	macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	B43legacy_WARN_ON(macctl & B43legacy_MACCTL_PSM_RUN);
+	macctl |= B43legacy_MACCTL_PSM_JMP0;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
+	/* Zero out all microcode PSM registers and shared memory. */
+	for (i = 0; i < 64; i++)
+		b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, i, 0);
+	for (i = 0; i < 4096; i += 2)
+		b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, i, 0);
+
+	/* Upload Microcode. */
+	data = (__be32 *) (dev->fw.ucode->data + hdr_len);
+	len = (dev->fw.ucode->size - hdr_len) / sizeof(__be32);
+	b43legacy_shm_control_word(dev,
+				   B43legacy_SHM_UCODE |
+				   B43legacy_SHM_AUTOINC_W,
+				   0x0000);
+	for (i = 0; i < len; i++) {
+		b43legacy_write32(dev, B43legacy_MMIO_SHM_DATA,
+				    be32_to_cpu(data[i]));
+		udelay(10);
+	}
+
+	if (dev->fw.pcm) {
+		/* Upload PCM data. */
+		data = (__be32 *) (dev->fw.pcm->data + hdr_len);
+		len = (dev->fw.pcm->size - hdr_len) / sizeof(__be32);
+		b43legacy_shm_control_word(dev, B43legacy_SHM_HW, 0x01EA);
+		b43legacy_write32(dev, B43legacy_MMIO_SHM_DATA, 0x00004000);
+		/* No need for autoinc bit in SHM_HW */
+		b43legacy_shm_control_word(dev, B43legacy_SHM_HW, 0x01EB);
+		for (i = 0; i < len; i++) {
+			b43legacy_write32(dev, B43legacy_MMIO_SHM_DATA,
+					  be32_to_cpu(data[i]));
+			udelay(10);
+		}
+	}
+
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON,
+			  B43legacy_IRQ_ALL);
+
+	/* Start the microcode PSM */
+	macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	macctl &= ~B43legacy_MACCTL_PSM_JMP0;
+	macctl |= B43legacy_MACCTL_PSM_RUN;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
+
+	/* Wait for the microcode to load and respond */
+	i = 0;
+	while (1) {
+		tmp = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
+		if (tmp == B43legacy_IRQ_MAC_SUSPENDED)
+			break;
+		i++;
+		if (i >= B43legacy_IRQWAIT_MAX_RETRIES) {
+			b43legacyerr(dev->wl, "Microcode not responding\n");
+			b43legacy_print_fw_helptext(dev->wl);
+			err = -ENODEV;
+			goto error;
+		}
+		msleep_interruptible(50);
+		if (signal_pending(current)) {
+			err = -EINTR;
+			goto error;
+		}
+	}
+	/* dummy read follows */
+	b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
+
+	/* Get and check the revisions. */
+	fwrev = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,
+				     B43legacy_SHM_SH_UCODEREV);
+	fwpatch = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,
+				       B43legacy_SHM_SH_UCODEPATCH);
+	fwdate = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,
+				      B43legacy_SHM_SH_UCODEDATE);
+	fwtime = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,
+				      B43legacy_SHM_SH_UCODETIME);
+
+	if (fwrev > 0x128) {
+		b43legacyerr(dev->wl, "YOU ARE TRYING TO LOAD V4 FIRMWARE."
+			     " Only firmware from binary drivers version 3.x"
+			     " is supported. You must change your firmware"
+			     " files.\n");
+		b43legacy_print_fw_helptext(dev->wl);
+		err = -EOPNOTSUPP;
+		goto error;
+	}
+	b43legacyinfo(dev->wl, "Loading firmware version 0x%X, patch level %u "
+		      "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", fwrev, fwpatch,
+		      (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF,
+		      (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F,
+		      fwtime & 0x1F);
+
+	dev->fw.rev = fwrev;
+	dev->fw.patch = fwpatch;
+
+	snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u",
+			dev->fw.rev, dev->fw.patch);
+	wiphy->hw_version = dev->dev->id.coreid;
+
+	return 0;
+
+error:
+	macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	macctl &= ~B43legacy_MACCTL_PSM_RUN;
+	macctl |= B43legacy_MACCTL_PSM_JMP0;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
+
+	return err;
+}
+
+static int b43legacy_write_initvals(struct b43legacy_wldev *dev,
+				    const struct b43legacy_iv *ivals,
+				    size_t count,
+				    size_t array_size)
+{
+	const struct b43legacy_iv *iv;
+	u16 offset;
+	size_t i;
+	bool bit32;
+
+	BUILD_BUG_ON(sizeof(struct b43legacy_iv) != 6);
+	iv = ivals;
+	for (i = 0; i < count; i++) {
+		if (array_size < sizeof(iv->offset_size))
+			goto err_format;
+		array_size -= sizeof(iv->offset_size);
+		offset = be16_to_cpu(iv->offset_size);
+		bit32 = !!(offset & B43legacy_IV_32BIT);
+		offset &= B43legacy_IV_OFFSET_MASK;
+		if (offset >= 0x1000)
+			goto err_format;
+		if (bit32) {
+			u32 value;
+
+			if (array_size < sizeof(iv->data.d32))
+				goto err_format;
+			array_size -= sizeof(iv->data.d32);
+
+			value = get_unaligned_be32(&iv->data.d32);
+			b43legacy_write32(dev, offset, value);
+
+			iv = (const struct b43legacy_iv *)((const uint8_t *)iv +
+							sizeof(__be16) +
+							sizeof(__be32));
+		} else {
+			u16 value;
+
+			if (array_size < sizeof(iv->data.d16))
+				goto err_format;
+			array_size -= sizeof(iv->data.d16);
+
+			value = be16_to_cpu(iv->data.d16);
+			b43legacy_write16(dev, offset, value);
+
+			iv = (const struct b43legacy_iv *)((const uint8_t *)iv +
+							sizeof(__be16) +
+							sizeof(__be16));
+		}
+	}
+	if (array_size)
+		goto err_format;
+
+	return 0;
+
+err_format:
+	b43legacyerr(dev->wl, "Initial Values Firmware file-format error.\n");
+	b43legacy_print_fw_helptext(dev->wl);
+
+	return -EPROTO;
+}
+
+static int b43legacy_upload_initvals(struct b43legacy_wldev *dev)
+{
+	const size_t hdr_len = sizeof(struct b43legacy_fw_header);
+	const struct b43legacy_fw_header *hdr;
+	struct b43legacy_firmware *fw = &dev->fw;
+	const struct b43legacy_iv *ivals;
+	size_t count;
+	int err;
+
+	hdr = (const struct b43legacy_fw_header *)(fw->initvals->data);
+	ivals = (const struct b43legacy_iv *)(fw->initvals->data + hdr_len);
+	count = be32_to_cpu(hdr->size);
+	err = b43legacy_write_initvals(dev, ivals, count,
+				 fw->initvals->size - hdr_len);
+	if (err)
+		goto out;
+	if (fw->initvals_band) {
+		hdr = (const struct b43legacy_fw_header *)
+		      (fw->initvals_band->data);
+		ivals = (const struct b43legacy_iv *)(fw->initvals_band->data
+			+ hdr_len);
+		count = be32_to_cpu(hdr->size);
+		err = b43legacy_write_initvals(dev, ivals, count,
+					 fw->initvals_band->size - hdr_len);
+		if (err)
+			goto out;
+	}
+out:
+
+	return err;
+}
+
+/* Initialize the GPIOs
+ * http://bcm-specs.sipsolutions.net/GPIO
+ */
+static int b43legacy_gpio_init(struct b43legacy_wldev *dev)
+{
+	struct ssb_bus *bus = dev->dev->bus;
+	struct ssb_device *gpiodev, *pcidev = NULL;
+	u32 mask;
+	u32 set;
+
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL,
+			  b43legacy_read32(dev,
+			  B43legacy_MMIO_MACCTL)
+			  & 0xFFFF3FFF);
+
+	b43legacy_write16(dev, B43legacy_MMIO_GPIO_MASK,
+			  b43legacy_read16(dev,
+			  B43legacy_MMIO_GPIO_MASK)
+			  | 0x000F);
+
+	mask = 0x0000001F;
+	set = 0x0000000F;
+	if (dev->dev->bus->chip_id == 0x4301) {
+		mask |= 0x0060;
+		set |= 0x0060;
+	}
+	if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_PACTRL) {
+		b43legacy_write16(dev, B43legacy_MMIO_GPIO_MASK,
+				  b43legacy_read16(dev,
+				  B43legacy_MMIO_GPIO_MASK)
+				  | 0x0200);
+		mask |= 0x0200;
+		set |= 0x0200;
+	}
+	if (dev->dev->id.revision >= 2)
+		mask  |= 0x0010; /* FIXME: This is redundant. */
+
+#ifdef CONFIG_SSB_DRIVER_PCICORE
+	pcidev = bus->pcicore.dev;
+#endif
+	gpiodev = bus->chipco.dev ? : pcidev;
+	if (!gpiodev)
+		return 0;
+	ssb_write32(gpiodev, B43legacy_GPIO_CONTROL,
+		    (ssb_read32(gpiodev, B43legacy_GPIO_CONTROL)
+		     & ~mask) | set);
+
+	return 0;
+}
+
+/* Turn off all GPIO stuff. Call this on module unload, for example. */
+static void b43legacy_gpio_cleanup(struct b43legacy_wldev *dev)
+{
+	struct ssb_bus *bus = dev->dev->bus;
+	struct ssb_device *gpiodev, *pcidev = NULL;
+
+#ifdef CONFIG_SSB_DRIVER_PCICORE
+	pcidev = bus->pcicore.dev;
+#endif
+	gpiodev = bus->chipco.dev ? : pcidev;
+	if (!gpiodev)
+		return;
+	ssb_write32(gpiodev, B43legacy_GPIO_CONTROL, 0);
+}
+
+/* http://bcm-specs.sipsolutions.net/EnableMac */
+void b43legacy_mac_enable(struct b43legacy_wldev *dev)
+{
+	dev->mac_suspended--;
+	B43legacy_WARN_ON(dev->mac_suspended < 0);
+	B43legacy_WARN_ON(irqs_disabled());
+	if (dev->mac_suspended == 0) {
+		b43legacy_write32(dev, B43legacy_MMIO_MACCTL,
+				  b43legacy_read32(dev,
+				  B43legacy_MMIO_MACCTL)
+				  | B43legacy_MACCTL_ENABLED);
+		b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON,
+				  B43legacy_IRQ_MAC_SUSPENDED);
+		/* the next two are dummy reads */
+		b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+		b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
+		b43legacy_power_saving_ctl_bits(dev, -1, -1);
+
+		/* Re-enable IRQs. */
+		spin_lock_irq(&dev->wl->irq_lock);
+		b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK,
+				  dev->irq_mask);
+		spin_unlock_irq(&dev->wl->irq_lock);
+	}
+}
+
+/* http://bcm-specs.sipsolutions.net/SuspendMAC */
+void b43legacy_mac_suspend(struct b43legacy_wldev *dev)
+{
+	int i;
+	u32 tmp;
+
+	might_sleep();
+	B43legacy_WARN_ON(irqs_disabled());
+	B43legacy_WARN_ON(dev->mac_suspended < 0);
+
+	if (dev->mac_suspended == 0) {
+		/* Mask IRQs before suspending MAC. Otherwise
+		 * the MAC stays busy and won't suspend. */
+		spin_lock_irq(&dev->wl->irq_lock);
+		b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
+		spin_unlock_irq(&dev->wl->irq_lock);
+		b43legacy_synchronize_irq(dev);
+
+		b43legacy_power_saving_ctl_bits(dev, -1, 1);
+		b43legacy_write32(dev, B43legacy_MMIO_MACCTL,
+				  b43legacy_read32(dev,
+				  B43legacy_MMIO_MACCTL)
+				  & ~B43legacy_MACCTL_ENABLED);
+		b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
+		for (i = 40; i; i--) {
+			tmp = b43legacy_read32(dev,
+					       B43legacy_MMIO_GEN_IRQ_REASON);
+			if (tmp & B43legacy_IRQ_MAC_SUSPENDED)
+				goto out;
+			msleep(1);
+		}
+		b43legacyerr(dev->wl, "MAC suspend failed\n");
+	}
+out:
+	dev->mac_suspended++;
+}
+
+static void b43legacy_adjust_opmode(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_wl *wl = dev->wl;
+	u32 ctl;
+	u16 cfp_pretbtt;
+
+	ctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	/* Reset status to STA infrastructure mode. */
+	ctl &= ~B43legacy_MACCTL_AP;
+	ctl &= ~B43legacy_MACCTL_KEEP_CTL;
+	ctl &= ~B43legacy_MACCTL_KEEP_BADPLCP;
+	ctl &= ~B43legacy_MACCTL_KEEP_BAD;
+	ctl &= ~B43legacy_MACCTL_PROMISC;
+	ctl &= ~B43legacy_MACCTL_BEACPROMISC;
+	ctl |= B43legacy_MACCTL_INFRA;
+
+	if (b43legacy_is_mode(wl, NL80211_IFTYPE_AP))
+		ctl |= B43legacy_MACCTL_AP;
+	else if (b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC))
+		ctl &= ~B43legacy_MACCTL_INFRA;
+
+	if (wl->filter_flags & FIF_CONTROL)
+		ctl |= B43legacy_MACCTL_KEEP_CTL;
+	if (wl->filter_flags & FIF_FCSFAIL)
+		ctl |= B43legacy_MACCTL_KEEP_BAD;
+	if (wl->filter_flags & FIF_PLCPFAIL)
+		ctl |= B43legacy_MACCTL_KEEP_BADPLCP;
+	if (wl->filter_flags & FIF_BCN_PRBRESP_PROMISC)
+		ctl |= B43legacy_MACCTL_BEACPROMISC;
+
+	/* Workaround: On old hardware the HW-MAC-address-filter
+	 * doesn't work properly, so always run promisc in filter
+	 * it in software. */
+	if (dev->dev->id.revision <= 4)
+		ctl |= B43legacy_MACCTL_PROMISC;
+
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, ctl);
+
+	cfp_pretbtt = 2;
+	if ((ctl & B43legacy_MACCTL_INFRA) &&
+	    !(ctl & B43legacy_MACCTL_AP)) {
+		if (dev->dev->bus->chip_id == 0x4306 &&
+		    dev->dev->bus->chip_rev == 3)
+			cfp_pretbtt = 100;
+		else
+			cfp_pretbtt = 50;
+	}
+	b43legacy_write16(dev, 0x612, cfp_pretbtt);
+}
+
+static void b43legacy_rate_memory_write(struct b43legacy_wldev *dev,
+					u16 rate,
+					int is_ofdm)
+{
+	u16 offset;
+
+	if (is_ofdm) {
+		offset = 0x480;
+		offset += (b43legacy_plcp_get_ratecode_ofdm(rate) & 0x000F) * 2;
+	} else {
+		offset = 0x4C0;
+		offset += (b43legacy_plcp_get_ratecode_cck(rate) & 0x000F) * 2;
+	}
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, offset + 0x20,
+			      b43legacy_shm_read16(dev,
+			      B43legacy_SHM_SHARED, offset));
+}
+
+static void b43legacy_rate_memory_init(struct b43legacy_wldev *dev)
+{
+	switch (dev->phy.type) {
+	case B43legacy_PHYTYPE_G:
+		b43legacy_rate_memory_write(dev, B43legacy_OFDM_RATE_6MB, 1);
+		b43legacy_rate_memory_write(dev, B43legacy_OFDM_RATE_12MB, 1);
+		b43legacy_rate_memory_write(dev, B43legacy_OFDM_RATE_18MB, 1);
+		b43legacy_rate_memory_write(dev, B43legacy_OFDM_RATE_24MB, 1);
+		b43legacy_rate_memory_write(dev, B43legacy_OFDM_RATE_36MB, 1);
+		b43legacy_rate_memory_write(dev, B43legacy_OFDM_RATE_48MB, 1);
+		b43legacy_rate_memory_write(dev, B43legacy_OFDM_RATE_54MB, 1);
+		/* fallthrough */
+	case B43legacy_PHYTYPE_B:
+		b43legacy_rate_memory_write(dev, B43legacy_CCK_RATE_1MB, 0);
+		b43legacy_rate_memory_write(dev, B43legacy_CCK_RATE_2MB, 0);
+		b43legacy_rate_memory_write(dev, B43legacy_CCK_RATE_5MB, 0);
+		b43legacy_rate_memory_write(dev, B43legacy_CCK_RATE_11MB, 0);
+		break;
+	default:
+		B43legacy_BUG_ON(1);
+	}
+}
+
+/* Set the TX-Antenna for management frames sent by firmware. */
+static void b43legacy_mgmtframe_txantenna(struct b43legacy_wldev *dev,
+					  int antenna)
+{
+	u16 ant = 0;
+	u16 tmp;
+
+	switch (antenna) {
+	case B43legacy_ANTENNA0:
+		ant |= B43legacy_TX4_PHY_ANT0;
+		break;
+	case B43legacy_ANTENNA1:
+		ant |= B43legacy_TX4_PHY_ANT1;
+		break;
+	case B43legacy_ANTENNA_AUTO:
+		ant |= B43legacy_TX4_PHY_ANTLAST;
+		break;
+	default:
+		B43legacy_BUG_ON(1);
+	}
+
+	/* FIXME We also need to set the other flags of the PHY control
+	 * field somewhere. */
+
+	/* For Beacons */
+	tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,
+				   B43legacy_SHM_SH_BEACPHYCTL);
+	tmp = (tmp & ~B43legacy_TX4_PHY_ANT) | ant;
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+			      B43legacy_SHM_SH_BEACPHYCTL, tmp);
+	/* For ACK/CTS */
+	tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,
+				   B43legacy_SHM_SH_ACKCTSPHYCTL);
+	tmp = (tmp & ~B43legacy_TX4_PHY_ANT) | ant;
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+			      B43legacy_SHM_SH_ACKCTSPHYCTL, tmp);
+	/* For Probe Resposes */
+	tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,
+				   B43legacy_SHM_SH_PRPHYCTL);
+	tmp = (tmp & ~B43legacy_TX4_PHY_ANT) | ant;
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+			      B43legacy_SHM_SH_PRPHYCTL, tmp);
+}
+
+/* This is the opposite of b43legacy_chip_init() */
+static void b43legacy_chip_exit(struct b43legacy_wldev *dev)
+{
+	b43legacy_radio_turn_off(dev, 1);
+	b43legacy_gpio_cleanup(dev);
+	/* firmware is released later */
+}
+
+/* Initialize the chip
+ * http://bcm-specs.sipsolutions.net/ChipInit
+ */
+static int b43legacy_chip_init(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	int err;
+	int tmp;
+	u32 value32, macctl;
+	u16 value16;
+
+	/* Initialize the MAC control */
+	macctl = B43legacy_MACCTL_IHR_ENABLED | B43legacy_MACCTL_SHM_ENABLED;
+	if (dev->phy.gmode)
+		macctl |= B43legacy_MACCTL_GMODE;
+	macctl |= B43legacy_MACCTL_INFRA;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
+
+	err = b43legacy_upload_microcode(dev);
+	if (err)
+		goto out; /* firmware is released later */
+
+	err = b43legacy_gpio_init(dev);
+	if (err)
+		goto out; /* firmware is released later */
+
+	err = b43legacy_upload_initvals(dev);
+	if (err)
+		goto err_gpio_clean;
+	b43legacy_radio_turn_on(dev);
+
+	b43legacy_write16(dev, 0x03E6, 0x0000);
+	err = b43legacy_phy_init(dev);
+	if (err)
+		goto err_radio_off;
+
+	/* Select initial Interference Mitigation. */
+	tmp = phy->interfmode;
+	phy->interfmode = B43legacy_INTERFMODE_NONE;
+	b43legacy_radio_set_interference_mitigation(dev, tmp);
+
+	b43legacy_phy_set_antenna_diversity(dev);
+	b43legacy_mgmtframe_txantenna(dev, B43legacy_ANTENNA_DEFAULT);
+
+	if (phy->type == B43legacy_PHYTYPE_B) {
+		value16 = b43legacy_read16(dev, 0x005E);
+		value16 |= 0x0004;
+		b43legacy_write16(dev, 0x005E, value16);
+	}
+	b43legacy_write32(dev, 0x0100, 0x01000000);
+	if (dev->dev->id.revision < 5)
+		b43legacy_write32(dev, 0x010C, 0x01000000);
+
+	value32 = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	value32 &= ~B43legacy_MACCTL_INFRA;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, value32);
+	value32 = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	value32 |= B43legacy_MACCTL_INFRA;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, value32);
+
+	if (b43legacy_using_pio(dev)) {
+		b43legacy_write32(dev, 0x0210, 0x00000100);
+		b43legacy_write32(dev, 0x0230, 0x00000100);
+		b43legacy_write32(dev, 0x0250, 0x00000100);
+		b43legacy_write32(dev, 0x0270, 0x00000100);
+		b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0034,
+				      0x0000);
+	}
+
+	/* Probe Response Timeout value */
+	/* FIXME: Default to 0, has to be set by ioctl probably... :-/ */
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0074, 0x0000);
+
+	/* Initially set the wireless operation mode. */
+	b43legacy_adjust_opmode(dev);
+
+	if (dev->dev->id.revision < 3) {
+		b43legacy_write16(dev, 0x060E, 0x0000);
+		b43legacy_write16(dev, 0x0610, 0x8000);
+		b43legacy_write16(dev, 0x0604, 0x0000);
+		b43legacy_write16(dev, 0x0606, 0x0200);
+	} else {
+		b43legacy_write32(dev, 0x0188, 0x80000000);
+		b43legacy_write32(dev, 0x018C, 0x02000000);
+	}
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, 0x00004000);
+	b43legacy_write32(dev, B43legacy_MMIO_DMA0_IRQ_MASK, 0x0001DC00);
+	b43legacy_write32(dev, B43legacy_MMIO_DMA1_IRQ_MASK, 0x0000DC00);
+	b43legacy_write32(dev, B43legacy_MMIO_DMA2_IRQ_MASK, 0x0000DC00);
+	b43legacy_write32(dev, B43legacy_MMIO_DMA3_IRQ_MASK, 0x0001DC00);
+	b43legacy_write32(dev, B43legacy_MMIO_DMA4_IRQ_MASK, 0x0000DC00);
+	b43legacy_write32(dev, B43legacy_MMIO_DMA5_IRQ_MASK, 0x0000DC00);
+
+	value32 = ssb_read32(dev->dev, SSB_TMSLOW);
+	value32 |= B43legacy_TMSLOW_MACPHYCLKEN;
+	ssb_write32(dev->dev, SSB_TMSLOW, value32);
+
+	b43legacy_write16(dev, B43legacy_MMIO_POWERUP_DELAY,
+			  dev->dev->bus->chipco.fast_pwrup_delay);
+
+	/* PHY TX errors counter. */
+	atomic_set(&phy->txerr_cnt, B43legacy_PHY_TX_BADNESS_LIMIT);
+
+	B43legacy_WARN_ON(err != 0);
+	b43legacydbg(dev->wl, "Chip initialized\n");
+out:
+	return err;
+
+err_radio_off:
+	b43legacy_radio_turn_off(dev, 1);
+err_gpio_clean:
+	b43legacy_gpio_cleanup(dev);
+	goto out;
+}
+
+static void b43legacy_periodic_every120sec(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+
+	if (phy->type != B43legacy_PHYTYPE_G || phy->rev < 2)
+		return;
+
+	b43legacy_mac_suspend(dev);
+	b43legacy_phy_lo_g_measure(dev);
+	b43legacy_mac_enable(dev);
+}
+
+static void b43legacy_periodic_every60sec(struct b43legacy_wldev *dev)
+{
+	b43legacy_phy_lo_mark_all_unused(dev);
+	if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_RSSI) {
+		b43legacy_mac_suspend(dev);
+		b43legacy_calc_nrssi_slope(dev);
+		b43legacy_mac_enable(dev);
+	}
+}
+
+static void b43legacy_periodic_every30sec(struct b43legacy_wldev *dev)
+{
+	/* Update device statistics. */
+	b43legacy_calculate_link_quality(dev);
+}
+
+static void b43legacy_periodic_every15sec(struct b43legacy_wldev *dev)
+{
+	b43legacy_phy_xmitpower(dev); /* FIXME: unless scanning? */
+
+	atomic_set(&dev->phy.txerr_cnt, B43legacy_PHY_TX_BADNESS_LIMIT);
+	wmb();
+}
+
+static void do_periodic_work(struct b43legacy_wldev *dev)
+{
+	unsigned int state;
+
+	state = dev->periodic_state;
+	if (state % 8 == 0)
+		b43legacy_periodic_every120sec(dev);
+	if (state % 4 == 0)
+		b43legacy_periodic_every60sec(dev);
+	if (state % 2 == 0)
+		b43legacy_periodic_every30sec(dev);
+	b43legacy_periodic_every15sec(dev);
+}
+
+/* Periodic work locking policy:
+ * 	The whole periodic work handler is protected by
+ * 	wl->mutex. If another lock is needed somewhere in the
+ * 	pwork callchain, it's acquired in-place, where it's needed.
+ */
+static void b43legacy_periodic_work_handler(struct work_struct *work)
+{
+	struct b43legacy_wldev *dev = container_of(work, struct b43legacy_wldev,
+					     periodic_work.work);
+	struct b43legacy_wl *wl = dev->wl;
+	unsigned long delay;
+
+	mutex_lock(&wl->mutex);
+
+	if (unlikely(b43legacy_status(dev) != B43legacy_STAT_STARTED))
+		goto out;
+	if (b43legacy_debug(dev, B43legacy_DBG_PWORK_STOP))
+		goto out_requeue;
+
+	do_periodic_work(dev);
+
+	dev->periodic_state++;
+out_requeue:
+	if (b43legacy_debug(dev, B43legacy_DBG_PWORK_FAST))
+		delay = msecs_to_jiffies(50);
+	else
+		delay = round_jiffies_relative(HZ * 15);
+	ieee80211_queue_delayed_work(wl->hw, &dev->periodic_work, delay);
+out:
+	mutex_unlock(&wl->mutex);
+}
+
+static void b43legacy_periodic_tasks_setup(struct b43legacy_wldev *dev)
+{
+	struct delayed_work *work = &dev->periodic_work;
+
+	dev->periodic_state = 0;
+	INIT_DELAYED_WORK(work, b43legacy_periodic_work_handler);
+	ieee80211_queue_delayed_work(dev->wl->hw, work, 0);
+}
+
+/* Validate access to the chip (SHM) */
+static int b43legacy_validate_chipaccess(struct b43legacy_wldev *dev)
+{
+	u32 value;
+	u32 shm_backup;
+
+	shm_backup = b43legacy_shm_read32(dev, B43legacy_SHM_SHARED, 0);
+	b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, 0, 0xAA5555AA);
+	if (b43legacy_shm_read32(dev, B43legacy_SHM_SHARED, 0) !=
+				 0xAA5555AA)
+		goto error;
+	b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, 0, 0x55AAAA55);
+	if (b43legacy_shm_read32(dev, B43legacy_SHM_SHARED, 0) !=
+				 0x55AAAA55)
+		goto error;
+	b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, 0, shm_backup);
+
+	value = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	if ((value | B43legacy_MACCTL_GMODE) !=
+	    (B43legacy_MACCTL_GMODE | B43legacy_MACCTL_IHR_ENABLED))
+		goto error;
+
+	value = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
+	if (value)
+		goto error;
+
+	return 0;
+error:
+	b43legacyerr(dev->wl, "Failed to validate the chipaccess\n");
+	return -ENODEV;
+}
+
+static void b43legacy_security_init(struct b43legacy_wldev *dev)
+{
+	dev->max_nr_keys = (dev->dev->id.revision >= 5) ? 58 : 20;
+	B43legacy_WARN_ON(dev->max_nr_keys > ARRAY_SIZE(dev->key));
+	dev->ktp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,
+					0x0056);
+	/* KTP is a word address, but we address SHM bytewise.
+	 * So multiply by two.
+	 */
+	dev->ktp *= 2;
+	if (dev->dev->id.revision >= 5)
+		/* Number of RCMTA address slots */
+		b43legacy_write16(dev, B43legacy_MMIO_RCMTA_COUNT,
+				  dev->max_nr_keys - 8);
+}
+
+#ifdef CONFIG_B43LEGACY_HWRNG
+static int b43legacy_rng_read(struct hwrng *rng, u32 *data)
+{
+	struct b43legacy_wl *wl = (struct b43legacy_wl *)rng->priv;
+	unsigned long flags;
+
+	/* Don't take wl->mutex here, as it could deadlock with
+	 * hwrng internal locking. It's not needed to take
+	 * wl->mutex here, anyway. */
+
+	spin_lock_irqsave(&wl->irq_lock, flags);
+	*data = b43legacy_read16(wl->current_dev, B43legacy_MMIO_RNG);
+	spin_unlock_irqrestore(&wl->irq_lock, flags);
+
+	return (sizeof(u16));
+}
+#endif
+
+static void b43legacy_rng_exit(struct b43legacy_wl *wl)
+{
+#ifdef CONFIG_B43LEGACY_HWRNG
+	if (wl->rng_initialized)
+		hwrng_unregister(&wl->rng);
+#endif
+}
+
+static int b43legacy_rng_init(struct b43legacy_wl *wl)
+{
+	int err = 0;
+
+#ifdef CONFIG_B43LEGACY_HWRNG
+	snprintf(wl->rng_name, ARRAY_SIZE(wl->rng_name),
+		 "%s_%s", KBUILD_MODNAME, wiphy_name(wl->hw->wiphy));
+	wl->rng.name = wl->rng_name;
+	wl->rng.data_read = b43legacy_rng_read;
+	wl->rng.priv = (unsigned long)wl;
+	wl->rng_initialized = 1;
+	err = hwrng_register(&wl->rng);
+	if (err) {
+		wl->rng_initialized = 0;
+		b43legacyerr(wl, "Failed to register the random "
+		       "number generator (%d)\n", err);
+	}
+
+#endif
+	return err;
+}
+
+static void b43legacy_tx_work(struct work_struct *work)
+{
+	struct b43legacy_wl *wl = container_of(work, struct b43legacy_wl,
+				  tx_work);
+	struct b43legacy_wldev *dev;
+	struct sk_buff *skb;
+	int queue_num;
+	int err = 0;
+
+	mutex_lock(&wl->mutex);
+	dev = wl->current_dev;
+	if (unlikely(!dev || b43legacy_status(dev) < B43legacy_STAT_STARTED)) {
+		mutex_unlock(&wl->mutex);
+		return;
+	}
+
+	for (queue_num = 0; queue_num < B43legacy_QOS_QUEUE_NUM; queue_num++) {
+		while (skb_queue_len(&wl->tx_queue[queue_num])) {
+			skb = skb_dequeue(&wl->tx_queue[queue_num]);
+			if (b43legacy_using_pio(dev))
+				err = b43legacy_pio_tx(dev, skb);
+			else
+				err = b43legacy_dma_tx(dev, skb);
+			if (err == -ENOSPC) {
+				wl->tx_queue_stopped[queue_num] = 1;
+				ieee80211_stop_queue(wl->hw, queue_num);
+				skb_queue_head(&wl->tx_queue[queue_num], skb);
+				break;
+			}
+			if (unlikely(err))
+				dev_kfree_skb(skb); /* Drop it */
+			err = 0;
+		}
+
+		if (!err)
+			wl->tx_queue_stopped[queue_num] = 0;
+	}
+
+	mutex_unlock(&wl->mutex);
+}
+
+static void b43legacy_op_tx(struct ieee80211_hw *hw,
+			    struct ieee80211_tx_control *control,
+			    struct sk_buff *skb)
+{
+	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
+
+	if (unlikely(skb->len < 2 + 2 + 6)) {
+		/* Too short, this can't be a valid frame. */
+		dev_kfree_skb_any(skb);
+		return;
+	}
+	B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags);
+
+	skb_queue_tail(&wl->tx_queue[skb->queue_mapping], skb);
+	if (!wl->tx_queue_stopped[skb->queue_mapping])
+		ieee80211_queue_work(wl->hw, &wl->tx_work);
+	else
+		ieee80211_stop_queue(wl->hw, skb->queue_mapping);
+}
+
+static int b43legacy_op_conf_tx(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif, u16 queue,
+				const struct ieee80211_tx_queue_params *params)
+{
+	return 0;
+}
+
+static int b43legacy_op_get_stats(struct ieee80211_hw *hw,
+				  struct ieee80211_low_level_stats *stats)
+{
+	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
+	unsigned long flags;
+
+	spin_lock_irqsave(&wl->irq_lock, flags);
+	memcpy(stats, &wl->ieee_stats, sizeof(*stats));
+	spin_unlock_irqrestore(&wl->irq_lock, flags);
+
+	return 0;
+}
+
+static const char *phymode_to_string(unsigned int phymode)
+{
+	switch (phymode) {
+	case B43legacy_PHYMODE_B:
+		return "B";
+	case B43legacy_PHYMODE_G:
+		return "G";
+	default:
+		B43legacy_BUG_ON(1);
+	}
+	return "";
+}
+
+static int find_wldev_for_phymode(struct b43legacy_wl *wl,
+				  unsigned int phymode,
+				  struct b43legacy_wldev **dev,
+				  bool *gmode)
+{
+	struct b43legacy_wldev *d;
+
+	list_for_each_entry(d, &wl->devlist, list) {
+		if (d->phy.possible_phymodes & phymode) {
+			/* Ok, this device supports the PHY-mode.
+			 * Set the gmode bit. */
+			*gmode = true;
+			*dev = d;
+
+			return 0;
+		}
+	}
+
+	return -ESRCH;
+}
+
+static void b43legacy_put_phy_into_reset(struct b43legacy_wldev *dev)
+{
+	struct ssb_device *sdev = dev->dev;
+	u32 tmslow;
+
+	tmslow = ssb_read32(sdev, SSB_TMSLOW);
+	tmslow &= ~B43legacy_TMSLOW_GMODE;
+	tmslow |= B43legacy_TMSLOW_PHYRESET;
+	tmslow |= SSB_TMSLOW_FGC;
+	ssb_write32(sdev, SSB_TMSLOW, tmslow);
+	msleep(1);
+
+	tmslow = ssb_read32(sdev, SSB_TMSLOW);
+	tmslow &= ~SSB_TMSLOW_FGC;
+	tmslow |= B43legacy_TMSLOW_PHYRESET;
+	ssb_write32(sdev, SSB_TMSLOW, tmslow);
+	msleep(1);
+}
+
+/* Expects wl->mutex locked */
+static int b43legacy_switch_phymode(struct b43legacy_wl *wl,
+				      unsigned int new_mode)
+{
+	struct b43legacy_wldev *uninitialized_var(up_dev);
+	struct b43legacy_wldev *down_dev;
+	int err;
+	bool gmode = false;
+	int prev_status;
+
+	err = find_wldev_for_phymode(wl, new_mode, &up_dev, &gmode);
+	if (err) {
+		b43legacyerr(wl, "Could not find a device for %s-PHY mode\n",
+		       phymode_to_string(new_mode));
+		return err;
+	}
+	if ((up_dev == wl->current_dev) &&
+	    (!!wl->current_dev->phy.gmode == !!gmode))
+		/* This device is already running. */
+		return 0;
+	b43legacydbg(wl, "Reconfiguring PHYmode to %s-PHY\n",
+	       phymode_to_string(new_mode));
+	down_dev = wl->current_dev;
+
+	prev_status = b43legacy_status(down_dev);
+	/* Shutdown the currently running core. */
+	if (prev_status >= B43legacy_STAT_STARTED)
+		b43legacy_wireless_core_stop(down_dev);
+	if (prev_status >= B43legacy_STAT_INITIALIZED)
+		b43legacy_wireless_core_exit(down_dev);
+
+	if (down_dev != up_dev)
+		/* We switch to a different core, so we put PHY into
+		 * RESET on the old core. */
+		b43legacy_put_phy_into_reset(down_dev);
+
+	/* Now start the new core. */
+	up_dev->phy.gmode = gmode;
+	if (prev_status >= B43legacy_STAT_INITIALIZED) {
+		err = b43legacy_wireless_core_init(up_dev);
+		if (err) {
+			b43legacyerr(wl, "Fatal: Could not initialize device"
+				     " for newly selected %s-PHY mode\n",
+				     phymode_to_string(new_mode));
+			goto init_failure;
+		}
+	}
+	if (prev_status >= B43legacy_STAT_STARTED) {
+		err = b43legacy_wireless_core_start(up_dev);
+		if (err) {
+			b43legacyerr(wl, "Fatal: Could not start device for "
+			       "newly selected %s-PHY mode\n",
+			       phymode_to_string(new_mode));
+			b43legacy_wireless_core_exit(up_dev);
+			goto init_failure;
+		}
+	}
+	B43legacy_WARN_ON(b43legacy_status(up_dev) != prev_status);
+
+	b43legacy_shm_write32(up_dev, B43legacy_SHM_SHARED, 0x003E, 0);
+
+	wl->current_dev = up_dev;
+
+	return 0;
+init_failure:
+	/* Whoops, failed to init the new core. No core is operating now. */
+	wl->current_dev = NULL;
+	return err;
+}
+
+/* Write the short and long frame retry limit values. */
+static void b43legacy_set_retry_limits(struct b43legacy_wldev *dev,
+				       unsigned int short_retry,
+				       unsigned int long_retry)
+{
+	/* The retry limit is a 4-bit counter. Enforce this to avoid overflowing
+	 * the chip-internal counter. */
+	short_retry = min(short_retry, (unsigned int)0xF);
+	long_retry = min(long_retry, (unsigned int)0xF);
+
+	b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0006, short_retry);
+	b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry);
+}
+
+static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
+				   u32 changed)
+{
+	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
+	struct b43legacy_wldev *dev;
+	struct b43legacy_phy *phy;
+	struct ieee80211_conf *conf = &hw->conf;
+	unsigned long flags;
+	unsigned int new_phymode = 0xFFFF;
+	int antenna_tx;
+	int err = 0;
+
+	antenna_tx = B43legacy_ANTENNA_DEFAULT;
+
+	mutex_lock(&wl->mutex);
+	dev = wl->current_dev;
+	phy = &dev->phy;
+
+	if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+		b43legacy_set_retry_limits(dev,
+					   conf->short_frame_max_tx_count,
+					   conf->long_frame_max_tx_count);
+	changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS;
+	if (!changed)
+		goto out_unlock_mutex;
+
+	/* Switch the PHY mode (if necessary). */
+	switch (conf->chandef.chan->band) {
+	case NL80211_BAND_2GHZ:
+		if (phy->type == B43legacy_PHYTYPE_B)
+			new_phymode = B43legacy_PHYMODE_B;
+		else
+			new_phymode = B43legacy_PHYMODE_G;
+		break;
+	default:
+		B43legacy_WARN_ON(1);
+	}
+	err = b43legacy_switch_phymode(wl, new_phymode);
+	if (err)
+		goto out_unlock_mutex;
+
+	/* Disable IRQs while reconfiguring the device.
+	 * This makes it possible to drop the spinlock throughout
+	 * the reconfiguration process. */
+	spin_lock_irqsave(&wl->irq_lock, flags);
+	if (b43legacy_status(dev) < B43legacy_STAT_STARTED) {
+		spin_unlock_irqrestore(&wl->irq_lock, flags);
+		goto out_unlock_mutex;
+	}
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
+	spin_unlock_irqrestore(&wl->irq_lock, flags);
+	b43legacy_synchronize_irq(dev);
+
+	/* Switch to the requested channel.
+	 * The firmware takes care of races with the TX handler. */
+	if (conf->chandef.chan->hw_value != phy->channel)
+		b43legacy_radio_selectchannel(dev, conf->chandef.chan->hw_value,
+					      0);
+
+	dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_MONITOR);
+
+	/* Adjust the desired TX power level. */
+	if (conf->power_level != 0) {
+		if (conf->power_level != phy->power_level) {
+			phy->power_level = conf->power_level;
+			b43legacy_phy_xmitpower(dev);
+		}
+	}
+
+	/* Antennas for RX and management frame TX. */
+	b43legacy_mgmtframe_txantenna(dev, antenna_tx);
+
+	if (wl->radio_enabled != phy->radio_on) {
+		if (wl->radio_enabled) {
+			b43legacy_radio_turn_on(dev);
+			b43legacyinfo(dev->wl, "Radio turned on by software\n");
+			if (!dev->radio_hw_enable)
+				b43legacyinfo(dev->wl, "The hardware RF-kill"
+					      " button still turns the radio"
+					      " physically off. Press the"
+					      " button to turn it on.\n");
+		} else {
+			b43legacy_radio_turn_off(dev, 0);
+			b43legacyinfo(dev->wl, "Radio turned off by"
+				      " software\n");
+		}
+	}
+
+	spin_lock_irqsave(&wl->irq_lock, flags);
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask);
+	mmiowb();
+	spin_unlock_irqrestore(&wl->irq_lock, flags);
+out_unlock_mutex:
+	mutex_unlock(&wl->mutex);
+
+	return err;
+}
+
+static void b43legacy_update_basic_rates(struct b43legacy_wldev *dev, u32 brates)
+{
+	struct ieee80211_supported_band *sband =
+		dev->wl->hw->wiphy->bands[NL80211_BAND_2GHZ];
+	struct ieee80211_rate *rate;
+	int i;
+	u16 basic, direct, offset, basic_offset, rateptr;
+
+	for (i = 0; i < sband->n_bitrates; i++) {
+		rate = &sband->bitrates[i];
+
+		if (b43legacy_is_cck_rate(rate->hw_value)) {
+			direct = B43legacy_SHM_SH_CCKDIRECT;
+			basic = B43legacy_SHM_SH_CCKBASIC;
+			offset = b43legacy_plcp_get_ratecode_cck(rate->hw_value);
+			offset &= 0xF;
+		} else {
+			direct = B43legacy_SHM_SH_OFDMDIRECT;
+			basic = B43legacy_SHM_SH_OFDMBASIC;
+			offset = b43legacy_plcp_get_ratecode_ofdm(rate->hw_value);
+			offset &= 0xF;
+		}
+
+		rate = ieee80211_get_response_rate(sband, brates, rate->bitrate);
+
+		if (b43legacy_is_cck_rate(rate->hw_value)) {
+			basic_offset = b43legacy_plcp_get_ratecode_cck(rate->hw_value);
+			basic_offset &= 0xF;
+		} else {
+			basic_offset = b43legacy_plcp_get_ratecode_ofdm(rate->hw_value);
+			basic_offset &= 0xF;
+		}
+
+		/*
+		 * Get the pointer that we need to point to
+		 * from the direct map
+		 */
+		rateptr = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,
+					       direct + 2 * basic_offset);
+		/* and write it to the basic map */
+		b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+				      basic + 2 * offset, rateptr);
+	}
+}
+
+static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw,
+				    struct ieee80211_vif *vif,
+				    struct ieee80211_bss_conf *conf,
+				    u32 changed)
+{
+	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
+	struct b43legacy_wldev *dev;
+	unsigned long flags;
+
+	mutex_lock(&wl->mutex);
+	B43legacy_WARN_ON(wl->vif != vif);
+
+	dev = wl->current_dev;
+
+	/* Disable IRQs while reconfiguring the device.
+	 * This makes it possible to drop the spinlock throughout
+	 * the reconfiguration process. */
+	spin_lock_irqsave(&wl->irq_lock, flags);
+	if (b43legacy_status(dev) < B43legacy_STAT_STARTED) {
+		spin_unlock_irqrestore(&wl->irq_lock, flags);
+		goto out_unlock_mutex;
+	}
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
+
+	if (changed & BSS_CHANGED_BSSID) {
+		b43legacy_synchronize_irq(dev);
+
+		if (conf->bssid)
+			memcpy(wl->bssid, conf->bssid, ETH_ALEN);
+		else
+			eth_zero_addr(wl->bssid);
+	}
+
+	if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) {
+		if (changed & BSS_CHANGED_BEACON &&
+		    (b43legacy_is_mode(wl, NL80211_IFTYPE_AP) ||
+		     b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC)))
+			b43legacy_update_templates(wl);
+
+		if (changed & BSS_CHANGED_BSSID)
+			b43legacy_write_mac_bssid_templates(dev);
+	}
+	spin_unlock_irqrestore(&wl->irq_lock, flags);
+
+	b43legacy_mac_suspend(dev);
+
+	if (changed & BSS_CHANGED_BEACON_INT &&
+	    (b43legacy_is_mode(wl, NL80211_IFTYPE_AP) ||
+	     b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC)))
+		b43legacy_set_beacon_int(dev, conf->beacon_int);
+
+	if (changed & BSS_CHANGED_BASIC_RATES)
+		b43legacy_update_basic_rates(dev, conf->basic_rates);
+
+	if (changed & BSS_CHANGED_ERP_SLOT) {
+		if (conf->use_short_slot)
+			b43legacy_short_slot_timing_enable(dev);
+		else
+			b43legacy_short_slot_timing_disable(dev);
+	}
+
+	b43legacy_mac_enable(dev);
+
+	spin_lock_irqsave(&wl->irq_lock, flags);
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask);
+	/* XXX: why? */
+	mmiowb();
+	spin_unlock_irqrestore(&wl->irq_lock, flags);
+ out_unlock_mutex:
+	mutex_unlock(&wl->mutex);
+}
+
+static void b43legacy_op_configure_filter(struct ieee80211_hw *hw,
+					  unsigned int changed,
+					  unsigned int *fflags,u64 multicast)
+{
+	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
+	struct b43legacy_wldev *dev = wl->current_dev;
+	unsigned long flags;
+
+	if (!dev) {
+		*fflags = 0;
+		return;
+	}
+
+	spin_lock_irqsave(&wl->irq_lock, flags);
+	*fflags &= FIF_ALLMULTI |
+		  FIF_FCSFAIL |
+		  FIF_PLCPFAIL |
+		  FIF_CONTROL |
+		  FIF_OTHER_BSS |
+		  FIF_BCN_PRBRESP_PROMISC;
+
+	changed &= FIF_ALLMULTI |
+		   FIF_FCSFAIL |
+		   FIF_PLCPFAIL |
+		   FIF_CONTROL |
+		   FIF_OTHER_BSS |
+		   FIF_BCN_PRBRESP_PROMISC;
+
+	wl->filter_flags = *fflags;
+
+	if (changed && b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED)
+		b43legacy_adjust_opmode(dev);
+	spin_unlock_irqrestore(&wl->irq_lock, flags);
+}
+
+/* Locking: wl->mutex */
+static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_wl *wl = dev->wl;
+	unsigned long flags;
+	int queue_num;
+
+	if (b43legacy_status(dev) < B43legacy_STAT_STARTED)
+		return;
+
+	/* Disable and sync interrupts. We must do this before than
+	 * setting the status to INITIALIZED, as the interrupt handler
+	 * won't care about IRQs then. */
+	spin_lock_irqsave(&wl->irq_lock, flags);
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
+	b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */
+	spin_unlock_irqrestore(&wl->irq_lock, flags);
+	b43legacy_synchronize_irq(dev);
+
+	b43legacy_set_status(dev, B43legacy_STAT_INITIALIZED);
+
+	mutex_unlock(&wl->mutex);
+	/* Must unlock as it would otherwise deadlock. No races here.
+	 * Cancel the possibly running self-rearming periodic work. */
+	cancel_delayed_work_sync(&dev->periodic_work);
+	cancel_work_sync(&wl->tx_work);
+	mutex_lock(&wl->mutex);
+
+	/* Drain all TX queues. */
+	for (queue_num = 0; queue_num < B43legacy_QOS_QUEUE_NUM; queue_num++) {
+		while (skb_queue_len(&wl->tx_queue[queue_num]))
+			dev_kfree_skb(skb_dequeue(&wl->tx_queue[queue_num]));
+	}
+
+b43legacy_mac_suspend(dev);
+	free_irq(dev->dev->irq, dev);
+	b43legacydbg(wl, "Wireless interface stopped\n");
+}
+
+/* Locking: wl->mutex */
+static int b43legacy_wireless_core_start(struct b43legacy_wldev *dev)
+{
+	int err;
+
+	B43legacy_WARN_ON(b43legacy_status(dev) != B43legacy_STAT_INITIALIZED);
+
+	drain_txstatus_queue(dev);
+	err = request_irq(dev->dev->irq, b43legacy_interrupt_handler,
+			  IRQF_SHARED, KBUILD_MODNAME, dev);
+	if (err) {
+		b43legacyerr(dev->wl, "Cannot request IRQ-%d\n",
+		       dev->dev->irq);
+		goto out;
+	}
+	/* We are ready to run. */
+	ieee80211_wake_queues(dev->wl->hw);
+	b43legacy_set_status(dev, B43legacy_STAT_STARTED);
+
+	/* Start data flow (TX/RX) */
+	b43legacy_mac_enable(dev);
+	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask);
+
+	/* Start maintenance work */
+	b43legacy_periodic_tasks_setup(dev);
+
+	b43legacydbg(dev->wl, "Wireless interface started\n");
+out:
+	return err;
+}
+
+/* Get PHY and RADIO versioning numbers */
+static int b43legacy_phy_versioning(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u32 tmp;
+	u8 analog_type;
+	u8 phy_type;
+	u8 phy_rev;
+	u16 radio_manuf;
+	u16 radio_ver;
+	u16 radio_rev;
+	int unsupported = 0;
+
+	/* Get PHY versioning */
+	tmp = b43legacy_read16(dev, B43legacy_MMIO_PHY_VER);
+	analog_type = (tmp & B43legacy_PHYVER_ANALOG)
+		      >> B43legacy_PHYVER_ANALOG_SHIFT;
+	phy_type = (tmp & B43legacy_PHYVER_TYPE) >> B43legacy_PHYVER_TYPE_SHIFT;
+	phy_rev = (tmp & B43legacy_PHYVER_VERSION);
+	switch (phy_type) {
+	case B43legacy_PHYTYPE_B:
+		if (phy_rev != 2 && phy_rev != 4
+		    && phy_rev != 6 && phy_rev != 7)
+			unsupported = 1;
+		break;
+	case B43legacy_PHYTYPE_G:
+		if (phy_rev > 8)
+			unsupported = 1;
+		break;
+	default:
+		unsupported = 1;
+	}
+	if (unsupported) {
+		b43legacyerr(dev->wl, "FOUND UNSUPPORTED PHY "
+		       "(Analog %u, Type %u, Revision %u)\n",
+		       analog_type, phy_type, phy_rev);
+		return -EOPNOTSUPP;
+	}
+	b43legacydbg(dev->wl, "Found PHY: Analog %u, Type %u, Revision %u\n",
+	       analog_type, phy_type, phy_rev);
+
+
+	/* Get RADIO versioning */
+	if (dev->dev->bus->chip_id == 0x4317) {
+		if (dev->dev->bus->chip_rev == 0)
+			tmp = 0x3205017F;
+		else if (dev->dev->bus->chip_rev == 1)
+			tmp = 0x4205017F;
+		else
+			tmp = 0x5205017F;
+	} else {
+		b43legacy_write16(dev, B43legacy_MMIO_RADIO_CONTROL,
+				  B43legacy_RADIOCTL_ID);
+		tmp = b43legacy_read16(dev, B43legacy_MMIO_RADIO_DATA_HIGH);
+		tmp <<= 16;
+		b43legacy_write16(dev, B43legacy_MMIO_RADIO_CONTROL,
+				  B43legacy_RADIOCTL_ID);
+		tmp |= b43legacy_read16(dev, B43legacy_MMIO_RADIO_DATA_LOW);
+	}
+	radio_manuf = (tmp & 0x00000FFF);
+	radio_ver = (tmp & 0x0FFFF000) >> 12;
+	radio_rev = (tmp & 0xF0000000) >> 28;
+	switch (phy_type) {
+	case B43legacy_PHYTYPE_B:
+		if ((radio_ver & 0xFFF0) != 0x2050)
+			unsupported = 1;
+		break;
+	case B43legacy_PHYTYPE_G:
+		if (radio_ver != 0x2050)
+			unsupported = 1;
+		break;
+	default:
+		B43legacy_BUG_ON(1);
+	}
+	if (unsupported) {
+		b43legacyerr(dev->wl, "FOUND UNSUPPORTED RADIO "
+		       "(Manuf 0x%X, Version 0x%X, Revision %u)\n",
+		       radio_manuf, radio_ver, radio_rev);
+		return -EOPNOTSUPP;
+	}
+	b43legacydbg(dev->wl, "Found Radio: Manuf 0x%X, Version 0x%X,"
+		     " Revision %u\n", radio_manuf, radio_ver, radio_rev);
+
+
+	phy->radio_manuf = radio_manuf;
+	phy->radio_ver = radio_ver;
+	phy->radio_rev = radio_rev;
+
+	phy->analog = analog_type;
+	phy->type = phy_type;
+	phy->rev = phy_rev;
+
+	return 0;
+}
+
+static void setup_struct_phy_for_init(struct b43legacy_wldev *dev,
+				      struct b43legacy_phy *phy)
+{
+	struct b43legacy_lopair *lo;
+	int i;
+
+	memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig));
+	memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos));
+
+	/* Assume the radio is enabled. If it's not enabled, the state will
+	 * immediately get fixed on the first periodic work run. */
+	dev->radio_hw_enable = true;
+
+	phy->savedpctlreg = 0xFFFF;
+	phy->aci_enable = false;
+	phy->aci_wlan_automatic = false;
+	phy->aci_hw_rssi = false;
+
+	lo = phy->_lo_pairs;
+	if (lo)
+		memset(lo, 0, sizeof(struct b43legacy_lopair) *
+				     B43legacy_LO_COUNT);
+	phy->max_lb_gain = 0;
+	phy->trsw_rx_gain = 0;
+
+	/* Set default attenuation values. */
+	phy->bbatt = b43legacy_default_baseband_attenuation(dev);
+	phy->rfatt = b43legacy_default_radio_attenuation(dev);
+	phy->txctl1 = b43legacy_default_txctl1(dev);
+	phy->txpwr_offset = 0;
+
+	/* NRSSI */
+	phy->nrssislope = 0;
+	for (i = 0; i < ARRAY_SIZE(phy->nrssi); i++)
+		phy->nrssi[i] = -1000;
+	for (i = 0; i < ARRAY_SIZE(phy->nrssi_lt); i++)
+		phy->nrssi_lt[i] = i;
+
+	phy->lofcal = 0xFFFF;
+	phy->initval = 0xFFFF;
+
+	phy->interfmode = B43legacy_INTERFMODE_NONE;
+	phy->channel = 0xFF;
+}
+
+static void setup_struct_wldev_for_init(struct b43legacy_wldev *dev)
+{
+	/* Flags */
+	dev->dfq_valid = false;
+
+	/* Stats */
+	memset(&dev->stats, 0, sizeof(dev->stats));
+
+	setup_struct_phy_for_init(dev, &dev->phy);
+
+	/* IRQ related flags */
+	dev->irq_reason = 0;
+	memset(dev->dma_reason, 0, sizeof(dev->dma_reason));
+	dev->irq_mask = B43legacy_IRQ_MASKTEMPLATE;
+
+	dev->mac_suspended = 1;
+
+	/* Noise calculation context */
+	memset(&dev->noisecalc, 0, sizeof(dev->noisecalc));
+}
+
+static void b43legacy_set_synth_pu_delay(struct b43legacy_wldev *dev,
+					  bool idle) {
+	u16 pu_delay = 1050;
+
+	if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_ADHOC) || idle)
+		pu_delay = 500;
+	if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8))
+		pu_delay = max(pu_delay, (u16)2400);
+
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+			      B43legacy_SHM_SH_SPUWKUP, pu_delay);
+}
+
+/* Set the TSF CFP pre-TargetBeaconTransmissionTime. */
+static void b43legacy_set_pretbtt(struct b43legacy_wldev *dev)
+{
+	u16 pretbtt;
+
+	/* The time value is in microseconds. */
+	if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_ADHOC))
+		pretbtt = 2;
+	else
+		pretbtt = 250;
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+			      B43legacy_SHM_SH_PRETBTT, pretbtt);
+	b43legacy_write16(dev, B43legacy_MMIO_TSF_CFP_PRETBTT, pretbtt);
+}
+
+/* Shutdown a wireless core */
+/* Locking: wl->mutex */
+static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u32 macctl;
+
+	B43legacy_WARN_ON(b43legacy_status(dev) > B43legacy_STAT_INITIALIZED);
+	if (b43legacy_status(dev) != B43legacy_STAT_INITIALIZED)
+		return;
+	b43legacy_set_status(dev, B43legacy_STAT_UNINIT);
+
+	/* Stop the microcode PSM. */
+	macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	macctl &= ~B43legacy_MACCTL_PSM_RUN;
+	macctl |= B43legacy_MACCTL_PSM_JMP0;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
+
+	b43legacy_leds_exit(dev);
+	b43legacy_rng_exit(dev->wl);
+	b43legacy_pio_free(dev);
+	b43legacy_dma_free(dev);
+	b43legacy_chip_exit(dev);
+	b43legacy_radio_turn_off(dev, 1);
+	b43legacy_switch_analog(dev, 0);
+	if (phy->dyn_tssi_tbl)
+		kfree(phy->tssi2dbm);
+	kfree(phy->lo_control);
+	phy->lo_control = NULL;
+	if (dev->wl->current_beacon) {
+		dev_kfree_skb_any(dev->wl->current_beacon);
+		dev->wl->current_beacon = NULL;
+	}
+
+	ssb_device_disable(dev->dev, 0);
+	ssb_bus_may_powerdown(dev->dev->bus);
+}
+
+static void prepare_phy_data_for_init(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	int i;
+
+	/* Set default attenuation values. */
+	phy->bbatt = b43legacy_default_baseband_attenuation(dev);
+	phy->rfatt = b43legacy_default_radio_attenuation(dev);
+	phy->txctl1 = b43legacy_default_txctl1(dev);
+	phy->txctl2 = 0xFFFF;
+	phy->txpwr_offset = 0;
+
+	/* NRSSI */
+	phy->nrssislope = 0;
+	for (i = 0; i < ARRAY_SIZE(phy->nrssi); i++)
+		phy->nrssi[i] = -1000;
+	for (i = 0; i < ARRAY_SIZE(phy->nrssi_lt); i++)
+		phy->nrssi_lt[i] = i;
+
+	phy->lofcal = 0xFFFF;
+	phy->initval = 0xFFFF;
+
+	phy->aci_enable = false;
+	phy->aci_wlan_automatic = false;
+	phy->aci_hw_rssi = false;
+
+	phy->antenna_diversity = 0xFFFF;
+	memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig));
+	memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos));
+
+	/* Flags */
+	phy->calibrated = 0;
+
+	if (phy->_lo_pairs)
+		memset(phy->_lo_pairs, 0,
+		       sizeof(struct b43legacy_lopair) * B43legacy_LO_COUNT);
+	memset(phy->loopback_gain, 0, sizeof(phy->loopback_gain));
+}
+
+/* Initialize a wireless core */
+static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_wl *wl = dev->wl;
+	struct ssb_bus *bus = dev->dev->bus;
+	struct b43legacy_phy *phy = &dev->phy;
+	struct ssb_sprom *sprom = &dev->dev->bus->sprom;
+	int err;
+	u32 hf;
+	u32 tmp;
+
+	B43legacy_WARN_ON(b43legacy_status(dev) != B43legacy_STAT_UNINIT);
+
+	err = ssb_bus_powerup(bus, 0);
+	if (err)
+		goto out;
+	if (!ssb_device_is_enabled(dev->dev)) {
+		tmp = phy->gmode ? B43legacy_TMSLOW_GMODE : 0;
+		b43legacy_wireless_core_reset(dev, tmp);
+	}
+
+	if ((phy->type == B43legacy_PHYTYPE_B) ||
+	    (phy->type == B43legacy_PHYTYPE_G)) {
+		phy->_lo_pairs = kcalloc(B43legacy_LO_COUNT,
+					 sizeof(struct b43legacy_lopair),
+					 GFP_KERNEL);
+		if (!phy->_lo_pairs)
+			return -ENOMEM;
+	}
+	setup_struct_wldev_for_init(dev);
+
+	err = b43legacy_phy_init_tssi2dbm_table(dev);
+	if (err)
+		goto err_kfree_lo_control;
+
+	/* Enable IRQ routing to this device. */
+	ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev);
+
+	prepare_phy_data_for_init(dev);
+	b43legacy_phy_calibrate(dev);
+	err = b43legacy_chip_init(dev);
+	if (err)
+		goto err_kfree_tssitbl;
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+			      B43legacy_SHM_SH_WLCOREREV,
+			      dev->dev->id.revision);
+	hf = b43legacy_hf_read(dev);
+	if (phy->type == B43legacy_PHYTYPE_G) {
+		hf |= B43legacy_HF_SYMW;
+		if (phy->rev == 1)
+			hf |= B43legacy_HF_GDCW;
+		if (sprom->boardflags_lo & B43legacy_BFL_PACTRL)
+			hf |= B43legacy_HF_OFDMPABOOST;
+	} else if (phy->type == B43legacy_PHYTYPE_B) {
+		hf |= B43legacy_HF_SYMW;
+		if (phy->rev >= 2 && phy->radio_ver == 0x2050)
+			hf &= ~B43legacy_HF_GDCW;
+	}
+	b43legacy_hf_write(dev, hf);
+
+	b43legacy_set_retry_limits(dev,
+				   B43legacy_DEFAULT_SHORT_RETRY_LIMIT,
+				   B43legacy_DEFAULT_LONG_RETRY_LIMIT);
+
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+			      0x0044, 3);
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+			      0x0046, 2);
+
+	/* Disable sending probe responses from firmware.
+	 * Setting the MaxTime to one usec will always trigger
+	 * a timeout, so we never send any probe resp.
+	 * A timeout of zero is infinite. */
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+			      B43legacy_SHM_SH_PRMAXTIME, 1);
+
+	b43legacy_rate_memory_init(dev);
+
+	/* Minimum Contention Window */
+	if (phy->type == B43legacy_PHYTYPE_B)
+		b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS,
+				      0x0003, 31);
+	else
+		b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS,
+				      0x0003, 15);
+	/* Maximum Contention Window */
+	b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS,
+			      0x0004, 1023);
+
+	do {
+		if (b43legacy_using_pio(dev))
+			err = b43legacy_pio_init(dev);
+		else {
+			err = b43legacy_dma_init(dev);
+			if (!err)
+				b43legacy_qos_init(dev);
+		}
+	} while (err == -EAGAIN);
+	if (err)
+		goto err_chip_exit;
+
+	b43legacy_set_synth_pu_delay(dev, 1);
+
+	ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */
+	b43legacy_upload_card_macaddress(dev);
+	b43legacy_security_init(dev);
+	b43legacy_rng_init(wl);
+
+	ieee80211_wake_queues(dev->wl->hw);
+	b43legacy_set_status(dev, B43legacy_STAT_INITIALIZED);
+
+	b43legacy_leds_init(dev);
+out:
+	return err;
+
+err_chip_exit:
+	b43legacy_chip_exit(dev);
+err_kfree_tssitbl:
+	if (phy->dyn_tssi_tbl)
+		kfree(phy->tssi2dbm);
+err_kfree_lo_control:
+	kfree(phy->lo_control);
+	phy->lo_control = NULL;
+	ssb_bus_may_powerdown(bus);
+	B43legacy_WARN_ON(b43legacy_status(dev) != B43legacy_STAT_UNINIT);
+	return err;
+}
+
+static int b43legacy_op_add_interface(struct ieee80211_hw *hw,
+				      struct ieee80211_vif *vif)
+{
+	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
+	struct b43legacy_wldev *dev;
+	unsigned long flags;
+	int err = -EOPNOTSUPP;
+
+	/* TODO: allow WDS/AP devices to coexist */
+
+	if (vif->type != NL80211_IFTYPE_AP &&
+	    vif->type != NL80211_IFTYPE_STATION &&
+	    vif->type != NL80211_IFTYPE_WDS &&
+	    vif->type != NL80211_IFTYPE_ADHOC)
+		return -EOPNOTSUPP;
+
+	mutex_lock(&wl->mutex);
+	if (wl->operating)
+		goto out_mutex_unlock;
+
+	b43legacydbg(wl, "Adding Interface type %d\n", vif->type);
+
+	dev = wl->current_dev;
+	wl->operating = true;
+	wl->vif = vif;
+	wl->if_type = vif->type;
+	memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
+
+	spin_lock_irqsave(&wl->irq_lock, flags);
+	b43legacy_adjust_opmode(dev);
+	b43legacy_set_pretbtt(dev);
+	b43legacy_set_synth_pu_delay(dev, 0);
+	b43legacy_upload_card_macaddress(dev);
+	spin_unlock_irqrestore(&wl->irq_lock, flags);
+
+	err = 0;
+ out_mutex_unlock:
+	mutex_unlock(&wl->mutex);
+
+	return err;
+}
+
+static void b43legacy_op_remove_interface(struct ieee80211_hw *hw,
+					  struct ieee80211_vif *vif)
+{
+	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
+	struct b43legacy_wldev *dev = wl->current_dev;
+	unsigned long flags;
+
+	b43legacydbg(wl, "Removing Interface type %d\n", vif->type);
+
+	mutex_lock(&wl->mutex);
+
+	B43legacy_WARN_ON(!wl->operating);
+	B43legacy_WARN_ON(wl->vif != vif);
+	wl->vif = NULL;
+
+	wl->operating = false;
+
+	spin_lock_irqsave(&wl->irq_lock, flags);
+	b43legacy_adjust_opmode(dev);
+	eth_zero_addr(wl->mac_addr);
+	b43legacy_upload_card_macaddress(dev);
+	spin_unlock_irqrestore(&wl->irq_lock, flags);
+
+	mutex_unlock(&wl->mutex);
+}
+
+static int b43legacy_op_start(struct ieee80211_hw *hw)
+{
+	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
+	struct b43legacy_wldev *dev = wl->current_dev;
+	int did_init = 0;
+	int err = 0;
+
+	/* Kill all old instance specific information to make sure
+	 * the card won't use it in the short timeframe between start
+	 * and mac80211 reconfiguring it. */
+	eth_zero_addr(wl->bssid);
+	eth_zero_addr(wl->mac_addr);
+	wl->filter_flags = 0;
+	wl->beacon0_uploaded = false;
+	wl->beacon1_uploaded = false;
+	wl->beacon_templates_virgin = true;
+	wl->radio_enabled = true;
+
+	mutex_lock(&wl->mutex);
+
+	if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) {
+		err = b43legacy_wireless_core_init(dev);
+		if (err)
+			goto out_mutex_unlock;
+		did_init = 1;
+	}
+
+	if (b43legacy_status(dev) < B43legacy_STAT_STARTED) {
+		err = b43legacy_wireless_core_start(dev);
+		if (err) {
+			if (did_init)
+				b43legacy_wireless_core_exit(dev);
+			goto out_mutex_unlock;
+		}
+	}
+
+	wiphy_rfkill_start_polling(hw->wiphy);
+
+out_mutex_unlock:
+	mutex_unlock(&wl->mutex);
+
+	return err;
+}
+
+static void b43legacy_op_stop(struct ieee80211_hw *hw)
+{
+	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
+	struct b43legacy_wldev *dev = wl->current_dev;
+
+	cancel_work_sync(&(wl->beacon_update_trigger));
+
+	mutex_lock(&wl->mutex);
+	if (b43legacy_status(dev) >= B43legacy_STAT_STARTED)
+		b43legacy_wireless_core_stop(dev);
+	b43legacy_wireless_core_exit(dev);
+	wl->radio_enabled = false;
+	mutex_unlock(&wl->mutex);
+}
+
+static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,
+				       struct ieee80211_sta *sta, bool set)
+{
+	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
+	unsigned long flags;
+
+	spin_lock_irqsave(&wl->irq_lock, flags);
+	b43legacy_update_templates(wl);
+	spin_unlock_irqrestore(&wl->irq_lock, flags);
+
+	return 0;
+}
+
+static int b43legacy_op_get_survey(struct ieee80211_hw *hw, int idx,
+				   struct survey_info *survey)
+{
+	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
+	struct b43legacy_wldev *dev = wl->current_dev;
+	struct ieee80211_conf *conf = &hw->conf;
+
+	if (idx != 0)
+		return -ENOENT;
+
+	survey->channel = conf->chandef.chan;
+	survey->filled = SURVEY_INFO_NOISE_DBM;
+	survey->noise = dev->stats.link_noise;
+
+	return 0;
+}
+
+static const struct ieee80211_ops b43legacy_hw_ops = {
+	.tx			= b43legacy_op_tx,
+	.conf_tx		= b43legacy_op_conf_tx,
+	.add_interface		= b43legacy_op_add_interface,
+	.remove_interface	= b43legacy_op_remove_interface,
+	.config			= b43legacy_op_dev_config,
+	.bss_info_changed	= b43legacy_op_bss_info_changed,
+	.configure_filter	= b43legacy_op_configure_filter,
+	.get_stats		= b43legacy_op_get_stats,
+	.start			= b43legacy_op_start,
+	.stop			= b43legacy_op_stop,
+	.set_tim		= b43legacy_op_beacon_set_tim,
+	.get_survey		= b43legacy_op_get_survey,
+	.rfkill_poll		= b43legacy_rfkill_poll,
+};
+
+/* Hard-reset the chip. Do not call this directly.
+ * Use b43legacy_controller_restart()
+ */
+static void b43legacy_chip_reset(struct work_struct *work)
+{
+	struct b43legacy_wldev *dev =
+		container_of(work, struct b43legacy_wldev, restart_work);
+	struct b43legacy_wl *wl = dev->wl;
+	int err = 0;
+	int prev_status;
+
+	mutex_lock(&wl->mutex);
+
+	prev_status = b43legacy_status(dev);
+	/* Bring the device down... */
+	if (prev_status >= B43legacy_STAT_STARTED)
+		b43legacy_wireless_core_stop(dev);
+	if (prev_status >= B43legacy_STAT_INITIALIZED)
+		b43legacy_wireless_core_exit(dev);
+
+	/* ...and up again. */
+	if (prev_status >= B43legacy_STAT_INITIALIZED) {
+		err = b43legacy_wireless_core_init(dev);
+		if (err)
+			goto out;
+	}
+	if (prev_status >= B43legacy_STAT_STARTED) {
+		err = b43legacy_wireless_core_start(dev);
+		if (err) {
+			b43legacy_wireless_core_exit(dev);
+			goto out;
+		}
+	}
+out:
+	if (err)
+		wl->current_dev = NULL; /* Failed to init the dev. */
+	mutex_unlock(&wl->mutex);
+	if (err)
+		b43legacyerr(wl, "Controller restart FAILED\n");
+	else
+		b43legacyinfo(wl, "Controller restarted\n");
+}
+
+static int b43legacy_setup_modes(struct b43legacy_wldev *dev,
+				 int have_bphy,
+				 int have_gphy)
+{
+	struct ieee80211_hw *hw = dev->wl->hw;
+	struct b43legacy_phy *phy = &dev->phy;
+
+	phy->possible_phymodes = 0;
+	if (have_bphy) {
+		hw->wiphy->bands[NL80211_BAND_2GHZ] =
+			&b43legacy_band_2GHz_BPHY;
+		phy->possible_phymodes |= B43legacy_PHYMODE_B;
+	}
+
+	if (have_gphy) {
+		hw->wiphy->bands[NL80211_BAND_2GHZ] =
+			&b43legacy_band_2GHz_GPHY;
+		phy->possible_phymodes |= B43legacy_PHYMODE_G;
+	}
+
+	return 0;
+}
+
+static void b43legacy_wireless_core_detach(struct b43legacy_wldev *dev)
+{
+	/* We release firmware that late to not be required to re-request
+	 * is all the time when we reinit the core. */
+	b43legacy_release_firmware(dev);
+}
+
+static int b43legacy_wireless_core_attach(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_wl *wl = dev->wl;
+	struct ssb_bus *bus = dev->dev->bus;
+	struct pci_dev *pdev = (bus->bustype == SSB_BUSTYPE_PCI) ? bus->host_pci : NULL;
+	int err;
+	int have_bphy = 0;
+	int have_gphy = 0;
+	u32 tmp;
+
+	/* Do NOT do any device initialization here.
+	 * Do it in wireless_core_init() instead.
+	 * This function is for gathering basic information about the HW, only.
+	 * Also some structs may be set up here. But most likely you want to
+	 * have that in core_init(), too.
+	 */
+
+	err = ssb_bus_powerup(bus, 0);
+	if (err) {
+		b43legacyerr(wl, "Bus powerup failed\n");
+		goto out;
+	}
+	/* Get the PHY type. */
+	if (dev->dev->id.revision >= 5) {
+		u32 tmshigh;
+
+		tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH);
+		have_gphy = !!(tmshigh & B43legacy_TMSHIGH_GPHY);
+		if (!have_gphy)
+			have_bphy = 1;
+	} else if (dev->dev->id.revision == 4)
+		have_gphy = 1;
+	else
+		have_bphy = 1;
+
+	dev->phy.gmode = (have_gphy || have_bphy);
+	dev->phy.radio_on = true;
+	tmp = dev->phy.gmode ? B43legacy_TMSLOW_GMODE : 0;
+	b43legacy_wireless_core_reset(dev, tmp);
+
+	err = b43legacy_phy_versioning(dev);
+	if (err)
+		goto err_powerdown;
+	/* Check if this device supports multiband. */
+	if (!pdev ||
+	    (pdev->device != 0x4312 &&
+	     pdev->device != 0x4319 &&
+	     pdev->device != 0x4324)) {
+		/* No multiband support. */
+		have_bphy = 0;
+		have_gphy = 0;
+		switch (dev->phy.type) {
+		case B43legacy_PHYTYPE_B:
+			have_bphy = 1;
+			break;
+		case B43legacy_PHYTYPE_G:
+			have_gphy = 1;
+			break;
+		default:
+			B43legacy_BUG_ON(1);
+		}
+	}
+	dev->phy.gmode = (have_gphy || have_bphy);
+	tmp = dev->phy.gmode ? B43legacy_TMSLOW_GMODE : 0;
+	b43legacy_wireless_core_reset(dev, tmp);
+
+	err = b43legacy_validate_chipaccess(dev);
+	if (err)
+		goto err_powerdown;
+	err = b43legacy_setup_modes(dev, have_bphy, have_gphy);
+	if (err)
+		goto err_powerdown;
+
+	/* Now set some default "current_dev" */
+	if (!wl->current_dev)
+		wl->current_dev = dev;
+	INIT_WORK(&dev->restart_work, b43legacy_chip_reset);
+
+	b43legacy_radio_turn_off(dev, 1);
+	b43legacy_switch_analog(dev, 0);
+	ssb_device_disable(dev->dev, 0);
+	ssb_bus_may_powerdown(bus);
+
+out:
+	return err;
+
+err_powerdown:
+	ssb_bus_may_powerdown(bus);
+	return err;
+}
+
+static void b43legacy_one_core_detach(struct ssb_device *dev)
+{
+	struct b43legacy_wldev *wldev;
+	struct b43legacy_wl *wl;
+
+	/* Do not cancel ieee80211-workqueue based work here.
+	 * See comment in b43legacy_remove(). */
+
+	wldev = ssb_get_drvdata(dev);
+	wl = wldev->wl;
+	b43legacy_debugfs_remove_device(wldev);
+	b43legacy_wireless_core_detach(wldev);
+	list_del(&wldev->list);
+	wl->nr_devs--;
+	ssb_set_drvdata(dev, NULL);
+	kfree(wldev);
+}
+
+static int b43legacy_one_core_attach(struct ssb_device *dev,
+				     struct b43legacy_wl *wl)
+{
+	struct b43legacy_wldev *wldev;
+	int err = -ENOMEM;
+
+	wldev = kzalloc(sizeof(*wldev), GFP_KERNEL);
+	if (!wldev)
+		goto out;
+
+	wldev->dev = dev;
+	wldev->wl = wl;
+	b43legacy_set_status(wldev, B43legacy_STAT_UNINIT);
+	wldev->bad_frames_preempt = modparam_bad_frames_preempt;
+	tasklet_init(&wldev->isr_tasklet,
+		     (void (*)(unsigned long))b43legacy_interrupt_tasklet,
+		     (unsigned long)wldev);
+	if (modparam_pio)
+		wldev->__using_pio = true;
+	INIT_LIST_HEAD(&wldev->list);
+
+	err = b43legacy_wireless_core_attach(wldev);
+	if (err)
+		goto err_kfree_wldev;
+
+	list_add(&wldev->list, &wl->devlist);
+	wl->nr_devs++;
+	ssb_set_drvdata(dev, wldev);
+	b43legacy_debugfs_add_device(wldev);
+out:
+	return err;
+
+err_kfree_wldev:
+	kfree(wldev);
+	return err;
+}
+
+static void b43legacy_sprom_fixup(struct ssb_bus *bus)
+{
+	/* boardflags workarounds */
+	if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
+	    bus->boardinfo.type == 0x4E &&
+	    bus->sprom.board_rev > 0x40)
+		bus->sprom.boardflags_lo |= B43legacy_BFL_PACTRL;
+}
+
+static void b43legacy_wireless_exit(struct ssb_device *dev,
+				  struct b43legacy_wl *wl)
+{
+	struct ieee80211_hw *hw = wl->hw;
+
+	ssb_set_devtypedata(dev, NULL);
+	ieee80211_free_hw(hw);
+}
+
+static int b43legacy_wireless_init(struct ssb_device *dev)
+{
+	struct ssb_sprom *sprom = &dev->bus->sprom;
+	struct ieee80211_hw *hw;
+	struct b43legacy_wl *wl;
+	int err = -ENOMEM;
+	int queue_num;
+
+	b43legacy_sprom_fixup(dev->bus);
+
+	hw = ieee80211_alloc_hw(sizeof(*wl), &b43legacy_hw_ops);
+	if (!hw) {
+		b43legacyerr(NULL, "Could not allocate ieee80211 device\n");
+		goto out;
+	}
+
+	/* fill hw info */
+	ieee80211_hw_set(hw, RX_INCLUDES_FCS);
+	ieee80211_hw_set(hw, SIGNAL_DBM);
+
+	hw->wiphy->interface_modes =
+		BIT(NL80211_IFTYPE_AP) |
+		BIT(NL80211_IFTYPE_STATION) |
+#ifdef CONFIG_WIRELESS_WDS
+		BIT(NL80211_IFTYPE_WDS) |
+#endif
+		BIT(NL80211_IFTYPE_ADHOC);
+	hw->queues = 1; /* FIXME: hardware has more queues */
+	hw->max_rates = 2;
+	SET_IEEE80211_DEV(hw, dev->dev);
+	if (is_valid_ether_addr(sprom->et1mac))
+		SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
+	else
+		SET_IEEE80211_PERM_ADDR(hw, sprom->il0mac);
+
+	wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
+
+	/* Get and initialize struct b43legacy_wl */
+	wl = hw_to_b43legacy_wl(hw);
+	memset(wl, 0, sizeof(*wl));
+	wl->hw = hw;
+	spin_lock_init(&wl->irq_lock);
+	spin_lock_init(&wl->leds_lock);
+	mutex_init(&wl->mutex);
+	INIT_LIST_HEAD(&wl->devlist);
+	INIT_WORK(&wl->beacon_update_trigger, b43legacy_beacon_update_trigger_work);
+	INIT_WORK(&wl->tx_work, b43legacy_tx_work);
+
+	/* Initialize queues and flags. */
+	for (queue_num = 0; queue_num < B43legacy_QOS_QUEUE_NUM; queue_num++) {
+		skb_queue_head_init(&wl->tx_queue[queue_num]);
+		wl->tx_queue_stopped[queue_num] = 0;
+	}
+
+	ssb_set_devtypedata(dev, wl);
+	b43legacyinfo(wl, "Broadcom %04X WLAN found (core revision %u)\n",
+		      dev->bus->chip_id, dev->id.revision);
+	err = 0;
+out:
+	return err;
+}
+
+static int b43legacy_probe(struct ssb_device *dev,
+			 const struct ssb_device_id *id)
+{
+	struct b43legacy_wl *wl;
+	int err;
+	int first = 0;
+
+	wl = ssb_get_devtypedata(dev);
+	if (!wl) {
+		/* Probing the first core - setup common struct b43legacy_wl */
+		first = 1;
+		err = b43legacy_wireless_init(dev);
+		if (err)
+			goto out;
+		wl = ssb_get_devtypedata(dev);
+		B43legacy_WARN_ON(!wl);
+	}
+	err = b43legacy_one_core_attach(dev, wl);
+	if (err)
+		goto err_wireless_exit;
+
+	/* setup and start work to load firmware */
+	INIT_WORK(&wl->firmware_load, b43legacy_request_firmware);
+	schedule_work(&wl->firmware_load);
+
+out:
+	return err;
+
+err_wireless_exit:
+	if (first)
+		b43legacy_wireless_exit(dev, wl);
+	return err;
+}
+
+static void b43legacy_remove(struct ssb_device *dev)
+{
+	struct b43legacy_wl *wl = ssb_get_devtypedata(dev);
+	struct b43legacy_wldev *wldev = ssb_get_drvdata(dev);
+
+	/* We must cancel any work here before unregistering from ieee80211,
+	 * as the ieee80211 unreg will destroy the workqueue. */
+	cancel_work_sync(&wldev->restart_work);
+	cancel_work_sync(&wl->firmware_load);
+	complete(&wldev->fw_load_complete);
+
+	B43legacy_WARN_ON(!wl);
+	if (!wldev->fw.ucode)
+		return;			/* NULL if fw never loaded */
+	if (wl->current_dev == wldev)
+		ieee80211_unregister_hw(wl->hw);
+
+	b43legacy_one_core_detach(dev);
+
+	if (list_empty(&wl->devlist))
+		/* Last core on the chip unregistered.
+		 * We can destroy common struct b43legacy_wl.
+		 */
+		b43legacy_wireless_exit(dev, wl);
+}
+
+/* Perform a hardware reset. This can be called from any context. */
+void b43legacy_controller_restart(struct b43legacy_wldev *dev,
+				  const char *reason)
+{
+	/* Must avoid requeueing, if we are in shutdown. */
+	if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)
+		return;
+	b43legacyinfo(dev->wl, "Controller RESET (%s) ...\n", reason);
+	ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
+}
+
+#ifdef CONFIG_PM
+
+static int b43legacy_suspend(struct ssb_device *dev, pm_message_t state)
+{
+	struct b43legacy_wldev *wldev = ssb_get_drvdata(dev);
+	struct b43legacy_wl *wl = wldev->wl;
+
+	b43legacydbg(wl, "Suspending...\n");
+
+	mutex_lock(&wl->mutex);
+	wldev->suspend_init_status = b43legacy_status(wldev);
+	if (wldev->suspend_init_status >= B43legacy_STAT_STARTED)
+		b43legacy_wireless_core_stop(wldev);
+	if (wldev->suspend_init_status >= B43legacy_STAT_INITIALIZED)
+		b43legacy_wireless_core_exit(wldev);
+	mutex_unlock(&wl->mutex);
+
+	b43legacydbg(wl, "Device suspended.\n");
+
+	return 0;
+}
+
+static int b43legacy_resume(struct ssb_device *dev)
+{
+	struct b43legacy_wldev *wldev = ssb_get_drvdata(dev);
+	struct b43legacy_wl *wl = wldev->wl;
+	int err = 0;
+
+	b43legacydbg(wl, "Resuming...\n");
+
+	mutex_lock(&wl->mutex);
+	if (wldev->suspend_init_status >= B43legacy_STAT_INITIALIZED) {
+		err = b43legacy_wireless_core_init(wldev);
+		if (err) {
+			b43legacyerr(wl, "Resume failed at core init\n");
+			goto out;
+		}
+	}
+	if (wldev->suspend_init_status >= B43legacy_STAT_STARTED) {
+		err = b43legacy_wireless_core_start(wldev);
+		if (err) {
+			b43legacy_wireless_core_exit(wldev);
+			b43legacyerr(wl, "Resume failed at core start\n");
+			goto out;
+		}
+	}
+
+	b43legacydbg(wl, "Device resumed.\n");
+out:
+	mutex_unlock(&wl->mutex);
+	return err;
+}
+
+#else	/* CONFIG_PM */
+# define b43legacy_suspend	NULL
+# define b43legacy_resume		NULL
+#endif	/* CONFIG_PM */
+
+static struct ssb_driver b43legacy_ssb_driver = {
+	.name		= KBUILD_MODNAME,
+	.id_table	= b43legacy_ssb_tbl,
+	.probe		= b43legacy_probe,
+	.remove		= b43legacy_remove,
+	.suspend	= b43legacy_suspend,
+	.resume		= b43legacy_resume,
+};
+
+static void b43legacy_print_driverinfo(void)
+{
+	const char *feat_pci = "", *feat_leds = "",
+		   *feat_pio = "", *feat_dma = "";
+
+#ifdef CONFIG_B43LEGACY_PCI_AUTOSELECT
+	feat_pci = "P";
+#endif
+#ifdef CONFIG_B43LEGACY_LEDS
+	feat_leds = "L";
+#endif
+#ifdef CONFIG_B43LEGACY_PIO
+	feat_pio = "I";
+#endif
+#ifdef CONFIG_B43LEGACY_DMA
+	feat_dma = "D";
+#endif
+	printk(KERN_INFO "Broadcom 43xx-legacy driver loaded "
+	       "[ Features: %s%s%s%s ]\n",
+	       feat_pci, feat_leds, feat_pio, feat_dma);
+}
+
+static int __init b43legacy_init(void)
+{
+	int err;
+
+	b43legacy_debugfs_init();
+
+	err = ssb_driver_register(&b43legacy_ssb_driver);
+	if (err)
+		goto err_dfs_exit;
+
+	b43legacy_print_driverinfo();
+
+	return err;
+
+err_dfs_exit:
+	b43legacy_debugfs_exit();
+	return err;
+}
+
+static void __exit b43legacy_exit(void)
+{
+	ssb_driver_unregister(&b43legacy_ssb_driver);
+	b43legacy_debugfs_exit();
+}
+
+module_init(b43legacy_init)
+module_exit(b43legacy_exit)
diff --git a/drivers/net/wireless/broadcom/b43legacy/main.h b/drivers/net/wireless/broadcom/b43legacy/main.h
new file mode 100644
index 0000000..b74a058
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/main.h
@@ -0,0 +1,127 @@
+/*
+
+  Broadcom B43legacy wireless driver
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+  Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
+  Copyright (c) 2005, 2006 Michael Buesch <m@bues.ch>
+  Copyright (c) 2005  Danny van Dyk <kugelfang@gentoo.org>
+  Copyright (c) 2005  Andreas Jaggi <andreas.jaggi@waterwave.ch>
+  Copyright (c) 2007  Larry Finger <Larry.Finger@lwfinger.net>
+
+  Some parts of the code in this file are derived from the ipw2200
+  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+
+  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.
+
+*/
+
+#ifndef B43legacy_MAIN_H_
+#define B43legacy_MAIN_H_
+
+#include "b43legacy.h"
+
+
+#define P4D_BYT3S(magic, nr_bytes)	u8 __p4dding##magic[nr_bytes]
+#define P4D_BYTES(line, nr_bytes)	P4D_BYT3S(line, nr_bytes)
+/* Magic helper macro to pad structures. Ignore those above. It's magic. */
+#define PAD_BYTES(nr_bytes)		P4D_BYTES(__LINE__ , (nr_bytes))
+
+
+/* Lightweight function to convert a frequency (in Mhz) to a channel number. */
+static inline
+u8 b43legacy_freq_to_channel_bg(int freq)
+{
+	u8 channel;
+
+	if (freq == 2484)
+		channel = 14;
+	else
+		channel = (freq - 2407) / 5;
+
+	return channel;
+}
+static inline
+u8 b43legacy_freq_to_channel(struct b43legacy_wldev *dev,
+			     int freq)
+{
+	return b43legacy_freq_to_channel_bg(freq);
+}
+
+/* Lightweight function to convert a channel number to a frequency (in Mhz). */
+static inline
+int b43legacy_channel_to_freq_bg(u8 channel)
+{
+	int freq;
+
+	if (channel == 14)
+		freq = 2484;
+	else
+		freq = 2407 + (5 * channel);
+
+	return freq;
+}
+
+static inline
+int b43legacy_channel_to_freq(struct b43legacy_wldev *dev,
+			      u8 channel)
+{
+	return b43legacy_channel_to_freq_bg(channel);
+}
+
+static inline
+int b43legacy_is_cck_rate(int rate)
+{
+	return (rate == B43legacy_CCK_RATE_1MB ||
+		rate == B43legacy_CCK_RATE_2MB ||
+		rate == B43legacy_CCK_RATE_5MB ||
+		rate == B43legacy_CCK_RATE_11MB);
+}
+
+static inline
+int b43legacy_is_ofdm_rate(int rate)
+{
+	return !b43legacy_is_cck_rate(rate);
+}
+
+void b43legacy_tsf_read(struct b43legacy_wldev *dev, u64 *tsf);
+void b43legacy_tsf_write(struct b43legacy_wldev *dev, u64 tsf);
+
+u32 b43legacy_shm_read32(struct b43legacy_wldev *dev,
+			 u16 routing, u16 offset);
+u16 b43legacy_shm_read16(struct b43legacy_wldev *dev,
+			 u16 routing, u16 offset);
+void b43legacy_shm_write32(struct b43legacy_wldev *dev,
+			 u16 routing, u16 offset,
+			 u32 value);
+void b43legacy_shm_write16(struct b43legacy_wldev *dev,
+			 u16 routing, u16 offset,
+			 u16 value);
+
+u32 b43legacy_hf_read(struct b43legacy_wldev *dev);
+void b43legacy_hf_write(struct b43legacy_wldev *dev, u32 value);
+
+void b43legacy_dummy_transmission(struct b43legacy_wldev *dev);
+
+void b43legacy_wireless_core_reset(struct b43legacy_wldev *dev, u32 flags);
+
+void b43legacy_mac_suspend(struct b43legacy_wldev *dev);
+void b43legacy_mac_enable(struct b43legacy_wldev *dev);
+
+void b43legacy_controller_restart(struct b43legacy_wldev *dev,
+				  const char *reason);
+
+#endif /* B43legacy_MAIN_H_ */
diff --git a/drivers/net/wireless/broadcom/b43legacy/phy.c b/drivers/net/wireless/broadcom/b43legacy/phy.c
new file mode 100644
index 0000000..995c7d0
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/phy.c
@@ -0,0 +1,2258 @@
+/*
+
+  Broadcom B43legacy wireless driver
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+		     Stefano Brivio <stefano.brivio@polimi.it>
+		     Michael Buesch <m@bues.ch>
+		     Danny van Dyk <kugelfang@gentoo.org>
+     Andreas Jaggi <andreas.jaggi@waterwave.ch>
+  Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
+
+  Some parts of the code in this file are derived from the ipw2200
+  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+
+  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/delay.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "b43legacy.h"
+#include "phy.h"
+#include "main.h"
+#include "radio.h"
+#include "ilt.h"
+
+
+static const s8 b43legacy_tssi2dbm_b_table[] = {
+	0x4D, 0x4C, 0x4B, 0x4A,
+	0x4A, 0x49, 0x48, 0x47,
+	0x47, 0x46, 0x45, 0x45,
+	0x44, 0x43, 0x42, 0x42,
+	0x41, 0x40, 0x3F, 0x3E,
+	0x3D, 0x3C, 0x3B, 0x3A,
+	0x39, 0x38, 0x37, 0x36,
+	0x35, 0x34, 0x32, 0x31,
+	0x30, 0x2F, 0x2D, 0x2C,
+	0x2B, 0x29, 0x28, 0x26,
+	0x25, 0x23, 0x21, 0x1F,
+	0x1D, 0x1A, 0x17, 0x14,
+	0x10, 0x0C, 0x06, 0x00,
+	  -7,   -7,   -7,   -7,
+	  -7,   -7,   -7,   -7,
+	  -7,   -7,   -7,   -7,
+};
+
+static const s8 b43legacy_tssi2dbm_g_table[] = {
+	 77,  77,  77,  76,
+	 76,  76,  75,  75,
+	 74,  74,  73,  73,
+	 73,  72,  72,  71,
+	 71,  70,  70,  69,
+	 68,  68,  67,  67,
+	 66,  65,  65,  64,
+	 63,  63,  62,  61,
+	 60,  59,  58,  57,
+	 56,  55,  54,  53,
+	 52,  50,  49,  47,
+	 45,  43,  40,  37,
+	 33,  28,  22,  14,
+	  5,  -7, -20, -20,
+	-20, -20, -20, -20,
+	-20, -20, -20, -20,
+};
+
+static void b43legacy_phy_initg(struct b43legacy_wldev *dev);
+
+
+static inline
+void b43legacy_voluntary_preempt(void)
+{
+	B43legacy_BUG_ON(!(!in_atomic() && !in_irq() &&
+			  !in_interrupt() && !irqs_disabled()));
+#ifndef CONFIG_PREEMPT
+	cond_resched();
+#endif /* CONFIG_PREEMPT */
+}
+
+/* Lock the PHY registers against concurrent access from the microcode.
+ * This lock is nonrecursive. */
+void b43legacy_phy_lock(struct b43legacy_wldev *dev)
+{
+#if B43legacy_DEBUG
+	B43legacy_WARN_ON(dev->phy.phy_locked);
+	dev->phy.phy_locked = 1;
+#endif
+
+	if (dev->dev->id.revision < 3) {
+		b43legacy_mac_suspend(dev);
+	} else {
+		if (!b43legacy_is_mode(dev->wl, NL80211_IFTYPE_AP))
+			b43legacy_power_saving_ctl_bits(dev, -1, 1);
+	}
+}
+
+void b43legacy_phy_unlock(struct b43legacy_wldev *dev)
+{
+#if B43legacy_DEBUG
+	B43legacy_WARN_ON(!dev->phy.phy_locked);
+	dev->phy.phy_locked = 0;
+#endif
+
+	if (dev->dev->id.revision < 3) {
+		b43legacy_mac_enable(dev);
+	} else {
+		if (!b43legacy_is_mode(dev->wl, NL80211_IFTYPE_AP))
+			b43legacy_power_saving_ctl_bits(dev, -1, -1);
+	}
+}
+
+u16 b43legacy_phy_read(struct b43legacy_wldev *dev, u16 offset)
+{
+	b43legacy_write16(dev, B43legacy_MMIO_PHY_CONTROL, offset);
+	return b43legacy_read16(dev, B43legacy_MMIO_PHY_DATA);
+}
+
+void b43legacy_phy_write(struct b43legacy_wldev *dev, u16 offset, u16 val)
+{
+	b43legacy_write16(dev, B43legacy_MMIO_PHY_CONTROL, offset);
+	mmiowb();
+	b43legacy_write16(dev, B43legacy_MMIO_PHY_DATA, val);
+}
+
+void b43legacy_phy_calibrate(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+
+	b43legacy_read32(dev, B43legacy_MMIO_MACCTL); /* Dummy read. */
+	if (phy->calibrated)
+		return;
+	if (phy->type == B43legacy_PHYTYPE_G && phy->rev == 1) {
+		b43legacy_wireless_core_reset(dev, 0);
+		b43legacy_phy_initg(dev);
+		b43legacy_wireless_core_reset(dev, B43legacy_TMSLOW_GMODE);
+	}
+	phy->calibrated = 1;
+}
+
+/* initialize B PHY power control
+ * as described in http://bcm-specs.sipsolutions.net/InitPowerControl
+ */
+static void b43legacy_phy_init_pctl(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 saved_batt = 0;
+	u16 saved_ratt = 0;
+	u16 saved_txctl1 = 0;
+	int must_reset_txpower = 0;
+
+	B43legacy_BUG_ON(!(phy->type == B43legacy_PHYTYPE_B ||
+			  phy->type == B43legacy_PHYTYPE_G));
+	if (is_bcm_board_vendor(dev) &&
+	    (dev->dev->bus->boardinfo.type == 0x0416))
+		return;
+
+	b43legacy_phy_write(dev, 0x0028, 0x8018);
+	b43legacy_write16(dev, 0x03E6, b43legacy_read16(dev, 0x03E6) & 0xFFDF);
+
+	if (phy->type == B43legacy_PHYTYPE_G) {
+		if (!phy->gmode)
+			return;
+		b43legacy_phy_write(dev, 0x047A, 0xC111);
+	}
+	if (phy->savedpctlreg != 0xFFFF)
+		return;
+#ifdef CONFIG_B43LEGACY_DEBUG
+	if (phy->manual_txpower_control)
+		return;
+#endif
+
+	if (phy->type == B43legacy_PHYTYPE_B &&
+	    phy->rev >= 2 &&
+	    phy->radio_ver == 0x2050)
+		b43legacy_radio_write16(dev, 0x0076,
+					b43legacy_radio_read16(dev, 0x0076)
+					| 0x0084);
+	else {
+		saved_batt = phy->bbatt;
+		saved_ratt = phy->rfatt;
+		saved_txctl1 = phy->txctl1;
+		if ((phy->radio_rev >= 6) && (phy->radio_rev <= 8)
+		    && /*FIXME: incomplete specs for 5 < revision < 9 */ 0)
+			b43legacy_radio_set_txpower_bg(dev, 0xB, 0x1F, 0);
+		else
+			b43legacy_radio_set_txpower_bg(dev, 0xB, 9, 0);
+		must_reset_txpower = 1;
+	}
+	b43legacy_dummy_transmission(dev);
+
+	phy->savedpctlreg = b43legacy_phy_read(dev, B43legacy_PHY_G_PCTL);
+
+	if (must_reset_txpower)
+		b43legacy_radio_set_txpower_bg(dev, saved_batt, saved_ratt,
+					       saved_txctl1);
+	else
+		b43legacy_radio_write16(dev, 0x0076, b43legacy_radio_read16(dev,
+					0x0076) & 0xFF7B);
+	b43legacy_radio_clear_tssi(dev);
+}
+
+static void b43legacy_phy_agcsetup(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 offset = 0x0000;
+
+	if (phy->rev == 1)
+		offset = 0x4C00;
+
+	b43legacy_ilt_write(dev, offset, 0x00FE);
+	b43legacy_ilt_write(dev, offset + 1, 0x000D);
+	b43legacy_ilt_write(dev, offset + 2, 0x0013);
+	b43legacy_ilt_write(dev, offset + 3, 0x0019);
+
+	if (phy->rev == 1) {
+		b43legacy_ilt_write(dev, 0x1800, 0x2710);
+		b43legacy_ilt_write(dev, 0x1801, 0x9B83);
+		b43legacy_ilt_write(dev, 0x1802, 0x9B83);
+		b43legacy_ilt_write(dev, 0x1803, 0x0F8D);
+		b43legacy_phy_write(dev, 0x0455, 0x0004);
+	}
+
+	b43legacy_phy_write(dev, 0x04A5, (b43legacy_phy_read(dev, 0x04A5)
+					  & 0x00FF) | 0x5700);
+	b43legacy_phy_write(dev, 0x041A, (b43legacy_phy_read(dev, 0x041A)
+					  & 0xFF80) | 0x000F);
+	b43legacy_phy_write(dev, 0x041A, (b43legacy_phy_read(dev, 0x041A)
+					  & 0xC07F) | 0x2B80);
+	b43legacy_phy_write(dev, 0x048C, (b43legacy_phy_read(dev, 0x048C)
+					  & 0xF0FF) | 0x0300);
+
+	b43legacy_radio_write16(dev, 0x007A,
+				b43legacy_radio_read16(dev, 0x007A)
+				| 0x0008);
+
+	b43legacy_phy_write(dev, 0x04A0, (b43legacy_phy_read(dev, 0x04A0)
+			    & 0xFFF0) | 0x0008);
+	b43legacy_phy_write(dev, 0x04A1, (b43legacy_phy_read(dev, 0x04A1)
+			    & 0xF0FF) | 0x0600);
+	b43legacy_phy_write(dev, 0x04A2, (b43legacy_phy_read(dev, 0x04A2)
+			    & 0xF0FF) | 0x0700);
+	b43legacy_phy_write(dev, 0x04A0, (b43legacy_phy_read(dev, 0x04A0)
+			    & 0xF0FF) | 0x0100);
+
+	if (phy->rev == 1)
+		b43legacy_phy_write(dev, 0x04A2,
+				    (b43legacy_phy_read(dev, 0x04A2)
+				    & 0xFFF0) | 0x0007);
+
+	b43legacy_phy_write(dev, 0x0488, (b43legacy_phy_read(dev, 0x0488)
+			    & 0xFF00) | 0x001C);
+	b43legacy_phy_write(dev, 0x0488, (b43legacy_phy_read(dev, 0x0488)
+			    & 0xC0FF) | 0x0200);
+	b43legacy_phy_write(dev, 0x0496, (b43legacy_phy_read(dev, 0x0496)
+			    & 0xFF00) | 0x001C);
+	b43legacy_phy_write(dev, 0x0489, (b43legacy_phy_read(dev, 0x0489)
+			    & 0xFF00) | 0x0020);
+	b43legacy_phy_write(dev, 0x0489, (b43legacy_phy_read(dev, 0x0489)
+			    & 0xC0FF) | 0x0200);
+	b43legacy_phy_write(dev, 0x0482, (b43legacy_phy_read(dev, 0x0482)
+			    & 0xFF00) | 0x002E);
+	b43legacy_phy_write(dev, 0x0496, (b43legacy_phy_read(dev, 0x0496)
+			    & 0x00FF) | 0x1A00);
+	b43legacy_phy_write(dev, 0x0481, (b43legacy_phy_read(dev, 0x0481)
+			    & 0xFF00) | 0x0028);
+	b43legacy_phy_write(dev, 0x0481, (b43legacy_phy_read(dev, 0x0481)
+			    & 0x00FF) | 0x2C00);
+
+	if (phy->rev == 1) {
+		b43legacy_phy_write(dev, 0x0430, 0x092B);
+		b43legacy_phy_write(dev, 0x041B,
+				    (b43legacy_phy_read(dev, 0x041B)
+				    & 0xFFE1) | 0x0002);
+	} else {
+		b43legacy_phy_write(dev, 0x041B,
+				    b43legacy_phy_read(dev, 0x041B) & 0xFFE1);
+		b43legacy_phy_write(dev, 0x041F, 0x287A);
+		b43legacy_phy_write(dev, 0x0420,
+				    (b43legacy_phy_read(dev, 0x0420)
+				    & 0xFFF0) | 0x0004);
+	}
+
+	if (phy->rev > 2) {
+		b43legacy_phy_write(dev, 0x0422, 0x287A);
+		b43legacy_phy_write(dev, 0x0420,
+				    (b43legacy_phy_read(dev, 0x0420)
+				    & 0x0FFF) | 0x3000);
+	}
+
+	b43legacy_phy_write(dev, 0x04A8, (b43legacy_phy_read(dev, 0x04A8)
+			    & 0x8080) | 0x7874);
+	b43legacy_phy_write(dev, 0x048E, 0x1C00);
+
+	if (phy->rev == 1) {
+		b43legacy_phy_write(dev, 0x04AB,
+				    (b43legacy_phy_read(dev, 0x04AB)
+				    & 0xF0FF) | 0x0600);
+		b43legacy_phy_write(dev, 0x048B, 0x005E);
+		b43legacy_phy_write(dev, 0x048C,
+				    (b43legacy_phy_read(dev, 0x048C) & 0xFF00)
+				    | 0x001E);
+		b43legacy_phy_write(dev, 0x048D, 0x0002);
+	}
+
+	b43legacy_ilt_write(dev, offset + 0x0800, 0);
+	b43legacy_ilt_write(dev, offset + 0x0801, 7);
+	b43legacy_ilt_write(dev, offset + 0x0802, 16);
+	b43legacy_ilt_write(dev, offset + 0x0803, 28);
+
+	if (phy->rev >= 6) {
+		b43legacy_phy_write(dev, 0x0426,
+				    (b43legacy_phy_read(dev, 0x0426) & 0xFFFC));
+		b43legacy_phy_write(dev, 0x0426,
+				    (b43legacy_phy_read(dev, 0x0426) & 0xEFFF));
+	}
+}
+
+static void b43legacy_phy_setupg(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 i;
+
+	B43legacy_BUG_ON(phy->type != B43legacy_PHYTYPE_G);
+	if (phy->rev == 1) {
+		b43legacy_phy_write(dev, 0x0406, 0x4F19);
+		b43legacy_phy_write(dev, B43legacy_PHY_G_CRS,
+				    (b43legacy_phy_read(dev,
+				    B43legacy_PHY_G_CRS) & 0xFC3F) | 0x0340);
+		b43legacy_phy_write(dev, 0x042C, 0x005A);
+		b43legacy_phy_write(dev, 0x0427, 0x001A);
+
+		for (i = 0; i < B43legacy_ILT_FINEFREQG_SIZE; i++)
+			b43legacy_ilt_write(dev, 0x5800 + i,
+					    b43legacy_ilt_finefreqg[i]);
+		for (i = 0; i < B43legacy_ILT_NOISEG1_SIZE; i++)
+			b43legacy_ilt_write(dev, 0x1800 + i,
+					    b43legacy_ilt_noiseg1[i]);
+		for (i = 0; i < B43legacy_ILT_ROTOR_SIZE; i++)
+			b43legacy_ilt_write32(dev, 0x2000 + i,
+					      b43legacy_ilt_rotor[i]);
+	} else {
+		/* nrssi values are signed 6-bit values. Why 0x7654 here? */
+		b43legacy_nrssi_hw_write(dev, 0xBA98, (s16)0x7654);
+
+		if (phy->rev == 2) {
+			b43legacy_phy_write(dev, 0x04C0, 0x1861);
+			b43legacy_phy_write(dev, 0x04C1, 0x0271);
+		} else if (phy->rev > 2) {
+			b43legacy_phy_write(dev, 0x04C0, 0x0098);
+			b43legacy_phy_write(dev, 0x04C1, 0x0070);
+			b43legacy_phy_write(dev, 0x04C9, 0x0080);
+		}
+		b43legacy_phy_write(dev, 0x042B, b43legacy_phy_read(dev,
+				    0x042B) | 0x800);
+
+		for (i = 0; i < 64; i++)
+			b43legacy_ilt_write(dev, 0x4000 + i, i);
+		for (i = 0; i < B43legacy_ILT_NOISEG2_SIZE; i++)
+			b43legacy_ilt_write(dev, 0x1800 + i,
+					    b43legacy_ilt_noiseg2[i]);
+	}
+
+	if (phy->rev <= 2)
+		for (i = 0; i < B43legacy_ILT_NOISESCALEG_SIZE; i++)
+			b43legacy_ilt_write(dev, 0x1400 + i,
+					    b43legacy_ilt_noisescaleg1[i]);
+	else if ((phy->rev >= 7) && (b43legacy_phy_read(dev, 0x0449) & 0x0200))
+		for (i = 0; i < B43legacy_ILT_NOISESCALEG_SIZE; i++)
+			b43legacy_ilt_write(dev, 0x1400 + i,
+					    b43legacy_ilt_noisescaleg3[i]);
+	else
+		for (i = 0; i < B43legacy_ILT_NOISESCALEG_SIZE; i++)
+			b43legacy_ilt_write(dev, 0x1400 + i,
+					    b43legacy_ilt_noisescaleg2[i]);
+
+	if (phy->rev == 2)
+		for (i = 0; i < B43legacy_ILT_SIGMASQR_SIZE; i++)
+			b43legacy_ilt_write(dev, 0x5000 + i,
+					    b43legacy_ilt_sigmasqr1[i]);
+	else if ((phy->rev > 2) && (phy->rev <= 8))
+		for (i = 0; i < B43legacy_ILT_SIGMASQR_SIZE; i++)
+			b43legacy_ilt_write(dev, 0x5000 + i,
+					    b43legacy_ilt_sigmasqr2[i]);
+
+	if (phy->rev == 1) {
+		for (i = 0; i < B43legacy_ILT_RETARD_SIZE; i++)
+			b43legacy_ilt_write32(dev, 0x2400 + i,
+					      b43legacy_ilt_retard[i]);
+		for (i = 4; i < 20; i++)
+			b43legacy_ilt_write(dev, 0x5400 + i, 0x0020);
+		b43legacy_phy_agcsetup(dev);
+
+		if (is_bcm_board_vendor(dev) &&
+		    (dev->dev->bus->boardinfo.type == 0x0416) &&
+		    (dev->dev->bus->sprom.board_rev == 0x0017))
+			return;
+
+		b43legacy_ilt_write(dev, 0x5001, 0x0002);
+		b43legacy_ilt_write(dev, 0x5002, 0x0001);
+	} else {
+		for (i = 0; i <= 0x20; i++)
+			b43legacy_ilt_write(dev, 0x1000 + i, 0x0820);
+		b43legacy_phy_agcsetup(dev);
+		b43legacy_phy_read(dev, 0x0400); /* dummy read */
+		b43legacy_phy_write(dev, 0x0403, 0x1000);
+		b43legacy_ilt_write(dev, 0x3C02, 0x000F);
+		b43legacy_ilt_write(dev, 0x3C03, 0x0014);
+
+		if (is_bcm_board_vendor(dev) &&
+		    (dev->dev->bus->boardinfo.type == 0x0416) &&
+		    (dev->dev->bus->sprom.board_rev == 0x0017))
+			return;
+
+		b43legacy_ilt_write(dev, 0x0401, 0x0002);
+		b43legacy_ilt_write(dev, 0x0402, 0x0001);
+	}
+}
+
+/* Initialize the APHY portion of a GPHY. */
+static void b43legacy_phy_inita(struct b43legacy_wldev *dev)
+{
+
+	might_sleep();
+
+	b43legacy_phy_setupg(dev);
+	if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_PACTRL)
+		b43legacy_phy_write(dev, 0x046E, 0x03CF);
+}
+
+static void b43legacy_phy_initb2(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 offset;
+	int val;
+
+	b43legacy_write16(dev, 0x03EC, 0x3F22);
+	b43legacy_phy_write(dev, 0x0020, 0x301C);
+	b43legacy_phy_write(dev, 0x0026, 0x0000);
+	b43legacy_phy_write(dev, 0x0030, 0x00C6);
+	b43legacy_phy_write(dev, 0x0088, 0x3E00);
+	val = 0x3C3D;
+	for (offset = 0x0089; offset < 0x00A7; offset++) {
+		b43legacy_phy_write(dev, offset, val);
+		val -= 0x0202;
+	}
+	b43legacy_phy_write(dev, 0x03E4, 0x3000);
+	b43legacy_radio_selectchannel(dev, phy->channel, 0);
+	if (phy->radio_ver != 0x2050) {
+		b43legacy_radio_write16(dev, 0x0075, 0x0080);
+		b43legacy_radio_write16(dev, 0x0079, 0x0081);
+	}
+	b43legacy_radio_write16(dev, 0x0050, 0x0020);
+	b43legacy_radio_write16(dev, 0x0050, 0x0023);
+	if (phy->radio_ver == 0x2050) {
+		b43legacy_radio_write16(dev, 0x0050, 0x0020);
+		b43legacy_radio_write16(dev, 0x005A, 0x0070);
+		b43legacy_radio_write16(dev, 0x005B, 0x007B);
+		b43legacy_radio_write16(dev, 0x005C, 0x00B0);
+		b43legacy_radio_write16(dev, 0x007A, 0x000F);
+		b43legacy_phy_write(dev, 0x0038, 0x0677);
+		b43legacy_radio_init2050(dev);
+	}
+	b43legacy_phy_write(dev, 0x0014, 0x0080);
+	b43legacy_phy_write(dev, 0x0032, 0x00CA);
+	b43legacy_phy_write(dev, 0x0032, 0x00CC);
+	b43legacy_phy_write(dev, 0x0035, 0x07C2);
+	b43legacy_phy_lo_b_measure(dev);
+	b43legacy_phy_write(dev, 0x0026, 0xCC00);
+	if (phy->radio_ver != 0x2050)
+		b43legacy_phy_write(dev, 0x0026, 0xCE00);
+	b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, 0x1000);
+	b43legacy_phy_write(dev, 0x002A, 0x88A3);
+	if (phy->radio_ver != 0x2050)
+		b43legacy_phy_write(dev, 0x002A, 0x88C2);
+	b43legacy_radio_set_txpower_bg(dev, 0xFFFF, 0xFFFF, 0xFFFF);
+	b43legacy_phy_init_pctl(dev);
+}
+
+static void b43legacy_phy_initb4(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 offset;
+	u16 val;
+
+	b43legacy_write16(dev, 0x03EC, 0x3F22);
+	b43legacy_phy_write(dev, 0x0020, 0x301C);
+	b43legacy_phy_write(dev, 0x0026, 0x0000);
+	b43legacy_phy_write(dev, 0x0030, 0x00C6);
+	b43legacy_phy_write(dev, 0x0088, 0x3E00);
+	val = 0x3C3D;
+	for (offset = 0x0089; offset < 0x00A7; offset++) {
+		b43legacy_phy_write(dev, offset, val);
+		val -= 0x0202;
+	}
+	b43legacy_phy_write(dev, 0x03E4, 0x3000);
+	b43legacy_radio_selectchannel(dev, phy->channel, 0);
+	if (phy->radio_ver != 0x2050) {
+		b43legacy_radio_write16(dev, 0x0075, 0x0080);
+		b43legacy_radio_write16(dev, 0x0079, 0x0081);
+	}
+	b43legacy_radio_write16(dev, 0x0050, 0x0020);
+	b43legacy_radio_write16(dev, 0x0050, 0x0023);
+	if (phy->radio_ver == 0x2050) {
+		b43legacy_radio_write16(dev, 0x0050, 0x0020);
+		b43legacy_radio_write16(dev, 0x005A, 0x0070);
+		b43legacy_radio_write16(dev, 0x005B, 0x007B);
+		b43legacy_radio_write16(dev, 0x005C, 0x00B0);
+		b43legacy_radio_write16(dev, 0x007A, 0x000F);
+		b43legacy_phy_write(dev, 0x0038, 0x0677);
+		b43legacy_radio_init2050(dev);
+	}
+	b43legacy_phy_write(dev, 0x0014, 0x0080);
+	b43legacy_phy_write(dev, 0x0032, 0x00CA);
+	if (phy->radio_ver == 0x2050)
+		b43legacy_phy_write(dev, 0x0032, 0x00E0);
+	b43legacy_phy_write(dev, 0x0035, 0x07C2);
+
+	b43legacy_phy_lo_b_measure(dev);
+
+	b43legacy_phy_write(dev, 0x0026, 0xCC00);
+	if (phy->radio_ver == 0x2050)
+		b43legacy_phy_write(dev, 0x0026, 0xCE00);
+	b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, 0x1100);
+	b43legacy_phy_write(dev, 0x002A, 0x88A3);
+	if (phy->radio_ver == 0x2050)
+		b43legacy_phy_write(dev, 0x002A, 0x88C2);
+	b43legacy_radio_set_txpower_bg(dev, 0xFFFF, 0xFFFF, 0xFFFF);
+	if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_RSSI) {
+		b43legacy_calc_nrssi_slope(dev);
+		b43legacy_calc_nrssi_threshold(dev);
+	}
+	b43legacy_phy_init_pctl(dev);
+}
+
+static void b43legacy_phy_initb5(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 offset;
+	u16 value;
+	u8 old_channel;
+
+	if (phy->analog == 1)
+		b43legacy_radio_write16(dev, 0x007A,
+					b43legacy_radio_read16(dev, 0x007A)
+					| 0x0050);
+	if (!is_bcm_board_vendor(dev) &&
+	    (dev->dev->bus->boardinfo.type != 0x0416)) {
+		value = 0x2120;
+		for (offset = 0x00A8 ; offset < 0x00C7; offset++) {
+			b43legacy_phy_write(dev, offset, value);
+			value += 0x0202;
+		}
+	}
+	b43legacy_phy_write(dev, 0x0035,
+			    (b43legacy_phy_read(dev, 0x0035) & 0xF0FF)
+			    | 0x0700);
+	if (phy->radio_ver == 0x2050)
+		b43legacy_phy_write(dev, 0x0038, 0x0667);
+
+	if (phy->gmode) {
+		if (phy->radio_ver == 0x2050) {
+			b43legacy_radio_write16(dev, 0x007A,
+					b43legacy_radio_read16(dev, 0x007A)
+					| 0x0020);
+			b43legacy_radio_write16(dev, 0x0051,
+					b43legacy_radio_read16(dev, 0x0051)
+					| 0x0004);
+		}
+		b43legacy_write16(dev, B43legacy_MMIO_PHY_RADIO, 0x0000);
+
+		b43legacy_phy_write(dev, 0x0802, b43legacy_phy_read(dev, 0x0802)
+				    | 0x0100);
+		b43legacy_phy_write(dev, 0x042B, b43legacy_phy_read(dev, 0x042B)
+				    | 0x2000);
+
+		b43legacy_phy_write(dev, 0x001C, 0x186A);
+
+		b43legacy_phy_write(dev, 0x0013, (b43legacy_phy_read(dev,
+				    0x0013) & 0x00FF) | 0x1900);
+		b43legacy_phy_write(dev, 0x0035, (b43legacy_phy_read(dev,
+				    0x0035) & 0xFFC0) | 0x0064);
+		b43legacy_phy_write(dev, 0x005D, (b43legacy_phy_read(dev,
+				    0x005D) & 0xFF80) | 0x000A);
+		b43legacy_phy_write(dev, 0x5B, 0x0000);
+		b43legacy_phy_write(dev, 0x5C, 0x0000);
+	}
+
+	if (dev->bad_frames_preempt)
+		b43legacy_phy_write(dev, B43legacy_PHY_RADIO_BITFIELD,
+				    b43legacy_phy_read(dev,
+				    B43legacy_PHY_RADIO_BITFIELD) | (1 << 12));
+
+	if (phy->analog == 1) {
+		b43legacy_phy_write(dev, 0x0026, 0xCE00);
+		b43legacy_phy_write(dev, 0x0021, 0x3763);
+		b43legacy_phy_write(dev, 0x0022, 0x1BC3);
+		b43legacy_phy_write(dev, 0x0023, 0x06F9);
+		b43legacy_phy_write(dev, 0x0024, 0x037E);
+	} else
+		b43legacy_phy_write(dev, 0x0026, 0xCC00);
+	b43legacy_phy_write(dev, 0x0030, 0x00C6);
+	b43legacy_write16(dev, 0x03EC, 0x3F22);
+
+	if (phy->analog == 1)
+		b43legacy_phy_write(dev, 0x0020, 0x3E1C);
+	else
+		b43legacy_phy_write(dev, 0x0020, 0x301C);
+
+	if (phy->analog == 0)
+		b43legacy_write16(dev, 0x03E4, 0x3000);
+
+	old_channel = (phy->channel == 0xFF) ? 1 : phy->channel;
+	/* Force to channel 7, even if not supported. */
+	b43legacy_radio_selectchannel(dev, 7, 0);
+
+	if (phy->radio_ver != 0x2050) {
+		b43legacy_radio_write16(dev, 0x0075, 0x0080);
+		b43legacy_radio_write16(dev, 0x0079, 0x0081);
+	}
+
+	b43legacy_radio_write16(dev, 0x0050, 0x0020);
+	b43legacy_radio_write16(dev, 0x0050, 0x0023);
+
+	if (phy->radio_ver == 0x2050) {
+		b43legacy_radio_write16(dev, 0x0050, 0x0020);
+		b43legacy_radio_write16(dev, 0x005A, 0x0070);
+	}
+
+	b43legacy_radio_write16(dev, 0x005B, 0x007B);
+	b43legacy_radio_write16(dev, 0x005C, 0x00B0);
+
+	b43legacy_radio_write16(dev, 0x007A, b43legacy_radio_read16(dev,
+				0x007A) | 0x0007);
+
+	b43legacy_radio_selectchannel(dev, old_channel, 0);
+
+	b43legacy_phy_write(dev, 0x0014, 0x0080);
+	b43legacy_phy_write(dev, 0x0032, 0x00CA);
+	b43legacy_phy_write(dev, 0x002A, 0x88A3);
+
+	b43legacy_radio_set_txpower_bg(dev, 0xFFFF, 0xFFFF, 0xFFFF);
+
+	if (phy->radio_ver == 0x2050)
+		b43legacy_radio_write16(dev, 0x005D, 0x000D);
+
+	b43legacy_write16(dev, 0x03E4, (b43legacy_read16(dev, 0x03E4) &
+			  0xFFC0) | 0x0004);
+}
+
+static void b43legacy_phy_initb6(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 offset;
+	u16 val;
+	u8 old_channel;
+
+	b43legacy_phy_write(dev, 0x003E, 0x817A);
+	b43legacy_radio_write16(dev, 0x007A,
+				(b43legacy_radio_read16(dev, 0x007A) | 0x0058));
+	if (phy->radio_rev == 4 ||
+	     phy->radio_rev == 5) {
+		b43legacy_radio_write16(dev, 0x0051, 0x0037);
+		b43legacy_radio_write16(dev, 0x0052, 0x0070);
+		b43legacy_radio_write16(dev, 0x0053, 0x00B3);
+		b43legacy_radio_write16(dev, 0x0054, 0x009B);
+		b43legacy_radio_write16(dev, 0x005A, 0x0088);
+		b43legacy_radio_write16(dev, 0x005B, 0x0088);
+		b43legacy_radio_write16(dev, 0x005D, 0x0088);
+		b43legacy_radio_write16(dev, 0x005E, 0x0088);
+		b43legacy_radio_write16(dev, 0x007D, 0x0088);
+		b43legacy_shm_write32(dev, B43legacy_SHM_SHARED,
+				      B43legacy_UCODEFLAGS_OFFSET,
+				      (b43legacy_shm_read32(dev,
+				      B43legacy_SHM_SHARED,
+				      B43legacy_UCODEFLAGS_OFFSET)
+				      | 0x00000200));
+	}
+	if (phy->radio_rev == 8) {
+		b43legacy_radio_write16(dev, 0x0051, 0x0000);
+		b43legacy_radio_write16(dev, 0x0052, 0x0040);
+		b43legacy_radio_write16(dev, 0x0053, 0x00B7);
+		b43legacy_radio_write16(dev, 0x0054, 0x0098);
+		b43legacy_radio_write16(dev, 0x005A, 0x0088);
+		b43legacy_radio_write16(dev, 0x005B, 0x006B);
+		b43legacy_radio_write16(dev, 0x005C, 0x000F);
+		if (dev->dev->bus->sprom.boardflags_lo & 0x8000) {
+			b43legacy_radio_write16(dev, 0x005D, 0x00FA);
+			b43legacy_radio_write16(dev, 0x005E, 0x00D8);
+		} else {
+			b43legacy_radio_write16(dev, 0x005D, 0x00F5);
+			b43legacy_radio_write16(dev, 0x005E, 0x00B8);
+		}
+		b43legacy_radio_write16(dev, 0x0073, 0x0003);
+		b43legacy_radio_write16(dev, 0x007D, 0x00A8);
+		b43legacy_radio_write16(dev, 0x007C, 0x0001);
+		b43legacy_radio_write16(dev, 0x007E, 0x0008);
+	}
+	val = 0x1E1F;
+	for (offset = 0x0088; offset < 0x0098; offset++) {
+		b43legacy_phy_write(dev, offset, val);
+		val -= 0x0202;
+	}
+	val = 0x3E3F;
+	for (offset = 0x0098; offset < 0x00A8; offset++) {
+		b43legacy_phy_write(dev, offset, val);
+		val -= 0x0202;
+	}
+	val = 0x2120;
+	for (offset = 0x00A8; offset < 0x00C8; offset++) {
+		b43legacy_phy_write(dev, offset, (val & 0x3F3F));
+		val += 0x0202;
+	}
+	if (phy->type == B43legacy_PHYTYPE_G) {
+		b43legacy_radio_write16(dev, 0x007A,
+					b43legacy_radio_read16(dev, 0x007A) |
+					0x0020);
+		b43legacy_radio_write16(dev, 0x0051,
+					b43legacy_radio_read16(dev, 0x0051) |
+					0x0004);
+		b43legacy_phy_write(dev, 0x0802,
+				    b43legacy_phy_read(dev, 0x0802) | 0x0100);
+		b43legacy_phy_write(dev, 0x042B,
+				    b43legacy_phy_read(dev, 0x042B) | 0x2000);
+		b43legacy_phy_write(dev, 0x5B, 0x0000);
+		b43legacy_phy_write(dev, 0x5C, 0x0000);
+	}
+
+	old_channel = phy->channel;
+	if (old_channel >= 8)
+		b43legacy_radio_selectchannel(dev, 1, 0);
+	else
+		b43legacy_radio_selectchannel(dev, 13, 0);
+
+	b43legacy_radio_write16(dev, 0x0050, 0x0020);
+	b43legacy_radio_write16(dev, 0x0050, 0x0023);
+	udelay(40);
+	if (phy->radio_rev < 6 || phy->radio_rev == 8) {
+		b43legacy_radio_write16(dev, 0x007C,
+					(b43legacy_radio_read16(dev, 0x007C)
+					| 0x0002));
+		b43legacy_radio_write16(dev, 0x0050, 0x0020);
+	}
+	if (phy->radio_rev <= 2) {
+		b43legacy_radio_write16(dev, 0x0050, 0x0020);
+		b43legacy_radio_write16(dev, 0x005A, 0x0070);
+		b43legacy_radio_write16(dev, 0x005B, 0x007B);
+		b43legacy_radio_write16(dev, 0x005C, 0x00B0);
+	}
+	b43legacy_radio_write16(dev, 0x007A,
+				(b43legacy_radio_read16(dev,
+				0x007A) & 0x00F8) | 0x0007);
+
+	b43legacy_radio_selectchannel(dev, old_channel, 0);
+
+	b43legacy_phy_write(dev, 0x0014, 0x0200);
+	if (phy->radio_rev >= 6)
+		b43legacy_phy_write(dev, 0x002A, 0x88C2);
+	else
+		b43legacy_phy_write(dev, 0x002A, 0x8AC0);
+	b43legacy_phy_write(dev, 0x0038, 0x0668);
+	b43legacy_radio_set_txpower_bg(dev, 0xFFFF, 0xFFFF, 0xFFFF);
+	if (phy->radio_rev == 4 || phy->radio_rev == 5)
+		b43legacy_phy_write(dev, 0x005D, (b43legacy_phy_read(dev,
+				    0x005D) & 0xFF80) | 0x0003);
+	if (phy->radio_rev <= 2)
+		b43legacy_radio_write16(dev, 0x005D, 0x000D);
+
+	if (phy->analog == 4) {
+		b43legacy_write16(dev, 0x03E4, 0x0009);
+		b43legacy_phy_write(dev, 0x61, b43legacy_phy_read(dev, 0x61)
+				    & 0xFFF);
+	} else
+		b43legacy_phy_write(dev, 0x0002, (b43legacy_phy_read(dev,
+				    0x0002) & 0xFFC0) | 0x0004);
+	if (phy->type == B43legacy_PHYTYPE_G)
+		b43legacy_write16(dev, 0x03E6, 0x0);
+	if (phy->type == B43legacy_PHYTYPE_B) {
+		b43legacy_write16(dev, 0x03E6, 0x8140);
+		b43legacy_phy_write(dev, 0x0016, 0x0410);
+		b43legacy_phy_write(dev, 0x0017, 0x0820);
+		b43legacy_phy_write(dev, 0x0062, 0x0007);
+		b43legacy_radio_init2050(dev);
+		b43legacy_phy_lo_g_measure(dev);
+		if (dev->dev->bus->sprom.boardflags_lo &
+		    B43legacy_BFL_RSSI) {
+			b43legacy_calc_nrssi_slope(dev);
+			b43legacy_calc_nrssi_threshold(dev);
+		}
+		b43legacy_phy_init_pctl(dev);
+	}
+}
+
+static void b43legacy_calc_loopback_gain(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 backup_phy[15] = {0};
+	u16 backup_radio[3];
+	u16 backup_bband;
+	u16 i;
+	u16 loop1_cnt;
+	u16 loop1_done;
+	u16 loop1_omitted;
+	u16 loop2_done;
+
+	backup_phy[0] = b43legacy_phy_read(dev, 0x0429);
+	backup_phy[1] = b43legacy_phy_read(dev, 0x0001);
+	backup_phy[2] = b43legacy_phy_read(dev, 0x0811);
+	backup_phy[3] = b43legacy_phy_read(dev, 0x0812);
+	if (phy->rev != 1) {
+		backup_phy[4] = b43legacy_phy_read(dev, 0x0814);
+		backup_phy[5] = b43legacy_phy_read(dev, 0x0815);
+	}
+	backup_phy[6] = b43legacy_phy_read(dev, 0x005A);
+	backup_phy[7] = b43legacy_phy_read(dev, 0x0059);
+	backup_phy[8] = b43legacy_phy_read(dev, 0x0058);
+	backup_phy[9] = b43legacy_phy_read(dev, 0x000A);
+	backup_phy[10] = b43legacy_phy_read(dev, 0x0003);
+	backup_phy[11] = b43legacy_phy_read(dev, 0x080F);
+	backup_phy[12] = b43legacy_phy_read(dev, 0x0810);
+	backup_phy[13] = b43legacy_phy_read(dev, 0x002B);
+	backup_phy[14] = b43legacy_phy_read(dev, 0x0015);
+	b43legacy_phy_read(dev, 0x002D); /* dummy read */
+	backup_bband = phy->bbatt;
+	backup_radio[0] = b43legacy_radio_read16(dev, 0x0052);
+	backup_radio[1] = b43legacy_radio_read16(dev, 0x0043);
+	backup_radio[2] = b43legacy_radio_read16(dev, 0x007A);
+
+	b43legacy_phy_write(dev, 0x0429,
+			    b43legacy_phy_read(dev, 0x0429) & 0x3FFF);
+	b43legacy_phy_write(dev, 0x0001,
+			    b43legacy_phy_read(dev, 0x0001) & 0x8000);
+	b43legacy_phy_write(dev, 0x0811,
+			    b43legacy_phy_read(dev, 0x0811) | 0x0002);
+	b43legacy_phy_write(dev, 0x0812,
+			    b43legacy_phy_read(dev, 0x0812) & 0xFFFD);
+	b43legacy_phy_write(dev, 0x0811,
+			    b43legacy_phy_read(dev, 0x0811) | 0x0001);
+	b43legacy_phy_write(dev, 0x0812,
+			    b43legacy_phy_read(dev, 0x0812) & 0xFFFE);
+	if (phy->rev != 1) {
+		b43legacy_phy_write(dev, 0x0814,
+				    b43legacy_phy_read(dev, 0x0814) | 0x0001);
+		b43legacy_phy_write(dev, 0x0815,
+				    b43legacy_phy_read(dev, 0x0815) & 0xFFFE);
+		b43legacy_phy_write(dev, 0x0814,
+				    b43legacy_phy_read(dev, 0x0814) | 0x0002);
+		b43legacy_phy_write(dev, 0x0815,
+				    b43legacy_phy_read(dev, 0x0815) & 0xFFFD);
+	}
+	b43legacy_phy_write(dev, 0x0811, b43legacy_phy_read(dev, 0x0811) |
+			    0x000C);
+	b43legacy_phy_write(dev, 0x0812, b43legacy_phy_read(dev, 0x0812) |
+			    0x000C);
+
+	b43legacy_phy_write(dev, 0x0811, (b43legacy_phy_read(dev, 0x0811)
+			    & 0xFFCF) | 0x0030);
+	b43legacy_phy_write(dev, 0x0812, (b43legacy_phy_read(dev, 0x0812)
+			    & 0xFFCF) | 0x0010);
+
+	b43legacy_phy_write(dev, 0x005A, 0x0780);
+	b43legacy_phy_write(dev, 0x0059, 0xC810);
+	b43legacy_phy_write(dev, 0x0058, 0x000D);
+	if (phy->analog == 0)
+		b43legacy_phy_write(dev, 0x0003, 0x0122);
+	else
+		b43legacy_phy_write(dev, 0x000A,
+				    b43legacy_phy_read(dev, 0x000A)
+				    | 0x2000);
+	if (phy->rev != 1) {
+		b43legacy_phy_write(dev, 0x0814,
+				    b43legacy_phy_read(dev, 0x0814) | 0x0004);
+		b43legacy_phy_write(dev, 0x0815,
+				    b43legacy_phy_read(dev, 0x0815) & 0xFFFB);
+	}
+	b43legacy_phy_write(dev, 0x0003,
+			    (b43legacy_phy_read(dev, 0x0003)
+			     & 0xFF9F) | 0x0040);
+	if (phy->radio_ver == 0x2050 && phy->radio_rev == 2) {
+		b43legacy_radio_write16(dev, 0x0052, 0x0000);
+		b43legacy_radio_write16(dev, 0x0043,
+					(b43legacy_radio_read16(dev, 0x0043)
+					 & 0xFFF0) | 0x0009);
+		loop1_cnt = 9;
+	} else if (phy->radio_rev == 8) {
+		b43legacy_radio_write16(dev, 0x0043, 0x000F);
+		loop1_cnt = 15;
+	} else
+		loop1_cnt = 0;
+
+	b43legacy_phy_set_baseband_attenuation(dev, 11);
+
+	if (phy->rev >= 3)
+		b43legacy_phy_write(dev, 0x080F, 0xC020);
+	else
+		b43legacy_phy_write(dev, 0x080F, 0x8020);
+	b43legacy_phy_write(dev, 0x0810, 0x0000);
+
+	b43legacy_phy_write(dev, 0x002B,
+			    (b43legacy_phy_read(dev, 0x002B)
+			     & 0xFFC0) | 0x0001);
+	b43legacy_phy_write(dev, 0x002B,
+			    (b43legacy_phy_read(dev, 0x002B)
+			     & 0xC0FF) | 0x0800);
+	b43legacy_phy_write(dev, 0x0811,
+			    b43legacy_phy_read(dev, 0x0811) | 0x0100);
+	b43legacy_phy_write(dev, 0x0812,
+			    b43legacy_phy_read(dev, 0x0812) & 0xCFFF);
+	if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_EXTLNA) {
+		if (phy->rev >= 7) {
+			b43legacy_phy_write(dev, 0x0811,
+					    b43legacy_phy_read(dev, 0x0811)
+					    | 0x0800);
+			b43legacy_phy_write(dev, 0x0812,
+					    b43legacy_phy_read(dev, 0x0812)
+					    | 0x8000);
+		}
+	}
+	b43legacy_radio_write16(dev, 0x007A,
+				b43legacy_radio_read16(dev, 0x007A)
+				& 0x00F7);
+
+	for (i = 0; i < loop1_cnt; i++) {
+		b43legacy_radio_write16(dev, 0x0043, loop1_cnt);
+		b43legacy_phy_write(dev, 0x0812,
+				    (b43legacy_phy_read(dev, 0x0812)
+				     & 0xF0FF) | (i << 8));
+		b43legacy_phy_write(dev, 0x0015,
+				    (b43legacy_phy_read(dev, 0x0015)
+				     & 0x0FFF) | 0xA000);
+		b43legacy_phy_write(dev, 0x0015,
+				    (b43legacy_phy_read(dev, 0x0015)
+				     & 0x0FFF) | 0xF000);
+		udelay(20);
+		if (b43legacy_phy_read(dev, 0x002D) >= 0x0DFC)
+			break;
+	}
+	loop1_done = i;
+	loop1_omitted = loop1_cnt - loop1_done;
+
+	loop2_done = 0;
+	if (loop1_done >= 8) {
+		b43legacy_phy_write(dev, 0x0812,
+				    b43legacy_phy_read(dev, 0x0812)
+				    | 0x0030);
+		for (i = loop1_done - 8; i < 16; i++) {
+			b43legacy_phy_write(dev, 0x0812,
+					    (b43legacy_phy_read(dev, 0x0812)
+					     & 0xF0FF) | (i << 8));
+			b43legacy_phy_write(dev, 0x0015,
+					    (b43legacy_phy_read(dev, 0x0015)
+					     & 0x0FFF) | 0xA000);
+			b43legacy_phy_write(dev, 0x0015,
+					    (b43legacy_phy_read(dev, 0x0015)
+					     & 0x0FFF) | 0xF000);
+			udelay(20);
+			if (b43legacy_phy_read(dev, 0x002D) >= 0x0DFC)
+				break;
+		}
+	}
+
+	if (phy->rev != 1) {
+		b43legacy_phy_write(dev, 0x0814, backup_phy[4]);
+		b43legacy_phy_write(dev, 0x0815, backup_phy[5]);
+	}
+	b43legacy_phy_write(dev, 0x005A, backup_phy[6]);
+	b43legacy_phy_write(dev, 0x0059, backup_phy[7]);
+	b43legacy_phy_write(dev, 0x0058, backup_phy[8]);
+	b43legacy_phy_write(dev, 0x000A, backup_phy[9]);
+	b43legacy_phy_write(dev, 0x0003, backup_phy[10]);
+	b43legacy_phy_write(dev, 0x080F, backup_phy[11]);
+	b43legacy_phy_write(dev, 0x0810, backup_phy[12]);
+	b43legacy_phy_write(dev, 0x002B, backup_phy[13]);
+	b43legacy_phy_write(dev, 0x0015, backup_phy[14]);
+
+	b43legacy_phy_set_baseband_attenuation(dev, backup_bband);
+
+	b43legacy_radio_write16(dev, 0x0052, backup_radio[0]);
+	b43legacy_radio_write16(dev, 0x0043, backup_radio[1]);
+	b43legacy_radio_write16(dev, 0x007A, backup_radio[2]);
+
+	b43legacy_phy_write(dev, 0x0811, backup_phy[2] | 0x0003);
+	udelay(10);
+	b43legacy_phy_write(dev, 0x0811, backup_phy[2]);
+	b43legacy_phy_write(dev, 0x0812, backup_phy[3]);
+	b43legacy_phy_write(dev, 0x0429, backup_phy[0]);
+	b43legacy_phy_write(dev, 0x0001, backup_phy[1]);
+
+	phy->loopback_gain[0] = ((loop1_done * 6) - (loop1_omitted * 4)) - 11;
+	phy->loopback_gain[1] = (24 - (3 * loop2_done)) * 2;
+}
+
+static void b43legacy_phy_initg(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 tmp;
+
+	if (phy->rev == 1)
+		b43legacy_phy_initb5(dev);
+	else
+		b43legacy_phy_initb6(dev);
+	if (phy->rev >= 2 && phy->gmode)
+		b43legacy_phy_inita(dev);
+
+	if (phy->rev >= 2) {
+		b43legacy_phy_write(dev, 0x0814, 0x0000);
+		b43legacy_phy_write(dev, 0x0815, 0x0000);
+	}
+	if (phy->rev == 2) {
+		b43legacy_phy_write(dev, 0x0811, 0x0000);
+		b43legacy_phy_write(dev, 0x0015, 0x00C0);
+	}
+	if (phy->rev > 5) {
+		b43legacy_phy_write(dev, 0x0811, 0x0400);
+		b43legacy_phy_write(dev, 0x0015, 0x00C0);
+	}
+	if (phy->gmode) {
+		tmp = b43legacy_phy_read(dev, 0x0400) & 0xFF;
+		if (tmp == 3) {
+			b43legacy_phy_write(dev, 0x04C2, 0x1816);
+			b43legacy_phy_write(dev, 0x04C3, 0x8606);
+		}
+		if (tmp == 4 || tmp == 5) {
+			b43legacy_phy_write(dev, 0x04C2, 0x1816);
+			b43legacy_phy_write(dev, 0x04C3, 0x8006);
+			b43legacy_phy_write(dev, 0x04CC,
+					    (b43legacy_phy_read(dev,
+					     0x04CC) & 0x00FF) |
+					     0x1F00);
+		}
+		if (phy->rev >= 2)
+			b43legacy_phy_write(dev, 0x047E, 0x0078);
+	}
+	if (phy->radio_rev == 8) {
+		b43legacy_phy_write(dev, 0x0801, b43legacy_phy_read(dev, 0x0801)
+				    | 0x0080);
+		b43legacy_phy_write(dev, 0x043E, b43legacy_phy_read(dev, 0x043E)
+				    | 0x0004);
+	}
+	if (phy->rev >= 2 && phy->gmode)
+		b43legacy_calc_loopback_gain(dev);
+	if (phy->radio_rev != 8) {
+		if (phy->initval == 0xFFFF)
+			phy->initval = b43legacy_radio_init2050(dev);
+		else
+			b43legacy_radio_write16(dev, 0x0078, phy->initval);
+	}
+	if (phy->txctl2 == 0xFFFF)
+		b43legacy_phy_lo_g_measure(dev);
+	else {
+		if (phy->radio_ver == 0x2050 && phy->radio_rev == 8)
+			b43legacy_radio_write16(dev, 0x0052,
+						(phy->txctl1 << 4) |
+						phy->txctl2);
+		else
+			b43legacy_radio_write16(dev, 0x0052,
+						(b43legacy_radio_read16(dev,
+						 0x0052) & 0xFFF0) |
+						 phy->txctl1);
+		if (phy->rev >= 6)
+			b43legacy_phy_write(dev, 0x0036,
+					    (b43legacy_phy_read(dev, 0x0036)
+					     & 0x0FFF) | (phy->txctl2 << 12));
+		if (dev->dev->bus->sprom.boardflags_lo &
+		    B43legacy_BFL_PACTRL)
+			b43legacy_phy_write(dev, 0x002E, 0x8075);
+		else
+			b43legacy_phy_write(dev, 0x002E, 0x807F);
+		if (phy->rev < 2)
+			b43legacy_phy_write(dev, 0x002F, 0x0101);
+		else
+			b43legacy_phy_write(dev, 0x002F, 0x0202);
+	}
+	if (phy->gmode) {
+		b43legacy_phy_lo_adjust(dev, 0);
+		b43legacy_phy_write(dev, 0x080F, 0x8078);
+	}
+
+	if (!(dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_RSSI)) {
+		/* The specs state to update the NRSSI LT with
+		 * the value 0x7FFFFFFF here. I think that is some weird
+		 * compiler optimization in the original driver.
+		 * Essentially, what we do here is resetting all NRSSI LT
+		 * entries to -32 (see the clamp_val() in nrssi_hw_update())
+		 */
+		b43legacy_nrssi_hw_update(dev, 0xFFFF);
+		b43legacy_calc_nrssi_threshold(dev);
+	} else if (phy->gmode || phy->rev >= 2) {
+		if (phy->nrssi[0] == -1000) {
+			B43legacy_WARN_ON(phy->nrssi[1] != -1000);
+			b43legacy_calc_nrssi_slope(dev);
+		} else {
+			B43legacy_WARN_ON(phy->nrssi[1] == -1000);
+			b43legacy_calc_nrssi_threshold(dev);
+		}
+	}
+	if (phy->radio_rev == 8)
+		b43legacy_phy_write(dev, 0x0805, 0x3230);
+	b43legacy_phy_init_pctl(dev);
+	if (dev->dev->bus->chip_id == 0x4306
+	    && dev->dev->bus->chip_package == 2) {
+		b43legacy_phy_write(dev, 0x0429,
+				    b43legacy_phy_read(dev, 0x0429) & 0xBFFF);
+		b43legacy_phy_write(dev, 0x04C3,
+				    b43legacy_phy_read(dev, 0x04C3) & 0x7FFF);
+	}
+}
+
+static u16 b43legacy_phy_lo_b_r15_loop(struct b43legacy_wldev *dev)
+{
+	int i;
+	u16 ret = 0;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	for (i = 0; i < 10; i++) {
+		b43legacy_phy_write(dev, 0x0015, 0xAFA0);
+		udelay(1);
+		b43legacy_phy_write(dev, 0x0015, 0xEFA0);
+		udelay(10);
+		b43legacy_phy_write(dev, 0x0015, 0xFFA0);
+		udelay(40);
+		ret += b43legacy_phy_read(dev, 0x002C);
+	}
+	local_irq_restore(flags);
+	b43legacy_voluntary_preempt();
+
+	return ret;
+}
+
+void b43legacy_phy_lo_b_measure(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 regstack[12] = { 0 };
+	u16 mls;
+	u16 fval;
+	int i;
+	int j;
+
+	regstack[0] = b43legacy_phy_read(dev, 0x0015);
+	regstack[1] = b43legacy_radio_read16(dev, 0x0052) & 0xFFF0;
+
+	if (phy->radio_ver == 0x2053) {
+		regstack[2] = b43legacy_phy_read(dev, 0x000A);
+		regstack[3] = b43legacy_phy_read(dev, 0x002A);
+		regstack[4] = b43legacy_phy_read(dev, 0x0035);
+		regstack[5] = b43legacy_phy_read(dev, 0x0003);
+		regstack[6] = b43legacy_phy_read(dev, 0x0001);
+		regstack[7] = b43legacy_phy_read(dev, 0x0030);
+
+		regstack[8] = b43legacy_radio_read16(dev, 0x0043);
+		regstack[9] = b43legacy_radio_read16(dev, 0x007A);
+		regstack[10] = b43legacy_read16(dev, 0x03EC);
+		regstack[11] = b43legacy_radio_read16(dev, 0x0052) & 0x00F0;
+
+		b43legacy_phy_write(dev, 0x0030, 0x00FF);
+		b43legacy_write16(dev, 0x03EC, 0x3F3F);
+		b43legacy_phy_write(dev, 0x0035, regstack[4] & 0xFF7F);
+		b43legacy_radio_write16(dev, 0x007A, regstack[9] & 0xFFF0);
+	}
+	b43legacy_phy_write(dev, 0x0015, 0xB000);
+	b43legacy_phy_write(dev, 0x002B, 0x0004);
+
+	if (phy->radio_ver == 0x2053) {
+		b43legacy_phy_write(dev, 0x002B, 0x0203);
+		b43legacy_phy_write(dev, 0x002A, 0x08A3);
+	}
+
+	phy->minlowsig[0] = 0xFFFF;
+
+	for (i = 0; i < 4; i++) {
+		b43legacy_radio_write16(dev, 0x0052, regstack[1] | i);
+		b43legacy_phy_lo_b_r15_loop(dev);
+	}
+	for (i = 0; i < 10; i++) {
+		b43legacy_radio_write16(dev, 0x0052, regstack[1] | i);
+		mls = b43legacy_phy_lo_b_r15_loop(dev) / 10;
+		if (mls < phy->minlowsig[0]) {
+			phy->minlowsig[0] = mls;
+			phy->minlowsigpos[0] = i;
+		}
+	}
+	b43legacy_radio_write16(dev, 0x0052, regstack[1]
+				| phy->minlowsigpos[0]);
+
+	phy->minlowsig[1] = 0xFFFF;
+
+	for (i = -4; i < 5; i += 2) {
+		for (j = -4; j < 5; j += 2) {
+			if (j < 0)
+				fval = (0x0100 * i) + j + 0x0100;
+			else
+				fval = (0x0100 * i) + j;
+			b43legacy_phy_write(dev, 0x002F, fval);
+			mls = b43legacy_phy_lo_b_r15_loop(dev) / 10;
+			if (mls < phy->minlowsig[1]) {
+				phy->minlowsig[1] = mls;
+				phy->minlowsigpos[1] = fval;
+			}
+		}
+	}
+	phy->minlowsigpos[1] += 0x0101;
+
+	b43legacy_phy_write(dev, 0x002F, phy->minlowsigpos[1]);
+	if (phy->radio_ver == 0x2053) {
+		b43legacy_phy_write(dev, 0x000A, regstack[2]);
+		b43legacy_phy_write(dev, 0x002A, regstack[3]);
+		b43legacy_phy_write(dev, 0x0035, regstack[4]);
+		b43legacy_phy_write(dev, 0x0003, regstack[5]);
+		b43legacy_phy_write(dev, 0x0001, regstack[6]);
+		b43legacy_phy_write(dev, 0x0030, regstack[7]);
+
+		b43legacy_radio_write16(dev, 0x0043, regstack[8]);
+		b43legacy_radio_write16(dev, 0x007A, regstack[9]);
+
+		b43legacy_radio_write16(dev, 0x0052,
+					(b43legacy_radio_read16(dev, 0x0052)
+					& 0x000F) | regstack[11]);
+
+		b43legacy_write16(dev, 0x03EC, regstack[10]);
+	}
+	b43legacy_phy_write(dev, 0x0015, regstack[0]);
+}
+
+static inline
+u16 b43legacy_phy_lo_g_deviation_subval(struct b43legacy_wldev *dev,
+					u16 control)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 ret;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	if (phy->gmode) {
+		b43legacy_phy_write(dev, 0x15, 0xE300);
+		control <<= 8;
+		b43legacy_phy_write(dev, 0x0812, control | 0x00B0);
+		udelay(5);
+		b43legacy_phy_write(dev, 0x0812, control | 0x00B2);
+		udelay(2);
+		b43legacy_phy_write(dev, 0x0812, control | 0x00B3);
+		udelay(4);
+		b43legacy_phy_write(dev, 0x0015, 0xF300);
+		udelay(8);
+	} else {
+		b43legacy_phy_write(dev, 0x0015, control | 0xEFA0);
+		udelay(2);
+		b43legacy_phy_write(dev, 0x0015, control | 0xEFE0);
+		udelay(4);
+		b43legacy_phy_write(dev, 0x0015, control | 0xFFE0);
+		udelay(8);
+	}
+	ret = b43legacy_phy_read(dev, 0x002D);
+	local_irq_restore(flags);
+	b43legacy_voluntary_preempt();
+
+	return ret;
+}
+
+static u32 b43legacy_phy_lo_g_singledeviation(struct b43legacy_wldev *dev,
+					      u16 control)
+{
+	int i;
+	u32 ret = 0;
+
+	for (i = 0; i < 8; i++)
+		ret += b43legacy_phy_lo_g_deviation_subval(dev, control);
+
+	return ret;
+}
+
+/* Write the LocalOscillator CONTROL */
+static inline
+void b43legacy_lo_write(struct b43legacy_wldev *dev,
+			struct b43legacy_lopair *pair)
+{
+	u16 value;
+
+	value = (u8)(pair->low);
+	value |= ((u8)(pair->high)) << 8;
+
+#ifdef CONFIG_B43LEGACY_DEBUG
+	/* Sanity check. */
+	if (pair->low < -8 || pair->low > 8 ||
+	    pair->high < -8 || pair->high > 8) {
+		b43legacydbg(dev->wl,
+		       "WARNING: Writing invalid LOpair "
+		       "(low: %d, high: %d)\n",
+		       pair->low, pair->high);
+		dump_stack();
+	}
+#endif
+
+	b43legacy_phy_write(dev, B43legacy_PHY_G_LO_CONTROL, value);
+}
+
+static inline
+struct b43legacy_lopair *b43legacy_find_lopair(struct b43legacy_wldev *dev,
+					       u16 bbatt,
+					       u16 rfatt,
+					       u16 tx)
+{
+	static const u8 dict[10] = { 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 };
+	struct b43legacy_phy *phy = &dev->phy;
+
+	if (bbatt > 6)
+		bbatt = 6;
+	B43legacy_WARN_ON(rfatt >= 10);
+
+	if (tx == 3)
+		return b43legacy_get_lopair(phy, rfatt, bbatt);
+	return b43legacy_get_lopair(phy, dict[rfatt], bbatt);
+}
+
+static inline
+struct b43legacy_lopair *b43legacy_current_lopair(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+
+	return b43legacy_find_lopair(dev, phy->bbatt,
+				     phy->rfatt, phy->txctl1);
+}
+
+/* Adjust B/G LO */
+void b43legacy_phy_lo_adjust(struct b43legacy_wldev *dev, int fixed)
+{
+	struct b43legacy_lopair *pair;
+
+	if (fixed) {
+		/* Use fixed values. Only for initialization. */
+		pair = b43legacy_find_lopair(dev, 2, 3, 0);
+	} else
+		pair = b43legacy_current_lopair(dev);
+	b43legacy_lo_write(dev, pair);
+}
+
+static void b43legacy_phy_lo_g_measure_txctl2(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 txctl2 = 0;
+	u16 i;
+	u32 smallest;
+	u32 tmp;
+
+	b43legacy_radio_write16(dev, 0x0052, 0x0000);
+	udelay(10);
+	smallest = b43legacy_phy_lo_g_singledeviation(dev, 0);
+	for (i = 0; i < 16; i++) {
+		b43legacy_radio_write16(dev, 0x0052, i);
+		udelay(10);
+		tmp = b43legacy_phy_lo_g_singledeviation(dev, 0);
+		if (tmp < smallest) {
+			smallest = tmp;
+			txctl2 = i;
+		}
+	}
+	phy->txctl2 = txctl2;
+}
+
+static
+void b43legacy_phy_lo_g_state(struct b43legacy_wldev *dev,
+			      const struct b43legacy_lopair *in_pair,
+			      struct b43legacy_lopair *out_pair,
+			      u16 r27)
+{
+	static const struct b43legacy_lopair transitions[8] = {
+		{ .high =  1,  .low =  1, },
+		{ .high =  1,  .low =  0, },
+		{ .high =  1,  .low = -1, },
+		{ .high =  0,  .low = -1, },
+		{ .high = -1,  .low = -1, },
+		{ .high = -1,  .low =  0, },
+		{ .high = -1,  .low =  1, },
+		{ .high =  0,  .low =  1, },
+	};
+	struct b43legacy_lopair lowest_transition = {
+		.high = in_pair->high,
+		.low = in_pair->low,
+	};
+	struct b43legacy_lopair tmp_pair;
+	struct b43legacy_lopair transition;
+	int i = 12;
+	int state = 0;
+	int found_lower;
+	int j;
+	int begin;
+	int end;
+	u32 lowest_deviation;
+	u32 tmp;
+
+	/* Note that in_pair and out_pair can point to the same pair.
+	 * Be careful. */
+
+	b43legacy_lo_write(dev, &lowest_transition);
+	lowest_deviation = b43legacy_phy_lo_g_singledeviation(dev, r27);
+	do {
+		found_lower = 0;
+		B43legacy_WARN_ON(!(state >= 0 && state <= 8));
+		if (state == 0) {
+			begin = 1;
+			end = 8;
+		} else if (state % 2 == 0) {
+			begin = state - 1;
+			end = state + 1;
+		} else {
+			begin = state - 2;
+			end = state + 2;
+		}
+		if (begin < 1)
+			begin += 8;
+		if (end > 8)
+			end -= 8;
+
+		j = begin;
+		tmp_pair.high = lowest_transition.high;
+		tmp_pair.low = lowest_transition.low;
+		while (1) {
+			B43legacy_WARN_ON(!(j >= 1 && j <= 8));
+			transition.high = tmp_pair.high +
+					  transitions[j - 1].high;
+			transition.low = tmp_pair.low + transitions[j - 1].low;
+			if ((abs(transition.low) < 9)
+			     && (abs(transition.high) < 9)) {
+				b43legacy_lo_write(dev, &transition);
+				tmp = b43legacy_phy_lo_g_singledeviation(dev,
+								       r27);
+				if (tmp < lowest_deviation) {
+					lowest_deviation = tmp;
+					state = j;
+					found_lower = 1;
+
+					lowest_transition.high =
+								transition.high;
+					lowest_transition.low = transition.low;
+				}
+			}
+			if (j == end)
+				break;
+			if (j == 8)
+				j = 1;
+			else
+				j++;
+		}
+	} while (i-- && found_lower);
+
+	out_pair->high = lowest_transition.high;
+	out_pair->low = lowest_transition.low;
+}
+
+/* Set the baseband attenuation value on chip. */
+void b43legacy_phy_set_baseband_attenuation(struct b43legacy_wldev *dev,
+					    u16 bbatt)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 value;
+
+	if (phy->analog == 0) {
+		value = (b43legacy_read16(dev, 0x03E6) & 0xFFF0);
+		value |= (bbatt & 0x000F);
+		b43legacy_write16(dev, 0x03E6, value);
+		return;
+	}
+
+	if (phy->analog > 1) {
+		value = b43legacy_phy_read(dev, 0x0060) & 0xFFC3;
+		value |= (bbatt << 2) & 0x003C;
+	} else {
+		value = b43legacy_phy_read(dev, 0x0060) & 0xFF87;
+		value |= (bbatt << 3) & 0x0078;
+	}
+	b43legacy_phy_write(dev, 0x0060, value);
+}
+
+/* http://bcm-specs.sipsolutions.net/LocalOscillator/Measure */
+void b43legacy_phy_lo_g_measure(struct b43legacy_wldev *dev)
+{
+	static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 };
+	const int is_initializing = (b43legacy_status(dev)
+				     < B43legacy_STAT_STARTED);
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 h;
+	u16 i;
+	u16 oldi = 0;
+	u16 j;
+	struct b43legacy_lopair control;
+	struct b43legacy_lopair *tmp_control;
+	u16 tmp;
+	u16 regstack[16] = { 0 };
+	u8 oldchannel;
+
+	/* XXX: What are these? */
+	u8 r27 = 0;
+	u16 r31;
+
+	oldchannel = phy->channel;
+	/* Setup */
+	if (phy->gmode) {
+		regstack[0] = b43legacy_phy_read(dev, B43legacy_PHY_G_CRS);
+		regstack[1] = b43legacy_phy_read(dev, 0x0802);
+		b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, regstack[0]
+				    & 0x7FFF);
+		b43legacy_phy_write(dev, 0x0802, regstack[1] & 0xFFFC);
+	}
+	regstack[3] = b43legacy_read16(dev, 0x03E2);
+	b43legacy_write16(dev, 0x03E2, regstack[3] | 0x8000);
+	regstack[4] = b43legacy_read16(dev, B43legacy_MMIO_CHANNEL_EXT);
+	regstack[5] = b43legacy_phy_read(dev, 0x15);
+	regstack[6] = b43legacy_phy_read(dev, 0x2A);
+	regstack[7] = b43legacy_phy_read(dev, 0x35);
+	regstack[8] = b43legacy_phy_read(dev, 0x60);
+	regstack[9] = b43legacy_radio_read16(dev, 0x43);
+	regstack[10] = b43legacy_radio_read16(dev, 0x7A);
+	regstack[11] = b43legacy_radio_read16(dev, 0x52);
+	if (phy->gmode) {
+		regstack[12] = b43legacy_phy_read(dev, 0x0811);
+		regstack[13] = b43legacy_phy_read(dev, 0x0812);
+		regstack[14] = b43legacy_phy_read(dev, 0x0814);
+		regstack[15] = b43legacy_phy_read(dev, 0x0815);
+	}
+	b43legacy_radio_selectchannel(dev, 6, 0);
+	if (phy->gmode) {
+		b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, regstack[0]
+				    & 0x7FFF);
+		b43legacy_phy_write(dev, 0x0802, regstack[1] & 0xFFFC);
+		b43legacy_dummy_transmission(dev);
+	}
+	b43legacy_radio_write16(dev, 0x0043, 0x0006);
+
+	b43legacy_phy_set_baseband_attenuation(dev, 2);
+
+	b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, 0x0000);
+	b43legacy_phy_write(dev, 0x002E, 0x007F);
+	b43legacy_phy_write(dev, 0x080F, 0x0078);
+	b43legacy_phy_write(dev, 0x0035, regstack[7] & ~(1 << 7));
+	b43legacy_radio_write16(dev, 0x007A, regstack[10] & 0xFFF0);
+	b43legacy_phy_write(dev, 0x002B, 0x0203);
+	b43legacy_phy_write(dev, 0x002A, 0x08A3);
+	if (phy->gmode) {
+		b43legacy_phy_write(dev, 0x0814, regstack[14] | 0x0003);
+		b43legacy_phy_write(dev, 0x0815, regstack[15] & 0xFFFC);
+		b43legacy_phy_write(dev, 0x0811, 0x01B3);
+		b43legacy_phy_write(dev, 0x0812, 0x00B2);
+	}
+	if (is_initializing)
+		b43legacy_phy_lo_g_measure_txctl2(dev);
+	b43legacy_phy_write(dev, 0x080F, 0x8078);
+
+	/* Measure */
+	control.low = 0;
+	control.high = 0;
+	for (h = 0; h < 10; h++) {
+		/* Loop over each possible RadioAttenuation (0-9) */
+		i = pairorder[h];
+		if (is_initializing) {
+			if (i == 3) {
+				control.low = 0;
+				control.high = 0;
+			} else if (((i % 2 == 1) && (oldi % 2 == 1)) ||
+				  ((i % 2 == 0) && (oldi % 2 == 0))) {
+				tmp_control = b43legacy_get_lopair(phy, oldi,
+								   0);
+				memcpy(&control, tmp_control, sizeof(control));
+			} else {
+				tmp_control = b43legacy_get_lopair(phy, 3, 0);
+				memcpy(&control, tmp_control, sizeof(control));
+			}
+		}
+		/* Loop over each possible BasebandAttenuation/2 */
+		for (j = 0; j < 4; j++) {
+			if (is_initializing) {
+				tmp = i * 2 + j;
+				r27 = 0;
+				r31 = 0;
+				if (tmp > 14) {
+					r31 = 1;
+					if (tmp > 17)
+						r27 = 1;
+					if (tmp > 19)
+						r27 = 2;
+				}
+			} else {
+				tmp_control = b43legacy_get_lopair(phy, i,
+								   j * 2);
+				if (!tmp_control->used)
+					continue;
+				memcpy(&control, tmp_control, sizeof(control));
+				r27 = 3;
+				r31 = 0;
+			}
+			b43legacy_radio_write16(dev, 0x43, i);
+			b43legacy_radio_write16(dev, 0x52, phy->txctl2);
+			udelay(10);
+			b43legacy_voluntary_preempt();
+
+			b43legacy_phy_set_baseband_attenuation(dev, j * 2);
+
+			tmp = (regstack[10] & 0xFFF0);
+			if (r31)
+				tmp |= 0x0008;
+			b43legacy_radio_write16(dev, 0x007A, tmp);
+
+			tmp_control = b43legacy_get_lopair(phy, i, j * 2);
+			b43legacy_phy_lo_g_state(dev, &control, tmp_control,
+						 r27);
+		}
+		oldi = i;
+	}
+	/* Loop over each possible RadioAttenuation (10-13) */
+	for (i = 10; i < 14; i++) {
+		/* Loop over each possible BasebandAttenuation/2 */
+		for (j = 0; j < 4; j++) {
+			if (is_initializing) {
+				tmp_control = b43legacy_get_lopair(phy, i - 9,
+								 j * 2);
+				memcpy(&control, tmp_control, sizeof(control));
+				/* FIXME: The next line is wrong, as the
+				 * following if statement can never trigger. */
+				tmp = (i - 9) * 2 + j - 5;
+				r27 = 0;
+				r31 = 0;
+				if (tmp > 14) {
+					r31 = 1;
+					if (tmp > 17)
+						r27 = 1;
+					if (tmp > 19)
+						r27 = 2;
+				}
+			} else {
+				tmp_control = b43legacy_get_lopair(phy, i - 9,
+								   j * 2);
+				if (!tmp_control->used)
+					continue;
+				memcpy(&control, tmp_control, sizeof(control));
+				r27 = 3;
+				r31 = 0;
+			}
+			b43legacy_radio_write16(dev, 0x43, i - 9);
+			/* FIXME: shouldn't txctl1 be zero in the next line
+			 * and 3 in the loop above? */
+			b43legacy_radio_write16(dev, 0x52,
+					      phy->txctl2
+					      | (3/*txctl1*/ << 4));
+			udelay(10);
+			b43legacy_voluntary_preempt();
+
+			b43legacy_phy_set_baseband_attenuation(dev, j * 2);
+
+			tmp = (regstack[10] & 0xFFF0);
+			if (r31)
+				tmp |= 0x0008;
+			b43legacy_radio_write16(dev, 0x7A, tmp);
+
+			tmp_control = b43legacy_get_lopair(phy, i, j * 2);
+			b43legacy_phy_lo_g_state(dev, &control, tmp_control,
+						 r27);
+		}
+	}
+
+	/* Restoration */
+	if (phy->gmode) {
+		b43legacy_phy_write(dev, 0x0015, 0xE300);
+		b43legacy_phy_write(dev, 0x0812, (r27 << 8) | 0xA0);
+		udelay(5);
+		b43legacy_phy_write(dev, 0x0812, (r27 << 8) | 0xA2);
+		udelay(2);
+		b43legacy_phy_write(dev, 0x0812, (r27 << 8) | 0xA3);
+		b43legacy_voluntary_preempt();
+	} else
+		b43legacy_phy_write(dev, 0x0015, r27 | 0xEFA0);
+	b43legacy_phy_lo_adjust(dev, is_initializing);
+	b43legacy_phy_write(dev, 0x002E, 0x807F);
+	if (phy->gmode)
+		b43legacy_phy_write(dev, 0x002F, 0x0202);
+	else
+		b43legacy_phy_write(dev, 0x002F, 0x0101);
+	b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, regstack[4]);
+	b43legacy_phy_write(dev, 0x0015, regstack[5]);
+	b43legacy_phy_write(dev, 0x002A, regstack[6]);
+	b43legacy_phy_write(dev, 0x0035, regstack[7]);
+	b43legacy_phy_write(dev, 0x0060, regstack[8]);
+	b43legacy_radio_write16(dev, 0x0043, regstack[9]);
+	b43legacy_radio_write16(dev, 0x007A, regstack[10]);
+	regstack[11] &= 0x00F0;
+	regstack[11] |= (b43legacy_radio_read16(dev, 0x52) & 0x000F);
+	b43legacy_radio_write16(dev, 0x52, regstack[11]);
+	b43legacy_write16(dev, 0x03E2, regstack[3]);
+	if (phy->gmode) {
+		b43legacy_phy_write(dev, 0x0811, regstack[12]);
+		b43legacy_phy_write(dev, 0x0812, regstack[13]);
+		b43legacy_phy_write(dev, 0x0814, regstack[14]);
+		b43legacy_phy_write(dev, 0x0815, regstack[15]);
+		b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, regstack[0]);
+		b43legacy_phy_write(dev, 0x0802, regstack[1]);
+	}
+	b43legacy_radio_selectchannel(dev, oldchannel, 1);
+
+#ifdef CONFIG_B43LEGACY_DEBUG
+	{
+		/* Sanity check for all lopairs. */
+		for (i = 0; i < B43legacy_LO_COUNT; i++) {
+			tmp_control = phy->_lo_pairs + i;
+			if (tmp_control->low < -8 || tmp_control->low > 8 ||
+			    tmp_control->high < -8 || tmp_control->high > 8)
+				b43legacywarn(dev->wl,
+				       "WARNING: Invalid LOpair (low: %d, high:"
+				       " %d, index: %d)\n",
+				       tmp_control->low, tmp_control->high, i);
+		}
+	}
+#endif /* CONFIG_B43LEGACY_DEBUG */
+}
+
+static
+void b43legacy_phy_lo_mark_current_used(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_lopair *pair;
+
+	pair = b43legacy_current_lopair(dev);
+	pair->used = 1;
+}
+
+void b43legacy_phy_lo_mark_all_unused(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	struct b43legacy_lopair *pair;
+	int i;
+
+	for (i = 0; i < B43legacy_LO_COUNT; i++) {
+		pair = phy->_lo_pairs + i;
+		pair->used = 0;
+	}
+}
+
+/* http://bcm-specs.sipsolutions.net/EstimatePowerOut
+ * This function converts a TSSI value to dBm in Q5.2
+ */
+static s8 b43legacy_phy_estimate_power_out(struct b43legacy_wldev *dev, s8 tssi)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	s8 dbm = 0;
+	s32 tmp;
+
+	tmp = phy->idle_tssi;
+	tmp += tssi;
+	tmp -= phy->savedpctlreg;
+
+	switch (phy->type) {
+	case B43legacy_PHYTYPE_B:
+	case B43legacy_PHYTYPE_G:
+		tmp = clamp_val(tmp, 0x00, 0x3F);
+		dbm = phy->tssi2dbm[tmp];
+		break;
+	default:
+		B43legacy_BUG_ON(1);
+	}
+
+	return dbm;
+}
+
+/* http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower */
+void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 tmp;
+	u16 txpower;
+	s8 v0;
+	s8 v1;
+	s8 v2;
+	s8 v3;
+	s8 average;
+	int max_pwr;
+	s16 desired_pwr;
+	s16 estimated_pwr;
+	s16 pwr_adjust;
+	s16 radio_att_delta;
+	s16 baseband_att_delta;
+	s16 radio_attenuation;
+	s16 baseband_attenuation;
+
+	if (phy->savedpctlreg == 0xFFFF)
+		return;
+	if ((dev->dev->bus->boardinfo.type == 0x0416) &&
+	    is_bcm_board_vendor(dev))
+		return;
+#ifdef CONFIG_B43LEGACY_DEBUG
+	if (phy->manual_txpower_control)
+		return;
+#endif
+
+	B43legacy_BUG_ON(!(phy->type == B43legacy_PHYTYPE_B ||
+			 phy->type == B43legacy_PHYTYPE_G));
+	tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x0058);
+	v0 = (s8)(tmp & 0x00FF);
+	v1 = (s8)((tmp & 0xFF00) >> 8);
+	tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x005A);
+	v2 = (s8)(tmp & 0x00FF);
+	v3 = (s8)((tmp & 0xFF00) >> 8);
+	tmp = 0;
+
+	if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F) {
+		tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,
+					 0x0070);
+		v0 = (s8)(tmp & 0x00FF);
+		v1 = (s8)((tmp & 0xFF00) >> 8);
+		tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,
+					 0x0072);
+		v2 = (s8)(tmp & 0x00FF);
+		v3 = (s8)((tmp & 0xFF00) >> 8);
+		if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F)
+			return;
+		v0 = (v0 + 0x20) & 0x3F;
+		v1 = (v1 + 0x20) & 0x3F;
+		v2 = (v2 + 0x20) & 0x3F;
+		v3 = (v3 + 0x20) & 0x3F;
+		tmp = 1;
+	}
+	b43legacy_radio_clear_tssi(dev);
+
+	average = (v0 + v1 + v2 + v3 + 2) / 4;
+
+	if (tmp && (b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x005E)
+	    & 0x8))
+		average -= 13;
+
+	estimated_pwr = b43legacy_phy_estimate_power_out(dev, average);
+
+	max_pwr = dev->dev->bus->sprom.maxpwr_bg;
+
+	if ((dev->dev->bus->sprom.boardflags_lo
+	     & B43legacy_BFL_PACTRL) &&
+	    (phy->type == B43legacy_PHYTYPE_G))
+		max_pwr -= 0x3;
+	if (unlikely(max_pwr <= 0)) {
+		b43legacywarn(dev->wl, "Invalid max-TX-power value in SPROM."
+			"\n");
+		max_pwr = 74; /* fake it */
+		dev->dev->bus->sprom.maxpwr_bg = max_pwr;
+	}
+
+	/* Use regulatory information to get the maximum power.
+	 * In the absence of such data from mac80211, we will use 20 dBm, which
+	 * is the value for the EU, US, Canada, and most of the world.
+	 * The regulatory maximum is reduced by the antenna gain (from sprom)
+	 * and 1.5 dBm (a safety factor??). The result is in Q5.2 format
+	 * which accounts for the factor of 4 */
+#define REG_MAX_PWR 20
+	max_pwr = min(REG_MAX_PWR * 4
+		      - dev->dev->bus->sprom.antenna_gain.a0
+		      - 0x6, max_pwr);
+
+	/* find the desired power in Q5.2 - power_level is in dBm
+	 * and limit it - max_pwr is already in Q5.2 */
+	desired_pwr = clamp_val(phy->power_level << 2, 0, max_pwr);
+	if (b43legacy_debug(dev, B43legacy_DBG_XMITPOWER))
+		b43legacydbg(dev->wl, "Current TX power output: " Q52_FMT
+		       " dBm, Desired TX power output: " Q52_FMT
+		       " dBm\n", Q52_ARG(estimated_pwr),
+		       Q52_ARG(desired_pwr));
+	/* Check if we need to adjust the current power. The factor of 2 is
+	 * for damping */
+	pwr_adjust = (desired_pwr - estimated_pwr) / 2;
+	/* RF attenuation delta
+	 * The minus sign is because lower attenuation => more power */
+	radio_att_delta = -(pwr_adjust + 7) >> 3;
+	/* Baseband attenuation delta */
+	baseband_att_delta = -(pwr_adjust >> 1) - (4 * radio_att_delta);
+	/* Do we need to adjust anything? */
+	if ((radio_att_delta == 0) && (baseband_att_delta == 0)) {
+		b43legacy_phy_lo_mark_current_used(dev);
+		return;
+	}
+
+	/* Calculate the new attenuation values. */
+	baseband_attenuation = phy->bbatt;
+	baseband_attenuation += baseband_att_delta;
+	radio_attenuation = phy->rfatt;
+	radio_attenuation += radio_att_delta;
+
+	/* Get baseband and radio attenuation values into permitted ranges.
+	 * baseband 0-11, radio 0-9.
+	 * Radio attenuation affects power level 4 times as much as baseband.
+	 */
+	if (radio_attenuation < 0) {
+		baseband_attenuation -= (4 * -radio_attenuation);
+		radio_attenuation = 0;
+	} else if (radio_attenuation > 9) {
+		baseband_attenuation += (4 * (radio_attenuation - 9));
+		radio_attenuation = 9;
+	} else {
+		while (baseband_attenuation < 0 && radio_attenuation > 0) {
+			baseband_attenuation += 4;
+			radio_attenuation--;
+		}
+		while (baseband_attenuation > 11 && radio_attenuation < 9) {
+			baseband_attenuation -= 4;
+			radio_attenuation++;
+		}
+	}
+	baseband_attenuation = clamp_val(baseband_attenuation, 0, 11);
+
+	txpower = phy->txctl1;
+	if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 2)) {
+		if (radio_attenuation <= 1) {
+			if (txpower == 0) {
+				txpower = 3;
+				radio_attenuation += 2;
+				baseband_attenuation += 2;
+			} else if (dev->dev->bus->sprom.boardflags_lo
+				   & B43legacy_BFL_PACTRL) {
+				baseband_attenuation += 4 *
+						     (radio_attenuation - 2);
+				radio_attenuation = 2;
+			}
+		} else if (radio_attenuation > 4 && txpower != 0) {
+			txpower = 0;
+			if (baseband_attenuation < 3) {
+				radio_attenuation -= 3;
+				baseband_attenuation += 2;
+			} else {
+				radio_attenuation -= 2;
+				baseband_attenuation -= 2;
+			}
+		}
+	}
+	/* Save the control values */
+	phy->txctl1 = txpower;
+	baseband_attenuation = clamp_val(baseband_attenuation, 0, 11);
+	radio_attenuation = clamp_val(radio_attenuation, 0, 9);
+	phy->rfatt = radio_attenuation;
+	phy->bbatt = baseband_attenuation;
+
+	/* Adjust the hardware */
+	b43legacy_phy_lock(dev);
+	b43legacy_radio_lock(dev);
+	b43legacy_radio_set_txpower_bg(dev, baseband_attenuation,
+				       radio_attenuation, txpower);
+	b43legacy_phy_lo_mark_current_used(dev);
+	b43legacy_radio_unlock(dev);
+	b43legacy_phy_unlock(dev);
+}
+
+static inline
+s32 b43legacy_tssi2dbm_ad(s32 num, s32 den)
+{
+	if (num < 0)
+		return num/den;
+	else
+		return (num+den/2)/den;
+}
+
+static inline
+s8 b43legacy_tssi2dbm_entry(s8 entry [], u8 index, s16 pab0, s16 pab1, s16 pab2)
+{
+	s32 m1;
+	s32 m2;
+	s32 f = 256;
+	s32 q;
+	s32 delta;
+	s8 i = 0;
+
+	m1 = b43legacy_tssi2dbm_ad(16 * pab0 + index * pab1, 32);
+	m2 = max(b43legacy_tssi2dbm_ad(32768 + index * pab2, 256), 1);
+	do {
+		if (i > 15)
+			return -EINVAL;
+		q = b43legacy_tssi2dbm_ad(f * 4096 -
+					  b43legacy_tssi2dbm_ad(m2 * f, 16) *
+					  f, 2048);
+		delta = abs(q - f);
+		f = q;
+		i++;
+	} while (delta >= 2);
+	entry[index] = clamp_val(b43legacy_tssi2dbm_ad(m1 * f, 8192),
+				   -127, 128);
+	return 0;
+}
+
+/* http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table */
+int b43legacy_phy_init_tssi2dbm_table(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	s16 pab0;
+	s16 pab1;
+	s16 pab2;
+	u8 idx;
+	s8 *dyn_tssi2dbm;
+
+	B43legacy_WARN_ON(!(phy->type == B43legacy_PHYTYPE_B ||
+			  phy->type == B43legacy_PHYTYPE_G));
+	pab0 = (s16)(dev->dev->bus->sprom.pa0b0);
+	pab1 = (s16)(dev->dev->bus->sprom.pa0b1);
+	pab2 = (s16)(dev->dev->bus->sprom.pa0b2);
+
+	if ((dev->dev->bus->chip_id == 0x4301) && (phy->radio_ver != 0x2050)) {
+		phy->idle_tssi = 0x34;
+		phy->tssi2dbm = b43legacy_tssi2dbm_b_table;
+		return 0;
+	}
+
+	if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
+	    pab0 != -1 && pab1 != -1 && pab2 != -1) {
+		/* The pabX values are set in SPROM. Use them. */
+		if ((s8)dev->dev->bus->sprom.itssi_bg != 0 &&
+		    (s8)dev->dev->bus->sprom.itssi_bg != -1)
+			phy->idle_tssi = (s8)(dev->dev->bus->sprom.
+					  itssi_bg);
+		else
+			phy->idle_tssi = 62;
+		dyn_tssi2dbm = kmalloc(64, GFP_KERNEL);
+		if (dyn_tssi2dbm == NULL) {
+			b43legacyerr(dev->wl, "Could not allocate memory "
+			       "for tssi2dbm table\n");
+			return -ENOMEM;
+		}
+		for (idx = 0; idx < 64; idx++)
+			if (b43legacy_tssi2dbm_entry(dyn_tssi2dbm, idx, pab0,
+						     pab1, pab2)) {
+				phy->tssi2dbm = NULL;
+				b43legacyerr(dev->wl, "Could not generate "
+				       "tssi2dBm table\n");
+				kfree(dyn_tssi2dbm);
+				return -ENODEV;
+			}
+		phy->tssi2dbm = dyn_tssi2dbm;
+		phy->dyn_tssi_tbl = 1;
+	} else {
+		/* pabX values not set in SPROM. */
+		switch (phy->type) {
+		case B43legacy_PHYTYPE_B:
+			phy->idle_tssi = 0x34;
+			phy->tssi2dbm = b43legacy_tssi2dbm_b_table;
+			break;
+		case B43legacy_PHYTYPE_G:
+			phy->idle_tssi = 0x34;
+			phy->tssi2dbm = b43legacy_tssi2dbm_g_table;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+int b43legacy_phy_init(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	int err = -ENODEV;
+
+	switch (phy->type) {
+	case B43legacy_PHYTYPE_B:
+		switch (phy->rev) {
+		case 2:
+			b43legacy_phy_initb2(dev);
+			err = 0;
+			break;
+		case 4:
+			b43legacy_phy_initb4(dev);
+			err = 0;
+			break;
+		case 5:
+			b43legacy_phy_initb5(dev);
+			err = 0;
+			break;
+		case 6:
+			b43legacy_phy_initb6(dev);
+			err = 0;
+			break;
+		}
+		break;
+	case B43legacy_PHYTYPE_G:
+		b43legacy_phy_initg(dev);
+		err = 0;
+		break;
+	}
+	if (err)
+		b43legacyerr(dev->wl, "Unknown PHYTYPE found\n");
+
+	return err;
+}
+
+void b43legacy_phy_set_antenna_diversity(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 antennadiv;
+	u16 offset;
+	u16 value;
+	u32 ucodeflags;
+
+	antennadiv = phy->antenna_diversity;
+
+	if (antennadiv == 0xFFFF)
+		antennadiv = 3;
+	B43legacy_WARN_ON(antennadiv > 3);
+
+	ucodeflags = b43legacy_shm_read32(dev, B43legacy_SHM_SHARED,
+					  B43legacy_UCODEFLAGS_OFFSET);
+	b43legacy_shm_write32(dev, B43legacy_SHM_SHARED,
+			      B43legacy_UCODEFLAGS_OFFSET,
+			      ucodeflags & ~B43legacy_UCODEFLAG_AUTODIV);
+
+	switch (phy->type) {
+	case B43legacy_PHYTYPE_G:
+		offset = 0x0400;
+
+		if (antennadiv == 2)
+			value = (3/*automatic*/ << 7);
+		else
+			value = (antennadiv << 7);
+		b43legacy_phy_write(dev, offset + 1,
+				    (b43legacy_phy_read(dev, offset + 1)
+				    & 0x7E7F) | value);
+
+		if (antennadiv >= 2) {
+			if (antennadiv == 2)
+				value = (antennadiv << 7);
+			else
+				value = (0/*force0*/ << 7);
+			b43legacy_phy_write(dev, offset + 0x2B,
+					    (b43legacy_phy_read(dev,
+					    offset + 0x2B)
+					    & 0xFEFF) | value);
+		}
+
+		if (phy->type == B43legacy_PHYTYPE_G) {
+			if (antennadiv >= 2)
+				b43legacy_phy_write(dev, 0x048C,
+						    b43legacy_phy_read(dev,
+						    0x048C) | 0x2000);
+			else
+				b43legacy_phy_write(dev, 0x048C,
+						    b43legacy_phy_read(dev,
+						    0x048C) & ~0x2000);
+			if (phy->rev >= 2) {
+				b43legacy_phy_write(dev, 0x0461,
+						    b43legacy_phy_read(dev,
+						    0x0461) | 0x0010);
+				b43legacy_phy_write(dev, 0x04AD,
+						    (b43legacy_phy_read(dev,
+						    0x04AD)
+						    & 0x00FF) | 0x0015);
+				if (phy->rev == 2)
+					b43legacy_phy_write(dev, 0x0427,
+							    0x0008);
+				else
+					b43legacy_phy_write(dev, 0x0427,
+						(b43legacy_phy_read(dev, 0x0427)
+						 & 0x00FF) | 0x0008);
+			} else if (phy->rev >= 6)
+				b43legacy_phy_write(dev, 0x049B, 0x00DC);
+		} else {
+			if (phy->rev < 3)
+				b43legacy_phy_write(dev, 0x002B,
+						    (b43legacy_phy_read(dev,
+						    0x002B) & 0x00FF)
+						    | 0x0024);
+			else {
+				b43legacy_phy_write(dev, 0x0061,
+						    b43legacy_phy_read(dev,
+						    0x0061) | 0x0010);
+				if (phy->rev == 3) {
+					b43legacy_phy_write(dev, 0x0093,
+							    0x001D);
+					b43legacy_phy_write(dev, 0x0027,
+							    0x0008);
+				} else {
+					b43legacy_phy_write(dev, 0x0093,
+							    0x003A);
+					b43legacy_phy_write(dev, 0x0027,
+						(b43legacy_phy_read(dev, 0x0027)
+						 & 0x00FF) | 0x0008);
+				}
+			}
+		}
+		break;
+	case B43legacy_PHYTYPE_B:
+		if (dev->dev->id.revision == 2)
+			value = (3/*automatic*/ << 7);
+		else
+			value = (antennadiv << 7);
+		b43legacy_phy_write(dev, 0x03E2,
+				    (b43legacy_phy_read(dev, 0x03E2)
+				    & 0xFE7F) | value);
+		break;
+	default:
+		B43legacy_WARN_ON(1);
+	}
+
+	if (antennadiv >= 2) {
+		ucodeflags = b43legacy_shm_read32(dev, B43legacy_SHM_SHARED,
+						  B43legacy_UCODEFLAGS_OFFSET);
+		b43legacy_shm_write32(dev, B43legacy_SHM_SHARED,
+				      B43legacy_UCODEFLAGS_OFFSET,
+				      ucodeflags | B43legacy_UCODEFLAG_AUTODIV);
+	}
+
+	phy->antenna_diversity = antennadiv;
+}
+
+/* Set the PowerSavingControlBits.
+ * Bitvalues:
+ *   0  => unset the bit
+ *   1  => set the bit
+ *   -1 => calculate the bit
+ */
+void b43legacy_power_saving_ctl_bits(struct b43legacy_wldev *dev,
+				     int bit25, int bit26)
+{
+	int i;
+	u32 status;
+
+/* FIXME: Force 25 to off and 26 to on for now: */
+bit25 = 0;
+bit26 = 1;
+
+	if (bit25 == -1) {
+		/* TODO: If powersave is not off and FIXME is not set and we
+		 *	are not in adhoc and thus is not an AP and we arei
+		 *	associated, set bit 25 */
+	}
+	if (bit26 == -1) {
+		/* TODO: If the device is awake or this is an AP, or we are
+		 *	scanning, or FIXME, or we are associated, or FIXME,
+		 *	or the latest PS-Poll packet sent was successful,
+		 *	set bit26  */
+	}
+	status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	if (bit25)
+		status |= B43legacy_MACCTL_HWPS;
+	else
+		status &= ~B43legacy_MACCTL_HWPS;
+	if (bit26)
+		status |= B43legacy_MACCTL_AWAKE;
+	else
+		status &= ~B43legacy_MACCTL_AWAKE;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status);
+	if (bit26 && dev->dev->id.revision >= 5) {
+		for (i = 0; i < 100; i++) {
+			if (b43legacy_shm_read32(dev, B43legacy_SHM_SHARED,
+						 0x0040) != 4)
+				break;
+			udelay(10);
+		}
+	}
+}
diff --git a/drivers/net/wireless/broadcom/b43legacy/phy.h b/drivers/net/wireless/broadcom/b43legacy/phy.h
new file mode 100644
index 0000000..831a7a4
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/phy.h
@@ -0,0 +1,209 @@
+/*
+
+  Broadcom B43legacy wireless driver
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+		     Stefano Brivio <stefano.brivio@polimi.it>
+		     Michael Buesch <m@bues.ch>
+		     Danny van Dyk <kugelfang@gentoo.org>
+		     Andreas Jaggi <andreas.jaggi@waterwave.ch>
+  Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
+
+  Some parts of the code in this file are derived from the ipw2200
+  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+
+  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.
+
+*/
+
+#ifndef B43legacy_PHY_H_
+#define B43legacy_PHY_H_
+
+#include <linux/types.h>
+
+enum {
+	B43legacy_ANTENNA0,	  /* Antenna 0 */
+	B43legacy_ANTENNA1,	  /* Antenna 0 */
+	B43legacy_ANTENNA_AUTO1,  /* Automatic, starting with antenna 1 */
+	B43legacy_ANTENNA_AUTO0,  /* Automatic, starting with antenna 0 */
+
+	B43legacy_ANTENNA_AUTO	= B43legacy_ANTENNA_AUTO0,
+	B43legacy_ANTENNA_DEFAULT = B43legacy_ANTENNA_AUTO,
+};
+
+enum {
+	B43legacy_INTERFMODE_NONE,
+	B43legacy_INTERFMODE_NONWLAN,
+	B43legacy_INTERFMODE_MANUALWLAN,
+	B43legacy_INTERFMODE_AUTOWLAN,
+};
+
+/*** PHY Registers ***/
+
+/* Routing */
+#define B43legacy_PHYROUTE_OFDM_GPHY	0x400
+#define B43legacy_PHYROUTE_EXT_GPHY	0x800
+
+/* Base registers. */
+#define B43legacy_PHY_BASE(reg)	(reg)
+/* OFDM (A) registers of a G-PHY */
+#define B43legacy_PHY_OFDM(reg)	((reg) | B43legacy_PHYROUTE_OFDM_GPHY)
+/* Extended G-PHY registers */
+#define B43legacy_PHY_EXTG(reg)	((reg) | B43legacy_PHYROUTE_EXT_GPHY)
+
+
+/* Extended G-PHY Registers */
+#define B43legacy_PHY_CLASSCTL		B43legacy_PHY_EXTG(0x02)	/* Classify control */
+#define B43legacy_PHY_GTABCTL		B43legacy_PHY_EXTG(0x03)	/* G-PHY table control (see below) */
+#define  B43legacy_PHY_GTABOFF		0x03FF			/* G-PHY table offset (see below) */
+#define  B43legacy_PHY_GTABNR		0xFC00			/* G-PHY table number (see below) */
+#define  B43legacy_PHY_GTABNR_SHIFT	10
+#define B43legacy_PHY_GTABDATA		B43legacy_PHY_EXTG(0x04)	/* G-PHY table data */
+#define B43legacy_PHY_LO_MASK		B43legacy_PHY_EXTG(0x0F)	/* Local Oscillator control mask */
+#define B43legacy_PHY_LO_CTL		B43legacy_PHY_EXTG(0x10)	/* Local Oscillator control */
+#define B43legacy_PHY_RFOVER		B43legacy_PHY_EXTG(0x11)	/* RF override */
+#define B43legacy_PHY_RFOVERVAL		B43legacy_PHY_EXTG(0x12)	/* RF override value */
+/*** OFDM table numbers ***/
+#define B43legacy_OFDMTAB(number, offset)				\
+			  (((number) << B43legacy_PHY_OTABLENR_SHIFT)	\
+			  | (offset))
+#define B43legacy_OFDMTAB_AGC1		B43legacy_OFDMTAB(0x00, 0)
+#define B43legacy_OFDMTAB_GAIN0		B43legacy_OFDMTAB(0x00, 0)
+#define B43legacy_OFDMTAB_GAINX		B43legacy_OFDMTAB(0x01, 0)
+#define B43legacy_OFDMTAB_GAIN1		B43legacy_OFDMTAB(0x01, 4)
+#define B43legacy_OFDMTAB_AGC3		B43legacy_OFDMTAB(0x02, 0)
+#define B43legacy_OFDMTAB_GAIN2		B43legacy_OFDMTAB(0x02, 3)
+#define B43legacy_OFDMTAB_LNAHPFGAIN1	B43legacy_OFDMTAB(0x03, 0)
+#define B43legacy_OFDMTAB_WRSSI		B43legacy_OFDMTAB(0x04, 0)
+#define B43legacy_OFDMTAB_LNAHPFGAIN2	B43legacy_OFDMTAB(0x04, 0)
+#define B43legacy_OFDMTAB_NOISESCALE	B43legacy_OFDMTAB(0x05, 0)
+#define B43legacy_OFDMTAB_AGC2		B43legacy_OFDMTAB(0x06, 0)
+#define B43legacy_OFDMTAB_ROTOR		B43legacy_OFDMTAB(0x08, 0)
+#define B43legacy_OFDMTAB_ADVRETARD	B43legacy_OFDMTAB(0x09, 0)
+#define B43legacy_OFDMTAB_DAC		B43legacy_OFDMTAB(0x0C, 0)
+#define B43legacy_OFDMTAB_DC		B43legacy_OFDMTAB(0x0E, 7)
+#define B43legacy_OFDMTAB_PWRDYN2	B43legacy_OFDMTAB(0x0E, 12)
+#define B43legacy_OFDMTAB_LNAGAIN	B43legacy_OFDMTAB(0x0E, 13)
+
+#define B43legacy_OFDMTAB_LPFGAIN	B43legacy_OFDMTAB(0x0F, 12)
+#define B43legacy_OFDMTAB_RSSI		B43legacy_OFDMTAB(0x10, 0)
+
+#define B43legacy_OFDMTAB_AGC1_R1	B43legacy_OFDMTAB(0x13, 0)
+#define B43legacy_OFDMTAB_GAINX_R1	B43legacy_OFDMTAB(0x14, 0)
+#define B43legacy_OFDMTAB_MINSIGSQ	B43legacy_OFDMTAB(0x14, 1)
+#define B43legacy_OFDMTAB_AGC3_R1	B43legacy_OFDMTAB(0x15, 0)
+#define B43legacy_OFDMTAB_WRSSI_R1	B43legacy_OFDMTAB(0x15, 4)
+#define B43legacy_OFDMTAB_TSSI		B43legacy_OFDMTAB(0x15, 0)
+#define B43legacy_OFDMTAB_DACRFPABB	B43legacy_OFDMTAB(0x16, 0)
+#define B43legacy_OFDMTAB_DACOFF	B43legacy_OFDMTAB(0x17, 0)
+#define B43legacy_OFDMTAB_DCBIAS	B43legacy_OFDMTAB(0x18, 0)
+
+void b43legacy_put_attenuation_into_ranges(int *_bbatt, int *_rfatt);
+
+/* OFDM (A) PHY Registers */
+#define B43legacy_PHY_VERSION_OFDM	B43legacy_PHY_OFDM(0x00)	/* Versioning register for A-PHY */
+#define B43legacy_PHY_BBANDCFG		B43legacy_PHY_OFDM(0x01)	/* Baseband config */
+#define  B43legacy_PHY_BBANDCFG_RXANT	0x180			/* RX Antenna selection */
+#define  B43legacy_PHY_BBANDCFG_RXANT_SHIFT	7
+#define B43legacy_PHY_PWRDOWN		B43legacy_PHY_OFDM(0x03)	/* Powerdown */
+#define B43legacy_PHY_CRSTHRES1		B43legacy_PHY_OFDM(0x06)	/* CRS Threshold 1 */
+#define B43legacy_PHY_LNAHPFCTL		B43legacy_PHY_OFDM(0x1C)	/* LNA/HPF control */
+#define B43legacy_PHY_ADIVRELATED	B43legacy_PHY_OFDM(0x27)	/* FIXME rename */
+#define B43legacy_PHY_CRS0		B43legacy_PHY_OFDM(0x29)
+#define B43legacy_PHY_ANTDWELL		B43legacy_PHY_OFDM(0x2B)	/* Antenna dwell */
+#define  B43legacy_PHY_ANTDWELL_AUTODIV1	0x0100			/* Automatic RX diversity start antenna */
+#define B43legacy_PHY_ENCORE		B43legacy_PHY_OFDM(0x49)	/* "Encore" (RangeMax / BroadRange) */
+#define  B43legacy_PHY_ENCORE_EN	0x0200				/* Encore enable */
+#define B43legacy_PHY_LMS		B43legacy_PHY_OFDM(0x55)
+#define B43legacy_PHY_OFDM61		B43legacy_PHY_OFDM(0x61)	/* FIXME rename */
+#define  B43legacy_PHY_OFDM61_10	0x0010				/* FIXME rename */
+#define B43legacy_PHY_IQBAL		B43legacy_PHY_OFDM(0x69)	/* I/Q balance */
+#define B43legacy_PHY_OTABLECTL		B43legacy_PHY_OFDM(0x72)	/* OFDM table control (see below) */
+#define  B43legacy_PHY_OTABLEOFF	0x03FF				/* OFDM table offset (see below) */
+#define  B43legacy_PHY_OTABLENR		0xFC00				/* OFDM table number (see below) */
+#define  B43legacy_PHY_OTABLENR_SHIFT	10
+#define B43legacy_PHY_OTABLEI		B43legacy_PHY_OFDM(0x73)	/* OFDM table data I */
+#define B43legacy_PHY_OTABLEQ		B43legacy_PHY_OFDM(0x74)	/* OFDM table data Q */
+#define B43legacy_PHY_HPWR_TSSICTL	B43legacy_PHY_OFDM(0x78)	/* Hardware power TSSI control */
+#define B43legacy_PHY_NRSSITHRES	B43legacy_PHY_OFDM(0x8A)	/* NRSSI threshold */
+#define B43legacy_PHY_ANTWRSETT		B43legacy_PHY_OFDM(0x8C)	/* Antenna WR settle */
+#define  B43legacy_PHY_ANTWRSETT_ARXDIV	0x2000				/* Automatic RX diversity enabled */
+#define B43legacy_PHY_CLIPPWRDOWNT	B43legacy_PHY_OFDM(0x93)	/* Clip powerdown threshold */
+#define B43legacy_PHY_OFDM9B		B43legacy_PHY_OFDM(0x9B)	/* FIXME rename */
+#define B43legacy_PHY_N1P1GAIN		B43legacy_PHY_OFDM(0xA0)
+#define B43legacy_PHY_P1P2GAIN		B43legacy_PHY_OFDM(0xA1)
+#define B43legacy_PHY_N1N2GAIN		B43legacy_PHY_OFDM(0xA2)
+#define B43legacy_PHY_CLIPTHRES		B43legacy_PHY_OFDM(0xA3)
+#define B43legacy_PHY_CLIPN1P2THRES	B43legacy_PHY_OFDM(0xA4)
+#define B43legacy_PHY_DIVSRCHIDX	B43legacy_PHY_OFDM(0xA8)	/* Divider search gain/index */
+#define B43legacy_PHY_CLIPP2THRES	B43legacy_PHY_OFDM(0xA9)
+#define B43legacy_PHY_CLIPP3THRES	B43legacy_PHY_OFDM(0xAA)
+#define B43legacy_PHY_DIVP1P2GAIN	B43legacy_PHY_OFDM(0xAB)
+#define B43legacy_PHY_DIVSRCHGAINBACK	B43legacy_PHY_OFDM(0xAD)	/* Divider search gain back */
+#define B43legacy_PHY_DIVSRCHGAINCHNG	B43legacy_PHY_OFDM(0xAE)	/* Divider search gain change */
+#define B43legacy_PHY_CRSTHRES1_R1	B43legacy_PHY_OFDM(0xC0)	/* CRS Threshold 1 (rev 1 only) */
+#define B43legacy_PHY_CRSTHRES2_R1	B43legacy_PHY_OFDM(0xC1)	/* CRS Threshold 2 (rev 1 only) */
+#define B43legacy_PHY_TSSIP_LTBASE	B43legacy_PHY_OFDM(0x380)	/* TSSI power lookup table base */
+#define B43legacy_PHY_DC_LTBASE		B43legacy_PHY_OFDM(0x3A0)	/* DC lookup table base */
+#define B43legacy_PHY_GAIN_LTBASE	B43legacy_PHY_OFDM(0x3C0)	/* Gain lookup table base */
+
+void b43legacy_put_attenuation_into_ranges(int *_bbatt, int *_rfatt);
+
+/* Masks for the different PHY versioning registers. */
+#define B43legacy_PHYVER_ANALOG		0xF000
+#define B43legacy_PHYVER_ANALOG_SHIFT	12
+#define B43legacy_PHYVER_TYPE		0x0F00
+#define B43legacy_PHYVER_TYPE_SHIFT	8
+#define B43legacy_PHYVER_VERSION	0x00FF
+
+struct b43legacy_wldev;
+
+void b43legacy_phy_lock(struct b43legacy_wldev *dev);
+void b43legacy_phy_unlock(struct b43legacy_wldev *dev);
+
+/* Card uses the loopback gain stuff */
+#define has_loopback_gain(phy)			 \
+	(((phy)->rev > 1) || ((phy)->gmode))
+
+u16 b43legacy_phy_read(struct b43legacy_wldev *dev, u16 offset);
+void b43legacy_phy_write(struct b43legacy_wldev *dev, u16 offset, u16 val);
+
+int b43legacy_phy_init_tssi2dbm_table(struct b43legacy_wldev *dev);
+int b43legacy_phy_init(struct b43legacy_wldev *dev);
+
+void b43legacy_set_rx_antenna(struct b43legacy_wldev *dev, int antenna);
+
+void b43legacy_phy_set_antenna_diversity(struct b43legacy_wldev *dev);
+void b43legacy_phy_calibrate(struct b43legacy_wldev *dev);
+int b43legacy_phy_connect(struct b43legacy_wldev *dev, int connect);
+
+void b43legacy_phy_lo_b_measure(struct b43legacy_wldev *dev);
+void b43legacy_phy_lo_g_measure(struct b43legacy_wldev *dev);
+void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev);
+
+/* Adjust the LocalOscillator to the saved values.
+ * "fixed" is only set to 1 once in initialization. Set to 0 otherwise.
+ */
+void b43legacy_phy_lo_adjust(struct b43legacy_wldev *dev, int fixed);
+void b43legacy_phy_lo_mark_all_unused(struct b43legacy_wldev *dev);
+
+void b43legacy_phy_set_baseband_attenuation(struct b43legacy_wldev *dev,
+					    u16 baseband_attenuation);
+
+void b43legacy_power_saving_ctl_bits(struct b43legacy_wldev *dev,
+				     int bit25, int bit26);
+
+#endif /* B43legacy_PHY_H_ */
diff --git a/drivers/net/wireless/broadcom/b43legacy/pio.c b/drivers/net/wireless/broadcom/b43legacy/pio.c
new file mode 100644
index 0000000..282eede
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/pio.c
@@ -0,0 +1,695 @@
+/*
+
+  Broadcom B43legacy wireless driver
+
+  PIO Transmission
+
+  Copyright (c) 2005 Michael Buesch <m@bues.ch>
+
+  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 "b43legacy.h"
+#include "pio.h"
+#include "main.h"
+#include "xmit.h"
+
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+
+static void tx_start(struct b43legacy_pioqueue *queue)
+{
+	b43legacy_pio_write(queue, B43legacy_PIO_TXCTL,
+			    B43legacy_PIO_TXCTL_INIT);
+}
+
+static void tx_octet(struct b43legacy_pioqueue *queue,
+		     u8 octet)
+{
+	if (queue->need_workarounds) {
+		b43legacy_pio_write(queue, B43legacy_PIO_TXDATA, octet);
+		b43legacy_pio_write(queue, B43legacy_PIO_TXCTL,
+				    B43legacy_PIO_TXCTL_WRITELO);
+	} else {
+		b43legacy_pio_write(queue, B43legacy_PIO_TXCTL,
+				    B43legacy_PIO_TXCTL_WRITELO);
+		b43legacy_pio_write(queue, B43legacy_PIO_TXDATA, octet);
+	}
+}
+
+static u16 tx_get_next_word(const u8 *txhdr,
+			    const u8 *packet,
+			    size_t txhdr_size,
+			    unsigned int *pos)
+{
+	const u8 *source;
+	unsigned int i = *pos;
+	u16 ret;
+
+	if (i < txhdr_size)
+		source = txhdr;
+	else {
+		source = packet;
+		i -= txhdr_size;
+	}
+	ret = le16_to_cpu(*((__le16 *)(source + i)));
+	*pos += 2;
+
+	return ret;
+}
+
+static void tx_data(struct b43legacy_pioqueue *queue,
+		    u8 *txhdr,
+		    const u8 *packet,
+		    unsigned int octets)
+{
+	u16 data;
+	unsigned int i = 0;
+
+	if (queue->need_workarounds) {
+		data = tx_get_next_word(txhdr, packet,
+					sizeof(struct b43legacy_txhdr_fw3), &i);
+		b43legacy_pio_write(queue, B43legacy_PIO_TXDATA, data);
+	}
+	b43legacy_pio_write(queue, B43legacy_PIO_TXCTL,
+			    B43legacy_PIO_TXCTL_WRITELO |
+			    B43legacy_PIO_TXCTL_WRITEHI);
+	while (i < octets - 1) {
+		data = tx_get_next_word(txhdr, packet,
+					sizeof(struct b43legacy_txhdr_fw3), &i);
+		b43legacy_pio_write(queue, B43legacy_PIO_TXDATA, data);
+	}
+	if (octets % 2)
+		tx_octet(queue, packet[octets -
+			 sizeof(struct b43legacy_txhdr_fw3) - 1]);
+}
+
+static void tx_complete(struct b43legacy_pioqueue *queue,
+			struct sk_buff *skb)
+{
+	if (queue->need_workarounds) {
+		b43legacy_pio_write(queue, B43legacy_PIO_TXDATA,
+				    skb->data[skb->len - 1]);
+		b43legacy_pio_write(queue, B43legacy_PIO_TXCTL,
+				    B43legacy_PIO_TXCTL_WRITELO |
+				    B43legacy_PIO_TXCTL_COMPLETE);
+	} else
+		b43legacy_pio_write(queue, B43legacy_PIO_TXCTL,
+				    B43legacy_PIO_TXCTL_COMPLETE);
+}
+
+static u16 generate_cookie(struct b43legacy_pioqueue *queue,
+			   struct b43legacy_pio_txpacket *packet)
+{
+	u16 cookie = 0x0000;
+	int packetindex;
+
+	/* We use the upper 4 bits for the PIO
+	 * controller ID and the lower 12 bits
+	 * for the packet index (in the cache).
+	 */
+	switch (queue->mmio_base) {
+	case B43legacy_MMIO_PIO1_BASE:
+		break;
+	case B43legacy_MMIO_PIO2_BASE:
+		cookie = 0x1000;
+		break;
+	case B43legacy_MMIO_PIO3_BASE:
+		cookie = 0x2000;
+		break;
+	case B43legacy_MMIO_PIO4_BASE:
+		cookie = 0x3000;
+		break;
+	default:
+		B43legacy_WARN_ON(1);
+	}
+	packetindex = pio_txpacket_getindex(packet);
+	B43legacy_WARN_ON(!(((u16)packetindex & 0xF000) == 0x0000));
+	cookie |= (u16)packetindex;
+
+	return cookie;
+}
+
+static
+struct b43legacy_pioqueue *parse_cookie(struct b43legacy_wldev *dev,
+					u16 cookie,
+					struct b43legacy_pio_txpacket **packet)
+{
+	struct b43legacy_pio *pio = &dev->pio;
+	struct b43legacy_pioqueue *queue = NULL;
+	int packetindex;
+
+	switch (cookie & 0xF000) {
+	case 0x0000:
+		queue = pio->queue0;
+		break;
+	case 0x1000:
+		queue = pio->queue1;
+		break;
+	case 0x2000:
+		queue = pio->queue2;
+		break;
+	case 0x3000:
+		queue = pio->queue3;
+		break;
+	default:
+		B43legacy_WARN_ON(1);
+	}
+	packetindex = (cookie & 0x0FFF);
+	B43legacy_WARN_ON(!(packetindex >= 0 && packetindex
+			  < B43legacy_PIO_MAXTXPACKETS));
+	*packet = &(queue->tx_packets_cache[packetindex]);
+
+	return queue;
+}
+
+union txhdr_union {
+	struct b43legacy_txhdr_fw3 txhdr_fw3;
+};
+
+static int pio_tx_write_fragment(struct b43legacy_pioqueue *queue,
+				  struct sk_buff *skb,
+				  struct b43legacy_pio_txpacket *packet,
+				  size_t txhdr_size)
+{
+	union txhdr_union txhdr_data;
+	u8 *txhdr = NULL;
+	unsigned int octets;
+	int err;
+
+	txhdr = (u8 *)(&txhdr_data.txhdr_fw3);
+
+	B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags != 0);
+	err = b43legacy_generate_txhdr(queue->dev,
+				 txhdr, skb->data, skb->len,
+				 IEEE80211_SKB_CB(skb),
+				 generate_cookie(queue, packet));
+	if (err)
+		return err;
+
+	tx_start(queue);
+	octets = skb->len + txhdr_size;
+	if (queue->need_workarounds)
+		octets--;
+	tx_data(queue, txhdr, (u8 *)skb->data, octets);
+	tx_complete(queue, skb);
+
+	return 0;
+}
+
+static void free_txpacket(struct b43legacy_pio_txpacket *packet,
+			  int irq_context)
+{
+	struct b43legacy_pioqueue *queue = packet->queue;
+
+	if (packet->skb) {
+		if (irq_context)
+			dev_kfree_skb_irq(packet->skb);
+		else
+			dev_kfree_skb(packet->skb);
+	}
+	list_move(&packet->list, &queue->txfree);
+	queue->nr_txfree++;
+}
+
+static int pio_tx_packet(struct b43legacy_pio_txpacket *packet)
+{
+	struct b43legacy_pioqueue *queue = packet->queue;
+	struct sk_buff *skb = packet->skb;
+	u16 octets;
+	int err;
+
+	octets = (u16)skb->len + sizeof(struct b43legacy_txhdr_fw3);
+	if (queue->tx_devq_size < octets) {
+		b43legacywarn(queue->dev->wl, "PIO queue too small. "
+			"Dropping packet.\n");
+		/* Drop it silently (return success) */
+		free_txpacket(packet, 1);
+		return 0;
+	}
+	B43legacy_WARN_ON(queue->tx_devq_packets >
+			  B43legacy_PIO_MAXTXDEVQPACKETS);
+	B43legacy_WARN_ON(queue->tx_devq_used > queue->tx_devq_size);
+	/* Check if there is sufficient free space on the device
+	 * TX queue. If not, return and let the TX tasklet
+	 * retry later.
+	 */
+	if (queue->tx_devq_packets == B43legacy_PIO_MAXTXDEVQPACKETS)
+		return -EBUSY;
+	if (queue->tx_devq_used + octets > queue->tx_devq_size)
+		return -EBUSY;
+	/* Now poke the device. */
+	err = pio_tx_write_fragment(queue, skb, packet,
+			      sizeof(struct b43legacy_txhdr_fw3));
+	if (unlikely(err == -ENOKEY)) {
+		/* Drop this packet, as we don't have the encryption key
+		 * anymore and must not transmit it unencrypted. */
+		free_txpacket(packet, 1);
+		return 0;
+	}
+
+	/* Account for the packet size.
+	 * (We must not overflow the device TX queue)
+	 */
+	queue->tx_devq_packets++;
+	queue->tx_devq_used += octets;
+
+	/* Transmission started, everything ok, move the
+	 * packet to the txrunning list.
+	 */
+	list_move_tail(&packet->list, &queue->txrunning);
+
+	return 0;
+}
+
+static void tx_tasklet(unsigned long d)
+{
+	struct b43legacy_pioqueue *queue = (struct b43legacy_pioqueue *)d;
+	struct b43legacy_wldev *dev = queue->dev;
+	unsigned long flags;
+	struct b43legacy_pio_txpacket *packet, *tmp_packet;
+	int err;
+	u16 txctl;
+
+	spin_lock_irqsave(&dev->wl->irq_lock, flags);
+	if (queue->tx_frozen)
+		goto out_unlock;
+	txctl = b43legacy_pio_read(queue, B43legacy_PIO_TXCTL);
+	if (txctl & B43legacy_PIO_TXCTL_SUSPEND)
+		goto out_unlock;
+
+	list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) {
+		/* Try to transmit the packet. This can fail, if
+		 * the device queue is full. In case of failure, the
+		 * packet is left in the txqueue.
+		 * If transmission succeed, the packet is moved to txrunning.
+		 * If it is impossible to transmit the packet, it
+		 * is dropped.
+		 */
+		err = pio_tx_packet(packet);
+		if (err)
+			break;
+	}
+out_unlock:
+	spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
+}
+
+static void setup_txqueues(struct b43legacy_pioqueue *queue)
+{
+	struct b43legacy_pio_txpacket *packet;
+	int i;
+
+	queue->nr_txfree = B43legacy_PIO_MAXTXPACKETS;
+	for (i = 0; i < B43legacy_PIO_MAXTXPACKETS; i++) {
+		packet = &(queue->tx_packets_cache[i]);
+
+		packet->queue = queue;
+		INIT_LIST_HEAD(&packet->list);
+
+		list_add(&packet->list, &queue->txfree);
+	}
+}
+
+static
+struct b43legacy_pioqueue *b43legacy_setup_pioqueue(struct b43legacy_wldev *dev,
+						    u16 pio_mmio_base)
+{
+	struct b43legacy_pioqueue *queue;
+	u32 value;
+	u16 qsize;
+
+	queue = kzalloc(sizeof(*queue), GFP_KERNEL);
+	if (!queue)
+		goto out;
+
+	queue->dev = dev;
+	queue->mmio_base = pio_mmio_base;
+	queue->need_workarounds = (dev->dev->id.revision < 3);
+
+	INIT_LIST_HEAD(&queue->txfree);
+	INIT_LIST_HEAD(&queue->txqueue);
+	INIT_LIST_HEAD(&queue->txrunning);
+	tasklet_init(&queue->txtask, tx_tasklet,
+		     (unsigned long)queue);
+
+	value = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	value &= ~B43legacy_MACCTL_BE;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, value);
+
+	qsize = b43legacy_read16(dev, queue->mmio_base
+				 + B43legacy_PIO_TXQBUFSIZE);
+	if (qsize == 0) {
+		b43legacyerr(dev->wl, "This card does not support PIO "
+		       "operation mode. Please use DMA mode "
+		       "(module parameter pio=0).\n");
+		goto err_freequeue;
+	}
+	if (qsize <= B43legacy_PIO_TXQADJUST) {
+		b43legacyerr(dev->wl, "PIO tx device-queue too small (%u)\n",
+		       qsize);
+		goto err_freequeue;
+	}
+	qsize -= B43legacy_PIO_TXQADJUST;
+	queue->tx_devq_size = qsize;
+
+	setup_txqueues(queue);
+
+out:
+	return queue;
+
+err_freequeue:
+	kfree(queue);
+	queue = NULL;
+	goto out;
+}
+
+static void cancel_transfers(struct b43legacy_pioqueue *queue)
+{
+	struct b43legacy_pio_txpacket *packet, *tmp_packet;
+
+	tasklet_kill(&queue->txtask);
+
+	list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list)
+		free_txpacket(packet, 0);
+	list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list)
+		free_txpacket(packet, 0);
+}
+
+static void b43legacy_destroy_pioqueue(struct b43legacy_pioqueue *queue)
+{
+	if (!queue)
+		return;
+
+	cancel_transfers(queue);
+	kfree(queue);
+}
+
+void b43legacy_pio_free(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_pio *pio;
+
+	if (!b43legacy_using_pio(dev))
+		return;
+	pio = &dev->pio;
+
+	b43legacy_destroy_pioqueue(pio->queue3);
+	pio->queue3 = NULL;
+	b43legacy_destroy_pioqueue(pio->queue2);
+	pio->queue2 = NULL;
+	b43legacy_destroy_pioqueue(pio->queue1);
+	pio->queue1 = NULL;
+	b43legacy_destroy_pioqueue(pio->queue0);
+	pio->queue0 = NULL;
+}
+
+int b43legacy_pio_init(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_pio *pio = &dev->pio;
+	struct b43legacy_pioqueue *queue;
+	int err = -ENOMEM;
+
+	queue = b43legacy_setup_pioqueue(dev, B43legacy_MMIO_PIO1_BASE);
+	if (!queue)
+		goto out;
+	pio->queue0 = queue;
+
+	queue = b43legacy_setup_pioqueue(dev, B43legacy_MMIO_PIO2_BASE);
+	if (!queue)
+		goto err_destroy0;
+	pio->queue1 = queue;
+
+	queue = b43legacy_setup_pioqueue(dev, B43legacy_MMIO_PIO3_BASE);
+	if (!queue)
+		goto err_destroy1;
+	pio->queue2 = queue;
+
+	queue = b43legacy_setup_pioqueue(dev, B43legacy_MMIO_PIO4_BASE);
+	if (!queue)
+		goto err_destroy2;
+	pio->queue3 = queue;
+
+	if (dev->dev->id.revision < 3)
+		dev->irq_mask |= B43legacy_IRQ_PIO_WORKAROUND;
+
+	b43legacydbg(dev->wl, "PIO initialized\n");
+	err = 0;
+out:
+	return err;
+
+err_destroy2:
+	b43legacy_destroy_pioqueue(pio->queue2);
+	pio->queue2 = NULL;
+err_destroy1:
+	b43legacy_destroy_pioqueue(pio->queue1);
+	pio->queue1 = NULL;
+err_destroy0:
+	b43legacy_destroy_pioqueue(pio->queue0);
+	pio->queue0 = NULL;
+	goto out;
+}
+
+int b43legacy_pio_tx(struct b43legacy_wldev *dev,
+		     struct sk_buff *skb)
+{
+	struct b43legacy_pioqueue *queue = dev->pio.queue1;
+	struct b43legacy_pio_txpacket *packet;
+
+	B43legacy_WARN_ON(queue->tx_suspended);
+	B43legacy_WARN_ON(list_empty(&queue->txfree));
+
+	packet = list_entry(queue->txfree.next, struct b43legacy_pio_txpacket,
+			    list);
+	packet->skb = skb;
+
+	list_move_tail(&packet->list, &queue->txqueue);
+	queue->nr_txfree--;
+	B43legacy_WARN_ON(queue->nr_txfree >= B43legacy_PIO_MAXTXPACKETS);
+
+	tasklet_schedule(&queue->txtask);
+
+	return 0;
+}
+
+void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev,
+				   const struct b43legacy_txstatus *status)
+{
+	struct b43legacy_pioqueue *queue;
+	struct b43legacy_pio_txpacket *packet;
+	struct ieee80211_tx_info *info;
+	int retry_limit;
+
+	queue = parse_cookie(dev, status->cookie, &packet);
+	B43legacy_WARN_ON(!queue);
+
+	if (!packet->skb)
+		return;
+
+	queue->tx_devq_packets--;
+	queue->tx_devq_used -= (packet->skb->len +
+				sizeof(struct b43legacy_txhdr_fw3));
+
+	info = IEEE80211_SKB_CB(packet->skb);
+
+	/* preserve the confiured retry limit before clearing the status
+	 * The xmit function has overwritten the rc's value with the actual
+	 * retry limit done by the hardware */
+	retry_limit = info->status.rates[0].count;
+	ieee80211_tx_info_clear_status(info);
+
+	if (status->acked)
+		info->flags |= IEEE80211_TX_STAT_ACK;
+
+	if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) {
+		/*
+		 * If the short retries (RTS, not data frame) have exceeded
+		 * the limit, the hw will not have tried the selected rate,
+		 * but will have used the fallback rate instead.
+		 * Don't let the rate control count attempts for the selected
+		 * rate in this case, otherwise the statistics will be off.
+		 */
+		info->status.rates[0].count = 0;
+		info->status.rates[1].count = status->frame_count;
+	} else {
+		if (status->frame_count > retry_limit) {
+			info->status.rates[0].count = retry_limit;
+			info->status.rates[1].count = status->frame_count -
+					retry_limit;
+
+		} else {
+			info->status.rates[0].count = status->frame_count;
+			info->status.rates[1].idx = -1;
+		}
+	}
+	ieee80211_tx_status_irqsafe(dev->wl->hw, packet->skb);
+	packet->skb = NULL;
+
+	free_txpacket(packet, 1);
+	/* If there are packets on the txqueue, poke the tasklet
+	 * to transmit them.
+	 */
+	if (!list_empty(&queue->txqueue))
+		tasklet_schedule(&queue->txtask);
+}
+
+static void pio_rx_error(struct b43legacy_pioqueue *queue,
+			 int clear_buffers,
+			 const char *error)
+{
+	int i;
+
+	b43legacyerr(queue->dev->wl, "PIO RX error: %s\n", error);
+	b43legacy_pio_write(queue, B43legacy_PIO_RXCTL,
+			    B43legacy_PIO_RXCTL_READY);
+	if (clear_buffers) {
+		B43legacy_WARN_ON(queue->mmio_base != B43legacy_MMIO_PIO1_BASE);
+		for (i = 0; i < 15; i++) {
+			/* Dummy read. */
+			b43legacy_pio_read(queue, B43legacy_PIO_RXDATA);
+		}
+	}
+}
+
+void b43legacy_pio_rx(struct b43legacy_pioqueue *queue)
+{
+	__le16 preamble[21] = { 0 };
+	struct b43legacy_rxhdr_fw3 *rxhdr;
+	u16 tmp;
+	u16 len;
+	u16 macstat;
+	int i;
+	int preamble_readwords;
+	struct sk_buff *skb;
+
+	tmp = b43legacy_pio_read(queue, B43legacy_PIO_RXCTL);
+	if (!(tmp & B43legacy_PIO_RXCTL_DATAAVAILABLE))
+		return;
+	b43legacy_pio_write(queue, B43legacy_PIO_RXCTL,
+			    B43legacy_PIO_RXCTL_DATAAVAILABLE);
+
+	for (i = 0; i < 10; i++) {
+		tmp = b43legacy_pio_read(queue, B43legacy_PIO_RXCTL);
+		if (tmp & B43legacy_PIO_RXCTL_READY)
+			goto data_ready;
+		udelay(10);
+	}
+	b43legacydbg(queue->dev->wl, "PIO RX timed out\n");
+	return;
+data_ready:
+
+	len = b43legacy_pio_read(queue, B43legacy_PIO_RXDATA);
+	if (unlikely(len > 0x700)) {
+		pio_rx_error(queue, 0, "len > 0x700");
+		return;
+	}
+	if (unlikely(len == 0 && queue->mmio_base !=
+		     B43legacy_MMIO_PIO4_BASE)) {
+		pio_rx_error(queue, 0, "len == 0");
+		return;
+	}
+	preamble[0] = cpu_to_le16(len);
+	if (queue->mmio_base == B43legacy_MMIO_PIO4_BASE)
+		preamble_readwords = 14 / sizeof(u16);
+	else
+		preamble_readwords = 18 / sizeof(u16);
+	for (i = 0; i < preamble_readwords; i++) {
+		tmp = b43legacy_pio_read(queue, B43legacy_PIO_RXDATA);
+		preamble[i + 1] = cpu_to_le16(tmp);
+	}
+	rxhdr = (struct b43legacy_rxhdr_fw3 *)preamble;
+	macstat = le16_to_cpu(rxhdr->mac_status);
+	if (macstat & B43legacy_RX_MAC_FCSERR) {
+		pio_rx_error(queue,
+			     (queue->mmio_base == B43legacy_MMIO_PIO1_BASE),
+			     "Frame FCS error");
+		return;
+	}
+	if (queue->mmio_base == B43legacy_MMIO_PIO4_BASE) {
+		/* We received an xmit status. */
+		struct b43legacy_hwtxstatus *hw;
+
+		hw = (struct b43legacy_hwtxstatus *)(preamble + 1);
+		b43legacy_handle_hwtxstatus(queue->dev, hw);
+
+		return;
+	}
+
+	skb = dev_alloc_skb(len);
+	if (unlikely(!skb)) {
+		pio_rx_error(queue, 1, "OOM");
+		return;
+	}
+	skb_put(skb, len);
+	for (i = 0; i < len - 1; i += 2) {
+		tmp = b43legacy_pio_read(queue, B43legacy_PIO_RXDATA);
+		*((__le16 *)(skb->data + i)) = cpu_to_le16(tmp);
+	}
+	if (len % 2) {
+		tmp = b43legacy_pio_read(queue, B43legacy_PIO_RXDATA);
+		skb->data[len - 1] = (tmp & 0x00FF);
+	}
+	b43legacy_rx(queue->dev, skb, rxhdr);
+}
+
+void b43legacy_pio_tx_suspend(struct b43legacy_pioqueue *queue)
+{
+	b43legacy_power_saving_ctl_bits(queue->dev, -1, 1);
+	b43legacy_pio_write(queue, B43legacy_PIO_TXCTL,
+			    b43legacy_pio_read(queue, B43legacy_PIO_TXCTL)
+			    | B43legacy_PIO_TXCTL_SUSPEND);
+}
+
+void b43legacy_pio_tx_resume(struct b43legacy_pioqueue *queue)
+{
+	b43legacy_pio_write(queue, B43legacy_PIO_TXCTL,
+			    b43legacy_pio_read(queue, B43legacy_PIO_TXCTL)
+			    & ~B43legacy_PIO_TXCTL_SUSPEND);
+	b43legacy_power_saving_ctl_bits(queue->dev, -1, -1);
+	tasklet_schedule(&queue->txtask);
+}
+
+void b43legacy_pio_freeze_txqueues(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_pio *pio;
+
+	B43legacy_WARN_ON(!b43legacy_using_pio(dev));
+	pio = &dev->pio;
+	pio->queue0->tx_frozen = 1;
+	pio->queue1->tx_frozen = 1;
+	pio->queue2->tx_frozen = 1;
+	pio->queue3->tx_frozen = 1;
+}
+
+void b43legacy_pio_thaw_txqueues(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_pio *pio;
+
+	B43legacy_WARN_ON(!b43legacy_using_pio(dev));
+	pio = &dev->pio;
+	pio->queue0->tx_frozen = 0;
+	pio->queue1->tx_frozen = 0;
+	pio->queue2->tx_frozen = 0;
+	pio->queue3->tx_frozen = 0;
+	if (!list_empty(&pio->queue0->txqueue))
+		tasklet_schedule(&pio->queue0->txtask);
+	if (!list_empty(&pio->queue1->txqueue))
+		tasklet_schedule(&pio->queue1->txtask);
+	if (!list_empty(&pio->queue2->txqueue))
+		tasklet_schedule(&pio->queue2->txtask);
+	if (!list_empty(&pio->queue3->txqueue))
+		tasklet_schedule(&pio->queue3->txtask);
+}
diff --git a/drivers/net/wireless/broadcom/b43legacy/pio.h b/drivers/net/wireless/broadcom/b43legacy/pio.h
new file mode 100644
index 0000000..1cd1b9c
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/pio.h
@@ -0,0 +1,159 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43legacy_PIO_H_
+#define B43legacy_PIO_H_
+
+#include "b43legacy.h"
+
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/skbuff.h>
+
+
+#define B43legacy_PIO_TXCTL		0x00
+#define B43legacy_PIO_TXDATA		0x02
+#define B43legacy_PIO_TXQBUFSIZE	0x04
+#define B43legacy_PIO_RXCTL		0x08
+#define B43legacy_PIO_RXDATA		0x0A
+
+#define B43legacy_PIO_TXCTL_WRITELO	(1 << 0)
+#define B43legacy_PIO_TXCTL_WRITEHI	(1 << 1)
+#define B43legacy_PIO_TXCTL_COMPLETE	(1 << 2)
+#define B43legacy_PIO_TXCTL_INIT	(1 << 3)
+#define B43legacy_PIO_TXCTL_SUSPEND	(1 << 7)
+
+#define B43legacy_PIO_RXCTL_DATAAVAILABLE	(1 << 0)
+#define B43legacy_PIO_RXCTL_READY		(1 << 1)
+
+/* PIO constants */
+#define B43legacy_PIO_MAXTXDEVQPACKETS	31
+#define B43legacy_PIO_TXQADJUST		80
+
+/* PIO tuning knobs */
+#define B43legacy_PIO_MAXTXPACKETS	256
+
+
+
+#ifdef CONFIG_B43LEGACY_PIO
+
+
+struct b43legacy_pioqueue;
+struct b43legacy_xmitstatus;
+
+struct b43legacy_pio_txpacket {
+	struct b43legacy_pioqueue *queue;
+	struct sk_buff *skb;
+	struct list_head list;
+};
+
+#define pio_txpacket_getindex(packet) ((int)((packet) - \
+			      (packet)->queue->tx_packets_cache))
+
+struct b43legacy_pioqueue {
+	struct b43legacy_wldev *dev;
+	u16 mmio_base;
+
+	bool tx_suspended;
+	bool tx_frozen;
+	bool need_workarounds; /* Workarounds needed for core.rev < 3 */
+
+	/* Adjusted size of the device internal TX buffer. */
+	u16 tx_devq_size;
+	/* Used octets of the device internal TX buffer. */
+	u16 tx_devq_used;
+	/* Used packet slots in the device internal TX buffer. */
+	u8 tx_devq_packets;
+	/* Packets from the txfree list can
+	 * be taken on incoming TX requests.
+	 */
+	struct list_head txfree;
+	unsigned int nr_txfree;
+	/* Packets on the txqueue are queued,
+	 * but not completely written to the chip, yet.
+	 */
+	struct list_head txqueue;
+	/* Packets on the txrunning queue are completely
+	 * posted to the device. We are waiting for the txstatus.
+	 */
+	struct list_head txrunning;
+	struct tasklet_struct txtask;
+	struct b43legacy_pio_txpacket
+			 tx_packets_cache[B43legacy_PIO_MAXTXPACKETS];
+};
+
+static inline
+u16 b43legacy_pio_read(struct b43legacy_pioqueue *queue,
+		     u16 offset)
+{
+	return b43legacy_read16(queue->dev, queue->mmio_base + offset);
+}
+
+static inline
+void b43legacy_pio_write(struct b43legacy_pioqueue *queue,
+		       u16 offset, u16 value)
+{
+	b43legacy_write16(queue->dev, queue->mmio_base + offset, value);
+	mmiowb();
+}
+
+
+int b43legacy_pio_init(struct b43legacy_wldev *dev);
+void b43legacy_pio_free(struct b43legacy_wldev *dev);
+
+int b43legacy_pio_tx(struct b43legacy_wldev *dev,
+		   struct sk_buff *skb);
+void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev,
+				 const struct b43legacy_txstatus *status);
+void b43legacy_pio_rx(struct b43legacy_pioqueue *queue);
+
+/* Suspend TX queue in hardware. */
+void b43legacy_pio_tx_suspend(struct b43legacy_pioqueue *queue);
+void b43legacy_pio_tx_resume(struct b43legacy_pioqueue *queue);
+/* Suspend (freeze) the TX tasklet (software level). */
+void b43legacy_pio_freeze_txqueues(struct b43legacy_wldev *dev);
+void b43legacy_pio_thaw_txqueues(struct b43legacy_wldev *dev);
+
+#else /* CONFIG_B43LEGACY_PIO */
+
+static inline
+int b43legacy_pio_init(struct b43legacy_wldev *dev)
+{
+	return 0;
+}
+static inline
+void b43legacy_pio_free(struct b43legacy_wldev *dev)
+{
+}
+static inline
+int b43legacy_pio_tx(struct b43legacy_wldev *dev,
+		   struct sk_buff *skb)
+{
+	return 0;
+}
+static inline
+void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev,
+				 const struct b43legacy_txstatus *status)
+{
+}
+static inline
+void b43legacy_pio_rx(struct b43legacy_pioqueue *queue)
+{
+}
+static inline
+void b43legacy_pio_tx_suspend(struct b43legacy_pioqueue *queue)
+{
+}
+static inline
+void b43legacy_pio_tx_resume(struct b43legacy_pioqueue *queue)
+{
+}
+static inline
+void b43legacy_pio_freeze_txqueues(struct b43legacy_wldev *dev)
+{
+}
+static inline
+void b43legacy_pio_thaw_txqueues(struct b43legacy_wldev *dev)
+{
+}
+
+#endif /* CONFIG_B43LEGACY_PIO */
+#endif /* B43legacy_PIO_H_ */
diff --git a/drivers/net/wireless/broadcom/b43legacy/radio.c b/drivers/net/wireless/broadcom/b43legacy/radio.c
new file mode 100644
index 0000000..eab1c93
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/radio.c
@@ -0,0 +1,2143 @@
+/*
+
+  Broadcom B43legacy wireless driver
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+		     Stefano Brivio <stefano.brivio@polimi.it>
+		     Michael Buesch <m@bues.ch>
+		     Danny van Dyk <kugelfang@gentoo.org>
+		     Andreas Jaggi <andreas.jaggi@waterwave.ch>
+  Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
+
+  Some parts of the code in this file are derived from the ipw2200
+  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+
+  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/delay.h>
+
+#include "b43legacy.h"
+#include "main.h"
+#include "phy.h"
+#include "radio.h"
+#include "ilt.h"
+
+
+/* Table for b43legacy_radio_calibrationvalue() */
+static const u16 rcc_table[16] = {
+	0x0002, 0x0003, 0x0001, 0x000F,
+	0x0006, 0x0007, 0x0005, 0x000F,
+	0x000A, 0x000B, 0x0009, 0x000F,
+	0x000E, 0x000F, 0x000D, 0x000F,
+};
+
+/* Reverse the bits of a 4bit value.
+ * Example:  1101 is flipped 1011
+ */
+static u16 flip_4bit(u16 value)
+{
+	u16 flipped = 0x0000;
+
+	B43legacy_BUG_ON(!((value & ~0x000F) == 0x0000));
+
+	flipped |= (value & 0x0001) << 3;
+	flipped |= (value & 0x0002) << 1;
+	flipped |= (value & 0x0004) >> 1;
+	flipped |= (value & 0x0008) >> 3;
+
+	return flipped;
+}
+
+/* Get the freq, as it has to be written to the device. */
+static inline
+u16 channel2freq_bg(u8 channel)
+{
+	/* Frequencies are given as frequencies_bg[index] + 2.4GHz
+	 * Starting with channel 1
+	 */
+	static const u16 frequencies_bg[14] = {
+		12, 17, 22, 27,
+		32, 37, 42, 47,
+		52, 57, 62, 67,
+		72, 84,
+	};
+
+	if (unlikely(channel < 1 || channel > 14)) {
+		printk(KERN_INFO "b43legacy: Channel %d is out of range\n",
+				  channel);
+		dump_stack();
+		return 2412;
+	}
+
+	return frequencies_bg[channel - 1];
+}
+
+void b43legacy_radio_lock(struct b43legacy_wldev *dev)
+{
+	u32 status;
+
+	status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	B43legacy_WARN_ON(status & B43legacy_MACCTL_RADIOLOCK);
+	status |= B43legacy_MACCTL_RADIOLOCK;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status);
+	mmiowb();
+	udelay(10);
+}
+
+void b43legacy_radio_unlock(struct b43legacy_wldev *dev)
+{
+	u32 status;
+
+	b43legacy_read16(dev, B43legacy_MMIO_PHY_VER); /* dummy read */
+	status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+	B43legacy_WARN_ON(!(status & B43legacy_MACCTL_RADIOLOCK));
+	status &= ~B43legacy_MACCTL_RADIOLOCK;
+	b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status);
+	mmiowb();
+}
+
+u16 b43legacy_radio_read16(struct b43legacy_wldev *dev, u16 offset)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+
+	switch (phy->type) {
+	case B43legacy_PHYTYPE_B:
+		if (phy->radio_ver == 0x2053) {
+			if (offset < 0x70)
+				offset += 0x80;
+			else if (offset < 0x80)
+				offset += 0x70;
+		} else if (phy->radio_ver == 0x2050)
+			offset |= 0x80;
+		else
+			B43legacy_WARN_ON(1);
+		break;
+	case B43legacy_PHYTYPE_G:
+		offset |= 0x80;
+		break;
+	default:
+		B43legacy_BUG_ON(1);
+	}
+
+	b43legacy_write16(dev, B43legacy_MMIO_RADIO_CONTROL, offset);
+	return b43legacy_read16(dev, B43legacy_MMIO_RADIO_DATA_LOW);
+}
+
+void b43legacy_radio_write16(struct b43legacy_wldev *dev, u16 offset, u16 val)
+{
+	b43legacy_write16(dev, B43legacy_MMIO_RADIO_CONTROL, offset);
+	mmiowb();
+	b43legacy_write16(dev, B43legacy_MMIO_RADIO_DATA_LOW, val);
+}
+
+static void b43legacy_set_all_gains(struct b43legacy_wldev *dev,
+				  s16 first, s16 second, s16 third)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 i;
+	u16 start = 0x08;
+	u16 end = 0x18;
+	u16 offset = 0x0400;
+	u16 tmp;
+
+	if (phy->rev <= 1) {
+		offset = 0x5000;
+		start = 0x10;
+		end = 0x20;
+	}
+
+	for (i = 0; i < 4; i++)
+		b43legacy_ilt_write(dev, offset + i, first);
+
+	for (i = start; i < end; i++)
+		b43legacy_ilt_write(dev, offset + i, second);
+
+	if (third != -1) {
+		tmp = ((u16)third << 14) | ((u16)third << 6);
+		b43legacy_phy_write(dev, 0x04A0,
+				    (b43legacy_phy_read(dev, 0x04A0) & 0xBFBF)
+				    | tmp);
+		b43legacy_phy_write(dev, 0x04A1,
+				    (b43legacy_phy_read(dev, 0x04A1) & 0xBFBF)
+				    | tmp);
+		b43legacy_phy_write(dev, 0x04A2,
+				    (b43legacy_phy_read(dev, 0x04A2) & 0xBFBF)
+				    | tmp);
+	}
+	b43legacy_dummy_transmission(dev);
+}
+
+static void b43legacy_set_original_gains(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 i;
+	u16 tmp;
+	u16 offset = 0x0400;
+	u16 start = 0x0008;
+	u16 end = 0x0018;
+
+	if (phy->rev <= 1) {
+		offset = 0x5000;
+		start = 0x0010;
+		end = 0x0020;
+	}
+
+	for (i = 0; i < 4; i++) {
+		tmp = (i & 0xFFFC);
+		tmp |= (i & 0x0001) << 1;
+		tmp |= (i & 0x0002) >> 1;
+
+		b43legacy_ilt_write(dev, offset + i, tmp);
+	}
+
+	for (i = start; i < end; i++)
+		b43legacy_ilt_write(dev, offset + i, i - start);
+
+	b43legacy_phy_write(dev, 0x04A0,
+			    (b43legacy_phy_read(dev, 0x04A0) & 0xBFBF)
+			    | 0x4040);
+	b43legacy_phy_write(dev, 0x04A1,
+			    (b43legacy_phy_read(dev, 0x04A1) & 0xBFBF)
+			    | 0x4040);
+	b43legacy_phy_write(dev, 0x04A2,
+			    (b43legacy_phy_read(dev, 0x04A2) & 0xBFBF)
+			    | 0x4000);
+	b43legacy_dummy_transmission(dev);
+}
+
+/* Synthetic PU workaround */
+static void b43legacy_synth_pu_workaround(struct b43legacy_wldev *dev,
+					  u8 channel)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+
+	might_sleep();
+
+	if (phy->radio_ver != 0x2050 || phy->radio_rev >= 6)
+		/* We do not need the workaround. */
+		return;
+
+	if (channel <= 10)
+		b43legacy_write16(dev, B43legacy_MMIO_CHANNEL,
+				  channel2freq_bg(channel + 4));
+	else
+		b43legacy_write16(dev, B43legacy_MMIO_CHANNEL,
+				  channel2freq_bg(channel));
+	msleep(1);
+	b43legacy_write16(dev, B43legacy_MMIO_CHANNEL,
+			  channel2freq_bg(channel));
+}
+
+u8 b43legacy_radio_aci_detect(struct b43legacy_wldev *dev, u8 channel)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u8 ret = 0;
+	u16 saved;
+	u16 rssi;
+	u16 temp;
+	int i;
+	int j = 0;
+
+	saved = b43legacy_phy_read(dev, 0x0403);
+	b43legacy_radio_selectchannel(dev, channel, 0);
+	b43legacy_phy_write(dev, 0x0403, (saved & 0xFFF8) | 5);
+	if (phy->aci_hw_rssi)
+		rssi = b43legacy_phy_read(dev, 0x048A) & 0x3F;
+	else
+		rssi = saved & 0x3F;
+	/* clamp temp to signed 5bit */
+	if (rssi > 32)
+		rssi -= 64;
+	for (i = 0; i < 100; i++) {
+		temp = (b43legacy_phy_read(dev, 0x047F) >> 8) & 0x3F;
+		if (temp > 32)
+			temp -= 64;
+		if (temp < rssi)
+			j++;
+		if (j >= 20)
+			ret = 1;
+	}
+	b43legacy_phy_write(dev, 0x0403, saved);
+
+	return ret;
+}
+
+u8 b43legacy_radio_aci_scan(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u8 ret[13] = { 0 };
+	unsigned int channel = phy->channel;
+	unsigned int i;
+	unsigned int j;
+	unsigned int start;
+	unsigned int end;
+
+	if (!((phy->type == B43legacy_PHYTYPE_G) && (phy->rev > 0)))
+		return 0;
+
+	b43legacy_phy_lock(dev);
+	b43legacy_radio_lock(dev);
+	b43legacy_phy_write(dev, 0x0802,
+			    b43legacy_phy_read(dev, 0x0802) & 0xFFFC);
+	b43legacy_phy_write(dev, B43legacy_PHY_G_CRS,
+			    b43legacy_phy_read(dev, B43legacy_PHY_G_CRS)
+			    & 0x7FFF);
+	b43legacy_set_all_gains(dev, 3, 8, 1);
+
+	start = (channel - 5 > 0) ? channel - 5 : 1;
+	end = (channel + 5 < 14) ? channel + 5 : 13;
+
+	for (i = start; i <= end; i++) {
+		if (abs(channel - i) > 2)
+			ret[i-1] = b43legacy_radio_aci_detect(dev, i);
+	}
+	b43legacy_radio_selectchannel(dev, channel, 0);
+	b43legacy_phy_write(dev, 0x0802,
+			    (b43legacy_phy_read(dev, 0x0802) & 0xFFFC)
+			    | 0x0003);
+	b43legacy_phy_write(dev, 0x0403,
+			    b43legacy_phy_read(dev, 0x0403) & 0xFFF8);
+	b43legacy_phy_write(dev, B43legacy_PHY_G_CRS,
+			    b43legacy_phy_read(dev, B43legacy_PHY_G_CRS)
+			    | 0x8000);
+	b43legacy_set_original_gains(dev);
+	for (i = 0; i < 13; i++) {
+		if (!ret[i])
+			continue;
+		end = (i + 5 < 13) ? i + 5 : 13;
+		for (j = i; j < end; j++)
+			ret[j] = 1;
+	}
+	b43legacy_radio_unlock(dev);
+	b43legacy_phy_unlock(dev);
+
+	return ret[channel - 1];
+}
+
+/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+void b43legacy_nrssi_hw_write(struct b43legacy_wldev *dev, u16 offset, s16 val)
+{
+	b43legacy_phy_write(dev, B43legacy_PHY_NRSSILT_CTRL, offset);
+	mmiowb();
+	b43legacy_phy_write(dev, B43legacy_PHY_NRSSILT_DATA, (u16)val);
+}
+
+/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+s16 b43legacy_nrssi_hw_read(struct b43legacy_wldev *dev, u16 offset)
+{
+	u16 val;
+
+	b43legacy_phy_write(dev, B43legacy_PHY_NRSSILT_CTRL, offset);
+	val = b43legacy_phy_read(dev, B43legacy_PHY_NRSSILT_DATA);
+
+	return (s16)val;
+}
+
+/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+void b43legacy_nrssi_hw_update(struct b43legacy_wldev *dev, u16 val)
+{
+	u16 i;
+	s16 tmp;
+
+	for (i = 0; i < 64; i++) {
+		tmp = b43legacy_nrssi_hw_read(dev, i);
+		tmp -= val;
+		tmp = clamp_val(tmp, -32, 31);
+		b43legacy_nrssi_hw_write(dev, i, tmp);
+	}
+}
+
+/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
+void b43legacy_nrssi_mem_update(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	s16 i;
+	s16 delta;
+	s32 tmp;
+
+	delta = 0x1F - phy->nrssi[0];
+	for (i = 0; i < 64; i++) {
+		tmp = (i - delta) * phy->nrssislope;
+		tmp /= 0x10000;
+		tmp += 0x3A;
+		tmp = clamp_val(tmp, 0, 0x3F);
+		phy->nrssi_lt[i] = tmp;
+	}
+}
+
+static void b43legacy_calc_nrssi_offset(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 backup[20] = { 0 };
+	s16 v47F;
+	u16 i;
+	u16 saved = 0xFFFF;
+
+	backup[0] = b43legacy_phy_read(dev, 0x0001);
+	backup[1] = b43legacy_phy_read(dev, 0x0811);
+	backup[2] = b43legacy_phy_read(dev, 0x0812);
+	backup[3] = b43legacy_phy_read(dev, 0x0814);
+	backup[4] = b43legacy_phy_read(dev, 0x0815);
+	backup[5] = b43legacy_phy_read(dev, 0x005A);
+	backup[6] = b43legacy_phy_read(dev, 0x0059);
+	backup[7] = b43legacy_phy_read(dev, 0x0058);
+	backup[8] = b43legacy_phy_read(dev, 0x000A);
+	backup[9] = b43legacy_phy_read(dev, 0x0003);
+	backup[10] = b43legacy_radio_read16(dev, 0x007A);
+	backup[11] = b43legacy_radio_read16(dev, 0x0043);
+
+	b43legacy_phy_write(dev, 0x0429,
+			    b43legacy_phy_read(dev, 0x0429) & 0x7FFF);
+	b43legacy_phy_write(dev, 0x0001,
+			    (b43legacy_phy_read(dev, 0x0001) & 0x3FFF)
+			    | 0x4000);
+	b43legacy_phy_write(dev, 0x0811,
+			    b43legacy_phy_read(dev, 0x0811) | 0x000C);
+	b43legacy_phy_write(dev, 0x0812,
+			    (b43legacy_phy_read(dev, 0x0812) & 0xFFF3)
+			    | 0x0004);
+	b43legacy_phy_write(dev, 0x0802,
+			    b43legacy_phy_read(dev, 0x0802) & ~(0x1 | 0x2));
+	if (phy->rev >= 6) {
+		backup[12] = b43legacy_phy_read(dev, 0x002E);
+		backup[13] = b43legacy_phy_read(dev, 0x002F);
+		backup[14] = b43legacy_phy_read(dev, 0x080F);
+		backup[15] = b43legacy_phy_read(dev, 0x0810);
+		backup[16] = b43legacy_phy_read(dev, 0x0801);
+		backup[17] = b43legacy_phy_read(dev, 0x0060);
+		backup[18] = b43legacy_phy_read(dev, 0x0014);
+		backup[19] = b43legacy_phy_read(dev, 0x0478);
+
+		b43legacy_phy_write(dev, 0x002E, 0);
+		b43legacy_phy_write(dev, 0x002F, 0);
+		b43legacy_phy_write(dev, 0x080F, 0);
+		b43legacy_phy_write(dev, 0x0810, 0);
+		b43legacy_phy_write(dev, 0x0478,
+				    b43legacy_phy_read(dev, 0x0478) | 0x0100);
+		b43legacy_phy_write(dev, 0x0801,
+				    b43legacy_phy_read(dev, 0x0801) | 0x0040);
+		b43legacy_phy_write(dev, 0x0060,
+				    b43legacy_phy_read(dev, 0x0060) | 0x0040);
+		b43legacy_phy_write(dev, 0x0014,
+				    b43legacy_phy_read(dev, 0x0014) | 0x0200);
+	}
+	b43legacy_radio_write16(dev, 0x007A,
+				b43legacy_radio_read16(dev, 0x007A) | 0x0070);
+	b43legacy_radio_write16(dev, 0x007A,
+				b43legacy_radio_read16(dev, 0x007A) | 0x0080);
+	udelay(30);
+
+	v47F = (s16)((b43legacy_phy_read(dev, 0x047F) >> 8) & 0x003F);
+	if (v47F >= 0x20)
+		v47F -= 0x40;
+	if (v47F == 31) {
+		for (i = 7; i >= 4; i--) {
+			b43legacy_radio_write16(dev, 0x007B, i);
+			udelay(20);
+			v47F = (s16)((b43legacy_phy_read(dev, 0x047F) >> 8)
+							 & 0x003F);
+			if (v47F >= 0x20)
+				v47F -= 0x40;
+			if (v47F < 31 && saved == 0xFFFF)
+				saved = i;
+		}
+		if (saved == 0xFFFF)
+			saved = 4;
+	} else {
+		b43legacy_radio_write16(dev, 0x007A,
+					b43legacy_radio_read16(dev, 0x007A)
+					& 0x007F);
+		b43legacy_phy_write(dev, 0x0814,
+				    b43legacy_phy_read(dev, 0x0814) | 0x0001);
+		b43legacy_phy_write(dev, 0x0815,
+				    b43legacy_phy_read(dev, 0x0815) & 0xFFFE);
+		b43legacy_phy_write(dev, 0x0811,
+				    b43legacy_phy_read(dev, 0x0811) | 0x000C);
+		b43legacy_phy_write(dev, 0x0812,
+				    b43legacy_phy_read(dev, 0x0812) | 0x000C);
+		b43legacy_phy_write(dev, 0x0811,
+				    b43legacy_phy_read(dev, 0x0811) | 0x0030);
+		b43legacy_phy_write(dev, 0x0812,
+				    b43legacy_phy_read(dev, 0x0812) | 0x0030);
+		b43legacy_phy_write(dev, 0x005A, 0x0480);
+		b43legacy_phy_write(dev, 0x0059, 0x0810);
+		b43legacy_phy_write(dev, 0x0058, 0x000D);
+		if (phy->analog == 0)
+			b43legacy_phy_write(dev, 0x0003, 0x0122);
+		else
+			b43legacy_phy_write(dev, 0x000A,
+					    b43legacy_phy_read(dev, 0x000A)
+					    | 0x2000);
+		b43legacy_phy_write(dev, 0x0814,
+				    b43legacy_phy_read(dev, 0x0814) | 0x0004);
+		b43legacy_phy_write(dev, 0x0815,
+				    b43legacy_phy_read(dev, 0x0815) & 0xFFFB);
+		b43legacy_phy_write(dev, 0x0003,
+				    (b43legacy_phy_read(dev, 0x0003) & 0xFF9F)
+				    | 0x0040);
+		b43legacy_radio_write16(dev, 0x007A,
+					b43legacy_radio_read16(dev, 0x007A)
+					| 0x000F);
+		b43legacy_set_all_gains(dev, 3, 0, 1);
+		b43legacy_radio_write16(dev, 0x0043,
+					(b43legacy_radio_read16(dev, 0x0043)
+					& 0x00F0) | 0x000F);
+		udelay(30);
+		v47F = (s16)((b43legacy_phy_read(dev, 0x047F) >> 8) & 0x003F);
+		if (v47F >= 0x20)
+			v47F -= 0x40;
+		if (v47F == -32) {
+			for (i = 0; i < 4; i++) {
+				b43legacy_radio_write16(dev, 0x007B, i);
+				udelay(20);
+				v47F = (s16)((b43legacy_phy_read(dev, 0x047F) >>
+								 8) & 0x003F);
+				if (v47F >= 0x20)
+					v47F -= 0x40;
+				if (v47F > -31 && saved == 0xFFFF)
+					saved = i;
+			}
+			if (saved == 0xFFFF)
+				saved = 3;
+		} else
+			saved = 0;
+	}
+	b43legacy_radio_write16(dev, 0x007B, saved);
+
+	if (phy->rev >= 6) {
+		b43legacy_phy_write(dev, 0x002E, backup[12]);
+		b43legacy_phy_write(dev, 0x002F, backup[13]);
+		b43legacy_phy_write(dev, 0x080F, backup[14]);
+		b43legacy_phy_write(dev, 0x0810, backup[15]);
+	}
+	b43legacy_phy_write(dev, 0x0814, backup[3]);
+	b43legacy_phy_write(dev, 0x0815, backup[4]);
+	b43legacy_phy_write(dev, 0x005A, backup[5]);
+	b43legacy_phy_write(dev, 0x0059, backup[6]);
+	b43legacy_phy_write(dev, 0x0058, backup[7]);
+	b43legacy_phy_write(dev, 0x000A, backup[8]);
+	b43legacy_phy_write(dev, 0x0003, backup[9]);
+	b43legacy_radio_write16(dev, 0x0043, backup[11]);
+	b43legacy_radio_write16(dev, 0x007A, backup[10]);
+	b43legacy_phy_write(dev, 0x0802,
+			    b43legacy_phy_read(dev, 0x0802) | 0x1 | 0x2);
+	b43legacy_phy_write(dev, 0x0429,
+			    b43legacy_phy_read(dev, 0x0429) | 0x8000);
+	b43legacy_set_original_gains(dev);
+	if (phy->rev >= 6) {
+		b43legacy_phy_write(dev, 0x0801, backup[16]);
+		b43legacy_phy_write(dev, 0x0060, backup[17]);
+		b43legacy_phy_write(dev, 0x0014, backup[18]);
+		b43legacy_phy_write(dev, 0x0478, backup[19]);
+	}
+	b43legacy_phy_write(dev, 0x0001, backup[0]);
+	b43legacy_phy_write(dev, 0x0812, backup[2]);
+	b43legacy_phy_write(dev, 0x0811, backup[1]);
+}
+
+void b43legacy_calc_nrssi_slope(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 backup[18] = { 0 };
+	u16 tmp;
+	s16 nrssi0;
+	s16 nrssi1;
+
+	switch (phy->type) {
+	case B43legacy_PHYTYPE_B:
+		backup[0] = b43legacy_radio_read16(dev, 0x007A);
+		backup[1] = b43legacy_radio_read16(dev, 0x0052);
+		backup[2] = b43legacy_radio_read16(dev, 0x0043);
+		backup[3] = b43legacy_phy_read(dev, 0x0030);
+		backup[4] = b43legacy_phy_read(dev, 0x0026);
+		backup[5] = b43legacy_phy_read(dev, 0x0015);
+		backup[6] = b43legacy_phy_read(dev, 0x002A);
+		backup[7] = b43legacy_phy_read(dev, 0x0020);
+		backup[8] = b43legacy_phy_read(dev, 0x005A);
+		backup[9] = b43legacy_phy_read(dev, 0x0059);
+		backup[10] = b43legacy_phy_read(dev, 0x0058);
+		backup[11] = b43legacy_read16(dev, 0x03E2);
+		backup[12] = b43legacy_read16(dev, 0x03E6);
+		backup[13] = b43legacy_read16(dev, B43legacy_MMIO_CHANNEL_EXT);
+
+		tmp  = b43legacy_radio_read16(dev, 0x007A);
+		tmp &= (phy->rev >= 5) ? 0x007F : 0x000F;
+		b43legacy_radio_write16(dev, 0x007A, tmp);
+		b43legacy_phy_write(dev, 0x0030, 0x00FF);
+		b43legacy_write16(dev, 0x03EC, 0x7F7F);
+		b43legacy_phy_write(dev, 0x0026, 0x0000);
+		b43legacy_phy_write(dev, 0x0015,
+				    b43legacy_phy_read(dev, 0x0015) | 0x0020);
+		b43legacy_phy_write(dev, 0x002A, 0x08A3);
+		b43legacy_radio_write16(dev, 0x007A,
+					b43legacy_radio_read16(dev, 0x007A)
+					| 0x0080);
+
+		nrssi0 = (s16)b43legacy_phy_read(dev, 0x0027);
+		b43legacy_radio_write16(dev, 0x007A,
+					b43legacy_radio_read16(dev, 0x007A)
+					& 0x007F);
+		if (phy->analog >= 2)
+			b43legacy_write16(dev, 0x03E6, 0x0040);
+		else if (phy->analog == 0)
+			b43legacy_write16(dev, 0x03E6, 0x0122);
+		else
+			b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT,
+					  b43legacy_read16(dev,
+					  B43legacy_MMIO_CHANNEL_EXT) & 0x2000);
+		b43legacy_phy_write(dev, 0x0020, 0x3F3F);
+		b43legacy_phy_write(dev, 0x0015, 0xF330);
+		b43legacy_radio_write16(dev, 0x005A, 0x0060);
+		b43legacy_radio_write16(dev, 0x0043,
+					b43legacy_radio_read16(dev, 0x0043)
+					& 0x00F0);
+		b43legacy_phy_write(dev, 0x005A, 0x0480);
+		b43legacy_phy_write(dev, 0x0059, 0x0810);
+		b43legacy_phy_write(dev, 0x0058, 0x000D);
+		udelay(20);
+
+		nrssi1 = (s16)b43legacy_phy_read(dev, 0x0027);
+		b43legacy_phy_write(dev, 0x0030, backup[3]);
+		b43legacy_radio_write16(dev, 0x007A, backup[0]);
+		b43legacy_write16(dev, 0x03E2, backup[11]);
+		b43legacy_phy_write(dev, 0x0026, backup[4]);
+		b43legacy_phy_write(dev, 0x0015, backup[5]);
+		b43legacy_phy_write(dev, 0x002A, backup[6]);
+		b43legacy_synth_pu_workaround(dev, phy->channel);
+		if (phy->analog != 0)
+			b43legacy_write16(dev, 0x03F4, backup[13]);
+
+		b43legacy_phy_write(dev, 0x0020, backup[7]);
+		b43legacy_phy_write(dev, 0x005A, backup[8]);
+		b43legacy_phy_write(dev, 0x0059, backup[9]);
+		b43legacy_phy_write(dev, 0x0058, backup[10]);
+		b43legacy_radio_write16(dev, 0x0052, backup[1]);
+		b43legacy_radio_write16(dev, 0x0043, backup[2]);
+
+		if (nrssi0 == nrssi1)
+			phy->nrssislope = 0x00010000;
+		else
+			phy->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
+
+		if (nrssi0 <= -4) {
+			phy->nrssi[0] = nrssi0;
+			phy->nrssi[1] = nrssi1;
+		}
+		break;
+	case B43legacy_PHYTYPE_G:
+		if (phy->radio_rev >= 9)
+			return;
+		if (phy->radio_rev == 8)
+			b43legacy_calc_nrssi_offset(dev);
+
+		b43legacy_phy_write(dev, B43legacy_PHY_G_CRS,
+				    b43legacy_phy_read(dev, B43legacy_PHY_G_CRS)
+				    & 0x7FFF);
+		b43legacy_phy_write(dev, 0x0802,
+				    b43legacy_phy_read(dev, 0x0802) & 0xFFFC);
+		backup[7] = b43legacy_read16(dev, 0x03E2);
+		b43legacy_write16(dev, 0x03E2,
+				  b43legacy_read16(dev, 0x03E2) | 0x8000);
+		backup[0] = b43legacy_radio_read16(dev, 0x007A);
+		backup[1] = b43legacy_radio_read16(dev, 0x0052);
+		backup[2] = b43legacy_radio_read16(dev, 0x0043);
+		backup[3] = b43legacy_phy_read(dev, 0x0015);
+		backup[4] = b43legacy_phy_read(dev, 0x005A);
+		backup[5] = b43legacy_phy_read(dev, 0x0059);
+		backup[6] = b43legacy_phy_read(dev, 0x0058);
+		backup[8] = b43legacy_read16(dev, 0x03E6);
+		backup[9] = b43legacy_read16(dev, B43legacy_MMIO_CHANNEL_EXT);
+		if (phy->rev >= 3) {
+			backup[10] = b43legacy_phy_read(dev, 0x002E);
+			backup[11] = b43legacy_phy_read(dev, 0x002F);
+			backup[12] = b43legacy_phy_read(dev, 0x080F);
+			backup[13] = b43legacy_phy_read(dev,
+						B43legacy_PHY_G_LO_CONTROL);
+			backup[14] = b43legacy_phy_read(dev, 0x0801);
+			backup[15] = b43legacy_phy_read(dev, 0x0060);
+			backup[16] = b43legacy_phy_read(dev, 0x0014);
+			backup[17] = b43legacy_phy_read(dev, 0x0478);
+			b43legacy_phy_write(dev, 0x002E, 0);
+			b43legacy_phy_write(dev, B43legacy_PHY_G_LO_CONTROL, 0);
+			switch (phy->rev) {
+			case 4: case 6: case 7:
+				b43legacy_phy_write(dev, 0x0478,
+						    b43legacy_phy_read(dev,
+						    0x0478) | 0x0100);
+				b43legacy_phy_write(dev, 0x0801,
+						    b43legacy_phy_read(dev,
+						    0x0801) | 0x0040);
+				break;
+			case 3: case 5:
+				b43legacy_phy_write(dev, 0x0801,
+						    b43legacy_phy_read(dev,
+						    0x0801) & 0xFFBF);
+				break;
+			}
+			b43legacy_phy_write(dev, 0x0060,
+					    b43legacy_phy_read(dev, 0x0060)
+					    | 0x0040);
+			b43legacy_phy_write(dev, 0x0014,
+					    b43legacy_phy_read(dev, 0x0014)
+					    | 0x0200);
+		}
+		b43legacy_radio_write16(dev, 0x007A,
+					b43legacy_radio_read16(dev, 0x007A)
+					| 0x0070);
+		b43legacy_set_all_gains(dev, 0, 8, 0);
+		b43legacy_radio_write16(dev, 0x007A,
+					b43legacy_radio_read16(dev, 0x007A)
+					& 0x00F7);
+		if (phy->rev >= 2) {
+			b43legacy_phy_write(dev, 0x0811,
+					    (b43legacy_phy_read(dev, 0x0811)
+					    & 0xFFCF) | 0x0030);
+			b43legacy_phy_write(dev, 0x0812,
+					    (b43legacy_phy_read(dev, 0x0812)
+					    & 0xFFCF) | 0x0010);
+		}
+		b43legacy_radio_write16(dev, 0x007A,
+					b43legacy_radio_read16(dev, 0x007A)
+					| 0x0080);
+		udelay(20);
+
+		nrssi0 = (s16)((b43legacy_phy_read(dev, 0x047F) >> 8) & 0x003F);
+		if (nrssi0 >= 0x0020)
+			nrssi0 -= 0x0040;
+
+		b43legacy_radio_write16(dev, 0x007A,
+					b43legacy_radio_read16(dev, 0x007A)
+					& 0x007F);
+		if (phy->analog >= 2)
+			b43legacy_phy_write(dev, 0x0003,
+					    (b43legacy_phy_read(dev, 0x0003)
+					    & 0xFF9F) | 0x0040);
+
+		b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT,
+				  b43legacy_read16(dev,
+				  B43legacy_MMIO_CHANNEL_EXT) | 0x2000);
+		b43legacy_radio_write16(dev, 0x007A,
+					b43legacy_radio_read16(dev, 0x007A)
+					| 0x000F);
+		b43legacy_phy_write(dev, 0x0015, 0xF330);
+		if (phy->rev >= 2) {
+			b43legacy_phy_write(dev, 0x0812,
+					    (b43legacy_phy_read(dev, 0x0812)
+					    & 0xFFCF) | 0x0020);
+			b43legacy_phy_write(dev, 0x0811,
+					    (b43legacy_phy_read(dev, 0x0811)
+					    & 0xFFCF) | 0x0020);
+		}
+
+		b43legacy_set_all_gains(dev, 3, 0, 1);
+		if (phy->radio_rev == 8)
+			b43legacy_radio_write16(dev, 0x0043, 0x001F);
+		else {
+			tmp = b43legacy_radio_read16(dev, 0x0052) & 0xFF0F;
+			b43legacy_radio_write16(dev, 0x0052, tmp | 0x0060);
+			tmp = b43legacy_radio_read16(dev, 0x0043) & 0xFFF0;
+			b43legacy_radio_write16(dev, 0x0043, tmp | 0x0009);
+		}
+		b43legacy_phy_write(dev, 0x005A, 0x0480);
+		b43legacy_phy_write(dev, 0x0059, 0x0810);
+		b43legacy_phy_write(dev, 0x0058, 0x000D);
+		udelay(20);
+		nrssi1 = (s16)((b43legacy_phy_read(dev, 0x047F) >> 8) & 0x003F);
+		if (nrssi1 >= 0x0020)
+			nrssi1 -= 0x0040;
+		if (nrssi0 == nrssi1)
+			phy->nrssislope = 0x00010000;
+		else
+			phy->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
+		if (nrssi0 >= -4) {
+			phy->nrssi[0] = nrssi1;
+			phy->nrssi[1] = nrssi0;
+		}
+		if (phy->rev >= 3) {
+			b43legacy_phy_write(dev, 0x002E, backup[10]);
+			b43legacy_phy_write(dev, 0x002F, backup[11]);
+			b43legacy_phy_write(dev, 0x080F, backup[12]);
+			b43legacy_phy_write(dev, B43legacy_PHY_G_LO_CONTROL,
+					    backup[13]);
+		}
+		if (phy->rev >= 2) {
+			b43legacy_phy_write(dev, 0x0812,
+					    b43legacy_phy_read(dev, 0x0812)
+					    & 0xFFCF);
+			b43legacy_phy_write(dev, 0x0811,
+					    b43legacy_phy_read(dev, 0x0811)
+					    & 0xFFCF);
+		}
+
+		b43legacy_radio_write16(dev, 0x007A, backup[0]);
+		b43legacy_radio_write16(dev, 0x0052, backup[1]);
+		b43legacy_radio_write16(dev, 0x0043, backup[2]);
+		b43legacy_write16(dev, 0x03E2, backup[7]);
+		b43legacy_write16(dev, 0x03E6, backup[8]);
+		b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, backup[9]);
+		b43legacy_phy_write(dev, 0x0015, backup[3]);
+		b43legacy_phy_write(dev, 0x005A, backup[4]);
+		b43legacy_phy_write(dev, 0x0059, backup[5]);
+		b43legacy_phy_write(dev, 0x0058, backup[6]);
+		b43legacy_synth_pu_workaround(dev, phy->channel);
+		b43legacy_phy_write(dev, 0x0802,
+				    b43legacy_phy_read(dev, 0x0802) | 0x0003);
+		b43legacy_set_original_gains(dev);
+		b43legacy_phy_write(dev, B43legacy_PHY_G_CRS,
+				    b43legacy_phy_read(dev, B43legacy_PHY_G_CRS)
+				    | 0x8000);
+		if (phy->rev >= 3) {
+			b43legacy_phy_write(dev, 0x0801, backup[14]);
+			b43legacy_phy_write(dev, 0x0060, backup[15]);
+			b43legacy_phy_write(dev, 0x0014, backup[16]);
+			b43legacy_phy_write(dev, 0x0478, backup[17]);
+		}
+		b43legacy_nrssi_mem_update(dev);
+		b43legacy_calc_nrssi_threshold(dev);
+		break;
+	default:
+		B43legacy_BUG_ON(1);
+	}
+}
+
+void b43legacy_calc_nrssi_threshold(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	s32 threshold;
+	s32 a;
+	s32 b;
+	s16 tmp16;
+	u16 tmp_u16;
+
+	switch (phy->type) {
+	case B43legacy_PHYTYPE_B: {
+		if (phy->radio_ver != 0x2050)
+			return;
+		if (!(dev->dev->bus->sprom.boardflags_lo &
+		    B43legacy_BFL_RSSI))
+			return;
+
+		if (phy->radio_rev >= 6) {
+			threshold = (phy->nrssi[1] - phy->nrssi[0]) * 32;
+			threshold += 20 * (phy->nrssi[0] + 1);
+			threshold /= 40;
+		} else
+			threshold = phy->nrssi[1] - 5;
+
+		threshold = clamp_val(threshold, 0, 0x3E);
+		b43legacy_phy_read(dev, 0x0020); /* dummy read */
+		b43legacy_phy_write(dev, 0x0020, (((u16)threshold) << 8)
+				    | 0x001C);
+
+		if (phy->radio_rev >= 6) {
+			b43legacy_phy_write(dev, 0x0087, 0x0E0D);
+			b43legacy_phy_write(dev, 0x0086, 0x0C0B);
+			b43legacy_phy_write(dev, 0x0085, 0x0A09);
+			b43legacy_phy_write(dev, 0x0084, 0x0808);
+			b43legacy_phy_write(dev, 0x0083, 0x0808);
+			b43legacy_phy_write(dev, 0x0082, 0x0604);
+			b43legacy_phy_write(dev, 0x0081, 0x0302);
+			b43legacy_phy_write(dev, 0x0080, 0x0100);
+		}
+		break;
+	}
+	case B43legacy_PHYTYPE_G:
+		if (!phy->gmode ||
+		    !(dev->dev->bus->sprom.boardflags_lo &
+		    B43legacy_BFL_RSSI)) {
+			tmp16 = b43legacy_nrssi_hw_read(dev, 0x20);
+			if (tmp16 >= 0x20)
+				tmp16 -= 0x40;
+			if (tmp16 < 3)
+				b43legacy_phy_write(dev, 0x048A,
+						    (b43legacy_phy_read(dev,
+						    0x048A) & 0xF000) | 0x09EB);
+			else
+				b43legacy_phy_write(dev, 0x048A,
+						    (b43legacy_phy_read(dev,
+						    0x048A) & 0xF000) | 0x0AED);
+		} else {
+			if (phy->interfmode ==
+			    B43legacy_RADIO_INTERFMODE_NONWLAN) {
+				a = 0xE;
+				b = 0xA;
+			} else if (!phy->aci_wlan_automatic &&
+				    phy->aci_enable) {
+				a = 0x13;
+				b = 0x12;
+			} else {
+				a = 0xE;
+				b = 0x11;
+			}
+
+			a = a * (phy->nrssi[1] - phy->nrssi[0]);
+			a += (phy->nrssi[0] << 6);
+			if (a < 32)
+				a += 31;
+			else
+				a += 32;
+			a = a >> 6;
+			a = clamp_val(a, -31, 31);
+
+			b = b * (phy->nrssi[1] - phy->nrssi[0]);
+			b += (phy->nrssi[0] << 6);
+			if (b < 32)
+				b += 31;
+			else
+				b += 32;
+			b = b >> 6;
+			b = clamp_val(b, -31, 31);
+
+			tmp_u16 = b43legacy_phy_read(dev, 0x048A) & 0xF000;
+			tmp_u16 |= ((u32)b & 0x0000003F);
+			tmp_u16 |= (((u32)a & 0x0000003F) << 6);
+			b43legacy_phy_write(dev, 0x048A, tmp_u16);
+		}
+		break;
+	default:
+		B43legacy_BUG_ON(1);
+	}
+}
+
+/* Stack implementation to save/restore values from the
+ * interference mitigation code.
+ * It is save to restore values in random order.
+ */
+static void _stack_save(u32 *_stackptr, size_t *stackidx,
+			u8 id, u16 offset, u16 value)
+{
+	u32 *stackptr = &(_stackptr[*stackidx]);
+
+	B43legacy_WARN_ON(!((offset & 0xE000) == 0x0000));
+	B43legacy_WARN_ON(!((id & 0xF8) == 0x00));
+	*stackptr = offset;
+	*stackptr |= ((u32)id) << 13;
+	*stackptr |= ((u32)value) << 16;
+	(*stackidx)++;
+	B43legacy_WARN_ON(!(*stackidx < B43legacy_INTERFSTACK_SIZE));
+}
+
+static u16 _stack_restore(u32 *stackptr,
+			  u8 id, u16 offset)
+{
+	size_t i;
+
+	B43legacy_WARN_ON(!((offset & 0xE000) == 0x0000));
+	B43legacy_WARN_ON(!((id & 0xF8) == 0x00));
+	for (i = 0; i < B43legacy_INTERFSTACK_SIZE; i++, stackptr++) {
+		if ((*stackptr & 0x00001FFF) != offset)
+			continue;
+		if (((*stackptr & 0x00007000) >> 13) != id)
+			continue;
+		return ((*stackptr & 0xFFFF0000) >> 16);
+	}
+	B43legacy_BUG_ON(1);
+
+	return 0;
+}
+
+#define phy_stacksave(offset)					\
+	do {							\
+		_stack_save(stack, &stackidx, 0x1, (offset),	\
+			    b43legacy_phy_read(dev, (offset)));	\
+	} while (0)
+#define phy_stackrestore(offset)				\
+	do {							\
+		b43legacy_phy_write(dev, (offset),		\
+				    _stack_restore(stack, 0x1,	\
+				    (offset)));			\
+	} while (0)
+#define radio_stacksave(offset)						\
+	do {								\
+		_stack_save(stack, &stackidx, 0x2, (offset),		\
+			    b43legacy_radio_read16(dev, (offset)));	\
+	} while (0)
+#define radio_stackrestore(offset)					\
+	do {								\
+		b43legacy_radio_write16(dev, (offset),			\
+					_stack_restore(stack, 0x2,	\
+					(offset)));			\
+	} while (0)
+#define ilt_stacksave(offset)					\
+	do {							\
+		_stack_save(stack, &stackidx, 0x3, (offset),	\
+			    b43legacy_ilt_read(dev, (offset)));	\
+	} while (0)
+#define ilt_stackrestore(offset)				\
+	do {							\
+		b43legacy_ilt_write(dev, (offset),		\
+				  _stack_restore(stack, 0x3,	\
+						 (offset)));	\
+	} while (0)
+
+static void
+b43legacy_radio_interference_mitigation_enable(struct b43legacy_wldev *dev,
+					       int mode)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 tmp;
+	u16 flipped;
+	u32 tmp32;
+	size_t stackidx = 0;
+	u32 *stack = phy->interfstack;
+
+	switch (mode) {
+	case B43legacy_RADIO_INTERFMODE_NONWLAN:
+		if (phy->rev != 1) {
+			b43legacy_phy_write(dev, 0x042B,
+					    b43legacy_phy_read(dev, 0x042B)
+					    | 0x0800);
+			b43legacy_phy_write(dev, B43legacy_PHY_G_CRS,
+					    b43legacy_phy_read(dev,
+					    B43legacy_PHY_G_CRS) & ~0x4000);
+			break;
+		}
+		radio_stacksave(0x0078);
+		tmp = (b43legacy_radio_read16(dev, 0x0078) & 0x001E);
+		flipped = flip_4bit(tmp);
+		if (flipped < 10 && flipped >= 8)
+			flipped = 7;
+		else if (flipped >= 10)
+			flipped -= 3;
+		flipped = flip_4bit(flipped);
+		flipped = (flipped << 1) | 0x0020;
+		b43legacy_radio_write16(dev, 0x0078, flipped);
+
+		b43legacy_calc_nrssi_threshold(dev);
+
+		phy_stacksave(0x0406);
+		b43legacy_phy_write(dev, 0x0406, 0x7E28);
+
+		b43legacy_phy_write(dev, 0x042B,
+				    b43legacy_phy_read(dev, 0x042B) | 0x0800);
+		b43legacy_phy_write(dev, B43legacy_PHY_RADIO_BITFIELD,
+				    b43legacy_phy_read(dev,
+				    B43legacy_PHY_RADIO_BITFIELD) | 0x1000);
+
+		phy_stacksave(0x04A0);
+		b43legacy_phy_write(dev, 0x04A0,
+				    (b43legacy_phy_read(dev, 0x04A0) & 0xC0C0)
+				    | 0x0008);
+		phy_stacksave(0x04A1);
+		b43legacy_phy_write(dev, 0x04A1,
+				    (b43legacy_phy_read(dev, 0x04A1) & 0xC0C0)
+				    | 0x0605);
+		phy_stacksave(0x04A2);
+		b43legacy_phy_write(dev, 0x04A2,
+				    (b43legacy_phy_read(dev, 0x04A2) & 0xC0C0)
+				    | 0x0204);
+		phy_stacksave(0x04A8);
+		b43legacy_phy_write(dev, 0x04A8,
+				    (b43legacy_phy_read(dev, 0x04A8) & 0xC0C0)
+				    | 0x0803);
+		phy_stacksave(0x04AB);
+		b43legacy_phy_write(dev, 0x04AB,
+				    (b43legacy_phy_read(dev, 0x04AB) & 0xC0C0)
+				    | 0x0605);
+
+		phy_stacksave(0x04A7);
+		b43legacy_phy_write(dev, 0x04A7, 0x0002);
+		phy_stacksave(0x04A3);
+		b43legacy_phy_write(dev, 0x04A3, 0x287A);
+		phy_stacksave(0x04A9);
+		b43legacy_phy_write(dev, 0x04A9, 0x2027);
+		phy_stacksave(0x0493);
+		b43legacy_phy_write(dev, 0x0493, 0x32F5);
+		phy_stacksave(0x04AA);
+		b43legacy_phy_write(dev, 0x04AA, 0x2027);
+		phy_stacksave(0x04AC);
+		b43legacy_phy_write(dev, 0x04AC, 0x32F5);
+		break;
+	case B43legacy_RADIO_INTERFMODE_MANUALWLAN:
+		if (b43legacy_phy_read(dev, 0x0033) & 0x0800)
+			break;
+
+		phy->aci_enable = true;
+
+		phy_stacksave(B43legacy_PHY_RADIO_BITFIELD);
+		phy_stacksave(B43legacy_PHY_G_CRS);
+		if (phy->rev < 2)
+			phy_stacksave(0x0406);
+		else {
+			phy_stacksave(0x04C0);
+			phy_stacksave(0x04C1);
+		}
+		phy_stacksave(0x0033);
+		phy_stacksave(0x04A7);
+		phy_stacksave(0x04A3);
+		phy_stacksave(0x04A9);
+		phy_stacksave(0x04AA);
+		phy_stacksave(0x04AC);
+		phy_stacksave(0x0493);
+		phy_stacksave(0x04A1);
+		phy_stacksave(0x04A0);
+		phy_stacksave(0x04A2);
+		phy_stacksave(0x048A);
+		phy_stacksave(0x04A8);
+		phy_stacksave(0x04AB);
+		if (phy->rev == 2) {
+			phy_stacksave(0x04AD);
+			phy_stacksave(0x04AE);
+		} else if (phy->rev >= 3) {
+			phy_stacksave(0x04AD);
+			phy_stacksave(0x0415);
+			phy_stacksave(0x0416);
+			phy_stacksave(0x0417);
+			ilt_stacksave(0x1A00 + 0x2);
+			ilt_stacksave(0x1A00 + 0x3);
+		}
+		phy_stacksave(0x042B);
+		phy_stacksave(0x048C);
+
+		b43legacy_phy_write(dev, B43legacy_PHY_RADIO_BITFIELD,
+				    b43legacy_phy_read(dev,
+				    B43legacy_PHY_RADIO_BITFIELD) & ~0x1000);
+		b43legacy_phy_write(dev, B43legacy_PHY_G_CRS,
+				    (b43legacy_phy_read(dev,
+				    B43legacy_PHY_G_CRS)
+				    & 0xFFFC) | 0x0002);
+
+		b43legacy_phy_write(dev, 0x0033, 0x0800);
+		b43legacy_phy_write(dev, 0x04A3, 0x2027);
+		b43legacy_phy_write(dev, 0x04A9, 0x1CA8);
+		b43legacy_phy_write(dev, 0x0493, 0x287A);
+		b43legacy_phy_write(dev, 0x04AA, 0x1CA8);
+		b43legacy_phy_write(dev, 0x04AC, 0x287A);
+
+		b43legacy_phy_write(dev, 0x04A0,
+				    (b43legacy_phy_read(dev, 0x04A0)
+				    & 0xFFC0) | 0x001A);
+		b43legacy_phy_write(dev, 0x04A7, 0x000D);
+
+		if (phy->rev < 2)
+			b43legacy_phy_write(dev, 0x0406, 0xFF0D);
+		else if (phy->rev == 2) {
+			b43legacy_phy_write(dev, 0x04C0, 0xFFFF);
+			b43legacy_phy_write(dev, 0x04C1, 0x00A9);
+		} else {
+			b43legacy_phy_write(dev, 0x04C0, 0x00C1);
+			b43legacy_phy_write(dev, 0x04C1, 0x0059);
+		}
+
+		b43legacy_phy_write(dev, 0x04A1,
+				    (b43legacy_phy_read(dev, 0x04A1)
+				    & 0xC0FF) | 0x1800);
+		b43legacy_phy_write(dev, 0x04A1,
+				    (b43legacy_phy_read(dev, 0x04A1)
+				    & 0xFFC0) | 0x0015);
+		b43legacy_phy_write(dev, 0x04A8,
+				    (b43legacy_phy_read(dev, 0x04A8)
+				    & 0xCFFF) | 0x1000);
+		b43legacy_phy_write(dev, 0x04A8,
+				    (b43legacy_phy_read(dev, 0x04A8)
+				    & 0xF0FF) | 0x0A00);
+		b43legacy_phy_write(dev, 0x04AB,
+				    (b43legacy_phy_read(dev, 0x04AB)
+				    & 0xCFFF) | 0x1000);
+		b43legacy_phy_write(dev, 0x04AB,
+				    (b43legacy_phy_read(dev, 0x04AB)
+				    & 0xF0FF) | 0x0800);
+		b43legacy_phy_write(dev, 0x04AB,
+				    (b43legacy_phy_read(dev, 0x04AB)
+				    & 0xFFCF) | 0x0010);
+		b43legacy_phy_write(dev, 0x04AB,
+				    (b43legacy_phy_read(dev, 0x04AB)
+				    & 0xFFF0) | 0x0005);
+		b43legacy_phy_write(dev, 0x04A8,
+				    (b43legacy_phy_read(dev, 0x04A8)
+				    & 0xFFCF) | 0x0010);
+		b43legacy_phy_write(dev, 0x04A8,
+				    (b43legacy_phy_read(dev, 0x04A8)
+				    & 0xFFF0) | 0x0006);
+		b43legacy_phy_write(dev, 0x04A2,
+				    (b43legacy_phy_read(dev, 0x04A2)
+				    & 0xF0FF) | 0x0800);
+		b43legacy_phy_write(dev, 0x04A0,
+				    (b43legacy_phy_read(dev, 0x04A0)
+				    & 0xF0FF) | 0x0500);
+		b43legacy_phy_write(dev, 0x04A2,
+				    (b43legacy_phy_read(dev, 0x04A2)
+				    & 0xFFF0) | 0x000B);
+
+		if (phy->rev >= 3) {
+			b43legacy_phy_write(dev, 0x048A,
+					    b43legacy_phy_read(dev, 0x048A)
+					    & ~0x8000);
+			b43legacy_phy_write(dev, 0x0415,
+					    (b43legacy_phy_read(dev, 0x0415)
+					    & 0x8000) | 0x36D8);
+			b43legacy_phy_write(dev, 0x0416,
+					    (b43legacy_phy_read(dev, 0x0416)
+					    & 0x8000) | 0x36D8);
+			b43legacy_phy_write(dev, 0x0417,
+					    (b43legacy_phy_read(dev, 0x0417)
+					    & 0xFE00) | 0x016D);
+		} else {
+			b43legacy_phy_write(dev, 0x048A,
+					    b43legacy_phy_read(dev, 0x048A)
+					    | 0x1000);
+			b43legacy_phy_write(dev, 0x048A,
+					    (b43legacy_phy_read(dev, 0x048A)
+					    & 0x9FFF) | 0x2000);
+			tmp32 = b43legacy_shm_read32(dev, B43legacy_SHM_SHARED,
+					    B43legacy_UCODEFLAGS_OFFSET);
+			if (!(tmp32 & 0x800)) {
+				tmp32 |= 0x800;
+				b43legacy_shm_write32(dev, B43legacy_SHM_SHARED,
+					    B43legacy_UCODEFLAGS_OFFSET,
+					    tmp32);
+			}
+		}
+		if (phy->rev >= 2)
+			b43legacy_phy_write(dev, 0x042B,
+					    b43legacy_phy_read(dev, 0x042B)
+					    | 0x0800);
+		b43legacy_phy_write(dev, 0x048C,
+				    (b43legacy_phy_read(dev, 0x048C)
+				    & 0xF0FF) | 0x0200);
+		if (phy->rev == 2) {
+			b43legacy_phy_write(dev, 0x04AE,
+					    (b43legacy_phy_read(dev, 0x04AE)
+					    & 0xFF00) | 0x007F);
+			b43legacy_phy_write(dev, 0x04AD,
+					    (b43legacy_phy_read(dev, 0x04AD)
+					    & 0x00FF) | 0x1300);
+		} else if (phy->rev >= 6) {
+			b43legacy_ilt_write(dev, 0x1A00 + 0x3, 0x007F);
+			b43legacy_ilt_write(dev, 0x1A00 + 0x2, 0x007F);
+			b43legacy_phy_write(dev, 0x04AD,
+					    b43legacy_phy_read(dev, 0x04AD)
+					    & 0x00FF);
+		}
+		b43legacy_calc_nrssi_slope(dev);
+		break;
+	default:
+		B43legacy_BUG_ON(1);
+	}
+}
+
+static void
+b43legacy_radio_interference_mitigation_disable(struct b43legacy_wldev *dev,
+						int mode)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u32 tmp32;
+	u32 *stack = phy->interfstack;
+
+	switch (mode) {
+	case B43legacy_RADIO_INTERFMODE_NONWLAN:
+		if (phy->rev != 1) {
+			b43legacy_phy_write(dev, 0x042B,
+					    b43legacy_phy_read(dev, 0x042B)
+					    & ~0x0800);
+			b43legacy_phy_write(dev, B43legacy_PHY_G_CRS,
+					    b43legacy_phy_read(dev,
+					    B43legacy_PHY_G_CRS) | 0x4000);
+			break;
+		}
+		phy_stackrestore(0x0078);
+		b43legacy_calc_nrssi_threshold(dev);
+		phy_stackrestore(0x0406);
+		b43legacy_phy_write(dev, 0x042B,
+				    b43legacy_phy_read(dev, 0x042B) & ~0x0800);
+		if (!dev->bad_frames_preempt)
+			b43legacy_phy_write(dev, B43legacy_PHY_RADIO_BITFIELD,
+					    b43legacy_phy_read(dev,
+					    B43legacy_PHY_RADIO_BITFIELD)
+					    & ~(1 << 11));
+		b43legacy_phy_write(dev, B43legacy_PHY_G_CRS,
+				    b43legacy_phy_read(dev, B43legacy_PHY_G_CRS)
+				    | 0x4000);
+		phy_stackrestore(0x04A0);
+		phy_stackrestore(0x04A1);
+		phy_stackrestore(0x04A2);
+		phy_stackrestore(0x04A8);
+		phy_stackrestore(0x04AB);
+		phy_stackrestore(0x04A7);
+		phy_stackrestore(0x04A3);
+		phy_stackrestore(0x04A9);
+		phy_stackrestore(0x0493);
+		phy_stackrestore(0x04AA);
+		phy_stackrestore(0x04AC);
+		break;
+	case B43legacy_RADIO_INTERFMODE_MANUALWLAN:
+		if (!(b43legacy_phy_read(dev, 0x0033) & 0x0800))
+			break;
+
+		phy->aci_enable = false;
+
+		phy_stackrestore(B43legacy_PHY_RADIO_BITFIELD);
+		phy_stackrestore(B43legacy_PHY_G_CRS);
+		phy_stackrestore(0x0033);
+		phy_stackrestore(0x04A3);
+		phy_stackrestore(0x04A9);
+		phy_stackrestore(0x0493);
+		phy_stackrestore(0x04AA);
+		phy_stackrestore(0x04AC);
+		phy_stackrestore(0x04A0);
+		phy_stackrestore(0x04A7);
+		if (phy->rev >= 2) {
+			phy_stackrestore(0x04C0);
+			phy_stackrestore(0x04C1);
+		} else
+			phy_stackrestore(0x0406);
+		phy_stackrestore(0x04A1);
+		phy_stackrestore(0x04AB);
+		phy_stackrestore(0x04A8);
+		if (phy->rev == 2) {
+			phy_stackrestore(0x04AD);
+			phy_stackrestore(0x04AE);
+		} else if (phy->rev >= 3) {
+			phy_stackrestore(0x04AD);
+			phy_stackrestore(0x0415);
+			phy_stackrestore(0x0416);
+			phy_stackrestore(0x0417);
+			ilt_stackrestore(0x1A00 + 0x2);
+			ilt_stackrestore(0x1A00 + 0x3);
+		}
+		phy_stackrestore(0x04A2);
+		phy_stackrestore(0x04A8);
+		phy_stackrestore(0x042B);
+		phy_stackrestore(0x048C);
+		tmp32 = b43legacy_shm_read32(dev, B43legacy_SHM_SHARED,
+					     B43legacy_UCODEFLAGS_OFFSET);
+		if (tmp32 & 0x800) {
+			tmp32 &= ~0x800;
+			b43legacy_shm_write32(dev, B43legacy_SHM_SHARED,
+					      B43legacy_UCODEFLAGS_OFFSET,
+					      tmp32);
+		}
+		b43legacy_calc_nrssi_slope(dev);
+		break;
+	default:
+		B43legacy_BUG_ON(1);
+	}
+}
+
+#undef phy_stacksave
+#undef phy_stackrestore
+#undef radio_stacksave
+#undef radio_stackrestore
+#undef ilt_stacksave
+#undef ilt_stackrestore
+
+int b43legacy_radio_set_interference_mitigation(struct b43legacy_wldev *dev,
+						int mode)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	int currentmode;
+
+	if ((phy->type != B43legacy_PHYTYPE_G) ||
+	    (phy->rev == 0) || (!phy->gmode))
+		return -ENODEV;
+
+	phy->aci_wlan_automatic = false;
+	switch (mode) {
+	case B43legacy_RADIO_INTERFMODE_AUTOWLAN:
+		phy->aci_wlan_automatic = true;
+		if (phy->aci_enable)
+			mode = B43legacy_RADIO_INTERFMODE_MANUALWLAN;
+		else
+			mode = B43legacy_RADIO_INTERFMODE_NONE;
+		break;
+	case B43legacy_RADIO_INTERFMODE_NONE:
+	case B43legacy_RADIO_INTERFMODE_NONWLAN:
+	case B43legacy_RADIO_INTERFMODE_MANUALWLAN:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	currentmode = phy->interfmode;
+	if (currentmode == mode)
+		return 0;
+	if (currentmode != B43legacy_RADIO_INTERFMODE_NONE)
+		b43legacy_radio_interference_mitigation_disable(dev,
+								currentmode);
+
+	if (mode == B43legacy_RADIO_INTERFMODE_NONE) {
+		phy->aci_enable = false;
+		phy->aci_hw_rssi = false;
+	} else
+		b43legacy_radio_interference_mitigation_enable(dev, mode);
+	phy->interfmode = mode;
+
+	return 0;
+}
+
+u16 b43legacy_radio_calibrationvalue(struct b43legacy_wldev *dev)
+{
+	u16 reg;
+	u16 index;
+	u16 ret;
+
+	reg = b43legacy_radio_read16(dev, 0x0060);
+	index = (reg & 0x001E) >> 1;
+	ret = rcc_table[index] << 1;
+	ret |= (reg & 0x0001);
+	ret |= 0x0020;
+
+	return ret;
+}
+
+#define LPD(L, P, D)    (((L) << 2) | ((P) << 1) | ((D) << 0))
+static u16 b43legacy_get_812_value(struct b43legacy_wldev *dev, u8 lpd)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 loop_or = 0;
+	u16 adj_loopback_gain = phy->loopback_gain[0];
+	u8 loop;
+	u16 extern_lna_control;
+
+	if (!phy->gmode)
+		return 0;
+	if (!has_loopback_gain(phy)) {
+		if (phy->rev < 7 || !(dev->dev->bus->sprom.boardflags_lo
+		    & B43legacy_BFL_EXTLNA)) {
+			switch (lpd) {
+			case LPD(0, 1, 1):
+				return 0x0FB2;
+			case LPD(0, 0, 1):
+				return 0x00B2;
+			case LPD(1, 0, 1):
+				return 0x30B2;
+			case LPD(1, 0, 0):
+				return 0x30B3;
+			default:
+				B43legacy_BUG_ON(1);
+			}
+		} else {
+			switch (lpd) {
+			case LPD(0, 1, 1):
+				return 0x8FB2;
+			case LPD(0, 0, 1):
+				return 0x80B2;
+			case LPD(1, 0, 1):
+				return 0x20B2;
+			case LPD(1, 0, 0):
+				return 0x20B3;
+			default:
+				B43legacy_BUG_ON(1);
+			}
+		}
+	} else {
+		if (phy->radio_rev == 8)
+			adj_loopback_gain += 0x003E;
+		else
+			adj_loopback_gain += 0x0026;
+		if (adj_loopback_gain >= 0x46) {
+			adj_loopback_gain -= 0x46;
+			extern_lna_control = 0x3000;
+		} else if (adj_loopback_gain >= 0x3A) {
+			adj_loopback_gain -= 0x3A;
+			extern_lna_control = 0x2000;
+		} else if (adj_loopback_gain >= 0x2E) {
+			adj_loopback_gain -= 0x2E;
+			extern_lna_control = 0x1000;
+		} else {
+			adj_loopback_gain -= 0x10;
+			extern_lna_control = 0x0000;
+		}
+		for (loop = 0; loop < 16; loop++) {
+			u16 tmp = adj_loopback_gain - 6 * loop;
+			if (tmp < 6)
+				break;
+		}
+
+		loop_or = (loop << 8) | extern_lna_control;
+		if (phy->rev >= 7 && dev->dev->bus->sprom.boardflags_lo
+		    & B43legacy_BFL_EXTLNA) {
+			if (extern_lna_control)
+				loop_or |= 0x8000;
+			switch (lpd) {
+			case LPD(0, 1, 1):
+				return 0x8F92;
+			case LPD(0, 0, 1):
+				return (0x8092 | loop_or);
+			case LPD(1, 0, 1):
+				return (0x2092 | loop_or);
+			case LPD(1, 0, 0):
+				return (0x2093 | loop_or);
+			default:
+				B43legacy_BUG_ON(1);
+			}
+		} else {
+			switch (lpd) {
+			case LPD(0, 1, 1):
+				return 0x0F92;
+			case LPD(0, 0, 1):
+			case LPD(1, 0, 1):
+				return (0x0092 | loop_or);
+			case LPD(1, 0, 0):
+				return (0x0093 | loop_or);
+			default:
+				B43legacy_BUG_ON(1);
+			}
+		}
+	}
+	return 0;
+}
+
+u16 b43legacy_radio_init2050(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 backup[21] = { 0 };
+	u16 ret;
+	u16 i;
+	u16 j;
+	u32 tmp1 = 0;
+	u32 tmp2 = 0;
+
+	backup[0] = b43legacy_radio_read16(dev, 0x0043);
+	backup[14] = b43legacy_radio_read16(dev, 0x0051);
+	backup[15] = b43legacy_radio_read16(dev, 0x0052);
+	backup[1] = b43legacy_phy_read(dev, 0x0015);
+	backup[16] = b43legacy_phy_read(dev, 0x005A);
+	backup[17] = b43legacy_phy_read(dev, 0x0059);
+	backup[18] = b43legacy_phy_read(dev, 0x0058);
+	if (phy->type == B43legacy_PHYTYPE_B) {
+		backup[2] = b43legacy_phy_read(dev, 0x0030);
+		backup[3] = b43legacy_read16(dev, 0x03EC);
+		b43legacy_phy_write(dev, 0x0030, 0x00FF);
+		b43legacy_write16(dev, 0x03EC, 0x3F3F);
+	} else {
+		if (phy->gmode) {
+			backup[4] = b43legacy_phy_read(dev, 0x0811);
+			backup[5] = b43legacy_phy_read(dev, 0x0812);
+			backup[6] = b43legacy_phy_read(dev, 0x0814);
+			backup[7] = b43legacy_phy_read(dev, 0x0815);
+			backup[8] = b43legacy_phy_read(dev,
+						       B43legacy_PHY_G_CRS);
+			backup[9] = b43legacy_phy_read(dev, 0x0802);
+			b43legacy_phy_write(dev, 0x0814,
+					    (b43legacy_phy_read(dev, 0x0814)
+					    | 0x0003));
+			b43legacy_phy_write(dev, 0x0815,
+					    (b43legacy_phy_read(dev, 0x0815)
+					    & 0xFFFC));
+			b43legacy_phy_write(dev, B43legacy_PHY_G_CRS,
+					    (b43legacy_phy_read(dev,
+					    B43legacy_PHY_G_CRS) & 0x7FFF));
+			b43legacy_phy_write(dev, 0x0802,
+					    (b43legacy_phy_read(dev, 0x0802)
+					    & 0xFFFC));
+			if (phy->rev > 1) { /* loopback gain enabled */
+				backup[19] = b43legacy_phy_read(dev, 0x080F);
+				backup[20] = b43legacy_phy_read(dev, 0x0810);
+				if (phy->rev >= 3)
+					b43legacy_phy_write(dev, 0x080F,
+							    0xC020);
+				else
+					b43legacy_phy_write(dev, 0x080F,
+							    0x8020);
+				b43legacy_phy_write(dev, 0x0810, 0x0000);
+			}
+			b43legacy_phy_write(dev, 0x0812,
+					    b43legacy_get_812_value(dev,
+					    LPD(0, 1, 1)));
+			if (phy->rev < 7 ||
+			    !(dev->dev->bus->sprom.boardflags_lo
+			    & B43legacy_BFL_EXTLNA))
+				b43legacy_phy_write(dev, 0x0811, 0x01B3);
+			else
+				b43legacy_phy_write(dev, 0x0811, 0x09B3);
+		}
+	}
+	b43legacy_write16(dev, B43legacy_MMIO_PHY_RADIO,
+			(b43legacy_read16(dev, B43legacy_MMIO_PHY_RADIO)
+					  | 0x8000));
+	backup[10] = b43legacy_phy_read(dev, 0x0035);
+	b43legacy_phy_write(dev, 0x0035,
+			    (b43legacy_phy_read(dev, 0x0035) & 0xFF7F));
+	backup[11] = b43legacy_read16(dev, 0x03E6);
+	backup[12] = b43legacy_read16(dev, B43legacy_MMIO_CHANNEL_EXT);
+
+	/* Initialization */
+	if (phy->analog == 0)
+		b43legacy_write16(dev, 0x03E6, 0x0122);
+	else {
+		if (phy->analog >= 2)
+			b43legacy_phy_write(dev, 0x0003,
+					    (b43legacy_phy_read(dev, 0x0003)
+					    & 0xFFBF) | 0x0040);
+		b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT,
+				  (b43legacy_read16(dev,
+				  B43legacy_MMIO_CHANNEL_EXT) | 0x2000));
+	}
+
+	ret = b43legacy_radio_calibrationvalue(dev);
+
+	if (phy->type == B43legacy_PHYTYPE_B)
+		b43legacy_radio_write16(dev, 0x0078, 0x0026);
+
+	if (phy->gmode)
+		b43legacy_phy_write(dev, 0x0812,
+				    b43legacy_get_812_value(dev,
+				    LPD(0, 1, 1)));
+	b43legacy_phy_write(dev, 0x0015, 0xBFAF);
+	b43legacy_phy_write(dev, 0x002B, 0x1403);
+	if (phy->gmode)
+		b43legacy_phy_write(dev, 0x0812,
+				    b43legacy_get_812_value(dev,
+				    LPD(0, 0, 1)));
+	b43legacy_phy_write(dev, 0x0015, 0xBFA0);
+	b43legacy_radio_write16(dev, 0x0051,
+				(b43legacy_radio_read16(dev, 0x0051)
+				| 0x0004));
+	if (phy->radio_rev == 8)
+		b43legacy_radio_write16(dev, 0x0043, 0x001F);
+	else {
+		b43legacy_radio_write16(dev, 0x0052, 0x0000);
+		b43legacy_radio_write16(dev, 0x0043,
+					(b43legacy_radio_read16(dev, 0x0043)
+					& 0xFFF0) | 0x0009);
+	}
+	b43legacy_phy_write(dev, 0x0058, 0x0000);
+
+	for (i = 0; i < 16; i++) {
+		b43legacy_phy_write(dev, 0x005A, 0x0480);
+		b43legacy_phy_write(dev, 0x0059, 0xC810);
+		b43legacy_phy_write(dev, 0x0058, 0x000D);
+		if (phy->gmode)
+			b43legacy_phy_write(dev, 0x0812,
+					    b43legacy_get_812_value(dev,
+					    LPD(1, 0, 1)));
+		b43legacy_phy_write(dev, 0x0015, 0xAFB0);
+		udelay(10);
+		if (phy->gmode)
+			b43legacy_phy_write(dev, 0x0812,
+					    b43legacy_get_812_value(dev,
+					    LPD(1, 0, 1)));
+		b43legacy_phy_write(dev, 0x0015, 0xEFB0);
+		udelay(10);
+		if (phy->gmode)
+			b43legacy_phy_write(dev, 0x0812,
+					    b43legacy_get_812_value(dev,
+					    LPD(1, 0, 0)));
+		b43legacy_phy_write(dev, 0x0015, 0xFFF0);
+		udelay(20);
+		tmp1 += b43legacy_phy_read(dev, 0x002D);
+		b43legacy_phy_write(dev, 0x0058, 0x0000);
+		if (phy->gmode)
+			b43legacy_phy_write(dev, 0x0812,
+					    b43legacy_get_812_value(dev,
+					    LPD(1, 0, 1)));
+		b43legacy_phy_write(dev, 0x0015, 0xAFB0);
+	}
+
+	tmp1++;
+	tmp1 >>= 9;
+	udelay(10);
+	b43legacy_phy_write(dev, 0x0058, 0x0000);
+
+	for (i = 0; i < 16; i++) {
+		b43legacy_radio_write16(dev, 0x0078, (flip_4bit(i) << 1)
+					| 0x0020);
+		backup[13] = b43legacy_radio_read16(dev, 0x0078);
+		udelay(10);
+		for (j = 0; j < 16; j++) {
+			b43legacy_phy_write(dev, 0x005A, 0x0D80);
+			b43legacy_phy_write(dev, 0x0059, 0xC810);
+			b43legacy_phy_write(dev, 0x0058, 0x000D);
+			if (phy->gmode)
+				b43legacy_phy_write(dev, 0x0812,
+						    b43legacy_get_812_value(dev,
+						    LPD(1, 0, 1)));
+			b43legacy_phy_write(dev, 0x0015, 0xAFB0);
+			udelay(10);
+			if (phy->gmode)
+				b43legacy_phy_write(dev, 0x0812,
+						    b43legacy_get_812_value(dev,
+						    LPD(1, 0, 1)));
+			b43legacy_phy_write(dev, 0x0015, 0xEFB0);
+			udelay(10);
+			if (phy->gmode)
+				b43legacy_phy_write(dev, 0x0812,
+						    b43legacy_get_812_value(dev,
+						    LPD(1, 0, 0)));
+			b43legacy_phy_write(dev, 0x0015, 0xFFF0);
+			udelay(10);
+			tmp2 += b43legacy_phy_read(dev, 0x002D);
+			b43legacy_phy_write(dev, 0x0058, 0x0000);
+			if (phy->gmode)
+				b43legacy_phy_write(dev, 0x0812,
+						    b43legacy_get_812_value(dev,
+						    LPD(1, 0, 1)));
+			b43legacy_phy_write(dev, 0x0015, 0xAFB0);
+		}
+		tmp2++;
+		tmp2 >>= 8;
+		if (tmp1 < tmp2)
+			break;
+	}
+
+	/* Restore the registers */
+	b43legacy_phy_write(dev, 0x0015, backup[1]);
+	b43legacy_radio_write16(dev, 0x0051, backup[14]);
+	b43legacy_radio_write16(dev, 0x0052, backup[15]);
+	b43legacy_radio_write16(dev, 0x0043, backup[0]);
+	b43legacy_phy_write(dev, 0x005A, backup[16]);
+	b43legacy_phy_write(dev, 0x0059, backup[17]);
+	b43legacy_phy_write(dev, 0x0058, backup[18]);
+	b43legacy_write16(dev, 0x03E6, backup[11]);
+	if (phy->analog != 0)
+		b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, backup[12]);
+	b43legacy_phy_write(dev, 0x0035, backup[10]);
+	b43legacy_radio_selectchannel(dev, phy->channel, 1);
+	if (phy->type == B43legacy_PHYTYPE_B) {
+		b43legacy_phy_write(dev, 0x0030, backup[2]);
+		b43legacy_write16(dev, 0x03EC, backup[3]);
+	} else {
+		if (phy->gmode) {
+			b43legacy_write16(dev, B43legacy_MMIO_PHY_RADIO,
+					  (b43legacy_read16(dev,
+					  B43legacy_MMIO_PHY_RADIO) & 0x7FFF));
+			b43legacy_phy_write(dev, 0x0811, backup[4]);
+			b43legacy_phy_write(dev, 0x0812, backup[5]);
+			b43legacy_phy_write(dev, 0x0814, backup[6]);
+			b43legacy_phy_write(dev, 0x0815, backup[7]);
+			b43legacy_phy_write(dev, B43legacy_PHY_G_CRS,
+					    backup[8]);
+			b43legacy_phy_write(dev, 0x0802, backup[9]);
+			if (phy->rev > 1) {
+				b43legacy_phy_write(dev, 0x080F, backup[19]);
+				b43legacy_phy_write(dev, 0x0810, backup[20]);
+			}
+		}
+	}
+	if (i >= 15)
+		ret = backup[13];
+
+	return ret;
+}
+
+static inline
+u16 freq_r3A_value(u16 frequency)
+{
+	u16 value;
+
+	if (frequency < 5091)
+		value = 0x0040;
+	else if (frequency < 5321)
+		value = 0x0000;
+	else if (frequency < 5806)
+		value = 0x0080;
+	else
+		value = 0x0040;
+
+	return value;
+}
+
+int b43legacy_radio_selectchannel(struct b43legacy_wldev *dev,
+				  u8 channel,
+				  int synthetic_pu_workaround)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+
+	if (channel == 0xFF) {
+		switch (phy->type) {
+		case B43legacy_PHYTYPE_B:
+		case B43legacy_PHYTYPE_G:
+			channel = B43legacy_RADIO_DEFAULT_CHANNEL_BG;
+			break;
+		default:
+			B43legacy_WARN_ON(1);
+		}
+	}
+
+/* TODO: Check if channel is valid - return -EINVAL if not */
+	if (synthetic_pu_workaround)
+		b43legacy_synth_pu_workaround(dev, channel);
+
+	b43legacy_write16(dev, B43legacy_MMIO_CHANNEL,
+			  channel2freq_bg(channel));
+
+	if (channel == 14) {
+		if (dev->dev->bus->sprom.country_code == 5)   /* JAPAN) */
+			b43legacy_shm_write32(dev, B43legacy_SHM_SHARED,
+					      B43legacy_UCODEFLAGS_OFFSET,
+					      b43legacy_shm_read32(dev,
+					      B43legacy_SHM_SHARED,
+					      B43legacy_UCODEFLAGS_OFFSET)
+					      & ~(1 << 7));
+		else
+			b43legacy_shm_write32(dev, B43legacy_SHM_SHARED,
+					      B43legacy_UCODEFLAGS_OFFSET,
+					      b43legacy_shm_read32(dev,
+					      B43legacy_SHM_SHARED,
+					      B43legacy_UCODEFLAGS_OFFSET)
+					      | (1 << 7));
+		b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT,
+				  b43legacy_read16(dev,
+				  B43legacy_MMIO_CHANNEL_EXT) | (1 << 11));
+	} else
+		b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT,
+				  b43legacy_read16(dev,
+				  B43legacy_MMIO_CHANNEL_EXT) & 0xF7BF);
+
+	phy->channel = channel;
+	/*XXX: Using the longer of 2 timeouts (8000 vs 2000 usecs). Specs states
+	 *     that 2000 usecs might suffice. */
+	msleep(8);
+
+	return 0;
+}
+
+void b43legacy_radio_set_txantenna(struct b43legacy_wldev *dev, u32 val)
+{
+	u16 tmp;
+
+	val <<= 8;
+	tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x0022) & 0xFCFF;
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0022, tmp | val);
+	tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x03A8) & 0xFCFF;
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x03A8, tmp | val);
+	tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x0054) & 0xFCFF;
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0054, tmp | val);
+}
+
+/* http://bcm-specs.sipsolutions.net/TX_Gain_Base_Band */
+static u16 b43legacy_get_txgain_base_band(u16 txpower)
+{
+	u16 ret;
+
+	B43legacy_WARN_ON(txpower > 63);
+
+	if (txpower >= 54)
+		ret = 2;
+	else if (txpower >= 49)
+		ret = 4;
+	else if (txpower >= 44)
+		ret = 5;
+	else
+		ret = 6;
+
+	return ret;
+}
+
+/* http://bcm-specs.sipsolutions.net/TX_Gain_Radio_Frequency_Power_Amplifier */
+static u16 b43legacy_get_txgain_freq_power_amp(u16 txpower)
+{
+	u16 ret;
+
+	B43legacy_WARN_ON(txpower > 63);
+
+	if (txpower >= 32)
+		ret = 0;
+	else if (txpower >= 25)
+		ret = 1;
+	else if (txpower >= 20)
+		ret = 2;
+	else if (txpower >= 12)
+		ret = 3;
+	else
+		ret = 4;
+
+	return ret;
+}
+
+/* http://bcm-specs.sipsolutions.net/TX_Gain_Digital_Analog_Converter */
+static u16 b43legacy_get_txgain_dac(u16 txpower)
+{
+	u16 ret;
+
+	B43legacy_WARN_ON(txpower > 63);
+
+	if (txpower >= 54)
+		ret = txpower - 53;
+	else if (txpower >= 49)
+		ret = txpower - 42;
+	else if (txpower >= 44)
+		ret = txpower - 37;
+	else if (txpower >= 32)
+		ret = txpower - 32;
+	else if (txpower >= 25)
+		ret = txpower - 20;
+	else if (txpower >= 20)
+		ret = txpower - 13;
+	else if (txpower >= 12)
+		ret = txpower - 8;
+	else
+		ret = txpower;
+
+	return ret;
+}
+
+void b43legacy_radio_set_txpower_a(struct b43legacy_wldev *dev, u16 txpower)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 pamp;
+	u16 base;
+	u16 dac;
+	u16 ilt;
+
+	txpower = clamp_val(txpower, 0, 63);
+
+	pamp = b43legacy_get_txgain_freq_power_amp(txpower);
+	pamp <<= 5;
+	pamp &= 0x00E0;
+	b43legacy_phy_write(dev, 0x0019, pamp);
+
+	base = b43legacy_get_txgain_base_band(txpower);
+	base &= 0x000F;
+	b43legacy_phy_write(dev, 0x0017, base | 0x0020);
+
+	ilt = b43legacy_ilt_read(dev, 0x3001);
+	ilt &= 0x0007;
+
+	dac = b43legacy_get_txgain_dac(txpower);
+	dac <<= 3;
+	dac |= ilt;
+
+	b43legacy_ilt_write(dev, 0x3001, dac);
+
+	phy->txpwr_offset = txpower;
+
+	/* TODO: FuncPlaceholder (Adjust BB loft cancel) */
+}
+
+void b43legacy_radio_set_txpower_bg(struct b43legacy_wldev *dev,
+				    u16 baseband_attenuation,
+				    u16 radio_attenuation,
+				    u16 txpower)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+
+	if (baseband_attenuation == 0xFFFF)
+		baseband_attenuation = phy->bbatt;
+	if (radio_attenuation == 0xFFFF)
+		radio_attenuation = phy->rfatt;
+	if (txpower == 0xFFFF)
+		txpower = phy->txctl1;
+	phy->bbatt = baseband_attenuation;
+	phy->rfatt = radio_attenuation;
+	phy->txctl1 = txpower;
+
+	B43legacy_WARN_ON(baseband_attenuation > 11);
+	if (phy->radio_rev < 6)
+		B43legacy_WARN_ON(radio_attenuation > 9);
+	else
+		B43legacy_WARN_ON(radio_attenuation > 31);
+	B43legacy_WARN_ON(txpower > 7);
+
+	b43legacy_phy_set_baseband_attenuation(dev, baseband_attenuation);
+	b43legacy_radio_write16(dev, 0x0043, radio_attenuation);
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0064,
+			      radio_attenuation);
+	if (phy->radio_ver == 0x2050)
+		b43legacy_radio_write16(dev, 0x0052,
+					(b43legacy_radio_read16(dev, 0x0052)
+					& ~0x0070) | ((txpower << 4) & 0x0070));
+	/* FIXME: The spec is very weird and unclear here. */
+	if (phy->type == B43legacy_PHYTYPE_G)
+		b43legacy_phy_lo_adjust(dev, 0);
+}
+
+u16 b43legacy_default_baseband_attenuation(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+
+	if (phy->radio_ver == 0x2050 && phy->radio_rev < 6)
+		return 0;
+	return 2;
+}
+
+u16 b43legacy_default_radio_attenuation(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	u16 att = 0xFFFF;
+
+	switch (phy->radio_ver) {
+	case 0x2053:
+		switch (phy->radio_rev) {
+		case 1:
+			att = 6;
+			break;
+		}
+		break;
+	case 0x2050:
+		switch (phy->radio_rev) {
+		case 0:
+			att = 5;
+			break;
+		case 1:
+			if (phy->type == B43legacy_PHYTYPE_G) {
+				if (is_bcm_board_vendor(dev) &&
+				    dev->dev->bus->boardinfo.type == 0x421 &&
+				    dev->dev->bus->sprom.board_rev >= 30)
+					att = 3;
+				else if (is_bcm_board_vendor(dev) &&
+					 dev->dev->bus->boardinfo.type == 0x416)
+					att = 3;
+				else
+					att = 1;
+			} else {
+				if (is_bcm_board_vendor(dev) &&
+				    dev->dev->bus->boardinfo.type == 0x421 &&
+				    dev->dev->bus->sprom.board_rev >= 30)
+					att = 7;
+				else
+					att = 6;
+			}
+			break;
+		case 2:
+			if (phy->type == B43legacy_PHYTYPE_G) {
+				if (is_bcm_board_vendor(dev) &&
+				    dev->dev->bus->boardinfo.type == 0x421 &&
+				    dev->dev->bus->sprom.board_rev >= 30)
+					att = 3;
+				else if (is_bcm_board_vendor(dev) &&
+					 dev->dev->bus->boardinfo.type ==
+					 0x416)
+					att = 5;
+				else if (dev->dev->bus->chip_id == 0x4320)
+					att = 4;
+				else
+					att = 3;
+			} else
+				att = 6;
+			break;
+		case 3:
+			att = 5;
+			break;
+		case 4:
+		case 5:
+			att = 1;
+			break;
+		case 6:
+		case 7:
+			att = 5;
+			break;
+		case 8:
+			att = 0x1A;
+			break;
+		case 9:
+		default:
+			att = 5;
+		}
+	}
+	if (is_bcm_board_vendor(dev) &&
+	    dev->dev->bus->boardinfo.type == 0x421) {
+		if (dev->dev->bus->sprom.board_rev < 0x43)
+			att = 2;
+		else if (dev->dev->bus->sprom.board_rev < 0x51)
+			att = 3;
+	}
+	if (att == 0xFFFF)
+		att = 5;
+
+	return att;
+}
+
+u16 b43legacy_default_txctl1(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+
+	if (phy->radio_ver != 0x2050)
+		return 0;
+	if (phy->radio_rev == 1)
+		return 3;
+	if (phy->radio_rev < 6)
+		return 2;
+	if (phy->radio_rev == 8)
+		return 1;
+	return 0;
+}
+
+void b43legacy_radio_turn_on(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	int err;
+	u8 channel;
+
+	might_sleep();
+
+	if (phy->radio_on)
+		return;
+
+	switch (phy->type) {
+	case B43legacy_PHYTYPE_B:
+	case B43legacy_PHYTYPE_G:
+		b43legacy_phy_write(dev, 0x0015, 0x8000);
+		b43legacy_phy_write(dev, 0x0015, 0xCC00);
+		b43legacy_phy_write(dev, 0x0015,
+				    (phy->gmode ? 0x00C0 : 0x0000));
+		if (phy->radio_off_context.valid) {
+			/* Restore the RFover values. */
+			b43legacy_phy_write(dev, B43legacy_PHY_RFOVER,
+					    phy->radio_off_context.rfover);
+			b43legacy_phy_write(dev, B43legacy_PHY_RFOVERVAL,
+					    phy->radio_off_context.rfoverval);
+			phy->radio_off_context.valid = false;
+		}
+		channel = phy->channel;
+		err = b43legacy_radio_selectchannel(dev,
+					B43legacy_RADIO_DEFAULT_CHANNEL_BG, 1);
+		err |= b43legacy_radio_selectchannel(dev, channel, 0);
+		B43legacy_WARN_ON(err);
+		break;
+	default:
+		B43legacy_BUG_ON(1);
+	}
+	phy->radio_on = true;
+}
+
+void b43legacy_radio_turn_off(struct b43legacy_wldev *dev, bool force)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+
+	if (!phy->radio_on && !force)
+		return;
+
+	if (phy->type == B43legacy_PHYTYPE_G && dev->dev->id.revision >= 5) {
+		u16 rfover, rfoverval;
+
+		rfover = b43legacy_phy_read(dev, B43legacy_PHY_RFOVER);
+		rfoverval = b43legacy_phy_read(dev, B43legacy_PHY_RFOVERVAL);
+		if (!force) {
+			phy->radio_off_context.rfover = rfover;
+			phy->radio_off_context.rfoverval = rfoverval;
+			phy->radio_off_context.valid = true;
+		}
+		b43legacy_phy_write(dev, B43legacy_PHY_RFOVER, rfover | 0x008C);
+		b43legacy_phy_write(dev, B43legacy_PHY_RFOVERVAL,
+				    rfoverval & 0xFF73);
+	} else
+		b43legacy_phy_write(dev, 0x0015, 0xAA00);
+	phy->radio_on = false;
+	b43legacydbg(dev->wl, "Radio initialized\n");
+}
+
+void b43legacy_radio_clear_tssi(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+
+	switch (phy->type) {
+	case B43legacy_PHYTYPE_B:
+	case B43legacy_PHYTYPE_G:
+		b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0058,
+				      0x7F7F);
+		b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x005a,
+				      0x7F7F);
+		b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0070,
+				      0x7F7F);
+		b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0072,
+				      0x7F7F);
+		break;
+	}
+}
diff --git a/drivers/net/wireless/broadcom/b43legacy/radio.h b/drivers/net/wireless/broadcom/b43legacy/radio.h
new file mode 100644
index 0000000..dd2976d
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/radio.h
@@ -0,0 +1,97 @@
+/*
+
+  Broadcom B43legacy wireless driver
+
+  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
+		     Stefano Brivio <stefano.brivio@polimi.it>
+		     Michael Buesch <m@bues.ch>
+		     Danny van Dyk <kugelfang@gentoo.org>
+		     Andreas Jaggi <andreas.jaggi@waterwave.ch>
+
+  Some parts of the code in this file are derived from the ipw2200
+  driver  Copyright(c) 2003 - 2004 Intel Corporation.
+
+  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.
+
+*/
+
+#ifndef B43legacy_RADIO_H_
+#define B43legacy_RADIO_H_
+
+#include "b43legacy.h"
+
+
+#define B43legacy_RADIO_DEFAULT_CHANNEL_BG	6
+
+/* Force antenna 0. */
+#define B43legacy_RADIO_TXANTENNA_0		0
+/* Force antenna 1. */
+#define B43legacy_RADIO_TXANTENNA_1		1
+/* Use the RX antenna, that was selected for the most recently
+ * received good PLCP header.
+ */
+#define B43legacy_RADIO_TXANTENNA_LASTPLCP	3
+#define B43legacy_RADIO_TXANTENNA_DEFAULT	B43legacy_RADIO_TXANTENNA_LASTPLCP
+
+#define B43legacy_RADIO_INTERFMODE_NONE		0
+#define B43legacy_RADIO_INTERFMODE_NONWLAN	1
+#define B43legacy_RADIO_INTERFMODE_MANUALWLAN	2
+#define B43legacy_RADIO_INTERFMODE_AUTOWLAN	3
+
+
+void b43legacy_radio_lock(struct b43legacy_wldev *dev);
+void b43legacy_radio_unlock(struct b43legacy_wldev *dev);
+
+u16 b43legacy_radio_read16(struct b43legacy_wldev *dev, u16 offset);
+void b43legacy_radio_write16(struct b43legacy_wldev *dev, u16 offset, u16 val);
+
+u16 b43legacy_radio_init2050(struct b43legacy_wldev *dev);
+
+void b43legacy_radio_turn_on(struct b43legacy_wldev *dev);
+void b43legacy_radio_turn_off(struct b43legacy_wldev *dev, bool force);
+
+int b43legacy_radio_selectchannel(struct b43legacy_wldev *dev, u8 channel,
+				  int synthetic_pu_workaround);
+
+void b43legacy_radio_set_txpower_a(struct b43legacy_wldev *dev, u16 txpower);
+void b43legacy_radio_set_txpower_bg(struct b43legacy_wldev *dev,
+				    u16 baseband_attenuation, u16 attenuation,
+				    u16 txpower);
+
+u16 b43legacy_default_baseband_attenuation(struct b43legacy_wldev *dev);
+u16 b43legacy_default_radio_attenuation(struct b43legacy_wldev *dev);
+u16 b43legacy_default_txctl1(struct b43legacy_wldev *dev);
+
+void b43legacy_radio_set_txantenna(struct b43legacy_wldev *dev, u32 val);
+
+void b43legacy_radio_clear_tssi(struct b43legacy_wldev *dev);
+
+u8 b43legacy_radio_aci_detect(struct b43legacy_wldev *dev, u8 channel);
+u8 b43legacy_radio_aci_scan(struct b43legacy_wldev *dev);
+
+int b43legacy_radio_set_interference_mitigation(struct b43legacy_wldev *dev,
+						int mode);
+
+void b43legacy_calc_nrssi_slope(struct b43legacy_wldev *dev);
+void b43legacy_calc_nrssi_threshold(struct b43legacy_wldev *dev);
+s16 b43legacy_nrssi_hw_read(struct b43legacy_wldev *dev, u16 offset);
+void b43legacy_nrssi_hw_write(struct b43legacy_wldev *dev, u16 offset, s16 val);
+void b43legacy_nrssi_hw_update(struct b43legacy_wldev *dev, u16 val);
+void b43legacy_nrssi_mem_update(struct b43legacy_wldev *dev);
+
+u16 b43legacy_radio_calibrationvalue(struct b43legacy_wldev *dev);
+
+#endif /* B43legacy_RADIO_H_ */
diff --git a/drivers/net/wireless/broadcom/b43legacy/rfkill.c b/drivers/net/wireless/broadcom/b43legacy/rfkill.c
new file mode 100644
index 0000000..7c1bdbc
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/rfkill.c
@@ -0,0 +1,91 @@
+/*
+
+  Broadcom B43 wireless driver
+  RFKILL support
+
+  Copyright (c) 2007 Michael Buesch <m@bues.ch>
+
+  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 "radio.h"
+#include "b43legacy.h"
+
+
+/* Returns TRUE, if the radio is enabled in hardware. */
+bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
+{
+	if (dev->dev->id.revision >= 3) {
+		if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI)
+		      & B43legacy_MMIO_RADIO_HWENABLED_HI_MASK))
+			return true;
+	} else {
+		/* To prevent CPU fault on PPC, do not read a register
+		 * unless the interface is started; however, on resume
+		 * for hibernation, this routine is entered early. When
+		 * that happens, unconditionally return TRUE.
+		 */
+		if (b43legacy_status(dev) < B43legacy_STAT_STARTED)
+			return true;
+		if (b43legacy_read16(dev, B43legacy_MMIO_RADIO_HWENABLED_LO)
+		    & B43legacy_MMIO_RADIO_HWENABLED_LO_MASK)
+			return true;
+	}
+	return false;
+}
+
+/* The poll callback for the hardware button. */
+void b43legacy_rfkill_poll(struct ieee80211_hw *hw)
+{
+	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
+	struct b43legacy_wldev *dev = wl->current_dev;
+	struct ssb_bus *bus = dev->dev->bus;
+	bool enabled;
+	bool brought_up = false;
+
+	mutex_lock(&wl->mutex);
+	if (unlikely(b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)) {
+		if (ssb_bus_powerup(bus, 0)) {
+			mutex_unlock(&wl->mutex);
+			return;
+		}
+		ssb_device_enable(dev->dev, 0);
+		brought_up = true;
+	}
+
+	enabled = b43legacy_is_hw_radio_enabled(dev);
+
+	if (unlikely(enabled != dev->radio_hw_enable)) {
+		dev->radio_hw_enable = enabled;
+		b43legacyinfo(wl, "Radio hardware status changed to %s\n",
+			enabled ? "ENABLED" : "DISABLED");
+		wiphy_rfkill_set_hw_state(hw->wiphy, !enabled);
+		if (enabled != dev->phy.radio_on) {
+			if (enabled)
+				b43legacy_radio_turn_on(dev);
+			else
+				b43legacy_radio_turn_off(dev, 0);
+		}
+	}
+
+	if (brought_up) {
+		ssb_device_disable(dev->dev, 0);
+		ssb_bus_may_powerdown(bus);
+	}
+
+	mutex_unlock(&wl->mutex);
+}
diff --git a/drivers/net/wireless/broadcom/b43legacy/rfkill.h b/drivers/net/wireless/broadcom/b43legacy/rfkill.h
new file mode 100644
index 0000000..7f314eb
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/rfkill.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43legacy_RFKILL_H_
+#define B43legacy_RFKILL_H_
+
+struct ieee80211_hw;
+struct b43legacy_wldev;
+
+void b43legacy_rfkill_poll(struct ieee80211_hw *hw);
+
+bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev);
+
+#endif /* B43legacy_RFKILL_H_ */
diff --git a/drivers/net/wireless/broadcom/b43legacy/sysfs.c b/drivers/net/wireless/broadcom/b43legacy/sysfs.c
new file mode 100644
index 0000000..2a1da15
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/sysfs.c
@@ -0,0 +1,238 @@
+/*
+
+  Broadcom B43legacy wireless driver
+
+  SYSFS support routines
+
+  Copyright (c) 2006 Michael Buesch <m@bues.ch>
+
+  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 "sysfs.h"
+#include "b43legacy.h"
+#include "main.h"
+#include "phy.h"
+#include "radio.h"
+
+#include <linux/capability.h>
+
+
+#define GENERIC_FILESIZE	64
+
+
+static int get_integer(const char *buf, size_t count)
+{
+	char tmp[10 + 1] = { 0 };
+	int ret = -EINVAL;
+
+	if (count == 0)
+		goto out;
+	count = min_t(size_t, count, 10);
+	memcpy(tmp, buf, count);
+	ret = simple_strtol(tmp, NULL, 10);
+out:
+	return ret;
+}
+
+static int get_boolean(const char *buf, size_t count)
+{
+	if (count != 0) {
+		if (buf[0] == '1')
+			return 1;
+		if (buf[0] == '0')
+			return 0;
+		if (count >= 4 && memcmp(buf, "true", 4) == 0)
+			return 1;
+		if (count >= 5 && memcmp(buf, "false", 5) == 0)
+			return 0;
+		if (count >= 3 && memcmp(buf, "yes", 3) == 0)
+			return 1;
+		if (count >= 2 && memcmp(buf, "no", 2) == 0)
+			return 0;
+		if (count >= 2 && memcmp(buf, "on", 2) == 0)
+			return 1;
+		if (count >= 3 && memcmp(buf, "off", 3) == 0)
+			return 0;
+	}
+	return -EINVAL;
+}
+
+static ssize_t b43legacy_attr_interfmode_show(struct device *dev,
+					      struct device_attribute *attr,
+					      char *buf)
+{
+	struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
+	ssize_t count = 0;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	mutex_lock(&wldev->wl->mutex);
+
+	switch (wldev->phy.interfmode) {
+	case B43legacy_INTERFMODE_NONE:
+		count = snprintf(buf, PAGE_SIZE, "0 (No Interference"
+				 " Mitigation)\n");
+		break;
+	case B43legacy_INTERFMODE_NONWLAN:
+		count = snprintf(buf, PAGE_SIZE, "1 (Non-WLAN Interference"
+				 " Mitigation)\n");
+		break;
+	case B43legacy_INTERFMODE_MANUALWLAN:
+		count = snprintf(buf, PAGE_SIZE, "2 (WLAN Interference"
+				 " Mitigation)\n");
+		break;
+	default:
+		B43legacy_WARN_ON(1);
+	}
+
+	mutex_unlock(&wldev->wl->mutex);
+
+	return count;
+}
+
+static ssize_t b43legacy_attr_interfmode_store(struct device *dev,
+					       struct device_attribute *attr,
+					       const char *buf, size_t count)
+{
+	struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
+	unsigned long flags;
+	int err;
+	int mode;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	mode = get_integer(buf, count);
+	switch (mode) {
+	case 0:
+		mode = B43legacy_INTERFMODE_NONE;
+		break;
+	case 1:
+		mode = B43legacy_INTERFMODE_NONWLAN;
+		break;
+	case 2:
+		mode = B43legacy_INTERFMODE_MANUALWLAN;
+		break;
+	case 3:
+		mode = B43legacy_INTERFMODE_AUTOWLAN;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	mutex_lock(&wldev->wl->mutex);
+	spin_lock_irqsave(&wldev->wl->irq_lock, flags);
+
+	err = b43legacy_radio_set_interference_mitigation(wldev, mode);
+	if (err)
+		b43legacyerr(wldev->wl, "Interference Mitigation not "
+		       "supported by device\n");
+	mmiowb();
+	spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
+	mutex_unlock(&wldev->wl->mutex);
+
+	return err ? err : count;
+}
+
+static DEVICE_ATTR(interference, 0644,
+		   b43legacy_attr_interfmode_show,
+		   b43legacy_attr_interfmode_store);
+
+static ssize_t b43legacy_attr_preamble_show(struct device *dev,
+					    struct device_attribute *attr,
+					    char *buf)
+{
+	struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
+	ssize_t count;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	mutex_lock(&wldev->wl->mutex);
+
+	if (wldev->short_preamble)
+		count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble"
+				 " enabled)\n");
+	else
+		count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble"
+				 " disabled)\n");
+
+	mutex_unlock(&wldev->wl->mutex);
+
+	return count;
+}
+
+static ssize_t b43legacy_attr_preamble_store(struct device *dev,
+					     struct device_attribute *attr,
+					     const char *buf, size_t count)
+{
+	struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev);
+	unsigned long flags;
+	int value;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	value = get_boolean(buf, count);
+	if (value < 0)
+		return value;
+	mutex_lock(&wldev->wl->mutex);
+	spin_lock_irqsave(&wldev->wl->irq_lock, flags);
+
+	wldev->short_preamble = !!value;
+
+	spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
+	mutex_unlock(&wldev->wl->mutex);
+
+	return count;
+}
+
+static DEVICE_ATTR(shortpreamble, 0644,
+		   b43legacy_attr_preamble_show,
+		   b43legacy_attr_preamble_store);
+
+int b43legacy_sysfs_register(struct b43legacy_wldev *wldev)
+{
+	struct device *dev = wldev->dev->dev;
+	int err;
+
+	B43legacy_WARN_ON(b43legacy_status(wldev) !=
+			  B43legacy_STAT_INITIALIZED);
+
+	err = device_create_file(dev, &dev_attr_interference);
+	if (err)
+		goto out;
+	err = device_create_file(dev, &dev_attr_shortpreamble);
+	if (err)
+		goto err_remove_interfmode;
+
+out:
+	return err;
+err_remove_interfmode:
+	device_remove_file(dev, &dev_attr_interference);
+	goto out;
+}
+
+void b43legacy_sysfs_unregister(struct b43legacy_wldev *wldev)
+{
+	struct device *dev = wldev->dev->dev;
+
+	device_remove_file(dev, &dev_attr_shortpreamble);
+	device_remove_file(dev, &dev_attr_interference);
+}
diff --git a/drivers/net/wireless/broadcom/b43legacy/sysfs.h b/drivers/net/wireless/broadcom/b43legacy/sysfs.h
new file mode 100644
index 0000000..ea9d783
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/sysfs.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43legacy_SYSFS_H_
+#define B43legacy_SYSFS_H_
+
+struct b43legacy_wldev;
+
+int b43legacy_sysfs_register(struct b43legacy_wldev *dev);
+void b43legacy_sysfs_unregister(struct b43legacy_wldev *dev);
+
+#endif /* B43legacy_SYSFS_H_ */
diff --git a/drivers/net/wireless/broadcom/b43legacy/xmit.c b/drivers/net/wireless/broadcom/b43legacy/xmit.c
new file mode 100644
index 0000000..35ccf40
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/xmit.c
@@ -0,0 +1,664 @@
+/*
+
+  Broadcom B43legacy wireless driver
+
+  Transmission (TX/RX) related functions.
+
+  Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
+  Copyright (C) 2005 Stefano Brivio <stefano.brivio@polimi.it>
+  Copyright (C) 2005, 2006 Michael Buesch <m@bues.ch>
+  Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
+  Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
+  Copyright (C) 2007 Larry Finger <Larry.Finger@lwfinger.net>
+
+  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 <net/dst.h>
+
+#include "xmit.h"
+#include "phy.h"
+#include "dma.h"
+#include "pio.h"
+
+
+/* Extract the bitrate out of a CCK PLCP header. */
+static u8 b43legacy_plcp_get_bitrate_idx_cck(struct b43legacy_plcp_hdr6 *plcp)
+{
+	switch (plcp->raw[0]) {
+	case 0x0A:
+		return 0;
+	case 0x14:
+		return 1;
+	case 0x37:
+		return 2;
+	case 0x6E:
+		return 3;
+	}
+	B43legacy_BUG_ON(1);
+	return -1;
+}
+
+/* Extract the bitrate out of an OFDM PLCP header. */
+static u8 b43legacy_plcp_get_bitrate_idx_ofdm(struct b43legacy_plcp_hdr6 *plcp,
+					      bool aphy)
+{
+	int base = aphy ? 0 : 4;
+
+	switch (plcp->raw[0] & 0xF) {
+	case 0xB:
+		return base + 0;
+	case 0xF:
+		return base + 1;
+	case 0xA:
+		return base + 2;
+	case 0xE:
+		return base + 3;
+	case 0x9:
+		return base + 4;
+	case 0xD:
+		return base + 5;
+	case 0x8:
+		return base + 6;
+	case 0xC:
+		return base + 7;
+	}
+	B43legacy_BUG_ON(1);
+	return -1;
+}
+
+u8 b43legacy_plcp_get_ratecode_cck(const u8 bitrate)
+{
+	switch (bitrate) {
+	case B43legacy_CCK_RATE_1MB:
+		return 0x0A;
+	case B43legacy_CCK_RATE_2MB:
+		return 0x14;
+	case B43legacy_CCK_RATE_5MB:
+		return 0x37;
+	case B43legacy_CCK_RATE_11MB:
+		return 0x6E;
+	}
+	B43legacy_BUG_ON(1);
+	return 0;
+}
+
+u8 b43legacy_plcp_get_ratecode_ofdm(const u8 bitrate)
+{
+	switch (bitrate) {
+	case B43legacy_OFDM_RATE_6MB:
+		return 0xB;
+	case B43legacy_OFDM_RATE_9MB:
+		return 0xF;
+	case B43legacy_OFDM_RATE_12MB:
+		return 0xA;
+	case B43legacy_OFDM_RATE_18MB:
+		return 0xE;
+	case B43legacy_OFDM_RATE_24MB:
+		return 0x9;
+	case B43legacy_OFDM_RATE_36MB:
+		return 0xD;
+	case B43legacy_OFDM_RATE_48MB:
+		return 0x8;
+	case B43legacy_OFDM_RATE_54MB:
+		return 0xC;
+	}
+	B43legacy_BUG_ON(1);
+	return 0;
+}
+
+void b43legacy_generate_plcp_hdr(struct b43legacy_plcp_hdr4 *plcp,
+				 const u16 octets, const u8 bitrate)
+{
+	__le32 *data = &(plcp->data);
+	__u8 *raw = plcp->raw;
+
+	if (b43legacy_is_ofdm_rate(bitrate)) {
+		u16 d;
+
+		d = b43legacy_plcp_get_ratecode_ofdm(bitrate);
+		B43legacy_WARN_ON(octets & 0xF000);
+		d |= (octets << 5);
+		*data = cpu_to_le32(d);
+	} else {
+		u32 plen;
+
+		plen = octets * 16 / bitrate;
+		if ((octets * 16 % bitrate) > 0) {
+			plen++;
+			if ((bitrate == B43legacy_CCK_RATE_11MB)
+			    && ((octets * 8 % 11) < 4))
+				raw[1] = 0x84;
+			else
+				raw[1] = 0x04;
+		} else
+			raw[1] = 0x04;
+		*data |= cpu_to_le32(plen << 16);
+		raw[0] = b43legacy_plcp_get_ratecode_cck(bitrate);
+	}
+}
+
+static u8 b43legacy_calc_fallback_rate(u8 bitrate)
+{
+	switch (bitrate) {
+	case B43legacy_CCK_RATE_1MB:
+		return B43legacy_CCK_RATE_1MB;
+	case B43legacy_CCK_RATE_2MB:
+		return B43legacy_CCK_RATE_1MB;
+	case B43legacy_CCK_RATE_5MB:
+		return B43legacy_CCK_RATE_2MB;
+	case B43legacy_CCK_RATE_11MB:
+		return B43legacy_CCK_RATE_5MB;
+	case B43legacy_OFDM_RATE_6MB:
+		return B43legacy_CCK_RATE_5MB;
+	case B43legacy_OFDM_RATE_9MB:
+		return B43legacy_OFDM_RATE_6MB;
+	case B43legacy_OFDM_RATE_12MB:
+		return B43legacy_OFDM_RATE_9MB;
+	case B43legacy_OFDM_RATE_18MB:
+		return B43legacy_OFDM_RATE_12MB;
+	case B43legacy_OFDM_RATE_24MB:
+		return B43legacy_OFDM_RATE_18MB;
+	case B43legacy_OFDM_RATE_36MB:
+		return B43legacy_OFDM_RATE_24MB;
+	case B43legacy_OFDM_RATE_48MB:
+		return B43legacy_OFDM_RATE_36MB;
+	case B43legacy_OFDM_RATE_54MB:
+		return B43legacy_OFDM_RATE_48MB;
+	}
+	B43legacy_BUG_ON(1);
+	return 0;
+}
+
+static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
+			       struct b43legacy_txhdr_fw3 *txhdr,
+			       const unsigned char *fragment_data,
+			       unsigned int fragment_len,
+			       struct ieee80211_tx_info *info,
+			       u16 cookie)
+{
+	const struct ieee80211_hdr *wlhdr;
+	int use_encryption = !!info->control.hw_key;
+	u8 rate;
+	struct ieee80211_rate *rate_fb;
+	int rate_ofdm;
+	int rate_fb_ofdm;
+	unsigned int plcp_fragment_len;
+	u32 mac_ctl = 0;
+	u16 phy_ctl = 0;
+	struct ieee80211_rate *tx_rate;
+	struct ieee80211_tx_rate *rates;
+
+	wlhdr = (const struct ieee80211_hdr *)fragment_data;
+
+	memset(txhdr, 0, sizeof(*txhdr));
+
+	tx_rate = ieee80211_get_tx_rate(dev->wl->hw, info);
+
+	rate = tx_rate->hw_value;
+	rate_ofdm = b43legacy_is_ofdm_rate(rate);
+	rate_fb = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : tx_rate;
+	rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value);
+
+	txhdr->mac_frame_ctl = wlhdr->frame_control;
+	memcpy(txhdr->tx_receiver, wlhdr->addr1, ETH_ALEN);
+
+	/* Calculate duration for fallback rate */
+	if ((rate_fb->hw_value == rate) ||
+	    (wlhdr->duration_id & cpu_to_le16(0x8000)) ||
+	    (wlhdr->duration_id == cpu_to_le16(0))) {
+		/* If the fallback rate equals the normal rate or the
+		 * dur_id field contains an AID, CFP magic or 0,
+		 * use the original dur_id field. */
+		txhdr->dur_fb = wlhdr->duration_id;
+	} else {
+		txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
+							 info->control.vif,
+							 info->band,
+							 fragment_len,
+							 rate_fb);
+	}
+
+	plcp_fragment_len = fragment_len + FCS_LEN;
+	if (use_encryption) {
+		u8 key_idx = info->control.hw_key->hw_key_idx;
+		struct b43legacy_key *key;
+		int wlhdr_len;
+		size_t iv_len;
+
+		B43legacy_WARN_ON(key_idx >= dev->max_nr_keys);
+		key = &(dev->key[key_idx]);
+
+		if (key->enabled) {
+			/* Hardware appends ICV. */
+			plcp_fragment_len += info->control.hw_key->icv_len;
+
+			key_idx = b43legacy_kidx_to_fw(dev, key_idx);
+			mac_ctl |= (key_idx << B43legacy_TX4_MAC_KEYIDX_SHIFT) &
+				   B43legacy_TX4_MAC_KEYIDX;
+			mac_ctl |= (key->algorithm <<
+				   B43legacy_TX4_MAC_KEYALG_SHIFT) &
+				   B43legacy_TX4_MAC_KEYALG;
+			wlhdr_len = ieee80211_hdrlen(wlhdr->frame_control);
+			iv_len = min_t(size_t, info->control.hw_key->iv_len,
+				     ARRAY_SIZE(txhdr->iv));
+			memcpy(txhdr->iv, ((u8 *)wlhdr) + wlhdr_len, iv_len);
+		} else {
+			/* This key is invalid. This might only happen
+			 * in a short timeframe after machine resume before
+			 * we were able to reconfigure keys.
+			 * Drop this packet completely. Do not transmit it
+			 * unencrypted to avoid leaking information. */
+			return -ENOKEY;
+		}
+	}
+	b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *)
+				    (&txhdr->plcp), plcp_fragment_len,
+				    rate);
+	b43legacy_generate_plcp_hdr(&txhdr->plcp_fb, plcp_fragment_len,
+				    rate_fb->hw_value);
+
+	/* PHY TX Control word */
+	if (rate_ofdm)
+		phy_ctl |= B43legacy_TX4_PHY_ENC_OFDM;
+	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+		phy_ctl |= B43legacy_TX4_PHY_SHORTPRMBL;
+	phy_ctl |= B43legacy_TX4_PHY_ANTLAST;
+
+	/* MAC control */
+	rates = info->control.rates;
+	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
+		mac_ctl |= B43legacy_TX4_MAC_ACK;
+	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
+		mac_ctl |= B43legacy_TX4_MAC_HWSEQ;
+	if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
+		mac_ctl |= B43legacy_TX4_MAC_STMSDU;
+	if (rate_fb_ofdm)
+		mac_ctl |= B43legacy_TX4_MAC_FALLBACKOFDM;
+
+	/* Overwrite rates[0].count to make the retry calculation
+	 * in the tx status easier. need the actual retry limit to
+	 * detect whether the fallback rate was used.
+	 */
+	if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
+	    (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) {
+		rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count;
+		mac_ctl |= B43legacy_TX4_MAC_LONGFRAME;
+	} else {
+		rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count;
+	}
+
+	/* Generate the RTS or CTS-to-self frame */
+	if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
+	    (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) {
+		unsigned int len;
+		struct ieee80211_hdr *hdr;
+		int rts_rate;
+		int rts_rate_fb;
+		int rts_rate_fb_ofdm;
+
+		rts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info)->hw_value;
+		rts_rate_fb = b43legacy_calc_fallback_rate(rts_rate);
+		rts_rate_fb_ofdm = b43legacy_is_ofdm_rate(rts_rate_fb);
+		if (rts_rate_fb_ofdm)
+			mac_ctl |= B43legacy_TX4_MAC_CTSFALLBACKOFDM;
+
+		if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
+			ieee80211_ctstoself_get(dev->wl->hw,
+						info->control.vif,
+						fragment_data,
+						fragment_len, info,
+						(struct ieee80211_cts *)
+						(txhdr->rts_frame));
+			mac_ctl |= B43legacy_TX4_MAC_SENDCTS;
+			len = sizeof(struct ieee80211_cts);
+		} else {
+			ieee80211_rts_get(dev->wl->hw,
+					  info->control.vif,
+					  fragment_data, fragment_len, info,
+					  (struct ieee80211_rts *)
+					  (txhdr->rts_frame));
+			mac_ctl |= B43legacy_TX4_MAC_SENDRTS;
+			len = sizeof(struct ieee80211_rts);
+		}
+		len += FCS_LEN;
+		b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *)
+					    (&txhdr->rts_plcp),
+					    len, rts_rate);
+		b43legacy_generate_plcp_hdr(&txhdr->rts_plcp_fb,
+					    len, rts_rate_fb);
+		hdr = (struct ieee80211_hdr *)(&txhdr->rts_frame);
+		txhdr->rts_dur_fb = hdr->duration_id;
+	}
+
+	/* Magic cookie */
+	txhdr->cookie = cpu_to_le16(cookie);
+
+	/* Apply the bitfields */
+	txhdr->mac_ctl = cpu_to_le32(mac_ctl);
+	txhdr->phy_ctl = cpu_to_le16(phy_ctl);
+
+	return 0;
+}
+
+int b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
+			      u8 *txhdr,
+			      const unsigned char *fragment_data,
+			      unsigned int fragment_len,
+			      struct ieee80211_tx_info *info,
+			      u16 cookie)
+{
+	return generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr,
+			   fragment_data, fragment_len,
+			   info, cookie);
+}
+
+static s8 b43legacy_rssi_postprocess(struct b43legacy_wldev *dev,
+				     u8 in_rssi, int ofdm,
+				     int adjust_2053, int adjust_2050)
+{
+	struct b43legacy_phy *phy = &dev->phy;
+	s32 tmp;
+
+	switch (phy->radio_ver) {
+	case 0x2050:
+		if (ofdm) {
+			tmp = in_rssi;
+			if (tmp > 127)
+				tmp -= 256;
+			tmp *= 73;
+			tmp /= 64;
+			if (adjust_2050)
+				tmp += 25;
+			else
+				tmp -= 3;
+		} else {
+			if (dev->dev->bus->sprom.boardflags_lo
+			    & B43legacy_BFL_RSSI) {
+				if (in_rssi > 63)
+					in_rssi = 63;
+				tmp = phy->nrssi_lt[in_rssi];
+				tmp = 31 - tmp;
+				tmp *= -131;
+				tmp /= 128;
+				tmp -= 57;
+			} else {
+				tmp = in_rssi;
+				tmp = 31 - tmp;
+				tmp *= -149;
+				tmp /= 128;
+				tmp -= 68;
+			}
+			if (phy->type == B43legacy_PHYTYPE_G &&
+			    adjust_2050)
+				tmp += 25;
+		}
+		break;
+	case 0x2060:
+		if (in_rssi > 127)
+			tmp = in_rssi - 256;
+		else
+			tmp = in_rssi;
+		break;
+	default:
+		tmp = in_rssi;
+		tmp -= 11;
+		tmp *= 103;
+		tmp /= 64;
+		if (adjust_2053)
+			tmp -= 109;
+		else
+			tmp -= 83;
+	}
+
+	return (s8)tmp;
+}
+
+void b43legacy_rx(struct b43legacy_wldev *dev,
+		  struct sk_buff *skb,
+		  const void *_rxhdr)
+{
+	struct ieee80211_rx_status status;
+	struct b43legacy_plcp_hdr6 *plcp;
+	struct ieee80211_hdr *wlhdr;
+	const struct b43legacy_rxhdr_fw3 *rxhdr = _rxhdr;
+	__le16 fctl;
+	u16 phystat0;
+	u16 phystat3;
+	u16 chanstat;
+	u16 mactime;
+	u32 macstat;
+	u16 chanid;
+	u8 jssi;
+	int padding;
+
+	memset(&status, 0, sizeof(status));
+
+	/* Get metadata about the frame from the header. */
+	phystat0 = le16_to_cpu(rxhdr->phy_status0);
+	phystat3 = le16_to_cpu(rxhdr->phy_status3);
+	jssi = rxhdr->jssi;
+	macstat = le16_to_cpu(rxhdr->mac_status);
+	mactime = le16_to_cpu(rxhdr->mac_time);
+	chanstat = le16_to_cpu(rxhdr->channel);
+
+	if (macstat & B43legacy_RX_MAC_FCSERR)
+		dev->wl->ieee_stats.dot11FCSErrorCount++;
+
+	/* Skip PLCP and padding */
+	padding = (macstat & B43legacy_RX_MAC_PADDING) ? 2 : 0;
+	if (unlikely(skb->len < (sizeof(struct b43legacy_plcp_hdr6) +
+	    padding))) {
+		b43legacydbg(dev->wl, "RX: Packet size underrun (1)\n");
+		goto drop;
+	}
+	plcp = (struct b43legacy_plcp_hdr6 *)(skb->data + padding);
+	skb_pull(skb, sizeof(struct b43legacy_plcp_hdr6) + padding);
+	/* The skb contains the Wireless Header + payload data now */
+	if (unlikely(skb->len < (2+2+6/*minimum hdr*/ + FCS_LEN))) {
+		b43legacydbg(dev->wl, "RX: Packet size underrun (2)\n");
+		goto drop;
+	}
+	wlhdr = (struct ieee80211_hdr *)(skb->data);
+	fctl = wlhdr->frame_control;
+
+	if ((macstat & B43legacy_RX_MAC_DEC) &&
+	    !(macstat & B43legacy_RX_MAC_DECERR)) {
+		unsigned int keyidx;
+		int wlhdr_len;
+		int iv_len;
+		int icv_len;
+
+		keyidx = ((macstat & B43legacy_RX_MAC_KEYIDX)
+			  >> B43legacy_RX_MAC_KEYIDX_SHIFT);
+		/* We must adjust the key index here. We want the "physical"
+		 * key index, but the ucode passed it slightly different.
+		 */
+		keyidx = b43legacy_kidx_to_raw(dev, keyidx);
+		B43legacy_WARN_ON(keyidx >= dev->max_nr_keys);
+
+		if (dev->key[keyidx].algorithm != B43legacy_SEC_ALGO_NONE) {
+			/* Remove PROTECTED flag to mark it as decrypted. */
+			B43legacy_WARN_ON(!ieee80211_has_protected(fctl));
+			fctl &= ~cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+			wlhdr->frame_control = fctl;
+
+			wlhdr_len = ieee80211_hdrlen(fctl);
+			if (unlikely(skb->len < (wlhdr_len + 3))) {
+				b43legacydbg(dev->wl, "RX: Packet size"
+					     " underrun3\n");
+				goto drop;
+			}
+			if (skb->data[wlhdr_len + 3] & (1 << 5)) {
+				/* The Ext-IV Bit is set in the "KeyID"
+				 * octet of the IV.
+				 */
+				iv_len = 8;
+				icv_len = 8;
+			} else {
+				iv_len = 4;
+				icv_len = 4;
+			}
+			if (unlikely(skb->len < (wlhdr_len + iv_len +
+			    icv_len))) {
+				b43legacydbg(dev->wl, "RX: Packet size"
+					     " underrun4\n");
+				goto drop;
+			}
+			/* Remove the IV */
+			memmove(skb->data + iv_len, skb->data, wlhdr_len);
+			skb_pull(skb, iv_len);
+			/* Remove the ICV */
+			skb_trim(skb, skb->len - icv_len);
+
+			status.flag |= RX_FLAG_DECRYPTED;
+		}
+	}
+
+	status.signal = b43legacy_rssi_postprocess(dev, jssi,
+				      (phystat0 & B43legacy_RX_PHYST0_OFDM),
+				      (phystat0 & B43legacy_RX_PHYST0_GAINCTL),
+				      (phystat3 & B43legacy_RX_PHYST3_TRSTATE));
+	/* change to support A PHY */
+	if (phystat0 & B43legacy_RX_PHYST0_OFDM)
+		status.rate_idx = b43legacy_plcp_get_bitrate_idx_ofdm(plcp, false);
+	else
+		status.rate_idx = b43legacy_plcp_get_bitrate_idx_cck(plcp);
+	status.antenna = !!(phystat0 & B43legacy_RX_PHYST0_ANT);
+
+	/*
+	 * All frames on monitor interfaces and beacons always need a full
+	 * 64-bit timestamp. Monitor interfaces need it for diagnostic
+	 * purposes and beacons for IBSS merging.
+	 * This code assumes we get to process the packet within 16 bits
+	 * of timestamp, i.e. about 65 milliseconds after the PHY received
+	 * the first symbol.
+	 */
+	if (ieee80211_is_beacon(fctl) || dev->wl->radiotap_enabled) {
+		u16 low_mactime_now;
+
+		b43legacy_tsf_read(dev, &status.mactime);
+		low_mactime_now = status.mactime;
+		status.mactime = status.mactime & ~0xFFFFULL;
+		status.mactime += mactime;
+		if (low_mactime_now <= mactime)
+			status.mactime -= 0x10000;
+		status.flag |= RX_FLAG_MACTIME_START;
+	}
+
+	chanid = (chanstat & B43legacy_RX_CHAN_ID) >>
+		  B43legacy_RX_CHAN_ID_SHIFT;
+	switch (chanstat & B43legacy_RX_CHAN_PHYTYPE) {
+	case B43legacy_PHYTYPE_B:
+	case B43legacy_PHYTYPE_G:
+		status.band = NL80211_BAND_2GHZ;
+		status.freq = chanid + 2400;
+		break;
+	default:
+		b43legacywarn(dev->wl, "Unexpected value for chanstat (0x%X)\n",
+		       chanstat);
+	}
+
+	memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
+	ieee80211_rx_irqsafe(dev->wl->hw, skb);
+
+	return;
+drop:
+	b43legacydbg(dev->wl, "RX: Packet dropped\n");
+	dev_kfree_skb_any(skb);
+}
+
+void b43legacy_handle_txstatus(struct b43legacy_wldev *dev,
+			     const struct b43legacy_txstatus *status)
+{
+	b43legacy_debugfs_log_txstat(dev, status);
+
+	if (status->intermediate)
+		return;
+	if (status->for_ampdu)
+		return;
+	if (!status->acked)
+		dev->wl->ieee_stats.dot11ACKFailureCount++;
+	if (status->rts_count) {
+		if (status->rts_count == 0xF) /* FIXME */
+			dev->wl->ieee_stats.dot11RTSFailureCount++;
+		else
+			dev->wl->ieee_stats.dot11RTSSuccessCount++;
+	}
+
+	if (b43legacy_using_pio(dev))
+		b43legacy_pio_handle_txstatus(dev, status);
+	else
+		b43legacy_dma_handle_txstatus(dev, status);
+}
+
+/* Handle TX status report as received through DMA/PIO queues */
+void b43legacy_handle_hwtxstatus(struct b43legacy_wldev *dev,
+				 const struct b43legacy_hwtxstatus *hw)
+{
+	struct b43legacy_txstatus status;
+	u8 tmp;
+
+	status.cookie = le16_to_cpu(hw->cookie);
+	status.seq = le16_to_cpu(hw->seq);
+	status.phy_stat = hw->phy_stat;
+	tmp = hw->count;
+	status.frame_count = (tmp >> 4);
+	status.rts_count = (tmp & 0x0F);
+	tmp = hw->flags << 1;
+	status.supp_reason = ((tmp & 0x1C) >> 2);
+	status.pm_indicated = !!(tmp & 0x80);
+	status.intermediate = !!(tmp & 0x40);
+	status.for_ampdu = !!(tmp & 0x20);
+	status.acked = !!(tmp & 0x02);
+
+	b43legacy_handle_txstatus(dev, &status);
+}
+
+/* Stop any TX operation on the device (suspend the hardware queues) */
+void b43legacy_tx_suspend(struct b43legacy_wldev *dev)
+{
+	if (b43legacy_using_pio(dev))
+		b43legacy_pio_freeze_txqueues(dev);
+	else
+		b43legacy_dma_tx_suspend(dev);
+}
+
+/* Resume any TX operation on the device (resume the hardware queues) */
+void b43legacy_tx_resume(struct b43legacy_wldev *dev)
+{
+	if (b43legacy_using_pio(dev))
+		b43legacy_pio_thaw_txqueues(dev);
+	else
+		b43legacy_dma_tx_resume(dev);
+}
+
+/* Initialize the QoS parameters */
+void b43legacy_qos_init(struct b43legacy_wldev *dev)
+{
+	/* FIXME: This function must probably be called from the mac80211
+	 * config callback. */
+return;
+
+	b43legacy_hf_write(dev, b43legacy_hf_read(dev) | B43legacy_HF_EDCF);
+	/* FIXME kill magic */
+	b43legacy_write16(dev, 0x688,
+			  b43legacy_read16(dev, 0x688) | 0x4);
+
+
+	/*TODO: We might need some stack support here to get the values. */
+}
diff --git a/drivers/net/wireless/broadcom/b43legacy/xmit.h b/drivers/net/wireless/broadcom/b43legacy/xmit.h
new file mode 100644
index 0000000..e4ef869
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43legacy/xmit.h
@@ -0,0 +1,262 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43legacy_XMIT_H_
+#define B43legacy_XMIT_H_
+
+#include "main.h"
+
+
+#define _b43legacy_declare_plcp_hdr(size)	\
+	struct b43legacy_plcp_hdr##size {	\
+		union {				\
+			__le32 data;		\
+			__u8 raw[size];		\
+		} __packed;	\
+	} __packed
+
+/* struct b43legacy_plcp_hdr4 */
+_b43legacy_declare_plcp_hdr(4);
+/* struct b43legacy_plcp_hdr6 */
+_b43legacy_declare_plcp_hdr(6);
+
+#undef _b43legacy_declare_plcp_hdr
+
+
+/* TX header for v3 firmware */
+struct b43legacy_txhdr_fw3 {
+	__le32 mac_ctl;				/* MAC TX control */
+	__le16 mac_frame_ctl;			/* Copy of the FrameControl */
+	__le16 tx_fes_time_norm;		/* TX FES Time Normal */
+	__le16 phy_ctl;				/* PHY TX control */
+	__u8 iv[16];				/* Encryption IV */
+	__u8 tx_receiver[6];			/* TX Frame Receiver address */
+	__le16 tx_fes_time_fb;			/* TX FES Time Fallback */
+	struct b43legacy_plcp_hdr4 rts_plcp_fb;	/* RTS fallback PLCP */
+	__le16 rts_dur_fb;			/* RTS fallback duration */
+	struct b43legacy_plcp_hdr4 plcp_fb;	/* Fallback PLCP */
+	__le16 dur_fb;				/* Fallback duration */
+	PAD_BYTES(2);
+	__le16 cookie;
+	__le16 unknown_scb_stuff;
+	struct b43legacy_plcp_hdr6 rts_plcp;	/* RTS PLCP */
+	__u8 rts_frame[18];			/* The RTS frame (if used) */
+	struct b43legacy_plcp_hdr6 plcp;
+} __packed;
+
+/* MAC TX control */
+#define B43legacy_TX4_MAC_KEYIDX	0x0FF00000 /* Security key index */
+#define B43legacy_TX4_MAC_KEYIDX_SHIFT	20
+#define B43legacy_TX4_MAC_KEYALG	0x00070000 /* Security key algorithm */
+#define B43legacy_TX4_MAC_KEYALG_SHIFT	16
+#define B43legacy_TX4_MAC_LIFETIME	0x00001000
+#define B43legacy_TX4_MAC_FRAMEBURST	0x00000800
+#define B43legacy_TX4_MAC_SENDCTS	0x00000400
+#define B43legacy_TX4_MAC_AMPDU		0x00000300
+#define B43legacy_TX4_MAC_AMPDU_SHIFT	8
+#define B43legacy_TX4_MAC_CTSFALLBACKOFDM	0x00000200
+#define B43legacy_TX4_MAC_FALLBACKOFDM	0x00000100
+#define B43legacy_TX4_MAC_5GHZ		0x00000080
+#define B43legacy_TX4_MAC_IGNPMQ	0x00000020
+#define B43legacy_TX4_MAC_HWSEQ		0x00000010 /* Use Hardware Seq No */
+#define B43legacy_TX4_MAC_STMSDU	0x00000008 /* Start MSDU */
+#define B43legacy_TX4_MAC_SENDRTS	0x00000004
+#define B43legacy_TX4_MAC_LONGFRAME	0x00000002
+#define B43legacy_TX4_MAC_ACK		0x00000001
+
+/* Extra Frame Types */
+#define B43legacy_TX4_EFT_FBOFDM	0x0001 /* Data frame fb rate type */
+#define B43legacy_TX4_EFT_RTSOFDM	0x0004 /* RTS/CTS rate type */
+#define B43legacy_TX4_EFT_RTSFBOFDM	0x0010 /* RTS/CTS fallback rate type */
+
+/* PHY TX control word */
+#define B43legacy_TX4_PHY_ENC		0x0003 /* Data frame encoding */
+#define B43legacy_TX4_PHY_ENC_CCK	0x0000 /* CCK */
+#define B43legacy_TX4_PHY_ENC_OFDM	0x0001 /* Data frame rate type */
+#define B43legacy_TX4_PHY_SHORTPRMBL	0x0010 /* Use short preamble */
+#define B43legacy_TX4_PHY_ANT		0x03C0 /* Antenna selection */
+#define  B43legacy_TX4_PHY_ANT0		0x0000 /* Use antenna 0 */
+#define  B43legacy_TX4_PHY_ANT1		0x0100 /* Use antenna 1 */
+#define  B43legacy_TX4_PHY_ANTLAST	0x0300 /* Use last used antenna */
+
+
+
+int b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
+			      u8 *txhdr,
+			      const unsigned char *fragment_data,
+			      unsigned int fragment_len,
+			      struct ieee80211_tx_info *info,
+			      u16 cookie);
+
+
+/* Transmit Status */
+struct b43legacy_txstatus {
+	u16 cookie;	/* The cookie from the txhdr */
+	u16 seq;	/* Sequence number */
+	u8 phy_stat;	/* PHY TX status */
+	u8 frame_count;	/* Frame transmit count */
+	u8 rts_count;	/* RTS transmit count */
+	u8 supp_reason;	/* Suppression reason */
+	/* flags */
+	u8 pm_indicated;/* PM mode indicated to AP */
+	u8 intermediate;/* Intermediate status notification */
+	u8 for_ampdu;	/* Status is for an AMPDU (afterburner) */
+	u8 acked;	/* Wireless ACK received */
+};
+
+/* txstatus supp_reason values */
+enum {
+	B43legacy_TXST_SUPP_NONE,	/* Not suppressed */
+	B43legacy_TXST_SUPP_PMQ,	/* Suppressed due to PMQ entry */
+	B43legacy_TXST_SUPP_FLUSH,	/* Suppressed due to flush request */
+	B43legacy_TXST_SUPP_PREV,	/* Previous fragment failed */
+	B43legacy_TXST_SUPP_CHAN,	/* Channel mismatch */
+	B43legacy_TXST_SUPP_LIFE,	/* Lifetime expired */
+	B43legacy_TXST_SUPP_UNDER,	/* Buffer underflow */
+	B43legacy_TXST_SUPP_ABNACK,	/* Afterburner NACK */
+};
+
+/* Transmit Status as received through DMA/PIO on old chips */
+struct b43legacy_hwtxstatus {
+	PAD_BYTES(4);
+	__le16 cookie;
+	u8 flags;
+	u8 count;
+	PAD_BYTES(2);
+	__le16 seq;
+	u8 phy_stat;
+	PAD_BYTES(1);
+} __packed;
+
+
+/* Receive header for v3 firmware. */
+struct b43legacy_rxhdr_fw3 {
+	__le16 frame_len;	/* Frame length */
+	PAD_BYTES(2);
+	__le16 phy_status0;	/* PHY RX Status 0 */
+	__u8 jssi;		/* PHY RX Status 1: JSSI */
+	__u8 sig_qual;		/* PHY RX Status 1: Signal Quality */
+	PAD_BYTES(2);		/* PHY RX Status 2 */
+	__le16 phy_status3;	/* PHY RX Status 3 */
+	__le16 mac_status;	/* MAC RX status */
+	__le16 mac_time;
+	__le16 channel;
+} __packed;
+
+
+/* PHY RX Status 0 */
+#define B43legacy_RX_PHYST0_GAINCTL	0x4000 /* Gain Control */
+#define B43legacy_RX_PHYST0_PLCPHCF	0x0200
+#define B43legacy_RX_PHYST0_PLCPFV	0x0100
+#define B43legacy_RX_PHYST0_SHORTPRMBL	0x0080 /* Recvd with Short Preamble */
+#define B43legacy_RX_PHYST0_LCRS	0x0040
+#define B43legacy_RX_PHYST0_ANT		0x0020 /* Antenna */
+#define B43legacy_RX_PHYST0_UNSRATE	0x0010
+#define B43legacy_RX_PHYST0_CLIP	0x000C
+#define B43legacy_RX_PHYST0_CLIP_SHIFT	2
+#define B43legacy_RX_PHYST0_FTYPE	0x0003 /* Frame type */
+#define  B43legacy_RX_PHYST0_CCK	0x0000 /* Frame type: CCK */
+#define  B43legacy_RX_PHYST0_OFDM	0x0001 /* Frame type: OFDM */
+#define  B43legacy_RX_PHYST0_PRE_N	0x0002 /* Pre-standard N-PHY frame */
+#define  B43legacy_RX_PHYST0_STD_N	0x0003 /* Standard N-PHY frame */
+
+/* PHY RX Status 2 */
+#define B43legacy_RX_PHYST2_LNAG	0xC000 /* LNA Gain */
+#define B43legacy_RX_PHYST2_LNAG_SHIFT	14
+#define B43legacy_RX_PHYST2_PNAG	0x3C00 /* PNA Gain */
+#define B43legacy_RX_PHYST2_PNAG_SHIFT	10
+#define B43legacy_RX_PHYST2_FOFF	0x03FF /* F offset */
+
+/* PHY RX Status 3 */
+#define B43legacy_RX_PHYST3_DIGG	0x1800 /* DIG Gain */
+#define B43legacy_RX_PHYST3_DIGG_SHIFT	11
+#define B43legacy_RX_PHYST3_TRSTATE	0x0400 /* TR state */
+
+/* MAC RX Status */
+#define B43legacy_RX_MAC_BEACONSENT	0x00008000 /* Beacon send flag */
+#define B43legacy_RX_MAC_KEYIDX		0x000007E0 /* Key index */
+#define B43legacy_RX_MAC_KEYIDX_SHIFT	5
+#define B43legacy_RX_MAC_DECERR		0x00000010 /* Decrypt error */
+#define B43legacy_RX_MAC_DEC		0x00000008 /* Decryption attempted */
+#define B43legacy_RX_MAC_PADDING	0x00000004 /* Pad bytes present */
+#define B43legacy_RX_MAC_RESP		0x00000002 /* Response frame xmitted */
+#define B43legacy_RX_MAC_FCSERR		0x00000001 /* FCS error */
+
+/* RX channel */
+#define B43legacy_RX_CHAN_GAIN		0xFC00 /* Gain */
+#define B43legacy_RX_CHAN_GAIN_SHIFT	10
+#define B43legacy_RX_CHAN_ID		0x03FC /* Channel ID */
+#define B43legacy_RX_CHAN_ID_SHIFT	2
+#define B43legacy_RX_CHAN_PHYTYPE	0x0003 /* PHY type */
+
+
+
+u8 b43legacy_plcp_get_ratecode_cck(const u8 bitrate);
+u8 b43legacy_plcp_get_ratecode_ofdm(const u8 bitrate);
+
+void b43legacy_generate_plcp_hdr(struct b43legacy_plcp_hdr4 *plcp,
+			       const u16 octets, const u8 bitrate);
+
+void b43legacy_rx(struct b43legacy_wldev *dev,
+		struct sk_buff *skb,
+		const void *_rxhdr);
+
+void b43legacy_handle_txstatus(struct b43legacy_wldev *dev,
+			       const struct b43legacy_txstatus *status);
+
+void b43legacy_handle_hwtxstatus(struct b43legacy_wldev *dev,
+				 const struct b43legacy_hwtxstatus *hw);
+
+void b43legacy_tx_suspend(struct b43legacy_wldev *dev);
+void b43legacy_tx_resume(struct b43legacy_wldev *dev);
+
+
+#define B43legacy_NR_QOSPARMS	22
+enum {
+	B43legacy_QOSPARM_TXOP = 0,
+	B43legacy_QOSPARM_CWMIN,
+	B43legacy_QOSPARM_CWMAX,
+	B43legacy_QOSPARM_CWCUR,
+	B43legacy_QOSPARM_AIFS,
+	B43legacy_QOSPARM_BSLOTS,
+	B43legacy_QOSPARM_REGGAP,
+	B43legacy_QOSPARM_STATUS,
+};
+
+void b43legacy_qos_init(struct b43legacy_wldev *dev);
+
+
+/* Helper functions for converting the key-table index from "firmware-format"
+ * to "raw-format" and back. The firmware API changed for this at some revision.
+ * We need to account for that here. */
+static inline
+int b43legacy_new_kidx_api(struct b43legacy_wldev *dev)
+{
+	/* FIXME: Not sure the change was at rev 351 */
+	return (dev->fw.rev >= 351);
+}
+static inline
+u8 b43legacy_kidx_to_fw(struct b43legacy_wldev *dev, u8 raw_kidx)
+{
+	u8 firmware_kidx;
+	if (b43legacy_new_kidx_api(dev))
+		firmware_kidx = raw_kidx;
+	else {
+		if (raw_kidx >= 4) /* Is per STA key? */
+			firmware_kidx = raw_kidx - 4;
+		else
+			firmware_kidx = raw_kidx; /* TX default key */
+	}
+	return firmware_kidx;
+}
+static inline
+u8 b43legacy_kidx_to_raw(struct b43legacy_wldev *dev, u8 firmware_kidx)
+{
+	u8 raw_kidx;
+	if (b43legacy_new_kidx_api(dev))
+		raw_kidx = firmware_kidx;
+	else
+		/* RX default keys or per STA keys */
+		raw_kidx = firmware_kidx + 4;
+	return raw_kidx;
+}
+
+#endif /* B43legacy_XMIT_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/Kconfig b/drivers/net/wireless/broadcom/brcm80211/Kconfig
new file mode 100644
index 0000000..6acba67
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/Kconfig
@@ -0,0 +1,86 @@
+config BRCMUTIL
+	tristate
+
+config BRCMSMAC
+	tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver"
+	depends on MAC80211
+	depends on BCMA_POSSIBLE
+	select BCMA
+	select NEW_LEDS if BCMA_DRIVER_GPIO
+	select LEDS_CLASS if BCMA_DRIVER_GPIO
+	select BRCMUTIL
+	select FW_LOADER
+	select CORDIC
+	---help---
+	  This module adds support for PCIe wireless adapters based on Broadcom
+	  IEEE802.11n SoftMAC chipsets. It also has WLAN led support, which will
+	  be available if you select BCMA_DRIVER_GPIO. If you choose to build a
+	  module, the driver will be called brcmsmac.ko.
+
+config BRCMFMAC
+	tristate "Broadcom FullMAC WLAN driver"
+	depends on CFG80211
+	select BRCMUTIL
+	---help---
+	  This module adds support for wireless adapters based on Broadcom
+	  FullMAC chipsets. It has to work with at least one of the bus
+	  interface support. If you choose to build a module, it'll be called
+	  brcmfmac.ko.
+
+config BRCMFMAC_PROTO_BCDC
+	bool
+
+config BRCMFMAC_PROTO_MSGBUF
+	bool
+
+config BRCMFMAC_SDIO
+	bool "SDIO bus interface support for FullMAC driver"
+	depends on (MMC = y || MMC = BRCMFMAC)
+	depends on BRCMFMAC
+	select BRCMFMAC_PROTO_BCDC
+	select FW_LOADER
+	default y
+	---help---
+	  This option enables the SDIO bus interface support for Broadcom
+	  IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to
+	  use the driver for a SDIO wireless card.
+
+config BRCMFMAC_USB
+	bool "USB bus interface support for FullMAC driver"
+	depends on (USB = y || USB = BRCMFMAC)
+	depends on BRCMFMAC
+	select BRCMFMAC_PROTO_BCDC
+	select FW_LOADER
+	---help---
+	  This option enables the USB bus interface support for Broadcom
+	  IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to
+	  use the driver for an USB wireless card.
+
+config BRCMFMAC_PCIE
+	bool "PCIE bus interface support for FullMAC driver"
+	depends on BRCMFMAC
+	depends on PCI
+	select BRCMFMAC_PROTO_MSGBUF
+	select FW_LOADER
+	---help---
+	  This option enables the PCIE bus interface support for Broadcom
+	  IEEE802.11ac embedded FullMAC WLAN driver. Say Y if you want to
+	  use the driver for an PCIE wireless card.
+
+config BRCM_TRACING
+	bool "Broadcom device tracing"
+	depends on BRCMSMAC || BRCMFMAC
+	---help---
+	  If you say Y here, the Broadcom wireless drivers will register
+	  with ftrace to dump event information into the trace ringbuffer.
+	  Tracing can be enabled at runtime to aid in debugging wireless
+	  issues. This option adds a small amount of overhead when tracing
+	  is disabled. If unsure, say Y to allow developers to better help
+	  you when wireless problems occur.
+
+config BRCMDBG
+	bool "Broadcom driver debug functions"
+	depends on BRCMSMAC || BRCMFMAC
+	select WANT_DEV_COREDUMP
+	---help---
+	  Selecting this enables additional code for debug purposes.
diff --git a/drivers/net/wireless/broadcom/brcm80211/Makefile b/drivers/net/wireless/broadcom/brcm80211/Makefile
new file mode 100644
index 0000000..b987920
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/Makefile
@@ -0,0 +1,23 @@
+#
+# Makefile fragment for Broadcom 802.11n Networking Device Driver
+#
+# Copyright (c) 2010 Broadcom Corporation
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# common flags
+subdir-ccflags-$(CONFIG_BRCMDBG)	+= -DDEBUG
+
+obj-$(CONFIG_BRCMUTIL)	+= brcmutil/
+obj-$(CONFIG_BRCMFMAC)	+= brcmfmac/
+obj-$(CONFIG_BRCMSMAC)	+= brcmsmac/
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile
new file mode 100644
index 0000000..1f5a9b9
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile
@@ -0,0 +1,56 @@
+#
+# Makefile fragment for Broadcom 802.11n Networking Device Driver
+#
+# Copyright (c) 2010 Broadcom Corporation
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ccflags-y += \
+	-Idrivers/net/wireless/broadcom/brcm80211/brcmfmac	\
+	-Idrivers/net/wireless/broadcom/brcm80211/include
+
+obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
+brcmfmac-objs += \
+		cfg80211.o \
+		chip.o \
+		fwil.o \
+		fweh.o \
+		p2p.o \
+		proto.o \
+		common.o \
+		core.o \
+		firmware.o \
+		feature.o \
+		btcoex.o \
+		vendor.o \
+		pno.o
+brcmfmac-$(CONFIG_BRCMFMAC_PROTO_BCDC) += \
+		bcdc.o \
+		fwsignal.o
+brcmfmac-$(CONFIG_BRCMFMAC_PROTO_MSGBUF) += \
+		commonring.o \
+		flowring.o \
+		msgbuf.o
+brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
+		sdio.o \
+		bcmsdh.o
+brcmfmac-$(CONFIG_BRCMFMAC_USB) += \
+		usb.o
+brcmfmac-$(CONFIG_BRCMFMAC_PCIE) += \
+		pcie.o
+brcmfmac-$(CONFIG_BRCMDBG) += \
+		debug.o
+brcmfmac-$(CONFIG_BRCM_TRACING) += \
+		tracepoint.o
+brcmfmac-$(CONFIG_OF) += \
+		of.o
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
new file mode 100644
index 0000000..1068a2a
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
@@ -0,0 +1,500 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*******************************************************************************
+ * Communicates with the dongle by using dcmd codes.
+ * For certain dcmd codes, the dongle interprets string data from the host.
+ ******************************************************************************/
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+
+#include "core.h"
+#include "bus.h"
+#include "fwsignal.h"
+#include "debug.h"
+#include "tracepoint.h"
+#include "proto.h"
+#include "bcdc.h"
+
+struct brcmf_proto_bcdc_dcmd {
+	__le32 cmd;	/* dongle command value */
+	__le32 len;	/* lower 16: output buflen;
+			 * upper 16: input buflen (excludes header) */
+	__le32 flags;	/* flag defns given below */
+	__le32 status;	/* status code returned from the device */
+};
+
+/* BCDC flag definitions */
+#define BCDC_DCMD_ERROR		0x01		/* 1=cmd failed */
+#define BCDC_DCMD_SET		0x02		/* 0=get, 1=set cmd */
+#define BCDC_DCMD_IF_MASK	0xF000		/* I/F index */
+#define BCDC_DCMD_IF_SHIFT	12
+#define BCDC_DCMD_ID_MASK	0xFFFF0000	/* id an cmd pairing */
+#define BCDC_DCMD_ID_SHIFT	16		/* ID Mask shift bits */
+#define BCDC_DCMD_ID(flags)	\
+	(((flags) & BCDC_DCMD_ID_MASK) >> BCDC_DCMD_ID_SHIFT)
+
+/*
+ * BCDC header - Broadcom specific extension of CDC.
+ * Used on data packets to convey priority across USB.
+ */
+#define	BCDC_HEADER_LEN		4
+#define BCDC_PROTO_VER		2	/* Protocol version */
+#define BCDC_FLAG_VER_MASK	0xf0	/* Protocol version mask */
+#define BCDC_FLAG_VER_SHIFT	4	/* Protocol version shift */
+#define BCDC_FLAG_SUM_GOOD	0x04	/* Good RX checksums */
+#define BCDC_FLAG_SUM_NEEDED	0x08	/* Dongle needs to do TX checksums */
+#define BCDC_PRIORITY_MASK	0x7
+#define BCDC_FLAG2_IF_MASK	0x0f	/* packet rx interface in APSTA */
+#define BCDC_FLAG2_IF_SHIFT	0
+
+#define BCDC_GET_IF_IDX(hdr) \
+	((int)((((hdr)->flags2) & BCDC_FLAG2_IF_MASK) >> BCDC_FLAG2_IF_SHIFT))
+#define BCDC_SET_IF_IDX(hdr, idx) \
+	((hdr)->flags2 = (((hdr)->flags2 & ~BCDC_FLAG2_IF_MASK) | \
+	((idx) << BCDC_FLAG2_IF_SHIFT)))
+
+/**
+ * struct brcmf_proto_bcdc_header - BCDC header format
+ *
+ * @flags: flags contain protocol and checksum info.
+ * @priority: 802.1d priority and USB flow control info (bit 4:7).
+ * @flags2: additional flags containing dongle interface index.
+ * @data_offset: start of packet data. header is following by firmware signals.
+ */
+struct brcmf_proto_bcdc_header {
+	u8 flags;
+	u8 priority;
+	u8 flags2;
+	u8 data_offset;
+};
+
+/*
+ * maximum length of firmware signal data between
+ * the BCDC header and packet data in the tx path.
+ */
+#define BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES	12
+
+#define RETRIES 2 /* # of retries to retrieve matching dcmd response */
+#define BUS_HEADER_LEN	(16+64)		/* Must be atleast SDPCM_RESERVE
+					 * (amount of header tha might be added)
+					 * plus any space that might be needed
+					 * for bus alignment padding.
+					 */
+struct brcmf_bcdc {
+	u16 reqid;
+	u8 bus_header[BUS_HEADER_LEN];
+	struct brcmf_proto_bcdc_dcmd msg;
+	unsigned char buf[BRCMF_DCMD_MAXLEN];
+	struct brcmf_fws_info *fws;
+};
+
+
+struct brcmf_fws_info *drvr_to_fws(struct brcmf_pub *drvr)
+{
+	struct brcmf_bcdc *bcdc = drvr->proto->pd;
+
+	return bcdc->fws;
+}
+
+static int
+brcmf_proto_bcdc_msg(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf,
+		     uint len, bool set)
+{
+	struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
+	struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg;
+	u32 flags;
+
+	brcmf_dbg(BCDC, "Enter\n");
+
+	memset(msg, 0, sizeof(struct brcmf_proto_bcdc_dcmd));
+
+	msg->cmd = cpu_to_le32(cmd);
+	msg->len = cpu_to_le32(len);
+	flags = (++bcdc->reqid << BCDC_DCMD_ID_SHIFT);
+	if (set)
+		flags |= BCDC_DCMD_SET;
+	flags = (flags & ~BCDC_DCMD_IF_MASK) |
+		(ifidx << BCDC_DCMD_IF_SHIFT);
+	msg->flags = cpu_to_le32(flags);
+
+	if (buf)
+		memcpy(bcdc->buf, buf, len);
+
+	len += sizeof(*msg);
+	if (len > BRCMF_TX_IOCTL_MAX_MSG_SIZE)
+		len = BRCMF_TX_IOCTL_MAX_MSG_SIZE;
+
+	/* Send request */
+	return brcmf_bus_txctl(drvr->bus_if, (unsigned char *)&bcdc->msg, len);
+}
+
+static int brcmf_proto_bcdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len)
+{
+	int ret;
+	struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
+
+	brcmf_dbg(BCDC, "Enter\n");
+	len += sizeof(struct brcmf_proto_bcdc_dcmd);
+	do {
+		ret = brcmf_bus_rxctl(drvr->bus_if, (unsigned char *)&bcdc->msg,
+				      len);
+		if (ret < 0)
+			break;
+	} while (BCDC_DCMD_ID(le32_to_cpu(bcdc->msg.flags)) != id);
+
+	return ret;
+}
+
+static int
+brcmf_proto_bcdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
+			    void *buf, uint len, int *fwerr)
+{
+	struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
+	struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg;
+	void *info;
+	int ret = 0, retries = 0;
+	u32 id, flags;
+
+	brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len);
+
+	*fwerr = 0;
+	ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, false);
+	if (ret < 0) {
+		brcmf_err("brcmf_proto_bcdc_msg failed w/status %d\n",
+			  ret);
+		goto done;
+	}
+
+retry:
+	/* wait for interrupt and get first fragment */
+	ret = brcmf_proto_bcdc_cmplt(drvr, bcdc->reqid, len);
+	if (ret < 0)
+		goto done;
+
+	flags = le32_to_cpu(msg->flags);
+	id = (flags & BCDC_DCMD_ID_MASK) >> BCDC_DCMD_ID_SHIFT;
+
+	if ((id < bcdc->reqid) && (++retries < RETRIES))
+		goto retry;
+	if (id != bcdc->reqid) {
+		brcmf_err("%s: unexpected request id %d (expected %d)\n",
+			  brcmf_ifname(brcmf_get_ifp(drvr, ifidx)), id,
+			  bcdc->reqid);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* Check info buffer */
+	info = (void *)&bcdc->buf[0];
+
+	/* Copy info buffer */
+	if (buf) {
+		if (ret < (int)len)
+			len = ret;
+		memcpy(buf, info, len);
+	}
+
+	ret = 0;
+
+	/* Check the ERROR flag */
+	if (flags & BCDC_DCMD_ERROR)
+		*fwerr = le32_to_cpu(msg->status);
+done:
+	return ret;
+}
+
+static int
+brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
+			  void *buf, uint len, int *fwerr)
+{
+	struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
+	struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg;
+	int ret;
+	u32 flags, id;
+
+	brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len);
+
+	*fwerr = 0;
+	ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, true);
+	if (ret < 0)
+		goto done;
+
+	ret = brcmf_proto_bcdc_cmplt(drvr, bcdc->reqid, len);
+	if (ret < 0)
+		goto done;
+
+	flags = le32_to_cpu(msg->flags);
+	id = (flags & BCDC_DCMD_ID_MASK) >> BCDC_DCMD_ID_SHIFT;
+
+	if (id != bcdc->reqid) {
+		brcmf_err("%s: unexpected request id %d (expected %d)\n",
+			  brcmf_ifname(brcmf_get_ifp(drvr, ifidx)), id,
+			  bcdc->reqid);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	ret = 0;
+
+	/* Check the ERROR flag */
+	if (flags & BCDC_DCMD_ERROR)
+		*fwerr = le32_to_cpu(msg->status);
+
+done:
+	return ret;
+}
+
+static void
+brcmf_proto_bcdc_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset,
+			 struct sk_buff *pktbuf)
+{
+	struct brcmf_proto_bcdc_header *h;
+
+	brcmf_dbg(BCDC, "Enter\n");
+
+	/* Push BDC header used to convey priority for buses that don't */
+	skb_push(pktbuf, BCDC_HEADER_LEN);
+
+	h = (struct brcmf_proto_bcdc_header *)(pktbuf->data);
+
+	h->flags = (BCDC_PROTO_VER << BCDC_FLAG_VER_SHIFT);
+	if (pktbuf->ip_summed == CHECKSUM_PARTIAL)
+		h->flags |= BCDC_FLAG_SUM_NEEDED;
+
+	h->priority = (pktbuf->priority & BCDC_PRIORITY_MASK);
+	h->flags2 = 0;
+	h->data_offset = offset;
+	BCDC_SET_IF_IDX(h, ifidx);
+	trace_brcmf_bcdchdr(pktbuf->data);
+}
+
+static int
+brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws,
+			 struct sk_buff *pktbuf, struct brcmf_if **ifp)
+{
+	struct brcmf_proto_bcdc_header *h;
+	struct brcmf_if *tmp_if;
+
+	brcmf_dbg(BCDC, "Enter\n");
+
+	/* Pop BCDC header used to convey priority for buses that don't */
+	if (pktbuf->len <= BCDC_HEADER_LEN) {
+		brcmf_dbg(INFO, "rx data too short (%d <= %d)\n",
+			  pktbuf->len, BCDC_HEADER_LEN);
+		return -EBADE;
+	}
+
+	trace_brcmf_bcdchdr(pktbuf->data);
+	h = (struct brcmf_proto_bcdc_header *)(pktbuf->data);
+
+	tmp_if = brcmf_get_ifp(drvr, BCDC_GET_IF_IDX(h));
+	if (!tmp_if) {
+		brcmf_dbg(INFO, "no matching ifp found\n");
+		return -EBADE;
+	}
+	if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) !=
+	    BCDC_PROTO_VER) {
+		brcmf_err("%s: non-BCDC packet received, flags 0x%x\n",
+			  brcmf_ifname(tmp_if), h->flags);
+		return -EBADE;
+	}
+
+	if (h->flags & BCDC_FLAG_SUM_GOOD) {
+		brcmf_dbg(BCDC, "%s: BDC rcv, good checksum, flags 0x%x\n",
+			  brcmf_ifname(tmp_if), h->flags);
+		pktbuf->ip_summed = CHECKSUM_UNNECESSARY;
+	}
+
+	pktbuf->priority = h->priority & BCDC_PRIORITY_MASK;
+
+	skb_pull(pktbuf, BCDC_HEADER_LEN);
+	if (do_fws)
+		brcmf_fws_hdrpull(tmp_if, h->data_offset << 2, pktbuf);
+	else
+		skb_pull(pktbuf, h->data_offset << 2);
+
+	if (pktbuf->len == 0)
+		return -ENODATA;
+
+	if (ifp != NULL)
+		*ifp = tmp_if;
+	return 0;
+}
+
+static int brcmf_proto_bcdc_tx_queue_data(struct brcmf_pub *drvr, int ifidx,
+					  struct sk_buff *skb)
+{
+	struct brcmf_if *ifp = brcmf_get_ifp(drvr, ifidx);
+	struct brcmf_bcdc *bcdc = drvr->proto->pd;
+
+	if (!brcmf_fws_queue_skbs(bcdc->fws))
+		return brcmf_proto_txdata(drvr, ifidx, 0, skb);
+
+	return brcmf_fws_process_skb(ifp, skb);
+}
+
+static int
+brcmf_proto_bcdc_txdata(struct brcmf_pub *drvr, int ifidx, u8 offset,
+			struct sk_buff *pktbuf)
+{
+	brcmf_proto_bcdc_hdrpush(drvr, ifidx, offset, pktbuf);
+	return brcmf_bus_txdata(drvr->bus_if, pktbuf);
+}
+
+void brcmf_proto_bcdc_txflowblock(struct device *dev, bool state)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_pub *drvr = bus_if->drvr;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	brcmf_fws_bus_blocked(drvr, state);
+}
+
+void
+brcmf_proto_bcdc_txcomplete(struct device *dev, struct sk_buff *txp,
+			    bool success)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_bcdc *bcdc = bus_if->drvr->proto->pd;
+	struct brcmf_if *ifp;
+
+	/* await txstatus signal for firmware if active */
+	if (brcmf_fws_fc_active(bcdc->fws)) {
+		if (!success)
+			brcmf_fws_bustxfail(bcdc->fws, txp);
+	} else {
+		if (brcmf_proto_bcdc_hdrpull(bus_if->drvr, false, txp, &ifp))
+			brcmu_pkt_buf_free_skb(txp);
+		else
+			brcmf_txfinalize(ifp, txp, success);
+	}
+}
+
+static void
+brcmf_proto_bcdc_configure_addr_mode(struct brcmf_pub *drvr, int ifidx,
+				     enum proto_addr_mode addr_mode)
+{
+}
+
+static void
+brcmf_proto_bcdc_delete_peer(struct brcmf_pub *drvr, int ifidx,
+			     u8 peer[ETH_ALEN])
+{
+}
+
+static void
+brcmf_proto_bcdc_add_tdls_peer(struct brcmf_pub *drvr, int ifidx,
+			       u8 peer[ETH_ALEN])
+{
+}
+
+static void brcmf_proto_bcdc_rxreorder(struct brcmf_if *ifp,
+				       struct sk_buff *skb)
+{
+	brcmf_fws_rxreorder(ifp, skb);
+}
+
+static void
+brcmf_proto_bcdc_add_if(struct brcmf_if *ifp)
+{
+	brcmf_fws_add_interface(ifp);
+}
+
+static void
+brcmf_proto_bcdc_del_if(struct brcmf_if *ifp)
+{
+	brcmf_fws_del_interface(ifp);
+}
+
+static void
+brcmf_proto_bcdc_reset_if(struct brcmf_if *ifp)
+{
+	brcmf_fws_reset_interface(ifp);
+}
+
+static int
+brcmf_proto_bcdc_init_done(struct brcmf_pub *drvr)
+{
+	struct brcmf_bcdc *bcdc = drvr->proto->pd;
+	struct brcmf_fws_info *fws;
+
+	fws = brcmf_fws_attach(drvr);
+	if (IS_ERR(fws))
+		return PTR_ERR(fws);
+
+	bcdc->fws = fws;
+	return 0;
+}
+
+static void brcmf_proto_bcdc_debugfs_create(struct brcmf_pub *drvr)
+{
+	brcmf_fws_debugfs_create(drvr);
+}
+
+int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
+{
+	struct brcmf_bcdc *bcdc;
+
+	bcdc = kzalloc(sizeof(*bcdc), GFP_ATOMIC);
+	if (!bcdc)
+		goto fail;
+
+	/* ensure that the msg buf directly follows the cdc msg struct */
+	if ((unsigned long)(&bcdc->msg + 1) != (unsigned long)bcdc->buf) {
+		brcmf_err("struct brcmf_proto_bcdc is not correctly defined\n");
+		goto fail;
+	}
+
+	drvr->proto->hdrpull = brcmf_proto_bcdc_hdrpull;
+	drvr->proto->query_dcmd = brcmf_proto_bcdc_query_dcmd;
+	drvr->proto->set_dcmd = brcmf_proto_bcdc_set_dcmd;
+	drvr->proto->tx_queue_data = brcmf_proto_bcdc_tx_queue_data;
+	drvr->proto->txdata = brcmf_proto_bcdc_txdata;
+	drvr->proto->configure_addr_mode = brcmf_proto_bcdc_configure_addr_mode;
+	drvr->proto->delete_peer = brcmf_proto_bcdc_delete_peer;
+	drvr->proto->add_tdls_peer = brcmf_proto_bcdc_add_tdls_peer;
+	drvr->proto->rxreorder = brcmf_proto_bcdc_rxreorder;
+	drvr->proto->add_if = brcmf_proto_bcdc_add_if;
+	drvr->proto->del_if = brcmf_proto_bcdc_del_if;
+	drvr->proto->reset_if = brcmf_proto_bcdc_reset_if;
+	drvr->proto->init_done = brcmf_proto_bcdc_init_done;
+	drvr->proto->debugfs_create = brcmf_proto_bcdc_debugfs_create;
+	drvr->proto->pd = bcdc;
+
+	drvr->hdrlen += BCDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES;
+	drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN +
+			sizeof(struct brcmf_proto_bcdc_dcmd);
+	return 0;
+
+fail:
+	kfree(bcdc);
+	return -ENOMEM;
+}
+
+void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr)
+{
+	struct brcmf_bcdc *bcdc = drvr->proto->pd;
+
+	drvr->proto->pd = NULL;
+	brcmf_fws_detach(bcdc->fws);
+	kfree(bcdc);
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.h
new file mode 100644
index 0000000..3b0e9ef
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef BRCMFMAC_BCDC_H
+#define BRCMFMAC_BCDC_H
+
+#ifdef CONFIG_BRCMFMAC_PROTO_BCDC
+int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr);
+void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr);
+void brcmf_proto_bcdc_txflowblock(struct device *dev, bool state);
+void brcmf_proto_bcdc_txcomplete(struct device *dev, struct sk_buff *txp,
+				 bool success);
+struct brcmf_fws_info *drvr_to_fws(struct brcmf_pub *drvr);
+#else
+static inline int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) { return 0; }
+static inline void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr) {}
+#endif
+
+#endif /* BRCMFMAC_BCDC_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
new file mode 100644
index 0000000..d2f788d
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -0,0 +1,1187 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* ****************** SDIO CARD Interface Functions **************************/
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/sched.h>
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+#include <linux/scatterlist.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/core.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/pm_runtime.h>
+#include <linux/suspend.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/acpi.h>
+#include <net/cfg80211.h>
+
+#include <defs.h>
+#include <brcm_hw_ids.h>
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+#include <chipcommon.h>
+#include <soc.h>
+#include "chip.h"
+#include "bus.h"
+#include "debug.h"
+#include "sdio.h"
+#include "core.h"
+#include "common.h"
+
+#define SDIOH_API_ACCESS_RETRY_LIMIT	2
+
+#define DMA_ALIGN_MASK	0x03
+
+#define SDIO_FUNC1_BLOCKSIZE		64
+#define SDIO_FUNC2_BLOCKSIZE		512
+/* Maximum milliseconds to wait for F2 to come up */
+#define SDIO_WAIT_F2RDY	3000
+
+#define BRCMF_DEFAULT_RXGLOM_SIZE	32  /* max rx frames in glom chain */
+
+struct brcmf_sdiod_freezer {
+	atomic_t freezing;
+	atomic_t thread_count;
+	u32 frozen_count;
+	wait_queue_head_t thread_freeze;
+	struct completion resumed;
+};
+
+static irqreturn_t brcmf_sdiod_oob_irqhandler(int irq, void *dev_id)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev_id);
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+
+	brcmf_dbg(INTR, "OOB intr triggered\n");
+
+	/* out-of-band interrupt is level-triggered which won't
+	 * be cleared until dpc
+	 */
+	if (sdiodev->irq_en) {
+		disable_irq_nosync(irq);
+		sdiodev->irq_en = false;
+	}
+
+	brcmf_sdio_isr(sdiodev->bus);
+
+	return IRQ_HANDLED;
+}
+
+static void brcmf_sdiod_ib_irqhandler(struct sdio_func *func)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(&func->dev);
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+
+	brcmf_dbg(INTR, "IB intr triggered\n");
+
+	brcmf_sdio_isr(sdiodev->bus);
+}
+
+/* dummy handler for SDIO function 2 interrupt */
+static void brcmf_sdiod_dummy_irqhandler(struct sdio_func *func)
+{
+}
+
+int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev)
+{
+	struct brcmfmac_sdio_pd *pdata;
+	int ret = 0;
+	u8 data;
+	u32 addr, gpiocontrol;
+
+	pdata = &sdiodev->settings->bus.sdio;
+	if (pdata->oob_irq_supported) {
+		brcmf_dbg(SDIO, "Enter, register OOB IRQ %d\n",
+			  pdata->oob_irq_nr);
+		spin_lock_init(&sdiodev->irq_en_lock);
+		sdiodev->irq_en = true;
+
+		ret = request_irq(pdata->oob_irq_nr, brcmf_sdiod_oob_irqhandler,
+				  pdata->oob_irq_flags, "brcmf_oob_intr",
+				  &sdiodev->func1->dev);
+		if (ret != 0) {
+			brcmf_err("request_irq failed %d\n", ret);
+			return ret;
+		}
+		sdiodev->oob_irq_requested = true;
+
+		ret = enable_irq_wake(pdata->oob_irq_nr);
+		if (ret != 0) {
+			brcmf_err("enable_irq_wake failed %d\n", ret);
+			return ret;
+		}
+		sdiodev->irq_wake = true;
+
+		sdio_claim_host(sdiodev->func1);
+
+		if (sdiodev->bus_if->chip == BRCM_CC_43362_CHIP_ID) {
+			/* assign GPIO to SDIO core */
+			addr = CORE_CC_REG(SI_ENUM_BASE, gpiocontrol);
+			gpiocontrol = brcmf_sdiod_readl(sdiodev, addr, &ret);
+			gpiocontrol |= 0x2;
+			brcmf_sdiod_writel(sdiodev, addr, gpiocontrol, &ret);
+
+			brcmf_sdiod_writeb(sdiodev, SBSDIO_GPIO_SELECT,
+					   0xf, &ret);
+			brcmf_sdiod_writeb(sdiodev, SBSDIO_GPIO_OUT, 0, &ret);
+			brcmf_sdiod_writeb(sdiodev, SBSDIO_GPIO_EN, 0x2, &ret);
+		}
+
+		/* must configure SDIO_CCCR_IENx to enable irq */
+		data = brcmf_sdiod_func0_rb(sdiodev, SDIO_CCCR_IENx, &ret);
+		data |= SDIO_CCCR_IEN_FUNC1 | SDIO_CCCR_IEN_FUNC2 |
+			SDIO_CCCR_IEN_FUNC0;
+		brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_IENx, data, &ret);
+
+		/* redirect, configure and enable io for interrupt signal */
+		data = SDIO_CCCR_BRCM_SEPINT_MASK | SDIO_CCCR_BRCM_SEPINT_OE;
+		if (pdata->oob_irq_flags & IRQF_TRIGGER_HIGH)
+			data |= SDIO_CCCR_BRCM_SEPINT_ACT_HI;
+		brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_BRCM_SEPINT,
+				     data, &ret);
+		sdio_release_host(sdiodev->func1);
+	} else {
+		brcmf_dbg(SDIO, "Entering\n");
+		sdio_claim_host(sdiodev->func1);
+		sdio_claim_irq(sdiodev->func1, brcmf_sdiod_ib_irqhandler);
+		sdio_claim_irq(sdiodev->func2, brcmf_sdiod_dummy_irqhandler);
+		sdio_release_host(sdiodev->func1);
+		sdiodev->sd_irq_requested = true;
+	}
+
+	return 0;
+}
+
+void brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev)
+{
+
+	brcmf_dbg(SDIO, "Entering oob=%d sd=%d\n",
+		  sdiodev->oob_irq_requested,
+		  sdiodev->sd_irq_requested);
+
+	if (sdiodev->oob_irq_requested) {
+		struct brcmfmac_sdio_pd *pdata;
+
+		pdata = &sdiodev->settings->bus.sdio;
+		sdio_claim_host(sdiodev->func1);
+		brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
+		brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
+		sdio_release_host(sdiodev->func1);
+
+		sdiodev->oob_irq_requested = false;
+		if (sdiodev->irq_wake) {
+			disable_irq_wake(pdata->oob_irq_nr);
+			sdiodev->irq_wake = false;
+		}
+		free_irq(pdata->oob_irq_nr, &sdiodev->func1->dev);
+		sdiodev->irq_en = false;
+		sdiodev->oob_irq_requested = false;
+	}
+
+	if (sdiodev->sd_irq_requested) {
+		sdio_claim_host(sdiodev->func1);
+		sdio_release_irq(sdiodev->func2);
+		sdio_release_irq(sdiodev->func1);
+		sdio_release_host(sdiodev->func1);
+		sdiodev->sd_irq_requested = false;
+	}
+}
+
+void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev,
+			      enum brcmf_sdiod_state state)
+{
+	if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM ||
+	    state == sdiodev->state)
+		return;
+
+	brcmf_dbg(TRACE, "%d -> %d\n", sdiodev->state, state);
+	switch (sdiodev->state) {
+	case BRCMF_SDIOD_DATA:
+		/* any other state means bus interface is down */
+		brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_DOWN);
+		break;
+	case BRCMF_SDIOD_DOWN:
+		/* transition from DOWN to DATA means bus interface is up */
+		if (state == BRCMF_SDIOD_DATA)
+			brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_UP);
+		break;
+	default:
+		break;
+	}
+	sdiodev->state = state;
+}
+
+static int brcmf_sdiod_set_backplane_window(struct brcmf_sdio_dev *sdiodev,
+					    u32 addr)
+{
+	u32 v, bar0 = addr & SBSDIO_SBWINDOW_MASK;
+	int err = 0, i;
+
+	if (bar0 == sdiodev->sbwad)
+		return 0;
+
+	v = bar0 >> 8;
+
+	for (i = 0 ; i < 3 && !err ; i++, v >>= 8)
+		brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i,
+				   v & 0xff, &err);
+
+	if (!err)
+		sdiodev->sbwad = bar0;
+
+	return err;
+}
+
+u32 brcmf_sdiod_readl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
+{
+	u32 data = 0;
+	int retval;
+
+	retval = brcmf_sdiod_set_backplane_window(sdiodev, addr);
+	if (retval)
+		goto out;
+
+	addr &= SBSDIO_SB_OFT_ADDR_MASK;
+	addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+
+	data = sdio_readl(sdiodev->func1, addr, &retval);
+
+out:
+	if (ret)
+		*ret = retval;
+
+	return data;
+}
+
+void brcmf_sdiod_writel(struct brcmf_sdio_dev *sdiodev, u32 addr,
+			u32 data, int *ret)
+{
+	int retval;
+
+	retval = brcmf_sdiod_set_backplane_window(sdiodev, addr);
+	if (retval)
+		goto out;
+
+	addr &= SBSDIO_SB_OFT_ADDR_MASK;
+	addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+
+	sdio_writel(sdiodev->func1, data, addr, &retval);
+
+out:
+	if (ret)
+		*ret = retval;
+}
+
+static int brcmf_sdiod_skbuff_read(struct brcmf_sdio_dev *sdiodev,
+				   struct sdio_func *func, u32 addr,
+				   struct sk_buff *skb)
+{
+	unsigned int req_sz;
+	int err;
+
+	/* Single skb use the standard mmc interface */
+	req_sz = skb->len + 3;
+	req_sz &= (uint)~3;
+
+	switch (func->num) {
+	case 1:
+		err = sdio_memcpy_fromio(func, ((u8 *)(skb->data)), addr,
+					 req_sz);
+		break;
+	case 2:
+		err = sdio_readsb(func, ((u8 *)(skb->data)), addr, req_sz);
+		break;
+	default:
+		/* bail out as things are really fishy here */
+		WARN(1, "invalid sdio function number: %d\n", func->num);
+		err = -ENOMEDIUM;
+	};
+
+	if (err == -ENOMEDIUM)
+		brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
+
+	return err;
+}
+
+static int brcmf_sdiod_skbuff_write(struct brcmf_sdio_dev *sdiodev,
+				    struct sdio_func *func, u32 addr,
+				    struct sk_buff *skb)
+{
+	unsigned int req_sz;
+	int err;
+
+	/* Single skb use the standard mmc interface */
+	req_sz = skb->len + 3;
+	req_sz &= (uint)~3;
+
+	err = sdio_memcpy_toio(func, addr, ((u8 *)(skb->data)), req_sz);
+
+	if (err == -ENOMEDIUM)
+		brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
+
+	return err;
+}
+
+/**
+ * brcmf_sdiod_sglist_rw - SDIO interface function for block data access
+ * @sdiodev: brcmfmac sdio device
+ * @func: SDIO function
+ * @write: direction flag
+ * @addr: dongle memory address as source/destination
+ * @pkt: skb pointer
+ *
+ * This function takes the respbonsibility as the interface function to MMC
+ * stack for block data access. It assumes that the skb passed down by the
+ * caller has already been padded and aligned.
+ */
+static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev,
+				 struct sdio_func *func,
+				 bool write, u32 addr,
+				 struct sk_buff_head *pktlist)
+{
+	unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset;
+	unsigned int max_req_sz, orig_offset, dst_offset;
+	unsigned short max_seg_cnt, seg_sz;
+	unsigned char *pkt_data, *orig_data, *dst_data;
+	struct sk_buff *pkt_next = NULL, *local_pkt_next;
+	struct sk_buff_head local_list, *target_list;
+	struct mmc_request mmc_req;
+	struct mmc_command mmc_cmd;
+	struct mmc_data mmc_dat;
+	struct scatterlist *sgl;
+	int ret = 0;
+
+	if (!pktlist->qlen)
+		return -EINVAL;
+
+	target_list = pktlist;
+	/* for host with broken sg support, prepare a page aligned list */
+	__skb_queue_head_init(&local_list);
+	if (!write && sdiodev->settings->bus.sdio.broken_sg_support) {
+		req_sz = 0;
+		skb_queue_walk(pktlist, pkt_next)
+			req_sz += pkt_next->len;
+		req_sz = ALIGN(req_sz, func->cur_blksize);
+		while (req_sz > PAGE_SIZE) {
+			pkt_next = brcmu_pkt_buf_get_skb(PAGE_SIZE);
+			if (pkt_next == NULL) {
+				ret = -ENOMEM;
+				goto exit;
+			}
+			__skb_queue_tail(&local_list, pkt_next);
+			req_sz -= PAGE_SIZE;
+		}
+		pkt_next = brcmu_pkt_buf_get_skb(req_sz);
+		if (pkt_next == NULL) {
+			ret = -ENOMEM;
+			goto exit;
+		}
+		__skb_queue_tail(&local_list, pkt_next);
+		target_list = &local_list;
+	}
+
+	func_blk_sz = func->cur_blksize;
+	max_req_sz = sdiodev->max_request_size;
+	max_seg_cnt = min_t(unsigned short, sdiodev->max_segment_count,
+			    target_list->qlen);
+	seg_sz = target_list->qlen;
+	pkt_offset = 0;
+	pkt_next = target_list->next;
+
+	memset(&mmc_req, 0, sizeof(struct mmc_request));
+	memset(&mmc_cmd, 0, sizeof(struct mmc_command));
+	memset(&mmc_dat, 0, sizeof(struct mmc_data));
+
+	mmc_dat.sg = sdiodev->sgtable.sgl;
+	mmc_dat.blksz = func_blk_sz;
+	mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
+	mmc_cmd.opcode = SD_IO_RW_EXTENDED;
+	mmc_cmd.arg = write ? 1<<31 : 0;	/* write flag  */
+	mmc_cmd.arg |= (func->num & 0x7) << 28;	/* SDIO func num */
+	mmc_cmd.arg |= 1 << 27;			/* block mode */
+	/* for function 1 the addr will be incremented */
+	mmc_cmd.arg |= (func->num == 1) ? 1 << 26 : 0;
+	mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
+	mmc_req.cmd = &mmc_cmd;
+	mmc_req.data = &mmc_dat;
+
+	while (seg_sz) {
+		req_sz = 0;
+		sg_cnt = 0;
+		sgl = sdiodev->sgtable.sgl;
+		/* prep sg table */
+		while (pkt_next != (struct sk_buff *)target_list) {
+			pkt_data = pkt_next->data + pkt_offset;
+			sg_data_sz = pkt_next->len - pkt_offset;
+			if (sg_data_sz > sdiodev->max_segment_size)
+				sg_data_sz = sdiodev->max_segment_size;
+			if (sg_data_sz > max_req_sz - req_sz)
+				sg_data_sz = max_req_sz - req_sz;
+
+			sg_set_buf(sgl, pkt_data, sg_data_sz);
+
+			sg_cnt++;
+			sgl = sg_next(sgl);
+			req_sz += sg_data_sz;
+			pkt_offset += sg_data_sz;
+			if (pkt_offset == pkt_next->len) {
+				pkt_offset = 0;
+				pkt_next = pkt_next->next;
+			}
+
+			if (req_sz >= max_req_sz || sg_cnt >= max_seg_cnt)
+				break;
+		}
+		seg_sz -= sg_cnt;
+
+		if (req_sz % func_blk_sz != 0) {
+			brcmf_err("sg request length %u is not %u aligned\n",
+				  req_sz, func_blk_sz);
+			ret = -ENOTBLK;
+			goto exit;
+		}
+
+		mmc_dat.sg_len = sg_cnt;
+		mmc_dat.blocks = req_sz / func_blk_sz;
+		mmc_cmd.arg |= (addr & 0x1FFFF) << 9;	/* address */
+		mmc_cmd.arg |= mmc_dat.blocks & 0x1FF;	/* block count */
+		/* incrementing addr for function 1 */
+		if (func->num == 1)
+			addr += req_sz;
+
+		mmc_set_data_timeout(&mmc_dat, func->card);
+		mmc_wait_for_req(func->card->host, &mmc_req);
+
+		ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error;
+		if (ret == -ENOMEDIUM) {
+			brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
+			break;
+		} else if (ret != 0) {
+			brcmf_err("CMD53 sg block %s failed %d\n",
+				  write ? "write" : "read", ret);
+			ret = -EIO;
+			break;
+		}
+	}
+
+	if (!write && sdiodev->settings->bus.sdio.broken_sg_support) {
+		local_pkt_next = local_list.next;
+		orig_offset = 0;
+		skb_queue_walk(pktlist, pkt_next) {
+			dst_offset = 0;
+			do {
+				req_sz = local_pkt_next->len - orig_offset;
+				req_sz = min_t(uint, pkt_next->len - dst_offset,
+					       req_sz);
+				orig_data = local_pkt_next->data + orig_offset;
+				dst_data = pkt_next->data + dst_offset;
+				memcpy(dst_data, orig_data, req_sz);
+				orig_offset += req_sz;
+				dst_offset += req_sz;
+				if (orig_offset == local_pkt_next->len) {
+					orig_offset = 0;
+					local_pkt_next = local_pkt_next->next;
+				}
+				if (dst_offset == pkt_next->len)
+					break;
+			} while (!skb_queue_empty(&local_list));
+		}
+	}
+
+exit:
+	sg_init_table(sdiodev->sgtable.sgl, sdiodev->sgtable.orig_nents);
+	while ((pkt_next = __skb_dequeue(&local_list)) != NULL)
+		brcmu_pkt_buf_free_skb(pkt_next);
+
+	return ret;
+}
+
+int brcmf_sdiod_recv_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes)
+{
+	struct sk_buff *mypkt;
+	int err;
+
+	mypkt = brcmu_pkt_buf_get_skb(nbytes);
+	if (!mypkt) {
+		brcmf_err("brcmu_pkt_buf_get_skb failed: len %d\n",
+			  nbytes);
+		return -EIO;
+	}
+
+	err = brcmf_sdiod_recv_pkt(sdiodev, mypkt);
+	if (!err)
+		memcpy(buf, mypkt->data, nbytes);
+
+	brcmu_pkt_buf_free_skb(mypkt);
+	return err;
+}
+
+int brcmf_sdiod_recv_pkt(struct brcmf_sdio_dev *sdiodev, struct sk_buff *pkt)
+{
+	u32 addr = sdiodev->cc_core->base;
+	int err = 0;
+
+	brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pkt->len);
+
+	err = brcmf_sdiod_set_backplane_window(sdiodev, addr);
+	if (err)
+		goto done;
+
+	addr &= SBSDIO_SB_OFT_ADDR_MASK;
+	addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+
+	err = brcmf_sdiod_skbuff_read(sdiodev, sdiodev->func2, addr, pkt);
+
+done:
+	return err;
+}
+
+int brcmf_sdiod_recv_chain(struct brcmf_sdio_dev *sdiodev,
+			   struct sk_buff_head *pktq, uint totlen)
+{
+	struct sk_buff *glom_skb = NULL;
+	struct sk_buff *skb;
+	u32 addr = sdiodev->cc_core->base;
+	int err = 0;
+
+	brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n",
+		  addr, pktq->qlen);
+
+	err = brcmf_sdiod_set_backplane_window(sdiodev, addr);
+	if (err)
+		goto done;
+
+	addr &= SBSDIO_SB_OFT_ADDR_MASK;
+	addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+
+	if (pktq->qlen == 1)
+		err = brcmf_sdiod_skbuff_read(sdiodev, sdiodev->func2, addr,
+					      pktq->next);
+	else if (!sdiodev->sg_support) {
+		glom_skb = brcmu_pkt_buf_get_skb(totlen);
+		if (!glom_skb)
+			return -ENOMEM;
+		err = brcmf_sdiod_skbuff_read(sdiodev, sdiodev->func2, addr,
+					      glom_skb);
+		if (err)
+			goto done;
+
+		skb_queue_walk(pktq, skb) {
+			memcpy(skb->data, glom_skb->data, skb->len);
+			skb_pull(glom_skb, skb->len);
+		}
+	} else
+		err = brcmf_sdiod_sglist_rw(sdiodev, sdiodev->func2, false,
+					    addr, pktq);
+
+done:
+	brcmu_pkt_buf_free_skb(glom_skb);
+	return err;
+}
+
+int brcmf_sdiod_send_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes)
+{
+	struct sk_buff *mypkt;
+	u32 addr = sdiodev->cc_core->base;
+	int err;
+
+	mypkt = brcmu_pkt_buf_get_skb(nbytes);
+
+	if (!mypkt) {
+		brcmf_err("brcmu_pkt_buf_get_skb failed: len %d\n",
+			  nbytes);
+		return -EIO;
+	}
+
+	memcpy(mypkt->data, buf, nbytes);
+
+	err = brcmf_sdiod_set_backplane_window(sdiodev, addr);
+	if (err)
+		return err;
+
+	addr &= SBSDIO_SB_OFT_ADDR_MASK;
+	addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+
+	if (!err)
+		err = brcmf_sdiod_skbuff_write(sdiodev, sdiodev->func2, addr,
+					       mypkt);
+
+	brcmu_pkt_buf_free_skb(mypkt);
+
+	return err;
+}
+
+int brcmf_sdiod_send_pkt(struct brcmf_sdio_dev *sdiodev,
+			 struct sk_buff_head *pktq)
+{
+	struct sk_buff *skb;
+	u32 addr = sdiodev->cc_core->base;
+	int err;
+
+	brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pktq->qlen);
+
+	err = brcmf_sdiod_set_backplane_window(sdiodev, addr);
+	if (err)
+		return err;
+
+	addr &= SBSDIO_SB_OFT_ADDR_MASK;
+	addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+
+	if (pktq->qlen == 1 || !sdiodev->sg_support) {
+		skb_queue_walk(pktq, skb) {
+			err = brcmf_sdiod_skbuff_write(sdiodev, sdiodev->func2,
+						       addr, skb);
+			if (err)
+				break;
+		}
+	} else {
+		err = brcmf_sdiod_sglist_rw(sdiodev, sdiodev->func2, true,
+					    addr, pktq);
+	}
+
+	return err;
+}
+
+int
+brcmf_sdiod_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
+		  u8 *data, uint size)
+{
+	int err = 0;
+	struct sk_buff *pkt;
+	u32 sdaddr;
+	uint dsize;
+
+	dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
+	pkt = dev_alloc_skb(dsize);
+	if (!pkt) {
+		brcmf_err("dev_alloc_skb failed: len %d\n", dsize);
+		return -EIO;
+	}
+	pkt->priority = 0;
+
+	/* Determine initial transfer parameters */
+	sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
+	if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
+		dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
+	else
+		dsize = size;
+
+	sdio_claim_host(sdiodev->func1);
+
+	/* Do the transfer(s) */
+	while (size) {
+		/* Set the backplane window to include the start address */
+		err = brcmf_sdiod_set_backplane_window(sdiodev, address);
+		if (err)
+			break;
+
+		brcmf_dbg(SDIO, "%s %d bytes at offset 0x%08x in window 0x%08x\n",
+			  write ? "write" : "read", dsize,
+			  sdaddr, address & SBSDIO_SBWINDOW_MASK);
+
+		sdaddr &= SBSDIO_SB_OFT_ADDR_MASK;
+		sdaddr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+
+		skb_put(pkt, dsize);
+
+		if (write) {
+			memcpy(pkt->data, data, dsize);
+			err = brcmf_sdiod_skbuff_write(sdiodev, sdiodev->func1,
+						       sdaddr, pkt);
+		} else {
+			err = brcmf_sdiod_skbuff_read(sdiodev, sdiodev->func1,
+						      sdaddr, pkt);
+		}
+
+		if (err) {
+			brcmf_err("membytes transfer failed\n");
+			break;
+		}
+		if (!write)
+			memcpy(data, pkt->data, dsize);
+		skb_trim(pkt, 0);
+
+		/* Adjust for next transfer (if any) */
+		size -= dsize;
+		if (size) {
+			data += dsize;
+			address += dsize;
+			sdaddr = 0;
+			dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
+		}
+	}
+
+	dev_kfree_skb(pkt);
+
+	sdio_release_host(sdiodev->func1);
+
+	return err;
+}
+
+int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, struct sdio_func *func)
+{
+	brcmf_dbg(SDIO, "Enter\n");
+
+	/* Issue abort cmd52 command through F0 */
+	brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_ABORT, func->num, NULL);
+
+	brcmf_dbg(SDIO, "Exit\n");
+	return 0;
+}
+
+void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev)
+{
+	struct sdio_func *func;
+	struct mmc_host *host;
+	uint max_blocks;
+	uint nents;
+	int err;
+
+	func = sdiodev->func2;
+	host = func->card->host;
+	sdiodev->sg_support = host->max_segs > 1;
+	max_blocks = min_t(uint, host->max_blk_count, 511u);
+	sdiodev->max_request_size = min_t(uint, host->max_req_size,
+					  max_blocks * func->cur_blksize);
+	sdiodev->max_segment_count = min_t(uint, host->max_segs,
+					   SG_MAX_SINGLE_ALLOC);
+	sdiodev->max_segment_size = host->max_seg_size;
+
+	if (!sdiodev->sg_support)
+		return;
+
+	nents = max_t(uint, BRCMF_DEFAULT_RXGLOM_SIZE,
+		      sdiodev->settings->bus.sdio.txglomsz);
+	nents += (nents >> 4) + 1;
+
+	WARN_ON(nents > sdiodev->max_segment_count);
+
+	brcmf_dbg(TRACE, "nents=%d\n", nents);
+	err = sg_alloc_table(&sdiodev->sgtable, nents, GFP_KERNEL);
+	if (err < 0) {
+		brcmf_err("allocation failed: disable scatter-gather");
+		sdiodev->sg_support = false;
+	}
+
+	sdiodev->txglomsz = sdiodev->settings->bus.sdio.txglomsz;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int brcmf_sdiod_freezer_attach(struct brcmf_sdio_dev *sdiodev)
+{
+	sdiodev->freezer = kzalloc(sizeof(*sdiodev->freezer), GFP_KERNEL);
+	if (!sdiodev->freezer)
+		return -ENOMEM;
+	atomic_set(&sdiodev->freezer->thread_count, 0);
+	atomic_set(&sdiodev->freezer->freezing, 0);
+	init_waitqueue_head(&sdiodev->freezer->thread_freeze);
+	init_completion(&sdiodev->freezer->resumed);
+	return 0;
+}
+
+static void brcmf_sdiod_freezer_detach(struct brcmf_sdio_dev *sdiodev)
+{
+	if (sdiodev->freezer) {
+		WARN_ON(atomic_read(&sdiodev->freezer->freezing));
+		kfree(sdiodev->freezer);
+	}
+}
+
+static int brcmf_sdiod_freezer_on(struct brcmf_sdio_dev *sdiodev)
+{
+	atomic_t *expect = &sdiodev->freezer->thread_count;
+	int res = 0;
+
+	sdiodev->freezer->frozen_count = 0;
+	reinit_completion(&sdiodev->freezer->resumed);
+	atomic_set(&sdiodev->freezer->freezing, 1);
+	brcmf_sdio_trigger_dpc(sdiodev->bus);
+	wait_event(sdiodev->freezer->thread_freeze,
+		   atomic_read(expect) == sdiodev->freezer->frozen_count);
+	sdio_claim_host(sdiodev->func1);
+	res = brcmf_sdio_sleep(sdiodev->bus, true);
+	sdio_release_host(sdiodev->func1);
+	return res;
+}
+
+static void brcmf_sdiod_freezer_off(struct brcmf_sdio_dev *sdiodev)
+{
+	sdio_claim_host(sdiodev->func1);
+	brcmf_sdio_sleep(sdiodev->bus, false);
+	sdio_release_host(sdiodev->func1);
+	atomic_set(&sdiodev->freezer->freezing, 0);
+	complete_all(&sdiodev->freezer->resumed);
+}
+
+bool brcmf_sdiod_freezing(struct brcmf_sdio_dev *sdiodev)
+{
+	return atomic_read(&sdiodev->freezer->freezing);
+}
+
+void brcmf_sdiod_try_freeze(struct brcmf_sdio_dev *sdiodev)
+{
+	if (!brcmf_sdiod_freezing(sdiodev))
+		return;
+	sdiodev->freezer->frozen_count++;
+	wake_up(&sdiodev->freezer->thread_freeze);
+	wait_for_completion(&sdiodev->freezer->resumed);
+}
+
+void brcmf_sdiod_freezer_count(struct brcmf_sdio_dev *sdiodev)
+{
+	atomic_inc(&sdiodev->freezer->thread_count);
+}
+
+void brcmf_sdiod_freezer_uncount(struct brcmf_sdio_dev *sdiodev)
+{
+	atomic_dec(&sdiodev->freezer->thread_count);
+}
+#else
+static int brcmf_sdiod_freezer_attach(struct brcmf_sdio_dev *sdiodev)
+{
+	return 0;
+}
+
+static void brcmf_sdiod_freezer_detach(struct brcmf_sdio_dev *sdiodev)
+{
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev)
+{
+	sdiodev->state = BRCMF_SDIOD_DOWN;
+	if (sdiodev->bus) {
+		brcmf_sdio_remove(sdiodev->bus);
+		sdiodev->bus = NULL;
+	}
+
+	brcmf_sdiod_freezer_detach(sdiodev);
+
+	/* Disable Function 2 */
+	sdio_claim_host(sdiodev->func2);
+	sdio_disable_func(sdiodev->func2);
+	sdio_release_host(sdiodev->func2);
+
+	/* Disable Function 1 */
+	sdio_claim_host(sdiodev->func1);
+	sdio_disable_func(sdiodev->func1);
+	sdio_release_host(sdiodev->func1);
+
+	sg_free_table(&sdiodev->sgtable);
+	sdiodev->sbwad = 0;
+
+	pm_runtime_allow(sdiodev->func1->card->host->parent);
+	return 0;
+}
+
+static void brcmf_sdiod_host_fixup(struct mmc_host *host)
+{
+	/* runtime-pm powers off the device */
+	pm_runtime_forbid(host->parent);
+	/* avoid removal detection upon resume */
+	host->caps |= MMC_CAP_NONREMOVABLE;
+}
+
+static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
+{
+	int ret = 0;
+
+	sdio_claim_host(sdiodev->func1);
+
+	ret = sdio_set_block_size(sdiodev->func1, SDIO_FUNC1_BLOCKSIZE);
+	if (ret) {
+		brcmf_err("Failed to set F1 blocksize\n");
+		sdio_release_host(sdiodev->func1);
+		goto out;
+	}
+	ret = sdio_set_block_size(sdiodev->func2, SDIO_FUNC2_BLOCKSIZE);
+	if (ret) {
+		brcmf_err("Failed to set F2 blocksize\n");
+		sdio_release_host(sdiodev->func1);
+		goto out;
+	}
+
+	/* increase F2 timeout */
+	sdiodev->func2->enable_timeout = SDIO_WAIT_F2RDY;
+
+	/* Enable Function 1 */
+	ret = sdio_enable_func(sdiodev->func1);
+	sdio_release_host(sdiodev->func1);
+	if (ret) {
+		brcmf_err("Failed to enable F1: err=%d\n", ret);
+		goto out;
+	}
+
+	ret = brcmf_sdiod_freezer_attach(sdiodev);
+	if (ret)
+		goto out;
+
+	/* try to attach to the target device */
+	sdiodev->bus = brcmf_sdio_probe(sdiodev);
+	if (!sdiodev->bus) {
+		ret = -ENODEV;
+		goto out;
+	}
+	brcmf_sdiod_host_fixup(sdiodev->func2->card->host);
+out:
+	if (ret)
+		brcmf_sdiod_remove(sdiodev);
+
+	return ret;
+}
+
+#define BRCMF_SDIO_DEVICE(dev_id)	\
+	{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, dev_id)}
+
+/* devices we support, null terminated */
+static const struct sdio_device_id brcmf_sdmmc_ids[] = {
+	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43143),
+	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43241),
+	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4329),
+	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4330),
+	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4334),
+	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43340),
+	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43341),
+	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43362),
+ 	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43364),
+	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4335_4339),
+	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4339),
+	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43430),
+	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4345),
+	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43455),
+	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354),
+	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4356),
+	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_CYPRESS_4373),
+	{ /* end: all zeroes */ }
+};
+MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
+
+
+static void brcmf_sdiod_acpi_set_power_manageable(struct device *dev,
+						  int val)
+{
+#if IS_ENABLED(CONFIG_ACPI)
+	struct acpi_device *adev;
+
+	adev = ACPI_COMPANION(dev);
+	if (adev)
+		adev->flags.power_manageable = 0;
+#endif
+}
+
+static int brcmf_ops_sdio_probe(struct sdio_func *func,
+				const struct sdio_device_id *id)
+{
+	int err;
+	struct brcmf_sdio_dev *sdiodev;
+	struct brcmf_bus *bus_if;
+	struct device *dev;
+
+	brcmf_dbg(SDIO, "Enter\n");
+	brcmf_dbg(SDIO, "Class=%x\n", func->class);
+	brcmf_dbg(SDIO, "sdio vendor ID: 0x%04x\n", func->vendor);
+	brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
+	brcmf_dbg(SDIO, "Function#: %d\n", func->num);
+
+	dev = &func->dev;
+
+	/* Set MMC_QUIRK_LENIENT_FN0 for this card */
+	func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
+
+	/* prohibit ACPI power management for this device */
+	brcmf_sdiod_acpi_set_power_manageable(dev, 0);
+
+	/* Consume func num 1 but dont do anything with it. */
+	if (func->num == 1)
+		return 0;
+
+	/* Ignore anything but func 2 */
+	if (func->num != 2)
+		return -ENODEV;
+
+	bus_if = kzalloc(sizeof(struct brcmf_bus), GFP_KERNEL);
+	if (!bus_if)
+		return -ENOMEM;
+	sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL);
+	if (!sdiodev) {
+		kfree(bus_if);
+		return -ENOMEM;
+	}
+
+	/* store refs to functions used. mmc_card does
+	 * not hold the F0 function pointer.
+	 */
+	sdiodev->func1 = func->card->sdio_func[0];
+	sdiodev->func2 = func;
+
+	sdiodev->bus_if = bus_if;
+	bus_if->bus_priv.sdio = sdiodev;
+	bus_if->proto_type = BRCMF_PROTO_BCDC;
+	dev_set_drvdata(&func->dev, bus_if);
+	dev_set_drvdata(&sdiodev->func1->dev, bus_if);
+	sdiodev->dev = &sdiodev->func1->dev;
+
+	brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_DOWN);
+
+	brcmf_dbg(SDIO, "F2 found, calling brcmf_sdiod_probe...\n");
+	err = brcmf_sdiod_probe(sdiodev);
+	if (err) {
+		brcmf_err("F2 error, probe failed %d...\n", err);
+		goto fail;
+	}
+
+	brcmf_dbg(SDIO, "F2 init completed...\n");
+	return 0;
+
+fail:
+	dev_set_drvdata(&func->dev, NULL);
+	dev_set_drvdata(&sdiodev->func1->dev, NULL);
+	kfree(sdiodev);
+	kfree(bus_if);
+	return err;
+}
+
+static void brcmf_ops_sdio_remove(struct sdio_func *func)
+{
+	struct brcmf_bus *bus_if;
+	struct brcmf_sdio_dev *sdiodev;
+
+	brcmf_dbg(SDIO, "Enter\n");
+	brcmf_dbg(SDIO, "sdio vendor ID: 0x%04x\n", func->vendor);
+	brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
+	brcmf_dbg(SDIO, "Function: %d\n", func->num);
+
+	bus_if = dev_get_drvdata(&func->dev);
+	if (bus_if) {
+		sdiodev = bus_if->bus_priv.sdio;
+
+		/* start by unregistering irqs */
+		brcmf_sdiod_intr_unregister(sdiodev);
+
+		if (func->num != 1)
+			return;
+
+		/* only proceed with rest of cleanup if func 1 */
+		brcmf_sdiod_remove(sdiodev);
+
+		dev_set_drvdata(&sdiodev->func1->dev, NULL);
+		dev_set_drvdata(&sdiodev->func2->dev, NULL);
+
+		kfree(bus_if);
+		kfree(sdiodev);
+	}
+
+	brcmf_dbg(SDIO, "Exit\n");
+}
+
+void brcmf_sdio_wowl_config(struct device *dev, bool enabled)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+
+	brcmf_dbg(SDIO, "Configuring WOWL, enabled=%d\n", enabled);
+	sdiodev->wowl_enabled = enabled;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int brcmf_ops_sdio_suspend(struct device *dev)
+{
+	struct sdio_func *func;
+	struct brcmf_bus *bus_if;
+	struct brcmf_sdio_dev *sdiodev;
+	mmc_pm_flag_t sdio_flags;
+
+	func = container_of(dev, struct sdio_func, dev);
+	brcmf_dbg(SDIO, "Enter: F%d\n", func->num);
+	if (func->num != 1)
+		return 0;
+
+
+	bus_if = dev_get_drvdata(dev);
+	sdiodev = bus_if->bus_priv.sdio;
+
+	brcmf_sdiod_freezer_on(sdiodev);
+	brcmf_sdio_wd_timer(sdiodev->bus, 0);
+
+	sdio_flags = MMC_PM_KEEP_POWER;
+	if (sdiodev->wowl_enabled) {
+		if (sdiodev->settings->bus.sdio.oob_irq_supported)
+			enable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr);
+		else
+			sdio_flags |= MMC_PM_WAKE_SDIO_IRQ;
+	}
+	if (sdio_set_host_pm_flags(sdiodev->func1, sdio_flags))
+		brcmf_err("Failed to set pm_flags %x\n", sdio_flags);
+	return 0;
+}
+
+static int brcmf_ops_sdio_resume(struct device *dev)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+	struct sdio_func *func = container_of(dev, struct sdio_func, dev);
+
+	brcmf_dbg(SDIO, "Enter: F%d\n", func->num);
+	if (func->num != 2)
+		return 0;
+
+	brcmf_sdiod_freezer_off(sdiodev);
+	return 0;
+}
+
+static const struct dev_pm_ops brcmf_sdio_pm_ops = {
+	.suspend	= brcmf_ops_sdio_suspend,
+	.resume		= brcmf_ops_sdio_resume,
+};
+#endif	/* CONFIG_PM_SLEEP */
+
+static struct sdio_driver brcmf_sdmmc_driver = {
+	.probe = brcmf_ops_sdio_probe,
+	.remove = brcmf_ops_sdio_remove,
+	.name = KBUILD_MODNAME,
+	.id_table = brcmf_sdmmc_ids,
+	.drv = {
+		.owner = THIS_MODULE,
+#ifdef CONFIG_PM_SLEEP
+		.pm = &brcmf_sdio_pm_ops,
+#endif	/* CONFIG_PM_SLEEP */
+		.coredump = brcmf_dev_coredump,
+	},
+};
+
+void brcmf_sdio_register(void)
+{
+	int ret;
+
+	ret = sdio_register_driver(&brcmf_sdmmc_driver);
+	if (ret)
+		brcmf_err("sdio_register_driver failed: %d\n", ret);
+}
+
+void brcmf_sdio_exit(void)
+{
+	brcmf_dbg(SDIO, "Enter\n");
+
+	sdio_unregister_driver(&brcmf_sdmmc_driver);
+}
+
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c
new file mode 100644
index 0000000..372363a
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c
@@ -0,0 +1,493 @@
+/*
+ * Copyright (c) 2013 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <net/cfg80211.h>
+
+#include <brcmu_wifi.h>
+#include <brcmu_utils.h>
+#include <defs.h>
+#include "core.h"
+#include "debug.h"
+#include "fwil.h"
+#include "fwil_types.h"
+#include "btcoex.h"
+#include "p2p.h"
+#include "cfg80211.h"
+
+/* T1 start SCO/eSCO priority suppression */
+#define BRCMF_BTCOEX_OPPR_WIN_TIME   msecs_to_jiffies(2000)
+
+/* BT registers values during DHCP */
+#define BRCMF_BT_DHCP_REG50 0x8022
+#define BRCMF_BT_DHCP_REG51 0
+#define BRCMF_BT_DHCP_REG64 0
+#define BRCMF_BT_DHCP_REG65 0
+#define BRCMF_BT_DHCP_REG71 0
+#define BRCMF_BT_DHCP_REG66 0x2710
+#define BRCMF_BT_DHCP_REG41 0x33
+#define BRCMF_BT_DHCP_REG68 0x190
+
+/* number of samples for SCO detection */
+#define BRCMF_BT_SCO_SAMPLES 12
+
+/**
+* enum brcmf_btcoex_state - BT coex DHCP state machine states
+* @BRCMF_BT_DHCP_IDLE: DCHP is idle
+* @BRCMF_BT_DHCP_START: DHCP started, wait before
+*	boosting wifi priority
+* @BRCMF_BT_DHCP_OPPR_WIN: graceful DHCP opportunity ended,
+*	boost wifi priority
+* @BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT: wifi priority boost end,
+*	restore defaults
+*/
+enum brcmf_btcoex_state {
+	BRCMF_BT_DHCP_IDLE,
+	BRCMF_BT_DHCP_START,
+	BRCMF_BT_DHCP_OPPR_WIN,
+	BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT
+};
+
+/**
+ * struct brcmf_btcoex_info - BT coex related information
+ * @vif: interface for which request was done.
+ * @timer: timer for DHCP state machine
+ * @timeout: configured timeout.
+ * @timer_on:  DHCP timer active
+ * @dhcp_done: DHCP finished before T1/T2 timer expiration
+ * @bt_state: DHCP state machine state
+ * @work: DHCP state machine work
+ * @cfg: driver private data for cfg80211 interface
+ * @reg66: saved value of btc_params 66
+ * @reg41: saved value of btc_params 41
+ * @reg68: saved value of btc_params 68
+ * @saved_regs_part1: flag indicating regs 66,41,68
+ *	have been saved
+ * @reg51: saved value of btc_params 51
+ * @reg64: saved value of btc_params 64
+ * @reg65: saved value of btc_params 65
+ * @reg71: saved value of btc_params 71
+ * @saved_regs_part1: flag indicating regs 50,51,64,65,71
+ *	have been saved
+ */
+struct brcmf_btcoex_info {
+	struct brcmf_cfg80211_vif *vif;
+	struct timer_list timer;
+	u16 timeout;
+	bool timer_on;
+	bool dhcp_done;
+	enum brcmf_btcoex_state bt_state;
+	struct work_struct work;
+	struct brcmf_cfg80211_info *cfg;
+	u32 reg66;
+	u32 reg41;
+	u32 reg68;
+	bool saved_regs_part1;
+	u32 reg50;
+	u32 reg51;
+	u32 reg64;
+	u32 reg65;
+	u32 reg71;
+	bool saved_regs_part2;
+};
+
+/**
+ * brcmf_btcoex_params_write() - write btc_params firmware variable
+ * @ifp: interface
+ * @addr: btc_params register number
+ * @data: data to write
+ */
+static s32 brcmf_btcoex_params_write(struct brcmf_if *ifp, u32 addr, u32 data)
+{
+	struct {
+		__le32 addr;
+		__le32 data;
+	} reg_write;
+
+	reg_write.addr = cpu_to_le32(addr);
+	reg_write.data = cpu_to_le32(data);
+	return brcmf_fil_iovar_data_set(ifp, "btc_params",
+					&reg_write, sizeof(reg_write));
+}
+
+/**
+ * brcmf_btcoex_params_read() - read btc_params firmware variable
+ * @ifp: interface
+ * @addr: btc_params register number
+ * @data: read data
+ */
+static s32 brcmf_btcoex_params_read(struct brcmf_if *ifp, u32 addr, u32 *data)
+{
+	*data = addr;
+
+	return brcmf_fil_iovar_int_get(ifp, "btc_params", data);
+}
+
+/**
+ * brcmf_btcoex_boost_wifi() - control BT SCO/eSCO parameters
+ * @btci: BT coex info
+ * @trump_sco:
+ *	true - set SCO/eSCO parameters for compatibility
+ *		during DHCP window
+ *	false - restore saved parameter values
+ *
+ * Enhanced BT COEX settings for eSCO compatibility during DHCP window
+ */
+static void brcmf_btcoex_boost_wifi(struct brcmf_btcoex_info *btci,
+				    bool trump_sco)
+{
+	struct brcmf_if *ifp = brcmf_get_ifp(btci->cfg->pub, 0);
+
+	if (trump_sco && !btci->saved_regs_part2) {
+		/* this should reduce eSCO agressive
+		 * retransmit w/o breaking it
+		 */
+
+		/* save current */
+		brcmf_dbg(INFO, "new SCO/eSCO coex algo {save & override}\n");
+		brcmf_btcoex_params_read(ifp, 50, &btci->reg50);
+		brcmf_btcoex_params_read(ifp, 51, &btci->reg51);
+		brcmf_btcoex_params_read(ifp, 64, &btci->reg64);
+		brcmf_btcoex_params_read(ifp, 65, &btci->reg65);
+		brcmf_btcoex_params_read(ifp, 71, &btci->reg71);
+
+		btci->saved_regs_part2 = true;
+		brcmf_dbg(INFO,
+			  "saved bt_params[50,51,64,65,71]: 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+			  btci->reg50, btci->reg51, btci->reg64,
+			  btci->reg65, btci->reg71);
+
+		/* pacify the eSco   */
+		brcmf_btcoex_params_write(ifp, 50, BRCMF_BT_DHCP_REG50);
+		brcmf_btcoex_params_write(ifp, 51, BRCMF_BT_DHCP_REG51);
+		brcmf_btcoex_params_write(ifp, 64, BRCMF_BT_DHCP_REG64);
+		brcmf_btcoex_params_write(ifp, 65, BRCMF_BT_DHCP_REG65);
+		brcmf_btcoex_params_write(ifp, 71, BRCMF_BT_DHCP_REG71);
+
+	} else if (btci->saved_regs_part2) {
+		/* restore previously saved bt params */
+		brcmf_dbg(INFO, "Do new SCO/eSCO coex algo {restore}\n");
+		brcmf_btcoex_params_write(ifp, 50, btci->reg50);
+		brcmf_btcoex_params_write(ifp, 51, btci->reg51);
+		brcmf_btcoex_params_write(ifp, 64, btci->reg64);
+		brcmf_btcoex_params_write(ifp, 65, btci->reg65);
+		brcmf_btcoex_params_write(ifp, 71, btci->reg71);
+
+		brcmf_dbg(INFO,
+			  "restored bt_params[50,51,64,65,71]: 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+			  btci->reg50, btci->reg51, btci->reg64,
+			  btci->reg65, btci->reg71);
+
+		btci->saved_regs_part2 = false;
+	} else {
+		brcmf_dbg(INFO, "attempted to restore not saved BTCOEX params\n");
+	}
+}
+
+/**
+ * brcmf_btcoex_is_sco_active() - check if SCO/eSCO is active
+ * @ifp: interface
+ *
+ * return: true if SCO/eSCO session is active
+ */
+static bool brcmf_btcoex_is_sco_active(struct brcmf_if *ifp)
+{
+	int ioc_res = 0;
+	bool res = false;
+	int sco_id_cnt = 0;
+	u32 param27;
+	int i;
+
+	for (i = 0; i < BRCMF_BT_SCO_SAMPLES; i++) {
+		ioc_res = brcmf_btcoex_params_read(ifp, 27, &param27);
+
+		if (ioc_res < 0) {
+			brcmf_err("ioc read btc params error\n");
+			break;
+		}
+
+		brcmf_dbg(INFO, "sample[%d], btc_params 27:%x\n", i, param27);
+
+		if ((param27 & 0x6) == 2) { /* count both sco & esco  */
+			sco_id_cnt++;
+		}
+
+		if (sco_id_cnt > 2) {
+			brcmf_dbg(INFO,
+				  "sco/esco detected, pkt id_cnt:%d samples:%d\n",
+				  sco_id_cnt, i);
+			res = true;
+			break;
+		}
+	}
+	brcmf_dbg(TRACE, "exit: result=%d\n", res);
+	return res;
+}
+
+/**
+ * btcmf_btcoex_save_part1() - save first step parameters.
+ */
+static void btcmf_btcoex_save_part1(struct brcmf_btcoex_info *btci)
+{
+	struct brcmf_if *ifp = btci->vif->ifp;
+
+	if (!btci->saved_regs_part1) {
+		/* Retrieve and save original reg value */
+		brcmf_btcoex_params_read(ifp, 66, &btci->reg66);
+		brcmf_btcoex_params_read(ifp, 41, &btci->reg41);
+		brcmf_btcoex_params_read(ifp, 68, &btci->reg68);
+		btci->saved_regs_part1 = true;
+		brcmf_dbg(INFO,
+			  "saved btc_params regs (66,41,68) 0x%x 0x%x 0x%x\n",
+			  btci->reg66, btci->reg41,
+			  btci->reg68);
+	}
+}
+
+/**
+ * brcmf_btcoex_restore_part1() - restore first step parameters.
+ */
+static void brcmf_btcoex_restore_part1(struct brcmf_btcoex_info *btci)
+{
+	struct brcmf_if *ifp;
+
+	if (btci->saved_regs_part1) {
+		btci->saved_regs_part1 = false;
+		ifp = btci->vif->ifp;
+		brcmf_btcoex_params_write(ifp, 66, btci->reg66);
+		brcmf_btcoex_params_write(ifp, 41, btci->reg41);
+		brcmf_btcoex_params_write(ifp, 68, btci->reg68);
+		brcmf_dbg(INFO,
+			  "restored btc_params regs {66,41,68} 0x%x 0x%x 0x%x\n",
+			  btci->reg66, btci->reg41,
+			  btci->reg68);
+	}
+}
+
+/**
+ * brcmf_btcoex_timerfunc() - BT coex timer callback
+ */
+static void brcmf_btcoex_timerfunc(struct timer_list *t)
+{
+	struct brcmf_btcoex_info *bt_local = from_timer(bt_local, t, timer);
+	brcmf_dbg(TRACE, "enter\n");
+
+	bt_local->timer_on = false;
+	schedule_work(&bt_local->work);
+}
+
+/**
+ * brcmf_btcoex_handler() - BT coex state machine work handler
+ * @work: work
+ */
+static void brcmf_btcoex_handler(struct work_struct *work)
+{
+	struct brcmf_btcoex_info *btci;
+	btci = container_of(work, struct brcmf_btcoex_info, work);
+	if (btci->timer_on) {
+		btci->timer_on = false;
+		del_timer_sync(&btci->timer);
+	}
+
+	switch (btci->bt_state) {
+	case BRCMF_BT_DHCP_START:
+		/* DHCP started provide OPPORTUNITY window
+		   to get DHCP address
+		*/
+		brcmf_dbg(INFO, "DHCP started\n");
+		btci->bt_state = BRCMF_BT_DHCP_OPPR_WIN;
+		if (btci->timeout < BRCMF_BTCOEX_OPPR_WIN_TIME) {
+			mod_timer(&btci->timer, btci->timer.expires);
+		} else {
+			btci->timeout -= BRCMF_BTCOEX_OPPR_WIN_TIME;
+			mod_timer(&btci->timer,
+				  jiffies + BRCMF_BTCOEX_OPPR_WIN_TIME);
+		}
+		btci->timer_on = true;
+		break;
+
+	case BRCMF_BT_DHCP_OPPR_WIN:
+		if (btci->dhcp_done) {
+			brcmf_dbg(INFO, "DHCP done before T1 expiration\n");
+			goto idle;
+		}
+
+		/* DHCP is not over yet, start lowering BT priority */
+		brcmf_dbg(INFO, "DHCP T1:%d expired\n",
+			  jiffies_to_msecs(BRCMF_BTCOEX_OPPR_WIN_TIME));
+		brcmf_btcoex_boost_wifi(btci, true);
+
+		btci->bt_state = BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT;
+		mod_timer(&btci->timer, jiffies + btci->timeout);
+		btci->timer_on = true;
+		break;
+
+	case BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT:
+		if (btci->dhcp_done)
+			brcmf_dbg(INFO, "DHCP done before T2 expiration\n");
+		else
+			brcmf_dbg(INFO, "DHCP T2:%d expired\n",
+				  BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT);
+
+		goto idle;
+
+	default:
+		brcmf_err("invalid state=%d !!!\n", btci->bt_state);
+		goto idle;
+	}
+
+	return;
+
+idle:
+	btci->bt_state = BRCMF_BT_DHCP_IDLE;
+	btci->timer_on = false;
+	brcmf_btcoex_boost_wifi(btci, false);
+	cfg80211_crit_proto_stopped(&btci->vif->wdev, GFP_KERNEL);
+	brcmf_btcoex_restore_part1(btci);
+	btci->vif = NULL;
+}
+
+/**
+ * brcmf_btcoex_attach() - initialize BT coex data
+ * @cfg: driver private cfg80211 data
+ *
+ * return: 0 on success
+ */
+int brcmf_btcoex_attach(struct brcmf_cfg80211_info *cfg)
+{
+	struct brcmf_btcoex_info *btci = NULL;
+	brcmf_dbg(TRACE, "enter\n");
+
+	btci = kmalloc(sizeof(struct brcmf_btcoex_info), GFP_KERNEL);
+	if (!btci)
+		return -ENOMEM;
+
+	btci->bt_state = BRCMF_BT_DHCP_IDLE;
+
+	/* Set up timer for BT  */
+	btci->timer_on = false;
+	btci->timeout = BRCMF_BTCOEX_OPPR_WIN_TIME;
+	timer_setup(&btci->timer, brcmf_btcoex_timerfunc, 0);
+	btci->cfg = cfg;
+	btci->saved_regs_part1 = false;
+	btci->saved_regs_part2 = false;
+
+	INIT_WORK(&btci->work, brcmf_btcoex_handler);
+
+	cfg->btcoex = btci;
+	return 0;
+}
+
+/**
+ * brcmf_btcoex_detach - clean BT coex data
+ * @cfg: driver private cfg80211 data
+ */
+void brcmf_btcoex_detach(struct brcmf_cfg80211_info *cfg)
+{
+	brcmf_dbg(TRACE, "enter\n");
+
+	if (!cfg->btcoex)
+		return;
+
+	if (cfg->btcoex->timer_on) {
+		cfg->btcoex->timer_on = false;
+		del_timer_sync(&cfg->btcoex->timer);
+	}
+
+	cancel_work_sync(&cfg->btcoex->work);
+
+	brcmf_btcoex_boost_wifi(cfg->btcoex, false);
+	brcmf_btcoex_restore_part1(cfg->btcoex);
+
+	kfree(cfg->btcoex);
+	cfg->btcoex = NULL;
+}
+
+static void brcmf_btcoex_dhcp_start(struct brcmf_btcoex_info *btci)
+{
+	struct brcmf_if *ifp = btci->vif->ifp;
+
+	btcmf_btcoex_save_part1(btci);
+	/* set new regs values */
+	brcmf_btcoex_params_write(ifp, 66, BRCMF_BT_DHCP_REG66);
+	brcmf_btcoex_params_write(ifp, 41, BRCMF_BT_DHCP_REG41);
+	brcmf_btcoex_params_write(ifp, 68, BRCMF_BT_DHCP_REG68);
+	btci->dhcp_done = false;
+	btci->bt_state = BRCMF_BT_DHCP_START;
+	schedule_work(&btci->work);
+	brcmf_dbg(TRACE, "enable BT DHCP Timer\n");
+}
+
+static void brcmf_btcoex_dhcp_end(struct brcmf_btcoex_info *btci)
+{
+	/* Stop any bt timer because DHCP session is done */
+	btci->dhcp_done = true;
+	if (btci->timer_on) {
+		brcmf_dbg(INFO, "disable BT DHCP Timer\n");
+		btci->timer_on = false;
+		del_timer_sync(&btci->timer);
+
+		/* schedule worker if transition to IDLE is needed */
+		if (btci->bt_state != BRCMF_BT_DHCP_IDLE) {
+			brcmf_dbg(INFO, "bt_state:%d\n",
+				  btci->bt_state);
+			schedule_work(&btci->work);
+		}
+	} else {
+		/* Restore original values */
+		brcmf_btcoex_restore_part1(btci);
+	}
+}
+
+/**
+ * brcmf_btcoex_set_mode - set BT coex mode
+ * @cfg: driver private cfg80211 data
+ * @mode: Wifi-Bluetooth coexistence mode
+ *
+ * return: 0 on success
+ */
+int brcmf_btcoex_set_mode(struct brcmf_cfg80211_vif *vif,
+			  enum brcmf_btcoex_mode mode, u16 duration)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(vif->wdev.wiphy);
+	struct brcmf_btcoex_info *btci = cfg->btcoex;
+	struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
+
+	switch (mode) {
+	case BRCMF_BTCOEX_DISABLED:
+		brcmf_dbg(INFO, "DHCP session starts\n");
+		if (btci->bt_state != BRCMF_BT_DHCP_IDLE)
+			return -EBUSY;
+		/* Start BT timer only for SCO connection */
+		if (brcmf_btcoex_is_sco_active(ifp)) {
+			btci->timeout = msecs_to_jiffies(duration);
+			btci->vif = vif;
+			brcmf_btcoex_dhcp_start(btci);
+		}
+		break;
+
+	case BRCMF_BTCOEX_ENABLED:
+		brcmf_dbg(INFO, "DHCP session ends\n");
+		if (btci->bt_state != BRCMF_BT_DHCP_IDLE &&
+		    vif == btci->vif) {
+			brcmf_btcoex_dhcp_end(btci);
+		}
+		break;
+	default:
+		brcmf_dbg(INFO, "Unknown mode, ignored\n");
+	}
+	return 0;
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.h
new file mode 100644
index 0000000..19647c6
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef WL_BTCOEX_H_
+#define WL_BTCOEX_H_
+
+enum brcmf_btcoex_mode {
+	BRCMF_BTCOEX_DISABLED,
+	BRCMF_BTCOEX_ENABLED
+};
+
+int brcmf_btcoex_attach(struct brcmf_cfg80211_info *cfg);
+void brcmf_btcoex_detach(struct brcmf_cfg80211_info *cfg);
+int brcmf_btcoex_set_mode(struct brcmf_cfg80211_vif *vif,
+			  enum brcmf_btcoex_mode mode, u16 duration);
+
+#endif /* WL_BTCOEX_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
new file mode 100644
index 0000000..c496518
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef BRCMFMAC_BUS_H
+#define BRCMFMAC_BUS_H
+
+#include "debug.h"
+
+/* IDs of the 6 default common rings of msgbuf protocol */
+#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT	0
+#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT		1
+#define BRCMF_H2D_MSGRING_FLOWRING_IDSTART	2
+#define BRCMF_D2H_MSGRING_CONTROL_COMPLETE	2
+#define BRCMF_D2H_MSGRING_TX_COMPLETE		3
+#define BRCMF_D2H_MSGRING_RX_COMPLETE		4
+
+
+#define BRCMF_NROF_H2D_COMMON_MSGRINGS		2
+#define BRCMF_NROF_D2H_COMMON_MSGRINGS		3
+#define BRCMF_NROF_COMMON_MSGRINGS	(BRCMF_NROF_H2D_COMMON_MSGRINGS + \
+					 BRCMF_NROF_D2H_COMMON_MSGRINGS)
+
+/* The level of bus communication with the dongle */
+enum brcmf_bus_state {
+	BRCMF_BUS_DOWN,		/* Not ready for frame transfers */
+	BRCMF_BUS_UP		/* Ready for frame transfers */
+};
+
+/* The level of bus communication with the dongle */
+enum brcmf_bus_protocol_type {
+	BRCMF_PROTO_BCDC,
+	BRCMF_PROTO_MSGBUF
+};
+
+struct brcmf_mp_device;
+
+struct brcmf_bus_dcmd {
+	char *name;
+	char *param;
+	int param_len;
+	struct list_head list;
+};
+
+/**
+ * struct brcmf_bus_ops - bus callback operations.
+ *
+ * @preinit: execute bus/device specific dongle init commands (optional).
+ * @init: prepare for communication with dongle.
+ * @stop: clear pending frames, disable data flow.
+ * @txdata: send a data frame to the dongle. When the data
+ *	has been transferred, the common driver must be
+ *	notified using brcmf_txcomplete(). The common
+ *	driver calls this function with interrupts
+ *	disabled.
+ * @txctl: transmit a control request message to dongle.
+ * @rxctl: receive a control response message from dongle.
+ * @gettxq: obtain a reference of bus transmit queue (optional).
+ * @wowl_config: specify if dongle is configured for wowl when going to suspend
+ * @get_ramsize: obtain size of device memory.
+ * @get_memdump: obtain device memory dump in provided buffer.
+ * @get_fwname: obtain firmware name.
+ *
+ * This structure provides an abstract interface towards the
+ * bus specific driver. For control messages to common driver
+ * will assure there is only one active transaction. Unless
+ * indicated otherwise these callbacks are mandatory.
+ */
+struct brcmf_bus_ops {
+	int (*preinit)(struct device *dev);
+	void (*stop)(struct device *dev);
+	int (*txdata)(struct device *dev, struct sk_buff *skb);
+	int (*txctl)(struct device *dev, unsigned char *msg, uint len);
+	int (*rxctl)(struct device *dev, unsigned char *msg, uint len);
+	struct pktq * (*gettxq)(struct device *dev);
+	void (*wowl_config)(struct device *dev, bool enabled);
+	size_t (*get_ramsize)(struct device *dev);
+	int (*get_memdump)(struct device *dev, void *data, size_t len);
+	int (*get_fwname)(struct device *dev, const char *ext,
+			  unsigned char *fw_name);
+};
+
+
+/**
+ * struct brcmf_bus_msgbuf - bus ringbuf if in case of msgbuf.
+ *
+ * @commonrings: commonrings which are always there.
+ * @flowrings: commonrings which are dynamically created and destroyed for data.
+ * @rx_dataoffset: if set then all rx data has this this offset.
+ * @max_rxbufpost: maximum number of buffers to post for rx.
+ * @max_flowrings: maximum number of tx flow rings supported.
+ * @max_submissionrings: maximum number of submission rings(h2d) supported.
+ * @max_completionrings: maximum number of completion rings(d2h) supported.
+ */
+struct brcmf_bus_msgbuf {
+	struct brcmf_commonring *commonrings[BRCMF_NROF_COMMON_MSGRINGS];
+	struct brcmf_commonring **flowrings;
+	u32 rx_dataoffset;
+	u32 max_rxbufpost;
+	u16 max_flowrings;
+	u16 max_submissionrings;
+	u16 max_completionrings;
+};
+
+
+/**
+ * struct brcmf_bus_stats - bus statistic counters.
+ *
+ * @pktcowed: packets cowed for extra headroom/unorphan.
+ * @pktcow_failed: packets dropped due to failed cow-ing.
+ */
+struct brcmf_bus_stats {
+	atomic_t pktcowed;
+	atomic_t pktcow_failed;
+};
+
+/**
+ * struct brcmf_bus - interface structure between common and bus layer
+ *
+ * @bus_priv: pointer to private bus device.
+ * @proto_type: protocol type, bcdc or msgbuf
+ * @dev: device pointer of bus device.
+ * @drvr: public driver information.
+ * @state: operational state of the bus interface.
+ * @stats: statistics shared between common and bus layer.
+ * @maxctl: maximum size for rxctl request message.
+ * @chip: device identifier of the dongle chip.
+ * @always_use_fws_queue: bus wants use queue also when fwsignal is inactive.
+ * @wowl_supported: is wowl supported by bus driver.
+ * @chiprev: revision of the dongle chip.
+ * @msgbuf: msgbuf protocol parameters provided by bus layer.
+ */
+struct brcmf_bus {
+	union {
+		struct brcmf_sdio_dev *sdio;
+		struct brcmf_usbdev *usb;
+		struct brcmf_pciedev *pcie;
+	} bus_priv;
+	enum brcmf_bus_protocol_type proto_type;
+	struct device *dev;
+	struct brcmf_pub *drvr;
+	enum brcmf_bus_state state;
+	struct brcmf_bus_stats stats;
+	uint maxctl;
+	u32 chip;
+	u32 chiprev;
+	bool always_use_fws_queue;
+	bool wowl_supported;
+
+	const struct brcmf_bus_ops *ops;
+	struct brcmf_bus_msgbuf *msgbuf;
+};
+
+/*
+ * callback wrappers
+ */
+static inline int brcmf_bus_preinit(struct brcmf_bus *bus)
+{
+	if (!bus->ops->preinit)
+		return 0;
+	return bus->ops->preinit(bus->dev);
+}
+
+static inline void brcmf_bus_stop(struct brcmf_bus *bus)
+{
+	bus->ops->stop(bus->dev);
+}
+
+static inline int brcmf_bus_txdata(struct brcmf_bus *bus, struct sk_buff *skb)
+{
+	return bus->ops->txdata(bus->dev, skb);
+}
+
+static inline
+int brcmf_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint len)
+{
+	return bus->ops->txctl(bus->dev, msg, len);
+}
+
+static inline
+int brcmf_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint len)
+{
+	return bus->ops->rxctl(bus->dev, msg, len);
+}
+
+static inline
+struct pktq *brcmf_bus_gettxq(struct brcmf_bus *bus)
+{
+	if (!bus->ops->gettxq)
+		return ERR_PTR(-ENOENT);
+
+	return bus->ops->gettxq(bus->dev);
+}
+
+static inline
+void brcmf_bus_wowl_config(struct brcmf_bus *bus, bool enabled)
+{
+	if (bus->ops->wowl_config)
+		bus->ops->wowl_config(bus->dev, enabled);
+}
+
+static inline size_t brcmf_bus_get_ramsize(struct brcmf_bus *bus)
+{
+	if (!bus->ops->get_ramsize)
+		return 0;
+
+	return bus->ops->get_ramsize(bus->dev);
+}
+
+static inline
+int brcmf_bus_get_memdump(struct brcmf_bus *bus, void *data, size_t len)
+{
+	if (!bus->ops->get_memdump)
+		return -EOPNOTSUPP;
+
+	return bus->ops->get_memdump(bus->dev, data, len);
+}
+
+static inline
+int brcmf_bus_get_fwname(struct brcmf_bus *bus, const char *ext,
+			 unsigned char *fw_name)
+{
+	return bus->ops->get_fwname(bus->dev, ext, fw_name);
+}
+
+/*
+ * interface functions from common layer
+ */
+
+/* Receive frame for delivery to OS.  Callee disposes of rxp. */
+void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp, bool handle_event);
+/* Receive async event packet from firmware. Callee disposes of rxp. */
+void brcmf_rx_event(struct device *dev, struct sk_buff *rxp);
+
+/* Indication from bus module regarding presence/insertion of dongle. */
+int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings);
+/* Indication from bus module regarding removal/absence of dongle */
+void brcmf_detach(struct device *dev);
+/* Indication from bus module that dongle should be reset */
+void brcmf_dev_reset(struct device *dev);
+/* Request from bus module to initiate a coredump */
+void brcmf_dev_coredump(struct device *dev);
+
+/* Configure the "global" bus state used by upper layers */
+void brcmf_bus_change_state(struct brcmf_bus *bus, enum brcmf_bus_state state);
+
+s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len);
+void brcmf_bus_add_txhdrlen(struct device *dev, uint len);
+
+#ifdef CONFIG_BRCMFMAC_SDIO
+void brcmf_sdio_exit(void);
+void brcmf_sdio_register(void);
+#endif
+#ifdef CONFIG_BRCMFMAC_USB
+void brcmf_usb_exit(void);
+void brcmf_usb_register(void);
+#endif
+
+#endif /* BRCMFMAC_BUS_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
new file mode 100644
index 0000000..64a794b
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -0,0 +1,7063 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* Toplevel file. Relies on dhd_linux.c to send commands to the dongle. */
+
+#include <linux/kernel.h>
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <net/cfg80211.h>
+#include <net/netlink.h>
+
+#include <brcmu_utils.h>
+#include <defs.h>
+#include <brcmu_wifi.h>
+#include "core.h"
+#include "debug.h"
+#include "tracepoint.h"
+#include "fwil_types.h"
+#include "p2p.h"
+#include "btcoex.h"
+#include "pno.h"
+#include "cfg80211.h"
+#include "feature.h"
+#include "fwil.h"
+#include "proto.h"
+#include "vendor.h"
+#include "bus.h"
+#include "common.h"
+
+#define BRCMF_SCAN_IE_LEN_MAX		2048
+
+#define WPA_OUI				"\x00\x50\xF2"	/* WPA OUI */
+#define WPA_OUI_TYPE			1
+#define RSN_OUI				"\x00\x0F\xAC"	/* RSN OUI */
+#define	WME_OUI_TYPE			2
+#define WPS_OUI_TYPE			4
+
+#define VS_IE_FIXED_HDR_LEN		6
+#define WPA_IE_VERSION_LEN		2
+#define WPA_IE_MIN_OUI_LEN		4
+#define WPA_IE_SUITE_COUNT_LEN		2
+
+#define WPA_CIPHER_NONE			0	/* None */
+#define WPA_CIPHER_WEP_40		1	/* WEP (40-bit) */
+#define WPA_CIPHER_TKIP			2	/* TKIP: default for WPA */
+#define WPA_CIPHER_AES_CCM		4	/* AES (CCM) */
+#define WPA_CIPHER_WEP_104		5	/* WEP (104-bit) */
+
+#define RSN_AKM_NONE			0	/* None (IBSS) */
+#define RSN_AKM_UNSPECIFIED		1	/* Over 802.1x */
+#define RSN_AKM_PSK			2	/* Pre-shared Key */
+#define RSN_AKM_SHA256_1X		5	/* SHA256, 802.1X */
+#define RSN_AKM_SHA256_PSK		6	/* SHA256, Pre-shared Key */
+#define RSN_CAP_LEN			2	/* Length of RSN capabilities */
+#define RSN_CAP_PTK_REPLAY_CNTR_MASK	(BIT(2) | BIT(3))
+#define RSN_CAP_MFPR_MASK		BIT(6)
+#define RSN_CAP_MFPC_MASK		BIT(7)
+#define RSN_PMKID_COUNT_LEN		2
+
+#define VNDR_IE_CMD_LEN			4	/* length of the set command
+						 * string :"add", "del" (+ NUL)
+						 */
+#define VNDR_IE_COUNT_OFFSET		4
+#define VNDR_IE_PKTFLAG_OFFSET		8
+#define VNDR_IE_VSIE_OFFSET		12
+#define VNDR_IE_HDR_SIZE		12
+#define VNDR_IE_PARSE_LIMIT		5
+
+#define	DOT11_MGMT_HDR_LEN		24	/* d11 management header len */
+#define	DOT11_BCN_PRB_FIXED_LEN		12	/* beacon/probe fixed length */
+
+#define BRCMF_SCAN_JOIN_ACTIVE_DWELL_TIME_MS	320
+#define BRCMF_SCAN_JOIN_PASSIVE_DWELL_TIME_MS	400
+#define BRCMF_SCAN_JOIN_PROBE_INTERVAL_MS	20
+
+#define BRCMF_SCAN_CHANNEL_TIME		40
+#define BRCMF_SCAN_UNASSOC_TIME		40
+#define BRCMF_SCAN_PASSIVE_TIME		120
+
+#define BRCMF_ND_INFO_TIMEOUT		msecs_to_jiffies(2000)
+
+#define BRCMF_ASSOC_PARAMS_FIXED_SIZE \
+	(sizeof(struct brcmf_assoc_params_le) - sizeof(u16))
+
+static bool check_vif_up(struct brcmf_cfg80211_vif *vif)
+{
+	if (!test_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state)) {
+		brcmf_dbg(INFO, "device is not ready : status (%lu)\n",
+			  vif->sme_state);
+		return false;
+	}
+	return true;
+}
+
+#define RATE_TO_BASE100KBPS(rate)   (((rate) * 10) / 2)
+#define RATETAB_ENT(_rateid, _flags) \
+	{                                                               \
+		.bitrate        = RATE_TO_BASE100KBPS(_rateid),     \
+		.hw_value       = (_rateid),                            \
+		.flags          = (_flags),                             \
+	}
+
+static struct ieee80211_rate __wl_rates[] = {
+	RATETAB_ENT(BRCM_RATE_1M, 0),
+	RATETAB_ENT(BRCM_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATETAB_ENT(BRCM_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATETAB_ENT(BRCM_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATETAB_ENT(BRCM_RATE_6M, 0),
+	RATETAB_ENT(BRCM_RATE_9M, 0),
+	RATETAB_ENT(BRCM_RATE_12M, 0),
+	RATETAB_ENT(BRCM_RATE_18M, 0),
+	RATETAB_ENT(BRCM_RATE_24M, 0),
+	RATETAB_ENT(BRCM_RATE_36M, 0),
+	RATETAB_ENT(BRCM_RATE_48M, 0),
+	RATETAB_ENT(BRCM_RATE_54M, 0),
+};
+
+#define wl_g_rates		(__wl_rates + 0)
+#define wl_g_rates_size		ARRAY_SIZE(__wl_rates)
+#define wl_a_rates		(__wl_rates + 4)
+#define wl_a_rates_size		(wl_g_rates_size - 4)
+
+#define CHAN2G(_channel, _freq) {				\
+	.band			= NL80211_BAND_2GHZ,		\
+	.center_freq		= (_freq),			\
+	.hw_value		= (_channel),			\
+	.max_antenna_gain	= 0,				\
+	.max_power		= 30,				\
+}
+
+#define CHAN5G(_channel) {					\
+	.band			= NL80211_BAND_5GHZ,		\
+	.center_freq		= 5000 + (5 * (_channel)),	\
+	.hw_value		= (_channel),			\
+	.max_antenna_gain	= 0,				\
+	.max_power		= 30,				\
+}
+
+static struct ieee80211_channel __wl_2ghz_channels[] = {
+	CHAN2G(1, 2412), CHAN2G(2, 2417), CHAN2G(3, 2422), CHAN2G(4, 2427),
+	CHAN2G(5, 2432), CHAN2G(6, 2437), CHAN2G(7, 2442), CHAN2G(8, 2447),
+	CHAN2G(9, 2452), CHAN2G(10, 2457), CHAN2G(11, 2462), CHAN2G(12, 2467),
+	CHAN2G(13, 2472), CHAN2G(14, 2484)
+};
+
+static struct ieee80211_channel __wl_5ghz_channels[] = {
+	CHAN5G(34), CHAN5G(36), CHAN5G(38), CHAN5G(40), CHAN5G(42),
+	CHAN5G(44), CHAN5G(46), CHAN5G(48), CHAN5G(52), CHAN5G(56),
+	CHAN5G(60), CHAN5G(64), CHAN5G(100), CHAN5G(104), CHAN5G(108),
+	CHAN5G(112), CHAN5G(116), CHAN5G(120), CHAN5G(124), CHAN5G(128),
+	CHAN5G(132), CHAN5G(136), CHAN5G(140), CHAN5G(144), CHAN5G(149),
+	CHAN5G(153), CHAN5G(157), CHAN5G(161), CHAN5G(165)
+};
+
+/* Band templates duplicated per wiphy. The channel info
+ * above is added to the band during setup.
+ */
+static const struct ieee80211_supported_band __wl_band_2ghz = {
+	.band = NL80211_BAND_2GHZ,
+	.bitrates = wl_g_rates,
+	.n_bitrates = wl_g_rates_size,
+};
+
+static const struct ieee80211_supported_band __wl_band_5ghz = {
+	.band = NL80211_BAND_5GHZ,
+	.bitrates = wl_a_rates,
+	.n_bitrates = wl_a_rates_size,
+};
+
+/* This is to override regulatory domains defined in cfg80211 module (reg.c)
+ * By default world regulatory domain defined in reg.c puts the flags
+ * NL80211_RRF_NO_IR for 5GHz channels (for * 36..48 and 149..165).
+ * With respect to these flags, wpa_supplicant doesn't * start p2p
+ * operations on 5GHz channels. All the changes in world regulatory
+ * domain are to be done here.
+ */
+static const struct ieee80211_regdomain brcmf_regdom = {
+	.n_reg_rules = 4,
+	.alpha2 =  "99",
+	.reg_rules = {
+		/* IEEE 802.11b/g, channels 1..11 */
+		REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
+		/* If any */
+		/* IEEE 802.11 channel 14 - Only JP enables
+		 * this and for 802.11b only
+		 */
+		REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
+		/* IEEE 802.11a, channel 36..64 */
+		REG_RULE(5150-10, 5350+10, 80, 6, 20, 0),
+		/* IEEE 802.11a, channel 100..165 */
+		REG_RULE(5470-10, 5850+10, 80, 6, 20, 0), }
+};
+
+/* Note: brcmf_cipher_suites is an array of int defining which cipher suites
+ * are supported. A pointer to this array and the number of entries is passed
+ * on to upper layers. AES_CMAC defines whether or not the driver supports MFP.
+ * So the cipher suite AES_CMAC has to be the last one in the array, and when
+ * device does not support MFP then the number of suites will be decreased by 1
+ */
+static const u32 brcmf_cipher_suites[] = {
+	WLAN_CIPHER_SUITE_WEP40,
+	WLAN_CIPHER_SUITE_WEP104,
+	WLAN_CIPHER_SUITE_TKIP,
+	WLAN_CIPHER_SUITE_CCMP,
+	/* Keep as last entry: */
+	WLAN_CIPHER_SUITE_AES_CMAC
+};
+
+/* Vendor specific ie. id = 221, oui and type defines exact ie */
+struct brcmf_vs_tlv {
+	u8 id;
+	u8 len;
+	u8 oui[3];
+	u8 oui_type;
+};
+
+struct parsed_vndr_ie_info {
+	u8 *ie_ptr;
+	u32 ie_len;	/* total length including id & length field */
+	struct brcmf_vs_tlv vndrie;
+};
+
+struct parsed_vndr_ies {
+	u32 count;
+	struct parsed_vndr_ie_info ie_info[VNDR_IE_PARSE_LIMIT];
+};
+
+static u8 nl80211_band_to_fwil(enum nl80211_band band)
+{
+	switch (band) {
+	case NL80211_BAND_2GHZ:
+		return WLC_BAND_2G;
+	case NL80211_BAND_5GHZ:
+		return WLC_BAND_5G;
+	default:
+		WARN_ON(1);
+		break;
+	}
+	return 0;
+}
+
+static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf,
+			       struct cfg80211_chan_def *ch)
+{
+	struct brcmu_chan ch_inf;
+	s32 primary_offset;
+
+	brcmf_dbg(TRACE, "chandef: control %d center %d width %d\n",
+		  ch->chan->center_freq, ch->center_freq1, ch->width);
+	ch_inf.chnum = ieee80211_frequency_to_channel(ch->center_freq1);
+	primary_offset = ch->chan->center_freq - ch->center_freq1;
+	switch (ch->width) {
+	case NL80211_CHAN_WIDTH_20:
+	case NL80211_CHAN_WIDTH_20_NOHT:
+		ch_inf.bw = BRCMU_CHAN_BW_20;
+		WARN_ON(primary_offset != 0);
+		break;
+	case NL80211_CHAN_WIDTH_40:
+		ch_inf.bw = BRCMU_CHAN_BW_40;
+		if (primary_offset > 0)
+			ch_inf.sb = BRCMU_CHAN_SB_U;
+		else
+			ch_inf.sb = BRCMU_CHAN_SB_L;
+		break;
+	case NL80211_CHAN_WIDTH_80:
+		ch_inf.bw = BRCMU_CHAN_BW_80;
+		if (primary_offset == -30)
+			ch_inf.sb = BRCMU_CHAN_SB_LL;
+		else if (primary_offset == -10)
+			ch_inf.sb = BRCMU_CHAN_SB_LU;
+		else if (primary_offset == 10)
+			ch_inf.sb = BRCMU_CHAN_SB_UL;
+		else
+			ch_inf.sb = BRCMU_CHAN_SB_UU;
+		break;
+	case NL80211_CHAN_WIDTH_80P80:
+	case NL80211_CHAN_WIDTH_160:
+	case NL80211_CHAN_WIDTH_5:
+	case NL80211_CHAN_WIDTH_10:
+	default:
+		WARN_ON_ONCE(1);
+	}
+	switch (ch->chan->band) {
+	case NL80211_BAND_2GHZ:
+		ch_inf.band = BRCMU_CHAN_BAND_2G;
+		break;
+	case NL80211_BAND_5GHZ:
+		ch_inf.band = BRCMU_CHAN_BAND_5G;
+		break;
+	case NL80211_BAND_60GHZ:
+	default:
+		WARN_ON_ONCE(1);
+	}
+	d11inf->encchspec(&ch_inf);
+
+	return ch_inf.chspec;
+}
+
+u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
+			struct ieee80211_channel *ch)
+{
+	struct brcmu_chan ch_inf;
+
+	ch_inf.chnum = ieee80211_frequency_to_channel(ch->center_freq);
+	ch_inf.bw = BRCMU_CHAN_BW_20;
+	d11inf->encchspec(&ch_inf);
+
+	return ch_inf.chspec;
+}
+
+/* Traverse a string of 1-byte tag/1-byte length/variable-length value
+ * triples, returning a pointer to the substring whose first element
+ * matches tag
+ */
+static const struct brcmf_tlv *
+brcmf_parse_tlvs(const void *buf, int buflen, uint key)
+{
+	const struct brcmf_tlv *elt = buf;
+	int totlen = buflen;
+
+	/* find tagged parameter */
+	while (totlen >= TLV_HDR_LEN) {
+		int len = elt->len;
+
+		/* validate remaining totlen */
+		if ((elt->id == key) && (totlen >= (len + TLV_HDR_LEN)))
+			return elt;
+
+		elt = (struct brcmf_tlv *)((u8 *)elt + (len + TLV_HDR_LEN));
+		totlen -= (len + TLV_HDR_LEN);
+	}
+
+	return NULL;
+}
+
+/* Is any of the tlvs the expected entry? If
+ * not update the tlvs buffer pointer/length.
+ */
+static bool
+brcmf_tlv_has_ie(const u8 *ie, const u8 **tlvs, u32 *tlvs_len,
+		 const u8 *oui, u32 oui_len, u8 type)
+{
+	/* If the contents match the OUI and the type */
+	if (ie[TLV_LEN_OFF] >= oui_len + 1 &&
+	    !memcmp(&ie[TLV_BODY_OFF], oui, oui_len) &&
+	    type == ie[TLV_BODY_OFF + oui_len]) {
+		return true;
+	}
+
+	if (tlvs == NULL)
+		return false;
+	/* point to the next ie */
+	ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN;
+	/* calculate the length of the rest of the buffer */
+	*tlvs_len -= (int)(ie - *tlvs);
+	/* update the pointer to the start of the buffer */
+	*tlvs = ie;
+
+	return false;
+}
+
+static struct brcmf_vs_tlv *
+brcmf_find_wpaie(const u8 *parse, u32 len)
+{
+	const struct brcmf_tlv *ie;
+
+	while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) {
+		if (brcmf_tlv_has_ie((const u8 *)ie, &parse, &len,
+				     WPA_OUI, TLV_OUI_LEN, WPA_OUI_TYPE))
+			return (struct brcmf_vs_tlv *)ie;
+	}
+	return NULL;
+}
+
+static struct brcmf_vs_tlv *
+brcmf_find_wpsie(const u8 *parse, u32 len)
+{
+	const struct brcmf_tlv *ie;
+
+	while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) {
+		if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len,
+				     WPA_OUI, TLV_OUI_LEN, WPS_OUI_TYPE))
+			return (struct brcmf_vs_tlv *)ie;
+	}
+	return NULL;
+}
+
+static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg,
+				     struct brcmf_cfg80211_vif *vif,
+				     enum nl80211_iftype new_type)
+{
+	struct brcmf_cfg80211_vif *pos;
+	bool check_combos = false;
+	int ret = 0;
+	struct iface_combination_params params = {
+		.num_different_channels = 1,
+	};
+
+	list_for_each_entry(pos, &cfg->vif_list, list)
+		if (pos == vif) {
+			params.iftype_num[new_type]++;
+		} else {
+			/* concurrent interfaces so need check combinations */
+			check_combos = true;
+			params.iftype_num[pos->wdev.iftype]++;
+		}
+
+	if (check_combos)
+		ret = cfg80211_check_combinations(cfg->wiphy, &params);
+
+	return ret;
+}
+
+static int brcmf_vif_add_validate(struct brcmf_cfg80211_info *cfg,
+				  enum nl80211_iftype new_type)
+{
+	struct brcmf_cfg80211_vif *pos;
+	struct iface_combination_params params = {
+		.num_different_channels = 1,
+	};
+
+	list_for_each_entry(pos, &cfg->vif_list, list)
+		params.iftype_num[pos->wdev.iftype]++;
+
+	params.iftype_num[new_type]++;
+	return cfg80211_check_combinations(cfg->wiphy, &params);
+}
+
+static void convert_key_from_CPU(struct brcmf_wsec_key *key,
+				 struct brcmf_wsec_key_le *key_le)
+{
+	key_le->index = cpu_to_le32(key->index);
+	key_le->len = cpu_to_le32(key->len);
+	key_le->algo = cpu_to_le32(key->algo);
+	key_le->flags = cpu_to_le32(key->flags);
+	key_le->rxiv.hi = cpu_to_le32(key->rxiv.hi);
+	key_le->rxiv.lo = cpu_to_le16(key->rxiv.lo);
+	key_le->iv_initialized = cpu_to_le32(key->iv_initialized);
+	memcpy(key_le->data, key->data, sizeof(key->data));
+	memcpy(key_le->ea, key->ea, sizeof(key->ea));
+}
+
+static int
+send_key_to_dongle(struct brcmf_if *ifp, struct brcmf_wsec_key *key)
+{
+	int err;
+	struct brcmf_wsec_key_le key_le;
+
+	convert_key_from_CPU(key, &key_le);
+
+	brcmf_netdev_wait_pend8021x(ifp);
+
+	err = brcmf_fil_bsscfg_data_set(ifp, "wsec_key", &key_le,
+					sizeof(key_le));
+
+	if (err)
+		brcmf_err("wsec_key error (%d)\n", err);
+	return err;
+}
+
+static void
+brcmf_cfg80211_update_proto_addr_mode(struct wireless_dev *wdev)
+{
+	struct brcmf_cfg80211_vif *vif;
+	struct brcmf_if *ifp;
+
+	vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
+	ifp = vif->ifp;
+
+	if ((wdev->iftype == NL80211_IFTYPE_ADHOC) ||
+	    (wdev->iftype == NL80211_IFTYPE_AP) ||
+	    (wdev->iftype == NL80211_IFTYPE_P2P_GO))
+		brcmf_proto_configure_addr_mode(ifp->drvr, ifp->ifidx,
+						ADDR_DIRECT);
+	else
+		brcmf_proto_configure_addr_mode(ifp->drvr, ifp->ifidx,
+						ADDR_INDIRECT);
+}
+
+static int brcmf_get_first_free_bsscfgidx(struct brcmf_pub *drvr)
+{
+	int bsscfgidx;
+
+	for (bsscfgidx = 0; bsscfgidx < BRCMF_MAX_IFS; bsscfgidx++) {
+		/* bsscfgidx 1 is reserved for legacy P2P */
+		if (bsscfgidx == 1)
+			continue;
+		if (!drvr->iflist[bsscfgidx])
+			return bsscfgidx;
+	}
+
+	return -ENOMEM;
+}
+
+static int brcmf_cfg80211_request_ap_if(struct brcmf_if *ifp)
+{
+	struct brcmf_mbss_ssid_le mbss_ssid_le;
+	int bsscfgidx;
+	int err;
+
+	memset(&mbss_ssid_le, 0, sizeof(mbss_ssid_le));
+	bsscfgidx = brcmf_get_first_free_bsscfgidx(ifp->drvr);
+	if (bsscfgidx < 0)
+		return bsscfgidx;
+
+	mbss_ssid_le.bsscfgidx = cpu_to_le32(bsscfgidx);
+	mbss_ssid_le.SSID_len = cpu_to_le32(5);
+	sprintf(mbss_ssid_le.SSID, "ssid%d" , bsscfgidx);
+
+	err = brcmf_fil_bsscfg_data_set(ifp, "bsscfg:ssid", &mbss_ssid_le,
+					sizeof(mbss_ssid_le));
+	if (err < 0)
+		brcmf_err("setting ssid failed %d\n", err);
+
+	return err;
+}
+
+/**
+ * brcmf_ap_add_vif() - create a new AP virtual interface for multiple BSS
+ *
+ * @wiphy: wiphy device of new interface.
+ * @name: name of the new interface.
+ * @params: contains mac address for AP device.
+ */
+static
+struct wireless_dev *brcmf_ap_add_vif(struct wiphy *wiphy, const char *name,
+				      struct vif_params *params)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
+	struct brcmf_cfg80211_vif *vif;
+	int err;
+
+	if (brcmf_cfg80211_vif_event_armed(cfg))
+		return ERR_PTR(-EBUSY);
+
+	brcmf_dbg(INFO, "Adding vif \"%s\"\n", name);
+
+	vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_AP);
+	if (IS_ERR(vif))
+		return (struct wireless_dev *)vif;
+
+	brcmf_cfg80211_arm_vif_event(cfg, vif);
+
+	err = brcmf_cfg80211_request_ap_if(ifp);
+	if (err) {
+		brcmf_cfg80211_arm_vif_event(cfg, NULL);
+		goto fail;
+	}
+
+	/* wait for firmware event */
+	err = brcmf_cfg80211_wait_vif_event(cfg, BRCMF_E_IF_ADD,
+					    BRCMF_VIF_EVENT_TIMEOUT);
+	brcmf_cfg80211_arm_vif_event(cfg, NULL);
+	if (!err) {
+		brcmf_err("timeout occurred\n");
+		err = -EIO;
+		goto fail;
+	}
+
+	/* interface created in firmware */
+	ifp = vif->ifp;
+	if (!ifp) {
+		brcmf_err("no if pointer provided\n");
+		err = -ENOENT;
+		goto fail;
+	}
+
+	strncpy(ifp->ndev->name, name, sizeof(ifp->ndev->name) - 1);
+	err = brcmf_net_attach(ifp, true);
+	if (err) {
+		brcmf_err("Registering netdevice failed\n");
+		free_netdev(ifp->ndev);
+		goto fail;
+	}
+
+	return &ifp->vif->wdev;
+
+fail:
+	brcmf_free_vif(vif);
+	return ERR_PTR(err);
+}
+
+static bool brcmf_is_apmode(struct brcmf_cfg80211_vif *vif)
+{
+	enum nl80211_iftype iftype;
+
+	iftype = vif->wdev.iftype;
+	return iftype == NL80211_IFTYPE_AP || iftype == NL80211_IFTYPE_P2P_GO;
+}
+
+static bool brcmf_is_ibssmode(struct brcmf_cfg80211_vif *vif)
+{
+	return vif->wdev.iftype == NL80211_IFTYPE_ADHOC;
+}
+
+static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy,
+						     const char *name,
+						     unsigned char name_assign_type,
+						     enum nl80211_iftype type,
+						     struct vif_params *params)
+{
+	struct wireless_dev *wdev;
+	int err;
+
+	brcmf_dbg(TRACE, "enter: %s type %d\n", name, type);
+	err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type);
+	if (err) {
+		brcmf_err("iface validation failed: err=%d\n", err);
+		return ERR_PTR(err);
+	}
+	switch (type) {
+	case NL80211_IFTYPE_ADHOC:
+	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_AP_VLAN:
+	case NL80211_IFTYPE_WDS:
+	case NL80211_IFTYPE_MONITOR:
+	case NL80211_IFTYPE_MESH_POINT:
+		return ERR_PTR(-EOPNOTSUPP);
+	case NL80211_IFTYPE_AP:
+		wdev = brcmf_ap_add_vif(wiphy, name, params);
+		break;
+	case NL80211_IFTYPE_P2P_CLIENT:
+	case NL80211_IFTYPE_P2P_GO:
+	case NL80211_IFTYPE_P2P_DEVICE:
+		wdev = brcmf_p2p_add_vif(wiphy, name, name_assign_type, type, params);
+		break;
+	case NL80211_IFTYPE_UNSPECIFIED:
+	default:
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (IS_ERR(wdev))
+		brcmf_err("add iface %s type %d failed: err=%d\n",
+			  name, type, (int)PTR_ERR(wdev));
+	else
+		brcmf_cfg80211_update_proto_addr_mode(wdev);
+
+	return wdev;
+}
+
+static void brcmf_scan_config_mpc(struct brcmf_if *ifp, int mpc)
+{
+	if (brcmf_feat_is_quirk_enabled(ifp, BRCMF_FEAT_QUIRK_NEED_MPC))
+		brcmf_set_mpc(ifp, mpc);
+}
+
+void brcmf_set_mpc(struct brcmf_if *ifp, int mpc)
+{
+	s32 err = 0;
+
+	if (check_vif_up(ifp->vif)) {
+		err = brcmf_fil_iovar_int_set(ifp, "mpc", mpc);
+		if (err) {
+			brcmf_err("fail to set mpc\n");
+			return;
+		}
+		brcmf_dbg(INFO, "MPC : %d\n", mpc);
+	}
+}
+
+s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
+				struct brcmf_if *ifp, bool aborted,
+				bool fw_abort)
+{
+	struct brcmf_scan_params_le params_le;
+	struct cfg80211_scan_request *scan_request;
+	u64 reqid;
+	u32 bucket;
+	s32 err = 0;
+
+	brcmf_dbg(SCAN, "Enter\n");
+
+	/* clear scan request, because the FW abort can cause a second call */
+	/* to this functon and might cause a double cfg80211_scan_done      */
+	scan_request = cfg->scan_request;
+	cfg->scan_request = NULL;
+
+	if (timer_pending(&cfg->escan_timeout))
+		del_timer_sync(&cfg->escan_timeout);
+
+	if (fw_abort) {
+		/* Do a scan abort to stop the driver's scan engine */
+		brcmf_dbg(SCAN, "ABORT scan in firmware\n");
+		memset(&params_le, 0, sizeof(params_le));
+		eth_broadcast_addr(params_le.bssid);
+		params_le.bss_type = DOT11_BSSTYPE_ANY;
+		params_le.scan_type = 0;
+		params_le.channel_num = cpu_to_le32(1);
+		params_le.nprobes = cpu_to_le32(1);
+		params_le.active_time = cpu_to_le32(-1);
+		params_le.passive_time = cpu_to_le32(-1);
+		params_le.home_time = cpu_to_le32(-1);
+		/* Scan is aborted by setting channel_list[0] to -1 */
+		params_le.channel_list[0] = cpu_to_le16(-1);
+		/* E-Scan (or anyother type) can be aborted by SCAN */
+		err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
+					     &params_le, sizeof(params_le));
+		if (err)
+			brcmf_err("Scan abort failed\n");
+	}
+
+	brcmf_scan_config_mpc(ifp, 1);
+
+	/*
+	 * e-scan can be initiated internally
+	 * which takes precedence.
+	 */
+	if (cfg->int_escan_map) {
+		brcmf_dbg(SCAN, "scheduled scan completed (%x)\n",
+			  cfg->int_escan_map);
+		while (cfg->int_escan_map) {
+			bucket = __ffs(cfg->int_escan_map);
+			cfg->int_escan_map &= ~BIT(bucket);
+			reqid = brcmf_pno_find_reqid_by_bucket(cfg->pno,
+							       bucket);
+			if (!aborted) {
+				brcmf_dbg(SCAN, "report results: reqid=%llu\n",
+					  reqid);
+				cfg80211_sched_scan_results(cfg_to_wiphy(cfg),
+							    reqid);
+			}
+		}
+	} else if (scan_request) {
+		struct cfg80211_scan_info info = {
+			.aborted = aborted,
+		};
+
+		brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n",
+			  aborted ? "Aborted" : "Done");
+		cfg80211_scan_done(scan_request, &info);
+	}
+	if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status))
+		brcmf_dbg(SCAN, "Scan complete, probably P2P scan\n");
+
+	return err;
+}
+
+static int brcmf_cfg80211_del_ap_iface(struct wiphy *wiphy,
+				       struct wireless_dev *wdev)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct net_device *ndev = wdev->netdev;
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	int ret;
+	int err;
+
+	brcmf_cfg80211_arm_vif_event(cfg, ifp->vif);
+
+	err = brcmf_fil_bsscfg_data_set(ifp, "interface_remove", NULL, 0);
+	if (err) {
+		brcmf_err("interface_remove failed %d\n", err);
+		goto err_unarm;
+	}
+
+	/* wait for firmware event */
+	ret = brcmf_cfg80211_wait_vif_event(cfg, BRCMF_E_IF_DEL,
+					    BRCMF_VIF_EVENT_TIMEOUT);
+	if (!ret) {
+		brcmf_err("timeout occurred\n");
+		err = -EIO;
+		goto err_unarm;
+	}
+
+	brcmf_remove_interface(ifp, true);
+
+err_unarm:
+	brcmf_cfg80211_arm_vif_event(cfg, NULL);
+	return err;
+}
+
+static
+int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct net_device *ndev = wdev->netdev;
+
+	if (ndev && ndev == cfg_to_ndev(cfg))
+		return -ENOTSUPP;
+
+	/* vif event pending in firmware */
+	if (brcmf_cfg80211_vif_event_armed(cfg))
+		return -EBUSY;
+
+	if (ndev) {
+		if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status) &&
+		    cfg->escan_info.ifp == netdev_priv(ndev))
+			brcmf_notify_escan_complete(cfg, netdev_priv(ndev),
+						    true, true);
+
+		brcmf_fil_iovar_int_set(netdev_priv(ndev), "mpc", 1);
+	}
+
+	switch (wdev->iftype) {
+	case NL80211_IFTYPE_ADHOC:
+	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_AP_VLAN:
+	case NL80211_IFTYPE_WDS:
+	case NL80211_IFTYPE_MONITOR:
+	case NL80211_IFTYPE_MESH_POINT:
+		return -EOPNOTSUPP;
+	case NL80211_IFTYPE_AP:
+		return brcmf_cfg80211_del_ap_iface(wiphy, wdev);
+	case NL80211_IFTYPE_P2P_CLIENT:
+	case NL80211_IFTYPE_P2P_GO:
+	case NL80211_IFTYPE_P2P_DEVICE:
+		return brcmf_p2p_del_vif(wiphy, wdev);
+	case NL80211_IFTYPE_UNSPECIFIED:
+	default:
+		return -EINVAL;
+	}
+	return -EOPNOTSUPP;
+}
+
+static s32
+brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
+			 enum nl80211_iftype type,
+			 struct vif_params *params)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_cfg80211_vif *vif = ifp->vif;
+	s32 infra = 0;
+	s32 ap = 0;
+	s32 err = 0;
+
+	brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, type=%d\n", ifp->bsscfgidx,
+		  type);
+
+	/* WAR: There are a number of p2p interface related problems which
+	 * need to be handled initially (before doing the validate).
+	 * wpa_supplicant tends to do iface changes on p2p device/client/go
+	 * which are not always possible/allowed. However we need to return
+	 * OK otherwise the wpa_supplicant wont start. The situation differs
+	 * on configuration and setup (p2pon=1 module param). The first check
+	 * is to see if the request is a change to station for p2p iface.
+	 */
+	if ((type == NL80211_IFTYPE_STATION) &&
+	    ((vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) ||
+	     (vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) ||
+	     (vif->wdev.iftype == NL80211_IFTYPE_P2P_DEVICE))) {
+		brcmf_dbg(TRACE, "Ignoring cmd for p2p if\n");
+		/* Now depending on whether module param p2pon=1 was used the
+		 * response needs to be either 0 or EOPNOTSUPP. The reason is
+		 * that if p2pon=1 is used, but a newer supplicant is used then
+		 * we should return an error, as this combination wont work.
+		 * In other situations 0 is returned and supplicant will start
+		 * normally. It will give a trace in cfg80211, but it is the
+		 * only way to get it working. Unfortunately this will result
+		 * in situation where we wont support new supplicant in
+		 * combination with module param p2pon=1, but that is the way
+		 * it is. If the user tries this then unloading of driver might
+		 * fail/lock.
+		 */
+		if (cfg->p2p.p2pdev_dynamically)
+			return -EOPNOTSUPP;
+		else
+			return 0;
+	}
+	err = brcmf_vif_change_validate(wiphy_to_cfg(wiphy), vif, type);
+	if (err) {
+		brcmf_err("iface validation failed: err=%d\n", err);
+		return err;
+	}
+	switch (type) {
+	case NL80211_IFTYPE_MONITOR:
+	case NL80211_IFTYPE_WDS:
+		brcmf_err("type (%d) : currently we do not support this type\n",
+			  type);
+		return -EOPNOTSUPP;
+	case NL80211_IFTYPE_ADHOC:
+		infra = 0;
+		break;
+	case NL80211_IFTYPE_STATION:
+		infra = 1;
+		break;
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_P2P_GO:
+		ap = 1;
+		break;
+	default:
+		err = -EINVAL;
+		goto done;
+	}
+
+	if (ap) {
+		if (type == NL80211_IFTYPE_P2P_GO) {
+			brcmf_dbg(INFO, "IF Type = P2P GO\n");
+			err = brcmf_p2p_ifchange(cfg, BRCMF_FIL_P2P_IF_GO);
+		}
+		if (!err) {
+			brcmf_dbg(INFO, "IF Type = AP\n");
+		}
+	} else {
+		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, infra);
+		if (err) {
+			brcmf_err("WLC_SET_INFRA error (%d)\n", err);
+			err = -EAGAIN;
+			goto done;
+		}
+		brcmf_dbg(INFO, "IF Type = %s\n", brcmf_is_ibssmode(vif) ?
+			  "Adhoc" : "Infra");
+	}
+	ndev->ieee80211_ptr->iftype = type;
+
+	brcmf_cfg80211_update_proto_addr_mode(&vif->wdev);
+
+done:
+	brcmf_dbg(TRACE, "Exit\n");
+
+	return err;
+}
+
+static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg,
+			     struct brcmf_scan_params_le *params_le,
+			     struct cfg80211_scan_request *request)
+{
+	u32 n_ssids;
+	u32 n_channels;
+	s32 i;
+	s32 offset;
+	u16 chanspec;
+	char *ptr;
+	struct brcmf_ssid_le ssid_le;
+
+	eth_broadcast_addr(params_le->bssid);
+	params_le->bss_type = DOT11_BSSTYPE_ANY;
+	params_le->scan_type = BRCMF_SCANTYPE_ACTIVE;
+	params_le->channel_num = 0;
+	params_le->nprobes = cpu_to_le32(-1);
+	params_le->active_time = cpu_to_le32(-1);
+	params_le->passive_time = cpu_to_le32(-1);
+	params_le->home_time = cpu_to_le32(-1);
+	memset(&params_le->ssid_le, 0, sizeof(params_le->ssid_le));
+
+	n_ssids = request->n_ssids;
+	n_channels = request->n_channels;
+
+	/* Copy channel array if applicable */
+	brcmf_dbg(SCAN, "### List of channelspecs to scan ### %d\n",
+		  n_channels);
+	if (n_channels > 0) {
+		for (i = 0; i < n_channels; i++) {
+			chanspec = channel_to_chanspec(&cfg->d11inf,
+						       request->channels[i]);
+			brcmf_dbg(SCAN, "Chan : %d, Channel spec: %x\n",
+				  request->channels[i]->hw_value, chanspec);
+			params_le->channel_list[i] = cpu_to_le16(chanspec);
+		}
+	} else {
+		brcmf_dbg(SCAN, "Scanning all channels\n");
+	}
+	/* Copy ssid array if applicable */
+	brcmf_dbg(SCAN, "### List of SSIDs to scan ### %d\n", n_ssids);
+	if (n_ssids > 0) {
+		offset = offsetof(struct brcmf_scan_params_le, channel_list) +
+				n_channels * sizeof(u16);
+		offset = roundup(offset, sizeof(u32));
+		ptr = (char *)params_le + offset;
+		for (i = 0; i < n_ssids; i++) {
+			memset(&ssid_le, 0, sizeof(ssid_le));
+			ssid_le.SSID_len =
+					cpu_to_le32(request->ssids[i].ssid_len);
+			memcpy(ssid_le.SSID, request->ssids[i].ssid,
+			       request->ssids[i].ssid_len);
+			if (!ssid_le.SSID_len)
+				brcmf_dbg(SCAN, "%d: Broadcast scan\n", i);
+			else
+				brcmf_dbg(SCAN, "%d: scan for  %.32s size=%d\n",
+					  i, ssid_le.SSID, ssid_le.SSID_len);
+			memcpy(ptr, &ssid_le, sizeof(ssid_le));
+			ptr += sizeof(ssid_le);
+		}
+	} else {
+		brcmf_dbg(SCAN, "Performing passive scan\n");
+		params_le->scan_type = BRCMF_SCANTYPE_PASSIVE;
+	}
+	/* Adding mask to channel numbers */
+	params_le->channel_num =
+		cpu_to_le32((n_ssids << BRCMF_SCAN_PARAMS_NSSID_SHIFT) |
+			(n_channels & BRCMF_SCAN_PARAMS_COUNT_MASK));
+}
+
+static s32
+brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
+		struct cfg80211_scan_request *request)
+{
+	s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE +
+			  offsetof(struct brcmf_escan_params_le, params_le);
+	struct brcmf_escan_params_le *params;
+	s32 err = 0;
+
+	brcmf_dbg(SCAN, "E-SCAN START\n");
+
+	if (request != NULL) {
+		/* Allocate space for populating ssids in struct */
+		params_size += sizeof(u32) * ((request->n_channels + 1) / 2);
+
+		/* Allocate space for populating ssids in struct */
+		params_size += sizeof(struct brcmf_ssid_le) * request->n_ssids;
+	}
+
+	params = kzalloc(params_size, GFP_KERNEL);
+	if (!params) {
+		err = -ENOMEM;
+		goto exit;
+	}
+	BUG_ON(params_size + sizeof("escan") >= BRCMF_DCMD_MEDLEN);
+	brcmf_escan_prep(cfg, &params->params_le, request);
+	params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
+	params->action = cpu_to_le16(WL_ESCAN_ACTION_START);
+	params->sync_id = cpu_to_le16(0x1234);
+
+	err = brcmf_fil_iovar_data_set(ifp, "escan", params, params_size);
+	if (err) {
+		if (err == -EBUSY)
+			brcmf_dbg(INFO, "system busy : escan canceled\n");
+		else
+			brcmf_err("error (%d)\n", err);
+	}
+
+	kfree(params);
+exit:
+	return err;
+}
+
+static s32
+brcmf_do_escan(struct brcmf_if *ifp, struct cfg80211_scan_request *request)
+{
+	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+	s32 err;
+	struct brcmf_scan_results *results;
+	struct escan_info *escan = &cfg->escan_info;
+
+	brcmf_dbg(SCAN, "Enter\n");
+	escan->ifp = ifp;
+	escan->wiphy = cfg->wiphy;
+	escan->escan_state = WL_ESCAN_STATE_SCANNING;
+
+	brcmf_scan_config_mpc(ifp, 0);
+	results = (struct brcmf_scan_results *)cfg->escan_info.escan_buf;
+	results->version = 0;
+	results->count = 0;
+	results->buflen = WL_ESCAN_RESULTS_FIXED_SIZE;
+
+	err = escan->run(cfg, ifp, request);
+	if (err)
+		brcmf_scan_config_mpc(ifp, 1);
+	return err;
+}
+
+static s32
+brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_cfg80211_vif *vif;
+	s32 err = 0;
+
+	brcmf_dbg(TRACE, "Enter\n");
+	vif = container_of(request->wdev, struct brcmf_cfg80211_vif, wdev);
+	if (!check_vif_up(vif))
+		return -EIO;
+
+	if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
+		brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status);
+		return -EAGAIN;
+	}
+	if (test_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status)) {
+		brcmf_err("Scanning being aborted: status (%lu)\n",
+			  cfg->scan_status);
+		return -EAGAIN;
+	}
+	if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) {
+		brcmf_err("Scanning suppressed: status (%lu)\n",
+			  cfg->scan_status);
+		return -EAGAIN;
+	}
+	if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state)) {
+		brcmf_err("Connecting: status (%lu)\n", vif->sme_state);
+		return -EAGAIN;
+	}
+
+	/* If scan req comes for p2p0, send it over primary I/F */
+	if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
+		vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif;
+
+	brcmf_dbg(SCAN, "START ESCAN\n");
+
+	cfg->scan_request = request;
+	set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
+
+	cfg->escan_info.run = brcmf_run_escan;
+	err = brcmf_p2p_scan_prep(wiphy, request, vif);
+	if (err)
+		goto scan_out;
+
+	err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_PRBREQ_FLAG,
+				    request->ie, request->ie_len);
+	if (err)
+		goto scan_out;
+
+	err = brcmf_do_escan(vif->ifp, request);
+	if (err)
+		goto scan_out;
+
+	/* Arm scan timeout timer */
+	mod_timer(&cfg->escan_timeout,
+		  jiffies + msecs_to_jiffies(BRCMF_ESCAN_TIMER_INTERVAL_MS));
+
+	return 0;
+
+scan_out:
+	brcmf_err("scan error (%d)\n", err);
+	clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
+	cfg->scan_request = NULL;
+	return err;
+}
+
+static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold)
+{
+	s32 err = 0;
+
+	err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "rtsthresh",
+				      rts_threshold);
+	if (err)
+		brcmf_err("Error (%d)\n", err);
+
+	return err;
+}
+
+static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold)
+{
+	s32 err = 0;
+
+	err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "fragthresh",
+				      frag_threshold);
+	if (err)
+		brcmf_err("Error (%d)\n", err);
+
+	return err;
+}
+
+static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l)
+{
+	s32 err = 0;
+	u32 cmd = (l ? BRCMF_C_SET_LRL : BRCMF_C_SET_SRL);
+
+	err = brcmf_fil_cmd_int_set(netdev_priv(ndev), cmd, retry);
+	if (err) {
+		brcmf_err("cmd (%d) , error (%d)\n", cmd, err);
+		return err;
+	}
+	return err;
+}
+
+static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct net_device *ndev = cfg_to_ndev(cfg);
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	s32 err = 0;
+
+	brcmf_dbg(TRACE, "Enter\n");
+	if (!check_vif_up(ifp->vif))
+		return -EIO;
+
+	if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
+	    (cfg->conf->rts_threshold != wiphy->rts_threshold)) {
+		cfg->conf->rts_threshold = wiphy->rts_threshold;
+		err = brcmf_set_rts(ndev, cfg->conf->rts_threshold);
+		if (!err)
+			goto done;
+	}
+	if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
+	    (cfg->conf->frag_threshold != wiphy->frag_threshold)) {
+		cfg->conf->frag_threshold = wiphy->frag_threshold;
+		err = brcmf_set_frag(ndev, cfg->conf->frag_threshold);
+		if (!err)
+			goto done;
+	}
+	if (changed & WIPHY_PARAM_RETRY_LONG
+	    && (cfg->conf->retry_long != wiphy->retry_long)) {
+		cfg->conf->retry_long = wiphy->retry_long;
+		err = brcmf_set_retry(ndev, cfg->conf->retry_long, true);
+		if (!err)
+			goto done;
+	}
+	if (changed & WIPHY_PARAM_RETRY_SHORT
+	    && (cfg->conf->retry_short != wiphy->retry_short)) {
+		cfg->conf->retry_short = wiphy->retry_short;
+		err = brcmf_set_retry(ndev, cfg->conf->retry_short, false);
+		if (!err)
+			goto done;
+	}
+
+done:
+	brcmf_dbg(TRACE, "Exit\n");
+	return err;
+}
+
+static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof)
+{
+	memset(prof, 0, sizeof(*prof));
+}
+
+static u16 brcmf_map_fw_linkdown_reason(const struct brcmf_event_msg *e)
+{
+	u16 reason;
+
+	switch (e->event_code) {
+	case BRCMF_E_DEAUTH:
+	case BRCMF_E_DEAUTH_IND:
+	case BRCMF_E_DISASSOC_IND:
+		reason = e->reason;
+		break;
+	case BRCMF_E_LINK:
+	default:
+		reason = 0;
+		break;
+	}
+	return reason;
+}
+
+static int brcmf_set_pmk(struct brcmf_if *ifp, const u8 *pmk_data, u16 pmk_len)
+{
+	struct brcmf_wsec_pmk_le pmk;
+	int i, err;
+
+	/* convert to firmware key format */
+	pmk.key_len = cpu_to_le16(pmk_len << 1);
+	pmk.flags = cpu_to_le16(BRCMF_WSEC_PASSPHRASE);
+	for (i = 0; i < pmk_len; i++)
+		snprintf(&pmk.key[2 * i], 3, "%02x", pmk_data[i]);
+
+	/* store psk in firmware */
+	err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_WSEC_PMK,
+				     &pmk, sizeof(pmk));
+	if (err < 0)
+		brcmf_err("failed to change PSK in firmware (len=%u)\n",
+			  pmk_len);
+
+	return err;
+}
+
+static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(vif->wdev.wiphy);
+	s32 err = 0;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state)) {
+		brcmf_dbg(INFO, "Call WLC_DISASSOC to stop excess roaming\n");
+		err = brcmf_fil_cmd_data_set(vif->ifp,
+					     BRCMF_C_DISASSOC, NULL, 0);
+		if (err) {
+			brcmf_err("WLC_DISASSOC failed (%d)\n", err);
+		}
+		if ((vif->wdev.iftype == NL80211_IFTYPE_STATION) ||
+		    (vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT))
+			cfg80211_disconnected(vif->wdev.netdev, reason, NULL, 0,
+					      true, GFP_KERNEL);
+	}
+	clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state);
+	clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
+	brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_ENABLED, 0);
+	if (vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_NONE) {
+		brcmf_set_pmk(vif->ifp, NULL, 0);
+		vif->profile.use_fwsup = BRCMF_PROFILE_FWSUP_NONE;
+	}
+	brcmf_dbg(TRACE, "Exit\n");
+}
+
+static s32
+brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
+		      struct cfg80211_ibss_params *params)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
+	struct brcmf_join_params join_params;
+	size_t join_params_size = 0;
+	s32 err = 0;
+	s32 wsec = 0;
+	s32 bcnprd;
+	u16 chanspec;
+	u32 ssid_len;
+
+	brcmf_dbg(TRACE, "Enter\n");
+	if (!check_vif_up(ifp->vif))
+		return -EIO;
+
+	if (params->ssid)
+		brcmf_dbg(CONN, "SSID: %s\n", params->ssid);
+	else {
+		brcmf_dbg(CONN, "SSID: NULL, Not supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	set_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
+
+	if (params->bssid)
+		brcmf_dbg(CONN, "BSSID: %pM\n", params->bssid);
+	else
+		brcmf_dbg(CONN, "No BSSID specified\n");
+
+	if (params->chandef.chan)
+		brcmf_dbg(CONN, "channel: %d\n",
+			  params->chandef.chan->center_freq);
+	else
+		brcmf_dbg(CONN, "no channel specified\n");
+
+	if (params->channel_fixed)
+		brcmf_dbg(CONN, "fixed channel required\n");
+	else
+		brcmf_dbg(CONN, "no fixed channel required\n");
+
+	if (params->ie && params->ie_len)
+		brcmf_dbg(CONN, "ie len: %d\n", params->ie_len);
+	else
+		brcmf_dbg(CONN, "no ie specified\n");
+
+	if (params->beacon_interval)
+		brcmf_dbg(CONN, "beacon interval: %d\n",
+			  params->beacon_interval);
+	else
+		brcmf_dbg(CONN, "no beacon interval specified\n");
+
+	if (params->basic_rates)
+		brcmf_dbg(CONN, "basic rates: %08X\n", params->basic_rates);
+	else
+		brcmf_dbg(CONN, "no basic rates specified\n");
+
+	if (params->privacy)
+		brcmf_dbg(CONN, "privacy required\n");
+	else
+		brcmf_dbg(CONN, "no privacy required\n");
+
+	/* Configure Privacy for starter */
+	if (params->privacy)
+		wsec |= WEP_ENABLED;
+
+	err = brcmf_fil_iovar_int_set(ifp, "wsec", wsec);
+	if (err) {
+		brcmf_err("wsec failed (%d)\n", err);
+		goto done;
+	}
+
+	/* Configure Beacon Interval for starter */
+	if (params->beacon_interval)
+		bcnprd = params->beacon_interval;
+	else
+		bcnprd = 100;
+
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD, bcnprd);
+	if (err) {
+		brcmf_err("WLC_SET_BCNPRD failed (%d)\n", err);
+		goto done;
+	}
+
+	/* Configure required join parameter */
+	memset(&join_params, 0, sizeof(struct brcmf_join_params));
+
+	/* SSID */
+	ssid_len = min_t(u32, params->ssid_len, IEEE80211_MAX_SSID_LEN);
+	memcpy(join_params.ssid_le.SSID, params->ssid, ssid_len);
+	join_params.ssid_le.SSID_len = cpu_to_le32(ssid_len);
+	join_params_size = sizeof(join_params.ssid_le);
+
+	/* BSSID */
+	if (params->bssid) {
+		memcpy(join_params.params_le.bssid, params->bssid, ETH_ALEN);
+		join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE;
+		memcpy(profile->bssid, params->bssid, ETH_ALEN);
+	} else {
+		eth_broadcast_addr(join_params.params_le.bssid);
+		eth_zero_addr(profile->bssid);
+	}
+
+	/* Channel */
+	if (params->chandef.chan) {
+		u32 target_channel;
+
+		cfg->channel =
+			ieee80211_frequency_to_channel(
+				params->chandef.chan->center_freq);
+		if (params->channel_fixed) {
+			/* adding chanspec */
+			chanspec = chandef_to_chanspec(&cfg->d11inf,
+						       &params->chandef);
+			join_params.params_le.chanspec_list[0] =
+				cpu_to_le16(chanspec);
+			join_params.params_le.chanspec_num = cpu_to_le32(1);
+			join_params_size += sizeof(join_params.params_le);
+		}
+
+		/* set channel for starter */
+		target_channel = cfg->channel;
+		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_CHANNEL,
+					    target_channel);
+		if (err) {
+			brcmf_err("WLC_SET_CHANNEL failed (%d)\n", err);
+			goto done;
+		}
+	} else
+		cfg->channel = 0;
+
+	cfg->ibss_starter = false;
+
+
+	err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
+				     &join_params, join_params_size);
+	if (err) {
+		brcmf_err("WLC_SET_SSID failed (%d)\n", err);
+		goto done;
+	}
+
+done:
+	if (err)
+		clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
+	brcmf_dbg(TRACE, "Exit\n");
+	return err;
+}
+
+static s32
+brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+
+	brcmf_dbg(TRACE, "Enter\n");
+	if (!check_vif_up(ifp->vif)) {
+		/* When driver is being unloaded, it can end up here. If an
+		 * error is returned then later on a debug trace in the wireless
+		 * core module will be printed. To avoid this 0 is returned.
+		 */
+		return 0;
+	}
+
+	brcmf_link_down(ifp->vif, WLAN_REASON_DEAUTH_LEAVING);
+	brcmf_net_setcarrier(ifp, false);
+
+	brcmf_dbg(TRACE, "Exit\n");
+
+	return 0;
+}
+
+static s32 brcmf_set_wpa_version(struct net_device *ndev,
+				 struct cfg80211_connect_params *sme)
+{
+	struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
+	struct brcmf_cfg80211_security *sec;
+	s32 val = 0;
+	s32 err = 0;
+
+	if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
+		val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
+	else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
+		val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
+	else
+		val = WPA_AUTH_DISABLED;
+	brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
+	err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth", val);
+	if (err) {
+		brcmf_err("set wpa_auth failed (%d)\n", err);
+		return err;
+	}
+	sec = &profile->sec;
+	sec->wpa_versions = sme->crypto.wpa_versions;
+	return err;
+}
+
+static s32 brcmf_set_auth_type(struct net_device *ndev,
+			       struct cfg80211_connect_params *sme)
+{
+	struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
+	struct brcmf_cfg80211_security *sec;
+	s32 val = 0;
+	s32 err = 0;
+
+	switch (sme->auth_type) {
+	case NL80211_AUTHTYPE_OPEN_SYSTEM:
+		val = 0;
+		brcmf_dbg(CONN, "open system\n");
+		break;
+	case NL80211_AUTHTYPE_SHARED_KEY:
+		val = 1;
+		brcmf_dbg(CONN, "shared key\n");
+		break;
+	default:
+		val = 2;
+		brcmf_dbg(CONN, "automatic, auth type (%d)\n", sme->auth_type);
+		break;
+	}
+
+	err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "auth", val);
+	if (err) {
+		brcmf_err("set auth failed (%d)\n", err);
+		return err;
+	}
+	sec = &profile->sec;
+	sec->auth_type = sme->auth_type;
+	return err;
+}
+
+static s32
+brcmf_set_wsec_mode(struct net_device *ndev,
+		    struct cfg80211_connect_params *sme)
+{
+	struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
+	struct brcmf_cfg80211_security *sec;
+	s32 pval = 0;
+	s32 gval = 0;
+	s32 wsec;
+	s32 err = 0;
+
+	if (sme->crypto.n_ciphers_pairwise) {
+		switch (sme->crypto.ciphers_pairwise[0]) {
+		case WLAN_CIPHER_SUITE_WEP40:
+		case WLAN_CIPHER_SUITE_WEP104:
+			pval = WEP_ENABLED;
+			break;
+		case WLAN_CIPHER_SUITE_TKIP:
+			pval = TKIP_ENABLED;
+			break;
+		case WLAN_CIPHER_SUITE_CCMP:
+			pval = AES_ENABLED;
+			break;
+		case WLAN_CIPHER_SUITE_AES_CMAC:
+			pval = AES_ENABLED;
+			break;
+		default:
+			brcmf_err("invalid cipher pairwise (%d)\n",
+				  sme->crypto.ciphers_pairwise[0]);
+			return -EINVAL;
+		}
+	}
+	if (sme->crypto.cipher_group) {
+		switch (sme->crypto.cipher_group) {
+		case WLAN_CIPHER_SUITE_WEP40:
+		case WLAN_CIPHER_SUITE_WEP104:
+			gval = WEP_ENABLED;
+			break;
+		case WLAN_CIPHER_SUITE_TKIP:
+			gval = TKIP_ENABLED;
+			break;
+		case WLAN_CIPHER_SUITE_CCMP:
+			gval = AES_ENABLED;
+			break;
+		case WLAN_CIPHER_SUITE_AES_CMAC:
+			gval = AES_ENABLED;
+			break;
+		default:
+			brcmf_err("invalid cipher group (%d)\n",
+				  sme->crypto.cipher_group);
+			return -EINVAL;
+		}
+	}
+
+	brcmf_dbg(CONN, "pval (%d) gval (%d)\n", pval, gval);
+	/* In case of privacy, but no security and WPS then simulate */
+	/* setting AES. WPS-2.0 allows no security                   */
+	if (brcmf_find_wpsie(sme->ie, sme->ie_len) && !pval && !gval &&
+	    sme->privacy)
+		pval = AES_ENABLED;
+
+	wsec = pval | gval;
+	err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wsec", wsec);
+	if (err) {
+		brcmf_err("error (%d)\n", err);
+		return err;
+	}
+
+	sec = &profile->sec;
+	sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
+	sec->cipher_group = sme->crypto.cipher_group;
+
+	return err;
+}
+
+static s32
+brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
+	s32 val;
+	s32 err;
+	const struct brcmf_tlv *rsn_ie;
+	const u8 *ie;
+	u32 ie_len;
+	u32 offset;
+	u16 rsn_cap;
+	u32 mfp;
+	u16 count;
+
+	profile->use_fwsup = BRCMF_PROFILE_FWSUP_NONE;
+
+	if (!sme->crypto.n_akm_suites)
+		return 0;
+
+	err = brcmf_fil_bsscfg_int_get(netdev_priv(ndev), "wpa_auth", &val);
+	if (err) {
+		brcmf_err("could not get wpa_auth (%d)\n", err);
+		return err;
+	}
+	if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
+		switch (sme->crypto.akm_suites[0]) {
+		case WLAN_AKM_SUITE_8021X:
+			val = WPA_AUTH_UNSPECIFIED;
+			if (sme->want_1x)
+				profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
+			break;
+		case WLAN_AKM_SUITE_PSK:
+			val = WPA_AUTH_PSK;
+			break;
+		default:
+			brcmf_err("invalid cipher group (%d)\n",
+				  sme->crypto.cipher_group);
+			return -EINVAL;
+		}
+	} else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
+		switch (sme->crypto.akm_suites[0]) {
+		case WLAN_AKM_SUITE_8021X:
+			val = WPA2_AUTH_UNSPECIFIED;
+			if (sme->want_1x)
+				profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
+			break;
+		case WLAN_AKM_SUITE_8021X_SHA256:
+			val = WPA2_AUTH_1X_SHA256;
+			if (sme->want_1x)
+				profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
+			break;
+		case WLAN_AKM_SUITE_PSK_SHA256:
+			val = WPA2_AUTH_PSK_SHA256;
+			break;
+		case WLAN_AKM_SUITE_PSK:
+			val = WPA2_AUTH_PSK;
+			break;
+		default:
+			brcmf_err("invalid cipher group (%d)\n",
+				  sme->crypto.cipher_group);
+			return -EINVAL;
+		}
+	}
+
+	if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X)
+		brcmf_dbg(INFO, "using 1X offload\n");
+
+	if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP))
+		goto skip_mfp_config;
+	/* The MFP mode (1 or 2) needs to be determined, parse IEs. The
+	 * IE will not be verified, just a quick search for MFP config
+	 */
+	rsn_ie = brcmf_parse_tlvs((const u8 *)sme->ie, sme->ie_len,
+				  WLAN_EID_RSN);
+	if (!rsn_ie)
+		goto skip_mfp_config;
+	ie = (const u8 *)rsn_ie;
+	ie_len = rsn_ie->len + TLV_HDR_LEN;
+	/* Skip unicast suite */
+	offset = TLV_HDR_LEN + WPA_IE_VERSION_LEN + WPA_IE_MIN_OUI_LEN;
+	if (offset + WPA_IE_SUITE_COUNT_LEN >= ie_len)
+		goto skip_mfp_config;
+	/* Skip multicast suite */
+	count = ie[offset] + (ie[offset + 1] << 8);
+	offset += WPA_IE_SUITE_COUNT_LEN + (count * WPA_IE_MIN_OUI_LEN);
+	if (offset + WPA_IE_SUITE_COUNT_LEN >= ie_len)
+		goto skip_mfp_config;
+	/* Skip auth key management suite(s) */
+	count = ie[offset] + (ie[offset + 1] << 8);
+	offset += WPA_IE_SUITE_COUNT_LEN + (count * WPA_IE_MIN_OUI_LEN);
+	if (offset + WPA_IE_SUITE_COUNT_LEN > ie_len)
+		goto skip_mfp_config;
+	/* Ready to read capabilities */
+	mfp = BRCMF_MFP_NONE;
+	rsn_cap = ie[offset] + (ie[offset + 1] << 8);
+	if (rsn_cap & RSN_CAP_MFPR_MASK)
+		mfp = BRCMF_MFP_REQUIRED;
+	else if (rsn_cap & RSN_CAP_MFPC_MASK)
+		mfp = BRCMF_MFP_CAPABLE;
+	brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "mfp", mfp);
+
+skip_mfp_config:
+	brcmf_dbg(CONN, "setting wpa_auth to %d\n", val);
+	err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth", val);
+	if (err) {
+		brcmf_err("could not set wpa_auth (%d)\n", err);
+		return err;
+	}
+
+	return err;
+}
+
+static s32
+brcmf_set_sharedkey(struct net_device *ndev,
+		    struct cfg80211_connect_params *sme)
+{
+	struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
+	struct brcmf_cfg80211_security *sec;
+	struct brcmf_wsec_key key;
+	s32 val;
+	s32 err = 0;
+
+	brcmf_dbg(CONN, "key len (%d)\n", sme->key_len);
+
+	if (sme->key_len == 0)
+		return 0;
+
+	sec = &profile->sec;
+	brcmf_dbg(CONN, "wpa_versions 0x%x cipher_pairwise 0x%x\n",
+		  sec->wpa_versions, sec->cipher_pairwise);
+
+	if (sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2))
+		return 0;
+
+	if (!(sec->cipher_pairwise &
+	    (WLAN_CIPHER_SUITE_WEP40 | WLAN_CIPHER_SUITE_WEP104)))
+		return 0;
+
+	memset(&key, 0, sizeof(key));
+	key.len = (u32) sme->key_len;
+	key.index = (u32) sme->key_idx;
+	if (key.len > sizeof(key.data)) {
+		brcmf_err("Too long key length (%u)\n", key.len);
+		return -EINVAL;
+	}
+	memcpy(key.data, sme->key, key.len);
+	key.flags = BRCMF_PRIMARY_KEY;
+	switch (sec->cipher_pairwise) {
+	case WLAN_CIPHER_SUITE_WEP40:
+		key.algo = CRYPTO_ALGO_WEP1;
+		break;
+	case WLAN_CIPHER_SUITE_WEP104:
+		key.algo = CRYPTO_ALGO_WEP128;
+		break;
+	default:
+		brcmf_err("Invalid algorithm (%d)\n",
+			  sme->crypto.ciphers_pairwise[0]);
+		return -EINVAL;
+	}
+	/* Set the new key/index */
+	brcmf_dbg(CONN, "key length (%d) key index (%d) algo (%d)\n",
+		  key.len, key.index, key.algo);
+	brcmf_dbg(CONN, "key \"%s\"\n", key.data);
+	err = send_key_to_dongle(netdev_priv(ndev), &key);
+	if (err)
+		return err;
+
+	if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
+		brcmf_dbg(CONN, "set auth_type to shared key\n");
+		val = WL_AUTH_SHARED_KEY;	/* shared key */
+		err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "auth", val);
+		if (err)
+			brcmf_err("set auth failed (%d)\n", err);
+	}
+	return err;
+}
+
+static
+enum nl80211_auth_type brcmf_war_auth_type(struct brcmf_if *ifp,
+					   enum nl80211_auth_type type)
+{
+	if (type == NL80211_AUTHTYPE_AUTOMATIC &&
+	    brcmf_feat_is_quirk_enabled(ifp, BRCMF_FEAT_QUIRK_AUTO_AUTH)) {
+		brcmf_dbg(CONN, "WAR: use OPEN instead of AUTO\n");
+		type = NL80211_AUTHTYPE_OPEN_SYSTEM;
+	}
+	return type;
+}
+
+static void brcmf_set_join_pref(struct brcmf_if *ifp,
+				struct cfg80211_bss_selection *bss_select)
+{
+	struct brcmf_join_pref_params join_pref_params[2];
+	enum nl80211_band band;
+	int err, i = 0;
+
+	join_pref_params[i].len = 2;
+	join_pref_params[i].rssi_gain = 0;
+
+	if (bss_select->behaviour != NL80211_BSS_SELECT_ATTR_BAND_PREF)
+		brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_ASSOC_PREFER, WLC_BAND_AUTO);
+
+	switch (bss_select->behaviour) {
+	case __NL80211_BSS_SELECT_ATTR_INVALID:
+		brcmf_c_set_joinpref_default(ifp);
+		return;
+	case NL80211_BSS_SELECT_ATTR_BAND_PREF:
+		join_pref_params[i].type = BRCMF_JOIN_PREF_BAND;
+		band = bss_select->param.band_pref;
+		join_pref_params[i].band = nl80211_band_to_fwil(band);
+		i++;
+		break;
+	case NL80211_BSS_SELECT_ATTR_RSSI_ADJUST:
+		join_pref_params[i].type = BRCMF_JOIN_PREF_RSSI_DELTA;
+		band = bss_select->param.adjust.band;
+		join_pref_params[i].band = nl80211_band_to_fwil(band);
+		join_pref_params[i].rssi_gain = bss_select->param.adjust.delta;
+		i++;
+		break;
+	case NL80211_BSS_SELECT_ATTR_RSSI:
+	default:
+		break;
+	}
+	join_pref_params[i].type = BRCMF_JOIN_PREF_RSSI;
+	join_pref_params[i].len = 2;
+	join_pref_params[i].rssi_gain = 0;
+	join_pref_params[i].band = 0;
+	err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params,
+				       sizeof(join_pref_params));
+	if (err)
+		brcmf_err("Set join_pref error (%d)\n", err);
+}
+
+static s32
+brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
+		       struct cfg80211_connect_params *sme)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
+	struct ieee80211_channel *chan = sme->channel;
+	struct brcmf_join_params join_params;
+	size_t join_params_size;
+	const struct brcmf_tlv *rsn_ie;
+	const struct brcmf_vs_tlv *wpa_ie;
+	const void *ie;
+	u32 ie_len;
+	struct brcmf_ext_join_params_le *ext_join_params;
+	u16 chanspec;
+	s32 err = 0;
+	u32 ssid_len;
+
+	brcmf_dbg(TRACE, "Enter\n");
+	if (!check_vif_up(ifp->vif))
+		return -EIO;
+
+	if (!sme->ssid) {
+		brcmf_err("Invalid ssid\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif) {
+		/* A normal (non P2P) connection request setup. */
+		ie = NULL;
+		ie_len = 0;
+		/* find the WPA_IE */
+		wpa_ie = brcmf_find_wpaie((u8 *)sme->ie, sme->ie_len);
+		if (wpa_ie) {
+			ie = wpa_ie;
+			ie_len = wpa_ie->len + TLV_HDR_LEN;
+		} else {
+			/* find the RSN_IE */
+			rsn_ie = brcmf_parse_tlvs((const u8 *)sme->ie,
+						  sme->ie_len,
+						  WLAN_EID_RSN);
+			if (rsn_ie) {
+				ie = rsn_ie;
+				ie_len = rsn_ie->len + TLV_HDR_LEN;
+			}
+		}
+		brcmf_fil_iovar_data_set(ifp, "wpaie", ie, ie_len);
+	}
+
+	err = brcmf_vif_set_mgmt_ie(ifp->vif, BRCMF_VNDR_IE_ASSOCREQ_FLAG,
+				    sme->ie, sme->ie_len);
+	if (err)
+		brcmf_err("Set Assoc REQ IE Failed\n");
+	else
+		brcmf_dbg(TRACE, "Applied Vndr IEs for Assoc request\n");
+
+	set_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
+
+	if (chan) {
+		cfg->channel =
+			ieee80211_frequency_to_channel(chan->center_freq);
+		chanspec = channel_to_chanspec(&cfg->d11inf, chan);
+		brcmf_dbg(CONN, "channel=%d, center_req=%d, chanspec=0x%04x\n",
+			  cfg->channel, chan->center_freq, chanspec);
+	} else {
+		cfg->channel = 0;
+		chanspec = 0;
+	}
+
+	brcmf_dbg(INFO, "ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len);
+
+	err = brcmf_set_wpa_version(ndev, sme);
+	if (err) {
+		brcmf_err("wl_set_wpa_version failed (%d)\n", err);
+		goto done;
+	}
+
+	sme->auth_type = brcmf_war_auth_type(ifp, sme->auth_type);
+	err = brcmf_set_auth_type(ndev, sme);
+	if (err) {
+		brcmf_err("wl_set_auth_type failed (%d)\n", err);
+		goto done;
+	}
+
+	err = brcmf_set_wsec_mode(ndev, sme);
+	if (err) {
+		brcmf_err("wl_set_set_cipher failed (%d)\n", err);
+		goto done;
+	}
+
+	err = brcmf_set_key_mgmt(ndev, sme);
+	if (err) {
+		brcmf_err("wl_set_key_mgmt failed (%d)\n", err);
+		goto done;
+	}
+
+	err = brcmf_set_sharedkey(ndev, sme);
+	if (err) {
+		brcmf_err("brcmf_set_sharedkey failed (%d)\n", err);
+		goto done;
+	}
+
+	if (sme->crypto.psk) {
+		if (WARN_ON(profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE)) {
+			err = -EINVAL;
+			goto done;
+		}
+		brcmf_dbg(INFO, "using PSK offload\n");
+		profile->use_fwsup = BRCMF_PROFILE_FWSUP_PSK;
+	}
+
+	if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE) {
+		/* enable firmware supplicant for this interface */
+		err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1);
+		if (err < 0) {
+			brcmf_err("failed to enable fw supplicant\n");
+			goto done;
+		}
+	}
+
+	if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_PSK) {
+		err = brcmf_set_pmk(ifp, sme->crypto.psk,
+				    BRCMF_WSEC_MAX_PSK_LEN);
+		if (err)
+			goto done;
+	}
+
+	/* Join with specific BSSID and cached SSID
+	 * If SSID is zero join based on BSSID only
+	 */
+	join_params_size = offsetof(struct brcmf_ext_join_params_le, assoc_le) +
+		offsetof(struct brcmf_assoc_params_le, chanspec_list);
+	if (cfg->channel)
+		join_params_size += sizeof(u16);
+	ext_join_params = kzalloc(join_params_size, GFP_KERNEL);
+	if (ext_join_params == NULL) {
+		err = -ENOMEM;
+		goto done;
+	}
+	ssid_len = min_t(u32, sme->ssid_len, IEEE80211_MAX_SSID_LEN);
+	ext_join_params->ssid_le.SSID_len = cpu_to_le32(ssid_len);
+	memcpy(&ext_join_params->ssid_le.SSID, sme->ssid, ssid_len);
+	if (ssid_len < IEEE80211_MAX_SSID_LEN)
+		brcmf_dbg(CONN, "SSID \"%s\", len (%d)\n",
+			  ext_join_params->ssid_le.SSID, ssid_len);
+
+	/* Set up join scan parameters */
+	ext_join_params->scan_le.scan_type = -1;
+	ext_join_params->scan_le.home_time = cpu_to_le32(-1);
+
+	if (sme->bssid)
+		memcpy(&ext_join_params->assoc_le.bssid, sme->bssid, ETH_ALEN);
+	else
+		eth_broadcast_addr(ext_join_params->assoc_le.bssid);
+
+	if (cfg->channel) {
+		ext_join_params->assoc_le.chanspec_num = cpu_to_le32(1);
+
+		ext_join_params->assoc_le.chanspec_list[0] =
+			cpu_to_le16(chanspec);
+		/* Increase dwell time to receive probe response or detect
+		 * beacon from target AP at a noisy air only during connect
+		 * command.
+		 */
+		ext_join_params->scan_le.active_time =
+			cpu_to_le32(BRCMF_SCAN_JOIN_ACTIVE_DWELL_TIME_MS);
+		ext_join_params->scan_le.passive_time =
+			cpu_to_le32(BRCMF_SCAN_JOIN_PASSIVE_DWELL_TIME_MS);
+		/* To sync with presence period of VSDB GO send probe request
+		 * more frequently. Probe request will be stopped when it gets
+		 * probe response from target AP/GO.
+		 */
+		ext_join_params->scan_le.nprobes =
+			cpu_to_le32(BRCMF_SCAN_JOIN_ACTIVE_DWELL_TIME_MS /
+				    BRCMF_SCAN_JOIN_PROBE_INTERVAL_MS);
+	} else {
+		ext_join_params->scan_le.active_time = cpu_to_le32(-1);
+		ext_join_params->scan_le.passive_time = cpu_to_le32(-1);
+		ext_join_params->scan_le.nprobes = cpu_to_le32(-1);
+	}
+
+	brcmf_set_join_pref(ifp, &sme->bss_select);
+
+	err  = brcmf_fil_bsscfg_data_set(ifp, "join", ext_join_params,
+					 join_params_size);
+	kfree(ext_join_params);
+	if (!err)
+		/* This is it. join command worked, we are done */
+		goto done;
+
+	/* join command failed, fallback to set ssid */
+	memset(&join_params, 0, sizeof(join_params));
+	join_params_size = sizeof(join_params.ssid_le);
+
+	memcpy(&join_params.ssid_le.SSID, sme->ssid, ssid_len);
+	join_params.ssid_le.SSID_len = cpu_to_le32(ssid_len);
+
+	if (sme->bssid)
+		memcpy(join_params.params_le.bssid, sme->bssid, ETH_ALEN);
+	else
+		eth_broadcast_addr(join_params.params_le.bssid);
+
+	if (cfg->channel) {
+		join_params.params_le.chanspec_list[0] = cpu_to_le16(chanspec);
+		join_params.params_le.chanspec_num = cpu_to_le32(1);
+		join_params_size += sizeof(join_params.params_le);
+	}
+	err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
+				     &join_params, join_params_size);
+	if (err)
+		brcmf_err("BRCMF_C_SET_SSID failed (%d)\n", err);
+
+done:
+	if (err)
+		clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
+	brcmf_dbg(TRACE, "Exit\n");
+	return err;
+}
+
+static s32
+brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev,
+		       u16 reason_code)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
+	struct brcmf_scb_val_le scbval;
+	s32 err = 0;
+
+	brcmf_dbg(TRACE, "Enter. Reason code = %d\n", reason_code);
+	if (!check_vif_up(ifp->vif))
+		return -EIO;
+
+	clear_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);
+	clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
+	cfg80211_disconnected(ndev, reason_code, NULL, 0, true, GFP_KERNEL);
+
+	memcpy(&scbval.ea, &profile->bssid, ETH_ALEN);
+	scbval.val = cpu_to_le32(reason_code);
+	err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_DISASSOC,
+				     &scbval, sizeof(scbval));
+	if (err)
+		brcmf_err("error (%d)\n", err);
+
+	brcmf_dbg(TRACE, "Exit\n");
+	return err;
+}
+
+static s32
+brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
+			    enum nl80211_tx_power_setting type, s32 mbm)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct net_device *ndev = cfg_to_ndev(cfg);
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	s32 err;
+	s32 disable;
+	u32 qdbm = 127;
+
+	brcmf_dbg(TRACE, "Enter %d %d\n", type, mbm);
+	if (!check_vif_up(ifp->vif))
+		return -EIO;
+
+	switch (type) {
+	case NL80211_TX_POWER_AUTOMATIC:
+		break;
+	case NL80211_TX_POWER_LIMITED:
+	case NL80211_TX_POWER_FIXED:
+		if (mbm < 0) {
+			brcmf_err("TX_POWER_FIXED - dbm is negative\n");
+			err = -EINVAL;
+			goto done;
+		}
+		qdbm =  MBM_TO_DBM(4 * mbm);
+		if (qdbm > 127)
+			qdbm = 127;
+		qdbm |= WL_TXPWR_OVERRIDE;
+		break;
+	default:
+		brcmf_err("Unsupported type %d\n", type);
+		err = -EINVAL;
+		goto done;
+	}
+	/* Make sure radio is off or on as far as software is concerned */
+	disable = WL_RADIO_SW_DISABLE << 16;
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_RADIO, disable);
+	if (err)
+		brcmf_err("WLC_SET_RADIO error (%d)\n", err);
+
+	err = brcmf_fil_iovar_int_set(ifp, "qtxpower", qdbm);
+	if (err)
+		brcmf_err("qtxpower error (%d)\n", err);
+
+done:
+	brcmf_dbg(TRACE, "Exit %d (qdbm)\n", qdbm & ~WL_TXPWR_OVERRIDE);
+	return err;
+}
+
+static s32
+brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
+			    s32 *dbm)
+{
+	struct brcmf_cfg80211_vif *vif = wdev_to_vif(wdev);
+	s32 qdbm = 0;
+	s32 err;
+
+	brcmf_dbg(TRACE, "Enter\n");
+	if (!check_vif_up(vif))
+		return -EIO;
+
+	err = brcmf_fil_iovar_int_get(vif->ifp, "qtxpower", &qdbm);
+	if (err) {
+		brcmf_err("error (%d)\n", err);
+		goto done;
+	}
+	*dbm = (qdbm & ~WL_TXPWR_OVERRIDE) / 4;
+
+done:
+	brcmf_dbg(TRACE, "Exit (0x%x %d)\n", qdbm, *dbm);
+	return err;
+}
+
+static s32
+brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev,
+				  u8 key_idx, bool unicast, bool multicast)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	u32 index;
+	u32 wsec;
+	s32 err = 0;
+
+	brcmf_dbg(TRACE, "Enter\n");
+	brcmf_dbg(CONN, "key index (%d)\n", key_idx);
+	if (!check_vif_up(ifp->vif))
+		return -EIO;
+
+	err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
+	if (err) {
+		brcmf_err("WLC_GET_WSEC error (%d)\n", err);
+		goto done;
+	}
+
+	if (wsec & WEP_ENABLED) {
+		/* Just select a new current key */
+		index = key_idx;
+		err = brcmf_fil_cmd_int_set(ifp,
+					    BRCMF_C_SET_KEY_PRIMARY, index);
+		if (err)
+			brcmf_err("error (%d)\n", err);
+	}
+done:
+	brcmf_dbg(TRACE, "Exit\n");
+	return err;
+}
+
+static s32
+brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
+		       u8 key_idx, bool pairwise, const u8 *mac_addr)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_wsec_key *key;
+	s32 err;
+
+	brcmf_dbg(TRACE, "Enter\n");
+	brcmf_dbg(CONN, "key index (%d)\n", key_idx);
+
+	if (!check_vif_up(ifp->vif))
+		return -EIO;
+
+	if (key_idx >= BRCMF_MAX_DEFAULT_KEYS) {
+		/* we ignore this key index in this case */
+		return -EINVAL;
+	}
+
+	key = &ifp->vif->profile.key[key_idx];
+
+	if (key->algo == CRYPTO_ALGO_OFF) {
+		brcmf_dbg(CONN, "Ignore clearing of (never configured) key\n");
+		return -EINVAL;
+	}
+
+	memset(key, 0, sizeof(*key));
+	key->index = (u32)key_idx;
+	key->flags = BRCMF_PRIMARY_KEY;
+
+	/* Clear the key/index */
+	err = send_key_to_dongle(ifp, key);
+
+	brcmf_dbg(TRACE, "Exit\n");
+	return err;
+}
+
+static s32
+brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
+		       u8 key_idx, bool pairwise, const u8 *mac_addr,
+		       struct key_params *params)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_wsec_key *key;
+	s32 val;
+	s32 wsec;
+	s32 err;
+	u8 keybuf[8];
+	bool ext_key;
+
+	brcmf_dbg(TRACE, "Enter\n");
+	brcmf_dbg(CONN, "key index (%d)\n", key_idx);
+	if (!check_vif_up(ifp->vif))
+		return -EIO;
+
+	if (key_idx >= BRCMF_MAX_DEFAULT_KEYS) {
+		/* we ignore this key index in this case */
+		brcmf_err("invalid key index (%d)\n", key_idx);
+		return -EINVAL;
+	}
+
+	if (params->key_len == 0)
+		return brcmf_cfg80211_del_key(wiphy, ndev, key_idx, pairwise,
+					      mac_addr);
+
+	if (params->key_len > sizeof(key->data)) {
+		brcmf_err("Too long key length (%u)\n", params->key_len);
+		return -EINVAL;
+	}
+
+	ext_key = false;
+	if (mac_addr && (params->cipher != WLAN_CIPHER_SUITE_WEP40) &&
+	    (params->cipher != WLAN_CIPHER_SUITE_WEP104)) {
+		brcmf_dbg(TRACE, "Ext key, mac %pM", mac_addr);
+		ext_key = true;
+	}
+
+	key = &ifp->vif->profile.key[key_idx];
+	memset(key, 0, sizeof(*key));
+	if ((ext_key) && (!is_multicast_ether_addr(mac_addr)))
+		memcpy((char *)&key->ea, (void *)mac_addr, ETH_ALEN);
+	key->len = params->key_len;
+	key->index = key_idx;
+	memcpy(key->data, params->key, key->len);
+	if (!ext_key)
+		key->flags = BRCMF_PRIMARY_KEY;
+
+	switch (params->cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+		key->algo = CRYPTO_ALGO_WEP1;
+		val = WEP_ENABLED;
+		brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP40\n");
+		break;
+	case WLAN_CIPHER_SUITE_WEP104:
+		key->algo = CRYPTO_ALGO_WEP128;
+		val = WEP_ENABLED;
+		brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
+		if (!brcmf_is_apmode(ifp->vif)) {
+			brcmf_dbg(CONN, "Swapping RX/TX MIC key\n");
+			memcpy(keybuf, &key->data[24], sizeof(keybuf));
+			memcpy(&key->data[24], &key->data[16], sizeof(keybuf));
+			memcpy(&key->data[16], keybuf, sizeof(keybuf));
+		}
+		key->algo = CRYPTO_ALGO_TKIP;
+		val = TKIP_ENABLED;
+		brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n");
+		break;
+	case WLAN_CIPHER_SUITE_AES_CMAC:
+		key->algo = CRYPTO_ALGO_AES_CCM;
+		val = AES_ENABLED;
+		brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");
+		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		key->algo = CRYPTO_ALGO_AES_CCM;
+		val = AES_ENABLED;
+		brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_CCMP\n");
+		break;
+	default:
+		brcmf_err("Invalid cipher (0x%x)\n", params->cipher);
+		err = -EINVAL;
+		goto done;
+	}
+
+	err = send_key_to_dongle(ifp, key);
+	if (ext_key || err)
+		goto done;
+
+	err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
+	if (err) {
+		brcmf_err("get wsec error (%d)\n", err);
+		goto done;
+	}
+	wsec |= val;
+	err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);
+	if (err) {
+		brcmf_err("set wsec error (%d)\n", err);
+		goto done;
+	}
+
+done:
+	brcmf_dbg(TRACE, "Exit\n");
+	return err;
+}
+
+static s32
+brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx,
+		       bool pairwise, const u8 *mac_addr, void *cookie,
+		       void (*callback)(void *cookie,
+					struct key_params *params))
+{
+	struct key_params params;
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
+	struct brcmf_cfg80211_security *sec;
+	s32 wsec;
+	s32 err = 0;
+
+	brcmf_dbg(TRACE, "Enter\n");
+	brcmf_dbg(CONN, "key index (%d)\n", key_idx);
+	if (!check_vif_up(ifp->vif))
+		return -EIO;
+
+	memset(&params, 0, sizeof(params));
+
+	err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
+	if (err) {
+		brcmf_err("WLC_GET_WSEC error (%d)\n", err);
+		/* Ignore this error, may happen during DISASSOC */
+		err = -EAGAIN;
+		goto done;
+	}
+	if (wsec & WEP_ENABLED) {
+		sec = &profile->sec;
+		if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
+			params.cipher = WLAN_CIPHER_SUITE_WEP40;
+			brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP40\n");
+		} else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
+			params.cipher = WLAN_CIPHER_SUITE_WEP104;
+			brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");
+		}
+	} else if (wsec & TKIP_ENABLED) {
+		params.cipher = WLAN_CIPHER_SUITE_TKIP;
+		brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n");
+	} else if (wsec & AES_ENABLED) {
+		params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
+		brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");
+	} else  {
+		brcmf_err("Invalid algo (0x%x)\n", wsec);
+		err = -EINVAL;
+		goto done;
+	}
+	callback(cookie, &params);
+
+done:
+	brcmf_dbg(TRACE, "Exit\n");
+	return err;
+}
+
+static s32
+brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
+				       struct net_device *ndev, u8 key_idx)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+
+	brcmf_dbg(TRACE, "Enter key_idx %d\n", key_idx);
+
+	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP))
+		return 0;
+
+	brcmf_dbg(INFO, "Not supported\n");
+
+	return -EOPNOTSUPP;
+}
+
+static void
+brcmf_cfg80211_reconfigure_wep(struct brcmf_if *ifp)
+{
+	s32 err;
+	u8 key_idx;
+	struct brcmf_wsec_key *key;
+	s32 wsec;
+
+	for (key_idx = 0; key_idx < BRCMF_MAX_DEFAULT_KEYS; key_idx++) {
+		key = &ifp->vif->profile.key[key_idx];
+		if ((key->algo == CRYPTO_ALGO_WEP1) ||
+		    (key->algo == CRYPTO_ALGO_WEP128))
+			break;
+	}
+	if (key_idx == BRCMF_MAX_DEFAULT_KEYS)
+		return;
+
+	err = send_key_to_dongle(ifp, key);
+	if (err) {
+		brcmf_err("Setting WEP key failed (%d)\n", err);
+		return;
+	}
+	err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
+	if (err) {
+		brcmf_err("get wsec error (%d)\n", err);
+		return;
+	}
+	wsec |= WEP_ENABLED;
+	err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);
+	if (err)
+		brcmf_err("set wsec error (%d)\n", err);
+}
+
+static void brcmf_convert_sta_flags(u32 fw_sta_flags, struct station_info *si)
+{
+	struct nl80211_sta_flag_update *sfu;
+
+	brcmf_dbg(TRACE, "flags %08x\n", fw_sta_flags);
+	si->filled |= BIT_ULL(NL80211_STA_INFO_STA_FLAGS);
+	sfu = &si->sta_flags;
+	sfu->mask = BIT(NL80211_STA_FLAG_WME) |
+		    BIT(NL80211_STA_FLAG_AUTHENTICATED) |
+		    BIT(NL80211_STA_FLAG_ASSOCIATED) |
+		    BIT(NL80211_STA_FLAG_AUTHORIZED);
+	if (fw_sta_flags & BRCMF_STA_WME)
+		sfu->set |= BIT(NL80211_STA_FLAG_WME);
+	if (fw_sta_flags & BRCMF_STA_AUTHE)
+		sfu->set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
+	if (fw_sta_flags & BRCMF_STA_ASSOC)
+		sfu->set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
+	if (fw_sta_flags & BRCMF_STA_AUTHO)
+		sfu->set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
+}
+
+static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si)
+{
+	struct {
+		__le32 len;
+		struct brcmf_bss_info_le bss_le;
+	} *buf;
+	u16 capability;
+	int err;
+
+	buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
+	if (!buf)
+		return;
+
+	buf->len = cpu_to_le32(WL_BSS_INFO_MAX);
+	err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO, buf,
+				     WL_BSS_INFO_MAX);
+	if (err) {
+		brcmf_err("Failed to get bss info (%d)\n", err);
+		goto out_kfree;
+	}
+	si->filled |= BIT_ULL(NL80211_STA_INFO_BSS_PARAM);
+	si->bss_param.beacon_interval = le16_to_cpu(buf->bss_le.beacon_period);
+	si->bss_param.dtim_period = buf->bss_le.dtim_period;
+	capability = le16_to_cpu(buf->bss_le.capability);
+	if (capability & IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT)
+		si->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT;
+	if (capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+		si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE;
+	if (capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
+		si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
+
+out_kfree:
+	kfree(buf);
+}
+
+static s32
+brcmf_cfg80211_get_station_ibss(struct brcmf_if *ifp,
+				struct station_info *sinfo)
+{
+	struct brcmf_scb_val_le scbval;
+	struct brcmf_pktcnt_le pktcnt;
+	s32 err;
+	u32 rate;
+	u32 rssi;
+
+	/* Get the current tx rate */
+	err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate);
+	if (err < 0) {
+		brcmf_err("BRCMF_C_GET_RATE error (%d)\n", err);
+		return err;
+	}
+	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
+	sinfo->txrate.legacy = rate * 5;
+
+	memset(&scbval, 0, sizeof(scbval));
+	err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI, &scbval,
+				     sizeof(scbval));
+	if (err) {
+		brcmf_err("BRCMF_C_GET_RSSI error (%d)\n", err);
+		return err;
+	}
+	rssi = le32_to_cpu(scbval.val);
+	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
+	sinfo->signal = rssi;
+
+	err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_GET_PKTCNTS, &pktcnt,
+				     sizeof(pktcnt));
+	if (err) {
+		brcmf_err("BRCMF_C_GET_GET_PKTCNTS error (%d)\n", err);
+		return err;
+	}
+	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS) |
+			 BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC) |
+			 BIT_ULL(NL80211_STA_INFO_TX_PACKETS) |
+			 BIT_ULL(NL80211_STA_INFO_TX_FAILED);
+	sinfo->rx_packets = le32_to_cpu(pktcnt.rx_good_pkt);
+	sinfo->rx_dropped_misc = le32_to_cpu(pktcnt.rx_bad_pkt);
+	sinfo->tx_packets = le32_to_cpu(pktcnt.tx_good_pkt);
+	sinfo->tx_failed  = le32_to_cpu(pktcnt.tx_bad_pkt);
+
+	return 0;
+}
+
+static s32
+brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
+			   const u8 *mac, struct station_info *sinfo)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_scb_val_le scb_val;
+	s32 err = 0;
+	struct brcmf_sta_info_le sta_info_le;
+	u32 sta_flags;
+	u32 is_tdls_peer;
+	s32 total_rssi;
+	s32 count_rssi;
+	int rssi;
+	u32 i;
+
+	brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac);
+	if (!check_vif_up(ifp->vif))
+		return -EIO;
+
+	if (brcmf_is_ibssmode(ifp->vif))
+		return brcmf_cfg80211_get_station_ibss(ifp, sinfo);
+
+	memset(&sta_info_le, 0, sizeof(sta_info_le));
+	memcpy(&sta_info_le, mac, ETH_ALEN);
+	err = brcmf_fil_iovar_data_get(ifp, "tdls_sta_info",
+				       &sta_info_le,
+				       sizeof(sta_info_le));
+	is_tdls_peer = !err;
+	if (err) {
+		err = brcmf_fil_iovar_data_get(ifp, "sta_info",
+					       &sta_info_le,
+					       sizeof(sta_info_le));
+		if (err < 0) {
+			brcmf_err("GET STA INFO failed, %d\n", err);
+			goto done;
+		}
+	}
+	brcmf_dbg(TRACE, "version %d\n", le16_to_cpu(sta_info_le.ver));
+	sinfo->filled = BIT_ULL(NL80211_STA_INFO_INACTIVE_TIME);
+	sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
+	sta_flags = le32_to_cpu(sta_info_le.flags);
+	brcmf_convert_sta_flags(sta_flags, sinfo);
+	sinfo->sta_flags.mask |= BIT(NL80211_STA_FLAG_TDLS_PEER);
+	if (is_tdls_peer)
+		sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
+	else
+		sinfo->sta_flags.set &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
+	if (sta_flags & BRCMF_STA_ASSOC) {
+		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CONNECTED_TIME);
+		sinfo->connected_time = le32_to_cpu(sta_info_le.in);
+		brcmf_fill_bss_param(ifp, sinfo);
+	}
+	if (sta_flags & BRCMF_STA_SCBSTATS) {
+		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
+		sinfo->tx_failed = le32_to_cpu(sta_info_le.tx_failures);
+		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
+		sinfo->tx_packets = le32_to_cpu(sta_info_le.tx_pkts);
+		sinfo->tx_packets += le32_to_cpu(sta_info_le.tx_mcast_pkts);
+		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS);
+		sinfo->rx_packets = le32_to_cpu(sta_info_le.rx_ucast_pkts);
+		sinfo->rx_packets += le32_to_cpu(sta_info_le.rx_mcast_pkts);
+		if (sinfo->tx_packets) {
+			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
+			sinfo->txrate.legacy =
+				le32_to_cpu(sta_info_le.tx_rate) / 100;
+		}
+		if (sinfo->rx_packets) {
+			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE);
+			sinfo->rxrate.legacy =
+				le32_to_cpu(sta_info_le.rx_rate) / 100;
+		}
+		if (le16_to_cpu(sta_info_le.ver) >= 4) {
+			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES);
+			sinfo->tx_bytes = le64_to_cpu(sta_info_le.tx_tot_bytes);
+			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES);
+			sinfo->rx_bytes = le64_to_cpu(sta_info_le.rx_tot_bytes);
+		}
+		total_rssi = 0;
+		count_rssi = 0;
+		for (i = 0; i < BRCMF_ANT_MAX; i++) {
+			if (sta_info_le.rssi[i]) {
+				sinfo->chain_signal_avg[count_rssi] =
+					sta_info_le.rssi[i];
+				sinfo->chain_signal[count_rssi] =
+					sta_info_le.rssi[i];
+				total_rssi += sta_info_le.rssi[i];
+				count_rssi++;
+			}
+		}
+		if (count_rssi) {
+			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL);
+			sinfo->chains = count_rssi;
+
+			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
+			total_rssi /= count_rssi;
+			sinfo->signal = total_rssi;
+		} else if (test_bit(BRCMF_VIF_STATUS_CONNECTED,
+			&ifp->vif->sme_state)) {
+			memset(&scb_val, 0, sizeof(scb_val));
+			err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI,
+						     &scb_val, sizeof(scb_val));
+			if (err) {
+				brcmf_err("Could not get rssi (%d)\n", err);
+				goto done;
+			} else {
+				rssi = le32_to_cpu(scb_val.val);
+				sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
+				sinfo->signal = rssi;
+				brcmf_dbg(CONN, "RSSI %d dBm\n", rssi);
+			}
+		}
+	}
+done:
+	brcmf_dbg(TRACE, "Exit\n");
+	return err;
+}
+
+static int
+brcmf_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *ndev,
+			    int idx, u8 *mac, struct station_info *sinfo)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	s32 err;
+
+	brcmf_dbg(TRACE, "Enter, idx %d\n", idx);
+
+	if (idx == 0) {
+		cfg->assoclist.count = cpu_to_le32(BRCMF_MAX_ASSOCLIST);
+		err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_ASSOCLIST,
+					     &cfg->assoclist,
+					     sizeof(cfg->assoclist));
+		if (err) {
+			brcmf_err("BRCMF_C_GET_ASSOCLIST unsupported, err=%d\n",
+				  err);
+			cfg->assoclist.count = 0;
+			return -EOPNOTSUPP;
+		}
+	}
+	if (idx < le32_to_cpu(cfg->assoclist.count)) {
+		memcpy(mac, cfg->assoclist.mac[idx], ETH_ALEN);
+		return brcmf_cfg80211_get_station(wiphy, ndev, mac, sinfo);
+	}
+	return -ENOENT;
+}
+
+static s32
+brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,
+			   bool enabled, s32 timeout)
+{
+	s32 pm;
+	s32 err = 0;
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_if *ifp = netdev_priv(ndev);
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	/*
+	 * Powersave enable/disable request is coming from the
+	 * cfg80211 even before the interface is up. In that
+	 * scenario, driver will be storing the power save
+	 * preference in cfg struct to apply this to
+	 * FW later while initializing the dongle
+	 */
+	cfg->pwr_save = enabled;
+	if (!check_vif_up(ifp->vif)) {
+
+		brcmf_dbg(INFO, "Device is not ready, storing the value in cfg_info struct\n");
+		goto done;
+	}
+
+	pm = enabled ? PM_FAST : PM_OFF;
+	/* Do not enable the power save after assoc if it is a p2p interface */
+	if (ifp->vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) {
+		brcmf_dbg(INFO, "Do not enable power save for P2P clients\n");
+		pm = PM_OFF;
+	}
+	brcmf_dbg(INFO, "power save %s\n", (pm ? "enabled" : "disabled"));
+
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, pm);
+	if (err) {
+		if (err == -ENODEV)
+			brcmf_err("net_device is not ready yet\n");
+		else
+			brcmf_err("error (%d)\n", err);
+	}
+done:
+	brcmf_dbg(TRACE, "Exit\n");
+	return err;
+}
+
+static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
+				   struct brcmf_bss_info_le *bi)
+{
+	struct wiphy *wiphy = cfg_to_wiphy(cfg);
+	struct cfg80211_bss *bss;
+	enum nl80211_band band;
+	struct brcmu_chan ch;
+	u16 channel;
+	u32 freq;
+	u16 notify_capability;
+	u16 notify_interval;
+	u8 *notify_ie;
+	size_t notify_ielen;
+	struct cfg80211_inform_bss bss_data = {};
+
+	if (le32_to_cpu(bi->length) > WL_BSS_INFO_MAX) {
+		brcmf_err("Bss info is larger than buffer. Discarding\n");
+		return 0;
+	}
+
+	if (!bi->ctl_ch) {
+		ch.chspec = le16_to_cpu(bi->chanspec);
+		cfg->d11inf.decchspec(&ch);
+		bi->ctl_ch = ch.control_ch_num;
+	}
+	channel = bi->ctl_ch;
+
+	if (channel <= CH_MAX_2G_CHANNEL)
+		band = NL80211_BAND_2GHZ;
+	else
+		band = NL80211_BAND_5GHZ;
+
+	freq = ieee80211_channel_to_frequency(channel, band);
+	bss_data.chan = ieee80211_get_channel(wiphy, freq);
+	bss_data.scan_width = NL80211_BSS_CHAN_WIDTH_20;
+	bss_data.boottime_ns = ktime_to_ns(ktime_get_boottime());
+
+	notify_capability = le16_to_cpu(bi->capability);
+	notify_interval = le16_to_cpu(bi->beacon_period);
+	notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
+	notify_ielen = le32_to_cpu(bi->ie_length);
+	bss_data.signal = (s16)le16_to_cpu(bi->RSSI) * 100;
+
+	brcmf_dbg(CONN, "bssid: %pM\n", bi->BSSID);
+	brcmf_dbg(CONN, "Channel: %d(%d)\n", channel, freq);
+	brcmf_dbg(CONN, "Capability: %X\n", notify_capability);
+	brcmf_dbg(CONN, "Beacon interval: %d\n", notify_interval);
+	brcmf_dbg(CONN, "Signal: %d\n", bss_data.signal);
+
+	bss = cfg80211_inform_bss_data(wiphy, &bss_data,
+				       CFG80211_BSS_FTYPE_UNKNOWN,
+				       (const u8 *)bi->BSSID,
+				       0, notify_capability,
+				       notify_interval, notify_ie,
+				       notify_ielen, GFP_KERNEL);
+
+	if (!bss)
+		return -ENOMEM;
+
+	cfg80211_put_bss(wiphy, bss);
+
+	return 0;
+}
+
+static struct brcmf_bss_info_le *
+next_bss_le(struct brcmf_scan_results *list, struct brcmf_bss_info_le *bss)
+{
+	if (bss == NULL)
+		return list->bss_info_le;
+	return (struct brcmf_bss_info_le *)((unsigned long)bss +
+					    le32_to_cpu(bss->length));
+}
+
+static s32 brcmf_inform_bss(struct brcmf_cfg80211_info *cfg)
+{
+	struct brcmf_scan_results *bss_list;
+	struct brcmf_bss_info_le *bi = NULL;	/* must be initialized */
+	s32 err = 0;
+	int i;
+
+	bss_list = (struct brcmf_scan_results *)cfg->escan_info.escan_buf;
+	if (bss_list->count != 0 &&
+	    bss_list->version != BRCMF_BSS_INFO_VERSION) {
+		brcmf_err("Version %d != WL_BSS_INFO_VERSION\n",
+			  bss_list->version);
+		return -EOPNOTSUPP;
+	}
+	brcmf_dbg(SCAN, "scanned AP count (%d)\n", bss_list->count);
+	for (i = 0; i < bss_list->count; i++) {
+		bi = next_bss_le(bss_list, bi);
+		err = brcmf_inform_single_bss(cfg, bi);
+		if (err)
+			break;
+	}
+	return err;
+}
+
+static s32 brcmf_inform_ibss(struct brcmf_cfg80211_info *cfg,
+			     struct net_device *ndev, const u8 *bssid)
+{
+	struct wiphy *wiphy = cfg_to_wiphy(cfg);
+	struct ieee80211_channel *notify_channel;
+	struct brcmf_bss_info_le *bi = NULL;
+	struct ieee80211_supported_band *band;
+	struct cfg80211_bss *bss;
+	struct brcmu_chan ch;
+	u8 *buf = NULL;
+	s32 err = 0;
+	u32 freq;
+	u16 notify_capability;
+	u16 notify_interval;
+	u8 *notify_ie;
+	size_t notify_ielen;
+	s32 notify_signal;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
+	if (buf == NULL) {
+		err = -ENOMEM;
+		goto CleanUp;
+	}
+
+	*(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
+
+	err = brcmf_fil_cmd_data_get(netdev_priv(ndev), BRCMF_C_GET_BSS_INFO,
+				     buf, WL_BSS_INFO_MAX);
+	if (err) {
+		brcmf_err("WLC_GET_BSS_INFO failed: %d\n", err);
+		goto CleanUp;
+	}
+
+	bi = (struct brcmf_bss_info_le *)(buf + 4);
+
+	ch.chspec = le16_to_cpu(bi->chanspec);
+	cfg->d11inf.decchspec(&ch);
+
+	if (ch.band == BRCMU_CHAN_BAND_2G)
+		band = wiphy->bands[NL80211_BAND_2GHZ];
+	else
+		band = wiphy->bands[NL80211_BAND_5GHZ];
+
+	freq = ieee80211_channel_to_frequency(ch.control_ch_num, band->band);
+	cfg->channel = freq;
+	notify_channel = ieee80211_get_channel(wiphy, freq);
+
+	notify_capability = le16_to_cpu(bi->capability);
+	notify_interval = le16_to_cpu(bi->beacon_period);
+	notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
+	notify_ielen = le32_to_cpu(bi->ie_length);
+	notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
+
+	brcmf_dbg(CONN, "channel: %d(%d)\n", ch.control_ch_num, freq);
+	brcmf_dbg(CONN, "capability: %X\n", notify_capability);
+	brcmf_dbg(CONN, "beacon interval: %d\n", notify_interval);
+	brcmf_dbg(CONN, "signal: %d\n", notify_signal);
+
+	bss = cfg80211_inform_bss(wiphy, notify_channel,
+				  CFG80211_BSS_FTYPE_UNKNOWN, bssid, 0,
+				  notify_capability, notify_interval,
+				  notify_ie, notify_ielen, notify_signal,
+				  GFP_KERNEL);
+
+	if (!bss) {
+		err = -ENOMEM;
+		goto CleanUp;
+	}
+
+	cfg80211_put_bss(wiphy, bss);
+
+CleanUp:
+
+	kfree(buf);
+
+	brcmf_dbg(TRACE, "Exit\n");
+
+	return err;
+}
+
+static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg,
+				 struct brcmf_if *ifp)
+{
+	struct brcmf_bss_info_le *bi;
+	const struct brcmf_tlv *tim;
+	u16 beacon_interval;
+	u8 dtim_period;
+	size_t ie_len;
+	u8 *ie;
+	s32 err = 0;
+
+	brcmf_dbg(TRACE, "Enter\n");
+	if (brcmf_is_ibssmode(ifp->vif))
+		return err;
+
+	*(__le32 *)cfg->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
+	err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO,
+				     cfg->extra_buf, WL_EXTRA_BUF_MAX);
+	if (err) {
+		brcmf_err("Could not get bss info %d\n", err);
+		goto update_bss_info_out;
+	}
+
+	bi = (struct brcmf_bss_info_le *)(cfg->extra_buf + 4);
+	err = brcmf_inform_single_bss(cfg, bi);
+	if (err)
+		goto update_bss_info_out;
+
+	ie = ((u8 *)bi) + le16_to_cpu(bi->ie_offset);
+	ie_len = le32_to_cpu(bi->ie_length);
+	beacon_interval = le16_to_cpu(bi->beacon_period);
+
+	tim = brcmf_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
+	if (tim)
+		dtim_period = tim->data[1];
+	else {
+		/*
+		* active scan was done so we could not get dtim
+		* information out of probe response.
+		* so we speficially query dtim information to dongle.
+		*/
+		u32 var;
+		err = brcmf_fil_iovar_int_get(ifp, "dtim_assoc", &var);
+		if (err) {
+			brcmf_err("wl dtim_assoc failed (%d)\n", err);
+			goto update_bss_info_out;
+		}
+		dtim_period = (u8)var;
+	}
+
+update_bss_info_out:
+	brcmf_dbg(TRACE, "Exit");
+	return err;
+}
+
+void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg)
+{
+	struct escan_info *escan = &cfg->escan_info;
+
+	set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);
+	if (cfg->int_escan_map || cfg->scan_request) {
+		escan->escan_state = WL_ESCAN_STATE_IDLE;
+		brcmf_notify_escan_complete(cfg, escan->ifp, true, true);
+	}
+	clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
+	clear_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);
+}
+
+static void brcmf_cfg80211_escan_timeout_worker(struct work_struct *work)
+{
+	struct brcmf_cfg80211_info *cfg =
+			container_of(work, struct brcmf_cfg80211_info,
+				     escan_timeout_work);
+
+	brcmf_inform_bss(cfg);
+	brcmf_notify_escan_complete(cfg, cfg->escan_info.ifp, true, true);
+}
+
+static void brcmf_escan_timeout(struct timer_list *t)
+{
+	struct brcmf_cfg80211_info *cfg =
+			from_timer(cfg, t, escan_timeout);
+
+	if (cfg->int_escan_map || cfg->scan_request) {
+		brcmf_err("timer expired\n");
+		schedule_work(&cfg->escan_timeout_work);
+	}
+}
+
+static s32
+brcmf_compare_update_same_bss(struct brcmf_cfg80211_info *cfg,
+			      struct brcmf_bss_info_le *bss,
+			      struct brcmf_bss_info_le *bss_info_le)
+{
+	struct brcmu_chan ch_bss, ch_bss_info_le;
+
+	ch_bss.chspec = le16_to_cpu(bss->chanspec);
+	cfg->d11inf.decchspec(&ch_bss);
+	ch_bss_info_le.chspec = le16_to_cpu(bss_info_le->chanspec);
+	cfg->d11inf.decchspec(&ch_bss_info_le);
+
+	if (!memcmp(&bss_info_le->BSSID, &bss->BSSID, ETH_ALEN) &&
+		ch_bss.band == ch_bss_info_le.band &&
+		bss_info_le->SSID_len == bss->SSID_len &&
+		!memcmp(bss_info_le->SSID, bss->SSID, bss_info_le->SSID_len)) {
+		if ((bss->flags & BRCMF_BSS_RSSI_ON_CHANNEL) ==
+			(bss_info_le->flags & BRCMF_BSS_RSSI_ON_CHANNEL)) {
+			s16 bss_rssi = le16_to_cpu(bss->RSSI);
+			s16 bss_info_rssi = le16_to_cpu(bss_info_le->RSSI);
+
+			/* preserve max RSSI if the measurements are
+			* both on-channel or both off-channel
+			*/
+			if (bss_info_rssi > bss_rssi)
+				bss->RSSI = bss_info_le->RSSI;
+		} else if ((bss->flags & BRCMF_BSS_RSSI_ON_CHANNEL) &&
+			(bss_info_le->flags & BRCMF_BSS_RSSI_ON_CHANNEL) == 0) {
+			/* preserve the on-channel rssi measurement
+			* if the new measurement is off channel
+			*/
+			bss->RSSI = bss_info_le->RSSI;
+			bss->flags |= BRCMF_BSS_RSSI_ON_CHANNEL;
+		}
+		return 1;
+	}
+	return 0;
+}
+
+static s32
+brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
+			     const struct brcmf_event_msg *e, void *data)
+{
+	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+	s32 status;
+	struct brcmf_escan_result_le *escan_result_le;
+	u32 escan_buflen;
+	struct brcmf_bss_info_le *bss_info_le;
+	struct brcmf_bss_info_le *bss = NULL;
+	u32 bi_length;
+	struct brcmf_scan_results *list;
+	u32 i;
+	bool aborted;
+
+	status = e->status;
+
+	if (status == BRCMF_E_STATUS_ABORT)
+		goto exit;
+
+	if (!test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
+		brcmf_err("scan not ready, bsscfgidx=%d\n", ifp->bsscfgidx);
+		return -EPERM;
+	}
+
+	if (status == BRCMF_E_STATUS_PARTIAL) {
+		brcmf_dbg(SCAN, "ESCAN Partial result\n");
+		if (e->datalen < sizeof(*escan_result_le)) {
+			brcmf_err("invalid event data length\n");
+			goto exit;
+		}
+		escan_result_le = (struct brcmf_escan_result_le *) data;
+		if (!escan_result_le) {
+			brcmf_err("Invalid escan result (NULL pointer)\n");
+			goto exit;
+		}
+		escan_buflen = le32_to_cpu(escan_result_le->buflen);
+		if (escan_buflen > BRCMF_ESCAN_BUF_SIZE ||
+		    escan_buflen > e->datalen ||
+		    escan_buflen < sizeof(*escan_result_le)) {
+			brcmf_err("Invalid escan buffer length: %d\n",
+				  escan_buflen);
+			goto exit;
+		}
+		if (le16_to_cpu(escan_result_le->bss_count) != 1) {
+			brcmf_err("Invalid bss_count %d: ignoring\n",
+				  escan_result_le->bss_count);
+			goto exit;
+		}
+		bss_info_le = &escan_result_le->bss_info_le;
+
+		if (brcmf_p2p_scan_finding_common_channel(cfg, bss_info_le))
+			goto exit;
+
+		if (!cfg->int_escan_map && !cfg->scan_request) {
+			brcmf_dbg(SCAN, "result without cfg80211 request\n");
+			goto exit;
+		}
+
+		bi_length = le32_to_cpu(bss_info_le->length);
+		if (bi_length != escan_buflen -	WL_ESCAN_RESULTS_FIXED_SIZE) {
+			brcmf_err("Ignoring invalid bss_info length: %d\n",
+				  bi_length);
+			goto exit;
+		}
+
+		if (!(cfg_to_wiphy(cfg)->interface_modes &
+					BIT(NL80211_IFTYPE_ADHOC))) {
+			if (le16_to_cpu(bss_info_le->capability) &
+						WLAN_CAPABILITY_IBSS) {
+				brcmf_err("Ignoring IBSS result\n");
+				goto exit;
+			}
+		}
+
+		list = (struct brcmf_scan_results *)
+				cfg->escan_info.escan_buf;
+		if (bi_length > BRCMF_ESCAN_BUF_SIZE - list->buflen) {
+			brcmf_err("Buffer is too small: ignoring\n");
+			goto exit;
+		}
+
+		for (i = 0; i < list->count; i++) {
+			bss = bss ? (struct brcmf_bss_info_le *)
+				((unsigned char *)bss +
+				le32_to_cpu(bss->length)) : list->bss_info_le;
+			if (brcmf_compare_update_same_bss(cfg, bss,
+							  bss_info_le))
+				goto exit;
+		}
+		memcpy(&cfg->escan_info.escan_buf[list->buflen], bss_info_le,
+		       bi_length);
+		list->version = le32_to_cpu(bss_info_le->version);
+		list->buflen += bi_length;
+		list->count++;
+	} else {
+		cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
+		if (brcmf_p2p_scan_finding_common_channel(cfg, NULL))
+			goto exit;
+		if (cfg->int_escan_map || cfg->scan_request) {
+			brcmf_inform_bss(cfg);
+			aborted = status != BRCMF_E_STATUS_SUCCESS;
+			brcmf_notify_escan_complete(cfg, ifp, aborted, false);
+		} else
+			brcmf_dbg(SCAN, "Ignored scan complete result 0x%x\n",
+				  status);
+	}
+exit:
+	return 0;
+}
+
+static void brcmf_init_escan(struct brcmf_cfg80211_info *cfg)
+{
+	brcmf_fweh_register(cfg->pub, BRCMF_E_ESCAN_RESULT,
+			    brcmf_cfg80211_escan_handler);
+	cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
+	/* Init scan_timeout timer */
+	timer_setup(&cfg->escan_timeout, brcmf_escan_timeout, 0);
+	INIT_WORK(&cfg->escan_timeout_work,
+		  brcmf_cfg80211_escan_timeout_worker);
+}
+
+static struct cfg80211_scan_request *
+brcmf_alloc_internal_escan_request(struct wiphy *wiphy, u32 n_netinfo) {
+	struct cfg80211_scan_request *req;
+	size_t req_size;
+
+	req_size = sizeof(*req) +
+		   n_netinfo * sizeof(req->channels[0]) +
+		   n_netinfo * sizeof(*req->ssids);
+
+	req = kzalloc(req_size, GFP_KERNEL);
+	if (req) {
+		req->wiphy = wiphy;
+		req->ssids = (void *)(&req->channels[0]) +
+			     n_netinfo * sizeof(req->channels[0]);
+	}
+	return req;
+}
+
+static int brcmf_internal_escan_add_info(struct cfg80211_scan_request *req,
+					 u8 *ssid, u8 ssid_len, u8 channel)
+{
+	struct ieee80211_channel *chan;
+	enum nl80211_band band;
+	int freq, i;
+
+	if (channel <= CH_MAX_2G_CHANNEL)
+		band = NL80211_BAND_2GHZ;
+	else
+		band = NL80211_BAND_5GHZ;
+
+	freq = ieee80211_channel_to_frequency(channel, band);
+	if (!freq)
+		return -EINVAL;
+
+	chan = ieee80211_get_channel(req->wiphy, freq);
+	if (!chan)
+		return -EINVAL;
+
+	for (i = 0; i < req->n_channels; i++) {
+		if (req->channels[i] == chan)
+			break;
+	}
+	if (i == req->n_channels)
+		req->channels[req->n_channels++] = chan;
+
+	for (i = 0; i < req->n_ssids; i++) {
+		if (req->ssids[i].ssid_len == ssid_len &&
+		    !memcmp(req->ssids[i].ssid, ssid, ssid_len))
+			break;
+	}
+	if (i == req->n_ssids) {
+		memcpy(req->ssids[req->n_ssids].ssid, ssid, ssid_len);
+		req->ssids[req->n_ssids++].ssid_len = ssid_len;
+	}
+	return 0;
+}
+
+static int brcmf_start_internal_escan(struct brcmf_if *ifp, u32 fwmap,
+				      struct cfg80211_scan_request *request)
+{
+	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+	int err;
+
+	if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
+		if (cfg->int_escan_map)
+			brcmf_dbg(SCAN, "aborting internal scan: map=%u\n",
+				  cfg->int_escan_map);
+		/* Abort any on-going scan */
+		brcmf_abort_scanning(cfg);
+	}
+
+	brcmf_dbg(SCAN, "start internal scan: map=%u\n", fwmap);
+	set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
+	cfg->escan_info.run = brcmf_run_escan;
+	err = brcmf_do_escan(ifp, request);
+	if (err) {
+		clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
+		return err;
+	}
+	cfg->int_escan_map = fwmap;
+	return 0;
+}
+
+static struct brcmf_pno_net_info_le *
+brcmf_get_netinfo_array(struct brcmf_pno_scanresults_le *pfn_v1)
+{
+	struct brcmf_pno_scanresults_v2_le *pfn_v2;
+	struct brcmf_pno_net_info_le *netinfo;
+
+	switch (pfn_v1->version) {
+	default:
+		WARN_ON(1);
+		/* fall-thru */
+	case cpu_to_le32(1):
+		netinfo = (struct brcmf_pno_net_info_le *)(pfn_v1 + 1);
+		break;
+	case cpu_to_le32(2):
+		pfn_v2 = (struct brcmf_pno_scanresults_v2_le *)pfn_v1;
+		netinfo = (struct brcmf_pno_net_info_le *)(pfn_v2 + 1);
+		break;
+	}
+
+	return netinfo;
+}
+
+/* PFN result doesn't have all the info which are required by the supplicant
+ * (For e.g IEs) Do a target Escan so that sched scan results are reported
+ * via wl_inform_single_bss in the required format. Escan does require the
+ * scan request in the form of cfg80211_scan_request. For timebeing, create
+ * cfg80211_scan_request one out of the received PNO event.
+ */
+static s32
+brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
+				const struct brcmf_event_msg *e, void *data)
+{
+	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+	struct brcmf_pno_net_info_le *netinfo, *netinfo_start;
+	struct cfg80211_scan_request *request = NULL;
+	struct wiphy *wiphy = cfg_to_wiphy(cfg);
+	int i, err = 0;
+	struct brcmf_pno_scanresults_le *pfn_result;
+	u32 bucket_map;
+	u32 result_count;
+	u32 status;
+	u32 datalen;
+
+	brcmf_dbg(SCAN, "Enter\n");
+
+	if (e->datalen < (sizeof(*pfn_result) + sizeof(*netinfo))) {
+		brcmf_dbg(SCAN, "Event data to small. Ignore\n");
+		return 0;
+	}
+
+	if (e->event_code == BRCMF_E_PFN_NET_LOST) {
+		brcmf_dbg(SCAN, "PFN NET LOST event. Do Nothing\n");
+		return 0;
+	}
+
+	pfn_result = (struct brcmf_pno_scanresults_le *)data;
+	result_count = le32_to_cpu(pfn_result->count);
+	status = le32_to_cpu(pfn_result->status);
+
+	/* PFN event is limited to fit 512 bytes so we may get
+	 * multiple NET_FOUND events. For now place a warning here.
+	 */
+	WARN_ON(status != BRCMF_PNO_SCAN_COMPLETE);
+	brcmf_dbg(SCAN, "PFN NET FOUND event. count: %d\n", result_count);
+	if (!result_count) {
+		brcmf_err("FALSE PNO Event. (pfn_count == 0)\n");
+		goto out_err;
+	}
+
+	netinfo_start = brcmf_get_netinfo_array(pfn_result);
+	datalen = e->datalen - ((void *)netinfo_start - (void *)pfn_result);
+	if (datalen < result_count * sizeof(*netinfo)) {
+		brcmf_err("insufficient event data\n");
+		goto out_err;
+	}
+
+	request = brcmf_alloc_internal_escan_request(wiphy,
+						     result_count);
+	if (!request) {
+		err = -ENOMEM;
+		goto out_err;
+	}
+
+	bucket_map = 0;
+	for (i = 0; i < result_count; i++) {
+		netinfo = &netinfo_start[i];
+
+		if (netinfo->SSID_len > IEEE80211_MAX_SSID_LEN)
+			netinfo->SSID_len = IEEE80211_MAX_SSID_LEN;
+		brcmf_dbg(SCAN, "SSID:%.32s Channel:%d\n",
+			  netinfo->SSID, netinfo->channel);
+		bucket_map |= brcmf_pno_get_bucket_map(cfg->pno, netinfo);
+		err = brcmf_internal_escan_add_info(request,
+						    netinfo->SSID,
+						    netinfo->SSID_len,
+						    netinfo->channel);
+		if (err)
+			goto out_err;
+	}
+
+	if (!bucket_map)
+		goto free_req;
+
+	err = brcmf_start_internal_escan(ifp, bucket_map, request);
+	if (!err)
+		goto free_req;
+
+out_err:
+	cfg80211_sched_scan_stopped(wiphy, 0);
+free_req:
+	kfree(request);
+	return err;
+}
+
+static int
+brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
+				struct net_device *ndev,
+				struct cfg80211_sched_scan_request *req)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+
+	brcmf_dbg(SCAN, "Enter: n_match_sets=%d n_ssids=%d\n",
+		  req->n_match_sets, req->n_ssids);
+
+	if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) {
+		brcmf_err("Scanning suppressed: status=%lu\n",
+			  cfg->scan_status);
+		return -EAGAIN;
+	}
+
+	if (req->n_match_sets <= 0) {
+		brcmf_dbg(SCAN, "invalid number of matchsets specified: %d\n",
+			  req->n_match_sets);
+		return -EINVAL;
+	}
+
+	return brcmf_pno_start_sched_scan(ifp, req);
+}
+
+static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,
+					  struct net_device *ndev, u64 reqid)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_if *ifp = netdev_priv(ndev);
+
+	brcmf_dbg(SCAN, "enter\n");
+	brcmf_pno_stop_sched_scan(ifp, reqid);
+	if (cfg->int_escan_map)
+		brcmf_notify_escan_complete(cfg, ifp, true, true);
+	return 0;
+}
+
+static __always_inline void brcmf_delay(u32 ms)
+{
+	if (ms < 1000 / HZ) {
+		cond_resched();
+		mdelay(ms);
+	} else {
+		msleep(ms);
+	}
+}
+
+static s32 brcmf_config_wowl_pattern(struct brcmf_if *ifp, u8 cmd[4],
+				     u8 *pattern, u32 patternsize, u8 *mask,
+				     u32 packet_offset)
+{
+	struct brcmf_fil_wowl_pattern_le *filter;
+	u32 masksize;
+	u32 patternoffset;
+	u8 *buf;
+	u32 bufsize;
+	s32 ret;
+
+	masksize = (patternsize + 7) / 8;
+	patternoffset = sizeof(*filter) - sizeof(filter->cmd) + masksize;
+
+	bufsize = sizeof(*filter) + patternsize + masksize;
+	buf = kzalloc(bufsize, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	filter = (struct brcmf_fil_wowl_pattern_le *)buf;
+
+	memcpy(filter->cmd, cmd, 4);
+	filter->masksize = cpu_to_le32(masksize);
+	filter->offset = cpu_to_le32(packet_offset);
+	filter->patternoffset = cpu_to_le32(patternoffset);
+	filter->patternsize = cpu_to_le32(patternsize);
+	filter->type = cpu_to_le32(BRCMF_WOWL_PATTERN_TYPE_BITMAP);
+
+	if ((mask) && (masksize))
+		memcpy(buf + sizeof(*filter), mask, masksize);
+	if ((pattern) && (patternsize))
+		memcpy(buf + sizeof(*filter) + masksize, pattern, patternsize);
+
+	ret = brcmf_fil_iovar_data_set(ifp, "wowl_pattern", buf, bufsize);
+
+	kfree(buf);
+	return ret;
+}
+
+static s32
+brcmf_wowl_nd_results(struct brcmf_if *ifp, const struct brcmf_event_msg *e,
+		      void *data)
+{
+	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+	struct brcmf_pno_scanresults_le *pfn_result;
+	struct brcmf_pno_net_info_le *netinfo;
+
+	brcmf_dbg(SCAN, "Enter\n");
+
+	if (e->datalen < (sizeof(*pfn_result) + sizeof(*netinfo))) {
+		brcmf_dbg(SCAN, "Event data to small. Ignore\n");
+		return 0;
+	}
+
+	pfn_result = (struct brcmf_pno_scanresults_le *)data;
+
+	if (e->event_code == BRCMF_E_PFN_NET_LOST) {
+		brcmf_dbg(SCAN, "PFN NET LOST event. Ignore\n");
+		return 0;
+	}
+
+	if (le32_to_cpu(pfn_result->count) < 1) {
+		brcmf_err("Invalid result count, expected 1 (%d)\n",
+			  le32_to_cpu(pfn_result->count));
+		return -EINVAL;
+	}
+
+	netinfo = brcmf_get_netinfo_array(pfn_result);
+	memcpy(cfg->wowl.nd->ssid.ssid, netinfo->SSID, netinfo->SSID_len);
+	cfg->wowl.nd->ssid.ssid_len = netinfo->SSID_len;
+	cfg->wowl.nd->n_channels = 1;
+	cfg->wowl.nd->channels[0] =
+		ieee80211_channel_to_frequency(netinfo->channel,
+			netinfo->channel <= CH_MAX_2G_CHANNEL ?
+					NL80211_BAND_2GHZ : NL80211_BAND_5GHZ);
+	cfg->wowl.nd_info->n_matches = 1;
+	cfg->wowl.nd_info->matches[0] = cfg->wowl.nd;
+
+	/* Inform (the resume task) that the net detect information was recvd */
+	cfg->wowl.nd_data_completed = true;
+	wake_up(&cfg->wowl.nd_data_wait);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static void brcmf_report_wowl_wakeind(struct wiphy *wiphy, struct brcmf_if *ifp)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_wowl_wakeind_le wake_ind_le;
+	struct cfg80211_wowlan_wakeup wakeup_data;
+	struct cfg80211_wowlan_wakeup *wakeup;
+	u32 wakeind;
+	s32 err;
+	int timeout;
+
+	err = brcmf_fil_iovar_data_get(ifp, "wowl_wakeind", &wake_ind_le,
+				       sizeof(wake_ind_le));
+	if (err) {
+		brcmf_err("Get wowl_wakeind failed, err = %d\n", err);
+		return;
+	}
+
+	wakeind = le32_to_cpu(wake_ind_le.ucode_wakeind);
+	if (wakeind & (BRCMF_WOWL_MAGIC | BRCMF_WOWL_DIS | BRCMF_WOWL_BCN |
+		       BRCMF_WOWL_RETR | BRCMF_WOWL_NET |
+		       BRCMF_WOWL_PFN_FOUND)) {
+		wakeup = &wakeup_data;
+		memset(&wakeup_data, 0, sizeof(wakeup_data));
+		wakeup_data.pattern_idx = -1;
+
+		if (wakeind & BRCMF_WOWL_MAGIC) {
+			brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_MAGIC\n");
+			wakeup_data.magic_pkt = true;
+		}
+		if (wakeind & BRCMF_WOWL_DIS) {
+			brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_DIS\n");
+			wakeup_data.disconnect = true;
+		}
+		if (wakeind & BRCMF_WOWL_BCN) {
+			brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_BCN\n");
+			wakeup_data.disconnect = true;
+		}
+		if (wakeind & BRCMF_WOWL_RETR) {
+			brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_RETR\n");
+			wakeup_data.disconnect = true;
+		}
+		if (wakeind & BRCMF_WOWL_NET) {
+			brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_NET\n");
+			/* For now always map to pattern 0, no API to get
+			 * correct information available at the moment.
+			 */
+			wakeup_data.pattern_idx = 0;
+		}
+		if (wakeind & BRCMF_WOWL_PFN_FOUND) {
+			brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_PFN_FOUND\n");
+			timeout = wait_event_timeout(cfg->wowl.nd_data_wait,
+				cfg->wowl.nd_data_completed,
+				BRCMF_ND_INFO_TIMEOUT);
+			if (!timeout)
+				brcmf_err("No result for wowl net detect\n");
+			else
+				wakeup_data.net_detect = cfg->wowl.nd_info;
+		}
+		if (wakeind & BRCMF_WOWL_GTK_FAILURE) {
+			brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_GTK_FAILURE\n");
+			wakeup_data.gtk_rekey_failure = true;
+		}
+	} else {
+		wakeup = NULL;
+	}
+	cfg80211_report_wowlan_wakeup(&ifp->vif->wdev, wakeup, GFP_KERNEL);
+}
+
+#else
+
+static void brcmf_report_wowl_wakeind(struct wiphy *wiphy, struct brcmf_if *ifp)
+{
+}
+
+#endif /* CONFIG_PM */
+
+static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct net_device *ndev = cfg_to_ndev(cfg);
+	struct brcmf_if *ifp = netdev_priv(ndev);
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	if (cfg->wowl.active) {
+		brcmf_report_wowl_wakeind(wiphy, ifp);
+		brcmf_fil_iovar_int_set(ifp, "wowl_clear", 0);
+		brcmf_config_wowl_pattern(ifp, "clr", NULL, 0, NULL, 0);
+		if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_ARP_ND))
+			brcmf_configure_arp_nd_offload(ifp, true);
+		brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM,
+				      cfg->wowl.pre_pmmode);
+		cfg->wowl.active = false;
+		if (cfg->wowl.nd_enabled) {
+			brcmf_cfg80211_sched_scan_stop(cfg->wiphy, ifp->ndev, 0);
+			brcmf_fweh_unregister(cfg->pub, BRCMF_E_PFN_NET_FOUND);
+			brcmf_fweh_register(cfg->pub, BRCMF_E_PFN_NET_FOUND,
+					    brcmf_notify_sched_scan_results);
+			cfg->wowl.nd_enabled = false;
+		}
+	}
+	return 0;
+}
+
+static void brcmf_configure_wowl(struct brcmf_cfg80211_info *cfg,
+				 struct brcmf_if *ifp,
+				 struct cfg80211_wowlan *wowl)
+{
+	u32 wowl_config;
+	struct brcmf_wowl_wakeind_le wowl_wakeind;
+	u32 i;
+
+	brcmf_dbg(TRACE, "Suspend, wowl config.\n");
+
+	if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_ARP_ND))
+		brcmf_configure_arp_nd_offload(ifp, false);
+	brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_PM, &cfg->wowl.pre_pmmode);
+	brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, PM_MAX);
+
+	wowl_config = 0;
+	if (wowl->disconnect)
+		wowl_config = BRCMF_WOWL_DIS | BRCMF_WOWL_BCN | BRCMF_WOWL_RETR;
+	if (wowl->magic_pkt)
+		wowl_config |= BRCMF_WOWL_MAGIC;
+	if ((wowl->patterns) && (wowl->n_patterns)) {
+		wowl_config |= BRCMF_WOWL_NET;
+		for (i = 0; i < wowl->n_patterns; i++) {
+			brcmf_config_wowl_pattern(ifp, "add",
+				(u8 *)wowl->patterns[i].pattern,
+				wowl->patterns[i].pattern_len,
+				(u8 *)wowl->patterns[i].mask,
+				wowl->patterns[i].pkt_offset);
+		}
+	}
+	if (wowl->nd_config) {
+		brcmf_cfg80211_sched_scan_start(cfg->wiphy, ifp->ndev,
+						wowl->nd_config);
+		wowl_config |= BRCMF_WOWL_PFN_FOUND;
+
+		cfg->wowl.nd_data_completed = false;
+		cfg->wowl.nd_enabled = true;
+		/* Now reroute the event for PFN to the wowl function. */
+		brcmf_fweh_unregister(cfg->pub, BRCMF_E_PFN_NET_FOUND);
+		brcmf_fweh_register(cfg->pub, BRCMF_E_PFN_NET_FOUND,
+				    brcmf_wowl_nd_results);
+	}
+	if (wowl->gtk_rekey_failure)
+		wowl_config |= BRCMF_WOWL_GTK_FAILURE;
+	if (!test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state))
+		wowl_config |= BRCMF_WOWL_UNASSOC;
+
+	memcpy(&wowl_wakeind, "clear", 6);
+	brcmf_fil_iovar_data_set(ifp, "wowl_wakeind", &wowl_wakeind,
+				 sizeof(wowl_wakeind));
+	brcmf_fil_iovar_int_set(ifp, "wowl", wowl_config);
+	brcmf_fil_iovar_int_set(ifp, "wowl_activate", 1);
+	brcmf_bus_wowl_config(cfg->pub->bus_if, true);
+	cfg->wowl.active = true;
+}
+
+static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
+				  struct cfg80211_wowlan *wowl)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct net_device *ndev = cfg_to_ndev(cfg);
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_cfg80211_vif *vif;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	/* if the primary net_device is not READY there is nothing
+	 * we can do but pray resume goes smoothly.
+	 */
+	if (!check_vif_up(ifp->vif))
+		goto exit;
+
+	/* Stop scheduled scan */
+	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO))
+		brcmf_cfg80211_sched_scan_stop(wiphy, ndev, 0);
+
+	/* end any scanning */
+	if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status))
+		brcmf_abort_scanning(cfg);
+
+	if (wowl == NULL) {
+		brcmf_bus_wowl_config(cfg->pub->bus_if, false);
+		list_for_each_entry(vif, &cfg->vif_list, list) {
+			if (!test_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state))
+				continue;
+			/* While going to suspend if associated with AP
+			 * disassociate from AP to save power while system is
+			 * in suspended state
+			 */
+			brcmf_link_down(vif, WLAN_REASON_UNSPECIFIED);
+			/* Make sure WPA_Supplicant receives all the event
+			 * generated due to DISASSOC call to the fw to keep
+			 * the state fw and WPA_Supplicant state consistent
+			 */
+			brcmf_delay(500);
+		}
+		/* Configure MPC */
+		brcmf_set_mpc(ifp, 1);
+
+	} else {
+		/* Configure WOWL paramaters */
+		brcmf_configure_wowl(cfg, ifp, wowl);
+	}
+
+exit:
+	brcmf_dbg(TRACE, "Exit\n");
+	/* clear any scanning activity */
+	cfg->scan_status = 0;
+	return 0;
+}
+
+static __used s32
+brcmf_update_pmklist(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp)
+{
+	struct brcmf_pmk_list_le *pmk_list;
+	int i;
+	u32 npmk;
+	s32 err;
+
+	pmk_list = &cfg->pmk_list;
+	npmk = le32_to_cpu(pmk_list->npmk);
+
+	brcmf_dbg(CONN, "No of elements %d\n", npmk);
+	for (i = 0; i < npmk; i++)
+		brcmf_dbg(CONN, "PMK[%d]: %pM\n", i, &pmk_list->pmk[i].bssid);
+
+	err = brcmf_fil_iovar_data_set(ifp, "pmkid_info", pmk_list,
+				       sizeof(*pmk_list));
+
+	return err;
+}
+
+static s32
+brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
+			 struct cfg80211_pmksa *pmksa)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_pmksa *pmk = &cfg->pmk_list.pmk[0];
+	s32 err;
+	u32 npmk, i;
+
+	brcmf_dbg(TRACE, "Enter\n");
+	if (!check_vif_up(ifp->vif))
+		return -EIO;
+
+	npmk = le32_to_cpu(cfg->pmk_list.npmk);
+	for (i = 0; i < npmk; i++)
+		if (!memcmp(pmksa->bssid, pmk[i].bssid, ETH_ALEN))
+			break;
+	if (i < BRCMF_MAXPMKID) {
+		memcpy(pmk[i].bssid, pmksa->bssid, ETH_ALEN);
+		memcpy(pmk[i].pmkid, pmksa->pmkid, WLAN_PMKID_LEN);
+		if (i == npmk) {
+			npmk++;
+			cfg->pmk_list.npmk = cpu_to_le32(npmk);
+		}
+	} else {
+		brcmf_err("Too many PMKSA entries cached %d\n", npmk);
+		return -EINVAL;
+	}
+
+	brcmf_dbg(CONN, "set_pmksa - PMK bssid: %pM =\n", pmk[npmk].bssid);
+	for (i = 0; i < WLAN_PMKID_LEN; i += 4)
+		brcmf_dbg(CONN, "%02x %02x %02x %02x\n", pmk[npmk].pmkid[i],
+			  pmk[npmk].pmkid[i + 1], pmk[npmk].pmkid[i + 2],
+			  pmk[npmk].pmkid[i + 3]);
+
+	err = brcmf_update_pmklist(cfg, ifp);
+
+	brcmf_dbg(TRACE, "Exit\n");
+	return err;
+}
+
+static s32
+brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
+			 struct cfg80211_pmksa *pmksa)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_pmksa *pmk = &cfg->pmk_list.pmk[0];
+	s32 err;
+	u32 npmk, i;
+
+	brcmf_dbg(TRACE, "Enter\n");
+	if (!check_vif_up(ifp->vif))
+		return -EIO;
+
+	brcmf_dbg(CONN, "del_pmksa - PMK bssid = %pM\n", pmksa->bssid);
+
+	npmk = le32_to_cpu(cfg->pmk_list.npmk);
+	for (i = 0; i < npmk; i++)
+		if (!memcmp(pmksa->bssid, pmk[i].bssid, ETH_ALEN))
+			break;
+
+	if ((npmk > 0) && (i < npmk)) {
+		for (; i < (npmk - 1); i++) {
+			memcpy(&pmk[i].bssid, &pmk[i + 1].bssid, ETH_ALEN);
+			memcpy(&pmk[i].pmkid, &pmk[i + 1].pmkid,
+			       WLAN_PMKID_LEN);
+		}
+		memset(&pmk[i], 0, sizeof(*pmk));
+		cfg->pmk_list.npmk = cpu_to_le32(npmk - 1);
+	} else {
+		brcmf_err("Cache entry not found\n");
+		return -EINVAL;
+	}
+
+	err = brcmf_update_pmklist(cfg, ifp);
+
+	brcmf_dbg(TRACE, "Exit\n");
+	return err;
+
+}
+
+static s32
+brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	s32 err;
+
+	brcmf_dbg(TRACE, "Enter\n");
+	if (!check_vif_up(ifp->vif))
+		return -EIO;
+
+	memset(&cfg->pmk_list, 0, sizeof(cfg->pmk_list));
+	err = brcmf_update_pmklist(cfg, ifp);
+
+	brcmf_dbg(TRACE, "Exit\n");
+	return err;
+
+}
+
+static s32 brcmf_configure_opensecurity(struct brcmf_if *ifp)
+{
+	s32 err;
+	s32 wpa_val;
+
+	/* set auth */
+	err = brcmf_fil_bsscfg_int_set(ifp, "auth", 0);
+	if (err < 0) {
+		brcmf_err("auth error %d\n", err);
+		return err;
+	}
+	/* set wsec */
+	err = brcmf_fil_bsscfg_int_set(ifp, "wsec", 0);
+	if (err < 0) {
+		brcmf_err("wsec error %d\n", err);
+		return err;
+	}
+	/* set upper-layer auth */
+	if (brcmf_is_ibssmode(ifp->vif))
+		wpa_val = WPA_AUTH_NONE;
+	else
+		wpa_val = WPA_AUTH_DISABLED;
+	err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", wpa_val);
+	if (err < 0) {
+		brcmf_err("wpa_auth error %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static bool brcmf_valid_wpa_oui(u8 *oui, bool is_rsn_ie)
+{
+	if (is_rsn_ie)
+		return (memcmp(oui, RSN_OUI, TLV_OUI_LEN) == 0);
+
+	return (memcmp(oui, WPA_OUI, TLV_OUI_LEN) == 0);
+}
+
+static s32
+brcmf_configure_wpaie(struct brcmf_if *ifp,
+		      const struct brcmf_vs_tlv *wpa_ie,
+		      bool is_rsn_ie)
+{
+	u32 auth = 0; /* d11 open authentication */
+	u16 count;
+	s32 err = 0;
+	s32 len;
+	u32 i;
+	u32 wsec;
+	u32 pval = 0;
+	u32 gval = 0;
+	u32 wpa_auth = 0;
+	u32 offset;
+	u8 *data;
+	u16 rsn_cap;
+	u32 wme_bss_disable;
+	u32 mfp;
+
+	brcmf_dbg(TRACE, "Enter\n");
+	if (wpa_ie == NULL)
+		goto exit;
+
+	len = wpa_ie->len + TLV_HDR_LEN;
+	data = (u8 *)wpa_ie;
+	offset = TLV_HDR_LEN;
+	if (!is_rsn_ie)
+		offset += VS_IE_FIXED_HDR_LEN;
+	else
+		offset += WPA_IE_VERSION_LEN;
+
+	/* check for multicast cipher suite */
+	if (offset + WPA_IE_MIN_OUI_LEN > len) {
+		err = -EINVAL;
+		brcmf_err("no multicast cipher suite\n");
+		goto exit;
+	}
+
+	if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
+		err = -EINVAL;
+		brcmf_err("ivalid OUI\n");
+		goto exit;
+	}
+	offset += TLV_OUI_LEN;
+
+	/* pick up multicast cipher */
+	switch (data[offset]) {
+	case WPA_CIPHER_NONE:
+		gval = 0;
+		break;
+	case WPA_CIPHER_WEP_40:
+	case WPA_CIPHER_WEP_104:
+		gval = WEP_ENABLED;
+		break;
+	case WPA_CIPHER_TKIP:
+		gval = TKIP_ENABLED;
+		break;
+	case WPA_CIPHER_AES_CCM:
+		gval = AES_ENABLED;
+		break;
+	default:
+		err = -EINVAL;
+		brcmf_err("Invalid multi cast cipher info\n");
+		goto exit;
+	}
+
+	offset++;
+	/* walk thru unicast cipher list and pick up what we recognize */
+	count = data[offset] + (data[offset + 1] << 8);
+	offset += WPA_IE_SUITE_COUNT_LEN;
+	/* Check for unicast suite(s) */
+	if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) {
+		err = -EINVAL;
+		brcmf_err("no unicast cipher suite\n");
+		goto exit;
+	}
+	for (i = 0; i < count; i++) {
+		if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
+			err = -EINVAL;
+			brcmf_err("ivalid OUI\n");
+			goto exit;
+		}
+		offset += TLV_OUI_LEN;
+		switch (data[offset]) {
+		case WPA_CIPHER_NONE:
+			break;
+		case WPA_CIPHER_WEP_40:
+		case WPA_CIPHER_WEP_104:
+			pval |= WEP_ENABLED;
+			break;
+		case WPA_CIPHER_TKIP:
+			pval |= TKIP_ENABLED;
+			break;
+		case WPA_CIPHER_AES_CCM:
+			pval |= AES_ENABLED;
+			break;
+		default:
+			brcmf_err("Invalid unicast security info\n");
+		}
+		offset++;
+	}
+	/* walk thru auth management suite list and pick up what we recognize */
+	count = data[offset] + (data[offset + 1] << 8);
+	offset += WPA_IE_SUITE_COUNT_LEN;
+	/* Check for auth key management suite(s) */
+	if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) {
+		err = -EINVAL;
+		brcmf_err("no auth key mgmt suite\n");
+		goto exit;
+	}
+	for (i = 0; i < count; i++) {
+		if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
+			err = -EINVAL;
+			brcmf_err("ivalid OUI\n");
+			goto exit;
+		}
+		offset += TLV_OUI_LEN;
+		switch (data[offset]) {
+		case RSN_AKM_NONE:
+			brcmf_dbg(TRACE, "RSN_AKM_NONE\n");
+			wpa_auth |= WPA_AUTH_NONE;
+			break;
+		case RSN_AKM_UNSPECIFIED:
+			brcmf_dbg(TRACE, "RSN_AKM_UNSPECIFIED\n");
+			is_rsn_ie ? (wpa_auth |= WPA2_AUTH_UNSPECIFIED) :
+				    (wpa_auth |= WPA_AUTH_UNSPECIFIED);
+			break;
+		case RSN_AKM_PSK:
+			brcmf_dbg(TRACE, "RSN_AKM_PSK\n");
+			is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) :
+				    (wpa_auth |= WPA_AUTH_PSK);
+			break;
+		case RSN_AKM_SHA256_PSK:
+			brcmf_dbg(TRACE, "RSN_AKM_MFP_PSK\n");
+			wpa_auth |= WPA2_AUTH_PSK_SHA256;
+			break;
+		case RSN_AKM_SHA256_1X:
+			brcmf_dbg(TRACE, "RSN_AKM_MFP_1X\n");
+			wpa_auth |= WPA2_AUTH_1X_SHA256;
+			break;
+		default:
+			brcmf_err("Invalid key mgmt info\n");
+		}
+		offset++;
+	}
+
+	mfp = BRCMF_MFP_NONE;
+	if (is_rsn_ie) {
+		wme_bss_disable = 1;
+		if ((offset + RSN_CAP_LEN) <= len) {
+			rsn_cap = data[offset] + (data[offset + 1] << 8);
+			if (rsn_cap & RSN_CAP_PTK_REPLAY_CNTR_MASK)
+				wme_bss_disable = 0;
+			if (rsn_cap & RSN_CAP_MFPR_MASK) {
+				brcmf_dbg(TRACE, "MFP Required\n");
+				mfp = BRCMF_MFP_REQUIRED;
+				/* Firmware only supports mfp required in
+				 * combination with WPA2_AUTH_PSK_SHA256 or
+				 * WPA2_AUTH_1X_SHA256.
+				 */
+				if (!(wpa_auth & (WPA2_AUTH_PSK_SHA256 |
+						  WPA2_AUTH_1X_SHA256))) {
+					err = -EINVAL;
+					goto exit;
+				}
+				/* Firmware has requirement that WPA2_AUTH_PSK/
+				 * WPA2_AUTH_UNSPECIFIED be set, if SHA256 OUI
+				 * is to be included in the rsn ie.
+				 */
+				if (wpa_auth & WPA2_AUTH_PSK_SHA256)
+					wpa_auth |= WPA2_AUTH_PSK;
+				else if (wpa_auth & WPA2_AUTH_1X_SHA256)
+					wpa_auth |= WPA2_AUTH_UNSPECIFIED;
+			} else if (rsn_cap & RSN_CAP_MFPC_MASK) {
+				brcmf_dbg(TRACE, "MFP Capable\n");
+				mfp = BRCMF_MFP_CAPABLE;
+			}
+		}
+		offset += RSN_CAP_LEN;
+		/* set wme_bss_disable to sync RSN Capabilities */
+		err = brcmf_fil_bsscfg_int_set(ifp, "wme_bss_disable",
+					       wme_bss_disable);
+		if (err < 0) {
+			brcmf_err("wme_bss_disable error %d\n", err);
+			goto exit;
+		}
+
+		/* Skip PMKID cnt as it is know to be 0 for AP. */
+		offset += RSN_PMKID_COUNT_LEN;
+
+		/* See if there is BIP wpa suite left for MFP */
+		if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP) &&
+		    ((offset + WPA_IE_MIN_OUI_LEN) <= len)) {
+			err = brcmf_fil_bsscfg_data_set(ifp, "bip",
+							&data[offset],
+							WPA_IE_MIN_OUI_LEN);
+			if (err < 0) {
+				brcmf_err("bip error %d\n", err);
+				goto exit;
+			}
+		}
+	}
+	/* FOR WPS , set SES_OW_ENABLED */
+	wsec = (pval | gval | SES_OW_ENABLED);
+
+	/* set auth */
+	err = brcmf_fil_bsscfg_int_set(ifp, "auth", auth);
+	if (err < 0) {
+		brcmf_err("auth error %d\n", err);
+		goto exit;
+	}
+	/* set wsec */
+	err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);
+	if (err < 0) {
+		brcmf_err("wsec error %d\n", err);
+		goto exit;
+	}
+	/* Configure MFP, this needs to go after wsec otherwise the wsec command
+	 * will overwrite the values set by MFP
+	 */
+	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP)) {
+		err = brcmf_fil_bsscfg_int_set(ifp, "mfp", mfp);
+		if (err < 0) {
+			brcmf_err("mfp error %d\n", err);
+			goto exit;
+		}
+	}
+	/* set upper-layer auth */
+	err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", wpa_auth);
+	if (err < 0) {
+		brcmf_err("wpa_auth error %d\n", err);
+		goto exit;
+	}
+
+exit:
+	return err;
+}
+
+static s32
+brcmf_parse_vndr_ies(const u8 *vndr_ie_buf, u32 vndr_ie_len,
+		     struct parsed_vndr_ies *vndr_ies)
+{
+	struct brcmf_vs_tlv *vndrie;
+	struct brcmf_tlv *ie;
+	struct parsed_vndr_ie_info *parsed_info;
+	s32 remaining_len;
+
+	remaining_len = (s32)vndr_ie_len;
+	memset(vndr_ies, 0, sizeof(*vndr_ies));
+
+	ie = (struct brcmf_tlv *)vndr_ie_buf;
+	while (ie) {
+		if (ie->id != WLAN_EID_VENDOR_SPECIFIC)
+			goto next;
+		vndrie = (struct brcmf_vs_tlv *)ie;
+		/* len should be bigger than OUI length + one */
+		if (vndrie->len < (VS_IE_FIXED_HDR_LEN - TLV_HDR_LEN + 1)) {
+			brcmf_err("invalid vndr ie. length is too small %d\n",
+				  vndrie->len);
+			goto next;
+		}
+		/* if wpa or wme ie, do not add ie */
+		if (!memcmp(vndrie->oui, (u8 *)WPA_OUI, TLV_OUI_LEN) &&
+		    ((vndrie->oui_type == WPA_OUI_TYPE) ||
+		    (vndrie->oui_type == WME_OUI_TYPE))) {
+			brcmf_dbg(TRACE, "Found WPA/WME oui. Do not add it\n");
+			goto next;
+		}
+
+		parsed_info = &vndr_ies->ie_info[vndr_ies->count];
+
+		/* save vndr ie information */
+		parsed_info->ie_ptr = (char *)vndrie;
+		parsed_info->ie_len = vndrie->len + TLV_HDR_LEN;
+		memcpy(&parsed_info->vndrie, vndrie, sizeof(*vndrie));
+
+		vndr_ies->count++;
+
+		brcmf_dbg(TRACE, "** OUI %02x %02x %02x, type 0x%02x\n",
+			  parsed_info->vndrie.oui[0],
+			  parsed_info->vndrie.oui[1],
+			  parsed_info->vndrie.oui[2],
+			  parsed_info->vndrie.oui_type);
+
+		if (vndr_ies->count >= VNDR_IE_PARSE_LIMIT)
+			break;
+next:
+		remaining_len -= (ie->len + TLV_HDR_LEN);
+		if (remaining_len <= TLV_HDR_LEN)
+			ie = NULL;
+		else
+			ie = (struct brcmf_tlv *)(((u8 *)ie) + ie->len +
+				TLV_HDR_LEN);
+	}
+	return 0;
+}
+
+static u32
+brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd)
+{
+
+	strncpy(iebuf, add_del_cmd, VNDR_IE_CMD_LEN - 1);
+	iebuf[VNDR_IE_CMD_LEN - 1] = '\0';
+
+	put_unaligned_le32(1, &iebuf[VNDR_IE_COUNT_OFFSET]);
+
+	put_unaligned_le32(pktflag, &iebuf[VNDR_IE_PKTFLAG_OFFSET]);
+
+	memcpy(&iebuf[VNDR_IE_VSIE_OFFSET], ie_ptr, ie_len);
+
+	return ie_len + VNDR_IE_HDR_SIZE;
+}
+
+s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
+			  const u8 *vndr_ie_buf, u32 vndr_ie_len)
+{
+	struct brcmf_if *ifp;
+	struct vif_saved_ie *saved_ie;
+	s32 err = 0;
+	u8  *iovar_ie_buf;
+	u8  *curr_ie_buf;
+	u8  *mgmt_ie_buf = NULL;
+	int mgmt_ie_buf_len;
+	u32 *mgmt_ie_len;
+	u32 del_add_ie_buf_len = 0;
+	u32 total_ie_buf_len = 0;
+	u32 parsed_ie_buf_len = 0;
+	struct parsed_vndr_ies old_vndr_ies;
+	struct parsed_vndr_ies new_vndr_ies;
+	struct parsed_vndr_ie_info *vndrie_info;
+	s32 i;
+	u8 *ptr;
+	int remained_buf_len;
+
+	if (!vif)
+		return -ENODEV;
+	ifp = vif->ifp;
+	saved_ie = &vif->saved_ie;
+
+	brcmf_dbg(TRACE, "bsscfgidx %d, pktflag : 0x%02X\n", ifp->bsscfgidx,
+		  pktflag);
+	iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
+	if (!iovar_ie_buf)
+		return -ENOMEM;
+	curr_ie_buf = iovar_ie_buf;
+	switch (pktflag) {
+	case BRCMF_VNDR_IE_PRBREQ_FLAG:
+		mgmt_ie_buf = saved_ie->probe_req_ie;
+		mgmt_ie_len = &saved_ie->probe_req_ie_len;
+		mgmt_ie_buf_len = sizeof(saved_ie->probe_req_ie);
+		break;
+	case BRCMF_VNDR_IE_PRBRSP_FLAG:
+		mgmt_ie_buf = saved_ie->probe_res_ie;
+		mgmt_ie_len = &saved_ie->probe_res_ie_len;
+		mgmt_ie_buf_len = sizeof(saved_ie->probe_res_ie);
+		break;
+	case BRCMF_VNDR_IE_BEACON_FLAG:
+		mgmt_ie_buf = saved_ie->beacon_ie;
+		mgmt_ie_len = &saved_ie->beacon_ie_len;
+		mgmt_ie_buf_len = sizeof(saved_ie->beacon_ie);
+		break;
+	case BRCMF_VNDR_IE_ASSOCREQ_FLAG:
+		mgmt_ie_buf = saved_ie->assoc_req_ie;
+		mgmt_ie_len = &saved_ie->assoc_req_ie_len;
+		mgmt_ie_buf_len = sizeof(saved_ie->assoc_req_ie);
+		break;
+	default:
+		err = -EPERM;
+		brcmf_err("not suitable type\n");
+		goto exit;
+	}
+
+	if (vndr_ie_len > mgmt_ie_buf_len) {
+		err = -ENOMEM;
+		brcmf_err("extra IE size too big\n");
+		goto exit;
+	}
+
+	/* parse and save new vndr_ie in curr_ie_buff before comparing it */
+	if (vndr_ie_buf && vndr_ie_len && curr_ie_buf) {
+		ptr = curr_ie_buf;
+		brcmf_parse_vndr_ies(vndr_ie_buf, vndr_ie_len, &new_vndr_ies);
+		for (i = 0; i < new_vndr_ies.count; i++) {
+			vndrie_info = &new_vndr_ies.ie_info[i];
+			memcpy(ptr + parsed_ie_buf_len, vndrie_info->ie_ptr,
+			       vndrie_info->ie_len);
+			parsed_ie_buf_len += vndrie_info->ie_len;
+		}
+	}
+
+	if (mgmt_ie_buf && *mgmt_ie_len) {
+		if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) &&
+		    (memcmp(mgmt_ie_buf, curr_ie_buf,
+			    parsed_ie_buf_len) == 0)) {
+			brcmf_dbg(TRACE, "Previous mgmt IE equals to current IE\n");
+			goto exit;
+		}
+
+		/* parse old vndr_ie */
+		brcmf_parse_vndr_ies(mgmt_ie_buf, *mgmt_ie_len, &old_vndr_ies);
+
+		/* make a command to delete old ie */
+		for (i = 0; i < old_vndr_ies.count; i++) {
+			vndrie_info = &old_vndr_ies.ie_info[i];
+
+			brcmf_dbg(TRACE, "DEL ID : %d, Len: %d , OUI:%02x:%02x:%02x\n",
+				  vndrie_info->vndrie.id,
+				  vndrie_info->vndrie.len,
+				  vndrie_info->vndrie.oui[0],
+				  vndrie_info->vndrie.oui[1],
+				  vndrie_info->vndrie.oui[2]);
+
+			del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag,
+							   vndrie_info->ie_ptr,
+							   vndrie_info->ie_len,
+							   "del");
+			curr_ie_buf += del_add_ie_buf_len;
+			total_ie_buf_len += del_add_ie_buf_len;
+		}
+	}
+
+	*mgmt_ie_len = 0;
+	/* Add if there is any extra IE */
+	if (mgmt_ie_buf && parsed_ie_buf_len) {
+		ptr = mgmt_ie_buf;
+
+		remained_buf_len = mgmt_ie_buf_len;
+
+		/* make a command to add new ie */
+		for (i = 0; i < new_vndr_ies.count; i++) {
+			vndrie_info = &new_vndr_ies.ie_info[i];
+
+			/* verify remained buf size before copy data */
+			if (remained_buf_len < (vndrie_info->vndrie.len +
+							VNDR_IE_VSIE_OFFSET)) {
+				brcmf_err("no space in mgmt_ie_buf: len left %d",
+					  remained_buf_len);
+				break;
+			}
+			remained_buf_len -= (vndrie_info->ie_len +
+					     VNDR_IE_VSIE_OFFSET);
+
+			brcmf_dbg(TRACE, "ADDED ID : %d, Len: %d, OUI:%02x:%02x:%02x\n",
+				  vndrie_info->vndrie.id,
+				  vndrie_info->vndrie.len,
+				  vndrie_info->vndrie.oui[0],
+				  vndrie_info->vndrie.oui[1],
+				  vndrie_info->vndrie.oui[2]);
+
+			del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag,
+							   vndrie_info->ie_ptr,
+							   vndrie_info->ie_len,
+							   "add");
+
+			/* save the parsed IE in wl struct */
+			memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr,
+			       vndrie_info->ie_len);
+			*mgmt_ie_len += vndrie_info->ie_len;
+
+			curr_ie_buf += del_add_ie_buf_len;
+			total_ie_buf_len += del_add_ie_buf_len;
+		}
+	}
+	if (total_ie_buf_len) {
+		err  = brcmf_fil_bsscfg_data_set(ifp, "vndr_ie", iovar_ie_buf,
+						 total_ie_buf_len);
+		if (err)
+			brcmf_err("vndr ie set error : %d\n", err);
+	}
+
+exit:
+	kfree(iovar_ie_buf);
+	return err;
+}
+
+s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif)
+{
+	s32 pktflags[] = {
+		BRCMF_VNDR_IE_PRBREQ_FLAG,
+		BRCMF_VNDR_IE_PRBRSP_FLAG,
+		BRCMF_VNDR_IE_BEACON_FLAG
+	};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(pktflags); i++)
+		brcmf_vif_set_mgmt_ie(vif, pktflags[i], NULL, 0);
+
+	memset(&vif->saved_ie, 0, sizeof(vif->saved_ie));
+	return 0;
+}
+
+static s32
+brcmf_config_ap_mgmt_ie(struct brcmf_cfg80211_vif *vif,
+			struct cfg80211_beacon_data *beacon)
+{
+	s32 err;
+
+	/* Set Beacon IEs to FW */
+	err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_BEACON_FLAG,
+				    beacon->tail, beacon->tail_len);
+	if (err) {
+		brcmf_err("Set Beacon IE Failed\n");
+		return err;
+	}
+	brcmf_dbg(TRACE, "Applied Vndr IEs for Beacon\n");
+
+	/* Set Probe Response IEs to FW */
+	err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_PRBRSP_FLAG,
+				    beacon->proberesp_ies,
+				    beacon->proberesp_ies_len);
+	if (err)
+		brcmf_err("Set Probe Resp IE Failed\n");
+	else
+		brcmf_dbg(TRACE, "Applied Vndr IEs for Probe Resp\n");
+
+	return err;
+}
+
+static s32
+brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
+			struct cfg80211_ap_settings *settings)
+{
+	s32 ie_offset;
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	const struct brcmf_tlv *ssid_ie;
+	const struct brcmf_tlv *country_ie;
+	struct brcmf_ssid_le ssid_le;
+	s32 err = -EPERM;
+	const struct brcmf_tlv *rsn_ie;
+	const struct brcmf_vs_tlv *wpa_ie;
+	struct brcmf_join_params join_params;
+	enum nl80211_iftype dev_role;
+	struct brcmf_fil_bss_enable_le bss_enable;
+	u16 chanspec = chandef_to_chanspec(&cfg->d11inf, &settings->chandef);
+	bool mbss;
+	int is_11d;
+	bool supports_11d;
+
+	brcmf_dbg(TRACE, "ctrlchn=%d, center=%d, bw=%d, beacon_interval=%d, dtim_period=%d,\n",
+		  settings->chandef.chan->hw_value,
+		  settings->chandef.center_freq1, settings->chandef.width,
+		  settings->beacon_interval, settings->dtim_period);
+	brcmf_dbg(TRACE, "ssid=%s(%zu), auth_type=%d, inactivity_timeout=%d\n",
+		  settings->ssid, settings->ssid_len, settings->auth_type,
+		  settings->inactivity_timeout);
+	dev_role = ifp->vif->wdev.iftype;
+	mbss = ifp->vif->mbss;
+
+	/* store current 11d setting */
+	if (brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_REGULATORY,
+				  &ifp->vif->is_11d)) {
+		is_11d = supports_11d = false;
+	} else {
+		country_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,
+					      settings->beacon.tail_len,
+					      WLAN_EID_COUNTRY);
+		is_11d = country_ie ? 1 : 0;
+		supports_11d = true;
+	}
+
+	memset(&ssid_le, 0, sizeof(ssid_le));
+	if (settings->ssid == NULL || settings->ssid_len == 0) {
+		ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
+		ssid_ie = brcmf_parse_tlvs(
+				(u8 *)&settings->beacon.head[ie_offset],
+				settings->beacon.head_len - ie_offset,
+				WLAN_EID_SSID);
+		if (!ssid_ie || ssid_ie->len > IEEE80211_MAX_SSID_LEN)
+			return -EINVAL;
+
+		memcpy(ssid_le.SSID, ssid_ie->data, ssid_ie->len);
+		ssid_le.SSID_len = cpu_to_le32(ssid_ie->len);
+		brcmf_dbg(TRACE, "SSID is (%s) in Head\n", ssid_le.SSID);
+	} else {
+		memcpy(ssid_le.SSID, settings->ssid, settings->ssid_len);
+		ssid_le.SSID_len = cpu_to_le32((u32)settings->ssid_len);
+	}
+
+	if (!mbss) {
+		brcmf_set_mpc(ifp, 0);
+		brcmf_configure_arp_nd_offload(ifp, false);
+	}
+
+	/* find the RSN_IE */
+	rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,
+				  settings->beacon.tail_len, WLAN_EID_RSN);
+
+	/* find the WPA_IE */
+	wpa_ie = brcmf_find_wpaie((u8 *)settings->beacon.tail,
+				  settings->beacon.tail_len);
+
+	if ((wpa_ie != NULL || rsn_ie != NULL)) {
+		brcmf_dbg(TRACE, "WPA(2) IE is found\n");
+		if (wpa_ie != NULL) {
+			/* WPA IE */
+			err = brcmf_configure_wpaie(ifp, wpa_ie, false);
+			if (err < 0)
+				goto exit;
+		} else {
+			struct brcmf_vs_tlv *tmp_ie;
+
+			tmp_ie = (struct brcmf_vs_tlv *)rsn_ie;
+
+			/* RSN IE */
+			err = brcmf_configure_wpaie(ifp, tmp_ie, true);
+			if (err < 0)
+				goto exit;
+		}
+	} else {
+		brcmf_dbg(TRACE, "No WPA(2) IEs found\n");
+		brcmf_configure_opensecurity(ifp);
+	}
+
+	/* Parameters shared by all radio interfaces */
+	if (!mbss) {
+		if ((supports_11d) && (is_11d != ifp->vif->is_11d)) {
+			err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY,
+						    is_11d);
+			if (err < 0) {
+				brcmf_err("Regulatory Set Error, %d\n", err);
+				goto exit;
+			}
+		}
+		if (settings->beacon_interval) {
+			err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD,
+						    settings->beacon_interval);
+			if (err < 0) {
+				brcmf_err("Beacon Interval Set Error, %d\n",
+					  err);
+				goto exit;
+			}
+		}
+		if (settings->dtim_period) {
+			err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_DTIMPRD,
+						    settings->dtim_period);
+			if (err < 0) {
+				brcmf_err("DTIM Interval Set Error, %d\n", err);
+				goto exit;
+			}
+		}
+
+		if ((dev_role == NL80211_IFTYPE_AP) &&
+		    ((ifp->ifidx == 0) ||
+		     !brcmf_feat_is_enabled(ifp, BRCMF_FEAT_RSDB))) {
+			err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
+			if (err < 0) {
+				brcmf_err("BRCMF_C_DOWN error %d\n", err);
+				goto exit;
+			}
+			brcmf_fil_iovar_int_set(ifp, "apsta", 0);
+		}
+
+		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 1);
+		if (err < 0) {
+			brcmf_err("SET INFRA error %d\n", err);
+			goto exit;
+		}
+	} else if (WARN_ON(supports_11d && (is_11d != ifp->vif->is_11d))) {
+		/* Multiple-BSS should use same 11d configuration */
+		err = -EINVAL;
+		goto exit;
+	}
+
+	/* Interface specific setup */
+	if (dev_role == NL80211_IFTYPE_AP) {
+		if ((brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) && (!mbss))
+			brcmf_fil_iovar_int_set(ifp, "mbss", 1);
+
+		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 1);
+		if (err < 0) {
+			brcmf_err("setting AP mode failed %d\n", err);
+			goto exit;
+		}
+		if (!mbss) {
+			/* Firmware 10.x requires setting channel after enabling
+			 * AP and before bringing interface up.
+			 */
+			err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
+			if (err < 0) {
+				brcmf_err("Set Channel failed: chspec=%d, %d\n",
+					  chanspec, err);
+				goto exit;
+			}
+		}
+		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
+		if (err < 0) {
+			brcmf_err("BRCMF_C_UP error (%d)\n", err);
+			goto exit;
+		}
+		/* On DOWN the firmware removes the WEP keys, reconfigure
+		 * them if they were set.
+		 */
+		brcmf_cfg80211_reconfigure_wep(ifp);
+
+		memset(&join_params, 0, sizeof(join_params));
+		/* join parameters starts with ssid */
+		memcpy(&join_params.ssid_le, &ssid_le, sizeof(ssid_le));
+		/* create softap */
+		err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
+					     &join_params, sizeof(join_params));
+		if (err < 0) {
+			brcmf_err("SET SSID error (%d)\n", err);
+			goto exit;
+		}
+
+		if (settings->hidden_ssid) {
+			err = brcmf_fil_iovar_int_set(ifp, "closednet", 1);
+			if (err) {
+				brcmf_err("closednet error (%d)\n", err);
+				goto exit;
+			}
+		}
+
+		brcmf_dbg(TRACE, "AP mode configuration complete\n");
+	} else if (dev_role == NL80211_IFTYPE_P2P_GO) {
+		err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
+		if (err < 0) {
+			brcmf_err("Set Channel failed: chspec=%d, %d\n",
+				  chanspec, err);
+			goto exit;
+		}
+		err = brcmf_fil_bsscfg_data_set(ifp, "ssid", &ssid_le,
+						sizeof(ssid_le));
+		if (err < 0) {
+			brcmf_err("setting ssid failed %d\n", err);
+			goto exit;
+		}
+		bss_enable.bsscfgidx = cpu_to_le32(ifp->bsscfgidx);
+		bss_enable.enable = cpu_to_le32(1);
+		err = brcmf_fil_iovar_data_set(ifp, "bss", &bss_enable,
+					       sizeof(bss_enable));
+		if (err < 0) {
+			brcmf_err("bss_enable config failed %d\n", err);
+			goto exit;
+		}
+
+		brcmf_dbg(TRACE, "GO mode configuration complete\n");
+	} else {
+		WARN_ON(1);
+	}
+
+	brcmf_config_ap_mgmt_ie(ifp->vif, &settings->beacon);
+	set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
+	brcmf_net_setcarrier(ifp, true);
+
+exit:
+	if ((err) && (!mbss)) {
+		brcmf_set_mpc(ifp, 1);
+		brcmf_configure_arp_nd_offload(ifp, true);
+	}
+	return err;
+}
+
+static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	s32 err;
+	struct brcmf_fil_bss_enable_le bss_enable;
+	struct brcmf_join_params join_params;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	if (ifp->vif->wdev.iftype == NL80211_IFTYPE_AP) {
+		/* Due to most likely deauths outstanding we sleep */
+		/* first to make sure they get processed by fw. */
+		msleep(400);
+
+		if (ifp->vif->mbss) {
+			err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
+			return err;
+		}
+
+		/* First BSS doesn't get a full reset */
+		if (ifp->bsscfgidx == 0)
+			brcmf_fil_iovar_int_set(ifp, "closednet", 0);
+
+		memset(&join_params, 0, sizeof(join_params));
+		err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
+					     &join_params, sizeof(join_params));
+		if (err < 0)
+			brcmf_err("SET SSID error (%d)\n", err);
+		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
+		if (err < 0)
+			brcmf_err("BRCMF_C_DOWN error %d\n", err);
+		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0);
+		if (err < 0)
+			brcmf_err("setting AP mode failed %d\n", err);
+		if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS))
+			brcmf_fil_iovar_int_set(ifp, "mbss", 0);
+		brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY,
+				      ifp->vif->is_11d);
+		/* Bring device back up so it can be used again */
+		err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
+		if (err < 0)
+			brcmf_err("BRCMF_C_UP error %d\n", err);
+
+		brcmf_vif_clear_mgmt_ies(ifp->vif);
+	} else {
+		bss_enable.bsscfgidx = cpu_to_le32(ifp->bsscfgidx);
+		bss_enable.enable = cpu_to_le32(0);
+		err = brcmf_fil_iovar_data_set(ifp, "bss", &bss_enable,
+					       sizeof(bss_enable));
+		if (err < 0)
+			brcmf_err("bss_enable config failed %d\n", err);
+	}
+	brcmf_set_mpc(ifp, 1);
+	brcmf_configure_arp_nd_offload(ifp, true);
+	clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
+	brcmf_net_setcarrier(ifp, false);
+
+	return err;
+}
+
+static s32
+brcmf_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *ndev,
+			     struct cfg80211_beacon_data *info)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	s32 err;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	err = brcmf_config_ap_mgmt_ie(ifp->vif, info);
+
+	return err;
+}
+
+static int
+brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev,
+			   struct station_del_parameters *params)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_scb_val_le scbval;
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	s32 err;
+
+	if (!params->mac)
+		return -EFAULT;
+
+	brcmf_dbg(TRACE, "Enter %pM\n", params->mac);
+
+	if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
+		ifp = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
+	if (!check_vif_up(ifp->vif))
+		return -EIO;
+
+	memcpy(&scbval.ea, params->mac, ETH_ALEN);
+	scbval.val = cpu_to_le32(params->reason_code);
+	err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON,
+				     &scbval, sizeof(scbval));
+	if (err)
+		brcmf_err("SCB_DEAUTHENTICATE_FOR_REASON failed %d\n", err);
+
+	brcmf_dbg(TRACE, "Exit\n");
+	return err;
+}
+
+static int
+brcmf_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev,
+			      const u8 *mac, struct station_parameters *params)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	s32 err;
+
+	brcmf_dbg(TRACE, "Enter, MAC %pM, mask 0x%04x set 0x%04x\n", mac,
+		  params->sta_flags_mask, params->sta_flags_set);
+
+	/* Ignore all 00 MAC */
+	if (is_zero_ether_addr(mac))
+		return 0;
+
+	if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
+		return 0;
+
+	if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
+		err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SCB_AUTHORIZE,
+					     (void *)mac, ETH_ALEN);
+	else
+		err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SCB_DEAUTHORIZE,
+					     (void *)mac, ETH_ALEN);
+	if (err < 0)
+		brcmf_err("Setting SCB (de-)authorize failed, %d\n", err);
+
+	return err;
+}
+
+static void
+brcmf_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
+				   struct wireless_dev *wdev,
+				   u16 frame_type, bool reg)
+{
+	struct brcmf_cfg80211_vif *vif;
+	u16 mgmt_type;
+
+	brcmf_dbg(TRACE, "Enter, frame_type %04x, reg=%d\n", frame_type, reg);
+
+	mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
+	vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
+	if (reg)
+		vif->mgmt_rx_reg |= BIT(mgmt_type);
+	else
+		vif->mgmt_rx_reg &= ~BIT(mgmt_type);
+}
+
+
+static int
+brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
+		       struct cfg80211_mgmt_tx_params *params, u64 *cookie)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct ieee80211_channel *chan = params->chan;
+	const u8 *buf = params->buf;
+	size_t len = params->len;
+	const struct ieee80211_mgmt *mgmt;
+	struct brcmf_cfg80211_vif *vif;
+	s32 err = 0;
+	s32 ie_offset;
+	s32 ie_len;
+	struct brcmf_fil_action_frame_le *action_frame;
+	struct brcmf_fil_af_params_le *af_params;
+	bool ack;
+	s32 chan_nr;
+	u32 freq;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	*cookie = 0;
+
+	mgmt = (const struct ieee80211_mgmt *)buf;
+
+	if (!ieee80211_is_mgmt(mgmt->frame_control)) {
+		brcmf_err("Driver only allows MGMT packet type\n");
+		return -EPERM;
+	}
+
+	vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
+
+	if (ieee80211_is_probe_resp(mgmt->frame_control)) {
+		/* Right now the only reason to get a probe response */
+		/* is for p2p listen response or for p2p GO from     */
+		/* wpa_supplicant. Unfortunately the probe is send   */
+		/* on primary ndev, while dongle wants it on the p2p */
+		/* vif. Since this is only reason for a probe        */
+		/* response to be sent, the vif is taken from cfg.   */
+		/* If ever desired to send proberesp for non p2p     */
+		/* response then data should be checked for          */
+		/* "DIRECT-". Note in future supplicant will take    */
+		/* dedicated p2p wdev to do this and then this 'hack'*/
+		/* is not needed anymore.                            */
+		ie_offset =  DOT11_MGMT_HDR_LEN +
+			     DOT11_BCN_PRB_FIXED_LEN;
+		ie_len = len - ie_offset;
+		if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif)
+			vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
+		err = brcmf_vif_set_mgmt_ie(vif,
+					    BRCMF_VNDR_IE_PRBRSP_FLAG,
+					    &buf[ie_offset],
+					    ie_len);
+		cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true,
+					GFP_KERNEL);
+	} else if (ieee80211_is_action(mgmt->frame_control)) {
+		if (len > BRCMF_FIL_ACTION_FRAME_SIZE + DOT11_MGMT_HDR_LEN) {
+			brcmf_err("invalid action frame length\n");
+			err = -EINVAL;
+			goto exit;
+		}
+		af_params = kzalloc(sizeof(*af_params), GFP_KERNEL);
+		if (af_params == NULL) {
+			brcmf_err("unable to allocate frame\n");
+			err = -ENOMEM;
+			goto exit;
+		}
+		action_frame = &af_params->action_frame;
+		/* Add the packet Id */
+		action_frame->packet_id = cpu_to_le32(*cookie);
+		/* Add BSSID */
+		memcpy(&action_frame->da[0], &mgmt->da[0], ETH_ALEN);
+		memcpy(&af_params->bssid[0], &mgmt->bssid[0], ETH_ALEN);
+		/* Add the length exepted for 802.11 header  */
+		action_frame->len = cpu_to_le16(len - DOT11_MGMT_HDR_LEN);
+		/* Add the channel. Use the one specified as parameter if any or
+		 * the current one (got from the firmware) otherwise
+		 */
+		if (chan)
+			freq = chan->center_freq;
+		else
+			brcmf_fil_cmd_int_get(vif->ifp, BRCMF_C_GET_CHANNEL,
+					      &freq);
+		chan_nr = ieee80211_frequency_to_channel(freq);
+		af_params->channel = cpu_to_le32(chan_nr);
+
+		memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN],
+		       le16_to_cpu(action_frame->len));
+
+		brcmf_dbg(TRACE, "Action frame, cookie=%lld, len=%d, freq=%d\n",
+			  *cookie, le16_to_cpu(action_frame->len), freq);
+
+		ack = brcmf_p2p_send_action_frame(cfg, cfg_to_ndev(cfg),
+						  af_params);
+
+		cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack,
+					GFP_KERNEL);
+		kfree(af_params);
+	} else {
+		brcmf_dbg(TRACE, "Unhandled, fc=%04x!!\n", mgmt->frame_control);
+		brcmf_dbg_hex_dump(true, buf, len, "payload, len=%zu\n", len);
+	}
+
+exit:
+	return err;
+}
+
+
+static int
+brcmf_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
+					struct wireless_dev *wdev,
+					u64 cookie)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_cfg80211_vif *vif;
+	int err = 0;
+
+	brcmf_dbg(TRACE, "Enter p2p listen cancel\n");
+
+	vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
+	if (vif == NULL) {
+		brcmf_err("No p2p device available for probe response\n");
+		err = -ENODEV;
+		goto exit;
+	}
+	brcmf_p2p_cancel_remain_on_channel(vif->ifp);
+exit:
+	return err;
+}
+
+static int brcmf_cfg80211_get_channel(struct wiphy *wiphy,
+				      struct wireless_dev *wdev,
+				      struct cfg80211_chan_def *chandef)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct net_device *ndev = wdev->netdev;
+	struct brcmf_if *ifp;
+	struct brcmu_chan ch;
+	enum nl80211_band band = 0;
+	enum nl80211_chan_width width = 0;
+	u32 chanspec;
+	int freq, err;
+
+	if (!ndev)
+		return -ENODEV;
+	ifp = netdev_priv(ndev);
+
+	err = brcmf_fil_iovar_int_get(ifp, "chanspec", &chanspec);
+	if (err) {
+		brcmf_err("chanspec failed (%d)\n", err);
+		return err;
+	}
+
+	ch.chspec = chanspec;
+	cfg->d11inf.decchspec(&ch);
+
+	switch (ch.band) {
+	case BRCMU_CHAN_BAND_2G:
+		band = NL80211_BAND_2GHZ;
+		break;
+	case BRCMU_CHAN_BAND_5G:
+		band = NL80211_BAND_5GHZ;
+		break;
+	}
+
+	switch (ch.bw) {
+	case BRCMU_CHAN_BW_80:
+		width = NL80211_CHAN_WIDTH_80;
+		break;
+	case BRCMU_CHAN_BW_40:
+		width = NL80211_CHAN_WIDTH_40;
+		break;
+	case BRCMU_CHAN_BW_20:
+		width = NL80211_CHAN_WIDTH_20;
+		break;
+	case BRCMU_CHAN_BW_80P80:
+		width = NL80211_CHAN_WIDTH_80P80;
+		break;
+	case BRCMU_CHAN_BW_160:
+		width = NL80211_CHAN_WIDTH_160;
+		break;
+	}
+
+	freq = ieee80211_channel_to_frequency(ch.control_ch_num, band);
+	chandef->chan = ieee80211_get_channel(wiphy, freq);
+	chandef->width = width;
+	chandef->center_freq1 = ieee80211_channel_to_frequency(ch.chnum, band);
+	chandef->center_freq2 = 0;
+
+	return 0;
+}
+
+static int brcmf_cfg80211_crit_proto_start(struct wiphy *wiphy,
+					   struct wireless_dev *wdev,
+					   enum nl80211_crit_proto_id proto,
+					   u16 duration)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_cfg80211_vif *vif;
+
+	vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
+
+	/* only DHCP support for now */
+	if (proto != NL80211_CRIT_PROTO_DHCP)
+		return -EINVAL;
+
+	/* suppress and abort scanning */
+	set_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
+	brcmf_abort_scanning(cfg);
+
+	return brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_DISABLED, duration);
+}
+
+static void brcmf_cfg80211_crit_proto_stop(struct wiphy *wiphy,
+					   struct wireless_dev *wdev)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_cfg80211_vif *vif;
+
+	vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
+
+	brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_ENABLED, 0);
+	clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
+}
+
+static s32
+brcmf_notify_tdls_peer_event(struct brcmf_if *ifp,
+			     const struct brcmf_event_msg *e, void *data)
+{
+	switch (e->reason) {
+	case BRCMF_E_REASON_TDLS_PEER_DISCOVERED:
+		brcmf_dbg(TRACE, "TDLS Peer Discovered\n");
+		break;
+	case BRCMF_E_REASON_TDLS_PEER_CONNECTED:
+		brcmf_dbg(TRACE, "TDLS Peer Connected\n");
+		brcmf_proto_add_tdls_peer(ifp->drvr, ifp->ifidx, (u8 *)e->addr);
+		break;
+	case BRCMF_E_REASON_TDLS_PEER_DISCONNECTED:
+		brcmf_dbg(TRACE, "TDLS Peer Disconnected\n");
+		brcmf_proto_delete_peer(ifp->drvr, ifp->ifidx, (u8 *)e->addr);
+		break;
+	}
+
+	return 0;
+}
+
+static int brcmf_convert_nl80211_tdls_oper(enum nl80211_tdls_operation oper)
+{
+	int ret;
+
+	switch (oper) {
+	case NL80211_TDLS_DISCOVERY_REQ:
+		ret = BRCMF_TDLS_MANUAL_EP_DISCOVERY;
+		break;
+	case NL80211_TDLS_SETUP:
+		ret = BRCMF_TDLS_MANUAL_EP_CREATE;
+		break;
+	case NL80211_TDLS_TEARDOWN:
+		ret = BRCMF_TDLS_MANUAL_EP_DELETE;
+		break;
+	default:
+		brcmf_err("unsupported operation: %d\n", oper);
+		ret = -EOPNOTSUPP;
+	}
+	return ret;
+}
+
+static int brcmf_cfg80211_tdls_oper(struct wiphy *wiphy,
+				    struct net_device *ndev, const u8 *peer,
+				    enum nl80211_tdls_operation oper)
+{
+	struct brcmf_if *ifp;
+	struct brcmf_tdls_iovar_le info;
+	int ret = 0;
+
+	ret = brcmf_convert_nl80211_tdls_oper(oper);
+	if (ret < 0)
+		return ret;
+
+	ifp = netdev_priv(ndev);
+	memset(&info, 0, sizeof(info));
+	info.mode = (u8)ret;
+	if (peer)
+		memcpy(info.ea, peer, ETH_ALEN);
+
+	ret = brcmf_fil_iovar_data_set(ifp, "tdls_endpoint",
+				       &info, sizeof(info));
+	if (ret < 0)
+		brcmf_err("tdls_endpoint iovar failed: ret=%d\n", ret);
+
+	return ret;
+}
+
+static int
+brcmf_cfg80211_update_conn_params(struct wiphy *wiphy,
+				  struct net_device *ndev,
+				  struct cfg80211_connect_params *sme,
+				  u32 changed)
+{
+	struct brcmf_if *ifp;
+	int err;
+
+	if (!(changed & UPDATE_ASSOC_IES))
+		return 0;
+
+	ifp = netdev_priv(ndev);
+	err = brcmf_vif_set_mgmt_ie(ifp->vif, BRCMF_VNDR_IE_ASSOCREQ_FLAG,
+				    sme->ie, sme->ie_len);
+	if (err)
+		brcmf_err("Set Assoc REQ IE Failed\n");
+	else
+		brcmf_dbg(TRACE, "Applied Vndr IEs for Assoc request\n");
+
+	return err;
+}
+
+#ifdef CONFIG_PM
+static int
+brcmf_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *ndev,
+			      struct cfg80211_gtk_rekey_data *gtk)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_gtk_keyinfo_le gtk_le;
+	int ret;
+
+	brcmf_dbg(TRACE, "Enter, bssidx=%d\n", ifp->bsscfgidx);
+
+	memcpy(gtk_le.kck, gtk->kck, sizeof(gtk_le.kck));
+	memcpy(gtk_le.kek, gtk->kek, sizeof(gtk_le.kek));
+	memcpy(gtk_le.replay_counter, gtk->replay_ctr,
+	       sizeof(gtk_le.replay_counter));
+
+	ret = brcmf_fil_iovar_data_set(ifp, "gtk_key_info", &gtk_le,
+				       sizeof(gtk_le));
+	if (ret < 0)
+		brcmf_err("gtk_key_info iovar failed: ret=%d\n", ret);
+
+	return ret;
+}
+#endif
+
+static int brcmf_cfg80211_set_pmk(struct wiphy *wiphy, struct net_device *dev,
+				  const struct cfg80211_pmk_conf *conf)
+{
+	struct brcmf_if *ifp;
+
+	brcmf_dbg(TRACE, "enter\n");
+
+	/* expect using firmware supplicant for 1X */
+	ifp = netdev_priv(dev);
+	if (WARN_ON(ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X))
+		return -EINVAL;
+
+	if (conf->pmk_len > BRCMF_WSEC_MAX_PSK_LEN)
+		return -ERANGE;
+
+	return brcmf_set_pmk(ifp, conf->pmk, conf->pmk_len);
+}
+
+static int brcmf_cfg80211_del_pmk(struct wiphy *wiphy, struct net_device *dev,
+				  const u8 *aa)
+{
+	struct brcmf_if *ifp;
+
+	brcmf_dbg(TRACE, "enter\n");
+	ifp = netdev_priv(dev);
+	if (WARN_ON(ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X))
+		return -EINVAL;
+
+	return brcmf_set_pmk(ifp, NULL, 0);
+}
+
+static struct cfg80211_ops brcmf_cfg80211_ops = {
+	.add_virtual_intf = brcmf_cfg80211_add_iface,
+	.del_virtual_intf = brcmf_cfg80211_del_iface,
+	.change_virtual_intf = brcmf_cfg80211_change_iface,
+	.scan = brcmf_cfg80211_scan,
+	.set_wiphy_params = brcmf_cfg80211_set_wiphy_params,
+	.join_ibss = brcmf_cfg80211_join_ibss,
+	.leave_ibss = brcmf_cfg80211_leave_ibss,
+	.get_station = brcmf_cfg80211_get_station,
+	.dump_station = brcmf_cfg80211_dump_station,
+	.set_tx_power = brcmf_cfg80211_set_tx_power,
+	.get_tx_power = brcmf_cfg80211_get_tx_power,
+	.add_key = brcmf_cfg80211_add_key,
+	.del_key = brcmf_cfg80211_del_key,
+	.get_key = brcmf_cfg80211_get_key,
+	.set_default_key = brcmf_cfg80211_config_default_key,
+	.set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key,
+	.set_power_mgmt = brcmf_cfg80211_set_power_mgmt,
+	.connect = brcmf_cfg80211_connect,
+	.disconnect = brcmf_cfg80211_disconnect,
+	.suspend = brcmf_cfg80211_suspend,
+	.resume = brcmf_cfg80211_resume,
+	.set_pmksa = brcmf_cfg80211_set_pmksa,
+	.del_pmksa = brcmf_cfg80211_del_pmksa,
+	.flush_pmksa = brcmf_cfg80211_flush_pmksa,
+	.start_ap = brcmf_cfg80211_start_ap,
+	.stop_ap = brcmf_cfg80211_stop_ap,
+	.change_beacon = brcmf_cfg80211_change_beacon,
+	.del_station = brcmf_cfg80211_del_station,
+	.change_station = brcmf_cfg80211_change_station,
+	.sched_scan_start = brcmf_cfg80211_sched_scan_start,
+	.sched_scan_stop = brcmf_cfg80211_sched_scan_stop,
+	.mgmt_frame_register = brcmf_cfg80211_mgmt_frame_register,
+	.mgmt_tx = brcmf_cfg80211_mgmt_tx,
+	.remain_on_channel = brcmf_p2p_remain_on_channel,
+	.cancel_remain_on_channel = brcmf_cfg80211_cancel_remain_on_channel,
+	.get_channel = brcmf_cfg80211_get_channel,
+	.start_p2p_device = brcmf_p2p_start_device,
+	.stop_p2p_device = brcmf_p2p_stop_device,
+	.crit_proto_start = brcmf_cfg80211_crit_proto_start,
+	.crit_proto_stop = brcmf_cfg80211_crit_proto_stop,
+	.tdls_oper = brcmf_cfg80211_tdls_oper,
+	.update_connect_params = brcmf_cfg80211_update_conn_params,
+	.set_pmk = brcmf_cfg80211_set_pmk,
+	.del_pmk = brcmf_cfg80211_del_pmk,
+};
+
+struct cfg80211_ops *brcmf_cfg80211_get_ops(void)
+{
+	return kmemdup(&brcmf_cfg80211_ops, sizeof(brcmf_cfg80211_ops),
+		       GFP_KERNEL);
+}
+
+struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
+					   enum nl80211_iftype type)
+{
+	struct brcmf_cfg80211_vif *vif_walk;
+	struct brcmf_cfg80211_vif *vif;
+	bool mbss;
+
+	brcmf_dbg(TRACE, "allocating virtual interface (size=%zu)\n",
+		  sizeof(*vif));
+	vif = kzalloc(sizeof(*vif), GFP_KERNEL);
+	if (!vif)
+		return ERR_PTR(-ENOMEM);
+
+	vif->wdev.wiphy = cfg->wiphy;
+	vif->wdev.iftype = type;
+
+	brcmf_init_prof(&vif->profile);
+
+	if (type == NL80211_IFTYPE_AP) {
+		mbss = false;
+		list_for_each_entry(vif_walk, &cfg->vif_list, list) {
+			if (vif_walk->wdev.iftype == NL80211_IFTYPE_AP) {
+				mbss = true;
+				break;
+			}
+		}
+		vif->mbss = mbss;
+	}
+
+	list_add_tail(&vif->list, &cfg->vif_list);
+	return vif;
+}
+
+void brcmf_free_vif(struct brcmf_cfg80211_vif *vif)
+{
+	list_del(&vif->list);
+	kfree(vif);
+}
+
+void brcmf_cfg80211_free_netdev(struct net_device *ndev)
+{
+	struct brcmf_cfg80211_vif *vif;
+	struct brcmf_if *ifp;
+
+	ifp = netdev_priv(ndev);
+	vif = ifp->vif;
+
+	if (vif)
+		brcmf_free_vif(vif);
+}
+
+static bool brcmf_is_linkup(struct brcmf_cfg80211_vif *vif,
+			    const struct brcmf_event_msg *e)
+{
+	u32 event = e->event_code;
+	u32 status = e->status;
+
+	if (vif->profile.use_fwsup == BRCMF_PROFILE_FWSUP_PSK &&
+	    event == BRCMF_E_PSK_SUP &&
+	    status == BRCMF_E_STATUS_FWSUP_COMPLETED)
+		set_bit(BRCMF_VIF_STATUS_EAP_SUCCESS, &vif->sme_state);
+	if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) {
+		brcmf_dbg(CONN, "Processing set ssid\n");
+		memcpy(vif->profile.bssid, e->addr, ETH_ALEN);
+		if (vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_PSK)
+			return true;
+
+		set_bit(BRCMF_VIF_STATUS_ASSOC_SUCCESS, &vif->sme_state);
+	}
+
+	if (test_bit(BRCMF_VIF_STATUS_EAP_SUCCESS, &vif->sme_state) &&
+	    test_bit(BRCMF_VIF_STATUS_ASSOC_SUCCESS, &vif->sme_state)) {
+		clear_bit(BRCMF_VIF_STATUS_EAP_SUCCESS, &vif->sme_state);
+		clear_bit(BRCMF_VIF_STATUS_ASSOC_SUCCESS, &vif->sme_state);
+		return true;
+	}
+	return false;
+}
+
+static bool brcmf_is_linkdown(const struct brcmf_event_msg *e)
+{
+	u32 event = e->event_code;
+	u16 flags = e->flags;
+
+	if ((event == BRCMF_E_DEAUTH) || (event == BRCMF_E_DEAUTH_IND) ||
+	    (event == BRCMF_E_DISASSOC_IND) ||
+	    ((event == BRCMF_E_LINK) && (!(flags & BRCMF_EVENT_MSG_LINK)))) {
+		brcmf_dbg(CONN, "Processing link down\n");
+		return true;
+	}
+	return false;
+}
+
+static bool brcmf_is_nonetwork(struct brcmf_cfg80211_info *cfg,
+			       const struct brcmf_event_msg *e)
+{
+	u32 event = e->event_code;
+	u32 status = e->status;
+
+	if (event == BRCMF_E_LINK && status == BRCMF_E_STATUS_NO_NETWORKS) {
+		brcmf_dbg(CONN, "Processing Link %s & no network found\n",
+			  e->flags & BRCMF_EVENT_MSG_LINK ? "up" : "down");
+		return true;
+	}
+
+	if (event == BRCMF_E_SET_SSID && status != BRCMF_E_STATUS_SUCCESS) {
+		brcmf_dbg(CONN, "Processing connecting & no network found\n");
+		return true;
+	}
+
+	if (event == BRCMF_E_PSK_SUP &&
+	    status != BRCMF_E_STATUS_FWSUP_COMPLETED) {
+		brcmf_dbg(CONN, "Processing failed supplicant state: %u\n",
+			  status);
+		return true;
+	}
+
+	return false;
+}
+
+static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_info *cfg)
+{
+	struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
+
+	kfree(conn_info->req_ie);
+	conn_info->req_ie = NULL;
+	conn_info->req_ie_len = 0;
+	kfree(conn_info->resp_ie);
+	conn_info->resp_ie = NULL;
+	conn_info->resp_ie_len = 0;
+}
+
+static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg,
+			       struct brcmf_if *ifp)
+{
+	struct brcmf_cfg80211_assoc_ielen_le *assoc_info;
+	struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
+	u32 req_len;
+	u32 resp_len;
+	s32 err = 0;
+
+	brcmf_clear_assoc_ies(cfg);
+
+	err = brcmf_fil_iovar_data_get(ifp, "assoc_info",
+				       cfg->extra_buf, WL_ASSOC_INFO_MAX);
+	if (err) {
+		brcmf_err("could not get assoc info (%d)\n", err);
+		return err;
+	}
+	assoc_info =
+		(struct brcmf_cfg80211_assoc_ielen_le *)cfg->extra_buf;
+	req_len = le32_to_cpu(assoc_info->req_len);
+	resp_len = le32_to_cpu(assoc_info->resp_len);
+	if (req_len) {
+		err = brcmf_fil_iovar_data_get(ifp, "assoc_req_ies",
+					       cfg->extra_buf,
+					       WL_ASSOC_INFO_MAX);
+		if (err) {
+			brcmf_err("could not get assoc req (%d)\n", err);
+			return err;
+		}
+		conn_info->req_ie_len = req_len;
+		conn_info->req_ie =
+		    kmemdup(cfg->extra_buf, conn_info->req_ie_len,
+			    GFP_KERNEL);
+	} else {
+		conn_info->req_ie_len = 0;
+		conn_info->req_ie = NULL;
+	}
+	if (resp_len) {
+		err = brcmf_fil_iovar_data_get(ifp, "assoc_resp_ies",
+					       cfg->extra_buf,
+					       WL_ASSOC_INFO_MAX);
+		if (err) {
+			brcmf_err("could not get assoc resp (%d)\n", err);
+			return err;
+		}
+		conn_info->resp_ie_len = resp_len;
+		conn_info->resp_ie =
+		    kmemdup(cfg->extra_buf, conn_info->resp_ie_len,
+			    GFP_KERNEL);
+	} else {
+		conn_info->resp_ie_len = 0;
+		conn_info->resp_ie = NULL;
+	}
+	brcmf_dbg(CONN, "req len (%d) resp len (%d)\n",
+		  conn_info->req_ie_len, conn_info->resp_ie_len);
+
+	return err;
+}
+
+static s32
+brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
+		       struct net_device *ndev,
+		       const struct brcmf_event_msg *e)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
+	struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
+	struct wiphy *wiphy = cfg_to_wiphy(cfg);
+	struct ieee80211_channel *notify_channel = NULL;
+	struct ieee80211_supported_band *band;
+	struct brcmf_bss_info_le *bi;
+	struct brcmu_chan ch;
+	struct cfg80211_roam_info roam_info = {};
+	u32 freq;
+	s32 err = 0;
+	u8 *buf;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	brcmf_get_assoc_ies(cfg, ifp);
+	memcpy(profile->bssid, e->addr, ETH_ALEN);
+	brcmf_update_bss_info(cfg, ifp);
+
+	buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
+	if (buf == NULL) {
+		err = -ENOMEM;
+		goto done;
+	}
+
+	/* data sent to dongle has to be little endian */
+	*(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
+	err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO,
+				     buf, WL_BSS_INFO_MAX);
+
+	if (err)
+		goto done;
+
+	bi = (struct brcmf_bss_info_le *)(buf + 4);
+	ch.chspec = le16_to_cpu(bi->chanspec);
+	cfg->d11inf.decchspec(&ch);
+
+	if (ch.band == BRCMU_CHAN_BAND_2G)
+		band = wiphy->bands[NL80211_BAND_2GHZ];
+	else
+		band = wiphy->bands[NL80211_BAND_5GHZ];
+
+	freq = ieee80211_channel_to_frequency(ch.control_ch_num, band->band);
+	notify_channel = ieee80211_get_channel(wiphy, freq);
+
+done:
+	kfree(buf);
+
+	roam_info.channel = notify_channel;
+	roam_info.bssid = profile->bssid;
+	roam_info.req_ie = conn_info->req_ie;
+	roam_info.req_ie_len = conn_info->req_ie_len;
+	roam_info.resp_ie = conn_info->resp_ie;
+	roam_info.resp_ie_len = conn_info->resp_ie_len;
+
+	cfg80211_roamed(ndev, &roam_info, GFP_KERNEL);
+	brcmf_dbg(CONN, "Report roaming result\n");
+
+	set_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);
+	brcmf_dbg(TRACE, "Exit\n");
+	return err;
+}
+
+static s32
+brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg,
+		       struct net_device *ndev, const struct brcmf_event_msg *e,
+		       bool completed)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
+	struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
+	struct cfg80211_connect_resp_params conn_params;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTING,
+			       &ifp->vif->sme_state)) {
+		memset(&conn_params, 0, sizeof(conn_params));
+		if (completed) {
+			brcmf_get_assoc_ies(cfg, ifp);
+			brcmf_update_bss_info(cfg, ifp);
+			set_bit(BRCMF_VIF_STATUS_CONNECTED,
+				&ifp->vif->sme_state);
+			conn_params.status = WLAN_STATUS_SUCCESS;
+		} else {
+			conn_params.status = WLAN_STATUS_AUTH_TIMEOUT;
+		}
+		conn_params.bssid = profile->bssid;
+		conn_params.req_ie = conn_info->req_ie;
+		conn_params.req_ie_len = conn_info->req_ie_len;
+		conn_params.resp_ie = conn_info->resp_ie;
+		conn_params.resp_ie_len = conn_info->resp_ie_len;
+		cfg80211_connect_done(ndev, &conn_params, GFP_KERNEL);
+		brcmf_dbg(CONN, "Report connect result - connection %s\n",
+			  completed ? "succeeded" : "failed");
+	}
+	brcmf_dbg(TRACE, "Exit\n");
+	return 0;
+}
+
+static s32
+brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg,
+			       struct net_device *ndev,
+			       const struct brcmf_event_msg *e, void *data)
+{
+	static int generation;
+	u32 event = e->event_code;
+	u32 reason = e->reason;
+	struct station_info *sinfo;
+
+	brcmf_dbg(CONN, "event %s (%u), reason %d\n",
+		  brcmf_fweh_event_name(event), event, reason);
+	if (event == BRCMF_E_LINK && reason == BRCMF_E_REASON_LINK_BSSCFG_DIS &&
+	    ndev != cfg_to_ndev(cfg)) {
+		brcmf_dbg(CONN, "AP mode link down\n");
+		complete(&cfg->vif_disabled);
+		return 0;
+	}
+
+	if (((event == BRCMF_E_ASSOC_IND) || (event == BRCMF_E_REASSOC_IND)) &&
+	    (reason == BRCMF_E_STATUS_SUCCESS)) {
+		if (!data) {
+			brcmf_err("No IEs present in ASSOC/REASSOC_IND");
+			return -EINVAL;
+		}
+
+		sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL);
+		if (!sinfo)
+			return -ENOMEM;
+
+		sinfo->assoc_req_ies = data;
+		sinfo->assoc_req_ies_len = e->datalen;
+		generation++;
+		sinfo->generation = generation;
+		cfg80211_new_sta(ndev, e->addr, sinfo, GFP_KERNEL);
+
+		kfree(sinfo);
+	} else if ((event == BRCMF_E_DISASSOC_IND) ||
+		   (event == BRCMF_E_DEAUTH_IND) ||
+		   (event == BRCMF_E_DEAUTH)) {
+		cfg80211_del_sta(ndev, e->addr, GFP_KERNEL);
+	}
+	return 0;
+}
+
+static s32
+brcmf_notify_connect_status(struct brcmf_if *ifp,
+			    const struct brcmf_event_msg *e, void *data)
+{
+	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+	struct net_device *ndev = ifp->ndev;
+	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
+	struct ieee80211_channel *chan;
+	s32 err = 0;
+
+	if ((e->event_code == BRCMF_E_DEAUTH) ||
+	    (e->event_code == BRCMF_E_DEAUTH_IND) ||
+	    (e->event_code == BRCMF_E_DISASSOC_IND) ||
+	    ((e->event_code == BRCMF_E_LINK) && (!e->flags))) {
+		brcmf_proto_delete_peer(ifp->drvr, ifp->ifidx, (u8 *)e->addr);
+	}
+
+	if (brcmf_is_apmode(ifp->vif)) {
+		err = brcmf_notify_connect_status_ap(cfg, ndev, e, data);
+	} else if (brcmf_is_linkup(ifp->vif, e)) {
+		brcmf_dbg(CONN, "Linkup\n");
+		if (brcmf_is_ibssmode(ifp->vif)) {
+			brcmf_inform_ibss(cfg, ndev, e->addr);
+			chan = ieee80211_get_channel(cfg->wiphy, cfg->channel);
+			memcpy(profile->bssid, e->addr, ETH_ALEN);
+			cfg80211_ibss_joined(ndev, e->addr, chan, GFP_KERNEL);
+			clear_bit(BRCMF_VIF_STATUS_CONNECTING,
+				  &ifp->vif->sme_state);
+			set_bit(BRCMF_VIF_STATUS_CONNECTED,
+				&ifp->vif->sme_state);
+		} else
+			brcmf_bss_connect_done(cfg, ndev, e, true);
+		brcmf_net_setcarrier(ifp, true);
+	} else if (brcmf_is_linkdown(e)) {
+		brcmf_dbg(CONN, "Linkdown\n");
+		if (!brcmf_is_ibssmode(ifp->vif)) {
+			brcmf_bss_connect_done(cfg, ndev, e, false);
+			brcmf_link_down(ifp->vif,
+					brcmf_map_fw_linkdown_reason(e));
+			brcmf_init_prof(ndev_to_prof(ndev));
+			if (ndev != cfg_to_ndev(cfg))
+				complete(&cfg->vif_disabled);
+			brcmf_net_setcarrier(ifp, false);
+		}
+	} else if (brcmf_is_nonetwork(cfg, e)) {
+		if (brcmf_is_ibssmode(ifp->vif))
+			clear_bit(BRCMF_VIF_STATUS_CONNECTING,
+				  &ifp->vif->sme_state);
+		else
+			brcmf_bss_connect_done(cfg, ndev, e, false);
+	}
+
+	return err;
+}
+
+static s32
+brcmf_notify_roaming_status(struct brcmf_if *ifp,
+			    const struct brcmf_event_msg *e, void *data)
+{
+	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+	u32 event = e->event_code;
+	u32 status = e->status;
+
+	if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) {
+		if (test_bit(BRCMF_VIF_STATUS_CONNECTED,
+			     &ifp->vif->sme_state)) {
+			brcmf_bss_roaming_done(cfg, ifp->ndev, e);
+		} else {
+			brcmf_bss_connect_done(cfg, ifp->ndev, e, true);
+			brcmf_net_setcarrier(ifp, true);
+		}
+	}
+
+	return 0;
+}
+
+static s32
+brcmf_notify_mic_status(struct brcmf_if *ifp,
+			const struct brcmf_event_msg *e, void *data)
+{
+	u16 flags = e->flags;
+	enum nl80211_key_type key_type;
+
+	if (flags & BRCMF_EVENT_MSG_GROUP)
+		key_type = NL80211_KEYTYPE_GROUP;
+	else
+		key_type = NL80211_KEYTYPE_PAIRWISE;
+
+	cfg80211_michael_mic_failure(ifp->ndev, (u8 *)&e->addr, key_type, -1,
+				     NULL, GFP_KERNEL);
+
+	return 0;
+}
+
+static s32 brcmf_notify_vif_event(struct brcmf_if *ifp,
+				  const struct brcmf_event_msg *e, void *data)
+{
+	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+	struct brcmf_if_event *ifevent = (struct brcmf_if_event *)data;
+	struct brcmf_cfg80211_vif_event *event = &cfg->vif_event;
+	struct brcmf_cfg80211_vif *vif;
+
+	brcmf_dbg(TRACE, "Enter: action %u flags %u ifidx %u bsscfgidx %u\n",
+		  ifevent->action, ifevent->flags, ifevent->ifidx,
+		  ifevent->bsscfgidx);
+
+	spin_lock(&event->vif_event_lock);
+	event->action = ifevent->action;
+	vif = event->vif;
+
+	switch (ifevent->action) {
+	case BRCMF_E_IF_ADD:
+		/* waiting process may have timed out */
+		if (!cfg->vif_event.vif) {
+			spin_unlock(&event->vif_event_lock);
+			return -EBADF;
+		}
+
+		ifp->vif = vif;
+		vif->ifp = ifp;
+		if (ifp->ndev) {
+			vif->wdev.netdev = ifp->ndev;
+			ifp->ndev->ieee80211_ptr = &vif->wdev;
+			SET_NETDEV_DEV(ifp->ndev, wiphy_dev(cfg->wiphy));
+		}
+		spin_unlock(&event->vif_event_lock);
+		wake_up(&event->vif_wq);
+		return 0;
+
+	case BRCMF_E_IF_DEL:
+		spin_unlock(&event->vif_event_lock);
+		/* event may not be upon user request */
+		if (brcmf_cfg80211_vif_event_armed(cfg))
+			wake_up(&event->vif_wq);
+		return 0;
+
+	case BRCMF_E_IF_CHANGE:
+		spin_unlock(&event->vif_event_lock);
+		wake_up(&event->vif_wq);
+		return 0;
+
+	default:
+		spin_unlock(&event->vif_event_lock);
+		break;
+	}
+	return -EINVAL;
+}
+
+static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
+{
+	conf->frag_threshold = (u32)-1;
+	conf->rts_threshold = (u32)-1;
+	conf->retry_short = (u32)-1;
+	conf->retry_long = (u32)-1;
+}
+
+static void brcmf_register_event_handlers(struct brcmf_cfg80211_info *cfg)
+{
+	brcmf_fweh_register(cfg->pub, BRCMF_E_LINK,
+			    brcmf_notify_connect_status);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_DEAUTH_IND,
+			    brcmf_notify_connect_status);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_DEAUTH,
+			    brcmf_notify_connect_status);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_DISASSOC_IND,
+			    brcmf_notify_connect_status);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_ASSOC_IND,
+			    brcmf_notify_connect_status);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_REASSOC_IND,
+			    brcmf_notify_connect_status);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_ROAM,
+			    brcmf_notify_roaming_status);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_MIC_ERROR,
+			    brcmf_notify_mic_status);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_SET_SSID,
+			    brcmf_notify_connect_status);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_PFN_NET_FOUND,
+			    brcmf_notify_sched_scan_results);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_IF,
+			    brcmf_notify_vif_event);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_P2P_PROBEREQ_MSG,
+			    brcmf_p2p_notify_rx_mgmt_p2p_probereq);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_P2P_DISC_LISTEN_COMPLETE,
+			    brcmf_p2p_notify_listen_complete);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_ACTION_FRAME_RX,
+			    brcmf_p2p_notify_action_frame_rx);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_ACTION_FRAME_COMPLETE,
+			    brcmf_p2p_notify_action_tx_complete);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE,
+			    brcmf_p2p_notify_action_tx_complete);
+	brcmf_fweh_register(cfg->pub, BRCMF_E_PSK_SUP,
+			    brcmf_notify_connect_status);
+}
+
+static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg)
+{
+	kfree(cfg->conf);
+	cfg->conf = NULL;
+	kfree(cfg->extra_buf);
+	cfg->extra_buf = NULL;
+	kfree(cfg->wowl.nd);
+	cfg->wowl.nd = NULL;
+	kfree(cfg->wowl.nd_info);
+	cfg->wowl.nd_info = NULL;
+	kfree(cfg->escan_info.escan_buf);
+	cfg->escan_info.escan_buf = NULL;
+}
+
+static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_info *cfg)
+{
+	cfg->conf = kzalloc(sizeof(*cfg->conf), GFP_KERNEL);
+	if (!cfg->conf)
+		goto init_priv_mem_out;
+	cfg->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
+	if (!cfg->extra_buf)
+		goto init_priv_mem_out;
+	cfg->wowl.nd = kzalloc(sizeof(*cfg->wowl.nd) + sizeof(u32), GFP_KERNEL);
+	if (!cfg->wowl.nd)
+		goto init_priv_mem_out;
+	cfg->wowl.nd_info = kzalloc(sizeof(*cfg->wowl.nd_info) +
+				    sizeof(struct cfg80211_wowlan_nd_match *),
+				    GFP_KERNEL);
+	if (!cfg->wowl.nd_info)
+		goto init_priv_mem_out;
+	cfg->escan_info.escan_buf = kzalloc(BRCMF_ESCAN_BUF_SIZE, GFP_KERNEL);
+	if (!cfg->escan_info.escan_buf)
+		goto init_priv_mem_out;
+
+	return 0;
+
+init_priv_mem_out:
+	brcmf_deinit_priv_mem(cfg);
+
+	return -ENOMEM;
+}
+
+static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg)
+{
+	s32 err = 0;
+
+	cfg->scan_request = NULL;
+	cfg->pwr_save = true;
+	cfg->dongle_up = false;		/* dongle is not up yet */
+	err = brcmf_init_priv_mem(cfg);
+	if (err)
+		return err;
+	brcmf_register_event_handlers(cfg);
+	mutex_init(&cfg->usr_sync);
+	brcmf_init_escan(cfg);
+	brcmf_init_conf(cfg->conf);
+	init_completion(&cfg->vif_disabled);
+	return err;
+}
+
+static void wl_deinit_priv(struct brcmf_cfg80211_info *cfg)
+{
+	cfg->dongle_up = false;	/* dongle down */
+	brcmf_abort_scanning(cfg);
+	brcmf_deinit_priv_mem(cfg);
+}
+
+static void init_vif_event(struct brcmf_cfg80211_vif_event *event)
+{
+	init_waitqueue_head(&event->vif_wq);
+	spin_lock_init(&event->vif_event_lock);
+}
+
+static s32 brcmf_dongle_roam(struct brcmf_if *ifp)
+{
+	s32 err;
+	u32 bcn_timeout;
+	__le32 roamtrigger[2];
+	__le32 roam_delta[2];
+
+	/* Configure beacon timeout value based upon roaming setting */
+	if (ifp->drvr->settings->roamoff)
+		bcn_timeout = BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_OFF;
+	else
+		bcn_timeout = BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_ON;
+	err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", bcn_timeout);
+	if (err) {
+		brcmf_err("bcn_timeout error (%d)\n", err);
+		goto roam_setup_done;
+	}
+
+	/* Enable/Disable built-in roaming to allow supplicant to take care of
+	 * roaming.
+	 */
+	brcmf_dbg(INFO, "Internal Roaming = %s\n",
+		  ifp->drvr->settings->roamoff ? "Off" : "On");
+	err = brcmf_fil_iovar_int_set(ifp, "roam_off",
+				      ifp->drvr->settings->roamoff);
+	if (err) {
+		brcmf_err("roam_off error (%d)\n", err);
+		goto roam_setup_done;
+	}
+
+	roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL);
+	roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL);
+	err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_TRIGGER,
+				     (void *)roamtrigger, sizeof(roamtrigger));
+	if (err) {
+		brcmf_err("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
+		goto roam_setup_done;
+	}
+
+	roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA);
+	roam_delta[1] = cpu_to_le32(BRCM_BAND_ALL);
+	err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_DELTA,
+				     (void *)roam_delta, sizeof(roam_delta));
+	if (err) {
+		brcmf_err("WLC_SET_ROAM_DELTA error (%d)\n", err);
+		goto roam_setup_done;
+	}
+
+roam_setup_done:
+	return err;
+}
+
+static s32
+brcmf_dongle_scantime(struct brcmf_if *ifp)
+{
+	s32 err = 0;
+
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,
+				    BRCMF_SCAN_CHANNEL_TIME);
+	if (err) {
+		brcmf_err("Scan assoc time error (%d)\n", err);
+		goto dongle_scantime_out;
+	}
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME,
+				    BRCMF_SCAN_UNASSOC_TIME);
+	if (err) {
+		brcmf_err("Scan unassoc time error (%d)\n", err);
+		goto dongle_scantime_out;
+	}
+
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_PASSIVE_TIME,
+				    BRCMF_SCAN_PASSIVE_TIME);
+	if (err) {
+		brcmf_err("Scan passive time error (%d)\n", err);
+		goto dongle_scantime_out;
+	}
+
+dongle_scantime_out:
+	return err;
+}
+
+static void brcmf_update_bw40_channel_flag(struct ieee80211_channel *channel,
+					   struct brcmu_chan *ch)
+{
+	u32 ht40_flag;
+
+	ht40_flag = channel->flags & IEEE80211_CHAN_NO_HT40;
+	if (ch->sb == BRCMU_CHAN_SB_U) {
+		if (ht40_flag == IEEE80211_CHAN_NO_HT40)
+			channel->flags &= ~IEEE80211_CHAN_NO_HT40;
+		channel->flags |= IEEE80211_CHAN_NO_HT40PLUS;
+	} else {
+		/* It should be one of
+		 * IEEE80211_CHAN_NO_HT40 or
+		 * IEEE80211_CHAN_NO_HT40PLUS
+		 */
+		channel->flags &= ~IEEE80211_CHAN_NO_HT40;
+		if (ht40_flag == IEEE80211_CHAN_NO_HT40)
+			channel->flags |= IEEE80211_CHAN_NO_HT40MINUS;
+	}
+}
+
+static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
+				    u32 bw_cap[])
+{
+	struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
+	struct ieee80211_supported_band *band;
+	struct ieee80211_channel *channel;
+	struct wiphy *wiphy;
+	struct brcmf_chanspec_list *list;
+	struct brcmu_chan ch;
+	int err;
+	u8 *pbuf;
+	u32 i, j;
+	u32 total;
+	u32 chaninfo;
+
+	pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
+
+	if (pbuf == NULL)
+		return -ENOMEM;
+
+	list = (struct brcmf_chanspec_list *)pbuf;
+
+	err = brcmf_fil_iovar_data_get(ifp, "chanspecs", pbuf,
+				       BRCMF_DCMD_MEDLEN);
+	if (err) {
+		brcmf_err("get chanspecs error (%d)\n", err);
+		goto fail_pbuf;
+	}
+
+	wiphy = cfg_to_wiphy(cfg);
+	band = wiphy->bands[NL80211_BAND_2GHZ];
+	if (band)
+		for (i = 0; i < band->n_channels; i++)
+			band->channels[i].flags = IEEE80211_CHAN_DISABLED;
+	band = wiphy->bands[NL80211_BAND_5GHZ];
+	if (band)
+		for (i = 0; i < band->n_channels; i++)
+			band->channels[i].flags = IEEE80211_CHAN_DISABLED;
+
+	total = le32_to_cpu(list->count);
+	for (i = 0; i < total; i++) {
+		ch.chspec = (u16)le32_to_cpu(list->element[i]);
+		cfg->d11inf.decchspec(&ch);
+
+		if (ch.band == BRCMU_CHAN_BAND_2G) {
+			band = wiphy->bands[NL80211_BAND_2GHZ];
+		} else if (ch.band == BRCMU_CHAN_BAND_5G) {
+			band = wiphy->bands[NL80211_BAND_5GHZ];
+		} else {
+			brcmf_err("Invalid channel Spec. 0x%x.\n", ch.chspec);
+			continue;
+		}
+		if (!band)
+			continue;
+		if (!(bw_cap[band->band] & WLC_BW_40MHZ_BIT) &&
+		    ch.bw == BRCMU_CHAN_BW_40)
+			continue;
+		if (!(bw_cap[band->band] & WLC_BW_80MHZ_BIT) &&
+		    ch.bw == BRCMU_CHAN_BW_80)
+			continue;
+
+		channel = NULL;
+		for (j = 0; j < band->n_channels; j++) {
+			if (band->channels[j].hw_value == ch.control_ch_num) {
+				channel = &band->channels[j];
+				break;
+			}
+		}
+		if (!channel) {
+			/* It seems firmware supports some channel we never
+			 * considered. Something new in IEEE standard?
+			 */
+			brcmf_err("Ignoring unexpected firmware channel %d\n",
+				  ch.control_ch_num);
+			continue;
+		}
+
+		if (channel->orig_flags & IEEE80211_CHAN_DISABLED)
+			continue;
+
+		/* assuming the chanspecs order is HT20,
+		 * HT40 upper, HT40 lower, and VHT80.
+		 */
+		if (ch.bw == BRCMU_CHAN_BW_80) {
+			channel->flags &= ~IEEE80211_CHAN_NO_80MHZ;
+		} else if (ch.bw == BRCMU_CHAN_BW_40) {
+			brcmf_update_bw40_channel_flag(channel, &ch);
+		} else {
+			/* enable the channel and disable other bandwidths
+			 * for now as mentioned order assure they are enabled
+			 * for subsequent chanspecs.
+			 */
+			channel->flags = IEEE80211_CHAN_NO_HT40 |
+					 IEEE80211_CHAN_NO_80MHZ |
+					 IEEE80211_CHAN_NO_160MHZ;
+			ch.bw = BRCMU_CHAN_BW_20;
+			cfg->d11inf.encchspec(&ch);
+			chaninfo = ch.chspec;
+			err = brcmf_fil_bsscfg_int_get(ifp, "per_chan_info",
+						       &chaninfo);
+			if (!err) {
+				if (chaninfo & WL_CHAN_RADAR)
+					channel->flags |=
+						(IEEE80211_CHAN_RADAR |
+						 IEEE80211_CHAN_NO_IR);
+				if (chaninfo & WL_CHAN_PASSIVE)
+					channel->flags |=
+						IEEE80211_CHAN_NO_IR;
+			}
+		}
+	}
+
+fail_pbuf:
+	kfree(pbuf);
+	return err;
+}
+
+static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg)
+{
+	struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
+	struct ieee80211_supported_band *band;
+	struct brcmf_fil_bwcap_le band_bwcap;
+	struct brcmf_chanspec_list *list;
+	u8 *pbuf;
+	u32 val;
+	int err;
+	struct brcmu_chan ch;
+	u32 num_chan;
+	int i, j;
+
+	/* verify support for bw_cap command */
+	val = WLC_BAND_5G;
+	err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &val);
+
+	if (!err) {
+		/* only set 2G bandwidth using bw_cap command */
+		band_bwcap.band = cpu_to_le32(WLC_BAND_2G);
+		band_bwcap.bw_cap = cpu_to_le32(WLC_BW_CAP_40MHZ);
+		err = brcmf_fil_iovar_data_set(ifp, "bw_cap", &band_bwcap,
+					       sizeof(band_bwcap));
+	} else {
+		brcmf_dbg(INFO, "fallback to mimo_bw_cap\n");
+		val = WLC_N_BW_40ALL;
+		err = brcmf_fil_iovar_int_set(ifp, "mimo_bw_cap", val);
+	}
+
+	if (!err) {
+		/* update channel info in 2G band */
+		pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
+
+		if (pbuf == NULL)
+			return -ENOMEM;
+
+		ch.band = BRCMU_CHAN_BAND_2G;
+		ch.bw = BRCMU_CHAN_BW_40;
+		ch.sb = BRCMU_CHAN_SB_NONE;
+		ch.chnum = 0;
+		cfg->d11inf.encchspec(&ch);
+
+		/* pass encoded chanspec in query */
+		*(__le16 *)pbuf = cpu_to_le16(ch.chspec);
+
+		err = brcmf_fil_iovar_data_get(ifp, "chanspecs", pbuf,
+					       BRCMF_DCMD_MEDLEN);
+		if (err) {
+			brcmf_err("get chanspecs error (%d)\n", err);
+			kfree(pbuf);
+			return err;
+		}
+
+		band = cfg_to_wiphy(cfg)->bands[NL80211_BAND_2GHZ];
+		list = (struct brcmf_chanspec_list *)pbuf;
+		num_chan = le32_to_cpu(list->count);
+		for (i = 0; i < num_chan; i++) {
+			ch.chspec = (u16)le32_to_cpu(list->element[i]);
+			cfg->d11inf.decchspec(&ch);
+			if (WARN_ON(ch.band != BRCMU_CHAN_BAND_2G))
+				continue;
+			if (WARN_ON(ch.bw != BRCMU_CHAN_BW_40))
+				continue;
+			for (j = 0; j < band->n_channels; j++) {
+				if (band->channels[j].hw_value == ch.control_ch_num)
+					break;
+			}
+			if (WARN_ON(j == band->n_channels))
+				continue;
+
+			brcmf_update_bw40_channel_flag(&band->channels[j], &ch);
+		}
+		kfree(pbuf);
+	}
+	return err;
+}
+
+static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[])
+{
+	u32 band, mimo_bwcap;
+	int err;
+
+	band = WLC_BAND_2G;
+	err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &band);
+	if (!err) {
+		bw_cap[NL80211_BAND_2GHZ] = band;
+		band = WLC_BAND_5G;
+		err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &band);
+		if (!err) {
+			bw_cap[NL80211_BAND_5GHZ] = band;
+			return;
+		}
+		WARN_ON(1);
+		return;
+	}
+	brcmf_dbg(INFO, "fallback to mimo_bw_cap info\n");
+	mimo_bwcap = 0;
+	err = brcmf_fil_iovar_int_get(ifp, "mimo_bw_cap", &mimo_bwcap);
+	if (err)
+		/* assume 20MHz if firmware does not give a clue */
+		mimo_bwcap = WLC_N_BW_20ALL;
+
+	switch (mimo_bwcap) {
+	case WLC_N_BW_40ALL:
+		bw_cap[NL80211_BAND_2GHZ] |= WLC_BW_40MHZ_BIT;
+		/* fall-thru */
+	case WLC_N_BW_20IN2G_40IN5G:
+		bw_cap[NL80211_BAND_5GHZ] |= WLC_BW_40MHZ_BIT;
+		/* fall-thru */
+	case WLC_N_BW_20ALL:
+		bw_cap[NL80211_BAND_2GHZ] |= WLC_BW_20MHZ_BIT;
+		bw_cap[NL80211_BAND_5GHZ] |= WLC_BW_20MHZ_BIT;
+		break;
+	default:
+		brcmf_err("invalid mimo_bw_cap value\n");
+	}
+}
+
+static void brcmf_update_ht_cap(struct ieee80211_supported_band *band,
+				u32 bw_cap[2], u32 nchain)
+{
+	band->ht_cap.ht_supported = true;
+	if (bw_cap[band->band] & WLC_BW_40MHZ_BIT) {
+		band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
+		band->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+	}
+	band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
+	band->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
+	band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+	band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
+	memset(band->ht_cap.mcs.rx_mask, 0xff, nchain);
+	band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
+}
+
+static __le16 brcmf_get_mcs_map(u32 nchain, enum ieee80211_vht_mcs_support supp)
+{
+	u16 mcs_map;
+	int i;
+
+	for (i = 0, mcs_map = 0xFFFF; i < nchain; i++)
+		mcs_map = (mcs_map << 2) | supp;
+
+	return cpu_to_le16(mcs_map);
+}
+
+static void brcmf_update_vht_cap(struct ieee80211_supported_band *band,
+				 u32 bw_cap[2], u32 nchain, u32 txstreams,
+				 u32 txbf_bfe_cap, u32 txbf_bfr_cap)
+{
+	__le16 mcs_map;
+
+	/* not allowed in 2.4G band */
+	if (band->band == NL80211_BAND_2GHZ)
+		return;
+
+	band->vht_cap.vht_supported = true;
+	/* 80MHz is mandatory */
+	band->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
+	if (bw_cap[band->band] & WLC_BW_160MHZ_BIT) {
+		band->vht_cap.cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
+		band->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
+	}
+	/* all support 256-QAM */
+	mcs_map = brcmf_get_mcs_map(nchain, IEEE80211_VHT_MCS_SUPPORT_0_9);
+	band->vht_cap.vht_mcs.rx_mcs_map = mcs_map;
+	band->vht_cap.vht_mcs.tx_mcs_map = mcs_map;
+
+	/* Beamforming support information */
+	if (txbf_bfe_cap & BRCMF_TXBF_SU_BFE_CAP)
+		band->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
+	if (txbf_bfe_cap & BRCMF_TXBF_MU_BFE_CAP)
+		band->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
+	if (txbf_bfr_cap & BRCMF_TXBF_SU_BFR_CAP)
+		band->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
+	if (txbf_bfr_cap & BRCMF_TXBF_MU_BFR_CAP)
+		band->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
+
+	if ((txbf_bfe_cap || txbf_bfr_cap) && (txstreams > 1)) {
+		band->vht_cap.cap |=
+			(2 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT);
+		band->vht_cap.cap |= ((txstreams - 1) <<
+				IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT);
+		band->vht_cap.cap |=
+			IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB;
+	}
+}
+
+static int brcmf_setup_wiphybands(struct brcmf_cfg80211_info *cfg)
+{
+	struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
+	struct wiphy *wiphy;
+	u32 nmode = 0;
+	u32 vhtmode = 0;
+	u32 bw_cap[2] = { WLC_BW_20MHZ_BIT, WLC_BW_20MHZ_BIT };
+	u32 rxchain;
+	u32 nchain;
+	int err;
+	s32 i;
+	struct ieee80211_supported_band *band;
+	u32 txstreams = 0;
+	u32 txbf_bfe_cap = 0;
+	u32 txbf_bfr_cap = 0;
+
+	(void)brcmf_fil_iovar_int_get(ifp, "vhtmode", &vhtmode);
+	err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode);
+	if (err) {
+		brcmf_err("nmode error (%d)\n", err);
+	} else {
+		brcmf_get_bwcap(ifp, bw_cap);
+	}
+	brcmf_dbg(INFO, "nmode=%d, vhtmode=%d, bw_cap=(%d, %d)\n",
+		  nmode, vhtmode, bw_cap[NL80211_BAND_2GHZ],
+		  bw_cap[NL80211_BAND_5GHZ]);
+
+	err = brcmf_fil_iovar_int_get(ifp, "rxchain", &rxchain);
+	if (err) {
+		brcmf_err("rxchain error (%d)\n", err);
+		nchain = 1;
+	} else {
+		for (nchain = 0; rxchain; nchain++)
+			rxchain = rxchain & (rxchain - 1);
+	}
+	brcmf_dbg(INFO, "nchain=%d\n", nchain);
+
+	err = brcmf_construct_chaninfo(cfg, bw_cap);
+	if (err) {
+		brcmf_err("brcmf_construct_chaninfo failed (%d)\n", err);
+		return err;
+	}
+
+	if (vhtmode) {
+		(void)brcmf_fil_iovar_int_get(ifp, "txstreams", &txstreams);
+		(void)brcmf_fil_iovar_int_get(ifp, "txbf_bfe_cap",
+					      &txbf_bfe_cap);
+		(void)brcmf_fil_iovar_int_get(ifp, "txbf_bfr_cap",
+					      &txbf_bfr_cap);
+	}
+
+	wiphy = cfg_to_wiphy(cfg);
+	for (i = 0; i < ARRAY_SIZE(wiphy->bands); i++) {
+		band = wiphy->bands[i];
+		if (band == NULL)
+			continue;
+
+		if (nmode)
+			brcmf_update_ht_cap(band, bw_cap, nchain);
+		if (vhtmode)
+			brcmf_update_vht_cap(band, bw_cap, nchain, txstreams,
+					     txbf_bfe_cap, txbf_bfr_cap);
+	}
+
+	return 0;
+}
+
+static const struct ieee80211_txrx_stypes
+brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
+	[NL80211_IFTYPE_STATION] = {
+		.tx = 0xffff,
+		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+	},
+	[NL80211_IFTYPE_P2P_CLIENT] = {
+		.tx = 0xffff,
+		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+	},
+	[NL80211_IFTYPE_P2P_GO] = {
+		.tx = 0xffff,
+		.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
+		      BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
+		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+		      BIT(IEEE80211_STYPE_DISASSOC >> 4) |
+		      BIT(IEEE80211_STYPE_AUTH >> 4) |
+		      BIT(IEEE80211_STYPE_DEAUTH >> 4) |
+		      BIT(IEEE80211_STYPE_ACTION >> 4)
+	},
+	[NL80211_IFTYPE_P2P_DEVICE] = {
+		.tx = 0xffff,
+		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+	}
+};
+
+/**
+ * brcmf_setup_ifmodes() - determine interface modes and combinations.
+ *
+ * @wiphy: wiphy object.
+ * @ifp: interface object needed for feat module api.
+ *
+ * The interface modes and combinations are determined dynamically here
+ * based on firmware functionality.
+ *
+ * no p2p and no mbss:
+ *
+ *	#STA <= 1, #AP <= 1, channels = 1, 2 total
+ *
+ * no p2p and mbss:
+ *
+ *	#STA <= 1, #AP <= 1, channels = 1, 2 total
+ *	#AP <= 4, matching BI, channels = 1, 4 total
+ *
+ * p2p, no mchan, and mbss:
+ *
+ *	#STA <= 1, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 1, 3 total
+ *	#STA <= 1, #P2P-DEV <= 1, #AP <= 1, #P2P-CL <= 1, channels = 1, 4 total
+ *	#AP <= 4, matching BI, channels = 1, 4 total
+ *
+ * p2p, mchan, and mbss:
+ *
+ *	#STA <= 1, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 2, 3 total
+ *	#STA <= 1, #P2P-DEV <= 1, #AP <= 1, #P2P-CL <= 1, channels = 1, 4 total
+ *	#AP <= 4, matching BI, channels = 1, 4 total
+ */
+static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp)
+{
+	struct ieee80211_iface_combination *combo = NULL;
+	struct ieee80211_iface_limit *c0_limits = NULL;
+	struct ieee80211_iface_limit *p2p_limits = NULL;
+	struct ieee80211_iface_limit *mbss_limits = NULL;
+	bool mbss, p2p;
+	int i, c, n_combos;
+
+	mbss = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS);
+	p2p = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P);
+
+	n_combos = 1 + !!p2p + !!mbss;
+	combo = kcalloc(n_combos, sizeof(*combo), GFP_KERNEL);
+	if (!combo)
+		goto err;
+
+	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+				 BIT(NL80211_IFTYPE_ADHOC) |
+				 BIT(NL80211_IFTYPE_AP);
+
+	c = 0;
+	i = 0;
+	c0_limits = kcalloc(p2p ? 3 : 2, sizeof(*c0_limits), GFP_KERNEL);
+	if (!c0_limits)
+		goto err;
+	c0_limits[i].max = 1;
+	c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION);
+	if (p2p) {
+		if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
+			combo[c].num_different_channels = 2;
+		else
+			combo[c].num_different_channels = 1;
+		wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) |
+					  BIT(NL80211_IFTYPE_P2P_GO) |
+					  BIT(NL80211_IFTYPE_P2P_DEVICE);
+		c0_limits[i].max = 1;
+		c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
+		c0_limits[i].max = 1;
+		c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
+				       BIT(NL80211_IFTYPE_P2P_GO);
+	} else {
+		combo[c].num_different_channels = 1;
+		c0_limits[i].max = 1;
+		c0_limits[i++].types = BIT(NL80211_IFTYPE_AP);
+	}
+	combo[c].max_interfaces = i;
+	combo[c].n_limits = i;
+	combo[c].limits = c0_limits;
+
+	if (p2p) {
+		c++;
+		i = 0;
+		p2p_limits = kcalloc(4, sizeof(*p2p_limits), GFP_KERNEL);
+		if (!p2p_limits)
+			goto err;
+		p2p_limits[i].max = 1;
+		p2p_limits[i++].types = BIT(NL80211_IFTYPE_STATION);
+		p2p_limits[i].max = 1;
+		p2p_limits[i++].types = BIT(NL80211_IFTYPE_AP);
+		p2p_limits[i].max = 1;
+		p2p_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT);
+		p2p_limits[i].max = 1;
+		p2p_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
+		combo[c].num_different_channels = 1;
+		combo[c].max_interfaces = i;
+		combo[c].n_limits = i;
+		combo[c].limits = p2p_limits;
+	}
+
+	if (mbss) {
+		c++;
+		i = 0;
+		mbss_limits = kcalloc(1, sizeof(*mbss_limits), GFP_KERNEL);
+		if (!mbss_limits)
+			goto err;
+		mbss_limits[i].max = 4;
+		mbss_limits[i++].types = BIT(NL80211_IFTYPE_AP);
+		combo[c].beacon_int_infra_match = true;
+		combo[c].num_different_channels = 1;
+		combo[c].max_interfaces = 4;
+		combo[c].n_limits = i;
+		combo[c].limits = mbss_limits;
+	}
+
+	wiphy->n_iface_combinations = n_combos;
+	wiphy->iface_combinations = combo;
+	return 0;
+
+err:
+	kfree(c0_limits);
+	kfree(p2p_limits);
+	kfree(mbss_limits);
+	kfree(combo);
+	return -ENOMEM;
+}
+
+#ifdef CONFIG_PM
+static const struct wiphy_wowlan_support brcmf_wowlan_support = {
+	.flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
+	.n_patterns = BRCMF_WOWL_MAXPATTERNS,
+	.pattern_max_len = BRCMF_WOWL_MAXPATTERNSIZE,
+	.pattern_min_len = 1,
+	.max_pkt_offset = 1500,
+};
+#endif
+
+static void brcmf_wiphy_wowl_params(struct wiphy *wiphy, struct brcmf_if *ifp)
+{
+#ifdef CONFIG_PM
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct wiphy_wowlan_support *wowl;
+
+	wowl = kmemdup(&brcmf_wowlan_support, sizeof(brcmf_wowlan_support),
+		       GFP_KERNEL);
+	if (!wowl) {
+		brcmf_err("only support basic wowlan features\n");
+		wiphy->wowlan = &brcmf_wowlan_support;
+		return;
+	}
+
+	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO)) {
+		if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_ND)) {
+			wowl->flags |= WIPHY_WOWLAN_NET_DETECT;
+			wowl->max_nd_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
+			init_waitqueue_head(&cfg->wowl.nd_data_wait);
+		}
+	}
+	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK)) {
+		wowl->flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY;
+		wowl->flags |= WIPHY_WOWLAN_GTK_REKEY_FAILURE;
+	}
+
+	wiphy->wowlan = wowl;
+#endif
+}
+
+static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
+{
+	struct brcmf_pub *drvr = ifp->drvr;
+	const struct ieee80211_iface_combination *combo;
+	struct ieee80211_supported_band *band;
+	u16 max_interfaces = 0;
+	bool gscan;
+	__le32 bandlist[3];
+	u32 n_bands;
+	int err, i;
+
+	wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
+	wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
+	wiphy->max_num_pmkids = BRCMF_MAXPMKID;
+
+	err = brcmf_setup_ifmodes(wiphy, ifp);
+	if (err)
+		return err;
+
+	for (i = 0, combo = wiphy->iface_combinations;
+	     i < wiphy->n_iface_combinations; i++, combo++) {
+		max_interfaces = max(max_interfaces, combo->max_interfaces);
+	}
+
+	for (i = 0; i < max_interfaces && i < ARRAY_SIZE(drvr->addresses);
+	     i++) {
+		u8 *addr = drvr->addresses[i].addr;
+
+		memcpy(addr, drvr->mac, ETH_ALEN);
+		if (i) {
+			addr[0] |= BIT(1);
+			addr[ETH_ALEN - 1] ^= i;
+		}
+	}
+	wiphy->addresses = drvr->addresses;
+	wiphy->n_addresses = i;
+
+	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+	wiphy->cipher_suites = brcmf_cipher_suites;
+	wiphy->n_cipher_suites = ARRAY_SIZE(brcmf_cipher_suites);
+	if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP))
+		wiphy->n_cipher_suites--;
+	wiphy->bss_select_support = BIT(NL80211_BSS_SELECT_ATTR_RSSI) |
+				    BIT(NL80211_BSS_SELECT_ATTR_BAND_PREF) |
+				    BIT(NL80211_BSS_SELECT_ATTR_RSSI_ADJUST);
+
+	wiphy->flags |= WIPHY_FLAG_NETNS_OK |
+			WIPHY_FLAG_PS_ON_BY_DEFAULT |
+			WIPHY_FLAG_HAVE_AP_SME |
+			WIPHY_FLAG_OFFCHAN_TX |
+			WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_TDLS))
+		wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
+	if (!ifp->drvr->settings->roamoff)
+		wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
+	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_FWSUP)) {
+		wiphy_ext_feature_set(wiphy,
+				      NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK);
+		wiphy_ext_feature_set(wiphy,
+				      NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X);
+	}
+	wiphy->mgmt_stypes = brcmf_txrx_stypes;
+	wiphy->max_remain_on_channel_duration = 5000;
+	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO)) {
+		gscan = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_GSCAN);
+		brcmf_pno_wiphy_params(wiphy, gscan);
+	}
+	/* vendor commands/events support */
+	wiphy->vendor_commands = brcmf_vendor_cmds;
+	wiphy->n_vendor_commands = BRCMF_VNDR_CMDS_LAST - 1;
+
+	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL))
+		brcmf_wiphy_wowl_params(wiphy, ifp);
+	err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BANDLIST, &bandlist,
+				     sizeof(bandlist));
+	if (err) {
+		brcmf_err("could not obtain band info: err=%d\n", err);
+		return err;
+	}
+	/* first entry in bandlist is number of bands */
+	n_bands = le32_to_cpu(bandlist[0]);
+	for (i = 1; i <= n_bands && i < ARRAY_SIZE(bandlist); i++) {
+		if (bandlist[i] == cpu_to_le32(WLC_BAND_2G)) {
+			band = kmemdup(&__wl_band_2ghz, sizeof(__wl_band_2ghz),
+				       GFP_KERNEL);
+			if (!band)
+				return -ENOMEM;
+
+			band->channels = kmemdup(&__wl_2ghz_channels,
+						 sizeof(__wl_2ghz_channels),
+						 GFP_KERNEL);
+			if (!band->channels) {
+				kfree(band);
+				return -ENOMEM;
+			}
+
+			band->n_channels = ARRAY_SIZE(__wl_2ghz_channels);
+			wiphy->bands[NL80211_BAND_2GHZ] = band;
+		}
+		if (bandlist[i] == cpu_to_le32(WLC_BAND_5G)) {
+			band = kmemdup(&__wl_band_5ghz, sizeof(__wl_band_5ghz),
+				       GFP_KERNEL);
+			if (!band)
+				return -ENOMEM;
+
+			band->channels = kmemdup(&__wl_5ghz_channels,
+						 sizeof(__wl_5ghz_channels),
+						 GFP_KERNEL);
+			if (!band->channels) {
+				kfree(band);
+				return -ENOMEM;
+			}
+
+			band->n_channels = ARRAY_SIZE(__wl_5ghz_channels);
+			wiphy->bands[NL80211_BAND_5GHZ] = band;
+		}
+	}
+
+	wiphy_read_of_freq_limits(wiphy);
+
+	return 0;
+}
+
+static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
+{
+	struct net_device *ndev;
+	struct wireless_dev *wdev;
+	struct brcmf_if *ifp;
+	s32 power_mode;
+	s32 err = 0;
+
+	if (cfg->dongle_up)
+		return err;
+
+	ndev = cfg_to_ndev(cfg);
+	wdev = ndev->ieee80211_ptr;
+	ifp = netdev_priv(ndev);
+
+	/* make sure RF is ready for work */
+	brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0);
+
+	brcmf_dongle_scantime(ifp);
+
+	power_mode = cfg->pwr_save ? PM_FAST : PM_OFF;
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, power_mode);
+	if (err)
+		goto default_conf_out;
+	brcmf_dbg(INFO, "power save set to %s\n",
+		  (power_mode ? "enabled" : "disabled"));
+
+	err = brcmf_dongle_roam(ifp);
+	if (err)
+		goto default_conf_out;
+	err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype,
+					  NULL);
+	if (err)
+		goto default_conf_out;
+
+	brcmf_configure_arp_nd_offload(ifp, true);
+
+	cfg->dongle_up = true;
+default_conf_out:
+
+	return err;
+
+}
+
+static s32 __brcmf_cfg80211_up(struct brcmf_if *ifp)
+{
+	set_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state);
+
+	return brcmf_config_dongle(ifp->drvr->config);
+}
+
+static s32 __brcmf_cfg80211_down(struct brcmf_if *ifp)
+{
+	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+
+	/*
+	 * While going down, if associated with AP disassociate
+	 * from AP to save power
+	 */
+	if (check_vif_up(ifp->vif)) {
+		brcmf_link_down(ifp->vif, WLAN_REASON_UNSPECIFIED);
+
+		/* Make sure WPA_Supplicant receives all the event
+		   generated due to DISASSOC call to the fw to keep
+		   the state fw and WPA_Supplicant state consistent
+		 */
+		brcmf_delay(500);
+	}
+
+	brcmf_abort_scanning(cfg);
+	clear_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state);
+
+	return 0;
+}
+
+s32 brcmf_cfg80211_up(struct net_device *ndev)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+	s32 err = 0;
+
+	mutex_lock(&cfg->usr_sync);
+	err = __brcmf_cfg80211_up(ifp);
+	mutex_unlock(&cfg->usr_sync);
+
+	return err;
+}
+
+s32 brcmf_cfg80211_down(struct net_device *ndev)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+	s32 err = 0;
+
+	mutex_lock(&cfg->usr_sync);
+	err = __brcmf_cfg80211_down(ifp);
+	mutex_unlock(&cfg->usr_sync);
+
+	return err;
+}
+
+enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp)
+{
+	struct wireless_dev *wdev = &ifp->vif->wdev;
+
+	return wdev->iftype;
+}
+
+bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg,
+			     unsigned long state)
+{
+	struct brcmf_cfg80211_vif *vif;
+
+	list_for_each_entry(vif, &cfg->vif_list, list) {
+		if (test_bit(state, &vif->sme_state))
+			return true;
+	}
+	return false;
+}
+
+static inline bool vif_event_equals(struct brcmf_cfg80211_vif_event *event,
+				    u8 action)
+{
+	u8 evt_action;
+
+	spin_lock(&event->vif_event_lock);
+	evt_action = event->action;
+	spin_unlock(&event->vif_event_lock);
+	return evt_action == action;
+}
+
+void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg,
+				  struct brcmf_cfg80211_vif *vif)
+{
+	struct brcmf_cfg80211_vif_event *event = &cfg->vif_event;
+
+	spin_lock(&event->vif_event_lock);
+	event->vif = vif;
+	event->action = 0;
+	spin_unlock(&event->vif_event_lock);
+}
+
+bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg)
+{
+	struct brcmf_cfg80211_vif_event *event = &cfg->vif_event;
+	bool armed;
+
+	spin_lock(&event->vif_event_lock);
+	armed = event->vif != NULL;
+	spin_unlock(&event->vif_event_lock);
+
+	return armed;
+}
+
+int brcmf_cfg80211_wait_vif_event(struct brcmf_cfg80211_info *cfg,
+				  u8 action, ulong timeout)
+{
+	struct brcmf_cfg80211_vif_event *event = &cfg->vif_event;
+
+	return wait_event_timeout(event->vif_wq,
+				  vif_event_equals(event, action), timeout);
+}
+
+static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2],
+					struct brcmf_fil_country_le *ccreq)
+{
+	struct brcmfmac_pd_cc *country_codes;
+	struct brcmfmac_pd_cc_entry *cc;
+	s32 found_index;
+	int i;
+
+	country_codes = drvr->settings->country_codes;
+	if (!country_codes) {
+		brcmf_dbg(TRACE, "No country codes configured for device\n");
+		return -EINVAL;
+	}
+
+	if ((alpha2[0] == ccreq->country_abbrev[0]) &&
+	    (alpha2[1] == ccreq->country_abbrev[1])) {
+		brcmf_dbg(TRACE, "Country code already set\n");
+		return -EAGAIN;
+	}
+
+	found_index = -1;
+	for (i = 0; i < country_codes->table_size; i++) {
+		cc = &country_codes->table[i];
+		if ((cc->iso3166[0] == '\0') && (found_index == -1))
+			found_index = i;
+		if ((cc->iso3166[0] == alpha2[0]) &&
+		    (cc->iso3166[1] == alpha2[1])) {
+			found_index = i;
+			break;
+		}
+	}
+	if (found_index == -1) {
+		brcmf_dbg(TRACE, "No country code match found\n");
+		return -EINVAL;
+	}
+	memset(ccreq, 0, sizeof(*ccreq));
+	ccreq->rev = cpu_to_le32(country_codes->table[found_index].rev);
+	memcpy(ccreq->ccode, country_codes->table[found_index].cc,
+	       BRCMF_COUNTRY_BUF_SZ);
+	ccreq->country_abbrev[0] = alpha2[0];
+	ccreq->country_abbrev[1] = alpha2[1];
+	ccreq->country_abbrev[2] = 0;
+
+	return 0;
+}
+
+static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy,
+					struct regulatory_request *req)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
+	struct brcmf_fil_country_le ccreq;
+	s32 err;
+	int i;
+
+	/* The country code gets set to "00" by default at boot, ignore */
+	if (req->alpha2[0] == '0' && req->alpha2[1] == '0')
+		return;
+
+	/* ignore non-ISO3166 country codes */
+	for (i = 0; i < 2; i++)
+		if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') {
+			brcmf_err("not an ISO3166 code (0x%02x 0x%02x)\n",
+				  req->alpha2[0], req->alpha2[1]);
+			return;
+		}
+
+	brcmf_dbg(TRACE, "Enter: initiator=%d, alpha=%c%c\n", req->initiator,
+		  req->alpha2[0], req->alpha2[1]);
+
+	err = brcmf_fil_iovar_data_get(ifp, "country", &ccreq, sizeof(ccreq));
+	if (err) {
+		brcmf_err("Country code iovar returned err = %d\n", err);
+		return;
+	}
+
+	err = brcmf_translate_country_code(ifp->drvr, req->alpha2, &ccreq);
+	if (err)
+		return;
+
+	err = brcmf_fil_iovar_data_set(ifp, "country", &ccreq, sizeof(ccreq));
+	if (err) {
+		brcmf_err("Firmware rejected country setting\n");
+		return;
+	}
+	brcmf_setup_wiphybands(cfg);
+}
+
+static void brcmf_free_wiphy(struct wiphy *wiphy)
+{
+	int i;
+
+	if (!wiphy)
+		return;
+
+	if (wiphy->iface_combinations) {
+		for (i = 0; i < wiphy->n_iface_combinations; i++)
+			kfree(wiphy->iface_combinations[i].limits);
+	}
+	kfree(wiphy->iface_combinations);
+	if (wiphy->bands[NL80211_BAND_2GHZ]) {
+		kfree(wiphy->bands[NL80211_BAND_2GHZ]->channels);
+		kfree(wiphy->bands[NL80211_BAND_2GHZ]);
+	}
+	if (wiphy->bands[NL80211_BAND_5GHZ]) {
+		kfree(wiphy->bands[NL80211_BAND_5GHZ]->channels);
+		kfree(wiphy->bands[NL80211_BAND_5GHZ]);
+	}
+#if IS_ENABLED(CONFIG_PM)
+	if (wiphy->wowlan != &brcmf_wowlan_support)
+		kfree(wiphy->wowlan);
+#endif
+}
+
+struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
+						  struct cfg80211_ops *ops,
+						  bool p2pdev_forced)
+{
+	struct wiphy *wiphy = drvr->wiphy;
+	struct net_device *ndev = brcmf_get_ifp(drvr, 0)->ndev;
+	struct brcmf_cfg80211_info *cfg;
+	struct brcmf_cfg80211_vif *vif;
+	struct brcmf_if *ifp;
+	s32 err = 0;
+	s32 io_type;
+	u16 *cap = NULL;
+
+	if (!ndev) {
+		brcmf_err("ndev is invalid\n");
+		return NULL;
+	}
+
+	cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
+	if (!cfg) {
+		brcmf_err("Could not allocate wiphy device\n");
+		return NULL;
+	}
+
+	cfg->wiphy = wiphy;
+	cfg->pub = drvr;
+	init_vif_event(&cfg->vif_event);
+	INIT_LIST_HEAD(&cfg->vif_list);
+
+	vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_STATION);
+	if (IS_ERR(vif))
+		goto wiphy_out;
+
+	ifp = netdev_priv(ndev);
+	vif->ifp = ifp;
+	vif->wdev.netdev = ndev;
+	ndev->ieee80211_ptr = &vif->wdev;
+	SET_NETDEV_DEV(ndev, wiphy_dev(cfg->wiphy));
+
+	err = wl_init_priv(cfg);
+	if (err) {
+		brcmf_err("Failed to init iwm_priv (%d)\n", err);
+		brcmf_free_vif(vif);
+		goto wiphy_out;
+	}
+	ifp->vif = vif;
+
+	/* determine d11 io type before wiphy setup */
+	err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION, &io_type);
+	if (err) {
+		brcmf_err("Failed to get D11 version (%d)\n", err);
+		goto priv_out;
+	}
+	cfg->d11inf.io_type = (u8)io_type;
+	brcmu_d11_attach(&cfg->d11inf);
+
+	/* regulatory notifer below needs access to cfg so
+	 * assign it now.
+	 */
+	drvr->config = cfg;
+
+	err = brcmf_setup_wiphy(wiphy, ifp);
+	if (err < 0)
+		goto priv_out;
+
+	brcmf_dbg(INFO, "Registering custom regulatory\n");
+	wiphy->reg_notifier = brcmf_cfg80211_reg_notifier;
+	wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
+	wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
+
+	/* firmware defaults to 40MHz disabled in 2G band. We signal
+	 * cfg80211 here that we do and have it decide we can enable
+	 * it. But first check if device does support 2G operation.
+	 */
+	if (wiphy->bands[NL80211_BAND_2GHZ]) {
+		cap = &wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap;
+		*cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+	}
+#ifdef CONFIG_PM
+	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK))
+		ops->set_rekey_data = brcmf_cfg80211_set_rekey_data;
+#endif
+	err = wiphy_register(wiphy);
+	if (err < 0) {
+		brcmf_err("Could not register wiphy device (%d)\n", err);
+		goto priv_out;
+	}
+
+	err = brcmf_setup_wiphybands(cfg);
+	if (err) {
+		brcmf_err("Setting wiphy bands failed (%d)\n", err);
+		goto wiphy_unreg_out;
+	}
+
+	/* If cfg80211 didn't disable 40MHz HT CAP in wiphy_register(),
+	 * setup 40MHz in 2GHz band and enable OBSS scanning.
+	 */
+	if (cap && (*cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) {
+		err = brcmf_enable_bw40_2g(cfg);
+		if (!err)
+			err = brcmf_fil_iovar_int_set(ifp, "obss_coex",
+						      BRCMF_OBSS_COEX_AUTO);
+		else
+			*cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+	}
+
+	err = brcmf_fweh_activate_events(ifp);
+	if (err) {
+		brcmf_err("FWEH activation failed (%d)\n", err);
+		goto wiphy_unreg_out;
+	}
+
+	err = brcmf_p2p_attach(cfg, p2pdev_forced);
+	if (err) {
+		brcmf_err("P2P initialisation failed (%d)\n", err);
+		goto wiphy_unreg_out;
+	}
+	err = brcmf_btcoex_attach(cfg);
+	if (err) {
+		brcmf_err("BT-coex initialisation failed (%d)\n", err);
+		brcmf_p2p_detach(&cfg->p2p);
+		goto wiphy_unreg_out;
+	}
+	err = brcmf_pno_attach(cfg);
+	if (err) {
+		brcmf_err("PNO initialisation failed (%d)\n", err);
+		brcmf_btcoex_detach(cfg);
+		brcmf_p2p_detach(&cfg->p2p);
+		goto wiphy_unreg_out;
+	}
+
+	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_TDLS)) {
+		err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1);
+		if (err) {
+			brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err);
+			wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_TDLS;
+		} else {
+			brcmf_fweh_register(cfg->pub, BRCMF_E_TDLS_PEER_EVENT,
+					    brcmf_notify_tdls_peer_event);
+		}
+	}
+
+	/* (re-) activate FWEH event handling */
+	err = brcmf_fweh_activate_events(ifp);
+	if (err) {
+		brcmf_err("FWEH activation failed (%d)\n", err);
+		goto detach;
+	}
+
+	/* Fill in some of the advertised nl80211 supported features */
+	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SCAN_RANDOM_MAC)) {
+		wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;
+#ifdef CONFIG_PM
+		if (wiphy->wowlan &&
+		    wiphy->wowlan->flags & WIPHY_WOWLAN_NET_DETECT)
+			wiphy->features |= NL80211_FEATURE_ND_RANDOM_MAC_ADDR;
+#endif
+	}
+
+	return cfg;
+
+detach:
+	brcmf_pno_detach(cfg);
+	brcmf_btcoex_detach(cfg);
+	brcmf_p2p_detach(&cfg->p2p);
+wiphy_unreg_out:
+	wiphy_unregister(cfg->wiphy);
+priv_out:
+	wl_deinit_priv(cfg);
+	brcmf_free_vif(vif);
+	ifp->vif = NULL;
+wiphy_out:
+	brcmf_free_wiphy(wiphy);
+	kfree(cfg);
+	return NULL;
+}
+
+void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
+{
+	if (!cfg)
+		return;
+
+	brcmf_pno_detach(cfg);
+	brcmf_btcoex_detach(cfg);
+	wiphy_unregister(cfg->wiphy);
+	kfree(cfg->ops);
+	wl_deinit_priv(cfg);
+	brcmf_free_wiphy(cfg->wiphy);
+	kfree(cfg);
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
new file mode 100644
index 0000000..a4aec00
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
@@ -0,0 +1,433 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef BRCMFMAC_CFG80211_H
+#define BRCMFMAC_CFG80211_H
+
+/* for brcmu_d11inf */
+#include <brcmu_d11.h>
+
+#include "core.h"
+#include "fwil_types.h"
+#include "p2p.h"
+
+#define BRCMF_SCAN_IE_LEN_MAX		2048
+
+#define WL_NUM_SCAN_MAX			10
+#define WL_TLV_INFO_MAX			1024
+#define WL_BSS_INFO_MAX			2048
+#define WL_ASSOC_INFO_MAX		512	/* assoc related fil max buf */
+#define WL_EXTRA_BUF_MAX		2048
+#define WL_ROAM_TRIGGER_LEVEL		-75
+#define WL_ROAM_DELTA			20
+
+/* Keep BRCMF_ESCAN_BUF_SIZE below 64K (65536). Allocing over 64K can be
+ * problematic on some systems and should be avoided.
+ */
+#define BRCMF_ESCAN_BUF_SIZE		65000
+#define BRCMF_ESCAN_TIMER_INTERVAL_MS	10000	/* E-Scan timeout */
+
+#define WL_ESCAN_ACTION_START		1
+#define WL_ESCAN_ACTION_CONTINUE	2
+#define WL_ESCAN_ACTION_ABORT		3
+
+#define WL_AUTH_SHARED_KEY		1	/* d11 shared authentication */
+#define IE_MAX_LEN			512
+
+/* IE TLV processing */
+#define TLV_LEN_OFF			1	/* length offset */
+#define TLV_HDR_LEN			2	/* header length */
+#define TLV_BODY_OFF			2	/* body offset */
+#define TLV_OUI_LEN			3	/* oui id length */
+
+/* 802.11 Mgmt Packet flags */
+#define BRCMF_VNDR_IE_BEACON_FLAG	0x1
+#define BRCMF_VNDR_IE_PRBRSP_FLAG	0x2
+#define BRCMF_VNDR_IE_ASSOCRSP_FLAG	0x4
+#define BRCMF_VNDR_IE_AUTHRSP_FLAG	0x8
+#define BRCMF_VNDR_IE_PRBREQ_FLAG	0x10
+#define BRCMF_VNDR_IE_ASSOCREQ_FLAG	0x20
+/* vendor IE in IW advertisement protocol ID field */
+#define BRCMF_VNDR_IE_IWAPID_FLAG	0x40
+/* allow custom IE id */
+#define BRCMF_VNDR_IE_CUSTOM_FLAG	0x100
+
+/* P2P Action Frames flags (spec ordered) */
+#define BRCMF_VNDR_IE_GONREQ_FLAG     0x001000
+#define BRCMF_VNDR_IE_GONRSP_FLAG     0x002000
+#define BRCMF_VNDR_IE_GONCFM_FLAG     0x004000
+#define BRCMF_VNDR_IE_INVREQ_FLAG     0x008000
+#define BRCMF_VNDR_IE_INVRSP_FLAG     0x010000
+#define BRCMF_VNDR_IE_DISREQ_FLAG     0x020000
+#define BRCMF_VNDR_IE_DISRSP_FLAG     0x040000
+#define BRCMF_VNDR_IE_PRDREQ_FLAG     0x080000
+#define BRCMF_VNDR_IE_PRDRSP_FLAG     0x100000
+
+#define BRCMF_VNDR_IE_P2PAF_SHIFT	12
+
+#define BRCMF_MAX_DEFAULT_KEYS		6
+
+/* beacon loss timeout defaults */
+#define BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_ON	2
+#define BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_OFF	4
+
+#define BRCMF_VIF_EVENT_TIMEOUT		msecs_to_jiffies(1500)
+
+/**
+ * enum brcmf_scan_status - scan engine status
+ *
+ * @BRCMF_SCAN_STATUS_BUSY: scanning in progress on dongle.
+ * @BRCMF_SCAN_STATUS_ABORT: scan being aborted on dongle.
+ * @BRCMF_SCAN_STATUS_SUPPRESS: scanning is suppressed in driver.
+ */
+enum brcmf_scan_status {
+	BRCMF_SCAN_STATUS_BUSY,
+	BRCMF_SCAN_STATUS_ABORT,
+	BRCMF_SCAN_STATUS_SUPPRESS,
+};
+
+/* dongle configuration */
+struct brcmf_cfg80211_conf {
+	u32 frag_threshold;
+	u32 rts_threshold;
+	u32 retry_short;
+	u32 retry_long;
+};
+
+/* security information with currently associated ap */
+struct brcmf_cfg80211_security {
+	u32 wpa_versions;
+	u32 auth_type;
+	u32 cipher_pairwise;
+	u32 cipher_group;
+};
+
+enum brcmf_profile_fwsup {
+	BRCMF_PROFILE_FWSUP_NONE,
+	BRCMF_PROFILE_FWSUP_PSK,
+	BRCMF_PROFILE_FWSUP_1X
+};
+
+/**
+ * struct brcmf_cfg80211_profile - profile information.
+ *
+ * @bssid: bssid of joined/joining ibss.
+ * @sec: security information.
+ * @key: key information
+ */
+struct brcmf_cfg80211_profile {
+	u8 bssid[ETH_ALEN];
+	struct brcmf_cfg80211_security sec;
+	struct brcmf_wsec_key key[BRCMF_MAX_DEFAULT_KEYS];
+	enum brcmf_profile_fwsup use_fwsup;
+};
+
+/**
+ * enum brcmf_vif_status - bit indices for vif status.
+ *
+ * @BRCMF_VIF_STATUS_READY: ready for operation.
+ * @BRCMF_VIF_STATUS_CONNECTING: connect/join in progress.
+ * @BRCMF_VIF_STATUS_CONNECTED: connected/joined successfully.
+ * @BRCMF_VIF_STATUS_DISCONNECTING: disconnect/disable in progress.
+ * @BRCMF_VIF_STATUS_AP_CREATED: AP operation started.
+ * @BRCMF_VIF_STATUS_EAP_SUCCUSS: EAPOL handshake successful.
+ * @BRCMF_VIF_STATUS_ASSOC_SUCCESS: successful SET_SSID received.
+ */
+enum brcmf_vif_status {
+	BRCMF_VIF_STATUS_READY,
+	BRCMF_VIF_STATUS_CONNECTING,
+	BRCMF_VIF_STATUS_CONNECTED,
+	BRCMF_VIF_STATUS_DISCONNECTING,
+	BRCMF_VIF_STATUS_AP_CREATED,
+	BRCMF_VIF_STATUS_EAP_SUCCESS,
+	BRCMF_VIF_STATUS_ASSOC_SUCCESS,
+};
+
+/**
+ * struct vif_saved_ie - holds saved IEs for a virtual interface.
+ *
+ * @probe_req_ie: IE info for probe request.
+ * @probe_res_ie: IE info for probe response.
+ * @beacon_ie: IE info for beacon frame.
+ * @probe_req_ie_len: IE info length for probe request.
+ * @probe_res_ie_len: IE info length for probe response.
+ * @beacon_ie_len: IE info length for beacon frame.
+ */
+struct vif_saved_ie {
+	u8  probe_req_ie[IE_MAX_LEN];
+	u8  probe_res_ie[IE_MAX_LEN];
+	u8  beacon_ie[IE_MAX_LEN];
+	u8  assoc_req_ie[IE_MAX_LEN];
+	u32 probe_req_ie_len;
+	u32 probe_res_ie_len;
+	u32 beacon_ie_len;
+	u32 assoc_req_ie_len;
+};
+
+/**
+ * struct brcmf_cfg80211_vif - virtual interface specific information.
+ *
+ * @ifp: lower layer interface pointer
+ * @wdev: wireless device.
+ * @profile: profile information.
+ * @sme_state: SME state using enum brcmf_vif_status bits.
+ * @list: linked list.
+ * @mgmt_rx_reg: registered rx mgmt frame types.
+ * @mbss: Multiple BSS type, set if not first AP (not relevant for P2P).
+ */
+struct brcmf_cfg80211_vif {
+	struct brcmf_if *ifp;
+	struct wireless_dev wdev;
+	struct brcmf_cfg80211_profile profile;
+	unsigned long sme_state;
+	struct vif_saved_ie saved_ie;
+	struct list_head list;
+	u16 mgmt_rx_reg;
+	bool mbss;
+	int is_11d;
+};
+
+/* association inform */
+struct brcmf_cfg80211_connect_info {
+	u8 *req_ie;
+	s32 req_ie_len;
+	u8 *resp_ie;
+	s32 resp_ie_len;
+};
+
+/* assoc ie length */
+struct brcmf_cfg80211_assoc_ielen_le {
+	__le32 req_len;
+	__le32 resp_len;
+};
+
+/* dongle escan state */
+enum wl_escan_state {
+	WL_ESCAN_STATE_IDLE,
+	WL_ESCAN_STATE_SCANNING
+};
+
+struct escan_info {
+	u32 escan_state;
+	u8 *escan_buf;
+	struct wiphy *wiphy;
+	struct brcmf_if *ifp;
+	s32 (*run)(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
+		   struct cfg80211_scan_request *request);
+};
+
+/**
+ * struct brcmf_cfg80211_vif_event - virtual interface event information.
+ *
+ * @vif_wq: waitqueue awaiting interface event from firmware.
+ * @vif_event_lock: protects other members in this structure.
+ * @vif_complete: completion for net attach.
+ * @action: either add, change, or delete.
+ * @vif: virtual interface object related to the event.
+ */
+struct brcmf_cfg80211_vif_event {
+	wait_queue_head_t vif_wq;
+	spinlock_t vif_event_lock;
+	u8 action;
+	struct brcmf_cfg80211_vif *vif;
+};
+
+/**
+ * struct brcmf_cfg80211_wowl - wowl related information.
+ *
+ * @active: set on suspend, cleared on resume.
+ * @pre_pmmode: firmware PM mode at entering suspend.
+ * @nd: net dectect data.
+ * @nd_info: helper struct to pass to cfg80211.
+ * @nd_data_wait: wait queue to sync net detect data.
+ * @nd_data_completed: completion for net detect data.
+ * @nd_enabled: net detect enabled.
+ */
+struct brcmf_cfg80211_wowl {
+	bool active;
+	u32 pre_pmmode;
+	struct cfg80211_wowlan_nd_match *nd;
+	struct cfg80211_wowlan_nd_info *nd_info;
+	wait_queue_head_t nd_data_wait;
+	bool nd_data_completed;
+	bool nd_enabled;
+};
+
+/**
+ * struct brcmf_cfg80211_info - dongle private data of cfg80211 interface
+ *
+ * @wiphy: wiphy object for cfg80211 interface.
+ * @ops: pointer to copy of ops as registered with wiphy object.
+ * @conf: dongle configuration.
+ * @p2p: peer-to-peer specific information.
+ * @btcoex: Bluetooth coexistence information.
+ * @scan_request: cfg80211 scan request object.
+ * @usr_sync: mainly for dongle up/down synchronization.
+ * @bss_list: bss_list holding scanned ap information.
+ * @bss_info: bss information for cfg80211 layer.
+ * @conn_info: association info.
+ * @pmk_list: wpa2 pmk list.
+ * @scan_status: scan activity on the dongle.
+ * @pub: common driver information.
+ * @channel: current channel.
+ * @int_escan_map: bucket map for which internal e-scan is done.
+ * @ibss_starter: indicates this sta is ibss starter.
+ * @pwr_save: indicate whether dongle to support power save mode.
+ * @dongle_up: indicate whether dongle up or not.
+ * @roam_on: on/off switch for dongle self-roaming.
+ * @scan_tried: indicates if first scan attempted.
+ * @dcmd_buf: dcmd buffer.
+ * @extra_buf: mainly to grab assoc information.
+ * @debugfsdir: debugfs folder for this device.
+ * @escan_info: escan information.
+ * @escan_timeout: Timer for catch scan timeout.
+ * @escan_timeout_work: scan timeout worker.
+ * @vif_list: linked list of vif instances.
+ * @vif_cnt: number of vif instances.
+ * @vif_event: vif event signalling.
+ * @wowl: wowl related information.
+ * @pno: information of pno module.
+ */
+struct brcmf_cfg80211_info {
+	struct wiphy *wiphy;
+	struct cfg80211_ops *ops;
+	struct brcmf_cfg80211_conf *conf;
+	struct brcmf_p2p_info p2p;
+	struct brcmf_btcoex_info *btcoex;
+	struct cfg80211_scan_request *scan_request;
+	struct mutex usr_sync;
+	struct wl_cfg80211_bss_info *bss_info;
+	struct brcmf_cfg80211_connect_info conn_info;
+	struct brcmf_pmk_list_le pmk_list;
+	unsigned long scan_status;
+	struct brcmf_pub *pub;
+	u32 channel;
+	u32 int_escan_map;
+	bool ibss_starter;
+	bool pwr_save;
+	bool dongle_up;
+	bool scan_tried;
+	u8 *dcmd_buf;
+	u8 *extra_buf;
+	struct dentry *debugfsdir;
+	struct escan_info escan_info;
+	struct timer_list escan_timeout;
+	struct work_struct escan_timeout_work;
+	struct list_head vif_list;
+	struct brcmf_cfg80211_vif_event vif_event;
+	struct completion vif_disabled;
+	struct brcmu_d11inf d11inf;
+	struct brcmf_assoclist_le assoclist;
+	struct brcmf_cfg80211_wowl wowl;
+	struct brcmf_pno_info *pno;
+};
+
+/**
+ * struct brcmf_tlv - tag_ID/length/value_buffer tuple.
+ *
+ * @id: tag identifier.
+ * @len: number of bytes in value buffer.
+ * @data: value buffer.
+ */
+struct brcmf_tlv {
+	u8 id;
+	u8 len;
+	u8 data[1];
+};
+
+static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *cfg)
+{
+	return cfg->wiphy;
+}
+
+static inline struct brcmf_cfg80211_info *wiphy_to_cfg(struct wiphy *w)
+{
+	struct brcmf_pub *drvr = wiphy_priv(w);
+	return drvr->config;
+}
+
+static inline struct brcmf_cfg80211_info *wdev_to_cfg(struct wireless_dev *wd)
+{
+	return wiphy_to_cfg(wd->wiphy);
+}
+
+static inline struct brcmf_cfg80211_vif *wdev_to_vif(struct wireless_dev *wdev)
+{
+	return container_of(wdev, struct brcmf_cfg80211_vif, wdev);
+}
+
+static inline
+struct net_device *cfg_to_ndev(struct brcmf_cfg80211_info *cfg)
+{
+	return brcmf_get_ifp(cfg->pub, 0)->ndev;
+}
+
+static inline struct brcmf_cfg80211_info *ndev_to_cfg(struct net_device *ndev)
+{
+	return wdev_to_cfg(ndev->ieee80211_ptr);
+}
+
+static inline struct brcmf_cfg80211_profile *ndev_to_prof(struct net_device *nd)
+{
+	struct brcmf_if *ifp = netdev_priv(nd);
+	return &ifp->vif->profile;
+}
+
+static inline struct brcmf_cfg80211_vif *ndev_to_vif(struct net_device *ndev)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	return ifp->vif;
+}
+
+static inline struct
+brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_info *cfg)
+{
+	return &cfg->conn_info;
+}
+
+struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
+						  struct cfg80211_ops *ops,
+						  bool p2pdev_forced);
+void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg);
+s32 brcmf_cfg80211_up(struct net_device *ndev);
+s32 brcmf_cfg80211_down(struct net_device *ndev);
+struct cfg80211_ops *brcmf_cfg80211_get_ops(void);
+enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp);
+
+struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
+					   enum nl80211_iftype type);
+void brcmf_free_vif(struct brcmf_cfg80211_vif *vif);
+
+s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
+			  const u8 *vndr_ie_buf, u32 vndr_ie_len);
+s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif);
+u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
+			struct ieee80211_channel *ch);
+bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg,
+			     unsigned long state);
+void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg,
+				  struct brcmf_cfg80211_vif *vif);
+bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg);
+int brcmf_cfg80211_wait_vif_event(struct brcmf_cfg80211_info *cfg,
+				  u8 action, ulong timeout);
+s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
+				struct brcmf_if *ifp, bool aborted,
+				bool fw_abort);
+void brcmf_set_mpc(struct brcmf_if *ndev, int mpc);
+void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg);
+void brcmf_cfg80211_free_netdev(struct net_device *ndev);
+
+#endif /* BRCMFMAC_CFG80211_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
new file mode 100644
index 0000000..927d62b
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
@@ -0,0 +1,1370 @@
+/*
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <linux/ssb/ssb_regs.h>
+#include <linux/bcma/bcma.h>
+#include <linux/bcma/bcma_regs.h>
+
+#include <defs.h>
+#include <soc.h>
+#include <brcm_hw_ids.h>
+#include <brcmu_utils.h>
+#include <chipcommon.h>
+#include "debug.h"
+#include "chip.h"
+
+/* SOC Interconnect types (aka chip types) */
+#define SOCI_SB		0
+#define SOCI_AI		1
+
+/* PL-368 DMP definitions */
+#define DMP_DESC_TYPE_MSK	0x0000000F
+#define  DMP_DESC_EMPTY		0x00000000
+#define  DMP_DESC_VALID		0x00000001
+#define  DMP_DESC_COMPONENT	0x00000001
+#define  DMP_DESC_MASTER_PORT	0x00000003
+#define  DMP_DESC_ADDRESS	0x00000005
+#define  DMP_DESC_ADDRSIZE_GT32	0x00000008
+#define  DMP_DESC_EOT		0x0000000F
+
+#define DMP_COMP_DESIGNER	0xFFF00000
+#define DMP_COMP_DESIGNER_S	20
+#define DMP_COMP_PARTNUM	0x000FFF00
+#define DMP_COMP_PARTNUM_S	8
+#define DMP_COMP_CLASS		0x000000F0
+#define DMP_COMP_CLASS_S	4
+#define DMP_COMP_REVISION	0xFF000000
+#define DMP_COMP_REVISION_S	24
+#define DMP_COMP_NUM_SWRAP	0x00F80000
+#define DMP_COMP_NUM_SWRAP_S	19
+#define DMP_COMP_NUM_MWRAP	0x0007C000
+#define DMP_COMP_NUM_MWRAP_S	14
+#define DMP_COMP_NUM_SPORT	0x00003E00
+#define DMP_COMP_NUM_SPORT_S	9
+#define DMP_COMP_NUM_MPORT	0x000001F0
+#define DMP_COMP_NUM_MPORT_S	4
+
+#define DMP_MASTER_PORT_UID	0x0000FF00
+#define DMP_MASTER_PORT_UID_S	8
+#define DMP_MASTER_PORT_NUM	0x000000F0
+#define DMP_MASTER_PORT_NUM_S	4
+
+#define DMP_SLAVE_ADDR_BASE	0xFFFFF000
+#define DMP_SLAVE_ADDR_BASE_S	12
+#define DMP_SLAVE_PORT_NUM	0x00000F00
+#define DMP_SLAVE_PORT_NUM_S	8
+#define DMP_SLAVE_TYPE		0x000000C0
+#define DMP_SLAVE_TYPE_S	6
+#define  DMP_SLAVE_TYPE_SLAVE	0
+#define  DMP_SLAVE_TYPE_BRIDGE	1
+#define  DMP_SLAVE_TYPE_SWRAP	2
+#define  DMP_SLAVE_TYPE_MWRAP	3
+#define DMP_SLAVE_SIZE_TYPE	0x00000030
+#define DMP_SLAVE_SIZE_TYPE_S	4
+#define  DMP_SLAVE_SIZE_4K	0
+#define  DMP_SLAVE_SIZE_8K	1
+#define  DMP_SLAVE_SIZE_16K	2
+#define  DMP_SLAVE_SIZE_DESC	3
+
+/* EROM CompIdentB */
+#define CIB_REV_MASK		0xff000000
+#define CIB_REV_SHIFT		24
+
+/* ARM CR4 core specific control flag bits */
+#define ARMCR4_BCMA_IOCTL_CPUHALT	0x0020
+
+/* D11 core specific control flag bits */
+#define D11_BCMA_IOCTL_PHYCLOCKEN	0x0004
+#define D11_BCMA_IOCTL_PHYRESET		0x0008
+
+/* chip core base & ramsize */
+/* bcm4329 */
+/* SDIO device core, ID 0x829 */
+#define BCM4329_CORE_BUS_BASE		0x18011000
+/* internal memory core, ID 0x80e */
+#define BCM4329_CORE_SOCRAM_BASE	0x18003000
+/* ARM Cortex M3 core, ID 0x82a */
+#define BCM4329_CORE_ARM_BASE		0x18002000
+
+/* Max possibly supported memory size (limited by IO mapped memory) */
+#define BRCMF_CHIP_MAX_MEMSIZE		(4 * 1024 * 1024)
+
+#define CORE_SB(base, field) \
+		(base + SBCONFIGOFF + offsetof(struct sbconfig, field))
+#define	SBCOREREV(sbidh) \
+	((((sbidh) & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT) | \
+	  ((sbidh) & SSB_IDHIGH_RCLO))
+
+struct sbconfig {
+	u32 PAD[2];
+	u32 sbipsflag;	/* initiator port ocp slave flag */
+	u32 PAD[3];
+	u32 sbtpsflag;	/* target port ocp slave flag */
+	u32 PAD[11];
+	u32 sbtmerrloga;	/* (sonics >= 2.3) */
+	u32 PAD;
+	u32 sbtmerrlog;	/* (sonics >= 2.3) */
+	u32 PAD[3];
+	u32 sbadmatch3;	/* address match3 */
+	u32 PAD;
+	u32 sbadmatch2;	/* address match2 */
+	u32 PAD;
+	u32 sbadmatch1;	/* address match1 */
+	u32 PAD[7];
+	u32 sbimstate;	/* initiator agent state */
+	u32 sbintvec;	/* interrupt mask */
+	u32 sbtmstatelow;	/* target state */
+	u32 sbtmstatehigh;	/* target state */
+	u32 sbbwa0;		/* bandwidth allocation table0 */
+	u32 PAD;
+	u32 sbimconfiglow;	/* initiator configuration */
+	u32 sbimconfighigh;	/* initiator configuration */
+	u32 sbadmatch0;	/* address match0 */
+	u32 PAD;
+	u32 sbtmconfiglow;	/* target configuration */
+	u32 sbtmconfighigh;	/* target configuration */
+	u32 sbbconfig;	/* broadcast configuration */
+	u32 PAD;
+	u32 sbbstate;	/* broadcast state */
+	u32 PAD[3];
+	u32 sbactcnfg;	/* activate configuration */
+	u32 PAD[3];
+	u32 sbflagst;	/* current sbflags */
+	u32 PAD[3];
+	u32 sbidlow;		/* identification */
+	u32 sbidhigh;	/* identification */
+};
+
+/* bankidx and bankinfo reg defines corerev >= 8 */
+#define SOCRAM_BANKINFO_RETNTRAM_MASK	0x00010000
+#define SOCRAM_BANKINFO_SZMASK		0x0000007f
+#define SOCRAM_BANKIDX_ROM_MASK		0x00000100
+
+#define SOCRAM_BANKIDX_MEMTYPE_SHIFT	8
+/* socram bankinfo memtype */
+#define SOCRAM_MEMTYPE_RAM		0
+#define SOCRAM_MEMTYPE_R0M		1
+#define SOCRAM_MEMTYPE_DEVRAM		2
+
+#define SOCRAM_BANKINFO_SZBASE		8192
+#define SRCI_LSS_MASK		0x00f00000
+#define SRCI_LSS_SHIFT		20
+#define	SRCI_SRNB_MASK		0xf0
+#define	SRCI_SRNB_SHIFT		4
+#define	SRCI_SRBSZ_MASK		0xf
+#define	SRCI_SRBSZ_SHIFT	0
+#define SR_BSZ_BASE		14
+
+struct sbsocramregs {
+	u32 coreinfo;
+	u32 bwalloc;
+	u32 extracoreinfo;
+	u32 biststat;
+	u32 bankidx;
+	u32 standbyctrl;
+
+	u32 errlogstatus;	/* rev 6 */
+	u32 errlogaddr;	/* rev 6 */
+	/* used for patching rev 3 & 5 */
+	u32 cambankidx;
+	u32 cambankstandbyctrl;
+	u32 cambankpatchctrl;
+	u32 cambankpatchtblbaseaddr;
+	u32 cambankcmdreg;
+	u32 cambankdatareg;
+	u32 cambankmaskreg;
+	u32 PAD[1];
+	u32 bankinfo;	/* corev 8 */
+	u32 bankpda;
+	u32 PAD[14];
+	u32 extmemconfig;
+	u32 extmemparitycsr;
+	u32 extmemparityerrdata;
+	u32 extmemparityerrcnt;
+	u32 extmemwrctrlandsize;
+	u32 PAD[84];
+	u32 workaround;
+	u32 pwrctl;		/* corerev >= 2 */
+	u32 PAD[133];
+	u32 sr_control;     /* corerev >= 15 */
+	u32 sr_status;      /* corerev >= 15 */
+	u32 sr_address;     /* corerev >= 15 */
+	u32 sr_data;        /* corerev >= 15 */
+};
+
+#define SOCRAMREGOFFS(_f)	offsetof(struct sbsocramregs, _f)
+#define SYSMEMREGOFFS(_f)	offsetof(struct sbsocramregs, _f)
+
+#define ARMCR4_CAP		(0x04)
+#define ARMCR4_BANKIDX		(0x40)
+#define ARMCR4_BANKINFO		(0x44)
+#define ARMCR4_BANKPDA		(0x4C)
+
+#define	ARMCR4_TCBBNB_MASK	0xf0
+#define	ARMCR4_TCBBNB_SHIFT	4
+#define	ARMCR4_TCBANB_MASK	0xf
+#define	ARMCR4_TCBANB_SHIFT	0
+
+#define	ARMCR4_BSZ_MASK		0x3f
+#define	ARMCR4_BSZ_MULT		8192
+
+struct brcmf_core_priv {
+	struct brcmf_core pub;
+	u32 wrapbase;
+	struct list_head list;
+	struct brcmf_chip_priv *chip;
+};
+
+struct brcmf_chip_priv {
+	struct brcmf_chip pub;
+	const struct brcmf_buscore_ops *ops;
+	void *ctx;
+	/* assured first core is chipcommon, second core is buscore */
+	struct list_head cores;
+	u16 num_cores;
+
+	bool (*iscoreup)(struct brcmf_core_priv *core);
+	void (*coredisable)(struct brcmf_core_priv *core, u32 prereset,
+			    u32 reset);
+	void (*resetcore)(struct brcmf_core_priv *core, u32 prereset, u32 reset,
+			  u32 postreset);
+};
+
+static void brcmf_chip_sb_corerev(struct brcmf_chip_priv *ci,
+				  struct brcmf_core *core)
+{
+	u32 regdata;
+
+	regdata = ci->ops->read32(ci->ctx, CORE_SB(core->base, sbidhigh));
+	core->rev = SBCOREREV(regdata);
+}
+
+static bool brcmf_chip_sb_iscoreup(struct brcmf_core_priv *core)
+{
+	struct brcmf_chip_priv *ci;
+	u32 regdata;
+	u32 address;
+
+	ci = core->chip;
+	address = CORE_SB(core->pub.base, sbtmstatelow);
+	regdata = ci->ops->read32(ci->ctx, address);
+	regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT |
+		    SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK);
+	return SSB_TMSLOW_CLOCK == regdata;
+}
+
+static bool brcmf_chip_ai_iscoreup(struct brcmf_core_priv *core)
+{
+	struct brcmf_chip_priv *ci;
+	u32 regdata;
+	bool ret;
+
+	ci = core->chip;
+	regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL);
+	ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK;
+
+	regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL);
+	ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0);
+
+	return ret;
+}
+
+static void brcmf_chip_sb_coredisable(struct brcmf_core_priv *core,
+				      u32 prereset, u32 reset)
+{
+	struct brcmf_chip_priv *ci;
+	u32 val, base;
+
+	ci = core->chip;
+	base = core->pub.base;
+	val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
+	if (val & SSB_TMSLOW_RESET)
+		return;
+
+	val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
+	if ((val & SSB_TMSLOW_CLOCK) != 0) {
+		/*
+		 * set target reject and spin until busy is clear
+		 * (preserve core-specific bits)
+		 */
+		val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
+		ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),
+					 val | SSB_TMSLOW_REJECT);
+
+		val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
+		udelay(1);
+		SPINWAIT((ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatehigh))
+			  & SSB_TMSHIGH_BUSY), 100000);
+
+		val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatehigh));
+		if (val & SSB_TMSHIGH_BUSY)
+			brcmf_err("core state still busy\n");
+
+		val = ci->ops->read32(ci->ctx, CORE_SB(base, sbidlow));
+		if (val & SSB_IDLOW_INITIATOR) {
+			val = ci->ops->read32(ci->ctx,
+					      CORE_SB(base, sbimstate));
+			val |= SSB_IMSTATE_REJECT;
+			ci->ops->write32(ci->ctx,
+					 CORE_SB(base, sbimstate), val);
+			val = ci->ops->read32(ci->ctx,
+					      CORE_SB(base, sbimstate));
+			udelay(1);
+			SPINWAIT((ci->ops->read32(ci->ctx,
+						  CORE_SB(base, sbimstate)) &
+				  SSB_IMSTATE_BUSY), 100000);
+		}
+
+		/* set reset and reject while enabling the clocks */
+		val = SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
+		      SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET;
+		ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow), val);
+		val = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
+		udelay(10);
+
+		/* clear the initiator reject bit */
+		val = ci->ops->read32(ci->ctx, CORE_SB(base, sbidlow));
+		if (val & SSB_IDLOW_INITIATOR) {
+			val = ci->ops->read32(ci->ctx,
+					      CORE_SB(base, sbimstate));
+			val &= ~SSB_IMSTATE_REJECT;
+			ci->ops->write32(ci->ctx,
+					 CORE_SB(base, sbimstate), val);
+		}
+	}
+
+	/* leave reset and reject asserted */
+	ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),
+			 (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET));
+	udelay(1);
+}
+
+static void brcmf_chip_ai_coredisable(struct brcmf_core_priv *core,
+				      u32 prereset, u32 reset)
+{
+	struct brcmf_chip_priv *ci;
+	u32 regdata;
+
+	ci = core->chip;
+
+	/* if core is already in reset, skip reset */
+	regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL);
+	if ((regdata & BCMA_RESET_CTL_RESET) != 0)
+		goto in_reset_configure;
+
+	/* configure reset */
+	ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL,
+			 prereset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK);
+	ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL);
+
+	/* put in reset */
+	ci->ops->write32(ci->ctx, core->wrapbase + BCMA_RESET_CTL,
+			 BCMA_RESET_CTL_RESET);
+	usleep_range(10, 20);
+
+	/* wait till reset is 1 */
+	SPINWAIT(ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL) !=
+		 BCMA_RESET_CTL_RESET, 300);
+
+in_reset_configure:
+	/* in-reset configure */
+	ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL,
+			 reset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK);
+	ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL);
+}
+
+static void brcmf_chip_sb_resetcore(struct brcmf_core_priv *core, u32 prereset,
+				    u32 reset, u32 postreset)
+{
+	struct brcmf_chip_priv *ci;
+	u32 regdata;
+	u32 base;
+
+	ci = core->chip;
+	base = core->pub.base;
+	/*
+	 * Must do the disable sequence first to work for
+	 * arbitrary current core state.
+	 */
+	brcmf_chip_sb_coredisable(core, 0, 0);
+
+	/*
+	 * Now do the initialization sequence.
+	 * set reset while enabling the clock and
+	 * forcing them on throughout the core
+	 */
+	ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),
+			 SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
+			 SSB_TMSLOW_RESET);
+	regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
+	udelay(1);
+
+	/* clear any serror */
+	regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatehigh));
+	if (regdata & SSB_TMSHIGH_SERR)
+		ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatehigh), 0);
+
+	regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbimstate));
+	if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO)) {
+		regdata &= ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO);
+		ci->ops->write32(ci->ctx, CORE_SB(base, sbimstate), regdata);
+	}
+
+	/* clear reset and allow it to propagate throughout the core */
+	ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),
+			 SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK);
+	regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
+	udelay(1);
+
+	/* leave clock enabled */
+	ci->ops->write32(ci->ctx, CORE_SB(base, sbtmstatelow),
+			 SSB_TMSLOW_CLOCK);
+	regdata = ci->ops->read32(ci->ctx, CORE_SB(base, sbtmstatelow));
+	udelay(1);
+}
+
+static void brcmf_chip_ai_resetcore(struct brcmf_core_priv *core, u32 prereset,
+				    u32 reset, u32 postreset)
+{
+	struct brcmf_chip_priv *ci;
+	int count;
+
+	ci = core->chip;
+
+	/* must disable first to work for arbitrary current core state */
+	brcmf_chip_ai_coredisable(core, prereset, reset);
+
+	count = 0;
+	while (ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL) &
+	       BCMA_RESET_CTL_RESET) {
+		ci->ops->write32(ci->ctx, core->wrapbase + BCMA_RESET_CTL, 0);
+		count++;
+		if (count > 50)
+			break;
+		usleep_range(40, 60);
+	}
+
+	ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL,
+			 postreset | BCMA_IOCTL_CLK);
+	ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL);
+}
+
+char *brcmf_chip_name(u32 id, u32 rev, char *buf, uint len)
+{
+	const char *fmt;
+
+	fmt = ((id > 0xa000) || (id < 0x4000)) ? "BCM%d/%u" : "BCM%x/%u";
+	snprintf(buf, len, fmt, id, rev);
+	return buf;
+}
+
+static struct brcmf_core *brcmf_chip_add_core(struct brcmf_chip_priv *ci,
+					      u16 coreid, u32 base,
+					      u32 wrapbase)
+{
+	struct brcmf_core_priv *core;
+
+	core = kzalloc(sizeof(*core), GFP_KERNEL);
+	if (!core)
+		return ERR_PTR(-ENOMEM);
+
+	core->pub.id = coreid;
+	core->pub.base = base;
+	core->chip = ci;
+	core->wrapbase = wrapbase;
+
+	list_add_tail(&core->list, &ci->cores);
+	return &core->pub;
+}
+
+/* safety check for chipinfo */
+static int brcmf_chip_cores_check(struct brcmf_chip_priv *ci)
+{
+	struct brcmf_core_priv *core;
+	bool need_socram = false;
+	bool has_socram = false;
+	bool cpu_found = false;
+	int idx = 1;
+
+	list_for_each_entry(core, &ci->cores, list) {
+		brcmf_dbg(INFO, " [%-2d] core 0x%x:%-2d base 0x%08x wrap 0x%08x\n",
+			  idx++, core->pub.id, core->pub.rev, core->pub.base,
+			  core->wrapbase);
+
+		switch (core->pub.id) {
+		case BCMA_CORE_ARM_CM3:
+			cpu_found = true;
+			need_socram = true;
+			break;
+		case BCMA_CORE_INTERNAL_MEM:
+			has_socram = true;
+			break;
+		case BCMA_CORE_ARM_CR4:
+			cpu_found = true;
+			break;
+		case BCMA_CORE_ARM_CA7:
+			cpu_found = true;
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (!cpu_found) {
+		brcmf_err("CPU core not detected\n");
+		return -ENXIO;
+	}
+	/* check RAM core presence for ARM CM3 core */
+	if (need_socram && !has_socram) {
+		brcmf_err("RAM core not provided with ARM CM3 core\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static u32 brcmf_chip_core_read32(struct brcmf_core_priv *core, u16 reg)
+{
+	return core->chip->ops->read32(core->chip->ctx, core->pub.base + reg);
+}
+
+static void brcmf_chip_core_write32(struct brcmf_core_priv *core,
+				    u16 reg, u32 val)
+{
+	core->chip->ops->write32(core->chip->ctx, core->pub.base + reg, val);
+}
+
+static bool brcmf_chip_socram_banksize(struct brcmf_core_priv *core, u8 idx,
+				       u32 *banksize)
+{
+	u32 bankinfo;
+	u32 bankidx = (SOCRAM_MEMTYPE_RAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
+
+	bankidx |= idx;
+	brcmf_chip_core_write32(core, SOCRAMREGOFFS(bankidx), bankidx);
+	bankinfo = brcmf_chip_core_read32(core, SOCRAMREGOFFS(bankinfo));
+	*banksize = (bankinfo & SOCRAM_BANKINFO_SZMASK) + 1;
+	*banksize *= SOCRAM_BANKINFO_SZBASE;
+	return !!(bankinfo & SOCRAM_BANKINFO_RETNTRAM_MASK);
+}
+
+static void brcmf_chip_socram_ramsize(struct brcmf_core_priv *sr, u32 *ramsize,
+				      u32 *srsize)
+{
+	u32 coreinfo;
+	uint nb, banksize, lss;
+	bool retent;
+	int i;
+
+	*ramsize = 0;
+	*srsize = 0;
+
+	if (WARN_ON(sr->pub.rev < 4))
+		return;
+
+	if (!brcmf_chip_iscoreup(&sr->pub))
+		brcmf_chip_resetcore(&sr->pub, 0, 0, 0);
+
+	/* Get info for determining size */
+	coreinfo = brcmf_chip_core_read32(sr, SOCRAMREGOFFS(coreinfo));
+	nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
+
+	if ((sr->pub.rev <= 7) || (sr->pub.rev == 12)) {
+		banksize = (coreinfo & SRCI_SRBSZ_MASK);
+		lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
+		if (lss != 0)
+			nb--;
+		*ramsize = nb * (1 << (banksize + SR_BSZ_BASE));
+		if (lss != 0)
+			*ramsize += (1 << ((lss - 1) + SR_BSZ_BASE));
+	} else {
+		nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
+		for (i = 0; i < nb; i++) {
+			retent = brcmf_chip_socram_banksize(sr, i, &banksize);
+			*ramsize += banksize;
+			if (retent)
+				*srsize += banksize;
+		}
+	}
+
+	/* hardcoded save&restore memory sizes */
+	switch (sr->chip->pub.chip) {
+	case BRCM_CC_4334_CHIP_ID:
+		if (sr->chip->pub.chiprev < 2)
+			*srsize = (32 * 1024);
+		break;
+	case BRCM_CC_43430_CHIP_ID:
+		/* assume sr for now as we can not check
+		 * firmware sr capability at this point.
+		 */
+		*srsize = (64 * 1024);
+		break;
+	default:
+		break;
+	}
+}
+
+/** Return the SYS MEM size */
+static u32 brcmf_chip_sysmem_ramsize(struct brcmf_core_priv *sysmem)
+{
+	u32 memsize = 0;
+	u32 coreinfo;
+	u32 idx;
+	u32 nb;
+	u32 banksize;
+
+	if (!brcmf_chip_iscoreup(&sysmem->pub))
+		brcmf_chip_resetcore(&sysmem->pub, 0, 0, 0);
+
+	coreinfo = brcmf_chip_core_read32(sysmem, SYSMEMREGOFFS(coreinfo));
+	nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
+
+	for (idx = 0; idx < nb; idx++) {
+		brcmf_chip_socram_banksize(sysmem, idx, &banksize);
+		memsize += banksize;
+	}
+
+	return memsize;
+}
+
+/** Return the TCM-RAM size of the ARMCR4 core. */
+static u32 brcmf_chip_tcm_ramsize(struct brcmf_core_priv *cr4)
+{
+	u32 corecap;
+	u32 memsize = 0;
+	u32 nab;
+	u32 nbb;
+	u32 totb;
+	u32 bxinfo;
+	u32 idx;
+
+	corecap = brcmf_chip_core_read32(cr4, ARMCR4_CAP);
+
+	nab = (corecap & ARMCR4_TCBANB_MASK) >> ARMCR4_TCBANB_SHIFT;
+	nbb = (corecap & ARMCR4_TCBBNB_MASK) >> ARMCR4_TCBBNB_SHIFT;
+	totb = nab + nbb;
+
+	for (idx = 0; idx < totb; idx++) {
+		brcmf_chip_core_write32(cr4, ARMCR4_BANKIDX, idx);
+		bxinfo = brcmf_chip_core_read32(cr4, ARMCR4_BANKINFO);
+		memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * ARMCR4_BSZ_MULT;
+	}
+
+	return memsize;
+}
+
+static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci)
+{
+	switch (ci->pub.chip) {
+	case BRCM_CC_4345_CHIP_ID:
+		return 0x198000;
+	case BRCM_CC_4335_CHIP_ID:
+	case BRCM_CC_4339_CHIP_ID:
+	case BRCM_CC_4350_CHIP_ID:
+	case BRCM_CC_4354_CHIP_ID:
+	case BRCM_CC_4356_CHIP_ID:
+	case BRCM_CC_43567_CHIP_ID:
+	case BRCM_CC_43569_CHIP_ID:
+	case BRCM_CC_43570_CHIP_ID:
+	case BRCM_CC_4358_CHIP_ID:
+	case BRCM_CC_4359_CHIP_ID:
+	case BRCM_CC_43602_CHIP_ID:
+	case BRCM_CC_4371_CHIP_ID:
+		return 0x180000;
+	case BRCM_CC_43465_CHIP_ID:
+	case BRCM_CC_43525_CHIP_ID:
+	case BRCM_CC_4365_CHIP_ID:
+	case BRCM_CC_4366_CHIP_ID:
+	case BRCM_CC_43664_CHIP_ID:
+		return 0x200000;
+	case CY_CC_4373_CHIP_ID:
+		return 0x160000;
+	default:
+		brcmf_err("unknown chip: %s\n", ci->pub.name);
+		break;
+	}
+	return 0;
+}
+
+static int brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci)
+{
+	struct brcmf_core_priv *mem_core;
+	struct brcmf_core *mem;
+
+	mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_ARM_CR4);
+	if (mem) {
+		mem_core = container_of(mem, struct brcmf_core_priv, pub);
+		ci->pub.ramsize = brcmf_chip_tcm_ramsize(mem_core);
+		ci->pub.rambase = brcmf_chip_tcm_rambase(ci);
+		if (!ci->pub.rambase) {
+			brcmf_err("RAM base not provided with ARM CR4 core\n");
+			return -EINVAL;
+		}
+	} else {
+		mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_SYS_MEM);
+		if (mem) {
+			mem_core = container_of(mem, struct brcmf_core_priv,
+						pub);
+			ci->pub.ramsize = brcmf_chip_sysmem_ramsize(mem_core);
+			ci->pub.rambase = brcmf_chip_tcm_rambase(ci);
+			if (!ci->pub.rambase) {
+				brcmf_err("RAM base not provided with ARM CA7 core\n");
+				return -EINVAL;
+			}
+		} else {
+			mem = brcmf_chip_get_core(&ci->pub,
+						  BCMA_CORE_INTERNAL_MEM);
+			if (!mem) {
+				brcmf_err("No memory cores found\n");
+				return -ENOMEM;
+			}
+			mem_core = container_of(mem, struct brcmf_core_priv,
+						pub);
+			brcmf_chip_socram_ramsize(mem_core, &ci->pub.ramsize,
+						  &ci->pub.srsize);
+		}
+	}
+	brcmf_dbg(INFO, "RAM: base=0x%x size=%d (0x%x) sr=%d (0x%x)\n",
+		  ci->pub.rambase, ci->pub.ramsize, ci->pub.ramsize,
+		  ci->pub.srsize, ci->pub.srsize);
+
+	if (!ci->pub.ramsize) {
+		brcmf_err("RAM size is undetermined\n");
+		return -ENOMEM;
+	}
+
+	if (ci->pub.ramsize > BRCMF_CHIP_MAX_MEMSIZE) {
+		brcmf_err("RAM size is incorrect\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static u32 brcmf_chip_dmp_get_desc(struct brcmf_chip_priv *ci, u32 *eromaddr,
+				   u8 *type)
+{
+	u32 val;
+
+	/* read next descriptor */
+	val = ci->ops->read32(ci->ctx, *eromaddr);
+	*eromaddr += 4;
+
+	if (!type)
+		return val;
+
+	/* determine descriptor type */
+	*type = (val & DMP_DESC_TYPE_MSK);
+	if ((*type & ~DMP_DESC_ADDRSIZE_GT32) == DMP_DESC_ADDRESS)
+		*type = DMP_DESC_ADDRESS;
+
+	return val;
+}
+
+static int brcmf_chip_dmp_get_regaddr(struct brcmf_chip_priv *ci, u32 *eromaddr,
+				      u32 *regbase, u32 *wrapbase)
+{
+	u8 desc;
+	u32 val;
+	u8 mpnum = 0;
+	u8 stype, sztype, wraptype;
+
+	*regbase = 0;
+	*wrapbase = 0;
+
+	val = brcmf_chip_dmp_get_desc(ci, eromaddr, &desc);
+	if (desc == DMP_DESC_MASTER_PORT) {
+		mpnum = (val & DMP_MASTER_PORT_NUM) >> DMP_MASTER_PORT_NUM_S;
+		wraptype = DMP_SLAVE_TYPE_MWRAP;
+	} else if (desc == DMP_DESC_ADDRESS) {
+		/* revert erom address */
+		*eromaddr -= 4;
+		wraptype = DMP_SLAVE_TYPE_SWRAP;
+	} else {
+		*eromaddr -= 4;
+		return -EILSEQ;
+	}
+
+	do {
+		/* locate address descriptor */
+		do {
+			val = brcmf_chip_dmp_get_desc(ci, eromaddr, &desc);
+			/* unexpected table end */
+			if (desc == DMP_DESC_EOT) {
+				*eromaddr -= 4;
+				return -EFAULT;
+			}
+		} while (desc != DMP_DESC_ADDRESS &&
+			 desc != DMP_DESC_COMPONENT);
+
+		/* stop if we crossed current component border */
+		if (desc == DMP_DESC_COMPONENT) {
+			*eromaddr -= 4;
+			return 0;
+		}
+
+		/* skip upper 32-bit address descriptor */
+		if (val & DMP_DESC_ADDRSIZE_GT32)
+			brcmf_chip_dmp_get_desc(ci, eromaddr, NULL);
+
+		sztype = (val & DMP_SLAVE_SIZE_TYPE) >> DMP_SLAVE_SIZE_TYPE_S;
+
+		/* next size descriptor can be skipped */
+		if (sztype == DMP_SLAVE_SIZE_DESC) {
+			val = brcmf_chip_dmp_get_desc(ci, eromaddr, NULL);
+			/* skip upper size descriptor if present */
+			if (val & DMP_DESC_ADDRSIZE_GT32)
+				brcmf_chip_dmp_get_desc(ci, eromaddr, NULL);
+		}
+
+		/* only look for 4K register regions */
+		if (sztype != DMP_SLAVE_SIZE_4K)
+			continue;
+
+		stype = (val & DMP_SLAVE_TYPE) >> DMP_SLAVE_TYPE_S;
+
+		/* only regular slave and wrapper */
+		if (*regbase == 0 && stype == DMP_SLAVE_TYPE_SLAVE)
+			*regbase = val & DMP_SLAVE_ADDR_BASE;
+		if (*wrapbase == 0 && stype == wraptype)
+			*wrapbase = val & DMP_SLAVE_ADDR_BASE;
+	} while (*regbase == 0 || *wrapbase == 0);
+
+	return 0;
+}
+
+static
+int brcmf_chip_dmp_erom_scan(struct brcmf_chip_priv *ci)
+{
+	struct brcmf_core *core;
+	u32 eromaddr;
+	u8 desc_type = 0;
+	u32 val;
+	u16 id;
+	u8 nmp, nsp, nmw, nsw, rev;
+	u32 base, wrap;
+	int err;
+
+	eromaddr = ci->ops->read32(ci->ctx, CORE_CC_REG(SI_ENUM_BASE, eromptr));
+
+	while (desc_type != DMP_DESC_EOT) {
+		val = brcmf_chip_dmp_get_desc(ci, &eromaddr, &desc_type);
+		if (!(val & DMP_DESC_VALID))
+			continue;
+
+		if (desc_type == DMP_DESC_EMPTY)
+			continue;
+
+		/* need a component descriptor */
+		if (desc_type != DMP_DESC_COMPONENT)
+			continue;
+
+		id = (val & DMP_COMP_PARTNUM) >> DMP_COMP_PARTNUM_S;
+
+		/* next descriptor must be component as well */
+		val = brcmf_chip_dmp_get_desc(ci, &eromaddr, &desc_type);
+		if (WARN_ON((val & DMP_DESC_TYPE_MSK) != DMP_DESC_COMPONENT))
+			return -EFAULT;
+
+		/* only look at cores with master port(s) */
+		nmp = (val & DMP_COMP_NUM_MPORT) >> DMP_COMP_NUM_MPORT_S;
+		nsp = (val & DMP_COMP_NUM_SPORT) >> DMP_COMP_NUM_SPORT_S;
+		nmw = (val & DMP_COMP_NUM_MWRAP) >> DMP_COMP_NUM_MWRAP_S;
+		nsw = (val & DMP_COMP_NUM_SWRAP) >> DMP_COMP_NUM_SWRAP_S;
+		rev = (val & DMP_COMP_REVISION) >> DMP_COMP_REVISION_S;
+
+		/* need core with ports */
+		if (nmw + nsw == 0 &&
+		    id != BCMA_CORE_PMU)
+			continue;
+
+		/* try to obtain register address info */
+		err = brcmf_chip_dmp_get_regaddr(ci, &eromaddr, &base, &wrap);
+		if (err)
+			continue;
+
+		/* finally a core to be added */
+		core = brcmf_chip_add_core(ci, id, base, wrap);
+		if (IS_ERR(core))
+			return PTR_ERR(core);
+
+		core->rev = rev;
+	}
+
+	return 0;
+}
+
+static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)
+{
+	struct brcmf_core *core;
+	u32 regdata;
+	u32 socitype;
+	int ret;
+
+	/* Get CC core rev
+	 * Chipid is assume to be at offset 0 from SI_ENUM_BASE
+	 * For different chiptypes or old sdio hosts w/o chipcommon,
+	 * other ways of recognition should be added here.
+	 */
+	regdata = ci->ops->read32(ci->ctx, CORE_CC_REG(SI_ENUM_BASE, chipid));
+	ci->pub.chip = regdata & CID_ID_MASK;
+	ci->pub.chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
+	socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
+
+	brcmf_chip_name(ci->pub.chip, ci->pub.chiprev,
+			ci->pub.name, sizeof(ci->pub.name));
+	brcmf_dbg(INFO, "found %s chip: %s\n",
+		  socitype == SOCI_SB ? "SB" : "AXI", ci->pub.name);
+
+	if (socitype == SOCI_SB) {
+		if (ci->pub.chip != BRCM_CC_4329_CHIP_ID) {
+			brcmf_err("SB chip is not supported\n");
+			return -ENODEV;
+		}
+		ci->iscoreup = brcmf_chip_sb_iscoreup;
+		ci->coredisable = brcmf_chip_sb_coredisable;
+		ci->resetcore = brcmf_chip_sb_resetcore;
+
+		core = brcmf_chip_add_core(ci, BCMA_CORE_CHIPCOMMON,
+					   SI_ENUM_BASE, 0);
+		brcmf_chip_sb_corerev(ci, core);
+		core = brcmf_chip_add_core(ci, BCMA_CORE_SDIO_DEV,
+					   BCM4329_CORE_BUS_BASE, 0);
+		brcmf_chip_sb_corerev(ci, core);
+		core = brcmf_chip_add_core(ci, BCMA_CORE_INTERNAL_MEM,
+					   BCM4329_CORE_SOCRAM_BASE, 0);
+		brcmf_chip_sb_corerev(ci, core);
+		core = brcmf_chip_add_core(ci, BCMA_CORE_ARM_CM3,
+					   BCM4329_CORE_ARM_BASE, 0);
+		brcmf_chip_sb_corerev(ci, core);
+
+		core = brcmf_chip_add_core(ci, BCMA_CORE_80211, 0x18001000, 0);
+		brcmf_chip_sb_corerev(ci, core);
+	} else if (socitype == SOCI_AI) {
+		ci->iscoreup = brcmf_chip_ai_iscoreup;
+		ci->coredisable = brcmf_chip_ai_coredisable;
+		ci->resetcore = brcmf_chip_ai_resetcore;
+
+		brcmf_chip_dmp_erom_scan(ci);
+	} else {
+		brcmf_err("chip backplane type %u is not supported\n",
+			  socitype);
+		return -ENODEV;
+	}
+
+	ret = brcmf_chip_cores_check(ci);
+	if (ret)
+		return ret;
+
+	/* assure chip is passive for core access */
+	brcmf_chip_set_passive(&ci->pub);
+
+	/* Call bus specific reset function now. Cores have been determined
+	 * but further access may require a chip specific reset at this point.
+	 */
+	if (ci->ops->reset) {
+		ci->ops->reset(ci->ctx, &ci->pub);
+		brcmf_chip_set_passive(&ci->pub);
+	}
+
+	return brcmf_chip_get_raminfo(ci);
+}
+
+static void brcmf_chip_disable_arm(struct brcmf_chip_priv *chip, u16 id)
+{
+	struct brcmf_core *core;
+	struct brcmf_core_priv *cpu;
+	u32 val;
+
+
+	core = brcmf_chip_get_core(&chip->pub, id);
+	if (!core)
+		return;
+
+	switch (id) {
+	case BCMA_CORE_ARM_CM3:
+		brcmf_chip_coredisable(core, 0, 0);
+		break;
+	case BCMA_CORE_ARM_CR4:
+	case BCMA_CORE_ARM_CA7:
+		cpu = container_of(core, struct brcmf_core_priv, pub);
+
+		/* clear all IOCTL bits except HALT bit */
+		val = chip->ops->read32(chip->ctx, cpu->wrapbase + BCMA_IOCTL);
+		val &= ARMCR4_BCMA_IOCTL_CPUHALT;
+		brcmf_chip_resetcore(core, val, ARMCR4_BCMA_IOCTL_CPUHALT,
+				     ARMCR4_BCMA_IOCTL_CPUHALT);
+		break;
+	default:
+		brcmf_err("unknown id: %u\n", id);
+		break;
+	}
+}
+
+static int brcmf_chip_setup(struct brcmf_chip_priv *chip)
+{
+	struct brcmf_chip *pub;
+	struct brcmf_core_priv *cc;
+	struct brcmf_core *pmu;
+	u32 base;
+	u32 val;
+	int ret = 0;
+
+	pub = &chip->pub;
+	cc = list_first_entry(&chip->cores, struct brcmf_core_priv, list);
+	base = cc->pub.base;
+
+	/* get chipcommon capabilites */
+	pub->cc_caps = chip->ops->read32(chip->ctx,
+					 CORE_CC_REG(base, capabilities));
+	pub->cc_caps_ext = chip->ops->read32(chip->ctx,
+					     CORE_CC_REG(base,
+							 capabilities_ext));
+
+	/* get pmu caps & rev */
+	pmu = brcmf_chip_get_pmu(pub); /* after reading cc_caps_ext */
+	if (pub->cc_caps & CC_CAP_PMU) {
+		val = chip->ops->read32(chip->ctx,
+					CORE_CC_REG(pmu->base, pmucapabilities));
+		pub->pmurev = val & PCAP_REV_MASK;
+		pub->pmucaps = val;
+	}
+
+	brcmf_dbg(INFO, "ccrev=%d, pmurev=%d, pmucaps=0x%x\n",
+		  cc->pub.rev, pub->pmurev, pub->pmucaps);
+
+	/* execute bus core specific setup */
+	if (chip->ops->setup)
+		ret = chip->ops->setup(chip->ctx, pub);
+
+	return ret;
+}
+
+struct brcmf_chip *brcmf_chip_attach(void *ctx,
+				     const struct brcmf_buscore_ops *ops)
+{
+	struct brcmf_chip_priv *chip;
+	int err = 0;
+
+	if (WARN_ON(!ops->read32))
+		err = -EINVAL;
+	if (WARN_ON(!ops->write32))
+		err = -EINVAL;
+	if (WARN_ON(!ops->prepare))
+		err = -EINVAL;
+	if (WARN_ON(!ops->activate))
+		err = -EINVAL;
+	if (err < 0)
+		return ERR_PTR(-EINVAL);
+
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+	if (!chip)
+		return ERR_PTR(-ENOMEM);
+
+	INIT_LIST_HEAD(&chip->cores);
+	chip->num_cores = 0;
+	chip->ops = ops;
+	chip->ctx = ctx;
+
+	err = ops->prepare(ctx);
+	if (err < 0)
+		goto fail;
+
+	err = brcmf_chip_recognition(chip);
+	if (err < 0)
+		goto fail;
+
+	err = brcmf_chip_setup(chip);
+	if (err < 0)
+		goto fail;
+
+	return &chip->pub;
+
+fail:
+	brcmf_chip_detach(&chip->pub);
+	return ERR_PTR(err);
+}
+
+void brcmf_chip_detach(struct brcmf_chip *pub)
+{
+	struct brcmf_chip_priv *chip;
+	struct brcmf_core_priv *core;
+	struct brcmf_core_priv *tmp;
+
+	chip = container_of(pub, struct brcmf_chip_priv, pub);
+	list_for_each_entry_safe(core, tmp, &chip->cores, list) {
+		list_del(&core->list);
+		kfree(core);
+	}
+	kfree(chip);
+}
+
+struct brcmf_core *brcmf_chip_get_core(struct brcmf_chip *pub, u16 coreid)
+{
+	struct brcmf_chip_priv *chip;
+	struct brcmf_core_priv *core;
+
+	chip = container_of(pub, struct brcmf_chip_priv, pub);
+	list_for_each_entry(core, &chip->cores, list)
+		if (core->pub.id == coreid)
+			return &core->pub;
+
+	return NULL;
+}
+
+struct brcmf_core *brcmf_chip_get_chipcommon(struct brcmf_chip *pub)
+{
+	struct brcmf_chip_priv *chip;
+	struct brcmf_core_priv *cc;
+
+	chip = container_of(pub, struct brcmf_chip_priv, pub);
+	cc = list_first_entry(&chip->cores, struct brcmf_core_priv, list);
+	if (WARN_ON(!cc || cc->pub.id != BCMA_CORE_CHIPCOMMON))
+		return brcmf_chip_get_core(pub, BCMA_CORE_CHIPCOMMON);
+	return &cc->pub;
+}
+
+struct brcmf_core *brcmf_chip_get_pmu(struct brcmf_chip *pub)
+{
+	struct brcmf_core *cc = brcmf_chip_get_chipcommon(pub);
+	struct brcmf_core *pmu;
+
+	/* See if there is separated PMU core available */
+	if (cc->rev >= 35 &&
+	    pub->cc_caps_ext & BCMA_CC_CAP_EXT_AOB_PRESENT) {
+		pmu = brcmf_chip_get_core(pub, BCMA_CORE_PMU);
+		if (pmu)
+			return pmu;
+	}
+
+	/* Fallback to ChipCommon core for older hardware */
+	return cc;
+}
+
+bool brcmf_chip_iscoreup(struct brcmf_core *pub)
+{
+	struct brcmf_core_priv *core;
+
+	core = container_of(pub, struct brcmf_core_priv, pub);
+	return core->chip->iscoreup(core);
+}
+
+void brcmf_chip_coredisable(struct brcmf_core *pub, u32 prereset, u32 reset)
+{
+	struct brcmf_core_priv *core;
+
+	core = container_of(pub, struct brcmf_core_priv, pub);
+	core->chip->coredisable(core, prereset, reset);
+}
+
+void brcmf_chip_resetcore(struct brcmf_core *pub, u32 prereset, u32 reset,
+			  u32 postreset)
+{
+	struct brcmf_core_priv *core;
+
+	core = container_of(pub, struct brcmf_core_priv, pub);
+	core->chip->resetcore(core, prereset, reset, postreset);
+}
+
+static void
+brcmf_chip_cm3_set_passive(struct brcmf_chip_priv *chip)
+{
+	struct brcmf_core *core;
+	struct brcmf_core_priv *sr;
+
+	brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CM3);
+	core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211);
+	brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET |
+				   D11_BCMA_IOCTL_PHYCLOCKEN,
+			     D11_BCMA_IOCTL_PHYCLOCKEN,
+			     D11_BCMA_IOCTL_PHYCLOCKEN);
+	core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_INTERNAL_MEM);
+	brcmf_chip_resetcore(core, 0, 0, 0);
+
+	/* disable bank #3 remap for this device */
+	if (chip->pub.chip == BRCM_CC_43430_CHIP_ID) {
+		sr = container_of(core, struct brcmf_core_priv, pub);
+		brcmf_chip_core_write32(sr, SOCRAMREGOFFS(bankidx), 3);
+		brcmf_chip_core_write32(sr, SOCRAMREGOFFS(bankpda), 0);
+	}
+}
+
+static bool brcmf_chip_cm3_set_active(struct brcmf_chip_priv *chip)
+{
+	struct brcmf_core *core;
+
+	core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_INTERNAL_MEM);
+	if (!brcmf_chip_iscoreup(core)) {
+		brcmf_err("SOCRAM core is down after reset?\n");
+		return false;
+	}
+
+	chip->ops->activate(chip->ctx, &chip->pub, 0);
+
+	core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CM3);
+	brcmf_chip_resetcore(core, 0, 0, 0);
+
+	return true;
+}
+
+static inline void
+brcmf_chip_cr4_set_passive(struct brcmf_chip_priv *chip)
+{
+	struct brcmf_core *core;
+
+	brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CR4);
+
+	core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211);
+	brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET |
+				   D11_BCMA_IOCTL_PHYCLOCKEN,
+			     D11_BCMA_IOCTL_PHYCLOCKEN,
+			     D11_BCMA_IOCTL_PHYCLOCKEN);
+}
+
+static bool brcmf_chip_cr4_set_active(struct brcmf_chip_priv *chip, u32 rstvec)
+{
+	struct brcmf_core *core;
+
+	chip->ops->activate(chip->ctx, &chip->pub, rstvec);
+
+	/* restore ARM */
+	core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CR4);
+	brcmf_chip_resetcore(core, ARMCR4_BCMA_IOCTL_CPUHALT, 0, 0);
+
+	return true;
+}
+
+static inline void
+brcmf_chip_ca7_set_passive(struct brcmf_chip_priv *chip)
+{
+	struct brcmf_core *core;
+
+	brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CA7);
+
+	core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211);
+	brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET |
+				   D11_BCMA_IOCTL_PHYCLOCKEN,
+			     D11_BCMA_IOCTL_PHYCLOCKEN,
+			     D11_BCMA_IOCTL_PHYCLOCKEN);
+}
+
+static bool brcmf_chip_ca7_set_active(struct brcmf_chip_priv *chip, u32 rstvec)
+{
+	struct brcmf_core *core;
+
+	chip->ops->activate(chip->ctx, &chip->pub, rstvec);
+
+	/* restore ARM */
+	core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CA7);
+	brcmf_chip_resetcore(core, ARMCR4_BCMA_IOCTL_CPUHALT, 0, 0);
+
+	return true;
+}
+
+void brcmf_chip_set_passive(struct brcmf_chip *pub)
+{
+	struct brcmf_chip_priv *chip;
+	struct brcmf_core *arm;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	chip = container_of(pub, struct brcmf_chip_priv, pub);
+	arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4);
+	if (arm) {
+		brcmf_chip_cr4_set_passive(chip);
+		return;
+	}
+	arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CA7);
+	if (arm) {
+		brcmf_chip_ca7_set_passive(chip);
+		return;
+	}
+	arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CM3);
+	if (arm) {
+		brcmf_chip_cm3_set_passive(chip);
+		return;
+	}
+}
+
+bool brcmf_chip_set_active(struct brcmf_chip *pub, u32 rstvec)
+{
+	struct brcmf_chip_priv *chip;
+	struct brcmf_core *arm;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	chip = container_of(pub, struct brcmf_chip_priv, pub);
+	arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4);
+	if (arm)
+		return brcmf_chip_cr4_set_active(chip, rstvec);
+	arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CA7);
+	if (arm)
+		return brcmf_chip_ca7_set_active(chip, rstvec);
+	arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CM3);
+	if (arm)
+		return brcmf_chip_cm3_set_active(chip);
+
+	return false;
+}
+
+bool brcmf_chip_sr_capable(struct brcmf_chip *pub)
+{
+	u32 base, addr, reg, pmu_cc3_mask = ~0;
+	struct brcmf_chip_priv *chip;
+	struct brcmf_core *pmu = brcmf_chip_get_pmu(pub);
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	/* old chips with PMU version less than 17 don't support save restore */
+	if (pub->pmurev < 17)
+		return false;
+
+	base = brcmf_chip_get_chipcommon(pub)->base;
+	chip = container_of(pub, struct brcmf_chip_priv, pub);
+
+	switch (pub->chip) {
+	case BRCM_CC_4354_CHIP_ID:
+	case BRCM_CC_4356_CHIP_ID:
+	case BRCM_CC_4345_CHIP_ID:
+		/* explicitly check SR engine enable bit */
+		pmu_cc3_mask = BIT(2);
+		/* fall-through */
+	case BRCM_CC_43241_CHIP_ID:
+	case BRCM_CC_4335_CHIP_ID:
+	case BRCM_CC_4339_CHIP_ID:
+		/* read PMU chipcontrol register 3 */
+		addr = CORE_CC_REG(pmu->base, chipcontrol_addr);
+		chip->ops->write32(chip->ctx, addr, 3);
+		addr = CORE_CC_REG(pmu->base, chipcontrol_data);
+		reg = chip->ops->read32(chip->ctx, addr);
+		return (reg & pmu_cc3_mask) != 0;
+	case BRCM_CC_43430_CHIP_ID:
+		addr = CORE_CC_REG(base, sr_control1);
+		reg = chip->ops->read32(chip->ctx, addr);
+		return reg != 0;
+	default:
+		addr = CORE_CC_REG(pmu->base, pmucapabilities_ext);
+		reg = chip->ops->read32(chip->ctx, addr);
+		if ((reg & PCAPEXT_SR_SUPPORTED_MASK) == 0)
+			return false;
+
+		addr = CORE_CC_REG(pmu->base, retention_ctl);
+		reg = chip->ops->read32(chip->ctx, addr);
+		return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK |
+			       PMU_RCTL_LOGIC_DISABLE_MASK)) == 0;
+	}
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
new file mode 100644
index 0000000..0ae3b33
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef BRCMF_CHIP_H
+#define BRCMF_CHIP_H
+
+#include <linux/types.h>
+
+#define CORE_CC_REG(base, field) \
+		(base + offsetof(struct chipcregs, field))
+
+/**
+ * struct brcmf_chip - chip level information.
+ *
+ * @chip: chip identifier.
+ * @chiprev: chip revision.
+ * @cc_caps: chipcommon core capabilities.
+ * @cc_caps_ext: chipcommon core extended capabilities.
+ * @pmucaps: PMU capabilities.
+ * @pmurev: PMU revision.
+ * @rambase: RAM base address (only applicable for ARM CR4 chips).
+ * @ramsize: amount of RAM on chip including retention.
+ * @srsize: amount of retention RAM on chip.
+ * @name: string representation of the chip identifier.
+ */
+struct brcmf_chip {
+	u32 chip;
+	u32 chiprev;
+	u32 cc_caps;
+	u32 cc_caps_ext;
+	u32 pmucaps;
+	u32 pmurev;
+	u32 rambase;
+	u32 ramsize;
+	u32 srsize;
+	char name[12];
+};
+
+/**
+ * struct brcmf_core - core related information.
+ *
+ * @id: core identifier.
+ * @rev: core revision.
+ * @base: base address of core register space.
+ */
+struct brcmf_core {
+	u16 id;
+	u16 rev;
+	u32 base;
+};
+
+/**
+ * struct brcmf_buscore_ops - buscore specific callbacks.
+ *
+ * @read32: read 32-bit value over bus.
+ * @write32: write 32-bit value over bus.
+ * @prepare: prepare bus for core configuration.
+ * @setup: bus-specific core setup.
+ * @active: chip becomes active.
+ *	The callback should use the provided @rstvec when non-zero.
+ */
+struct brcmf_buscore_ops {
+	u32 (*read32)(void *ctx, u32 addr);
+	void (*write32)(void *ctx, u32 addr, u32 value);
+	int (*prepare)(void *ctx);
+	int (*reset)(void *ctx, struct brcmf_chip *chip);
+	int (*setup)(void *ctx, struct brcmf_chip *chip);
+	void (*activate)(void *ctx, struct brcmf_chip *chip, u32 rstvec);
+};
+
+struct brcmf_chip *brcmf_chip_attach(void *ctx,
+				     const struct brcmf_buscore_ops *ops);
+void brcmf_chip_detach(struct brcmf_chip *chip);
+struct brcmf_core *brcmf_chip_get_core(struct brcmf_chip *chip, u16 coreid);
+struct brcmf_core *brcmf_chip_get_chipcommon(struct brcmf_chip *chip);
+struct brcmf_core *brcmf_chip_get_pmu(struct brcmf_chip *pub);
+bool brcmf_chip_iscoreup(struct brcmf_core *core);
+void brcmf_chip_coredisable(struct brcmf_core *core, u32 prereset, u32 reset);
+void brcmf_chip_resetcore(struct brcmf_core *core, u32 prereset, u32 reset,
+			  u32 postreset);
+void brcmf_chip_set_passive(struct brcmf_chip *ci);
+bool brcmf_chip_set_active(struct brcmf_chip *ci, u32 rstvec);
+bool brcmf_chip_sr_capable(struct brcmf_chip *pub);
+char *brcmf_chip_name(u32 chipid, u32 chiprev, char *buf, uint len);
+
+#endif /* BRCMF_AXIDMP_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
new file mode 100644
index 0000000..cd36510
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
@@ -0,0 +1,524 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/netdevice.h>
+#include <linux/module.h>
+#include <linux/firmware.h>
+#include <brcmu_wifi.h>
+#include <brcmu_utils.h>
+#include "core.h"
+#include "bus.h"
+#include "debug.h"
+#include "fwil.h"
+#include "fwil_types.h"
+#include "tracepoint.h"
+#include "common.h"
+#include "of.h"
+#include "firmware.h"
+#include "chip.h"
+
+MODULE_AUTHOR("Broadcom Corporation");
+MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
+MODULE_LICENSE("Dual BSD/GPL");
+
+#define BRCMF_DEFAULT_SCAN_CHANNEL_TIME	40
+#define BRCMF_DEFAULT_SCAN_UNASSOC_TIME	40
+
+/* default boost value for RSSI_DELTA in preferred join selection */
+#define BRCMF_JOIN_PREF_RSSI_BOOST	8
+
+#define BRCMF_DEFAULT_TXGLOM_SIZE	32  /* max tx frames in glom chain */
+
+static int brcmf_sdiod_txglomsz = BRCMF_DEFAULT_TXGLOM_SIZE;
+module_param_named(txglomsz, brcmf_sdiod_txglomsz, int, 0);
+MODULE_PARM_DESC(txglomsz, "Maximum tx packet chain size [SDIO]");
+
+/* Debug level configuration. See debug.h for bits, sysfs modifiable */
+int brcmf_msg_level;
+module_param_named(debug, brcmf_msg_level, int, 0600);
+MODULE_PARM_DESC(debug, "Level of debug output");
+
+static int brcmf_p2p_enable;
+module_param_named(p2pon, brcmf_p2p_enable, int, 0);
+MODULE_PARM_DESC(p2pon, "Enable legacy p2p management functionality");
+
+static int brcmf_feature_disable;
+module_param_named(feature_disable, brcmf_feature_disable, int, 0);
+MODULE_PARM_DESC(feature_disable, "Disable features");
+
+static char brcmf_firmware_path[BRCMF_FW_ALTPATH_LEN];
+module_param_string(alternative_fw_path, brcmf_firmware_path,
+		    BRCMF_FW_ALTPATH_LEN, 0400);
+MODULE_PARM_DESC(alternative_fw_path, "Alternative firmware path");
+
+static int brcmf_fcmode;
+module_param_named(fcmode, brcmf_fcmode, int, 0);
+MODULE_PARM_DESC(fcmode, "Mode of firmware signalled flow control");
+
+static int brcmf_roamoff;
+module_param_named(roamoff, brcmf_roamoff, int, 0400);
+MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine");
+
+static int brcmf_iapp_enable;
+module_param_named(iapp, brcmf_iapp_enable, int, 0);
+MODULE_PARM_DESC(iapp, "Enable partial support for the obsoleted Inter-Access Point Protocol");
+
+#ifdef DEBUG
+/* always succeed brcmf_bus_started() */
+static int brcmf_ignore_probe_fail;
+module_param_named(ignore_probe_fail, brcmf_ignore_probe_fail, int, 0);
+MODULE_PARM_DESC(ignore_probe_fail, "always succeed probe for debugging");
+#endif
+
+static struct brcmfmac_platform_data *brcmfmac_pdata;
+struct brcmf_mp_global_t brcmf_mp_global;
+
+void brcmf_c_set_joinpref_default(struct brcmf_if *ifp)
+{
+	struct brcmf_join_pref_params join_pref_params[2];
+	int err;
+
+	/* Setup join_pref to select target by RSSI (boost on 5GHz) */
+	join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA;
+	join_pref_params[0].len = 2;
+	join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST;
+	join_pref_params[0].band = WLC_BAND_5G;
+
+	join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI;
+	join_pref_params[1].len = 2;
+	join_pref_params[1].rssi_gain = 0;
+	join_pref_params[1].band = 0;
+	err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params,
+				       sizeof(join_pref_params));
+	if (err)
+		brcmf_err("Set join_pref error (%d)\n", err);
+}
+
+static int brcmf_c_download(struct brcmf_if *ifp, u16 flag,
+			    struct brcmf_dload_data_le *dload_buf,
+			    u32 len)
+{
+	s32 err;
+
+	flag |= (DLOAD_HANDLER_VER << DLOAD_FLAG_VER_SHIFT);
+	dload_buf->flag = cpu_to_le16(flag);
+	dload_buf->dload_type = cpu_to_le16(DL_TYPE_CLM);
+	dload_buf->len = cpu_to_le32(len);
+	dload_buf->crc = cpu_to_le32(0);
+	len = sizeof(*dload_buf) + len - 1;
+
+	err = brcmf_fil_iovar_data_set(ifp, "clmload", dload_buf, len);
+
+	return err;
+}
+
+static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
+{
+	struct brcmf_bus *bus = ifp->drvr->bus_if;
+	struct brcmf_dload_data_le *chunk_buf;
+	const struct firmware *clm = NULL;
+	u8 clm_name[BRCMF_FW_NAME_LEN];
+	u32 chunk_len;
+	u32 datalen;
+	u32 cumulative_len;
+	u16 dl_flag = DL_BEGIN;
+	u32 status;
+	s32 err;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	memset(clm_name, 0, sizeof(clm_name));
+	err = brcmf_bus_get_fwname(bus, ".clm_blob", clm_name);
+	if (err) {
+		brcmf_err("get CLM blob file name failed (%d)\n", err);
+		return err;
+	}
+
+	err = request_firmware(&clm, clm_name, bus->dev);
+	if (err) {
+		brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n",
+			   err);
+		return 0;
+	}
+
+	chunk_buf = kzalloc(sizeof(*chunk_buf) + MAX_CHUNK_LEN - 1, GFP_KERNEL);
+	if (!chunk_buf) {
+		err = -ENOMEM;
+		goto done;
+	}
+
+	datalen = clm->size;
+	cumulative_len = 0;
+	do {
+		if (datalen > MAX_CHUNK_LEN) {
+			chunk_len = MAX_CHUNK_LEN;
+		} else {
+			chunk_len = datalen;
+			dl_flag |= DL_END;
+		}
+		memcpy(chunk_buf->data, clm->data + cumulative_len, chunk_len);
+
+		err = brcmf_c_download(ifp, dl_flag, chunk_buf, chunk_len);
+
+		dl_flag &= ~DL_BEGIN;
+
+		cumulative_len += chunk_len;
+		datalen -= chunk_len;
+	} while ((datalen > 0) && (err == 0));
+
+	if (err) {
+		brcmf_err("clmload (%zu byte file) failed (%d); ",
+			  clm->size, err);
+		/* Retrieve clmload_status and print */
+		err = brcmf_fil_iovar_int_get(ifp, "clmload_status", &status);
+		if (err)
+			brcmf_err("get clmload_status failed (%d)\n", err);
+		else
+			brcmf_dbg(INFO, "clmload_status=%d\n", status);
+		err = -EIO;
+	}
+
+	kfree(chunk_buf);
+done:
+	release_firmware(clm);
+	return err;
+}
+
+int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
+{
+	s8 eventmask[BRCMF_EVENTING_MASK_LEN];
+	u8 buf[BRCMF_DCMD_SMLEN];
+	struct brcmf_bus *bus;
+	struct brcmf_rev_info_le revinfo;
+	struct brcmf_rev_info *ri;
+	char *clmver;
+	char *ptr;
+	s32 err;
+
+	/* retreive mac address */
+	err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
+				       sizeof(ifp->mac_addr));
+	if (err < 0) {
+		brcmf_err("Retreiving cur_etheraddr failed, %d\n", err);
+		goto done;
+	}
+	memcpy(ifp->drvr->wiphy->perm_addr, ifp->drvr->mac, ETH_ALEN);
+	memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac));
+
+	bus = ifp->drvr->bus_if;
+	ri = &ifp->drvr->revinfo;
+
+	err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_REVINFO,
+				     &revinfo, sizeof(revinfo));
+	if (err < 0) {
+		brcmf_err("retrieving revision info failed, %d\n", err);
+		strlcpy(ri->chipname, "UNKNOWN", sizeof(ri->chipname));
+	} else {
+		ri->vendorid = le32_to_cpu(revinfo.vendorid);
+		ri->deviceid = le32_to_cpu(revinfo.deviceid);
+		ri->radiorev = le32_to_cpu(revinfo.radiorev);
+		ri->corerev = le32_to_cpu(revinfo.corerev);
+		ri->boardid = le32_to_cpu(revinfo.boardid);
+		ri->boardvendor = le32_to_cpu(revinfo.boardvendor);
+		ri->boardrev = le32_to_cpu(revinfo.boardrev);
+		ri->driverrev = le32_to_cpu(revinfo.driverrev);
+		ri->ucoderev = le32_to_cpu(revinfo.ucoderev);
+		ri->bus = le32_to_cpu(revinfo.bus);
+		ri->phytype = le32_to_cpu(revinfo.phytype);
+		ri->phyrev = le32_to_cpu(revinfo.phyrev);
+		ri->anarev = le32_to_cpu(revinfo.anarev);
+		ri->chippkg = le32_to_cpu(revinfo.chippkg);
+		ri->nvramrev = le32_to_cpu(revinfo.nvramrev);
+
+		/* use revinfo if not known yet */
+		if (!bus->chip) {
+			bus->chip = le32_to_cpu(revinfo.chipnum);
+			bus->chiprev = le32_to_cpu(revinfo.chiprev);
+		}
+	}
+	ri->result = err;
+
+	if (bus->chip)
+		brcmf_chip_name(bus->chip, bus->chiprev,
+				ri->chipname, sizeof(ri->chipname));
+
+	/* Do any CLM downloading */
+	err = brcmf_c_process_clm_blob(ifp);
+	if (err < 0) {
+		brcmf_err("download CLM blob file failed, %d\n", err);
+		goto done;
+	}
+
+	/* query for 'ver' to get version info from firmware */
+	memset(buf, 0, sizeof(buf));
+	strcpy(buf, "ver");
+	err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf));
+	if (err < 0) {
+		brcmf_err("Retreiving version information failed, %d\n",
+			  err);
+		goto done;
+	}
+	ptr = (char *)buf;
+	strsep(&ptr, "\n");
+
+	/* Print fw version info */
+	brcmf_info("Firmware: %s %s\n", ri->chipname, buf);
+
+	/* locate firmware version number for ethtool */
+	ptr = strrchr(buf, ' ') + 1;
+	strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver));
+
+	/* Query for 'clmver' to get CLM version info from firmware */
+	memset(buf, 0, sizeof(buf));
+	err = brcmf_fil_iovar_data_get(ifp, "clmver", buf, sizeof(buf));
+	if (err) {
+		brcmf_dbg(TRACE, "retrieving clmver failed, %d\n", err);
+	} else {
+		clmver = (char *)buf;
+		/* store CLM version for adding it to revinfo debugfs file */
+		memcpy(ifp->drvr->clmver, clmver, sizeof(ifp->drvr->clmver));
+
+		/* Replace all newline/linefeed characters with space
+		 * character
+		 */
+		ptr = clmver;
+		while ((ptr = strnchr(ptr, '\n', sizeof(buf))) != NULL)
+			*ptr = ' ';
+
+		brcmf_dbg(INFO, "CLM version = %s\n", clmver);
+	}
+
+	/* set mpc */
+	err = brcmf_fil_iovar_int_set(ifp, "mpc", 1);
+	if (err) {
+		brcmf_err("failed setting mpc\n");
+		goto done;
+	}
+
+	brcmf_c_set_joinpref_default(ifp);
+
+	/* Setup event_msgs, enable E_IF */
+	err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask,
+				       BRCMF_EVENTING_MASK_LEN);
+	if (err) {
+		brcmf_err("Get event_msgs error (%d)\n", err);
+		goto done;
+	}
+	setbit(eventmask, BRCMF_E_IF);
+	err = brcmf_fil_iovar_data_set(ifp, "event_msgs", eventmask,
+				       BRCMF_EVENTING_MASK_LEN);
+	if (err) {
+		brcmf_err("Set event_msgs error (%d)\n", err);
+		goto done;
+	}
+
+	/* Setup default scan channel time */
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,
+				    BRCMF_DEFAULT_SCAN_CHANNEL_TIME);
+	if (err) {
+		brcmf_err("BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n",
+			  err);
+		goto done;
+	}
+
+	/* Setup default scan unassoc time */
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME,
+				    BRCMF_DEFAULT_SCAN_UNASSOC_TIME);
+	if (err) {
+		brcmf_err("BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n",
+			  err);
+		goto done;
+	}
+
+	/* Enable tx beamforming, errors can be ignored (not supported) */
+	(void)brcmf_fil_iovar_int_set(ifp, "txbf", 1);
+done:
+	return err;
+}
+
+#ifndef CONFIG_BRCM_TRACING
+void __brcmf_err(const char *func, const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+	pr_err("%s: %pV", func, &vaf);
+
+	va_end(args);
+}
+#endif
+
+#if defined(CONFIG_BRCM_TRACING) || defined(CONFIG_BRCMDBG)
+void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...)
+{
+	struct va_format vaf = {
+		.fmt = fmt,
+	};
+	va_list args;
+
+	va_start(args, fmt);
+	vaf.va = &args;
+	if (brcmf_msg_level & level)
+		pr_debug("%s %pV", func, &vaf);
+	trace_brcmf_dbg(level, func, &vaf);
+	va_end(args);
+}
+#endif
+
+static void brcmf_mp_attach(void)
+{
+	/* If module param firmware path is set then this will always be used,
+	 * if not set then if available use the platform data version. To make
+	 * sure it gets initialized at all, always copy the module param version
+	 */
+	strlcpy(brcmf_mp_global.firmware_path, brcmf_firmware_path,
+		BRCMF_FW_ALTPATH_LEN);
+	if ((brcmfmac_pdata) && (brcmfmac_pdata->fw_alternative_path) &&
+	    (brcmf_mp_global.firmware_path[0] == '\0')) {
+		strlcpy(brcmf_mp_global.firmware_path,
+			brcmfmac_pdata->fw_alternative_path,
+			BRCMF_FW_ALTPATH_LEN);
+	}
+}
+
+struct brcmf_mp_device *brcmf_get_module_param(struct device *dev,
+					       enum brcmf_bus_type bus_type,
+					       u32 chip, u32 chiprev)
+{
+	struct brcmf_mp_device *settings;
+	struct brcmfmac_pd_device *device_pd;
+	bool found;
+	int i;
+
+	brcmf_dbg(INFO, "Enter, bus=%d, chip=%d, rev=%d\n", bus_type, chip,
+		  chiprev);
+	settings = kzalloc(sizeof(*settings), GFP_ATOMIC);
+	if (!settings)
+		return NULL;
+
+	/* start by using the module paramaters */
+	settings->p2p_enable = !!brcmf_p2p_enable;
+	settings->feature_disable = brcmf_feature_disable;
+	settings->fcmode = brcmf_fcmode;
+	settings->roamoff = !!brcmf_roamoff;
+	settings->iapp = !!brcmf_iapp_enable;
+#ifdef DEBUG
+	settings->ignore_probe_fail = !!brcmf_ignore_probe_fail;
+#endif
+
+	if (bus_type == BRCMF_BUSTYPE_SDIO)
+		settings->bus.sdio.txglomsz = brcmf_sdiod_txglomsz;
+
+	/* See if there is any device specific platform data configured */
+	found = false;
+	if (brcmfmac_pdata) {
+		for (i = 0; i < brcmfmac_pdata->device_count; i++) {
+			device_pd = &brcmfmac_pdata->devices[i];
+			if ((device_pd->bus_type == bus_type) &&
+			    (device_pd->id == chip) &&
+			    ((device_pd->rev == chiprev) ||
+			     (device_pd->rev == -1))) {
+				brcmf_dbg(INFO, "Platform data for device found\n");
+				settings->country_codes =
+						device_pd->country_codes;
+				if (device_pd->bus_type == BRCMF_BUSTYPE_SDIO)
+					memcpy(&settings->bus.sdio,
+					       &device_pd->bus.sdio,
+					       sizeof(settings->bus.sdio));
+				found = true;
+				break;
+			}
+		}
+	}
+	if (!found) {
+		/* No platform data for this device, try OF (Open Firwmare) */
+		brcmf_of_probe(dev, bus_type, settings);
+	}
+	return settings;
+}
+
+void brcmf_release_module_param(struct brcmf_mp_device *module_param)
+{
+	kfree(module_param);
+}
+
+static int __init brcmf_common_pd_probe(struct platform_device *pdev)
+{
+	brcmf_dbg(INFO, "Enter\n");
+
+	brcmfmac_pdata = dev_get_platdata(&pdev->dev);
+
+	if (brcmfmac_pdata->power_on)
+		brcmfmac_pdata->power_on();
+
+	return 0;
+}
+
+static int brcmf_common_pd_remove(struct platform_device *pdev)
+{
+	brcmf_dbg(INFO, "Enter\n");
+
+	if (brcmfmac_pdata->power_off)
+		brcmfmac_pdata->power_off();
+
+	return 0;
+}
+
+static struct platform_driver brcmf_pd = {
+	.remove		= brcmf_common_pd_remove,
+	.driver		= {
+		.name	= BRCMFMAC_PDATA_NAME,
+	}
+};
+
+static int __init brcmfmac_module_init(void)
+{
+	int err;
+
+	/* Get the platform data (if available) for our devices */
+	err = platform_driver_probe(&brcmf_pd, brcmf_common_pd_probe);
+	if (err == -ENODEV)
+		brcmf_dbg(INFO, "No platform data available.\n");
+
+	/* Initialize global module paramaters */
+	brcmf_mp_attach();
+
+	/* Continue the initialization by registering the different busses */
+	err = brcmf_core_init();
+	if (err) {
+		if (brcmfmac_pdata)
+			platform_driver_unregister(&brcmf_pd);
+	}
+
+	return err;
+}
+
+static void __exit brcmfmac_module_exit(void)
+{
+	brcmf_core_exit();
+	if (brcmfmac_pdata)
+		platform_driver_unregister(&brcmf_pd);
+}
+
+module_init(brcmfmac_module_init);
+module_exit(brcmfmac_module_exit);
+
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
new file mode 100644
index 0000000..a34642c
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
@@ -0,0 +1,77 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef BRCMFMAC_COMMON_H
+#define BRCMFMAC_COMMON_H
+
+#include <linux/platform_device.h>
+#include <linux/platform_data/brcmfmac.h>
+#include "fwil_types.h"
+
+#define BRCMF_FW_ALTPATH_LEN			256
+
+/* Definitions for the module global and device specific settings are defined
+ * here. Two structs are used for them. brcmf_mp_global_t and brcmf_mp_device.
+ * The mp_global is instantiated once in a global struct and gets initialized
+ * by the common_attach function which should be called before any other
+ * (module) initiliazation takes place. The device specific settings is part
+ * of the drvr struct and should be initialized on every brcmf_attach.
+ */
+
+/**
+ * struct brcmf_mp_global_t - Global module paramaters.
+ *
+ * @firmware_path: Alternative firmware path.
+ */
+struct brcmf_mp_global_t {
+	char	firmware_path[BRCMF_FW_ALTPATH_LEN];
+};
+
+extern struct brcmf_mp_global_t brcmf_mp_global;
+
+/**
+ * struct brcmf_mp_device - Device module paramaters.
+ *
+ * @p2p_enable: Legacy P2P0 enable (old wpa_supplicant).
+ * @feature_disable: Feature_disable bitmask.
+ * @fcmode: FWS flow control.
+ * @roamoff: Firmware roaming off?
+ * @ignore_probe_fail: Ignore probe failure.
+ * @country_codes: If available, pointer to struct for translating country codes
+ * @bus: Bus specific platform data. Only SDIO at the mmoment.
+ */
+struct brcmf_mp_device {
+	bool		p2p_enable;
+	unsigned int	feature_disable;
+	int		fcmode;
+	bool		roamoff;
+	bool		iapp;
+	bool		ignore_probe_fail;
+	struct brcmfmac_pd_cc *country_codes;
+	union {
+		struct brcmfmac_sdio_pd sdio;
+	} bus;
+};
+
+void brcmf_c_set_joinpref_default(struct brcmf_if *ifp);
+
+struct brcmf_mp_device *brcmf_get_module_param(struct device *dev,
+					       enum brcmf_bus_type bus_type,
+					       u32 chip, u32 chiprev);
+void brcmf_release_module_param(struct brcmf_mp_device *module_param);
+
+/* Sets dongle media info (drv_version, mac address). */
+int brcmf_c_preinit_dcmds(struct brcmf_if *ifp);
+
+#endif /* BRCMFMAC_COMMON_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/commonring.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/commonring.c
new file mode 100644
index 0000000..7b0e521
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/commonring.c
@@ -0,0 +1,252 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+
+#include "core.h"
+#include "commonring.h"
+
+void brcmf_commonring_register_cb(struct brcmf_commonring *commonring,
+				  int (*cr_ring_bell)(void *ctx),
+				  int (*cr_update_rptr)(void *ctx),
+				  int (*cr_update_wptr)(void *ctx),
+				  int (*cr_write_rptr)(void *ctx),
+				  int (*cr_write_wptr)(void *ctx), void *ctx)
+{
+	commonring->cr_ring_bell = cr_ring_bell;
+	commonring->cr_update_rptr = cr_update_rptr;
+	commonring->cr_update_wptr = cr_update_wptr;
+	commonring->cr_write_rptr = cr_write_rptr;
+	commonring->cr_write_wptr = cr_write_wptr;
+	commonring->cr_ctx = ctx;
+}
+
+
+void brcmf_commonring_config(struct brcmf_commonring *commonring, u16 depth,
+			     u16 item_len, void *buf_addr)
+{
+	commonring->depth = depth;
+	commonring->item_len = item_len;
+	commonring->buf_addr = buf_addr;
+	if (!commonring->inited) {
+		spin_lock_init(&commonring->lock);
+		commonring->inited = true;
+	}
+	commonring->r_ptr = 0;
+	if (commonring->cr_write_rptr)
+		commonring->cr_write_rptr(commonring->cr_ctx);
+	commonring->w_ptr = 0;
+	if (commonring->cr_write_wptr)
+		commonring->cr_write_wptr(commonring->cr_ctx);
+	commonring->f_ptr = 0;
+}
+
+
+void brcmf_commonring_lock(struct brcmf_commonring *commonring)
+		__acquires(&commonring->lock)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&commonring->lock, flags);
+	commonring->flags = flags;
+}
+
+
+void brcmf_commonring_unlock(struct brcmf_commonring *commonring)
+		__releases(&commonring->lock)
+{
+	spin_unlock_irqrestore(&commonring->lock, commonring->flags);
+}
+
+
+bool brcmf_commonring_write_available(struct brcmf_commonring *commonring)
+{
+	u16 available;
+	bool retry = true;
+
+again:
+	if (commonring->r_ptr <= commonring->w_ptr)
+		available = commonring->depth - commonring->w_ptr +
+			    commonring->r_ptr;
+	else
+		available = commonring->r_ptr - commonring->w_ptr;
+
+	if (available > 1) {
+		if (!commonring->was_full)
+			return true;
+		if (available > commonring->depth / 8) {
+			commonring->was_full = false;
+			return true;
+		}
+		if (retry) {
+			if (commonring->cr_update_rptr)
+				commonring->cr_update_rptr(commonring->cr_ctx);
+			retry = false;
+			goto again;
+		}
+		return false;
+	}
+
+	if (retry) {
+		if (commonring->cr_update_rptr)
+			commonring->cr_update_rptr(commonring->cr_ctx);
+		retry = false;
+		goto again;
+	}
+
+	commonring->was_full = true;
+	return false;
+}
+
+
+void *brcmf_commonring_reserve_for_write(struct brcmf_commonring *commonring)
+{
+	void *ret_ptr;
+	u16 available;
+	bool retry = true;
+
+again:
+	if (commonring->r_ptr <= commonring->w_ptr)
+		available = commonring->depth - commonring->w_ptr +
+			    commonring->r_ptr;
+	else
+		available = commonring->r_ptr - commonring->w_ptr;
+
+	if (available > 1) {
+		ret_ptr = commonring->buf_addr +
+			  (commonring->w_ptr * commonring->item_len);
+		commonring->w_ptr++;
+		if (commonring->w_ptr == commonring->depth)
+			commonring->w_ptr = 0;
+		return ret_ptr;
+	}
+
+	if (retry) {
+		if (commonring->cr_update_rptr)
+			commonring->cr_update_rptr(commonring->cr_ctx);
+		retry = false;
+		goto again;
+	}
+
+	commonring->was_full = true;
+	return NULL;
+}
+
+
+void *
+brcmf_commonring_reserve_for_write_multiple(struct brcmf_commonring *commonring,
+					    u16 n_items, u16 *alloced)
+{
+	void *ret_ptr;
+	u16 available;
+	bool retry = true;
+
+again:
+	if (commonring->r_ptr <= commonring->w_ptr)
+		available = commonring->depth - commonring->w_ptr +
+			    commonring->r_ptr;
+	else
+		available = commonring->r_ptr - commonring->w_ptr;
+
+	if (available > 1) {
+		ret_ptr = commonring->buf_addr +
+			  (commonring->w_ptr * commonring->item_len);
+		*alloced = min_t(u16, n_items, available - 1);
+		if (*alloced + commonring->w_ptr > commonring->depth)
+			*alloced = commonring->depth - commonring->w_ptr;
+		commonring->w_ptr += *alloced;
+		if (commonring->w_ptr == commonring->depth)
+			commonring->w_ptr = 0;
+		return ret_ptr;
+	}
+
+	if (retry) {
+		if (commonring->cr_update_rptr)
+			commonring->cr_update_rptr(commonring->cr_ctx);
+		retry = false;
+		goto again;
+	}
+
+	commonring->was_full = true;
+	return NULL;
+}
+
+
+int brcmf_commonring_write_complete(struct brcmf_commonring *commonring)
+{
+	void *address;
+
+	address = commonring->buf_addr;
+	address += (commonring->f_ptr * commonring->item_len);
+	if (commonring->f_ptr > commonring->w_ptr) {
+		address = commonring->buf_addr;
+		commonring->f_ptr = 0;
+	}
+
+	commonring->f_ptr = commonring->w_ptr;
+
+	if (commonring->cr_write_wptr)
+		commonring->cr_write_wptr(commonring->cr_ctx);
+	if (commonring->cr_ring_bell)
+		return commonring->cr_ring_bell(commonring->cr_ctx);
+
+	return -EIO;
+}
+
+
+void brcmf_commonring_write_cancel(struct brcmf_commonring *commonring,
+				   u16 n_items)
+{
+	if (commonring->w_ptr == 0)
+		commonring->w_ptr = commonring->depth - n_items;
+	else
+		commonring->w_ptr -= n_items;
+}
+
+
+void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
+				    u16 *n_items)
+{
+	if (commonring->cr_update_wptr)
+		commonring->cr_update_wptr(commonring->cr_ctx);
+
+	*n_items = (commonring->w_ptr >= commonring->r_ptr) ?
+				(commonring->w_ptr - commonring->r_ptr) :
+				(commonring->depth - commonring->r_ptr);
+
+	if (*n_items == 0)
+		return NULL;
+
+	return commonring->buf_addr +
+	       (commonring->r_ptr * commonring->item_len);
+}
+
+
+int brcmf_commonring_read_complete(struct brcmf_commonring *commonring,
+				   u16 n_items)
+{
+	commonring->r_ptr += n_items;
+	if (commonring->r_ptr == commonring->depth)
+		commonring->r_ptr = 0;
+
+	if (commonring->cr_write_rptr)
+		return commonring->cr_write_rptr(commonring->cr_ctx);
+
+	return -EIO;
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/commonring.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/commonring.h
new file mode 100644
index 0000000..b850336
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/commonring.h
@@ -0,0 +1,72 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef BRCMFMAC_COMMONRING_H
+#define BRCMFMAC_COMMONRING_H
+
+
+struct brcmf_commonring {
+	u16 r_ptr;
+	u16 w_ptr;
+	u16 f_ptr;
+	u16 depth;
+	u16 item_len;
+
+	void *buf_addr;
+
+	int (*cr_ring_bell)(void *ctx);
+	int (*cr_update_rptr)(void *ctx);
+	int (*cr_update_wptr)(void *ctx);
+	int (*cr_write_rptr)(void *ctx);
+	int (*cr_write_wptr)(void *ctx);
+
+	void *cr_ctx;
+
+	spinlock_t lock;
+	unsigned long flags;
+	bool inited;
+	bool was_full;
+
+	atomic_t outstanding_tx;
+};
+
+
+void brcmf_commonring_register_cb(struct brcmf_commonring *commonring,
+				  int (*cr_ring_bell)(void *ctx),
+				  int (*cr_update_rptr)(void *ctx),
+				  int (*cr_update_wptr)(void *ctx),
+				  int (*cr_write_rptr)(void *ctx),
+				  int (*cr_write_wptr)(void *ctx), void *ctx);
+void brcmf_commonring_config(struct brcmf_commonring *commonring, u16 depth,
+			     u16 item_len, void *buf_addr);
+void brcmf_commonring_lock(struct brcmf_commonring *commonring);
+void brcmf_commonring_unlock(struct brcmf_commonring *commonring);
+bool brcmf_commonring_write_available(struct brcmf_commonring *commonring);
+void *brcmf_commonring_reserve_for_write(struct brcmf_commonring *commonring);
+void *
+brcmf_commonring_reserve_for_write_multiple(struct brcmf_commonring *commonring,
+					    u16 n_items, u16 *alloced);
+int brcmf_commonring_write_complete(struct brcmf_commonring *commonring);
+void brcmf_commonring_write_cancel(struct brcmf_commonring *commonring,
+				   u16 n_items);
+void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
+				    u16 *n_items);
+int brcmf_commonring_read_complete(struct brcmf_commonring *commonring,
+				   u16 n_items);
+
+#define brcmf_commonring_n_items(commonring) (commonring->depth)
+#define brcmf_commonring_len_item(commonring) (commonring->item_len)
+
+
+#endif /* BRCMFMAC_COMMONRING_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
new file mode 100644
index 0000000..b1f702f
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -0,0 +1,1347 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+#include <linux/inetdevice.h>
+#include <net/cfg80211.h>
+#include <net/rtnetlink.h>
+#include <net/addrconf.h>
+#include <net/ieee80211_radiotap.h>
+#include <net/ipv6.h>
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+
+#include "core.h"
+#include "bus.h"
+#include "debug.h"
+#include "fwil_types.h"
+#include "p2p.h"
+#include "pno.h"
+#include "cfg80211.h"
+#include "fwil.h"
+#include "feature.h"
+#include "proto.h"
+#include "pcie.h"
+#include "common.h"
+
+#define MAX_WAIT_FOR_8021X_TX			msecs_to_jiffies(950)
+
+#define BRCMF_BSSIDX_INVALID			-1
+
+char *brcmf_ifname(struct brcmf_if *ifp)
+{
+	if (!ifp)
+		return "<if_null>";
+
+	if (ifp->ndev)
+		return ifp->ndev->name;
+
+	return "<if_none>";
+}
+
+struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx)
+{
+	struct brcmf_if *ifp;
+	s32 bsscfgidx;
+
+	if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
+		brcmf_err("ifidx %d out of range\n", ifidx);
+		return NULL;
+	}
+
+	ifp = NULL;
+	bsscfgidx = drvr->if2bss[ifidx];
+	if (bsscfgidx >= 0)
+		ifp = drvr->iflist[bsscfgidx];
+
+	return ifp;
+}
+
+void brcmf_configure_arp_nd_offload(struct brcmf_if *ifp, bool enable)
+{
+	s32 err;
+	u32 mode;
+
+	if (enable)
+		mode = BRCMF_ARP_OL_AGENT | BRCMF_ARP_OL_PEER_AUTO_REPLY;
+	else
+		mode = 0;
+
+	/* Try to set and enable ARP offload feature, this may fail, then it  */
+	/* is simply not supported and err 0 will be returned                 */
+	err = brcmf_fil_iovar_int_set(ifp, "arp_ol", mode);
+	if (err) {
+		brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, err = %d\n",
+			  mode, err);
+	} else {
+		err = brcmf_fil_iovar_int_set(ifp, "arpoe", enable);
+		if (err) {
+			brcmf_dbg(TRACE, "failed to configure (%d) ARP offload err = %d\n",
+				  enable, err);
+		} else {
+			brcmf_dbg(TRACE, "successfully configured (%d) ARP offload to 0x%x\n",
+				  enable, mode);
+		}
+	}
+
+	err = brcmf_fil_iovar_int_set(ifp, "ndoe", enable);
+	if (err) {
+		brcmf_dbg(TRACE, "failed to configure (%d) ND offload err = %d\n",
+			  enable, err);
+	} else {
+		brcmf_dbg(TRACE, "successfully configured (%d) ND offload to 0x%x\n",
+			  enable, mode);
+	}
+}
+
+static void _brcmf_set_multicast_list(struct work_struct *work)
+{
+	struct brcmf_if *ifp;
+	struct net_device *ndev;
+	struct netdev_hw_addr *ha;
+	u32 cmd_value, cnt;
+	__le32 cnt_le;
+	char *buf, *bufp;
+	u32 buflen;
+	s32 err;
+
+	ifp = container_of(work, struct brcmf_if, multicast_work);
+
+	brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
+
+	ndev = ifp->ndev;
+
+	/* Determine initial value of allmulti flag */
+	cmd_value = (ndev->flags & IFF_ALLMULTI) ? true : false;
+
+	/* Send down the multicast list first. */
+	cnt = netdev_mc_count(ndev);
+	buflen = sizeof(cnt) + (cnt * ETH_ALEN);
+	buf = kmalloc(buflen, GFP_ATOMIC);
+	if (!buf)
+		return;
+	bufp = buf;
+
+	cnt_le = cpu_to_le32(cnt);
+	memcpy(bufp, &cnt_le, sizeof(cnt_le));
+	bufp += sizeof(cnt_le);
+
+	netdev_for_each_mc_addr(ha, ndev) {
+		if (!cnt)
+			break;
+		memcpy(bufp, ha->addr, ETH_ALEN);
+		bufp += ETH_ALEN;
+		cnt--;
+	}
+
+	err = brcmf_fil_iovar_data_set(ifp, "mcast_list", buf, buflen);
+	if (err < 0) {
+		brcmf_err("Setting mcast_list failed, %d\n", err);
+		cmd_value = cnt ? true : cmd_value;
+	}
+
+	kfree(buf);
+
+	/*
+	 * Now send the allmulti setting.  This is based on the setting in the
+	 * net_device flags, but might be modified above to be turned on if we
+	 * were trying to set some addresses and dongle rejected it...
+	 */
+	err = brcmf_fil_iovar_int_set(ifp, "allmulti", cmd_value);
+	if (err < 0)
+		brcmf_err("Setting allmulti failed, %d\n", err);
+
+	/*Finally, pick up the PROMISC flag */
+	cmd_value = (ndev->flags & IFF_PROMISC) ? true : false;
+	err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PROMISC, cmd_value);
+	if (err < 0)
+		brcmf_err("Setting BRCMF_C_SET_PROMISC failed, %d\n",
+			  err);
+	brcmf_configure_arp_nd_offload(ifp, !cmd_value);
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
+static void _brcmf_update_ndtable(struct work_struct *work)
+{
+	struct brcmf_if *ifp;
+	int i, ret;
+
+	ifp = container_of(work, struct brcmf_if, ndoffload_work);
+
+	/* clear the table in firmware */
+	ret = brcmf_fil_iovar_data_set(ifp, "nd_hostip_clear", NULL, 0);
+	if (ret) {
+		brcmf_dbg(TRACE, "fail to clear nd ip table err:%d\n", ret);
+		return;
+	}
+
+	for (i = 0; i < ifp->ipv6addr_idx; i++) {
+		ret = brcmf_fil_iovar_data_set(ifp, "nd_hostip",
+					       &ifp->ipv6_addr_tbl[i],
+					       sizeof(struct in6_addr));
+		if (ret)
+			brcmf_err("add nd ip err %d\n", ret);
+	}
+}
+#else
+static void _brcmf_update_ndtable(struct work_struct *work)
+{
+}
+#endif
+
+static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct sockaddr *sa = (struct sockaddr *)addr;
+	int err;
+
+	brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
+
+	err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", sa->sa_data,
+				       ETH_ALEN);
+	if (err < 0) {
+		brcmf_err("Setting cur_etheraddr failed, %d\n", err);
+	} else {
+		brcmf_dbg(TRACE, "updated to %pM\n", sa->sa_data);
+		memcpy(ifp->mac_addr, sa->sa_data, ETH_ALEN);
+		memcpy(ifp->ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
+	}
+	return err;
+}
+
+static void brcmf_netdev_set_multicast_list(struct net_device *ndev)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+
+	schedule_work(&ifp->multicast_work);
+}
+
+/**
+ * brcmf_skb_is_iapp - checks if skb is an IAPP packet
+ *
+ * @skb: skb to check
+ */
+static bool brcmf_skb_is_iapp(struct sk_buff *skb)
+{
+	static const u8 iapp_l2_update_packet[6] __aligned(2) = {
+		0x00, 0x01, 0xaf, 0x81, 0x01, 0x00,
+	};
+	unsigned char *eth_data;
+#if !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+	const u16 *a, *b;
+#endif
+
+	if (skb->len - skb->mac_len != 6 ||
+	    !is_multicast_ether_addr(eth_hdr(skb)->h_dest))
+		return false;
+
+	eth_data = skb_mac_header(skb) + ETH_HLEN;
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+	return !(((*(const u32 *)eth_data) ^ (*(const u32 *)iapp_l2_update_packet)) |
+		 ((*(const u16 *)(eth_data + 4)) ^ (*(const u16 *)(iapp_l2_update_packet + 4))));
+#else
+	a = (const u16 *)eth_data;
+	b = (const u16 *)iapp_l2_update_packet;
+
+	return !((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]));
+#endif
+}
+
+static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
+					   struct net_device *ndev)
+{
+	int ret;
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_pub *drvr = ifp->drvr;
+	struct ethhdr *eh;
+	int head_delta;
+
+	brcmf_dbg(DATA, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
+
+	/* Can the device send data? */
+	if (drvr->bus_if->state != BRCMF_BUS_UP) {
+		brcmf_err("xmit rejected state=%d\n", drvr->bus_if->state);
+		netif_stop_queue(ndev);
+		dev_kfree_skb(skb);
+		ret = -ENODEV;
+		goto done;
+	}
+
+	/* Some recent Broadcom's firmwares disassociate STA when they receive
+	 * an 802.11f ADD frame. This behavior can lead to a local DoS security
+	 * issue. Attacker may trigger disassociation of any STA by sending a
+	 * proper Ethernet frame to the wireless interface.
+	 *
+	 * Moreover this feature may break AP interfaces in some specific
+	 * setups. This applies e.g. to the bridge with hairpin mode enabled and
+	 * IFLA_BRPORT_MCAST_TO_UCAST set. IAPP packet generated by a firmware
+	 * will get passed back to the wireless interface and cause immediate
+	 * disassociation of a just-connected STA.
+	 */
+	if (!drvr->settings->iapp && brcmf_skb_is_iapp(skb)) {
+		dev_kfree_skb(skb);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* Make sure there's enough writeable headroom */
+	if (skb_headroom(skb) < drvr->hdrlen || skb_header_cloned(skb)) {
+		head_delta = max_t(int, drvr->hdrlen - skb_headroom(skb), 0);
+
+		brcmf_dbg(INFO, "%s: insufficient headroom (%d)\n",
+			  brcmf_ifname(ifp), head_delta);
+		atomic_inc(&drvr->bus_if->stats.pktcowed);
+		ret = pskb_expand_head(skb, ALIGN(head_delta, NET_SKB_PAD), 0,
+				       GFP_ATOMIC);
+		if (ret < 0) {
+			brcmf_err("%s: failed to expand headroom\n",
+				  brcmf_ifname(ifp));
+			atomic_inc(&drvr->bus_if->stats.pktcow_failed);
+			goto done;
+		}
+	}
+
+	/* validate length for ether packet */
+	if (skb->len < sizeof(*eh)) {
+		ret = -EINVAL;
+		dev_kfree_skb(skb);
+		goto done;
+	}
+
+	eh = (struct ethhdr *)(skb->data);
+
+	if (eh->h_proto == htons(ETH_P_PAE))
+		atomic_inc(&ifp->pend_8021x_cnt);
+
+	/* determine the priority */
+	if ((skb->priority == 0) || (skb->priority > 7))
+		skb->priority = cfg80211_classify8021d(skb, NULL);
+
+	ret = brcmf_proto_tx_queue_data(drvr, ifp->ifidx, skb);
+	if (ret < 0)
+		brcmf_txfinalize(ifp, skb, false);
+
+done:
+	if (ret) {
+		ndev->stats.tx_dropped++;
+	} else {
+		ndev->stats.tx_packets++;
+		ndev->stats.tx_bytes += skb->len;
+	}
+
+	/* Return ok: we always eat the packet */
+	return NETDEV_TX_OK;
+}
+
+void brcmf_txflowblock_if(struct brcmf_if *ifp,
+			  enum brcmf_netif_stop_reason reason, bool state)
+{
+	unsigned long flags;
+
+	if (!ifp || !ifp->ndev)
+		return;
+
+	brcmf_dbg(TRACE, "enter: bsscfgidx=%d stop=0x%X reason=%d state=%d\n",
+		  ifp->bsscfgidx, ifp->netif_stop, reason, state);
+
+	spin_lock_irqsave(&ifp->netif_stop_lock, flags);
+	if (state) {
+		if (!ifp->netif_stop)
+			netif_stop_queue(ifp->ndev);
+		ifp->netif_stop |= reason;
+	} else {
+		ifp->netif_stop &= ~reason;
+		if (!ifp->netif_stop)
+			netif_wake_queue(ifp->ndev);
+	}
+	spin_unlock_irqrestore(&ifp->netif_stop_lock, flags);
+}
+
+void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb)
+{
+	/* Most of Broadcom's firmwares send 802.11f ADD frame every time a new
+	 * STA connects to the AP interface. This is an obsoleted standard most
+	 * users don't use, so don't pass these frames up unless requested.
+	 */
+	if (!ifp->drvr->settings->iapp && brcmf_skb_is_iapp(skb)) {
+		brcmu_pkt_buf_free_skb(skb);
+		return;
+	}
+
+	if (skb->pkt_type == PACKET_MULTICAST)
+		ifp->ndev->stats.multicast++;
+
+	if (!(ifp->ndev->flags & IFF_UP)) {
+		brcmu_pkt_buf_free_skb(skb);
+		return;
+	}
+
+	ifp->ndev->stats.rx_bytes += skb->len;
+	ifp->ndev->stats.rx_packets++;
+
+	brcmf_dbg(DATA, "rx proto=0x%X\n", ntohs(skb->protocol));
+	if (in_interrupt())
+		netif_rx(skb);
+	else
+		/* If the receive is not processed inside an ISR,
+		 * the softirqd must be woken explicitly to service
+		 * the NET_RX_SOFTIRQ.  This is handled by netif_rx_ni().
+		 */
+		netif_rx_ni(skb);
+}
+
+void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb)
+{
+	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR_FMT_RADIOTAP)) {
+		/* Do nothing */
+	} else {
+		struct ieee80211_radiotap_header *radiotap;
+
+		/* TODO: use RX status to fill some radiotap data */
+		radiotap = skb_push(skb, sizeof(*radiotap));
+		memset(radiotap, 0, sizeof(*radiotap));
+		radiotap->it_len = cpu_to_le16(sizeof(*radiotap));
+
+		/* TODO: 4 bytes with receive status? */
+		skb->len -= 4;
+	}
+
+	skb->dev = ifp->ndev;
+	skb_reset_mac_header(skb);
+	skb->pkt_type = PACKET_OTHERHOST;
+	skb->protocol = htons(ETH_P_802_2);
+
+	brcmf_netif_rx(ifp, skb);
+}
+
+static int brcmf_rx_hdrpull(struct brcmf_pub *drvr, struct sk_buff *skb,
+			    struct brcmf_if **ifp)
+{
+	int ret;
+
+	/* process and remove protocol-specific header */
+	ret = brcmf_proto_hdrpull(drvr, true, skb, ifp);
+
+	if (ret || !(*ifp) || !(*ifp)->ndev) {
+		if (ret != -ENODATA && *ifp)
+			(*ifp)->ndev->stats.rx_errors++;
+		brcmu_pkt_buf_free_skb(skb);
+		return -ENODATA;
+	}
+
+	skb->protocol = eth_type_trans(skb, (*ifp)->ndev);
+	return 0;
+}
+
+void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_event)
+{
+	struct brcmf_if *ifp;
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_pub *drvr = bus_if->drvr;
+
+	brcmf_dbg(DATA, "Enter: %s: rxp=%p\n", dev_name(dev), skb);
+
+	if (brcmf_rx_hdrpull(drvr, skb, &ifp))
+		return;
+
+	if (brcmf_proto_is_reorder_skb(skb)) {
+		brcmf_proto_rxreorder(ifp, skb);
+	} else {
+		/* Process special event packets */
+		if (handle_event)
+			brcmf_fweh_process_skb(ifp->drvr, skb);
+
+		brcmf_netif_rx(ifp, skb);
+	}
+}
+
+void brcmf_rx_event(struct device *dev, struct sk_buff *skb)
+{
+	struct brcmf_if *ifp;
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_pub *drvr = bus_if->drvr;
+
+	brcmf_dbg(EVENT, "Enter: %s: rxp=%p\n", dev_name(dev), skb);
+
+	if (brcmf_rx_hdrpull(drvr, skb, &ifp))
+		return;
+
+	brcmf_fweh_process_skb(ifp->drvr, skb);
+	brcmu_pkt_buf_free_skb(skb);
+}
+
+void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success)
+{
+	struct ethhdr *eh;
+	u16 type;
+
+	eh = (struct ethhdr *)(txp->data);
+	type = ntohs(eh->h_proto);
+
+	if (type == ETH_P_PAE) {
+		atomic_dec(&ifp->pend_8021x_cnt);
+		if (waitqueue_active(&ifp->pend_8021x_wait))
+			wake_up(&ifp->pend_8021x_wait);
+	}
+
+	if (!success)
+		ifp->ndev->stats.tx_errors++;
+
+	brcmu_pkt_buf_free_skb(txp);
+}
+
+static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
+				    struct ethtool_drvinfo *info)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_pub *drvr = ifp->drvr;
+	char drev[BRCMU_DOTREV_LEN] = "n/a";
+
+	if (drvr->revinfo.result == 0)
+		brcmu_dotrev_str(drvr->revinfo.driverrev, drev);
+	strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
+	strlcpy(info->version, drev, sizeof(info->version));
+	strlcpy(info->fw_version, drvr->fwver, sizeof(info->fw_version));
+	strlcpy(info->bus_info, dev_name(drvr->bus_if->dev),
+		sizeof(info->bus_info));
+}
+
+static const struct ethtool_ops brcmf_ethtool_ops = {
+	.get_drvinfo = brcmf_ethtool_get_drvinfo,
+};
+
+static int brcmf_netdev_stop(struct net_device *ndev)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+
+	brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
+
+	brcmf_cfg80211_down(ndev);
+
+	brcmf_fil_iovar_data_set(ifp, "arp_hostip_clear", NULL, 0);
+
+	brcmf_net_setcarrier(ifp, false);
+
+	return 0;
+}
+
+static int brcmf_netdev_open(struct net_device *ndev)
+{
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_pub *drvr = ifp->drvr;
+	struct brcmf_bus *bus_if = drvr->bus_if;
+	u32 toe_ol;
+
+	brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
+
+	/* If bus is not ready, can't continue */
+	if (bus_if->state != BRCMF_BUS_UP) {
+		brcmf_err("failed bus is not ready\n");
+		return -EAGAIN;
+	}
+
+	atomic_set(&ifp->pend_8021x_cnt, 0);
+
+	/* Get current TOE mode from dongle */
+	if (brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_ol) >= 0
+	    && (toe_ol & TOE_TX_CSUM_OL) != 0)
+		ndev->features |= NETIF_F_IP_CSUM;
+	else
+		ndev->features &= ~NETIF_F_IP_CSUM;
+
+	if (brcmf_cfg80211_up(ndev)) {
+		brcmf_err("failed to bring up cfg80211\n");
+		return -EIO;
+	}
+
+	/* Clear, carrier, set when connected or AP mode. */
+	netif_carrier_off(ndev);
+	return 0;
+}
+
+static const struct net_device_ops brcmf_netdev_ops_pri = {
+	.ndo_open = brcmf_netdev_open,
+	.ndo_stop = brcmf_netdev_stop,
+	.ndo_start_xmit = brcmf_netdev_start_xmit,
+	.ndo_set_mac_address = brcmf_netdev_set_mac_address,
+	.ndo_set_rx_mode = brcmf_netdev_set_multicast_list
+};
+
+int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked)
+{
+	struct brcmf_pub *drvr = ifp->drvr;
+	struct net_device *ndev;
+	s32 err;
+
+	brcmf_dbg(TRACE, "Enter, bsscfgidx=%d mac=%pM\n", ifp->bsscfgidx,
+		  ifp->mac_addr);
+	ndev = ifp->ndev;
+
+	/* set appropriate operations */
+	ndev->netdev_ops = &brcmf_netdev_ops_pri;
+
+	ndev->needed_headroom += drvr->hdrlen;
+	ndev->ethtool_ops = &brcmf_ethtool_ops;
+
+	/* set the mac address & netns */
+	memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
+	dev_net_set(ndev, wiphy_net(cfg_to_wiphy(drvr->config)));
+
+	INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);
+	INIT_WORK(&ifp->ndoffload_work, _brcmf_update_ndtable);
+
+	if (rtnl_locked)
+		err = register_netdevice(ndev);
+	else
+		err = register_netdev(ndev);
+	if (err != 0) {
+		brcmf_err("couldn't register the net device\n");
+		goto fail;
+	}
+
+	ndev->priv_destructor = brcmf_cfg80211_free_netdev;
+	brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
+	return 0;
+
+fail:
+	drvr->iflist[ifp->bsscfgidx] = NULL;
+	ndev->netdev_ops = NULL;
+	return -EBADE;
+}
+
+static void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked)
+{
+	if (ndev->reg_state == NETREG_REGISTERED) {
+		if (rtnl_locked)
+			unregister_netdevice(ndev);
+		else
+			unregister_netdev(ndev);
+	} else {
+		brcmf_cfg80211_free_netdev(ndev);
+		free_netdev(ndev);
+	}
+}
+
+void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on)
+{
+	struct net_device *ndev;
+
+	brcmf_dbg(TRACE, "Enter, bsscfgidx=%d carrier=%d\n", ifp->bsscfgidx,
+		  on);
+
+	ndev = ifp->ndev;
+	brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_DISCONNECTED, !on);
+	if (on) {
+		if (!netif_carrier_ok(ndev))
+			netif_carrier_on(ndev);
+
+	} else {
+		if (netif_carrier_ok(ndev))
+			netif_carrier_off(ndev);
+	}
+}
+
+static int brcmf_net_p2p_open(struct net_device *ndev)
+{
+	brcmf_dbg(TRACE, "Enter\n");
+
+	return brcmf_cfg80211_up(ndev);
+}
+
+static int brcmf_net_p2p_stop(struct net_device *ndev)
+{
+	brcmf_dbg(TRACE, "Enter\n");
+
+	return brcmf_cfg80211_down(ndev);
+}
+
+static netdev_tx_t brcmf_net_p2p_start_xmit(struct sk_buff *skb,
+					    struct net_device *ndev)
+{
+	if (skb)
+		dev_kfree_skb_any(skb);
+
+	return NETDEV_TX_OK;
+}
+
+static const struct net_device_ops brcmf_netdev_ops_p2p = {
+	.ndo_open = brcmf_net_p2p_open,
+	.ndo_stop = brcmf_net_p2p_stop,
+	.ndo_start_xmit = brcmf_net_p2p_start_xmit
+};
+
+static int brcmf_net_p2p_attach(struct brcmf_if *ifp)
+{
+	struct net_device *ndev;
+
+	brcmf_dbg(TRACE, "Enter, bsscfgidx=%d mac=%pM\n", ifp->bsscfgidx,
+		  ifp->mac_addr);
+	ndev = ifp->ndev;
+
+	ndev->netdev_ops = &brcmf_netdev_ops_p2p;
+
+	/* set the mac address */
+	memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
+
+	if (register_netdev(ndev) != 0) {
+		brcmf_err("couldn't register the p2p net device\n");
+		goto fail;
+	}
+
+	brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
+
+	return 0;
+
+fail:
+	ifp->drvr->iflist[ifp->bsscfgidx] = NULL;
+	ndev->netdev_ops = NULL;
+	return -EBADE;
+}
+
+struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,
+			      bool is_p2pdev, const char *name, u8 *mac_addr)
+{
+	struct brcmf_if *ifp;
+	struct net_device *ndev;
+
+	brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, ifidx=%d\n", bsscfgidx, ifidx);
+
+	ifp = drvr->iflist[bsscfgidx];
+	/*
+	 * Delete the existing interface before overwriting it
+	 * in case we missed the BRCMF_E_IF_DEL event.
+	 */
+	if (ifp) {
+		if (ifidx) {
+			brcmf_err("ERROR: netdev:%s already exists\n",
+				  ifp->ndev->name);
+			netif_stop_queue(ifp->ndev);
+			brcmf_net_detach(ifp->ndev, false);
+			drvr->iflist[bsscfgidx] = NULL;
+		} else {
+			brcmf_dbg(INFO, "netdev:%s ignore IF event\n",
+				  ifp->ndev->name);
+			return ERR_PTR(-EINVAL);
+		}
+	}
+
+	if (!drvr->settings->p2p_enable && is_p2pdev) {
+		/* this is P2P_DEVICE interface */
+		brcmf_dbg(INFO, "allocate non-netdev interface\n");
+		ifp = kzalloc(sizeof(*ifp), GFP_KERNEL);
+		if (!ifp)
+			return ERR_PTR(-ENOMEM);
+	} else {
+		brcmf_dbg(INFO, "allocate netdev interface\n");
+		/* Allocate netdev, including space for private structure */
+		ndev = alloc_netdev(sizeof(*ifp), is_p2pdev ? "p2p%d" : name,
+				    NET_NAME_UNKNOWN, ether_setup);
+		if (!ndev)
+			return ERR_PTR(-ENOMEM);
+
+		ndev->needs_free_netdev = true;
+		ifp = netdev_priv(ndev);
+		ifp->ndev = ndev;
+		/* store mapping ifidx to bsscfgidx */
+		if (drvr->if2bss[ifidx] == BRCMF_BSSIDX_INVALID)
+			drvr->if2bss[ifidx] = bsscfgidx;
+	}
+
+	ifp->drvr = drvr;
+	drvr->iflist[bsscfgidx] = ifp;
+	ifp->ifidx = ifidx;
+	ifp->bsscfgidx = bsscfgidx;
+
+	init_waitqueue_head(&ifp->pend_8021x_wait);
+	spin_lock_init(&ifp->netif_stop_lock);
+
+	if (mac_addr != NULL)
+		memcpy(ifp->mac_addr, mac_addr, ETH_ALEN);
+
+	brcmf_dbg(TRACE, " ==== pid:%x, if:%s (%pM) created ===\n",
+		  current->pid, name, ifp->mac_addr);
+
+	return ifp;
+}
+
+static void brcmf_del_if(struct brcmf_pub *drvr, s32 bsscfgidx,
+			 bool rtnl_locked)
+{
+	struct brcmf_if *ifp;
+
+	ifp = drvr->iflist[bsscfgidx];
+	drvr->iflist[bsscfgidx] = NULL;
+	if (!ifp) {
+		brcmf_err("Null interface, bsscfgidx=%d\n", bsscfgidx);
+		return;
+	}
+	brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, ifidx=%d\n", bsscfgidx,
+		  ifp->ifidx);
+	if (drvr->if2bss[ifp->ifidx] == bsscfgidx)
+		drvr->if2bss[ifp->ifidx] = BRCMF_BSSIDX_INVALID;
+	if (ifp->ndev) {
+		if (bsscfgidx == 0) {
+			if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
+				rtnl_lock();
+				brcmf_netdev_stop(ifp->ndev);
+				rtnl_unlock();
+			}
+		} else {
+			netif_stop_queue(ifp->ndev);
+		}
+
+		if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
+			cancel_work_sync(&ifp->multicast_work);
+			cancel_work_sync(&ifp->ndoffload_work);
+		}
+		brcmf_net_detach(ifp->ndev, rtnl_locked);
+	} else {
+		/* Only p2p device interfaces which get dynamically created
+		 * end up here. In this case the p2p module should be informed
+		 * about the removal of the interface within the firmware. If
+		 * not then p2p commands towards the firmware will cause some
+		 * serious troublesome side effects. The p2p module will clean
+		 * up the ifp if needed.
+		 */
+		brcmf_p2p_ifp_removed(ifp, rtnl_locked);
+		kfree(ifp);
+	}
+}
+
+void brcmf_remove_interface(struct brcmf_if *ifp, bool rtnl_locked)
+{
+	if (!ifp || WARN_ON(ifp->drvr->iflist[ifp->bsscfgidx] != ifp))
+		return;
+	brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, ifidx=%d\n", ifp->bsscfgidx,
+		  ifp->ifidx);
+	brcmf_proto_del_if(ifp->drvr, ifp);
+	brcmf_del_if(ifp->drvr, ifp->bsscfgidx, rtnl_locked);
+}
+
+static int brcmf_psm_watchdog_notify(struct brcmf_if *ifp,
+				     const struct brcmf_event_msg *evtmsg,
+				     void *data)
+{
+	int err;
+
+	brcmf_dbg(TRACE, "enter: bsscfgidx=%d\n", ifp->bsscfgidx);
+
+	brcmf_err("PSM's watchdog has fired!\n");
+
+	err = brcmf_debug_create_memdump(ifp->drvr->bus_if, data,
+					 evtmsg->datalen);
+	if (err)
+		brcmf_err("Failed to get memory dump, %d\n", err);
+
+	return err;
+}
+
+#ifdef CONFIG_INET
+#define ARPOL_MAX_ENTRIES	8
+static int brcmf_inetaddr_changed(struct notifier_block *nb,
+				  unsigned long action, void *data)
+{
+	struct brcmf_pub *drvr = container_of(nb, struct brcmf_pub,
+					      inetaddr_notifier);
+	struct in_ifaddr *ifa = data;
+	struct net_device *ndev = ifa->ifa_dev->dev;
+	struct brcmf_if *ifp;
+	int idx, i, ret;
+	u32 val;
+	__be32 addr_table[ARPOL_MAX_ENTRIES] = {0};
+
+	/* Find out if the notification is meant for us */
+	for (idx = 0; idx < BRCMF_MAX_IFS; idx++) {
+		ifp = drvr->iflist[idx];
+		if (ifp && ifp->ndev == ndev)
+			break;
+		if (idx == BRCMF_MAX_IFS - 1)
+			return NOTIFY_DONE;
+	}
+
+	/* check if arp offload is supported */
+	ret = brcmf_fil_iovar_int_get(ifp, "arpoe", &val);
+	if (ret)
+		return NOTIFY_OK;
+
+	/* old version only support primary index */
+	ret = brcmf_fil_iovar_int_get(ifp, "arp_version", &val);
+	if (ret)
+		val = 1;
+	if (val == 1)
+		ifp = drvr->iflist[0];
+
+	/* retrieve the table from firmware */
+	ret = brcmf_fil_iovar_data_get(ifp, "arp_hostip", addr_table,
+				       sizeof(addr_table));
+	if (ret) {
+		brcmf_err("fail to get arp ip table err:%d\n", ret);
+		return NOTIFY_OK;
+	}
+
+	for (i = 0; i < ARPOL_MAX_ENTRIES; i++)
+		if (ifa->ifa_address == addr_table[i])
+			break;
+
+	switch (action) {
+	case NETDEV_UP:
+		if (i == ARPOL_MAX_ENTRIES) {
+			brcmf_dbg(TRACE, "add %pI4 to arp table\n",
+				  &ifa->ifa_address);
+			/* set it directly */
+			ret = brcmf_fil_iovar_data_set(ifp, "arp_hostip",
+				&ifa->ifa_address, sizeof(ifa->ifa_address));
+			if (ret)
+				brcmf_err("add arp ip err %d\n", ret);
+		}
+		break;
+	case NETDEV_DOWN:
+		if (i < ARPOL_MAX_ENTRIES) {
+			addr_table[i] = 0;
+			brcmf_dbg(TRACE, "remove %pI4 from arp table\n",
+				  &ifa->ifa_address);
+			/* clear the table in firmware */
+			ret = brcmf_fil_iovar_data_set(ifp, "arp_hostip_clear",
+						       NULL, 0);
+			if (ret) {
+				brcmf_err("fail to clear arp ip table err:%d\n",
+					  ret);
+				return NOTIFY_OK;
+			}
+			for (i = 0; i < ARPOL_MAX_ENTRIES; i++) {
+				if (addr_table[i] == 0)
+					continue;
+				ret = brcmf_fil_iovar_data_set(ifp, "arp_hostip",
+							       &addr_table[i],
+							       sizeof(addr_table[i]));
+				if (ret)
+					brcmf_err("add arp ip err %d\n",
+						  ret);
+			}
+		}
+		break;
+	default:
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+#endif
+
+#if IS_ENABLED(CONFIG_IPV6)
+static int brcmf_inet6addr_changed(struct notifier_block *nb,
+				   unsigned long action, void *data)
+{
+	struct brcmf_pub *drvr = container_of(nb, struct brcmf_pub,
+					      inet6addr_notifier);
+	struct inet6_ifaddr *ifa = data;
+	struct brcmf_if *ifp;
+	int i;
+	struct in6_addr *table;
+
+	/* Only handle primary interface */
+	ifp = drvr->iflist[0];
+	if (!ifp)
+		return NOTIFY_DONE;
+	if (ifp->ndev != ifa->idev->dev)
+		return NOTIFY_DONE;
+
+	table = ifp->ipv6_addr_tbl;
+	for (i = 0; i < NDOL_MAX_ENTRIES; i++)
+		if (ipv6_addr_equal(&ifa->addr, &table[i]))
+			break;
+
+	switch (action) {
+	case NETDEV_UP:
+		if (i == NDOL_MAX_ENTRIES) {
+			if (ifp->ipv6addr_idx < NDOL_MAX_ENTRIES) {
+				table[ifp->ipv6addr_idx++] = ifa->addr;
+			} else {
+				for (i = 0; i < NDOL_MAX_ENTRIES - 1; i++)
+					table[i] = table[i + 1];
+				table[NDOL_MAX_ENTRIES - 1] = ifa->addr;
+			}
+		}
+		break;
+	case NETDEV_DOWN:
+		if (i < NDOL_MAX_ENTRIES) {
+			for (; i < ifp->ipv6addr_idx - 1; i++)
+				table[i] = table[i + 1];
+			memset(&table[i], 0, sizeof(table[i]));
+			ifp->ipv6addr_idx--;
+		}
+		break;
+	default:
+		break;
+	}
+
+	schedule_work(&ifp->ndoffload_work);
+
+	return NOTIFY_OK;
+}
+#endif
+
+static int brcmf_revinfo_read(struct seq_file *s, void *data)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(s->private);
+	struct brcmf_rev_info *ri = &bus_if->drvr->revinfo;
+	char drev[BRCMU_DOTREV_LEN];
+	char brev[BRCMU_BOARDREV_LEN];
+
+	seq_printf(s, "vendorid: 0x%04x\n", ri->vendorid);
+	seq_printf(s, "deviceid: 0x%04x\n", ri->deviceid);
+	seq_printf(s, "radiorev: %s\n", brcmu_dotrev_str(ri->radiorev, drev));
+	seq_printf(s, "chip: %s\n", ri->chipname);
+	seq_printf(s, "chippkg: %u\n", ri->chippkg);
+	seq_printf(s, "corerev: %u\n", ri->corerev);
+	seq_printf(s, "boardid: 0x%04x\n", ri->boardid);
+	seq_printf(s, "boardvendor: 0x%04x\n", ri->boardvendor);
+	seq_printf(s, "boardrev: %s\n", brcmu_boardrev_str(ri->boardrev, brev));
+	seq_printf(s, "driverrev: %s\n", brcmu_dotrev_str(ri->driverrev, drev));
+	seq_printf(s, "ucoderev: %u\n", ri->ucoderev);
+	seq_printf(s, "bus: %u\n", ri->bus);
+	seq_printf(s, "phytype: %u\n", ri->phytype);
+	seq_printf(s, "phyrev: %u\n", ri->phyrev);
+	seq_printf(s, "anarev: %u\n", ri->anarev);
+	seq_printf(s, "nvramrev: %08x\n", ri->nvramrev);
+
+	seq_printf(s, "clmver: %s\n", bus_if->drvr->clmver);
+
+	return 0;
+}
+
+static int brcmf_bus_started(struct brcmf_pub *drvr, struct cfg80211_ops *ops)
+{
+	int ret = -1;
+	struct brcmf_bus *bus_if = drvr->bus_if;
+	struct brcmf_if *ifp;
+	struct brcmf_if *p2p_ifp;
+
+	brcmf_dbg(TRACE, "\n");
+
+	/* add primary networking interface */
+	ifp = brcmf_add_if(drvr, 0, 0, false, "wlan%d", NULL);
+	if (IS_ERR(ifp))
+		return PTR_ERR(ifp);
+
+	p2p_ifp = NULL;
+
+	/* signal bus ready */
+	brcmf_bus_change_state(bus_if, BRCMF_BUS_UP);
+
+	/* do bus specific preinit here */
+	ret = brcmf_bus_preinit(bus_if);
+	if (ret < 0)
+		goto fail;
+
+	/* Bus is ready, do any initialization */
+	ret = brcmf_c_preinit_dcmds(ifp);
+	if (ret < 0)
+		goto fail;
+
+	brcmf_feat_attach(drvr);
+
+	ret = brcmf_proto_init_done(drvr);
+	if (ret < 0)
+		goto fail;
+
+	brcmf_proto_add_if(drvr, ifp);
+
+	drvr->config = brcmf_cfg80211_attach(drvr, ops,
+					     drvr->settings->p2p_enable);
+	if (drvr->config == NULL) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	ret = brcmf_net_attach(ifp, false);
+
+	if ((!ret) && (drvr->settings->p2p_enable)) {
+		p2p_ifp = drvr->iflist[1];
+		if (p2p_ifp)
+			ret = brcmf_net_p2p_attach(p2p_ifp);
+	}
+
+	if (ret)
+		goto fail;
+
+#ifdef CONFIG_INET
+	drvr->inetaddr_notifier.notifier_call = brcmf_inetaddr_changed;
+	ret = register_inetaddr_notifier(&drvr->inetaddr_notifier);
+	if (ret)
+		goto fail;
+
+#if IS_ENABLED(CONFIG_IPV6)
+	drvr->inet6addr_notifier.notifier_call = brcmf_inet6addr_changed;
+	ret = register_inet6addr_notifier(&drvr->inet6addr_notifier);
+	if (ret) {
+		unregister_inetaddr_notifier(&drvr->inetaddr_notifier);
+		goto fail;
+	}
+#endif
+#endif /* CONFIG_INET */
+
+	/* populate debugfs */
+	brcmf_debugfs_add_entry(drvr, "revinfo", brcmf_revinfo_read);
+	brcmf_feat_debugfs_create(drvr);
+	brcmf_proto_debugfs_create(drvr);
+
+	return 0;
+
+fail:
+	brcmf_err("failed: %d\n", ret);
+	if (drvr->config) {
+		brcmf_cfg80211_detach(drvr->config);
+		drvr->config = NULL;
+	}
+	brcmf_net_detach(ifp->ndev, false);
+	if (p2p_ifp)
+		brcmf_net_detach(p2p_ifp->ndev, false);
+	drvr->iflist[0] = NULL;
+	drvr->iflist[1] = NULL;
+	if (drvr->settings->ignore_probe_fail)
+		ret = 0;
+
+	return ret;
+}
+
+int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings)
+{
+	struct wiphy *wiphy;
+	struct cfg80211_ops *ops;
+	struct brcmf_pub *drvr = NULL;
+	int ret = 0;
+	int i;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	ops = brcmf_cfg80211_get_ops();
+	if (!ops)
+		return -ENOMEM;
+
+	wiphy = wiphy_new(ops, sizeof(*drvr));
+	if (!wiphy)
+		return -ENOMEM;
+
+	set_wiphy_dev(wiphy, dev);
+	drvr = wiphy_priv(wiphy);
+	drvr->wiphy = wiphy;
+
+	for (i = 0; i < ARRAY_SIZE(drvr->if2bss); i++)
+		drvr->if2bss[i] = BRCMF_BSSIDX_INVALID;
+
+	mutex_init(&drvr->proto_block);
+
+	/* Link to bus module */
+	drvr->hdrlen = 0;
+	drvr->bus_if = dev_get_drvdata(dev);
+	drvr->bus_if->drvr = drvr;
+	drvr->settings = settings;
+
+	/* Attach and link in the protocol */
+	ret = brcmf_proto_attach(drvr);
+	if (ret != 0) {
+		brcmf_err("brcmf_prot_attach failed\n");
+		goto fail;
+	}
+
+	/* Attach to events important for core code */
+	brcmf_fweh_register(drvr, BRCMF_E_PSM_WATCHDOG,
+			    brcmf_psm_watchdog_notify);
+
+	/* attach firmware event handler */
+	brcmf_fweh_attach(drvr);
+
+	ret = brcmf_bus_started(drvr, ops);
+	if (ret != 0) {
+		brcmf_err("dongle is not responding: err=%d\n", ret);
+		goto fail;
+	}
+
+	drvr->config->ops = ops;
+	return 0;
+
+fail:
+	brcmf_detach(dev);
+	kfree(ops);
+
+	return ret;
+}
+
+void brcmf_bus_add_txhdrlen(struct device *dev, uint len)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_pub *drvr = bus_if->drvr;
+
+	if (drvr) {
+		drvr->hdrlen += len;
+	}
+}
+
+void brcmf_dev_reset(struct device *dev)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_pub *drvr = bus_if->drvr;
+
+	if (drvr == NULL)
+		return;
+
+	if (drvr->iflist[0])
+		brcmf_fil_cmd_int_set(drvr->iflist[0], BRCMF_C_TERMINATED, 1);
+}
+
+void brcmf_dev_coredump(struct device *dev)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+
+	if (brcmf_debug_create_memdump(bus_if, NULL, 0) < 0)
+		brcmf_dbg(TRACE, "failed to create coredump\n");
+}
+
+void brcmf_detach(struct device *dev)
+{
+	s32 i;
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_pub *drvr = bus_if->drvr;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	if (drvr == NULL)
+		return;
+
+#ifdef CONFIG_INET
+	unregister_inetaddr_notifier(&drvr->inetaddr_notifier);
+#endif
+
+#if IS_ENABLED(CONFIG_IPV6)
+	unregister_inet6addr_notifier(&drvr->inet6addr_notifier);
+#endif
+
+	/* stop firmware event handling */
+	brcmf_fweh_detach(drvr);
+	if (drvr->config)
+		brcmf_p2p_detach(&drvr->config->p2p);
+
+	brcmf_bus_change_state(bus_if, BRCMF_BUS_DOWN);
+
+	/* make sure primary interface removed last */
+	for (i = BRCMF_MAX_IFS-1; i > -1; i--)
+		brcmf_remove_interface(drvr->iflist[i], false);
+
+	brcmf_cfg80211_detach(drvr->config);
+	drvr->config = NULL;
+
+	brcmf_bus_stop(drvr->bus_if);
+
+	brcmf_proto_detach(drvr);
+
+	bus_if->drvr = NULL;
+	wiphy_free(drvr->wiphy);
+}
+
+s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_if *ifp = bus_if->drvr->iflist[0];
+
+	return brcmf_fil_iovar_data_set(ifp, name, data, len);
+}
+
+static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp)
+{
+	return atomic_read(&ifp->pend_8021x_cnt);
+}
+
+int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp)
+{
+	int err;
+
+	err = wait_event_timeout(ifp->pend_8021x_wait,
+				 !brcmf_get_pend_8021x_cnt(ifp),
+				 MAX_WAIT_FOR_8021X_TX);
+
+	if (!err)
+		brcmf_err("Timed out waiting for no pending 802.1x packets\n");
+
+	return !err;
+}
+
+void brcmf_bus_change_state(struct brcmf_bus *bus, enum brcmf_bus_state state)
+{
+	struct brcmf_pub *drvr = bus->drvr;
+	struct net_device *ndev;
+	int ifidx;
+
+	brcmf_dbg(TRACE, "%d -> %d\n", bus->state, state);
+
+	if (!drvr) {
+		brcmf_dbg(INFO, "ignoring transition, bus not attached yet\n");
+		return;
+	}
+
+	bus->state = state;
+
+	if (state == BRCMF_BUS_UP) {
+		for (ifidx = 0; ifidx < BRCMF_MAX_IFS; ifidx++) {
+			if ((drvr->iflist[ifidx]) &&
+			    (drvr->iflist[ifidx]->ndev)) {
+				ndev = drvr->iflist[ifidx]->ndev;
+				if (netif_queue_stopped(ndev))
+					netif_wake_queue(ndev);
+			}
+		}
+	}
+}
+
+static void brcmf_driver_register(struct work_struct *work)
+{
+#ifdef CONFIG_BRCMFMAC_SDIO
+	brcmf_sdio_register();
+#endif
+#ifdef CONFIG_BRCMFMAC_USB
+	brcmf_usb_register();
+#endif
+#ifdef CONFIG_BRCMFMAC_PCIE
+	brcmf_pcie_register();
+#endif
+}
+static DECLARE_WORK(brcmf_driver_work, brcmf_driver_register);
+
+int __init brcmf_core_init(void)
+{
+	if (!schedule_work(&brcmf_driver_work))
+		return -EBUSY;
+
+	return 0;
+}
+
+void __exit brcmf_core_exit(void)
+{
+	cancel_work_sync(&brcmf_driver_work);
+
+#ifdef CONFIG_BRCMFMAC_SDIO
+	brcmf_sdio_exit();
+#endif
+#ifdef CONFIG_BRCMFMAC_USB
+	brcmf_usb_exit();
+#endif
+#ifdef CONFIG_BRCMFMAC_PCIE
+	brcmf_pcie_exit();
+#endif
+}
+
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
new file mode 100644
index 0000000..dcf6e27
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/****************
+ * Common types *
+ */
+
+#ifndef BRCMFMAC_CORE_H
+#define BRCMFMAC_CORE_H
+
+#include <net/cfg80211.h>
+#include "fweh.h"
+
+#define TOE_TX_CSUM_OL		0x00000001
+#define TOE_RX_CSUM_OL		0x00000002
+
+/* For supporting multiple interfaces */
+#define BRCMF_MAX_IFS	16
+
+/* Small, medium and maximum buffer size for dcmd
+ */
+#define BRCMF_DCMD_SMLEN	256
+#define BRCMF_DCMD_MEDLEN	1536
+#define BRCMF_DCMD_MAXLEN	8192
+
+/* IOCTL from host to device are limited in lenght. A device can only handle
+ * ethernet frame size. This limitation is to be applied by protocol layer.
+ */
+#define BRCMF_TX_IOCTL_MAX_MSG_SIZE	(ETH_FRAME_LEN+ETH_FCS_LEN)
+
+#define BRCMF_AMPDU_RX_REORDER_MAXFLOWS		256
+
+/* Length of firmware version string stored for
+ * ethtool driver info which uses 32 bytes as well.
+ */
+#define BRCMF_DRIVER_FIRMWARE_VERSION_LEN	32
+
+#define NDOL_MAX_ENTRIES	8
+
+/**
+ * struct brcmf_ampdu_rx_reorder - AMPDU receive reorder info
+ *
+ * @pktslots: dynamic allocated array for ordering AMPDU packets.
+ * @flow_id: AMPDU flow identifier.
+ * @cur_idx: last AMPDU index from firmware.
+ * @exp_idx: expected next AMPDU index.
+ * @max_idx: maximum amount of packets per AMPDU.
+ * @pend_pkts: number of packets currently in @pktslots.
+ */
+struct brcmf_ampdu_rx_reorder {
+	struct sk_buff **pktslots;
+	u8 flow_id;
+	u8 cur_idx;
+	u8 exp_idx;
+	u8 max_idx;
+	u8 pend_pkts;
+};
+
+/* Forward decls for struct brcmf_pub (see below) */
+struct brcmf_proto;	/* device communication protocol info */
+struct brcmf_fws_info;	/* firmware signalling info */
+struct brcmf_mp_device;	/* module paramateres, device specific */
+
+/*
+ * struct brcmf_rev_info
+ *
+ * The result field stores the error code of the
+ * revision info request from firmware. For the
+ * other fields see struct brcmf_rev_info_le in
+ * fwil_types.h
+ */
+struct brcmf_rev_info {
+	int result;
+	u32 vendorid;
+	u32 deviceid;
+	u32 radiorev;
+	u32 corerev;
+	u32 boardid;
+	u32 boardvendor;
+	u32 boardrev;
+	u32 driverrev;
+	u32 ucoderev;
+	u32 bus;
+	char chipname[12];
+	u32 phytype;
+	u32 phyrev;
+	u32 anarev;
+	u32 chippkg;
+	u32 nvramrev;
+};
+
+/* Common structure for module and instance linkage */
+struct brcmf_pub {
+	/* Linkage ponters */
+	struct brcmf_bus *bus_if;
+	struct brcmf_proto *proto;
+	struct wiphy *wiphy;
+	struct brcmf_cfg80211_info *config;
+
+	/* Internal brcmf items */
+	uint hdrlen;		/* Total BRCMF header length (proto + bus) */
+
+	/* Dongle media info */
+	char fwver[BRCMF_DRIVER_FIRMWARE_VERSION_LEN];
+	u8 mac[ETH_ALEN];		/* MAC address obtained from dongle */
+
+	struct mac_address addresses[BRCMF_MAX_IFS];
+
+	struct brcmf_if *iflist[BRCMF_MAX_IFS];
+	s32 if2bss[BRCMF_MAX_IFS];
+	struct brcmf_if *mon_if;
+
+	struct mutex proto_block;
+	unsigned char proto_buf[BRCMF_DCMD_MAXLEN];
+
+	struct brcmf_fweh_info fweh;
+
+	struct brcmf_ampdu_rx_reorder
+		*reorder_flows[BRCMF_AMPDU_RX_REORDER_MAXFLOWS];
+
+	u32 feat_flags;
+	u32 chip_quirks;
+
+	struct brcmf_rev_info revinfo;
+#ifdef DEBUG
+	struct dentry *dbgfs_dir;
+#endif
+
+	struct notifier_block inetaddr_notifier;
+	struct notifier_block inet6addr_notifier;
+	struct brcmf_mp_device *settings;
+
+	u8 clmver[BRCMF_DCMD_SMLEN];
+};
+
+/* forward declarations */
+struct brcmf_cfg80211_vif;
+struct brcmf_fws_mac_descriptor;
+
+/**
+ * enum brcmf_netif_stop_reason - reason for stopping netif queue.
+ *
+ * @BRCMF_NETIF_STOP_REASON_FWS_FC:
+ *	netif stopped due to firmware signalling flow control.
+ * @BRCMF_NETIF_STOP_REASON_FLOW:
+ *	netif stopped due to flowring full.
+ * @BRCMF_NETIF_STOP_REASON_DISCONNECTED:
+ *	netif stopped due to not being connected (STA mode).
+ */
+enum brcmf_netif_stop_reason {
+	BRCMF_NETIF_STOP_REASON_FWS_FC = BIT(0),
+	BRCMF_NETIF_STOP_REASON_FLOW = BIT(1),
+	BRCMF_NETIF_STOP_REASON_DISCONNECTED = BIT(2)
+};
+
+/**
+ * struct brcmf_if - interface control information.
+ *
+ * @drvr: points to device related information.
+ * @vif: points to cfg80211 specific interface information.
+ * @ndev: associated network device.
+ * @multicast_work: worker object for multicast provisioning.
+ * @ndoffload_work: worker object for neighbor discovery offload configuration.
+ * @fws_desc: interface specific firmware-signalling descriptor.
+ * @ifidx: interface index in device firmware.
+ * @bsscfgidx: index of bss associated with this interface.
+ * @mac_addr: assigned mac address.
+ * @netif_stop: bitmap indicates reason why netif queues are stopped.
+ * @netif_stop_lock: spinlock for update netif_stop from multiple sources.
+ * @pend_8021x_cnt: tracks outstanding number of 802.1x frames.
+ * @pend_8021x_wait: used for signalling change in count.
+ * @fwil_fwerr: flag indicating fwil layer should return firmware error codes.
+ */
+struct brcmf_if {
+	struct brcmf_pub *drvr;
+	struct brcmf_cfg80211_vif *vif;
+	struct net_device *ndev;
+	struct work_struct multicast_work;
+	struct work_struct ndoffload_work;
+	struct brcmf_fws_mac_descriptor *fws_desc;
+	int ifidx;
+	s32 bsscfgidx;
+	u8 mac_addr[ETH_ALEN];
+	u8 netif_stop;
+	spinlock_t netif_stop_lock;
+	atomic_t pend_8021x_cnt;
+	wait_queue_head_t pend_8021x_wait;
+	struct in6_addr ipv6_addr_tbl[NDOL_MAX_ENTRIES];
+	u8 ipv6addr_idx;
+	bool fwil_fwerr;
+};
+
+int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp);
+
+/* Return pointer to interface name */
+char *brcmf_ifname(struct brcmf_if *ifp);
+struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx);
+void brcmf_configure_arp_nd_offload(struct brcmf_if *ifp, bool enable);
+int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
+struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,
+			      bool is_p2pdev, const char *name, u8 *mac_addr);
+void brcmf_remove_interface(struct brcmf_if *ifp, bool rtnl_locked);
+void brcmf_txflowblock_if(struct brcmf_if *ifp,
+			  enum brcmf_netif_stop_reason reason, bool state);
+void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
+void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
+void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb);
+void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on);
+int __init brcmf_core_init(void);
+void __exit brcmf_core_exit(void);
+
+#endif /* BRCMFMAC_CORE_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c
new file mode 100644
index 0000000..489b5df
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/debugfs.h>
+#include <linux/netdevice.h>
+#include <linux/module.h>
+#include <linux/devcoredump.h>
+
+#include <brcmu_wifi.h>
+#include <brcmu_utils.h>
+#include "core.h"
+#include "bus.h"
+#include "fweh.h"
+#include "debug.h"
+
+int brcmf_debug_create_memdump(struct brcmf_bus *bus, const void *data,
+			       size_t len)
+{
+	void *dump;
+	size_t ramsize;
+	int err;
+
+	ramsize = brcmf_bus_get_ramsize(bus);
+	if (!ramsize)
+		return -ENOTSUPP;
+
+	dump = vzalloc(len + ramsize);
+	if (!dump)
+		return -ENOMEM;
+
+	if (data && len > 0)
+		memcpy(dump, data, len);
+	err = brcmf_bus_get_memdump(bus, dump + len, ramsize);
+	if (err) {
+		vfree(dump);
+		return err;
+	}
+
+	dev_coredumpv(bus->dev, dump, len + ramsize, GFP_KERNEL);
+
+	return 0;
+}
+
+struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr)
+{
+	return drvr->wiphy->debugfsdir;
+}
+
+int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
+			    int (*read_fn)(struct seq_file *seq, void *data))
+{
+	struct dentry *e;
+
+	WARN(!drvr->wiphy->debugfsdir, "wiphy not (yet) registered\n");
+	e = debugfs_create_devm_seqfile(drvr->bus_if->dev, fn,
+					drvr->wiphy->debugfsdir, read_fn);
+	return PTR_ERR_OR_ZERO(e);
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
new file mode 100644
index 0000000..cfed062
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef BRCMFMAC_DEBUG_H
+#define BRCMFMAC_DEBUG_H
+
+#include <linux/net.h>	/* net_ratelimit() */
+
+/* message levels */
+#define BRCMF_TRACE_VAL		0x00000002
+#define BRCMF_INFO_VAL		0x00000004
+#define BRCMF_DATA_VAL		0x00000008
+#define BRCMF_CTL_VAL		0x00000010
+#define BRCMF_TIMER_VAL		0x00000020
+#define BRCMF_HDRS_VAL		0x00000040
+#define BRCMF_BYTES_VAL		0x00000080
+#define BRCMF_INTR_VAL		0x00000100
+#define BRCMF_GLOM_VAL		0x00000200
+#define BRCMF_EVENT_VAL		0x00000400
+#define BRCMF_BTA_VAL		0x00000800
+#define BRCMF_FIL_VAL		0x00001000
+#define BRCMF_USB_VAL		0x00002000
+#define BRCMF_SCAN_VAL		0x00004000
+#define BRCMF_CONN_VAL		0x00008000
+#define BRCMF_BCDC_VAL		0x00010000
+#define BRCMF_SDIO_VAL		0x00020000
+#define BRCMF_MSGBUF_VAL	0x00040000
+#define BRCMF_PCIE_VAL		0x00080000
+#define BRCMF_FWCON_VAL		0x00100000
+
+/* set default print format */
+#undef pr_fmt
+#define pr_fmt(fmt)		KBUILD_MODNAME ": " fmt
+
+__printf(2, 3)
+void __brcmf_err(const char *func, const char *fmt, ...);
+/* Macro for error messages. When debugging / tracing the driver all error
+ * messages are important to us.
+ */
+#define brcmf_err(fmt, ...)						\
+	do {								\
+		if (IS_ENABLED(CONFIG_BRCMDBG) ||			\
+		    IS_ENABLED(CONFIG_BRCM_TRACING) ||			\
+		    net_ratelimit())					\
+			__brcmf_err(__func__, fmt, ##__VA_ARGS__);	\
+	} while (0)
+
+#if defined(DEBUG) || defined(CONFIG_BRCM_TRACING)
+
+/* For debug/tracing purposes treat info messages as errors */
+#define brcmf_info brcmf_err
+
+__printf(3, 4)
+void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...);
+#define brcmf_dbg(level, fmt, ...)				\
+do {								\
+	__brcmf_dbg(BRCMF_##level##_VAL, __func__,		\
+		    fmt, ##__VA_ARGS__);			\
+} while (0)
+#define BRCMF_DATA_ON()		(brcmf_msg_level & BRCMF_DATA_VAL)
+#define BRCMF_CTL_ON()		(brcmf_msg_level & BRCMF_CTL_VAL)
+#define BRCMF_HDRS_ON()		(brcmf_msg_level & BRCMF_HDRS_VAL)
+#define BRCMF_BYTES_ON()	(brcmf_msg_level & BRCMF_BYTES_VAL)
+#define BRCMF_GLOM_ON()		(brcmf_msg_level & BRCMF_GLOM_VAL)
+#define BRCMF_EVENT_ON()	(brcmf_msg_level & BRCMF_EVENT_VAL)
+#define BRCMF_FIL_ON()		(brcmf_msg_level & BRCMF_FIL_VAL)
+#define BRCMF_FWCON_ON()	(brcmf_msg_level & BRCMF_FWCON_VAL)
+#define BRCMF_SCAN_ON()		(brcmf_msg_level & BRCMF_SCAN_VAL)
+
+#else /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */
+
+#define brcmf_info(fmt, ...)						\
+	do {								\
+		pr_info("%s: " fmt, __func__, ##__VA_ARGS__);		\
+	} while (0)
+
+#define brcmf_dbg(level, fmt, ...) no_printk(fmt, ##__VA_ARGS__)
+
+#define BRCMF_DATA_ON()		0
+#define BRCMF_CTL_ON()		0
+#define BRCMF_HDRS_ON()		0
+#define BRCMF_BYTES_ON()	0
+#define BRCMF_GLOM_ON()		0
+#define BRCMF_EVENT_ON()	0
+#define BRCMF_FIL_ON()		0
+#define BRCMF_FWCON_ON()	0
+#define BRCMF_SCAN_ON()		0
+
+#endif /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */
+
+#define brcmf_dbg_hex_dump(test, data, len, fmt, ...)			\
+do {									\
+	trace_brcmf_hexdump((void *)data, len);				\
+	if (test)							\
+		brcmu_dbg_hex_dump(data, len, fmt, ##__VA_ARGS__);	\
+} while (0)
+
+extern int brcmf_msg_level;
+
+struct brcmf_bus;
+struct brcmf_pub;
+#ifdef DEBUG
+struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr);
+int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
+			    int (*read_fn)(struct seq_file *seq, void *data));
+int brcmf_debug_create_memdump(struct brcmf_bus *bus, const void *data,
+			       size_t len);
+#else
+static inline
+int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
+			    int (*read_fn)(struct seq_file *seq, void *data))
+{
+	return 0;
+}
+static inline
+int brcmf_debug_create_memdump(struct brcmf_bus *bus, const void *data,
+			       size_t len)
+{
+	return 0;
+}
+#endif
+
+#endif /* BRCMFMAC_DEBUG_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
new file mode 100644
index 0000000..8347da6
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/netdevice.h>
+#include <linux/module.h>
+
+#include <brcm_hw_ids.h>
+#include <brcmu_wifi.h>
+#include "core.h"
+#include "bus.h"
+#include "debug.h"
+#include "fwil.h"
+#include "fwil_types.h"
+#include "feature.h"
+#include "common.h"
+
+#define BRCMF_FW_UNSUPPORTED	23
+
+/*
+ * expand feature list to array of feature strings.
+ */
+#define BRCMF_FEAT_DEF(_f) \
+	#_f,
+static const char *brcmf_feat_names[] = {
+	BRCMF_FEAT_LIST
+};
+#undef BRCMF_FEAT_DEF
+
+struct brcmf_feat_fwcap {
+	enum brcmf_feat_id feature;
+	const char * const fwcap_id;
+};
+
+static const struct brcmf_feat_fwcap brcmf_fwcap_map[] = {
+	{ BRCMF_FEAT_MBSS, "mbss" },
+	{ BRCMF_FEAT_MCHAN, "mchan" },
+	{ BRCMF_FEAT_P2P, "p2p" },
+	{ BRCMF_FEAT_MONITOR, "monitor" },
+	{ BRCMF_FEAT_MONITOR_FMT_RADIOTAP, "rtap" },
+};
+
+#ifdef DEBUG
+/*
+ * expand quirk list to array of quirk strings.
+ */
+#define BRCMF_QUIRK_DEF(_q) \
+	#_q,
+static const char * const brcmf_quirk_names[] = {
+	BRCMF_QUIRK_LIST
+};
+#undef BRCMF_QUIRK_DEF
+
+/**
+ * brcmf_feat_debugfs_read() - expose feature info to debugfs.
+ *
+ * @seq: sequence for debugfs entry.
+ * @data: raw data pointer.
+ */
+static int brcmf_feat_debugfs_read(struct seq_file *seq, void *data)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
+	u32 feats = bus_if->drvr->feat_flags;
+	u32 quirks = bus_if->drvr->chip_quirks;
+	int id;
+
+	seq_printf(seq, "Features: %08x\n", feats);
+	for (id = 0; id < BRCMF_FEAT_LAST; id++)
+		if (feats & BIT(id))
+			seq_printf(seq, "\t%s\n", brcmf_feat_names[id]);
+	seq_printf(seq, "\nQuirks:   %08x\n", quirks);
+	for (id = 0; id < BRCMF_FEAT_QUIRK_LAST; id++)
+		if (quirks & BIT(id))
+			seq_printf(seq, "\t%s\n", brcmf_quirk_names[id]);
+	return 0;
+}
+#else
+static int brcmf_feat_debugfs_read(struct seq_file *seq, void *data)
+{
+	return 0;
+}
+#endif /* DEBUG */
+
+struct brcmf_feat_fwfeat {
+	const char * const fwid;
+	u32 feat_flags;
+};
+
+static const struct brcmf_feat_fwfeat brcmf_feat_fwfeat_map[] = {
+	/* brcmfmac43602-pcie.ap.bin from linux-firmware.git commit ea1178515b88 */
+	{ "01-6cb8e269", BIT(BRCMF_FEAT_MONITOR) },
+	/* brcmfmac4366b-pcie.bin from linux-firmware.git commit 52442afee990 */
+	{ "01-c47a91a4", BIT(BRCMF_FEAT_MONITOR) },
+};
+
+static void brcmf_feat_firmware_overrides(struct brcmf_pub *drv)
+{
+	const struct brcmf_feat_fwfeat *e;
+	u32 feat_flags = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(brcmf_feat_fwfeat_map); i++) {
+		e = &brcmf_feat_fwfeat_map[i];
+		if (!strcmp(e->fwid, drv->fwver)) {
+			feat_flags = e->feat_flags;
+			break;
+		}
+	}
+
+	if (!feat_flags)
+		return;
+
+	for (i = 0; i < BRCMF_FEAT_LAST; i++)
+		if (feat_flags & BIT(i))
+			brcmf_dbg(INFO, "enabling firmware feature: %s\n",
+				  brcmf_feat_names[i]);
+	drv->feat_flags |= feat_flags;
+}
+
+/**
+ * brcmf_feat_iovar_int_get() - determine feature through iovar query.
+ *
+ * @ifp: interface to query.
+ * @id: feature id.
+ * @name: iovar name.
+ */
+static void brcmf_feat_iovar_int_get(struct brcmf_if *ifp,
+				     enum brcmf_feat_id id, char *name)
+{
+	u32 data;
+	int err;
+
+	/* we need to know firmware error */
+	ifp->fwil_fwerr = true;
+
+	err = brcmf_fil_iovar_int_get(ifp, name, &data);
+	if (err == 0) {
+		brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
+		ifp->drvr->feat_flags |= BIT(id);
+	} else {
+		brcmf_dbg(TRACE, "%s feature check failed: %d\n",
+			  brcmf_feat_names[id], err);
+	}
+
+	ifp->fwil_fwerr = false;
+}
+
+static void brcmf_feat_iovar_data_set(struct brcmf_if *ifp,
+				      enum brcmf_feat_id id, char *name,
+				      const void *data, size_t len)
+{
+	int err;
+
+	/* we need to know firmware error */
+	ifp->fwil_fwerr = true;
+
+	err = brcmf_fil_iovar_data_set(ifp, name, data, len);
+	if (err != -BRCMF_FW_UNSUPPORTED) {
+		brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
+		ifp->drvr->feat_flags |= BIT(id);
+	} else {
+		brcmf_dbg(TRACE, "%s feature check failed: %d\n",
+			  brcmf_feat_names[id], err);
+	}
+
+	ifp->fwil_fwerr = false;
+}
+
+#define MAX_CAPS_BUFFER_SIZE	512
+static void brcmf_feat_firmware_capabilities(struct brcmf_if *ifp)
+{
+	char caps[MAX_CAPS_BUFFER_SIZE];
+	enum brcmf_feat_id id;
+	int i, err;
+
+	err = brcmf_fil_iovar_data_get(ifp, "cap", caps, sizeof(caps));
+	if (err) {
+		brcmf_err("could not get firmware cap (%d)\n", err);
+		return;
+	}
+
+	brcmf_dbg(INFO, "[ %s]\n", caps);
+
+	for (i = 0; i < ARRAY_SIZE(brcmf_fwcap_map); i++) {
+		if (strnstr(caps, brcmf_fwcap_map[i].fwcap_id, sizeof(caps))) {
+			id = brcmf_fwcap_map[i].feature;
+			brcmf_dbg(INFO, "enabling feature: %s\n",
+				  brcmf_feat_names[id]);
+			ifp->drvr->feat_flags |= BIT(id);
+		}
+	}
+}
+
+/**
+ * brcmf_feat_fwcap_debugfs_read() - expose firmware capabilities to debugfs.
+ *
+ * @seq: sequence for debugfs entry.
+ * @data: raw data pointer.
+ */
+static int brcmf_feat_fwcap_debugfs_read(struct seq_file *seq, void *data)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
+	struct brcmf_if *ifp = brcmf_get_ifp(bus_if->drvr, 0);
+	char caps[MAX_CAPS_BUFFER_SIZE + 1] = { };
+	char *tmp;
+	int err;
+
+	err = brcmf_fil_iovar_data_get(ifp, "cap", caps, sizeof(caps));
+	if (err) {
+		brcmf_err("could not get firmware cap (%d)\n", err);
+		return err;
+	}
+
+	/* Put every capability in a new line */
+	for (tmp = caps; *tmp; tmp++) {
+		if (*tmp == ' ')
+			*tmp = '\n';
+	}
+
+	/* Usually there is a space at the end of capabilities string */
+	seq_printf(seq, "%s", caps);
+	/* So make sure we don't print two line breaks */
+	if (tmp > caps && *(tmp - 1) != '\n')
+		seq_printf(seq, "\n");
+
+	return 0;
+}
+
+void brcmf_feat_attach(struct brcmf_pub *drvr)
+{
+	struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
+	struct brcmf_pno_macaddr_le pfn_mac;
+	struct brcmf_gscan_config gscan_cfg;
+	u32 wowl_cap;
+	s32 err;
+
+	brcmf_feat_firmware_capabilities(ifp);
+	memset(&gscan_cfg, 0, sizeof(gscan_cfg));
+	if (drvr->bus_if->chip != BRCM_CC_43430_CHIP_ID &&
+	    drvr->bus_if->chip != BRCM_CC_4345_CHIP_ID)
+		brcmf_feat_iovar_data_set(ifp, BRCMF_FEAT_GSCAN,
+					  "pfn_gscan_cfg",
+					  &gscan_cfg, sizeof(gscan_cfg));
+	brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_PNO, "pfn");
+	if (drvr->bus_if->wowl_supported)
+		brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl");
+	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL)) {
+		err = brcmf_fil_iovar_int_get(ifp, "wowl_cap", &wowl_cap);
+		if (!err) {
+			ifp->drvr->feat_flags |= BIT(BRCMF_FEAT_WOWL_ARP_ND);
+			if (wowl_cap & BRCMF_WOWL_PFN_FOUND)
+				ifp->drvr->feat_flags |=
+					BIT(BRCMF_FEAT_WOWL_ND);
+			if (wowl_cap & BRCMF_WOWL_GTK_FAILURE)
+				ifp->drvr->feat_flags |=
+					BIT(BRCMF_FEAT_WOWL_GTK);
+		}
+	}
+	/* MBSS does not work for 43362 */
+	if (drvr->bus_if->chip == BRCM_CC_43362_CHIP_ID)
+		ifp->drvr->feat_flags &= ~BIT(BRCMF_FEAT_MBSS);
+	brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_RSDB, "rsdb_mode");
+	brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_TDLS, "tdls_enable");
+	brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MFP, "mfp");
+
+	pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER;
+	err = brcmf_fil_iovar_data_get(ifp, "pfn_macaddr", &pfn_mac,
+				       sizeof(pfn_mac));
+	if (!err)
+		ifp->drvr->feat_flags |= BIT(BRCMF_FEAT_SCAN_RANDOM_MAC);
+
+	if (drvr->settings->feature_disable) {
+		brcmf_dbg(INFO, "Features: 0x%02x, disable: 0x%02x\n",
+			  ifp->drvr->feat_flags,
+			  drvr->settings->feature_disable);
+		ifp->drvr->feat_flags &= ~drvr->settings->feature_disable;
+	}
+	brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_FWSUP, "sup_wpa");
+
+	brcmf_feat_firmware_overrides(drvr);
+
+	/* set chip related quirks */
+	switch (drvr->bus_if->chip) {
+	case BRCM_CC_43236_CHIP_ID:
+		drvr->chip_quirks |= BIT(BRCMF_FEAT_QUIRK_AUTO_AUTH);
+		break;
+	case BRCM_CC_4329_CHIP_ID:
+		drvr->chip_quirks |= BIT(BRCMF_FEAT_QUIRK_NEED_MPC);
+		break;
+	default:
+		/* no quirks */
+		break;
+	}
+}
+
+void brcmf_feat_debugfs_create(struct brcmf_pub *drvr)
+{
+	brcmf_debugfs_add_entry(drvr, "features", brcmf_feat_debugfs_read);
+	brcmf_debugfs_add_entry(drvr, "fwcap", brcmf_feat_fwcap_debugfs_read);
+}
+
+bool brcmf_feat_is_enabled(struct brcmf_if *ifp, enum brcmf_feat_id id)
+{
+	return (ifp->drvr->feat_flags & BIT(id));
+}
+
+bool brcmf_feat_is_quirk_enabled(struct brcmf_if *ifp,
+				 enum brcmf_feat_quirk quirk)
+{
+	return (ifp->drvr->chip_quirks & BIT(quirk));
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
new file mode 100644
index 0000000..0b4974d
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef _BRCMF_FEATURE_H
+#define _BRCMF_FEATURE_H
+
+/*
+ * Features:
+ *
+ * MBSS: multiple BSSID support (eg. guest network in AP mode).
+ * MCHAN: multi-channel for concurrent P2P.
+ * PNO: preferred network offload.
+ * WOWL: Wake-On-WLAN.
+ * P2P: peer-to-peer
+ * RSDB: Real Simultaneous Dual Band
+ * TDLS: Tunneled Direct Link Setup
+ * SCAN_RANDOM_MAC: Random MAC during (net detect) scheduled scan.
+ * WOWL_ND: WOWL net detect (PNO)
+ * WOWL_GTK: (WOWL) GTK rekeying offload
+ * WOWL_ARP_ND: ARP and Neighbor Discovery offload support during WOWL.
+ * MFP: 802.11w Management Frame Protection.
+ * GSCAN: enhanced scan offload feature.
+ * FWSUP: Firmware supplicant.
+ * MONITOR: firmware can pass monitor packets to host.
+ * MONITOR_FMT_RADIOTAP: firmware provides monitor packets with radiotap header
+ */
+#define BRCMF_FEAT_LIST \
+	BRCMF_FEAT_DEF(MBSS) \
+	BRCMF_FEAT_DEF(MCHAN) \
+	BRCMF_FEAT_DEF(PNO) \
+	BRCMF_FEAT_DEF(WOWL) \
+	BRCMF_FEAT_DEF(P2P) \
+	BRCMF_FEAT_DEF(RSDB) \
+	BRCMF_FEAT_DEF(TDLS) \
+	BRCMF_FEAT_DEF(SCAN_RANDOM_MAC) \
+	BRCMF_FEAT_DEF(WOWL_ND) \
+	BRCMF_FEAT_DEF(WOWL_GTK) \
+	BRCMF_FEAT_DEF(WOWL_ARP_ND) \
+	BRCMF_FEAT_DEF(MFP) \
+	BRCMF_FEAT_DEF(GSCAN) \
+	BRCMF_FEAT_DEF(FWSUP) \
+	BRCMF_FEAT_DEF(MONITOR) \
+	BRCMF_FEAT_DEF(MONITOR_FMT_RADIOTAP)
+
+/*
+ * Quirks:
+ *
+ * AUTO_AUTH: workaround needed for automatic authentication type.
+ * NEED_MPC: driver needs to disable MPC during scanning operation.
+ */
+#define BRCMF_QUIRK_LIST \
+	BRCMF_QUIRK_DEF(AUTO_AUTH) \
+	BRCMF_QUIRK_DEF(NEED_MPC)
+
+#define BRCMF_FEAT_DEF(_f) \
+	BRCMF_FEAT_ ## _f,
+/*
+ * expand feature list to enumeration.
+ */
+enum brcmf_feat_id {
+	BRCMF_FEAT_LIST
+	BRCMF_FEAT_LAST
+};
+#undef BRCMF_FEAT_DEF
+
+#define BRCMF_QUIRK_DEF(_q) \
+	BRCMF_FEAT_QUIRK_ ## _q,
+/*
+ * expand quirk list to enumeration.
+ */
+enum brcmf_feat_quirk {
+	BRCMF_QUIRK_LIST
+	BRCMF_FEAT_QUIRK_LAST
+};
+#undef BRCMF_QUIRK_DEF
+
+/**
+ * brcmf_feat_attach() - determine features and quirks.
+ *
+ * @drvr: driver instance.
+ */
+void brcmf_feat_attach(struct brcmf_pub *drvr);
+
+/**
+ * brcmf_feat_debugfs_create() - create debugfs entries.
+ *
+ * @drvr: driver instance.
+ */
+void brcmf_feat_debugfs_create(struct brcmf_pub *drvr);
+
+/**
+ * brcmf_feat_is_enabled() - query feature.
+ *
+ * @ifp: interface instance.
+ * @id: feature id to check.
+ *
+ * Return: true is feature is enabled; otherwise false.
+ */
+bool brcmf_feat_is_enabled(struct brcmf_if *ifp, enum brcmf_feat_id id);
+
+/**
+ * brcmf_feat_is_quirk_enabled() - query chip quirk.
+ *
+ * @ifp: interface instance.
+ * @quirk: quirk id to check.
+ *
+ * Return: true is quirk is enabled; otherwise false.
+ */
+bool brcmf_feat_is_quirk_enabled(struct brcmf_if *ifp,
+				 enum brcmf_feat_quirk quirk);
+
+#endif /* _BRCMF_FEATURE_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
new file mode 100644
index 0000000..9095b83
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
@@ -0,0 +1,693 @@
+/*
+ * Copyright (c) 2013 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/module.h>
+#include <linux/bcm47xx_nvram.h>
+
+#include "debug.h"
+#include "firmware.h"
+#include "core.h"
+#include "common.h"
+#include "chip.h"
+
+#define BRCMF_FW_MAX_NVRAM_SIZE			64000
+#define BRCMF_FW_NVRAM_DEVPATH_LEN		19	/* devpath0=pcie/1/4/ */
+#define BRCMF_FW_NVRAM_PCIEDEV_LEN		10	/* pcie/1/4/ + \0 */
+#define BRCMF_FW_DEFAULT_BOARDREV		"boardrev=0xff"
+
+enum nvram_parser_state {
+	IDLE,
+	KEY,
+	VALUE,
+	COMMENT,
+	END
+};
+
+/**
+ * struct nvram_parser - internal info for parser.
+ *
+ * @state: current parser state.
+ * @data: input buffer being parsed.
+ * @nvram: output buffer with parse result.
+ * @nvram_len: lenght of parse result.
+ * @line: current line.
+ * @column: current column in line.
+ * @pos: byte offset in input buffer.
+ * @entry: start position of key,value entry.
+ * @multi_dev_v1: detect pcie multi device v1 (compressed).
+ * @multi_dev_v2: detect pcie multi device v2.
+ * @boardrev_found: nvram contains boardrev information.
+ */
+struct nvram_parser {
+	enum nvram_parser_state state;
+	const u8 *data;
+	u8 *nvram;
+	u32 nvram_len;
+	u32 line;
+	u32 column;
+	u32 pos;
+	u32 entry;
+	bool multi_dev_v1;
+	bool multi_dev_v2;
+	bool boardrev_found;
+};
+
+/**
+ * is_nvram_char() - check if char is a valid one for NVRAM entry
+ *
+ * It accepts all printable ASCII chars except for '#' which opens a comment.
+ * Please note that ' ' (space) while accepted is not a valid key name char.
+ */
+static bool is_nvram_char(char c)
+{
+	/* comment marker excluded */
+	if (c == '#')
+		return false;
+
+	/* key and value may have any other readable character */
+	return (c >= 0x20 && c < 0x7f);
+}
+
+static bool is_whitespace(char c)
+{
+	return (c == ' ' || c == '\r' || c == '\n' || c == '\t');
+}
+
+static enum nvram_parser_state brcmf_nvram_handle_idle(struct nvram_parser *nvp)
+{
+	char c;
+
+	c = nvp->data[nvp->pos];
+	if (c == '\n')
+		return COMMENT;
+	if (is_whitespace(c) || c == '\0')
+		goto proceed;
+	if (c == '#')
+		return COMMENT;
+	if (is_nvram_char(c)) {
+		nvp->entry = nvp->pos;
+		return KEY;
+	}
+	brcmf_dbg(INFO, "warning: ln=%d:col=%d: ignoring invalid character\n",
+		  nvp->line, nvp->column);
+proceed:
+	nvp->column++;
+	nvp->pos++;
+	return IDLE;
+}
+
+static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp)
+{
+	enum nvram_parser_state st = nvp->state;
+	char c;
+
+	c = nvp->data[nvp->pos];
+	if (c == '=') {
+		/* ignore RAW1 by treating as comment */
+		if (strncmp(&nvp->data[nvp->entry], "RAW1", 4) == 0)
+			st = COMMENT;
+		else
+			st = VALUE;
+		if (strncmp(&nvp->data[nvp->entry], "devpath", 7) == 0)
+			nvp->multi_dev_v1 = true;
+		if (strncmp(&nvp->data[nvp->entry], "pcie/", 5) == 0)
+			nvp->multi_dev_v2 = true;
+		if (strncmp(&nvp->data[nvp->entry], "boardrev", 8) == 0)
+			nvp->boardrev_found = true;
+	} else if (!is_nvram_char(c) || c == ' ') {
+		brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
+			  nvp->line, nvp->column);
+		return COMMENT;
+	}
+
+	nvp->column++;
+	nvp->pos++;
+	return st;
+}
+
+static enum nvram_parser_state
+brcmf_nvram_handle_value(struct nvram_parser *nvp)
+{
+	char c;
+	char *skv;
+	char *ekv;
+	u32 cplen;
+
+	c = nvp->data[nvp->pos];
+	if (!is_nvram_char(c)) {
+		/* key,value pair complete */
+		ekv = (u8 *)&nvp->data[nvp->pos];
+		skv = (u8 *)&nvp->data[nvp->entry];
+		cplen = ekv - skv;
+		if (nvp->nvram_len + cplen + 1 >= BRCMF_FW_MAX_NVRAM_SIZE)
+			return END;
+		/* copy to output buffer */
+		memcpy(&nvp->nvram[nvp->nvram_len], skv, cplen);
+		nvp->nvram_len += cplen;
+		nvp->nvram[nvp->nvram_len] = '\0';
+		nvp->nvram_len++;
+		return IDLE;
+	}
+	nvp->pos++;
+	nvp->column++;
+	return VALUE;
+}
+
+static enum nvram_parser_state
+brcmf_nvram_handle_comment(struct nvram_parser *nvp)
+{
+	char *eoc, *sol;
+
+	sol = (char *)&nvp->data[nvp->pos];
+	eoc = strchr(sol, '\n');
+	if (!eoc) {
+		eoc = strchr(sol, '\0');
+		if (!eoc)
+			return END;
+	}
+
+	/* eat all moving to next line */
+	nvp->line++;
+	nvp->column = 1;
+	nvp->pos += (eoc - sol) + 1;
+	return IDLE;
+}
+
+static enum nvram_parser_state brcmf_nvram_handle_end(struct nvram_parser *nvp)
+{
+	/* final state */
+	return END;
+}
+
+static enum nvram_parser_state
+(*nv_parser_states[])(struct nvram_parser *nvp) = {
+	brcmf_nvram_handle_idle,
+	brcmf_nvram_handle_key,
+	brcmf_nvram_handle_value,
+	brcmf_nvram_handle_comment,
+	brcmf_nvram_handle_end
+};
+
+static int brcmf_init_nvram_parser(struct nvram_parser *nvp,
+				   const u8 *data, size_t data_len)
+{
+	size_t size;
+
+	memset(nvp, 0, sizeof(*nvp));
+	nvp->data = data;
+	/* Limit size to MAX_NVRAM_SIZE, some files contain lot of comment */
+	if (data_len > BRCMF_FW_MAX_NVRAM_SIZE)
+		size = BRCMF_FW_MAX_NVRAM_SIZE;
+	else
+		size = data_len;
+	/* Alloc for extra 0 byte + roundup by 4 + length field */
+	size += 1 + 3 + sizeof(u32);
+	nvp->nvram = kzalloc(size, GFP_KERNEL);
+	if (!nvp->nvram)
+		return -ENOMEM;
+
+	nvp->line = 1;
+	nvp->column = 1;
+	return 0;
+}
+
+/* brcmf_fw_strip_multi_v1 :Some nvram files contain settings for multiple
+ * devices. Strip it down for one device, use domain_nr/bus_nr to determine
+ * which data is to be returned. v1 is the version where nvram is stored
+ * compressed and "devpath" maps to index for valid entries.
+ */
+static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
+				    u16 bus_nr)
+{
+	/* Device path with a leading '=' key-value separator */
+	char pci_path[] = "=pci/?/?";
+	size_t pci_len;
+	char pcie_path[] = "=pcie/?/?";
+	size_t pcie_len;
+
+	u32 i, j;
+	bool found;
+	u8 *nvram;
+	u8 id;
+
+	nvram = kzalloc(nvp->nvram_len + 1 + 3 + sizeof(u32), GFP_KERNEL);
+	if (!nvram)
+		goto fail;
+
+	/* min length: devpath0=pcie/1/4/ + 0:x=y */
+	if (nvp->nvram_len < BRCMF_FW_NVRAM_DEVPATH_LEN + 6)
+		goto fail;
+
+	/* First search for the devpathX and see if it is the configuration
+	 * for domain_nr/bus_nr. Search complete nvp
+	 */
+	snprintf(pci_path, sizeof(pci_path), "=pci/%d/%d", domain_nr,
+		 bus_nr);
+	pci_len = strlen(pci_path);
+	snprintf(pcie_path, sizeof(pcie_path), "=pcie/%d/%d", domain_nr,
+		 bus_nr);
+	pcie_len = strlen(pcie_path);
+	found = false;
+	i = 0;
+	while (i < nvp->nvram_len - BRCMF_FW_NVRAM_DEVPATH_LEN) {
+		/* Format: devpathX=pcie/Y/Z/
+		 * Y = domain_nr, Z = bus_nr, X = virtual ID
+		 */
+		if (strncmp(&nvp->nvram[i], "devpath", 7) == 0 &&
+		    (!strncmp(&nvp->nvram[i + 8], pci_path, pci_len) ||
+		     !strncmp(&nvp->nvram[i + 8], pcie_path, pcie_len))) {
+			id = nvp->nvram[i + 7] - '0';
+			found = true;
+			break;
+		}
+		while (nvp->nvram[i] != 0)
+			i++;
+		i++;
+	}
+	if (!found)
+		goto fail;
+
+	/* Now copy all valid entries, release old nvram and assign new one */
+	i = 0;
+	j = 0;
+	while (i < nvp->nvram_len) {
+		if ((nvp->nvram[i] - '0' == id) && (nvp->nvram[i + 1] == ':')) {
+			i += 2;
+			if (strncmp(&nvp->nvram[i], "boardrev", 8) == 0)
+				nvp->boardrev_found = true;
+			while (nvp->nvram[i] != 0) {
+				nvram[j] = nvp->nvram[i];
+				i++;
+				j++;
+			}
+			nvram[j] = 0;
+			j++;
+		}
+		while (nvp->nvram[i] != 0)
+			i++;
+		i++;
+	}
+	kfree(nvp->nvram);
+	nvp->nvram = nvram;
+	nvp->nvram_len = j;
+	return;
+
+fail:
+	kfree(nvram);
+	nvp->nvram_len = 0;
+}
+
+/* brcmf_fw_strip_multi_v2 :Some nvram files contain settings for multiple
+ * devices. Strip it down for one device, use domain_nr/bus_nr to determine
+ * which data is to be returned. v2 is the version where nvram is stored
+ * uncompressed, all relevant valid entries are identified by
+ * pcie/domain_nr/bus_nr:
+ */
+static void brcmf_fw_strip_multi_v2(struct nvram_parser *nvp, u16 domain_nr,
+				    u16 bus_nr)
+{
+	char prefix[BRCMF_FW_NVRAM_PCIEDEV_LEN];
+	size_t len;
+	u32 i, j;
+	u8 *nvram;
+
+	nvram = kzalloc(nvp->nvram_len + 1 + 3 + sizeof(u32), GFP_KERNEL);
+	if (!nvram)
+		goto fail;
+
+	/* Copy all valid entries, release old nvram and assign new one.
+	 * Valid entries are of type pcie/X/Y/ where X = domain_nr and
+	 * Y = bus_nr.
+	 */
+	snprintf(prefix, sizeof(prefix), "pcie/%d/%d/", domain_nr, bus_nr);
+	len = strlen(prefix);
+	i = 0;
+	j = 0;
+	while (i < nvp->nvram_len - len) {
+		if (strncmp(&nvp->nvram[i], prefix, len) == 0) {
+			i += len;
+			if (strncmp(&nvp->nvram[i], "boardrev", 8) == 0)
+				nvp->boardrev_found = true;
+			while (nvp->nvram[i] != 0) {
+				nvram[j] = nvp->nvram[i];
+				i++;
+				j++;
+			}
+			nvram[j] = 0;
+			j++;
+		}
+		while (nvp->nvram[i] != 0)
+			i++;
+		i++;
+	}
+	kfree(nvp->nvram);
+	nvp->nvram = nvram;
+	nvp->nvram_len = j;
+	return;
+fail:
+	kfree(nvram);
+	nvp->nvram_len = 0;
+}
+
+static void brcmf_fw_add_defaults(struct nvram_parser *nvp)
+{
+	if (nvp->boardrev_found)
+		return;
+
+	memcpy(&nvp->nvram[nvp->nvram_len], &BRCMF_FW_DEFAULT_BOARDREV,
+	       strlen(BRCMF_FW_DEFAULT_BOARDREV));
+	nvp->nvram_len += strlen(BRCMF_FW_DEFAULT_BOARDREV);
+	nvp->nvram[nvp->nvram_len] = '\0';
+	nvp->nvram_len++;
+}
+
+/* brcmf_nvram_strip :Takes a buffer of "<var>=<value>\n" lines read from a fil
+ * and ending in a NUL. Removes carriage returns, empty lines, comment lines,
+ * and converts newlines to NULs. Shortens buffer as needed and pads with NULs.
+ * End of buffer is completed with token identifying length of buffer.
+ */
+static void *brcmf_fw_nvram_strip(const u8 *data, size_t data_len,
+				  u32 *new_length, u16 domain_nr, u16 bus_nr)
+{
+	struct nvram_parser nvp;
+	u32 pad;
+	u32 token;
+	__le32 token_le;
+
+	if (brcmf_init_nvram_parser(&nvp, data, data_len) < 0)
+		return NULL;
+
+	while (nvp.pos < data_len) {
+		nvp.state = nv_parser_states[nvp.state](&nvp);
+		if (nvp.state == END)
+			break;
+	}
+	if (nvp.multi_dev_v1) {
+		nvp.boardrev_found = false;
+		brcmf_fw_strip_multi_v1(&nvp, domain_nr, bus_nr);
+	} else if (nvp.multi_dev_v2) {
+		nvp.boardrev_found = false;
+		brcmf_fw_strip_multi_v2(&nvp, domain_nr, bus_nr);
+	}
+
+	if (nvp.nvram_len == 0) {
+		kfree(nvp.nvram);
+		return NULL;
+	}
+
+	brcmf_fw_add_defaults(&nvp);
+
+	pad = nvp.nvram_len;
+	*new_length = roundup(nvp.nvram_len + 1, 4);
+	while (pad != *new_length) {
+		nvp.nvram[pad] = 0;
+		pad++;
+	}
+
+	token = *new_length / 4;
+	token = (~token << 16) | (token & 0x0000FFFF);
+	token_le = cpu_to_le32(token);
+
+	memcpy(&nvp.nvram[*new_length], &token_le, sizeof(token_le));
+	*new_length += sizeof(token_le);
+
+	return nvp.nvram;
+}
+
+void brcmf_fw_nvram_free(void *nvram)
+{
+	kfree(nvram);
+}
+
+struct brcmf_fw {
+	struct device *dev;
+	struct brcmf_fw_request *req;
+	u32 curpos;
+	void (*done)(struct device *dev, int err, struct brcmf_fw_request *req);
+};
+
+static void brcmf_fw_request_done(const struct firmware *fw, void *ctx);
+
+static void brcmf_fw_free_request(struct brcmf_fw_request *req)
+{
+	struct brcmf_fw_item *item;
+	int i;
+
+	for (i = 0, item = &req->items[0]; i < req->n_items; i++, item++) {
+		if (item->type == BRCMF_FW_TYPE_BINARY)
+			release_firmware(item->binary);
+		else if (item->type == BRCMF_FW_TYPE_NVRAM)
+			brcmf_fw_nvram_free(item->nv_data.data);
+	}
+	kfree(req);
+}
+
+static int brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
+{
+	struct brcmf_fw *fwctx = ctx;
+	struct brcmf_fw_item *cur;
+	u32 nvram_length = 0;
+	void *nvram = NULL;
+	u8 *data = NULL;
+	size_t data_len;
+	bool raw_nvram;
+
+	brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
+
+	cur = &fwctx->req->items[fwctx->curpos];
+
+	if (fw && fw->data) {
+		data = (u8 *)fw->data;
+		data_len = fw->size;
+		raw_nvram = false;
+	} else {
+		data = bcm47xx_nvram_get_contents(&data_len);
+		if (!data && !(cur->flags & BRCMF_FW_REQF_OPTIONAL))
+			goto fail;
+		raw_nvram = true;
+	}
+
+	if (data)
+		nvram = brcmf_fw_nvram_strip(data, data_len, &nvram_length,
+					     fwctx->req->domain_nr,
+					     fwctx->req->bus_nr);
+
+	if (raw_nvram)
+		bcm47xx_nvram_release_contents(data);
+	release_firmware(fw);
+	if (!nvram && !(cur->flags & BRCMF_FW_REQF_OPTIONAL))
+		goto fail;
+
+	brcmf_dbg(TRACE, "nvram %p len %d\n", nvram, nvram_length);
+	cur->nv_data.data = nvram;
+	cur->nv_data.len = nvram_length;
+	return 0;
+
+fail:
+	return -ENOENT;
+}
+
+static int brcmf_fw_request_next_item(struct brcmf_fw *fwctx, bool async)
+{
+	struct brcmf_fw_item *cur;
+	const struct firmware *fw = NULL;
+	int ret;
+
+	cur = &fwctx->req->items[fwctx->curpos];
+
+	brcmf_dbg(TRACE, "%srequest for %s\n", async ? "async " : "",
+		  cur->path);
+
+	if (async)
+		ret = request_firmware_nowait(THIS_MODULE, true, cur->path,
+					      fwctx->dev, GFP_KERNEL, fwctx,
+					      brcmf_fw_request_done);
+	else
+		ret = request_firmware(&fw, cur->path, fwctx->dev);
+
+	if (ret < 0) {
+		brcmf_fw_request_done(NULL, fwctx);
+	} else if (!async && fw) {
+		brcmf_dbg(TRACE, "firmware %s %sfound\n", cur->path,
+			  fw ? "" : "not ");
+		if (cur->type == BRCMF_FW_TYPE_BINARY)
+			cur->binary = fw;
+		else if (cur->type == BRCMF_FW_TYPE_NVRAM)
+			brcmf_fw_request_nvram_done(fw, fwctx);
+		else
+			release_firmware(fw);
+
+		return -EAGAIN;
+	}
+	return 0;
+}
+
+static void brcmf_fw_request_done(const struct firmware *fw, void *ctx)
+{
+	struct brcmf_fw *fwctx = ctx;
+	struct brcmf_fw_item *cur;
+	int ret = 0;
+
+	cur = &fwctx->req->items[fwctx->curpos];
+
+	brcmf_dbg(TRACE, "enter: firmware %s %sfound\n", cur->path,
+		  fw ? "" : "not ");
+
+	if (!fw)
+		ret = -ENOENT;
+
+	switch (cur->type) {
+	case BRCMF_FW_TYPE_NVRAM:
+		ret = brcmf_fw_request_nvram_done(fw, fwctx);
+		break;
+	case BRCMF_FW_TYPE_BINARY:
+		cur->binary = fw;
+		break;
+	default:
+		/* something fishy here so bail out early */
+		brcmf_err("unknown fw type: %d\n", cur->type);
+		release_firmware(fw);
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	if (ret < 0 && !(cur->flags & BRCMF_FW_REQF_OPTIONAL))
+		goto fail;
+
+	do {
+		if (++fwctx->curpos == fwctx->req->n_items) {
+			ret = 0;
+			goto done;
+		}
+
+		ret = brcmf_fw_request_next_item(fwctx, false);
+	} while (ret == -EAGAIN);
+
+	return;
+
+fail:
+	brcmf_dbg(TRACE, "failed err=%d: dev=%s, fw=%s\n", ret,
+		  dev_name(fwctx->dev), cur->path);
+	brcmf_fw_free_request(fwctx->req);
+	fwctx->req = NULL;
+done:
+	fwctx->done(fwctx->dev, ret, fwctx->req);
+	kfree(fwctx);
+}
+
+static bool brcmf_fw_request_is_valid(struct brcmf_fw_request *req)
+{
+	struct brcmf_fw_item *item;
+	int i;
+
+	if (!req->n_items)
+		return false;
+
+	for (i = 0, item = &req->items[0]; i < req->n_items; i++, item++) {
+		if (!item->path)
+			return false;
+	}
+	return true;
+}
+
+int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,
+			   void (*fw_cb)(struct device *dev, int err,
+					 struct brcmf_fw_request *req))
+{
+	struct brcmf_fw *fwctx;
+
+	brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
+	if (!fw_cb)
+		return -EINVAL;
+
+	if (!brcmf_fw_request_is_valid(req))
+		return -EINVAL;
+
+	fwctx = kzalloc(sizeof(*fwctx), GFP_KERNEL);
+	if (!fwctx)
+		return -ENOMEM;
+
+	fwctx->dev = dev;
+	fwctx->req = req;
+	fwctx->done = fw_cb;
+
+	brcmf_fw_request_next_item(fwctx, true);
+	return 0;
+}
+
+struct brcmf_fw_request *
+brcmf_fw_alloc_request(u32 chip, u32 chiprev,
+		       const struct brcmf_firmware_mapping mapping_table[],
+		       u32 table_size, struct brcmf_fw_name *fwnames,
+		       u32 n_fwnames)
+{
+	struct brcmf_fw_request *fwreq;
+	char chipname[12];
+	const char *mp_path;
+	u32 i, j;
+	char end;
+	size_t reqsz;
+
+	for (i = 0; i < table_size; i++) {
+		if (mapping_table[i].chipid == chip &&
+		    mapping_table[i].revmask & BIT(chiprev))
+			break;
+	}
+
+	if (i == table_size) {
+		brcmf_err("Unknown chipid %d [%d]\n", chip, chiprev);
+		return NULL;
+	}
+
+	reqsz = sizeof(*fwreq) + n_fwnames * sizeof(struct brcmf_fw_item);
+	fwreq = kzalloc(reqsz, GFP_KERNEL);
+	if (!fwreq)
+		return NULL;
+
+	brcmf_chip_name(chip, chiprev, chipname, sizeof(chipname));
+
+	brcmf_info("using %s for chip %s\n",
+		   mapping_table[i].fw_base, chipname);
+
+	mp_path = brcmf_mp_global.firmware_path;
+	end = mp_path[strlen(mp_path) - 1];
+	fwreq->n_items = n_fwnames;
+
+	for (j = 0; j < n_fwnames; j++) {
+		fwreq->items[j].path = fwnames[j].path;
+		/* check if firmware path is provided by module parameter */
+		if (brcmf_mp_global.firmware_path[0] != '\0') {
+			strlcpy(fwnames[j].path, mp_path,
+				BRCMF_FW_NAME_LEN);
+
+			if (end != '/') {
+				strlcat(fwnames[j].path, "/",
+					BRCMF_FW_NAME_LEN);
+			}
+		}
+		strlcat(fwnames[j].path, mapping_table[i].fw_base,
+			BRCMF_FW_NAME_LEN);
+		strlcat(fwnames[j].path, fwnames[j].extension,
+			BRCMF_FW_NAME_LEN);
+		fwreq->items[j].path = fwnames[j].path;
+	}
+
+	return fwreq;
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
new file mode 100644
index 0000000..2893e56
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2013 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef BRCMFMAC_FIRMWARE_H
+#define BRCMFMAC_FIRMWARE_H
+
+#define BRCMF_FW_REQF_OPTIONAL		0x0001
+
+#define	BRCMF_FW_NAME_LEN		320
+
+#define BRCMF_FW_DEFAULT_PATH		"brcm/"
+
+/**
+ * struct brcmf_firmware_mapping - Used to map chipid/revmask to firmware
+ *	filename and nvram filename. Each bus type implementation should create
+ *	a table of firmware mappings (using the macros defined below).
+ *
+ * @chipid: ID of chip.
+ * @revmask: bitmask of revisions, e.g. 0x10 means rev 4 only, 0xf means rev 0-3
+ * @fw: name of the firmware file.
+ * @nvram: name of nvram file.
+ */
+struct brcmf_firmware_mapping {
+	u32 chipid;
+	u32 revmask;
+	const char *fw_base;
+};
+
+#define BRCMF_FW_DEF(fw_name, fw_base) \
+static const char BRCM_ ## fw_name ## _FIRMWARE_BASENAME[] = \
+	BRCMF_FW_DEFAULT_PATH fw_base; \
+MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH fw_base ".bin")
+
+#define BRCMF_FW_ENTRY(chipid, mask, name) \
+	{ chipid, mask, BRCM_ ## name ## _FIRMWARE_BASENAME }
+
+void brcmf_fw_nvram_free(void *nvram);
+
+enum brcmf_fw_type {
+	BRCMF_FW_TYPE_BINARY,
+	BRCMF_FW_TYPE_NVRAM
+};
+
+struct brcmf_fw_item {
+	const char *path;
+	enum brcmf_fw_type type;
+	u16 flags;
+	union {
+		const struct firmware *binary;
+		struct {
+			void *data;
+			u32 len;
+		} nv_data;
+	};
+};
+
+struct brcmf_fw_request {
+	u16 domain_nr;
+	u16 bus_nr;
+	u32 n_items;
+	struct brcmf_fw_item items[0];
+};
+
+struct brcmf_fw_name {
+	const char *extension;
+	char *path;
+};
+
+struct brcmf_fw_request *
+brcmf_fw_alloc_request(u32 chip, u32 chiprev,
+		       const struct brcmf_firmware_mapping mapping_table[],
+		       u32 table_size, struct brcmf_fw_name *fwnames,
+		       u32 n_fwnames);
+
+/*
+ * Request firmware(s) asynchronously. When the asynchronous request
+ * fails it will not use the callback, but call device_release_driver()
+ * instead which will call the driver .remove() callback.
+ */
+int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,
+			   void (*fw_cb)(struct device *dev, int err,
+					 struct brcmf_fw_request *req));
+
+#endif /* BRCMFMAC_FIRMWARE_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c
new file mode 100644
index 0000000..d0d8b32
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c
@@ -0,0 +1,521 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <brcmu_utils.h>
+
+#include "core.h"
+#include "debug.h"
+#include "bus.h"
+#include "proto.h"
+#include "flowring.h"
+#include "msgbuf.h"
+#include "common.h"
+
+
+#define BRCMF_FLOWRING_HIGH		1024
+#define BRCMF_FLOWRING_LOW		(BRCMF_FLOWRING_HIGH - 256)
+#define BRCMF_FLOWRING_INVALID_IFIDX	0xff
+
+#define BRCMF_FLOWRING_HASH_AP(da, fifo, ifidx) (da[5] * 2 + fifo + ifidx * 16)
+#define BRCMF_FLOWRING_HASH_STA(fifo, ifidx) (fifo + ifidx * 16)
+
+static const u8 brcmf_flowring_prio2fifo[] = {
+	1,
+	0,
+	0,
+	1,
+	2,
+	2,
+	3,
+	3
+};
+
+static const u8 ALLFFMAC[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+
+static bool
+brcmf_flowring_is_tdls_mac(struct brcmf_flowring *flow, u8 mac[ETH_ALEN])
+{
+	struct brcmf_flowring_tdls_entry *search;
+
+	search = flow->tdls_entry;
+
+	while (search) {
+		if (memcmp(search->mac, mac, ETH_ALEN) == 0)
+			return true;
+		search = search->next;
+	}
+
+	return false;
+}
+
+
+u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
+			  u8 prio, u8 ifidx)
+{
+	struct brcmf_flowring_hash *hash;
+	u16 hash_idx;
+	u32 i;
+	bool found;
+	bool sta;
+	u8 fifo;
+	u8 *mac;
+
+	fifo = brcmf_flowring_prio2fifo[prio];
+	sta = (flow->addr_mode[ifidx] == ADDR_INDIRECT);
+	mac = da;
+	if ((!sta) && (is_multicast_ether_addr(da))) {
+		mac = (u8 *)ALLFFMAC;
+		fifo = 0;
+	}
+	if ((sta) && (flow->tdls_active) &&
+	    (brcmf_flowring_is_tdls_mac(flow, da))) {
+		sta = false;
+	}
+	hash_idx =  sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) :
+			  BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx);
+	hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1);
+	found = false;
+	hash = flow->hash;
+	for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
+		if ((sta || (memcmp(hash[hash_idx].mac, mac, ETH_ALEN) == 0)) &&
+		    (hash[hash_idx].fifo == fifo) &&
+		    (hash[hash_idx].ifidx == ifidx)) {
+			found = true;
+			break;
+		}
+		hash_idx++;
+		hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1);
+	}
+	if (found)
+		return hash[hash_idx].flowid;
+
+	return BRCMF_FLOWRING_INVALID_ID;
+}
+
+
+u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
+			  u8 prio, u8 ifidx)
+{
+	struct brcmf_flowring_ring *ring;
+	struct brcmf_flowring_hash *hash;
+	u16 hash_idx;
+	u32 i;
+	bool found;
+	u8 fifo;
+	bool sta;
+	u8 *mac;
+
+	fifo = brcmf_flowring_prio2fifo[prio];
+	sta = (flow->addr_mode[ifidx] == ADDR_INDIRECT);
+	mac = da;
+	if ((!sta) && (is_multicast_ether_addr(da))) {
+		mac = (u8 *)ALLFFMAC;
+		fifo = 0;
+	}
+	if ((sta) && (flow->tdls_active) &&
+	    (brcmf_flowring_is_tdls_mac(flow, da))) {
+		sta = false;
+	}
+	hash_idx =  sta ? BRCMF_FLOWRING_HASH_STA(fifo, ifidx) :
+			  BRCMF_FLOWRING_HASH_AP(mac, fifo, ifidx);
+	hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1);
+	found = false;
+	hash = flow->hash;
+	for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
+		if ((hash[hash_idx].ifidx == BRCMF_FLOWRING_INVALID_IFIDX) &&
+		    (is_zero_ether_addr(hash[hash_idx].mac))) {
+			found = true;
+			break;
+		}
+		hash_idx++;
+		hash_idx &= (BRCMF_FLOWRING_HASHSIZE - 1);
+	}
+	if (found) {
+		for (i = 0; i < flow->nrofrings; i++) {
+			if (flow->rings[i] == NULL)
+				break;
+		}
+		if (i == flow->nrofrings)
+			return -ENOMEM;
+
+		ring = kzalloc(sizeof(*ring), GFP_ATOMIC);
+		if (!ring)
+			return -ENOMEM;
+
+		memcpy(hash[hash_idx].mac, mac, ETH_ALEN);
+		hash[hash_idx].fifo = fifo;
+		hash[hash_idx].ifidx = ifidx;
+		hash[hash_idx].flowid = i;
+
+		ring->hash_id = hash_idx;
+		ring->status = RING_CLOSED;
+		skb_queue_head_init(&ring->skblist);
+		flow->rings[i] = ring;
+
+		return i;
+	}
+	return BRCMF_FLOWRING_INVALID_ID;
+}
+
+
+u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u16 flowid)
+{
+	struct brcmf_flowring_ring *ring;
+
+	ring = flow->rings[flowid];
+
+	return flow->hash[ring->hash_id].fifo;
+}
+
+
+static void brcmf_flowring_block(struct brcmf_flowring *flow, u16 flowid,
+				 bool blocked)
+{
+	struct brcmf_flowring_ring *ring;
+	struct brcmf_bus *bus_if;
+	struct brcmf_pub *drvr;
+	struct brcmf_if *ifp;
+	bool currently_blocked;
+	int i;
+	u8 ifidx;
+	unsigned long flags;
+
+	spin_lock_irqsave(&flow->block_lock, flags);
+
+	ring = flow->rings[flowid];
+	if (ring->blocked == blocked) {
+		spin_unlock_irqrestore(&flow->block_lock, flags);
+		return;
+	}
+	ifidx = brcmf_flowring_ifidx_get(flow, flowid);
+
+	currently_blocked = false;
+	for (i = 0; i < flow->nrofrings; i++) {
+		if ((flow->rings[i]) && (i != flowid)) {
+			ring = flow->rings[i];
+			if ((ring->status == RING_OPEN) &&
+			    (brcmf_flowring_ifidx_get(flow, i) == ifidx)) {
+				if (ring->blocked) {
+					currently_blocked = true;
+					break;
+				}
+			}
+		}
+	}
+	flow->rings[flowid]->blocked = blocked;
+	if (currently_blocked) {
+		spin_unlock_irqrestore(&flow->block_lock, flags);
+		return;
+	}
+
+	bus_if = dev_get_drvdata(flow->dev);
+	drvr = bus_if->drvr;
+	ifp = brcmf_get_ifp(drvr, ifidx);
+	brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FLOW, blocked);
+
+	spin_unlock_irqrestore(&flow->block_lock, flags);
+}
+
+
+void brcmf_flowring_delete(struct brcmf_flowring *flow, u16 flowid)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev);
+	struct brcmf_flowring_ring *ring;
+	struct brcmf_if *ifp;
+	u16 hash_idx;
+	u8 ifidx;
+	struct sk_buff *skb;
+
+	ring = flow->rings[flowid];
+	if (!ring)
+		return;
+
+	ifidx = brcmf_flowring_ifidx_get(flow, flowid);
+	ifp = brcmf_get_ifp(bus_if->drvr, ifidx);
+
+	brcmf_flowring_block(flow, flowid, false);
+	hash_idx = ring->hash_id;
+	flow->hash[hash_idx].ifidx = BRCMF_FLOWRING_INVALID_IFIDX;
+	eth_zero_addr(flow->hash[hash_idx].mac);
+	flow->rings[flowid] = NULL;
+
+	skb = skb_dequeue(&ring->skblist);
+	while (skb) {
+		brcmf_txfinalize(ifp, skb, false);
+		skb = skb_dequeue(&ring->skblist);
+	}
+
+	kfree(ring);
+}
+
+
+u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u16 flowid,
+			   struct sk_buff *skb)
+{
+	struct brcmf_flowring_ring *ring;
+
+	ring = flow->rings[flowid];
+
+	skb_queue_tail(&ring->skblist, skb);
+
+	if (!ring->blocked &&
+	    (skb_queue_len(&ring->skblist) > BRCMF_FLOWRING_HIGH)) {
+		brcmf_flowring_block(flow, flowid, true);
+		brcmf_dbg(MSGBUF, "Flowcontrol: BLOCK for ring %d\n", flowid);
+		/* To prevent (work around) possible race condition, check
+		 * queue len again. It is also possible to use locking to
+		 * protect, but that is undesirable for every enqueue and
+		 * dequeue. This simple check will solve a possible race
+		 * condition if it occurs.
+		 */
+		if (skb_queue_len(&ring->skblist) < BRCMF_FLOWRING_LOW)
+			brcmf_flowring_block(flow, flowid, false);
+	}
+	return skb_queue_len(&ring->skblist);
+}
+
+
+struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u16 flowid)
+{
+	struct brcmf_flowring_ring *ring;
+	struct sk_buff *skb;
+
+	ring = flow->rings[flowid];
+	if (ring->status != RING_OPEN)
+		return NULL;
+
+	skb = skb_dequeue(&ring->skblist);
+
+	if (ring->blocked &&
+	    (skb_queue_len(&ring->skblist) < BRCMF_FLOWRING_LOW)) {
+		brcmf_flowring_block(flow, flowid, false);
+		brcmf_dbg(MSGBUF, "Flowcontrol: OPEN for ring %d\n", flowid);
+	}
+
+	return skb;
+}
+
+
+void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u16 flowid,
+			     struct sk_buff *skb)
+{
+	struct brcmf_flowring_ring *ring;
+
+	ring = flow->rings[flowid];
+
+	skb_queue_head(&ring->skblist, skb);
+}
+
+
+u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u16 flowid)
+{
+	struct brcmf_flowring_ring *ring;
+
+	ring = flow->rings[flowid];
+	if (!ring)
+		return 0;
+
+	if (ring->status != RING_OPEN)
+		return 0;
+
+	return skb_queue_len(&ring->skblist);
+}
+
+
+void brcmf_flowring_open(struct brcmf_flowring *flow, u16 flowid)
+{
+	struct brcmf_flowring_ring *ring;
+
+	ring = flow->rings[flowid];
+	if (!ring) {
+		brcmf_err("Ring NULL, for flowid %d\n", flowid);
+		return;
+	}
+
+	ring->status = RING_OPEN;
+}
+
+
+u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u16 flowid)
+{
+	struct brcmf_flowring_ring *ring;
+	u16 hash_idx;
+
+	ring = flow->rings[flowid];
+	hash_idx = ring->hash_id;
+
+	return flow->hash[hash_idx].ifidx;
+}
+
+
+struct brcmf_flowring *brcmf_flowring_attach(struct device *dev, u16 nrofrings)
+{
+	struct brcmf_flowring *flow;
+	u32 i;
+
+	flow = kzalloc(sizeof(*flow), GFP_KERNEL);
+	if (flow) {
+		flow->dev = dev;
+		flow->nrofrings = nrofrings;
+		spin_lock_init(&flow->block_lock);
+		for (i = 0; i < ARRAY_SIZE(flow->addr_mode); i++)
+			flow->addr_mode[i] = ADDR_INDIRECT;
+		for (i = 0; i < ARRAY_SIZE(flow->hash); i++)
+			flow->hash[i].ifidx = BRCMF_FLOWRING_INVALID_IFIDX;
+		flow->rings = kcalloc(nrofrings, sizeof(*flow->rings),
+				      GFP_KERNEL);
+		if (!flow->rings) {
+			kfree(flow);
+			flow = NULL;
+		}
+	}
+
+	return flow;
+}
+
+
+void brcmf_flowring_detach(struct brcmf_flowring *flow)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev);
+	struct brcmf_pub *drvr = bus_if->drvr;
+	struct brcmf_flowring_tdls_entry *search;
+	struct brcmf_flowring_tdls_entry *remove;
+	u16 flowid;
+
+	for (flowid = 0; flowid < flow->nrofrings; flowid++) {
+		if (flow->rings[flowid])
+			brcmf_msgbuf_delete_flowring(drvr, flowid);
+	}
+
+	search = flow->tdls_entry;
+	while (search) {
+		remove = search;
+		search = search->next;
+		kfree(remove);
+	}
+	kfree(flow->rings);
+	kfree(flow);
+}
+
+
+void brcmf_flowring_configure_addr_mode(struct brcmf_flowring *flow, int ifidx,
+					enum proto_addr_mode addr_mode)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev);
+	struct brcmf_pub *drvr = bus_if->drvr;
+	u32 i;
+	u16 flowid;
+
+	if (flow->addr_mode[ifidx] != addr_mode) {
+		for (i = 0; i < ARRAY_SIZE(flow->hash); i++) {
+			if (flow->hash[i].ifidx == ifidx) {
+				flowid = flow->hash[i].flowid;
+				if (flow->rings[flowid]->status != RING_OPEN)
+					continue;
+				flow->rings[flowid]->status = RING_CLOSING;
+				brcmf_msgbuf_delete_flowring(drvr, flowid);
+			}
+		}
+		flow->addr_mode[ifidx] = addr_mode;
+	}
+}
+
+
+void brcmf_flowring_delete_peer(struct brcmf_flowring *flow, int ifidx,
+				u8 peer[ETH_ALEN])
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(flow->dev);
+	struct brcmf_pub *drvr = bus_if->drvr;
+	struct brcmf_flowring_hash *hash;
+	struct brcmf_flowring_tdls_entry *prev;
+	struct brcmf_flowring_tdls_entry *search;
+	u32 i;
+	u16 flowid;
+	bool sta;
+
+	sta = (flow->addr_mode[ifidx] == ADDR_INDIRECT);
+
+	search = flow->tdls_entry;
+	prev = NULL;
+	while (search) {
+		if (memcmp(search->mac, peer, ETH_ALEN) == 0) {
+			sta = false;
+			break;
+		}
+		prev = search;
+		search = search->next;
+	}
+
+	hash = flow->hash;
+	for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
+		if ((sta || (memcmp(hash[i].mac, peer, ETH_ALEN) == 0)) &&
+		    (hash[i].ifidx == ifidx)) {
+			flowid = flow->hash[i].flowid;
+			if (flow->rings[flowid]->status == RING_OPEN) {
+				flow->rings[flowid]->status = RING_CLOSING;
+				brcmf_msgbuf_delete_flowring(drvr, flowid);
+			}
+		}
+	}
+
+	if (search) {
+		if (prev)
+			prev->next = search->next;
+		else
+			flow->tdls_entry = search->next;
+		kfree(search);
+		if (flow->tdls_entry == NULL)
+			flow->tdls_active = false;
+	}
+}
+
+
+void brcmf_flowring_add_tdls_peer(struct brcmf_flowring *flow, int ifidx,
+				  u8 peer[ETH_ALEN])
+{
+	struct brcmf_flowring_tdls_entry *tdls_entry;
+	struct brcmf_flowring_tdls_entry *search;
+
+	tdls_entry = kzalloc(sizeof(*tdls_entry), GFP_ATOMIC);
+	if (tdls_entry == NULL)
+		return;
+
+	memcpy(tdls_entry->mac, peer, ETH_ALEN);
+	tdls_entry->next = NULL;
+	if (flow->tdls_entry == NULL) {
+		flow->tdls_entry = tdls_entry;
+	} else {
+		search = flow->tdls_entry;
+		if (memcmp(search->mac, peer, ETH_ALEN) == 0)
+			goto free_entry;
+		while (search->next) {
+			search = search->next;
+			if (memcmp(search->mac, peer, ETH_ALEN) == 0)
+				goto free_entry;
+		}
+		search->next = tdls_entry;
+	}
+
+	flow->tdls_active = true;
+	return;
+
+free_entry:
+	kfree(tdls_entry);
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h
new file mode 100644
index 0000000..068e68d
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h
@@ -0,0 +1,84 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef BRCMFMAC_FLOWRING_H
+#define BRCMFMAC_FLOWRING_H
+
+
+#define BRCMF_FLOWRING_HASHSIZE		512		/* has to be 2^x */
+#define BRCMF_FLOWRING_INVALID_ID	0xFFFFFFFF
+
+
+struct brcmf_flowring_hash {
+	u8 mac[ETH_ALEN];
+	u8 fifo;
+	u8 ifidx;
+	u16 flowid;
+};
+
+enum ring_status {
+	RING_CLOSED,
+	RING_CLOSING,
+	RING_OPEN
+};
+
+struct brcmf_flowring_ring {
+	u16 hash_id;
+	bool blocked;
+	enum ring_status status;
+	struct sk_buff_head skblist;
+};
+
+struct brcmf_flowring_tdls_entry {
+	u8 mac[ETH_ALEN];
+	struct brcmf_flowring_tdls_entry *next;
+};
+
+struct brcmf_flowring {
+	struct device *dev;
+	struct brcmf_flowring_hash hash[BRCMF_FLOWRING_HASHSIZE];
+	struct brcmf_flowring_ring **rings;
+	spinlock_t block_lock;
+	enum proto_addr_mode addr_mode[BRCMF_MAX_IFS];
+	u16 nrofrings;
+	bool tdls_active;
+	struct brcmf_flowring_tdls_entry *tdls_entry;
+};
+
+
+u32 brcmf_flowring_lookup(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
+			  u8 prio, u8 ifidx);
+u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
+			  u8 prio, u8 ifidx);
+void brcmf_flowring_delete(struct brcmf_flowring *flow, u16 flowid);
+void brcmf_flowring_open(struct brcmf_flowring *flow, u16 flowid);
+u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u16 flowid);
+u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u16 flowid,
+			   struct sk_buff *skb);
+struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u16 flowid);
+void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u16 flowid,
+			     struct sk_buff *skb);
+u32 brcmf_flowring_qlen(struct brcmf_flowring *flow, u16 flowid);
+u8 brcmf_flowring_ifidx_get(struct brcmf_flowring *flow, u16 flowid);
+struct brcmf_flowring *brcmf_flowring_attach(struct device *dev, u16 nrofrings);
+void brcmf_flowring_detach(struct brcmf_flowring *flow);
+void brcmf_flowring_configure_addr_mode(struct brcmf_flowring *flow, int ifidx,
+					enum proto_addr_mode addr_mode);
+void brcmf_flowring_delete_peer(struct brcmf_flowring *flow, int ifidx,
+				u8 peer[ETH_ALEN]);
+void brcmf_flowring_add_tdls_peer(struct brcmf_flowring *flow, int ifidx,
+				  u8 peer[ETH_ALEN]);
+
+
+#endif /* BRCMFMAC_FLOWRING_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
new file mode 100644
index 0000000..e7eaa57
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
@@ -0,0 +1,448 @@
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/netdevice.h>
+
+#include "brcmu_wifi.h"
+#include "brcmu_utils.h"
+
+#include "cfg80211.h"
+#include "core.h"
+#include "debug.h"
+#include "tracepoint.h"
+#include "fweh.h"
+#include "fwil.h"
+#include "proto.h"
+
+/**
+ * struct brcmf_fweh_queue_item - event item on event queue.
+ *
+ * @q: list element for queuing.
+ * @code: event code.
+ * @ifidx: interface index related to this event.
+ * @ifaddr: ethernet address for interface.
+ * @emsg: common parameters of the firmware event message.
+ * @data: event specific data part of the firmware event.
+ */
+struct brcmf_fweh_queue_item {
+	struct list_head q;
+	enum brcmf_fweh_event_code code;
+	u8 ifidx;
+	u8 ifaddr[ETH_ALEN];
+	struct brcmf_event_msg_be emsg;
+	u32 datalen;
+	u8 data[0];
+};
+
+/**
+ * struct brcmf_fweh_event_name - code, name mapping entry.
+ */
+struct brcmf_fweh_event_name {
+	enum brcmf_fweh_event_code code;
+	const char *name;
+};
+
+#ifdef DEBUG
+#define BRCMF_ENUM_DEF(id, val) \
+	{ val, #id },
+
+/* array for mapping code to event name */
+static struct brcmf_fweh_event_name fweh_event_names[] = {
+	BRCMF_FWEH_EVENT_ENUM_DEFLIST
+};
+#undef BRCMF_ENUM_DEF
+
+/**
+ * brcmf_fweh_event_name() - returns name for given event code.
+ *
+ * @code: code to lookup.
+ */
+const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(fweh_event_names); i++) {
+		if (fweh_event_names[i].code == code)
+			return fweh_event_names[i].name;
+	}
+	return "unknown";
+}
+#else
+const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code)
+{
+	return "nodebug";
+}
+#endif
+
+/**
+ * brcmf_fweh_queue_event() - create and queue event.
+ *
+ * @fweh: firmware event handling info.
+ * @event: event queue entry.
+ */
+static void brcmf_fweh_queue_event(struct brcmf_fweh_info *fweh,
+				   struct brcmf_fweh_queue_item *event)
+{
+	ulong flags;
+
+	spin_lock_irqsave(&fweh->evt_q_lock, flags);
+	list_add_tail(&event->q, &fweh->event_q);
+	spin_unlock_irqrestore(&fweh->evt_q_lock, flags);
+	schedule_work(&fweh->event_work);
+}
+
+static int brcmf_fweh_call_event_handler(struct brcmf_if *ifp,
+					 enum brcmf_fweh_event_code code,
+					 struct brcmf_event_msg *emsg,
+					 void *data)
+{
+	struct brcmf_fweh_info *fweh;
+	int err = -EINVAL;
+
+	if (ifp) {
+		fweh = &ifp->drvr->fweh;
+
+		/* handle the event if valid interface and handler */
+		if (fweh->evt_handler[code])
+			err = fweh->evt_handler[code](ifp, emsg, data);
+		else
+			brcmf_err("unhandled event %d ignored\n", code);
+	} else {
+		brcmf_err("no interface object\n");
+	}
+	return err;
+}
+
+/**
+ * brcmf_fweh_handle_if_event() - handle IF event.
+ *
+ * @drvr: driver information object.
+ * @item: queue entry.
+ * @ifpp: interface object (may change upon ADD action).
+ */
+static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
+				       struct brcmf_event_msg *emsg,
+				       void *data)
+{
+	struct brcmf_if_event *ifevent = data;
+	struct brcmf_if *ifp;
+	bool is_p2pdev;
+	int err = 0;
+
+	brcmf_dbg(EVENT, "action: %u ifidx: %u bsscfgidx: %u flags: %u role: %u\n",
+		  ifevent->action, ifevent->ifidx, ifevent->bsscfgidx,
+		  ifevent->flags, ifevent->role);
+
+	/* The P2P Device interface event must not be ignored contrary to what
+	 * firmware tells us. Older firmware uses p2p noif, with sta role.
+	 * This should be accepted when p2pdev_setup is ongoing. TDLS setup will
+	 * use the same ifevent and should be ignored.
+	 */
+	is_p2pdev = ((ifevent->flags & BRCMF_E_IF_FLAG_NOIF) &&
+		     (ifevent->role == BRCMF_E_IF_ROLE_P2P_CLIENT ||
+		      ((ifevent->role == BRCMF_E_IF_ROLE_STA) &&
+		       (drvr->fweh.p2pdev_setup_ongoing))));
+	if (!is_p2pdev && (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) {
+		brcmf_dbg(EVENT, "event can be ignored\n");
+		return;
+	}
+	if (ifevent->ifidx >= BRCMF_MAX_IFS) {
+		brcmf_err("invalid interface index: %u\n", ifevent->ifidx);
+		return;
+	}
+
+	ifp = drvr->iflist[ifevent->bsscfgidx];
+
+	if (ifevent->action == BRCMF_E_IF_ADD) {
+		brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname,
+			  emsg->addr);
+		ifp = brcmf_add_if(drvr, ifevent->bsscfgidx, ifevent->ifidx,
+				   is_p2pdev, emsg->ifname, emsg->addr);
+		if (IS_ERR(ifp))
+			return;
+		if (!is_p2pdev)
+			brcmf_proto_add_if(drvr, ifp);
+		if (!drvr->fweh.evt_handler[BRCMF_E_IF])
+			if (brcmf_net_attach(ifp, false) < 0)
+				return;
+	}
+
+	if (ifp && ifevent->action == BRCMF_E_IF_CHANGE)
+		brcmf_proto_reset_if(drvr, ifp);
+
+	err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
+
+	if (ifp && ifevent->action == BRCMF_E_IF_DEL) {
+		bool armed = brcmf_cfg80211_vif_event_armed(drvr->config);
+
+		/* Default handling in case no-one waits for this event */
+		if (!armed)
+			brcmf_remove_interface(ifp, false);
+	}
+}
+
+/**
+ * brcmf_fweh_dequeue_event() - get event from the queue.
+ *
+ * @fweh: firmware event handling info.
+ */
+static struct brcmf_fweh_queue_item *
+brcmf_fweh_dequeue_event(struct brcmf_fweh_info *fweh)
+{
+	struct brcmf_fweh_queue_item *event = NULL;
+	ulong flags;
+
+	spin_lock_irqsave(&fweh->evt_q_lock, flags);
+	if (!list_empty(&fweh->event_q)) {
+		event = list_first_entry(&fweh->event_q,
+					 struct brcmf_fweh_queue_item, q);
+		list_del(&event->q);
+	}
+	spin_unlock_irqrestore(&fweh->evt_q_lock, flags);
+
+	return event;
+}
+
+/**
+ * brcmf_fweh_event_worker() - firmware event worker.
+ *
+ * @work: worker object.
+ */
+static void brcmf_fweh_event_worker(struct work_struct *work)
+{
+	struct brcmf_pub *drvr;
+	struct brcmf_if *ifp;
+	struct brcmf_fweh_info *fweh;
+	struct brcmf_fweh_queue_item *event;
+	int err = 0;
+	struct brcmf_event_msg_be *emsg_be;
+	struct brcmf_event_msg emsg;
+
+	fweh = container_of(work, struct brcmf_fweh_info, event_work);
+	drvr = container_of(fweh, struct brcmf_pub, fweh);
+
+	while ((event = brcmf_fweh_dequeue_event(fweh))) {
+		brcmf_dbg(EVENT, "event %s (%u) ifidx %u bsscfg %u addr %pM\n",
+			  brcmf_fweh_event_name(event->code), event->code,
+			  event->emsg.ifidx, event->emsg.bsscfgidx,
+			  event->emsg.addr);
+
+		/* convert event message */
+		emsg_be = &event->emsg;
+		emsg.version = be16_to_cpu(emsg_be->version);
+		emsg.flags = be16_to_cpu(emsg_be->flags);
+		emsg.event_code = event->code;
+		emsg.status = be32_to_cpu(emsg_be->status);
+		emsg.reason = be32_to_cpu(emsg_be->reason);
+		emsg.auth_type = be32_to_cpu(emsg_be->auth_type);
+		emsg.datalen = be32_to_cpu(emsg_be->datalen);
+		memcpy(emsg.addr, emsg_be->addr, ETH_ALEN);
+		memcpy(emsg.ifname, emsg_be->ifname, sizeof(emsg.ifname));
+		emsg.ifidx = emsg_be->ifidx;
+		emsg.bsscfgidx = emsg_be->bsscfgidx;
+
+		brcmf_dbg(EVENT, "  version %u flags %u status %u reason %u\n",
+			  emsg.version, emsg.flags, emsg.status, emsg.reason);
+		brcmf_dbg_hex_dump(BRCMF_EVENT_ON(), event->data,
+				   min_t(u32, emsg.datalen, 64),
+				   "event payload, len=%d\n", emsg.datalen);
+
+		/* special handling of interface event */
+		if (event->code == BRCMF_E_IF) {
+			brcmf_fweh_handle_if_event(drvr, &emsg, event->data);
+			goto event_free;
+		}
+
+		if (event->code == BRCMF_E_TDLS_PEER_EVENT)
+			ifp = drvr->iflist[0];
+		else
+			ifp = drvr->iflist[emsg.bsscfgidx];
+		err = brcmf_fweh_call_event_handler(ifp, event->code, &emsg,
+						    event->data);
+		if (err) {
+			brcmf_err("event handler failed (%d)\n",
+				  event->code);
+			err = 0;
+		}
+event_free:
+		kfree(event);
+	}
+}
+
+/**
+ * brcmf_fweh_p2pdev_setup() - P2P device setup ongoing (or not).
+ *
+ * @ifp: ifp on which setup is taking place or finished.
+ * @ongoing: p2p device setup in progress (or not).
+ */
+void brcmf_fweh_p2pdev_setup(struct brcmf_if *ifp, bool ongoing)
+{
+	ifp->drvr->fweh.p2pdev_setup_ongoing = ongoing;
+}
+
+/**
+ * brcmf_fweh_attach() - initialize firmware event handling.
+ *
+ * @drvr: driver information object.
+ */
+void brcmf_fweh_attach(struct brcmf_pub *drvr)
+{
+	struct brcmf_fweh_info *fweh = &drvr->fweh;
+	INIT_WORK(&fweh->event_work, brcmf_fweh_event_worker);
+	spin_lock_init(&fweh->evt_q_lock);
+	INIT_LIST_HEAD(&fweh->event_q);
+}
+
+/**
+ * brcmf_fweh_detach() - cleanup firmware event handling.
+ *
+ * @drvr: driver information object.
+ */
+void brcmf_fweh_detach(struct brcmf_pub *drvr)
+{
+	struct brcmf_fweh_info *fweh = &drvr->fweh;
+	struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
+	s8 eventmask[BRCMF_EVENTING_MASK_LEN];
+
+	if (ifp) {
+		/* clear all events */
+		memset(eventmask, 0, BRCMF_EVENTING_MASK_LEN);
+		(void)brcmf_fil_iovar_data_set(ifp, "event_msgs",
+					       eventmask,
+					       BRCMF_EVENTING_MASK_LEN);
+	}
+	/* cancel the worker */
+	cancel_work_sync(&fweh->event_work);
+	WARN_ON(!list_empty(&fweh->event_q));
+	memset(fweh->evt_handler, 0, sizeof(fweh->evt_handler));
+}
+
+/**
+ * brcmf_fweh_register() - register handler for given event code.
+ *
+ * @drvr: driver information object.
+ * @code: event code.
+ * @handler: handler for the given event code.
+ */
+int brcmf_fweh_register(struct brcmf_pub *drvr, enum brcmf_fweh_event_code code,
+			brcmf_fweh_handler_t handler)
+{
+	if (drvr->fweh.evt_handler[code]) {
+		brcmf_err("event code %d already registered\n", code);
+		return -ENOSPC;
+	}
+	drvr->fweh.evt_handler[code] = handler;
+	brcmf_dbg(TRACE, "event handler registered for %s\n",
+		  brcmf_fweh_event_name(code));
+	return 0;
+}
+
+/**
+ * brcmf_fweh_unregister() - remove handler for given code.
+ *
+ * @drvr: driver information object.
+ * @code: event code.
+ */
+void brcmf_fweh_unregister(struct brcmf_pub *drvr,
+			   enum brcmf_fweh_event_code code)
+{
+	brcmf_dbg(TRACE, "event handler cleared for %s\n",
+		  brcmf_fweh_event_name(code));
+	drvr->fweh.evt_handler[code] = NULL;
+}
+
+/**
+ * brcmf_fweh_activate_events() - enables firmware events registered.
+ *
+ * @ifp: primary interface object.
+ */
+int brcmf_fweh_activate_events(struct brcmf_if *ifp)
+{
+	int i, err;
+	s8 eventmask[BRCMF_EVENTING_MASK_LEN];
+
+	memset(eventmask, 0, sizeof(eventmask));
+	for (i = 0; i < BRCMF_E_LAST; i++) {
+		if (ifp->drvr->fweh.evt_handler[i]) {
+			brcmf_dbg(EVENT, "enable event %s\n",
+				  brcmf_fweh_event_name(i));
+			setbit(eventmask, i);
+		}
+	}
+
+	/* want to handle IF event as well */
+	brcmf_dbg(EVENT, "enable event IF\n");
+	setbit(eventmask, BRCMF_E_IF);
+
+	err = brcmf_fil_iovar_data_set(ifp, "event_msgs",
+				       eventmask, BRCMF_EVENTING_MASK_LEN);
+	if (err)
+		brcmf_err("Set event_msgs error (%d)\n", err);
+
+	return err;
+}
+
+/**
+ * brcmf_fweh_process_event() - process skb as firmware event.
+ *
+ * @drvr: driver information object.
+ * @event_packet: event packet to process.
+ *
+ * If the packet buffer contains a firmware event message it will
+ * dispatch the event to a registered handler (using worker).
+ */
+void brcmf_fweh_process_event(struct brcmf_pub *drvr,
+			      struct brcmf_event *event_packet,
+			      u32 packet_len)
+{
+	enum brcmf_fweh_event_code code;
+	struct brcmf_fweh_info *fweh = &drvr->fweh;
+	struct brcmf_fweh_queue_item *event;
+	gfp_t alloc_flag = GFP_KERNEL;
+	void *data;
+	u32 datalen;
+
+	/* get event info */
+	code = get_unaligned_be32(&event_packet->msg.event_type);
+	datalen = get_unaligned_be32(&event_packet->msg.datalen);
+	data = &event_packet[1];
+
+	if (code >= BRCMF_E_LAST)
+		return;
+
+	if (code != BRCMF_E_IF && !fweh->evt_handler[code])
+		return;
+
+	if (datalen > BRCMF_DCMD_MAXLEN ||
+	    datalen + sizeof(*event_packet) > packet_len)
+		return;
+
+	if (in_interrupt())
+		alloc_flag = GFP_ATOMIC;
+
+	event = kzalloc(sizeof(*event) + datalen, alloc_flag);
+	if (!event)
+		return;
+
+	event->code = code;
+	event->ifidx = event_packet->msg.ifidx;
+
+	/* use memcpy to get aligned event message */
+	memcpy(&event->emsg, &event_packet->msg, sizeof(event->emsg));
+	memcpy(event->data, data, datalen);
+	event->datalen = datalen;
+	memcpy(event->ifaddr, event_packet->eth.h_dest, ETH_ALEN);
+
+	brcmf_fweh_queue_event(fweh, event);
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
new file mode 100644
index 0000000..816f80e
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#ifndef FWEH_H_
+#define FWEH_H_
+
+#include <asm/unaligned.h>
+#include <linux/skbuff.h>
+#include <linux/if_ether.h>
+#include <linux/if.h>
+
+/* formward declarations */
+struct brcmf_pub;
+struct brcmf_if;
+struct brcmf_cfg80211_info;
+
+/* list of firmware events */
+#define BRCMF_FWEH_EVENT_ENUM_DEFLIST \
+	BRCMF_ENUM_DEF(SET_SSID, 0) \
+	BRCMF_ENUM_DEF(JOIN, 1) \
+	BRCMF_ENUM_DEF(START, 2) \
+	BRCMF_ENUM_DEF(AUTH, 3) \
+	BRCMF_ENUM_DEF(AUTH_IND, 4) \
+	BRCMF_ENUM_DEF(DEAUTH, 5) \
+	BRCMF_ENUM_DEF(DEAUTH_IND, 6) \
+	BRCMF_ENUM_DEF(ASSOC, 7) \
+	BRCMF_ENUM_DEF(ASSOC_IND, 8) \
+	BRCMF_ENUM_DEF(REASSOC, 9) \
+	BRCMF_ENUM_DEF(REASSOC_IND, 10) \
+	BRCMF_ENUM_DEF(DISASSOC, 11) \
+	BRCMF_ENUM_DEF(DISASSOC_IND, 12) \
+	BRCMF_ENUM_DEF(QUIET_START, 13) \
+	BRCMF_ENUM_DEF(QUIET_END, 14) \
+	BRCMF_ENUM_DEF(BEACON_RX, 15) \
+	BRCMF_ENUM_DEF(LINK, 16) \
+	BRCMF_ENUM_DEF(MIC_ERROR, 17) \
+	BRCMF_ENUM_DEF(NDIS_LINK, 18) \
+	BRCMF_ENUM_DEF(ROAM, 19) \
+	BRCMF_ENUM_DEF(TXFAIL, 20) \
+	BRCMF_ENUM_DEF(PMKID_CACHE, 21) \
+	BRCMF_ENUM_DEF(RETROGRADE_TSF, 22) \
+	BRCMF_ENUM_DEF(PRUNE, 23) \
+	BRCMF_ENUM_DEF(AUTOAUTH, 24) \
+	BRCMF_ENUM_DEF(EAPOL_MSG, 25) \
+	BRCMF_ENUM_DEF(SCAN_COMPLETE, 26) \
+	BRCMF_ENUM_DEF(ADDTS_IND, 27) \
+	BRCMF_ENUM_DEF(DELTS_IND, 28) \
+	BRCMF_ENUM_DEF(BCNSENT_IND, 29) \
+	BRCMF_ENUM_DEF(BCNRX_MSG, 30) \
+	BRCMF_ENUM_DEF(BCNLOST_MSG, 31) \
+	BRCMF_ENUM_DEF(ROAM_PREP, 32) \
+	BRCMF_ENUM_DEF(PFN_NET_FOUND, 33) \
+	BRCMF_ENUM_DEF(PFN_NET_LOST, 34) \
+	BRCMF_ENUM_DEF(RESET_COMPLETE, 35) \
+	BRCMF_ENUM_DEF(JOIN_START, 36) \
+	BRCMF_ENUM_DEF(ROAM_START, 37) \
+	BRCMF_ENUM_DEF(ASSOC_START, 38) \
+	BRCMF_ENUM_DEF(IBSS_ASSOC, 39) \
+	BRCMF_ENUM_DEF(RADIO, 40) \
+	BRCMF_ENUM_DEF(PSM_WATCHDOG, 41) \
+	BRCMF_ENUM_DEF(PROBREQ_MSG, 44) \
+	BRCMF_ENUM_DEF(SCAN_CONFIRM_IND, 45) \
+	BRCMF_ENUM_DEF(PSK_SUP, 46) \
+	BRCMF_ENUM_DEF(COUNTRY_CODE_CHANGED, 47) \
+	BRCMF_ENUM_DEF(EXCEEDED_MEDIUM_TIME, 48) \
+	BRCMF_ENUM_DEF(ICV_ERROR, 49) \
+	BRCMF_ENUM_DEF(UNICAST_DECODE_ERROR, 50) \
+	BRCMF_ENUM_DEF(MULTICAST_DECODE_ERROR, 51) \
+	BRCMF_ENUM_DEF(TRACE, 52) \
+	BRCMF_ENUM_DEF(IF, 54) \
+	BRCMF_ENUM_DEF(P2P_DISC_LISTEN_COMPLETE, 55) \
+	BRCMF_ENUM_DEF(RSSI, 56) \
+	BRCMF_ENUM_DEF(EXTLOG_MSG, 58) \
+	BRCMF_ENUM_DEF(ACTION_FRAME, 59) \
+	BRCMF_ENUM_DEF(ACTION_FRAME_COMPLETE, 60) \
+	BRCMF_ENUM_DEF(PRE_ASSOC_IND, 61) \
+	BRCMF_ENUM_DEF(PRE_REASSOC_IND, 62) \
+	BRCMF_ENUM_DEF(CHANNEL_ADOPTED, 63) \
+	BRCMF_ENUM_DEF(AP_STARTED, 64) \
+	BRCMF_ENUM_DEF(DFS_AP_STOP, 65) \
+	BRCMF_ENUM_DEF(DFS_AP_RESUME, 66) \
+	BRCMF_ENUM_DEF(ESCAN_RESULT, 69) \
+	BRCMF_ENUM_DEF(ACTION_FRAME_OFF_CHAN_COMPLETE, 70) \
+	BRCMF_ENUM_DEF(PROBERESP_MSG, 71) \
+	BRCMF_ENUM_DEF(P2P_PROBEREQ_MSG, 72) \
+	BRCMF_ENUM_DEF(DCS_REQUEST, 73) \
+	BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \
+	BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75) \
+	BRCMF_ENUM_DEF(TDLS_PEER_EVENT, 92) \
+	BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127)
+
+#define BRCMF_ENUM_DEF(id, val) \
+	BRCMF_E_##id = (val),
+
+/* firmware event codes sent by the dongle */
+enum brcmf_fweh_event_code {
+	BRCMF_FWEH_EVENT_ENUM_DEFLIST
+	/* this determines event mask length which must match
+	 * minimum length check in device firmware so it is
+	 * hard-coded here.
+	 */
+	BRCMF_E_LAST = 139
+};
+#undef BRCMF_ENUM_DEF
+
+#define BRCMF_EVENTING_MASK_LEN		DIV_ROUND_UP(BRCMF_E_LAST, 8)
+
+/* flags field values in struct brcmf_event_msg */
+#define BRCMF_EVENT_MSG_LINK		0x01
+#define BRCMF_EVENT_MSG_FLUSHTXQ	0x02
+#define BRCMF_EVENT_MSG_GROUP		0x04
+
+/* status field values in struct brcmf_event_msg */
+#define BRCMF_E_STATUS_SUCCESS			0
+#define BRCMF_E_STATUS_FAIL			1
+#define BRCMF_E_STATUS_TIMEOUT			2
+#define BRCMF_E_STATUS_NO_NETWORKS		3
+#define BRCMF_E_STATUS_ABORT			4
+#define BRCMF_E_STATUS_NO_ACK			5
+#define BRCMF_E_STATUS_UNSOLICITED		6
+#define BRCMF_E_STATUS_ATTEMPT			7
+#define BRCMF_E_STATUS_PARTIAL			8
+#define BRCMF_E_STATUS_NEWSCAN			9
+#define BRCMF_E_STATUS_NEWASSOC			10
+#define BRCMF_E_STATUS_11HQUIET			11
+#define BRCMF_E_STATUS_SUPPRESS			12
+#define BRCMF_E_STATUS_NOCHANS			13
+#define BRCMF_E_STATUS_CS_ABORT			15
+#define BRCMF_E_STATUS_ERROR			16
+
+/* status field values for PSK_SUP event */
+#define BRCMF_E_STATUS_FWSUP_WAIT_M1		4
+#define BRCMF_E_STATUS_FWSUP_PREP_M2		5
+#define BRCMF_E_STATUS_FWSUP_COMPLETED		6
+#define BRCMF_E_STATUS_FWSUP_TIMEOUT		7
+#define BRCMF_E_STATUS_FWSUP_WAIT_M3		8
+#define BRCMF_E_STATUS_FWSUP_PREP_M4		9
+#define BRCMF_E_STATUS_FWSUP_WAIT_G1		10
+#define BRCMF_E_STATUS_FWSUP_PREP_G2		11
+
+/* reason field values in struct brcmf_event_msg */
+#define BRCMF_E_REASON_INITIAL_ASSOC		0
+#define BRCMF_E_REASON_LOW_RSSI			1
+#define BRCMF_E_REASON_DEAUTH			2
+#define BRCMF_E_REASON_DISASSOC			3
+#define BRCMF_E_REASON_BCNS_LOST		4
+#define BRCMF_E_REASON_MINTXRATE		9
+#define BRCMF_E_REASON_TXFAIL			10
+
+#define BRCMF_E_REASON_LINK_BSSCFG_DIS		4
+#define BRCMF_E_REASON_FAST_ROAM_FAILED		5
+#define BRCMF_E_REASON_DIRECTED_ROAM		6
+#define BRCMF_E_REASON_TSPEC_REJECTED		7
+#define BRCMF_E_REASON_BETTER_AP		8
+
+#define BRCMF_E_REASON_TDLS_PEER_DISCOVERED	0
+#define BRCMF_E_REASON_TDLS_PEER_CONNECTED	1
+#define BRCMF_E_REASON_TDLS_PEER_DISCONNECTED	2
+
+/* reason field values for PSK_SUP event */
+#define BRCMF_E_REASON_FWSUP_OTHER		0
+#define BRCMF_E_REASON_FWSUP_DECRYPT_KEY_DATA	1
+#define BRCMF_E_REASON_FWSUP_BAD_UCAST_WEP128	2
+#define BRCMF_E_REASON_FWSUP_BAD_UCAST_WEP40	3
+#define BRCMF_E_REASON_FWSUP_UNSUP_KEY_LEN	4
+#define BRCMF_E_REASON_FWSUP_PW_KEY_CIPHER	5
+#define BRCMF_E_REASON_FWSUP_MSG3_TOO_MANY_IE	6
+#define BRCMF_E_REASON_FWSUP_MSG3_IE_MISMATCH	7
+#define BRCMF_E_REASON_FWSUP_NO_INSTALL_FLAG	8
+#define BRCMF_E_REASON_FWSUP_MSG3_NO_GTK	9
+#define BRCMF_E_REASON_FWSUP_GRP_KEY_CIPHER	10
+#define BRCMF_E_REASON_FWSUP_GRP_MSG1_NO_GTK	11
+#define BRCMF_E_REASON_FWSUP_GTK_DECRYPT_FAIL	12
+#define BRCMF_E_REASON_FWSUP_SEND_FAIL		13
+#define BRCMF_E_REASON_FWSUP_DEAUTH		14
+#define BRCMF_E_REASON_FWSUP_WPA_PSK_TMO	15
+#define BRCMF_E_REASON_FWSUP_WPA_PSK_M1_TMO	16
+#define BRCMF_E_REASON_FWSUP_WPA_PSK_M3_TMO	17
+
+/* action field values for brcmf_ifevent */
+#define BRCMF_E_IF_ADD				1
+#define BRCMF_E_IF_DEL				2
+#define BRCMF_E_IF_CHANGE			3
+
+/* flag field values for brcmf_ifevent */
+#define BRCMF_E_IF_FLAG_NOIF			1
+
+/* role field values for brcmf_ifevent */
+#define BRCMF_E_IF_ROLE_STA			0
+#define BRCMF_E_IF_ROLE_AP			1
+#define BRCMF_E_IF_ROLE_WDS			2
+#define BRCMF_E_IF_ROLE_P2P_GO			3
+#define BRCMF_E_IF_ROLE_P2P_CLIENT		4
+
+/**
+ * definitions for event packet validation.
+ */
+#define BRCM_OUI				"\x00\x10\x18"
+#define BCMILCP_BCM_SUBTYPE_EVENT		1
+
+
+/**
+ * struct brcm_ethhdr - broadcom specific ether header.
+ *
+ * @subtype: subtype for this packet.
+ * @length: TODO: length of appended data.
+ * @version: version indication.
+ * @oui: OUI of this packet.
+ * @usr_subtype: subtype for this OUI.
+ */
+struct brcm_ethhdr {
+	__be16 subtype;
+	__be16 length;
+	u8 version;
+	u8 oui[3];
+	__be16 usr_subtype;
+} __packed;
+
+struct brcmf_event_msg_be {
+	__be16 version;
+	__be16 flags;
+	__be32 event_type;
+	__be32 status;
+	__be32 reason;
+	__be32 auth_type;
+	__be32 datalen;
+	u8 addr[ETH_ALEN];
+	char ifname[IFNAMSIZ];
+	u8 ifidx;
+	u8 bsscfgidx;
+} __packed;
+
+/**
+ * struct brcmf_event - contents of broadcom event packet.
+ *
+ * @eth: standard ether header.
+ * @hdr: broadcom specific ether header.
+ * @msg: common part of the actual event message.
+ */
+struct brcmf_event {
+	struct ethhdr eth;
+	struct brcm_ethhdr hdr;
+	struct brcmf_event_msg_be msg;
+} __packed;
+
+/**
+ * struct brcmf_event_msg - firmware event message.
+ *
+ * @version: version information.
+ * @flags: event flags.
+ * @event_code: firmware event code.
+ * @status: status information.
+ * @reason: reason code.
+ * @auth_type: authentication type.
+ * @datalen: lenght of event data buffer.
+ * @addr: ether address.
+ * @ifname: interface name.
+ * @ifidx: interface index.
+ * @bsscfgidx: bsscfg index.
+ */
+struct brcmf_event_msg {
+	u16 version;
+	u16 flags;
+	u32 event_code;
+	u32 status;
+	u32 reason;
+	s32 auth_type;
+	u32 datalen;
+	u8 addr[ETH_ALEN];
+	char ifname[IFNAMSIZ];
+	u8 ifidx;
+	u8 bsscfgidx;
+};
+
+struct brcmf_if_event {
+	u8 ifidx;
+	u8 action;
+	u8 flags;
+	u8 bsscfgidx;
+	u8 role;
+};
+
+typedef int (*brcmf_fweh_handler_t)(struct brcmf_if *ifp,
+				    const struct brcmf_event_msg *evtmsg,
+				    void *data);
+
+/**
+ * struct brcmf_fweh_info - firmware event handling information.
+ *
+ * @p2pdev_setup_ongoing: P2P device creation in progress.
+ * @event_work: event worker.
+ * @evt_q_lock: lock for event queue protection.
+ * @event_q: event queue.
+ * @evt_handler: registered event handlers.
+ */
+struct brcmf_fweh_info {
+	bool p2pdev_setup_ongoing;
+	struct work_struct event_work;
+	spinlock_t evt_q_lock;
+	struct list_head event_q;
+	int (*evt_handler[BRCMF_E_LAST])(struct brcmf_if *ifp,
+					 const struct brcmf_event_msg *evtmsg,
+					 void *data);
+};
+
+const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code);
+
+void brcmf_fweh_attach(struct brcmf_pub *drvr);
+void brcmf_fweh_detach(struct brcmf_pub *drvr);
+int brcmf_fweh_register(struct brcmf_pub *drvr, enum brcmf_fweh_event_code code,
+			int (*handler)(struct brcmf_if *ifp,
+				       const struct brcmf_event_msg *evtmsg,
+				       void *data));
+void brcmf_fweh_unregister(struct brcmf_pub *drvr,
+			   enum brcmf_fweh_event_code code);
+int brcmf_fweh_activate_events(struct brcmf_if *ifp);
+void brcmf_fweh_process_event(struct brcmf_pub *drvr,
+			      struct brcmf_event *event_packet,
+			      u32 packet_len);
+void brcmf_fweh_p2pdev_setup(struct brcmf_if *ifp, bool ongoing);
+
+static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr,
+					  struct sk_buff *skb)
+{
+	struct brcmf_event *event_packet;
+	u16 usr_stype;
+
+	/* only process events when protocol matches */
+	if (skb->protocol != cpu_to_be16(ETH_P_LINK_CTL))
+		return;
+
+	if ((skb->len + ETH_HLEN) < sizeof(*event_packet))
+		return;
+
+	/* check for BRCM oui match */
+	event_packet = (struct brcmf_event *)skb_mac_header(skb);
+	if (memcmp(BRCM_OUI, &event_packet->hdr.oui[0],
+		   sizeof(event_packet->hdr.oui)))
+		return;
+
+	/* final match on usr_subtype */
+	usr_stype = get_unaligned_be16(&event_packet->hdr.usr_subtype);
+	if (usr_stype != BCMILCP_BCM_SUBTYPE_EVENT)
+		return;
+
+	brcmf_fweh_process_event(drvr, event_packet, skb->len + ETH_HLEN);
+}
+
+#endif /* FWEH_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
new file mode 100644
index 0000000..802d7cb
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
@@ -0,0 +1,427 @@
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* FWIL is the Firmware Interface Layer. In this module the support functions
+ * are located to set and get variables to and from the firmware.
+ */
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+#include "core.h"
+#include "bus.h"
+#include "debug.h"
+#include "tracepoint.h"
+#include "fwil.h"
+#include "proto.h"
+
+
+#define MAX_HEX_DUMP_LEN	64
+
+#ifdef DEBUG
+static const char * const brcmf_fil_errstr[] = {
+	"BCME_OK",
+	"BCME_ERROR",
+	"BCME_BADARG",
+	"BCME_BADOPTION",
+	"BCME_NOTUP",
+	"BCME_NOTDOWN",
+	"BCME_NOTAP",
+	"BCME_NOTSTA",
+	"BCME_BADKEYIDX",
+	"BCME_RADIOOFF",
+	"BCME_NOTBANDLOCKED",
+	"BCME_NOCLK",
+	"BCME_BADRATESET",
+	"BCME_BADBAND",
+	"BCME_BUFTOOSHORT",
+	"BCME_BUFTOOLONG",
+	"BCME_BUSY",
+	"BCME_NOTASSOCIATED",
+	"BCME_BADSSIDLEN",
+	"BCME_OUTOFRANGECHAN",
+	"BCME_BADCHAN",
+	"BCME_BADADDR",
+	"BCME_NORESOURCE",
+	"BCME_UNSUPPORTED",
+	"BCME_BADLEN",
+	"BCME_NOTREADY",
+	"BCME_EPERM",
+	"BCME_NOMEM",
+	"BCME_ASSOCIATED",
+	"BCME_RANGE",
+	"BCME_NOTFOUND",
+	"BCME_WME_NOT_ENABLED",
+	"BCME_TSPEC_NOTFOUND",
+	"BCME_ACM_NOTSUPPORTED",
+	"BCME_NOT_WME_ASSOCIATION",
+	"BCME_SDIO_ERROR",
+	"BCME_DONGLE_DOWN",
+	"BCME_VERSION",
+	"BCME_TXFAIL",
+	"BCME_RXFAIL",
+	"BCME_NODEVICE",
+	"BCME_NMODE_DISABLED",
+	"BCME_NONRESIDENT",
+	"BCME_SCANREJECT",
+	"BCME_USAGE_ERROR",
+	"BCME_IOCTL_ERROR",
+	"BCME_SERIAL_PORT_ERR",
+	"BCME_DISABLED",
+	"BCME_DECERR",
+	"BCME_ENCERR",
+	"BCME_MICERR",
+	"BCME_REPLAY",
+	"BCME_IE_NOTFOUND",
+};
+
+static const char *brcmf_fil_get_errstr(u32 err)
+{
+	if (err >= ARRAY_SIZE(brcmf_fil_errstr))
+		return "(unknown)";
+
+	return brcmf_fil_errstr[err];
+}
+#else
+static const char *brcmf_fil_get_errstr(u32 err)
+{
+	return "";
+}
+#endif /* DEBUG */
+
+static s32
+brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
+{
+	struct brcmf_pub *drvr = ifp->drvr;
+	s32 err, fwerr;
+
+	if (drvr->bus_if->state != BRCMF_BUS_UP) {
+		brcmf_err("bus is down. we have nothing to do.\n");
+		return -EIO;
+	}
+
+	if (data != NULL)
+		len = min_t(uint, len, BRCMF_DCMD_MAXLEN);
+	if (set)
+		err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd,
+					   data, len, &fwerr);
+	else
+		err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd,
+					     data, len, &fwerr);
+
+	if (err) {
+		brcmf_dbg(FIL, "Failed: error=%d\n", err);
+	} else if (fwerr < 0) {
+		brcmf_dbg(FIL, "Firmware error: %s (%d)\n",
+			  brcmf_fil_get_errstr((u32)(-fwerr)), fwerr);
+		err = -EBADE;
+	}
+	if (ifp->fwil_fwerr)
+		return fwerr;
+
+	return err;
+}
+
+s32
+brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len)
+{
+	s32 err;
+
+	mutex_lock(&ifp->drvr->proto_block);
+
+	brcmf_dbg(FIL, "ifidx=%d, cmd=%d, len=%d\n", ifp->ifidx, cmd, len);
+	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
+			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
+
+	err = brcmf_fil_cmd_data(ifp, cmd, data, len, true);
+	mutex_unlock(&ifp->drvr->proto_block);
+
+	return err;
+}
+
+s32
+brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len)
+{
+	s32 err;
+
+	mutex_lock(&ifp->drvr->proto_block);
+	err = brcmf_fil_cmd_data(ifp, cmd, data, len, false);
+
+	brcmf_dbg(FIL, "ifidx=%d, cmd=%d, len=%d\n", ifp->ifidx, cmd, len);
+	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
+			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
+
+	mutex_unlock(&ifp->drvr->proto_block);
+
+	return err;
+}
+
+
+s32
+brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data)
+{
+	s32 err;
+	__le32 data_le = cpu_to_le32(data);
+
+	mutex_lock(&ifp->drvr->proto_block);
+	brcmf_dbg(FIL, "ifidx=%d, cmd=%d, value=%d\n", ifp->ifidx, cmd, data);
+	err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), true);
+	mutex_unlock(&ifp->drvr->proto_block);
+
+	return err;
+}
+
+s32
+brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data)
+{
+	s32 err;
+	__le32 data_le = cpu_to_le32(*data);
+
+	mutex_lock(&ifp->drvr->proto_block);
+	err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), false);
+	mutex_unlock(&ifp->drvr->proto_block);
+	*data = le32_to_cpu(data_le);
+	brcmf_dbg(FIL, "ifidx=%d, cmd=%d, value=%d\n", ifp->ifidx, cmd, *data);
+
+	return err;
+}
+
+static u32
+brcmf_create_iovar(char *name, const char *data, u32 datalen,
+		   char *buf, u32 buflen)
+{
+	u32 len;
+
+	len = strlen(name) + 1;
+
+	if ((len + datalen) > buflen)
+		return 0;
+
+	memcpy(buf, name, len);
+
+	/* append data onto the end of the name string */
+	if (data && datalen)
+		memcpy(&buf[len], data, datalen);
+
+	return len + datalen;
+}
+
+
+s32
+brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, const void *data,
+			 u32 len)
+{
+	struct brcmf_pub *drvr = ifp->drvr;
+	s32 err;
+	u32 buflen;
+
+	mutex_lock(&drvr->proto_block);
+
+	brcmf_dbg(FIL, "ifidx=%d, name=%s, len=%d\n", ifp->ifidx, name, len);
+	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
+			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
+
+	buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf,
+				    sizeof(drvr->proto_buf));
+	if (buflen) {
+		err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf,
+					 buflen, true);
+	} else {
+		err = -EPERM;
+		brcmf_err("Creating iovar failed\n");
+	}
+
+	mutex_unlock(&drvr->proto_block);
+	return err;
+}
+
+s32
+brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data,
+			 u32 len)
+{
+	struct brcmf_pub *drvr = ifp->drvr;
+	s32 err;
+	u32 buflen;
+
+	mutex_lock(&drvr->proto_block);
+
+	buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf,
+				    sizeof(drvr->proto_buf));
+	if (buflen) {
+		err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf,
+					 buflen, false);
+		if (err == 0)
+			memcpy(data, drvr->proto_buf, len);
+	} else {
+		err = -EPERM;
+		brcmf_err("Creating iovar failed\n");
+	}
+
+	brcmf_dbg(FIL, "ifidx=%d, name=%s, len=%d\n", ifp->ifidx, name, len);
+	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
+			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
+
+	mutex_unlock(&drvr->proto_block);
+	return err;
+}
+
+s32
+brcmf_fil_iovar_int_set(struct brcmf_if *ifp, char *name, u32 data)
+{
+	__le32 data_le = cpu_to_le32(data);
+
+	return brcmf_fil_iovar_data_set(ifp, name, &data_le, sizeof(data_le));
+}
+
+s32
+brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data)
+{
+	__le32 data_le = cpu_to_le32(*data);
+	s32 err;
+
+	err = brcmf_fil_iovar_data_get(ifp, name, &data_le, sizeof(data_le));
+	if (err == 0)
+		*data = le32_to_cpu(data_le);
+	return err;
+}
+
+static u32
+brcmf_create_bsscfg(s32 bsscfgidx, char *name, char *data, u32 datalen,
+		    char *buf, u32 buflen)
+{
+	const s8 *prefix = "bsscfg:";
+	s8 *p;
+	u32 prefixlen;
+	u32 namelen;
+	u32 iolen;
+	__le32 bsscfgidx_le;
+
+	if (bsscfgidx == 0)
+		return brcmf_create_iovar(name, data, datalen, buf, buflen);
+
+	prefixlen = strlen(prefix);
+	namelen = strlen(name) + 1; /* lengh of iovar  name + null */
+	iolen = prefixlen + namelen + sizeof(bsscfgidx_le) + datalen;
+
+	if (buflen < iolen) {
+		brcmf_err("buffer is too short\n");
+		return 0;
+	}
+
+	p = buf;
+
+	/* copy prefix, no null */
+	memcpy(p, prefix, prefixlen);
+	p += prefixlen;
+
+	/* copy iovar name including null */
+	memcpy(p, name, namelen);
+	p += namelen;
+
+	/* bss config index as first data */
+	bsscfgidx_le = cpu_to_le32(bsscfgidx);
+	memcpy(p, &bsscfgidx_le, sizeof(bsscfgidx_le));
+	p += sizeof(bsscfgidx_le);
+
+	/* parameter buffer follows */
+	if (datalen)
+		memcpy(p, data, datalen);
+
+	return iolen;
+}
+
+s32
+brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name,
+			  void *data, u32 len)
+{
+	struct brcmf_pub *drvr = ifp->drvr;
+	s32 err;
+	u32 buflen;
+
+	mutex_lock(&drvr->proto_block);
+
+	brcmf_dbg(FIL, "ifidx=%d, bsscfgidx=%d, name=%s, len=%d\n", ifp->ifidx,
+		  ifp->bsscfgidx, name, len);
+	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
+			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
+
+	buflen = brcmf_create_bsscfg(ifp->bsscfgidx, name, data, len,
+				     drvr->proto_buf, sizeof(drvr->proto_buf));
+	if (buflen) {
+		err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf,
+					 buflen, true);
+	} else {
+		err = -EPERM;
+		brcmf_err("Creating bsscfg failed\n");
+	}
+
+	mutex_unlock(&drvr->proto_block);
+	return err;
+}
+
+s32
+brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name,
+			  void *data, u32 len)
+{
+	struct brcmf_pub *drvr = ifp->drvr;
+	s32 err;
+	u32 buflen;
+
+	mutex_lock(&drvr->proto_block);
+
+	buflen = brcmf_create_bsscfg(ifp->bsscfgidx, name, data, len,
+				     drvr->proto_buf, sizeof(drvr->proto_buf));
+	if (buflen) {
+		err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf,
+					 buflen, false);
+		if (err == 0)
+			memcpy(data, drvr->proto_buf, len);
+	} else {
+		err = -EPERM;
+		brcmf_err("Creating bsscfg failed\n");
+	}
+	brcmf_dbg(FIL, "ifidx=%d, bsscfgidx=%d, name=%s, len=%d\n", ifp->ifidx,
+		  ifp->bsscfgidx, name, len);
+	brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
+			   min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
+
+	mutex_unlock(&drvr->proto_block);
+	return err;
+
+}
+
+s32
+brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, char *name, u32 data)
+{
+	__le32 data_le = cpu_to_le32(data);
+
+	return brcmf_fil_bsscfg_data_set(ifp, name, &data_le,
+					 sizeof(data_le));
+}
+
+s32
+brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, char *name, u32 *data)
+{
+	__le32 data_le = cpu_to_le32(*data);
+	s32 err;
+
+	err = brcmf_fil_bsscfg_data_get(ifp, name, &data_le,
+					sizeof(data_le));
+	if (err == 0)
+		*data = le32_to_cpu(data_le);
+	return err;
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h
new file mode 100644
index 0000000..63b1287
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _fwil_h_
+#define _fwil_h_
+
+/*******************************************************************************
+ * Dongle command codes that are interpreted by firmware
+ ******************************************************************************/
+#define BRCMF_C_GET_VERSION			1
+#define BRCMF_C_UP				2
+#define BRCMF_C_DOWN				3
+#define BRCMF_C_SET_PROMISC			10
+#define BRCMF_C_GET_RATE			12
+#define BRCMF_C_GET_INFRA			19
+#define BRCMF_C_SET_INFRA			20
+#define BRCMF_C_GET_AUTH			21
+#define BRCMF_C_SET_AUTH			22
+#define BRCMF_C_GET_BSSID			23
+#define BRCMF_C_GET_SSID			25
+#define BRCMF_C_SET_SSID			26
+#define BRCMF_C_TERMINATED			28
+#define BRCMF_C_GET_CHANNEL			29
+#define BRCMF_C_SET_CHANNEL			30
+#define BRCMF_C_GET_SRL				31
+#define BRCMF_C_SET_SRL				32
+#define BRCMF_C_GET_LRL				33
+#define BRCMF_C_SET_LRL				34
+#define BRCMF_C_GET_RADIO			37
+#define BRCMF_C_SET_RADIO			38
+#define BRCMF_C_GET_PHYTYPE			39
+#define BRCMF_C_SET_KEY				45
+#define BRCMF_C_GET_REGULATORY			46
+#define BRCMF_C_SET_REGULATORY			47
+#define BRCMF_C_SET_PASSIVE_SCAN		49
+#define BRCMF_C_SCAN				50
+#define BRCMF_C_SCAN_RESULTS			51
+#define BRCMF_C_DISASSOC			52
+#define BRCMF_C_REASSOC				53
+#define BRCMF_C_SET_ROAM_TRIGGER		55
+#define BRCMF_C_SET_ROAM_DELTA			57
+#define BRCMF_C_GET_BCNPRD			75
+#define BRCMF_C_SET_BCNPRD			76
+#define BRCMF_C_GET_DTIMPRD			77
+#define BRCMF_C_SET_DTIMPRD			78
+#define BRCMF_C_SET_COUNTRY			84
+#define BRCMF_C_GET_PM				85
+#define BRCMF_C_SET_PM				86
+#define BRCMF_C_GET_REVINFO			98
+#define BRCMF_C_GET_CURR_RATESET		114
+#define BRCMF_C_GET_AP				117
+#define BRCMF_C_SET_AP				118
+#define BRCMF_C_SET_SCB_AUTHORIZE		121
+#define BRCMF_C_SET_SCB_DEAUTHORIZE		122
+#define BRCMF_C_GET_RSSI			127
+#define BRCMF_C_GET_WSEC			133
+#define BRCMF_C_SET_WSEC			134
+#define BRCMF_C_GET_PHY_NOISE			135
+#define BRCMF_C_GET_BSS_INFO			136
+#define BRCMF_C_GET_GET_PKTCNTS			137
+#define BRCMF_C_GET_BANDLIST			140
+#define BRCMF_C_SET_SCB_TIMEOUT			158
+#define BRCMF_C_GET_ASSOCLIST			159
+#define BRCMF_C_GET_PHYLIST			180
+#define BRCMF_C_SET_SCAN_CHANNEL_TIME		185
+#define BRCMF_C_SET_SCAN_UNASSOC_TIME		187
+#define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON	201
+#define BRCMF_C_SET_ASSOC_PREFER		205
+#define BRCMF_C_GET_VALID_CHANNELS		217
+#define BRCMF_C_GET_KEY_PRIMARY			235
+#define BRCMF_C_SET_KEY_PRIMARY			236
+#define BRCMF_C_SET_SCAN_PASSIVE_TIME		258
+#define BRCMF_C_GET_VAR				262
+#define BRCMF_C_SET_VAR				263
+#define BRCMF_C_SET_WSEC_PMK			268
+
+s32 brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len);
+s32 brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len);
+s32 brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data);
+s32 brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data);
+
+s32 brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, const void *data,
+			     u32 len);
+s32 brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data,
+			     u32 len);
+s32 brcmf_fil_iovar_int_set(struct brcmf_if *ifp, char *name, u32 data);
+s32 brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data);
+
+s32 brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name, void *data,
+			      u32 len);
+s32 brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name, void *data,
+			      u32 len);
+s32 brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, char *name, u32 data);
+s32 brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, char *name, u32 *data);
+
+#endif /* _fwil_h_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
new file mode 100644
index 0000000..d5bb81e
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
@@ -0,0 +1,999 @@
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#ifndef FWIL_TYPES_H_
+#define FWIL_TYPES_H_
+
+#include <linux/if_ether.h>
+
+
+#define BRCMF_FIL_ACTION_FRAME_SIZE	1800
+
+/* ARP Offload feature flags for arp_ol iovar */
+#define BRCMF_ARP_OL_AGENT		0x00000001
+#define BRCMF_ARP_OL_SNOOP		0x00000002
+#define BRCMF_ARP_OL_HOST_AUTO_REPLY	0x00000004
+#define BRCMF_ARP_OL_PEER_AUTO_REPLY	0x00000008
+
+#define	BRCMF_BSS_INFO_VERSION	109 /* curr ver of brcmf_bss_info_le struct */
+#define BRCMF_BSS_RSSI_ON_CHANNEL	0x0002
+
+#define BRCMF_STA_BRCM			0x00000001	/* Running a Broadcom driver */
+#define BRCMF_STA_WME			0x00000002	/* WMM association */
+#define BRCMF_STA_NONERP		0x00000004	/* No ERP */
+#define BRCMF_STA_AUTHE			0x00000008	/* Authenticated */
+#define BRCMF_STA_ASSOC			0x00000010	/* Associated */
+#define BRCMF_STA_AUTHO			0x00000020	/* Authorized */
+#define BRCMF_STA_WDS			0x00000040	/* Wireless Distribution System */
+#define BRCMF_STA_WDS_LINKUP		0x00000080	/* WDS traffic/probes flowing properly */
+#define BRCMF_STA_PS			0x00000100	/* STA is in power save mode from AP's viewpoint */
+#define BRCMF_STA_APSD_BE		0x00000200	/* APSD delv/trigger for AC_BE is default enabled */
+#define BRCMF_STA_APSD_BK		0x00000400	/* APSD delv/trigger for AC_BK is default enabled */
+#define BRCMF_STA_APSD_VI		0x00000800	/* APSD delv/trigger for AC_VI is default enabled */
+#define BRCMF_STA_APSD_VO		0x00001000	/* APSD delv/trigger for AC_VO is default enabled */
+#define BRCMF_STA_N_CAP			0x00002000	/* STA 802.11n capable */
+#define BRCMF_STA_SCBSTATS		0x00004000	/* Per STA debug stats */
+#define BRCMF_STA_AMPDU_CAP		0x00008000	/* STA AMPDU capable */
+#define BRCMF_STA_AMSDU_CAP		0x00010000	/* STA AMSDU capable */
+#define BRCMF_STA_MIMO_PS		0x00020000	/* mimo ps mode is enabled */
+#define BRCMF_STA_MIMO_RTS		0x00040000	/* send rts in mimo ps mode */
+#define BRCMF_STA_RIFS_CAP		0x00080000	/* rifs enabled */
+#define BRCMF_STA_VHT_CAP		0x00100000	/* STA VHT(11ac) capable */
+#define BRCMF_STA_WPS			0x00200000	/* WPS state */
+#define BRCMF_STA_DWDS_CAP		0x01000000	/* DWDS CAP */
+#define BRCMF_STA_DWDS			0x02000000	/* DWDS active */
+
+/* size of brcmf_scan_params not including variable length array */
+#define BRCMF_SCAN_PARAMS_FIXED_SIZE	64
+
+/* masks for channel and ssid count */
+#define BRCMF_SCAN_PARAMS_COUNT_MASK	0x0000ffff
+#define BRCMF_SCAN_PARAMS_NSSID_SHIFT	16
+
+/* scan type definitions */
+#define BRCMF_SCANTYPE_DEFAULT		0xFF
+#define BRCMF_SCANTYPE_ACTIVE		0
+#define BRCMF_SCANTYPE_PASSIVE		1
+
+#define BRCMF_WSEC_MAX_PSK_LEN		32
+#define	BRCMF_WSEC_PASSPHRASE		BIT(0)
+
+/* primary (ie tx) key */
+#define BRCMF_PRIMARY_KEY		(1 << 1)
+#define DOT11_BSSTYPE_ANY		2
+#define BRCMF_ESCAN_REQ_VERSION		1
+
+#define BRCMF_MAXRATES_IN_SET		16	/* max # of rates in rateset */
+
+/* OBSS Coex Auto/On/Off */
+#define BRCMF_OBSS_COEX_AUTO		(-1)
+#define BRCMF_OBSS_COEX_OFF		0
+#define BRCMF_OBSS_COEX_ON		1
+
+/* WOWL bits */
+/* Wakeup on Magic packet: */
+#define BRCMF_WOWL_MAGIC		(1 << 0)
+/* Wakeup on Netpattern */
+#define BRCMF_WOWL_NET			(1 << 1)
+/* Wakeup on loss-of-link due to Disassoc/Deauth: */
+#define BRCMF_WOWL_DIS			(1 << 2)
+/* Wakeup on retrograde TSF: */
+#define BRCMF_WOWL_RETR			(1 << 3)
+/* Wakeup on loss of beacon: */
+#define BRCMF_WOWL_BCN			(1 << 4)
+/* Wakeup after test: */
+#define BRCMF_WOWL_TST			(1 << 5)
+/* Wakeup after PTK refresh: */
+#define BRCMF_WOWL_M1			(1 << 6)
+/* Wakeup after receipt of EAP-Identity Req: */
+#define BRCMF_WOWL_EAPID		(1 << 7)
+/* Wakeind via PME(0) or GPIO(1): */
+#define BRCMF_WOWL_PME_GPIO		(1 << 8)
+/* need tkip phase 1 key to be updated by the driver: */
+#define BRCMF_WOWL_NEEDTKIP1		(1 << 9)
+/* enable wakeup if GTK fails: */
+#define BRCMF_WOWL_GTK_FAILURE		(1 << 10)
+/* support extended magic packets: */
+#define BRCMF_WOWL_EXTMAGPAT		(1 << 11)
+/* support ARP/NS/keepalive offloading: */
+#define BRCMF_WOWL_ARPOFFLOAD		(1 << 12)
+/* read protocol version for EAPOL frames: */
+#define BRCMF_WOWL_WPA2			(1 << 13)
+/* If the bit is set, use key rotaton: */
+#define BRCMF_WOWL_KEYROT		(1 << 14)
+/* If the bit is set, frm received was bcast frame: */
+#define BRCMF_WOWL_BCAST		(1 << 15)
+/* If the bit is set, scan offload is enabled: */
+#define BRCMF_WOWL_SCANOL		(1 << 16)
+/* Wakeup on tcpkeep alive timeout: */
+#define BRCMF_WOWL_TCPKEEP_TIME		(1 << 17)
+/* Wakeup on mDNS Conflict Resolution: */
+#define BRCMF_WOWL_MDNS_CONFLICT	(1 << 18)
+/* Wakeup on mDNS Service Connect: */
+#define BRCMF_WOWL_MDNS_SERVICE		(1 << 19)
+/* tcp keepalive got data: */
+#define BRCMF_WOWL_TCPKEEP_DATA		(1 << 20)
+/* Firmware died in wowl mode: */
+#define BRCMF_WOWL_FW_HALT		(1 << 21)
+/* Enable detection of radio button changes: */
+#define BRCMF_WOWL_ENAB_HWRADIO		(1 << 22)
+/* Offloads detected MIC failure(s): */
+#define BRCMF_WOWL_MIC_FAIL		(1 << 23)
+/* Wakeup in Unassociated state (Net/Magic Pattern): */
+#define BRCMF_WOWL_UNASSOC		(1 << 24)
+/* Wakeup if received matched secured pattern: */
+#define BRCMF_WOWL_SECURE		(1 << 25)
+/* Wakeup on finding preferred network */
+#define BRCMF_WOWL_PFN_FOUND		(1 << 27)
+/* Wakeup on receiving pairwise key EAP packets: */
+#define WIPHY_WOWL_EAP_PK		(1 << 28)
+/* Link Down indication in WoWL mode: */
+#define BRCMF_WOWL_LINKDOWN		(1 << 31)
+
+#define BRCMF_WOWL_MAXPATTERNS		8
+#define BRCMF_WOWL_MAXPATTERNSIZE	128
+
+#define BRCMF_COUNTRY_BUF_SZ		4
+#define BRCMF_ANT_MAX			4
+
+#define BRCMF_MAX_ASSOCLIST		128
+
+#define BRCMF_TXBF_SU_BFE_CAP		BIT(0)
+#define BRCMF_TXBF_MU_BFE_CAP		BIT(1)
+#define BRCMF_TXBF_SU_BFR_CAP		BIT(0)
+#define BRCMF_TXBF_MU_BFR_CAP		BIT(1)
+
+#define	BRCMF_MAXPMKID			16	/* max # PMKID cache entries */
+#define BRCMF_NUMCHANNELS		64
+
+#define BRCMF_PFN_MACADDR_CFG_VER	1
+#define BRCMF_PFN_MAC_OUI_ONLY		BIT(0)
+#define BRCMF_PFN_SET_MAC_UNASSOC	BIT(1)
+
+#define BRCMF_MCSSET_LEN		16
+
+#define BRCMF_RSN_KCK_LENGTH		16
+#define BRCMF_RSN_KEK_LENGTH		16
+#define BRCMF_RSN_REPLAY_LEN		8
+
+#define BRCMF_MFP_NONE			0
+#define BRCMF_MFP_CAPABLE		1
+#define BRCMF_MFP_REQUIRED		2
+
+#define BRCMF_VHT_CAP_MCS_MAP_NSS_MAX	8
+
+/* MAX_CHUNK_LEN is the maximum length for data passing to firmware in each
+ * ioctl. It is relatively small because firmware has small maximum size input
+ * playload restriction for ioctls.
+ */
+#define MAX_CHUNK_LEN			1400
+
+#define DLOAD_HANDLER_VER		1	/* Downloader version */
+#define DLOAD_FLAG_VER_MASK		0xf000	/* Downloader version mask */
+#define DLOAD_FLAG_VER_SHIFT		12	/* Downloader version shift */
+
+#define DL_BEGIN			0x0002
+#define DL_END				0x0004
+
+#define DL_TYPE_CLM			2
+
+/* join preference types for join_pref iovar */
+enum brcmf_join_pref_types {
+	BRCMF_JOIN_PREF_RSSI = 1,
+	BRCMF_JOIN_PREF_WPA,
+	BRCMF_JOIN_PREF_BAND,
+	BRCMF_JOIN_PREF_RSSI_DELTA,
+};
+
+enum brcmf_fil_p2p_if_types {
+	BRCMF_FIL_P2P_IF_CLIENT,
+	BRCMF_FIL_P2P_IF_GO,
+	BRCMF_FIL_P2P_IF_DYNBCN_GO,
+	BRCMF_FIL_P2P_IF_DEV,
+};
+
+enum brcmf_wowl_pattern_type {
+	BRCMF_WOWL_PATTERN_TYPE_BITMAP = 0,
+	BRCMF_WOWL_PATTERN_TYPE_ARP,
+	BRCMF_WOWL_PATTERN_TYPE_NA
+};
+
+struct brcmf_fil_p2p_if_le {
+	u8 addr[ETH_ALEN];
+	__le16 type;
+	__le16 chspec;
+};
+
+struct brcmf_fil_chan_info_le {
+	__le32 hw_channel;
+	__le32 target_channel;
+	__le32 scan_channel;
+};
+
+struct brcmf_fil_action_frame_le {
+	u8	da[ETH_ALEN];
+	__le16	len;
+	__le32	packet_id;
+	u8	data[BRCMF_FIL_ACTION_FRAME_SIZE];
+};
+
+struct brcmf_fil_af_params_le {
+	__le32					channel;
+	__le32					dwell_time;
+	u8					bssid[ETH_ALEN];
+	u8					pad[2];
+	struct brcmf_fil_action_frame_le	action_frame;
+};
+
+struct brcmf_fil_bss_enable_le {
+	__le32 bsscfgidx;
+	__le32 enable;
+};
+
+struct brcmf_fil_bwcap_le {
+	__le32 band;
+	__le32 bw_cap;
+};
+
+/**
+ * struct tdls_iovar - common structure for tdls iovars.
+ *
+ * @ea: ether address of peer station.
+ * @mode: mode value depending on specific tdls iovar.
+ * @chanspec: channel specification.
+ * @pad: unused (for future use).
+ */
+struct brcmf_tdls_iovar_le {
+	u8 ea[ETH_ALEN];		/* Station address */
+	u8 mode;			/* mode: depends on iovar */
+	__le16 chanspec;
+	__le32 pad;			/* future */
+};
+
+enum brcmf_tdls_manual_ep_ops {
+	BRCMF_TDLS_MANUAL_EP_CREATE = 1,
+	BRCMF_TDLS_MANUAL_EP_DELETE = 3,
+	BRCMF_TDLS_MANUAL_EP_DISCOVERY = 6
+};
+
+/* Pattern matching filter. Specifies an offset within received packets to
+ * start matching, the pattern to match, the size of the pattern, and a bitmask
+ * that indicates which bits within the pattern should be matched.
+ */
+struct brcmf_pkt_filter_pattern_le {
+	/*
+	 * Offset within received packet to start pattern matching.
+	 * Offset '0' is the first byte of the ethernet header.
+	 */
+	__le32 offset;
+	/* Size of the pattern.  Bitmask must be the same size.*/
+	__le32 size_bytes;
+	/*
+	 * Variable length mask and pattern data. mask starts at offset 0.
+	 * Pattern immediately follows mask.
+	 */
+	u8 mask_and_pattern[1];
+};
+
+/* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */
+struct brcmf_pkt_filter_le {
+	__le32 id;		/* Unique filter id, specified by app. */
+	__le32 type;		/* Filter type (WL_PKT_FILTER_TYPE_xxx). */
+	__le32 negate_match;	/* Negate the result of filter matches */
+	union {			/* Filter definitions */
+		struct brcmf_pkt_filter_pattern_le pattern; /* Filter pattern */
+	} u;
+};
+
+/* IOVAR "pkt_filter_enable" parameter. */
+struct brcmf_pkt_filter_enable_le {
+	__le32 id;		/* Unique filter id */
+	__le32 enable;		/* Enable/disable bool */
+};
+
+/* BSS info structure
+ * Applications MUST CHECK ie_offset field and length field to access IEs and
+ * next bss_info structure in a vector (in struct brcmf_scan_results)
+ */
+struct brcmf_bss_info_le {
+	__le32 version;		/* version field */
+	__le32 length;		/* byte length of data in this record,
+				 * starting at version and including IEs
+				 */
+	u8 BSSID[ETH_ALEN];
+	__le16 beacon_period;	/* units are Kusec */
+	__le16 capability;	/* Capability information */
+	u8 SSID_len;
+	u8 SSID[32];
+	struct {
+		__le32 count;   /* # rates in this set */
+		u8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */
+	} rateset;		/* supported rates */
+	__le16 chanspec;	/* chanspec for bss */
+	__le16 atim_window;	/* units are Kusec */
+	u8 dtim_period;	/* DTIM period */
+	__le16 RSSI;		/* receive signal strength (in dBm) */
+	s8 phy_noise;		/* noise (in dBm) */
+
+	u8 n_cap;		/* BSS is 802.11N Capable */
+	/* 802.11N BSS Capabilities (based on HT_CAP_*): */
+	__le32 nbss_cap;
+	u8 ctl_ch;		/* 802.11N BSS control channel number */
+	__le32 reserved32[1];	/* Reserved for expansion of BSS properties */
+	u8 flags;		/* flags */
+	u8 reserved[3];	/* Reserved for expansion of BSS properties */
+	u8 basic_mcs[BRCMF_MCSSET_LEN];	/* 802.11N BSS required MCS set */
+
+	__le16 ie_offset;	/* offset at which IEs start, from beginning */
+	__le32 ie_length;	/* byte length of Information Elements */
+	__le16 SNR;		/* average SNR of during frame reception */
+	/* Add new fields here */
+	/* variable length Information Elements */
+};
+
+struct brcm_rateset_le {
+	/* # rates in this set */
+	__le32 count;
+	/* rates in 500kbps units w/hi bit set if basic */
+	u8 rates[BRCMF_MAXRATES_IN_SET];
+};
+
+struct brcmf_ssid_le {
+	__le32 SSID_len;
+	unsigned char SSID[IEEE80211_MAX_SSID_LEN];
+};
+
+struct brcmf_scan_params_le {
+	struct brcmf_ssid_le ssid_le;	/* default: {0, ""} */
+	u8 bssid[ETH_ALEN];	/* default: bcast */
+	s8 bss_type;		/* default: any,
+				 * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT
+				 */
+	u8 scan_type;	/* flags, 0 use default */
+	__le32 nprobes;	  /* -1 use default, number of probes per channel */
+	__le32 active_time;	/* -1 use default, dwell time per channel for
+				 * active scanning
+				 */
+	__le32 passive_time;	/* -1 use default, dwell time per channel
+				 * for passive scanning
+				 */
+	__le32 home_time;	/* -1 use default, dwell time for the
+				 * home channel between channel scans
+				 */
+	__le32 channel_num;	/* count of channels and ssids that follow
+				 *
+				 * low half is count of channels in
+				 * channel_list, 0 means default (use all
+				 * available channels)
+				 *
+				 * high half is entries in struct brcmf_ssid
+				 * array that follows channel_list, aligned for
+				 * s32 (4 bytes) meaning an odd channel count
+				 * implies a 2-byte pad between end of
+				 * channel_list and first ssid
+				 *
+				 * if ssid count is zero, single ssid in the
+				 * fixed parameter portion is assumed, otherwise
+				 * ssid in the fixed portion is ignored
+				 */
+	__le16 channel_list[1];	/* list of chanspecs */
+};
+
+struct brcmf_scan_results {
+	u32 buflen;
+	u32 version;
+	u32 count;
+	struct brcmf_bss_info_le bss_info_le[];
+};
+
+struct brcmf_escan_params_le {
+	__le32 version;
+	__le16 action;
+	__le16 sync_id;
+	struct brcmf_scan_params_le params_le;
+};
+
+struct brcmf_escan_result_le {
+	__le32 buflen;
+	__le32 version;
+	__le16 sync_id;
+	__le16 bss_count;
+	struct brcmf_bss_info_le bss_info_le;
+};
+
+#define WL_ESCAN_RESULTS_FIXED_SIZE (sizeof(struct brcmf_escan_result_le) - \
+	sizeof(struct brcmf_bss_info_le))
+
+/* used for association with a specific BSSID and chanspec list */
+struct brcmf_assoc_params_le {
+	/* 00:00:00:00:00:00: broadcast scan */
+	u8 bssid[ETH_ALEN];
+	/* 0: all available channels, otherwise count of chanspecs in
+	 * chanspec_list */
+	__le32 chanspec_num;
+	/* list of chanspecs */
+	__le16 chanspec_list[1];
+};
+
+/**
+ * struct join_pref params - parameters for preferred join selection.
+ *
+ * @type: preference type (see enum brcmf_join_pref_types).
+ * @len: length of bytes following (currently always 2).
+ * @rssi_gain: signal gain for selection (only when @type is RSSI_DELTA).
+ * @band: band to which selection preference applies.
+ *	This is used if @type is BAND or RSSI_DELTA.
+ */
+struct brcmf_join_pref_params {
+	u8 type;
+	u8 len;
+	u8 rssi_gain;
+	u8 band;
+};
+
+/* used for join with or without a specific bssid and channel list */
+struct brcmf_join_params {
+	struct brcmf_ssid_le ssid_le;
+	struct brcmf_assoc_params_le params_le;
+};
+
+/* scan params for extended join */
+struct brcmf_join_scan_params_le {
+	u8 scan_type;		/* 0 use default, active or passive scan */
+	__le32 nprobes;		/* -1 use default, nr of probes per channel */
+	__le32 active_time;	/* -1 use default, dwell time per channel for
+				 * active scanning
+				 */
+	__le32 passive_time;	/* -1 use default, dwell time per channel
+				 * for passive scanning
+				 */
+	__le32 home_time;	/* -1 use default, dwell time for the home
+				 * channel between channel scans
+				 */
+};
+
+/* extended join params */
+struct brcmf_ext_join_params_le {
+	struct brcmf_ssid_le ssid_le;	/* {0, ""}: wildcard scan */
+	struct brcmf_join_scan_params_le scan_le;
+	struct brcmf_assoc_params_le assoc_le;
+};
+
+struct brcmf_wsec_key {
+	u32 index;		/* key index */
+	u32 len;		/* key length */
+	u8 data[WLAN_MAX_KEY_LEN];	/* key data */
+	u32 pad_1[18];
+	u32 algo;	/* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
+	u32 flags;	/* misc flags */
+	u32 pad_2[3];
+	u32 iv_initialized;	/* has IV been initialized already? */
+	u32 pad_3;
+	/* Rx IV */
+	struct {
+		u32 hi;	/* upper 32 bits of IV */
+		u16 lo;	/* lower 16 bits of IV */
+	} rxiv;
+	u32 pad_4[2];
+	u8 ea[ETH_ALEN];	/* per station */
+};
+
+/*
+ * dongle requires same struct as above but with fields in little endian order
+ */
+struct brcmf_wsec_key_le {
+	__le32 index;		/* key index */
+	__le32 len;		/* key length */
+	u8 data[WLAN_MAX_KEY_LEN];	/* key data */
+	__le32 pad_1[18];
+	__le32 algo;	/* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
+	__le32 flags;	/* misc flags */
+	__le32 pad_2[3];
+	__le32 iv_initialized;	/* has IV been initialized already? */
+	__le32 pad_3;
+	/* Rx IV */
+	struct {
+		__le32 hi;	/* upper 32 bits of IV */
+		__le16 lo;	/* lower 16 bits of IV */
+	} rxiv;
+	__le32 pad_4[2];
+	u8 ea[ETH_ALEN];	/* per station */
+};
+
+/**
+ * struct brcmf_wsec_pmk_le - firmware pmk material.
+ *
+ * @key_len: number of octets in key material.
+ * @flags: key handling qualifiers.
+ * @key: PMK key material.
+ */
+struct brcmf_wsec_pmk_le {
+	__le16  key_len;
+	__le16  flags;
+	u8 key[2 * BRCMF_WSEC_MAX_PSK_LEN + 1];
+};
+
+/* Used to get specific STA parameters */
+struct brcmf_scb_val_le {
+	__le32 val;
+	u8 ea[ETH_ALEN];
+};
+
+/* channel encoding */
+struct brcmf_channel_info_le {
+	__le32 hw_channel;
+	__le32 target_channel;
+	__le32 scan_channel;
+};
+
+struct brcmf_sta_info_le {
+	__le16 ver;		/* version of this struct */
+	__le16 len;		/* length in bytes of this structure */
+	__le16 cap;		/* sta's advertised capabilities */
+	__le32 flags;		/* flags defined below */
+	__le32 idle;		/* time since data pkt rx'd from sta */
+	u8 ea[ETH_ALEN];		/* Station address */
+	__le32 count;			/* # rates in this set */
+	u8 rates[BRCMF_MAXRATES_IN_SET];	/* rates in 500kbps units */
+						/* w/hi bit set if basic */
+	__le32 in;		/* seconds elapsed since associated */
+	__le32 listen_interval_inms; /* Min Listen interval in ms for STA */
+
+	/* Fields valid for ver >= 3 */
+	__le32 tx_pkts;	/* # of packets transmitted */
+	__le32 tx_failures;	/* # of packets failed */
+	__le32 rx_ucast_pkts;	/* # of unicast packets received */
+	__le32 rx_mcast_pkts;	/* # of multicast packets received */
+	__le32 tx_rate;	/* Rate of last successful tx frame */
+	__le32 rx_rate;	/* Rate of last successful rx frame */
+	__le32 rx_decrypt_succeeds;	/* # of packet decrypted successfully */
+	__le32 rx_decrypt_failures;	/* # of packet decrypted failed */
+
+	/* Fields valid for ver >= 4 */
+	__le32 tx_tot_pkts;    /* # of tx pkts (ucast + mcast) */
+	__le32 rx_tot_pkts;    /* # of data packets recvd (uni + mcast) */
+	__le32 tx_mcast_pkts;  /* # of mcast pkts txed */
+	__le64 tx_tot_bytes;   /* data bytes txed (ucast + mcast) */
+	__le64 rx_tot_bytes;   /* data bytes recvd (ucast + mcast) */
+	__le64 tx_ucast_bytes; /* data bytes txed (ucast) */
+	__le64 tx_mcast_bytes; /* # data bytes txed (mcast) */
+	__le64 rx_ucast_bytes; /* data bytes recvd (ucast) */
+	__le64 rx_mcast_bytes; /* data bytes recvd (mcast) */
+	s8 rssi[BRCMF_ANT_MAX];   /* per antenna rssi */
+	s8 nf[BRCMF_ANT_MAX];     /* per antenna noise floor */
+	__le16 aid;                    /* association ID */
+	__le16 ht_capabilities;        /* advertised ht caps */
+	__le16 vht_flags;              /* converted vht flags */
+	__le32 tx_pkts_retry_cnt;      /* # of frames where a retry was
+					 * exhausted.
+					 */
+	__le32 tx_pkts_retry_exhausted; /* # of user frames where a retry
+					 * was exhausted
+					 */
+	s8 rx_lastpkt_rssi[BRCMF_ANT_MAX]; /* Per antenna RSSI of last
+					    * received data frame.
+					    */
+	/* TX WLAN retry/failure statistics:
+	 * Separated for host requested frames and locally generated frames.
+	 * Include unicast frame only where the retries/failures can be counted.
+	 */
+	__le32 tx_pkts_total;          /* # user frames sent successfully */
+	__le32 tx_pkts_retries;        /* # user frames retries */
+	__le32 tx_pkts_fw_total;       /* # FW generated sent successfully */
+	__le32 tx_pkts_fw_retries;     /* # retries for FW generated frames */
+	__le32 tx_pkts_fw_retry_exhausted;     /* # FW generated where a retry
+						* was exhausted
+						*/
+	__le32 rx_pkts_retried;        /* # rx with retry bit set */
+	__le32 tx_rate_fallback;       /* lowest fallback TX rate */
+
+	/* Fields valid for ver >= 5 */
+	struct {
+		__le32 count;					/* # rates in this set */
+		u8 rates[BRCMF_MAXRATES_IN_SET];		/* rates in 500kbps units w/hi bit set if basic */
+		u8 mcs[BRCMF_MCSSET_LEN];			/* supported mcs index bit map */
+		__le16 vht_mcs[BRCMF_VHT_CAP_MCS_MAP_NSS_MAX];	/* supported mcs index bit map per nss */
+	} rateset_adv;
+};
+
+struct brcmf_chanspec_list {
+	__le32	count;		/* # of entries */
+	__le32	element[1];	/* variable length uint32 list */
+};
+
+/*
+ * WLC_E_PROBRESP_MSG
+ * WLC_E_P2P_PROBREQ_MSG
+ * WLC_E_ACTION_FRAME_RX
+ */
+struct brcmf_rx_mgmt_data {
+	__be16	version;
+	__be16	chanspec;
+	__be32	rssi;
+	__be32	mactime;
+	__be32	rate;
+};
+
+/**
+ * struct brcmf_fil_wowl_pattern_le - wowl pattern configuration struct.
+ *
+ * @cmd: "add", "del" or "clr".
+ * @masksize: Size of the mask in #of bytes
+ * @offset: Pattern byte offset in packet
+ * @patternoffset: Offset of start of pattern. Starting from field masksize.
+ * @patternsize: Size of the pattern itself in #of bytes
+ * @id: id
+ * @reasonsize: Size of the wakeup reason code
+ * @type: Type of pattern (enum brcmf_wowl_pattern_type)
+ */
+struct brcmf_fil_wowl_pattern_le {
+	u8	cmd[4];
+	__le32	masksize;
+	__le32	offset;
+	__le32	patternoffset;
+	__le32	patternsize;
+	__le32	id;
+	__le32	reasonsize;
+	__le32	type;
+	/* u8 mask[] - Mask follows the structure above */
+	/* u8 pattern[] - Pattern follows the mask is at 'patternoffset' */
+};
+
+struct brcmf_mbss_ssid_le {
+	__le32	bsscfgidx;
+	__le32	SSID_len;
+	unsigned char SSID[32];
+};
+
+/**
+ * struct brcmf_fil_country_le - country configuration structure.
+ *
+ * @country_abbrev: null-terminated country code used in the country IE.
+ * @rev: revision specifier for ccode. on set, -1 indicates unspecified.
+ * @ccode: null-terminated built-in country code.
+ */
+struct brcmf_fil_country_le {
+	char country_abbrev[BRCMF_COUNTRY_BUF_SZ];
+	__le32 rev;
+	char ccode[BRCMF_COUNTRY_BUF_SZ];
+};
+
+/**
+ * struct brcmf_rev_info_le - device revision info.
+ *
+ * @vendorid: PCI vendor id.
+ * @deviceid: device id of chip.
+ * @radiorev: radio revision.
+ * @chiprev: chip revision.
+ * @corerev: core revision.
+ * @boardid: board identifier (usu. PCI sub-device id).
+ * @boardvendor: board vendor (usu. PCI sub-vendor id).
+ * @boardrev: board revision.
+ * @driverrev: driver version.
+ * @ucoderev: microcode version.
+ * @bus: bus type.
+ * @chipnum: chip number.
+ * @phytype: phy type.
+ * @phyrev: phy revision.
+ * @anarev: anacore rev.
+ * @chippkg: chip package info.
+ * @nvramrev: nvram revision number.
+ */
+struct brcmf_rev_info_le {
+	__le32 vendorid;
+	__le32 deviceid;
+	__le32 radiorev;
+	__le32 chiprev;
+	__le32 corerev;
+	__le32 boardid;
+	__le32 boardvendor;
+	__le32 boardrev;
+	__le32 driverrev;
+	__le32 ucoderev;
+	__le32 bus;
+	__le32 chipnum;
+	__le32 phytype;
+	__le32 phyrev;
+	__le32 anarev;
+	__le32 chippkg;
+	__le32 nvramrev;
+};
+
+/**
+ * struct brcmf_assoclist_le - request assoc list.
+ *
+ * @count: indicates number of stations.
+ * @mac: MAC addresses of stations.
+ */
+struct brcmf_assoclist_le {
+	__le32 count;
+	u8 mac[BRCMF_MAX_ASSOCLIST][ETH_ALEN];
+};
+
+/**
+ * struct brcmf_wowl_wakeind_le - Wakeup indicators
+ *	Note: note both fields contain same information.
+ *
+ * @pci_wakeind: Whether PCI PMECSR PMEStatus bit was set.
+ * @ucode_wakeind: What wakeup-event indication was set by ucode
+ */
+struct brcmf_wowl_wakeind_le {
+	__le32 pci_wakeind;
+	__le32 ucode_wakeind;
+};
+
+/**
+ * struct brcmf_pmksa - PMK Security Association
+ *
+ * @bssid: The AP's BSSID.
+ * @pmkid: he PMK material itself.
+ */
+struct brcmf_pmksa {
+	u8 bssid[ETH_ALEN];
+	u8 pmkid[WLAN_PMKID_LEN];
+};
+
+/**
+ * struct brcmf_pmk_list_le - List of pmksa's.
+ *
+ * @npmk: Number of pmksa's.
+ * @pmk: PMK SA information.
+ */
+struct brcmf_pmk_list_le {
+	__le32 npmk;
+	struct brcmf_pmksa pmk[BRCMF_MAXPMKID];
+};
+
+/**
+ * struct brcmf_pno_param_le - PNO scan configuration parameters
+ *
+ * @version: PNO parameters version.
+ * @scan_freq: scan frequency.
+ * @lost_network_timeout: #sec. to declare discovered network as lost.
+ * @flags: Bit field to control features of PFN such as sort criteria auto
+ *	enable switch and background scan.
+ * @rssi_margin: Margin to avoid jitter for choosing a PFN based on RSSI sort
+ *	criteria.
+ * @bestn: number of best networks in each scan.
+ * @mscan: number of scans recorded.
+ * @repeat: minimum number of scan intervals before scan frequency changes
+ *	in adaptive scan.
+ * @exp: exponent of 2 for maximum scan interval.
+ * @slow_freq: slow scan period.
+ */
+struct brcmf_pno_param_le {
+	__le32 version;
+	__le32 scan_freq;
+	__le32 lost_network_timeout;
+	__le16 flags;
+	__le16 rssi_margin;
+	u8 bestn;
+	u8 mscan;
+	u8 repeat;
+	u8 exp;
+	__le32 slow_freq;
+};
+
+/**
+ * struct brcmf_pno_config_le - PNO channel configuration.
+ *
+ * @reporttype: determines what is reported.
+ * @channel_num: number of channels specified in @channel_list.
+ * @channel_list: channels to use in PNO scan.
+ * @flags: reserved.
+ */
+struct brcmf_pno_config_le {
+	__le32  reporttype;
+	__le32  channel_num;
+	__le16  channel_list[BRCMF_NUMCHANNELS];
+	__le32  flags;
+};
+
+/**
+ * struct brcmf_pno_net_param_le - scan parameters per preferred network.
+ *
+ * @ssid: ssid name and its length.
+ * @flags: bit2: hidden.
+ * @infra: BSS vs IBSS.
+ * @auth: Open vs Closed.
+ * @wpa_auth: WPA type.
+ * @wsec: wsec value.
+ */
+struct brcmf_pno_net_param_le {
+	struct brcmf_ssid_le ssid;
+	__le32 flags;
+	__le32 infra;
+	__le32 auth;
+	__le32 wpa_auth;
+	__le32 wsec;
+};
+
+/**
+ * struct brcmf_pno_net_info_le - information per found network.
+ *
+ * @bssid: BSS network identifier.
+ * @channel: channel number only.
+ * @SSID_len: length of ssid.
+ * @SSID: ssid characters.
+ * @RSSI: receive signal strength (in dBm).
+ * @timestamp: age in seconds.
+ */
+struct brcmf_pno_net_info_le {
+	u8 bssid[ETH_ALEN];
+	u8 channel;
+	u8 SSID_len;
+	u8 SSID[32];
+	__le16	RSSI;
+	__le16	timestamp;
+};
+
+/**
+ * struct brcmf_pno_scanresults_le - result returned in PNO NET FOUND event.
+ *
+ * @version: PNO version identifier.
+ * @status: indicates completion status of PNO scan.
+ * @count: amount of brcmf_pno_net_info_le entries appended.
+ */
+struct brcmf_pno_scanresults_le {
+	__le32 version;
+	__le32 status;
+	__le32 count;
+};
+
+struct brcmf_pno_scanresults_v2_le {
+	__le32 version;
+	__le32 status;
+	__le32 count;
+	__le32 scan_ch_bucket;
+};
+
+/**
+ * struct brcmf_pno_macaddr_le - to configure PNO macaddr randomization.
+ *
+ * @version: PNO version identifier.
+ * @flags: Flags defining how mac addrss should be used.
+ * @mac: MAC address.
+ */
+struct brcmf_pno_macaddr_le {
+	u8 version;
+	u8 flags;
+	u8 mac[ETH_ALEN];
+};
+
+/**
+ * struct brcmf_dload_data_le - data passing to firmware for downloading
+ * @flag: flags related to download data.
+ * @dload_type: type of download data.
+ * @len: length in bytes of download data.
+ * @crc: crc of download data.
+ * @data: download data.
+ */
+struct brcmf_dload_data_le {
+	__le16 flag;
+	__le16 dload_type;
+	__le32 len;
+	__le32 crc;
+	u8 data[1];
+};
+
+/**
+ * struct brcmf_pno_bssid_le - bssid configuration for PNO scan.
+ *
+ * @bssid: BSS network identifier.
+ * @flags: flags for this BSSID.
+ */
+struct brcmf_pno_bssid_le {
+	u8 bssid[ETH_ALEN];
+	__le16 flags;
+};
+
+/**
+ * struct brcmf_pktcnt_le - packet counters.
+ *
+ * @rx_good_pkt: packets (MSDUs & MMPDUs) received from this station
+ * @rx_bad_pkt: failed rx packets
+ * @tx_good_pkt: packets (MSDUs & MMPDUs) transmitted to this station
+ * @tx_bad_pkt: failed tx packets
+ * @rx_ocast_good_pkt: unicast packets destined for others
+ */
+struct brcmf_pktcnt_le {
+	__le32 rx_good_pkt;
+	__le32 rx_bad_pkt;
+	__le32 tx_good_pkt;
+	__le32 tx_bad_pkt;
+	__le32 rx_ocast_good_pkt;
+};
+
+/**
+ * struct brcmf_gtk_keyinfo_le - GTP rekey data
+ *
+ * @kck: key confirmation key.
+ * @kek: key encryption key.
+ * @replay_counter: replay counter.
+ */
+struct brcmf_gtk_keyinfo_le {
+	u8 kck[BRCMF_RSN_KCK_LENGTH];
+	u8 kek[BRCMF_RSN_KEK_LENGTH];
+	u8 replay_counter[BRCMF_RSN_REPLAY_LEN];
+};
+
+#define BRCMF_PNO_REPORT_NO_BATCH	BIT(2)
+
+/**
+ * struct brcmf_gscan_bucket_config - configuration data for channel bucket.
+ *
+ * @bucket_end_index: last channel index in @channel_list in
+ *	@struct brcmf_pno_config_le.
+ * @bucket_freq_multiple: scan interval expressed in N * @scan_freq.
+ * @flag: channel bucket report flags.
+ * @reserved: for future use.
+ * @repeat: number of scan at interval for exponential scan.
+ * @max_freq_multiple: maximum scan interval for exponential scan.
+ */
+struct brcmf_gscan_bucket_config {
+	u8 bucket_end_index;
+	u8 bucket_freq_multiple;
+	u8 flag;
+	u8 reserved;
+	__le16 repeat;
+	__le16 max_freq_multiple;
+};
+
+/* version supported which must match firmware */
+#define BRCMF_GSCAN_CFG_VERSION                     2
+
+/**
+ * enum brcmf_gscan_cfg_flags - bit values for gscan flags.
+ *
+ * @BRCMF_GSCAN_CFG_FLAGS_ALL_RESULTS: send probe responses/beacons to host.
+ * @BRCMF_GSCAN_CFG_ALL_BUCKETS_IN_1ST_SCAN: all buckets will be included in
+ *	first scan cycle.
+ * @BRCMF_GSCAN_CFG_FLAGS_CHANGE_ONLY: indicated only flags member is changed.
+ */
+enum brcmf_gscan_cfg_flags {
+	BRCMF_GSCAN_CFG_FLAGS_ALL_RESULTS = BIT(0),
+	BRCMF_GSCAN_CFG_ALL_BUCKETS_IN_1ST_SCAN = BIT(3),
+	BRCMF_GSCAN_CFG_FLAGS_CHANGE_ONLY = BIT(7),
+};
+
+/**
+ * struct brcmf_gscan_config - configuration data for gscan.
+ *
+ * @version: version of the api to match firmware.
+ * @flags: flags according %enum brcmf_gscan_cfg_flags.
+ * @buffer_threshold: percentage threshold of buffer to generate an event.
+ * @swc_nbssid_threshold: number of BSSIDs with significant change that
+ *	will generate an event.
+ * @swc_rssi_window_size: size of rssi cache buffer (max=8).
+ * @count_of_channel_buckets: number of array members in @bucket.
+ * @retry_threshold: !unknown!
+ * @lost_ap_window: !unknown!
+ * @bucket: array of channel buckets.
+ */
+struct brcmf_gscan_config {
+	__le16 version;
+	u8 flags;
+	u8 buffer_threshold;
+	u8 swc_nbssid_threshold;
+	u8 swc_rssi_window_size;
+	u8 count_of_channel_buckets;
+	u8 retry_threshold;
+	__le16  lost_ap_window;
+	struct brcmf_gscan_bucket_config bucket[1];
+};
+
+#endif /* FWIL_TYPES_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
new file mode 100644
index 0000000..f3cbf78
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
@@ -0,0 +1,2483 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/if_ether.h>
+#include <linux/spinlock.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/err.h>
+#include <linux/jiffies.h>
+#include <net/cfg80211.h>
+
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+#include "core.h"
+#include "debug.h"
+#include "bus.h"
+#include "fwil.h"
+#include "fwil_types.h"
+#include "fweh.h"
+#include "fwsignal.h"
+#include "p2p.h"
+#include "cfg80211.h"
+#include "proto.h"
+#include "bcdc.h"
+#include "common.h"
+
+/**
+ * DOC: Firmware Signalling
+ *
+ * Firmware can send signals to host and vice versa, which are passed in the
+ * data packets using TLV based header. This signalling layer is on top of the
+ * BDC bus protocol layer.
+ */
+
+/*
+ * single definition for firmware-driver flow control tlv's.
+ *
+ * each tlv is specified by BRCMF_FWS_TLV_DEF(name, ID, length).
+ * A length value 0 indicates variable length tlv.
+ */
+#define BRCMF_FWS_TLV_DEFLIST \
+	BRCMF_FWS_TLV_DEF(MAC_OPEN, 1, 1) \
+	BRCMF_FWS_TLV_DEF(MAC_CLOSE, 2, 1) \
+	BRCMF_FWS_TLV_DEF(MAC_REQUEST_CREDIT, 3, 2) \
+	BRCMF_FWS_TLV_DEF(TXSTATUS, 4, 4) \
+	BRCMF_FWS_TLV_DEF(PKTTAG, 5, 4) \
+	BRCMF_FWS_TLV_DEF(MACDESC_ADD,	6, 8) \
+	BRCMF_FWS_TLV_DEF(MACDESC_DEL, 7, 8) \
+	BRCMF_FWS_TLV_DEF(RSSI, 8, 1) \
+	BRCMF_FWS_TLV_DEF(INTERFACE_OPEN, 9, 1) \
+	BRCMF_FWS_TLV_DEF(INTERFACE_CLOSE, 10, 1) \
+	BRCMF_FWS_TLV_DEF(FIFO_CREDITBACK, 11, 6) \
+	BRCMF_FWS_TLV_DEF(PENDING_TRAFFIC_BMP, 12, 2) \
+	BRCMF_FWS_TLV_DEF(MAC_REQUEST_PACKET, 13, 3) \
+	BRCMF_FWS_TLV_DEF(HOST_REORDER_RXPKTS, 14, 10) \
+	BRCMF_FWS_TLV_DEF(TRANS_ID, 18, 6) \
+	BRCMF_FWS_TLV_DEF(COMP_TXSTATUS, 19, 1) \
+	BRCMF_FWS_TLV_DEF(FILLER, 255, 0)
+
+/*
+ * enum brcmf_fws_tlv_type - definition of tlv identifiers.
+ */
+#define BRCMF_FWS_TLV_DEF(name, id, len) \
+	BRCMF_FWS_TYPE_ ## name =  id,
+enum brcmf_fws_tlv_type {
+	BRCMF_FWS_TLV_DEFLIST
+	BRCMF_FWS_TYPE_INVALID
+};
+#undef BRCMF_FWS_TLV_DEF
+
+/*
+ * enum brcmf_fws_tlv_len - definition of tlv lengths.
+ */
+#define BRCMF_FWS_TLV_DEF(name, id, len) \
+	BRCMF_FWS_TYPE_ ## name ## _LEN = (len),
+enum brcmf_fws_tlv_len {
+	BRCMF_FWS_TLV_DEFLIST
+};
+#undef BRCMF_FWS_TLV_DEF
+
+/* AMPDU rx reordering definitions */
+#define BRCMF_RXREORDER_FLOWID_OFFSET		0
+#define BRCMF_RXREORDER_MAXIDX_OFFSET		2
+#define BRCMF_RXREORDER_FLAGS_OFFSET		4
+#define BRCMF_RXREORDER_CURIDX_OFFSET		6
+#define BRCMF_RXREORDER_EXPIDX_OFFSET		8
+
+#define BRCMF_RXREORDER_DEL_FLOW		0x01
+#define BRCMF_RXREORDER_FLUSH_ALL		0x02
+#define BRCMF_RXREORDER_CURIDX_VALID		0x04
+#define BRCMF_RXREORDER_EXPIDX_VALID		0x08
+#define BRCMF_RXREORDER_NEW_HOLE		0x10
+
+#ifdef DEBUG
+/*
+ * brcmf_fws_tlv_names - array of tlv names.
+ */
+#define BRCMF_FWS_TLV_DEF(name, id, len) \
+	{ id, #name },
+static struct {
+	enum brcmf_fws_tlv_type id;
+	const char *name;
+} brcmf_fws_tlv_names[] = {
+	BRCMF_FWS_TLV_DEFLIST
+};
+#undef BRCMF_FWS_TLV_DEF
+
+
+static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(brcmf_fws_tlv_names); i++)
+		if (brcmf_fws_tlv_names[i].id == id)
+			return brcmf_fws_tlv_names[i].name;
+
+	return "INVALID";
+}
+#else
+static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id)
+{
+	return "NODEBUG";
+}
+#endif /* DEBUG */
+
+/*
+ * The PKTTAG tlv has additional bytes when firmware-signalling
+ * mode has REUSESEQ flag set.
+ */
+#define BRCMF_FWS_TYPE_SEQ_LEN				2
+
+/*
+ * flags used to enable tlv signalling from firmware.
+ */
+#define BRCMF_FWS_FLAGS_RSSI_SIGNALS			0x0001
+#define BRCMF_FWS_FLAGS_XONXOFF_SIGNALS			0x0002
+#define BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS		0x0004
+#define BRCMF_FWS_FLAGS_HOST_PROPTXSTATUS_ACTIVE	0x0008
+#define BRCMF_FWS_FLAGS_PSQ_GENERATIONFSM_ENABLE	0x0010
+#define BRCMF_FWS_FLAGS_PSQ_ZERO_BUFFER_ENABLE		0x0020
+#define BRCMF_FWS_FLAGS_HOST_RXREORDER_ACTIVE		0x0040
+
+#define BRCMF_FWS_MAC_DESC_TABLE_SIZE			32
+#define BRCMF_FWS_MAC_DESC_ID_INVALID			0xff
+
+#define BRCMF_FWS_HOSTIF_FLOWSTATE_OFF			0
+#define BRCMF_FWS_HOSTIF_FLOWSTATE_ON			1
+#define BRCMF_FWS_FLOWCONTROL_HIWATER			128
+#define BRCMF_FWS_FLOWCONTROL_LOWATER			64
+
+#define BRCMF_FWS_PSQ_PREC_COUNT		((BRCMF_FWS_FIFO_COUNT + 1) * 2)
+#define BRCMF_FWS_PSQ_LEN				256
+
+#define BRCMF_FWS_HTOD_FLAG_PKTFROMHOST			0x01
+#define BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED		0x02
+
+#define BRCMF_FWS_RET_OK_NOSCHEDULE			0
+#define BRCMF_FWS_RET_OK_SCHEDULE			1
+
+#define BRCMF_FWS_MODE_REUSESEQ_SHIFT			3	/* seq reuse */
+#define BRCMF_FWS_MODE_SET_REUSESEQ(x, val)	((x) = \
+		((x) & ~(1 << BRCMF_FWS_MODE_REUSESEQ_SHIFT)) | \
+		(((val) & 1) << BRCMF_FWS_MODE_REUSESEQ_SHIFT))
+#define BRCMF_FWS_MODE_GET_REUSESEQ(x)	\
+		(((x) >> BRCMF_FWS_MODE_REUSESEQ_SHIFT) & 1)
+
+/**
+ * enum brcmf_fws_skb_state - indicates processing state of skb.
+ *
+ * @BRCMF_FWS_SKBSTATE_NEW: sk_buff is newly arrived in the driver.
+ * @BRCMF_FWS_SKBSTATE_DELAYED: sk_buff had to wait on queue.
+ * @BRCMF_FWS_SKBSTATE_SUPPRESSED: sk_buff has been suppressed by firmware.
+ * @BRCMF_FWS_SKBSTATE_TIM: allocated for TIM update info.
+ */
+enum brcmf_fws_skb_state {
+	BRCMF_FWS_SKBSTATE_NEW,
+	BRCMF_FWS_SKBSTATE_DELAYED,
+	BRCMF_FWS_SKBSTATE_SUPPRESSED,
+	BRCMF_FWS_SKBSTATE_TIM
+};
+
+/**
+ * struct brcmf_skbuff_cb - control buffer associated with skbuff.
+ *
+ * @bus_flags: 2 bytes reserved for bus specific parameters
+ * @if_flags: holds interface index and packet related flags.
+ * @htod: host to device packet identifier (used in PKTTAG tlv).
+ * @htod_seq: this 16-bit is original seq number for every suppress packet.
+ * @state: transmit state of the packet.
+ * @mac: descriptor related to destination for this packet.
+ *
+ * This information is stored in control buffer struct sk_buff::cb, which
+ * provides 48 bytes of storage so this structure should not exceed that.
+ */
+struct brcmf_skbuff_cb {
+	u16 bus_flags;
+	u16 if_flags;
+	u32 htod;
+	u16 htod_seq;
+	enum brcmf_fws_skb_state state;
+	struct brcmf_fws_mac_descriptor *mac;
+};
+
+/*
+ * macro casting skbuff control buffer to struct brcmf_skbuff_cb.
+ */
+#define brcmf_skbcb(skb)	((struct brcmf_skbuff_cb *)((skb)->cb))
+
+/*
+ * sk_buff control if flags
+ *
+ *	b[11]  - packet sent upon firmware request.
+ *	b[10]  - packet only contains signalling data.
+ *	b[9]   - packet is a tx packet.
+ *	b[8]   - packet used requested credit
+ *	b[7]   - interface in AP mode.
+ *	b[3:0] - interface index.
+ */
+#define BRCMF_SKB_IF_FLAGS_REQUESTED_MASK	0x0800
+#define BRCMF_SKB_IF_FLAGS_REQUESTED_SHIFT	11
+#define BRCMF_SKB_IF_FLAGS_SIGNAL_ONLY_MASK	0x0400
+#define BRCMF_SKB_IF_FLAGS_SIGNAL_ONLY_SHIFT	10
+#define BRCMF_SKB_IF_FLAGS_TRANSMIT_MASK        0x0200
+#define BRCMF_SKB_IF_FLAGS_TRANSMIT_SHIFT	9
+#define BRCMF_SKB_IF_FLAGS_REQ_CREDIT_MASK	0x0100
+#define BRCMF_SKB_IF_FLAGS_REQ_CREDIT_SHIFT	8
+#define BRCMF_SKB_IF_FLAGS_IF_AP_MASK		0x0080
+#define BRCMF_SKB_IF_FLAGS_IF_AP_SHIFT		7
+#define BRCMF_SKB_IF_FLAGS_INDEX_MASK		0x000f
+#define BRCMF_SKB_IF_FLAGS_INDEX_SHIFT		0
+
+#define brcmf_skb_if_flags_set_field(skb, field, value) \
+	brcmu_maskset16(&(brcmf_skbcb(skb)->if_flags), \
+			BRCMF_SKB_IF_FLAGS_ ## field ## _MASK, \
+			BRCMF_SKB_IF_FLAGS_ ## field ## _SHIFT, (value))
+#define brcmf_skb_if_flags_get_field(skb, field) \
+	brcmu_maskget16(brcmf_skbcb(skb)->if_flags, \
+			BRCMF_SKB_IF_FLAGS_ ## field ## _MASK, \
+			BRCMF_SKB_IF_FLAGS_ ## field ## _SHIFT)
+
+/*
+ * sk_buff control packet identifier
+ *
+ * 32-bit packet identifier used in PKTTAG tlv from host to dongle.
+ *
+ * - Generated at the host (e.g. dhd)
+ * - Seen as a generic sequence number by firmware except for the flags field.
+ *
+ * Generation	: b[31]	=> generation number for this packet [host->fw]
+ *			   OR, current generation number [fw->host]
+ * Flags	: b[30:27] => command, status flags
+ * FIFO-AC	: b[26:24] => AC-FIFO id
+ * h-slot	: b[23:8] => hanger-slot
+ * freerun	: b[7:0] => A free running counter
+ */
+#define BRCMF_SKB_HTOD_TAG_GENERATION_MASK		0x80000000
+#define BRCMF_SKB_HTOD_TAG_GENERATION_SHIFT		31
+#define BRCMF_SKB_HTOD_TAG_FLAGS_MASK			0x78000000
+#define BRCMF_SKB_HTOD_TAG_FLAGS_SHIFT			27
+#define BRCMF_SKB_HTOD_TAG_FIFO_MASK			0x07000000
+#define BRCMF_SKB_HTOD_TAG_FIFO_SHIFT			24
+#define BRCMF_SKB_HTOD_TAG_HSLOT_MASK			0x00ffff00
+#define BRCMF_SKB_HTOD_TAG_HSLOT_SHIFT			8
+#define BRCMF_SKB_HTOD_TAG_FREERUN_MASK			0x000000ff
+#define BRCMF_SKB_HTOD_TAG_FREERUN_SHIFT		0
+
+#define brcmf_skb_htod_tag_set_field(skb, field, value) \
+	brcmu_maskset32(&(brcmf_skbcb(skb)->htod), \
+			BRCMF_SKB_HTOD_TAG_ ## field ## _MASK, \
+			BRCMF_SKB_HTOD_TAG_ ## field ## _SHIFT, (value))
+#define brcmf_skb_htod_tag_get_field(skb, field) \
+	brcmu_maskget32(brcmf_skbcb(skb)->htod, \
+			BRCMF_SKB_HTOD_TAG_ ## field ## _MASK, \
+			BRCMF_SKB_HTOD_TAG_ ## field ## _SHIFT)
+
+#define BRCMF_SKB_HTOD_SEQ_FROMFW_MASK			0x2000
+#define BRCMF_SKB_HTOD_SEQ_FROMFW_SHIFT			13
+#define BRCMF_SKB_HTOD_SEQ_FROMDRV_MASK			0x1000
+#define BRCMF_SKB_HTOD_SEQ_FROMDRV_SHIFT		12
+#define BRCMF_SKB_HTOD_SEQ_NR_MASK			0x0fff
+#define BRCMF_SKB_HTOD_SEQ_NR_SHIFT			0
+
+#define brcmf_skb_htod_seq_set_field(skb, field, value) \
+	brcmu_maskset16(&(brcmf_skbcb(skb)->htod_seq), \
+			BRCMF_SKB_HTOD_SEQ_ ## field ## _MASK, \
+			BRCMF_SKB_HTOD_SEQ_ ## field ## _SHIFT, (value))
+#define brcmf_skb_htod_seq_get_field(skb, field) \
+	brcmu_maskget16(brcmf_skbcb(skb)->htod_seq, \
+			BRCMF_SKB_HTOD_SEQ_ ## field ## _MASK, \
+			BRCMF_SKB_HTOD_SEQ_ ## field ## _SHIFT)
+
+#define BRCMF_FWS_TXSTAT_GENERATION_MASK	0x80000000
+#define BRCMF_FWS_TXSTAT_GENERATION_SHIFT	31
+#define BRCMF_FWS_TXSTAT_FLAGS_MASK		0x78000000
+#define BRCMF_FWS_TXSTAT_FLAGS_SHIFT		27
+#define BRCMF_FWS_TXSTAT_FIFO_MASK		0x07000000
+#define BRCMF_FWS_TXSTAT_FIFO_SHIFT		24
+#define BRCMF_FWS_TXSTAT_HSLOT_MASK		0x00FFFF00
+#define BRCMF_FWS_TXSTAT_HSLOT_SHIFT		8
+#define BRCMF_FWS_TXSTAT_FREERUN_MASK		0x000000FF
+#define BRCMF_FWS_TXSTAT_FREERUN_SHIFT		0
+
+#define brcmf_txstatus_get_field(txs, field) \
+	brcmu_maskget32(txs, BRCMF_FWS_TXSTAT_ ## field ## _MASK, \
+			BRCMF_FWS_TXSTAT_ ## field ## _SHIFT)
+
+/* How long to defer borrowing in jiffies */
+#define BRCMF_FWS_BORROW_DEFER_PERIOD		(HZ / 10)
+
+/**
+ * enum brcmf_fws_fifo - fifo indices used by dongle firmware.
+ *
+ * @BRCMF_FWS_FIFO_FIRST: first fifo, ie. background.
+ * @BRCMF_FWS_FIFO_AC_BK: fifo for background traffic.
+ * @BRCMF_FWS_FIFO_AC_BE: fifo for best-effort traffic.
+ * @BRCMF_FWS_FIFO_AC_VI: fifo for video traffic.
+ * @BRCMF_FWS_FIFO_AC_VO: fifo for voice traffic.
+ * @BRCMF_FWS_FIFO_BCMC: fifo for broadcast/multicast (AP only).
+ * @BRCMF_FWS_FIFO_ATIM: fifo for ATIM (AP only).
+ * @BRCMF_FWS_FIFO_COUNT: number of fifos.
+ */
+enum brcmf_fws_fifo {
+	BRCMF_FWS_FIFO_FIRST,
+	BRCMF_FWS_FIFO_AC_BK = BRCMF_FWS_FIFO_FIRST,
+	BRCMF_FWS_FIFO_AC_BE,
+	BRCMF_FWS_FIFO_AC_VI,
+	BRCMF_FWS_FIFO_AC_VO,
+	BRCMF_FWS_FIFO_BCMC,
+	BRCMF_FWS_FIFO_ATIM,
+	BRCMF_FWS_FIFO_COUNT
+};
+
+/**
+ * enum brcmf_fws_txstatus - txstatus flag values.
+ *
+ * @BRCMF_FWS_TXSTATUS_DISCARD:
+ *	host is free to discard the packet.
+ * @BRCMF_FWS_TXSTATUS_CORE_SUPPRESS:
+ *	802.11 core suppressed the packet.
+ * @BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS:
+ *	firmware suppress the packet as device is already in PS mode.
+ * @BRCMF_FWS_TXSTATUS_FW_TOSSED:
+ *	firmware tossed the packet.
+ * @BRCMF_FWS_TXSTATUS_HOST_TOSSED:
+ *	host tossed the packet.
+ */
+enum brcmf_fws_txstatus {
+	BRCMF_FWS_TXSTATUS_DISCARD,
+	BRCMF_FWS_TXSTATUS_CORE_SUPPRESS,
+	BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS,
+	BRCMF_FWS_TXSTATUS_FW_TOSSED,
+	BRCMF_FWS_TXSTATUS_HOST_TOSSED
+};
+
+enum brcmf_fws_fcmode {
+	BRCMF_FWS_FCMODE_NONE,
+	BRCMF_FWS_FCMODE_IMPLIED_CREDIT,
+	BRCMF_FWS_FCMODE_EXPLICIT_CREDIT
+};
+
+enum brcmf_fws_mac_desc_state {
+	BRCMF_FWS_STATE_OPEN = 1,
+	BRCMF_FWS_STATE_CLOSE
+};
+
+/**
+ * struct brcmf_fws_mac_descriptor - firmware signalling data per node/interface
+ *
+ * @occupied: slot is in use.
+ * @mac_handle: handle for mac entry determined by firmware.
+ * @interface_id: interface index.
+ * @state: current state.
+ * @suppressed: mac entry is suppressed.
+ * @generation: generation bit.
+ * @ac_bitmap: ac queue bitmap.
+ * @requested_credit: credits requested by firmware.
+ * @ea: ethernet address.
+ * @seq: per-node free-running sequence.
+ * @psq: power-save queue.
+ * @transit_count: packet in transit to firmware.
+ */
+struct brcmf_fws_mac_descriptor {
+	char name[16];
+	u8 occupied;
+	u8 mac_handle;
+	u8 interface_id;
+	u8 state;
+	bool suppressed;
+	u8 generation;
+	u8 ac_bitmap;
+	u8 requested_credit;
+	u8 requested_packet;
+	u8 ea[ETH_ALEN];
+	u8 seq[BRCMF_FWS_FIFO_COUNT];
+	struct pktq psq;
+	int transit_count;
+	int suppr_transit_count;
+	bool send_tim_signal;
+	u8 traffic_pending_bmp;
+	u8 traffic_lastreported_bmp;
+};
+
+#define BRCMF_FWS_HANGER_MAXITEMS	1024
+
+/**
+ * enum brcmf_fws_hanger_item_state - state of hanger item.
+ *
+ * @BRCMF_FWS_HANGER_ITEM_STATE_FREE: item is free for use.
+ * @BRCMF_FWS_HANGER_ITEM_STATE_INUSE: item is in use.
+ * @BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED: item was suppressed.
+ */
+enum brcmf_fws_hanger_item_state {
+	BRCMF_FWS_HANGER_ITEM_STATE_FREE = 1,
+	BRCMF_FWS_HANGER_ITEM_STATE_INUSE,
+	BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED
+};
+
+
+/**
+ * struct brcmf_fws_hanger_item - single entry for tx pending packet.
+ *
+ * @state: entry is either free or occupied.
+ * @pkt: packet itself.
+ */
+struct brcmf_fws_hanger_item {
+	enum brcmf_fws_hanger_item_state state;
+	struct sk_buff *pkt;
+};
+
+/**
+ * struct brcmf_fws_hanger - holds packets awaiting firmware txstatus.
+ *
+ * @pushed: packets pushed to await txstatus.
+ * @popped: packets popped upon handling txstatus.
+ * @failed_to_push: packets that could not be pushed.
+ * @failed_to_pop: packets that could not be popped.
+ * @failed_slotfind: packets for which failed to find an entry.
+ * @slot_pos: last returned item index for a free entry.
+ * @items: array of hanger items.
+ */
+struct brcmf_fws_hanger {
+	u32 pushed;
+	u32 popped;
+	u32 failed_to_push;
+	u32 failed_to_pop;
+	u32 failed_slotfind;
+	u32 slot_pos;
+	struct brcmf_fws_hanger_item items[BRCMF_FWS_HANGER_MAXITEMS];
+};
+
+struct brcmf_fws_macdesc_table {
+	struct brcmf_fws_mac_descriptor nodes[BRCMF_FWS_MAC_DESC_TABLE_SIZE];
+	struct brcmf_fws_mac_descriptor iface[BRCMF_MAX_IFS];
+	struct brcmf_fws_mac_descriptor other;
+};
+
+struct brcmf_fws_stats {
+	u32 tlv_parse_failed;
+	u32 tlv_invalid_type;
+	u32 header_only_pkt;
+	u32 header_pulls;
+	u32 pkt2bus;
+	u32 send_pkts[5];
+	u32 requested_sent[5];
+	u32 generic_error;
+	u32 mac_update_failed;
+	u32 mac_ps_update_failed;
+	u32 if_update_failed;
+	u32 packet_request_failed;
+	u32 credit_request_failed;
+	u32 rollback_success;
+	u32 rollback_failed;
+	u32 delayq_full_error;
+	u32 supprq_full_error;
+	u32 txs_indicate;
+	u32 txs_discard;
+	u32 txs_supp_core;
+	u32 txs_supp_ps;
+	u32 txs_tossed;
+	u32 txs_host_tossed;
+	u32 bus_flow_block;
+	u32 fws_flow_block;
+};
+
+struct brcmf_fws_info {
+	struct brcmf_pub *drvr;
+	spinlock_t spinlock;
+	ulong flags;
+	struct brcmf_fws_stats stats;
+	struct brcmf_fws_hanger hanger;
+	enum brcmf_fws_fcmode fcmode;
+	bool fw_signals;
+	bool bcmc_credit_check;
+	struct brcmf_fws_macdesc_table desc;
+	struct workqueue_struct *fws_wq;
+	struct work_struct fws_dequeue_work;
+	u32 fifo_enqpkt[BRCMF_FWS_FIFO_COUNT];
+	int fifo_credit[BRCMF_FWS_FIFO_COUNT];
+	int credits_borrowed[BRCMF_FWS_FIFO_AC_VO + 1];
+	int deq_node_pos[BRCMF_FWS_FIFO_COUNT];
+	u32 fifo_credit_map;
+	u32 fifo_delay_map;
+	unsigned long borrow_defer_timestamp;
+	bool bus_flow_blocked;
+	bool creditmap_received;
+	u8 mode;
+	bool avoid_queueing;
+};
+
+/*
+ * brcmf_fws_prio2fifo - mapping from 802.1d priority to firmware fifo index.
+ */
+static const int brcmf_fws_prio2fifo[] = {
+	BRCMF_FWS_FIFO_AC_BE,
+	BRCMF_FWS_FIFO_AC_BK,
+	BRCMF_FWS_FIFO_AC_BK,
+	BRCMF_FWS_FIFO_AC_BE,
+	BRCMF_FWS_FIFO_AC_VI,
+	BRCMF_FWS_FIFO_AC_VI,
+	BRCMF_FWS_FIFO_AC_VO,
+	BRCMF_FWS_FIFO_AC_VO
+};
+
+#define BRCMF_FWS_TLV_DEF(name, id, len) \
+	case BRCMF_FWS_TYPE_ ## name: \
+		return len;
+
+/**
+ * brcmf_fws_get_tlv_len() - returns defined length for given tlv id.
+ *
+ * @fws: firmware-signalling information.
+ * @id: identifier of the TLV.
+ *
+ * Return: the specified length for the given TLV; Otherwise -EINVAL.
+ */
+static int brcmf_fws_get_tlv_len(struct brcmf_fws_info *fws,
+				 enum brcmf_fws_tlv_type id)
+{
+	switch (id) {
+	BRCMF_FWS_TLV_DEFLIST
+	default:
+		fws->stats.tlv_invalid_type++;
+		break;
+	}
+	return -EINVAL;
+}
+#undef BRCMF_FWS_TLV_DEF
+
+static void brcmf_fws_lock(struct brcmf_fws_info *fws)
+		__acquires(&fws->spinlock)
+{
+	spin_lock_irqsave(&fws->spinlock, fws->flags);
+}
+
+static void brcmf_fws_unlock(struct brcmf_fws_info *fws)
+		__releases(&fws->spinlock)
+{
+	spin_unlock_irqrestore(&fws->spinlock, fws->flags);
+}
+
+static bool brcmf_fws_ifidx_match(struct sk_buff *skb, void *arg)
+{
+	u32 ifidx = brcmf_skb_if_flags_get_field(skb, INDEX);
+	return ifidx == *(int *)arg;
+}
+
+static void brcmf_fws_psq_flush(struct brcmf_fws_info *fws, struct pktq *q,
+				int ifidx)
+{
+	bool (*matchfn)(struct sk_buff *, void *) = NULL;
+	struct sk_buff *skb;
+	int prec;
+
+	if (ifidx != -1)
+		matchfn = brcmf_fws_ifidx_match;
+	for (prec = 0; prec < q->num_prec; prec++) {
+		skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx);
+		while (skb) {
+			brcmu_pkt_buf_free_skb(skb);
+			skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx);
+		}
+	}
+}
+
+static void brcmf_fws_hanger_init(struct brcmf_fws_hanger *hanger)
+{
+	int i;
+
+	memset(hanger, 0, sizeof(*hanger));
+	for (i = 0; i < ARRAY_SIZE(hanger->items); i++)
+		hanger->items[i].state = BRCMF_FWS_HANGER_ITEM_STATE_FREE;
+}
+
+static u32 brcmf_fws_hanger_get_free_slot(struct brcmf_fws_hanger *h)
+{
+	u32 i;
+
+	i = (h->slot_pos + 1) % BRCMF_FWS_HANGER_MAXITEMS;
+
+	while (i != h->slot_pos) {
+		if (h->items[i].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) {
+			h->slot_pos = i;
+			goto done;
+		}
+		i++;
+		if (i == BRCMF_FWS_HANGER_MAXITEMS)
+			i = 0;
+	}
+	brcmf_err("all slots occupied\n");
+	h->failed_slotfind++;
+	i = BRCMF_FWS_HANGER_MAXITEMS;
+done:
+	return i;
+}
+
+static int brcmf_fws_hanger_pushpkt(struct brcmf_fws_hanger *h,
+				    struct sk_buff *pkt, u32 slot_id)
+{
+	if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS)
+		return -ENOENT;
+
+	if (h->items[slot_id].state != BRCMF_FWS_HANGER_ITEM_STATE_FREE) {
+		brcmf_err("slot is not free\n");
+		h->failed_to_push++;
+		return -EINVAL;
+	}
+
+	h->items[slot_id].state = BRCMF_FWS_HANGER_ITEM_STATE_INUSE;
+	h->items[slot_id].pkt = pkt;
+	h->pushed++;
+	return 0;
+}
+
+static inline int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h,
+					  u32 slot_id, struct sk_buff **pktout,
+					  bool remove_item)
+{
+	if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS)
+		return -ENOENT;
+
+	if (h->items[slot_id].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) {
+		brcmf_err("entry not in use\n");
+		h->failed_to_pop++;
+		return -EINVAL;
+	}
+
+	*pktout = h->items[slot_id].pkt;
+	if (remove_item) {
+		h->items[slot_id].state = BRCMF_FWS_HANGER_ITEM_STATE_FREE;
+		h->items[slot_id].pkt = NULL;
+		h->popped++;
+	}
+	return 0;
+}
+
+static int brcmf_fws_hanger_mark_suppressed(struct brcmf_fws_hanger *h,
+					    u32 slot_id)
+{
+	if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS)
+		return -ENOENT;
+
+	if (h->items[slot_id].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) {
+		brcmf_err("entry not in use\n");
+		return -EINVAL;
+	}
+
+	h->items[slot_id].state = BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED;
+	return 0;
+}
+
+static void brcmf_fws_hanger_cleanup(struct brcmf_fws_info *fws,
+				     bool (*fn)(struct sk_buff *, void *),
+				     int ifidx)
+{
+	struct brcmf_fws_hanger *h = &fws->hanger;
+	struct sk_buff *skb;
+	int i;
+	enum brcmf_fws_hanger_item_state s;
+
+	for (i = 0; i < ARRAY_SIZE(h->items); i++) {
+		s = h->items[i].state;
+		if (s == BRCMF_FWS_HANGER_ITEM_STATE_INUSE ||
+		    s == BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED) {
+			skb = h->items[i].pkt;
+			if (fn == NULL || fn(skb, &ifidx)) {
+				/* suppress packets freed from psq */
+				if (s == BRCMF_FWS_HANGER_ITEM_STATE_INUSE)
+					brcmu_pkt_buf_free_skb(skb);
+				h->items[i].state =
+					BRCMF_FWS_HANGER_ITEM_STATE_FREE;
+			}
+		}
+	}
+}
+
+static void brcmf_fws_macdesc_set_name(struct brcmf_fws_info *fws,
+				       struct brcmf_fws_mac_descriptor *desc)
+{
+	if (desc == &fws->desc.other)
+		strlcpy(desc->name, "MAC-OTHER", sizeof(desc->name));
+	else if (desc->mac_handle)
+		scnprintf(desc->name, sizeof(desc->name), "MAC-%d:%d",
+			  desc->mac_handle, desc->interface_id);
+	else
+		scnprintf(desc->name, sizeof(desc->name), "MACIF:%d",
+			  desc->interface_id);
+}
+
+static void brcmf_fws_macdesc_init(struct brcmf_fws_mac_descriptor *desc,
+				   u8 *addr, u8 ifidx)
+{
+	brcmf_dbg(TRACE,
+		  "enter: desc %p ea=%pM, ifidx=%u\n", desc, addr, ifidx);
+	desc->occupied = 1;
+	desc->state = BRCMF_FWS_STATE_OPEN;
+	desc->requested_credit = 0;
+	desc->requested_packet = 0;
+	/* depending on use may need ifp->bsscfgidx instead */
+	desc->interface_id = ifidx;
+	desc->ac_bitmap = 0xff; /* update this when handling APSD */
+	if (addr)
+		memcpy(&desc->ea[0], addr, ETH_ALEN);
+}
+
+static
+void brcmf_fws_macdesc_deinit(struct brcmf_fws_mac_descriptor *desc)
+{
+	brcmf_dbg(TRACE,
+		  "enter: ea=%pM, ifidx=%u\n", desc->ea, desc->interface_id);
+	desc->occupied = 0;
+	desc->state = BRCMF_FWS_STATE_CLOSE;
+	desc->requested_credit = 0;
+	desc->requested_packet = 0;
+}
+
+static struct brcmf_fws_mac_descriptor *
+brcmf_fws_macdesc_lookup(struct brcmf_fws_info *fws, u8 *ea)
+{
+	struct brcmf_fws_mac_descriptor *entry;
+	int i;
+
+	if (ea == NULL)
+		return ERR_PTR(-EINVAL);
+
+	entry = &fws->desc.nodes[0];
+	for (i = 0; i < ARRAY_SIZE(fws->desc.nodes); i++) {
+		if (entry->occupied && !memcmp(entry->ea, ea, ETH_ALEN))
+			return entry;
+		entry++;
+	}
+
+	return ERR_PTR(-ENOENT);
+}
+
+static struct brcmf_fws_mac_descriptor*
+brcmf_fws_macdesc_find(struct brcmf_fws_info *fws, struct brcmf_if *ifp, u8 *da)
+{
+	struct brcmf_fws_mac_descriptor *entry = &fws->desc.other;
+	bool multicast;
+
+	multicast = is_multicast_ether_addr(da);
+
+	/* Multicast destination, STA and P2P clients get the interface entry.
+	 * STA/GC gets the Mac Entry for TDLS destinations, TDLS destinations
+	 * have their own entry.
+	 */
+	if (multicast && ifp->fws_desc) {
+		entry = ifp->fws_desc;
+		goto done;
+	}
+
+	entry = brcmf_fws_macdesc_lookup(fws, da);
+	if (IS_ERR(entry))
+		entry = ifp->fws_desc;
+
+done:
+	return entry;
+}
+
+static bool brcmf_fws_macdesc_closed(struct brcmf_fws_info *fws,
+				     struct brcmf_fws_mac_descriptor *entry,
+				     int fifo)
+{
+	struct brcmf_fws_mac_descriptor *if_entry;
+	bool closed;
+
+	/* for unique destination entries the related interface
+	 * may be closed.
+	 */
+	if (entry->mac_handle) {
+		if_entry = &fws->desc.iface[entry->interface_id];
+		if (if_entry->state == BRCMF_FWS_STATE_CLOSE)
+			return true;
+	}
+	/* an entry is closed when the state is closed and
+	 * the firmware did not request anything.
+	 */
+	closed = entry->state == BRCMF_FWS_STATE_CLOSE &&
+		 !entry->requested_credit && !entry->requested_packet;
+
+	/* Or firmware does not allow traffic for given fifo */
+	return closed || !(entry->ac_bitmap & BIT(fifo));
+}
+
+static void brcmf_fws_macdesc_cleanup(struct brcmf_fws_info *fws,
+				      struct brcmf_fws_mac_descriptor *entry,
+				      int ifidx)
+{
+	if (entry->occupied && (ifidx == -1 || ifidx == entry->interface_id)) {
+		brcmf_fws_psq_flush(fws, &entry->psq, ifidx);
+		entry->occupied = !!(entry->psq.len);
+	}
+}
+
+static void brcmf_fws_bus_txq_cleanup(struct brcmf_fws_info *fws,
+				      bool (*fn)(struct sk_buff *, void *),
+				      int ifidx)
+{
+	struct brcmf_fws_hanger_item *hi;
+	struct pktq *txq;
+	struct sk_buff *skb;
+	int prec;
+	u32 hslot;
+
+	txq = brcmf_bus_gettxq(fws->drvr->bus_if);
+	if (IS_ERR(txq)) {
+		brcmf_dbg(TRACE, "no txq to clean up\n");
+		return;
+	}
+
+	for (prec = 0; prec < txq->num_prec; prec++) {
+		skb = brcmu_pktq_pdeq_match(txq, prec, fn, &ifidx);
+		while (skb) {
+			hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
+			hi = &fws->hanger.items[hslot];
+			WARN_ON(skb != hi->pkt);
+			hi->state = BRCMF_FWS_HANGER_ITEM_STATE_FREE;
+			brcmu_pkt_buf_free_skb(skb);
+			skb = brcmu_pktq_pdeq_match(txq, prec, fn, &ifidx);
+		}
+	}
+}
+
+static void brcmf_fws_cleanup(struct brcmf_fws_info *fws, int ifidx)
+{
+	int i;
+	struct brcmf_fws_mac_descriptor *table;
+	bool (*matchfn)(struct sk_buff *, void *) = NULL;
+
+	if (fws == NULL)
+		return;
+
+	if (ifidx != -1)
+		matchfn = brcmf_fws_ifidx_match;
+
+	/* cleanup individual nodes */
+	table = &fws->desc.nodes[0];
+	for (i = 0; i < ARRAY_SIZE(fws->desc.nodes); i++)
+		brcmf_fws_macdesc_cleanup(fws, &table[i], ifidx);
+
+	brcmf_fws_macdesc_cleanup(fws, &fws->desc.other, ifidx);
+	brcmf_fws_bus_txq_cleanup(fws, matchfn, ifidx);
+	brcmf_fws_hanger_cleanup(fws, matchfn, ifidx);
+}
+
+static u8 brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb)
+{
+	struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
+	u8 *wlh;
+	u16 data_offset = 0;
+	u8 fillers;
+	__le32 pkttag = cpu_to_le32(brcmf_skbcb(skb)->htod);
+	__le16 pktseq = cpu_to_le16(brcmf_skbcb(skb)->htod_seq);
+
+	brcmf_dbg(TRACE, "enter: %s, idx=%d hslot=%d htod %X seq %X\n",
+		  entry->name, brcmf_skb_if_flags_get_field(skb, INDEX),
+		  (le32_to_cpu(pkttag) >> 8) & 0xffff,
+		  brcmf_skbcb(skb)->htod, brcmf_skbcb(skb)->htod_seq);
+	if (entry->send_tim_signal)
+		data_offset += 2 + BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN;
+	if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode))
+		data_offset += BRCMF_FWS_TYPE_SEQ_LEN;
+	/* +2 is for Type[1] and Len[1] in TLV, plus TIM signal */
+	data_offset += 2 + BRCMF_FWS_TYPE_PKTTAG_LEN;
+	fillers = round_up(data_offset, 4) - data_offset;
+	data_offset += fillers;
+
+	skb_push(skb, data_offset);
+	wlh = skb->data;
+
+	wlh[0] = BRCMF_FWS_TYPE_PKTTAG;
+	wlh[1] = BRCMF_FWS_TYPE_PKTTAG_LEN;
+	memcpy(&wlh[2], &pkttag, sizeof(pkttag));
+	if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode)) {
+		wlh[1] += BRCMF_FWS_TYPE_SEQ_LEN;
+		memcpy(&wlh[2 + BRCMF_FWS_TYPE_PKTTAG_LEN], &pktseq,
+		       sizeof(pktseq));
+	}
+	wlh += wlh[1] + 2;
+
+	if (entry->send_tim_signal) {
+		entry->send_tim_signal = 0;
+		wlh[0] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP;
+		wlh[1] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN;
+		wlh[2] = entry->mac_handle;
+		wlh[3] = entry->traffic_pending_bmp;
+		brcmf_dbg(TRACE, "adding TIM info: handle %d bmp 0x%X\n",
+			  entry->mac_handle, entry->traffic_pending_bmp);
+		wlh += BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN + 2;
+		entry->traffic_lastreported_bmp = entry->traffic_pending_bmp;
+	}
+	if (fillers)
+		memset(wlh, BRCMF_FWS_TYPE_FILLER, fillers);
+
+	return (u8)(data_offset >> 2);
+}
+
+static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws,
+				 struct brcmf_fws_mac_descriptor *entry,
+				 int fifo, bool send_immediately)
+{
+	struct sk_buff *skb;
+	struct brcmf_skbuff_cb *skcb;
+	s32 err;
+	u32 len;
+	u8 data_offset;
+	int ifidx;
+
+	/* check delayedQ and suppressQ in one call using bitmap */
+	if (brcmu_pktq_mlen(&entry->psq, 3 << (fifo * 2)) == 0)
+		entry->traffic_pending_bmp &= ~NBITVAL(fifo);
+	else
+		entry->traffic_pending_bmp |= NBITVAL(fifo);
+
+	entry->send_tim_signal = false;
+	if (entry->traffic_lastreported_bmp != entry->traffic_pending_bmp)
+		entry->send_tim_signal = true;
+	if (send_immediately && entry->send_tim_signal &&
+	    entry->state == BRCMF_FWS_STATE_CLOSE) {
+		/* create a dummy packet and sent that. The traffic          */
+		/* bitmap info will automatically be attached to that packet */
+		len = BRCMF_FWS_TYPE_PKTTAG_LEN + 2 +
+		      BRCMF_FWS_TYPE_SEQ_LEN +
+		      BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN + 2 +
+		      4 + fws->drvr->hdrlen;
+		skb = brcmu_pkt_buf_get_skb(len);
+		if (skb == NULL)
+			return false;
+		skb_pull(skb, len);
+		skcb = brcmf_skbcb(skb);
+		skcb->mac = entry;
+		skcb->state = BRCMF_FWS_SKBSTATE_TIM;
+		skcb->htod = 0;
+		skcb->htod_seq = 0;
+		data_offset = brcmf_fws_hdrpush(fws, skb);
+		ifidx = brcmf_skb_if_flags_get_field(skb, INDEX);
+		brcmf_fws_unlock(fws);
+		err = brcmf_proto_txdata(fws->drvr, ifidx, data_offset, skb);
+		brcmf_fws_lock(fws);
+		if (err)
+			brcmu_pkt_buf_free_skb(skb);
+		return true;
+	}
+	return false;
+}
+
+static void
+brcmf_fws_flow_control_check(struct brcmf_fws_info *fws, struct pktq *pq,
+			     u8 if_id)
+{
+	struct brcmf_if *ifp = brcmf_get_ifp(fws->drvr, if_id);
+
+	if (WARN_ON(!ifp))
+		return;
+
+	if ((ifp->netif_stop & BRCMF_NETIF_STOP_REASON_FWS_FC) &&
+	    pq->len <= BRCMF_FWS_FLOWCONTROL_LOWATER)
+		brcmf_txflowblock_if(ifp,
+				     BRCMF_NETIF_STOP_REASON_FWS_FC, false);
+	if (!(ifp->netif_stop & BRCMF_NETIF_STOP_REASON_FWS_FC) &&
+	    pq->len >= BRCMF_FWS_FLOWCONTROL_HIWATER) {
+		fws->stats.fws_flow_block++;
+		brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FWS_FC, true);
+	}
+	return;
+}
+
+static int brcmf_fws_rssi_indicate(struct brcmf_fws_info *fws, s8 rssi)
+{
+	brcmf_dbg(CTL, "rssi %d\n", rssi);
+	return 0;
+}
+
+static
+int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
+{
+	struct brcmf_fws_mac_descriptor *entry, *existing;
+	u8 mac_handle;
+	u8 ifidx;
+	u8 *addr;
+
+	mac_handle = *data++;
+	ifidx = *data++;
+	addr = data;
+
+	entry = &fws->desc.nodes[mac_handle & 0x1F];
+	if (type == BRCMF_FWS_TYPE_MACDESC_DEL) {
+		if (entry->occupied) {
+			brcmf_dbg(TRACE, "deleting %s mac %pM\n",
+				  entry->name, addr);
+			brcmf_fws_lock(fws);
+			brcmf_fws_macdesc_cleanup(fws, entry, -1);
+			brcmf_fws_macdesc_deinit(entry);
+			brcmf_fws_unlock(fws);
+		} else
+			fws->stats.mac_update_failed++;
+		return 0;
+	}
+
+	existing = brcmf_fws_macdesc_lookup(fws, addr);
+	if (IS_ERR(existing)) {
+		if (!entry->occupied) {
+			brcmf_fws_lock(fws);
+			entry->mac_handle = mac_handle;
+			brcmf_fws_macdesc_init(entry, addr, ifidx);
+			brcmf_fws_macdesc_set_name(fws, entry);
+			brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT,
+					BRCMF_FWS_PSQ_LEN);
+			brcmf_fws_unlock(fws);
+			brcmf_dbg(TRACE, "add %s mac %pM\n", entry->name, addr);
+		} else {
+			fws->stats.mac_update_failed++;
+		}
+	} else {
+		if (entry != existing) {
+			brcmf_dbg(TRACE, "copy mac %s\n", existing->name);
+			brcmf_fws_lock(fws);
+			memcpy(entry, existing,
+			       offsetof(struct brcmf_fws_mac_descriptor, psq));
+			entry->mac_handle = mac_handle;
+			brcmf_fws_macdesc_deinit(existing);
+			brcmf_fws_macdesc_set_name(fws, entry);
+			brcmf_fws_unlock(fws);
+			brcmf_dbg(TRACE, "relocate %s mac %pM\n", entry->name,
+				  addr);
+		} else {
+			brcmf_dbg(TRACE, "use existing\n");
+			WARN_ON(entry->mac_handle != mac_handle);
+			/* TODO: what should we do here: continue, reinit, .. */
+		}
+	}
+	return 0;
+}
+
+static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws,
+					    u8 type, u8 *data)
+{
+	struct brcmf_fws_mac_descriptor *entry;
+	u8 mac_handle;
+	int ret;
+
+	mac_handle = data[0];
+	entry = &fws->desc.nodes[mac_handle & 0x1F];
+	if (!entry->occupied) {
+		fws->stats.mac_ps_update_failed++;
+		return -ESRCH;
+	}
+	brcmf_fws_lock(fws);
+	/* a state update should wipe old credits */
+	entry->requested_credit = 0;
+	entry->requested_packet = 0;
+	if (type == BRCMF_FWS_TYPE_MAC_OPEN) {
+		entry->state = BRCMF_FWS_STATE_OPEN;
+		ret = BRCMF_FWS_RET_OK_SCHEDULE;
+	} else {
+		entry->state = BRCMF_FWS_STATE_CLOSE;
+		brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_BK, false);
+		brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_BE, false);
+		brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VI, false);
+		brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VO, true);
+		ret = BRCMF_FWS_RET_OK_NOSCHEDULE;
+	}
+	brcmf_fws_unlock(fws);
+	return ret;
+}
+
+static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
+					      u8 type, u8 *data)
+{
+	struct brcmf_fws_mac_descriptor *entry;
+	u8 ifidx;
+	int ret;
+
+	ifidx = data[0];
+
+	if (ifidx >= BRCMF_MAX_IFS) {
+		ret = -ERANGE;
+		goto fail;
+	}
+
+	entry = &fws->desc.iface[ifidx];
+	if (!entry->occupied) {
+		ret = -ESRCH;
+		goto fail;
+	}
+
+	brcmf_dbg(TRACE, "%s (%d): %s\n", brcmf_fws_get_tlv_name(type), type,
+		  entry->name);
+	brcmf_fws_lock(fws);
+	switch (type) {
+	case BRCMF_FWS_TYPE_INTERFACE_OPEN:
+		entry->state = BRCMF_FWS_STATE_OPEN;
+		ret = BRCMF_FWS_RET_OK_SCHEDULE;
+		break;
+	case BRCMF_FWS_TYPE_INTERFACE_CLOSE:
+		entry->state = BRCMF_FWS_STATE_CLOSE;
+		ret = BRCMF_FWS_RET_OK_NOSCHEDULE;
+		break;
+	default:
+		ret = -EINVAL;
+		brcmf_fws_unlock(fws);
+		goto fail;
+	}
+	brcmf_fws_unlock(fws);
+	return ret;
+
+fail:
+	fws->stats.if_update_failed++;
+	return ret;
+}
+
+static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type,
+				      u8 *data)
+{
+	struct brcmf_fws_mac_descriptor *entry;
+
+	entry = &fws->desc.nodes[data[1] & 0x1F];
+	if (!entry->occupied) {
+		if (type == BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT)
+			fws->stats.credit_request_failed++;
+		else
+			fws->stats.packet_request_failed++;
+		return -ESRCH;
+	}
+
+	brcmf_dbg(TRACE, "%s (%d): %s cnt %d bmp %d\n",
+		  brcmf_fws_get_tlv_name(type), type, entry->name,
+		  data[0], data[2]);
+	brcmf_fws_lock(fws);
+	if (type == BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT)
+		entry->requested_credit = data[0];
+	else
+		entry->requested_packet = data[0];
+
+	entry->ac_bitmap = data[2];
+	brcmf_fws_unlock(fws);
+	return BRCMF_FWS_RET_OK_SCHEDULE;
+}
+
+static void
+brcmf_fws_macdesc_use_req_credit(struct brcmf_fws_mac_descriptor *entry,
+				 struct sk_buff *skb)
+{
+	if (entry->requested_credit > 0) {
+		entry->requested_credit--;
+		brcmf_skb_if_flags_set_field(skb, REQUESTED, 1);
+		brcmf_skb_if_flags_set_field(skb, REQ_CREDIT, 1);
+		if (entry->state != BRCMF_FWS_STATE_CLOSE)
+			brcmf_err("requested credit set while mac not closed!\n");
+	} else if (entry->requested_packet > 0) {
+		entry->requested_packet--;
+		brcmf_skb_if_flags_set_field(skb, REQUESTED, 1);
+		brcmf_skb_if_flags_set_field(skb, REQ_CREDIT, 0);
+		if (entry->state != BRCMF_FWS_STATE_CLOSE)
+			brcmf_err("requested packet set while mac not closed!\n");
+	} else {
+		brcmf_skb_if_flags_set_field(skb, REQUESTED, 0);
+		brcmf_skb_if_flags_set_field(skb, REQ_CREDIT, 0);
+	}
+}
+
+static void brcmf_fws_macdesc_return_req_credit(struct sk_buff *skb)
+{
+	struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
+
+	if ((brcmf_skb_if_flags_get_field(skb, REQ_CREDIT)) &&
+	    (entry->state == BRCMF_FWS_STATE_CLOSE))
+		entry->requested_credit++;
+}
+
+static void brcmf_fws_return_credits(struct brcmf_fws_info *fws,
+				     u8 fifo, u8 credits)
+{
+	int lender_ac;
+	int *borrowed;
+	int *fifo_credit;
+
+	if (!credits)
+		return;
+
+	fws->fifo_credit_map |= 1 << fifo;
+
+	if ((fifo == BRCMF_FWS_FIFO_AC_BE) &&
+	    (fws->credits_borrowed[0])) {
+		for (lender_ac = BRCMF_FWS_FIFO_AC_VO; lender_ac >= 0;
+		     lender_ac--) {
+			borrowed = &fws->credits_borrowed[lender_ac];
+			if (*borrowed) {
+				fws->fifo_credit_map |= (1 << lender_ac);
+				fifo_credit = &fws->fifo_credit[lender_ac];
+				if (*borrowed >= credits) {
+					*borrowed -= credits;
+					*fifo_credit += credits;
+					return;
+				} else {
+					credits -= *borrowed;
+					*fifo_credit += *borrowed;
+					*borrowed = 0;
+				}
+			}
+		}
+	}
+
+	fws->fifo_credit[fifo] += credits;
+}
+
+static void brcmf_fws_schedule_deq(struct brcmf_fws_info *fws)
+{
+	/* only schedule dequeue when there are credits for delayed traffic */
+	if ((fws->fifo_credit_map & fws->fifo_delay_map) ||
+	    (!brcmf_fws_fc_active(fws) && fws->fifo_delay_map))
+		queue_work(fws->fws_wq, &fws->fws_dequeue_work);
+}
+
+static int brcmf_fws_enq(struct brcmf_fws_info *fws,
+			 enum brcmf_fws_skb_state state, int fifo,
+			 struct sk_buff *p)
+{
+	int prec = 2 * fifo;
+	u32 *qfull_stat = &fws->stats.delayq_full_error;
+	struct brcmf_fws_mac_descriptor *entry;
+	struct pktq *pq;
+	struct sk_buff_head *queue;
+	struct sk_buff *p_head;
+	struct sk_buff *p_tail;
+	u32 fr_new;
+	u32 fr_compare;
+
+	entry = brcmf_skbcb(p)->mac;
+	if (entry == NULL) {
+		brcmf_err("no mac descriptor found for skb %p\n", p);
+		return -ENOENT;
+	}
+
+	brcmf_dbg(DATA, "enter: fifo %d skb %p\n", fifo, p);
+	if (state == BRCMF_FWS_SKBSTATE_SUPPRESSED) {
+		prec += 1;
+		qfull_stat = &fws->stats.supprq_full_error;
+
+		/* Fix out of order delivery of frames. Dont assume frame    */
+		/* can be inserted at the end, but look for correct position */
+		pq = &entry->psq;
+		if (pktq_full(pq) || pktq_pfull(pq, prec)) {
+			*qfull_stat += 1;
+			return -ENFILE;
+		}
+		queue = &pq->q[prec].skblist;
+
+		p_head = skb_peek(queue);
+		p_tail = skb_peek_tail(queue);
+		fr_new = brcmf_skb_htod_tag_get_field(p, FREERUN);
+
+		while (p_head != p_tail) {
+			fr_compare = brcmf_skb_htod_tag_get_field(p_tail,
+								  FREERUN);
+			/* be sure to handle wrap of 256 */
+			if (((fr_new > fr_compare) &&
+			     ((fr_new - fr_compare) < 128)) ||
+			    ((fr_new < fr_compare) &&
+			     ((fr_compare - fr_new) > 128)))
+				break;
+			p_tail = skb_queue_prev(queue, p_tail);
+		}
+		/* Position found. Determine what to do */
+		if (p_tail == NULL) {
+			/* empty list */
+			__skb_queue_tail(queue, p);
+		} else {
+			fr_compare = brcmf_skb_htod_tag_get_field(p_tail,
+								  FREERUN);
+			if (((fr_new > fr_compare) &&
+			     ((fr_new - fr_compare) < 128)) ||
+			    ((fr_new < fr_compare) &&
+			     ((fr_compare - fr_new) > 128))) {
+				/* After tail */
+				__skb_queue_after(queue, p_tail, p);
+			} else {
+				/* Before tail */
+				__skb_insert(p, p_tail->prev, p_tail, queue);
+			}
+		}
+
+		/* Complete the counters and statistics */
+		pq->len++;
+		if (pq->hi_prec < prec)
+			pq->hi_prec = (u8) prec;
+	} else if (brcmu_pktq_penq(&entry->psq, prec, p) == NULL) {
+		*qfull_stat += 1;
+		return -ENFILE;
+	}
+
+	/* increment total enqueued packet count */
+	fws->fifo_delay_map |= 1 << fifo;
+	fws->fifo_enqpkt[fifo]++;
+
+	/* update the sk_buff state */
+	brcmf_skbcb(p)->state = state;
+
+	/*
+	 * A packet has been pushed so update traffic
+	 * availability bitmap, if applicable
+	 */
+	brcmf_fws_tim_update(fws, entry, fifo, true);
+	brcmf_fws_flow_control_check(fws, &entry->psq,
+				     brcmf_skb_if_flags_get_field(p, INDEX));
+	return 0;
+}
+
+static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo)
+{
+	struct brcmf_fws_mac_descriptor *table;
+	struct brcmf_fws_mac_descriptor *entry;
+	struct sk_buff *p;
+	int num_nodes;
+	int node_pos;
+	int prec_out;
+	int pmsk;
+	int i;
+
+	table = (struct brcmf_fws_mac_descriptor *)&fws->desc;
+	num_nodes = sizeof(fws->desc) / sizeof(struct brcmf_fws_mac_descriptor);
+	node_pos = fws->deq_node_pos[fifo];
+
+	for (i = 0; i < num_nodes; i++) {
+		entry = &table[(node_pos + i) % num_nodes];
+		if (!entry->occupied ||
+		    brcmf_fws_macdesc_closed(fws, entry, fifo))
+			continue;
+
+		if (entry->suppressed)
+			pmsk = 2;
+		else
+			pmsk = 3;
+		p = brcmu_pktq_mdeq(&entry->psq, pmsk << (fifo * 2), &prec_out);
+		if (p == NULL) {
+			if (entry->suppressed) {
+				if (entry->suppr_transit_count)
+					continue;
+				entry->suppressed = false;
+				p = brcmu_pktq_mdeq(&entry->psq,
+						    1 << (fifo * 2), &prec_out);
+			}
+		}
+		if  (p == NULL)
+			continue;
+
+		brcmf_fws_macdesc_use_req_credit(entry, p);
+
+		/* move dequeue position to ensure fair round-robin */
+		fws->deq_node_pos[fifo] = (node_pos + i + 1) % num_nodes;
+		brcmf_fws_flow_control_check(fws, &entry->psq,
+					     brcmf_skb_if_flags_get_field(p,
+									  INDEX)
+					     );
+		/*
+		 * A packet has been picked up, update traffic
+		 * availability bitmap, if applicable
+		 */
+		brcmf_fws_tim_update(fws, entry, fifo, false);
+
+		/*
+		 * decrement total enqueued fifo packets and
+		 * clear delay bitmap if done.
+		 */
+		fws->fifo_enqpkt[fifo]--;
+		if (fws->fifo_enqpkt[fifo] == 0)
+			fws->fifo_delay_map &= ~(1 << fifo);
+		goto done;
+	}
+	p = NULL;
+done:
+	brcmf_dbg(DATA, "exit: fifo %d skb %p\n", fifo, p);
+	return p;
+}
+
+static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
+					 struct sk_buff *skb,
+					 u32 genbit, u16 seq)
+{
+	struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
+	u32 hslot;
+	int ret;
+
+	hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
+
+	/* this packet was suppressed */
+	if (!entry->suppressed) {
+		entry->suppressed = true;
+		entry->suppr_transit_count = entry->transit_count;
+		brcmf_dbg(DATA, "suppress %s: transit %d\n",
+			  entry->name, entry->transit_count);
+	}
+
+	entry->generation = genbit;
+
+	brcmf_skb_htod_tag_set_field(skb, GENERATION, genbit);
+	brcmf_skbcb(skb)->htod_seq = seq;
+	if (brcmf_skb_htod_seq_get_field(skb, FROMFW)) {
+		brcmf_skb_htod_seq_set_field(skb, FROMDRV, 1);
+		brcmf_skb_htod_seq_set_field(skb, FROMFW, 0);
+	} else {
+		brcmf_skb_htod_seq_set_field(skb, FROMDRV, 0);
+	}
+	ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo, skb);
+
+	if (ret != 0) {
+		/* suppress q is full drop this packet */
+		brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb, true);
+	} else {
+		/* Mark suppressed to avoid a double free during wlfc cleanup */
+		brcmf_fws_hanger_mark_suppressed(&fws->hanger, hslot);
+	}
+
+	return ret;
+}
+
+static int
+brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
+		      u32 genbit, u16 seq)
+{
+	u32 fifo;
+	int ret;
+	bool remove_from_hanger = true;
+	struct sk_buff *skb;
+	struct brcmf_skbuff_cb *skcb;
+	struct brcmf_fws_mac_descriptor *entry = NULL;
+	struct brcmf_if *ifp;
+
+	brcmf_dbg(DATA, "flags %d\n", flags);
+
+	if (flags == BRCMF_FWS_TXSTATUS_DISCARD)
+		fws->stats.txs_discard++;
+	else if (flags == BRCMF_FWS_TXSTATUS_CORE_SUPPRESS) {
+		fws->stats.txs_supp_core++;
+		remove_from_hanger = false;
+	} else if (flags == BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS) {
+		fws->stats.txs_supp_ps++;
+		remove_from_hanger = false;
+	} else if (flags == BRCMF_FWS_TXSTATUS_FW_TOSSED)
+		fws->stats.txs_tossed++;
+	else if (flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED)
+		fws->stats.txs_host_tossed++;
+	else
+		brcmf_err("unexpected txstatus\n");
+
+	ret = brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
+				      remove_from_hanger);
+	if (ret != 0) {
+		brcmf_err("no packet in hanger slot: hslot=%d\n", hslot);
+		return ret;
+	}
+
+	skcb = brcmf_skbcb(skb);
+	entry = skcb->mac;
+	if (WARN_ON(!entry)) {
+		brcmu_pkt_buf_free_skb(skb);
+		return -EINVAL;
+	}
+	entry->transit_count--;
+	if (entry->suppressed && entry->suppr_transit_count)
+		entry->suppr_transit_count--;
+
+	brcmf_dbg(DATA, "%s flags %d htod %X seq %X\n", entry->name, flags,
+		  skcb->htod, seq);
+
+	/* pick up the implicit credit from this packet */
+	fifo = brcmf_skb_htod_tag_get_field(skb, FIFO);
+	if ((fws->fcmode == BRCMF_FWS_FCMODE_IMPLIED_CREDIT) ||
+	    (brcmf_skb_if_flags_get_field(skb, REQ_CREDIT)) ||
+	    (flags == BRCMF_FWS_TXSTATUS_HOST_TOSSED)) {
+		brcmf_fws_return_credits(fws, fifo, 1);
+		brcmf_fws_schedule_deq(fws);
+	}
+	brcmf_fws_macdesc_return_req_credit(skb);
+
+	ret = brcmf_proto_hdrpull(fws->drvr, false, skb, &ifp);
+	if (ret) {
+		brcmu_pkt_buf_free_skb(skb);
+		return -EINVAL;
+	}
+	if (!remove_from_hanger)
+		ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb,
+						    genbit, seq);
+	if (remove_from_hanger || ret)
+		brcmf_txfinalize(ifp, skb, true);
+
+	return 0;
+}
+
+static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
+					     u8 *data)
+{
+	int i;
+
+	if (fws->fcmode != BRCMF_FWS_FCMODE_EXPLICIT_CREDIT) {
+		brcmf_dbg(INFO, "ignored\n");
+		return BRCMF_FWS_RET_OK_NOSCHEDULE;
+	}
+
+	brcmf_dbg(DATA, "enter: data %pM\n", data);
+	brcmf_fws_lock(fws);
+	for (i = 0; i < BRCMF_FWS_FIFO_COUNT; i++)
+		brcmf_fws_return_credits(fws, i, data[i]);
+
+	brcmf_dbg(DATA, "map: credit %x delay %x\n", fws->fifo_credit_map,
+		  fws->fifo_delay_map);
+	brcmf_fws_unlock(fws);
+	return BRCMF_FWS_RET_OK_SCHEDULE;
+}
+
+static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
+{
+	__le32 status_le;
+	__le16 seq_le;
+	u32 status;
+	u32 hslot;
+	u32 genbit;
+	u8 flags;
+	u16 seq;
+
+	fws->stats.txs_indicate++;
+	memcpy(&status_le, data, sizeof(status_le));
+	status = le32_to_cpu(status_le);
+	flags = brcmf_txstatus_get_field(status, FLAGS);
+	hslot = brcmf_txstatus_get_field(status, HSLOT);
+	genbit = brcmf_txstatus_get_field(status, GENERATION);
+	if (BRCMF_FWS_MODE_GET_REUSESEQ(fws->mode)) {
+		memcpy(&seq_le, &data[BRCMF_FWS_TYPE_PKTTAG_LEN],
+		       sizeof(seq_le));
+		seq = le16_to_cpu(seq_le);
+	} else {
+		seq = 0;
+	}
+
+	brcmf_fws_lock(fws);
+	brcmf_fws_txs_process(fws, flags, hslot, genbit, seq);
+	brcmf_fws_unlock(fws);
+	return BRCMF_FWS_RET_OK_NOSCHEDULE;
+}
+
+static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data)
+{
+	__le32 timestamp;
+
+	memcpy(&timestamp, &data[2], sizeof(timestamp));
+	brcmf_dbg(CTL, "received: seq %d, timestamp %d\n", data[1],
+		  le32_to_cpu(timestamp));
+	return 0;
+}
+
+static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp,
+				       const struct brcmf_event_msg *e,
+				       void *data)
+{
+	struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr);
+	int i;
+	u8 *credits = data;
+
+	if (e->datalen < BRCMF_FWS_FIFO_COUNT) {
+		brcmf_err("event payload too small (%d)\n", e->datalen);
+		return -EINVAL;
+	}
+	if (fws->creditmap_received)
+		return 0;
+
+	fws->creditmap_received = true;
+
+	brcmf_dbg(TRACE, "enter: credits %pM\n", credits);
+	brcmf_fws_lock(fws);
+	for (i = 0; i < ARRAY_SIZE(fws->fifo_credit); i++) {
+		if (*credits)
+			fws->fifo_credit_map |= 1 << i;
+		else
+			fws->fifo_credit_map &= ~(1 << i);
+		fws->fifo_credit[i] = *credits++;
+	}
+	brcmf_fws_schedule_deq(fws);
+	brcmf_fws_unlock(fws);
+	return 0;
+}
+
+static int brcmf_fws_notify_bcmc_credit_support(struct brcmf_if *ifp,
+						const struct brcmf_event_msg *e,
+						void *data)
+{
+	struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr);
+
+	if (fws) {
+		brcmf_fws_lock(fws);
+		fws->bcmc_credit_check = true;
+		brcmf_fws_unlock(fws);
+	}
+	return 0;
+}
+
+static void brcmf_rxreorder_get_skb_list(struct brcmf_ampdu_rx_reorder *rfi,
+					 u8 start, u8 end,
+					 struct sk_buff_head *skb_list)
+{
+	/* initialize return list */
+	__skb_queue_head_init(skb_list);
+
+	if (rfi->pend_pkts == 0) {
+		brcmf_dbg(INFO, "no packets in reorder queue\n");
+		return;
+	}
+
+	do {
+		if (rfi->pktslots[start]) {
+			__skb_queue_tail(skb_list, rfi->pktslots[start]);
+			rfi->pktslots[start] = NULL;
+		}
+		start++;
+		if (start > rfi->max_idx)
+			start = 0;
+	} while (start != end);
+	rfi->pend_pkts -= skb_queue_len(skb_list);
+}
+
+void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *pkt)
+{
+	u8 *reorder_data;
+	u8 flow_id, max_idx, cur_idx, exp_idx, end_idx;
+	struct brcmf_ampdu_rx_reorder *rfi;
+	struct sk_buff_head reorder_list;
+	struct sk_buff *pnext;
+	u8 flags;
+	u32 buf_size;
+
+	reorder_data = ((struct brcmf_skb_reorder_data *)pkt->cb)->reorder;
+	flow_id = reorder_data[BRCMF_RXREORDER_FLOWID_OFFSET];
+	flags = reorder_data[BRCMF_RXREORDER_FLAGS_OFFSET];
+
+	/* validate flags and flow id */
+	if (flags == 0xFF) {
+		brcmf_err("invalid flags...so ignore this packet\n");
+		brcmf_netif_rx(ifp, pkt);
+		return;
+	}
+
+	rfi = ifp->drvr->reorder_flows[flow_id];
+	if (flags & BRCMF_RXREORDER_DEL_FLOW) {
+		brcmf_dbg(INFO, "flow-%d: delete\n",
+			  flow_id);
+
+		if (rfi == NULL) {
+			brcmf_dbg(INFO, "received flags to cleanup, but no flow (%d) yet\n",
+				  flow_id);
+			brcmf_netif_rx(ifp, pkt);
+			return;
+		}
+
+		brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, rfi->exp_idx,
+					     &reorder_list);
+		/* add the last packet */
+		__skb_queue_tail(&reorder_list, pkt);
+		kfree(rfi);
+		ifp->drvr->reorder_flows[flow_id] = NULL;
+		goto netif_rx;
+	}
+	/* from here on we need a flow reorder instance */
+	if (rfi == NULL) {
+		buf_size = sizeof(*rfi);
+		max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET];
+
+		buf_size += (max_idx + 1) * sizeof(pkt);
+
+		/* allocate space for flow reorder info */
+		brcmf_dbg(INFO, "flow-%d: start, maxidx %d\n",
+			  flow_id, max_idx);
+		rfi = kzalloc(buf_size, GFP_ATOMIC);
+		if (rfi == NULL) {
+			brcmf_err("failed to alloc buffer\n");
+			brcmf_netif_rx(ifp, pkt);
+			return;
+		}
+
+		ifp->drvr->reorder_flows[flow_id] = rfi;
+		rfi->pktslots = (struct sk_buff **)(rfi + 1);
+		rfi->max_idx = max_idx;
+	}
+	if (flags & BRCMF_RXREORDER_NEW_HOLE)  {
+		if (rfi->pend_pkts) {
+			brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx,
+						     rfi->exp_idx,
+						     &reorder_list);
+			WARN_ON(rfi->pend_pkts);
+		} else {
+			__skb_queue_head_init(&reorder_list);
+		}
+		rfi->cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET];
+		rfi->exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
+		rfi->max_idx = reorder_data[BRCMF_RXREORDER_MAXIDX_OFFSET];
+		rfi->pktslots[rfi->cur_idx] = pkt;
+		rfi->pend_pkts++;
+		brcmf_dbg(DATA, "flow-%d: new hole %d (%d), pending %d\n",
+			  flow_id, rfi->cur_idx, rfi->exp_idx, rfi->pend_pkts);
+	} else if (flags & BRCMF_RXREORDER_CURIDX_VALID) {
+		cur_idx = reorder_data[BRCMF_RXREORDER_CURIDX_OFFSET];
+		exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
+
+		if ((exp_idx == rfi->exp_idx) && (cur_idx != rfi->exp_idx)) {
+			/* still in the current hole */
+			/* enqueue the current on the buffer chain */
+			if (rfi->pktslots[cur_idx] != NULL) {
+				brcmf_dbg(INFO, "HOLE: ERROR buffer pending..free it\n");
+				brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]);
+				rfi->pktslots[cur_idx] = NULL;
+			}
+			rfi->pktslots[cur_idx] = pkt;
+			rfi->pend_pkts++;
+			rfi->cur_idx = cur_idx;
+			brcmf_dbg(DATA, "flow-%d: store pkt %d (%d), pending %d\n",
+				  flow_id, cur_idx, exp_idx, rfi->pend_pkts);
+
+			/* can return now as there is no reorder
+			 * list to process.
+			 */
+			return;
+		}
+		if (rfi->exp_idx == cur_idx) {
+			if (rfi->pktslots[cur_idx] != NULL) {
+				brcmf_dbg(INFO, "error buffer pending..free it\n");
+				brcmu_pkt_buf_free_skb(rfi->pktslots[cur_idx]);
+				rfi->pktslots[cur_idx] = NULL;
+			}
+			rfi->pktslots[cur_idx] = pkt;
+			rfi->pend_pkts++;
+
+			/* got the expected one. flush from current to expected
+			 * and update expected
+			 */
+			brcmf_dbg(DATA, "flow-%d: expected %d (%d), pending %d\n",
+				  flow_id, cur_idx, exp_idx, rfi->pend_pkts);
+
+			rfi->cur_idx = cur_idx;
+			rfi->exp_idx = exp_idx;
+
+			brcmf_rxreorder_get_skb_list(rfi, cur_idx, exp_idx,
+						     &reorder_list);
+			brcmf_dbg(DATA, "flow-%d: freeing buffers %d, pending %d\n",
+				  flow_id, skb_queue_len(&reorder_list),
+				  rfi->pend_pkts);
+		} else {
+			u8 end_idx;
+
+			brcmf_dbg(DATA, "flow-%d (0x%x): both moved, old %d/%d, new %d/%d\n",
+				  flow_id, flags, rfi->cur_idx, rfi->exp_idx,
+				  cur_idx, exp_idx);
+			if (flags & BRCMF_RXREORDER_FLUSH_ALL)
+				end_idx = rfi->exp_idx;
+			else
+				end_idx = exp_idx;
+
+			/* flush pkts first */
+			brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx,
+						     &reorder_list);
+
+			if (exp_idx == ((cur_idx + 1) % (rfi->max_idx + 1))) {
+				__skb_queue_tail(&reorder_list, pkt);
+			} else {
+				rfi->pktslots[cur_idx] = pkt;
+				rfi->pend_pkts++;
+			}
+			rfi->exp_idx = exp_idx;
+			rfi->cur_idx = cur_idx;
+		}
+	} else {
+		/* explicity window move updating the expected index */
+		exp_idx = reorder_data[BRCMF_RXREORDER_EXPIDX_OFFSET];
+
+		brcmf_dbg(DATA, "flow-%d (0x%x): change expected: %d -> %d\n",
+			  flow_id, flags, rfi->exp_idx, exp_idx);
+		if (flags & BRCMF_RXREORDER_FLUSH_ALL)
+			end_idx =  rfi->exp_idx;
+		else
+			end_idx =  exp_idx;
+
+		brcmf_rxreorder_get_skb_list(rfi, rfi->exp_idx, end_idx,
+					     &reorder_list);
+		__skb_queue_tail(&reorder_list, pkt);
+		/* set the new expected idx */
+		rfi->exp_idx = exp_idx;
+	}
+netif_rx:
+	skb_queue_walk_safe(&reorder_list, pkt, pnext) {
+		__skb_unlink(pkt, &reorder_list);
+		brcmf_netif_rx(ifp, pkt);
+	}
+}
+
+void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb)
+{
+	struct brcmf_skb_reorder_data *rd;
+	struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr);
+	u8 *signal_data;
+	s16 data_len;
+	u8 type;
+	u8 len;
+	u8 *data;
+	s32 status;
+	s32 err;
+
+	brcmf_dbg(HDRS, "enter: ifidx %d, skblen %u, sig %d\n",
+		  ifp->ifidx, skb->len, siglen);
+
+	WARN_ON(siglen > skb->len);
+
+	if (!siglen)
+		return;
+	/* if flow control disabled, skip to packet data and leave */
+	if ((!fws) || (!fws->fw_signals)) {
+		skb_pull(skb, siglen);
+		return;
+	}
+
+	fws->stats.header_pulls++;
+	data_len = siglen;
+	signal_data = skb->data;
+
+	status = BRCMF_FWS_RET_OK_NOSCHEDULE;
+	while (data_len > 0) {
+		/* extract tlv info */
+		type = signal_data[0];
+
+		/* FILLER type is actually not a TLV, but
+		 * a single byte that can be skipped.
+		 */
+		if (type == BRCMF_FWS_TYPE_FILLER) {
+			signal_data += 1;
+			data_len -= 1;
+			continue;
+		}
+		len = signal_data[1];
+		data = signal_data + 2;
+
+		brcmf_dbg(HDRS, "tlv type=%s (%d), len=%d (%d)\n",
+			  brcmf_fws_get_tlv_name(type), type, len,
+			  brcmf_fws_get_tlv_len(fws, type));
+
+		/* abort parsing when length invalid */
+		if (data_len < len + 2)
+			break;
+
+		if (len < brcmf_fws_get_tlv_len(fws, type))
+			break;
+
+		err = BRCMF_FWS_RET_OK_NOSCHEDULE;
+		switch (type) {
+		case BRCMF_FWS_TYPE_COMP_TXSTATUS:
+			break;
+		case BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS:
+			rd = (struct brcmf_skb_reorder_data *)skb->cb;
+			rd->reorder = data;
+			break;
+		case BRCMF_FWS_TYPE_MACDESC_ADD:
+		case BRCMF_FWS_TYPE_MACDESC_DEL:
+			brcmf_fws_macdesc_indicate(fws, type, data);
+			break;
+		case BRCMF_FWS_TYPE_MAC_OPEN:
+		case BRCMF_FWS_TYPE_MAC_CLOSE:
+			err = brcmf_fws_macdesc_state_indicate(fws, type, data);
+			break;
+		case BRCMF_FWS_TYPE_INTERFACE_OPEN:
+		case BRCMF_FWS_TYPE_INTERFACE_CLOSE:
+			err = brcmf_fws_interface_state_indicate(fws, type,
+								 data);
+			break;
+		case BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT:
+		case BRCMF_FWS_TYPE_MAC_REQUEST_PACKET:
+			err = brcmf_fws_request_indicate(fws, type, data);
+			break;
+		case BRCMF_FWS_TYPE_TXSTATUS:
+			brcmf_fws_txstatus_indicate(fws, data);
+			break;
+		case BRCMF_FWS_TYPE_FIFO_CREDITBACK:
+			err = brcmf_fws_fifocreditback_indicate(fws, data);
+			break;
+		case BRCMF_FWS_TYPE_RSSI:
+			brcmf_fws_rssi_indicate(fws, *data);
+			break;
+		case BRCMF_FWS_TYPE_TRANS_ID:
+			brcmf_fws_dbg_seqnum_check(fws, data);
+			break;
+		case BRCMF_FWS_TYPE_PKTTAG:
+		case BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP:
+		default:
+			fws->stats.tlv_invalid_type++;
+			break;
+		}
+		if (err == BRCMF_FWS_RET_OK_SCHEDULE)
+			status = BRCMF_FWS_RET_OK_SCHEDULE;
+		signal_data += len + 2;
+		data_len -= len + 2;
+	}
+
+	if (data_len != 0)
+		fws->stats.tlv_parse_failed++;
+
+	if (status == BRCMF_FWS_RET_OK_SCHEDULE)
+		brcmf_fws_schedule_deq(fws);
+
+	/* signalling processing result does
+	 * not affect the actual ethernet packet.
+	 */
+	skb_pull(skb, siglen);
+
+	/* this may be a signal-only packet
+	 */
+	if (skb->len == 0)
+		fws->stats.header_only_pkt++;
+}
+
+static u8 brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
+				   struct sk_buff *p)
+{
+	struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p);
+	struct brcmf_fws_mac_descriptor *entry = skcb->mac;
+	u8 flags;
+
+	if (skcb->state != BRCMF_FWS_SKBSTATE_SUPPRESSED)
+		brcmf_skb_htod_tag_set_field(p, GENERATION, entry->generation);
+	flags = BRCMF_FWS_HTOD_FLAG_PKTFROMHOST;
+	if (brcmf_skb_if_flags_get_field(p, REQUESTED)) {
+		/*
+		 * Indicate that this packet is being sent in response to an
+		 * explicit request from the firmware side.
+		 */
+		flags |= BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED;
+	}
+	brcmf_skb_htod_tag_set_field(p, FLAGS, flags);
+	return brcmf_fws_hdrpush(fws, p);
+}
+
+static void brcmf_fws_rollback_toq(struct brcmf_fws_info *fws,
+				   struct sk_buff *skb, int fifo)
+{
+	struct brcmf_fws_mac_descriptor *entry;
+	struct sk_buff *pktout;
+	int qidx, hslot;
+	int rc = 0;
+
+	entry = brcmf_skbcb(skb)->mac;
+	if (entry->occupied) {
+		qidx = 2 * fifo;
+		if (brcmf_skbcb(skb)->state == BRCMF_FWS_SKBSTATE_SUPPRESSED)
+			qidx++;
+
+		pktout = brcmu_pktq_penq_head(&entry->psq, qidx, skb);
+		if (pktout == NULL) {
+			brcmf_err("%s queue %d full\n", entry->name, qidx);
+			rc = -ENOSPC;
+		}
+	} else {
+		brcmf_err("%s entry removed\n", entry->name);
+		rc = -ENOENT;
+	}
+
+	if (rc) {
+		fws->stats.rollback_failed++;
+		hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
+		brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED,
+				      hslot, 0, 0);
+	} else {
+		fws->stats.rollback_success++;
+		brcmf_fws_return_credits(fws, fifo, 1);
+		brcmf_fws_macdesc_return_req_credit(skb);
+	}
+}
+
+static int brcmf_fws_borrow_credit(struct brcmf_fws_info *fws)
+{
+	int lender_ac;
+
+	if (time_after(fws->borrow_defer_timestamp, jiffies)) {
+		fws->fifo_credit_map &= ~(1 << BRCMF_FWS_FIFO_AC_BE);
+		return -ENAVAIL;
+	}
+
+	for (lender_ac = 0; lender_ac <= BRCMF_FWS_FIFO_AC_VO; lender_ac++) {
+		if (fws->fifo_credit[lender_ac]) {
+			fws->credits_borrowed[lender_ac]++;
+			fws->fifo_credit[lender_ac]--;
+			if (fws->fifo_credit[lender_ac] == 0)
+				fws->fifo_credit_map &= ~(1 << lender_ac);
+			fws->fifo_credit_map |= (1 << BRCMF_FWS_FIFO_AC_BE);
+			brcmf_dbg(DATA, "borrow credit from: %d\n", lender_ac);
+			return 0;
+		}
+	}
+	fws->fifo_credit_map &= ~(1 << BRCMF_FWS_FIFO_AC_BE);
+	return -ENAVAIL;
+}
+
+static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo,
+				struct sk_buff *skb)
+{
+	struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb);
+	struct brcmf_fws_mac_descriptor *entry;
+	int rc;
+	u8 ifidx;
+	u8 data_offset;
+
+	entry = skcb->mac;
+	if (IS_ERR(entry))
+		return PTR_ERR(entry);
+
+	data_offset = brcmf_fws_precommit_skb(fws, fifo, skb);
+	entry->transit_count++;
+	if (entry->suppressed)
+		entry->suppr_transit_count++;
+	ifidx = brcmf_skb_if_flags_get_field(skb, INDEX);
+	brcmf_fws_unlock(fws);
+	rc = brcmf_proto_txdata(fws->drvr, ifidx, data_offset, skb);
+	brcmf_fws_lock(fws);
+	brcmf_dbg(DATA, "%s flags %X htod %X bus_tx %d\n", entry->name,
+		  skcb->if_flags, skcb->htod, rc);
+	if (rc < 0) {
+		entry->transit_count--;
+		if (entry->suppressed)
+			entry->suppr_transit_count--;
+		(void)brcmf_proto_hdrpull(fws->drvr, false, skb, NULL);
+		goto rollback;
+	}
+
+	fws->stats.pkt2bus++;
+	fws->stats.send_pkts[fifo]++;
+	if (brcmf_skb_if_flags_get_field(skb, REQUESTED))
+		fws->stats.requested_sent[fifo]++;
+
+	return rc;
+
+rollback:
+	brcmf_fws_rollback_toq(fws, skb, fifo);
+	return rc;
+}
+
+static int brcmf_fws_assign_htod(struct brcmf_fws_info *fws, struct sk_buff *p,
+				  int fifo)
+{
+	struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p);
+	int rc, hslot;
+
+	skcb->htod = 0;
+	skcb->htod_seq = 0;
+	hslot = brcmf_fws_hanger_get_free_slot(&fws->hanger);
+	brcmf_skb_htod_tag_set_field(p, HSLOT, hslot);
+	brcmf_skb_htod_tag_set_field(p, FREERUN, skcb->mac->seq[fifo]);
+	brcmf_skb_htod_tag_set_field(p, FIFO, fifo);
+	rc = brcmf_fws_hanger_pushpkt(&fws->hanger, p, hslot);
+	if (!rc)
+		skcb->mac->seq[fifo]++;
+	else
+		fws->stats.generic_error++;
+	return rc;
+}
+
+int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
+{
+	struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr);
+	struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb);
+	struct ethhdr *eh = (struct ethhdr *)(skb->data);
+	int fifo = BRCMF_FWS_FIFO_BCMC;
+	bool multicast = is_multicast_ether_addr(eh->h_dest);
+	int rc = 0;
+
+	brcmf_dbg(DATA, "tx proto=0x%X\n", ntohs(eh->h_proto));
+
+	/* set control buffer information */
+	skcb->if_flags = 0;
+	skcb->state = BRCMF_FWS_SKBSTATE_NEW;
+	brcmf_skb_if_flags_set_field(skb, INDEX, ifp->ifidx);
+	if (!multicast)
+		fifo = brcmf_fws_prio2fifo[skb->priority];
+
+	brcmf_fws_lock(fws);
+	if (fifo != BRCMF_FWS_FIFO_AC_BE && fifo < BRCMF_FWS_FIFO_BCMC)
+		fws->borrow_defer_timestamp = jiffies +
+					      BRCMF_FWS_BORROW_DEFER_PERIOD;
+
+	skcb->mac = brcmf_fws_macdesc_find(fws, ifp, eh->h_dest);
+	brcmf_dbg(DATA, "%s mac %pM multi %d fifo %d\n", skcb->mac->name,
+		  eh->h_dest, multicast, fifo);
+	if (!brcmf_fws_assign_htod(fws, skb, fifo)) {
+		brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb);
+		brcmf_fws_schedule_deq(fws);
+	} else {
+		brcmf_err("drop skb: no hanger slot\n");
+		brcmf_txfinalize(ifp, skb, false);
+		rc = -ENOMEM;
+	}
+	brcmf_fws_unlock(fws);
+
+	return rc;
+}
+
+void brcmf_fws_reset_interface(struct brcmf_if *ifp)
+{
+	struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc;
+
+	brcmf_dbg(TRACE, "enter: bsscfgidx=%d\n", ifp->bsscfgidx);
+	if (!entry)
+		return;
+
+	brcmf_fws_macdesc_init(entry, ifp->mac_addr, ifp->ifidx);
+}
+
+void brcmf_fws_add_interface(struct brcmf_if *ifp)
+{
+	struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr);
+	struct brcmf_fws_mac_descriptor *entry;
+
+	if (!ifp->ndev || !brcmf_fws_queue_skbs(fws))
+		return;
+
+	entry = &fws->desc.iface[ifp->ifidx];
+	ifp->fws_desc = entry;
+	brcmf_fws_macdesc_init(entry, ifp->mac_addr, ifp->ifidx);
+	brcmf_fws_macdesc_set_name(fws, entry);
+	brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT,
+			BRCMF_FWS_PSQ_LEN);
+	brcmf_dbg(TRACE, "added %s\n", entry->name);
+}
+
+void brcmf_fws_del_interface(struct brcmf_if *ifp)
+{
+	struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc;
+	struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr);
+
+	if (!entry)
+		return;
+
+	brcmf_fws_lock(fws);
+	ifp->fws_desc = NULL;
+	brcmf_dbg(TRACE, "deleting %s\n", entry->name);
+	brcmf_fws_macdesc_deinit(entry);
+	brcmf_fws_cleanup(fws, ifp->ifidx);
+	brcmf_fws_unlock(fws);
+}
+
+static void brcmf_fws_dequeue_worker(struct work_struct *worker)
+{
+	struct brcmf_fws_info *fws;
+	struct brcmf_pub *drvr;
+	struct sk_buff *skb;
+	int fifo;
+	u32 hslot;
+	u32 ifidx;
+	int ret;
+
+	fws = container_of(worker, struct brcmf_fws_info, fws_dequeue_work);
+	drvr = fws->drvr;
+
+	brcmf_fws_lock(fws);
+	for (fifo = BRCMF_FWS_FIFO_BCMC; fifo >= 0 && !fws->bus_flow_blocked;
+	     fifo--) {
+		if (!brcmf_fws_fc_active(fws)) {
+			while ((skb = brcmf_fws_deq(fws, fifo)) != NULL) {
+				hslot = brcmf_skb_htod_tag_get_field(skb,
+								     HSLOT);
+				brcmf_fws_hanger_poppkt(&fws->hanger, hslot,
+							&skb, true);
+				ifidx = brcmf_skb_if_flags_get_field(skb,
+								     INDEX);
+				/* Use proto layer to send data frame */
+				brcmf_fws_unlock(fws);
+				ret = brcmf_proto_txdata(drvr, ifidx, 0, skb);
+				brcmf_fws_lock(fws);
+				if (ret < 0)
+					brcmf_txfinalize(brcmf_get_ifp(drvr,
+								       ifidx),
+							 skb, false);
+				if (fws->bus_flow_blocked)
+					break;
+			}
+			continue;
+		}
+		while ((fws->fifo_credit[fifo]) || ((!fws->bcmc_credit_check) &&
+		       (fifo == BRCMF_FWS_FIFO_BCMC))) {
+			skb = brcmf_fws_deq(fws, fifo);
+			if (!skb)
+				break;
+			fws->fifo_credit[fifo]--;
+			if (brcmf_fws_commit_skb(fws, fifo, skb))
+				break;
+			if (fws->bus_flow_blocked)
+				break;
+		}
+		if ((fifo == BRCMF_FWS_FIFO_AC_BE) &&
+		    (fws->fifo_credit[fifo] == 0) &&
+		    (!fws->bus_flow_blocked)) {
+			while (brcmf_fws_borrow_credit(fws) == 0) {
+				skb = brcmf_fws_deq(fws, fifo);
+				if (!skb) {
+					brcmf_fws_return_credits(fws, fifo, 1);
+					break;
+				}
+				if (brcmf_fws_commit_skb(fws, fifo, skb))
+					break;
+				if (fws->bus_flow_blocked)
+					break;
+			}
+		}
+	}
+	brcmf_fws_unlock(fws);
+}
+
+#ifdef DEBUG
+static int brcmf_debugfs_fws_stats_read(struct seq_file *seq, void *data)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
+	struct brcmf_fws_stats *fwstats = &(drvr_to_fws(bus_if->drvr)->stats);
+
+	seq_printf(seq,
+		   "header_pulls:      %u\n"
+		   "header_only_pkt:   %u\n"
+		   "tlv_parse_failed:  %u\n"
+		   "tlv_invalid_type:  %u\n"
+		   "mac_update_fails:  %u\n"
+		   "ps_update_fails:   %u\n"
+		   "if_update_fails:   %u\n"
+		   "pkt2bus:           %u\n"
+		   "generic_error:     %u\n"
+		   "rollback_success:  %u\n"
+		   "rollback_failed:   %u\n"
+		   "delayq_full:       %u\n"
+		   "supprq_full:       %u\n"
+		   "txs_indicate:      %u\n"
+		   "txs_discard:       %u\n"
+		   "txs_suppr_core:    %u\n"
+		   "txs_suppr_ps:      %u\n"
+		   "txs_tossed:        %u\n"
+		   "txs_host_tossed:   %u\n"
+		   "bus_flow_block:    %u\n"
+		   "fws_flow_block:    %u\n"
+		   "send_pkts:         BK:%u BE:%u VO:%u VI:%u BCMC:%u\n"
+		   "requested_sent:    BK:%u BE:%u VO:%u VI:%u BCMC:%u\n",
+		   fwstats->header_pulls,
+		   fwstats->header_only_pkt,
+		   fwstats->tlv_parse_failed,
+		   fwstats->tlv_invalid_type,
+		   fwstats->mac_update_failed,
+		   fwstats->mac_ps_update_failed,
+		   fwstats->if_update_failed,
+		   fwstats->pkt2bus,
+		   fwstats->generic_error,
+		   fwstats->rollback_success,
+		   fwstats->rollback_failed,
+		   fwstats->delayq_full_error,
+		   fwstats->supprq_full_error,
+		   fwstats->txs_indicate,
+		   fwstats->txs_discard,
+		   fwstats->txs_supp_core,
+		   fwstats->txs_supp_ps,
+		   fwstats->txs_tossed,
+		   fwstats->txs_host_tossed,
+		   fwstats->bus_flow_block,
+		   fwstats->fws_flow_block,
+		   fwstats->send_pkts[0], fwstats->send_pkts[1],
+		   fwstats->send_pkts[2], fwstats->send_pkts[3],
+		   fwstats->send_pkts[4],
+		   fwstats->requested_sent[0],
+		   fwstats->requested_sent[1],
+		   fwstats->requested_sent[2],
+		   fwstats->requested_sent[3],
+		   fwstats->requested_sent[4]);
+
+	return 0;
+}
+#else
+static int brcmf_debugfs_fws_stats_read(struct seq_file *seq, void *data)
+{
+	return 0;
+}
+#endif
+
+struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr)
+{
+	struct brcmf_fws_info *fws;
+	struct brcmf_if *ifp;
+	u32 tlv = BRCMF_FWS_FLAGS_RSSI_SIGNALS;
+	int rc;
+	u32 mode;
+
+	fws = kzalloc(sizeof(*fws), GFP_KERNEL);
+	if (!fws) {
+		rc = -ENOMEM;
+		goto fail;
+	}
+
+	spin_lock_init(&fws->spinlock);
+
+	/* store drvr reference */
+	fws->drvr = drvr;
+	fws->fcmode = drvr->settings->fcmode;
+
+	if ((drvr->bus_if->always_use_fws_queue == false) &&
+	    (fws->fcmode == BRCMF_FWS_FCMODE_NONE)) {
+		fws->avoid_queueing = true;
+		brcmf_dbg(INFO, "FWS queueing will be avoided\n");
+		return fws;
+	}
+
+	fws->fws_wq = create_singlethread_workqueue("brcmf_fws_wq");
+	if (fws->fws_wq == NULL) {
+		brcmf_err("workqueue creation failed\n");
+		rc = -EBADF;
+		goto fail;
+	}
+	INIT_WORK(&fws->fws_dequeue_work, brcmf_fws_dequeue_worker);
+
+	/* enable firmware signalling if fcmode active */
+	if (fws->fcmode != BRCMF_FWS_FCMODE_NONE)
+		tlv |= BRCMF_FWS_FLAGS_XONXOFF_SIGNALS |
+		       BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS |
+		       BRCMF_FWS_FLAGS_HOST_PROPTXSTATUS_ACTIVE |
+		       BRCMF_FWS_FLAGS_HOST_RXREORDER_ACTIVE;
+
+	rc = brcmf_fweh_register(drvr, BRCMF_E_FIFO_CREDIT_MAP,
+				 brcmf_fws_notify_credit_map);
+	if (rc < 0) {
+		brcmf_err("register credit map handler failed\n");
+		goto fail;
+	}
+	rc = brcmf_fweh_register(drvr, BRCMF_E_BCMC_CREDIT_SUPPORT,
+				 brcmf_fws_notify_bcmc_credit_support);
+	if (rc < 0) {
+		brcmf_err("register bcmc credit handler failed\n");
+		brcmf_fweh_unregister(drvr, BRCMF_E_FIFO_CREDIT_MAP);
+		goto fail;
+	}
+
+	/* Setting the iovar may fail if feature is unsupported
+	 * so leave the rc as is so driver initialization can
+	 * continue. Set mode back to none indicating not enabled.
+	 */
+	fws->fw_signals = true;
+	ifp = brcmf_get_ifp(drvr, 0);
+	if (brcmf_fil_iovar_int_set(ifp, "tlv", tlv)) {
+		brcmf_err("failed to set bdcv2 tlv signaling\n");
+		fws->fcmode = BRCMF_FWS_FCMODE_NONE;
+		fws->fw_signals = false;
+	}
+
+	if (brcmf_fil_iovar_int_set(ifp, "ampdu_hostreorder", 1))
+		brcmf_dbg(INFO, "enabling AMPDU host-reorder failed\n");
+
+	/* Enable seq number reuse, if supported */
+	if (brcmf_fil_iovar_int_get(ifp, "wlfc_mode", &mode) == 0) {
+		if (BRCMF_FWS_MODE_GET_REUSESEQ(mode)) {
+			mode = 0;
+			BRCMF_FWS_MODE_SET_REUSESEQ(mode, 1);
+			if (brcmf_fil_iovar_int_set(ifp,
+						    "wlfc_mode", mode) == 0) {
+				BRCMF_FWS_MODE_SET_REUSESEQ(fws->mode, 1);
+			}
+		}
+	}
+
+	brcmf_fws_hanger_init(&fws->hanger);
+	brcmf_fws_macdesc_init(&fws->desc.other, NULL, 0);
+	brcmf_fws_macdesc_set_name(fws, &fws->desc.other);
+	brcmf_dbg(INFO, "added %s\n", fws->desc.other.name);
+	brcmu_pktq_init(&fws->desc.other.psq, BRCMF_FWS_PSQ_PREC_COUNT,
+			BRCMF_FWS_PSQ_LEN);
+
+	brcmf_dbg(INFO, "%s bdcv2 tlv signaling [%x]\n",
+		  fws->fw_signals ? "enabled" : "disabled", tlv);
+	return fws;
+
+fail:
+	brcmf_fws_detach(fws);
+	return ERR_PTR(rc);
+}
+
+void brcmf_fws_detach(struct brcmf_fws_info *fws)
+{
+	if (!fws)
+		return;
+
+	if (fws->fws_wq)
+		destroy_workqueue(fws->fws_wq);
+
+	/* cleanup */
+	brcmf_fws_lock(fws);
+	brcmf_fws_cleanup(fws, -1);
+	brcmf_fws_unlock(fws);
+
+	/* free top structure */
+	kfree(fws);
+}
+
+void brcmf_fws_debugfs_create(struct brcmf_pub *drvr)
+{
+	/* create debugfs file for statistics */
+	brcmf_debugfs_add_entry(drvr, "fws_stats",
+				brcmf_debugfs_fws_stats_read);
+}
+
+bool brcmf_fws_queue_skbs(struct brcmf_fws_info *fws)
+{
+	return !fws->avoid_queueing;
+}
+
+bool brcmf_fws_fc_active(struct brcmf_fws_info *fws)
+{
+	if (!fws->creditmap_received)
+		return false;
+
+	return fws->fcmode != BRCMF_FWS_FCMODE_NONE;
+}
+
+void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb)
+{
+	u32 hslot;
+
+	if (brcmf_skbcb(skb)->state == BRCMF_FWS_SKBSTATE_TIM) {
+		brcmu_pkt_buf_free_skb(skb);
+		return;
+	}
+	brcmf_fws_lock(fws);
+	hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
+	brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot, 0, 0);
+	brcmf_fws_unlock(fws);
+}
+
+void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked)
+{
+	struct brcmf_fws_info *fws = drvr_to_fws(drvr);
+	struct brcmf_if *ifp;
+	int i;
+
+	if (fws->avoid_queueing) {
+		for (i = 0; i < BRCMF_MAX_IFS; i++) {
+			ifp = drvr->iflist[i];
+			if (!ifp || !ifp->ndev)
+				continue;
+			brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FLOW,
+					     flow_blocked);
+		}
+	} else {
+		fws->bus_flow_blocked = flow_blocked;
+		if (!flow_blocked)
+			brcmf_fws_schedule_deq(fws);
+		else
+			fws->stats.bus_flow_block++;
+	}
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h
new file mode 100644
index 0000000..4e68357
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#ifndef FWSIGNAL_H_
+#define FWSIGNAL_H_
+
+struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr);
+void brcmf_fws_detach(struct brcmf_fws_info *fws);
+void brcmf_fws_debugfs_create(struct brcmf_pub *drvr);
+bool brcmf_fws_queue_skbs(struct brcmf_fws_info *fws);
+bool brcmf_fws_fc_active(struct brcmf_fws_info *fws);
+void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb);
+int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb);
+
+void brcmf_fws_reset_interface(struct brcmf_if *ifp);
+void brcmf_fws_add_interface(struct brcmf_if *ifp);
+void brcmf_fws_del_interface(struct brcmf_if *ifp);
+void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb);
+void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked);
+void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb);
+
+#endif /* FWSIGNAL_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
new file mode 100644
index 0000000..4e8397a
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
@@ -0,0 +1,1602 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*******************************************************************************
+ * Communicates with the dongle by using dcmd codes.
+ * For certain dcmd codes, the dongle interprets string data from the host.
+ ******************************************************************************/
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+
+#include "core.h"
+#include "debug.h"
+#include "proto.h"
+#include "msgbuf.h"
+#include "commonring.h"
+#include "flowring.h"
+#include "bus.h"
+#include "tracepoint.h"
+
+
+#define MSGBUF_IOCTL_RESP_TIMEOUT		msecs_to_jiffies(2000)
+
+#define MSGBUF_TYPE_GEN_STATUS			0x1
+#define MSGBUF_TYPE_RING_STATUS			0x2
+#define MSGBUF_TYPE_FLOW_RING_CREATE		0x3
+#define MSGBUF_TYPE_FLOW_RING_CREATE_CMPLT	0x4
+#define MSGBUF_TYPE_FLOW_RING_DELETE		0x5
+#define MSGBUF_TYPE_FLOW_RING_DELETE_CMPLT	0x6
+#define MSGBUF_TYPE_FLOW_RING_FLUSH		0x7
+#define MSGBUF_TYPE_FLOW_RING_FLUSH_CMPLT	0x8
+#define MSGBUF_TYPE_IOCTLPTR_REQ		0x9
+#define MSGBUF_TYPE_IOCTLPTR_REQ_ACK		0xA
+#define MSGBUF_TYPE_IOCTLRESP_BUF_POST		0xB
+#define MSGBUF_TYPE_IOCTL_CMPLT			0xC
+#define MSGBUF_TYPE_EVENT_BUF_POST		0xD
+#define MSGBUF_TYPE_WL_EVENT			0xE
+#define MSGBUF_TYPE_TX_POST			0xF
+#define MSGBUF_TYPE_TX_STATUS			0x10
+#define MSGBUF_TYPE_RXBUF_POST			0x11
+#define MSGBUF_TYPE_RX_CMPLT			0x12
+#define MSGBUF_TYPE_LPBK_DMAXFER		0x13
+#define MSGBUF_TYPE_LPBK_DMAXFER_CMPLT		0x14
+
+#define NR_TX_PKTIDS				2048
+#define NR_RX_PKTIDS				1024
+
+#define BRCMF_IOCTL_REQ_PKTID			0xFFFE
+
+#define BRCMF_MSGBUF_MAX_PKT_SIZE		2048
+#define BRCMF_MSGBUF_RXBUFPOST_THRESHOLD	32
+#define BRCMF_MSGBUF_MAX_IOCTLRESPBUF_POST	8
+#define BRCMF_MSGBUF_MAX_EVENTBUF_POST		8
+
+#define BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_3	0x01
+#define BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_11	0x02
+#define BRCMF_MSGBUF_PKT_FLAGS_FRAME_MASK	0x07
+#define BRCMF_MSGBUF_PKT_FLAGS_PRIO_SHIFT	5
+
+#define BRCMF_MSGBUF_TX_FLUSH_CNT1		32
+#define BRCMF_MSGBUF_TX_FLUSH_CNT2		96
+
+#define BRCMF_MSGBUF_DELAY_TXWORKER_THRS	96
+#define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS	32
+#define BRCMF_MSGBUF_UPDATE_RX_PTR_THRS		48
+
+
+struct msgbuf_common_hdr {
+	u8				msgtype;
+	u8				ifidx;
+	u8				flags;
+	u8				rsvd0;
+	__le32				request_id;
+};
+
+struct msgbuf_ioctl_req_hdr {
+	struct msgbuf_common_hdr	msg;
+	__le32				cmd;
+	__le16				trans_id;
+	__le16				input_buf_len;
+	__le16				output_buf_len;
+	__le16				rsvd0[3];
+	struct msgbuf_buf_addr		req_buf_addr;
+	__le32				rsvd1[2];
+};
+
+struct msgbuf_tx_msghdr {
+	struct msgbuf_common_hdr	msg;
+	u8				txhdr[ETH_HLEN];
+	u8				flags;
+	u8				seg_cnt;
+	struct msgbuf_buf_addr		metadata_buf_addr;
+	struct msgbuf_buf_addr		data_buf_addr;
+	__le16				metadata_buf_len;
+	__le16				data_len;
+	__le32				rsvd0;
+};
+
+struct msgbuf_rx_bufpost {
+	struct msgbuf_common_hdr	msg;
+	__le16				metadata_buf_len;
+	__le16				data_buf_len;
+	__le32				rsvd0;
+	struct msgbuf_buf_addr		metadata_buf_addr;
+	struct msgbuf_buf_addr		data_buf_addr;
+};
+
+struct msgbuf_rx_ioctl_resp_or_event {
+	struct msgbuf_common_hdr	msg;
+	__le16				host_buf_len;
+	__le16				rsvd0[3];
+	struct msgbuf_buf_addr		host_buf_addr;
+	__le32				rsvd1[4];
+};
+
+struct msgbuf_completion_hdr {
+	__le16				status;
+	__le16				flow_ring_id;
+};
+
+struct msgbuf_rx_event {
+	struct msgbuf_common_hdr	msg;
+	struct msgbuf_completion_hdr	compl_hdr;
+	__le16				event_data_len;
+	__le16				seqnum;
+	__le16				rsvd0[4];
+};
+
+struct msgbuf_ioctl_resp_hdr {
+	struct msgbuf_common_hdr	msg;
+	struct msgbuf_completion_hdr	compl_hdr;
+	__le16				resp_len;
+	__le16				trans_id;
+	__le32				cmd;
+	__le32				rsvd0;
+};
+
+struct msgbuf_tx_status {
+	struct msgbuf_common_hdr	msg;
+	struct msgbuf_completion_hdr	compl_hdr;
+	__le16				metadata_len;
+	__le16				tx_status;
+};
+
+struct msgbuf_rx_complete {
+	struct msgbuf_common_hdr	msg;
+	struct msgbuf_completion_hdr	compl_hdr;
+	__le16				metadata_len;
+	__le16				data_len;
+	__le16				data_offset;
+	__le16				flags;
+	__le32				rx_status_0;
+	__le32				rx_status_1;
+	__le32				rsvd0;
+};
+
+struct msgbuf_tx_flowring_create_req {
+	struct msgbuf_common_hdr	msg;
+	u8				da[ETH_ALEN];
+	u8				sa[ETH_ALEN];
+	u8				tid;
+	u8				if_flags;
+	__le16				flow_ring_id;
+	u8				tc;
+	u8				priority;
+	__le16				int_vector;
+	__le16				max_items;
+	__le16				len_item;
+	struct msgbuf_buf_addr		flow_ring_addr;
+};
+
+struct msgbuf_tx_flowring_delete_req {
+	struct msgbuf_common_hdr	msg;
+	__le16				flow_ring_id;
+	__le16				reason;
+	__le32				rsvd0[7];
+};
+
+struct msgbuf_flowring_create_resp {
+	struct msgbuf_common_hdr	msg;
+	struct msgbuf_completion_hdr	compl_hdr;
+	__le32				rsvd0[3];
+};
+
+struct msgbuf_flowring_delete_resp {
+	struct msgbuf_common_hdr	msg;
+	struct msgbuf_completion_hdr	compl_hdr;
+	__le32				rsvd0[3];
+};
+
+struct msgbuf_flowring_flush_resp {
+	struct msgbuf_common_hdr	msg;
+	struct msgbuf_completion_hdr	compl_hdr;
+	__le32				rsvd0[3];
+};
+
+struct brcmf_msgbuf_work_item {
+	struct list_head queue;
+	u32 flowid;
+	int ifidx;
+	u8 sa[ETH_ALEN];
+	u8 da[ETH_ALEN];
+};
+
+struct brcmf_msgbuf {
+	struct brcmf_pub *drvr;
+
+	struct brcmf_commonring **commonrings;
+	struct brcmf_commonring **flowrings;
+	dma_addr_t *flowring_dma_handle;
+
+	u16 max_flowrings;
+	u16 max_submissionrings;
+	u16 max_completionrings;
+
+	u16 rx_dataoffset;
+	u32 max_rxbufpost;
+	u16 rx_metadata_offset;
+	u32 rxbufpost;
+
+	u32 max_ioctlrespbuf;
+	u32 cur_ioctlrespbuf;
+	u32 max_eventbuf;
+	u32 cur_eventbuf;
+
+	void *ioctbuf;
+	dma_addr_t ioctbuf_handle;
+	u32 ioctbuf_phys_hi;
+	u32 ioctbuf_phys_lo;
+	int ioctl_resp_status;
+	u32 ioctl_resp_ret_len;
+	u32 ioctl_resp_pktid;
+
+	u16 data_seq_no;
+	u16 ioctl_seq_no;
+	u32 reqid;
+	wait_queue_head_t ioctl_resp_wait;
+	bool ctl_completed;
+
+	struct brcmf_msgbuf_pktids *tx_pktids;
+	struct brcmf_msgbuf_pktids *rx_pktids;
+	struct brcmf_flowring *flow;
+
+	struct workqueue_struct *txflow_wq;
+	struct work_struct txflow_work;
+	unsigned long *flow_map;
+	unsigned long *txstatus_done_map;
+
+	struct work_struct flowring_work;
+	spinlock_t flowring_work_lock;
+	struct list_head work_queue;
+};
+
+struct brcmf_msgbuf_pktid {
+	atomic_t  allocated;
+	u16 data_offset;
+	struct sk_buff *skb;
+	dma_addr_t physaddr;
+};
+
+struct brcmf_msgbuf_pktids {
+	u32 array_size;
+	u32 last_allocated_idx;
+	enum dma_data_direction direction;
+	struct brcmf_msgbuf_pktid *array;
+};
+
+static void brcmf_msgbuf_rxbuf_ioctlresp_post(struct brcmf_msgbuf *msgbuf);
+
+
+static struct brcmf_msgbuf_pktids *
+brcmf_msgbuf_init_pktids(u32 nr_array_entries,
+			 enum dma_data_direction direction)
+{
+	struct brcmf_msgbuf_pktid *array;
+	struct brcmf_msgbuf_pktids *pktids;
+
+	array = kcalloc(nr_array_entries, sizeof(*array), GFP_KERNEL);
+	if (!array)
+		return NULL;
+
+	pktids = kzalloc(sizeof(*pktids), GFP_KERNEL);
+	if (!pktids) {
+		kfree(array);
+		return NULL;
+	}
+	pktids->array = array;
+	pktids->array_size = nr_array_entries;
+
+	return pktids;
+}
+
+
+static int
+brcmf_msgbuf_alloc_pktid(struct device *dev,
+			 struct brcmf_msgbuf_pktids *pktids,
+			 struct sk_buff *skb, u16 data_offset,
+			 dma_addr_t *physaddr, u32 *idx)
+{
+	struct brcmf_msgbuf_pktid *array;
+	u32 count;
+
+	array = pktids->array;
+
+	*physaddr = dma_map_single(dev, skb->data + data_offset,
+				   skb->len - data_offset, pktids->direction);
+
+	if (dma_mapping_error(dev, *physaddr)) {
+		brcmf_err("dma_map_single failed !!\n");
+		return -ENOMEM;
+	}
+
+	*idx = pktids->last_allocated_idx;
+
+	count = 0;
+	do {
+		(*idx)++;
+		if (*idx == pktids->array_size)
+			*idx = 0;
+		if (array[*idx].allocated.counter == 0)
+			if (atomic_cmpxchg(&array[*idx].allocated, 0, 1) == 0)
+				break;
+		count++;
+	} while (count < pktids->array_size);
+
+	if (count == pktids->array_size)
+		return -ENOMEM;
+
+	array[*idx].data_offset = data_offset;
+	array[*idx].physaddr = *physaddr;
+	array[*idx].skb = skb;
+
+	pktids->last_allocated_idx = *idx;
+
+	return 0;
+}
+
+
+static struct sk_buff *
+brcmf_msgbuf_get_pktid(struct device *dev, struct brcmf_msgbuf_pktids *pktids,
+		       u32 idx)
+{
+	struct brcmf_msgbuf_pktid *pktid;
+	struct sk_buff *skb;
+
+	if (idx >= pktids->array_size) {
+		brcmf_err("Invalid packet id %d (max %d)\n", idx,
+			  pktids->array_size);
+		return NULL;
+	}
+	if (pktids->array[idx].allocated.counter) {
+		pktid = &pktids->array[idx];
+		dma_unmap_single(dev, pktid->physaddr,
+				 pktid->skb->len - pktid->data_offset,
+				 pktids->direction);
+		skb = pktid->skb;
+		pktid->allocated.counter = 0;
+		return skb;
+	} else {
+		brcmf_err("Invalid packet id %d (not in use)\n", idx);
+	}
+
+	return NULL;
+}
+
+
+static void
+brcmf_msgbuf_release_array(struct device *dev,
+			   struct brcmf_msgbuf_pktids *pktids)
+{
+	struct brcmf_msgbuf_pktid *array;
+	struct brcmf_msgbuf_pktid *pktid;
+	u32 count;
+
+	array = pktids->array;
+	count = 0;
+	do {
+		if (array[count].allocated.counter) {
+			pktid = &array[count];
+			dma_unmap_single(dev, pktid->physaddr,
+					 pktid->skb->len - pktid->data_offset,
+					 pktids->direction);
+			brcmu_pkt_buf_free_skb(pktid->skb);
+		}
+		count++;
+	} while (count < pktids->array_size);
+
+	kfree(array);
+	kfree(pktids);
+}
+
+
+static void brcmf_msgbuf_release_pktids(struct brcmf_msgbuf *msgbuf)
+{
+	if (msgbuf->rx_pktids)
+		brcmf_msgbuf_release_array(msgbuf->drvr->bus_if->dev,
+					   msgbuf->rx_pktids);
+	if (msgbuf->tx_pktids)
+		brcmf_msgbuf_release_array(msgbuf->drvr->bus_if->dev,
+					   msgbuf->tx_pktids);
+}
+
+
+static int brcmf_msgbuf_tx_ioctl(struct brcmf_pub *drvr, int ifidx,
+				 uint cmd, void *buf, uint len)
+{
+	struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+	struct brcmf_commonring *commonring;
+	struct msgbuf_ioctl_req_hdr *request;
+	u16 buf_len;
+	void *ret_ptr;
+	int err;
+
+	commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT];
+	brcmf_commonring_lock(commonring);
+	ret_ptr = brcmf_commonring_reserve_for_write(commonring);
+	if (!ret_ptr) {
+		brcmf_err("Failed to reserve space in commonring\n");
+		brcmf_commonring_unlock(commonring);
+		return -ENOMEM;
+	}
+
+	msgbuf->reqid++;
+
+	request = (struct msgbuf_ioctl_req_hdr *)ret_ptr;
+	request->msg.msgtype = MSGBUF_TYPE_IOCTLPTR_REQ;
+	request->msg.ifidx = (u8)ifidx;
+	request->msg.flags = 0;
+	request->msg.request_id = cpu_to_le32(BRCMF_IOCTL_REQ_PKTID);
+	request->cmd = cpu_to_le32(cmd);
+	request->output_buf_len = cpu_to_le16(len);
+	request->trans_id = cpu_to_le16(msgbuf->reqid);
+
+	buf_len = min_t(u16, len, BRCMF_TX_IOCTL_MAX_MSG_SIZE);
+	request->input_buf_len = cpu_to_le16(buf_len);
+	request->req_buf_addr.high_addr = cpu_to_le32(msgbuf->ioctbuf_phys_hi);
+	request->req_buf_addr.low_addr = cpu_to_le32(msgbuf->ioctbuf_phys_lo);
+	if (buf)
+		memcpy(msgbuf->ioctbuf, buf, buf_len);
+	else
+		memset(msgbuf->ioctbuf, 0, buf_len);
+
+	err = brcmf_commonring_write_complete(commonring);
+	brcmf_commonring_unlock(commonring);
+
+	return err;
+}
+
+
+static int brcmf_msgbuf_ioctl_resp_wait(struct brcmf_msgbuf *msgbuf)
+{
+	return wait_event_timeout(msgbuf->ioctl_resp_wait,
+				  msgbuf->ctl_completed,
+				  MSGBUF_IOCTL_RESP_TIMEOUT);
+}
+
+
+static void brcmf_msgbuf_ioctl_resp_wake(struct brcmf_msgbuf *msgbuf)
+{
+	msgbuf->ctl_completed = true;
+	wake_up(&msgbuf->ioctl_resp_wait);
+}
+
+
+static int brcmf_msgbuf_query_dcmd(struct brcmf_pub *drvr, int ifidx,
+				   uint cmd, void *buf, uint len, int *fwerr)
+{
+	struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+	struct sk_buff *skb = NULL;
+	int timeout;
+	int err;
+
+	brcmf_dbg(MSGBUF, "ifidx=%d, cmd=%d, len=%d\n", ifidx, cmd, len);
+	*fwerr = 0;
+	msgbuf->ctl_completed = false;
+	err = brcmf_msgbuf_tx_ioctl(drvr, ifidx, cmd, buf, len);
+	if (err)
+		return err;
+
+	timeout = brcmf_msgbuf_ioctl_resp_wait(msgbuf);
+	if (!timeout) {
+		brcmf_err("Timeout on response for query command\n");
+		return -EIO;
+	}
+
+	skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
+				     msgbuf->rx_pktids,
+				     msgbuf->ioctl_resp_pktid);
+	if (msgbuf->ioctl_resp_ret_len != 0) {
+		if (!skb)
+			return -EBADF;
+
+		memcpy(buf, skb->data, (len < msgbuf->ioctl_resp_ret_len) ?
+				       len : msgbuf->ioctl_resp_ret_len);
+	}
+	brcmu_pkt_buf_free_skb(skb);
+
+	*fwerr = msgbuf->ioctl_resp_status;
+	return 0;
+}
+
+
+static int brcmf_msgbuf_set_dcmd(struct brcmf_pub *drvr, int ifidx,
+				 uint cmd, void *buf, uint len, int *fwerr)
+{
+	return brcmf_msgbuf_query_dcmd(drvr, ifidx, cmd, buf, len, fwerr);
+}
+
+
+static int brcmf_msgbuf_hdrpull(struct brcmf_pub *drvr, bool do_fws,
+				struct sk_buff *skb, struct brcmf_if **ifp)
+{
+	return -ENODEV;
+}
+
+static void brcmf_msgbuf_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb)
+{
+}
+
+static void
+brcmf_msgbuf_remove_flowring(struct brcmf_msgbuf *msgbuf, u16 flowid)
+{
+	u32 dma_sz;
+	void *dma_buf;
+
+	brcmf_dbg(MSGBUF, "Removing flowring %d\n", flowid);
+
+	dma_sz = BRCMF_H2D_TXFLOWRING_MAX_ITEM * BRCMF_H2D_TXFLOWRING_ITEMSIZE;
+	dma_buf = msgbuf->flowrings[flowid]->buf_addr;
+	dma_free_coherent(msgbuf->drvr->bus_if->dev, dma_sz, dma_buf,
+			  msgbuf->flowring_dma_handle[flowid]);
+
+	brcmf_flowring_delete(msgbuf->flow, flowid);
+}
+
+
+static struct brcmf_msgbuf_work_item *
+brcmf_msgbuf_dequeue_work(struct brcmf_msgbuf *msgbuf)
+{
+	struct brcmf_msgbuf_work_item *work = NULL;
+	ulong flags;
+
+	spin_lock_irqsave(&msgbuf->flowring_work_lock, flags);
+	if (!list_empty(&msgbuf->work_queue)) {
+		work = list_first_entry(&msgbuf->work_queue,
+					struct brcmf_msgbuf_work_item, queue);
+		list_del(&work->queue);
+	}
+	spin_unlock_irqrestore(&msgbuf->flowring_work_lock, flags);
+
+	return work;
+}
+
+
+static u32
+brcmf_msgbuf_flowring_create_worker(struct brcmf_msgbuf *msgbuf,
+				    struct brcmf_msgbuf_work_item *work)
+{
+	struct msgbuf_tx_flowring_create_req *create;
+	struct brcmf_commonring *commonring;
+	void *ret_ptr;
+	u32 flowid;
+	void *dma_buf;
+	u32 dma_sz;
+	u64 address;
+	int err;
+
+	flowid = work->flowid;
+	dma_sz = BRCMF_H2D_TXFLOWRING_MAX_ITEM * BRCMF_H2D_TXFLOWRING_ITEMSIZE;
+	dma_buf = dma_alloc_coherent(msgbuf->drvr->bus_if->dev, dma_sz,
+				     &msgbuf->flowring_dma_handle[flowid],
+				     GFP_KERNEL);
+	if (!dma_buf) {
+		brcmf_err("dma_alloc_coherent failed\n");
+		brcmf_flowring_delete(msgbuf->flow, flowid);
+		return BRCMF_FLOWRING_INVALID_ID;
+	}
+
+	brcmf_commonring_config(msgbuf->flowrings[flowid],
+				BRCMF_H2D_TXFLOWRING_MAX_ITEM,
+				BRCMF_H2D_TXFLOWRING_ITEMSIZE, dma_buf);
+
+	commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT];
+	brcmf_commonring_lock(commonring);
+	ret_ptr = brcmf_commonring_reserve_for_write(commonring);
+	if (!ret_ptr) {
+		brcmf_err("Failed to reserve space in commonring\n");
+		brcmf_commonring_unlock(commonring);
+		brcmf_msgbuf_remove_flowring(msgbuf, flowid);
+		return BRCMF_FLOWRING_INVALID_ID;
+	}
+
+	create = (struct msgbuf_tx_flowring_create_req *)ret_ptr;
+	create->msg.msgtype = MSGBUF_TYPE_FLOW_RING_CREATE;
+	create->msg.ifidx = work->ifidx;
+	create->msg.request_id = 0;
+	create->tid = brcmf_flowring_tid(msgbuf->flow, flowid);
+	create->flow_ring_id = cpu_to_le16(flowid +
+					   BRCMF_H2D_MSGRING_FLOWRING_IDSTART);
+	memcpy(create->sa, work->sa, ETH_ALEN);
+	memcpy(create->da, work->da, ETH_ALEN);
+	address = (u64)msgbuf->flowring_dma_handle[flowid];
+	create->flow_ring_addr.high_addr = cpu_to_le32(address >> 32);
+	create->flow_ring_addr.low_addr = cpu_to_le32(address & 0xffffffff);
+	create->max_items = cpu_to_le16(BRCMF_H2D_TXFLOWRING_MAX_ITEM);
+	create->len_item = cpu_to_le16(BRCMF_H2D_TXFLOWRING_ITEMSIZE);
+
+	brcmf_dbg(MSGBUF, "Send Flow Create Req flow ID %d for peer %pM prio %d ifindex %d\n",
+		  flowid, work->da, create->tid, work->ifidx);
+
+	err = brcmf_commonring_write_complete(commonring);
+	brcmf_commonring_unlock(commonring);
+	if (err) {
+		brcmf_err("Failed to write commonring\n");
+		brcmf_msgbuf_remove_flowring(msgbuf, flowid);
+		return BRCMF_FLOWRING_INVALID_ID;
+	}
+
+	return flowid;
+}
+
+
+static void brcmf_msgbuf_flowring_worker(struct work_struct *work)
+{
+	struct brcmf_msgbuf *msgbuf;
+	struct brcmf_msgbuf_work_item *create;
+
+	msgbuf = container_of(work, struct brcmf_msgbuf, flowring_work);
+
+	while ((create = brcmf_msgbuf_dequeue_work(msgbuf))) {
+		brcmf_msgbuf_flowring_create_worker(msgbuf, create);
+		kfree(create);
+	}
+}
+
+
+static u32 brcmf_msgbuf_flowring_create(struct brcmf_msgbuf *msgbuf, int ifidx,
+					struct sk_buff *skb)
+{
+	struct brcmf_msgbuf_work_item *create;
+	struct ethhdr *eh = (struct ethhdr *)(skb->data);
+	u32 flowid;
+	ulong flags;
+
+	create = kzalloc(sizeof(*create), GFP_ATOMIC);
+	if (create == NULL)
+		return BRCMF_FLOWRING_INVALID_ID;
+
+	flowid = brcmf_flowring_create(msgbuf->flow, eh->h_dest,
+				       skb->priority, ifidx);
+	if (flowid == BRCMF_FLOWRING_INVALID_ID) {
+		kfree(create);
+		return flowid;
+	}
+
+	create->flowid = flowid;
+	create->ifidx = ifidx;
+	memcpy(create->sa, eh->h_source, ETH_ALEN);
+	memcpy(create->da, eh->h_dest, ETH_ALEN);
+
+	spin_lock_irqsave(&msgbuf->flowring_work_lock, flags);
+	list_add_tail(&create->queue, &msgbuf->work_queue);
+	spin_unlock_irqrestore(&msgbuf->flowring_work_lock, flags);
+	schedule_work(&msgbuf->flowring_work);
+
+	return flowid;
+}
+
+
+static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u16 flowid)
+{
+	struct brcmf_flowring *flow = msgbuf->flow;
+	struct brcmf_commonring *commonring;
+	void *ret_ptr;
+	u32 count;
+	struct sk_buff *skb;
+	dma_addr_t physaddr;
+	u32 pktid;
+	struct msgbuf_tx_msghdr *tx_msghdr;
+	u64 address;
+
+	commonring = msgbuf->flowrings[flowid];
+	if (!brcmf_commonring_write_available(commonring))
+		return;
+
+	brcmf_commonring_lock(commonring);
+
+	count = BRCMF_MSGBUF_TX_FLUSH_CNT2 - BRCMF_MSGBUF_TX_FLUSH_CNT1;
+	while (brcmf_flowring_qlen(flow, flowid)) {
+		skb = brcmf_flowring_dequeue(flow, flowid);
+		if (skb == NULL) {
+			brcmf_err("No SKB, but qlen %d\n",
+				  brcmf_flowring_qlen(flow, flowid));
+			break;
+		}
+		skb_orphan(skb);
+		if (brcmf_msgbuf_alloc_pktid(msgbuf->drvr->bus_if->dev,
+					     msgbuf->tx_pktids, skb, ETH_HLEN,
+					     &physaddr, &pktid)) {
+			brcmf_flowring_reinsert(flow, flowid, skb);
+			brcmf_err("No PKTID available !!\n");
+			break;
+		}
+		ret_ptr = brcmf_commonring_reserve_for_write(commonring);
+		if (!ret_ptr) {
+			brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
+					       msgbuf->tx_pktids, pktid);
+			brcmf_flowring_reinsert(flow, flowid, skb);
+			break;
+		}
+		count++;
+
+		tx_msghdr = (struct msgbuf_tx_msghdr *)ret_ptr;
+
+		tx_msghdr->msg.msgtype = MSGBUF_TYPE_TX_POST;
+		tx_msghdr->msg.request_id = cpu_to_le32(pktid);
+		tx_msghdr->msg.ifidx = brcmf_flowring_ifidx_get(flow, flowid);
+		tx_msghdr->flags = BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_3;
+		tx_msghdr->flags |= (skb->priority & 0x07) <<
+				    BRCMF_MSGBUF_PKT_FLAGS_PRIO_SHIFT;
+		tx_msghdr->seg_cnt = 1;
+		memcpy(tx_msghdr->txhdr, skb->data, ETH_HLEN);
+		tx_msghdr->data_len = cpu_to_le16(skb->len - ETH_HLEN);
+		address = (u64)physaddr;
+		tx_msghdr->data_buf_addr.high_addr = cpu_to_le32(address >> 32);
+		tx_msghdr->data_buf_addr.low_addr =
+			cpu_to_le32(address & 0xffffffff);
+		tx_msghdr->metadata_buf_len = 0;
+		tx_msghdr->metadata_buf_addr.high_addr = 0;
+		tx_msghdr->metadata_buf_addr.low_addr = 0;
+		atomic_inc(&commonring->outstanding_tx);
+		if (count >= BRCMF_MSGBUF_TX_FLUSH_CNT2) {
+			brcmf_commonring_write_complete(commonring);
+			count = 0;
+		}
+	}
+	if (count)
+		brcmf_commonring_write_complete(commonring);
+	brcmf_commonring_unlock(commonring);
+}
+
+
+static void brcmf_msgbuf_txflow_worker(struct work_struct *worker)
+{
+	struct brcmf_msgbuf *msgbuf;
+	u32 flowid;
+
+	msgbuf = container_of(worker, struct brcmf_msgbuf, txflow_work);
+	for_each_set_bit(flowid, msgbuf->flow_map, msgbuf->max_flowrings) {
+		clear_bit(flowid, msgbuf->flow_map);
+		brcmf_msgbuf_txflow(msgbuf, flowid);
+	}
+}
+
+
+static int brcmf_msgbuf_schedule_txdata(struct brcmf_msgbuf *msgbuf, u32 flowid,
+					bool force)
+{
+	struct brcmf_commonring *commonring;
+
+	set_bit(flowid, msgbuf->flow_map);
+	commonring = msgbuf->flowrings[flowid];
+	if ((force) || (atomic_read(&commonring->outstanding_tx) <
+			BRCMF_MSGBUF_DELAY_TXWORKER_THRS))
+		queue_work(msgbuf->txflow_wq, &msgbuf->txflow_work);
+
+	return 0;
+}
+
+
+static int brcmf_msgbuf_tx_queue_data(struct brcmf_pub *drvr, int ifidx,
+				      struct sk_buff *skb)
+{
+	struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+	struct brcmf_flowring *flow = msgbuf->flow;
+	struct ethhdr *eh = (struct ethhdr *)(skb->data);
+	u32 flowid;
+	u32 queue_count;
+	bool force;
+
+	flowid = brcmf_flowring_lookup(flow, eh->h_dest, skb->priority, ifidx);
+	if (flowid == BRCMF_FLOWRING_INVALID_ID) {
+		flowid = brcmf_msgbuf_flowring_create(msgbuf, ifidx, skb);
+		if (flowid == BRCMF_FLOWRING_INVALID_ID)
+			return -ENOMEM;
+	}
+	queue_count = brcmf_flowring_enqueue(flow, flowid, skb);
+	force = ((queue_count % BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS) == 0);
+	brcmf_msgbuf_schedule_txdata(msgbuf, flowid, force);
+
+	return 0;
+}
+
+
+static void
+brcmf_msgbuf_configure_addr_mode(struct brcmf_pub *drvr, int ifidx,
+				 enum proto_addr_mode addr_mode)
+{
+	struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+
+	brcmf_flowring_configure_addr_mode(msgbuf->flow, ifidx, addr_mode);
+}
+
+
+static void
+brcmf_msgbuf_delete_peer(struct brcmf_pub *drvr, int ifidx, u8 peer[ETH_ALEN])
+{
+	struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+
+	brcmf_flowring_delete_peer(msgbuf->flow, ifidx, peer);
+}
+
+
+static void
+brcmf_msgbuf_add_tdls_peer(struct brcmf_pub *drvr, int ifidx, u8 peer[ETH_ALEN])
+{
+	struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+
+	brcmf_flowring_add_tdls_peer(msgbuf->flow, ifidx, peer);
+}
+
+
+static void
+brcmf_msgbuf_process_ioctl_complete(struct brcmf_msgbuf *msgbuf, void *buf)
+{
+	struct msgbuf_ioctl_resp_hdr *ioctl_resp;
+
+	ioctl_resp = (struct msgbuf_ioctl_resp_hdr *)buf;
+
+	msgbuf->ioctl_resp_status =
+			(s16)le16_to_cpu(ioctl_resp->compl_hdr.status);
+	msgbuf->ioctl_resp_ret_len = le16_to_cpu(ioctl_resp->resp_len);
+	msgbuf->ioctl_resp_pktid = le32_to_cpu(ioctl_resp->msg.request_id);
+
+	brcmf_msgbuf_ioctl_resp_wake(msgbuf);
+
+	if (msgbuf->cur_ioctlrespbuf)
+		msgbuf->cur_ioctlrespbuf--;
+	brcmf_msgbuf_rxbuf_ioctlresp_post(msgbuf);
+}
+
+
+static void
+brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf)
+{
+	struct brcmf_commonring *commonring;
+	struct msgbuf_tx_status *tx_status;
+	u32 idx;
+	struct sk_buff *skb;
+	u16 flowid;
+
+	tx_status = (struct msgbuf_tx_status *)buf;
+	idx = le32_to_cpu(tx_status->msg.request_id);
+	flowid = le16_to_cpu(tx_status->compl_hdr.flow_ring_id);
+	flowid -= BRCMF_H2D_MSGRING_FLOWRING_IDSTART;
+	skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
+				     msgbuf->tx_pktids, idx);
+	if (!skb)
+		return;
+
+	set_bit(flowid, msgbuf->txstatus_done_map);
+	commonring = msgbuf->flowrings[flowid];
+	atomic_dec(&commonring->outstanding_tx);
+
+	brcmf_txfinalize(brcmf_get_ifp(msgbuf->drvr, tx_status->msg.ifidx),
+			 skb, true);
+}
+
+
+static u32 brcmf_msgbuf_rxbuf_data_post(struct brcmf_msgbuf *msgbuf, u32 count)
+{
+	struct brcmf_commonring *commonring;
+	void *ret_ptr;
+	struct sk_buff *skb;
+	u16 alloced;
+	u32 pktlen;
+	dma_addr_t physaddr;
+	struct msgbuf_rx_bufpost *rx_bufpost;
+	u64 address;
+	u32 pktid;
+	u32 i;
+
+	commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_RXPOST_SUBMIT];
+	ret_ptr = brcmf_commonring_reserve_for_write_multiple(commonring,
+							      count,
+							      &alloced);
+	if (!ret_ptr) {
+		brcmf_dbg(MSGBUF, "Failed to reserve space in commonring\n");
+		return 0;
+	}
+
+	for (i = 0; i < alloced; i++) {
+		rx_bufpost = (struct msgbuf_rx_bufpost *)ret_ptr;
+		memset(rx_bufpost, 0, sizeof(*rx_bufpost));
+
+		skb = brcmu_pkt_buf_get_skb(BRCMF_MSGBUF_MAX_PKT_SIZE);
+
+		if (skb == NULL) {
+			brcmf_err("Failed to alloc SKB\n");
+			brcmf_commonring_write_cancel(commonring, alloced - i);
+			break;
+		}
+
+		pktlen = skb->len;
+		if (brcmf_msgbuf_alloc_pktid(msgbuf->drvr->bus_if->dev,
+					     msgbuf->rx_pktids, skb, 0,
+					     &physaddr, &pktid)) {
+			dev_kfree_skb_any(skb);
+			brcmf_err("No PKTID available !!\n");
+			brcmf_commonring_write_cancel(commonring, alloced - i);
+			break;
+		}
+
+		if (msgbuf->rx_metadata_offset) {
+			address = (u64)physaddr;
+			rx_bufpost->metadata_buf_len =
+				cpu_to_le16(msgbuf->rx_metadata_offset);
+			rx_bufpost->metadata_buf_addr.high_addr =
+				cpu_to_le32(address >> 32);
+			rx_bufpost->metadata_buf_addr.low_addr =
+				cpu_to_le32(address & 0xffffffff);
+
+			skb_pull(skb, msgbuf->rx_metadata_offset);
+			pktlen = skb->len;
+			physaddr += msgbuf->rx_metadata_offset;
+		}
+		rx_bufpost->msg.msgtype = MSGBUF_TYPE_RXBUF_POST;
+		rx_bufpost->msg.request_id = cpu_to_le32(pktid);
+
+		address = (u64)physaddr;
+		rx_bufpost->data_buf_len = cpu_to_le16((u16)pktlen);
+		rx_bufpost->data_buf_addr.high_addr =
+			cpu_to_le32(address >> 32);
+		rx_bufpost->data_buf_addr.low_addr =
+			cpu_to_le32(address & 0xffffffff);
+
+		ret_ptr += brcmf_commonring_len_item(commonring);
+	}
+
+	if (i)
+		brcmf_commonring_write_complete(commonring);
+
+	return i;
+}
+
+
+static void
+brcmf_msgbuf_rxbuf_data_fill(struct brcmf_msgbuf *msgbuf)
+{
+	u32 fillbufs;
+	u32 retcount;
+
+	fillbufs = msgbuf->max_rxbufpost - msgbuf->rxbufpost;
+
+	while (fillbufs) {
+		retcount = brcmf_msgbuf_rxbuf_data_post(msgbuf, fillbufs);
+		if (!retcount)
+			break;
+		msgbuf->rxbufpost += retcount;
+		fillbufs -= retcount;
+	}
+}
+
+
+static void
+brcmf_msgbuf_update_rxbufpost_count(struct brcmf_msgbuf *msgbuf, u16 rxcnt)
+{
+	msgbuf->rxbufpost -= rxcnt;
+	if (msgbuf->rxbufpost <= (msgbuf->max_rxbufpost -
+				  BRCMF_MSGBUF_RXBUFPOST_THRESHOLD))
+		brcmf_msgbuf_rxbuf_data_fill(msgbuf);
+}
+
+
+static u32
+brcmf_msgbuf_rxbuf_ctrl_post(struct brcmf_msgbuf *msgbuf, bool event_buf,
+			     u32 count)
+{
+	struct brcmf_commonring *commonring;
+	void *ret_ptr;
+	struct sk_buff *skb;
+	u16 alloced;
+	u32 pktlen;
+	dma_addr_t physaddr;
+	struct msgbuf_rx_ioctl_resp_or_event *rx_bufpost;
+	u64 address;
+	u32 pktid;
+	u32 i;
+
+	commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT];
+	brcmf_commonring_lock(commonring);
+	ret_ptr = brcmf_commonring_reserve_for_write_multiple(commonring,
+							      count,
+							      &alloced);
+	if (!ret_ptr) {
+		brcmf_err("Failed to reserve space in commonring\n");
+		brcmf_commonring_unlock(commonring);
+		return 0;
+	}
+
+	for (i = 0; i < alloced; i++) {
+		rx_bufpost = (struct msgbuf_rx_ioctl_resp_or_event *)ret_ptr;
+		memset(rx_bufpost, 0, sizeof(*rx_bufpost));
+
+		skb = brcmu_pkt_buf_get_skb(BRCMF_MSGBUF_MAX_PKT_SIZE);
+
+		if (skb == NULL) {
+			brcmf_err("Failed to alloc SKB\n");
+			brcmf_commonring_write_cancel(commonring, alloced - i);
+			break;
+		}
+
+		pktlen = skb->len;
+		if (brcmf_msgbuf_alloc_pktid(msgbuf->drvr->bus_if->dev,
+					     msgbuf->rx_pktids, skb, 0,
+					     &physaddr, &pktid)) {
+			dev_kfree_skb_any(skb);
+			brcmf_err("No PKTID available !!\n");
+			brcmf_commonring_write_cancel(commonring, alloced - i);
+			break;
+		}
+		if (event_buf)
+			rx_bufpost->msg.msgtype = MSGBUF_TYPE_EVENT_BUF_POST;
+		else
+			rx_bufpost->msg.msgtype =
+				MSGBUF_TYPE_IOCTLRESP_BUF_POST;
+		rx_bufpost->msg.request_id = cpu_to_le32(pktid);
+
+		address = (u64)physaddr;
+		rx_bufpost->host_buf_len = cpu_to_le16((u16)pktlen);
+		rx_bufpost->host_buf_addr.high_addr =
+			cpu_to_le32(address >> 32);
+		rx_bufpost->host_buf_addr.low_addr =
+			cpu_to_le32(address & 0xffffffff);
+
+		ret_ptr += brcmf_commonring_len_item(commonring);
+	}
+
+	if (i)
+		brcmf_commonring_write_complete(commonring);
+
+	brcmf_commonring_unlock(commonring);
+
+	return i;
+}
+
+
+static void brcmf_msgbuf_rxbuf_ioctlresp_post(struct brcmf_msgbuf *msgbuf)
+{
+	u32 count;
+
+	count = msgbuf->max_ioctlrespbuf - msgbuf->cur_ioctlrespbuf;
+	count = brcmf_msgbuf_rxbuf_ctrl_post(msgbuf, false, count);
+	msgbuf->cur_ioctlrespbuf += count;
+}
+
+
+static void brcmf_msgbuf_rxbuf_event_post(struct brcmf_msgbuf *msgbuf)
+{
+	u32 count;
+
+	count = msgbuf->max_eventbuf - msgbuf->cur_eventbuf;
+	count = brcmf_msgbuf_rxbuf_ctrl_post(msgbuf, true, count);
+	msgbuf->cur_eventbuf += count;
+}
+
+
+static void brcmf_msgbuf_process_event(struct brcmf_msgbuf *msgbuf, void *buf)
+{
+	struct msgbuf_rx_event *event;
+	u32 idx;
+	u16 buflen;
+	struct sk_buff *skb;
+	struct brcmf_if *ifp;
+
+	event = (struct msgbuf_rx_event *)buf;
+	idx = le32_to_cpu(event->msg.request_id);
+	buflen = le16_to_cpu(event->event_data_len);
+
+	if (msgbuf->cur_eventbuf)
+		msgbuf->cur_eventbuf--;
+	brcmf_msgbuf_rxbuf_event_post(msgbuf);
+
+	skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
+				     msgbuf->rx_pktids, idx);
+	if (!skb)
+		return;
+
+	if (msgbuf->rx_dataoffset)
+		skb_pull(skb, msgbuf->rx_dataoffset);
+
+	skb_trim(skb, buflen);
+
+	ifp = brcmf_get_ifp(msgbuf->drvr, event->msg.ifidx);
+	if (!ifp || !ifp->ndev) {
+		brcmf_err("Received pkt for invalid ifidx %d\n",
+			  event->msg.ifidx);
+		goto exit;
+	}
+
+	skb->protocol = eth_type_trans(skb, ifp->ndev);
+
+	brcmf_fweh_process_skb(ifp->drvr, skb);
+
+exit:
+	brcmu_pkt_buf_free_skb(skb);
+}
+
+
+static void
+brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)
+{
+	struct msgbuf_rx_complete *rx_complete;
+	struct sk_buff *skb;
+	u16 data_offset;
+	u16 buflen;
+	u16 flags;
+	u32 idx;
+	struct brcmf_if *ifp;
+
+	brcmf_msgbuf_update_rxbufpost_count(msgbuf, 1);
+
+	rx_complete = (struct msgbuf_rx_complete *)buf;
+	data_offset = le16_to_cpu(rx_complete->data_offset);
+	buflen = le16_to_cpu(rx_complete->data_len);
+	idx = le32_to_cpu(rx_complete->msg.request_id);
+	flags = le16_to_cpu(rx_complete->flags);
+
+	skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
+				     msgbuf->rx_pktids, idx);
+	if (!skb)
+		return;
+
+	if (data_offset)
+		skb_pull(skb, data_offset);
+	else if (msgbuf->rx_dataoffset)
+		skb_pull(skb, msgbuf->rx_dataoffset);
+
+	skb_trim(skb, buflen);
+
+	if ((flags & BRCMF_MSGBUF_PKT_FLAGS_FRAME_MASK) ==
+	    BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_11) {
+		ifp = msgbuf->drvr->mon_if;
+
+		if (!ifp) {
+			brcmf_err("Received unexpected monitor pkt\n");
+			brcmu_pkt_buf_free_skb(skb);
+			return;
+		}
+
+		brcmf_netif_mon_rx(ifp, skb);
+		return;
+	}
+
+	ifp = brcmf_get_ifp(msgbuf->drvr, rx_complete->msg.ifidx);
+	if (!ifp || !ifp->ndev) {
+		brcmf_err("Received pkt for invalid ifidx %d\n",
+			  rx_complete->msg.ifidx);
+		brcmu_pkt_buf_free_skb(skb);
+		return;
+	}
+
+	skb->protocol = eth_type_trans(skb, ifp->ndev);
+	brcmf_netif_rx(ifp, skb);
+}
+
+
+static void
+brcmf_msgbuf_process_flow_ring_create_response(struct brcmf_msgbuf *msgbuf,
+					       void *buf)
+{
+	struct msgbuf_flowring_create_resp *flowring_create_resp;
+	u16 status;
+	u16 flowid;
+
+	flowring_create_resp = (struct msgbuf_flowring_create_resp *)buf;
+
+	flowid = le16_to_cpu(flowring_create_resp->compl_hdr.flow_ring_id);
+	flowid -= BRCMF_H2D_MSGRING_FLOWRING_IDSTART;
+	status =  le16_to_cpu(flowring_create_resp->compl_hdr.status);
+
+	if (status) {
+		brcmf_err("Flowring creation failed, code %d\n", status);
+		brcmf_msgbuf_remove_flowring(msgbuf, flowid);
+		return;
+	}
+	brcmf_dbg(MSGBUF, "Flowring %d Create response status %d\n", flowid,
+		  status);
+
+	brcmf_flowring_open(msgbuf->flow, flowid);
+
+	brcmf_msgbuf_schedule_txdata(msgbuf, flowid, true);
+}
+
+
+static void
+brcmf_msgbuf_process_flow_ring_delete_response(struct brcmf_msgbuf *msgbuf,
+					       void *buf)
+{
+	struct msgbuf_flowring_delete_resp *flowring_delete_resp;
+	u16 status;
+	u16 flowid;
+
+	flowring_delete_resp = (struct msgbuf_flowring_delete_resp *)buf;
+
+	flowid = le16_to_cpu(flowring_delete_resp->compl_hdr.flow_ring_id);
+	flowid -= BRCMF_H2D_MSGRING_FLOWRING_IDSTART;
+	status =  le16_to_cpu(flowring_delete_resp->compl_hdr.status);
+
+	if (status) {
+		brcmf_err("Flowring deletion failed, code %d\n", status);
+		brcmf_flowring_delete(msgbuf->flow, flowid);
+		return;
+	}
+	brcmf_dbg(MSGBUF, "Flowring %d Delete response status %d\n", flowid,
+		  status);
+
+	brcmf_msgbuf_remove_flowring(msgbuf, flowid);
+}
+
+
+static void brcmf_msgbuf_process_msgtype(struct brcmf_msgbuf *msgbuf, void *buf)
+{
+	struct msgbuf_common_hdr *msg;
+
+	msg = (struct msgbuf_common_hdr *)buf;
+	switch (msg->msgtype) {
+	case MSGBUF_TYPE_FLOW_RING_CREATE_CMPLT:
+		brcmf_dbg(MSGBUF, "MSGBUF_TYPE_FLOW_RING_CREATE_CMPLT\n");
+		brcmf_msgbuf_process_flow_ring_create_response(msgbuf, buf);
+		break;
+	case MSGBUF_TYPE_FLOW_RING_DELETE_CMPLT:
+		brcmf_dbg(MSGBUF, "MSGBUF_TYPE_FLOW_RING_DELETE_CMPLT\n");
+		brcmf_msgbuf_process_flow_ring_delete_response(msgbuf, buf);
+		break;
+	case MSGBUF_TYPE_IOCTLPTR_REQ_ACK:
+		brcmf_dbg(MSGBUF, "MSGBUF_TYPE_IOCTLPTR_REQ_ACK\n");
+		break;
+	case MSGBUF_TYPE_IOCTL_CMPLT:
+		brcmf_dbg(MSGBUF, "MSGBUF_TYPE_IOCTL_CMPLT\n");
+		brcmf_msgbuf_process_ioctl_complete(msgbuf, buf);
+		break;
+	case MSGBUF_TYPE_WL_EVENT:
+		brcmf_dbg(MSGBUF, "MSGBUF_TYPE_WL_EVENT\n");
+		brcmf_msgbuf_process_event(msgbuf, buf);
+		break;
+	case MSGBUF_TYPE_TX_STATUS:
+		brcmf_dbg(MSGBUF, "MSGBUF_TYPE_TX_STATUS\n");
+		brcmf_msgbuf_process_txstatus(msgbuf, buf);
+		break;
+	case MSGBUF_TYPE_RX_CMPLT:
+		brcmf_dbg(MSGBUF, "MSGBUF_TYPE_RX_CMPLT\n");
+		brcmf_msgbuf_process_rx_complete(msgbuf, buf);
+		break;
+	default:
+		brcmf_err("Unsupported msgtype %d\n", msg->msgtype);
+		break;
+	}
+}
+
+
+static void brcmf_msgbuf_process_rx(struct brcmf_msgbuf *msgbuf,
+				    struct brcmf_commonring *commonring)
+{
+	void *buf;
+	u16 count;
+	u16 processed;
+
+again:
+	buf = brcmf_commonring_get_read_ptr(commonring, &count);
+	if (buf == NULL)
+		return;
+
+	processed = 0;
+	while (count) {
+		brcmf_msgbuf_process_msgtype(msgbuf,
+					     buf + msgbuf->rx_dataoffset);
+		buf += brcmf_commonring_len_item(commonring);
+		processed++;
+		if (processed == BRCMF_MSGBUF_UPDATE_RX_PTR_THRS) {
+			brcmf_commonring_read_complete(commonring, processed);
+			processed = 0;
+		}
+		count--;
+	}
+	if (processed)
+		brcmf_commonring_read_complete(commonring, processed);
+
+	if (commonring->r_ptr == 0)
+		goto again;
+}
+
+
+int brcmf_proto_msgbuf_rx_trigger(struct device *dev)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_pub *drvr = bus_if->drvr;
+	struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+	struct brcmf_commonring *commonring;
+	void *buf;
+	u32 flowid;
+	int qlen;
+
+	buf = msgbuf->commonrings[BRCMF_D2H_MSGRING_RX_COMPLETE];
+	brcmf_msgbuf_process_rx(msgbuf, buf);
+	buf = msgbuf->commonrings[BRCMF_D2H_MSGRING_TX_COMPLETE];
+	brcmf_msgbuf_process_rx(msgbuf, buf);
+	buf = msgbuf->commonrings[BRCMF_D2H_MSGRING_CONTROL_COMPLETE];
+	brcmf_msgbuf_process_rx(msgbuf, buf);
+
+	for_each_set_bit(flowid, msgbuf->txstatus_done_map,
+			 msgbuf->max_flowrings) {
+		clear_bit(flowid, msgbuf->txstatus_done_map);
+		commonring = msgbuf->flowrings[flowid];
+		qlen = brcmf_flowring_qlen(msgbuf->flow, flowid);
+		if ((qlen > BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS) ||
+		    ((qlen) && (atomic_read(&commonring->outstanding_tx) <
+				BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS)))
+			brcmf_msgbuf_schedule_txdata(msgbuf, flowid, true);
+	}
+
+	return 0;
+}
+
+
+void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid)
+{
+	struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+	struct msgbuf_tx_flowring_delete_req *delete;
+	struct brcmf_commonring *commonring;
+	void *ret_ptr;
+	u8 ifidx;
+	int err;
+
+	commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT];
+	brcmf_commonring_lock(commonring);
+	ret_ptr = brcmf_commonring_reserve_for_write(commonring);
+	if (!ret_ptr) {
+		brcmf_err("FW unaware, flowring will be removed !!\n");
+		brcmf_commonring_unlock(commonring);
+		brcmf_msgbuf_remove_flowring(msgbuf, flowid);
+		return;
+	}
+
+	delete = (struct msgbuf_tx_flowring_delete_req *)ret_ptr;
+
+	ifidx = brcmf_flowring_ifidx_get(msgbuf->flow, flowid);
+
+	delete->msg.msgtype = MSGBUF_TYPE_FLOW_RING_DELETE;
+	delete->msg.ifidx = ifidx;
+	delete->msg.request_id = 0;
+
+	delete->flow_ring_id = cpu_to_le16(flowid +
+					   BRCMF_H2D_MSGRING_FLOWRING_IDSTART);
+	delete->reason = 0;
+
+	brcmf_dbg(MSGBUF, "Send Flow Delete Req flow ID %d, ifindex %d\n",
+		  flowid, ifidx);
+
+	err = brcmf_commonring_write_complete(commonring);
+	brcmf_commonring_unlock(commonring);
+	if (err) {
+		brcmf_err("Failed to submit RING_DELETE, flowring will be removed\n");
+		brcmf_msgbuf_remove_flowring(msgbuf, flowid);
+	}
+}
+
+#ifdef DEBUG
+static int brcmf_msgbuf_stats_read(struct seq_file *seq, void *data)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
+	struct brcmf_pub *drvr = bus_if->drvr;
+	struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+	struct brcmf_commonring *commonring;
+	u16 i;
+	struct brcmf_flowring_ring *ring;
+	struct brcmf_flowring_hash *hash;
+
+	commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT];
+	seq_printf(seq, "h2d_ctl_submit: rp %4u, wp %4u, depth %4u\n",
+		   commonring->r_ptr, commonring->w_ptr, commonring->depth);
+	commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_RXPOST_SUBMIT];
+	seq_printf(seq, "h2d_rx_submit:  rp %4u, wp %4u, depth %4u\n",
+		   commonring->r_ptr, commonring->w_ptr, commonring->depth);
+	commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_CONTROL_COMPLETE];
+	seq_printf(seq, "d2h_ctl_cmplt:  rp %4u, wp %4u, depth %4u\n",
+		   commonring->r_ptr, commonring->w_ptr, commonring->depth);
+	commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_TX_COMPLETE];
+	seq_printf(seq, "d2h_tx_cmplt:   rp %4u, wp %4u, depth %4u\n",
+		   commonring->r_ptr, commonring->w_ptr, commonring->depth);
+	commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_RX_COMPLETE];
+	seq_printf(seq, "d2h_rx_cmplt:   rp %4u, wp %4u, depth %4u\n",
+		   commonring->r_ptr, commonring->w_ptr, commonring->depth);
+
+	seq_printf(seq, "\nh2d_flowrings: depth %u\n",
+		   BRCMF_H2D_TXFLOWRING_MAX_ITEM);
+	seq_puts(seq, "Active flowrings:\n");
+	hash = msgbuf->flow->hash;
+	for (i = 0; i < msgbuf->flow->nrofrings; i++) {
+		if (!msgbuf->flow->rings[i])
+			continue;
+		ring = msgbuf->flow->rings[i];
+		if (ring->status != RING_OPEN)
+			continue;
+		commonring = msgbuf->flowrings[i];
+		hash = &msgbuf->flow->hash[ring->hash_id];
+		seq_printf(seq, "id %3u: rp %4u, wp %4u, qlen %4u, blocked %u\n"
+				"        ifidx %u, fifo %u, da %pM\n",
+				i, commonring->r_ptr, commonring->w_ptr,
+				skb_queue_len(&ring->skblist), ring->blocked,
+				hash->ifidx, hash->fifo, hash->mac);
+	}
+
+	return 0;
+}
+#else
+static int brcmf_msgbuf_stats_read(struct seq_file *seq, void *data)
+{
+	return 0;
+}
+#endif
+
+static void brcmf_msgbuf_debugfs_create(struct brcmf_pub *drvr)
+{
+	brcmf_debugfs_add_entry(drvr, "msgbuf_stats", brcmf_msgbuf_stats_read);
+}
+
+int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
+{
+	struct brcmf_bus_msgbuf *if_msgbuf;
+	struct brcmf_msgbuf *msgbuf;
+	u64 address;
+	u32 count;
+
+	if_msgbuf = drvr->bus_if->msgbuf;
+
+	if (if_msgbuf->max_flowrings >= BRCMF_FLOWRING_HASHSIZE) {
+		brcmf_err("driver not configured for this many flowrings %d\n",
+			  if_msgbuf->max_flowrings);
+		if_msgbuf->max_flowrings = BRCMF_FLOWRING_HASHSIZE - 1;
+	}
+
+	msgbuf = kzalloc(sizeof(*msgbuf), GFP_KERNEL);
+	if (!msgbuf)
+		goto fail;
+
+	msgbuf->txflow_wq = create_singlethread_workqueue("msgbuf_txflow");
+	if (msgbuf->txflow_wq == NULL) {
+		brcmf_err("workqueue creation failed\n");
+		goto fail;
+	}
+	INIT_WORK(&msgbuf->txflow_work, brcmf_msgbuf_txflow_worker);
+	count = BITS_TO_LONGS(if_msgbuf->max_flowrings);
+	count = count * sizeof(unsigned long);
+	msgbuf->flow_map = kzalloc(count, GFP_KERNEL);
+	if (!msgbuf->flow_map)
+		goto fail;
+
+	msgbuf->txstatus_done_map = kzalloc(count, GFP_KERNEL);
+	if (!msgbuf->txstatus_done_map)
+		goto fail;
+
+	msgbuf->drvr = drvr;
+	msgbuf->ioctbuf = dma_alloc_coherent(drvr->bus_if->dev,
+					     BRCMF_TX_IOCTL_MAX_MSG_SIZE,
+					     &msgbuf->ioctbuf_handle,
+					     GFP_KERNEL);
+	if (!msgbuf->ioctbuf)
+		goto fail;
+	address = (u64)msgbuf->ioctbuf_handle;
+	msgbuf->ioctbuf_phys_hi = address >> 32;
+	msgbuf->ioctbuf_phys_lo = address & 0xffffffff;
+
+	drvr->proto->hdrpull = brcmf_msgbuf_hdrpull;
+	drvr->proto->query_dcmd = brcmf_msgbuf_query_dcmd;
+	drvr->proto->set_dcmd = brcmf_msgbuf_set_dcmd;
+	drvr->proto->tx_queue_data = brcmf_msgbuf_tx_queue_data;
+	drvr->proto->configure_addr_mode = brcmf_msgbuf_configure_addr_mode;
+	drvr->proto->delete_peer = brcmf_msgbuf_delete_peer;
+	drvr->proto->add_tdls_peer = brcmf_msgbuf_add_tdls_peer;
+	drvr->proto->rxreorder = brcmf_msgbuf_rxreorder;
+	drvr->proto->debugfs_create = brcmf_msgbuf_debugfs_create;
+	drvr->proto->pd = msgbuf;
+
+	init_waitqueue_head(&msgbuf->ioctl_resp_wait);
+
+	msgbuf->commonrings =
+		(struct brcmf_commonring **)if_msgbuf->commonrings;
+	msgbuf->flowrings = (struct brcmf_commonring **)if_msgbuf->flowrings;
+	msgbuf->max_flowrings = if_msgbuf->max_flowrings;
+	msgbuf->flowring_dma_handle =
+		kcalloc(msgbuf->max_flowrings,
+			sizeof(*msgbuf->flowring_dma_handle), GFP_KERNEL);
+	if (!msgbuf->flowring_dma_handle)
+		goto fail;
+
+	msgbuf->rx_dataoffset = if_msgbuf->rx_dataoffset;
+	msgbuf->max_rxbufpost = if_msgbuf->max_rxbufpost;
+
+	msgbuf->max_ioctlrespbuf = BRCMF_MSGBUF_MAX_IOCTLRESPBUF_POST;
+	msgbuf->max_eventbuf = BRCMF_MSGBUF_MAX_EVENTBUF_POST;
+
+	msgbuf->tx_pktids = brcmf_msgbuf_init_pktids(NR_TX_PKTIDS,
+						     DMA_TO_DEVICE);
+	if (!msgbuf->tx_pktids)
+		goto fail;
+	msgbuf->rx_pktids = brcmf_msgbuf_init_pktids(NR_RX_PKTIDS,
+						     DMA_FROM_DEVICE);
+	if (!msgbuf->rx_pktids)
+		goto fail;
+
+	msgbuf->flow = brcmf_flowring_attach(drvr->bus_if->dev,
+					     if_msgbuf->max_flowrings);
+	if (!msgbuf->flow)
+		goto fail;
+
+
+	brcmf_dbg(MSGBUF, "Feeding buffers, rx data %d, rx event %d, rx ioctl resp %d\n",
+		  msgbuf->max_rxbufpost, msgbuf->max_eventbuf,
+		  msgbuf->max_ioctlrespbuf);
+	count = 0;
+	do {
+		brcmf_msgbuf_rxbuf_data_fill(msgbuf);
+		if (msgbuf->max_rxbufpost != msgbuf->rxbufpost)
+			msleep(10);
+		else
+			break;
+		count++;
+	} while (count < 10);
+	brcmf_msgbuf_rxbuf_event_post(msgbuf);
+	brcmf_msgbuf_rxbuf_ioctlresp_post(msgbuf);
+
+	INIT_WORK(&msgbuf->flowring_work, brcmf_msgbuf_flowring_worker);
+	spin_lock_init(&msgbuf->flowring_work_lock);
+	INIT_LIST_HEAD(&msgbuf->work_queue);
+
+	return 0;
+
+fail:
+	if (msgbuf) {
+		kfree(msgbuf->flow_map);
+		kfree(msgbuf->txstatus_done_map);
+		brcmf_msgbuf_release_pktids(msgbuf);
+		kfree(msgbuf->flowring_dma_handle);
+		if (msgbuf->ioctbuf)
+			dma_free_coherent(drvr->bus_if->dev,
+					  BRCMF_TX_IOCTL_MAX_MSG_SIZE,
+					  msgbuf->ioctbuf,
+					  msgbuf->ioctbuf_handle);
+		kfree(msgbuf);
+	}
+	return -ENOMEM;
+}
+
+
+void brcmf_proto_msgbuf_detach(struct brcmf_pub *drvr)
+{
+	struct brcmf_msgbuf *msgbuf;
+	struct brcmf_msgbuf_work_item *work;
+
+	brcmf_dbg(TRACE, "Enter\n");
+	if (drvr->proto->pd) {
+		msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+		cancel_work_sync(&msgbuf->flowring_work);
+		while (!list_empty(&msgbuf->work_queue)) {
+			work = list_first_entry(&msgbuf->work_queue,
+						struct brcmf_msgbuf_work_item,
+						queue);
+			list_del(&work->queue);
+			kfree(work);
+		}
+		kfree(msgbuf->flow_map);
+		kfree(msgbuf->txstatus_done_map);
+		if (msgbuf->txflow_wq)
+			destroy_workqueue(msgbuf->txflow_wq);
+
+		brcmf_flowring_detach(msgbuf->flow);
+		dma_free_coherent(drvr->bus_if->dev,
+				  BRCMF_TX_IOCTL_MAX_MSG_SIZE,
+				  msgbuf->ioctbuf, msgbuf->ioctbuf_handle);
+		brcmf_msgbuf_release_pktids(msgbuf);
+		kfree(msgbuf->flowring_dma_handle);
+		kfree(msgbuf);
+		drvr->proto->pd = NULL;
+	}
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
new file mode 100644
index 0000000..692235d
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
@@ -0,0 +1,53 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef BRCMFMAC_MSGBUF_H
+#define BRCMFMAC_MSGBUF_H
+
+#ifdef CONFIG_BRCMFMAC_PROTO_MSGBUF
+
+#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM	64
+#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM	512
+#define BRCMF_D2H_MSGRING_CONTROL_COMPLETE_MAX_ITEM	64
+#define BRCMF_D2H_MSGRING_TX_COMPLETE_MAX_ITEM		1024
+#define BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM		512
+#define BRCMF_H2D_TXFLOWRING_MAX_ITEM			512
+
+#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_ITEMSIZE	40
+#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_ITEMSIZE	32
+#define BRCMF_D2H_MSGRING_CONTROL_COMPLETE_ITEMSIZE	24
+#define BRCMF_D2H_MSGRING_TX_COMPLETE_ITEMSIZE_PRE_V7	16
+#define BRCMF_D2H_MSGRING_TX_COMPLETE_ITEMSIZE		24
+#define BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE_PRE_V7	32
+#define BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE		40
+#define BRCMF_H2D_TXFLOWRING_ITEMSIZE			48
+
+struct msgbuf_buf_addr {
+	__le32		low_addr;
+	__le32		high_addr;
+};
+
+int brcmf_proto_msgbuf_rx_trigger(struct device *dev);
+void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid);
+int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr);
+void brcmf_proto_msgbuf_detach(struct brcmf_pub *drvr);
+#else
+static inline int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
+{
+	return 0;
+}
+static inline void brcmf_proto_msgbuf_detach(struct brcmf_pub *drvr) {}
+#endif
+
+#endif /* BRCMFMAC_MSGBUF_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
new file mode 100644
index 0000000..aee6e59
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+
+#include <defs.h>
+#include "debug.h"
+#include "core.h"
+#include "common.h"
+#include "of.h"
+
+void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
+		    struct brcmf_mp_device *settings)
+{
+	struct brcmfmac_sdio_pd *sdio = &settings->bus.sdio;
+	struct device_node *np = dev->of_node;
+	int irq;
+	u32 irqf;
+	u32 val;
+
+	if (!np || bus_type != BRCMF_BUSTYPE_SDIO ||
+	    !of_device_is_compatible(np, "brcm,bcm4329-fmac"))
+		return;
+
+	if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0)
+		sdio->drive_strength = val;
+
+	/* make sure there are interrupts defined in the node */
+	if (!of_find_property(np, "interrupts", NULL))
+		return;
+
+	irq = irq_of_parse_and_map(np, 0);
+	if (!irq) {
+		brcmf_err("interrupt could not be mapped\n");
+		return;
+	}
+	irqf = irqd_get_trigger_type(irq_get_irq_data(irq));
+
+	sdio->oob_irq_supported = true;
+	sdio->oob_irq_nr = irq;
+	sdio->oob_irq_flags = irqf;
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
new file mode 100644
index 0000000..95b7032
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifdef CONFIG_OF
+void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
+		    struct brcmf_mp_device *settings);
+#else
+static void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
+			   struct brcmf_mp_device *settings)
+{
+}
+#endif /* CONFIG_OF */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
new file mode 100644
index 0000000..3e9c4f2
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
@@ -0,0 +1,2405 @@
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/rtnetlink.h>
+#include <net/cfg80211.h>
+
+#include <brcmu_wifi.h>
+#include <brcmu_utils.h>
+#include <defs.h>
+#include "core.h"
+#include "debug.h"
+#include "fwil.h"
+#include "fwil_types.h"
+#include "p2p.h"
+#include "cfg80211.h"
+
+/* parameters used for p2p escan */
+#define P2PAPI_SCAN_NPROBES 1
+#define P2PAPI_SCAN_DWELL_TIME_MS 80
+#define P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS 40
+#define P2PAPI_SCAN_HOME_TIME_MS 60
+#define P2PAPI_SCAN_NPROBS_TIME_MS 30
+#define P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS 100
+#define WL_SCAN_CONNECT_DWELL_TIME_MS 200
+#define WL_SCAN_JOIN_PROBE_INTERVAL_MS 20
+
+#define BRCMF_P2P_WILDCARD_SSID		"DIRECT-"
+#define BRCMF_P2P_WILDCARD_SSID_LEN	(sizeof(BRCMF_P2P_WILDCARD_SSID) - 1)
+
+#define SOCIAL_CHAN_1		1
+#define SOCIAL_CHAN_2		6
+#define SOCIAL_CHAN_3		11
+#define IS_P2P_SOCIAL_CHANNEL(channel) ((channel == SOCIAL_CHAN_1) || \
+					 (channel == SOCIAL_CHAN_2) || \
+					 (channel == SOCIAL_CHAN_3))
+#define BRCMF_P2P_TEMP_CHAN	SOCIAL_CHAN_3
+#define SOCIAL_CHAN_CNT		3
+#define AF_PEER_SEARCH_CNT	2
+
+#define BRCMF_SCB_TIMEOUT_VALUE	20
+
+#define P2P_VER			9	/* P2P version: 9=WiFi P2P v1.0 */
+#define P2P_PUB_AF_CATEGORY	0x04
+#define P2P_PUB_AF_ACTION	0x09
+#define P2P_AF_CATEGORY		0x7f
+#define P2P_OUI			"\x50\x6F\x9A"	/* P2P OUI */
+#define P2P_OUI_LEN		3		/* P2P OUI length */
+
+/* Action Frame Constants */
+#define DOT11_ACTION_HDR_LEN	2	/* action frame category + action */
+#define DOT11_ACTION_CAT_OFF	0	/* category offset */
+#define DOT11_ACTION_ACT_OFF	1	/* action offset */
+
+#define P2P_AF_DWELL_TIME		200
+#define P2P_AF_MIN_DWELL_TIME		100
+#define P2P_AF_MED_DWELL_TIME		400
+#define P2P_AF_LONG_DWELL_TIME		1000
+#define P2P_AF_TX_MAX_RETRY		1
+#define P2P_AF_MAX_WAIT_TIME		msecs_to_jiffies(2000)
+#define P2P_INVALID_CHANNEL		-1
+#define P2P_CHANNEL_SYNC_RETRY		5
+#define P2P_AF_FRM_SCAN_MAX_WAIT	msecs_to_jiffies(1500)
+#define P2P_DEFAULT_SLEEP_TIME_VSDB	200
+
+/* WiFi P2P Public Action Frame OUI Subtypes */
+#define P2P_PAF_GON_REQ		0	/* Group Owner Negotiation Req */
+#define P2P_PAF_GON_RSP		1	/* Group Owner Negotiation Rsp */
+#define P2P_PAF_GON_CONF	2	/* Group Owner Negotiation Confirm */
+#define P2P_PAF_INVITE_REQ	3	/* P2P Invitation Request */
+#define P2P_PAF_INVITE_RSP	4	/* P2P Invitation Response */
+#define P2P_PAF_DEVDIS_REQ	5	/* Device Discoverability Request */
+#define P2P_PAF_DEVDIS_RSP	6	/* Device Discoverability Response */
+#define P2P_PAF_PROVDIS_REQ	7	/* Provision Discovery Request */
+#define P2P_PAF_PROVDIS_RSP	8	/* Provision Discovery Response */
+#define P2P_PAF_SUBTYPE_INVALID	255	/* Invalid Subtype */
+
+/* WiFi P2P Action Frame OUI Subtypes */
+#define P2P_AF_NOTICE_OF_ABSENCE	0	/* Notice of Absence */
+#define P2P_AF_PRESENCE_REQ		1	/* P2P Presence Request */
+#define P2P_AF_PRESENCE_RSP		2	/* P2P Presence Response */
+#define P2P_AF_GO_DISC_REQ		3	/* GO Discoverability Request */
+
+/* P2P Service Discovery related */
+#define P2PSD_ACTION_CATEGORY		0x04	/* Public action frame */
+#define P2PSD_ACTION_ID_GAS_IREQ	0x0a	/* GAS Initial Request AF */
+#define P2PSD_ACTION_ID_GAS_IRESP	0x0b	/* GAS Initial Response AF */
+#define P2PSD_ACTION_ID_GAS_CREQ	0x0c	/* GAS Comback Request AF */
+#define P2PSD_ACTION_ID_GAS_CRESP	0x0d	/* GAS Comback Response AF */
+
+#define BRCMF_P2P_DISABLE_TIMEOUT	msecs_to_jiffies(500)
+/**
+ * struct brcmf_p2p_disc_st_le - set discovery state in firmware.
+ *
+ * @state: requested discovery state (see enum brcmf_p2p_disc_state).
+ * @chspec: channel parameter for %WL_P2P_DISC_ST_LISTEN state.
+ * @dwell: dwell time in ms for %WL_P2P_DISC_ST_LISTEN state.
+ */
+struct brcmf_p2p_disc_st_le {
+	u8 state;
+	__le16 chspec;
+	__le16 dwell;
+};
+
+/**
+ * enum brcmf_p2p_disc_state - P2P discovery state values
+ *
+ * @WL_P2P_DISC_ST_SCAN: P2P discovery with wildcard SSID and P2P IE.
+ * @WL_P2P_DISC_ST_LISTEN: P2P discovery off-channel for specified time.
+ * @WL_P2P_DISC_ST_SEARCH: P2P discovery with P2P wildcard SSID and P2P IE.
+ */
+enum brcmf_p2p_disc_state {
+	WL_P2P_DISC_ST_SCAN,
+	WL_P2P_DISC_ST_LISTEN,
+	WL_P2P_DISC_ST_SEARCH
+};
+
+/**
+ * struct brcmf_p2p_scan_le - P2P specific scan request.
+ *
+ * @type: type of scan method requested (values: 'E' or 'S').
+ * @reserved: reserved (ignored).
+ * @eparams: parameters used for type 'E'.
+ * @sparams: parameters used for type 'S'.
+ */
+struct brcmf_p2p_scan_le {
+	u8 type;
+	u8 reserved[3];
+	union {
+		struct brcmf_escan_params_le eparams;
+		struct brcmf_scan_params_le sparams;
+	};
+};
+
+/**
+ * struct brcmf_p2p_pub_act_frame - WiFi P2P Public Action Frame
+ *
+ * @category: P2P_PUB_AF_CATEGORY
+ * @action: P2P_PUB_AF_ACTION
+ * @oui[3]: P2P_OUI
+ * @oui_type: OUI type - P2P_VER
+ * @subtype: OUI subtype - P2P_TYPE_*
+ * @dialog_token: nonzero, identifies req/rsp transaction
+ * @elts[1]: Variable length information elements.
+ */
+struct brcmf_p2p_pub_act_frame {
+	u8	category;
+	u8	action;
+	u8	oui[3];
+	u8	oui_type;
+	u8	subtype;
+	u8	dialog_token;
+	u8	elts[1];
+};
+
+/**
+ * struct brcmf_p2p_action_frame - WiFi P2P Action Frame
+ *
+ * @category: P2P_AF_CATEGORY
+ * @OUI[3]: OUI - P2P_OUI
+ * @type: OUI Type - P2P_VER
+ * @subtype: OUI Subtype - P2P_AF_*
+ * @dialog_token: nonzero, identifies req/resp tranaction
+ * @elts[1]: Variable length information elements.
+ */
+struct brcmf_p2p_action_frame {
+	u8	category;
+	u8	oui[3];
+	u8	type;
+	u8	subtype;
+	u8	dialog_token;
+	u8	elts[1];
+};
+
+/**
+ * struct brcmf_p2psd_gas_pub_act_frame - Wi-Fi GAS Public Action Frame
+ *
+ * @category: 0x04 Public Action Frame
+ * @action: 0x6c Advertisement Protocol
+ * @dialog_token: nonzero, identifies req/rsp transaction
+ * @query_data[1]: Query Data. SD gas ireq SD gas iresp
+ */
+struct brcmf_p2psd_gas_pub_act_frame {
+	u8	category;
+	u8	action;
+	u8	dialog_token;
+	u8	query_data[1];
+};
+
+/**
+ * struct brcmf_config_af_params - Action Frame Parameters for tx.
+ *
+ * @mpc_onoff: To make sure to send successfully action frame, we have to
+ *             turn off mpc  0: off, 1: on,  (-1): do nothing
+ * @search_channel: 1: search peer's channel to send af
+ * extra_listen: keep the dwell time to get af response frame.
+ */
+struct brcmf_config_af_params {
+	s32 mpc_onoff;
+	bool search_channel;
+	bool extra_listen;
+};
+
+/**
+ * brcmf_p2p_is_pub_action() - true if p2p public type frame.
+ *
+ * @frame: action frame data.
+ * @frame_len: length of action frame data.
+ *
+ * Determine if action frame is p2p public action type
+ */
+static bool brcmf_p2p_is_pub_action(void *frame, u32 frame_len)
+{
+	struct brcmf_p2p_pub_act_frame *pact_frm;
+
+	if (frame == NULL)
+		return false;
+
+	pact_frm = (struct brcmf_p2p_pub_act_frame *)frame;
+	if (frame_len < sizeof(struct brcmf_p2p_pub_act_frame) - 1)
+		return false;
+
+	if (pact_frm->category == P2P_PUB_AF_CATEGORY &&
+	    pact_frm->action == P2P_PUB_AF_ACTION &&
+	    pact_frm->oui_type == P2P_VER &&
+	    memcmp(pact_frm->oui, P2P_OUI, P2P_OUI_LEN) == 0)
+		return true;
+
+	return false;
+}
+
+/**
+ * brcmf_p2p_is_p2p_action() - true if p2p action type frame.
+ *
+ * @frame: action frame data.
+ * @frame_len: length of action frame data.
+ *
+ * Determine if action frame is p2p action type
+ */
+static bool brcmf_p2p_is_p2p_action(void *frame, u32 frame_len)
+{
+	struct brcmf_p2p_action_frame *act_frm;
+
+	if (frame == NULL)
+		return false;
+
+	act_frm = (struct brcmf_p2p_action_frame *)frame;
+	if (frame_len < sizeof(struct brcmf_p2p_action_frame) - 1)
+		return false;
+
+	if (act_frm->category == P2P_AF_CATEGORY &&
+	    act_frm->type  == P2P_VER &&
+	    memcmp(act_frm->oui, P2P_OUI, P2P_OUI_LEN) == 0)
+		return true;
+
+	return false;
+}
+
+/**
+ * brcmf_p2p_is_gas_action() - true if p2p gas action type frame.
+ *
+ * @frame: action frame data.
+ * @frame_len: length of action frame data.
+ *
+ * Determine if action frame is p2p gas action type
+ */
+static bool brcmf_p2p_is_gas_action(void *frame, u32 frame_len)
+{
+	struct brcmf_p2psd_gas_pub_act_frame *sd_act_frm;
+
+	if (frame == NULL)
+		return false;
+
+	sd_act_frm = (struct brcmf_p2psd_gas_pub_act_frame *)frame;
+	if (frame_len < sizeof(struct brcmf_p2psd_gas_pub_act_frame) - 1)
+		return false;
+
+	if (sd_act_frm->category != P2PSD_ACTION_CATEGORY)
+		return false;
+
+	if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_IREQ ||
+	    sd_act_frm->action == P2PSD_ACTION_ID_GAS_IRESP ||
+	    sd_act_frm->action == P2PSD_ACTION_ID_GAS_CREQ ||
+	    sd_act_frm->action == P2PSD_ACTION_ID_GAS_CRESP)
+		return true;
+
+	return false;
+}
+
+/**
+ * brcmf_p2p_print_actframe() - debug print routine.
+ *
+ * @tx: Received or to be transmitted
+ * @frame: action frame data.
+ * @frame_len: length of action frame data.
+ *
+ * Print information about the p2p action frame
+ */
+
+#ifdef DEBUG
+
+static void brcmf_p2p_print_actframe(bool tx, void *frame, u32 frame_len)
+{
+	struct brcmf_p2p_pub_act_frame *pact_frm;
+	struct brcmf_p2p_action_frame *act_frm;
+	struct brcmf_p2psd_gas_pub_act_frame *sd_act_frm;
+
+	if (!frame || frame_len <= 2)
+		return;
+
+	if (brcmf_p2p_is_pub_action(frame, frame_len)) {
+		pact_frm = (struct brcmf_p2p_pub_act_frame *)frame;
+		switch (pact_frm->subtype) {
+		case P2P_PAF_GON_REQ:
+			brcmf_dbg(TRACE, "%s P2P Group Owner Negotiation Req Frame\n",
+				  (tx) ? "TX" : "RX");
+			break;
+		case P2P_PAF_GON_RSP:
+			brcmf_dbg(TRACE, "%s P2P Group Owner Negotiation Rsp Frame\n",
+				  (tx) ? "TX" : "RX");
+			break;
+		case P2P_PAF_GON_CONF:
+			brcmf_dbg(TRACE, "%s P2P Group Owner Negotiation Confirm Frame\n",
+				  (tx) ? "TX" : "RX");
+			break;
+		case P2P_PAF_INVITE_REQ:
+			brcmf_dbg(TRACE, "%s P2P Invitation Request  Frame\n",
+				  (tx) ? "TX" : "RX");
+			break;
+		case P2P_PAF_INVITE_RSP:
+			brcmf_dbg(TRACE, "%s P2P Invitation Response Frame\n",
+				  (tx) ? "TX" : "RX");
+			break;
+		case P2P_PAF_DEVDIS_REQ:
+			brcmf_dbg(TRACE, "%s P2P Device Discoverability Request Frame\n",
+				  (tx) ? "TX" : "RX");
+			break;
+		case P2P_PAF_DEVDIS_RSP:
+			brcmf_dbg(TRACE, "%s P2P Device Discoverability Response Frame\n",
+				  (tx) ? "TX" : "RX");
+			break;
+		case P2P_PAF_PROVDIS_REQ:
+			brcmf_dbg(TRACE, "%s P2P Provision Discovery Request Frame\n",
+				  (tx) ? "TX" : "RX");
+			break;
+		case P2P_PAF_PROVDIS_RSP:
+			brcmf_dbg(TRACE, "%s P2P Provision Discovery Response Frame\n",
+				  (tx) ? "TX" : "RX");
+			break;
+		default:
+			brcmf_dbg(TRACE, "%s Unknown P2P Public Action Frame\n",
+				  (tx) ? "TX" : "RX");
+			break;
+		}
+	} else if (brcmf_p2p_is_p2p_action(frame, frame_len)) {
+		act_frm = (struct brcmf_p2p_action_frame *)frame;
+		switch (act_frm->subtype) {
+		case P2P_AF_NOTICE_OF_ABSENCE:
+			brcmf_dbg(TRACE, "%s P2P Notice of Absence Frame\n",
+				  (tx) ? "TX" : "RX");
+			break;
+		case P2P_AF_PRESENCE_REQ:
+			brcmf_dbg(TRACE, "%s P2P Presence Request Frame\n",
+				  (tx) ? "TX" : "RX");
+			break;
+		case P2P_AF_PRESENCE_RSP:
+			brcmf_dbg(TRACE, "%s P2P Presence Response Frame\n",
+				  (tx) ? "TX" : "RX");
+			break;
+		case P2P_AF_GO_DISC_REQ:
+			brcmf_dbg(TRACE, "%s P2P Discoverability Request Frame\n",
+				  (tx) ? "TX" : "RX");
+			break;
+		default:
+			brcmf_dbg(TRACE, "%s Unknown P2P Action Frame\n",
+				  (tx) ? "TX" : "RX");
+		}
+
+	} else if (brcmf_p2p_is_gas_action(frame, frame_len)) {
+		sd_act_frm = (struct brcmf_p2psd_gas_pub_act_frame *)frame;
+		switch (sd_act_frm->action) {
+		case P2PSD_ACTION_ID_GAS_IREQ:
+			brcmf_dbg(TRACE, "%s P2P GAS Initial Request\n",
+				  (tx) ? "TX" : "RX");
+			break;
+		case P2PSD_ACTION_ID_GAS_IRESP:
+			brcmf_dbg(TRACE, "%s P2P GAS Initial Response\n",
+				  (tx) ? "TX" : "RX");
+			break;
+		case P2PSD_ACTION_ID_GAS_CREQ:
+			brcmf_dbg(TRACE, "%s P2P GAS Comback Request\n",
+				  (tx) ? "TX" : "RX");
+			break;
+		case P2PSD_ACTION_ID_GAS_CRESP:
+			brcmf_dbg(TRACE, "%s P2P GAS Comback Response\n",
+				  (tx) ? "TX" : "RX");
+			break;
+		default:
+			brcmf_dbg(TRACE, "%s Unknown P2P GAS Frame\n",
+				  (tx) ? "TX" : "RX");
+			break;
+		}
+	}
+}
+
+#else
+
+static void brcmf_p2p_print_actframe(bool tx, void *frame, u32 frame_len)
+{
+}
+
+#endif
+
+
+/**
+ * brcmf_p2p_set_firmware() - prepare firmware for peer-to-peer operation.
+ *
+ * @ifp: ifp to use for iovars (primary).
+ * @p2p_mac: mac address to configure for p2p_da_override
+ */
+static int brcmf_p2p_set_firmware(struct brcmf_if *ifp, u8 *p2p_mac)
+{
+	s32 ret = 0;
+
+	brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
+	brcmf_fil_iovar_int_set(ifp, "apsta", 1);
+	brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
+
+	/* In case of COB type, firmware has default mac address
+	 * After Initializing firmware, we have to set current mac address to
+	 * firmware for P2P device address. This must be done with discovery
+	 * disabled.
+	 */
+	brcmf_fil_iovar_int_set(ifp, "p2p_disc", 0);
+
+	ret = brcmf_fil_iovar_data_set(ifp, "p2p_da_override", p2p_mac,
+				       ETH_ALEN);
+	if (ret)
+		brcmf_err("failed to update device address ret %d\n", ret);
+
+	return ret;
+}
+
+/**
+ * brcmf_p2p_generate_bss_mac() - derive mac addresses for P2P.
+ *
+ * @p2p: P2P specific data.
+ * @dev_addr: optional device address.
+ *
+ * P2P needs mac addresses for P2P device and interface. If no device
+ * address it specified, these are derived from a random ethernet
+ * address.
+ */
+static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p, u8 *dev_addr)
+{
+	bool random_addr = false;
+
+	if (!dev_addr || is_zero_ether_addr(dev_addr))
+		random_addr = true;
+
+	/* Generate the P2P Device Address obtaining a random ethernet
+	 * address with the locally administered bit set.
+	 */
+	if (random_addr)
+		eth_random_addr(p2p->dev_addr);
+	else
+		memcpy(p2p->dev_addr, dev_addr, ETH_ALEN);
+
+	/* Generate the P2P Interface Address.  If the discovery and connection
+	 * BSSCFGs need to simultaneously co-exist, then this address must be
+	 * different from the P2P Device Address, but also locally administered.
+	 */
+	memcpy(p2p->int_addr, p2p->dev_addr, ETH_ALEN);
+	p2p->int_addr[0] |= 0x02;
+	p2p->int_addr[4] ^= 0x80;
+}
+
+/**
+ * brcmf_p2p_scan_is_p2p_request() - is cfg80211 scan request a P2P scan.
+ *
+ * @request: the scan request as received from cfg80211.
+ *
+ * returns true if one of the ssids in the request matches the
+ * P2P wildcard ssid; otherwise returns false.
+ */
+static bool brcmf_p2p_scan_is_p2p_request(struct cfg80211_scan_request *request)
+{
+	struct cfg80211_ssid *ssids = request->ssids;
+	int i;
+
+	for (i = 0; i < request->n_ssids; i++) {
+		if (ssids[i].ssid_len != BRCMF_P2P_WILDCARD_SSID_LEN)
+			continue;
+
+		brcmf_dbg(INFO, "comparing ssid \"%s\"", ssids[i].ssid);
+		if (!memcmp(BRCMF_P2P_WILDCARD_SSID, ssids[i].ssid,
+			    BRCMF_P2P_WILDCARD_SSID_LEN))
+			return true;
+	}
+	return false;
+}
+
+/**
+ * brcmf_p2p_set_discover_state - set discover state in firmware.
+ *
+ * @ifp: low-level interface object.
+ * @state: discover state to set.
+ * @chanspec: channel parameters (for state @WL_P2P_DISC_ST_LISTEN only).
+ * @listen_ms: duration to listen (for state @WL_P2P_DISC_ST_LISTEN only).
+ */
+static s32 brcmf_p2p_set_discover_state(struct brcmf_if *ifp, u8 state,
+					u16 chanspec, u16 listen_ms)
+{
+	struct brcmf_p2p_disc_st_le discover_state;
+	s32 ret = 0;
+	brcmf_dbg(TRACE, "enter\n");
+
+	discover_state.state = state;
+	discover_state.chspec = cpu_to_le16(chanspec);
+	discover_state.dwell = cpu_to_le16(listen_ms);
+	ret = brcmf_fil_bsscfg_data_set(ifp, "p2p_state", &discover_state,
+					sizeof(discover_state));
+	return ret;
+}
+
+/**
+ * brcmf_p2p_deinit_discovery() - disable P2P device discovery.
+ *
+ * @p2p: P2P specific data.
+ *
+ * Resets the discovery state and disables it in firmware.
+ */
+static s32 brcmf_p2p_deinit_discovery(struct brcmf_p2p_info *p2p)
+{
+	struct brcmf_cfg80211_vif *vif;
+
+	brcmf_dbg(TRACE, "enter\n");
+
+	/* Set the discovery state to SCAN */
+	vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
+	(void)brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_SCAN, 0, 0);
+
+	/* Disable P2P discovery in the firmware */
+	vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif;
+	(void)brcmf_fil_iovar_int_set(vif->ifp, "p2p_disc", 0);
+
+	return 0;
+}
+
+/**
+ * brcmf_p2p_enable_discovery() - initialize and configure discovery.
+ *
+ * @p2p: P2P specific data.
+ *
+ * Initializes the discovery device and configure the virtual interface.
+ */
+static int brcmf_p2p_enable_discovery(struct brcmf_p2p_info *p2p)
+{
+	struct brcmf_cfg80211_vif *vif;
+	s32 ret = 0;
+
+	brcmf_dbg(TRACE, "enter\n");
+	vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
+	if (!vif) {
+		brcmf_err("P2P config device not available\n");
+		ret = -EPERM;
+		goto exit;
+	}
+
+	if (test_bit(BRCMF_P2P_STATUS_ENABLED, &p2p->status)) {
+		brcmf_dbg(INFO, "P2P config device already configured\n");
+		goto exit;
+	}
+
+	/* Re-initialize P2P Discovery in the firmware */
+	vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif;
+	ret = brcmf_fil_iovar_int_set(vif->ifp, "p2p_disc", 1);
+	if (ret < 0) {
+		brcmf_err("set p2p_disc error\n");
+		goto exit;
+	}
+	vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
+	ret = brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_SCAN, 0, 0);
+	if (ret < 0) {
+		brcmf_err("unable to set WL_P2P_DISC_ST_SCAN\n");
+		goto exit;
+	}
+
+	/*
+	 * Set wsec to any non-zero value in the discovery bsscfg
+	 * to ensure our P2P probe responses have the privacy bit
+	 * set in the 802.11 WPA IE. Some peer devices may not
+	 * initiate WPS with us if this bit is not set.
+	 */
+	ret = brcmf_fil_bsscfg_int_set(vif->ifp, "wsec", AES_ENABLED);
+	if (ret < 0) {
+		brcmf_err("wsec error %d\n", ret);
+		goto exit;
+	}
+
+	set_bit(BRCMF_P2P_STATUS_ENABLED, &p2p->status);
+exit:
+	return ret;
+}
+
+/**
+ * brcmf_p2p_escan() - initiate a P2P scan.
+ *
+ * @p2p: P2P specific data.
+ * @num_chans: number of channels to scan.
+ * @chanspecs: channel parameters for @num_chans channels.
+ * @search_state: P2P discover state to use.
+ * @bss_type: type of P2P bss.
+ */
+static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans,
+			   u16 chanspecs[], s32 search_state,
+			   enum p2p_bss_type bss_type)
+{
+	s32 ret = 0;
+	s32 memsize = offsetof(struct brcmf_p2p_scan_le,
+			       eparams.params_le.channel_list);
+	s32 nprobes;
+	s32 active;
+	u32 i;
+	u8 *memblk;
+	struct brcmf_cfg80211_vif *vif;
+	struct brcmf_p2p_scan_le *p2p_params;
+	struct brcmf_scan_params_le *sparams;
+
+	memsize += num_chans * sizeof(__le16);
+	memblk = kzalloc(memsize, GFP_KERNEL);
+	if (!memblk)
+		return -ENOMEM;
+
+	vif = p2p->bss_idx[bss_type].vif;
+	if (vif == NULL) {
+		brcmf_err("no vif for bss type %d\n", bss_type);
+		ret = -EINVAL;
+		goto exit;
+	}
+	p2p_params = (struct brcmf_p2p_scan_le *)memblk;
+	sparams = &p2p_params->eparams.params_le;
+
+	switch (search_state) {
+	case WL_P2P_DISC_ST_SEARCH:
+		/*
+		 * If we in SEARCH STATE, we don't need to set SSID explictly
+		 * because dongle use P2P WILDCARD internally by default, use
+		 * null ssid, which it is already due to kzalloc.
+		 */
+		break;
+	case WL_P2P_DISC_ST_SCAN:
+		/*
+		 * wpa_supplicant has p2p_find command with type social or
+		 * progressive. For progressive, we need to set the ssid to
+		 * P2P WILDCARD because we just do broadcast scan unless
+		 * setting SSID.
+		 */
+		sparams->ssid_le.SSID_len =
+				cpu_to_le32(BRCMF_P2P_WILDCARD_SSID_LEN);
+		memcpy(sparams->ssid_le.SSID, BRCMF_P2P_WILDCARD_SSID,
+		       BRCMF_P2P_WILDCARD_SSID_LEN);
+		break;
+	default:
+		brcmf_err(" invalid search state %d\n", search_state);
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	brcmf_p2p_set_discover_state(vif->ifp, search_state, 0, 0);
+
+	/*
+	 * set p2p scan parameters.
+	 */
+	p2p_params->type = 'E';
+
+	/* determine the scan engine parameters */
+	sparams->bss_type = DOT11_BSSTYPE_ANY;
+	sparams->scan_type = BRCMF_SCANTYPE_ACTIVE;
+
+	eth_broadcast_addr(sparams->bssid);
+	sparams->home_time = cpu_to_le32(P2PAPI_SCAN_HOME_TIME_MS);
+
+	/*
+	 * SOCIAL_CHAN_CNT + 1 takes care of the Progressive scan
+	 * supported by the supplicant.
+	 */
+	if (num_chans == SOCIAL_CHAN_CNT || num_chans == (SOCIAL_CHAN_CNT + 1))
+		active = P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS;
+	else if (num_chans == AF_PEER_SEARCH_CNT)
+		active = P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS;
+	else if (brcmf_get_vif_state_any(p2p->cfg, BRCMF_VIF_STATUS_CONNECTED))
+		active = -1;
+	else
+		active = P2PAPI_SCAN_DWELL_TIME_MS;
+
+	/* Override scan params to find a peer for a connection */
+	if (num_chans == 1) {
+		active = WL_SCAN_CONNECT_DWELL_TIME_MS;
+		/* WAR to sync with presence period of VSDB GO.
+		 * send probe request more frequently
+		 */
+		nprobes = active / WL_SCAN_JOIN_PROBE_INTERVAL_MS;
+	} else {
+		nprobes = active / P2PAPI_SCAN_NPROBS_TIME_MS;
+	}
+
+	if (nprobes <= 0)
+		nprobes = 1;
+
+	brcmf_dbg(INFO, "nprobes # %d, active_time %d\n", nprobes, active);
+	sparams->active_time = cpu_to_le32(active);
+	sparams->nprobes = cpu_to_le32(nprobes);
+	sparams->passive_time = cpu_to_le32(-1);
+	sparams->channel_num = cpu_to_le32(num_chans &
+					   BRCMF_SCAN_PARAMS_COUNT_MASK);
+	for (i = 0; i < num_chans; i++)
+		sparams->channel_list[i] = cpu_to_le16(chanspecs[i]);
+
+	/* set the escan specific parameters */
+	p2p_params->eparams.version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
+	p2p_params->eparams.action =  cpu_to_le16(WL_ESCAN_ACTION_START);
+	p2p_params->eparams.sync_id = cpu_to_le16(0x1234);
+	/* perform p2p scan on primary device */
+	ret = brcmf_fil_bsscfg_data_set(vif->ifp, "p2p_scan", memblk, memsize);
+	if (!ret)
+		set_bit(BRCMF_SCAN_STATUS_BUSY, &p2p->cfg->scan_status);
+exit:
+	kfree(memblk);
+	return ret;
+}
+
+/**
+ * brcmf_p2p_run_escan() - escan callback for peer-to-peer.
+ *
+ * @cfg: driver private data for cfg80211 interface.
+ * @ndev: net device for which scan is requested.
+ * @request: scan request from cfg80211.
+ * @action: scan action.
+ *
+ * Determines the P2P discovery state based to scan request parameters and
+ * validates the channels in the request.
+ */
+static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg,
+			       struct brcmf_if *ifp,
+			       struct cfg80211_scan_request *request)
+{
+	struct brcmf_p2p_info *p2p = &cfg->p2p;
+	s32 err = 0;
+	s32 search_state = WL_P2P_DISC_ST_SCAN;
+	struct brcmf_cfg80211_vif *vif;
+	struct net_device *dev = NULL;
+	int i, num_nodfs = 0;
+	u16 *chanspecs;
+
+	brcmf_dbg(TRACE, "enter\n");
+
+	if (!request) {
+		err = -EINVAL;
+		goto exit;
+	}
+
+	if (request->n_channels) {
+		chanspecs = kcalloc(request->n_channels, sizeof(*chanspecs),
+				    GFP_KERNEL);
+		if (!chanspecs) {
+			err = -ENOMEM;
+			goto exit;
+		}
+		vif = p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif;
+		if (vif)
+			dev = vif->wdev.netdev;
+		if (request->n_channels == 3 &&
+		    request->channels[0]->hw_value == SOCIAL_CHAN_1 &&
+		    request->channels[1]->hw_value == SOCIAL_CHAN_2 &&
+		    request->channels[2]->hw_value == SOCIAL_CHAN_3) {
+			/* SOCIAL CHANNELS 1, 6, 11 */
+			search_state = WL_P2P_DISC_ST_SEARCH;
+			brcmf_dbg(INFO, "P2P SEARCH PHASE START\n");
+		} else if (dev != NULL &&
+			   vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) {
+			/* If you are already a GO, then do SEARCH only */
+			brcmf_dbg(INFO, "Already a GO. Do SEARCH Only\n");
+			search_state = WL_P2P_DISC_ST_SEARCH;
+		} else {
+			brcmf_dbg(INFO, "P2P SCAN STATE START\n");
+		}
+
+		/*
+		 * no P2P scanning on passive or DFS channels.
+		 */
+		for (i = 0; i < request->n_channels; i++) {
+			struct ieee80211_channel *chan = request->channels[i];
+
+			if (chan->flags & (IEEE80211_CHAN_RADAR |
+					   IEEE80211_CHAN_NO_IR))
+				continue;
+
+			chanspecs[i] = channel_to_chanspec(&p2p->cfg->d11inf,
+							   chan);
+			brcmf_dbg(INFO, "%d: chan=%d, channel spec=%x\n",
+				  num_nodfs, chan->hw_value, chanspecs[i]);
+			num_nodfs++;
+		}
+		err = brcmf_p2p_escan(p2p, num_nodfs, chanspecs, search_state,
+				      P2PAPI_BSSCFG_DEVICE);
+		kfree(chanspecs);
+	}
+exit:
+	if (err)
+		brcmf_err("error (%d)\n", err);
+	return err;
+}
+
+
+/**
+ * brcmf_p2p_find_listen_channel() - find listen channel in ie string.
+ *
+ * @ie: string of information elements.
+ * @ie_len: length of string.
+ *
+ * Scan ie for p2p ie and look for attribute 6 channel. If available determine
+ * channel and return it.
+ */
+static s32 brcmf_p2p_find_listen_channel(const u8 *ie, u32 ie_len)
+{
+	u8 channel_ie[5];
+	s32 listen_channel;
+	s32 err;
+
+	err = cfg80211_get_p2p_attr(ie, ie_len,
+				    IEEE80211_P2P_ATTR_LISTEN_CHANNEL,
+				    channel_ie, sizeof(channel_ie));
+	if (err < 0)
+		return err;
+
+	/* listen channel subel length format:     */
+	/* 3(country) + 1(op. class) + 1(chan num) */
+	listen_channel = (s32)channel_ie[3 + 1];
+
+	if (listen_channel == SOCIAL_CHAN_1 ||
+	    listen_channel == SOCIAL_CHAN_2 ||
+	    listen_channel == SOCIAL_CHAN_3) {
+		brcmf_dbg(INFO, "Found my Listen Channel %d\n", listen_channel);
+		return listen_channel;
+	}
+
+	return -EPERM;
+}
+
+
+/**
+ * brcmf_p2p_scan_prep() - prepare scan based on request.
+ *
+ * @wiphy: wiphy device.
+ * @request: scan request from cfg80211.
+ * @vif: vif on which scan request is to be executed.
+ *
+ * Prepare the scan appropriately for type of scan requested. Overrides the
+ * escan .run() callback for peer-to-peer scanning.
+ */
+int brcmf_p2p_scan_prep(struct wiphy *wiphy,
+			struct cfg80211_scan_request *request,
+			struct brcmf_cfg80211_vif *vif)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_p2p_info *p2p = &cfg->p2p;
+	int err;
+
+	if (brcmf_p2p_scan_is_p2p_request(request)) {
+		/* find my listen channel */
+		err = brcmf_p2p_find_listen_channel(request->ie,
+						    request->ie_len);
+		if (err < 0)
+			return err;
+
+		p2p->afx_hdl.my_listen_chan = err;
+
+		clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status);
+		brcmf_dbg(INFO, "P2P: GO_NEG_PHASE status cleared\n");
+
+		err = brcmf_p2p_enable_discovery(p2p);
+		if (err)
+			return err;
+
+		vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
+
+		/* override .run_escan() callback. */
+		cfg->escan_info.run = brcmf_p2p_run_escan;
+	}
+	return 0;
+}
+
+
+/**
+ * brcmf_p2p_discover_listen() - set firmware to discover listen state.
+ *
+ * @p2p: p2p device.
+ * @channel: channel nr for discover listen.
+ * @duration: time in ms to stay on channel.
+ *
+ */
+static s32
+brcmf_p2p_discover_listen(struct brcmf_p2p_info *p2p, u16 channel, u32 duration)
+{
+	struct brcmf_cfg80211_vif *vif;
+	struct brcmu_chan ch;
+	s32 err = 0;
+
+	vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
+	if (!vif) {
+		brcmf_err("Discovery is not set, so we have nothing to do\n");
+		err = -EPERM;
+		goto exit;
+	}
+
+	if (test_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN, &p2p->status)) {
+		brcmf_err("Previous LISTEN is not completed yet\n");
+		/* WAR: prevent cookie mismatch in wpa_supplicant return OK */
+		goto exit;
+	}
+
+	ch.chnum = channel;
+	ch.bw = BRCMU_CHAN_BW_20;
+	p2p->cfg->d11inf.encchspec(&ch);
+	err = brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_LISTEN,
+					   ch.chspec, (u16)duration);
+	if (!err) {
+		set_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN, &p2p->status);
+		p2p->remain_on_channel_cookie++;
+	}
+exit:
+	return err;
+}
+
+
+/**
+ * brcmf_p2p_remain_on_channel() - put device on channel and stay there.
+ *
+ * @wiphy: wiphy device.
+ * @channel: channel to stay on.
+ * @duration: time in ms to remain on channel.
+ *
+ */
+int brcmf_p2p_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
+				struct ieee80211_channel *channel,
+				unsigned int duration, u64 *cookie)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_p2p_info *p2p = &cfg->p2p;
+	s32 err;
+	u16 channel_nr;
+
+	channel_nr = ieee80211_frequency_to_channel(channel->center_freq);
+	brcmf_dbg(TRACE, "Enter, channel: %d, duration ms (%d)\n", channel_nr,
+		  duration);
+
+	err = brcmf_p2p_enable_discovery(p2p);
+	if (err)
+		goto exit;
+	err = brcmf_p2p_discover_listen(p2p, channel_nr, duration);
+	if (err)
+		goto exit;
+
+	memcpy(&p2p->remain_on_channel, channel, sizeof(*channel));
+	*cookie = p2p->remain_on_channel_cookie;
+	cfg80211_ready_on_channel(wdev, *cookie, channel, duration, GFP_KERNEL);
+
+exit:
+	return err;
+}
+
+
+/**
+ * brcmf_p2p_notify_listen_complete() - p2p listen has completed.
+ *
+ * @ifp: interfac control.
+ * @e: event message. Not used, to make it usable for fweh event dispatcher.
+ * @data: payload of message. Not used.
+ *
+ */
+int brcmf_p2p_notify_listen_complete(struct brcmf_if *ifp,
+				     const struct brcmf_event_msg *e,
+				     void *data)
+{
+	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+	struct brcmf_p2p_info *p2p = &cfg->p2p;
+
+	brcmf_dbg(TRACE, "Enter\n");
+	if (test_and_clear_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN,
+			       &p2p->status)) {
+		if (test_and_clear_bit(BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN,
+				       &p2p->status)) {
+			clear_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME,
+				  &p2p->status);
+			brcmf_dbg(INFO, "Listen DONE, wake up wait_next_af\n");
+			complete(&p2p->wait_next_af);
+		}
+
+		cfg80211_remain_on_channel_expired(&ifp->vif->wdev,
+						   p2p->remain_on_channel_cookie,
+						   &p2p->remain_on_channel,
+						   GFP_KERNEL);
+	}
+	return 0;
+}
+
+
+/**
+ * brcmf_p2p_cancel_remain_on_channel() - cancel p2p listen state.
+ *
+ * @ifp: interfac control.
+ *
+ */
+void brcmf_p2p_cancel_remain_on_channel(struct brcmf_if *ifp)
+{
+	if (!ifp)
+		return;
+	brcmf_p2p_set_discover_state(ifp, WL_P2P_DISC_ST_SCAN, 0, 0);
+	brcmf_p2p_notify_listen_complete(ifp, NULL, NULL);
+}
+
+
+/**
+ * brcmf_p2p_act_frm_search() - search function for action frame.
+ *
+ * @p2p: p2p device.
+ * channel: channel on which action frame is to be trasmitted.
+ *
+ * search function to reach at common channel to send action frame. When
+ * channel is 0 then all social channels will be used to send af
+ */
+static s32 brcmf_p2p_act_frm_search(struct brcmf_p2p_info *p2p, u16 channel)
+{
+	s32 err;
+	u32 channel_cnt;
+	u16 *default_chan_list;
+	u32 i;
+	struct brcmu_chan ch;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	if (channel)
+		channel_cnt = AF_PEER_SEARCH_CNT;
+	else
+		channel_cnt = SOCIAL_CHAN_CNT;
+	default_chan_list = kcalloc(channel_cnt, sizeof(*default_chan_list),
+				    GFP_KERNEL);
+	if (default_chan_list == NULL) {
+		brcmf_err("channel list allocation failed\n");
+		err = -ENOMEM;
+		goto exit;
+	}
+	ch.bw = BRCMU_CHAN_BW_20;
+	if (channel) {
+		ch.chnum = channel;
+		p2p->cfg->d11inf.encchspec(&ch);
+		/* insert same channel to the chan_list */
+		for (i = 0; i < channel_cnt; i++)
+			default_chan_list[i] = ch.chspec;
+	} else {
+		ch.chnum = SOCIAL_CHAN_1;
+		p2p->cfg->d11inf.encchspec(&ch);
+		default_chan_list[0] = ch.chspec;
+		ch.chnum = SOCIAL_CHAN_2;
+		p2p->cfg->d11inf.encchspec(&ch);
+		default_chan_list[1] = ch.chspec;
+		ch.chnum = SOCIAL_CHAN_3;
+		p2p->cfg->d11inf.encchspec(&ch);
+		default_chan_list[2] = ch.chspec;
+	}
+	err = brcmf_p2p_escan(p2p, channel_cnt, default_chan_list,
+			      WL_P2P_DISC_ST_SEARCH, P2PAPI_BSSCFG_DEVICE);
+	kfree(default_chan_list);
+exit:
+	return err;
+}
+
+
+/**
+ * brcmf_p2p_afx_handler() - afx worker thread.
+ *
+ * @work:
+ *
+ */
+static void brcmf_p2p_afx_handler(struct work_struct *work)
+{
+	struct afx_hdl *afx_hdl = container_of(work, struct afx_hdl, afx_work);
+	struct brcmf_p2p_info *p2p = container_of(afx_hdl,
+						  struct brcmf_p2p_info,
+						  afx_hdl);
+	s32 err;
+
+	if (!afx_hdl->is_active)
+		return;
+
+	if (afx_hdl->is_listen && afx_hdl->my_listen_chan)
+		/* 100ms ~ 300ms */
+		err = brcmf_p2p_discover_listen(p2p, afx_hdl->my_listen_chan,
+						100 * (1 + prandom_u32() % 3));
+	else
+		err = brcmf_p2p_act_frm_search(p2p, afx_hdl->peer_listen_chan);
+
+	if (err) {
+		brcmf_err("ERROR occurred! value is (%d)\n", err);
+		if (test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL,
+			     &p2p->status))
+			complete(&afx_hdl->act_frm_scan);
+	}
+}
+
+
+/**
+ * brcmf_p2p_af_searching_channel() - search channel.
+ *
+ * @p2p: p2p device info struct.
+ *
+ */
+static s32 brcmf_p2p_af_searching_channel(struct brcmf_p2p_info *p2p)
+{
+	struct afx_hdl *afx_hdl = &p2p->afx_hdl;
+	struct brcmf_cfg80211_vif *pri_vif;
+	unsigned long duration;
+	s32 retry;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	pri_vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif;
+
+	reinit_completion(&afx_hdl->act_frm_scan);
+	set_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, &p2p->status);
+	afx_hdl->is_active = true;
+	afx_hdl->peer_chan = P2P_INVALID_CHANNEL;
+
+	/* Loop to wait until we find a peer's channel or the
+	 * pending action frame tx is cancelled.
+	 */
+	retry = 0;
+	duration = msecs_to_jiffies(P2P_AF_FRM_SCAN_MAX_WAIT);
+	while ((retry < P2P_CHANNEL_SYNC_RETRY) &&
+	       (afx_hdl->peer_chan == P2P_INVALID_CHANNEL)) {
+		afx_hdl->is_listen = false;
+		brcmf_dbg(TRACE, "Scheduling action frame for sending.. (%d)\n",
+			  retry);
+		/* search peer on peer's listen channel */
+		schedule_work(&afx_hdl->afx_work);
+		wait_for_completion_timeout(&afx_hdl->act_frm_scan, duration);
+		if ((afx_hdl->peer_chan != P2P_INVALID_CHANNEL) ||
+		    (!test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL,
+			       &p2p->status)))
+			break;
+
+		if (afx_hdl->my_listen_chan) {
+			brcmf_dbg(TRACE, "Scheduling listen peer, channel=%d\n",
+				  afx_hdl->my_listen_chan);
+			/* listen on my listen channel */
+			afx_hdl->is_listen = true;
+			schedule_work(&afx_hdl->afx_work);
+			wait_for_completion_timeout(&afx_hdl->act_frm_scan,
+						    duration);
+		}
+		if ((afx_hdl->peer_chan != P2P_INVALID_CHANNEL) ||
+		    (!test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL,
+			       &p2p->status)))
+			break;
+		retry++;
+
+		/* if sta is connected or connecting, sleep for a while before
+		 * retry af tx or finding a peer
+		 */
+		if (test_bit(BRCMF_VIF_STATUS_CONNECTED, &pri_vif->sme_state) ||
+		    test_bit(BRCMF_VIF_STATUS_CONNECTING, &pri_vif->sme_state))
+			msleep(P2P_DEFAULT_SLEEP_TIME_VSDB);
+	}
+
+	brcmf_dbg(TRACE, "Completed search/listen peer_chan=%d\n",
+		  afx_hdl->peer_chan);
+	afx_hdl->is_active = false;
+
+	clear_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, &p2p->status);
+
+	return afx_hdl->peer_chan;
+}
+
+
+/**
+ * brcmf_p2p_scan_finding_common_channel() - was escan used for finding channel
+ *
+ * @cfg: common configuration struct.
+ * @bi: bss info struct, result from scan.
+ *
+ */
+bool brcmf_p2p_scan_finding_common_channel(struct brcmf_cfg80211_info *cfg,
+					   struct brcmf_bss_info_le *bi)
+
+{
+	struct brcmf_p2p_info *p2p = &cfg->p2p;
+	struct afx_hdl *afx_hdl = &p2p->afx_hdl;
+	struct brcmu_chan ch;
+	u8 *ie;
+	s32 err;
+	u8 p2p_dev_addr[ETH_ALEN];
+
+	if (!test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, &p2p->status))
+		return false;
+
+	if (bi == NULL) {
+		brcmf_dbg(TRACE, "ACTION FRAME SCAN Done\n");
+		if (afx_hdl->peer_chan == P2P_INVALID_CHANNEL)
+			complete(&afx_hdl->act_frm_scan);
+		return true;
+	}
+
+	ie = ((u8 *)bi) + le16_to_cpu(bi->ie_offset);
+	memset(p2p_dev_addr, 0, sizeof(p2p_dev_addr));
+	err = cfg80211_get_p2p_attr(ie, le32_to_cpu(bi->ie_length),
+				    IEEE80211_P2P_ATTR_DEVICE_INFO,
+				    p2p_dev_addr, sizeof(p2p_dev_addr));
+	if (err < 0)
+		err = cfg80211_get_p2p_attr(ie, le32_to_cpu(bi->ie_length),
+					    IEEE80211_P2P_ATTR_DEVICE_ID,
+					    p2p_dev_addr, sizeof(p2p_dev_addr));
+	if ((err >= 0) &&
+	    (ether_addr_equal(p2p_dev_addr, afx_hdl->tx_dst_addr))) {
+		if (!bi->ctl_ch) {
+			ch.chspec = le16_to_cpu(bi->chanspec);
+			cfg->d11inf.decchspec(&ch);
+			bi->ctl_ch = ch.control_ch_num;
+		}
+		afx_hdl->peer_chan = bi->ctl_ch;
+		brcmf_dbg(TRACE, "ACTION FRAME SCAN : Peer %pM found, channel : %d\n",
+			  afx_hdl->tx_dst_addr, afx_hdl->peer_chan);
+		complete(&afx_hdl->act_frm_scan);
+	}
+	return true;
+}
+
+/**
+ * brcmf_p2p_stop_wait_next_action_frame() - finish scan if af tx complete.
+ *
+ * @cfg: common configuration struct.
+ *
+ */
+static void
+brcmf_p2p_stop_wait_next_action_frame(struct brcmf_cfg80211_info *cfg)
+{
+	struct brcmf_p2p_info *p2p = &cfg->p2p;
+	struct brcmf_if *ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
+
+	if (test_bit(BRCMF_P2P_STATUS_SENDING_ACT_FRAME, &p2p->status) &&
+	    (test_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status) ||
+	     test_bit(BRCMF_P2P_STATUS_ACTION_TX_NOACK, &p2p->status))) {
+		brcmf_dbg(TRACE, "*** Wake UP ** abort actframe iovar\n");
+		/* if channel is not zero, "actfame" uses off channel scan.
+		 * So abort scan for off channel completion.
+		 */
+		if (p2p->af_sent_channel)
+			brcmf_notify_escan_complete(cfg, ifp, true, true);
+	} else if (test_bit(BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN,
+			    &p2p->status)) {
+		brcmf_dbg(TRACE, "*** Wake UP ** abort listen for next af frame\n");
+		/* So abort scan to cancel listen */
+		brcmf_notify_escan_complete(cfg, ifp, true, true);
+	}
+}
+
+
+/**
+ * brcmf_p2p_gon_req_collision() - Check if go negotiaton collission
+ *
+ * @p2p: p2p device info struct.
+ *
+ * return true if recevied action frame is to be dropped.
+ */
+static bool
+brcmf_p2p_gon_req_collision(struct brcmf_p2p_info *p2p, u8 *mac)
+{
+	struct brcmf_cfg80211_info *cfg = p2p->cfg;
+	struct brcmf_if *ifp;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	if (!test_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME, &p2p->status) ||
+	    !p2p->gon_req_action)
+		return false;
+
+	brcmf_dbg(TRACE, "GO Negotiation Request COLLISION !!!\n");
+	/* if sa(peer) addr is less than da(my) addr, then this device
+	 * process peer's gon request and block to send gon req.
+	 * if not (sa addr > da addr),
+	 * this device will process gon request and drop gon req of peer.
+	 */
+	ifp = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->ifp;
+	if (memcmp(mac, ifp->mac_addr, ETH_ALEN) < 0) {
+		brcmf_dbg(INFO, "Block transmit gon req !!!\n");
+		p2p->block_gon_req_tx = true;
+		/* if we are finding a common channel for sending af,
+		 * do not scan more to block to send current gon req
+		 */
+		if (test_and_clear_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL,
+				       &p2p->status))
+			complete(&p2p->afx_hdl.act_frm_scan);
+		if (test_and_clear_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME,
+				       &p2p->status))
+			brcmf_p2p_stop_wait_next_action_frame(cfg);
+		return false;
+	}
+
+	/* drop gon request of peer to process gon request by this device. */
+	brcmf_dbg(INFO, "Drop received gon req !!!\n");
+
+	return true;
+}
+
+
+/**
+ * brcmf_p2p_notify_action_frame_rx() - received action frame.
+ *
+ * @ifp: interfac control.
+ * @e: event message. Not used, to make it usable for fweh event dispatcher.
+ * @data: payload of message, containing action frame data.
+ *
+ */
+int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
+				     const struct brcmf_event_msg *e,
+				     void *data)
+{
+	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+	struct brcmf_p2p_info *p2p = &cfg->p2p;
+	struct afx_hdl *afx_hdl = &p2p->afx_hdl;
+	struct wireless_dev *wdev;
+	u32 mgmt_frame_len = e->datalen - sizeof(struct brcmf_rx_mgmt_data);
+	struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data;
+	u8 *frame = (u8 *)(rxframe + 1);
+	struct brcmf_p2p_pub_act_frame *act_frm;
+	struct brcmf_p2psd_gas_pub_act_frame *sd_act_frm;
+	struct brcmu_chan ch;
+	struct ieee80211_mgmt *mgmt_frame;
+	s32 freq;
+	u16 mgmt_type;
+	u8 action;
+
+	if (e->datalen < sizeof(*rxframe)) {
+		brcmf_dbg(SCAN, "Event data to small. Ignore\n");
+		return 0;
+	}
+
+	ch.chspec = be16_to_cpu(rxframe->chanspec);
+	cfg->d11inf.decchspec(&ch);
+	/* Check if wpa_supplicant has registered for this frame */
+	brcmf_dbg(INFO, "ifp->vif->mgmt_rx_reg %04x\n", ifp->vif->mgmt_rx_reg);
+	mgmt_type = (IEEE80211_STYPE_ACTION & IEEE80211_FCTL_STYPE) >> 4;
+	if ((ifp->vif->mgmt_rx_reg & BIT(mgmt_type)) == 0)
+		return 0;
+
+	brcmf_p2p_print_actframe(false, frame, mgmt_frame_len);
+
+	action = P2P_PAF_SUBTYPE_INVALID;
+	if (brcmf_p2p_is_pub_action(frame, mgmt_frame_len)) {
+		act_frm = (struct brcmf_p2p_pub_act_frame *)frame;
+		action = act_frm->subtype;
+		if ((action == P2P_PAF_GON_REQ) &&
+		    (brcmf_p2p_gon_req_collision(p2p, (u8 *)e->addr))) {
+			if (test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL,
+				     &p2p->status) &&
+			    (ether_addr_equal(afx_hdl->tx_dst_addr, e->addr))) {
+				afx_hdl->peer_chan = ch.control_ch_num;
+				brcmf_dbg(INFO, "GON request: Peer found, channel=%d\n",
+					  afx_hdl->peer_chan);
+				complete(&afx_hdl->act_frm_scan);
+			}
+			return 0;
+		}
+		/* After complete GO Negotiation, roll back to mpc mode */
+		if ((action == P2P_PAF_GON_CONF) ||
+		    (action == P2P_PAF_PROVDIS_RSP))
+			brcmf_set_mpc(ifp, 1);
+		if (action == P2P_PAF_GON_CONF) {
+			brcmf_dbg(TRACE, "P2P: GO_NEG_PHASE status cleared\n");
+			clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status);
+		}
+	} else if (brcmf_p2p_is_gas_action(frame, mgmt_frame_len)) {
+		sd_act_frm = (struct brcmf_p2psd_gas_pub_act_frame *)frame;
+		action = sd_act_frm->action;
+	}
+
+	if (test_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME, &p2p->status) &&
+	    (p2p->next_af_subtype == action)) {
+		brcmf_dbg(TRACE, "We got a right next frame! (%d)\n", action);
+		clear_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME,
+			  &p2p->status);
+		/* Stop waiting for next AF. */
+		brcmf_p2p_stop_wait_next_action_frame(cfg);
+	}
+
+	mgmt_frame = kzalloc(offsetof(struct ieee80211_mgmt, u) +
+			     mgmt_frame_len, GFP_KERNEL);
+	if (!mgmt_frame) {
+		brcmf_err("No memory available for action frame\n");
+		return -ENOMEM;
+	}
+	memcpy(mgmt_frame->da, ifp->mac_addr, ETH_ALEN);
+	brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSSID, mgmt_frame->bssid,
+			       ETH_ALEN);
+	memcpy(mgmt_frame->sa, e->addr, ETH_ALEN);
+	mgmt_frame->frame_control = cpu_to_le16(IEEE80211_STYPE_ACTION);
+	memcpy(&mgmt_frame->u, frame, mgmt_frame_len);
+	mgmt_frame_len += offsetof(struct ieee80211_mgmt, u);
+
+	freq = ieee80211_channel_to_frequency(ch.control_ch_num,
+					      ch.band == BRCMU_CHAN_BAND_2G ?
+					      NL80211_BAND_2GHZ :
+					      NL80211_BAND_5GHZ);
+
+	wdev = &ifp->vif->wdev;
+	cfg80211_rx_mgmt(wdev, freq, 0, (u8 *)mgmt_frame, mgmt_frame_len, 0);
+
+	kfree(mgmt_frame);
+	return 0;
+}
+
+
+/**
+ * brcmf_p2p_notify_action_tx_complete() - transmit action frame complete
+ *
+ * @ifp: interfac control.
+ * @e: event message. Not used, to make it usable for fweh event dispatcher.
+ * @data: not used.
+ *
+ */
+int brcmf_p2p_notify_action_tx_complete(struct brcmf_if *ifp,
+					const struct brcmf_event_msg *e,
+					void *data)
+{
+	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+	struct brcmf_p2p_info *p2p = &cfg->p2p;
+
+	brcmf_dbg(INFO, "Enter: event %s, status=%d\n",
+		  e->event_code == BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE ?
+		  "ACTION_FRAME_OFF_CHAN_COMPLETE" : "ACTION_FRAME_COMPLETE",
+		  e->status);
+
+	if (!test_bit(BRCMF_P2P_STATUS_SENDING_ACT_FRAME, &p2p->status))
+		return 0;
+
+	if (e->event_code == BRCMF_E_ACTION_FRAME_COMPLETE) {
+		if (e->status == BRCMF_E_STATUS_SUCCESS)
+			set_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED,
+				&p2p->status);
+		else {
+			set_bit(BRCMF_P2P_STATUS_ACTION_TX_NOACK, &p2p->status);
+			/* If there is no ack, we don't need to wait for
+			 * WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE event
+			 */
+			brcmf_p2p_stop_wait_next_action_frame(cfg);
+		}
+
+	} else {
+		complete(&p2p->send_af_done);
+	}
+	return 0;
+}
+
+
+/**
+ * brcmf_p2p_tx_action_frame() - send action frame over fil.
+ *
+ * @p2p: p2p info struct for vif.
+ * @af_params: action frame data/info.
+ *
+ * Send an action frame immediately without doing channel synchronization.
+ *
+ * This function waits for a completion event before returning.
+ * The WLC_E_ACTION_FRAME_COMPLETE event will be received when the action
+ * frame is transmitted.
+ */
+static s32 brcmf_p2p_tx_action_frame(struct brcmf_p2p_info *p2p,
+				     struct brcmf_fil_af_params_le *af_params)
+{
+	struct brcmf_cfg80211_vif *vif;
+	s32 err = 0;
+	s32 timeout = 0;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	reinit_completion(&p2p->send_af_done);
+	clear_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status);
+	clear_bit(BRCMF_P2P_STATUS_ACTION_TX_NOACK, &p2p->status);
+
+	vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
+	err = brcmf_fil_bsscfg_data_set(vif->ifp, "actframe", af_params,
+					sizeof(*af_params));
+	if (err) {
+		brcmf_err(" sending action frame has failed\n");
+		goto exit;
+	}
+
+	p2p->af_sent_channel = le32_to_cpu(af_params->channel);
+	p2p->af_tx_sent_jiffies = jiffies;
+
+	timeout = wait_for_completion_timeout(&p2p->send_af_done,
+					      P2P_AF_MAX_WAIT_TIME);
+
+	if (test_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status)) {
+		brcmf_dbg(TRACE, "TX action frame operation is success\n");
+	} else {
+		err = -EIO;
+		brcmf_dbg(TRACE, "TX action frame operation has failed\n");
+	}
+	/* clear status bit for action tx */
+	clear_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status);
+	clear_bit(BRCMF_P2P_STATUS_ACTION_TX_NOACK, &p2p->status);
+
+exit:
+	return err;
+}
+
+
+/**
+ * brcmf_p2p_pub_af_tx() - public action frame tx routine.
+ *
+ * @cfg: driver private data for cfg80211 interface.
+ * @af_params: action frame data/info.
+ * @config_af_params: configuration data for action frame.
+ *
+ * routine which transmits ation frame public type.
+ */
+static s32 brcmf_p2p_pub_af_tx(struct brcmf_cfg80211_info *cfg,
+			       struct brcmf_fil_af_params_le *af_params,
+			       struct brcmf_config_af_params *config_af_params)
+{
+	struct brcmf_p2p_info *p2p = &cfg->p2p;
+	struct brcmf_fil_action_frame_le *action_frame;
+	struct brcmf_p2p_pub_act_frame *act_frm;
+	s32 err = 0;
+	u16 ie_len;
+
+	action_frame = &af_params->action_frame;
+	act_frm = (struct brcmf_p2p_pub_act_frame *)(action_frame->data);
+
+	config_af_params->extra_listen = true;
+
+	switch (act_frm->subtype) {
+	case P2P_PAF_GON_REQ:
+		brcmf_dbg(TRACE, "P2P: GO_NEG_PHASE status set\n");
+		set_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status);
+		config_af_params->mpc_onoff = 0;
+		config_af_params->search_channel = true;
+		p2p->next_af_subtype = act_frm->subtype + 1;
+		p2p->gon_req_action = true;
+		/* increase dwell time to wait for RESP frame */
+		af_params->dwell_time = cpu_to_le32(P2P_AF_MED_DWELL_TIME);
+		break;
+	case P2P_PAF_GON_RSP:
+		p2p->next_af_subtype = act_frm->subtype + 1;
+		/* increase dwell time to wait for CONF frame */
+		af_params->dwell_time = cpu_to_le32(P2P_AF_MED_DWELL_TIME);
+		break;
+	case P2P_PAF_GON_CONF:
+		/* If we reached till GO Neg confirmation reset the filter */
+		brcmf_dbg(TRACE, "P2P: GO_NEG_PHASE status cleared\n");
+		clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status);
+		/* turn on mpc again if go nego is done */
+		config_af_params->mpc_onoff = 1;
+		/* minimize dwell time */
+		af_params->dwell_time = cpu_to_le32(P2P_AF_MIN_DWELL_TIME);
+		config_af_params->extra_listen = false;
+		break;
+	case P2P_PAF_INVITE_REQ:
+		config_af_params->search_channel = true;
+		p2p->next_af_subtype = act_frm->subtype + 1;
+		/* increase dwell time */
+		af_params->dwell_time = cpu_to_le32(P2P_AF_MED_DWELL_TIME);
+		break;
+	case P2P_PAF_INVITE_RSP:
+		/* minimize dwell time */
+		af_params->dwell_time = cpu_to_le32(P2P_AF_MIN_DWELL_TIME);
+		config_af_params->extra_listen = false;
+		break;
+	case P2P_PAF_DEVDIS_REQ:
+		config_af_params->search_channel = true;
+		p2p->next_af_subtype = act_frm->subtype + 1;
+		/* maximize dwell time to wait for RESP frame */
+		af_params->dwell_time = cpu_to_le32(P2P_AF_LONG_DWELL_TIME);
+		break;
+	case P2P_PAF_DEVDIS_RSP:
+		/* minimize dwell time */
+		af_params->dwell_time = cpu_to_le32(P2P_AF_MIN_DWELL_TIME);
+		config_af_params->extra_listen = false;
+		break;
+	case P2P_PAF_PROVDIS_REQ:
+		ie_len = le16_to_cpu(action_frame->len) -
+			 offsetof(struct brcmf_p2p_pub_act_frame, elts);
+		if (cfg80211_get_p2p_attr(&act_frm->elts[0], ie_len,
+					  IEEE80211_P2P_ATTR_GROUP_ID,
+					  NULL, 0) < 0)
+			config_af_params->search_channel = true;
+		config_af_params->mpc_onoff = 0;
+		p2p->next_af_subtype = act_frm->subtype + 1;
+		/* increase dwell time to wait for RESP frame */
+		af_params->dwell_time = cpu_to_le32(P2P_AF_MED_DWELL_TIME);
+		break;
+	case P2P_PAF_PROVDIS_RSP:
+		/* wpa_supplicant send go nego req right after prov disc */
+		p2p->next_af_subtype = P2P_PAF_GON_REQ;
+		/* increase dwell time to MED level */
+		af_params->dwell_time = cpu_to_le32(P2P_AF_MED_DWELL_TIME);
+		config_af_params->extra_listen = false;
+		break;
+	default:
+		brcmf_err("Unknown p2p pub act frame subtype: %d\n",
+			  act_frm->subtype);
+		err = -EINVAL;
+	}
+	return err;
+}
+
+/**
+ * brcmf_p2p_send_action_frame() - send action frame .
+ *
+ * @cfg: driver private data for cfg80211 interface.
+ * @ndev: net device to transmit on.
+ * @af_params: configuration data for action frame.
+ */
+bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg,
+				 struct net_device *ndev,
+				 struct brcmf_fil_af_params_le *af_params)
+{
+	struct brcmf_p2p_info *p2p = &cfg->p2p;
+	struct brcmf_if *ifp = netdev_priv(ndev);
+	struct brcmf_fil_action_frame_le *action_frame;
+	struct brcmf_config_af_params config_af_params;
+	struct afx_hdl *afx_hdl = &p2p->afx_hdl;
+	u16 action_frame_len;
+	bool ack = false;
+	u8 category;
+	u8 action;
+	s32 tx_retry;
+	s32 extra_listen_time;
+	uint delta_ms;
+
+	action_frame = &af_params->action_frame;
+	action_frame_len = le16_to_cpu(action_frame->len);
+
+	brcmf_p2p_print_actframe(true, action_frame->data, action_frame_len);
+
+	/* Add the default dwell time. Dwell time to stay off-channel */
+	/* to wait for a response action frame after transmitting an  */
+	/* GO Negotiation action frame                                */
+	af_params->dwell_time = cpu_to_le32(P2P_AF_DWELL_TIME);
+
+	category = action_frame->data[DOT11_ACTION_CAT_OFF];
+	action = action_frame->data[DOT11_ACTION_ACT_OFF];
+
+	/* initialize variables */
+	p2p->next_af_subtype = P2P_PAF_SUBTYPE_INVALID;
+	p2p->gon_req_action = false;
+
+	/* config parameters */
+	config_af_params.mpc_onoff = -1;
+	config_af_params.search_channel = false;
+	config_af_params.extra_listen = false;
+
+	if (brcmf_p2p_is_pub_action(action_frame->data, action_frame_len)) {
+		/* p2p public action frame process */
+		if (brcmf_p2p_pub_af_tx(cfg, af_params, &config_af_params)) {
+			/* Just send unknown subtype frame with */
+			/* default parameters.                  */
+			brcmf_err("P2P Public action frame, unknown subtype.\n");
+		}
+	} else if (brcmf_p2p_is_gas_action(action_frame->data,
+					   action_frame_len)) {
+		/* service discovery process */
+		if (action == P2PSD_ACTION_ID_GAS_IREQ ||
+		    action == P2PSD_ACTION_ID_GAS_CREQ) {
+			/* configure service discovery query frame */
+			config_af_params.search_channel = true;
+
+			/* save next af suptype to cancel */
+			/* remaining dwell time           */
+			p2p->next_af_subtype = action + 1;
+
+			af_params->dwell_time =
+				cpu_to_le32(P2P_AF_MED_DWELL_TIME);
+		} else if (action == P2PSD_ACTION_ID_GAS_IRESP ||
+			   action == P2PSD_ACTION_ID_GAS_CRESP) {
+			/* configure service discovery response frame */
+			af_params->dwell_time =
+				cpu_to_le32(P2P_AF_MIN_DWELL_TIME);
+		} else {
+			brcmf_err("Unknown action type: %d\n", action);
+			goto exit;
+		}
+	} else if (brcmf_p2p_is_p2p_action(action_frame->data,
+					   action_frame_len)) {
+		/* do not configure anything. it will be */
+		/* sent with a default configuration     */
+	} else {
+		brcmf_err("Unknown Frame: category 0x%x, action 0x%x\n",
+			  category, action);
+		return false;
+	}
+
+	/* if connecting on primary iface, sleep for a while before sending
+	 * af tx for VSDB
+	 */
+	if (test_bit(BRCMF_VIF_STATUS_CONNECTING,
+		     &p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->sme_state))
+		msleep(50);
+
+	/* if scan is ongoing, abort current scan. */
+	if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status))
+		brcmf_abort_scanning(cfg);
+
+	memcpy(afx_hdl->tx_dst_addr, action_frame->da, ETH_ALEN);
+
+	/* To make sure to send successfully action frame, turn off mpc */
+	if (config_af_params.mpc_onoff == 0)
+		brcmf_set_mpc(ifp, 0);
+
+	/* set status and destination address before sending af */
+	if (p2p->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
+		/* set status to cancel the remained dwell time in rx process */
+		set_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME, &p2p->status);
+	}
+
+	p2p->af_sent_channel = 0;
+	set_bit(BRCMF_P2P_STATUS_SENDING_ACT_FRAME, &p2p->status);
+	/* validate channel and p2p ies */
+	if (config_af_params.search_channel &&
+	    IS_P2P_SOCIAL_CHANNEL(le32_to_cpu(af_params->channel)) &&
+	    p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->saved_ie.probe_req_ie_len) {
+		afx_hdl = &p2p->afx_hdl;
+		afx_hdl->peer_listen_chan = le32_to_cpu(af_params->channel);
+
+		if (brcmf_p2p_af_searching_channel(p2p) ==
+							P2P_INVALID_CHANNEL) {
+			brcmf_err("Couldn't find peer's channel.\n");
+			goto exit;
+		}
+
+		/* Abort scan even for VSDB scenarios. Scan gets aborted in
+		 * firmware but after the check of piggyback algorithm. To take
+		 * care of current piggback algo, lets abort the scan here
+		 * itself.
+		 */
+		brcmf_notify_escan_complete(cfg, ifp, true, true);
+
+		/* update channel */
+		af_params->channel = cpu_to_le32(afx_hdl->peer_chan);
+	}
+
+	tx_retry = 0;
+	while (!p2p->block_gon_req_tx &&
+	       (ack == false) && (tx_retry < P2P_AF_TX_MAX_RETRY)) {
+		ack = !brcmf_p2p_tx_action_frame(p2p, af_params);
+		tx_retry++;
+	}
+	if (ack == false) {
+		brcmf_err("Failed to send Action Frame(retry %d)\n", tx_retry);
+		clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status);
+	}
+
+exit:
+	clear_bit(BRCMF_P2P_STATUS_SENDING_ACT_FRAME, &p2p->status);
+
+	/* WAR: sometimes dongle does not keep the dwell time of 'actframe'.
+	 * if we coundn't get the next action response frame and dongle does
+	 * not keep the dwell time, go to listen state again to get next action
+	 * response frame.
+	 */
+	if (ack && config_af_params.extra_listen && !p2p->block_gon_req_tx &&
+	    test_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME, &p2p->status) &&
+	    p2p->af_sent_channel == afx_hdl->my_listen_chan) {
+		delta_ms = jiffies_to_msecs(jiffies - p2p->af_tx_sent_jiffies);
+		if (le32_to_cpu(af_params->dwell_time) > delta_ms)
+			extra_listen_time = le32_to_cpu(af_params->dwell_time) -
+					    delta_ms;
+		else
+			extra_listen_time = 0;
+		if (extra_listen_time > 50) {
+			set_bit(BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN,
+				&p2p->status);
+			brcmf_dbg(INFO, "Wait more time! actual af time:%d, calculated extra listen:%d\n",
+				  le32_to_cpu(af_params->dwell_time),
+				  extra_listen_time);
+			extra_listen_time += 100;
+			if (!brcmf_p2p_discover_listen(p2p,
+						       p2p->af_sent_channel,
+						       extra_listen_time)) {
+				unsigned long duration;
+
+				extra_listen_time += 100;
+				duration = msecs_to_jiffies(extra_listen_time);
+				wait_for_completion_timeout(&p2p->wait_next_af,
+							    duration);
+			}
+			clear_bit(BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN,
+				  &p2p->status);
+		}
+	}
+
+	if (p2p->block_gon_req_tx) {
+		/* if ack is true, supplicant will wait more time(100ms).
+		 * so we will return it as a success to get more time .
+		 */
+		p2p->block_gon_req_tx = false;
+		ack = true;
+	}
+
+	clear_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME, &p2p->status);
+	/* if all done, turn mpc on again */
+	if (config_af_params.mpc_onoff == 1)
+		brcmf_set_mpc(ifp, 1);
+
+	return ack;
+}
+
+/**
+ * brcmf_p2p_notify_rx_mgmt_p2p_probereq() - Event handler for p2p probe req.
+ *
+ * @ifp: interface pointer for which event was received.
+ * @e: even message.
+ * @data: payload of event message (probe request).
+ */
+s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
+					  const struct brcmf_event_msg *e,
+					  void *data)
+{
+	struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+	struct brcmf_p2p_info *p2p = &cfg->p2p;
+	struct afx_hdl *afx_hdl = &p2p->afx_hdl;
+	struct brcmf_cfg80211_vif *vif = ifp->vif;
+	struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data;
+	struct brcmu_chan ch;
+	u8 *mgmt_frame;
+	u32 mgmt_frame_len;
+	s32 freq;
+	u16 mgmt_type;
+
+	brcmf_dbg(INFO, "Enter: event %d reason %d\n", e->event_code,
+		  e->reason);
+
+	if (e->datalen < sizeof(*rxframe)) {
+		brcmf_dbg(SCAN, "Event data to small. Ignore\n");
+		return 0;
+	}
+
+	ch.chspec = be16_to_cpu(rxframe->chanspec);
+	cfg->d11inf.decchspec(&ch);
+
+	if (test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, &p2p->status) &&
+	    (ether_addr_equal(afx_hdl->tx_dst_addr, e->addr))) {
+		afx_hdl->peer_chan = ch.control_ch_num;
+		brcmf_dbg(INFO, "PROBE REQUEST: Peer found, channel=%d\n",
+			  afx_hdl->peer_chan);
+		complete(&afx_hdl->act_frm_scan);
+	}
+
+	/* Firmware sends us two proberesponses for each idx one. At the */
+	/* moment anything but bsscfgidx 0 is passed up to supplicant    */
+	if (e->bsscfgidx == 0)
+		return 0;
+
+	/* Filter any P2P probe reqs arriving during the GO-NEG Phase */
+	if (test_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status)) {
+		brcmf_dbg(INFO, "Filtering P2P probe_req in GO-NEG phase\n");
+		return 0;
+	}
+
+	/* Check if wpa_supplicant has registered for this frame */
+	brcmf_dbg(INFO, "vif->mgmt_rx_reg %04x\n", vif->mgmt_rx_reg);
+	mgmt_type = (IEEE80211_STYPE_PROBE_REQ & IEEE80211_FCTL_STYPE) >> 4;
+	if ((vif->mgmt_rx_reg & BIT(mgmt_type)) == 0)
+		return 0;
+
+	mgmt_frame = (u8 *)(rxframe + 1);
+	mgmt_frame_len = e->datalen - sizeof(*rxframe);
+	freq = ieee80211_channel_to_frequency(ch.control_ch_num,
+					      ch.band == BRCMU_CHAN_BAND_2G ?
+					      NL80211_BAND_2GHZ :
+					      NL80211_BAND_5GHZ);
+
+	cfg80211_rx_mgmt(&vif->wdev, freq, 0, mgmt_frame, mgmt_frame_len, 0);
+
+	brcmf_dbg(INFO, "mgmt_frame_len (%d) , e->datalen (%d), chanspec (%04x), freq (%d)\n",
+		  mgmt_frame_len, e->datalen, ch.chspec, freq);
+
+	return 0;
+}
+
+
+/**
+ * brcmf_p2p_get_current_chanspec() - Get current operation channel.
+ *
+ * @p2p: P2P specific data.
+ * @chanspec: chanspec to be returned.
+ */
+static void brcmf_p2p_get_current_chanspec(struct brcmf_p2p_info *p2p,
+					   u16 *chanspec)
+{
+	struct brcmf_if *ifp;
+	u8 mac_addr[ETH_ALEN];
+	struct brcmu_chan ch;
+	struct brcmf_bss_info_le *bi;
+	u8 *buf;
+
+	ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
+
+	if (brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSSID, mac_addr,
+				   ETH_ALEN) == 0) {
+		buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
+		if (buf != NULL) {
+			*(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
+			if (brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO,
+						   buf, WL_BSS_INFO_MAX) == 0) {
+				bi = (struct brcmf_bss_info_le *)(buf + 4);
+				*chanspec = le16_to_cpu(bi->chanspec);
+				kfree(buf);
+				return;
+			}
+			kfree(buf);
+		}
+	}
+	/* Use default channel for P2P */
+	ch.chnum = BRCMF_P2P_TEMP_CHAN;
+	ch.bw = BRCMU_CHAN_BW_20;
+	p2p->cfg->d11inf.encchspec(&ch);
+	*chanspec = ch.chspec;
+}
+
+/**
+ * Change a P2P Role.
+ * Parameters:
+ * @mac: MAC address of the BSS to change a role
+ * Returns 0 if success.
+ */
+int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg,
+		       enum brcmf_fil_p2p_if_types if_type)
+{
+	struct brcmf_p2p_info *p2p = &cfg->p2p;
+	struct brcmf_cfg80211_vif *vif;
+	struct brcmf_fil_p2p_if_le if_request;
+	s32 err;
+	u16 chanspec;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif;
+	if (!vif) {
+		brcmf_err("vif for P2PAPI_BSSCFG_PRIMARY does not exist\n");
+		return -EPERM;
+	}
+	brcmf_notify_escan_complete(cfg, vif->ifp, true, true);
+	vif = p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif;
+	if (!vif) {
+		brcmf_err("vif for P2PAPI_BSSCFG_CONNECTION does not exist\n");
+		return -EPERM;
+	}
+	brcmf_set_mpc(vif->ifp, 0);
+
+	/* In concurrency case, STA may be already associated in a particular */
+	/* channel. so retrieve the current channel of primary interface and  */
+	/* then start the virtual interface on that.                          */
+	brcmf_p2p_get_current_chanspec(p2p, &chanspec);
+
+	if_request.type = cpu_to_le16((u16)if_type);
+	if_request.chspec = cpu_to_le16(chanspec);
+	memcpy(if_request.addr, p2p->int_addr, sizeof(if_request.addr));
+
+	brcmf_cfg80211_arm_vif_event(cfg, vif);
+	err = brcmf_fil_iovar_data_set(vif->ifp, "p2p_ifupd", &if_request,
+				       sizeof(if_request));
+	if (err) {
+		brcmf_err("p2p_ifupd FAILED, err=%d\n", err);
+		brcmf_cfg80211_arm_vif_event(cfg, NULL);
+		return err;
+	}
+	err = brcmf_cfg80211_wait_vif_event(cfg, BRCMF_E_IF_CHANGE,
+					    BRCMF_VIF_EVENT_TIMEOUT);
+	brcmf_cfg80211_arm_vif_event(cfg, NULL);
+	if (!err)  {
+		brcmf_err("No BRCMF_E_IF_CHANGE event received\n");
+		return -EIO;
+	}
+
+	err = brcmf_fil_cmd_int_set(vif->ifp, BRCMF_C_SET_SCB_TIMEOUT,
+				    BRCMF_SCB_TIMEOUT_VALUE);
+
+	return err;
+}
+
+static int brcmf_p2p_request_p2p_if(struct brcmf_p2p_info *p2p,
+				    struct brcmf_if *ifp, u8 ea[ETH_ALEN],
+				    enum brcmf_fil_p2p_if_types iftype)
+{
+	struct brcmf_fil_p2p_if_le if_request;
+	int err;
+	u16 chanspec;
+
+	/* we need a default channel */
+	brcmf_p2p_get_current_chanspec(p2p, &chanspec);
+
+	/* fill the firmware request */
+	memcpy(if_request.addr, ea, ETH_ALEN);
+	if_request.type = cpu_to_le16((u16)iftype);
+	if_request.chspec = cpu_to_le16(chanspec);
+
+	err = brcmf_fil_iovar_data_set(ifp, "p2p_ifadd", &if_request,
+				       sizeof(if_request));
+
+	return err;
+}
+
+static int brcmf_p2p_disable_p2p_if(struct brcmf_cfg80211_vif *vif)
+{
+	struct brcmf_cfg80211_info *cfg = wdev_to_cfg(&vif->wdev);
+	struct net_device *pri_ndev = cfg_to_ndev(cfg);
+	struct brcmf_if *ifp = netdev_priv(pri_ndev);
+	u8 *addr = vif->wdev.netdev->dev_addr;
+
+	return brcmf_fil_iovar_data_set(ifp, "p2p_ifdis", addr, ETH_ALEN);
+}
+
+static int brcmf_p2p_release_p2p_if(struct brcmf_cfg80211_vif *vif)
+{
+	struct brcmf_cfg80211_info *cfg = wdev_to_cfg(&vif->wdev);
+	struct net_device *pri_ndev = cfg_to_ndev(cfg);
+	struct brcmf_if *ifp = netdev_priv(pri_ndev);
+	u8 *addr = vif->wdev.netdev->dev_addr;
+
+	return brcmf_fil_iovar_data_set(ifp, "p2p_ifdel", addr, ETH_ALEN);
+}
+
+/**
+ * brcmf_p2p_create_p2pdev() - create a P2P_DEVICE virtual interface.
+ *
+ * @p2p: P2P specific data.
+ * @wiphy: wiphy device of new interface.
+ * @addr: mac address for this new interface.
+ */
+static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p,
+						    struct wiphy *wiphy,
+						    u8 *addr)
+{
+	struct brcmf_cfg80211_vif *p2p_vif;
+	struct brcmf_if *p2p_ifp;
+	struct brcmf_if *pri_ifp;
+	int err;
+	u32 bsscfgidx;
+
+	if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
+		return ERR_PTR(-ENOSPC);
+
+	p2p_vif = brcmf_alloc_vif(p2p->cfg, NL80211_IFTYPE_P2P_DEVICE);
+	if (IS_ERR(p2p_vif)) {
+		brcmf_err("could not create discovery vif\n");
+		return (struct wireless_dev *)p2p_vif;
+	}
+
+	pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
+
+	/* firmware requires unique mac address for p2pdev interface */
+	if (addr && ether_addr_equal(addr, pri_ifp->mac_addr)) {
+		brcmf_err("discovery vif must be different from primary interface\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	brcmf_p2p_generate_bss_mac(p2p, addr);
+	brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
+
+	brcmf_cfg80211_arm_vif_event(p2p->cfg, p2p_vif);
+	brcmf_fweh_p2pdev_setup(pri_ifp, true);
+
+	/* Initialize P2P Discovery in the firmware */
+	err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
+	if (err < 0) {
+		brcmf_err("set p2p_disc error\n");
+		brcmf_fweh_p2pdev_setup(pri_ifp, false);
+		brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL);
+		goto fail;
+	}
+
+	/* wait for firmware event */
+	err = brcmf_cfg80211_wait_vif_event(p2p->cfg, BRCMF_E_IF_ADD,
+					    BRCMF_VIF_EVENT_TIMEOUT);
+	brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL);
+	brcmf_fweh_p2pdev_setup(pri_ifp, false);
+	if (!err) {
+		brcmf_err("timeout occurred\n");
+		err = -EIO;
+		goto fail;
+	}
+
+	/* discovery interface created */
+	p2p_ifp = p2p_vif->ifp;
+	p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
+	memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
+	memcpy(&p2p_vif->wdev.address, p2p->dev_addr, sizeof(p2p->dev_addr));
+
+	/* verify bsscfg index for P2P discovery */
+	err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bsscfgidx);
+	if (err < 0) {
+		brcmf_err("retrieving discover bsscfg index failed\n");
+		goto fail;
+	}
+
+	WARN_ON(p2p_ifp->bsscfgidx != bsscfgidx);
+
+	init_completion(&p2p->send_af_done);
+	INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler);
+	init_completion(&p2p->afx_hdl.act_frm_scan);
+	init_completion(&p2p->wait_next_af);
+
+	return &p2p_vif->wdev;
+
+fail:
+	brcmf_free_vif(p2p_vif);
+	return ERR_PTR(err);
+}
+
+/**
+ * brcmf_p2p_add_vif() - create a new P2P virtual interface.
+ *
+ * @wiphy: wiphy device of new interface.
+ * @name: name of the new interface.
+ * @name_assign_type: origin of the interface name
+ * @type: nl80211 interface type.
+ * @params: contains mac address for P2P device.
+ */
+struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
+				       unsigned char name_assign_type,
+				       enum nl80211_iftype type,
+				       struct vif_params *params)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
+	struct brcmf_cfg80211_vif *vif;
+	enum brcmf_fil_p2p_if_types iftype;
+	int err;
+
+	if (brcmf_cfg80211_vif_event_armed(cfg))
+		return ERR_PTR(-EBUSY);
+
+	brcmf_dbg(INFO, "adding vif \"%s\" (type=%d)\n", name, type);
+
+	switch (type) {
+	case NL80211_IFTYPE_P2P_CLIENT:
+		iftype = BRCMF_FIL_P2P_IF_CLIENT;
+		break;
+	case NL80211_IFTYPE_P2P_GO:
+		iftype = BRCMF_FIL_P2P_IF_GO;
+		break;
+	case NL80211_IFTYPE_P2P_DEVICE:
+		return brcmf_p2p_create_p2pdev(&cfg->p2p, wiphy,
+					       params->macaddr);
+	default:
+		return ERR_PTR(-EOPNOTSUPP);
+	}
+
+	vif = brcmf_alloc_vif(cfg, type);
+	if (IS_ERR(vif))
+		return (struct wireless_dev *)vif;
+	brcmf_cfg80211_arm_vif_event(cfg, vif);
+
+	err = brcmf_p2p_request_p2p_if(&cfg->p2p, ifp, cfg->p2p.int_addr,
+				       iftype);
+	if (err) {
+		brcmf_cfg80211_arm_vif_event(cfg, NULL);
+		goto fail;
+	}
+
+	/* wait for firmware event */
+	err = brcmf_cfg80211_wait_vif_event(cfg, BRCMF_E_IF_ADD,
+					    BRCMF_VIF_EVENT_TIMEOUT);
+	brcmf_cfg80211_arm_vif_event(cfg, NULL);
+	if (!err) {
+		brcmf_err("timeout occurred\n");
+		err = -EIO;
+		goto fail;
+	}
+
+	/* interface created in firmware */
+	ifp = vif->ifp;
+	if (!ifp) {
+		brcmf_err("no if pointer provided\n");
+		err = -ENOENT;
+		goto fail;
+	}
+
+	strncpy(ifp->ndev->name, name, sizeof(ifp->ndev->name) - 1);
+	ifp->ndev->name_assign_type = name_assign_type;
+	err = brcmf_net_attach(ifp, true);
+	if (err) {
+		brcmf_err("Registering netdevice failed\n");
+		free_netdev(ifp->ndev);
+		goto fail;
+	}
+
+	cfg->p2p.bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = vif;
+	/* Disable firmware roaming for P2P interface  */
+	brcmf_fil_iovar_int_set(ifp, "roam_off", 1);
+	if (iftype == BRCMF_FIL_P2P_IF_GO) {
+		/* set station timeout for p2p */
+		brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCB_TIMEOUT,
+				      BRCMF_SCB_TIMEOUT_VALUE);
+	}
+	return &ifp->vif->wdev;
+
+fail:
+	brcmf_free_vif(vif);
+	return ERR_PTR(err);
+}
+
+/**
+ * brcmf_p2p_del_vif() - delete a P2P virtual interface.
+ *
+ * @wiphy: wiphy device of interface.
+ * @wdev: wireless device of interface.
+ */
+int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_p2p_info *p2p = &cfg->p2p;
+	struct brcmf_cfg80211_vif *vif;
+	enum nl80211_iftype iftype;
+	bool wait_for_disable = false;
+	int err;
+
+	brcmf_dbg(TRACE, "delete P2P vif\n");
+	vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
+
+	iftype = vif->wdev.iftype;
+	brcmf_cfg80211_arm_vif_event(cfg, vif);
+	switch (iftype) {
+	case NL80211_IFTYPE_P2P_CLIENT:
+		if (test_bit(BRCMF_VIF_STATUS_DISCONNECTING, &vif->sme_state))
+			wait_for_disable = true;
+		break;
+
+	case NL80211_IFTYPE_P2P_GO:
+		if (!brcmf_p2p_disable_p2p_if(vif))
+			wait_for_disable = true;
+		break;
+
+	case NL80211_IFTYPE_P2P_DEVICE:
+		if (!p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
+			return 0;
+		brcmf_p2p_cancel_remain_on_channel(vif->ifp);
+		brcmf_p2p_deinit_discovery(p2p);
+		break;
+
+	default:
+		return -ENOTSUPP;
+	}
+
+	clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status);
+	brcmf_dbg(INFO, "P2P: GO_NEG_PHASE status cleared\n");
+
+	if (wait_for_disable)
+		wait_for_completion_timeout(&cfg->vif_disabled,
+					    BRCMF_P2P_DISABLE_TIMEOUT);
+
+	err = 0;
+	if (iftype != NL80211_IFTYPE_P2P_DEVICE) {
+		brcmf_vif_clear_mgmt_ies(vif);
+		err = brcmf_p2p_release_p2p_if(vif);
+	}
+	if (!err) {
+		/* wait for firmware event */
+		err = brcmf_cfg80211_wait_vif_event(cfg, BRCMF_E_IF_DEL,
+						    BRCMF_VIF_EVENT_TIMEOUT);
+		if (!err)
+			err = -EIO;
+		else
+			err = 0;
+	}
+	brcmf_remove_interface(vif->ifp, true);
+
+	brcmf_cfg80211_arm_vif_event(cfg, NULL);
+	if (iftype != NL80211_IFTYPE_P2P_DEVICE)
+		p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL;
+
+	return err;
+}
+
+void brcmf_p2p_ifp_removed(struct brcmf_if *ifp, bool rtnl_locked)
+{
+	struct brcmf_cfg80211_info *cfg;
+	struct brcmf_cfg80211_vif *vif;
+
+	brcmf_dbg(INFO, "P2P: device interface removed\n");
+	vif = ifp->vif;
+	cfg = wdev_to_cfg(&vif->wdev);
+	cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
+	if (!rtnl_locked)
+		rtnl_lock();
+	cfg80211_unregister_wdev(&vif->wdev);
+	if (!rtnl_locked)
+		rtnl_unlock();
+	brcmf_free_vif(vif);
+}
+
+int brcmf_p2p_start_device(struct wiphy *wiphy, struct wireless_dev *wdev)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_p2p_info *p2p = &cfg->p2p;
+	struct brcmf_cfg80211_vif *vif;
+	int err;
+
+	vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
+	mutex_lock(&cfg->usr_sync);
+	err = brcmf_p2p_enable_discovery(p2p);
+	if (!err)
+		set_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state);
+	mutex_unlock(&cfg->usr_sync);
+	return err;
+}
+
+void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev)
+{
+	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+	struct brcmf_p2p_info *p2p = &cfg->p2p;
+	struct brcmf_cfg80211_vif *vif;
+
+	vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
+	/* This call can be result of the unregister_wdev call. In that case
+	 * we dont want to do anything anymore. Just return. The config vif
+	 * will have been cleared at this point.
+	 */
+	if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif == vif) {
+		mutex_lock(&cfg->usr_sync);
+		/* Set the discovery state to SCAN */
+		(void)brcmf_p2p_set_discover_state(vif->ifp,
+						   WL_P2P_DISC_ST_SCAN, 0, 0);
+		brcmf_abort_scanning(cfg);
+		clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state);
+		mutex_unlock(&cfg->usr_sync);
+	}
+}
+
+/**
+ * brcmf_p2p_attach() - attach for P2P.
+ *
+ * @cfg: driver private data for cfg80211 interface.
+ * @p2pdev_forced: create p2p device interface at attach.
+ */
+s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced)
+{
+	struct brcmf_p2p_info *p2p;
+	struct brcmf_if *pri_ifp;
+	s32 err = 0;
+	void *err_ptr;
+
+	p2p = &cfg->p2p;
+	p2p->cfg = cfg;
+
+	pri_ifp = brcmf_get_ifp(cfg->pub, 0);
+	p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif;
+
+	if (p2pdev_forced) {
+		err_ptr = brcmf_p2p_create_p2pdev(p2p, NULL, NULL);
+		if (IS_ERR(err_ptr)) {
+			brcmf_err("P2P device creation failed.\n");
+			err = PTR_ERR(err_ptr);
+		}
+	} else {
+		p2p->p2pdev_dynamically = true;
+	}
+	return err;
+}
+
+/**
+ * brcmf_p2p_detach() - detach P2P.
+ *
+ * @p2p: P2P specific data.
+ */
+void brcmf_p2p_detach(struct brcmf_p2p_info *p2p)
+{
+	struct brcmf_cfg80211_vif *vif;
+
+	vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
+	if (vif != NULL) {
+		brcmf_p2p_cancel_remain_on_channel(vif->ifp);
+		brcmf_p2p_deinit_discovery(p2p);
+		brcmf_remove_interface(vif->ifp, false);
+	}
+	/* just set it all to zero */
+	memset(p2p, 0, sizeof(*p2p));
+}
+
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h
new file mode 100644
index 0000000..0e8b34d
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef WL_CFGP2P_H_
+#define WL_CFGP2P_H_
+
+#include <net/cfg80211.h>
+
+struct brcmf_cfg80211_info;
+
+/**
+ * enum p2p_bss_type - different type of BSS configurations.
+ *
+ * @P2PAPI_BSSCFG_PRIMARY: maps to driver's primary bsscfg.
+ * @P2PAPI_BSSCFG_DEVICE: maps to driver's P2P device discovery bsscfg.
+ * @P2PAPI_BSSCFG_CONNECTION: maps to driver's P2P connection bsscfg.
+ * @P2PAPI_BSSCFG_MAX: used for range checking.
+ */
+enum p2p_bss_type {
+	P2PAPI_BSSCFG_PRIMARY, /* maps to driver's primary bsscfg */
+	P2PAPI_BSSCFG_DEVICE, /* maps to driver's P2P device discovery bsscfg */
+	P2PAPI_BSSCFG_CONNECTION, /* maps to driver's P2P connection bsscfg */
+	P2PAPI_BSSCFG_MAX
+};
+
+/**
+ * struct p2p_bss - peer-to-peer bss related information.
+ *
+ * @vif: virtual interface of this P2P bss.
+ * @private_data: TBD
+ */
+struct p2p_bss {
+	struct brcmf_cfg80211_vif *vif;
+	void *private_data;
+};
+
+/**
+ * enum brcmf_p2p_status - P2P specific dongle status.
+ *
+ * @BRCMF_P2P_STATUS_IF_ADD: peer-to-peer vif add sent to dongle.
+ * @BRCMF_P2P_STATUS_IF_DEL: NOT-USED?
+ * @BRCMF_P2P_STATUS_IF_DELETING: peer-to-peer vif delete sent to dongle.
+ * @BRCMF_P2P_STATUS_IF_CHANGING: peer-to-peer vif change sent to dongle.
+ * @BRCMF_P2P_STATUS_IF_CHANGED: peer-to-peer vif change completed on dongle.
+ * @BRCMF_P2P_STATUS_ACTION_TX_COMPLETED: action frame tx completed.
+ * @BRCMF_P2P_STATUS_ACTION_TX_NOACK: action frame tx not acked.
+ * @BRCMF_P2P_STATUS_GO_NEG_PHASE: P2P GO negotiation ongoing.
+ * @BRCMF_P2P_STATUS_DISCOVER_LISTEN: P2P listen, remaining on channel.
+ * @BRCMF_P2P_STATUS_SENDING_ACT_FRAME: In the process of sending action frame.
+ * @BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN: extra listen time for af tx.
+ * @BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME: waiting for action frame response.
+ * @BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL: search channel for AF active.
+ */
+enum brcmf_p2p_status {
+	BRCMF_P2P_STATUS_ENABLED,
+	BRCMF_P2P_STATUS_IF_ADD,
+	BRCMF_P2P_STATUS_IF_DEL,
+	BRCMF_P2P_STATUS_IF_DELETING,
+	BRCMF_P2P_STATUS_IF_CHANGING,
+	BRCMF_P2P_STATUS_IF_CHANGED,
+	BRCMF_P2P_STATUS_ACTION_TX_COMPLETED,
+	BRCMF_P2P_STATUS_ACTION_TX_NOACK,
+	BRCMF_P2P_STATUS_GO_NEG_PHASE,
+	BRCMF_P2P_STATUS_DISCOVER_LISTEN,
+	BRCMF_P2P_STATUS_SENDING_ACT_FRAME,
+	BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN,
+	BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME,
+	BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL
+};
+
+/**
+ * struct afx_hdl - action frame off channel storage.
+ *
+ * @afx_work: worker thread for searching channel
+ * @act_frm_scan: thread synchronizing struct.
+ * @is_active: channel searching active.
+ * @peer_chan: current channel.
+ * @is_listen: sets mode for afx worker.
+ * @my_listen_chan: this peers listen channel.
+ * @peer_listen_chan: remote peers listen channel.
+ * @tx_dst_addr: mac address where tx af should be sent to.
+ */
+struct afx_hdl {
+	struct work_struct afx_work;
+	struct completion act_frm_scan;
+	bool is_active;
+	s32 peer_chan;
+	bool is_listen;
+	u16 my_listen_chan;
+	u16 peer_listen_chan;
+	u8 tx_dst_addr[ETH_ALEN];
+};
+
+/**
+ * struct brcmf_p2p_info - p2p specific driver information.
+ *
+ * @cfg: driver private data for cfg80211 interface.
+ * @status: status of P2P (see enum brcmf_p2p_status).
+ * @dev_addr: P2P device address.
+ * @int_addr: P2P interface address.
+ * @bss_idx: informate for P2P bss types.
+ * @listen_timer: timer for @WL_P2P_DISC_ST_LISTEN discover state.
+ * @listen_channel: channel for @WL_P2P_DISC_ST_LISTEN discover state.
+ * @remain_on_channel: contains copy of struct used by cfg80211.
+ * @remain_on_channel_cookie: cookie counter for remain on channel cmd
+ * @next_af_subtype: expected action frame subtype.
+ * @send_af_done: indication that action frame tx is complete.
+ * @afx_hdl: action frame search handler info.
+ * @af_sent_channel: channel action frame is sent.
+ * @af_tx_sent_jiffies: jiffies time when af tx was transmitted.
+ * @wait_next_af: thread synchronizing struct.
+ * @gon_req_action: about to send go negotiation requets frame.
+ * @block_gon_req_tx: drop tx go negotiation requets frame.
+ * @p2pdev_dynamically: is p2p device if created by module param or supplicant.
+ */
+struct brcmf_p2p_info {
+	struct brcmf_cfg80211_info *cfg;
+	unsigned long status;
+	u8 dev_addr[ETH_ALEN];
+	u8 int_addr[ETH_ALEN];
+	struct p2p_bss bss_idx[P2PAPI_BSSCFG_MAX];
+	struct timer_list listen_timer;
+	u8 listen_channel;
+	struct ieee80211_channel remain_on_channel;
+	u32 remain_on_channel_cookie;
+	u8 next_af_subtype;
+	struct completion send_af_done;
+	struct afx_hdl afx_hdl;
+	u32 af_sent_channel;
+	unsigned long af_tx_sent_jiffies;
+	struct completion wait_next_af;
+	bool gon_req_action;
+	bool block_gon_req_tx;
+	bool p2pdev_dynamically;
+};
+
+s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced);
+void brcmf_p2p_detach(struct brcmf_p2p_info *p2p);
+struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
+				       unsigned char name_assign_type,
+				       enum nl80211_iftype type,
+				       struct vif_params *params);
+int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev);
+int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg,
+		       enum brcmf_fil_p2p_if_types if_type);
+void brcmf_p2p_ifp_removed(struct brcmf_if *ifp, bool rtnl_locked);
+int brcmf_p2p_start_device(struct wiphy *wiphy, struct wireless_dev *wdev);
+void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev);
+int brcmf_p2p_scan_prep(struct wiphy *wiphy,
+			struct cfg80211_scan_request *request,
+			struct brcmf_cfg80211_vif *vif);
+int brcmf_p2p_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
+				struct ieee80211_channel *channel,
+				unsigned int duration, u64 *cookie);
+int brcmf_p2p_notify_listen_complete(struct brcmf_if *ifp,
+				     const struct brcmf_event_msg *e,
+				     void *data);
+void brcmf_p2p_cancel_remain_on_channel(struct brcmf_if *ifp);
+int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
+				     const struct brcmf_event_msg *e,
+				     void *data);
+int brcmf_p2p_notify_action_tx_complete(struct brcmf_if *ifp,
+					const struct brcmf_event_msg *e,
+					void *data);
+bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg,
+				 struct net_device *ndev,
+				 struct brcmf_fil_af_params_le *af_params);
+bool brcmf_p2p_scan_finding_common_channel(struct brcmf_cfg80211_info *cfg,
+					   struct brcmf_bss_info_le *bi);
+s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
+					  const struct brcmf_event_msg *e,
+					  void *data);
+#endif /* WL_CFGP2P_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
new file mode 100644
index 0000000..4fffa69
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -0,0 +1,2072 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/firmware.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/bcma/bcma.h>
+#include <linux/sched.h>
+#include <asm/unaligned.h>
+
+#include <soc.h>
+#include <chipcommon.h>
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+#include <brcm_hw_ids.h>
+
+#include "debug.h"
+#include "bus.h"
+#include "commonring.h"
+#include "msgbuf.h"
+#include "pcie.h"
+#include "firmware.h"
+#include "chip.h"
+#include "core.h"
+#include "common.h"
+
+
+enum brcmf_pcie_state {
+	BRCMFMAC_PCIE_STATE_DOWN,
+	BRCMFMAC_PCIE_STATE_UP
+};
+
+BRCMF_FW_DEF(43602, "brcmfmac43602-pcie");
+BRCMF_FW_DEF(4350, "brcmfmac4350-pcie");
+BRCMF_FW_DEF(4350C, "brcmfmac4350c2-pcie");
+BRCMF_FW_DEF(4356, "brcmfmac4356-pcie");
+BRCMF_FW_DEF(43570, "brcmfmac43570-pcie");
+BRCMF_FW_DEF(4358, "brcmfmac4358-pcie");
+BRCMF_FW_DEF(4359, "brcmfmac4359-pcie");
+BRCMF_FW_DEF(4365B, "brcmfmac4365b-pcie");
+BRCMF_FW_DEF(4365C, "brcmfmac4365c-pcie");
+BRCMF_FW_DEF(4366B, "brcmfmac4366b-pcie");
+BRCMF_FW_DEF(4366C, "brcmfmac4366c-pcie");
+BRCMF_FW_DEF(4371, "brcmfmac4371-pcie");
+
+static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
+	BRCMF_FW_ENTRY(BRCM_CC_43602_CHIP_ID, 0xFFFFFFFF, 43602),
+	BRCMF_FW_ENTRY(BRCM_CC_43465_CHIP_ID, 0xFFFFFFF0, 4366C),
+	BRCMF_FW_ENTRY(BRCM_CC_4350_CHIP_ID, 0x000000FF, 4350C),
+	BRCMF_FW_ENTRY(BRCM_CC_4350_CHIP_ID, 0xFFFFFF00, 4350),
+	BRCMF_FW_ENTRY(BRCM_CC_43525_CHIP_ID, 0xFFFFFFF0, 4365C),
+	BRCMF_FW_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356),
+	BRCMF_FW_ENTRY(BRCM_CC_43567_CHIP_ID, 0xFFFFFFFF, 43570),
+	BRCMF_FW_ENTRY(BRCM_CC_43569_CHIP_ID, 0xFFFFFFFF, 43570),
+	BRCMF_FW_ENTRY(BRCM_CC_43570_CHIP_ID, 0xFFFFFFFF, 43570),
+	BRCMF_FW_ENTRY(BRCM_CC_4358_CHIP_ID, 0xFFFFFFFF, 4358),
+	BRCMF_FW_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359),
+	BRCMF_FW_ENTRY(BRCM_CC_4365_CHIP_ID, 0x0000000F, 4365B),
+	BRCMF_FW_ENTRY(BRCM_CC_4365_CHIP_ID, 0xFFFFFFF0, 4365C),
+	BRCMF_FW_ENTRY(BRCM_CC_4366_CHIP_ID, 0x0000000F, 4366B),
+	BRCMF_FW_ENTRY(BRCM_CC_4366_CHIP_ID, 0xFFFFFFF0, 4366C),
+	BRCMF_FW_ENTRY(BRCM_CC_43664_CHIP_ID, 0xFFFFFFF0, 4366C),
+	BRCMF_FW_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371),
+};
+
+#define BRCMF_PCIE_FW_UP_TIMEOUT		2000 /* msec */
+
+#define BRCMF_PCIE_REG_MAP_SIZE			(32 * 1024)
+
+/* backplane addres space accessed by BAR0 */
+#define	BRCMF_PCIE_BAR0_WINDOW			0x80
+#define BRCMF_PCIE_BAR0_REG_SIZE		0x1000
+#define	BRCMF_PCIE_BAR0_WRAPPERBASE		0x70
+
+#define BRCMF_PCIE_BAR0_WRAPBASE_DMP_OFFSET	0x1000
+#define BRCMF_PCIE_BARO_PCIE_ENUM_OFFSET	0x2000
+
+#define BRCMF_PCIE_ARMCR4REG_BANKIDX		0x40
+#define BRCMF_PCIE_ARMCR4REG_BANKPDA		0x4C
+
+#define BRCMF_PCIE_REG_INTSTATUS		0x90
+#define BRCMF_PCIE_REG_INTMASK			0x94
+#define BRCMF_PCIE_REG_SBMBX			0x98
+
+#define BRCMF_PCIE_REG_LINK_STATUS_CTRL		0xBC
+
+#define BRCMF_PCIE_PCIE2REG_INTMASK		0x24
+#define BRCMF_PCIE_PCIE2REG_MAILBOXINT		0x48
+#define BRCMF_PCIE_PCIE2REG_MAILBOXMASK		0x4C
+#define BRCMF_PCIE_PCIE2REG_CONFIGADDR		0x120
+#define BRCMF_PCIE_PCIE2REG_CONFIGDATA		0x124
+#define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0	0x140
+#define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1	0x144
+
+#define BRCMF_PCIE2_INTA			0x01
+#define BRCMF_PCIE2_INTB			0x02
+
+#define BRCMF_PCIE_INT_0			0x01
+#define BRCMF_PCIE_INT_1			0x02
+#define BRCMF_PCIE_INT_DEF			(BRCMF_PCIE_INT_0 | \
+						 BRCMF_PCIE_INT_1)
+
+#define BRCMF_PCIE_MB_INT_FN0_0			0x0100
+#define BRCMF_PCIE_MB_INT_FN0_1			0x0200
+#define	BRCMF_PCIE_MB_INT_D2H0_DB0		0x10000
+#define	BRCMF_PCIE_MB_INT_D2H0_DB1		0x20000
+#define	BRCMF_PCIE_MB_INT_D2H1_DB0		0x40000
+#define	BRCMF_PCIE_MB_INT_D2H1_DB1		0x80000
+#define	BRCMF_PCIE_MB_INT_D2H2_DB0		0x100000
+#define	BRCMF_PCIE_MB_INT_D2H2_DB1		0x200000
+#define	BRCMF_PCIE_MB_INT_D2H3_DB0		0x400000
+#define	BRCMF_PCIE_MB_INT_D2H3_DB1		0x800000
+
+#define BRCMF_PCIE_MB_INT_D2H_DB		(BRCMF_PCIE_MB_INT_D2H0_DB0 | \
+						 BRCMF_PCIE_MB_INT_D2H0_DB1 | \
+						 BRCMF_PCIE_MB_INT_D2H1_DB0 | \
+						 BRCMF_PCIE_MB_INT_D2H1_DB1 | \
+						 BRCMF_PCIE_MB_INT_D2H2_DB0 | \
+						 BRCMF_PCIE_MB_INT_D2H2_DB1 | \
+						 BRCMF_PCIE_MB_INT_D2H3_DB0 | \
+						 BRCMF_PCIE_MB_INT_D2H3_DB1)
+
+#define BRCMF_PCIE_SHARED_VERSION_7		7
+#define BRCMF_PCIE_MIN_SHARED_VERSION		5
+#define BRCMF_PCIE_MAX_SHARED_VERSION		BRCMF_PCIE_SHARED_VERSION_7
+#define BRCMF_PCIE_SHARED_VERSION_MASK		0x00FF
+#define BRCMF_PCIE_SHARED_DMA_INDEX		0x10000
+#define BRCMF_PCIE_SHARED_DMA_2B_IDX		0x100000
+#define BRCMF_PCIE_SHARED_HOSTRDY_DB1		0x10000000
+
+#define BRCMF_PCIE_FLAGS_HTOD_SPLIT		0x4000
+#define BRCMF_PCIE_FLAGS_DTOH_SPLIT		0x8000
+
+#define BRCMF_SHARED_MAX_RXBUFPOST_OFFSET	34
+#define BRCMF_SHARED_RING_BASE_OFFSET		52
+#define BRCMF_SHARED_RX_DATAOFFSET_OFFSET	36
+#define BRCMF_SHARED_CONSOLE_ADDR_OFFSET	20
+#define BRCMF_SHARED_HTOD_MB_DATA_ADDR_OFFSET	40
+#define BRCMF_SHARED_DTOH_MB_DATA_ADDR_OFFSET	44
+#define BRCMF_SHARED_RING_INFO_ADDR_OFFSET	48
+#define BRCMF_SHARED_DMA_SCRATCH_LEN_OFFSET	52
+#define BRCMF_SHARED_DMA_SCRATCH_ADDR_OFFSET	56
+#define BRCMF_SHARED_DMA_RINGUPD_LEN_OFFSET	64
+#define BRCMF_SHARED_DMA_RINGUPD_ADDR_OFFSET	68
+
+#define BRCMF_RING_H2D_RING_COUNT_OFFSET	0
+#define BRCMF_RING_D2H_RING_COUNT_OFFSET	1
+#define BRCMF_RING_H2D_RING_MEM_OFFSET		4
+#define BRCMF_RING_H2D_RING_STATE_OFFSET	8
+
+#define BRCMF_RING_MEM_BASE_ADDR_OFFSET		8
+#define BRCMF_RING_MAX_ITEM_OFFSET		4
+#define BRCMF_RING_LEN_ITEMS_OFFSET		6
+#define BRCMF_RING_MEM_SZ			16
+#define BRCMF_RING_STATE_SZ			8
+
+#define BRCMF_DEF_MAX_RXBUFPOST			255
+
+#define BRCMF_CONSOLE_BUFADDR_OFFSET		8
+#define BRCMF_CONSOLE_BUFSIZE_OFFSET		12
+#define BRCMF_CONSOLE_WRITEIDX_OFFSET		16
+
+#define BRCMF_DMA_D2H_SCRATCH_BUF_LEN		8
+#define BRCMF_DMA_D2H_RINGUPD_BUF_LEN		1024
+
+#define BRCMF_D2H_DEV_D3_ACK			0x00000001
+#define BRCMF_D2H_DEV_DS_ENTER_REQ		0x00000002
+#define BRCMF_D2H_DEV_DS_EXIT_NOTE		0x00000004
+#define BRCMF_D2H_DEV_FWHALT			0x10000000
+
+#define BRCMF_H2D_HOST_D3_INFORM		0x00000001
+#define BRCMF_H2D_HOST_DS_ACK			0x00000002
+#define BRCMF_H2D_HOST_D0_INFORM_IN_USE		0x00000008
+#define BRCMF_H2D_HOST_D0_INFORM		0x00000010
+
+#define BRCMF_PCIE_MBDATA_TIMEOUT		msecs_to_jiffies(2000)
+
+#define BRCMF_PCIE_CFGREG_STATUS_CMD		0x4
+#define BRCMF_PCIE_CFGREG_PM_CSR		0x4C
+#define BRCMF_PCIE_CFGREG_MSI_CAP		0x58
+#define BRCMF_PCIE_CFGREG_MSI_ADDR_L		0x5C
+#define BRCMF_PCIE_CFGREG_MSI_ADDR_H		0x60
+#define BRCMF_PCIE_CFGREG_MSI_DATA		0x64
+#define BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL	0xBC
+#define BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL2	0xDC
+#define BRCMF_PCIE_CFGREG_RBAR_CTRL		0x228
+#define BRCMF_PCIE_CFGREG_PML1_SUB_CTRL1	0x248
+#define BRCMF_PCIE_CFGREG_REG_BAR2_CONFIG	0x4E0
+#define BRCMF_PCIE_CFGREG_REG_BAR3_CONFIG	0x4F4
+#define BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB	3
+
+/* Magic number at a magic location to find RAM size */
+#define BRCMF_RAMSIZE_MAGIC			0x534d4152	/* SMAR */
+#define BRCMF_RAMSIZE_OFFSET			0x6c
+
+
+struct brcmf_pcie_console {
+	u32 base_addr;
+	u32 buf_addr;
+	u32 bufsize;
+	u32 read_idx;
+	u8 log_str[256];
+	u8 log_idx;
+};
+
+struct brcmf_pcie_shared_info {
+	u32 tcm_base_address;
+	u32 flags;
+	struct brcmf_pcie_ringbuf *commonrings[BRCMF_NROF_COMMON_MSGRINGS];
+	struct brcmf_pcie_ringbuf *flowrings;
+	u16 max_rxbufpost;
+	u16 max_flowrings;
+	u16 max_submissionrings;
+	u16 max_completionrings;
+	u32 rx_dataoffset;
+	u32 htod_mb_data_addr;
+	u32 dtoh_mb_data_addr;
+	u32 ring_info_addr;
+	struct brcmf_pcie_console console;
+	void *scratch;
+	dma_addr_t scratch_dmahandle;
+	void *ringupd;
+	dma_addr_t ringupd_dmahandle;
+	u8 version;
+};
+
+struct brcmf_pcie_core_info {
+	u32 base;
+	u32 wrapbase;
+};
+
+struct brcmf_pciedev_info {
+	enum brcmf_pcie_state state;
+	bool in_irq;
+	struct pci_dev *pdev;
+	char fw_name[BRCMF_FW_NAME_LEN];
+	char nvram_name[BRCMF_FW_NAME_LEN];
+	void __iomem *regs;
+	void __iomem *tcm;
+	u32 ram_base;
+	u32 ram_size;
+	struct brcmf_chip *ci;
+	u32 coreid;
+	struct brcmf_pcie_shared_info shared;
+	wait_queue_head_t mbdata_resp_wait;
+	bool mbdata_completed;
+	bool irq_allocated;
+	bool wowl_enabled;
+	u8 dma_idx_sz;
+	void *idxbuf;
+	u32 idxbuf_sz;
+	dma_addr_t idxbuf_dmahandle;
+	u16 (*read_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset);
+	void (*write_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+			  u16 value);
+	struct brcmf_mp_device *settings;
+};
+
+struct brcmf_pcie_ringbuf {
+	struct brcmf_commonring commonring;
+	dma_addr_t dma_handle;
+	u32 w_idx_addr;
+	u32 r_idx_addr;
+	struct brcmf_pciedev_info *devinfo;
+	u8 id;
+};
+
+/**
+ * struct brcmf_pcie_dhi_ringinfo - dongle/host interface shared ring info
+ *
+ * @ringmem: dongle memory pointer to ring memory location
+ * @h2d_w_idx_ptr: h2d ring write indices dongle memory pointers
+ * @h2d_r_idx_ptr: h2d ring read indices dongle memory pointers
+ * @d2h_w_idx_ptr: d2h ring write indices dongle memory pointers
+ * @d2h_r_idx_ptr: d2h ring read indices dongle memory pointers
+ * @h2d_w_idx_hostaddr: h2d ring write indices host memory pointers
+ * @h2d_r_idx_hostaddr: h2d ring read indices host memory pointers
+ * @d2h_w_idx_hostaddr: d2h ring write indices host memory pointers
+ * @d2h_r_idx_hostaddr: d2h ring reaD indices host memory pointers
+ * @max_flowrings: maximum number of tx flow rings supported.
+ * @max_submissionrings: maximum number of submission rings(h2d) supported.
+ * @max_completionrings: maximum number of completion rings(d2h) supported.
+ */
+struct brcmf_pcie_dhi_ringinfo {
+	__le32			ringmem;
+	__le32			h2d_w_idx_ptr;
+	__le32			h2d_r_idx_ptr;
+	__le32			d2h_w_idx_ptr;
+	__le32			d2h_r_idx_ptr;
+	struct msgbuf_buf_addr	h2d_w_idx_hostaddr;
+	struct msgbuf_buf_addr	h2d_r_idx_hostaddr;
+	struct msgbuf_buf_addr	d2h_w_idx_hostaddr;
+	struct msgbuf_buf_addr	d2h_r_idx_hostaddr;
+	__le16			max_flowrings;
+	__le16			max_submissionrings;
+	__le16			max_completionrings;
+};
+
+static const u32 brcmf_ring_max_item[BRCMF_NROF_COMMON_MSGRINGS] = {
+	BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM,
+	BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM,
+	BRCMF_D2H_MSGRING_CONTROL_COMPLETE_MAX_ITEM,
+	BRCMF_D2H_MSGRING_TX_COMPLETE_MAX_ITEM,
+	BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM
+};
+
+static const u32 brcmf_ring_itemsize_pre_v7[BRCMF_NROF_COMMON_MSGRINGS] = {
+	BRCMF_H2D_MSGRING_CONTROL_SUBMIT_ITEMSIZE,
+	BRCMF_H2D_MSGRING_RXPOST_SUBMIT_ITEMSIZE,
+	BRCMF_D2H_MSGRING_CONTROL_COMPLETE_ITEMSIZE,
+	BRCMF_D2H_MSGRING_TX_COMPLETE_ITEMSIZE_PRE_V7,
+	BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE_PRE_V7
+};
+
+static const u32 brcmf_ring_itemsize[BRCMF_NROF_COMMON_MSGRINGS] = {
+	BRCMF_H2D_MSGRING_CONTROL_SUBMIT_ITEMSIZE,
+	BRCMF_H2D_MSGRING_RXPOST_SUBMIT_ITEMSIZE,
+	BRCMF_D2H_MSGRING_CONTROL_COMPLETE_ITEMSIZE,
+	BRCMF_D2H_MSGRING_TX_COMPLETE_ITEMSIZE,
+	BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE
+};
+
+
+static u32
+brcmf_pcie_read_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset)
+{
+	void __iomem *address = devinfo->regs + reg_offset;
+
+	return (ioread32(address));
+}
+
+
+static void
+brcmf_pcie_write_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset,
+		       u32 value)
+{
+	void __iomem *address = devinfo->regs + reg_offset;
+
+	iowrite32(value, address);
+}
+
+
+static u8
+brcmf_pcie_read_tcm8(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
+{
+	void __iomem *address = devinfo->tcm + mem_offset;
+
+	return (ioread8(address));
+}
+
+
+static u16
+brcmf_pcie_read_tcm16(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
+{
+	void __iomem *address = devinfo->tcm + mem_offset;
+
+	return (ioread16(address));
+}
+
+
+static void
+brcmf_pcie_write_tcm16(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+		       u16 value)
+{
+	void __iomem *address = devinfo->tcm + mem_offset;
+
+	iowrite16(value, address);
+}
+
+
+static u16
+brcmf_pcie_read_idx(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
+{
+	u16 *address = devinfo->idxbuf + mem_offset;
+
+	return (*(address));
+}
+
+
+static void
+brcmf_pcie_write_idx(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+		     u16 value)
+{
+	u16 *address = devinfo->idxbuf + mem_offset;
+
+	*(address) = value;
+}
+
+
+static u32
+brcmf_pcie_read_tcm32(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
+{
+	void __iomem *address = devinfo->tcm + mem_offset;
+
+	return (ioread32(address));
+}
+
+
+static void
+brcmf_pcie_write_tcm32(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+		       u32 value)
+{
+	void __iomem *address = devinfo->tcm + mem_offset;
+
+	iowrite32(value, address);
+}
+
+
+static u32
+brcmf_pcie_read_ram32(struct brcmf_pciedev_info *devinfo, u32 mem_offset)
+{
+	void __iomem *addr = devinfo->tcm + devinfo->ci->rambase + mem_offset;
+
+	return (ioread32(addr));
+}
+
+
+static void
+brcmf_pcie_write_ram32(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+		       u32 value)
+{
+	void __iomem *addr = devinfo->tcm + devinfo->ci->rambase + mem_offset;
+
+	iowrite32(value, addr);
+}
+
+
+static void
+brcmf_pcie_copy_mem_todev(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+			  void *srcaddr, u32 len)
+{
+	void __iomem *address = devinfo->tcm + mem_offset;
+	__le32 *src32;
+	__le16 *src16;
+	u8 *src8;
+
+	if (((ulong)address & 4) || ((ulong)srcaddr & 4) || (len & 4)) {
+		if (((ulong)address & 2) || ((ulong)srcaddr & 2) || (len & 2)) {
+			src8 = (u8 *)srcaddr;
+			while (len) {
+				iowrite8(*src8, address);
+				address++;
+				src8++;
+				len--;
+			}
+		} else {
+			len = len / 2;
+			src16 = (__le16 *)srcaddr;
+			while (len) {
+				iowrite16(le16_to_cpu(*src16), address);
+				address += 2;
+				src16++;
+				len--;
+			}
+		}
+	} else {
+		len = len / 4;
+		src32 = (__le32 *)srcaddr;
+		while (len) {
+			iowrite32(le32_to_cpu(*src32), address);
+			address += 4;
+			src32++;
+			len--;
+		}
+	}
+}
+
+
+static void
+brcmf_pcie_copy_dev_tomem(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
+			  void *dstaddr, u32 len)
+{
+	void __iomem *address = devinfo->tcm + mem_offset;
+	__le32 *dst32;
+	__le16 *dst16;
+	u8 *dst8;
+
+	if (((ulong)address & 4) || ((ulong)dstaddr & 4) || (len & 4)) {
+		if (((ulong)address & 2) || ((ulong)dstaddr & 2) || (len & 2)) {
+			dst8 = (u8 *)dstaddr;
+			while (len) {
+				*dst8 = ioread8(address);
+				address++;
+				dst8++;
+				len--;
+			}
+		} else {
+			len = len / 2;
+			dst16 = (__le16 *)dstaddr;
+			while (len) {
+				*dst16 = cpu_to_le16(ioread16(address));
+				address += 2;
+				dst16++;
+				len--;
+			}
+		}
+	} else {
+		len = len / 4;
+		dst32 = (__le32 *)dstaddr;
+		while (len) {
+			*dst32 = cpu_to_le32(ioread32(address));
+			address += 4;
+			dst32++;
+			len--;
+		}
+	}
+}
+
+
+#define WRITECC32(devinfo, reg, value) brcmf_pcie_write_reg32(devinfo, \
+		CHIPCREGOFFS(reg), value)
+
+
+static void
+brcmf_pcie_select_core(struct brcmf_pciedev_info *devinfo, u16 coreid)
+{
+	const struct pci_dev *pdev = devinfo->pdev;
+	struct brcmf_core *core;
+	u32 bar0_win;
+
+	core = brcmf_chip_get_core(devinfo->ci, coreid);
+	if (core) {
+		bar0_win = core->base;
+		pci_write_config_dword(pdev, BRCMF_PCIE_BAR0_WINDOW, bar0_win);
+		if (pci_read_config_dword(pdev, BRCMF_PCIE_BAR0_WINDOW,
+					  &bar0_win) == 0) {
+			if (bar0_win != core->base) {
+				bar0_win = core->base;
+				pci_write_config_dword(pdev,
+						       BRCMF_PCIE_BAR0_WINDOW,
+						       bar0_win);
+			}
+		}
+	} else {
+		brcmf_err("Unsupported core selected %x\n", coreid);
+	}
+}
+
+
+static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo)
+{
+	struct brcmf_core *core;
+	u16 cfg_offset[] = { BRCMF_PCIE_CFGREG_STATUS_CMD,
+			     BRCMF_PCIE_CFGREG_PM_CSR,
+			     BRCMF_PCIE_CFGREG_MSI_CAP,
+			     BRCMF_PCIE_CFGREG_MSI_ADDR_L,
+			     BRCMF_PCIE_CFGREG_MSI_ADDR_H,
+			     BRCMF_PCIE_CFGREG_MSI_DATA,
+			     BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL2,
+			     BRCMF_PCIE_CFGREG_RBAR_CTRL,
+			     BRCMF_PCIE_CFGREG_PML1_SUB_CTRL1,
+			     BRCMF_PCIE_CFGREG_REG_BAR2_CONFIG,
+			     BRCMF_PCIE_CFGREG_REG_BAR3_CONFIG };
+	u32 i;
+	u32 val;
+	u32 lsc;
+
+	if (!devinfo->ci)
+		return;
+
+	/* Disable ASPM */
+	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+	pci_read_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,
+			      &lsc);
+	val = lsc & (~BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB);
+	pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,
+			       val);
+
+	/* Watchdog reset */
+	brcmf_pcie_select_core(devinfo, BCMA_CORE_CHIPCOMMON);
+	WRITECC32(devinfo, watchdog, 4);
+	msleep(100);
+
+	/* Restore ASPM */
+	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+	pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL,
+			       lsc);
+
+	core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2);
+	if (core->rev <= 13) {
+		for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) {
+			brcmf_pcie_write_reg32(devinfo,
+					       BRCMF_PCIE_PCIE2REG_CONFIGADDR,
+					       cfg_offset[i]);
+			val = brcmf_pcie_read_reg32(devinfo,
+				BRCMF_PCIE_PCIE2REG_CONFIGDATA);
+			brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n",
+				  cfg_offset[i], val);
+			brcmf_pcie_write_reg32(devinfo,
+					       BRCMF_PCIE_PCIE2REG_CONFIGDATA,
+					       val);
+		}
+	}
+}
+
+
+static void brcmf_pcie_attach(struct brcmf_pciedev_info *devinfo)
+{
+	u32 config;
+
+	/* BAR1 window may not be sized properly */
+	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0);
+	config = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA);
+	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, config);
+
+	device_wakeup_enable(&devinfo->pdev->dev);
+}
+
+
+static int brcmf_pcie_enter_download_state(struct brcmf_pciedev_info *devinfo)
+{
+	if (devinfo->ci->chip == BRCM_CC_43602_CHIP_ID) {
+		brcmf_pcie_select_core(devinfo, BCMA_CORE_ARM_CR4);
+		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKIDX,
+				       5);
+		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKPDA,
+				       0);
+		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKIDX,
+				       7);
+		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKPDA,
+				       0);
+	}
+	return 0;
+}
+
+
+static int brcmf_pcie_exit_download_state(struct brcmf_pciedev_info *devinfo,
+					  u32 resetintr)
+{
+	struct brcmf_core *core;
+
+	if (devinfo->ci->chip == BRCM_CC_43602_CHIP_ID) {
+		core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_INTERNAL_MEM);
+		brcmf_chip_resetcore(core, 0, 0, 0);
+	}
+
+	if (!brcmf_chip_set_active(devinfo->ci, resetintr))
+		return -EINVAL;
+	return 0;
+}
+
+
+static int
+brcmf_pcie_send_mb_data(struct brcmf_pciedev_info *devinfo, u32 htod_mb_data)
+{
+	struct brcmf_pcie_shared_info *shared;
+	u32 addr;
+	u32 cur_htod_mb_data;
+	u32 i;
+
+	shared = &devinfo->shared;
+	addr = shared->htod_mb_data_addr;
+	cur_htod_mb_data = brcmf_pcie_read_tcm32(devinfo, addr);
+
+	if (cur_htod_mb_data != 0)
+		brcmf_dbg(PCIE, "MB transaction is already pending 0x%04x\n",
+			  cur_htod_mb_data);
+
+	i = 0;
+	while (cur_htod_mb_data != 0) {
+		msleep(10);
+		i++;
+		if (i > 100)
+			return -EIO;
+		cur_htod_mb_data = brcmf_pcie_read_tcm32(devinfo, addr);
+	}
+
+	brcmf_pcie_write_tcm32(devinfo, addr, htod_mb_data);
+	pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_SBMBX, 1);
+	pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_SBMBX, 1);
+
+	return 0;
+}
+
+
+static void brcmf_pcie_handle_mb_data(struct brcmf_pciedev_info *devinfo)
+{
+	struct brcmf_pcie_shared_info *shared;
+	u32 addr;
+	u32 dtoh_mb_data;
+
+	shared = &devinfo->shared;
+	addr = shared->dtoh_mb_data_addr;
+	dtoh_mb_data = brcmf_pcie_read_tcm32(devinfo, addr);
+
+	if (!dtoh_mb_data)
+		return;
+
+	brcmf_pcie_write_tcm32(devinfo, addr, 0);
+
+	brcmf_dbg(PCIE, "D2H_MB_DATA: 0x%04x\n", dtoh_mb_data);
+	if (dtoh_mb_data & BRCMF_D2H_DEV_DS_ENTER_REQ)  {
+		brcmf_dbg(PCIE, "D2H_MB_DATA: DEEP SLEEP REQ\n");
+		brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_DS_ACK);
+		brcmf_dbg(PCIE, "D2H_MB_DATA: sent DEEP SLEEP ACK\n");
+	}
+	if (dtoh_mb_data & BRCMF_D2H_DEV_DS_EXIT_NOTE)
+		brcmf_dbg(PCIE, "D2H_MB_DATA: DEEP SLEEP EXIT\n");
+	if (dtoh_mb_data & BRCMF_D2H_DEV_D3_ACK) {
+		brcmf_dbg(PCIE, "D2H_MB_DATA: D3 ACK\n");
+		devinfo->mbdata_completed = true;
+		wake_up(&devinfo->mbdata_resp_wait);
+	}
+	if (dtoh_mb_data & BRCMF_D2H_DEV_FWHALT) {
+		brcmf_dbg(PCIE, "D2H_MB_DATA: FW HALT\n");
+		brcmf_dev_coredump(&devinfo->pdev->dev);
+	}
+}
+
+
+static void brcmf_pcie_bus_console_init(struct brcmf_pciedev_info *devinfo)
+{
+	struct brcmf_pcie_shared_info *shared;
+	struct brcmf_pcie_console *console;
+	u32 addr;
+
+	shared = &devinfo->shared;
+	console = &shared->console;
+	addr = shared->tcm_base_address + BRCMF_SHARED_CONSOLE_ADDR_OFFSET;
+	console->base_addr = brcmf_pcie_read_tcm32(devinfo, addr);
+
+	addr = console->base_addr + BRCMF_CONSOLE_BUFADDR_OFFSET;
+	console->buf_addr = brcmf_pcie_read_tcm32(devinfo, addr);
+	addr = console->base_addr + BRCMF_CONSOLE_BUFSIZE_OFFSET;
+	console->bufsize = brcmf_pcie_read_tcm32(devinfo, addr);
+
+	brcmf_dbg(FWCON, "Console: base %x, buf %x, size %d\n",
+		  console->base_addr, console->buf_addr, console->bufsize);
+}
+
+
+static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo)
+{
+	struct brcmf_pcie_console *console;
+	u32 addr;
+	u8 ch;
+	u32 newidx;
+
+	if (!BRCMF_FWCON_ON())
+		return;
+
+	console = &devinfo->shared.console;
+	addr = console->base_addr + BRCMF_CONSOLE_WRITEIDX_OFFSET;
+	newidx = brcmf_pcie_read_tcm32(devinfo, addr);
+	while (newidx != console->read_idx) {
+		addr = console->buf_addr + console->read_idx;
+		ch = brcmf_pcie_read_tcm8(devinfo, addr);
+		console->read_idx++;
+		if (console->read_idx == console->bufsize)
+			console->read_idx = 0;
+		if (ch == '\r')
+			continue;
+		console->log_str[console->log_idx] = ch;
+		console->log_idx++;
+		if ((ch != '\n') &&
+		    (console->log_idx == (sizeof(console->log_str) - 2))) {
+			ch = '\n';
+			console->log_str[console->log_idx] = ch;
+			console->log_idx++;
+		}
+		if (ch == '\n') {
+			console->log_str[console->log_idx] = 0;
+			pr_debug("CONSOLE: %s", console->log_str);
+			console->log_idx = 0;
+		}
+	}
+}
+
+
+static void brcmf_pcie_intr_disable(struct brcmf_pciedev_info *devinfo)
+{
+	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXMASK, 0);
+}
+
+
+static void brcmf_pcie_intr_enable(struct brcmf_pciedev_info *devinfo)
+{
+	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXMASK,
+			       BRCMF_PCIE_MB_INT_D2H_DB |
+			       BRCMF_PCIE_MB_INT_FN0_0 |
+			       BRCMF_PCIE_MB_INT_FN0_1);
+}
+
+static void brcmf_pcie_hostready(struct brcmf_pciedev_info *devinfo)
+{
+	if (devinfo->shared.flags & BRCMF_PCIE_SHARED_HOSTRDY_DB1)
+		brcmf_pcie_write_reg32(devinfo,
+				       BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1, 1);
+}
+
+static irqreturn_t brcmf_pcie_quick_check_isr(int irq, void *arg)
+{
+	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg;
+
+	if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT)) {
+		brcmf_pcie_intr_disable(devinfo);
+		brcmf_dbg(PCIE, "Enter\n");
+		return IRQ_WAKE_THREAD;
+	}
+	return IRQ_NONE;
+}
+
+
+static irqreturn_t brcmf_pcie_isr_thread(int irq, void *arg)
+{
+	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)arg;
+	u32 status;
+
+	devinfo->in_irq = true;
+	status = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT);
+	brcmf_dbg(PCIE, "Enter %x\n", status);
+	if (status) {
+		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT,
+				       status);
+		if (status & (BRCMF_PCIE_MB_INT_FN0_0 |
+			      BRCMF_PCIE_MB_INT_FN0_1))
+			brcmf_pcie_handle_mb_data(devinfo);
+		if (status & BRCMF_PCIE_MB_INT_D2H_DB) {
+			if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)
+				brcmf_proto_msgbuf_rx_trigger(
+							&devinfo->pdev->dev);
+		}
+	}
+	brcmf_pcie_bus_console_read(devinfo);
+	if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)
+		brcmf_pcie_intr_enable(devinfo);
+	devinfo->in_irq = false;
+	return IRQ_HANDLED;
+}
+
+
+static int brcmf_pcie_request_irq(struct brcmf_pciedev_info *devinfo)
+{
+	struct pci_dev *pdev;
+
+	pdev = devinfo->pdev;
+
+	brcmf_pcie_intr_disable(devinfo);
+
+	brcmf_dbg(PCIE, "Enter\n");
+
+	pci_enable_msi(pdev);
+	if (request_threaded_irq(pdev->irq, brcmf_pcie_quick_check_isr,
+				 brcmf_pcie_isr_thread, IRQF_SHARED,
+				 "brcmf_pcie_intr", devinfo)) {
+		pci_disable_msi(pdev);
+		brcmf_err("Failed to request IRQ %d\n", pdev->irq);
+		return -EIO;
+	}
+	devinfo->irq_allocated = true;
+	return 0;
+}
+
+
+static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo)
+{
+	struct pci_dev *pdev;
+	u32 status;
+	u32 count;
+
+	if (!devinfo->irq_allocated)
+		return;
+
+	pdev = devinfo->pdev;
+
+	brcmf_pcie_intr_disable(devinfo);
+	free_irq(pdev->irq, devinfo);
+	pci_disable_msi(pdev);
+
+	msleep(50);
+	count = 0;
+	while ((devinfo->in_irq) && (count < 20)) {
+		msleep(50);
+		count++;
+	}
+	if (devinfo->in_irq)
+		brcmf_err("Still in IRQ (processing) !!!\n");
+
+	status = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT);
+	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT, status);
+
+	devinfo->irq_allocated = false;
+}
+
+
+static int brcmf_pcie_ring_mb_write_rptr(void *ctx)
+{
+	struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;
+	struct brcmf_pciedev_info *devinfo = ring->devinfo;
+	struct brcmf_commonring *commonring = &ring->commonring;
+
+	if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
+		return -EIO;
+
+	brcmf_dbg(PCIE, "W r_ptr %d (%d), ring %d\n", commonring->r_ptr,
+		  commonring->w_ptr, ring->id);
+
+	devinfo->write_ptr(devinfo, ring->r_idx_addr, commonring->r_ptr);
+
+	return 0;
+}
+
+
+static int brcmf_pcie_ring_mb_write_wptr(void *ctx)
+{
+	struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;
+	struct brcmf_pciedev_info *devinfo = ring->devinfo;
+	struct brcmf_commonring *commonring = &ring->commonring;
+
+	if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
+		return -EIO;
+
+	brcmf_dbg(PCIE, "W w_ptr %d (%d), ring %d\n", commonring->w_ptr,
+		  commonring->r_ptr, ring->id);
+
+	devinfo->write_ptr(devinfo, ring->w_idx_addr, commonring->w_ptr);
+
+	return 0;
+}
+
+
+static int brcmf_pcie_ring_mb_ring_bell(void *ctx)
+{
+	struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;
+	struct brcmf_pciedev_info *devinfo = ring->devinfo;
+
+	if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
+		return -EIO;
+
+	brcmf_dbg(PCIE, "RING !\n");
+	/* Any arbitrary value will do, lets use 1 */
+	brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0, 1);
+
+	return 0;
+}
+
+
+static int brcmf_pcie_ring_mb_update_rptr(void *ctx)
+{
+	struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;
+	struct brcmf_pciedev_info *devinfo = ring->devinfo;
+	struct brcmf_commonring *commonring = &ring->commonring;
+
+	if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
+		return -EIO;
+
+	commonring->r_ptr = devinfo->read_ptr(devinfo, ring->r_idx_addr);
+
+	brcmf_dbg(PCIE, "R r_ptr %d (%d), ring %d\n", commonring->r_ptr,
+		  commonring->w_ptr, ring->id);
+
+	return 0;
+}
+
+
+static int brcmf_pcie_ring_mb_update_wptr(void *ctx)
+{
+	struct brcmf_pcie_ringbuf *ring = (struct brcmf_pcie_ringbuf *)ctx;
+	struct brcmf_pciedev_info *devinfo = ring->devinfo;
+	struct brcmf_commonring *commonring = &ring->commonring;
+
+	if (devinfo->state != BRCMFMAC_PCIE_STATE_UP)
+		return -EIO;
+
+	commonring->w_ptr = devinfo->read_ptr(devinfo, ring->w_idx_addr);
+
+	brcmf_dbg(PCIE, "R w_ptr %d (%d), ring %d\n", commonring->w_ptr,
+		  commonring->r_ptr, ring->id);
+
+	return 0;
+}
+
+
+static void *
+brcmf_pcie_init_dmabuffer_for_device(struct brcmf_pciedev_info *devinfo,
+				     u32 size, u32 tcm_dma_phys_addr,
+				     dma_addr_t *dma_handle)
+{
+	void *ring;
+	u64 address;
+
+	ring = dma_alloc_coherent(&devinfo->pdev->dev, size, dma_handle,
+				  GFP_KERNEL);
+	if (!ring)
+		return NULL;
+
+	address = (u64)*dma_handle;
+	brcmf_pcie_write_tcm32(devinfo, tcm_dma_phys_addr,
+			       address & 0xffffffff);
+	brcmf_pcie_write_tcm32(devinfo, tcm_dma_phys_addr + 4, address >> 32);
+
+	memset(ring, 0, size);
+
+	return (ring);
+}
+
+
+static struct brcmf_pcie_ringbuf *
+brcmf_pcie_alloc_dma_and_ring(struct brcmf_pciedev_info *devinfo, u32 ring_id,
+			      u32 tcm_ring_phys_addr)
+{
+	void *dma_buf;
+	dma_addr_t dma_handle;
+	struct brcmf_pcie_ringbuf *ring;
+	u32 size;
+	u32 addr;
+	const u32 *ring_itemsize_array;
+
+	if (devinfo->shared.version < BRCMF_PCIE_SHARED_VERSION_7)
+		ring_itemsize_array = brcmf_ring_itemsize_pre_v7;
+	else
+		ring_itemsize_array = brcmf_ring_itemsize;
+
+	size = brcmf_ring_max_item[ring_id] * ring_itemsize_array[ring_id];
+	dma_buf = brcmf_pcie_init_dmabuffer_for_device(devinfo, size,
+			tcm_ring_phys_addr + BRCMF_RING_MEM_BASE_ADDR_OFFSET,
+			&dma_handle);
+	if (!dma_buf)
+		return NULL;
+
+	addr = tcm_ring_phys_addr + BRCMF_RING_MAX_ITEM_OFFSET;
+	brcmf_pcie_write_tcm16(devinfo, addr, brcmf_ring_max_item[ring_id]);
+	addr = tcm_ring_phys_addr + BRCMF_RING_LEN_ITEMS_OFFSET;
+	brcmf_pcie_write_tcm16(devinfo, addr, ring_itemsize_array[ring_id]);
+
+	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
+	if (!ring) {
+		dma_free_coherent(&devinfo->pdev->dev, size, dma_buf,
+				  dma_handle);
+		return NULL;
+	}
+	brcmf_commonring_config(&ring->commonring, brcmf_ring_max_item[ring_id],
+				ring_itemsize_array[ring_id], dma_buf);
+	ring->dma_handle = dma_handle;
+	ring->devinfo = devinfo;
+	brcmf_commonring_register_cb(&ring->commonring,
+				     brcmf_pcie_ring_mb_ring_bell,
+				     brcmf_pcie_ring_mb_update_rptr,
+				     brcmf_pcie_ring_mb_update_wptr,
+				     brcmf_pcie_ring_mb_write_rptr,
+				     brcmf_pcie_ring_mb_write_wptr, ring);
+
+	return (ring);
+}
+
+
+static void brcmf_pcie_release_ringbuffer(struct device *dev,
+					  struct brcmf_pcie_ringbuf *ring)
+{
+	void *dma_buf;
+	u32 size;
+
+	if (!ring)
+		return;
+
+	dma_buf = ring->commonring.buf_addr;
+	if (dma_buf) {
+		size = ring->commonring.depth * ring->commonring.item_len;
+		dma_free_coherent(dev, size, dma_buf, ring->dma_handle);
+	}
+	kfree(ring);
+}
+
+
+static void brcmf_pcie_release_ringbuffers(struct brcmf_pciedev_info *devinfo)
+{
+	u32 i;
+
+	for (i = 0; i < BRCMF_NROF_COMMON_MSGRINGS; i++) {
+		brcmf_pcie_release_ringbuffer(&devinfo->pdev->dev,
+					      devinfo->shared.commonrings[i]);
+		devinfo->shared.commonrings[i] = NULL;
+	}
+	kfree(devinfo->shared.flowrings);
+	devinfo->shared.flowrings = NULL;
+	if (devinfo->idxbuf) {
+		dma_free_coherent(&devinfo->pdev->dev,
+				  devinfo->idxbuf_sz,
+				  devinfo->idxbuf,
+				  devinfo->idxbuf_dmahandle);
+		devinfo->idxbuf = NULL;
+	}
+}
+
+
+static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo)
+{
+	struct brcmf_pcie_ringbuf *ring;
+	struct brcmf_pcie_ringbuf *rings;
+	u32 d2h_w_idx_ptr;
+	u32 d2h_r_idx_ptr;
+	u32 h2d_w_idx_ptr;
+	u32 h2d_r_idx_ptr;
+	u32 ring_mem_ptr;
+	u32 i;
+	u64 address;
+	u32 bufsz;
+	u8 idx_offset;
+	struct brcmf_pcie_dhi_ringinfo ringinfo;
+	u16 max_flowrings;
+	u16 max_submissionrings;
+	u16 max_completionrings;
+
+	memcpy_fromio(&ringinfo, devinfo->tcm + devinfo->shared.ring_info_addr,
+		      sizeof(ringinfo));
+	if (devinfo->shared.version >= 6) {
+		max_submissionrings = le16_to_cpu(ringinfo.max_submissionrings);
+		max_flowrings = le16_to_cpu(ringinfo.max_flowrings);
+		max_completionrings = le16_to_cpu(ringinfo.max_completionrings);
+	} else {
+		max_submissionrings = le16_to_cpu(ringinfo.max_flowrings);
+		max_flowrings = max_submissionrings -
+				BRCMF_NROF_H2D_COMMON_MSGRINGS;
+		max_completionrings = BRCMF_NROF_D2H_COMMON_MSGRINGS;
+	}
+
+	if (devinfo->dma_idx_sz != 0) {
+		bufsz = (max_submissionrings + max_completionrings) *
+			devinfo->dma_idx_sz * 2;
+		devinfo->idxbuf = dma_alloc_coherent(&devinfo->pdev->dev, bufsz,
+						     &devinfo->idxbuf_dmahandle,
+						     GFP_KERNEL);
+		if (!devinfo->idxbuf)
+			devinfo->dma_idx_sz = 0;
+	}
+
+	if (devinfo->dma_idx_sz == 0) {
+		d2h_w_idx_ptr = le32_to_cpu(ringinfo.d2h_w_idx_ptr);
+		d2h_r_idx_ptr = le32_to_cpu(ringinfo.d2h_r_idx_ptr);
+		h2d_w_idx_ptr = le32_to_cpu(ringinfo.h2d_w_idx_ptr);
+		h2d_r_idx_ptr = le32_to_cpu(ringinfo.h2d_r_idx_ptr);
+		idx_offset = sizeof(u32);
+		devinfo->write_ptr = brcmf_pcie_write_tcm16;
+		devinfo->read_ptr = brcmf_pcie_read_tcm16;
+		brcmf_dbg(PCIE, "Using TCM indices\n");
+	} else {
+		memset(devinfo->idxbuf, 0, bufsz);
+		devinfo->idxbuf_sz = bufsz;
+		idx_offset = devinfo->dma_idx_sz;
+		devinfo->write_ptr = brcmf_pcie_write_idx;
+		devinfo->read_ptr = brcmf_pcie_read_idx;
+
+		h2d_w_idx_ptr = 0;
+		address = (u64)devinfo->idxbuf_dmahandle;
+		ringinfo.h2d_w_idx_hostaddr.low_addr =
+			cpu_to_le32(address & 0xffffffff);
+		ringinfo.h2d_w_idx_hostaddr.high_addr =
+			cpu_to_le32(address >> 32);
+
+		h2d_r_idx_ptr = h2d_w_idx_ptr +
+				max_submissionrings * idx_offset;
+		address += max_submissionrings * idx_offset;
+		ringinfo.h2d_r_idx_hostaddr.low_addr =
+			cpu_to_le32(address & 0xffffffff);
+		ringinfo.h2d_r_idx_hostaddr.high_addr =
+			cpu_to_le32(address >> 32);
+
+		d2h_w_idx_ptr = h2d_r_idx_ptr +
+				max_submissionrings * idx_offset;
+		address += max_submissionrings * idx_offset;
+		ringinfo.d2h_w_idx_hostaddr.low_addr =
+			cpu_to_le32(address & 0xffffffff);
+		ringinfo.d2h_w_idx_hostaddr.high_addr =
+			cpu_to_le32(address >> 32);
+
+		d2h_r_idx_ptr = d2h_w_idx_ptr +
+				max_completionrings * idx_offset;
+		address += max_completionrings * idx_offset;
+		ringinfo.d2h_r_idx_hostaddr.low_addr =
+			cpu_to_le32(address & 0xffffffff);
+		ringinfo.d2h_r_idx_hostaddr.high_addr =
+			cpu_to_le32(address >> 32);
+
+		memcpy_toio(devinfo->tcm + devinfo->shared.ring_info_addr,
+			    &ringinfo, sizeof(ringinfo));
+		brcmf_dbg(PCIE, "Using host memory indices\n");
+	}
+
+	ring_mem_ptr = le32_to_cpu(ringinfo.ringmem);
+
+	for (i = 0; i < BRCMF_NROF_H2D_COMMON_MSGRINGS; i++) {
+		ring = brcmf_pcie_alloc_dma_and_ring(devinfo, i, ring_mem_ptr);
+		if (!ring)
+			goto fail;
+		ring->w_idx_addr = h2d_w_idx_ptr;
+		ring->r_idx_addr = h2d_r_idx_ptr;
+		ring->id = i;
+		devinfo->shared.commonrings[i] = ring;
+
+		h2d_w_idx_ptr += idx_offset;
+		h2d_r_idx_ptr += idx_offset;
+		ring_mem_ptr += BRCMF_RING_MEM_SZ;
+	}
+
+	for (i = BRCMF_NROF_H2D_COMMON_MSGRINGS;
+	     i < BRCMF_NROF_COMMON_MSGRINGS; i++) {
+		ring = brcmf_pcie_alloc_dma_and_ring(devinfo, i, ring_mem_ptr);
+		if (!ring)
+			goto fail;
+		ring->w_idx_addr = d2h_w_idx_ptr;
+		ring->r_idx_addr = d2h_r_idx_ptr;
+		ring->id = i;
+		devinfo->shared.commonrings[i] = ring;
+
+		d2h_w_idx_ptr += idx_offset;
+		d2h_r_idx_ptr += idx_offset;
+		ring_mem_ptr += BRCMF_RING_MEM_SZ;
+	}
+
+	devinfo->shared.max_flowrings = max_flowrings;
+	devinfo->shared.max_submissionrings = max_submissionrings;
+	devinfo->shared.max_completionrings = max_completionrings;
+	rings = kcalloc(max_flowrings, sizeof(*ring), GFP_KERNEL);
+	if (!rings)
+		goto fail;
+
+	brcmf_dbg(PCIE, "Nr of flowrings is %d\n", max_flowrings);
+
+	for (i = 0; i < max_flowrings; i++) {
+		ring = &rings[i];
+		ring->devinfo = devinfo;
+		ring->id = i + BRCMF_H2D_MSGRING_FLOWRING_IDSTART;
+		brcmf_commonring_register_cb(&ring->commonring,
+					     brcmf_pcie_ring_mb_ring_bell,
+					     brcmf_pcie_ring_mb_update_rptr,
+					     brcmf_pcie_ring_mb_update_wptr,
+					     brcmf_pcie_ring_mb_write_rptr,
+					     brcmf_pcie_ring_mb_write_wptr,
+					     ring);
+		ring->w_idx_addr = h2d_w_idx_ptr;
+		ring->r_idx_addr = h2d_r_idx_ptr;
+		h2d_w_idx_ptr += idx_offset;
+		h2d_r_idx_ptr += idx_offset;
+	}
+	devinfo->shared.flowrings = rings;
+
+	return 0;
+
+fail:
+	brcmf_err("Allocating ring buffers failed\n");
+	brcmf_pcie_release_ringbuffers(devinfo);
+	return -ENOMEM;
+}
+
+
+static void
+brcmf_pcie_release_scratchbuffers(struct brcmf_pciedev_info *devinfo)
+{
+	if (devinfo->shared.scratch)
+		dma_free_coherent(&devinfo->pdev->dev,
+				  BRCMF_DMA_D2H_SCRATCH_BUF_LEN,
+				  devinfo->shared.scratch,
+				  devinfo->shared.scratch_dmahandle);
+	if (devinfo->shared.ringupd)
+		dma_free_coherent(&devinfo->pdev->dev,
+				  BRCMF_DMA_D2H_RINGUPD_BUF_LEN,
+				  devinfo->shared.ringupd,
+				  devinfo->shared.ringupd_dmahandle);
+}
+
+static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo)
+{
+	u64 address;
+	u32 addr;
+
+	devinfo->shared.scratch =
+		dma_zalloc_coherent(&devinfo->pdev->dev,
+					BRCMF_DMA_D2H_SCRATCH_BUF_LEN,
+					&devinfo->shared.scratch_dmahandle,
+					GFP_KERNEL);
+	if (!devinfo->shared.scratch)
+		goto fail;
+
+	addr = devinfo->shared.tcm_base_address +
+	       BRCMF_SHARED_DMA_SCRATCH_ADDR_OFFSET;
+	address = (u64)devinfo->shared.scratch_dmahandle;
+	brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
+	brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
+	addr = devinfo->shared.tcm_base_address +
+	       BRCMF_SHARED_DMA_SCRATCH_LEN_OFFSET;
+	brcmf_pcie_write_tcm32(devinfo, addr, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);
+
+	devinfo->shared.ringupd =
+		dma_zalloc_coherent(&devinfo->pdev->dev,
+					BRCMF_DMA_D2H_RINGUPD_BUF_LEN,
+					&devinfo->shared.ringupd_dmahandle,
+					GFP_KERNEL);
+	if (!devinfo->shared.ringupd)
+		goto fail;
+
+	addr = devinfo->shared.tcm_base_address +
+	       BRCMF_SHARED_DMA_RINGUPD_ADDR_OFFSET;
+	address = (u64)devinfo->shared.ringupd_dmahandle;
+	brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
+	brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
+	addr = devinfo->shared.tcm_base_address +
+	       BRCMF_SHARED_DMA_RINGUPD_LEN_OFFSET;
+	brcmf_pcie_write_tcm32(devinfo, addr, BRCMF_DMA_D2H_RINGUPD_BUF_LEN);
+	return 0;
+
+fail:
+	brcmf_err("Allocating scratch buffers failed\n");
+	brcmf_pcie_release_scratchbuffers(devinfo);
+	return -ENOMEM;
+}
+
+
+static void brcmf_pcie_down(struct device *dev)
+{
+}
+
+
+static int brcmf_pcie_tx(struct device *dev, struct sk_buff *skb)
+{
+	return 0;
+}
+
+
+static int brcmf_pcie_tx_ctlpkt(struct device *dev, unsigned char *msg,
+				uint len)
+{
+	return 0;
+}
+
+
+static int brcmf_pcie_rx_ctlpkt(struct device *dev, unsigned char *msg,
+				uint len)
+{
+	return 0;
+}
+
+
+static void brcmf_pcie_wowl_config(struct device *dev, bool enabled)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
+	struct brcmf_pciedev_info *devinfo = buspub->devinfo;
+
+	brcmf_dbg(PCIE, "Configuring WOWL, enabled=%d\n", enabled);
+	devinfo->wowl_enabled = enabled;
+}
+
+
+static size_t brcmf_pcie_get_ramsize(struct device *dev)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
+	struct brcmf_pciedev_info *devinfo = buspub->devinfo;
+
+	return devinfo->ci->ramsize - devinfo->ci->srsize;
+}
+
+
+static int brcmf_pcie_get_memdump(struct device *dev, void *data, size_t len)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
+	struct brcmf_pciedev_info *devinfo = buspub->devinfo;
+
+	brcmf_dbg(PCIE, "dump at 0x%08X: len=%zu\n", devinfo->ci->rambase, len);
+	brcmf_pcie_copy_dev_tomem(devinfo, devinfo->ci->rambase, data, len);
+	return 0;
+}
+
+static
+int brcmf_pcie_get_fwname(struct device *dev, const char *ext, u8 *fw_name)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_fw_request *fwreq;
+	struct brcmf_fw_name fwnames[] = {
+		{ ext, fw_name },
+	};
+
+	fwreq = brcmf_fw_alloc_request(bus_if->chip, bus_if->chiprev,
+				       brcmf_pcie_fwnames,
+				       ARRAY_SIZE(brcmf_pcie_fwnames),
+				       fwnames, ARRAY_SIZE(fwnames));
+	if (!fwreq)
+		return -ENOMEM;
+
+	kfree(fwreq);
+	return 0;
+}
+
+static const struct brcmf_bus_ops brcmf_pcie_bus_ops = {
+	.txdata = brcmf_pcie_tx,
+	.stop = brcmf_pcie_down,
+	.txctl = brcmf_pcie_tx_ctlpkt,
+	.rxctl = brcmf_pcie_rx_ctlpkt,
+	.wowl_config = brcmf_pcie_wowl_config,
+	.get_ramsize = brcmf_pcie_get_ramsize,
+	.get_memdump = brcmf_pcie_get_memdump,
+	.get_fwname = brcmf_pcie_get_fwname,
+};
+
+
+static void
+brcmf_pcie_adjust_ramsize(struct brcmf_pciedev_info *devinfo, u8 *data,
+			  u32 data_len)
+{
+	__le32 *field;
+	u32 newsize;
+
+	if (data_len < BRCMF_RAMSIZE_OFFSET + 8)
+		return;
+
+	field = (__le32 *)&data[BRCMF_RAMSIZE_OFFSET];
+	if (le32_to_cpup(field) != BRCMF_RAMSIZE_MAGIC)
+		return;
+	field++;
+	newsize = le32_to_cpup(field);
+
+	brcmf_dbg(PCIE, "Found ramsize info in FW, adjusting to 0x%x\n",
+		  newsize);
+	devinfo->ci->ramsize = newsize;
+}
+
+
+static int
+brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
+			       u32 sharedram_addr)
+{
+	struct brcmf_pcie_shared_info *shared;
+	u32 addr;
+
+	shared = &devinfo->shared;
+	shared->tcm_base_address = sharedram_addr;
+
+	shared->flags = brcmf_pcie_read_tcm32(devinfo, sharedram_addr);
+	shared->version = (u8)(shared->flags & BRCMF_PCIE_SHARED_VERSION_MASK);
+	brcmf_dbg(PCIE, "PCIe protocol version %d\n", shared->version);
+	if ((shared->version > BRCMF_PCIE_MAX_SHARED_VERSION) ||
+	    (shared->version < BRCMF_PCIE_MIN_SHARED_VERSION)) {
+		brcmf_err("Unsupported PCIE version %d\n", shared->version);
+		return -EINVAL;
+	}
+
+	/* check firmware support dma indicies */
+	if (shared->flags & BRCMF_PCIE_SHARED_DMA_INDEX) {
+		if (shared->flags & BRCMF_PCIE_SHARED_DMA_2B_IDX)
+			devinfo->dma_idx_sz = sizeof(u16);
+		else
+			devinfo->dma_idx_sz = sizeof(u32);
+	}
+
+	addr = sharedram_addr + BRCMF_SHARED_MAX_RXBUFPOST_OFFSET;
+	shared->max_rxbufpost = brcmf_pcie_read_tcm16(devinfo, addr);
+	if (shared->max_rxbufpost == 0)
+		shared->max_rxbufpost = BRCMF_DEF_MAX_RXBUFPOST;
+
+	addr = sharedram_addr + BRCMF_SHARED_RX_DATAOFFSET_OFFSET;
+	shared->rx_dataoffset = brcmf_pcie_read_tcm32(devinfo, addr);
+
+	addr = sharedram_addr + BRCMF_SHARED_HTOD_MB_DATA_ADDR_OFFSET;
+	shared->htod_mb_data_addr = brcmf_pcie_read_tcm32(devinfo, addr);
+
+	addr = sharedram_addr + BRCMF_SHARED_DTOH_MB_DATA_ADDR_OFFSET;
+	shared->dtoh_mb_data_addr = brcmf_pcie_read_tcm32(devinfo, addr);
+
+	addr = sharedram_addr + BRCMF_SHARED_RING_INFO_ADDR_OFFSET;
+	shared->ring_info_addr = brcmf_pcie_read_tcm32(devinfo, addr);
+
+	brcmf_dbg(PCIE, "max rx buf post %d, rx dataoffset %d\n",
+		  shared->max_rxbufpost, shared->rx_dataoffset);
+
+	brcmf_pcie_bus_console_init(devinfo);
+
+	return 0;
+}
+
+
+static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
+					const struct firmware *fw, void *nvram,
+					u32 nvram_len)
+{
+	u32 sharedram_addr;
+	u32 sharedram_addr_written;
+	u32 loop_counter;
+	int err;
+	u32 address;
+	u32 resetintr;
+
+	brcmf_dbg(PCIE, "Halt ARM.\n");
+	err = brcmf_pcie_enter_download_state(devinfo);
+	if (err)
+		return err;
+
+	brcmf_dbg(PCIE, "Download FW %s\n", devinfo->fw_name);
+	brcmf_pcie_copy_mem_todev(devinfo, devinfo->ci->rambase,
+				  (void *)fw->data, fw->size);
+
+	resetintr = get_unaligned_le32(fw->data);
+	release_firmware(fw);
+
+	/* reset last 4 bytes of RAM address. to be used for shared
+	 * area. This identifies when FW is running
+	 */
+	brcmf_pcie_write_ram32(devinfo, devinfo->ci->ramsize - 4, 0);
+
+	if (nvram) {
+		brcmf_dbg(PCIE, "Download NVRAM %s\n", devinfo->nvram_name);
+		address = devinfo->ci->rambase + devinfo->ci->ramsize -
+			  nvram_len;
+		brcmf_pcie_copy_mem_todev(devinfo, address, nvram, nvram_len);
+		brcmf_fw_nvram_free(nvram);
+	} else {
+		brcmf_dbg(PCIE, "No matching NVRAM file found %s\n",
+			  devinfo->nvram_name);
+	}
+
+	sharedram_addr_written = brcmf_pcie_read_ram32(devinfo,
+						       devinfo->ci->ramsize -
+						       4);
+	brcmf_dbg(PCIE, "Bring ARM in running state\n");
+	err = brcmf_pcie_exit_download_state(devinfo, resetintr);
+	if (err)
+		return err;
+
+	brcmf_dbg(PCIE, "Wait for FW init\n");
+	sharedram_addr = sharedram_addr_written;
+	loop_counter = BRCMF_PCIE_FW_UP_TIMEOUT / 50;
+	while ((sharedram_addr == sharedram_addr_written) && (loop_counter)) {
+		msleep(50);
+		sharedram_addr = brcmf_pcie_read_ram32(devinfo,
+						       devinfo->ci->ramsize -
+						       4);
+		loop_counter--;
+	}
+	if (sharedram_addr == sharedram_addr_written) {
+		brcmf_err("FW failed to initialize\n");
+		return -ENODEV;
+	}
+	brcmf_dbg(PCIE, "Shared RAM addr: 0x%08x\n", sharedram_addr);
+
+	return (brcmf_pcie_init_share_ram_info(devinfo, sharedram_addr));
+}
+
+
+static int brcmf_pcie_get_resource(struct brcmf_pciedev_info *devinfo)
+{
+	struct pci_dev *pdev;
+	int err;
+	phys_addr_t  bar0_addr, bar1_addr;
+	ulong bar1_size;
+
+	pdev = devinfo->pdev;
+
+	err = pci_enable_device(pdev);
+	if (err) {
+		brcmf_err("pci_enable_device failed err=%d\n", err);
+		return err;
+	}
+
+	pci_set_master(pdev);
+
+	/* Bar-0 mapped address */
+	bar0_addr = pci_resource_start(pdev, 0);
+	/* Bar-1 mapped address */
+	bar1_addr = pci_resource_start(pdev, 2);
+	/* read Bar-1 mapped memory range */
+	bar1_size = pci_resource_len(pdev, 2);
+	if ((bar1_size == 0) || (bar1_addr == 0)) {
+		brcmf_err("BAR1 Not enabled, device size=%ld, addr=%#016llx\n",
+			  bar1_size, (unsigned long long)bar1_addr);
+		return -EINVAL;
+	}
+
+	devinfo->regs = ioremap_nocache(bar0_addr, BRCMF_PCIE_REG_MAP_SIZE);
+	devinfo->tcm = ioremap_nocache(bar1_addr, bar1_size);
+
+	if (!devinfo->regs || !devinfo->tcm) {
+		brcmf_err("ioremap() failed (%p,%p)\n", devinfo->regs,
+			  devinfo->tcm);
+		return -EINVAL;
+	}
+	brcmf_dbg(PCIE, "Phys addr : reg space = %p base addr %#016llx\n",
+		  devinfo->regs, (unsigned long long)bar0_addr);
+	brcmf_dbg(PCIE, "Phys addr : mem space = %p base addr %#016llx size 0x%x\n",
+		  devinfo->tcm, (unsigned long long)bar1_addr,
+		  (unsigned int)bar1_size);
+
+	return 0;
+}
+
+
+static void brcmf_pcie_release_resource(struct brcmf_pciedev_info *devinfo)
+{
+	if (devinfo->tcm)
+		iounmap(devinfo->tcm);
+	if (devinfo->regs)
+		iounmap(devinfo->regs);
+
+	pci_disable_device(devinfo->pdev);
+}
+
+
+static u32 brcmf_pcie_buscore_prep_addr(const struct pci_dev *pdev, u32 addr)
+{
+	u32 ret_addr;
+
+	ret_addr = addr & (BRCMF_PCIE_BAR0_REG_SIZE - 1);
+	addr &= ~(BRCMF_PCIE_BAR0_REG_SIZE - 1);
+	pci_write_config_dword(pdev, BRCMF_PCIE_BAR0_WINDOW, addr);
+
+	return ret_addr;
+}
+
+
+static u32 brcmf_pcie_buscore_read32(void *ctx, u32 addr)
+{
+	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
+
+	addr = brcmf_pcie_buscore_prep_addr(devinfo->pdev, addr);
+	return brcmf_pcie_read_reg32(devinfo, addr);
+}
+
+
+static void brcmf_pcie_buscore_write32(void *ctx, u32 addr, u32 value)
+{
+	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
+
+	addr = brcmf_pcie_buscore_prep_addr(devinfo->pdev, addr);
+	brcmf_pcie_write_reg32(devinfo, addr, value);
+}
+
+
+static int brcmf_pcie_buscoreprep(void *ctx)
+{
+	return brcmf_pcie_get_resource(ctx);
+}
+
+
+static int brcmf_pcie_buscore_reset(void *ctx, struct brcmf_chip *chip)
+{
+	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
+	u32 val;
+
+	devinfo->ci = chip;
+	brcmf_pcie_reset_device(devinfo);
+
+	val = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT);
+	if (val != 0xffffffff)
+		brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT,
+				       val);
+
+	return 0;
+}
+
+
+static void brcmf_pcie_buscore_activate(void *ctx, struct brcmf_chip *chip,
+					u32 rstvec)
+{
+	struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
+
+	brcmf_pcie_write_tcm32(devinfo, 0, rstvec);
+}
+
+
+static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {
+	.prepare = brcmf_pcie_buscoreprep,
+	.reset = brcmf_pcie_buscore_reset,
+	.activate = brcmf_pcie_buscore_activate,
+	.read32 = brcmf_pcie_buscore_read32,
+	.write32 = brcmf_pcie_buscore_write32,
+};
+
+#define BRCMF_PCIE_FW_CODE	0
+#define BRCMF_PCIE_FW_NVRAM	1
+
+static void brcmf_pcie_setup(struct device *dev, int ret,
+			     struct brcmf_fw_request *fwreq)
+{
+	const struct firmware *fw;
+	void *nvram;
+	struct brcmf_bus *bus;
+	struct brcmf_pciedev *pcie_bus_dev;
+	struct brcmf_pciedev_info *devinfo;
+	struct brcmf_commonring **flowrings;
+	u32 i, nvram_len;
+
+	/* check firmware loading result */
+	if (ret)
+		goto fail;
+
+	bus = dev_get_drvdata(dev);
+	pcie_bus_dev = bus->bus_priv.pcie;
+	devinfo = pcie_bus_dev->devinfo;
+	brcmf_pcie_attach(devinfo);
+
+	fw = fwreq->items[BRCMF_PCIE_FW_CODE].binary;
+	nvram = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.data;
+	nvram_len = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.len;
+	kfree(fwreq);
+
+	/* Some of the firmwares have the size of the memory of the device
+	 * defined inside the firmware. This is because part of the memory in
+	 * the device is shared and the devision is determined by FW. Parse
+	 * the firmware and adjust the chip memory size now.
+	 */
+	brcmf_pcie_adjust_ramsize(devinfo, (u8 *)fw->data, fw->size);
+
+	ret = brcmf_pcie_download_fw_nvram(devinfo, fw, nvram, nvram_len);
+	if (ret)
+		goto fail;
+
+	devinfo->state = BRCMFMAC_PCIE_STATE_UP;
+
+	ret = brcmf_pcie_init_ringbuffers(devinfo);
+	if (ret)
+		goto fail;
+
+	ret = brcmf_pcie_init_scratchbuffers(devinfo);
+	if (ret)
+		goto fail;
+
+	brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+	ret = brcmf_pcie_request_irq(devinfo);
+	if (ret)
+		goto fail;
+
+	/* hook the commonrings in the bus structure. */
+	for (i = 0; i < BRCMF_NROF_COMMON_MSGRINGS; i++)
+		bus->msgbuf->commonrings[i] =
+				&devinfo->shared.commonrings[i]->commonring;
+
+	flowrings = kcalloc(devinfo->shared.max_flowrings, sizeof(*flowrings),
+			    GFP_KERNEL);
+	if (!flowrings)
+		goto fail;
+
+	for (i = 0; i < devinfo->shared.max_flowrings; i++)
+		flowrings[i] = &devinfo->shared.flowrings[i].commonring;
+	bus->msgbuf->flowrings = flowrings;
+
+	bus->msgbuf->rx_dataoffset = devinfo->shared.rx_dataoffset;
+	bus->msgbuf->max_rxbufpost = devinfo->shared.max_rxbufpost;
+	bus->msgbuf->max_flowrings = devinfo->shared.max_flowrings;
+
+	init_waitqueue_head(&devinfo->mbdata_resp_wait);
+
+	brcmf_pcie_intr_enable(devinfo);
+	brcmf_pcie_hostready(devinfo);
+	if (brcmf_attach(&devinfo->pdev->dev, devinfo->settings) == 0)
+		return;
+
+	brcmf_pcie_bus_console_read(devinfo);
+
+fail:
+	device_release_driver(dev);
+}
+
+static struct brcmf_fw_request *
+brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
+{
+	struct brcmf_fw_request *fwreq;
+	struct brcmf_fw_name fwnames[] = {
+		{ ".bin", devinfo->fw_name },
+		{ ".txt", devinfo->nvram_name },
+	};
+
+	fwreq = brcmf_fw_alloc_request(devinfo->ci->chip, devinfo->ci->chiprev,
+				       brcmf_pcie_fwnames,
+				       ARRAY_SIZE(brcmf_pcie_fwnames),
+				       fwnames, ARRAY_SIZE(fwnames));
+	if (!fwreq)
+		return NULL;
+
+	fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
+	fwreq->items[BRCMF_PCIE_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
+	fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL;
+	/* NVRAM reserves PCI domain 0 for Broadcom's SDK faked bus */
+	fwreq->domain_nr = pci_domain_nr(devinfo->pdev->bus) + 1;
+	fwreq->bus_nr = devinfo->pdev->bus->number;
+
+	return fwreq;
+}
+
+static int
+brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	int ret;
+	struct brcmf_fw_request *fwreq;
+	struct brcmf_pciedev_info *devinfo;
+	struct brcmf_pciedev *pcie_bus_dev;
+	struct brcmf_bus *bus;
+
+	brcmf_dbg(PCIE, "Enter %x:%x\n", pdev->vendor, pdev->device);
+
+	ret = -ENOMEM;
+	devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
+	if (devinfo == NULL)
+		return ret;
+
+	devinfo->pdev = pdev;
+	pcie_bus_dev = NULL;
+	devinfo->ci = brcmf_chip_attach(devinfo, &brcmf_pcie_buscore_ops);
+	if (IS_ERR(devinfo->ci)) {
+		ret = PTR_ERR(devinfo->ci);
+		devinfo->ci = NULL;
+		goto fail;
+	}
+
+	pcie_bus_dev = kzalloc(sizeof(*pcie_bus_dev), GFP_KERNEL);
+	if (pcie_bus_dev == NULL) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	devinfo->settings = brcmf_get_module_param(&devinfo->pdev->dev,
+						   BRCMF_BUSTYPE_PCIE,
+						   devinfo->ci->chip,
+						   devinfo->ci->chiprev);
+	if (!devinfo->settings) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	bus = kzalloc(sizeof(*bus), GFP_KERNEL);
+	if (!bus) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+	bus->msgbuf = kzalloc(sizeof(*bus->msgbuf), GFP_KERNEL);
+	if (!bus->msgbuf) {
+		ret = -ENOMEM;
+		kfree(bus);
+		goto fail;
+	}
+
+	/* hook it all together. */
+	pcie_bus_dev->devinfo = devinfo;
+	pcie_bus_dev->bus = bus;
+	bus->dev = &pdev->dev;
+	bus->bus_priv.pcie = pcie_bus_dev;
+	bus->ops = &brcmf_pcie_bus_ops;
+	bus->proto_type = BRCMF_PROTO_MSGBUF;
+	bus->chip = devinfo->coreid;
+	bus->wowl_supported = pci_pme_capable(pdev, PCI_D3hot);
+	dev_set_drvdata(&pdev->dev, bus);
+
+	fwreq = brcmf_pcie_prepare_fw_request(devinfo);
+	if (!fwreq) {
+		ret = -ENOMEM;
+		goto fail_bus;
+	}
+
+	ret = brcmf_fw_get_firmwares(bus->dev, fwreq, brcmf_pcie_setup);
+	if (ret < 0) {
+		kfree(fwreq);
+		goto fail_bus;
+	}
+	return 0;
+
+fail_bus:
+	kfree(bus->msgbuf);
+	kfree(bus);
+fail:
+	brcmf_err("failed %x:%x\n", pdev->vendor, pdev->device);
+	brcmf_pcie_release_resource(devinfo);
+	if (devinfo->ci)
+		brcmf_chip_detach(devinfo->ci);
+	if (devinfo->settings)
+		brcmf_release_module_param(devinfo->settings);
+	kfree(pcie_bus_dev);
+	kfree(devinfo);
+	return ret;
+}
+
+
+static void
+brcmf_pcie_remove(struct pci_dev *pdev)
+{
+	struct brcmf_pciedev_info *devinfo;
+	struct brcmf_bus *bus;
+
+	brcmf_dbg(PCIE, "Enter\n");
+
+	bus = dev_get_drvdata(&pdev->dev);
+	if (bus == NULL)
+		return;
+
+	devinfo = bus->bus_priv.pcie->devinfo;
+
+	devinfo->state = BRCMFMAC_PCIE_STATE_DOWN;
+	if (devinfo->ci)
+		brcmf_pcie_intr_disable(devinfo);
+
+	brcmf_detach(&pdev->dev);
+
+	kfree(bus->bus_priv.pcie);
+	kfree(bus->msgbuf->flowrings);
+	kfree(bus->msgbuf);
+	kfree(bus);
+
+	brcmf_pcie_release_irq(devinfo);
+	brcmf_pcie_release_scratchbuffers(devinfo);
+	brcmf_pcie_release_ringbuffers(devinfo);
+	brcmf_pcie_reset_device(devinfo);
+	brcmf_pcie_release_resource(devinfo);
+
+	if (devinfo->ci)
+		brcmf_chip_detach(devinfo->ci);
+	if (devinfo->settings)
+		brcmf_release_module_param(devinfo->settings);
+
+	kfree(devinfo);
+	dev_set_drvdata(&pdev->dev, NULL);
+}
+
+
+#ifdef CONFIG_PM
+
+
+static int brcmf_pcie_pm_enter_D3(struct device *dev)
+{
+	struct brcmf_pciedev_info *devinfo;
+	struct brcmf_bus *bus;
+
+	brcmf_dbg(PCIE, "Enter\n");
+
+	bus = dev_get_drvdata(dev);
+	devinfo = bus->bus_priv.pcie->devinfo;
+
+	brcmf_bus_change_state(bus, BRCMF_BUS_DOWN);
+
+	devinfo->mbdata_completed = false;
+	brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D3_INFORM);
+
+	wait_event_timeout(devinfo->mbdata_resp_wait, devinfo->mbdata_completed,
+			   BRCMF_PCIE_MBDATA_TIMEOUT);
+	if (!devinfo->mbdata_completed) {
+		brcmf_err("Timeout on response for entering D3 substate\n");
+		brcmf_bus_change_state(bus, BRCMF_BUS_UP);
+		return -EIO;
+	}
+
+	devinfo->state = BRCMFMAC_PCIE_STATE_DOWN;
+
+	return 0;
+}
+
+
+static int brcmf_pcie_pm_leave_D3(struct device *dev)
+{
+	struct brcmf_pciedev_info *devinfo;
+	struct brcmf_bus *bus;
+	struct pci_dev *pdev;
+	int err;
+
+	brcmf_dbg(PCIE, "Enter\n");
+
+	bus = dev_get_drvdata(dev);
+	devinfo = bus->bus_priv.pcie->devinfo;
+	brcmf_dbg(PCIE, "Enter, dev=%p, bus=%p\n", dev, bus);
+
+	/* Check if device is still up and running, if so we are ready */
+	if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_INTMASK) != 0) {
+		brcmf_dbg(PCIE, "Try to wakeup device....\n");
+		if (brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D0_INFORM))
+			goto cleanup;
+		brcmf_dbg(PCIE, "Hot resume, continue....\n");
+		devinfo->state = BRCMFMAC_PCIE_STATE_UP;
+		brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
+		brcmf_bus_change_state(bus, BRCMF_BUS_UP);
+		brcmf_pcie_intr_enable(devinfo);
+		brcmf_pcie_hostready(devinfo);
+		return 0;
+	}
+
+cleanup:
+	brcmf_chip_detach(devinfo->ci);
+	devinfo->ci = NULL;
+	pdev = devinfo->pdev;
+	brcmf_pcie_remove(pdev);
+
+	err = brcmf_pcie_probe(pdev, NULL);
+	if (err)
+		brcmf_err("probe after resume failed, err=%d\n", err);
+
+	return err;
+}
+
+
+static const struct dev_pm_ops brcmf_pciedrvr_pm = {
+	.suspend = brcmf_pcie_pm_enter_D3,
+	.resume = brcmf_pcie_pm_leave_D3,
+	.freeze = brcmf_pcie_pm_enter_D3,
+	.restore = brcmf_pcie_pm_leave_D3,
+};
+
+
+#endif /* CONFIG_PM */
+
+
+#define BRCMF_PCIE_DEVICE(dev_id)	{ BRCM_PCIE_VENDOR_ID_BROADCOM, dev_id,\
+	PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 }
+#define BRCMF_PCIE_DEVICE_SUB(dev_id, subvend, subdev)	{ \
+	BRCM_PCIE_VENDOR_ID_BROADCOM, dev_id,\
+	subvend, subdev, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 }
+
+static const struct pci_device_id brcmf_pcie_devid_table[] = {
+	BRCMF_PCIE_DEVICE(BRCM_PCIE_4350_DEVICE_ID),
+	BRCMF_PCIE_DEVICE(BRCM_PCIE_4356_DEVICE_ID),
+	BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID),
+	BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID),
+	BRCMF_PCIE_DEVICE(BRCM_PCIE_4358_DEVICE_ID),
+	BRCMF_PCIE_DEVICE(BRCM_PCIE_4359_DEVICE_ID),
+	BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_DEVICE_ID),
+	BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID),
+	BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID),
+	BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_RAW_DEVICE_ID),
+	BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_DEVICE_ID),
+	BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_2G_DEVICE_ID),
+	BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_5G_DEVICE_ID),
+	BRCMF_PCIE_DEVICE_SUB(0x4365, BRCM_PCIE_VENDOR_ID_BROADCOM, 0x4365),
+	BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_DEVICE_ID),
+	BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_2G_DEVICE_ID),
+	BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID),
+	BRCMF_PCIE_DEVICE(BRCM_PCIE_4371_DEVICE_ID),
+	{ /* end: all zeroes */ }
+};
+
+
+MODULE_DEVICE_TABLE(pci, brcmf_pcie_devid_table);
+
+
+static struct pci_driver brcmf_pciedrvr = {
+	.node = {},
+	.name = KBUILD_MODNAME,
+	.id_table = brcmf_pcie_devid_table,
+	.probe = brcmf_pcie_probe,
+	.remove = brcmf_pcie_remove,
+#ifdef CONFIG_PM
+	.driver.pm = &brcmf_pciedrvr_pm,
+#endif
+	.driver.coredump = brcmf_dev_coredump,
+};
+
+
+void brcmf_pcie_register(void)
+{
+	int err;
+
+	brcmf_dbg(PCIE, "Enter\n");
+	err = pci_register_driver(&brcmf_pciedrvr);
+	if (err)
+		brcmf_err("PCIE driver registration failed, err=%d\n", err);
+}
+
+
+void brcmf_pcie_exit(void)
+{
+	brcmf_dbg(PCIE, "Enter\n");
+	pci_unregister_driver(&brcmf_pciedrvr);
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.h
new file mode 100644
index 0000000..6edaaf8
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.h
@@ -0,0 +1,29 @@
+/* Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef BRCMFMAC_PCIE_H
+#define BRCMFMAC_PCIE_H
+
+
+struct brcmf_pciedev {
+	struct brcmf_bus *bus;
+	struct brcmf_pciedev_info *devinfo;
+};
+
+
+void brcmf_pcie_exit(void);
+void brcmf_pcie_register(void);
+
+
+#endif /* BRCMFMAC_PCIE_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
new file mode 100644
index 0000000..ffa243e
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
@@ -0,0 +1,591 @@
+/*
+ * Copyright (c) 2016 Broadcom
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/netdevice.h>
+#include <linux/gcd.h>
+#include <net/cfg80211.h>
+
+#include "core.h"
+#include "debug.h"
+#include "fwil.h"
+#include "fwil_types.h"
+#include "cfg80211.h"
+#include "pno.h"
+
+#define BRCMF_PNO_VERSION		2
+#define BRCMF_PNO_REPEAT		4
+#define BRCMF_PNO_FREQ_EXPO_MAX		3
+#define BRCMF_PNO_IMMEDIATE_SCAN_BIT	3
+#define BRCMF_PNO_ENABLE_BD_SCAN_BIT	5
+#define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT	6
+#define BRCMF_PNO_REPORT_SEPARATELY_BIT	11
+#define BRCMF_PNO_SCAN_INCOMPLETE	0
+#define BRCMF_PNO_WPA_AUTH_ANY		0xFFFFFFFF
+#define BRCMF_PNO_HIDDEN_BIT		2
+#define BRCMF_PNO_SCHED_SCAN_PERIOD	30
+
+#define BRCMF_PNO_MAX_BUCKETS		16
+#define GSCAN_BATCH_NO_THR_SET			101
+#define GSCAN_RETRY_THRESHOLD			3
+
+struct brcmf_pno_info {
+	int n_reqs;
+	struct cfg80211_sched_scan_request *reqs[BRCMF_PNO_MAX_BUCKETS];
+	struct mutex req_lock;
+};
+
+#define ifp_to_pno(_ifp)	((_ifp)->drvr->config->pno)
+
+static int brcmf_pno_store_request(struct brcmf_pno_info *pi,
+				   struct cfg80211_sched_scan_request *req)
+{
+	if (WARN(pi->n_reqs == BRCMF_PNO_MAX_BUCKETS,
+		 "pno request storage full\n"))
+		return -ENOSPC;
+
+	brcmf_dbg(SCAN, "reqid=%llu\n", req->reqid);
+	mutex_lock(&pi->req_lock);
+	pi->reqs[pi->n_reqs++] = req;
+	mutex_unlock(&pi->req_lock);
+	return 0;
+}
+
+static int brcmf_pno_remove_request(struct brcmf_pno_info *pi, u64 reqid)
+{
+	int i, err = 0;
+
+	mutex_lock(&pi->req_lock);
+
+	/* find request */
+	for (i = 0; i < pi->n_reqs; i++) {
+		if (pi->reqs[i]->reqid == reqid)
+			break;
+	}
+	/* request not found */
+	if (WARN(i == pi->n_reqs, "reqid not found\n")) {
+		err = -ENOENT;
+		goto done;
+	}
+
+	brcmf_dbg(SCAN, "reqid=%llu\n", reqid);
+	pi->n_reqs--;
+
+	/* if last we are done */
+	if (!pi->n_reqs || i == pi->n_reqs)
+		goto done;
+
+	/* fill the gap with remaining requests */
+	while (i <= pi->n_reqs - 1) {
+		pi->reqs[i] = pi->reqs[i + 1];
+		i++;
+	}
+
+done:
+	mutex_unlock(&pi->req_lock);
+	return err;
+}
+
+static int brcmf_pno_channel_config(struct brcmf_if *ifp,
+				    struct brcmf_pno_config_le *cfg)
+{
+	cfg->reporttype = 0;
+	cfg->flags = 0;
+
+	return brcmf_fil_iovar_data_set(ifp, "pfn_cfg", cfg, sizeof(*cfg));
+}
+
+static int brcmf_pno_config(struct brcmf_if *ifp, u32 scan_freq,
+			    u32 mscan, u32 bestn)
+{
+	struct brcmf_pno_param_le pfn_param;
+	u16 flags;
+	u32 pfnmem;
+	s32 err;
+
+	memset(&pfn_param, 0, sizeof(pfn_param));
+	pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION);
+
+	/* set extra pno params */
+	flags = BIT(BRCMF_PNO_IMMEDIATE_SCAN_BIT) |
+		BIT(BRCMF_PNO_ENABLE_ADAPTSCAN_BIT);
+	pfn_param.repeat = BRCMF_PNO_REPEAT;
+	pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX;
+
+	/* set up pno scan fr */
+	pfn_param.scan_freq = cpu_to_le32(scan_freq);
+
+	if (mscan) {
+		pfnmem = bestn;
+
+		/* set bestn in firmware */
+		err = brcmf_fil_iovar_int_set(ifp, "pfnmem", pfnmem);
+		if (err < 0) {
+			brcmf_err("failed to set pfnmem\n");
+			goto exit;
+		}
+		/* get max mscan which the firmware supports */
+		err = brcmf_fil_iovar_int_get(ifp, "pfnmem", &pfnmem);
+		if (err < 0) {
+			brcmf_err("failed to get pfnmem\n");
+			goto exit;
+		}
+		mscan = min_t(u32, mscan, pfnmem);
+		pfn_param.mscan = mscan;
+		pfn_param.bestn = bestn;
+		flags |= BIT(BRCMF_PNO_ENABLE_BD_SCAN_BIT);
+		brcmf_dbg(INFO, "mscan=%d, bestn=%d\n", mscan, bestn);
+	}
+
+	pfn_param.flags = cpu_to_le16(flags);
+	err = brcmf_fil_iovar_data_set(ifp, "pfn_set", &pfn_param,
+				       sizeof(pfn_param));
+	if (err)
+		brcmf_err("pfn_set failed, err=%d\n", err);
+
+exit:
+	return err;
+}
+
+static int brcmf_pno_set_random(struct brcmf_if *ifp, struct brcmf_pno_info *pi)
+{
+	struct brcmf_pno_macaddr_le pfn_mac;
+	u8 *mac_addr = NULL;
+	u8 *mac_mask = NULL;
+	int err, i;
+
+	for (i = 0; i < pi->n_reqs; i++)
+		if (pi->reqs[i]->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
+			mac_addr = pi->reqs[i]->mac_addr;
+			mac_mask = pi->reqs[i]->mac_addr_mask;
+			break;
+		}
+
+	/* no random mac requested */
+	if (!mac_addr)
+		return 0;
+
+	pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER;
+	pfn_mac.flags = BRCMF_PFN_MAC_OUI_ONLY | BRCMF_PFN_SET_MAC_UNASSOC;
+
+	memcpy(pfn_mac.mac, mac_addr, ETH_ALEN);
+	for (i = 0; i < ETH_ALEN; i++) {
+		pfn_mac.mac[i] &= mac_mask[i];
+		pfn_mac.mac[i] |= get_random_int() & ~(mac_mask[i]);
+	}
+	/* Clear multi bit */
+	pfn_mac.mac[0] &= 0xFE;
+	/* Set locally administered */
+	pfn_mac.mac[0] |= 0x02;
+
+	brcmf_dbg(SCAN, "enabling random mac: reqid=%llu mac=%pM\n",
+		  pi->reqs[i]->reqid, pfn_mac.mac);
+	err = brcmf_fil_iovar_data_set(ifp, "pfn_macaddr", &pfn_mac,
+				       sizeof(pfn_mac));
+	if (err)
+		brcmf_err("pfn_macaddr failed, err=%d\n", err);
+
+	return err;
+}
+
+static int brcmf_pno_add_ssid(struct brcmf_if *ifp, struct cfg80211_ssid *ssid,
+			      bool active)
+{
+	struct brcmf_pno_net_param_le pfn;
+	int err;
+
+	pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN);
+	pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY);
+	pfn.wsec = cpu_to_le32(0);
+	pfn.infra = cpu_to_le32(1);
+	pfn.flags = 0;
+	if (active)
+		pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT);
+	pfn.ssid.SSID_len = cpu_to_le32(ssid->ssid_len);
+	memcpy(pfn.ssid.SSID, ssid->ssid, ssid->ssid_len);
+
+	brcmf_dbg(SCAN, "adding ssid=%.32s (active=%d)\n", ssid->ssid, active);
+	err = brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn, sizeof(pfn));
+	if (err < 0)
+		brcmf_err("adding failed: err=%d\n", err);
+	return err;
+}
+
+static int brcmf_pno_add_bssid(struct brcmf_if *ifp, const u8 *bssid)
+{
+	struct brcmf_pno_bssid_le bssid_cfg;
+	int err;
+
+	memcpy(bssid_cfg.bssid, bssid, ETH_ALEN);
+	bssid_cfg.flags = 0;
+
+	brcmf_dbg(SCAN, "adding bssid=%pM\n", bssid);
+	err = brcmf_fil_iovar_data_set(ifp, "pfn_add_bssid", &bssid_cfg,
+				       sizeof(bssid_cfg));
+	if (err < 0)
+		brcmf_err("adding failed: err=%d\n", err);
+	return err;
+}
+
+static bool brcmf_is_ssid_active(struct cfg80211_ssid *ssid,
+				 struct cfg80211_sched_scan_request *req)
+{
+	int i;
+
+	if (!ssid || !req->ssids || !req->n_ssids)
+		return false;
+
+	for (i = 0; i < req->n_ssids; i++) {
+		if (ssid->ssid_len == req->ssids[i].ssid_len) {
+			if (!strncmp(ssid->ssid, req->ssids[i].ssid,
+				     ssid->ssid_len))
+				return true;
+		}
+	}
+	return false;
+}
+
+static int brcmf_pno_clean(struct brcmf_if *ifp)
+{
+	int ret;
+
+	/* Disable pfn */
+	ret = brcmf_fil_iovar_int_set(ifp, "pfn", 0);
+	if (ret == 0) {
+		/* clear pfn */
+		ret = brcmf_fil_iovar_data_set(ifp, "pfnclear", NULL, 0);
+	}
+	if (ret < 0)
+		brcmf_err("failed code %d\n", ret);
+
+	return ret;
+}
+
+static int brcmf_pno_get_bucket_channels(struct cfg80211_sched_scan_request *r,
+					 struct brcmf_pno_config_le *pno_cfg)
+{
+	u32 n_chan = le32_to_cpu(pno_cfg->channel_num);
+	u16 chan;
+	int i, err = 0;
+
+	for (i = 0; i < r->n_channels; i++) {
+		if (n_chan >= BRCMF_NUMCHANNELS) {
+			err = -ENOSPC;
+			goto done;
+		}
+		chan = r->channels[i]->hw_value;
+		brcmf_dbg(SCAN, "[%d] Chan : %u\n", n_chan, chan);
+		pno_cfg->channel_list[n_chan++] = cpu_to_le16(chan);
+	}
+	/* return number of channels */
+	err = n_chan;
+done:
+	pno_cfg->channel_num = cpu_to_le32(n_chan);
+	return err;
+}
+
+static int brcmf_pno_prep_fwconfig(struct brcmf_pno_info *pi,
+				   struct brcmf_pno_config_le *pno_cfg,
+				   struct brcmf_gscan_bucket_config **buckets,
+				   u32 *scan_freq)
+{
+	struct cfg80211_sched_scan_request *sr;
+	struct brcmf_gscan_bucket_config *fw_buckets;
+	int i, err, chidx;
+
+	brcmf_dbg(SCAN, "n_reqs=%d\n", pi->n_reqs);
+	if (WARN_ON(!pi->n_reqs))
+		return -ENODATA;
+
+	/*
+	 * actual scan period is determined using gcd() for each
+	 * scheduled scan period.
+	 */
+	*scan_freq = pi->reqs[0]->scan_plans[0].interval;
+	for (i = 1; i < pi->n_reqs; i++) {
+		sr = pi->reqs[i];
+		*scan_freq = gcd(sr->scan_plans[0].interval, *scan_freq);
+	}
+	if (*scan_freq < BRCMF_PNO_SCHED_SCAN_MIN_PERIOD) {
+		brcmf_dbg(SCAN, "scan period too small, using minimum\n");
+		*scan_freq = BRCMF_PNO_SCHED_SCAN_MIN_PERIOD;
+	}
+
+	*buckets = NULL;
+	fw_buckets = kcalloc(pi->n_reqs, sizeof(*fw_buckets), GFP_KERNEL);
+	if (!fw_buckets)
+		return -ENOMEM;
+
+	memset(pno_cfg, 0, sizeof(*pno_cfg));
+	for (i = 0; i < pi->n_reqs; i++) {
+		sr = pi->reqs[i];
+		chidx = brcmf_pno_get_bucket_channels(sr, pno_cfg);
+		if (chidx < 0) {
+			err = chidx;
+			goto fail;
+		}
+		fw_buckets[i].bucket_end_index = chidx - 1;
+		fw_buckets[i].bucket_freq_multiple =
+			sr->scan_plans[0].interval / *scan_freq;
+		/* assure period is non-zero */
+		if (!fw_buckets[i].bucket_freq_multiple)
+			fw_buckets[i].bucket_freq_multiple = 1;
+		fw_buckets[i].flag = BRCMF_PNO_REPORT_NO_BATCH;
+	}
+
+	if (BRCMF_SCAN_ON()) {
+		brcmf_err("base period=%u\n", *scan_freq);
+		for (i = 0; i < pi->n_reqs; i++) {
+			brcmf_err("[%d] period %u max %u repeat %u flag %x idx %u\n",
+				  i, fw_buckets[i].bucket_freq_multiple,
+				  le16_to_cpu(fw_buckets[i].max_freq_multiple),
+				  fw_buckets[i].repeat, fw_buckets[i].flag,
+				  fw_buckets[i].bucket_end_index);
+		}
+	}
+	*buckets = fw_buckets;
+	return pi->n_reqs;
+
+fail:
+	kfree(fw_buckets);
+	return err;
+}
+
+static int brcmf_pno_config_networks(struct brcmf_if *ifp,
+				     struct brcmf_pno_info *pi)
+{
+	struct cfg80211_sched_scan_request *r;
+	struct cfg80211_match_set *ms;
+	bool active;
+	int i, j, err = 0;
+
+	for (i = 0; i < pi->n_reqs; i++) {
+		r = pi->reqs[i];
+
+		for (j = 0; j < r->n_match_sets; j++) {
+			ms = &r->match_sets[j];
+			if (ms->ssid.ssid_len) {
+				active = brcmf_is_ssid_active(&ms->ssid, r);
+				err = brcmf_pno_add_ssid(ifp, &ms->ssid,
+							 active);
+			}
+			if (!err && is_valid_ether_addr(ms->bssid))
+				err = brcmf_pno_add_bssid(ifp, ms->bssid);
+
+			if (err < 0)
+				return err;
+		}
+	}
+	return 0;
+}
+
+static int brcmf_pno_config_sched_scans(struct brcmf_if *ifp)
+{
+	struct brcmf_pno_info *pi;
+	struct brcmf_gscan_config *gscan_cfg;
+	struct brcmf_gscan_bucket_config *buckets;
+	struct brcmf_pno_config_le pno_cfg;
+	size_t gsz;
+	u32 scan_freq;
+	int err, n_buckets;
+
+	pi = ifp_to_pno(ifp);
+	n_buckets = brcmf_pno_prep_fwconfig(pi, &pno_cfg, &buckets,
+					    &scan_freq);
+	if (n_buckets < 0)
+		return n_buckets;
+
+	gsz = sizeof(*gscan_cfg) + (n_buckets - 1) * sizeof(*buckets);
+	gscan_cfg = kzalloc(gsz, GFP_KERNEL);
+	if (!gscan_cfg) {
+		err = -ENOMEM;
+		goto free_buckets;
+	}
+
+	/* clean up everything */
+	err = brcmf_pno_clean(ifp);
+	if  (err < 0) {
+		brcmf_err("failed error=%d\n", err);
+		goto free_gscan;
+	}
+
+	/* configure pno */
+	err = brcmf_pno_config(ifp, scan_freq, 0, 0);
+	if (err < 0)
+		goto free_gscan;
+
+	err = brcmf_pno_channel_config(ifp, &pno_cfg);
+	if (err < 0)
+		goto clean;
+
+	gscan_cfg->version = cpu_to_le16(BRCMF_GSCAN_CFG_VERSION);
+	gscan_cfg->retry_threshold = GSCAN_RETRY_THRESHOLD;
+	gscan_cfg->buffer_threshold = GSCAN_BATCH_NO_THR_SET;
+	gscan_cfg->flags = BRCMF_GSCAN_CFG_ALL_BUCKETS_IN_1ST_SCAN;
+
+	gscan_cfg->count_of_channel_buckets = n_buckets;
+	memcpy(&gscan_cfg->bucket[0], buckets,
+	       n_buckets * sizeof(*buckets));
+
+	err = brcmf_fil_iovar_data_set(ifp, "pfn_gscan_cfg", gscan_cfg, gsz);
+
+	if (err < 0)
+		goto clean;
+
+	/* configure random mac */
+	err = brcmf_pno_set_random(ifp, pi);
+	if (err < 0)
+		goto clean;
+
+	err = brcmf_pno_config_networks(ifp, pi);
+	if (err < 0)
+		goto clean;
+
+	/* Enable the PNO */
+	err = brcmf_fil_iovar_int_set(ifp, "pfn", 1);
+
+clean:
+	if (err < 0)
+		brcmf_pno_clean(ifp);
+free_gscan:
+	kfree(gscan_cfg);
+free_buckets:
+	kfree(buckets);
+	return err;
+}
+
+int brcmf_pno_start_sched_scan(struct brcmf_if *ifp,
+			       struct cfg80211_sched_scan_request *req)
+{
+	struct brcmf_pno_info *pi;
+	int ret;
+
+	brcmf_dbg(TRACE, "reqid=%llu\n", req->reqid);
+
+	pi = ifp_to_pno(ifp);
+	ret = brcmf_pno_store_request(pi, req);
+	if (ret < 0)
+		return ret;
+
+	ret = brcmf_pno_config_sched_scans(ifp);
+	if (ret < 0) {
+		brcmf_pno_remove_request(pi, req->reqid);
+		if (pi->n_reqs)
+			(void)brcmf_pno_config_sched_scans(ifp);
+		return ret;
+	}
+	return 0;
+}
+
+int brcmf_pno_stop_sched_scan(struct brcmf_if *ifp, u64 reqid)
+{
+	struct brcmf_pno_info *pi;
+	int err;
+
+	brcmf_dbg(TRACE, "reqid=%llu\n", reqid);
+
+	pi = ifp_to_pno(ifp);
+	err = brcmf_pno_remove_request(pi, reqid);
+	if (err)
+		return err;
+
+	brcmf_pno_clean(ifp);
+
+	if (pi->n_reqs)
+		(void)brcmf_pno_config_sched_scans(ifp);
+
+	return 0;
+}
+
+int brcmf_pno_attach(struct brcmf_cfg80211_info *cfg)
+{
+	struct brcmf_pno_info *pi;
+
+	brcmf_dbg(TRACE, "enter\n");
+	pi = kzalloc(sizeof(*pi), GFP_KERNEL);
+	if (!pi)
+		return -ENOMEM;
+
+	cfg->pno = pi;
+	mutex_init(&pi->req_lock);
+	return 0;
+}
+
+void brcmf_pno_detach(struct brcmf_cfg80211_info *cfg)
+{
+	struct brcmf_pno_info *pi;
+
+	brcmf_dbg(TRACE, "enter\n");
+	pi = cfg->pno;
+	cfg->pno = NULL;
+
+	WARN_ON(pi->n_reqs);
+	mutex_destroy(&pi->req_lock);
+	kfree(pi);
+}
+
+void brcmf_pno_wiphy_params(struct wiphy *wiphy, bool gscan)
+{
+	/* scheduled scan settings */
+	wiphy->max_sched_scan_reqs = gscan ? BRCMF_PNO_MAX_BUCKETS : 1;
+	wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
+	wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
+	wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
+	wiphy->max_sched_scan_plan_interval = BRCMF_PNO_SCHED_SCAN_MAX_PERIOD;
+}
+
+u64 brcmf_pno_find_reqid_by_bucket(struct brcmf_pno_info *pi, u32 bucket)
+{
+	u64 reqid = 0;
+
+	mutex_lock(&pi->req_lock);
+
+	if (bucket < pi->n_reqs)
+		reqid = pi->reqs[bucket]->reqid;
+
+	mutex_unlock(&pi->req_lock);
+	return reqid;
+}
+
+u32 brcmf_pno_get_bucket_map(struct brcmf_pno_info *pi,
+			     struct brcmf_pno_net_info_le *ni)
+{
+	struct cfg80211_sched_scan_request *req;
+	struct cfg80211_match_set *ms;
+	u32 bucket_map = 0;
+	int i, j;
+
+	mutex_lock(&pi->req_lock);
+	for (i = 0; i < pi->n_reqs; i++) {
+		req = pi->reqs[i];
+
+		if (!req->n_match_sets)
+			continue;
+		for (j = 0; j < req->n_match_sets; j++) {
+			ms = &req->match_sets[j];
+			if (ms->ssid.ssid_len == ni->SSID_len &&
+			    !memcmp(ms->ssid.ssid, ni->SSID, ni->SSID_len)) {
+				bucket_map |= BIT(i);
+				break;
+			}
+			if (is_valid_ether_addr(ms->bssid) &&
+			    !memcmp(ms->bssid, ni->bssid, ETH_ALEN)) {
+				bucket_map |= BIT(i);
+				break;
+			}
+		}
+	}
+	mutex_unlock(&pi->req_lock);
+	return bucket_map;
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
new file mode 100644
index 0000000..cd9e35a
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2016 Broadcom
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef _BRCMF_PNO_H
+#define _BRCMF_PNO_H
+
+#define BRCMF_PNO_SCAN_COMPLETE			1
+#define BRCMF_PNO_MAX_PFN_COUNT			16
+#define BRCMF_PNO_SCHED_SCAN_MIN_PERIOD	10
+#define BRCMF_PNO_SCHED_SCAN_MAX_PERIOD	508
+
+/* forward declaration */
+struct brcmf_pno_info;
+
+/**
+ * brcmf_pno_start_sched_scan - initiate scheduled scan on device.
+ *
+ * @ifp: interface object used.
+ * @req: configuration parameters for scheduled scan.
+ */
+int brcmf_pno_start_sched_scan(struct brcmf_if *ifp,
+			       struct cfg80211_sched_scan_request *req);
+
+/**
+ * brcmf_pno_stop_sched_scan - terminate scheduled scan on device.
+ *
+ * @ifp: interface object used.
+ * @reqid: unique identifier of scan to be stopped.
+ */
+int brcmf_pno_stop_sched_scan(struct brcmf_if *ifp, u64 reqid);
+
+/**
+ * brcmf_pno_wiphy_params - fill scheduled scan parameters in wiphy instance.
+ *
+ * @wiphy: wiphy instance to be used.
+ * @gscan: indicates whether the device has support for g-scan feature.
+ */
+void brcmf_pno_wiphy_params(struct wiphy *wiphy, bool gscan);
+
+/**
+ * brcmf_pno_attach - allocate and attach module information.
+ *
+ * @cfg: cfg80211 context used.
+ */
+int brcmf_pno_attach(struct brcmf_cfg80211_info *cfg);
+
+/**
+ * brcmf_pno_detach - detach and free module information.
+ *
+ * @cfg: cfg80211 context used.
+ */
+void brcmf_pno_detach(struct brcmf_cfg80211_info *cfg);
+
+/**
+ * brcmf_pno_find_reqid_by_bucket - find request id for given bucket index.
+ *
+ * @pi: pno instance used.
+ * @bucket: index of firmware bucket.
+ */
+u64 brcmf_pno_find_reqid_by_bucket(struct brcmf_pno_info *pi, u32 bucket);
+
+/**
+ * brcmf_pno_get_bucket_map - determine bucket map for given netinfo.
+ *
+ * @pi: pno instance used.
+ * @netinfo: netinfo to compare with bucket configuration.
+ */
+u32 brcmf_pno_get_bucket_map(struct brcmf_pno_info *pi,
+			     struct brcmf_pno_net_info_le *netinfo);
+
+#endif /* _BRCMF_PNO_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c
new file mode 100644
index 0000000..c5ff551
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+ #include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+
+#include <brcmu_wifi.h>
+#include "core.h"
+#include "bus.h"
+#include "debug.h"
+#include "proto.h"
+#include "bcdc.h"
+#include "msgbuf.h"
+
+
+int brcmf_proto_attach(struct brcmf_pub *drvr)
+{
+	struct brcmf_proto *proto;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	proto = kzalloc(sizeof(*proto), GFP_ATOMIC);
+	if (!proto)
+		goto fail;
+
+	drvr->proto = proto;
+
+	if (drvr->bus_if->proto_type == BRCMF_PROTO_BCDC) {
+		if (brcmf_proto_bcdc_attach(drvr))
+			goto fail;
+	} else if (drvr->bus_if->proto_type == BRCMF_PROTO_MSGBUF) {
+		if (brcmf_proto_msgbuf_attach(drvr))
+			goto fail;
+	} else {
+		brcmf_err("Unsupported proto type %d\n",
+			  drvr->bus_if->proto_type);
+		goto fail;
+	}
+	if (!proto->tx_queue_data || (proto->hdrpull == NULL) ||
+	    (proto->query_dcmd == NULL) || (proto->set_dcmd == NULL) ||
+	    (proto->configure_addr_mode == NULL) ||
+	    (proto->delete_peer == NULL) || (proto->add_tdls_peer == NULL) ||
+	    (proto->debugfs_create == NULL)) {
+		brcmf_err("Not all proto handlers have been installed\n");
+		goto fail;
+	}
+	return 0;
+
+fail:
+	kfree(proto);
+	drvr->proto = NULL;
+	return -ENOMEM;
+}
+
+void brcmf_proto_detach(struct brcmf_pub *drvr)
+{
+	brcmf_dbg(TRACE, "Enter\n");
+
+	if (drvr->proto) {
+		if (drvr->bus_if->proto_type == BRCMF_PROTO_BCDC)
+			brcmf_proto_bcdc_detach(drvr);
+		else if (drvr->bus_if->proto_type == BRCMF_PROTO_MSGBUF)
+			brcmf_proto_msgbuf_detach(drvr);
+		kfree(drvr->proto);
+		drvr->proto = NULL;
+	}
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
new file mode 100644
index 0000000..d3c3b9a
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2013 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef BRCMFMAC_PROTO_H
+#define BRCMFMAC_PROTO_H
+
+
+enum proto_addr_mode {
+	ADDR_INDIRECT	= 0,
+	ADDR_DIRECT
+};
+
+struct brcmf_skb_reorder_data {
+	u8 *reorder;
+};
+
+struct brcmf_proto {
+	int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws,
+		       struct sk_buff *skb, struct brcmf_if **ifp);
+	int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd,
+			  void *buf, uint len, int *fwerr);
+	int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf,
+			uint len, int *fwerr);
+	int (*tx_queue_data)(struct brcmf_pub *drvr, int ifidx,
+			     struct sk_buff *skb);
+	int (*txdata)(struct brcmf_pub *drvr, int ifidx, u8 offset,
+		      struct sk_buff *skb);
+	void (*configure_addr_mode)(struct brcmf_pub *drvr, int ifidx,
+				    enum proto_addr_mode addr_mode);
+	void (*delete_peer)(struct brcmf_pub *drvr, int ifidx,
+			    u8 peer[ETH_ALEN]);
+	void (*add_tdls_peer)(struct brcmf_pub *drvr, int ifidx,
+			      u8 peer[ETH_ALEN]);
+	void (*rxreorder)(struct brcmf_if *ifp, struct sk_buff *skb);
+	void (*add_if)(struct brcmf_if *ifp);
+	void (*del_if)(struct brcmf_if *ifp);
+	void (*reset_if)(struct brcmf_if *ifp);
+	int (*init_done)(struct brcmf_pub *drvr);
+	void (*debugfs_create)(struct brcmf_pub *drvr);
+	void *pd;
+};
+
+
+int brcmf_proto_attach(struct brcmf_pub *drvr);
+void brcmf_proto_detach(struct brcmf_pub *drvr);
+
+static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws,
+				      struct sk_buff *skb,
+				      struct brcmf_if **ifp)
+{
+	struct brcmf_if *tmp = NULL;
+
+	/* assure protocol is always called with
+	 * non-null initialized pointer.
+	 */
+	if (ifp)
+		*ifp = NULL;
+	else
+		ifp = &tmp;
+	return drvr->proto->hdrpull(drvr, do_fws, skb, ifp);
+}
+static inline int brcmf_proto_query_dcmd(struct brcmf_pub *drvr, int ifidx,
+					 uint cmd, void *buf, uint len,
+					 int *fwerr)
+{
+	return drvr->proto->query_dcmd(drvr, ifidx, cmd, buf, len,fwerr);
+}
+static inline int brcmf_proto_set_dcmd(struct brcmf_pub *drvr, int ifidx,
+				       uint cmd, void *buf, uint len,
+				       int *fwerr)
+{
+	return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len, fwerr);
+}
+
+static inline int brcmf_proto_tx_queue_data(struct brcmf_pub *drvr, int ifidx,
+					    struct sk_buff *skb)
+{
+	return drvr->proto->tx_queue_data(drvr, ifidx, skb);
+}
+
+static inline int brcmf_proto_txdata(struct brcmf_pub *drvr, int ifidx,
+				     u8 offset, struct sk_buff *skb)
+{
+	return drvr->proto->txdata(drvr, ifidx, offset, skb);
+}
+static inline void
+brcmf_proto_configure_addr_mode(struct brcmf_pub *drvr, int ifidx,
+				enum proto_addr_mode addr_mode)
+{
+	drvr->proto->configure_addr_mode(drvr, ifidx, addr_mode);
+}
+static inline void
+brcmf_proto_delete_peer(struct brcmf_pub *drvr, int ifidx, u8 peer[ETH_ALEN])
+{
+	drvr->proto->delete_peer(drvr, ifidx, peer);
+}
+static inline void
+brcmf_proto_add_tdls_peer(struct brcmf_pub *drvr, int ifidx, u8 peer[ETH_ALEN])
+{
+	drvr->proto->add_tdls_peer(drvr, ifidx, peer);
+}
+static inline bool brcmf_proto_is_reorder_skb(struct sk_buff *skb)
+{
+	struct brcmf_skb_reorder_data *rd;
+
+	rd = (struct brcmf_skb_reorder_data *)skb->cb;
+	return !!rd->reorder;
+}
+
+static inline void
+brcmf_proto_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb)
+{
+	ifp->drvr->proto->rxreorder(ifp, skb);
+}
+
+static inline void
+brcmf_proto_add_if(struct brcmf_pub *drvr, struct brcmf_if *ifp)
+{
+	if (!drvr->proto->add_if)
+		return;
+	drvr->proto->add_if(ifp);
+}
+
+static inline void
+brcmf_proto_del_if(struct brcmf_pub *drvr, struct brcmf_if *ifp)
+{
+	if (!drvr->proto->del_if)
+		return;
+	drvr->proto->del_if(ifp);
+}
+
+static inline void
+brcmf_proto_reset_if(struct brcmf_pub *drvr, struct brcmf_if *ifp)
+{
+	if (!drvr->proto->reset_if)
+		return;
+	drvr->proto->reset_if(ifp);
+}
+
+static inline int
+brcmf_proto_init_done(struct brcmf_pub *drvr)
+{
+	if (!drvr->proto->init_done)
+		return 0;
+	return drvr->proto->init_done(drvr);
+}
+
+static inline void
+brcmf_proto_debugfs_create(struct brcmf_pub *drvr)
+{
+	drvr->proto->debugfs_create(drvr);
+}
+
+#endif /* BRCMFMAC_PROTO_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
new file mode 100644
index 0000000..a907d7b
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -0,0 +1,4380 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/types.h>
+#include <linux/atomic.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/printk.h>
+#include <linux/pci_ids.h>
+#include <linux/netdevice.h>
+#include <linux/interrupt.h>
+#include <linux/sched/signal.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/card.h>
+#include <linux/semaphore.h>
+#include <linux/firmware.h>
+#include <linux/module.h>
+#include <linux/bcma/bcma.h>
+#include <linux/debugfs.h>
+#include <linux/vmalloc.h>
+#include <asm/unaligned.h>
+#include <defs.h>
+#include <brcmu_wifi.h>
+#include <brcmu_utils.h>
+#include <brcm_hw_ids.h>
+#include <soc.h>
+#include "sdio.h"
+#include "chip.h"
+#include "firmware.h"
+#include "core.h"
+#include "common.h"
+#include "bcdc.h"
+
+#define DCMD_RESP_TIMEOUT	msecs_to_jiffies(2500)
+#define CTL_DONE_TIMEOUT	msecs_to_jiffies(2500)
+
+#ifdef DEBUG
+
+#define BRCMF_TRAP_INFO_SIZE	80
+
+#define CBUF_LEN	(128)
+
+/* Device console log buffer state */
+#define CONSOLE_BUFFER_MAX	2024
+
+struct rte_log_le {
+	__le32 buf;		/* Can't be pointer on (64-bit) hosts */
+	__le32 buf_size;
+	__le32 idx;
+	char *_buf_compat;	/* Redundant pointer for backward compat. */
+};
+
+struct rte_console {
+	/* Virtual UART
+	 * When there is no UART (e.g. Quickturn),
+	 * the host should write a complete
+	 * input line directly into cbuf and then write
+	 * the length into vcons_in.
+	 * This may also be used when there is a real UART
+	 * (at risk of conflicting with
+	 * the real UART).  vcons_out is currently unused.
+	 */
+	uint vcons_in;
+	uint vcons_out;
+
+	/* Output (logging) buffer
+	 * Console output is written to a ring buffer log_buf at index log_idx.
+	 * The host may read the output when it sees log_idx advance.
+	 * Output will be lost if the output wraps around faster than the host
+	 * polls.
+	 */
+	struct rte_log_le log_le;
+
+	/* Console input line buffer
+	 * Characters are read one at a time into cbuf
+	 * until <CR> is received, then
+	 * the buffer is processed as a command line.
+	 * Also used for virtual UART.
+	 */
+	uint cbuf_idx;
+	char cbuf[CBUF_LEN];
+};
+
+#endif				/* DEBUG */
+#include <chipcommon.h>
+
+#include "bus.h"
+#include "debug.h"
+#include "tracepoint.h"
+
+#define TXQLEN		2048	/* bulk tx queue length */
+#define TXHI		(TXQLEN - 256)	/* turn on flow control above TXHI */
+#define TXLOW		(TXHI - 256)	/* turn off flow control below TXLOW */
+#define PRIOMASK	7
+
+#define TXRETRIES	2	/* # of retries for tx frames */
+
+#define BRCMF_RXBOUND	50	/* Default for max rx frames in
+				 one scheduling */
+
+#define BRCMF_TXBOUND	20	/* Default for max tx frames in
+				 one scheduling */
+
+#define BRCMF_TXMINMAX	1	/* Max tx frames if rx still pending */
+
+#define MEMBLOCK	2048	/* Block size used for downloading
+				 of dongle image */
+#define MAX_DATA_BUF	(32 * 1024)	/* Must be large enough to hold
+				 biggest possible glom */
+
+#define BRCMF_FIRSTREAD	(1 << 6)
+
+#define BRCMF_CONSOLE	10	/* watchdog interval to poll console */
+
+/* SBSDIO_DEVICE_CTL */
+
+/* 1: device will assert busy signal when receiving CMD53 */
+#define SBSDIO_DEVCTL_SETBUSY		0x01
+/* 1: assertion of sdio interrupt is synchronous to the sdio clock */
+#define SBSDIO_DEVCTL_SPI_INTR_SYNC	0x02
+/* 1: mask all interrupts to host except the chipActive (rev 8) */
+#define SBSDIO_DEVCTL_CA_INT_ONLY	0x04
+/* 1: isolate internal sdio signals, put external pads in tri-state; requires
+ * sdio bus power cycle to clear (rev 9) */
+#define SBSDIO_DEVCTL_PADS_ISO		0x08
+/* Force SD->SB reset mapping (rev 11) */
+#define SBSDIO_DEVCTL_SB_RST_CTL	0x30
+/*   Determined by CoreControl bit */
+#define SBSDIO_DEVCTL_RST_CORECTL	0x00
+/*   Force backplane reset */
+#define SBSDIO_DEVCTL_RST_BPRESET	0x10
+/*   Force no backplane reset */
+#define SBSDIO_DEVCTL_RST_NOBPRESET	0x20
+
+/* direct(mapped) cis space */
+
+/* MAPPED common CIS address */
+#define SBSDIO_CIS_BASE_COMMON		0x1000
+/* maximum bytes in one CIS */
+#define SBSDIO_CIS_SIZE_LIMIT		0x200
+/* cis offset addr is < 17 bits */
+#define SBSDIO_CIS_OFT_ADDR_MASK	0x1FFFF
+
+/* manfid tuple length, include tuple, link bytes */
+#define SBSDIO_CIS_MANFID_TUPLE_LEN	6
+
+#define SD_REG(field) \
+		(offsetof(struct sdpcmd_regs, field))
+
+/* SDIO function 1 register CHIPCLKCSR */
+/* Force ALP request to backplane */
+#define SBSDIO_FORCE_ALP		0x01
+/* Force HT request to backplane */
+#define SBSDIO_FORCE_HT			0x02
+/* Force ILP request to backplane */
+#define SBSDIO_FORCE_ILP		0x04
+/* Make ALP ready (power up xtal) */
+#define SBSDIO_ALP_AVAIL_REQ		0x08
+/* Make HT ready (power up PLL) */
+#define SBSDIO_HT_AVAIL_REQ		0x10
+/* Squelch clock requests from HW */
+#define SBSDIO_FORCE_HW_CLKREQ_OFF	0x20
+/* Status: ALP is ready */
+#define SBSDIO_ALP_AVAIL		0x40
+/* Status: HT is ready */
+#define SBSDIO_HT_AVAIL			0x80
+#define SBSDIO_CSR_MASK			0x1F
+#define SBSDIO_AVBITS		(SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL)
+#define SBSDIO_ALPAV(regval)	((regval) & SBSDIO_AVBITS)
+#define SBSDIO_HTAV(regval)	(((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS)
+#define SBSDIO_ALPONLY(regval)	(SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval))
+#define SBSDIO_CLKAV(regval, alponly) \
+	(SBSDIO_ALPAV(regval) && (alponly ? 1 : SBSDIO_HTAV(regval)))
+
+/* intstatus */
+#define I_SMB_SW0	(1 << 0)	/* To SB Mail S/W interrupt 0 */
+#define I_SMB_SW1	(1 << 1)	/* To SB Mail S/W interrupt 1 */
+#define I_SMB_SW2	(1 << 2)	/* To SB Mail S/W interrupt 2 */
+#define I_SMB_SW3	(1 << 3)	/* To SB Mail S/W interrupt 3 */
+#define I_SMB_SW_MASK	0x0000000f	/* To SB Mail S/W interrupts mask */
+#define I_SMB_SW_SHIFT	0	/* To SB Mail S/W interrupts shift */
+#define I_HMB_SW0	(1 << 4)	/* To Host Mail S/W interrupt 0 */
+#define I_HMB_SW1	(1 << 5)	/* To Host Mail S/W interrupt 1 */
+#define I_HMB_SW2	(1 << 6)	/* To Host Mail S/W interrupt 2 */
+#define I_HMB_SW3	(1 << 7)	/* To Host Mail S/W interrupt 3 */
+#define I_HMB_SW_MASK	0x000000f0	/* To Host Mail S/W interrupts mask */
+#define I_HMB_SW_SHIFT	4	/* To Host Mail S/W interrupts shift */
+#define I_WR_OOSYNC	(1 << 8)	/* Write Frame Out Of Sync */
+#define I_RD_OOSYNC	(1 << 9)	/* Read Frame Out Of Sync */
+#define	I_PC		(1 << 10)	/* descriptor error */
+#define	I_PD		(1 << 11)	/* data error */
+#define	I_DE		(1 << 12)	/* Descriptor protocol Error */
+#define	I_RU		(1 << 13)	/* Receive descriptor Underflow */
+#define	I_RO		(1 << 14)	/* Receive fifo Overflow */
+#define	I_XU		(1 << 15)	/* Transmit fifo Underflow */
+#define	I_RI		(1 << 16)	/* Receive Interrupt */
+#define I_BUSPWR	(1 << 17)	/* SDIO Bus Power Change (rev 9) */
+#define I_XMTDATA_AVAIL (1 << 23)	/* bits in fifo */
+#define	I_XI		(1 << 24)	/* Transmit Interrupt */
+#define I_RF_TERM	(1 << 25)	/* Read Frame Terminate */
+#define I_WF_TERM	(1 << 26)	/* Write Frame Terminate */
+#define I_PCMCIA_XU	(1 << 27)	/* PCMCIA Transmit FIFO Underflow */
+#define I_SBINT		(1 << 28)	/* sbintstatus Interrupt */
+#define I_CHIPACTIVE	(1 << 29)	/* chip from doze to active state */
+#define I_SRESET	(1 << 30)	/* CCCR RES interrupt */
+#define I_IOE2		(1U << 31)	/* CCCR IOE2 Bit Changed */
+#define	I_ERRORS	(I_PC | I_PD | I_DE | I_RU | I_RO | I_XU)
+#define I_DMA		(I_RI | I_XI | I_ERRORS)
+
+/* corecontrol */
+#define CC_CISRDY		(1 << 0)	/* CIS Ready */
+#define CC_BPRESEN		(1 << 1)	/* CCCR RES signal */
+#define CC_F2RDY		(1 << 2)	/* set CCCR IOR2 bit */
+#define CC_CLRPADSISO		(1 << 3)	/* clear SDIO pads isolation */
+#define CC_XMTDATAAVAIL_MODE	(1 << 4)
+#define CC_XMTDATAAVAIL_CTRL	(1 << 5)
+
+/* SDA_FRAMECTRL */
+#define SFC_RF_TERM	(1 << 0)	/* Read Frame Terminate */
+#define SFC_WF_TERM	(1 << 1)	/* Write Frame Terminate */
+#define SFC_CRC4WOOS	(1 << 2)	/* CRC error for write out of sync */
+#define SFC_ABORTALL	(1 << 3)	/* Abort all in-progress frames */
+
+/*
+ * Software allocation of To SB Mailbox resources
+ */
+
+/* tosbmailbox bits corresponding to intstatus bits */
+#define SMB_NAK		(1 << 0)	/* Frame NAK */
+#define SMB_INT_ACK	(1 << 1)	/* Host Interrupt ACK */
+#define SMB_USE_OOB	(1 << 2)	/* Use OOB Wakeup */
+#define SMB_DEV_INT	(1 << 3)	/* Miscellaneous Interrupt */
+
+/* tosbmailboxdata */
+#define SMB_DATA_VERSION_SHIFT	16	/* host protocol version */
+
+/*
+ * Software allocation of To Host Mailbox resources
+ */
+
+/* intstatus bits */
+#define I_HMB_FC_STATE	I_HMB_SW0	/* Flow Control State */
+#define I_HMB_FC_CHANGE	I_HMB_SW1	/* Flow Control State Changed */
+#define I_HMB_FRAME_IND	I_HMB_SW2	/* Frame Indication */
+#define I_HMB_HOST_INT	I_HMB_SW3	/* Miscellaneous Interrupt */
+
+/* tohostmailboxdata */
+#define HMB_DATA_NAKHANDLED	0x0001	/* retransmit NAK'd frame */
+#define HMB_DATA_DEVREADY	0x0002	/* talk to host after enable */
+#define HMB_DATA_FC		0x0004	/* per prio flowcontrol update flag */
+#define HMB_DATA_FWREADY	0x0008	/* fw ready for protocol activity */
+#define HMB_DATA_FWHALT		0x0010	/* firmware halted */
+
+#define HMB_DATA_FCDATA_MASK	0xff000000
+#define HMB_DATA_FCDATA_SHIFT	24
+
+#define HMB_DATA_VERSION_MASK	0x00ff0000
+#define HMB_DATA_VERSION_SHIFT	16
+
+/*
+ * Software-defined protocol header
+ */
+
+/* Current protocol version */
+#define SDPCM_PROT_VERSION	4
+
+/*
+ * Shared structure between dongle and the host.
+ * The structure contains pointers to trap or assert information.
+ */
+#define SDPCM_SHARED_VERSION       0x0003
+#define SDPCM_SHARED_VERSION_MASK  0x00FF
+#define SDPCM_SHARED_ASSERT_BUILT  0x0100
+#define SDPCM_SHARED_ASSERT        0x0200
+#define SDPCM_SHARED_TRAP          0x0400
+
+/* Space for header read, limit for data packets */
+#define MAX_HDR_READ	(1 << 6)
+#define MAX_RX_DATASZ	2048
+
+/* Bump up limit on waiting for HT to account for first startup;
+ * if the image is doing a CRC calculation before programming the PMU
+ * for HT availability, it could take a couple hundred ms more, so
+ * max out at a 1 second (1000000us).
+ */
+#undef PMU_MAX_TRANSITION_DLY
+#define PMU_MAX_TRANSITION_DLY 1000000
+
+/* Value for ChipClockCSR during initial setup */
+#define BRCMF_INIT_CLKCTL1	(SBSDIO_FORCE_HW_CLKREQ_OFF |	\
+					SBSDIO_ALP_AVAIL_REQ)
+
+/* Flags for SDH calls */
+#define F2SYNC	(SDIO_REQ_4BYTE | SDIO_REQ_FIXED)
+
+#define BRCMF_IDLE_ACTIVE	0	/* Do not request any SD clock change
+					 * when idle
+					 */
+#define BRCMF_IDLE_INTERVAL	1
+
+#define KSO_WAIT_US 50
+#define MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US)
+#define BRCMF_SDIO_MAX_ACCESS_ERRORS	5
+
+/*
+ * Conversion of 802.1D priority to precedence level
+ */
+static uint prio2prec(u32 prio)
+{
+	return (prio == PRIO_8021D_NONE || prio == PRIO_8021D_BE) ?
+	       (prio^2) : prio;
+}
+
+#ifdef DEBUG
+/* Device console log buffer state */
+struct brcmf_console {
+	uint count;		/* Poll interval msec counter */
+	uint log_addr;		/* Log struct address (fixed) */
+	struct rte_log_le log_le;	/* Log struct (host copy) */
+	uint bufsize;		/* Size of log buffer */
+	u8 *buf;		/* Log buffer (host copy) */
+	uint last;		/* Last buffer read index */
+};
+
+struct brcmf_trap_info {
+	__le32		type;
+	__le32		epc;
+	__le32		cpsr;
+	__le32		spsr;
+	__le32		r0;	/* a1 */
+	__le32		r1;	/* a2 */
+	__le32		r2;	/* a3 */
+	__le32		r3;	/* a4 */
+	__le32		r4;	/* v1 */
+	__le32		r5;	/* v2 */
+	__le32		r6;	/* v3 */
+	__le32		r7;	/* v4 */
+	__le32		r8;	/* v5 */
+	__le32		r9;	/* sb/v6 */
+	__le32		r10;	/* sl/v7 */
+	__le32		r11;	/* fp/v8 */
+	__le32		r12;	/* ip */
+	__le32		r13;	/* sp */
+	__le32		r14;	/* lr */
+	__le32		pc;	/* r15 */
+};
+#endif				/* DEBUG */
+
+struct sdpcm_shared {
+	u32 flags;
+	u32 trap_addr;
+	u32 assert_exp_addr;
+	u32 assert_file_addr;
+	u32 assert_line;
+	u32 console_addr;	/* Address of struct rte_console */
+	u32 msgtrace_addr;
+	u8 tag[32];
+	u32 brpt_addr;
+};
+
+struct sdpcm_shared_le {
+	__le32 flags;
+	__le32 trap_addr;
+	__le32 assert_exp_addr;
+	__le32 assert_file_addr;
+	__le32 assert_line;
+	__le32 console_addr;	/* Address of struct rte_console */
+	__le32 msgtrace_addr;
+	u8 tag[32];
+	__le32 brpt_addr;
+};
+
+/* dongle SDIO bus specific header info */
+struct brcmf_sdio_hdrinfo {
+	u8 seq_num;
+	u8 channel;
+	u16 len;
+	u16 len_left;
+	u16 len_nxtfrm;
+	u8 dat_offset;
+	bool lastfrm;
+	u16 tail_pad;
+};
+
+/*
+ * hold counter variables
+ */
+struct brcmf_sdio_count {
+	uint intrcount;		/* Count of device interrupt callbacks */
+	uint lastintrs;		/* Count as of last watchdog timer */
+	uint pollcnt;		/* Count of active polls */
+	uint regfails;		/* Count of R_REG failures */
+	uint tx_sderrs;		/* Count of tx attempts with sd errors */
+	uint fcqueued;		/* Tx packets that got queued */
+	uint rxrtx;		/* Count of rtx requests (NAK to dongle) */
+	uint rx_toolong;	/* Receive frames too long to receive */
+	uint rxc_errors;	/* SDIO errors when reading control frames */
+	uint rx_hdrfail;	/* SDIO errors on header reads */
+	uint rx_badhdr;		/* Bad received headers (roosync?) */
+	uint rx_badseq;		/* Mismatched rx sequence number */
+	uint fc_rcvd;		/* Number of flow-control events received */
+	uint fc_xoff;		/* Number which turned on flow-control */
+	uint fc_xon;		/* Number which turned off flow-control */
+	uint rxglomfail;	/* Failed deglom attempts */
+	uint rxglomframes;	/* Number of glom frames (superframes) */
+	uint rxglompkts;	/* Number of packets from glom frames */
+	uint f2rxhdrs;		/* Number of header reads */
+	uint f2rxdata;		/* Number of frame data reads */
+	uint f2txdata;		/* Number of f2 frame writes */
+	uint f1regdata;		/* Number of f1 register accesses */
+	uint tickcnt;		/* Number of watchdog been schedule */
+	ulong tx_ctlerrs;	/* Err of sending ctrl frames */
+	ulong tx_ctlpkts;	/* Ctrl frames sent to dongle */
+	ulong rx_ctlerrs;	/* Err of processing rx ctrl frames */
+	ulong rx_ctlpkts;	/* Ctrl frames processed from dongle */
+	ulong rx_readahead_cnt;	/* packets where header read-ahead was used */
+};
+
+/* misc chip info needed by some of the routines */
+/* Private data for SDIO bus interaction */
+struct brcmf_sdio {
+	struct brcmf_sdio_dev *sdiodev;	/* sdio device handler */
+	struct brcmf_chip *ci;	/* Chip info struct */
+	struct brcmf_core *sdio_core; /* sdio core info struct */
+
+	u32 hostintmask;	/* Copy of Host Interrupt Mask */
+	atomic_t intstatus;	/* Intstatus bits (events) pending */
+	atomic_t fcstate;	/* State of dongle flow-control */
+
+	uint blocksize;		/* Block size of SDIO transfers */
+	uint roundup;		/* Max roundup limit */
+
+	struct pktq txq;	/* Queue length used for flow-control */
+	u8 flowcontrol;	/* per prio flow control bitmask */
+	u8 tx_seq;		/* Transmit sequence number (next) */
+	u8 tx_max;		/* Maximum transmit sequence allowed */
+
+	u8 *hdrbuf;		/* buffer for handling rx frame */
+	u8 *rxhdr;		/* Header of current rx frame (in hdrbuf) */
+	u8 rx_seq;		/* Receive sequence number (expected) */
+	struct brcmf_sdio_hdrinfo cur_read;
+				/* info of current read frame */
+	bool rxskip;		/* Skip receive (awaiting NAK ACK) */
+	bool rxpending;		/* Data frame pending in dongle */
+
+	uint rxbound;		/* Rx frames to read before resched */
+	uint txbound;		/* Tx frames to send before resched */
+	uint txminmax;
+
+	struct sk_buff *glomd;	/* Packet containing glomming descriptor */
+	struct sk_buff_head glom; /* Packet list for glommed superframe */
+
+	u8 *rxbuf;		/* Buffer for receiving control packets */
+	uint rxblen;		/* Allocated length of rxbuf */
+	u8 *rxctl;		/* Aligned pointer into rxbuf */
+	u8 *rxctl_orig;		/* pointer for freeing rxctl */
+	uint rxlen;		/* Length of valid data in buffer */
+	spinlock_t rxctl_lock;	/* protection lock for ctrl frame resources */
+
+	u8 sdpcm_ver;	/* Bus protocol reported by dongle */
+
+	bool intr;		/* Use interrupts */
+	bool poll;		/* Use polling */
+	atomic_t ipend;		/* Device interrupt is pending */
+	uint spurious;		/* Count of spurious interrupts */
+	uint pollrate;		/* Ticks between device polls */
+	uint polltick;		/* Tick counter */
+
+#ifdef DEBUG
+	uint console_interval;
+	struct brcmf_console console;	/* Console output polling support */
+	uint console_addr;	/* Console address from shared struct */
+#endif				/* DEBUG */
+
+	uint clkstate;		/* State of sd and backplane clock(s) */
+	s32 idletime;		/* Control for activity timeout */
+	s32 idlecount;		/* Activity timeout counter */
+	s32 idleclock;		/* How to set bus driver when idle */
+	bool rxflow_mode;	/* Rx flow control mode */
+	bool rxflow;		/* Is rx flow control on */
+	bool alp_only;		/* Don't use HT clock (ALP only) */
+
+	u8 *ctrl_frame_buf;
+	u16 ctrl_frame_len;
+	bool ctrl_frame_stat;
+	int ctrl_frame_err;
+
+	spinlock_t txq_lock;		/* protect bus->txq */
+	wait_queue_head_t ctrl_wait;
+	wait_queue_head_t dcmd_resp_wait;
+
+	struct timer_list timer;
+	struct completion watchdog_wait;
+	struct task_struct *watchdog_tsk;
+	bool wd_active;
+
+	struct workqueue_struct *brcmf_wq;
+	struct work_struct datawork;
+	bool dpc_triggered;
+	bool dpc_running;
+
+	bool txoff;		/* Transmit flow-controlled */
+	struct brcmf_sdio_count sdcnt;
+	bool sr_enabled; /* SaveRestore enabled */
+	bool sleeping;
+
+	u8 tx_hdrlen;		/* sdio bus header length for tx packet */
+	bool txglom;		/* host tx glomming enable flag */
+	u16 head_align;		/* buffer pointer alignment */
+	u16 sgentry_align;	/* scatter-gather buffer alignment */
+};
+
+/* clkstate */
+#define CLK_NONE	0
+#define CLK_SDONLY	1
+#define CLK_PENDING	2
+#define CLK_AVAIL	3
+
+#ifdef DEBUG
+static int qcount[NUMPRIO];
+#endif				/* DEBUG */
+
+#define DEFAULT_SDIO_DRIVE_STRENGTH	6	/* in milliamps */
+
+#define RETRYCHAN(chan) ((chan) == SDPCM_EVENT_CHANNEL)
+
+/* Limit on rounding up frames */
+static const uint max_roundup = 512;
+
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+#define ALIGNMENT  8
+#else
+#define ALIGNMENT  4
+#endif
+
+enum brcmf_sdio_frmtype {
+	BRCMF_SDIO_FT_NORMAL,
+	BRCMF_SDIO_FT_SUPER,
+	BRCMF_SDIO_FT_SUB,
+};
+
+#define SDIOD_DRVSTR_KEY(chip, pmu)     (((chip) << 16) | (pmu))
+
+/* SDIO Pad drive strength to select value mappings */
+struct sdiod_drive_str {
+	u8 strength;	/* Pad Drive Strength in mA */
+	u8 sel;		/* Chip-specific select value */
+};
+
+/* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8V) */
+static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8[] = {
+	{32, 0x6},
+	{26, 0x7},
+	{22, 0x4},
+	{16, 0x5},
+	{12, 0x2},
+	{8, 0x3},
+	{4, 0x0},
+	{0, 0x1}
+};
+
+/* SDIO Drive Strength to sel value table for PMU Rev 13 (1.8v) */
+static const struct sdiod_drive_str sdiod_drive_strength_tab5_1v8[] = {
+	{6, 0x7},
+	{5, 0x6},
+	{4, 0x5},
+	{3, 0x4},
+	{2, 0x2},
+	{1, 0x1},
+	{0, 0x0}
+};
+
+/* SDIO Drive Strength to sel value table for PMU Rev 17 (1.8v) */
+static const struct sdiod_drive_str sdiod_drvstr_tab6_1v8[] = {
+	{3, 0x3},
+	{2, 0x2},
+	{1, 0x1},
+	{0, 0x0} };
+
+/* SDIO Drive Strength to sel value table for 43143 PMU Rev 17 (3.3V) */
+static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3[] = {
+	{16, 0x7},
+	{12, 0x5},
+	{8,  0x3},
+	{4,  0x1}
+};
+
+BRCMF_FW_DEF(43143, "brcmfmac43143-sdio");
+BRCMF_FW_DEF(43241B0, "brcmfmac43241b0-sdio");
+BRCMF_FW_DEF(43241B4, "brcmfmac43241b4-sdio");
+BRCMF_FW_DEF(43241B5, "brcmfmac43241b5-sdio");
+BRCMF_FW_DEF(4329, "brcmfmac4329-sdio");
+BRCMF_FW_DEF(4330, "brcmfmac4330-sdio");
+BRCMF_FW_DEF(4334, "brcmfmac4334-sdio");
+BRCMF_FW_DEF(43340, "brcmfmac43340-sdio");
+BRCMF_FW_DEF(4335, "brcmfmac4335-sdio");
+BRCMF_FW_DEF(43362, "brcmfmac43362-sdio");
+BRCMF_FW_DEF(4339, "brcmfmac4339-sdio");
+BRCMF_FW_DEF(43430A0, "brcmfmac43430a0-sdio");
+/* Note the names are not postfixed with a1 for backward compatibility */
+BRCMF_FW_DEF(43430A1, "brcmfmac43430-sdio");
+BRCMF_FW_DEF(43455, "brcmfmac43455-sdio");
+BRCMF_FW_DEF(4354, "brcmfmac4354-sdio");
+BRCMF_FW_DEF(4356, "brcmfmac4356-sdio");
+BRCMF_FW_DEF(4373, "brcmfmac4373-sdio");
+
+static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {
+	BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143),
+	BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x0000001F, 43241B0),
+	BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x00000020, 43241B4),
+	BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0xFFFFFFC0, 43241B5),
+	BRCMF_FW_ENTRY(BRCM_CC_4329_CHIP_ID, 0xFFFFFFFF, 4329),
+	BRCMF_FW_ENTRY(BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, 4330),
+	BRCMF_FW_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334),
+	BRCMF_FW_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340),
+	BRCMF_FW_ENTRY(BRCM_CC_43341_CHIP_ID, 0xFFFFFFFF, 43340),
+	BRCMF_FW_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335),
+	BRCMF_FW_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362),
+	BRCMF_FW_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339),
+	BRCMF_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 0x00000001, 43430A0),
+	BRCMF_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 0xFFFFFFFE, 43430A1),
+	BRCMF_FW_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFFFFFC0, 43455),
+	BRCMF_FW_ENTRY(BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, 4354),
+	BRCMF_FW_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356),
+	BRCMF_FW_ENTRY(CY_CC_4373_CHIP_ID, 0xFFFFFFFF, 4373)
+};
+
+static void pkt_align(struct sk_buff *p, int len, int align)
+{
+	uint datalign;
+	datalign = (unsigned long)(p->data);
+	datalign = roundup(datalign, (align)) - datalign;
+	if (datalign)
+		skb_pull(p, datalign);
+	__skb_trim(p, len);
+}
+
+/* To check if there's window offered */
+static bool data_ok(struct brcmf_sdio *bus)
+{
+	return (u8)(bus->tx_max - bus->tx_seq) != 0 &&
+	       ((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0;
+}
+
+static int
+brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on)
+{
+	u8 wr_val = 0, rd_val, cmp_val, bmask;
+	int err = 0;
+	int err_cnt = 0;
+	int try_cnt = 0;
+
+	brcmf_dbg(TRACE, "Enter: on=%d\n", on);
+
+	wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
+	/* 1st KSO write goes to AOS wake up core if device is asleep  */
+	brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err);
+
+	if (on) {
+		/* device WAKEUP through KSO:
+		 * write bit 0 & read back until
+		 * both bits 0 (kso bit) & 1 (dev on status) are set
+		 */
+		cmp_val = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK |
+			  SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK;
+		bmask = cmp_val;
+		usleep_range(2000, 3000);
+	} else {
+		/* Put device to sleep, turn off KSO */
+		cmp_val = 0;
+		/* only check for bit0, bit1(dev on status) may not
+		 * get cleared right away
+		 */
+		bmask = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK;
+	}
+
+	do {
+		/* reliable KSO bit set/clr:
+		 * the sdiod sleep write access is synced to PMU 32khz clk
+		 * just one write attempt may fail,
+		 * read it back until it matches written value
+		 */
+		rd_val = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
+					   &err);
+		if (!err) {
+			if ((rd_val & bmask) == cmp_val)
+				break;
+			err_cnt = 0;
+		}
+		/* bail out upon subsequent access errors */
+		if (err && (err_cnt++ > BRCMF_SDIO_MAX_ACCESS_ERRORS))
+			break;
+
+		udelay(KSO_WAIT_US);
+		brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, wr_val,
+				   &err);
+
+	} while (try_cnt++ < MAX_KSO_ATTEMPTS);
+
+	if (try_cnt > 2)
+		brcmf_dbg(SDIO, "try_cnt=%d rd_val=0x%x err=%d\n", try_cnt,
+			  rd_val, err);
+
+	if (try_cnt > MAX_KSO_ATTEMPTS)
+		brcmf_err("max tries: rd_val=0x%x err=%d\n", rd_val, err);
+
+	return err;
+}
+
+#define HOSTINTMASK		(I_HMB_SW_MASK | I_CHIPACTIVE)
+
+/* Turn backplane clock on or off */
+static int brcmf_sdio_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
+{
+	int err;
+	u8 clkctl, clkreq, devctl;
+	unsigned long timeout;
+
+	brcmf_dbg(SDIO, "Enter\n");
+
+	clkctl = 0;
+
+	if (bus->sr_enabled) {
+		bus->clkstate = (on ? CLK_AVAIL : CLK_SDONLY);
+		return 0;
+	}
+
+	if (on) {
+		/* Request HT Avail */
+		clkreq =
+		    bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ;
+
+		brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+				   clkreq, &err);
+		if (err) {
+			brcmf_err("HT Avail request error: %d\n", err);
+			return -EBADE;
+		}
+
+		/* Check current status */
+		clkctl = brcmf_sdiod_readb(bus->sdiodev,
+					   SBSDIO_FUNC1_CHIPCLKCSR, &err);
+		if (err) {
+			brcmf_err("HT Avail read error: %d\n", err);
+			return -EBADE;
+		}
+
+		/* Go to pending and await interrupt if appropriate */
+		if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) {
+			/* Allow only clock-available interrupt */
+			devctl = brcmf_sdiod_readb(bus->sdiodev,
+						   SBSDIO_DEVICE_CTL, &err);
+			if (err) {
+				brcmf_err("Devctl error setting CA: %d\n", err);
+				return -EBADE;
+			}
+
+			devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
+			brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_DEVICE_CTL,
+					   devctl, &err);
+			brcmf_dbg(SDIO, "CLKCTL: set PENDING\n");
+			bus->clkstate = CLK_PENDING;
+
+			return 0;
+		} else if (bus->clkstate == CLK_PENDING) {
+			/* Cancel CA-only interrupt filter */
+			devctl = brcmf_sdiod_readb(bus->sdiodev,
+						   SBSDIO_DEVICE_CTL, &err);
+			devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
+			brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_DEVICE_CTL,
+					   devctl, &err);
+		}
+
+		/* Otherwise, wait here (polling) for HT Avail */
+		timeout = jiffies +
+			  msecs_to_jiffies(PMU_MAX_TRANSITION_DLY/1000);
+		while (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
+			clkctl = brcmf_sdiod_readb(bus->sdiodev,
+						   SBSDIO_FUNC1_CHIPCLKCSR,
+						   &err);
+			if (time_after(jiffies, timeout))
+				break;
+			else
+				usleep_range(5000, 10000);
+		}
+		if (err) {
+			brcmf_err("HT Avail request error: %d\n", err);
+			return -EBADE;
+		}
+		if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
+			brcmf_err("HT Avail timeout (%d): clkctl 0x%02x\n",
+				  PMU_MAX_TRANSITION_DLY, clkctl);
+			return -EBADE;
+		}
+
+		/* Mark clock available */
+		bus->clkstate = CLK_AVAIL;
+		brcmf_dbg(SDIO, "CLKCTL: turned ON\n");
+
+#if defined(DEBUG)
+		if (!bus->alp_only) {
+			if (SBSDIO_ALPONLY(clkctl))
+				brcmf_err("HT Clock should be on\n");
+		}
+#endif				/* defined (DEBUG) */
+
+	} else {
+		clkreq = 0;
+
+		if (bus->clkstate == CLK_PENDING) {
+			/* Cancel CA-only interrupt filter */
+			devctl = brcmf_sdiod_readb(bus->sdiodev,
+						   SBSDIO_DEVICE_CTL, &err);
+			devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
+			brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_DEVICE_CTL,
+					   devctl, &err);
+		}
+
+		bus->clkstate = CLK_SDONLY;
+		brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+				   clkreq, &err);
+		brcmf_dbg(SDIO, "CLKCTL: turned OFF\n");
+		if (err) {
+			brcmf_err("Failed access turning clock off: %d\n",
+				  err);
+			return -EBADE;
+		}
+	}
+	return 0;
+}
+
+/* Change idle/active SD state */
+static int brcmf_sdio_sdclk(struct brcmf_sdio *bus, bool on)
+{
+	brcmf_dbg(SDIO, "Enter\n");
+
+	if (on)
+		bus->clkstate = CLK_SDONLY;
+	else
+		bus->clkstate = CLK_NONE;
+
+	return 0;
+}
+
+/* Transition SD and backplane clock readiness */
+static int brcmf_sdio_clkctl(struct brcmf_sdio *bus, uint target, bool pendok)
+{
+#ifdef DEBUG
+	uint oldstate = bus->clkstate;
+#endif				/* DEBUG */
+
+	brcmf_dbg(SDIO, "Enter\n");
+
+	/* Early exit if we're already there */
+	if (bus->clkstate == target)
+		return 0;
+
+	switch (target) {
+	case CLK_AVAIL:
+		/* Make sure SD clock is available */
+		if (bus->clkstate == CLK_NONE)
+			brcmf_sdio_sdclk(bus, true);
+		/* Now request HT Avail on the backplane */
+		brcmf_sdio_htclk(bus, true, pendok);
+		break;
+
+	case CLK_SDONLY:
+		/* Remove HT request, or bring up SD clock */
+		if (bus->clkstate == CLK_NONE)
+			brcmf_sdio_sdclk(bus, true);
+		else if (bus->clkstate == CLK_AVAIL)
+			brcmf_sdio_htclk(bus, false, false);
+		else
+			brcmf_err("request for %d -> %d\n",
+				  bus->clkstate, target);
+		break;
+
+	case CLK_NONE:
+		/* Make sure to remove HT request */
+		if (bus->clkstate == CLK_AVAIL)
+			brcmf_sdio_htclk(bus, false, false);
+		/* Now remove the SD clock */
+		brcmf_sdio_sdclk(bus, false);
+		break;
+	}
+#ifdef DEBUG
+	brcmf_dbg(SDIO, "%d -> %d\n", oldstate, bus->clkstate);
+#endif				/* DEBUG */
+
+	return 0;
+}
+
+static int
+brcmf_sdio_bus_sleep(struct brcmf_sdio *bus, bool sleep, bool pendok)
+{
+	int err = 0;
+	u8 clkcsr;
+
+	brcmf_dbg(SDIO, "Enter: request %s currently %s\n",
+		  (sleep ? "SLEEP" : "WAKE"),
+		  (bus->sleeping ? "SLEEP" : "WAKE"));
+
+	/* If SR is enabled control bus state with KSO */
+	if (bus->sr_enabled) {
+		/* Done if we're already in the requested state */
+		if (sleep == bus->sleeping)
+			goto end;
+
+		/* Going to sleep */
+		if (sleep) {
+			clkcsr = brcmf_sdiod_readb(bus->sdiodev,
+						   SBSDIO_FUNC1_CHIPCLKCSR,
+						   &err);
+			if ((clkcsr & SBSDIO_CSR_MASK) == 0) {
+				brcmf_dbg(SDIO, "no clock, set ALP\n");
+				brcmf_sdiod_writeb(bus->sdiodev,
+						   SBSDIO_FUNC1_CHIPCLKCSR,
+						   SBSDIO_ALP_AVAIL_REQ, &err);
+			}
+			err = brcmf_sdio_kso_control(bus, false);
+		} else {
+			err = brcmf_sdio_kso_control(bus, true);
+		}
+		if (err) {
+			brcmf_err("error while changing bus sleep state %d\n",
+				  err);
+			goto done;
+		}
+	}
+
+end:
+	/* control clocks */
+	if (sleep) {
+		if (!bus->sr_enabled)
+			brcmf_sdio_clkctl(bus, CLK_NONE, pendok);
+	} else {
+		brcmf_sdio_clkctl(bus, CLK_AVAIL, pendok);
+		brcmf_sdio_wd_timer(bus, true);
+	}
+	bus->sleeping = sleep;
+	brcmf_dbg(SDIO, "new state %s\n",
+		  (sleep ? "SLEEP" : "WAKE"));
+done:
+	brcmf_dbg(SDIO, "Exit: err=%d\n", err);
+	return err;
+
+}
+
+#ifdef DEBUG
+static inline bool brcmf_sdio_valid_shared_address(u32 addr)
+{
+	return !(addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff));
+}
+
+static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
+				 struct sdpcm_shared *sh)
+{
+	u32 addr = 0;
+	int rv;
+	u32 shaddr = 0;
+	struct sdpcm_shared_le sh_le;
+	__le32 addr_le;
+
+	sdio_claim_host(bus->sdiodev->func1);
+	brcmf_sdio_bus_sleep(bus, false, false);
+
+	/*
+	 * Read last word in socram to determine
+	 * address of sdpcm_shared structure
+	 */
+	shaddr = bus->ci->rambase + bus->ci->ramsize - 4;
+	if (!bus->ci->rambase && brcmf_chip_sr_capable(bus->ci))
+		shaddr -= bus->ci->srsize;
+	rv = brcmf_sdiod_ramrw(bus->sdiodev, false, shaddr,
+			       (u8 *)&addr_le, 4);
+	if (rv < 0)
+		goto fail;
+
+	/*
+	 * Check if addr is valid.
+	 * NVRAM length at the end of memory should have been overwritten.
+	 */
+	addr = le32_to_cpu(addr_le);
+	if (!brcmf_sdio_valid_shared_address(addr)) {
+		brcmf_err("invalid sdpcm_shared address 0x%08X\n", addr);
+		rv = -EINVAL;
+		goto fail;
+	}
+
+	brcmf_dbg(INFO, "sdpcm_shared address 0x%08X\n", addr);
+
+	/* Read hndrte_shared structure */
+	rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr, (u8 *)&sh_le,
+			       sizeof(struct sdpcm_shared_le));
+	if (rv < 0)
+		goto fail;
+
+	sdio_release_host(bus->sdiodev->func1);
+
+	/* Endianness */
+	sh->flags = le32_to_cpu(sh_le.flags);
+	sh->trap_addr = le32_to_cpu(sh_le.trap_addr);
+	sh->assert_exp_addr = le32_to_cpu(sh_le.assert_exp_addr);
+	sh->assert_file_addr = le32_to_cpu(sh_le.assert_file_addr);
+	sh->assert_line = le32_to_cpu(sh_le.assert_line);
+	sh->console_addr = le32_to_cpu(sh_le.console_addr);
+	sh->msgtrace_addr = le32_to_cpu(sh_le.msgtrace_addr);
+
+	if ((sh->flags & SDPCM_SHARED_VERSION_MASK) > SDPCM_SHARED_VERSION) {
+		brcmf_err("sdpcm shared version unsupported: dhd %d dongle %d\n",
+			  SDPCM_SHARED_VERSION,
+			  sh->flags & SDPCM_SHARED_VERSION_MASK);
+		return -EPROTO;
+	}
+	return 0;
+
+fail:
+	brcmf_err("unable to obtain sdpcm_shared info: rv=%d (addr=0x%x)\n",
+		  rv, addr);
+	sdio_release_host(bus->sdiodev->func1);
+	return rv;
+}
+
+static void brcmf_sdio_get_console_addr(struct brcmf_sdio *bus)
+{
+	struct sdpcm_shared sh;
+
+	if (brcmf_sdio_readshared(bus, &sh) == 0)
+		bus->console_addr = sh.console_addr;
+}
+#else
+static void brcmf_sdio_get_console_addr(struct brcmf_sdio *bus)
+{
+}
+#endif /* DEBUG */
+
+static u32 brcmf_sdio_hostmail(struct brcmf_sdio *bus)
+{
+	struct brcmf_sdio_dev *sdiod = bus->sdiodev;
+	struct brcmf_core *core = bus->sdio_core;
+	u32 intstatus = 0;
+	u32 hmb_data;
+	u8 fcbits;
+	int ret;
+
+	brcmf_dbg(SDIO, "Enter\n");
+
+	/* Read mailbox data and ack that we did so */
+	hmb_data = brcmf_sdiod_readl(sdiod,
+				     core->base + SD_REG(tohostmailboxdata),
+				     &ret);
+
+	if (!ret)
+		brcmf_sdiod_writel(sdiod, core->base + SD_REG(tosbmailbox),
+				   SMB_INT_ACK, &ret);
+
+	bus->sdcnt.f1regdata += 2;
+
+	/* dongle indicates the firmware has halted/crashed */
+	if (hmb_data & HMB_DATA_FWHALT) {
+		brcmf_err("mailbox indicates firmware halted\n");
+		brcmf_dev_coredump(&sdiod->func1->dev);
+	}
+
+	/* Dongle recomposed rx frames, accept them again */
+	if (hmb_data & HMB_DATA_NAKHANDLED) {
+		brcmf_dbg(SDIO, "Dongle reports NAK handled, expect rtx of %d\n",
+			  bus->rx_seq);
+		if (!bus->rxskip)
+			brcmf_err("unexpected NAKHANDLED!\n");
+
+		bus->rxskip = false;
+		intstatus |= I_HMB_FRAME_IND;
+	}
+
+	/*
+	 * DEVREADY does not occur with gSPI.
+	 */
+	if (hmb_data & (HMB_DATA_DEVREADY | HMB_DATA_FWREADY)) {
+		bus->sdpcm_ver =
+		    (hmb_data & HMB_DATA_VERSION_MASK) >>
+		    HMB_DATA_VERSION_SHIFT;
+		if (bus->sdpcm_ver != SDPCM_PROT_VERSION)
+			brcmf_err("Version mismatch, dongle reports %d, "
+				  "expecting %d\n",
+				  bus->sdpcm_ver, SDPCM_PROT_VERSION);
+		else
+			brcmf_dbg(SDIO, "Dongle ready, protocol version %d\n",
+				  bus->sdpcm_ver);
+
+		/*
+		 * Retrieve console state address now that firmware should have
+		 * updated it.
+		 */
+		brcmf_sdio_get_console_addr(bus);
+	}
+
+	/*
+	 * Flow Control has been moved into the RX headers and this out of band
+	 * method isn't used any more.
+	 * remaining backward compatible with older dongles.
+	 */
+	if (hmb_data & HMB_DATA_FC) {
+		fcbits = (hmb_data & HMB_DATA_FCDATA_MASK) >>
+							HMB_DATA_FCDATA_SHIFT;
+
+		if (fcbits & ~bus->flowcontrol)
+			bus->sdcnt.fc_xoff++;
+
+		if (bus->flowcontrol & ~fcbits)
+			bus->sdcnt.fc_xon++;
+
+		bus->sdcnt.fc_rcvd++;
+		bus->flowcontrol = fcbits;
+	}
+
+	/* Shouldn't be any others */
+	if (hmb_data & ~(HMB_DATA_DEVREADY |
+			 HMB_DATA_NAKHANDLED |
+			 HMB_DATA_FC |
+			 HMB_DATA_FWREADY |
+			 HMB_DATA_FWHALT |
+			 HMB_DATA_FCDATA_MASK | HMB_DATA_VERSION_MASK))
+		brcmf_err("Unknown mailbox data content: 0x%02x\n",
+			  hmb_data);
+
+	return intstatus;
+}
+
+static void brcmf_sdio_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
+{
+	struct brcmf_sdio_dev *sdiod = bus->sdiodev;
+	struct brcmf_core *core = bus->sdio_core;
+	uint retries = 0;
+	u16 lastrbc;
+	u8 hi, lo;
+	int err;
+
+	brcmf_err("%sterminate frame%s\n",
+		  abort ? "abort command, " : "",
+		  rtx ? ", send NAK" : "");
+
+	if (abort)
+		brcmf_sdiod_abort(bus->sdiodev, bus->sdiodev->func2);
+
+	brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM,
+			   &err);
+	bus->sdcnt.f1regdata++;
+
+	/* Wait until the packet has been flushed (device/FIFO stable) */
+	for (lastrbc = retries = 0xffff; retries > 0; retries--) {
+		hi = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_RFRAMEBCHI,
+				       &err);
+		lo = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_RFRAMEBCLO,
+				       &err);
+		bus->sdcnt.f1regdata += 2;
+
+		if ((hi == 0) && (lo == 0))
+			break;
+
+		if ((hi > (lastrbc >> 8)) && (lo > (lastrbc & 0x00ff))) {
+			brcmf_err("count growing: last 0x%04x now 0x%04x\n",
+				  lastrbc, (hi << 8) + lo);
+		}
+		lastrbc = (hi << 8) + lo;
+	}
+
+	if (!retries)
+		brcmf_err("count never zeroed: last 0x%04x\n", lastrbc);
+	else
+		brcmf_dbg(SDIO, "flush took %d iterations\n", 0xffff - retries);
+
+	if (rtx) {
+		bus->sdcnt.rxrtx++;
+		brcmf_sdiod_writel(sdiod, core->base + SD_REG(tosbmailbox),
+				   SMB_NAK, &err);
+
+		bus->sdcnt.f1regdata++;
+		if (err == 0)
+			bus->rxskip = true;
+	}
+
+	/* Clear partial in any case */
+	bus->cur_read.len = 0;
+}
+
+static void brcmf_sdio_txfail(struct brcmf_sdio *bus)
+{
+	struct brcmf_sdio_dev *sdiodev = bus->sdiodev;
+	u8 i, hi, lo;
+
+	/* On failure, abort the command and terminate the frame */
+	brcmf_err("sdio error, abort command and terminate frame\n");
+	bus->sdcnt.tx_sderrs++;
+
+	brcmf_sdiod_abort(sdiodev, sdiodev->func2);
+	brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, NULL);
+	bus->sdcnt.f1regdata++;
+
+	for (i = 0; i < 3; i++) {
+		hi = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_WFRAMEBCHI, NULL);
+		lo = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_WFRAMEBCLO, NULL);
+		bus->sdcnt.f1regdata += 2;
+		if ((hi == 0) && (lo == 0))
+			break;
+	}
+}
+
+/* return total length of buffer chain */
+static uint brcmf_sdio_glom_len(struct brcmf_sdio *bus)
+{
+	struct sk_buff *p;
+	uint total;
+
+	total = 0;
+	skb_queue_walk(&bus->glom, p)
+		total += p->len;
+	return total;
+}
+
+static void brcmf_sdio_free_glom(struct brcmf_sdio *bus)
+{
+	struct sk_buff *cur, *next;
+
+	skb_queue_walk_safe(&bus->glom, cur, next) {
+		skb_unlink(cur, &bus->glom);
+		brcmu_pkt_buf_free_skb(cur);
+	}
+}
+
+/**
+ * brcmfmac sdio bus specific header
+ * This is the lowest layer header wrapped on the packets transmitted between
+ * host and WiFi dongle which contains information needed for SDIO core and
+ * firmware
+ *
+ * It consists of 3 parts: hardware header, hardware extension header and
+ * software header
+ * hardware header (frame tag) - 4 bytes
+ * Byte 0~1: Frame length
+ * Byte 2~3: Checksum, bit-wise inverse of frame length
+ * hardware extension header - 8 bytes
+ * Tx glom mode only, N/A for Rx or normal Tx
+ * Byte 0~1: Packet length excluding hw frame tag
+ * Byte 2: Reserved
+ * Byte 3: Frame flags, bit 0: last frame indication
+ * Byte 4~5: Reserved
+ * Byte 6~7: Tail padding length
+ * software header - 8 bytes
+ * Byte 0: Rx/Tx sequence number
+ * Byte 1: 4 MSB Channel number, 4 LSB arbitrary flag
+ * Byte 2: Length of next data frame, reserved for Tx
+ * Byte 3: Data offset
+ * Byte 4: Flow control bits, reserved for Tx
+ * Byte 5: Maximum Sequence number allowed by firmware for Tx, N/A for Tx packet
+ * Byte 6~7: Reserved
+ */
+#define SDPCM_HWHDR_LEN			4
+#define SDPCM_HWEXT_LEN			8
+#define SDPCM_SWHDR_LEN			8
+#define SDPCM_HDRLEN			(SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN)
+/* software header */
+#define SDPCM_SEQ_MASK			0x000000ff
+#define SDPCM_SEQ_WRAP			256
+#define SDPCM_CHANNEL_MASK		0x00000f00
+#define SDPCM_CHANNEL_SHIFT		8
+#define SDPCM_CONTROL_CHANNEL		0	/* Control */
+#define SDPCM_EVENT_CHANNEL		1	/* Asyc Event Indication */
+#define SDPCM_DATA_CHANNEL		2	/* Data Xmit/Recv */
+#define SDPCM_GLOM_CHANNEL		3	/* Coalesced packets */
+#define SDPCM_TEST_CHANNEL		15	/* Test/debug packets */
+#define SDPCM_GLOMDESC(p)		(((u8 *)p)[1] & 0x80)
+#define SDPCM_NEXTLEN_MASK		0x00ff0000
+#define SDPCM_NEXTLEN_SHIFT		16
+#define SDPCM_DOFFSET_MASK		0xff000000
+#define SDPCM_DOFFSET_SHIFT		24
+#define SDPCM_FCMASK_MASK		0x000000ff
+#define SDPCM_WINDOW_MASK		0x0000ff00
+#define SDPCM_WINDOW_SHIFT		8
+
+static inline u8 brcmf_sdio_getdatoffset(u8 *swheader)
+{
+	u32 hdrvalue;
+	hdrvalue = *(u32 *)swheader;
+	return (u8)((hdrvalue & SDPCM_DOFFSET_MASK) >> SDPCM_DOFFSET_SHIFT);
+}
+
+static inline bool brcmf_sdio_fromevntchan(u8 *swheader)
+{
+	u32 hdrvalue;
+	u8 ret;
+
+	hdrvalue = *(u32 *)swheader;
+	ret = (u8)((hdrvalue & SDPCM_CHANNEL_MASK) >> SDPCM_CHANNEL_SHIFT);
+
+	return (ret == SDPCM_EVENT_CHANNEL);
+}
+
+static int brcmf_sdio_hdparse(struct brcmf_sdio *bus, u8 *header,
+			      struct brcmf_sdio_hdrinfo *rd,
+			      enum brcmf_sdio_frmtype type)
+{
+	u16 len, checksum;
+	u8 rx_seq, fc, tx_seq_max;
+	u32 swheader;
+
+	trace_brcmf_sdpcm_hdr(SDPCM_RX, header);
+
+	/* hw header */
+	len = get_unaligned_le16(header);
+	checksum = get_unaligned_le16(header + sizeof(u16));
+	/* All zero means no more to read */
+	if (!(len | checksum)) {
+		bus->rxpending = false;
+		return -ENODATA;
+	}
+	if ((u16)(~(len ^ checksum))) {
+		brcmf_err("HW header checksum error\n");
+		bus->sdcnt.rx_badhdr++;
+		brcmf_sdio_rxfail(bus, false, false);
+		return -EIO;
+	}
+	if (len < SDPCM_HDRLEN) {
+		brcmf_err("HW header length error\n");
+		return -EPROTO;
+	}
+	if (type == BRCMF_SDIO_FT_SUPER &&
+	    (roundup(len, bus->blocksize) != rd->len)) {
+		brcmf_err("HW superframe header length error\n");
+		return -EPROTO;
+	}
+	if (type == BRCMF_SDIO_FT_SUB && len > rd->len) {
+		brcmf_err("HW subframe header length error\n");
+		return -EPROTO;
+	}
+	rd->len = len;
+
+	/* software header */
+	header += SDPCM_HWHDR_LEN;
+	swheader = le32_to_cpu(*(__le32 *)header);
+	if (type == BRCMF_SDIO_FT_SUPER && SDPCM_GLOMDESC(header)) {
+		brcmf_err("Glom descriptor found in superframe head\n");
+		rd->len = 0;
+		return -EINVAL;
+	}
+	rx_seq = (u8)(swheader & SDPCM_SEQ_MASK);
+	rd->channel = (swheader & SDPCM_CHANNEL_MASK) >> SDPCM_CHANNEL_SHIFT;
+	if (len > MAX_RX_DATASZ && rd->channel != SDPCM_CONTROL_CHANNEL &&
+	    type != BRCMF_SDIO_FT_SUPER) {
+		brcmf_err("HW header length too long\n");
+		bus->sdcnt.rx_toolong++;
+		brcmf_sdio_rxfail(bus, false, false);
+		rd->len = 0;
+		return -EPROTO;
+	}
+	if (type == BRCMF_SDIO_FT_SUPER && rd->channel != SDPCM_GLOM_CHANNEL) {
+		brcmf_err("Wrong channel for superframe\n");
+		rd->len = 0;
+		return -EINVAL;
+	}
+	if (type == BRCMF_SDIO_FT_SUB && rd->channel != SDPCM_DATA_CHANNEL &&
+	    rd->channel != SDPCM_EVENT_CHANNEL) {
+		brcmf_err("Wrong channel for subframe\n");
+		rd->len = 0;
+		return -EINVAL;
+	}
+	rd->dat_offset = brcmf_sdio_getdatoffset(header);
+	if (rd->dat_offset < SDPCM_HDRLEN || rd->dat_offset > rd->len) {
+		brcmf_err("seq %d: bad data offset\n", rx_seq);
+		bus->sdcnt.rx_badhdr++;
+		brcmf_sdio_rxfail(bus, false, false);
+		rd->len = 0;
+		return -ENXIO;
+	}
+	if (rd->seq_num != rx_seq) {
+		brcmf_dbg(SDIO, "seq %d, expected %d\n", rx_seq, rd->seq_num);
+		bus->sdcnt.rx_badseq++;
+		rd->seq_num = rx_seq;
+	}
+	/* no need to check the reset for subframe */
+	if (type == BRCMF_SDIO_FT_SUB)
+		return 0;
+	rd->len_nxtfrm = (swheader & SDPCM_NEXTLEN_MASK) >> SDPCM_NEXTLEN_SHIFT;
+	if (rd->len_nxtfrm << 4 > MAX_RX_DATASZ) {
+		/* only warm for NON glom packet */
+		if (rd->channel != SDPCM_GLOM_CHANNEL)
+			brcmf_err("seq %d: next length error\n", rx_seq);
+		rd->len_nxtfrm = 0;
+	}
+	swheader = le32_to_cpu(*(__le32 *)(header + 4));
+	fc = swheader & SDPCM_FCMASK_MASK;
+	if (bus->flowcontrol != fc) {
+		if (~bus->flowcontrol & fc)
+			bus->sdcnt.fc_xoff++;
+		if (bus->flowcontrol & ~fc)
+			bus->sdcnt.fc_xon++;
+		bus->sdcnt.fc_rcvd++;
+		bus->flowcontrol = fc;
+	}
+	tx_seq_max = (swheader & SDPCM_WINDOW_MASK) >> SDPCM_WINDOW_SHIFT;
+	if ((u8)(tx_seq_max - bus->tx_seq) > 0x40) {
+		brcmf_err("seq %d: max tx seq number error\n", rx_seq);
+		tx_seq_max = bus->tx_seq + 2;
+	}
+	bus->tx_max = tx_seq_max;
+
+	return 0;
+}
+
+static inline void brcmf_sdio_update_hwhdr(u8 *header, u16 frm_length)
+{
+	*(__le16 *)header = cpu_to_le16(frm_length);
+	*(((__le16 *)header) + 1) = cpu_to_le16(~frm_length);
+}
+
+static void brcmf_sdio_hdpack(struct brcmf_sdio *bus, u8 *header,
+			      struct brcmf_sdio_hdrinfo *hd_info)
+{
+	u32 hdrval;
+	u8 hdr_offset;
+
+	brcmf_sdio_update_hwhdr(header, hd_info->len);
+	hdr_offset = SDPCM_HWHDR_LEN;
+
+	if (bus->txglom) {
+		hdrval = (hd_info->len - hdr_offset) | (hd_info->lastfrm << 24);
+		*((__le32 *)(header + hdr_offset)) = cpu_to_le32(hdrval);
+		hdrval = (u16)hd_info->tail_pad << 16;
+		*(((__le32 *)(header + hdr_offset)) + 1) = cpu_to_le32(hdrval);
+		hdr_offset += SDPCM_HWEXT_LEN;
+	}
+
+	hdrval = hd_info->seq_num;
+	hdrval |= (hd_info->channel << SDPCM_CHANNEL_SHIFT) &
+		  SDPCM_CHANNEL_MASK;
+	hdrval |= (hd_info->dat_offset << SDPCM_DOFFSET_SHIFT) &
+		  SDPCM_DOFFSET_MASK;
+	*((__le32 *)(header + hdr_offset)) = cpu_to_le32(hdrval);
+	*(((__le32 *)(header + hdr_offset)) + 1) = 0;
+	trace_brcmf_sdpcm_hdr(SDPCM_TX + !!(bus->txglom), header);
+}
+
+static u8 brcmf_sdio_rxglom(struct brcmf_sdio *bus, u8 rxseq)
+{
+	u16 dlen, totlen;
+	u8 *dptr, num = 0;
+	u16 sublen;
+	struct sk_buff *pfirst, *pnext;
+
+	int errcode;
+	u8 doff, sfdoff;
+
+	struct brcmf_sdio_hdrinfo rd_new;
+
+	/* If packets, issue read(s) and send up packet chain */
+	/* Return sequence numbers consumed? */
+
+	brcmf_dbg(SDIO, "start: glomd %p glom %p\n",
+		  bus->glomd, skb_peek(&bus->glom));
+
+	/* If there's a descriptor, generate the packet chain */
+	if (bus->glomd) {
+		pfirst = pnext = NULL;
+		dlen = (u16) (bus->glomd->len);
+		dptr = bus->glomd->data;
+		if (!dlen || (dlen & 1)) {
+			brcmf_err("bad glomd len(%d), ignore descriptor\n",
+				  dlen);
+			dlen = 0;
+		}
+
+		for (totlen = num = 0; dlen; num++) {
+			/* Get (and move past) next length */
+			sublen = get_unaligned_le16(dptr);
+			dlen -= sizeof(u16);
+			dptr += sizeof(u16);
+			if ((sublen < SDPCM_HDRLEN) ||
+			    ((num == 0) && (sublen < (2 * SDPCM_HDRLEN)))) {
+				brcmf_err("descriptor len %d bad: %d\n",
+					  num, sublen);
+				pnext = NULL;
+				break;
+			}
+			if (sublen % bus->sgentry_align) {
+				brcmf_err("sublen %d not multiple of %d\n",
+					  sublen, bus->sgentry_align);
+			}
+			totlen += sublen;
+
+			/* For last frame, adjust read len so total
+				 is a block multiple */
+			if (!dlen) {
+				sublen +=
+				    (roundup(totlen, bus->blocksize) - totlen);
+				totlen = roundup(totlen, bus->blocksize);
+			}
+
+			/* Allocate/chain packet for next subframe */
+			pnext = brcmu_pkt_buf_get_skb(sublen + bus->sgentry_align);
+			if (pnext == NULL) {
+				brcmf_err("bcm_pkt_buf_get_skb failed, num %d len %d\n",
+					  num, sublen);
+				break;
+			}
+			skb_queue_tail(&bus->glom, pnext);
+
+			/* Adhere to start alignment requirements */
+			pkt_align(pnext, sublen, bus->sgentry_align);
+		}
+
+		/* If all allocations succeeded, save packet chain
+			 in bus structure */
+		if (pnext) {
+			brcmf_dbg(GLOM, "allocated %d-byte packet chain for %d subframes\n",
+				  totlen, num);
+			if (BRCMF_GLOM_ON() && bus->cur_read.len &&
+			    totlen != bus->cur_read.len) {
+				brcmf_dbg(GLOM, "glomdesc mismatch: nextlen %d glomdesc %d rxseq %d\n",
+					  bus->cur_read.len, totlen, rxseq);
+			}
+			pfirst = pnext = NULL;
+		} else {
+			brcmf_sdio_free_glom(bus);
+			num = 0;
+		}
+
+		/* Done with descriptor packet */
+		brcmu_pkt_buf_free_skb(bus->glomd);
+		bus->glomd = NULL;
+		bus->cur_read.len = 0;
+	}
+
+	/* Ok -- either we just generated a packet chain,
+		 or had one from before */
+	if (!skb_queue_empty(&bus->glom)) {
+		if (BRCMF_GLOM_ON()) {
+			brcmf_dbg(GLOM, "try superframe read, packet chain:\n");
+			skb_queue_walk(&bus->glom, pnext) {
+				brcmf_dbg(GLOM, "    %p: %p len 0x%04x (%d)\n",
+					  pnext, (u8 *) (pnext->data),
+					  pnext->len, pnext->len);
+			}
+		}
+
+		pfirst = skb_peek(&bus->glom);
+		dlen = (u16) brcmf_sdio_glom_len(bus);
+
+		/* Do an SDIO read for the superframe.  Configurable iovar to
+		 * read directly into the chained packet, or allocate a large
+		 * packet and and copy into the chain.
+		 */
+		sdio_claim_host(bus->sdiodev->func1);
+		errcode = brcmf_sdiod_recv_chain(bus->sdiodev,
+						 &bus->glom, dlen);
+		sdio_release_host(bus->sdiodev->func1);
+		bus->sdcnt.f2rxdata++;
+
+		/* On failure, kill the superframe */
+		if (errcode < 0) {
+			brcmf_err("glom read of %d bytes failed: %d\n",
+				  dlen, errcode);
+
+			sdio_claim_host(bus->sdiodev->func1);
+			brcmf_sdio_rxfail(bus, true, false);
+			bus->sdcnt.rxglomfail++;
+			brcmf_sdio_free_glom(bus);
+			sdio_release_host(bus->sdiodev->func1);
+			return 0;
+		}
+
+		brcmf_dbg_hex_dump(BRCMF_GLOM_ON(),
+				   pfirst->data, min_t(int, pfirst->len, 48),
+				   "SUPERFRAME:\n");
+
+		rd_new.seq_num = rxseq;
+		rd_new.len = dlen;
+		sdio_claim_host(bus->sdiodev->func1);
+		errcode = brcmf_sdio_hdparse(bus, pfirst->data, &rd_new,
+					     BRCMF_SDIO_FT_SUPER);
+		sdio_release_host(bus->sdiodev->func1);
+		bus->cur_read.len = rd_new.len_nxtfrm << 4;
+
+		/* Remove superframe header, remember offset */
+		skb_pull(pfirst, rd_new.dat_offset);
+		sfdoff = rd_new.dat_offset;
+		num = 0;
+
+		/* Validate all the subframe headers */
+		skb_queue_walk(&bus->glom, pnext) {
+			/* leave when invalid subframe is found */
+			if (errcode)
+				break;
+
+			rd_new.len = pnext->len;
+			rd_new.seq_num = rxseq++;
+			sdio_claim_host(bus->sdiodev->func1);
+			errcode = brcmf_sdio_hdparse(bus, pnext->data, &rd_new,
+						     BRCMF_SDIO_FT_SUB);
+			sdio_release_host(bus->sdiodev->func1);
+			brcmf_dbg_hex_dump(BRCMF_GLOM_ON(),
+					   pnext->data, 32, "subframe:\n");
+
+			num++;
+		}
+
+		if (errcode) {
+			/* Terminate frame on error */
+			sdio_claim_host(bus->sdiodev->func1);
+			brcmf_sdio_rxfail(bus, true, false);
+			bus->sdcnt.rxglomfail++;
+			brcmf_sdio_free_glom(bus);
+			sdio_release_host(bus->sdiodev->func1);
+			bus->cur_read.len = 0;
+			return 0;
+		}
+
+		/* Basic SD framing looks ok - process each packet (header) */
+
+		skb_queue_walk_safe(&bus->glom, pfirst, pnext) {
+			dptr = (u8 *) (pfirst->data);
+			sublen = get_unaligned_le16(dptr);
+			doff = brcmf_sdio_getdatoffset(&dptr[SDPCM_HWHDR_LEN]);
+
+			brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_DATA_ON(),
+					   dptr, pfirst->len,
+					   "Rx Subframe Data:\n");
+
+			__skb_trim(pfirst, sublen);
+			skb_pull(pfirst, doff);
+
+			if (pfirst->len == 0) {
+				skb_unlink(pfirst, &bus->glom);
+				brcmu_pkt_buf_free_skb(pfirst);
+				continue;
+			}
+
+			brcmf_dbg_hex_dump(BRCMF_GLOM_ON(),
+					   pfirst->data,
+					   min_t(int, pfirst->len, 32),
+					   "subframe %d to stack, %p (%p/%d) nxt/lnk %p/%p\n",
+					   bus->glom.qlen, pfirst, pfirst->data,
+					   pfirst->len, pfirst->next,
+					   pfirst->prev);
+			skb_unlink(pfirst, &bus->glom);
+			if (brcmf_sdio_fromevntchan(&dptr[SDPCM_HWHDR_LEN]))
+				brcmf_rx_event(bus->sdiodev->dev, pfirst);
+			else
+				brcmf_rx_frame(bus->sdiodev->dev, pfirst,
+					       false);
+			bus->sdcnt.rxglompkts++;
+		}
+
+		bus->sdcnt.rxglomframes++;
+	}
+	return num;
+}
+
+static int brcmf_sdio_dcmd_resp_wait(struct brcmf_sdio *bus, uint *condition,
+				     bool *pending)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	int timeout = DCMD_RESP_TIMEOUT;
+
+	/* Wait until control frame is available */
+	add_wait_queue(&bus->dcmd_resp_wait, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+
+	while (!(*condition) && (!signal_pending(current) && timeout))
+		timeout = schedule_timeout(timeout);
+
+	if (signal_pending(current))
+		*pending = true;
+
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&bus->dcmd_resp_wait, &wait);
+
+	return timeout;
+}
+
+static int brcmf_sdio_dcmd_resp_wake(struct brcmf_sdio *bus)
+{
+	wake_up_interruptible(&bus->dcmd_resp_wait);
+
+	return 0;
+}
+static void
+brcmf_sdio_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
+{
+	uint rdlen, pad;
+	u8 *buf = NULL, *rbuf;
+	int sdret;
+
+	brcmf_dbg(SDIO, "Enter\n");
+	if (bus->rxblen)
+		buf = vzalloc(bus->rxblen);
+	if (!buf)
+		goto done;
+
+	rbuf = bus->rxbuf;
+	pad = ((unsigned long)rbuf % bus->head_align);
+	if (pad)
+		rbuf += (bus->head_align - pad);
+
+	/* Copy the already-read portion over */
+	memcpy(buf, hdr, BRCMF_FIRSTREAD);
+	if (len <= BRCMF_FIRSTREAD)
+		goto gotpkt;
+
+	/* Raise rdlen to next SDIO block to avoid tail command */
+	rdlen = len - BRCMF_FIRSTREAD;
+	if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
+		pad = bus->blocksize - (rdlen % bus->blocksize);
+		if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
+		    ((len + pad) < bus->sdiodev->bus_if->maxctl))
+			rdlen += pad;
+	} else if (rdlen % bus->head_align) {
+		rdlen += bus->head_align - (rdlen % bus->head_align);
+	}
+
+	/* Drop if the read is too big or it exceeds our maximum */
+	if ((rdlen + BRCMF_FIRSTREAD) > bus->sdiodev->bus_if->maxctl) {
+		brcmf_err("%d-byte control read exceeds %d-byte buffer\n",
+			  rdlen, bus->sdiodev->bus_if->maxctl);
+		brcmf_sdio_rxfail(bus, false, false);
+		goto done;
+	}
+
+	if ((len - doff) > bus->sdiodev->bus_if->maxctl) {
+		brcmf_err("%d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n",
+			  len, len - doff, bus->sdiodev->bus_if->maxctl);
+		bus->sdcnt.rx_toolong++;
+		brcmf_sdio_rxfail(bus, false, false);
+		goto done;
+	}
+
+	/* Read remain of frame body */
+	sdret = brcmf_sdiod_recv_buf(bus->sdiodev, rbuf, rdlen);
+	bus->sdcnt.f2rxdata++;
+
+	/* Control frame failures need retransmission */
+	if (sdret < 0) {
+		brcmf_err("read %d control bytes failed: %d\n",
+			  rdlen, sdret);
+		bus->sdcnt.rxc_errors++;
+		brcmf_sdio_rxfail(bus, true, true);
+		goto done;
+	} else
+		memcpy(buf + BRCMF_FIRSTREAD, rbuf, rdlen);
+
+gotpkt:
+
+	brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_CTL_ON(),
+			   buf, len, "RxCtrl:\n");
+
+	/* Point to valid data and indicate its length */
+	spin_lock_bh(&bus->rxctl_lock);
+	if (bus->rxctl) {
+		brcmf_err("last control frame is being processed.\n");
+		spin_unlock_bh(&bus->rxctl_lock);
+		vfree(buf);
+		goto done;
+	}
+	bus->rxctl = buf + doff;
+	bus->rxctl_orig = buf;
+	bus->rxlen = len - doff;
+	spin_unlock_bh(&bus->rxctl_lock);
+
+done:
+	/* Awake any waiters */
+	brcmf_sdio_dcmd_resp_wake(bus);
+}
+
+/* Pad read to blocksize for efficiency */
+static void brcmf_sdio_pad(struct brcmf_sdio *bus, u16 *pad, u16 *rdlen)
+{
+	if (bus->roundup && bus->blocksize && *rdlen > bus->blocksize) {
+		*pad = bus->blocksize - (*rdlen % bus->blocksize);
+		if (*pad <= bus->roundup && *pad < bus->blocksize &&
+		    *rdlen + *pad + BRCMF_FIRSTREAD < MAX_RX_DATASZ)
+			*rdlen += *pad;
+	} else if (*rdlen % bus->head_align) {
+		*rdlen += bus->head_align - (*rdlen % bus->head_align);
+	}
+}
+
+static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
+{
+	struct sk_buff *pkt;		/* Packet for event or data frames */
+	u16 pad;		/* Number of pad bytes to read */
+	uint rxleft = 0;	/* Remaining number of frames allowed */
+	int ret;		/* Return code from calls */
+	uint rxcount = 0;	/* Total frames read */
+	struct brcmf_sdio_hdrinfo *rd = &bus->cur_read, rd_new;
+	u8 head_read = 0;
+
+	brcmf_dbg(SDIO, "Enter\n");
+
+	/* Not finished unless we encounter no more frames indication */
+	bus->rxpending = true;
+
+	for (rd->seq_num = bus->rx_seq, rxleft = maxframes;
+	     !bus->rxskip && rxleft && bus->sdiodev->state == BRCMF_SDIOD_DATA;
+	     rd->seq_num++, rxleft--) {
+
+		/* Handle glomming separately */
+		if (bus->glomd || !skb_queue_empty(&bus->glom)) {
+			u8 cnt;
+			brcmf_dbg(GLOM, "calling rxglom: glomd %p, glom %p\n",
+				  bus->glomd, skb_peek(&bus->glom));
+			cnt = brcmf_sdio_rxglom(bus, rd->seq_num);
+			brcmf_dbg(GLOM, "rxglom returned %d\n", cnt);
+			rd->seq_num += cnt - 1;
+			rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1;
+			continue;
+		}
+
+		rd->len_left = rd->len;
+		/* read header first for unknow frame length */
+		sdio_claim_host(bus->sdiodev->func1);
+		if (!rd->len) {
+			ret = brcmf_sdiod_recv_buf(bus->sdiodev,
+						   bus->rxhdr, BRCMF_FIRSTREAD);
+			bus->sdcnt.f2rxhdrs++;
+			if (ret < 0) {
+				brcmf_err("RXHEADER FAILED: %d\n",
+					  ret);
+				bus->sdcnt.rx_hdrfail++;
+				brcmf_sdio_rxfail(bus, true, true);
+				sdio_release_host(bus->sdiodev->func1);
+				continue;
+			}
+
+			brcmf_dbg_hex_dump(BRCMF_BYTES_ON() || BRCMF_HDRS_ON(),
+					   bus->rxhdr, SDPCM_HDRLEN,
+					   "RxHdr:\n");
+
+			if (brcmf_sdio_hdparse(bus, bus->rxhdr, rd,
+					       BRCMF_SDIO_FT_NORMAL)) {
+				sdio_release_host(bus->sdiodev->func1);
+				if (!bus->rxpending)
+					break;
+				else
+					continue;
+			}
+
+			if (rd->channel == SDPCM_CONTROL_CHANNEL) {
+				brcmf_sdio_read_control(bus, bus->rxhdr,
+							rd->len,
+							rd->dat_offset);
+				/* prepare the descriptor for the next read */
+				rd->len = rd->len_nxtfrm << 4;
+				rd->len_nxtfrm = 0;
+				/* treat all packet as event if we don't know */
+				rd->channel = SDPCM_EVENT_CHANNEL;
+				sdio_release_host(bus->sdiodev->func1);
+				continue;
+			}
+			rd->len_left = rd->len > BRCMF_FIRSTREAD ?
+				       rd->len - BRCMF_FIRSTREAD : 0;
+			head_read = BRCMF_FIRSTREAD;
+		}
+
+		brcmf_sdio_pad(bus, &pad, &rd->len_left);
+
+		pkt = brcmu_pkt_buf_get_skb(rd->len_left + head_read +
+					    bus->head_align);
+		if (!pkt) {
+			/* Give up on data, request rtx of events */
+			brcmf_err("brcmu_pkt_buf_get_skb failed\n");
+			brcmf_sdio_rxfail(bus, false,
+					    RETRYCHAN(rd->channel));
+			sdio_release_host(bus->sdiodev->func1);
+			continue;
+		}
+		skb_pull(pkt, head_read);
+		pkt_align(pkt, rd->len_left, bus->head_align);
+
+		ret = brcmf_sdiod_recv_pkt(bus->sdiodev, pkt);
+		bus->sdcnt.f2rxdata++;
+		sdio_release_host(bus->sdiodev->func1);
+
+		if (ret < 0) {
+			brcmf_err("read %d bytes from channel %d failed: %d\n",
+				  rd->len, rd->channel, ret);
+			brcmu_pkt_buf_free_skb(pkt);
+			sdio_claim_host(bus->sdiodev->func1);
+			brcmf_sdio_rxfail(bus, true,
+					    RETRYCHAN(rd->channel));
+			sdio_release_host(bus->sdiodev->func1);
+			continue;
+		}
+
+		if (head_read) {
+			skb_push(pkt, head_read);
+			memcpy(pkt->data, bus->rxhdr, head_read);
+			head_read = 0;
+		} else {
+			memcpy(bus->rxhdr, pkt->data, SDPCM_HDRLEN);
+			rd_new.seq_num = rd->seq_num;
+			sdio_claim_host(bus->sdiodev->func1);
+			if (brcmf_sdio_hdparse(bus, bus->rxhdr, &rd_new,
+					       BRCMF_SDIO_FT_NORMAL)) {
+				rd->len = 0;
+				brcmu_pkt_buf_free_skb(pkt);
+			}
+			bus->sdcnt.rx_readahead_cnt++;
+			if (rd->len != roundup(rd_new.len, 16)) {
+				brcmf_err("frame length mismatch:read %d, should be %d\n",
+					  rd->len,
+					  roundup(rd_new.len, 16) >> 4);
+				rd->len = 0;
+				brcmf_sdio_rxfail(bus, true, true);
+				sdio_release_host(bus->sdiodev->func1);
+				brcmu_pkt_buf_free_skb(pkt);
+				continue;
+			}
+			sdio_release_host(bus->sdiodev->func1);
+			rd->len_nxtfrm = rd_new.len_nxtfrm;
+			rd->channel = rd_new.channel;
+			rd->dat_offset = rd_new.dat_offset;
+
+			brcmf_dbg_hex_dump(!(BRCMF_BYTES_ON() &&
+					     BRCMF_DATA_ON()) &&
+					   BRCMF_HDRS_ON(),
+					   bus->rxhdr, SDPCM_HDRLEN,
+					   "RxHdr:\n");
+
+			if (rd_new.channel == SDPCM_CONTROL_CHANNEL) {
+				brcmf_err("readahead on control packet %d?\n",
+					  rd_new.seq_num);
+				/* Force retry w/normal header read */
+				rd->len = 0;
+				sdio_claim_host(bus->sdiodev->func1);
+				brcmf_sdio_rxfail(bus, false, true);
+				sdio_release_host(bus->sdiodev->func1);
+				brcmu_pkt_buf_free_skb(pkt);
+				continue;
+			}
+		}
+
+		brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_DATA_ON(),
+				   pkt->data, rd->len, "Rx Data:\n");
+
+		/* Save superframe descriptor and allocate packet frame */
+		if (rd->channel == SDPCM_GLOM_CHANNEL) {
+			if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_HWHDR_LEN])) {
+				brcmf_dbg(GLOM, "glom descriptor, %d bytes:\n",
+					  rd->len);
+				brcmf_dbg_hex_dump(BRCMF_GLOM_ON(),
+						   pkt->data, rd->len,
+						   "Glom Data:\n");
+				__skb_trim(pkt, rd->len);
+				skb_pull(pkt, SDPCM_HDRLEN);
+				bus->glomd = pkt;
+			} else {
+				brcmf_err("%s: glom superframe w/o "
+					  "descriptor!\n", __func__);
+				sdio_claim_host(bus->sdiodev->func1);
+				brcmf_sdio_rxfail(bus, false, false);
+				sdio_release_host(bus->sdiodev->func1);
+			}
+			/* prepare the descriptor for the next read */
+			rd->len = rd->len_nxtfrm << 4;
+			rd->len_nxtfrm = 0;
+			/* treat all packet as event if we don't know */
+			rd->channel = SDPCM_EVENT_CHANNEL;
+			continue;
+		}
+
+		/* Fill in packet len and prio, deliver upward */
+		__skb_trim(pkt, rd->len);
+		skb_pull(pkt, rd->dat_offset);
+
+		if (pkt->len == 0)
+			brcmu_pkt_buf_free_skb(pkt);
+		else if (rd->channel == SDPCM_EVENT_CHANNEL)
+			brcmf_rx_event(bus->sdiodev->dev, pkt);
+		else
+			brcmf_rx_frame(bus->sdiodev->dev, pkt,
+				       false);
+
+		/* prepare the descriptor for the next read */
+		rd->len = rd->len_nxtfrm << 4;
+		rd->len_nxtfrm = 0;
+		/* treat all packet as event if we don't know */
+		rd->channel = SDPCM_EVENT_CHANNEL;
+	}
+
+	rxcount = maxframes - rxleft;
+	/* Message if we hit the limit */
+	if (!rxleft)
+		brcmf_dbg(DATA, "hit rx limit of %d frames\n", maxframes);
+	else
+		brcmf_dbg(DATA, "processed %d frames\n", rxcount);
+	/* Back off rxseq if awaiting rtx, update rx_seq */
+	if (bus->rxskip)
+		rd->seq_num--;
+	bus->rx_seq = rd->seq_num;
+
+	return rxcount;
+}
+
+static void
+brcmf_sdio_wait_event_wakeup(struct brcmf_sdio *bus)
+{
+	wake_up_interruptible(&bus->ctrl_wait);
+	return;
+}
+
+static int brcmf_sdio_txpkt_hdalign(struct brcmf_sdio *bus, struct sk_buff *pkt)
+{
+	struct brcmf_bus_stats *stats;
+	u16 head_pad;
+	u8 *dat_buf;
+
+	dat_buf = (u8 *)(pkt->data);
+
+	/* Check head padding */
+	head_pad = ((unsigned long)dat_buf % bus->head_align);
+	if (head_pad) {
+		if (skb_headroom(pkt) < head_pad) {
+			stats = &bus->sdiodev->bus_if->stats;
+			atomic_inc(&stats->pktcowed);
+			if (skb_cow_head(pkt, head_pad)) {
+				atomic_inc(&stats->pktcow_failed);
+				return -ENOMEM;
+			}
+			head_pad = 0;
+		}
+		skb_push(pkt, head_pad);
+		dat_buf = (u8 *)(pkt->data);
+	}
+	memset(dat_buf, 0, head_pad + bus->tx_hdrlen);
+	return head_pad;
+}
+
+/*
+ * struct brcmf_skbuff_cb reserves first two bytes in sk_buff::cb for
+ * bus layer usage.
+ */
+/* flag marking a dummy skb added for DMA alignment requirement */
+#define ALIGN_SKB_FLAG		0x8000
+/* bit mask of data length chopped from the previous packet */
+#define ALIGN_SKB_CHOP_LEN_MASK	0x7fff
+
+static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio *bus,
+				    struct sk_buff_head *pktq,
+				    struct sk_buff *pkt, u16 total_len)
+{
+	struct brcmf_sdio_dev *sdiodev;
+	struct sk_buff *pkt_pad;
+	u16 tail_pad, tail_chop, chain_pad;
+	unsigned int blksize;
+	bool lastfrm;
+	int ntail, ret;
+
+	sdiodev = bus->sdiodev;
+	blksize = sdiodev->func2->cur_blksize;
+	/* sg entry alignment should be a divisor of block size */
+	WARN_ON(blksize % bus->sgentry_align);
+
+	/* Check tail padding */
+	lastfrm = skb_queue_is_last(pktq, pkt);
+	tail_pad = 0;
+	tail_chop = pkt->len % bus->sgentry_align;
+	if (tail_chop)
+		tail_pad = bus->sgentry_align - tail_chop;
+	chain_pad = (total_len + tail_pad) % blksize;
+	if (lastfrm && chain_pad)
+		tail_pad += blksize - chain_pad;
+	if (skb_tailroom(pkt) < tail_pad && pkt->len > blksize) {
+		pkt_pad = brcmu_pkt_buf_get_skb(tail_pad + tail_chop +
+						bus->head_align);
+		if (pkt_pad == NULL)
+			return -ENOMEM;
+		ret = brcmf_sdio_txpkt_hdalign(bus, pkt_pad);
+		if (unlikely(ret < 0)) {
+			kfree_skb(pkt_pad);
+			return ret;
+		}
+		memcpy(pkt_pad->data,
+		       pkt->data + pkt->len - tail_chop,
+		       tail_chop);
+		*(u16 *)(pkt_pad->cb) = ALIGN_SKB_FLAG + tail_chop;
+		skb_trim(pkt, pkt->len - tail_chop);
+		skb_trim(pkt_pad, tail_pad + tail_chop);
+		__skb_queue_after(pktq, pkt, pkt_pad);
+	} else {
+		ntail = pkt->data_len + tail_pad -
+			(pkt->end - pkt->tail);
+		if (skb_cloned(pkt) || ntail > 0)
+			if (pskb_expand_head(pkt, 0, ntail, GFP_ATOMIC))
+				return -ENOMEM;
+		if (skb_linearize(pkt))
+			return -ENOMEM;
+		__skb_put(pkt, tail_pad);
+	}
+
+	return tail_pad;
+}
+
+/**
+ * brcmf_sdio_txpkt_prep - packet preparation for transmit
+ * @bus: brcmf_sdio structure pointer
+ * @pktq: packet list pointer
+ * @chan: virtual channel to transmit the packet
+ *
+ * Processes to be applied to the packet
+ *	- Align data buffer pointer
+ *	- Align data buffer length
+ *	- Prepare header
+ * Return: negative value if there is error
+ */
+static int
+brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
+		      uint chan)
+{
+	u16 head_pad, total_len;
+	struct sk_buff *pkt_next;
+	u8 txseq;
+	int ret;
+	struct brcmf_sdio_hdrinfo hd_info = {0};
+
+	txseq = bus->tx_seq;
+	total_len = 0;
+	skb_queue_walk(pktq, pkt_next) {
+		/* alignment packet inserted in previous
+		 * loop cycle can be skipped as it is
+		 * already properly aligned and does not
+		 * need an sdpcm header.
+		 */
+		if (*(u16 *)(pkt_next->cb) & ALIGN_SKB_FLAG)
+			continue;
+
+		/* align packet data pointer */
+		ret = brcmf_sdio_txpkt_hdalign(bus, pkt_next);
+		if (ret < 0)
+			return ret;
+		head_pad = (u16)ret;
+		if (head_pad)
+			memset(pkt_next->data + bus->tx_hdrlen, 0, head_pad);
+
+		total_len += pkt_next->len;
+
+		hd_info.len = pkt_next->len;
+		hd_info.lastfrm = skb_queue_is_last(pktq, pkt_next);
+		if (bus->txglom && pktq->qlen > 1) {
+			ret = brcmf_sdio_txpkt_prep_sg(bus, pktq,
+						       pkt_next, total_len);
+			if (ret < 0)
+				return ret;
+			hd_info.tail_pad = (u16)ret;
+			total_len += (u16)ret;
+		}
+
+		hd_info.channel = chan;
+		hd_info.dat_offset = head_pad + bus->tx_hdrlen;
+		hd_info.seq_num = txseq++;
+
+		/* Now fill the header */
+		brcmf_sdio_hdpack(bus, pkt_next->data, &hd_info);
+
+		if (BRCMF_BYTES_ON() &&
+		    ((BRCMF_CTL_ON() && chan == SDPCM_CONTROL_CHANNEL) ||
+		     (BRCMF_DATA_ON() && chan != SDPCM_CONTROL_CHANNEL)))
+			brcmf_dbg_hex_dump(true, pkt_next->data, hd_info.len,
+					   "Tx Frame:\n");
+		else if (BRCMF_HDRS_ON())
+			brcmf_dbg_hex_dump(true, pkt_next->data,
+					   head_pad + bus->tx_hdrlen,
+					   "Tx Header:\n");
+	}
+	/* Hardware length tag of the first packet should be total
+	 * length of the chain (including padding)
+	 */
+	if (bus->txglom)
+		brcmf_sdio_update_hwhdr(pktq->next->data, total_len);
+	return 0;
+}
+
+/**
+ * brcmf_sdio_txpkt_postp - packet post processing for transmit
+ * @bus: brcmf_sdio structure pointer
+ * @pktq: packet list pointer
+ *
+ * Processes to be applied to the packet
+ *	- Remove head padding
+ *	- Remove tail padding
+ */
+static void
+brcmf_sdio_txpkt_postp(struct brcmf_sdio *bus, struct sk_buff_head *pktq)
+{
+	u8 *hdr;
+	u32 dat_offset;
+	u16 tail_pad;
+	u16 dummy_flags, chop_len;
+	struct sk_buff *pkt_next, *tmp, *pkt_prev;
+
+	skb_queue_walk_safe(pktq, pkt_next, tmp) {
+		dummy_flags = *(u16 *)(pkt_next->cb);
+		if (dummy_flags & ALIGN_SKB_FLAG) {
+			chop_len = dummy_flags & ALIGN_SKB_CHOP_LEN_MASK;
+			if (chop_len) {
+				pkt_prev = pkt_next->prev;
+				skb_put(pkt_prev, chop_len);
+			}
+			__skb_unlink(pkt_next, pktq);
+			brcmu_pkt_buf_free_skb(pkt_next);
+		} else {
+			hdr = pkt_next->data + bus->tx_hdrlen - SDPCM_SWHDR_LEN;
+			dat_offset = le32_to_cpu(*(__le32 *)hdr);
+			dat_offset = (dat_offset & SDPCM_DOFFSET_MASK) >>
+				     SDPCM_DOFFSET_SHIFT;
+			skb_pull(pkt_next, dat_offset);
+			if (bus->txglom) {
+				tail_pad = le16_to_cpu(*(__le16 *)(hdr - 2));
+				skb_trim(pkt_next, pkt_next->len - tail_pad);
+			}
+		}
+	}
+}
+
+/* Writes a HW/SW header into the packet and sends it. */
+/* Assumes: (a) header space already there, (b) caller holds lock */
+static int brcmf_sdio_txpkt(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
+			    uint chan)
+{
+	int ret;
+	struct sk_buff *pkt_next, *tmp;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	ret = brcmf_sdio_txpkt_prep(bus, pktq, chan);
+	if (ret)
+		goto done;
+
+	sdio_claim_host(bus->sdiodev->func1);
+	ret = brcmf_sdiod_send_pkt(bus->sdiodev, pktq);
+	bus->sdcnt.f2txdata++;
+
+	if (ret < 0)
+		brcmf_sdio_txfail(bus);
+
+	sdio_release_host(bus->sdiodev->func1);
+
+done:
+	brcmf_sdio_txpkt_postp(bus, pktq);
+	if (ret == 0)
+		bus->tx_seq = (bus->tx_seq + pktq->qlen) % SDPCM_SEQ_WRAP;
+	skb_queue_walk_safe(pktq, pkt_next, tmp) {
+		__skb_unlink(pkt_next, pktq);
+		brcmf_proto_bcdc_txcomplete(bus->sdiodev->dev, pkt_next,
+					    ret == 0);
+	}
+	return ret;
+}
+
+static uint brcmf_sdio_sendfromq(struct brcmf_sdio *bus, uint maxframes)
+{
+	struct sk_buff *pkt;
+	struct sk_buff_head pktq;
+	u32 intstat_addr = bus->sdio_core->base + SD_REG(intstatus);
+	u32 intstatus = 0;
+	int ret = 0, prec_out, i;
+	uint cnt = 0;
+	u8 tx_prec_map, pkt_num;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	tx_prec_map = ~bus->flowcontrol;
+
+	/* Send frames until the limit or some other event */
+	for (cnt = 0; (cnt < maxframes) && data_ok(bus);) {
+		pkt_num = 1;
+		if (bus->txglom)
+			pkt_num = min_t(u8, bus->tx_max - bus->tx_seq,
+					bus->sdiodev->txglomsz);
+		pkt_num = min_t(u32, pkt_num,
+				brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol));
+		__skb_queue_head_init(&pktq);
+		spin_lock_bh(&bus->txq_lock);
+		for (i = 0; i < pkt_num; i++) {
+			pkt = brcmu_pktq_mdeq(&bus->txq, tx_prec_map,
+					      &prec_out);
+			if (pkt == NULL)
+				break;
+			__skb_queue_tail(&pktq, pkt);
+		}
+		spin_unlock_bh(&bus->txq_lock);
+		if (i == 0)
+			break;
+
+		ret = brcmf_sdio_txpkt(bus, &pktq, SDPCM_DATA_CHANNEL);
+
+		cnt += i;
+
+		/* In poll mode, need to check for other events */
+		if (!bus->intr) {
+			/* Check device status, signal pending interrupt */
+			sdio_claim_host(bus->sdiodev->func1);
+			intstatus = brcmf_sdiod_readl(bus->sdiodev,
+						      intstat_addr, &ret);
+			sdio_release_host(bus->sdiodev->func1);
+
+			bus->sdcnt.f2txdata++;
+			if (ret != 0)
+				break;
+			if (intstatus & bus->hostintmask)
+				atomic_set(&bus->ipend, 1);
+		}
+	}
+
+	/* Deflow-control stack if needed */
+	if ((bus->sdiodev->state == BRCMF_SDIOD_DATA) &&
+	    bus->txoff && (pktq_len(&bus->txq) < TXLOW)) {
+		bus->txoff = false;
+		brcmf_proto_bcdc_txflowblock(bus->sdiodev->dev, false);
+	}
+
+	return cnt;
+}
+
+static int brcmf_sdio_tx_ctrlframe(struct brcmf_sdio *bus, u8 *frame, u16 len)
+{
+	u8 doff;
+	u16 pad;
+	uint retries = 0;
+	struct brcmf_sdio_hdrinfo hd_info = {0};
+	int ret;
+
+	brcmf_dbg(SDIO, "Enter\n");
+
+	/* Back the pointer to make room for bus header */
+	frame -= bus->tx_hdrlen;
+	len += bus->tx_hdrlen;
+
+	/* Add alignment padding (optional for ctl frames) */
+	doff = ((unsigned long)frame % bus->head_align);
+	if (doff) {
+		frame -= doff;
+		len += doff;
+		memset(frame + bus->tx_hdrlen, 0, doff);
+	}
+
+	/* Round send length to next SDIO block */
+	pad = 0;
+	if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
+		pad = bus->blocksize - (len % bus->blocksize);
+		if ((pad > bus->roundup) || (pad >= bus->blocksize))
+			pad = 0;
+	} else if (len % bus->head_align) {
+		pad = bus->head_align - (len % bus->head_align);
+	}
+	len += pad;
+
+	hd_info.len = len - pad;
+	hd_info.channel = SDPCM_CONTROL_CHANNEL;
+	hd_info.dat_offset = doff + bus->tx_hdrlen;
+	hd_info.seq_num = bus->tx_seq;
+	hd_info.lastfrm = true;
+	hd_info.tail_pad = pad;
+	brcmf_sdio_hdpack(bus, frame, &hd_info);
+
+	if (bus->txglom)
+		brcmf_sdio_update_hwhdr(frame, len);
+
+	brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_CTL_ON(),
+			   frame, len, "Tx Frame:\n");
+	brcmf_dbg_hex_dump(!(BRCMF_BYTES_ON() && BRCMF_CTL_ON()) &&
+			   BRCMF_HDRS_ON(),
+			   frame, min_t(u16, len, 16), "TxHdr:\n");
+
+	do {
+		ret = brcmf_sdiod_send_buf(bus->sdiodev, frame, len);
+
+		if (ret < 0)
+			brcmf_sdio_txfail(bus);
+		else
+			bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQ_WRAP;
+	} while (ret < 0 && retries++ < TXRETRIES);
+
+	return ret;
+}
+
+static void brcmf_sdio_bus_stop(struct device *dev)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+	struct brcmf_sdio *bus = sdiodev->bus;
+	struct brcmf_core *core = bus->sdio_core;
+	u32 local_hostintmask;
+	u8 saveclk;
+	int err;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	if (bus->watchdog_tsk) {
+		send_sig(SIGTERM, bus->watchdog_tsk, 1);
+		kthread_stop(bus->watchdog_tsk);
+		bus->watchdog_tsk = NULL;
+	}
+
+	if (sdiodev->state != BRCMF_SDIOD_NOMEDIUM) {
+		sdio_claim_host(sdiodev->func1);
+
+		/* Enable clock for device interrupts */
+		brcmf_sdio_bus_sleep(bus, false, false);
+
+		/* Disable and clear interrupts at the chip level also */
+		brcmf_sdiod_writel(sdiodev, core->base + SD_REG(hostintmask),
+				   0, NULL);
+
+		local_hostintmask = bus->hostintmask;
+		bus->hostintmask = 0;
+
+		/* Force backplane clocks to assure F2 interrupt propagates */
+		saveclk = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+					    &err);
+		if (!err)
+			brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+					   (saveclk | SBSDIO_FORCE_HT), &err);
+		if (err)
+			brcmf_err("Failed to force clock for F2: err %d\n",
+				  err);
+
+		/* Turn off the bus (F2), free any pending packets */
+		brcmf_dbg(INTR, "disable SDIO interrupts\n");
+		sdio_disable_func(sdiodev->func2);
+
+		/* Clear any pending interrupts now that F2 is disabled */
+		brcmf_sdiod_writel(sdiodev, core->base + SD_REG(intstatus),
+				   local_hostintmask, NULL);
+
+		sdio_release_host(sdiodev->func1);
+	}
+	/* Clear the data packet queues */
+	brcmu_pktq_flush(&bus->txq, true, NULL, NULL);
+
+	/* Clear any held glomming stuff */
+	brcmu_pkt_buf_free_skb(bus->glomd);
+	brcmf_sdio_free_glom(bus);
+
+	/* Clear rx control and wake any waiters */
+	spin_lock_bh(&bus->rxctl_lock);
+	bus->rxlen = 0;
+	spin_unlock_bh(&bus->rxctl_lock);
+	brcmf_sdio_dcmd_resp_wake(bus);
+
+	/* Reset some F2 state stuff */
+	bus->rxskip = false;
+	bus->tx_seq = bus->rx_seq = 0;
+}
+
+static inline void brcmf_sdio_clrintr(struct brcmf_sdio *bus)
+{
+	struct brcmf_sdio_dev *sdiodev;
+	unsigned long flags;
+
+	sdiodev = bus->sdiodev;
+	if (sdiodev->oob_irq_requested) {
+		spin_lock_irqsave(&sdiodev->irq_en_lock, flags);
+		if (!sdiodev->irq_en && !atomic_read(&bus->ipend)) {
+			enable_irq(sdiodev->settings->bus.sdio.oob_irq_nr);
+			sdiodev->irq_en = true;
+		}
+		spin_unlock_irqrestore(&sdiodev->irq_en_lock, flags);
+	}
+}
+
+static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus)
+{
+	struct brcmf_core *core = bus->sdio_core;
+	u32 addr;
+	unsigned long val;
+	int ret;
+
+	addr = core->base + SD_REG(intstatus);
+
+	val = brcmf_sdiod_readl(bus->sdiodev, addr, &ret);
+	bus->sdcnt.f1regdata++;
+	if (ret != 0)
+		return ret;
+
+	val &= bus->hostintmask;
+	atomic_set(&bus->fcstate, !!(val & I_HMB_FC_STATE));
+
+	/* Clear interrupts */
+	if (val) {
+		brcmf_sdiod_writel(bus->sdiodev, addr, val, &ret);
+		bus->sdcnt.f1regdata++;
+		atomic_or(val, &bus->intstatus);
+	}
+
+	return ret;
+}
+
+static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
+{
+	struct brcmf_sdio_dev *sdiod = bus->sdiodev;
+	u32 newstatus = 0;
+	u32 intstat_addr = bus->sdio_core->base + SD_REG(intstatus);
+	unsigned long intstatus;
+	uint txlimit = bus->txbound;	/* Tx frames to send before resched */
+	uint framecnt;			/* Temporary counter of tx/rx frames */
+	int err = 0;
+
+	brcmf_dbg(SDIO, "Enter\n");
+
+	sdio_claim_host(bus->sdiodev->func1);
+
+	/* If waiting for HTAVAIL, check status */
+	if (!bus->sr_enabled && bus->clkstate == CLK_PENDING) {
+		u8 clkctl, devctl = 0;
+
+#ifdef DEBUG
+		/* Check for inconsistent device control */
+		devctl = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_DEVICE_CTL,
+					   &err);
+#endif				/* DEBUG */
+
+		/* Read CSR, if clock on switch to AVAIL, else ignore */
+		clkctl = brcmf_sdiod_readb(bus->sdiodev,
+					   SBSDIO_FUNC1_CHIPCLKCSR, &err);
+
+		brcmf_dbg(SDIO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n",
+			  devctl, clkctl);
+
+		if (SBSDIO_HTAV(clkctl)) {
+			devctl = brcmf_sdiod_readb(bus->sdiodev,
+						   SBSDIO_DEVICE_CTL, &err);
+			devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
+			brcmf_sdiod_writeb(bus->sdiodev,
+					   SBSDIO_DEVICE_CTL, devctl, &err);
+			bus->clkstate = CLK_AVAIL;
+		}
+	}
+
+	/* Make sure backplane clock is on */
+	brcmf_sdio_bus_sleep(bus, false, true);
+
+	/* Pending interrupt indicates new device status */
+	if (atomic_read(&bus->ipend) > 0) {
+		atomic_set(&bus->ipend, 0);
+		err = brcmf_sdio_intr_rstatus(bus);
+	}
+
+	/* Start with leftover status bits */
+	intstatus = atomic_xchg(&bus->intstatus, 0);
+
+	/* Handle flow-control change: read new state in case our ack
+	 * crossed another change interrupt.  If change still set, assume
+	 * FC ON for safety, let next loop through do the debounce.
+	 */
+	if (intstatus & I_HMB_FC_CHANGE) {
+		intstatus &= ~I_HMB_FC_CHANGE;
+		brcmf_sdiod_writel(sdiod, intstat_addr, I_HMB_FC_CHANGE, &err);
+
+		newstatus = brcmf_sdiod_readl(sdiod, intstat_addr, &err);
+
+		bus->sdcnt.f1regdata += 2;
+		atomic_set(&bus->fcstate,
+			   !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE)));
+		intstatus |= (newstatus & bus->hostintmask);
+	}
+
+	/* Handle host mailbox indication */
+	if (intstatus & I_HMB_HOST_INT) {
+		intstatus &= ~I_HMB_HOST_INT;
+		intstatus |= brcmf_sdio_hostmail(bus);
+	}
+
+	sdio_release_host(bus->sdiodev->func1);
+
+	/* Generally don't ask for these, can get CRC errors... */
+	if (intstatus & I_WR_OOSYNC) {
+		brcmf_err("Dongle reports WR_OOSYNC\n");
+		intstatus &= ~I_WR_OOSYNC;
+	}
+
+	if (intstatus & I_RD_OOSYNC) {
+		brcmf_err("Dongle reports RD_OOSYNC\n");
+		intstatus &= ~I_RD_OOSYNC;
+	}
+
+	if (intstatus & I_SBINT) {
+		brcmf_err("Dongle reports SBINT\n");
+		intstatus &= ~I_SBINT;
+	}
+
+	/* Would be active due to wake-wlan in gSPI */
+	if (intstatus & I_CHIPACTIVE) {
+		brcmf_dbg(SDIO, "Dongle reports CHIPACTIVE\n");
+		intstatus &= ~I_CHIPACTIVE;
+	}
+
+	/* Ignore frame indications if rxskip is set */
+	if (bus->rxskip)
+		intstatus &= ~I_HMB_FRAME_IND;
+
+	/* On frame indication, read available frames */
+	if ((intstatus & I_HMB_FRAME_IND) && (bus->clkstate == CLK_AVAIL)) {
+		brcmf_sdio_readframes(bus, bus->rxbound);
+		if (!bus->rxpending)
+			intstatus &= ~I_HMB_FRAME_IND;
+	}
+
+	/* Keep still-pending events for next scheduling */
+	if (intstatus)
+		atomic_or(intstatus, &bus->intstatus);
+
+	brcmf_sdio_clrintr(bus);
+
+	if (bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL) &&
+	    data_ok(bus)) {
+		sdio_claim_host(bus->sdiodev->func1);
+		if (bus->ctrl_frame_stat) {
+			err = brcmf_sdio_tx_ctrlframe(bus,  bus->ctrl_frame_buf,
+						      bus->ctrl_frame_len);
+			bus->ctrl_frame_err = err;
+			wmb();
+			bus->ctrl_frame_stat = false;
+		}
+		sdio_release_host(bus->sdiodev->func1);
+		brcmf_sdio_wait_event_wakeup(bus);
+	}
+	/* Send queued frames (limit 1 if rx may still be pending) */
+	if ((bus->clkstate == CLK_AVAIL) && !atomic_read(&bus->fcstate) &&
+	    brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit &&
+	    data_ok(bus)) {
+		framecnt = bus->rxpending ? min(txlimit, bus->txminmax) :
+					    txlimit;
+		brcmf_sdio_sendfromq(bus, framecnt);
+	}
+
+	if ((bus->sdiodev->state != BRCMF_SDIOD_DATA) || (err != 0)) {
+		brcmf_err("failed backplane access over SDIO, halting operation\n");
+		atomic_set(&bus->intstatus, 0);
+		if (bus->ctrl_frame_stat) {
+			sdio_claim_host(bus->sdiodev->func1);
+			if (bus->ctrl_frame_stat) {
+				bus->ctrl_frame_err = -ENODEV;
+				wmb();
+				bus->ctrl_frame_stat = false;
+				brcmf_sdio_wait_event_wakeup(bus);
+			}
+			sdio_release_host(bus->sdiodev->func1);
+		}
+	} else if (atomic_read(&bus->intstatus) ||
+		   atomic_read(&bus->ipend) > 0 ||
+		   (!atomic_read(&bus->fcstate) &&
+		    brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) &&
+		    data_ok(bus))) {
+		bus->dpc_triggered = true;
+	}
+}
+
+static struct pktq *brcmf_sdio_bus_gettxq(struct device *dev)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+	struct brcmf_sdio *bus = sdiodev->bus;
+
+	return &bus->txq;
+}
+
+static bool brcmf_sdio_prec_enq(struct pktq *q, struct sk_buff *pkt, int prec)
+{
+	struct sk_buff *p;
+	int eprec = -1;		/* precedence to evict from */
+
+	/* Fast case, precedence queue is not full and we are also not
+	 * exceeding total queue length
+	 */
+	if (!pktq_pfull(q, prec) && !pktq_full(q)) {
+		brcmu_pktq_penq(q, prec, pkt);
+		return true;
+	}
+
+	/* Determine precedence from which to evict packet, if any */
+	if (pktq_pfull(q, prec)) {
+		eprec = prec;
+	} else if (pktq_full(q)) {
+		p = brcmu_pktq_peek_tail(q, &eprec);
+		if (eprec > prec)
+			return false;
+	}
+
+	/* Evict if needed */
+	if (eprec >= 0) {
+		/* Detect queueing to unconfigured precedence */
+		if (eprec == prec)
+			return false;	/* refuse newer (incoming) packet */
+		/* Evict packet according to discard policy */
+		p = brcmu_pktq_pdeq_tail(q, eprec);
+		if (p == NULL)
+			brcmf_err("brcmu_pktq_pdeq_tail() failed\n");
+		brcmu_pkt_buf_free_skb(p);
+	}
+
+	/* Enqueue */
+	p = brcmu_pktq_penq(q, prec, pkt);
+	if (p == NULL)
+		brcmf_err("brcmu_pktq_penq() failed\n");
+
+	return p != NULL;
+}
+
+static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt)
+{
+	int ret = -EBADE;
+	uint prec;
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+	struct brcmf_sdio *bus = sdiodev->bus;
+
+	brcmf_dbg(TRACE, "Enter: pkt: data %p len %d\n", pkt->data, pkt->len);
+	if (sdiodev->state != BRCMF_SDIOD_DATA)
+		return -EIO;
+
+	/* Add space for the header */
+	skb_push(pkt, bus->tx_hdrlen);
+	/* precondition: IS_ALIGNED((unsigned long)(pkt->data), 2) */
+
+	prec = prio2prec((pkt->priority & PRIOMASK));
+
+	/* Check for existing queue, current flow-control,
+			 pending event, or pending clock */
+	brcmf_dbg(TRACE, "deferring pktq len %d\n", pktq_len(&bus->txq));
+	bus->sdcnt.fcqueued++;
+
+	/* Priority based enq */
+	spin_lock_bh(&bus->txq_lock);
+	/* reset bus_flags in packet cb */
+	*(u16 *)(pkt->cb) = 0;
+	if (!brcmf_sdio_prec_enq(&bus->txq, pkt, prec)) {
+		skb_pull(pkt, bus->tx_hdrlen);
+		brcmf_err("out of bus->txq !!!\n");
+		ret = -ENOSR;
+	} else {
+		ret = 0;
+	}
+
+	if (pktq_len(&bus->txq) >= TXHI) {
+		bus->txoff = true;
+		brcmf_proto_bcdc_txflowblock(dev, true);
+	}
+	spin_unlock_bh(&bus->txq_lock);
+
+#ifdef DEBUG
+	if (pktq_plen(&bus->txq, prec) > qcount[prec])
+		qcount[prec] = pktq_plen(&bus->txq, prec);
+#endif
+
+	brcmf_sdio_trigger_dpc(bus);
+	return ret;
+}
+
+#ifdef DEBUG
+#define CONSOLE_LINE_MAX	192
+
+static int brcmf_sdio_readconsole(struct brcmf_sdio *bus)
+{
+	struct brcmf_console *c = &bus->console;
+	u8 line[CONSOLE_LINE_MAX], ch;
+	u32 n, idx, addr;
+	int rv;
+
+	/* Don't do anything until FWREADY updates console address */
+	if (bus->console_addr == 0)
+		return 0;
+
+	/* Read console log struct */
+	addr = bus->console_addr + offsetof(struct rte_console, log_le);
+	rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr, (u8 *)&c->log_le,
+			       sizeof(c->log_le));
+	if (rv < 0)
+		return rv;
+
+	/* Allocate console buffer (one time only) */
+	if (c->buf == NULL) {
+		c->bufsize = le32_to_cpu(c->log_le.buf_size);
+		c->buf = kmalloc(c->bufsize, GFP_ATOMIC);
+		if (c->buf == NULL)
+			return -ENOMEM;
+	}
+
+	idx = le32_to_cpu(c->log_le.idx);
+
+	/* Protect against corrupt value */
+	if (idx > c->bufsize)
+		return -EBADE;
+
+	/* Skip reading the console buffer if the index pointer
+	 has not moved */
+	if (idx == c->last)
+		return 0;
+
+	/* Read the console buffer */
+	addr = le32_to_cpu(c->log_le.buf);
+	rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr, c->buf, c->bufsize);
+	if (rv < 0)
+		return rv;
+
+	while (c->last != idx) {
+		for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
+			if (c->last == idx) {
+				/* This would output a partial line.
+				 * Instead, back up
+				 * the buffer pointer and output this
+				 * line next time around.
+				 */
+				if (c->last >= n)
+					c->last -= n;
+				else
+					c->last = c->bufsize - n;
+				goto break2;
+			}
+			ch = c->buf[c->last];
+			c->last = (c->last + 1) % c->bufsize;
+			if (ch == '\n')
+				break;
+			line[n] = ch;
+		}
+
+		if (n > 0) {
+			if (line[n - 1] == '\r')
+				n--;
+			line[n] = 0;
+			pr_debug("CONSOLE: %s\n", line);
+		}
+	}
+break2:
+
+	return 0;
+}
+#endif				/* DEBUG */
+
+static int
+brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+	struct brcmf_sdio *bus = sdiodev->bus;
+	int ret;
+
+	brcmf_dbg(TRACE, "Enter\n");
+	if (sdiodev->state != BRCMF_SDIOD_DATA)
+		return -EIO;
+
+	/* Send from dpc */
+	bus->ctrl_frame_buf = msg;
+	bus->ctrl_frame_len = msglen;
+	wmb();
+	bus->ctrl_frame_stat = true;
+
+	brcmf_sdio_trigger_dpc(bus);
+	wait_event_interruptible_timeout(bus->ctrl_wait, !bus->ctrl_frame_stat,
+					 CTL_DONE_TIMEOUT);
+	ret = 0;
+	if (bus->ctrl_frame_stat) {
+		sdio_claim_host(bus->sdiodev->func1);
+		if (bus->ctrl_frame_stat) {
+			brcmf_dbg(SDIO, "ctrl_frame timeout\n");
+			bus->ctrl_frame_stat = false;
+			ret = -ETIMEDOUT;
+		}
+		sdio_release_host(bus->sdiodev->func1);
+	}
+	if (!ret) {
+		brcmf_dbg(SDIO, "ctrl_frame complete, err=%d\n",
+			  bus->ctrl_frame_err);
+		rmb();
+		ret = bus->ctrl_frame_err;
+	}
+
+	if (ret)
+		bus->sdcnt.tx_ctlerrs++;
+	else
+		bus->sdcnt.tx_ctlpkts++;
+
+	return ret;
+}
+
+#ifdef DEBUG
+static int brcmf_sdio_dump_console(struct seq_file *seq, struct brcmf_sdio *bus,
+				   struct sdpcm_shared *sh)
+{
+	u32 addr, console_ptr, console_size, console_index;
+	char *conbuf = NULL;
+	__le32 sh_val;
+	int rv;
+
+	/* obtain console information from device memory */
+	addr = sh->console_addr + offsetof(struct rte_console, log_le);
+	rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr,
+			       (u8 *)&sh_val, sizeof(u32));
+	if (rv < 0)
+		return rv;
+	console_ptr = le32_to_cpu(sh_val);
+
+	addr = sh->console_addr + offsetof(struct rte_console, log_le.buf_size);
+	rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr,
+			       (u8 *)&sh_val, sizeof(u32));
+	if (rv < 0)
+		return rv;
+	console_size = le32_to_cpu(sh_val);
+
+	addr = sh->console_addr + offsetof(struct rte_console, log_le.idx);
+	rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr,
+			       (u8 *)&sh_val, sizeof(u32));
+	if (rv < 0)
+		return rv;
+	console_index = le32_to_cpu(sh_val);
+
+	/* allocate buffer for console data */
+	if (console_size <= CONSOLE_BUFFER_MAX)
+		conbuf = vzalloc(console_size+1);
+
+	if (!conbuf)
+		return -ENOMEM;
+
+	/* obtain the console data from device */
+	conbuf[console_size] = '\0';
+	rv = brcmf_sdiod_ramrw(bus->sdiodev, false, console_ptr, (u8 *)conbuf,
+			       console_size);
+	if (rv < 0)
+		goto done;
+
+	rv = seq_write(seq, conbuf + console_index,
+		       console_size - console_index);
+	if (rv < 0)
+		goto done;
+
+	if (console_index > 0)
+		rv = seq_write(seq, conbuf, console_index - 1);
+
+done:
+	vfree(conbuf);
+	return rv;
+}
+
+static int brcmf_sdio_trap_info(struct seq_file *seq, struct brcmf_sdio *bus,
+				struct sdpcm_shared *sh)
+{
+	int error;
+	struct brcmf_trap_info tr;
+
+	if ((sh->flags & SDPCM_SHARED_TRAP) == 0) {
+		brcmf_dbg(INFO, "no trap in firmware\n");
+		return 0;
+	}
+
+	error = brcmf_sdiod_ramrw(bus->sdiodev, false, sh->trap_addr, (u8 *)&tr,
+				  sizeof(struct brcmf_trap_info));
+	if (error < 0)
+		return error;
+
+	seq_printf(seq,
+		   "dongle trap info: type 0x%x @ epc 0x%08x\n"
+		   "  cpsr 0x%08x spsr 0x%08x sp 0x%08x\n"
+		   "  lr   0x%08x pc   0x%08x offset 0x%x\n"
+		   "  r0   0x%08x r1   0x%08x r2 0x%08x r3 0x%08x\n"
+		   "  r4   0x%08x r5   0x%08x r6 0x%08x r7 0x%08x\n",
+		   le32_to_cpu(tr.type), le32_to_cpu(tr.epc),
+		   le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr),
+		   le32_to_cpu(tr.r13), le32_to_cpu(tr.r14),
+		   le32_to_cpu(tr.pc), sh->trap_addr,
+		   le32_to_cpu(tr.r0), le32_to_cpu(tr.r1),
+		   le32_to_cpu(tr.r2), le32_to_cpu(tr.r3),
+		   le32_to_cpu(tr.r4), le32_to_cpu(tr.r5),
+		   le32_to_cpu(tr.r6), le32_to_cpu(tr.r7));
+
+	return 0;
+}
+
+static int brcmf_sdio_assert_info(struct seq_file *seq, struct brcmf_sdio *bus,
+				  struct sdpcm_shared *sh)
+{
+	int error = 0;
+	char file[80] = "?";
+	char expr[80] = "<???>";
+
+	if ((sh->flags & SDPCM_SHARED_ASSERT_BUILT) == 0) {
+		brcmf_dbg(INFO, "firmware not built with -assert\n");
+		return 0;
+	} else if ((sh->flags & SDPCM_SHARED_ASSERT) == 0) {
+		brcmf_dbg(INFO, "no assert in dongle\n");
+		return 0;
+	}
+
+	sdio_claim_host(bus->sdiodev->func1);
+	if (sh->assert_file_addr != 0) {
+		error = brcmf_sdiod_ramrw(bus->sdiodev, false,
+					  sh->assert_file_addr, (u8 *)file, 80);
+		if (error < 0)
+			return error;
+	}
+	if (sh->assert_exp_addr != 0) {
+		error = brcmf_sdiod_ramrw(bus->sdiodev, false,
+					  sh->assert_exp_addr, (u8 *)expr, 80);
+		if (error < 0)
+			return error;
+	}
+	sdio_release_host(bus->sdiodev->func1);
+
+	seq_printf(seq, "dongle assert: %s:%d: assert(%s)\n",
+		   file, sh->assert_line, expr);
+	return 0;
+}
+
+static int brcmf_sdio_checkdied(struct brcmf_sdio *bus)
+{
+	int error;
+	struct sdpcm_shared sh;
+
+	error = brcmf_sdio_readshared(bus, &sh);
+
+	if (error < 0)
+		return error;
+
+	if ((sh.flags & SDPCM_SHARED_ASSERT_BUILT) == 0)
+		brcmf_dbg(INFO, "firmware not built with -assert\n");
+	else if (sh.flags & SDPCM_SHARED_ASSERT)
+		brcmf_err("assertion in dongle\n");
+
+	if (sh.flags & SDPCM_SHARED_TRAP)
+		brcmf_err("firmware trap in dongle\n");
+
+	return 0;
+}
+
+static int brcmf_sdio_died_dump(struct seq_file *seq, struct brcmf_sdio *bus)
+{
+	int error = 0;
+	struct sdpcm_shared sh;
+
+	error = brcmf_sdio_readshared(bus, &sh);
+	if (error < 0)
+		goto done;
+
+	error = brcmf_sdio_assert_info(seq, bus, &sh);
+	if (error < 0)
+		goto done;
+
+	error = brcmf_sdio_trap_info(seq, bus, &sh);
+	if (error < 0)
+		goto done;
+
+	error = brcmf_sdio_dump_console(seq, bus, &sh);
+
+done:
+	return error;
+}
+
+static int brcmf_sdio_forensic_read(struct seq_file *seq, void *data)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
+	struct brcmf_sdio *bus = bus_if->bus_priv.sdio->bus;
+
+	return brcmf_sdio_died_dump(seq, bus);
+}
+
+static int brcmf_debugfs_sdio_count_read(struct seq_file *seq, void *data)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+	struct brcmf_sdio_count *sdcnt = &sdiodev->bus->sdcnt;
+
+	seq_printf(seq,
+		   "intrcount:    %u\nlastintrs:    %u\n"
+		   "pollcnt:      %u\nregfails:     %u\n"
+		   "tx_sderrs:    %u\nfcqueued:     %u\n"
+		   "rxrtx:        %u\nrx_toolong:   %u\n"
+		   "rxc_errors:   %u\nrx_hdrfail:   %u\n"
+		   "rx_badhdr:    %u\nrx_badseq:    %u\n"
+		   "fc_rcvd:      %u\nfc_xoff:      %u\n"
+		   "fc_xon:       %u\nrxglomfail:   %u\n"
+		   "rxglomframes: %u\nrxglompkts:   %u\n"
+		   "f2rxhdrs:     %u\nf2rxdata:     %u\n"
+		   "f2txdata:     %u\nf1regdata:    %u\n"
+		   "tickcnt:      %u\ntx_ctlerrs:   %lu\n"
+		   "tx_ctlpkts:   %lu\nrx_ctlerrs:   %lu\n"
+		   "rx_ctlpkts:   %lu\nrx_readahead: %lu\n",
+		   sdcnt->intrcount, sdcnt->lastintrs,
+		   sdcnt->pollcnt, sdcnt->regfails,
+		   sdcnt->tx_sderrs, sdcnt->fcqueued,
+		   sdcnt->rxrtx, sdcnt->rx_toolong,
+		   sdcnt->rxc_errors, sdcnt->rx_hdrfail,
+		   sdcnt->rx_badhdr, sdcnt->rx_badseq,
+		   sdcnt->fc_rcvd, sdcnt->fc_xoff,
+		   sdcnt->fc_xon, sdcnt->rxglomfail,
+		   sdcnt->rxglomframes, sdcnt->rxglompkts,
+		   sdcnt->f2rxhdrs, sdcnt->f2rxdata,
+		   sdcnt->f2txdata, sdcnt->f1regdata,
+		   sdcnt->tickcnt, sdcnt->tx_ctlerrs,
+		   sdcnt->tx_ctlpkts, sdcnt->rx_ctlerrs,
+		   sdcnt->rx_ctlpkts, sdcnt->rx_readahead_cnt);
+
+	return 0;
+}
+
+static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus)
+{
+	struct brcmf_pub *drvr = bus->sdiodev->bus_if->drvr;
+	struct dentry *dentry = brcmf_debugfs_get_devdir(drvr);
+
+	if (IS_ERR_OR_NULL(dentry))
+		return;
+
+	bus->console_interval = BRCMF_CONSOLE;
+
+	brcmf_debugfs_add_entry(drvr, "forensics", brcmf_sdio_forensic_read);
+	brcmf_debugfs_add_entry(drvr, "counters",
+				brcmf_debugfs_sdio_count_read);
+	debugfs_create_u32("console_interval", 0644, dentry,
+			   &bus->console_interval);
+}
+#else
+static int brcmf_sdio_checkdied(struct brcmf_sdio *bus)
+{
+	return 0;
+}
+
+static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus)
+{
+}
+#endif /* DEBUG */
+
+static int
+brcmf_sdio_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
+{
+	int timeleft;
+	uint rxlen = 0;
+	bool pending;
+	u8 *buf;
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+	struct brcmf_sdio *bus = sdiodev->bus;
+
+	brcmf_dbg(TRACE, "Enter\n");
+	if (sdiodev->state != BRCMF_SDIOD_DATA)
+		return -EIO;
+
+	/* Wait until control frame is available */
+	timeleft = brcmf_sdio_dcmd_resp_wait(bus, &bus->rxlen, &pending);
+
+	spin_lock_bh(&bus->rxctl_lock);
+	rxlen = bus->rxlen;
+	memcpy(msg, bus->rxctl, min(msglen, rxlen));
+	bus->rxctl = NULL;
+	buf = bus->rxctl_orig;
+	bus->rxctl_orig = NULL;
+	bus->rxlen = 0;
+	spin_unlock_bh(&bus->rxctl_lock);
+	vfree(buf);
+
+	if (rxlen) {
+		brcmf_dbg(CTL, "resumed on rxctl frame, got %d expected %d\n",
+			  rxlen, msglen);
+	} else if (timeleft == 0) {
+		brcmf_err("resumed on timeout\n");
+		brcmf_sdio_checkdied(bus);
+	} else if (pending) {
+		brcmf_dbg(CTL, "cancelled\n");
+		return -ERESTARTSYS;
+	} else {
+		brcmf_dbg(CTL, "resumed for unknown reason?\n");
+		brcmf_sdio_checkdied(bus);
+	}
+
+	if (rxlen)
+		bus->sdcnt.rx_ctlpkts++;
+	else
+		bus->sdcnt.rx_ctlerrs++;
+
+	return rxlen ? (int)rxlen : -ETIMEDOUT;
+}
+
+#ifdef DEBUG
+static bool
+brcmf_sdio_verifymemory(struct brcmf_sdio_dev *sdiodev, u32 ram_addr,
+			u8 *ram_data, uint ram_sz)
+{
+	char *ram_cmp;
+	int err;
+	bool ret = true;
+	int address;
+	int offset;
+	int len;
+
+	/* read back and verify */
+	brcmf_dbg(INFO, "Compare RAM dl & ul at 0x%08x; size=%d\n", ram_addr,
+		  ram_sz);
+	ram_cmp = kmalloc(MEMBLOCK, GFP_KERNEL);
+	/* do not proceed while no memory but  */
+	if (!ram_cmp)
+		return true;
+
+	address = ram_addr;
+	offset = 0;
+	while (offset < ram_sz) {
+		len = ((offset + MEMBLOCK) < ram_sz) ? MEMBLOCK :
+		      ram_sz - offset;
+		err = brcmf_sdiod_ramrw(sdiodev, false, address, ram_cmp, len);
+		if (err) {
+			brcmf_err("error %d on reading %d membytes at 0x%08x\n",
+				  err, len, address);
+			ret = false;
+			break;
+		} else if (memcmp(ram_cmp, &ram_data[offset], len)) {
+			brcmf_err("Downloaded RAM image is corrupted, block offset is %d, len is %d\n",
+				  offset, len);
+			ret = false;
+			break;
+		}
+		offset += len;
+		address += len;
+	}
+
+	kfree(ram_cmp);
+
+	return ret;
+}
+#else	/* DEBUG */
+static bool
+brcmf_sdio_verifymemory(struct brcmf_sdio_dev *sdiodev, u32 ram_addr,
+			u8 *ram_data, uint ram_sz)
+{
+	return true;
+}
+#endif	/* DEBUG */
+
+static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus,
+					 const struct firmware *fw)
+{
+	int err;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	err = brcmf_sdiod_ramrw(bus->sdiodev, true, bus->ci->rambase,
+				(u8 *)fw->data, fw->size);
+	if (err)
+		brcmf_err("error %d on writing %d membytes at 0x%08x\n",
+			  err, (int)fw->size, bus->ci->rambase);
+	else if (!brcmf_sdio_verifymemory(bus->sdiodev, bus->ci->rambase,
+					  (u8 *)fw->data, fw->size))
+		err = -EIO;
+
+	return err;
+}
+
+static int brcmf_sdio_download_nvram(struct brcmf_sdio *bus,
+				     void *vars, u32 varsz)
+{
+	int address;
+	int err;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	address = bus->ci->ramsize - varsz + bus->ci->rambase;
+	err = brcmf_sdiod_ramrw(bus->sdiodev, true, address, vars, varsz);
+	if (err)
+		brcmf_err("error %d on writing %d nvram bytes at 0x%08x\n",
+			  err, varsz, address);
+	else if (!brcmf_sdio_verifymemory(bus->sdiodev, address, vars, varsz))
+		err = -EIO;
+
+	return err;
+}
+
+static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus,
+					const struct firmware *fw,
+					void *nvram, u32 nvlen)
+{
+	int bcmerror;
+	u32 rstvec;
+
+	sdio_claim_host(bus->sdiodev->func1);
+	brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
+
+	rstvec = get_unaligned_le32(fw->data);
+	brcmf_dbg(SDIO, "firmware rstvec: %x\n", rstvec);
+
+	bcmerror = brcmf_sdio_download_code_file(bus, fw);
+	release_firmware(fw);
+	if (bcmerror) {
+		brcmf_err("dongle image file download failed\n");
+		brcmf_fw_nvram_free(nvram);
+		goto err;
+	}
+
+	bcmerror = brcmf_sdio_download_nvram(bus, nvram, nvlen);
+	brcmf_fw_nvram_free(nvram);
+	if (bcmerror) {
+		brcmf_err("dongle nvram file download failed\n");
+		goto err;
+	}
+
+	/* Take arm out of reset */
+	if (!brcmf_chip_set_active(bus->ci, rstvec)) {
+		brcmf_err("error getting out of ARM core reset\n");
+		goto err;
+	}
+
+err:
+	brcmf_sdio_clkctl(bus, CLK_SDONLY, false);
+	sdio_release_host(bus->sdiodev->func1);
+	return bcmerror;
+}
+
+static void brcmf_sdio_sr_init(struct brcmf_sdio *bus)
+{
+	int err = 0;
+	u8 val;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	val = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, &err);
+	if (err) {
+		brcmf_err("error reading SBSDIO_FUNC1_WAKEUPCTRL\n");
+		return;
+	}
+
+	val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
+	brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, val, &err);
+	if (err) {
+		brcmf_err("error writing SBSDIO_FUNC1_WAKEUPCTRL\n");
+		return;
+	}
+
+	/* Add CMD14 Support */
+	brcmf_sdiod_func0_wb(bus->sdiodev, SDIO_CCCR_BRCM_CARDCAP,
+			     (SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT |
+			      SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT),
+			     &err);
+	if (err) {
+		brcmf_err("error writing SDIO_CCCR_BRCM_CARDCAP\n");
+		return;
+	}
+
+	brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+			   SBSDIO_FORCE_HT, &err);
+	if (err) {
+		brcmf_err("error writing SBSDIO_FUNC1_CHIPCLKCSR\n");
+		return;
+	}
+
+	/* set flag */
+	bus->sr_enabled = true;
+	brcmf_dbg(INFO, "SR enabled\n");
+}
+
+/* enable KSO bit */
+static int brcmf_sdio_kso_init(struct brcmf_sdio *bus)
+{
+	struct brcmf_core *core = bus->sdio_core;
+	u8 val;
+	int err = 0;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	/* KSO bit added in SDIO core rev 12 */
+	if (core->rev < 12)
+		return 0;
+
+	val = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, &err);
+	if (err) {
+		brcmf_err("error reading SBSDIO_FUNC1_SLEEPCSR\n");
+		return err;
+	}
+
+	if (!(val & SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) {
+		val |= (SBSDIO_FUNC1_SLEEPCSR_KSO_EN <<
+			SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
+		brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
+				   val, &err);
+		if (err) {
+			brcmf_err("error writing SBSDIO_FUNC1_SLEEPCSR\n");
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+
+static int brcmf_sdio_bus_preinit(struct device *dev)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+	struct brcmf_sdio *bus = sdiodev->bus;
+	struct brcmf_core *core = bus->sdio_core;
+	uint pad_size;
+	u32 value;
+	int err;
+
+	/* maxctl provided by common layer */
+	if (WARN_ON(!bus_if->maxctl))
+		return -EINVAL;
+
+	/* Allocate control receive buffer */
+	bus_if->maxctl += bus->roundup;
+	value = roundup((bus_if->maxctl + SDPCM_HDRLEN), ALIGNMENT);
+	value += bus->head_align;
+	bus->rxbuf = kmalloc(value, GFP_ATOMIC);
+	if (bus->rxbuf)
+		bus->rxblen = value;
+
+	brcmf_sdio_debugfs_create(bus);
+
+	/* the commands below use the terms tx and rx from
+	 * a device perspective, ie. bus:txglom affects the
+	 * bus transfers from device to host.
+	 */
+	if (core->rev < 12) {
+		/* for sdio core rev < 12, disable txgloming */
+		value = 0;
+		err = brcmf_iovar_data_set(dev, "bus:txglom", &value,
+					   sizeof(u32));
+	} else {
+		/* otherwise, set txglomalign */
+		value = sdiodev->settings->bus.sdio.sd_sgentry_align;
+		/* SDIO ADMA requires at least 32 bit alignment */
+		value = max_t(u32, value, ALIGNMENT);
+		err = brcmf_iovar_data_set(dev, "bus:txglomalign", &value,
+					   sizeof(u32));
+	}
+
+	if (err < 0)
+		goto done;
+
+	bus->tx_hdrlen = SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN;
+	if (sdiodev->sg_support) {
+		bus->txglom = false;
+		value = 1;
+		pad_size = bus->sdiodev->func2->cur_blksize << 1;
+		err = brcmf_iovar_data_set(bus->sdiodev->dev, "bus:rxglom",
+					   &value, sizeof(u32));
+		if (err < 0) {
+			/* bus:rxglom is allowed to fail */
+			err = 0;
+		} else {
+			bus->txglom = true;
+			bus->tx_hdrlen += SDPCM_HWEXT_LEN;
+		}
+	}
+	brcmf_bus_add_txhdrlen(bus->sdiodev->dev, bus->tx_hdrlen);
+
+done:
+	return err;
+}
+
+static size_t brcmf_sdio_bus_get_ramsize(struct device *dev)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+	struct brcmf_sdio *bus = sdiodev->bus;
+
+	return bus->ci->ramsize - bus->ci->srsize;
+}
+
+static int brcmf_sdio_bus_get_memdump(struct device *dev, void *data,
+				      size_t mem_size)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+	struct brcmf_sdio *bus = sdiodev->bus;
+	int err;
+	int address;
+	int offset;
+	int len;
+
+	brcmf_dbg(INFO, "dump at 0x%08x: size=%zu\n", bus->ci->rambase,
+		  mem_size);
+
+	address = bus->ci->rambase;
+	offset = err = 0;
+	sdio_claim_host(sdiodev->func1);
+	while (offset < mem_size) {
+		len = ((offset + MEMBLOCK) < mem_size) ? MEMBLOCK :
+		      mem_size - offset;
+		err = brcmf_sdiod_ramrw(sdiodev, false, address, data, len);
+		if (err) {
+			brcmf_err("error %d on reading %d membytes at 0x%08x\n",
+				  err, len, address);
+			goto done;
+		}
+		data += len;
+		offset += len;
+		address += len;
+	}
+
+done:
+	sdio_release_host(sdiodev->func1);
+	return err;
+}
+
+void brcmf_sdio_trigger_dpc(struct brcmf_sdio *bus)
+{
+	if (!bus->dpc_triggered) {
+		bus->dpc_triggered = true;
+		queue_work(bus->brcmf_wq, &bus->datawork);
+	}
+}
+
+void brcmf_sdio_isr(struct brcmf_sdio *bus)
+{
+	brcmf_dbg(TRACE, "Enter\n");
+
+	if (!bus) {
+		brcmf_err("bus is null pointer, exiting\n");
+		return;
+	}
+
+	/* Count the interrupt call */
+	bus->sdcnt.intrcount++;
+	if (in_interrupt())
+		atomic_set(&bus->ipend, 1);
+	else
+		if (brcmf_sdio_intr_rstatus(bus)) {
+			brcmf_err("failed backplane access\n");
+		}
+
+	/* Disable additional interrupts (is this needed now)? */
+	if (!bus->intr)
+		brcmf_err("isr w/o interrupt configured!\n");
+
+	bus->dpc_triggered = true;
+	queue_work(bus->brcmf_wq, &bus->datawork);
+}
+
+static void brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus)
+{
+	brcmf_dbg(TIMER, "Enter\n");
+
+	/* Poll period: check device if appropriate. */
+	if (!bus->sr_enabled &&
+	    bus->poll && (++bus->polltick >= bus->pollrate)) {
+		u32 intstatus = 0;
+
+		/* Reset poll tick */
+		bus->polltick = 0;
+
+		/* Check device if no interrupts */
+		if (!bus->intr ||
+		    (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) {
+
+			if (!bus->dpc_triggered) {
+				u8 devpend;
+
+				sdio_claim_host(bus->sdiodev->func1);
+				devpend = brcmf_sdiod_func0_rb(bus->sdiodev,
+						  SDIO_CCCR_INTx, NULL);
+				sdio_release_host(bus->sdiodev->func1);
+				intstatus = devpend & (INTR_STATUS_FUNC1 |
+						       INTR_STATUS_FUNC2);
+			}
+
+			/* If there is something, make like the ISR and
+				 schedule the DPC */
+			if (intstatus) {
+				bus->sdcnt.pollcnt++;
+				atomic_set(&bus->ipend, 1);
+
+				bus->dpc_triggered = true;
+				queue_work(bus->brcmf_wq, &bus->datawork);
+			}
+		}
+
+		/* Update interrupt tracking */
+		bus->sdcnt.lastintrs = bus->sdcnt.intrcount;
+	}
+#ifdef DEBUG
+	/* Poll for console output periodically */
+	if (bus->sdiodev->state == BRCMF_SDIOD_DATA && BRCMF_FWCON_ON() &&
+	    bus->console_interval != 0) {
+		bus->console.count += jiffies_to_msecs(BRCMF_WD_POLL);
+		if (bus->console.count >= bus->console_interval) {
+			bus->console.count -= bus->console_interval;
+			sdio_claim_host(bus->sdiodev->func1);
+			/* Make sure backplane clock is on */
+			brcmf_sdio_bus_sleep(bus, false, false);
+			if (brcmf_sdio_readconsole(bus) < 0)
+				/* stop on error */
+				bus->console_interval = 0;
+			sdio_release_host(bus->sdiodev->func1);
+		}
+	}
+#endif				/* DEBUG */
+
+	/* On idle timeout clear activity flag and/or turn off clock */
+	if (!bus->dpc_triggered) {
+		rmb();
+		if ((!bus->dpc_running) && (bus->idletime > 0) &&
+		    (bus->clkstate == CLK_AVAIL)) {
+			bus->idlecount++;
+			if (bus->idlecount > bus->idletime) {
+				brcmf_dbg(SDIO, "idle\n");
+				sdio_claim_host(bus->sdiodev->func1);
+				brcmf_sdio_wd_timer(bus, false);
+				bus->idlecount = 0;
+				brcmf_sdio_bus_sleep(bus, true, false);
+				sdio_release_host(bus->sdiodev->func1);
+			}
+		} else {
+			bus->idlecount = 0;
+		}
+	} else {
+		bus->idlecount = 0;
+	}
+}
+
+static void brcmf_sdio_dataworker(struct work_struct *work)
+{
+	struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio,
+					      datawork);
+
+	bus->dpc_running = true;
+	wmb();
+	while (READ_ONCE(bus->dpc_triggered)) {
+		bus->dpc_triggered = false;
+		brcmf_sdio_dpc(bus);
+		bus->idlecount = 0;
+	}
+	bus->dpc_running = false;
+	if (brcmf_sdiod_freezing(bus->sdiodev)) {
+		brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DOWN);
+		brcmf_sdiod_try_freeze(bus->sdiodev);
+		brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DATA);
+	}
+}
+
+static void
+brcmf_sdio_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
+			     struct brcmf_chip *ci, u32 drivestrength)
+{
+	const struct sdiod_drive_str *str_tab = NULL;
+	u32 str_mask;
+	u32 str_shift;
+	u32 i;
+	u32 drivestrength_sel = 0;
+	u32 cc_data_temp;
+	u32 addr;
+
+	if (!(ci->cc_caps & CC_CAP_PMU))
+		return;
+
+	switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
+	case SDIOD_DRVSTR_KEY(BRCM_CC_4330_CHIP_ID, 12):
+		str_tab = sdiod_drvstr_tab1_1v8;
+		str_mask = 0x00003800;
+		str_shift = 11;
+		break;
+	case SDIOD_DRVSTR_KEY(BRCM_CC_4334_CHIP_ID, 17):
+		str_tab = sdiod_drvstr_tab6_1v8;
+		str_mask = 0x00001800;
+		str_shift = 11;
+		break;
+	case SDIOD_DRVSTR_KEY(BRCM_CC_43143_CHIP_ID, 17):
+		/* note: 43143 does not support tristate */
+		i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1;
+		if (drivestrength >= sdiod_drvstr_tab2_3v3[i].strength) {
+			str_tab = sdiod_drvstr_tab2_3v3;
+			str_mask = 0x00000007;
+			str_shift = 0;
+		} else
+			brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n",
+				  ci->name, drivestrength);
+		break;
+	case SDIOD_DRVSTR_KEY(BRCM_CC_43362_CHIP_ID, 13):
+		str_tab = sdiod_drive_strength_tab5_1v8;
+		str_mask = 0x00003800;
+		str_shift = 11;
+		break;
+	default:
+		brcmf_dbg(INFO, "No SDIO driver strength init needed for chip %s rev %d pmurev %d\n",
+			  ci->name, ci->chiprev, ci->pmurev);
+		break;
+	}
+
+	if (str_tab != NULL) {
+		struct brcmf_core *pmu = brcmf_chip_get_pmu(ci);
+
+		for (i = 0; str_tab[i].strength != 0; i++) {
+			if (drivestrength >= str_tab[i].strength) {
+				drivestrength_sel = str_tab[i].sel;
+				break;
+			}
+		}
+		addr = CORE_CC_REG(pmu->base, chipcontrol_addr);
+		brcmf_sdiod_writel(sdiodev, addr, 1, NULL);
+		cc_data_temp = brcmf_sdiod_readl(sdiodev, addr, NULL);
+		cc_data_temp &= ~str_mask;
+		drivestrength_sel <<= str_shift;
+		cc_data_temp |= drivestrength_sel;
+		brcmf_sdiod_writel(sdiodev, addr, cc_data_temp, NULL);
+
+		brcmf_dbg(INFO, "SDIO: %d mA (req=%d mA) drive strength selected, set to 0x%08x\n",
+			  str_tab[i].strength, drivestrength, cc_data_temp);
+	}
+}
+
+static int brcmf_sdio_buscoreprep(void *ctx)
+{
+	struct brcmf_sdio_dev *sdiodev = ctx;
+	int err = 0;
+	u8 clkval, clkset;
+
+	/* Try forcing SDIO core to do ALPAvail request only */
+	clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
+	brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
+	if (err) {
+		brcmf_err("error writing for HT off\n");
+		return err;
+	}
+
+	/* If register supported, wait for ALPAvail and then force ALP */
+	/* This may take up to 15 milliseconds */
+	clkval = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, NULL);
+
+	if ((clkval & ~SBSDIO_AVBITS) != clkset) {
+		brcmf_err("ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
+			  clkset, clkval);
+		return -EACCES;
+	}
+
+	SPINWAIT(((clkval = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+					      NULL)),
+		 !SBSDIO_ALPAV(clkval)),
+		 PMU_MAX_TRANSITION_DLY);
+
+	if (!SBSDIO_ALPAV(clkval)) {
+		brcmf_err("timeout on ALPAV wait, clkval 0x%02x\n",
+			  clkval);
+		return -EBUSY;
+	}
+
+	clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
+	brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
+	udelay(65);
+
+	/* Also, disable the extra SDIO pull-ups */
+	brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
+
+	return 0;
+}
+
+static void brcmf_sdio_buscore_activate(void *ctx, struct brcmf_chip *chip,
+					u32 rstvec)
+{
+	struct brcmf_sdio_dev *sdiodev = ctx;
+	struct brcmf_core *core = sdiodev->bus->sdio_core;
+	u32 reg_addr;
+
+	/* clear all interrupts */
+	reg_addr = core->base + SD_REG(intstatus);
+	brcmf_sdiod_writel(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
+
+	if (rstvec)
+		/* Write reset vector to address 0 */
+		brcmf_sdiod_ramrw(sdiodev, true, 0, (void *)&rstvec,
+				  sizeof(rstvec));
+}
+
+static u32 brcmf_sdio_buscore_read32(void *ctx, u32 addr)
+{
+	struct brcmf_sdio_dev *sdiodev = ctx;
+	u32 val, rev;
+
+	val = brcmf_sdiod_readl(sdiodev, addr, NULL);
+
+	/*
+	 * this is a bit of special handling if reading the chipcommon chipid
+	 * register. The 4339 is a next-gen of the 4335. It uses the same
+	 * SDIO device id as 4335 and the chipid register returns 4335 as well.
+	 * It can be identified as 4339 by looking at the chip revision. It
+	 * is corrected here so the chip.c module has the right info.
+	 */
+	if (addr == CORE_CC_REG(SI_ENUM_BASE, chipid) &&
+	    (sdiodev->func1->device == SDIO_DEVICE_ID_BROADCOM_4339 ||
+	     sdiodev->func1->device == SDIO_DEVICE_ID_BROADCOM_4335_4339)) {
+		rev = (val & CID_REV_MASK) >> CID_REV_SHIFT;
+		if (rev >= 2) {
+			val &= ~CID_ID_MASK;
+			val |= BRCM_CC_4339_CHIP_ID;
+		}
+	}
+
+	return val;
+}
+
+static void brcmf_sdio_buscore_write32(void *ctx, u32 addr, u32 val)
+{
+	struct brcmf_sdio_dev *sdiodev = ctx;
+
+	brcmf_sdiod_writel(sdiodev, addr, val, NULL);
+}
+
+static const struct brcmf_buscore_ops brcmf_sdio_buscore_ops = {
+	.prepare = brcmf_sdio_buscoreprep,
+	.activate = brcmf_sdio_buscore_activate,
+	.read32 = brcmf_sdio_buscore_read32,
+	.write32 = brcmf_sdio_buscore_write32,
+};
+
+static bool
+brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
+{
+	struct brcmf_sdio_dev *sdiodev;
+	u8 clkctl = 0;
+	int err = 0;
+	int reg_addr;
+	u32 reg_val;
+	u32 drivestrength;
+
+	sdiodev = bus->sdiodev;
+	sdio_claim_host(sdiodev->func1);
+
+	pr_debug("F1 signature read @0x18000000=0x%4x\n",
+		 brcmf_sdiod_readl(sdiodev, SI_ENUM_BASE, NULL));
+
+	/*
+	 * Force PLL off until brcmf_chip_attach()
+	 * programs PLL control regs
+	 */
+
+	brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, BRCMF_INIT_CLKCTL1,
+			   &err);
+	if (!err)
+		clkctl = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+					   &err);
+
+	if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) {
+		brcmf_err("ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n",
+			  err, BRCMF_INIT_CLKCTL1, clkctl);
+		goto fail;
+	}
+
+	bus->ci = brcmf_chip_attach(sdiodev, &brcmf_sdio_buscore_ops);
+	if (IS_ERR(bus->ci)) {
+		brcmf_err("brcmf_chip_attach failed!\n");
+		bus->ci = NULL;
+		goto fail;
+	}
+
+	/* Pick up the SDIO core info struct from chip.c */
+	bus->sdio_core   = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
+	if (!bus->sdio_core)
+		goto fail;
+
+	/* Pick up the CHIPCOMMON core info struct, for bulk IO in bcmsdh.c */
+	sdiodev->cc_core = brcmf_chip_get_core(bus->ci, BCMA_CORE_CHIPCOMMON);
+	if (!sdiodev->cc_core)
+		goto fail;
+
+	sdiodev->settings = brcmf_get_module_param(sdiodev->dev,
+						   BRCMF_BUSTYPE_SDIO,
+						   bus->ci->chip,
+						   bus->ci->chiprev);
+	if (!sdiodev->settings) {
+		brcmf_err("Failed to get device parameters\n");
+		goto fail;
+	}
+	/* platform specific configuration:
+	 *   alignments must be at least 4 bytes for ADMA
+	 */
+	bus->head_align = ALIGNMENT;
+	bus->sgentry_align = ALIGNMENT;
+	if (sdiodev->settings->bus.sdio.sd_head_align > ALIGNMENT)
+		bus->head_align = sdiodev->settings->bus.sdio.sd_head_align;
+	if (sdiodev->settings->bus.sdio.sd_sgentry_align > ALIGNMENT)
+		bus->sgentry_align =
+				sdiodev->settings->bus.sdio.sd_sgentry_align;
+
+	/* allocate scatter-gather table. sg support
+	 * will be disabled upon allocation failure.
+	 */
+	brcmf_sdiod_sgtable_alloc(sdiodev);
+
+#ifdef CONFIG_PM_SLEEP
+	/* wowl can be supported when KEEP_POWER is true and (WAKE_SDIO_IRQ
+	 * is true or when platform data OOB irq is true).
+	 */
+	if ((sdio_get_host_pm_caps(sdiodev->func1) & MMC_PM_KEEP_POWER) &&
+	    ((sdio_get_host_pm_caps(sdiodev->func1) & MMC_PM_WAKE_SDIO_IRQ) ||
+	     (sdiodev->settings->bus.sdio.oob_irq_supported)))
+		sdiodev->bus_if->wowl_supported = true;
+#endif
+
+	if (brcmf_sdio_kso_init(bus)) {
+		brcmf_err("error enabling KSO\n");
+		goto fail;
+	}
+
+	if (sdiodev->settings->bus.sdio.drive_strength)
+		drivestrength = sdiodev->settings->bus.sdio.drive_strength;
+	else
+		drivestrength = DEFAULT_SDIO_DRIVE_STRENGTH;
+	brcmf_sdio_drivestrengthinit(sdiodev, bus->ci, drivestrength);
+
+	/* Set card control so an SDIO card reset does a WLAN backplane reset */
+	reg_val = brcmf_sdiod_func0_rb(sdiodev, SDIO_CCCR_BRCM_CARDCTRL, &err);
+	if (err)
+		goto fail;
+
+	reg_val |= SDIO_CCCR_BRCM_CARDCTRL_WLANRESET;
+
+	brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_BRCM_CARDCTRL, reg_val, &err);
+	if (err)
+		goto fail;
+
+	/* set PMUControl so a backplane reset does PMU state reload */
+	reg_addr = CORE_CC_REG(brcmf_chip_get_pmu(bus->ci)->base, pmucontrol);
+	reg_val = brcmf_sdiod_readl(sdiodev, reg_addr, &err);
+	if (err)
+		goto fail;
+
+	reg_val |= (BCMA_CC_PMU_CTL_RES_RELOAD << BCMA_CC_PMU_CTL_RES_SHIFT);
+
+	brcmf_sdiod_writel(sdiodev, reg_addr, reg_val, &err);
+	if (err)
+		goto fail;
+
+	sdio_release_host(sdiodev->func1);
+
+	brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
+
+	/* allocate header buffer */
+	bus->hdrbuf = kzalloc(MAX_HDR_READ + bus->head_align, GFP_KERNEL);
+	if (!bus->hdrbuf)
+		return false;
+	/* Locate an appropriately-aligned portion of hdrbuf */
+	bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0],
+				    bus->head_align);
+
+	/* Set the poll and/or interrupt flags */
+	bus->intr = true;
+	bus->poll = false;
+	if (bus->poll)
+		bus->pollrate = 1;
+
+	return true;
+
+fail:
+	sdio_release_host(sdiodev->func1);
+	return false;
+}
+
+static int
+brcmf_sdio_watchdog_thread(void *data)
+{
+	struct brcmf_sdio *bus = (struct brcmf_sdio *)data;
+	int wait;
+
+	allow_signal(SIGTERM);
+	/* Run until signal received */
+	brcmf_sdiod_freezer_count(bus->sdiodev);
+	while (1) {
+		if (kthread_should_stop())
+			break;
+		brcmf_sdiod_freezer_uncount(bus->sdiodev);
+		wait = wait_for_completion_interruptible(&bus->watchdog_wait);
+		brcmf_sdiod_freezer_count(bus->sdiodev);
+		brcmf_sdiod_try_freeze(bus->sdiodev);
+		if (!wait) {
+			brcmf_sdio_bus_watchdog(bus);
+			/* Count the tick for reference */
+			bus->sdcnt.tickcnt++;
+			reinit_completion(&bus->watchdog_wait);
+		} else
+			break;
+	}
+	return 0;
+}
+
+static void
+brcmf_sdio_watchdog(struct timer_list *t)
+{
+	struct brcmf_sdio *bus = from_timer(bus, t, timer);
+
+	if (bus->watchdog_tsk) {
+		complete(&bus->watchdog_wait);
+		/* Reschedule the watchdog */
+		if (bus->wd_active)
+			mod_timer(&bus->timer,
+				  jiffies + BRCMF_WD_POLL);
+	}
+}
+
+static
+int brcmf_sdio_get_fwname(struct device *dev, const char *ext, u8 *fw_name)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_fw_request *fwreq;
+	struct brcmf_fw_name fwnames[] = {
+		{ ext, fw_name },
+	};
+
+	fwreq = brcmf_fw_alloc_request(bus_if->chip, bus_if->chiprev,
+				       brcmf_sdio_fwnames,
+				       ARRAY_SIZE(brcmf_sdio_fwnames),
+				       fwnames, ARRAY_SIZE(fwnames));
+	if (!fwreq)
+		return -ENOMEM;
+
+	kfree(fwreq);
+	return 0;
+}
+
+static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
+	.stop = brcmf_sdio_bus_stop,
+	.preinit = brcmf_sdio_bus_preinit,
+	.txdata = brcmf_sdio_bus_txdata,
+	.txctl = brcmf_sdio_bus_txctl,
+	.rxctl = brcmf_sdio_bus_rxctl,
+	.gettxq = brcmf_sdio_bus_gettxq,
+	.wowl_config = brcmf_sdio_wowl_config,
+	.get_ramsize = brcmf_sdio_bus_get_ramsize,
+	.get_memdump = brcmf_sdio_bus_get_memdump,
+	.get_fwname = brcmf_sdio_get_fwname,
+};
+
+#define BRCMF_SDIO_FW_CODE	0
+#define BRCMF_SDIO_FW_NVRAM	1
+
+static void brcmf_sdio_firmware_callback(struct device *dev, int err,
+					 struct brcmf_fw_request *fwreq)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_sdio_dev *sdiod = bus_if->bus_priv.sdio;
+	struct brcmf_sdio *bus = sdiod->bus;
+	struct brcmf_core *core = bus->sdio_core;
+	const struct firmware *code;
+	void *nvram;
+	u32 nvram_len;
+	u8 saveclk;
+
+	brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err);
+
+	if (err)
+		goto fail;
+
+	code = fwreq->items[BRCMF_SDIO_FW_CODE].binary;
+	nvram = fwreq->items[BRCMF_SDIO_FW_NVRAM].nv_data.data;
+	nvram_len = fwreq->items[BRCMF_SDIO_FW_NVRAM].nv_data.len;
+	kfree(fwreq);
+
+	/* try to download image and nvram to the dongle */
+	bus->alp_only = true;
+	err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len);
+	if (err)
+		goto fail;
+	bus->alp_only = false;
+
+	/* Start the watchdog timer */
+	bus->sdcnt.tickcnt = 0;
+	brcmf_sdio_wd_timer(bus, true);
+
+	sdio_claim_host(sdiod->func1);
+
+	/* Make sure backplane clock is on, needed to generate F2 interrupt */
+	brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
+	if (bus->clkstate != CLK_AVAIL)
+		goto release;
+
+	/* Force clocks on backplane to be sure F2 interrupt propagates */
+	saveclk = brcmf_sdiod_readb(sdiod, SBSDIO_FUNC1_CHIPCLKCSR, &err);
+	if (!err) {
+		brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_CHIPCLKCSR,
+				   (saveclk | SBSDIO_FORCE_HT), &err);
+	}
+	if (err) {
+		brcmf_err("Failed to force clock for F2: err %d\n", err);
+		goto release;
+	}
+
+	/* Enable function 2 (frame transfers) */
+	brcmf_sdiod_writel(sdiod, core->base + SD_REG(tosbmailboxdata),
+			   SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT, NULL);
+
+	err = sdio_enable_func(sdiod->func2);
+
+	brcmf_dbg(INFO, "enable F2: err=%d\n", err);
+
+	/* If F2 successfully enabled, set core and enable interrupts */
+	if (!err) {
+		/* Set up the interrupt mask and enable interrupts */
+		bus->hostintmask = HOSTINTMASK;
+		brcmf_sdiod_writel(sdiod, core->base + SD_REG(hostintmask),
+				   bus->hostintmask, NULL);
+
+
+		brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK, 8, &err);
+	} else {
+		/* Disable F2 again */
+		sdio_disable_func(sdiod->func2);
+		goto release;
+	}
+
+	if (brcmf_chip_sr_capable(bus->ci)) {
+		brcmf_sdio_sr_init(bus);
+	} else {
+		/* Restore previous clock setting */
+		brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_CHIPCLKCSR,
+				   saveclk, &err);
+	}
+
+	if (err == 0) {
+		/* Allow full data communication using DPC from now on. */
+		brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DATA);
+
+		err = brcmf_sdiod_intr_register(sdiod);
+		if (err != 0)
+			brcmf_err("intr register failed:%d\n", err);
+	}
+
+	/* If we didn't come up, turn off backplane clock */
+	if (err != 0)
+		brcmf_sdio_clkctl(bus, CLK_NONE, false);
+
+	sdio_release_host(sdiod->func1);
+
+	/* Assign bus interface call back */
+	sdiod->bus_if->dev = sdiod->dev;
+	sdiod->bus_if->ops = &brcmf_sdio_bus_ops;
+	sdiod->bus_if->chip = bus->ci->chip;
+	sdiod->bus_if->chiprev = bus->ci->chiprev;
+
+	/* Attach to the common layer, reserve hdr space */
+	err = brcmf_attach(sdiod->dev, sdiod->settings);
+	if (err != 0) {
+		brcmf_err("brcmf_attach failed\n");
+		goto fail;
+	}
+
+	/* ready */
+	return;
+
+release:
+	sdio_release_host(sdiod->func1);
+fail:
+	brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), err);
+	device_release_driver(&sdiod->func2->dev);
+	device_release_driver(dev);
+}
+
+static struct brcmf_fw_request *
+brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus)
+{
+	struct brcmf_fw_request *fwreq;
+	struct brcmf_fw_name fwnames[] = {
+		{ ".bin", bus->sdiodev->fw_name },
+		{ ".txt", bus->sdiodev->nvram_name },
+	};
+
+	fwreq = brcmf_fw_alloc_request(bus->ci->chip, bus->ci->chiprev,
+				       brcmf_sdio_fwnames,
+				       ARRAY_SIZE(brcmf_sdio_fwnames),
+				       fwnames, ARRAY_SIZE(fwnames));
+	if (!fwreq)
+		return NULL;
+
+	fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
+	fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
+
+	return fwreq;
+}
+
+struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
+{
+	int ret;
+	struct brcmf_sdio *bus;
+	struct workqueue_struct *wq;
+	struct brcmf_fw_request *fwreq;
+
+	brcmf_dbg(TRACE, "Enter\n");
+
+	/* Allocate private bus interface state */
+	bus = kzalloc(sizeof(struct brcmf_sdio), GFP_ATOMIC);
+	if (!bus)
+		goto fail;
+
+	bus->sdiodev = sdiodev;
+	sdiodev->bus = bus;
+	skb_queue_head_init(&bus->glom);
+	bus->txbound = BRCMF_TXBOUND;
+	bus->rxbound = BRCMF_RXBOUND;
+	bus->txminmax = BRCMF_TXMINMAX;
+	bus->tx_seq = SDPCM_SEQ_WRAP - 1;
+
+	/* single-threaded workqueue */
+	wq = alloc_ordered_workqueue("brcmf_wq/%s", WQ_MEM_RECLAIM,
+				     dev_name(&sdiodev->func1->dev));
+	if (!wq) {
+		brcmf_err("insufficient memory to create txworkqueue\n");
+		goto fail;
+	}
+	brcmf_sdiod_freezer_count(sdiodev);
+	INIT_WORK(&bus->datawork, brcmf_sdio_dataworker);
+	bus->brcmf_wq = wq;
+
+	/* attempt to attach to the dongle */
+	if (!(brcmf_sdio_probe_attach(bus))) {
+		brcmf_err("brcmf_sdio_probe_attach failed\n");
+		goto fail;
+	}
+
+	spin_lock_init(&bus->rxctl_lock);
+	spin_lock_init(&bus->txq_lock);
+	init_waitqueue_head(&bus->ctrl_wait);
+	init_waitqueue_head(&bus->dcmd_resp_wait);
+
+	/* Set up the watchdog timer */
+	timer_setup(&bus->timer, brcmf_sdio_watchdog, 0);
+	/* Initialize watchdog thread */
+	init_completion(&bus->watchdog_wait);
+	bus->watchdog_tsk = kthread_run(brcmf_sdio_watchdog_thread,
+					bus, "brcmf_wdog/%s",
+					dev_name(&sdiodev->func1->dev));
+	if (IS_ERR(bus->watchdog_tsk)) {
+		pr_warn("brcmf_watchdog thread failed to start\n");
+		bus->watchdog_tsk = NULL;
+	}
+	/* Initialize DPC thread */
+	bus->dpc_triggered = false;
+	bus->dpc_running = false;
+
+	/* default sdio bus header length for tx packet */
+	bus->tx_hdrlen = SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN;
+
+	/* Query the F2 block size, set roundup accordingly */
+	bus->blocksize = bus->sdiodev->func2->cur_blksize;
+	bus->roundup = min(max_roundup, bus->blocksize);
+
+	sdio_claim_host(bus->sdiodev->func1);
+
+	/* Disable F2 to clear any intermediate frame state on the dongle */
+	sdio_disable_func(bus->sdiodev->func2);
+
+	bus->rxflow = false;
+
+	/* Done with backplane-dependent accesses, can drop clock... */
+	brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
+
+	sdio_release_host(bus->sdiodev->func1);
+
+	/* ...and initialize clock/power states */
+	bus->clkstate = CLK_SDONLY;
+	bus->idletime = BRCMF_IDLE_INTERVAL;
+	bus->idleclock = BRCMF_IDLE_ACTIVE;
+
+	/* SR state */
+	bus->sr_enabled = false;
+
+	brcmf_dbg(INFO, "completed!!\n");
+
+	fwreq = brcmf_sdio_prepare_fw_request(bus);
+	if (!fwreq) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	ret = brcmf_fw_get_firmwares(sdiodev->dev, fwreq,
+				     brcmf_sdio_firmware_callback);
+	if (ret != 0) {
+		brcmf_err("async firmware request failed: %d\n", ret);
+		kfree(fwreq);
+		goto fail;
+	}
+
+	return bus;
+
+fail:
+	brcmf_sdio_remove(bus);
+	return NULL;
+}
+
+/* Detach and free everything */
+void brcmf_sdio_remove(struct brcmf_sdio *bus)
+{
+	brcmf_dbg(TRACE, "Enter\n");
+
+	if (bus) {
+		/* Stop watchdog task */
+		if (bus->watchdog_tsk) {
+			send_sig(SIGTERM, bus->watchdog_tsk, 1);
+			kthread_stop(bus->watchdog_tsk);
+			bus->watchdog_tsk = NULL;
+		}
+
+		/* De-register interrupt handler */
+		brcmf_sdiod_intr_unregister(bus->sdiodev);
+
+		brcmf_detach(bus->sdiodev->dev);
+
+		cancel_work_sync(&bus->datawork);
+		if (bus->brcmf_wq)
+			destroy_workqueue(bus->brcmf_wq);
+
+		if (bus->ci) {
+			if (bus->sdiodev->state != BRCMF_SDIOD_NOMEDIUM) {
+				sdio_claim_host(bus->sdiodev->func1);
+				brcmf_sdio_wd_timer(bus, false);
+				brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
+				/* Leave the device in state where it is
+				 * 'passive'. This is done by resetting all
+				 * necessary cores.
+				 */
+				msleep(20);
+				brcmf_chip_set_passive(bus->ci);
+				brcmf_sdio_clkctl(bus, CLK_NONE, false);
+				sdio_release_host(bus->sdiodev->func1);
+			}
+			brcmf_chip_detach(bus->ci);
+		}
+		if (bus->sdiodev->settings)
+			brcmf_release_module_param(bus->sdiodev->settings);
+
+		kfree(bus->rxbuf);
+		kfree(bus->hdrbuf);
+		kfree(bus);
+	}
+
+	brcmf_dbg(TRACE, "Disconnected\n");
+}
+
+void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, bool active)
+{
+	/* Totally stop the timer */
+	if (!active && bus->wd_active) {
+		del_timer_sync(&bus->timer);
+		bus->wd_active = false;
+		return;
+	}
+
+	/* don't start the wd until fw is loaded */
+	if (bus->sdiodev->state != BRCMF_SDIOD_DATA)
+		return;
+
+	if (active) {
+		if (!bus->wd_active) {
+			/* Create timer again when watchdog period is
+			   dynamically changed or in the first instance
+			 */
+			bus->timer.expires = jiffies + BRCMF_WD_POLL;
+			add_timer(&bus->timer);
+			bus->wd_active = true;
+		} else {
+			/* Re arm the timer, at last watchdog period */
+			mod_timer(&bus->timer, jiffies + BRCMF_WD_POLL);
+		}
+	}
+}
+
+int brcmf_sdio_sleep(struct brcmf_sdio *bus, bool sleep)
+{
+	int ret;
+
+	sdio_claim_host(bus->sdiodev->func1);
+	ret = brcmf_sdio_bus_sleep(bus, sleep, false);
+	sdio_release_host(bus->sdiodev->func1);
+
+	return ret;
+}
+
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
new file mode 100644
index 0000000..7faed83
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	BRCMFMAC_SDIO_H
+#define	BRCMFMAC_SDIO_H
+
+#include <linux/skbuff.h>
+#include <linux/firmware.h>
+#include "firmware.h"
+
+#define SDIOD_FBR_SIZE		0x100
+
+/* io_en */
+#define SDIO_FUNC_ENABLE_1	0x02
+#define SDIO_FUNC_ENABLE_2	0x04
+
+/* io_rdys */
+#define SDIO_FUNC_READY_1	0x02
+#define SDIO_FUNC_READY_2	0x04
+
+/* intr_status */
+#define INTR_STATUS_FUNC1	0x2
+#define INTR_STATUS_FUNC2	0x4
+
+/* mask of register map */
+#define REG_F0_REG_MASK		0x7FF
+#define REG_F1_MISC_MASK	0x1FFFF
+
+/* function 0 vendor specific CCCR registers */
+
+#define SDIO_CCCR_BRCM_CARDCAP			0xf0
+#define SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT	BIT(1)
+#define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT	BIT(2)
+#define SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC	BIT(3)
+
+/* Interrupt enable bits for each function */
+#define SDIO_CCCR_IEN_FUNC0			BIT(0)
+#define SDIO_CCCR_IEN_FUNC1			BIT(1)
+#define SDIO_CCCR_IEN_FUNC2			BIT(2)
+
+#define SDIO_CCCR_BRCM_CARDCTRL			0xf1
+#define SDIO_CCCR_BRCM_CARDCTRL_WLANRESET	BIT(1)
+
+#define SDIO_CCCR_BRCM_SEPINT			0xf2
+#define SDIO_CCCR_BRCM_SEPINT_MASK		BIT(0)
+#define SDIO_CCCR_BRCM_SEPINT_OE		BIT(1)
+#define SDIO_CCCR_BRCM_SEPINT_ACT_HI		BIT(2)
+
+/* function 1 miscellaneous registers */
+
+/* sprom command and status */
+#define SBSDIO_SPROM_CS			0x10000
+/* sprom info register */
+#define SBSDIO_SPROM_INFO		0x10001
+/* sprom indirect access data byte 0 */
+#define SBSDIO_SPROM_DATA_LOW		0x10002
+/* sprom indirect access data byte 1 */
+#define SBSDIO_SPROM_DATA_HIGH		0x10003
+/* sprom indirect access addr byte 0 */
+#define SBSDIO_SPROM_ADDR_LOW		0x10004
+/* gpio select */
+#define SBSDIO_GPIO_SELECT		0x10005
+/* gpio output */
+#define SBSDIO_GPIO_OUT			0x10006
+/* gpio enable */
+#define SBSDIO_GPIO_EN			0x10007
+/* rev < 7, watermark for sdio device */
+#define SBSDIO_WATERMARK		0x10008
+/* control busy signal generation */
+#define SBSDIO_DEVICE_CTL		0x10009
+
+/* SB Address Window Low (b15) */
+#define SBSDIO_FUNC1_SBADDRLOW		0x1000A
+/* SB Address Window Mid (b23:b16) */
+#define SBSDIO_FUNC1_SBADDRMID		0x1000B
+/* SB Address Window High (b31:b24)    */
+#define SBSDIO_FUNC1_SBADDRHIGH		0x1000C
+/* Frame Control (frame term/abort) */
+#define SBSDIO_FUNC1_FRAMECTRL		0x1000D
+/* ChipClockCSR (ALP/HT ctl/status) */
+#define SBSDIO_FUNC1_CHIPCLKCSR		0x1000E
+/* SdioPullUp (on cmd, d0-d2) */
+#define SBSDIO_FUNC1_SDIOPULLUP		0x1000F
+/* Write Frame Byte Count Low */
+#define SBSDIO_FUNC1_WFRAMEBCLO		0x10019
+/* Write Frame Byte Count High */
+#define SBSDIO_FUNC1_WFRAMEBCHI		0x1001A
+/* Read Frame Byte Count Low */
+#define SBSDIO_FUNC1_RFRAMEBCLO		0x1001B
+/* Read Frame Byte Count High */
+#define SBSDIO_FUNC1_RFRAMEBCHI		0x1001C
+/* MesBusyCtl (rev 11) */
+#define SBSDIO_FUNC1_MESBUSYCTRL	0x1001D
+/* Sdio Core Rev 12 */
+#define SBSDIO_FUNC1_WAKEUPCTRL		0x1001E
+#define SBSDIO_FUNC1_WCTRL_ALPWAIT_MASK		0x1
+#define SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT	0
+#define SBSDIO_FUNC1_WCTRL_HTWAIT_MASK		0x2
+#define SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT		1
+#define SBSDIO_FUNC1_SLEEPCSR		0x1001F
+#define SBSDIO_FUNC1_SLEEPCSR_KSO_MASK		0x1
+#define SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT		0
+#define SBSDIO_FUNC1_SLEEPCSR_KSO_EN		1
+#define SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK	0x2
+#define SBSDIO_FUNC1_SLEEPCSR_DEVON_SHIFT	1
+
+#define SBSDIO_FUNC1_MISC_REG_START	0x10000	/* f1 misc register start */
+#define SBSDIO_FUNC1_MISC_REG_LIMIT	0x1001F	/* f1 misc register end */
+
+/* function 1 OCP space */
+
+/* sb offset addr is <= 15 bits, 32k */
+#define SBSDIO_SB_OFT_ADDR_MASK		0x07FFF
+#define SBSDIO_SB_OFT_ADDR_LIMIT	0x08000
+/* with b15, maps to 32-bit SB access */
+#define SBSDIO_SB_ACCESS_2_4B_FLAG	0x08000
+
+/* Address bits from SBADDR regs */
+#define SBSDIO_SBWINDOW_MASK		0xffff8000
+
+#define SDIOH_READ              0	/* Read request */
+#define SDIOH_WRITE             1	/* Write request */
+
+#define SDIOH_DATA_FIX          0	/* Fixed addressing */
+#define SDIOH_DATA_INC          1	/* Incremental addressing */
+
+/* internal return code */
+#define SUCCESS	0
+#define ERROR	1
+
+/* Packet alignment for most efficient SDIO (can change based on platform) */
+#define BRCMF_SDALIGN	(1 << 6)
+
+/* watchdog polling interval */
+#define BRCMF_WD_POLL	msecs_to_jiffies(10)
+
+/**
+ * enum brcmf_sdiod_state - the state of the bus.
+ *
+ * @BRCMF_SDIOD_DOWN: Device can be accessed, no DPC.
+ * @BRCMF_SDIOD_DATA: Ready for data transfers, DPC enabled.
+ * @BRCMF_SDIOD_NOMEDIUM: No medium access to dongle possible.
+ */
+enum brcmf_sdiod_state {
+	BRCMF_SDIOD_DOWN,
+	BRCMF_SDIOD_DATA,
+	BRCMF_SDIOD_NOMEDIUM
+};
+
+struct brcmf_sdreg {
+	int func;
+	int offset;
+	int value;
+};
+
+struct brcmf_sdio;
+struct brcmf_sdiod_freezer;
+
+struct brcmf_sdio_dev {
+	struct sdio_func *func1;
+	struct sdio_func *func2;
+	u32 sbwad;			/* Save backplane window address */
+	struct brcmf_core *cc_core;	/* chipcommon core info struct */
+	struct brcmf_sdio *bus;
+	struct device *dev;
+	struct brcmf_bus *bus_if;
+	struct brcmf_mp_device *settings;
+	bool oob_irq_requested;
+	bool sd_irq_requested;
+	bool irq_en;			/* irq enable flags */
+	spinlock_t irq_en_lock;
+	bool irq_wake;			/* irq wake enable flags */
+	bool sg_support;
+	uint max_request_size;
+	ushort max_segment_count;
+	uint max_segment_size;
+	uint txglomsz;
+	struct sg_table sgtable;
+	char fw_name[BRCMF_FW_NAME_LEN];
+	char nvram_name[BRCMF_FW_NAME_LEN];
+	bool wowl_enabled;
+	enum brcmf_sdiod_state state;
+	struct brcmf_sdiod_freezer *freezer;
+};
+
+/* sdio core registers */
+struct sdpcmd_regs {
+	u32 corecontrol;		/* 0x00, rev8 */
+	u32 corestatus;			/* rev8 */
+	u32 PAD[1];
+	u32 biststatus;			/* rev8 */
+
+	/* PCMCIA access */
+	u16 pcmciamesportaladdr;	/* 0x010, rev8 */
+	u16 PAD[1];
+	u16 pcmciamesportalmask;	/* rev8 */
+	u16 PAD[1];
+	u16 pcmciawrframebc;		/* rev8 */
+	u16 PAD[1];
+	u16 pcmciaunderflowtimer;	/* rev8 */
+	u16 PAD[1];
+
+	/* interrupt */
+	u32 intstatus;			/* 0x020, rev8 */
+	u32 hostintmask;		/* rev8 */
+	u32 intmask;			/* rev8 */
+	u32 sbintstatus;		/* rev8 */
+	u32 sbintmask;			/* rev8 */
+	u32 funcintmask;		/* rev4 */
+	u32 PAD[2];
+	u32 tosbmailbox;		/* 0x040, rev8 */
+	u32 tohostmailbox;		/* rev8 */
+	u32 tosbmailboxdata;		/* rev8 */
+	u32 tohostmailboxdata;		/* rev8 */
+
+	/* synchronized access to registers in SDIO clock domain */
+	u32 sdioaccess;			/* 0x050, rev8 */
+	u32 PAD[3];
+
+	/* PCMCIA frame control */
+	u8 pcmciaframectrl;		/* 0x060, rev8 */
+	u8 PAD[3];
+	u8 pcmciawatermark;		/* rev8 */
+	u8 PAD[155];
+
+	/* interrupt batching control */
+	u32 intrcvlazy;			/* 0x100, rev8 */
+	u32 PAD[3];
+
+	/* counters */
+	u32 cmd52rd;			/* 0x110, rev8 */
+	u32 cmd52wr;			/* rev8 */
+	u32 cmd53rd;			/* rev8 */
+	u32 cmd53wr;			/* rev8 */
+	u32 abort;			/* rev8 */
+	u32 datacrcerror;		/* rev8 */
+	u32 rdoutofsync;		/* rev8 */
+	u32 wroutofsync;		/* rev8 */
+	u32 writebusy;			/* rev8 */
+	u32 readwait;			/* rev8 */
+	u32 readterm;			/* rev8 */
+	u32 writeterm;			/* rev8 */
+	u32 PAD[40];
+	u32 clockctlstatus;		/* rev8 */
+	u32 PAD[7];
+
+	u32 PAD[128];			/* DMA engines */
+
+	/* SDIO/PCMCIA CIS region */
+	char cis[512];			/* 0x400-0x5ff, rev6 */
+
+	/* PCMCIA function control registers */
+	char pcmciafcr[256];		/* 0x600-6ff, rev6 */
+	u16 PAD[55];
+
+	/* PCMCIA backplane access */
+	u16 backplanecsr;		/* 0x76E, rev6 */
+	u16 backplaneaddr0;		/* rev6 */
+	u16 backplaneaddr1;		/* rev6 */
+	u16 backplaneaddr2;		/* rev6 */
+	u16 backplaneaddr3;		/* rev6 */
+	u16 backplanedata0;		/* rev6 */
+	u16 backplanedata1;		/* rev6 */
+	u16 backplanedata2;		/* rev6 */
+	u16 backplanedata3;		/* rev6 */
+	u16 PAD[31];
+
+	/* sprom "size" & "blank" info */
+	u16 spromstatus;		/* 0x7BE, rev2 */
+	u32 PAD[464];
+
+	u16 PAD[0x80];
+};
+
+/* Register/deregister interrupt handler. */
+int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev);
+void brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev);
+
+/* SDIO device register access interface */
+/* Accessors for SDIO Function 0 */
+#define brcmf_sdiod_func0_rb(sdiodev, addr, r) \
+	sdio_f0_readb((sdiodev)->func1, (addr), (r))
+
+#define brcmf_sdiod_func0_wb(sdiodev, addr, v, ret) \
+	sdio_f0_writeb((sdiodev)->func1, (v), (addr), (ret))
+
+/* Accessors for SDIO Function 1 */
+#define brcmf_sdiod_readb(sdiodev, addr, r) \
+	sdio_readb((sdiodev)->func1, (addr), (r))
+
+#define brcmf_sdiod_writeb(sdiodev, addr, v, ret) \
+	sdio_writeb((sdiodev)->func1, (v), (addr), (ret))
+
+u32 brcmf_sdiod_readl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
+void brcmf_sdiod_writel(struct brcmf_sdio_dev *sdiodev, u32 addr, u32 data,
+			int *ret);
+
+/* Buffer transfer to/from device (client) core via cmd53.
+ *   fn:       function number
+ *   flags:    backplane width, address increment, sync/async
+ *   buf:      pointer to memory data buffer
+ *   nbytes:   number of bytes to transfer to/from buf
+ *   pkt:      pointer to packet associated with buf (if any)
+ *   complete: callback function for command completion (async only)
+ *   handle:   handle for completion callback (first arg in callback)
+ * Returns 0 or error code.
+ * NOTE: Async operation is not currently supported.
+ */
+int brcmf_sdiod_send_pkt(struct brcmf_sdio_dev *sdiodev,
+			 struct sk_buff_head *pktq);
+int brcmf_sdiod_send_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes);
+
+int brcmf_sdiod_recv_pkt(struct brcmf_sdio_dev *sdiodev, struct sk_buff *pkt);
+int brcmf_sdiod_recv_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes);
+int brcmf_sdiod_recv_chain(struct brcmf_sdio_dev *sdiodev,
+			   struct sk_buff_head *pktq, uint totlen);
+
+/* Flags bits */
+
+/* Four-byte target (backplane) width (vs. two-byte) */
+#define SDIO_REQ_4BYTE	0x1
+/* Fixed address (FIFO) (vs. incrementing address) */
+#define SDIO_REQ_FIXED	0x2
+
+/* Read/write to memory block (F1, no FIFO) via CMD53 (sync only).
+ *   rw:       read or write (0/1)
+ *   addr:     direct SDIO address
+ *   buf:      pointer to memory data buffer
+ *   nbytes:   number of bytes to transfer to/from buf
+ * Returns 0 or error code.
+ */
+int brcmf_sdiod_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
+		      u8 *data, uint size);
+
+/* Issue an abort to the specified function */
+int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, struct sdio_func *func);
+
+void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev);
+void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev,
+			      enum brcmf_sdiod_state state);
+#ifdef CONFIG_PM_SLEEP
+bool brcmf_sdiod_freezing(struct brcmf_sdio_dev *sdiodev);
+void brcmf_sdiod_try_freeze(struct brcmf_sdio_dev *sdiodev);
+void brcmf_sdiod_freezer_count(struct brcmf_sdio_dev *sdiodev);
+void brcmf_sdiod_freezer_uncount(struct brcmf_sdio_dev *sdiodev);
+#else
+static inline bool brcmf_sdiod_freezing(struct brcmf_sdio_dev *sdiodev)
+{
+	return false;
+}
+static inline void brcmf_sdiod_try_freeze(struct brcmf_sdio_dev *sdiodev)
+{
+}
+static inline void brcmf_sdiod_freezer_count(struct brcmf_sdio_dev *sdiodev)
+{
+}
+static inline void brcmf_sdiod_freezer_uncount(struct brcmf_sdio_dev *sdiodev)
+{
+}
+#endif /* CONFIG_PM_SLEEP */
+
+struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev);
+void brcmf_sdio_remove(struct brcmf_sdio *bus);
+void brcmf_sdio_isr(struct brcmf_sdio *bus);
+
+void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, bool active);
+void brcmf_sdio_wowl_config(struct device *dev, bool enabled);
+int brcmf_sdio_sleep(struct brcmf_sdio *bus, bool sleep);
+void brcmf_sdio_trigger_dpc(struct brcmf_sdio *bus);
+
+#endif /* BRCMFMAC_SDIO_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.c
new file mode 100644
index 0000000..fe67559
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/module.h> /* bug in tracepoint.h, it should include this */
+
+#ifndef __CHECKER__
+#define CREATE_TRACE_POINTS
+#include "tracepoint.h"
+#include "debug.h"
+
+void __brcmf_err(const char *func, const char *fmt, ...)
+{
+	struct va_format vaf = {
+		.fmt = fmt,
+	};
+	va_list args;
+
+	va_start(args, fmt);
+	vaf.va = &args;
+	pr_err("%s: %pV", func, &vaf);
+	trace_brcmf_err(func, &vaf);
+	va_end(args);
+}
+
+#endif
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.h
new file mode 100644
index 0000000..4d7d51f
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2013 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#if !defined(BRCMF_TRACEPOINT_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define BRCMF_TRACEPOINT_H_
+
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+
+#ifndef CONFIG_BRCM_TRACING
+
+#undef TRACE_EVENT
+#define TRACE_EVENT(name, proto, ...) \
+static inline void trace_ ## name(proto) {}
+
+#undef DECLARE_EVENT_CLASS
+#define DECLARE_EVENT_CLASS(...)
+
+#undef DEFINE_EVENT
+#define DEFINE_EVENT(evt_class, name, proto, ...) \
+static inline void trace_ ## name(proto) {}
+
+#endif /* CONFIG_BRCM_TRACING */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM	brcmfmac
+
+#define MAX_MSG_LEN		100
+
+TRACE_EVENT(brcmf_err,
+	TP_PROTO(const char *func, struct va_format *vaf),
+	TP_ARGS(func, vaf),
+	TP_STRUCT__entry(
+		__string(func, func)
+		__dynamic_array(char, msg, MAX_MSG_LEN)
+	),
+	TP_fast_assign(
+		__assign_str(func, func);
+		WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
+				       MAX_MSG_LEN, vaf->fmt,
+				       *vaf->va) >= MAX_MSG_LEN);
+	),
+	TP_printk("%s: %s", __get_str(func), __get_str(msg))
+);
+
+TRACE_EVENT(brcmf_dbg,
+	TP_PROTO(u32 level, const char *func, struct va_format *vaf),
+	TP_ARGS(level, func, vaf),
+	TP_STRUCT__entry(
+		__field(u32, level)
+		__string(func, func)
+		__dynamic_array(char, msg, MAX_MSG_LEN)
+	),
+	TP_fast_assign(
+		__entry->level = level;
+		__assign_str(func, func);
+		WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
+				       MAX_MSG_LEN, vaf->fmt,
+				       *vaf->va) >= MAX_MSG_LEN);
+	),
+	TP_printk("%s: %s", __get_str(func), __get_str(msg))
+);
+
+TRACE_EVENT(brcmf_hexdump,
+	TP_PROTO(void *data, size_t len),
+	TP_ARGS(data, len),
+	TP_STRUCT__entry(
+		__field(unsigned long, len)
+		__field(unsigned long, addr)
+		__dynamic_array(u8, hdata, len)
+	),
+	TP_fast_assign(
+		__entry->len = len;
+		__entry->addr = (unsigned long)data;
+		memcpy(__get_dynamic_array(hdata), data, len);
+	),
+	TP_printk("hexdump [addr=%lx, length=%lu]", __entry->addr, __entry->len)
+);
+
+TRACE_EVENT(brcmf_bcdchdr,
+	TP_PROTO(void *data),
+	TP_ARGS(data),
+	TP_STRUCT__entry(
+		__field(u8, flags)
+		__field(u8, prio)
+		__field(u8, flags2)
+		__field(u32, siglen)
+		__dynamic_array(u8, signal, *((u8 *)data + 3) * 4)
+	),
+	TP_fast_assign(
+		__entry->flags = *(u8 *)data;
+		__entry->prio = *((u8 *)data + 1);
+		__entry->flags2 = *((u8 *)data + 2);
+		__entry->siglen = *((u8 *)data + 3) * 4;
+		memcpy(__get_dynamic_array(signal),
+		       (u8 *)data + 4, __entry->siglen);
+	),
+	TP_printk("bcdc: prio=%d siglen=%d", __entry->prio, __entry->siglen)
+);
+
+#ifndef SDPCM_RX
+#define SDPCM_RX	0
+#endif
+#ifndef SDPCM_TX
+#define SDPCM_TX	1
+#endif
+#ifndef SDPCM_GLOM
+#define SDPCM_GLOM	2
+#endif
+
+TRACE_EVENT(brcmf_sdpcm_hdr,
+	TP_PROTO(u8 dir, void *data),
+	TP_ARGS(dir, data),
+	TP_STRUCT__entry(
+		__field(u8, dir)
+		__field(u16, len)
+		__dynamic_array(u8, hdr, dir == SDPCM_GLOM ? 20 : 12)
+	),
+	TP_fast_assign(
+		memcpy(__get_dynamic_array(hdr), data, dir == SDPCM_GLOM ? 20 : 12);
+		__entry->len = *(u8 *)data | (*((u8 *)data + 1) << 8);
+		__entry->dir = dir;
+	),
+	TP_printk("sdpcm: %s len %u, seq %d",
+		  __entry->dir == SDPCM_RX ? "RX" : "TX",
+		  __entry->len, ((u8 *)__get_dynamic_array(hdr))[4])
+);
+
+#ifdef CONFIG_BRCM_TRACING
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE tracepoint
+
+#include <trace/define_trace.h>
+
+#endif /* CONFIG_BRCM_TRACING */
+
+#endif /* BRCMF_TRACEPOINT_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
new file mode 100644
index 0000000..a4308c6
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
@@ -0,0 +1,1555 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/firmware.h>
+#include <linux/usb.h>
+#include <linux/vmalloc.h>
+
+#include <brcmu_utils.h>
+#include <brcm_hw_ids.h>
+#include <brcmu_wifi.h>
+#include "bus.h"
+#include "debug.h"
+#include "firmware.h"
+#include "usb.h"
+#include "core.h"
+#include "common.h"
+#include "bcdc.h"
+
+
+#define IOCTL_RESP_TIMEOUT		msecs_to_jiffies(2000)
+
+#define BRCMF_USB_RESET_GETVER_SPINWAIT	100	/* in unit of ms */
+#define BRCMF_USB_RESET_GETVER_LOOP_CNT	10
+
+#define BRCMF_POSTBOOT_ID		0xA123  /* ID to detect if dongle
+						   has boot up */
+#define BRCMF_USB_NRXQ			50
+#define BRCMF_USB_NTXQ			50
+
+#define BRCMF_USB_CBCTL_WRITE		0
+#define BRCMF_USB_CBCTL_READ		1
+#define BRCMF_USB_MAX_PKT_SIZE		1600
+
+BRCMF_FW_DEF(43143, "brcmfmac43143");
+BRCMF_FW_DEF(43236B, "brcmfmac43236b");
+BRCMF_FW_DEF(43242A, "brcmfmac43242a");
+BRCMF_FW_DEF(43569, "brcmfmac43569");
+BRCMF_FW_DEF(4373, "brcmfmac4373");
+
+static const struct brcmf_firmware_mapping brcmf_usb_fwnames[] = {
+	BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143),
+	BRCMF_FW_ENTRY(BRCM_CC_43235_CHIP_ID, 0x00000008, 43236B),
+	BRCMF_FW_ENTRY(BRCM_CC_43236_CHIP_ID, 0x00000008, 43236B),
+	BRCMF_FW_ENTRY(BRCM_CC_43238_CHIP_ID, 0x00000008, 43236B),
+	BRCMF_FW_ENTRY(BRCM_CC_43242_CHIP_ID, 0xFFFFFFFF, 43242A),
+	BRCMF_FW_ENTRY(BRCM_CC_43566_CHIP_ID, 0xFFFFFFFF, 43569),
+	BRCMF_FW_ENTRY(BRCM_CC_43569_CHIP_ID, 0xFFFFFFFF, 43569),
+	BRCMF_FW_ENTRY(CY_CC_4373_CHIP_ID, 0xFFFFFFFF, 4373)
+};
+
+#define TRX_MAGIC		0x30524448	/* "HDR0" */
+#define TRX_MAX_OFFSET		3		/* Max number of file offsets */
+#define TRX_UNCOMP_IMAGE	0x20		/* Trx holds uncompressed img */
+#define TRX_RDL_CHUNK		1500		/* size of each dl transfer */
+#define TRX_OFFSETS_DLFWLEN_IDX	0
+
+/* Control messages: bRequest values */
+#define DL_GETSTATE	0	/* returns the rdl_state_t struct */
+#define DL_CHECK_CRC	1	/* currently unused */
+#define DL_GO		2	/* execute downloaded image */
+#define DL_START	3	/* initialize dl state */
+#define DL_REBOOT	4	/* reboot the device in 2 seconds */
+#define DL_GETVER	5	/* returns the bootrom_id_t struct */
+#define DL_GO_PROTECTED	6	/* execute the downloaded code and set reset
+				 * event to occur in 2 seconds.  It is the
+				 * responsibility of the downloaded code to
+				 * clear this event
+				 */
+#define DL_EXEC		7	/* jump to a supplied address */
+#define DL_RESETCFG	8	/* To support single enum on dongle
+				 * - Not used by bootloader
+				 */
+#define DL_DEFER_RESP_OK 9	/* Potentially defer the response to setup
+				 * if resp unavailable
+				 */
+
+/* states */
+#define DL_WAITING	0	/* waiting to rx first pkt */
+#define DL_READY	1	/* hdr was good, waiting for more of the
+				 * compressed image
+				 */
+#define DL_BAD_HDR	2	/* hdr was corrupted */
+#define DL_BAD_CRC	3	/* compressed image was corrupted */
+#define DL_RUNNABLE	4	/* download was successful,waiting for go cmd */
+#define DL_START_FAIL	5	/* failed to initialize correctly */
+#define DL_NVRAM_TOOBIG	6	/* host specified nvram data exceeds DL_NVRAM
+				 * value
+				 */
+#define DL_IMAGE_TOOBIG	7	/* firmware image too big */
+
+
+struct trx_header_le {
+	__le32 magic;		/* "HDR0" */
+	__le32 len;		/* Length of file including header */
+	__le32 crc32;		/* CRC from flag_version to end of file */
+	__le32 flag_version;	/* 0:15 flags, 16:31 version */
+	__le32 offsets[TRX_MAX_OFFSET];	/* Offsets of partitions from start of
+					 * header
+					 */
+};
+
+struct rdl_state_le {
+	__le32 state;
+	__le32 bytes;
+};
+
+struct bootrom_id_le {
+	__le32 chip;		/* Chip id */
+	__le32 chiprev;		/* Chip rev */
+	__le32 ramsize;		/* Size of  RAM */
+	__le32 remapbase;	/* Current remap base address */
+	__le32 boardtype;	/* Type of board */
+	__le32 boardrev;	/* Board revision */
+};
+
+struct brcmf_usb_image {
+	struct list_head list;
+	s8 *fwname;
+	u8 *image;
+	int image_len;
+};
+
+struct brcmf_usbdev_info {
+	struct brcmf_usbdev bus_pub; /* MUST BE FIRST */
+	spinlock_t qlock;
+	struct list_head rx_freeq;
+	struct list_head rx_postq;
+	struct list_head tx_freeq;
+	struct list_head tx_postq;
+	uint rx_pipe, tx_pipe;
+
+	int rx_low_watermark;
+	int tx_low_watermark;
+	int tx_high_watermark;
+	int tx_freecount;
+	bool tx_flowblock;
+	spinlock_t tx_flowblock_lock;
+
+	struct brcmf_usbreq *tx_reqs;
+	struct brcmf_usbreq *rx_reqs;
+
+	char fw_name[BRCMF_FW_NAME_LEN];
+	const u8 *image;	/* buffer for combine fw and nvram */
+	int image_len;
+
+	struct usb_device *usbdev;
+	struct device *dev;
+	struct mutex dev_init_lock;
+
+	int ctl_in_pipe, ctl_out_pipe;
+	struct urb *ctl_urb; /* URB for control endpoint */
+	struct usb_ctrlrequest ctl_write;
+	struct usb_ctrlrequest ctl_read;
+	u32 ctl_urb_actual_length;
+	int ctl_urb_status;
+	int ctl_completed;
+	wait_queue_head_t ioctl_resp_wait;
+	ulong ctl_op;
+	u8 ifnum;
+
+	struct urb *bulk_urb; /* used for FW download */
+
+	bool wowl_enabled;
+	struct brcmf_mp_device *settings;
+};
+
+static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
+				struct brcmf_usbreq  *req);
+
+static struct brcmf_usbdev *brcmf_usb_get_buspub(struct device *dev)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	return bus_if->bus_priv.usb;
+}
+
+static struct brcmf_usbdev_info *brcmf_usb_get_businfo(struct device *dev)
+{
+	return brcmf_usb_get_buspub(dev)->devinfo;
+}
+
+static int brcmf_usb_ioctl_resp_wait(struct brcmf_usbdev_info *devinfo)
+{
+	return wait_event_timeout(devinfo->ioctl_resp_wait,
+				  devinfo->ctl_completed, IOCTL_RESP_TIMEOUT);
+}
+
+static void brcmf_usb_ioctl_resp_wake(struct brcmf_usbdev_info *devinfo)
+{
+	wake_up(&devinfo->ioctl_resp_wait);
+}
+
+static void
+brcmf_usb_ctl_complete(struct brcmf_usbdev_info *devinfo, int type, int status)
+{
+	brcmf_dbg(USB, "Enter, status=%d\n", status);
+
+	if (unlikely(devinfo == NULL))
+		return;
+
+	if (type == BRCMF_USB_CBCTL_READ) {
+		if (status == 0)
+			devinfo->bus_pub.stats.rx_ctlpkts++;
+		else
+			devinfo->bus_pub.stats.rx_ctlerrs++;
+	} else if (type == BRCMF_USB_CBCTL_WRITE) {
+		if (status == 0)
+			devinfo->bus_pub.stats.tx_ctlpkts++;
+		else
+			devinfo->bus_pub.stats.tx_ctlerrs++;
+	}
+
+	devinfo->ctl_urb_status = status;
+	devinfo->ctl_completed = true;
+	brcmf_usb_ioctl_resp_wake(devinfo);
+}
+
+static void
+brcmf_usb_ctlread_complete(struct urb *urb)
+{
+	struct brcmf_usbdev_info *devinfo =
+		(struct brcmf_usbdev_info *)urb->context;
+
+	brcmf_dbg(USB, "Enter\n");
+	devinfo->ctl_urb_actual_length = urb->actual_length;
+	brcmf_usb_ctl_complete(devinfo, BRCMF_USB_CBCTL_READ,
+		urb->status);
+}
+
+static void
+brcmf_usb_ctlwrite_complete(struct urb *urb)
+{
+	struct brcmf_usbdev_info *devinfo =
+		(struct brcmf_usbdev_info *)urb->context;
+
+	brcmf_dbg(USB, "Enter\n");
+	brcmf_usb_ctl_complete(devinfo, BRCMF_USB_CBCTL_WRITE,
+		urb->status);
+}
+
+static int
+brcmf_usb_send_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len)
+{
+	int ret;
+	u16 size;
+
+	brcmf_dbg(USB, "Enter\n");
+	if (devinfo == NULL || buf == NULL ||
+	    len == 0 || devinfo->ctl_urb == NULL)
+		return -EINVAL;
+
+	size = len;
+	devinfo->ctl_write.wLength = cpu_to_le16p(&size);
+	devinfo->ctl_urb->transfer_buffer_length = size;
+	devinfo->ctl_urb_status = 0;
+	devinfo->ctl_urb_actual_length = 0;
+
+	usb_fill_control_urb(devinfo->ctl_urb,
+		devinfo->usbdev,
+		devinfo->ctl_out_pipe,
+		(unsigned char *) &devinfo->ctl_write,
+		buf, size,
+		(usb_complete_t)brcmf_usb_ctlwrite_complete,
+		devinfo);
+
+	ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC);
+	if (ret < 0)
+		brcmf_err("usb_submit_urb failed %d\n", ret);
+
+	return ret;
+}
+
+static int
+brcmf_usb_recv_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len)
+{
+	int ret;
+	u16 size;
+
+	brcmf_dbg(USB, "Enter\n");
+	if ((devinfo == NULL) || (buf == NULL) || (len == 0)
+		|| (devinfo->ctl_urb == NULL))
+		return -EINVAL;
+
+	size = len;
+	devinfo->ctl_read.wLength = cpu_to_le16p(&size);
+	devinfo->ctl_urb->transfer_buffer_length = size;
+
+	devinfo->ctl_read.bRequestType = USB_DIR_IN
+		| USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+	devinfo->ctl_read.bRequest = 1;
+
+	usb_fill_control_urb(devinfo->ctl_urb,
+		devinfo->usbdev,
+		devinfo->ctl_in_pipe,
+		(unsigned char *) &devinfo->ctl_read,
+		buf, size,
+		(usb_complete_t)brcmf_usb_ctlread_complete,
+		devinfo);
+
+	ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC);
+	if (ret < 0)
+		brcmf_err("usb_submit_urb failed %d\n", ret);
+
+	return ret;
+}
+
+static int brcmf_usb_tx_ctlpkt(struct device *dev, u8 *buf, u32 len)
+{
+	int err = 0;
+	int timeout = 0;
+	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
+
+	brcmf_dbg(USB, "Enter\n");
+	if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP)
+		return -EIO;
+
+	if (test_and_set_bit(0, &devinfo->ctl_op))
+		return -EIO;
+
+	devinfo->ctl_completed = false;
+	err = brcmf_usb_send_ctl(devinfo, buf, len);
+	if (err) {
+		brcmf_err("fail %d bytes: %d\n", err, len);
+		clear_bit(0, &devinfo->ctl_op);
+		return err;
+	}
+	timeout = brcmf_usb_ioctl_resp_wait(devinfo);
+	clear_bit(0, &devinfo->ctl_op);
+	if (!timeout) {
+		brcmf_err("Txctl wait timed out\n");
+		err = -EIO;
+	}
+	return err;
+}
+
+static int brcmf_usb_rx_ctlpkt(struct device *dev, u8 *buf, u32 len)
+{
+	int err = 0;
+	int timeout = 0;
+	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
+
+	brcmf_dbg(USB, "Enter\n");
+	if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP)
+		return -EIO;
+
+	if (test_and_set_bit(0, &devinfo->ctl_op))
+		return -EIO;
+
+	devinfo->ctl_completed = false;
+	err = brcmf_usb_recv_ctl(devinfo, buf, len);
+	if (err) {
+		brcmf_err("fail %d bytes: %d\n", err, len);
+		clear_bit(0, &devinfo->ctl_op);
+		return err;
+	}
+	timeout = brcmf_usb_ioctl_resp_wait(devinfo);
+	err = devinfo->ctl_urb_status;
+	clear_bit(0, &devinfo->ctl_op);
+	if (!timeout) {
+		brcmf_err("rxctl wait timed out\n");
+		err = -EIO;
+	}
+	if (!err)
+		return devinfo->ctl_urb_actual_length;
+	else
+		return err;
+}
+
+static struct brcmf_usbreq *brcmf_usb_deq(struct brcmf_usbdev_info *devinfo,
+					  struct list_head *q, int *counter)
+{
+	unsigned long flags;
+	struct brcmf_usbreq  *req;
+	spin_lock_irqsave(&devinfo->qlock, flags);
+	if (list_empty(q)) {
+		spin_unlock_irqrestore(&devinfo->qlock, flags);
+		return NULL;
+	}
+	req = list_entry(q->next, struct brcmf_usbreq, list);
+	list_del_init(q->next);
+	if (counter)
+		(*counter)--;
+	spin_unlock_irqrestore(&devinfo->qlock, flags);
+	return req;
+
+}
+
+static void brcmf_usb_enq(struct brcmf_usbdev_info *devinfo,
+			  struct list_head *q, struct brcmf_usbreq *req,
+			  int *counter)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&devinfo->qlock, flags);
+	list_add_tail(&req->list, q);
+	if (counter)
+		(*counter)++;
+	spin_unlock_irqrestore(&devinfo->qlock, flags);
+}
+
+static struct brcmf_usbreq *
+brcmf_usbdev_qinit(struct list_head *q, int qsize)
+{
+	int i;
+	struct brcmf_usbreq *req, *reqs;
+
+	reqs = kcalloc(qsize, sizeof(struct brcmf_usbreq), GFP_ATOMIC);
+	if (reqs == NULL)
+		return NULL;
+
+	req = reqs;
+
+	for (i = 0; i < qsize; i++) {
+		req->urb = usb_alloc_urb(0, GFP_ATOMIC);
+		if (!req->urb)
+			goto fail;
+
+		INIT_LIST_HEAD(&req->list);
+		list_add_tail(&req->list, q);
+		req++;
+	}
+	return reqs;
+fail:
+	brcmf_err("fail!\n");
+	while (!list_empty(q)) {
+		req = list_entry(q->next, struct brcmf_usbreq, list);
+		if (req)
+			usb_free_urb(req->urb);
+		list_del(q->next);
+	}
+	return NULL;
+
+}
+
+static void brcmf_usb_free_q(struct list_head *q, bool pending)
+{
+	struct brcmf_usbreq *req, *next;
+	int i = 0;
+	list_for_each_entry_safe(req, next, q, list) {
+		if (!req->urb) {
+			brcmf_err("bad req\n");
+			break;
+		}
+		i++;
+		if (pending) {
+			usb_kill_urb(req->urb);
+		} else {
+			usb_free_urb(req->urb);
+			list_del_init(&req->list);
+		}
+	}
+}
+
+static void brcmf_usb_del_fromq(struct brcmf_usbdev_info *devinfo,
+				struct brcmf_usbreq *req)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&devinfo->qlock, flags);
+	list_del_init(&req->list);
+	spin_unlock_irqrestore(&devinfo->qlock, flags);
+}
+
+
+static void brcmf_usb_tx_complete(struct urb *urb)
+{
+	struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context;
+	struct brcmf_usbdev_info *devinfo = req->devinfo;
+	unsigned long flags;
+
+	brcmf_dbg(USB, "Enter, urb->status=%d, skb=%p\n", urb->status,
+		  req->skb);
+	brcmf_usb_del_fromq(devinfo, req);
+
+	brcmf_proto_bcdc_txcomplete(devinfo->dev, req->skb, urb->status == 0);
+	req->skb = NULL;
+	brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req, &devinfo->tx_freecount);
+	spin_lock_irqsave(&devinfo->tx_flowblock_lock, flags);
+	if (devinfo->tx_freecount > devinfo->tx_high_watermark &&
+		devinfo->tx_flowblock) {
+		brcmf_proto_bcdc_txflowblock(devinfo->dev, false);
+		devinfo->tx_flowblock = false;
+	}
+	spin_unlock_irqrestore(&devinfo->tx_flowblock_lock, flags);
+}
+
+static void brcmf_usb_rx_complete(struct urb *urb)
+{
+	struct brcmf_usbreq  *req = (struct brcmf_usbreq *)urb->context;
+	struct brcmf_usbdev_info *devinfo = req->devinfo;
+	struct sk_buff *skb;
+
+	brcmf_dbg(USB, "Enter, urb->status=%d\n", urb->status);
+	brcmf_usb_del_fromq(devinfo, req);
+	skb = req->skb;
+	req->skb = NULL;
+
+	/* zero lenght packets indicate usb "failure". Do not refill */
+	if (urb->status != 0 || !urb->actual_length) {
+		brcmu_pkt_buf_free_skb(skb);
+		brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
+		return;
+	}
+
+	if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) {
+		skb_put(skb, urb->actual_length);
+		brcmf_rx_frame(devinfo->dev, skb, true);
+		brcmf_usb_rx_refill(devinfo, req);
+	} else {
+		brcmu_pkt_buf_free_skb(skb);
+		brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
+	}
+	return;
+
+}
+
+static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
+				struct brcmf_usbreq  *req)
+{
+	struct sk_buff *skb;
+	int ret;
+
+	if (!req || !devinfo)
+		return;
+
+	skb = dev_alloc_skb(devinfo->bus_pub.bus_mtu);
+	if (!skb) {
+		brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
+		return;
+	}
+	req->skb = skb;
+
+	usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->rx_pipe,
+			  skb->data, skb_tailroom(skb), brcmf_usb_rx_complete,
+			  req);
+	req->devinfo = devinfo;
+	brcmf_usb_enq(devinfo, &devinfo->rx_postq, req, NULL);
+
+	ret = usb_submit_urb(req->urb, GFP_ATOMIC);
+	if (ret) {
+		brcmf_usb_del_fromq(devinfo, req);
+		brcmu_pkt_buf_free_skb(req->skb);
+		req->skb = NULL;
+		brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
+	}
+	return;
+}
+
+static void brcmf_usb_rx_fill_all(struct brcmf_usbdev_info *devinfo)
+{
+	struct brcmf_usbreq *req;
+
+	if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) {
+		brcmf_err("bus is not up=%d\n", devinfo->bus_pub.state);
+		return;
+	}
+	while ((req = brcmf_usb_deq(devinfo, &devinfo->rx_freeq, NULL)) != NULL)
+		brcmf_usb_rx_refill(devinfo, req);
+}
+
+static void
+brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state)
+{
+	struct brcmf_bus *bcmf_bus = devinfo->bus_pub.bus;
+	int old_state;
+
+	brcmf_dbg(USB, "Enter, current state=%d, new state=%d\n",
+		  devinfo->bus_pub.state, state);
+
+	if (devinfo->bus_pub.state == state)
+		return;
+
+	old_state = devinfo->bus_pub.state;
+	devinfo->bus_pub.state = state;
+
+	/* update state of upper layer */
+	if (state == BRCMFMAC_USB_STATE_DOWN) {
+		brcmf_dbg(USB, "DBUS is down\n");
+		brcmf_bus_change_state(bcmf_bus, BRCMF_BUS_DOWN);
+	} else if (state == BRCMFMAC_USB_STATE_UP) {
+		brcmf_dbg(USB, "DBUS is up\n");
+		brcmf_bus_change_state(bcmf_bus, BRCMF_BUS_UP);
+	} else {
+		brcmf_dbg(USB, "DBUS current state=%d\n", state);
+	}
+}
+
+static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
+{
+	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
+	struct brcmf_usbreq  *req;
+	int ret;
+	unsigned long flags;
+
+	brcmf_dbg(USB, "Enter, skb=%p\n", skb);
+	if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) {
+		ret = -EIO;
+		goto fail;
+	}
+
+	req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq,
+					&devinfo->tx_freecount);
+	if (!req) {
+		brcmf_err("no req to send\n");
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	req->skb = skb;
+	req->devinfo = devinfo;
+	usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->tx_pipe,
+			  skb->data, skb->len, brcmf_usb_tx_complete, req);
+	req->urb->transfer_flags |= URB_ZERO_PACKET;
+	brcmf_usb_enq(devinfo, &devinfo->tx_postq, req, NULL);
+	ret = usb_submit_urb(req->urb, GFP_ATOMIC);
+	if (ret) {
+		brcmf_err("brcmf_usb_tx usb_submit_urb FAILED\n");
+		brcmf_usb_del_fromq(devinfo, req);
+		req->skb = NULL;
+		brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req,
+			      &devinfo->tx_freecount);
+		goto fail;
+	}
+
+	spin_lock_irqsave(&devinfo->tx_flowblock_lock, flags);
+	if (devinfo->tx_freecount < devinfo->tx_low_watermark &&
+	    !devinfo->tx_flowblock) {
+		brcmf_proto_bcdc_txflowblock(dev, true);
+		devinfo->tx_flowblock = true;
+	}
+	spin_unlock_irqrestore(&devinfo->tx_flowblock_lock, flags);
+	return 0;
+
+fail:
+	return ret;
+}
+
+
+static int brcmf_usb_up(struct device *dev)
+{
+	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
+
+	brcmf_dbg(USB, "Enter\n");
+	if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP)
+		return 0;
+
+	/* Success, indicate devinfo is fully up */
+	brcmf_usb_state_change(devinfo, BRCMFMAC_USB_STATE_UP);
+
+	if (devinfo->ctl_urb) {
+		devinfo->ctl_in_pipe = usb_rcvctrlpipe(devinfo->usbdev, 0);
+		devinfo->ctl_out_pipe = usb_sndctrlpipe(devinfo->usbdev, 0);
+
+		/* CTL Write */
+		devinfo->ctl_write.bRequestType =
+			USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+		devinfo->ctl_write.bRequest = 0;
+		devinfo->ctl_write.wValue = cpu_to_le16(0);
+		devinfo->ctl_write.wIndex = cpu_to_le16(devinfo->ifnum);
+
+		/* CTL Read */
+		devinfo->ctl_read.bRequestType =
+			USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+		devinfo->ctl_read.bRequest = 1;
+		devinfo->ctl_read.wValue = cpu_to_le16(0);
+		devinfo->ctl_read.wIndex = cpu_to_le16(devinfo->ifnum);
+	}
+	brcmf_usb_rx_fill_all(devinfo);
+	return 0;
+}
+
+static void brcmf_cancel_all_urbs(struct brcmf_usbdev_info *devinfo)
+{
+	if (devinfo->ctl_urb)
+		usb_kill_urb(devinfo->ctl_urb);
+	if (devinfo->bulk_urb)
+		usb_kill_urb(devinfo->bulk_urb);
+	brcmf_usb_free_q(&devinfo->tx_postq, true);
+	brcmf_usb_free_q(&devinfo->rx_postq, true);
+}
+
+static void brcmf_usb_down(struct device *dev)
+{
+	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
+
+	brcmf_dbg(USB, "Enter\n");
+	if (devinfo == NULL)
+		return;
+
+	if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_DOWN)
+		return;
+
+	brcmf_usb_state_change(devinfo, BRCMFMAC_USB_STATE_DOWN);
+
+	brcmf_cancel_all_urbs(devinfo);
+}
+
+static void
+brcmf_usb_sync_complete(struct urb *urb)
+{
+	struct brcmf_usbdev_info *devinfo =
+			(struct brcmf_usbdev_info *)urb->context;
+
+	devinfo->ctl_completed = true;
+	brcmf_usb_ioctl_resp_wake(devinfo);
+}
+
+static int brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd,
+			    void *buffer, int buflen)
+{
+	int ret;
+	char *tmpbuf;
+	u16 size;
+
+	if ((!devinfo) || (devinfo->ctl_urb == NULL))
+		return -EINVAL;
+
+	tmpbuf = kmalloc(buflen, GFP_ATOMIC);
+	if (!tmpbuf)
+		return -ENOMEM;
+
+	size = buflen;
+	devinfo->ctl_urb->transfer_buffer_length = size;
+
+	devinfo->ctl_read.wLength = cpu_to_le16p(&size);
+	devinfo->ctl_read.bRequestType = USB_DIR_IN | USB_TYPE_VENDOR |
+		USB_RECIP_INTERFACE;
+	devinfo->ctl_read.bRequest = cmd;
+
+	usb_fill_control_urb(devinfo->ctl_urb,
+		devinfo->usbdev,
+		usb_rcvctrlpipe(devinfo->usbdev, 0),
+		(unsigned char *) &devinfo->ctl_read,
+		(void *) tmpbuf, size,
+		(usb_complete_t)brcmf_usb_sync_complete, devinfo);
+
+	devinfo->ctl_completed = false;
+	ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC);
+	if (ret < 0) {
+		brcmf_err("usb_submit_urb failed %d\n", ret);
+		goto finalize;
+	}
+
+	if (!brcmf_usb_ioctl_resp_wait(devinfo)) {
+		usb_kill_urb(devinfo->ctl_urb);
+		ret = -ETIMEDOUT;
+	} else {
+		memcpy(buffer, tmpbuf, buflen);
+	}
+
+finalize:
+	kfree(tmpbuf);
+	return ret;
+}
+
+static bool
+brcmf_usb_dlneeded(struct brcmf_usbdev_info *devinfo)
+{
+	struct bootrom_id_le id;
+	u32 chipid, chiprev;
+
+	brcmf_dbg(USB, "Enter\n");
+
+	if (devinfo == NULL)
+		return false;
+
+	/* Check if firmware downloaded already by querying runtime ID */
+	id.chip = cpu_to_le32(0xDEAD);
+	brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id, sizeof(id));
+
+	chipid = le32_to_cpu(id.chip);
+	chiprev = le32_to_cpu(id.chiprev);
+
+	if ((chipid & 0x4300) == 0x4300)
+		brcmf_dbg(USB, "chip %x rev 0x%x\n", chipid, chiprev);
+	else
+		brcmf_dbg(USB, "chip %d rev 0x%x\n", chipid, chiprev);
+	if (chipid == BRCMF_POSTBOOT_ID) {
+		brcmf_dbg(USB, "firmware already downloaded\n");
+		brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id, sizeof(id));
+		return false;
+	} else {
+		devinfo->bus_pub.devid = chipid;
+		devinfo->bus_pub.chiprev = chiprev;
+	}
+	return true;
+}
+
+static int
+brcmf_usb_resetcfg(struct brcmf_usbdev_info *devinfo)
+{
+	struct bootrom_id_le id;
+	u32 loop_cnt;
+	int err;
+
+	brcmf_dbg(USB, "Enter\n");
+
+	loop_cnt = 0;
+	do {
+		mdelay(BRCMF_USB_RESET_GETVER_SPINWAIT);
+		loop_cnt++;
+		id.chip = cpu_to_le32(0xDEAD);       /* Get the ID */
+		err = brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id, sizeof(id));
+		if ((err) && (err != -ETIMEDOUT))
+			return err;
+		if (id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID))
+			break;
+	} while (loop_cnt < BRCMF_USB_RESET_GETVER_LOOP_CNT);
+
+	if (id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID)) {
+		brcmf_dbg(USB, "postboot chip 0x%x/rev 0x%x\n",
+			  le32_to_cpu(id.chip), le32_to_cpu(id.chiprev));
+
+		brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id, sizeof(id));
+		return 0;
+	} else {
+		brcmf_err("Cannot talk to Dongle. Firmware is not UP, %d ms\n",
+			  BRCMF_USB_RESET_GETVER_SPINWAIT * loop_cnt);
+		return -EINVAL;
+	}
+}
+
+
+static int
+brcmf_usb_dl_send_bulk(struct brcmf_usbdev_info *devinfo, void *buffer, int len)
+{
+	int ret;
+
+	if ((devinfo == NULL) || (devinfo->bulk_urb == NULL))
+		return -EINVAL;
+
+	/* Prepare the URB */
+	usb_fill_bulk_urb(devinfo->bulk_urb, devinfo->usbdev,
+			  devinfo->tx_pipe, buffer, len,
+			  (usb_complete_t)brcmf_usb_sync_complete, devinfo);
+
+	devinfo->bulk_urb->transfer_flags |= URB_ZERO_PACKET;
+
+	devinfo->ctl_completed = false;
+	ret = usb_submit_urb(devinfo->bulk_urb, GFP_ATOMIC);
+	if (ret) {
+		brcmf_err("usb_submit_urb failed %d\n", ret);
+		return ret;
+	}
+	ret = brcmf_usb_ioctl_resp_wait(devinfo);
+	return (ret == 0);
+}
+
+static int
+brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen)
+{
+	unsigned int sendlen, sent, dllen;
+	char *bulkchunk = NULL, *dlpos;
+	struct rdl_state_le state;
+	u32 rdlstate, rdlbytes;
+	int err = 0;
+
+	brcmf_dbg(USB, "Enter, fw %p, len %d\n", fw, fwlen);
+
+	bulkchunk = kmalloc(TRX_RDL_CHUNK, GFP_ATOMIC);
+	if (bulkchunk == NULL) {
+		err = -ENOMEM;
+		goto fail;
+	}
+
+	/* 1) Prepare USB boot loader for runtime image */
+	brcmf_usb_dl_cmd(devinfo, DL_START, &state, sizeof(state));
+
+	rdlstate = le32_to_cpu(state.state);
+	rdlbytes = le32_to_cpu(state.bytes);
+
+	/* 2) Check we are in the Waiting state */
+	if (rdlstate != DL_WAITING) {
+		brcmf_err("Failed to DL_START\n");
+		err = -EINVAL;
+		goto fail;
+	}
+	sent = 0;
+	dlpos = fw;
+	dllen = fwlen;
+
+	/* Get chip id and rev */
+	while (rdlbytes != dllen) {
+		/* Wait until the usb device reports it received all
+		 * the bytes we sent */
+		if ((rdlbytes == sent) && (rdlbytes != dllen)) {
+			if ((dllen-sent) < TRX_RDL_CHUNK)
+				sendlen = dllen-sent;
+			else
+				sendlen = TRX_RDL_CHUNK;
+
+			/* simply avoid having to send a ZLP by ensuring we
+			 * never have an even
+			 * multiple of 64
+			 */
+			if (!(sendlen % 64))
+				sendlen -= 4;
+
+			/* send data */
+			memcpy(bulkchunk, dlpos, sendlen);
+			if (brcmf_usb_dl_send_bulk(devinfo, bulkchunk,
+						   sendlen)) {
+				brcmf_err("send_bulk failed\n");
+				err = -EINVAL;
+				goto fail;
+			}
+
+			dlpos += sendlen;
+			sent += sendlen;
+		}
+		err = brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state,
+				       sizeof(state));
+		if (err) {
+			brcmf_err("DL_GETSTATE Failed\n");
+			goto fail;
+		}
+
+		rdlstate = le32_to_cpu(state.state);
+		rdlbytes = le32_to_cpu(state.bytes);
+
+		/* restart if an error is reported */
+		if (rdlstate == DL_BAD_HDR || rdlstate == DL_BAD_CRC) {
+			brcmf_err("Bad Hdr or Bad CRC state %d\n",
+				  rdlstate);
+			err = -EINVAL;
+			goto fail;
+		}
+	}
+
+fail:
+	kfree(bulkchunk);
+	brcmf_dbg(USB, "Exit, err=%d\n", err);
+	return err;
+}
+
+static int brcmf_usb_dlstart(struct brcmf_usbdev_info *devinfo, u8 *fw, int len)
+{
+	int err;
+
+	brcmf_dbg(USB, "Enter\n");
+
+	if (devinfo == NULL)
+		return -EINVAL;
+
+	if (devinfo->bus_pub.devid == 0xDEAD)
+		return -EINVAL;
+
+	err = brcmf_usb_dl_writeimage(devinfo, fw, len);
+	if (err == 0)
+		devinfo->bus_pub.state = BRCMFMAC_USB_STATE_DL_DONE;
+	else
+		devinfo->bus_pub.state = BRCMFMAC_USB_STATE_DL_FAIL;
+	brcmf_dbg(USB, "Exit, err=%d\n", err);
+
+	return err;
+}
+
+static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo)
+{
+	struct rdl_state_le state;
+
+	brcmf_dbg(USB, "Enter\n");
+	if (!devinfo)
+		return -EINVAL;
+
+	if (devinfo->bus_pub.devid == 0xDEAD)
+		return -EINVAL;
+
+	/* Check we are runnable */
+	state.state = 0;
+	brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state, sizeof(state));
+
+	/* Start the image */
+	if (state.state == cpu_to_le32(DL_RUNNABLE)) {
+		if (brcmf_usb_dl_cmd(devinfo, DL_GO, &state, sizeof(state)))
+			return -ENODEV;
+		if (brcmf_usb_resetcfg(devinfo))
+			return -ENODEV;
+		/* The Dongle may go for re-enumeration. */
+	} else {
+		brcmf_err("Dongle not runnable\n");
+		return -EINVAL;
+	}
+	brcmf_dbg(USB, "Exit\n");
+	return 0;
+}
+
+static int
+brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo)
+{
+	int err;
+
+	brcmf_dbg(USB, "Enter\n");
+	if (devinfo == NULL)
+		return -ENODEV;
+
+	if (!devinfo->image) {
+		brcmf_err("No firmware!\n");
+		return -ENOENT;
+	}
+
+	err = brcmf_usb_dlstart(devinfo,
+		(u8 *)devinfo->image, devinfo->image_len);
+	if (err == 0)
+		err = brcmf_usb_dlrun(devinfo);
+	return err;
+}
+
+
+static void brcmf_usb_detach(struct brcmf_usbdev_info *devinfo)
+{
+	brcmf_dbg(USB, "Enter, devinfo %p\n", devinfo);
+
+	/* free the URBS */
+	brcmf_usb_free_q(&devinfo->rx_freeq, false);
+	brcmf_usb_free_q(&devinfo->tx_freeq, false);
+
+	usb_free_urb(devinfo->ctl_urb);
+	usb_free_urb(devinfo->bulk_urb);
+
+	kfree(devinfo->tx_reqs);
+	kfree(devinfo->rx_reqs);
+
+	if (devinfo->settings)
+		brcmf_release_module_param(devinfo->settings);
+}
+
+
+static int check_file(const u8 *headers)
+{
+	struct trx_header_le *trx;
+	int actual_len = -1;
+
+	brcmf_dbg(USB, "Enter\n");
+	/* Extract trx header */
+	trx = (struct trx_header_le *) headers;
+	if (trx->magic != cpu_to_le32(TRX_MAGIC))
+		return -1;
+
+	headers += sizeof(struct trx_header_le);
+
+	if (le32_to_cpu(trx->flag_version) & TRX_UNCOMP_IMAGE) {
+		actual_len = le32_to_cpu(trx->offsets[TRX_OFFSETS_DLFWLEN_IDX]);
+		return actual_len + sizeof(struct trx_header_le);
+	}
+	return -1;
+}
+
+
+static
+struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo,
+				      int nrxq, int ntxq)
+{
+	brcmf_dbg(USB, "Enter\n");
+
+	devinfo->bus_pub.nrxq = nrxq;
+	devinfo->rx_low_watermark = nrxq / 2;
+	devinfo->bus_pub.devinfo = devinfo;
+	devinfo->bus_pub.ntxq = ntxq;
+	devinfo->bus_pub.state = BRCMFMAC_USB_STATE_DOWN;
+
+	/* flow control when too many tx urbs posted */
+	devinfo->tx_low_watermark = ntxq / 4;
+	devinfo->tx_high_watermark = devinfo->tx_low_watermark * 3;
+	devinfo->bus_pub.bus_mtu = BRCMF_USB_MAX_PKT_SIZE;
+
+	/* Initialize other structure content */
+	init_waitqueue_head(&devinfo->ioctl_resp_wait);
+
+	/* Initialize the spinlocks */
+	spin_lock_init(&devinfo->qlock);
+	spin_lock_init(&devinfo->tx_flowblock_lock);
+
+	INIT_LIST_HEAD(&devinfo->rx_freeq);
+	INIT_LIST_HEAD(&devinfo->rx_postq);
+
+	INIT_LIST_HEAD(&devinfo->tx_freeq);
+	INIT_LIST_HEAD(&devinfo->tx_postq);
+
+	devinfo->tx_flowblock = false;
+
+	devinfo->rx_reqs = brcmf_usbdev_qinit(&devinfo->rx_freeq, nrxq);
+	if (!devinfo->rx_reqs)
+		goto error;
+
+	devinfo->tx_reqs = brcmf_usbdev_qinit(&devinfo->tx_freeq, ntxq);
+	if (!devinfo->tx_reqs)
+		goto error;
+	devinfo->tx_freecount = ntxq;
+
+	devinfo->ctl_urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!devinfo->ctl_urb)
+		goto error;
+	devinfo->bulk_urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!devinfo->bulk_urb)
+		goto error;
+
+	return &devinfo->bus_pub;
+
+error:
+	brcmf_err("failed!\n");
+	brcmf_usb_detach(devinfo);
+	return NULL;
+}
+
+static void brcmf_usb_wowl_config(struct device *dev, bool enabled)
+{
+	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
+
+	brcmf_dbg(USB, "Configuring WOWL, enabled=%d\n", enabled);
+	devinfo->wowl_enabled = enabled;
+	if (enabled)
+		device_set_wakeup_enable(devinfo->dev, true);
+	else
+		device_set_wakeup_enable(devinfo->dev, false);
+}
+
+static
+int brcmf_usb_get_fwname(struct device *dev, const char *ext, u8 *fw_name)
+{
+	struct brcmf_bus *bus = dev_get_drvdata(dev);
+	struct brcmf_fw_request *fwreq;
+	struct brcmf_fw_name fwnames[] = {
+		{ ext, fw_name },
+	};
+
+	fwreq = brcmf_fw_alloc_request(bus->chip, bus->chiprev,
+				       brcmf_usb_fwnames,
+				       ARRAY_SIZE(brcmf_usb_fwnames),
+				       fwnames, ARRAY_SIZE(fwnames));
+	if (!fwreq)
+		return -ENOMEM;
+
+	kfree(fwreq);
+	return 0;
+}
+
+static const struct brcmf_bus_ops brcmf_usb_bus_ops = {
+	.preinit = brcmf_usb_up,
+	.stop = brcmf_usb_down,
+	.txdata = brcmf_usb_tx,
+	.txctl = brcmf_usb_tx_ctlpkt,
+	.rxctl = brcmf_usb_rx_ctlpkt,
+	.wowl_config = brcmf_usb_wowl_config,
+	.get_fwname = brcmf_usb_get_fwname,
+};
+
+#define BRCMF_USB_FW_CODE	0
+
+static void brcmf_usb_probe_phase2(struct device *dev, int ret,
+				   struct brcmf_fw_request *fwreq)
+{
+	struct brcmf_bus *bus = dev_get_drvdata(dev);
+	struct brcmf_usbdev_info *devinfo = bus->bus_priv.usb->devinfo;
+	const struct firmware *fw;
+
+	if (ret)
+		goto error;
+
+	brcmf_dbg(USB, "Start fw downloading\n");
+
+	fw = fwreq->items[BRCMF_USB_FW_CODE].binary;
+	kfree(fwreq);
+
+	ret = check_file(fw->data);
+	if (ret < 0) {
+		brcmf_err("invalid firmware\n");
+		release_firmware(fw);
+		goto error;
+	}
+
+	devinfo->image = fw->data;
+	devinfo->image_len = fw->size;
+
+	ret = brcmf_usb_fw_download(devinfo);
+	release_firmware(fw);
+	if (ret)
+		goto error;
+
+	/* Attach to the common driver interface */
+	ret = brcmf_attach(devinfo->dev, devinfo->settings);
+	if (ret)
+		goto error;
+
+	mutex_unlock(&devinfo->dev_init_lock);
+	return;
+error:
+	brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), ret);
+	mutex_unlock(&devinfo->dev_init_lock);
+	device_release_driver(dev);
+}
+
+static struct brcmf_fw_request *
+brcmf_usb_prepare_fw_request(struct brcmf_usbdev_info *devinfo)
+{
+	struct brcmf_fw_request *fwreq;
+	struct brcmf_fw_name fwnames[] = {
+		{ ".bin", devinfo->fw_name },
+	};
+
+	fwreq = brcmf_fw_alloc_request(devinfo->bus_pub.devid,
+				       devinfo->bus_pub.chiprev,
+				       brcmf_usb_fwnames,
+				       ARRAY_SIZE(brcmf_usb_fwnames),
+				       fwnames, ARRAY_SIZE(fwnames));
+	if (!fwreq)
+		return NULL;
+
+	fwreq->items[BRCMF_USB_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
+
+	return fwreq;
+}
+
+static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
+{
+	struct brcmf_bus *bus = NULL;
+	struct brcmf_usbdev *bus_pub = NULL;
+	struct device *dev = devinfo->dev;
+	struct brcmf_fw_request *fwreq;
+	int ret;
+
+	brcmf_dbg(USB, "Enter\n");
+	bus_pub = brcmf_usb_attach(devinfo, BRCMF_USB_NRXQ, BRCMF_USB_NTXQ);
+	if (!bus_pub)
+		return -ENODEV;
+
+	bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC);
+	if (!bus) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	bus->dev = dev;
+	bus_pub->bus = bus;
+	bus->bus_priv.usb = bus_pub;
+	dev_set_drvdata(dev, bus);
+	bus->ops = &brcmf_usb_bus_ops;
+	bus->proto_type = BRCMF_PROTO_BCDC;
+	bus->always_use_fws_queue = true;
+#ifdef CONFIG_PM
+	bus->wowl_supported = true;
+#endif
+
+	devinfo->settings = brcmf_get_module_param(bus->dev, BRCMF_BUSTYPE_USB,
+						   bus_pub->devid,
+						   bus_pub->chiprev);
+	if (!devinfo->settings) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	if (!brcmf_usb_dlneeded(devinfo)) {
+		ret = brcmf_attach(devinfo->dev, devinfo->settings);
+		if (ret)
+			goto fail;
+		/* we are done */
+		mutex_unlock(&devinfo->dev_init_lock);
+		return 0;
+	}
+	bus->chip = bus_pub->devid;
+	bus->chiprev = bus_pub->chiprev;
+
+	fwreq = brcmf_usb_prepare_fw_request(devinfo);
+	if (!fwreq) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	/* request firmware here */
+	ret = brcmf_fw_get_firmwares(dev, fwreq, brcmf_usb_probe_phase2);
+	if (ret) {
+		brcmf_err("firmware request failed: %d\n", ret);
+		kfree(fwreq);
+		goto fail;
+	}
+
+	return 0;
+
+fail:
+	/* Release resources in reverse order */
+	kfree(bus);
+	brcmf_usb_detach(devinfo);
+	return ret;
+}
+
+static void
+brcmf_usb_disconnect_cb(struct brcmf_usbdev_info *devinfo)
+{
+	if (!devinfo)
+		return;
+	brcmf_dbg(USB, "Enter, bus_pub %p\n", devinfo);
+
+	brcmf_detach(devinfo->dev);
+	kfree(devinfo->bus_pub.bus);
+	brcmf_usb_detach(devinfo);
+}
+
+static int
+brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	struct usb_device *usb = interface_to_usbdev(intf);
+	struct brcmf_usbdev_info *devinfo;
+	struct usb_interface_descriptor	*desc;
+	struct usb_endpoint_descriptor *endpoint;
+	int ret = 0;
+	u32 num_of_eps;
+	u8 endpoint_num, ep;
+
+	brcmf_dbg(USB, "Enter 0x%04x:0x%04x\n", id->idVendor, id->idProduct);
+
+	devinfo = kzalloc(sizeof(*devinfo), GFP_ATOMIC);
+	if (devinfo == NULL)
+		return -ENOMEM;
+
+	devinfo->usbdev = usb;
+	devinfo->dev = &usb->dev;
+	/* Take an init lock, to protect for disconnect while still loading.
+	 * Necessary because of the asynchronous firmware load construction
+	 */
+	mutex_init(&devinfo->dev_init_lock);
+	mutex_lock(&devinfo->dev_init_lock);
+
+	usb_set_intfdata(intf, devinfo);
+
+	/* Check that the device supports only one configuration */
+	if (usb->descriptor.bNumConfigurations != 1) {
+		brcmf_err("Number of configurations: %d not supported\n",
+			  usb->descriptor.bNumConfigurations);
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	if ((usb->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) &&
+	    (usb->descriptor.bDeviceClass != USB_CLASS_MISC) &&
+	    (usb->descriptor.bDeviceClass != USB_CLASS_WIRELESS_CONTROLLER)) {
+		brcmf_err("Device class: 0x%x not supported\n",
+			  usb->descriptor.bDeviceClass);
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	desc = &intf->altsetting[0].desc;
+	if ((desc->bInterfaceClass != USB_CLASS_VENDOR_SPEC) ||
+	    (desc->bInterfaceSubClass != 2) ||
+	    (desc->bInterfaceProtocol != 0xff)) {
+		brcmf_err("non WLAN interface %d: 0x%x:0x%x:0x%x\n",
+			  desc->bInterfaceNumber, desc->bInterfaceClass,
+			  desc->bInterfaceSubClass, desc->bInterfaceProtocol);
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	num_of_eps = desc->bNumEndpoints;
+	for (ep = 0; ep < num_of_eps; ep++) {
+		endpoint = &intf->altsetting[0].endpoint[ep].desc;
+		endpoint_num = usb_endpoint_num(endpoint);
+		if (!usb_endpoint_xfer_bulk(endpoint))
+			continue;
+		if (usb_endpoint_dir_in(endpoint)) {
+			if (!devinfo->rx_pipe)
+				devinfo->rx_pipe =
+					usb_rcvbulkpipe(usb, endpoint_num);
+		} else {
+			if (!devinfo->tx_pipe)
+				devinfo->tx_pipe =
+					usb_sndbulkpipe(usb, endpoint_num);
+		}
+	}
+	if (devinfo->rx_pipe == 0) {
+		brcmf_err("No RX (in) Bulk EP found\n");
+		ret = -ENODEV;
+		goto fail;
+	}
+	if (devinfo->tx_pipe == 0) {
+		brcmf_err("No TX (out) Bulk EP found\n");
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	devinfo->ifnum = desc->bInterfaceNumber;
+
+	if (usb->speed == USB_SPEED_SUPER_PLUS)
+		brcmf_dbg(USB, "Broadcom super speed plus USB WLAN interface detected\n");
+	else if (usb->speed == USB_SPEED_SUPER)
+		brcmf_dbg(USB, "Broadcom super speed USB WLAN interface detected\n");
+	else if (usb->speed == USB_SPEED_HIGH)
+		brcmf_dbg(USB, "Broadcom high speed USB WLAN interface detected\n");
+	else
+		brcmf_dbg(USB, "Broadcom full speed USB WLAN interface detected\n");
+
+	ret = brcmf_usb_probe_cb(devinfo);
+	if (ret)
+		goto fail;
+
+	/* Success */
+	return 0;
+
+fail:
+	mutex_unlock(&devinfo->dev_init_lock);
+	kfree(devinfo);
+	usb_set_intfdata(intf, NULL);
+	return ret;
+}
+
+static void
+brcmf_usb_disconnect(struct usb_interface *intf)
+{
+	struct brcmf_usbdev_info *devinfo;
+
+	brcmf_dbg(USB, "Enter\n");
+	devinfo = (struct brcmf_usbdev_info *)usb_get_intfdata(intf);
+
+	if (devinfo) {
+		mutex_lock(&devinfo->dev_init_lock);
+		/* Make sure that devinfo still exists. Firmware probe routines
+		 * may have released the device and cleared the intfdata.
+		 */
+		if (!usb_get_intfdata(intf))
+			goto done;
+
+		brcmf_usb_disconnect_cb(devinfo);
+		kfree(devinfo);
+	}
+done:
+	brcmf_dbg(USB, "Exit\n");
+}
+
+/*
+ * only need to signal the bus being down and update the state.
+ */
+static int brcmf_usb_suspend(struct usb_interface *intf, pm_message_t state)
+{
+	struct usb_device *usb = interface_to_usbdev(intf);
+	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
+
+	brcmf_dbg(USB, "Enter\n");
+	devinfo->bus_pub.state = BRCMFMAC_USB_STATE_SLEEP;
+	if (devinfo->wowl_enabled)
+		brcmf_cancel_all_urbs(devinfo);
+	else
+		brcmf_detach(&usb->dev);
+	return 0;
+}
+
+/*
+ * (re-) start the bus.
+ */
+static int brcmf_usb_resume(struct usb_interface *intf)
+{
+	struct usb_device *usb = interface_to_usbdev(intf);
+	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
+
+	brcmf_dbg(USB, "Enter\n");
+	if (!devinfo->wowl_enabled)
+		return brcmf_attach(devinfo->dev, devinfo->settings);
+
+	devinfo->bus_pub.state = BRCMFMAC_USB_STATE_UP;
+	brcmf_usb_rx_fill_all(devinfo);
+	return 0;
+}
+
+static int brcmf_usb_reset_resume(struct usb_interface *intf)
+{
+	struct usb_device *usb = interface_to_usbdev(intf);
+	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
+	struct brcmf_fw_request *fwreq;
+	int ret;
+
+	brcmf_dbg(USB, "Enter\n");
+
+	fwreq = brcmf_usb_prepare_fw_request(devinfo);
+	if (!fwreq)
+		return -ENOMEM;
+
+	ret = brcmf_fw_get_firmwares(&usb->dev, fwreq, brcmf_usb_probe_phase2);
+	if (ret < 0)
+		kfree(fwreq);
+
+	return ret;
+}
+
+#define BRCMF_USB_DEVICE(dev_id)	\
+	{ USB_DEVICE(BRCM_USB_VENDOR_ID_BROADCOM, dev_id) }
+
+#define LINKSYS_USB_DEVICE(dev_id)	\
+	{ USB_DEVICE(BRCM_USB_VENDOR_ID_LINKSYS, dev_id) }
+
+#define CYPRESS_USB_DEVICE(dev_id)	\
+	{ USB_DEVICE(CY_USB_VENDOR_ID_CYPRESS, dev_id) }
+
+static const struct usb_device_id brcmf_usb_devid_table[] = {
+	BRCMF_USB_DEVICE(BRCM_USB_43143_DEVICE_ID),
+	BRCMF_USB_DEVICE(BRCM_USB_43236_DEVICE_ID),
+	BRCMF_USB_DEVICE(BRCM_USB_43242_DEVICE_ID),
+	BRCMF_USB_DEVICE(BRCM_USB_43569_DEVICE_ID),
+	LINKSYS_USB_DEVICE(BRCM_USB_43235_LINKSYS_DEVICE_ID),
+	CYPRESS_USB_DEVICE(CY_USB_4373_DEVICE_ID),
+	{ USB_DEVICE(BRCM_USB_VENDOR_ID_LG, BRCM_USB_43242_LG_DEVICE_ID) },
+	/* special entry for device with firmware loaded and running */
+	BRCMF_USB_DEVICE(BRCM_USB_BCMFW_DEVICE_ID),
+	CYPRESS_USB_DEVICE(BRCM_USB_BCMFW_DEVICE_ID),
+	{ /* end: all zeroes */ }
+};
+
+MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table);
+
+static struct usb_driver brcmf_usbdrvr = {
+	.name = KBUILD_MODNAME,
+	.probe = brcmf_usb_probe,
+	.disconnect = brcmf_usb_disconnect,
+	.id_table = brcmf_usb_devid_table,
+	.suspend = brcmf_usb_suspend,
+	.resume = brcmf_usb_resume,
+	.reset_resume = brcmf_usb_reset_resume,
+	.disable_hub_initiated_lpm = 1,
+};
+
+static int brcmf_usb_reset_device(struct device *dev, void *notused)
+{
+	/* device past is the usb interface so we
+	 * need to use parent here.
+	 */
+	brcmf_dev_reset(dev->parent);
+	return 0;
+}
+
+void brcmf_usb_exit(void)
+{
+	struct device_driver *drv = &brcmf_usbdrvr.drvwrap.driver;
+	int ret;
+
+	brcmf_dbg(USB, "Enter\n");
+	ret = driver_for_each_device(drv, NULL, NULL,
+				     brcmf_usb_reset_device);
+	usb_deregister(&brcmf_usbdrvr);
+}
+
+void brcmf_usb_register(void)
+{
+	brcmf_dbg(USB, "Enter\n");
+	usb_register(&brcmf_usbdrvr);
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.h
new file mode 100644
index 0000000..f483a8c
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef BRCMFMAC_USB_H
+#define BRCMFMAC_USB_H
+
+enum brcmf_usb_state {
+	BRCMFMAC_USB_STATE_DOWN,
+	BRCMFMAC_USB_STATE_DL_FAIL,
+	BRCMFMAC_USB_STATE_DL_DONE,
+	BRCMFMAC_USB_STATE_UP,
+	BRCMFMAC_USB_STATE_SLEEP
+};
+
+struct brcmf_stats {
+	u32 tx_ctlpkts;
+	u32 tx_ctlerrs;
+	u32 rx_ctlpkts;
+	u32 rx_ctlerrs;
+};
+
+struct brcmf_usbdev {
+	struct brcmf_bus *bus;
+	struct brcmf_usbdev_info *devinfo;
+	enum brcmf_usb_state state;
+	struct brcmf_stats stats;
+	int ntxq, nrxq, rxsize;
+	u32 bus_mtu;
+	int devid;
+	int chiprev; /* chip revsion number */
+};
+
+/* IO Request Block (IRB) */
+struct brcmf_usbreq {
+	struct list_head list;
+	struct brcmf_usbdev_info *devinfo;
+	struct urb *urb;
+	struct sk_buff  *skb;
+};
+
+#endif /* BRCMFMAC_USB_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c
new file mode 100644
index 0000000..8eff275
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/vmalloc.h>
+#include <net/cfg80211.h>
+#include <net/netlink.h>
+
+#include <brcmu_wifi.h>
+#include "fwil_types.h"
+#include "core.h"
+#include "p2p.h"
+#include "debug.h"
+#include "cfg80211.h"
+#include "vendor.h"
+#include "fwil.h"
+
+static int brcmf_cfg80211_vndr_cmds_dcmd_handler(struct wiphy *wiphy,
+						 struct wireless_dev *wdev,
+						 const void *data, int len)
+{
+	struct brcmf_cfg80211_vif *vif;
+	struct brcmf_if *ifp;
+	const struct brcmf_vndr_dcmd_hdr *cmdhdr = data;
+	struct sk_buff *reply;
+	int ret, payload, ret_len;
+	void *dcmd_buf = NULL, *wr_pointer;
+	u16 msglen, maxmsglen = PAGE_SIZE - 0x100;
+
+	if (len < sizeof(*cmdhdr)) {
+		brcmf_err("vendor command too short: %d\n", len);
+		return -EINVAL;
+	}
+
+	vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
+	ifp = vif->ifp;
+
+	brcmf_dbg(TRACE, "ifidx=%d, cmd=%d\n", ifp->ifidx, cmdhdr->cmd);
+
+	if (cmdhdr->offset > len) {
+		brcmf_err("bad buffer offset %d > %d\n", cmdhdr->offset, len);
+		return -EINVAL;
+	}
+
+	len -= cmdhdr->offset;
+	ret_len = cmdhdr->len;
+	if (ret_len > 0 || len > 0) {
+		if (len > BRCMF_DCMD_MAXLEN) {
+			brcmf_err("oversize input buffer %d\n", len);
+			len = BRCMF_DCMD_MAXLEN;
+		}
+		if (ret_len > BRCMF_DCMD_MAXLEN) {
+			brcmf_err("oversize return buffer %d\n", ret_len);
+			ret_len = BRCMF_DCMD_MAXLEN;
+		}
+		payload = max(ret_len, len) + 1;
+		dcmd_buf = vzalloc(payload);
+		if (NULL == dcmd_buf)
+			return -ENOMEM;
+
+		memcpy(dcmd_buf, (void *)cmdhdr + cmdhdr->offset, len);
+		*(char *)(dcmd_buf + len)  = '\0';
+	}
+
+	if (cmdhdr->set)
+		ret = brcmf_fil_cmd_data_set(ifp, cmdhdr->cmd, dcmd_buf,
+					     ret_len);
+	else
+		ret = brcmf_fil_cmd_data_get(ifp, cmdhdr->cmd, dcmd_buf,
+					     ret_len);
+	if (ret != 0)
+		goto exit;
+
+	wr_pointer = dcmd_buf;
+	while (ret_len > 0) {
+		msglen = ret_len > maxmsglen ? maxmsglen : ret_len;
+		ret_len -= msglen;
+		payload = msglen + sizeof(msglen);
+		reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload);
+		if (NULL == reply) {
+			ret = -ENOMEM;
+			break;
+		}
+
+		if (nla_put(reply, BRCMF_NLATTR_DATA, msglen, wr_pointer) ||
+		    nla_put_u16(reply, BRCMF_NLATTR_LEN, msglen)) {
+			kfree_skb(reply);
+			ret = -ENOBUFS;
+			break;
+		}
+
+		ret = cfg80211_vendor_cmd_reply(reply);
+		if (ret)
+			break;
+
+		wr_pointer += msglen;
+	}
+
+exit:
+	vfree(dcmd_buf);
+
+	return ret;
+}
+
+const struct wiphy_vendor_command brcmf_vendor_cmds[] = {
+	{
+		{
+			.vendor_id = BROADCOM_OUI,
+			.subcmd = BRCMF_VNDR_CMDS_DCMD
+		},
+		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+			 WIPHY_VENDOR_CMD_NEED_NETDEV,
+		.doit = brcmf_cfg80211_vndr_cmds_dcmd_handler
+	},
+};
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.h
new file mode 100644
index 0000000..061b7bf
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _vendor_h_
+#define _vendor_h_
+
+#define BROADCOM_OUI	0x001018
+
+enum brcmf_vndr_cmds {
+	BRCMF_VNDR_CMDS_UNSPEC,
+	BRCMF_VNDR_CMDS_DCMD,
+	BRCMF_VNDR_CMDS_LAST
+};
+
+/**
+ * enum brcmf_nlattrs - nl80211 message attributes
+ *
+ * @BRCMF_NLATTR_LEN: message body length
+ * @BRCMF_NLATTR_DATA: message body
+ */
+enum brcmf_nlattrs {
+	BRCMF_NLATTR_UNSPEC,
+
+	BRCMF_NLATTR_LEN,
+	BRCMF_NLATTR_DATA,
+
+	__BRCMF_NLATTR_AFTER_LAST,
+	BRCMF_NLATTR_MAX = __BRCMF_NLATTR_AFTER_LAST - 1
+};
+
+/**
+ * struct brcmf_vndr_dcmd_hdr - message header for cfg80211 vendor command dcmd
+ *				support
+ *
+ * @cmd: common dongle cmd definition
+ * @len: length of expecting return buffer
+ * @offset: offset of data buffer
+ * @set: get or set request(optional)
+ * @magic: magic number for verification
+ */
+struct brcmf_vndr_dcmd_hdr {
+	uint cmd;
+	int len;
+	uint offset;
+	uint set;
+	uint magic;
+};
+
+extern const struct wiphy_vendor_command brcmf_vendor_cmds[];
+
+#endif /* _vendor_h_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile
new file mode 100644
index 0000000..ed83f33
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile
@@ -0,0 +1,47 @@
+#
+# Makefile fragment for Broadcom 802.11n Networking Device Driver
+#
+# Copyright (c) 2010 Broadcom Corporation
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ccflags-y := \
+	-Idrivers/net/wireless/broadcom/brcm80211/brcmsmac \
+	-Idrivers/net/wireless/broadcom/brcm80211/brcmsmac/phy \
+	-Idrivers/net/wireless/broadcom/brcm80211/include
+
+brcmsmac-y := \
+	mac80211_if.o \
+	ucode_loader.o \
+	ampdu.o \
+	antsel.o \
+	channel.o \
+	main.o \
+	phy_shim.o \
+	pmu.o \
+	rate.o \
+	stf.o \
+	aiutils.o \
+	phy/phy_cmn.o \
+	phy/phy_lcn.o \
+	phy/phy_n.o \
+	phy/phytbl_lcn.o \
+	phy/phytbl_n.o \
+	phy/phy_qmath.o \
+	dma.o \
+	brcms_trace_events.o \
+	debug.o
+
+brcmsmac-$(CONFIG_BCMA_DRIVER_GPIO) += led.o
+
+obj-$(CONFIG_BRCMSMAC)	+= brcmsmac.o
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/aiutils.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/aiutils.c
new file mode 100644
index 0000000..5336597
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/aiutils.c
@@ -0,0 +1,710 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * File contents: support functions for PCI/PCIe
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/delay.h>
+
+#include <defs.h>
+#include <chipcommon.h>
+#include <brcmu_utils.h>
+#include <brcm_hw_ids.h>
+#include <soc.h>
+#include "types.h"
+#include "pub.h"
+#include "pmu.h"
+#include "aiutils.h"
+
+/* slow_clk_ctl */
+ /* slow clock source mask */
+#define SCC_SS_MASK		0x00000007
+ /* source of slow clock is LPO */
+#define	SCC_SS_LPO		0x00000000
+ /* source of slow clock is crystal */
+#define	SCC_SS_XTAL		0x00000001
+ /* source of slow clock is PCI */
+#define	SCC_SS_PCI		0x00000002
+ /* LPOFreqSel, 1: 160Khz, 0: 32KHz */
+#define SCC_LF			0x00000200
+ /* LPOPowerDown, 1: LPO is disabled, 0: LPO is enabled */
+#define SCC_LP			0x00000400
+ /* ForceSlowClk, 1: sb/cores running on slow clock, 0: power logic control */
+#define SCC_FS			0x00000800
+ /* IgnorePllOffReq, 1/0:
+  *  power logic ignores/honors PLL clock disable requests from core
+  */
+#define SCC_IP			0x00001000
+ /* XtalControlEn, 1/0:
+  *  power logic does/doesn't disable crystal when appropriate
+  */
+#define SCC_XC			0x00002000
+ /* XtalPU (RO), 1/0: crystal running/disabled */
+#define SCC_XP			0x00004000
+ /* ClockDivider (SlowClk = 1/(4+divisor)) */
+#define SCC_CD_MASK		0xffff0000
+#define SCC_CD_SHIFT		16
+
+/* system_clk_ctl */
+ /* ILPen: Enable Idle Low Power */
+#define	SYCC_IE			0x00000001
+ /* ALPen: Enable Active Low Power */
+#define	SYCC_AE			0x00000002
+ /* ForcePLLOn */
+#define	SYCC_FP			0x00000004
+ /* Force ALP (or HT if ALPen is not set */
+#define	SYCC_AR			0x00000008
+ /* Force HT */
+#define	SYCC_HR			0x00000010
+ /* ClkDiv  (ILP = 1/(4 * (divisor + 1)) */
+#define SYCC_CD_MASK		0xffff0000
+#define SYCC_CD_SHIFT		16
+
+#define CST4329_SPROM_OTP_SEL_MASK	0x00000003
+ /* OTP is powered up, use def. CIS, no SPROM */
+#define CST4329_DEFCIS_SEL		0
+ /* OTP is powered up, SPROM is present */
+#define CST4329_SPROM_SEL		1
+ /* OTP is powered up, no SPROM */
+#define CST4329_OTP_SEL			2
+ /* OTP is powered down, SPROM is present */
+#define CST4329_OTP_PWRDN		3
+
+#define CST4329_SPI_SDIO_MODE_MASK	0x00000004
+#define CST4329_SPI_SDIO_MODE_SHIFT	2
+
+/* 43224 chip-specific ChipControl register bits */
+#define CCTRL43224_GPIO_TOGGLE          0x8000
+ /* 12 mA drive strength */
+#define CCTRL_43224A0_12MA_LED_DRIVE    0x00F000F0
+ /* 12 mA drive strength for later 43224s */
+#define CCTRL_43224B0_12MA_LED_DRIVE    0xF0
+
+/* 43236 Chip specific ChipStatus register bits */
+#define CST43236_SFLASH_MASK		0x00000040
+#define CST43236_OTP_MASK		0x00000080
+#define CST43236_HSIC_MASK		0x00000100	/* USB/HSIC */
+#define CST43236_BP_CLK			0x00000200	/* 120/96Mbps */
+#define CST43236_BOOT_MASK		0x00001800
+#define CST43236_BOOT_SHIFT		11
+#define CST43236_BOOT_FROM_SRAM		0 /* boot from SRAM, ARM in reset */
+#define CST43236_BOOT_FROM_ROM		1 /* boot from ROM */
+#define CST43236_BOOT_FROM_FLASH	2 /* boot from FLASH */
+#define CST43236_BOOT_FROM_INVALID	3
+
+/* 4331 chip-specific ChipControl register bits */
+ /* 0 disable */
+#define CCTRL4331_BT_COEXIST		(1<<0)
+ /* 0 SECI is disabled (JTAG functional) */
+#define CCTRL4331_SECI			(1<<1)
+ /* 0 disable */
+#define CCTRL4331_EXT_LNA		(1<<2)
+ /* sprom/gpio13-15 mux */
+#define CCTRL4331_SPROM_GPIO13_15       (1<<3)
+ /* 0 ext pa disable, 1 ext pa enabled */
+#define CCTRL4331_EXTPA_EN		(1<<4)
+ /* set drive out GPIO_CLK on sprom_cs pin */
+#define CCTRL4331_GPIOCLK_ON_SPROMCS	(1<<5)
+ /* use sprom_cs pin as PCIE mdio interface */
+#define CCTRL4331_PCIE_MDIO_ON_SPROMCS	(1<<6)
+ /* aband extpa will be at gpio2/5 and sprom_dout */
+#define CCTRL4331_EXTPA_ON_GPIO2_5	(1<<7)
+ /* override core control on pipe_AuxClkEnable */
+#define CCTRL4331_OVR_PIPEAUXCLKEN	(1<<8)
+ /* override core control on pipe_AuxPowerDown */
+#define CCTRL4331_OVR_PIPEAUXPWRDOWN	(1<<9)
+ /* pcie_auxclkenable */
+#define CCTRL4331_PCIE_AUXCLKEN		(1<<10)
+ /* pcie_pipe_pllpowerdown */
+#define CCTRL4331_PCIE_PIPE_PLLDOWN	(1<<11)
+ /* enable bt_shd0 at gpio4 */
+#define CCTRL4331_BT_SHD0_ON_GPIO4	(1<<16)
+ /* enable bt_shd1 at gpio5 */
+#define CCTRL4331_BT_SHD1_ON_GPIO5	(1<<17)
+
+/* 4331 Chip specific ChipStatus register bits */
+ /* crystal frequency 20/40Mhz */
+#define	CST4331_XTAL_FREQ		0x00000001
+#define	CST4331_SPROM_PRESENT		0x00000002
+#define	CST4331_OTP_PRESENT		0x00000004
+#define	CST4331_LDO_RF			0x00000008
+#define	CST4331_LDO_PAR			0x00000010
+
+/* 4319 chip-specific ChipStatus register bits */
+#define	CST4319_SPI_CPULESSUSB		0x00000001
+#define	CST4319_SPI_CLK_POL		0x00000002
+#define	CST4319_SPI_CLK_PH		0x00000008
+ /* gpio [7:6], SDIO CIS selection */
+#define	CST4319_SPROM_OTP_SEL_MASK	0x000000c0
+#define	CST4319_SPROM_OTP_SEL_SHIFT	6
+ /* use default CIS, OTP is powered up */
+#define	CST4319_DEFCIS_SEL		0x00000000
+ /* use SPROM, OTP is powered up */
+#define	CST4319_SPROM_SEL		0x00000040
+ /* use OTP, OTP is powered up */
+#define	CST4319_OTP_SEL			0x00000080
+ /* use SPROM, OTP is powered down */
+#define	CST4319_OTP_PWRDN		0x000000c0
+ /* gpio [8], sdio/usb mode */
+#define	CST4319_SDIO_USB_MODE		0x00000100
+#define	CST4319_REMAP_SEL_MASK		0x00000600
+#define	CST4319_ILPDIV_EN		0x00000800
+#define	CST4319_XTAL_PD_POL		0x00001000
+#define	CST4319_LPO_SEL			0x00002000
+#define	CST4319_RES_INIT_MODE		0x0000c000
+ /* PALDO is configured with external PNP */
+#define	CST4319_PALDO_EXTPNP		0x00010000
+#define	CST4319_CBUCK_MODE_MASK		0x00060000
+#define CST4319_CBUCK_MODE_BURST	0x00020000
+#define CST4319_CBUCK_MODE_LPBURST	0x00060000
+#define	CST4319_RCAL_VALID		0x01000000
+#define	CST4319_RCAL_VALUE_MASK		0x3e000000
+#define	CST4319_RCAL_VALUE_SHIFT	25
+
+/* 4336 chip-specific ChipStatus register bits */
+#define	CST4336_SPI_MODE_MASK		0x00000001
+#define	CST4336_SPROM_PRESENT		0x00000002
+#define	CST4336_OTP_PRESENT		0x00000004
+#define	CST4336_ARMREMAP_0		0x00000008
+#define	CST4336_ILPDIV_EN_MASK		0x00000010
+#define	CST4336_ILPDIV_EN_SHIFT		4
+#define	CST4336_XTAL_PD_POL_MASK	0x00000020
+#define	CST4336_XTAL_PD_POL_SHIFT	5
+#define	CST4336_LPO_SEL_MASK		0x00000040
+#define	CST4336_LPO_SEL_SHIFT		6
+#define	CST4336_RES_INIT_MODE_MASK	0x00000180
+#define	CST4336_RES_INIT_MODE_SHIFT	7
+#define	CST4336_CBUCK_MODE_MASK		0x00000600
+#define	CST4336_CBUCK_MODE_SHIFT	9
+
+/* 4313 chip-specific ChipStatus register bits */
+#define	CST4313_SPROM_PRESENT			1
+#define	CST4313_OTP_PRESENT			2
+#define	CST4313_SPROM_OTP_SEL_MASK		0x00000002
+#define	CST4313_SPROM_OTP_SEL_SHIFT		0
+
+/* 4313 Chip specific ChipControl register bits */
+ /* 12 mA drive strengh for later 4313 */
+#define CCTRL_4313_12MA_LED_DRIVE    0x00000007
+
+/* Manufacturer Ids */
+#define	MFGID_ARM		0x43b
+#define	MFGID_BRCM		0x4bf
+#define	MFGID_MIPS		0x4a7
+
+/* Enumeration ROM registers */
+#define	ER_EROMENTRY		0x000
+#define	ER_REMAPCONTROL		0xe00
+#define	ER_REMAPSELECT		0xe04
+#define	ER_MASTERSELECT		0xe10
+#define	ER_ITCR			0xf00
+#define	ER_ITIP			0xf04
+
+/* Erom entries */
+#define	ER_TAG			0xe
+#define	ER_TAG1			0x6
+#define	ER_VALID		1
+#define	ER_CI			0
+#define	ER_MP			2
+#define	ER_ADD			4
+#define	ER_END			0xe
+#define	ER_BAD			0xffffffff
+
+/* EROM CompIdentA */
+#define	CIA_MFG_MASK		0xfff00000
+#define	CIA_MFG_SHIFT		20
+#define	CIA_CID_MASK		0x000fff00
+#define	CIA_CID_SHIFT		8
+#define	CIA_CCL_MASK		0x000000f0
+#define	CIA_CCL_SHIFT		4
+
+/* EROM CompIdentB */
+#define	CIB_REV_MASK		0xff000000
+#define	CIB_REV_SHIFT		24
+#define	CIB_NSW_MASK		0x00f80000
+#define	CIB_NSW_SHIFT		19
+#define	CIB_NMW_MASK		0x0007c000
+#define	CIB_NMW_SHIFT		14
+#define	CIB_NSP_MASK		0x00003e00
+#define	CIB_NSP_SHIFT		9
+#define	CIB_NMP_MASK		0x000001f0
+#define	CIB_NMP_SHIFT		4
+
+/* EROM AddrDesc */
+#define	AD_ADDR_MASK		0xfffff000
+#define	AD_SP_MASK		0x00000f00
+#define	AD_SP_SHIFT		8
+#define	AD_ST_MASK		0x000000c0
+#define	AD_ST_SHIFT		6
+#define	AD_ST_SLAVE		0x00000000
+#define	AD_ST_BRIDGE		0x00000040
+#define	AD_ST_SWRAP		0x00000080
+#define	AD_ST_MWRAP		0x000000c0
+#define	AD_SZ_MASK		0x00000030
+#define	AD_SZ_SHIFT		4
+#define	AD_SZ_4K		0x00000000
+#define	AD_SZ_8K		0x00000010
+#define	AD_SZ_16K		0x00000020
+#define	AD_SZ_SZD		0x00000030
+#define	AD_AG32			0x00000008
+#define	AD_ADDR_ALIGN		0x00000fff
+#define	AD_SZ_BASE		0x00001000	/* 4KB */
+
+/* EROM SizeDesc */
+#define	SD_SZ_MASK		0xfffff000
+#define	SD_SG32			0x00000008
+#define	SD_SZ_ALIGN		0x00000fff
+
+/* PCI config space bit 4 for 4306c0 slow clock source */
+#define	PCI_CFG_GPIO_SCS	0x10
+/* PCI config space GPIO 14 for Xtal power-up */
+#define PCI_CFG_GPIO_XTAL	0x40
+/* PCI config space GPIO 15 for PLL power-down */
+#define PCI_CFG_GPIO_PLL	0x80
+
+/* power control defines */
+#define PLL_DELAY		150	/* us pll on delay */
+#define FREF_DELAY		200	/* us fref change delay */
+#define	XTAL_ON_DELAY		1000	/* us crystal power-on delay */
+
+/* resetctrl */
+#define	AIRC_RESET		1
+
+#define	NOREV		-1	/* Invalid rev */
+
+/* GPIO Based LED powersave defines */
+#define DEFAULT_GPIO_ONTIME	10	/* Default: 10% on */
+#define DEFAULT_GPIO_OFFTIME	90	/* Default: 10% on */
+
+/* When Srom support present, fields in sromcontrol */
+#define	SRC_START		0x80000000
+#define	SRC_BUSY		0x80000000
+#define	SRC_OPCODE		0x60000000
+#define	SRC_OP_READ		0x00000000
+#define	SRC_OP_WRITE		0x20000000
+#define	SRC_OP_WRDIS		0x40000000
+#define	SRC_OP_WREN		0x60000000
+#define	SRC_OTPSEL		0x00000010
+#define	SRC_LOCK		0x00000008
+#define	SRC_SIZE_MASK		0x00000006
+#define	SRC_SIZE_1K		0x00000000
+#define	SRC_SIZE_4K		0x00000002
+#define	SRC_SIZE_16K		0x00000004
+#define	SRC_SIZE_SHIFT		1
+#define	SRC_PRESENT		0x00000001
+
+/* External PA enable mask */
+#define GPIO_CTRL_EPA_EN_MASK 0x40
+
+#define DEFAULT_GPIOTIMERVAL \
+	((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME)
+
+#define	BADIDX		(SI_MAXCORES + 1)
+
+#define	IS_SIM(chippkg)	\
+	((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID))
+
+#define	GOODCOREADDR(x, b) \
+	(((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \
+		IS_ALIGNED((x), SI_CORE_SIZE))
+
+struct aidmp {
+	u32 oobselina30;	/* 0x000 */
+	u32 oobselina74;	/* 0x004 */
+	u32 PAD[6];
+	u32 oobselinb30;	/* 0x020 */
+	u32 oobselinb74;	/* 0x024 */
+	u32 PAD[6];
+	u32 oobselinc30;	/* 0x040 */
+	u32 oobselinc74;	/* 0x044 */
+	u32 PAD[6];
+	u32 oobselind30;	/* 0x060 */
+	u32 oobselind74;	/* 0x064 */
+	u32 PAD[38];
+	u32 oobselouta30;	/* 0x100 */
+	u32 oobselouta74;	/* 0x104 */
+	u32 PAD[6];
+	u32 oobseloutb30;	/* 0x120 */
+	u32 oobseloutb74;	/* 0x124 */
+	u32 PAD[6];
+	u32 oobseloutc30;	/* 0x140 */
+	u32 oobseloutc74;	/* 0x144 */
+	u32 PAD[6];
+	u32 oobseloutd30;	/* 0x160 */
+	u32 oobseloutd74;	/* 0x164 */
+	u32 PAD[38];
+	u32 oobsynca;	/* 0x200 */
+	u32 oobseloutaen;	/* 0x204 */
+	u32 PAD[6];
+	u32 oobsyncb;	/* 0x220 */
+	u32 oobseloutben;	/* 0x224 */
+	u32 PAD[6];
+	u32 oobsyncc;	/* 0x240 */
+	u32 oobseloutcen;	/* 0x244 */
+	u32 PAD[6];
+	u32 oobsyncd;	/* 0x260 */
+	u32 oobseloutden;	/* 0x264 */
+	u32 PAD[38];
+	u32 oobaextwidth;	/* 0x300 */
+	u32 oobainwidth;	/* 0x304 */
+	u32 oobaoutwidth;	/* 0x308 */
+	u32 PAD[5];
+	u32 oobbextwidth;	/* 0x320 */
+	u32 oobbinwidth;	/* 0x324 */
+	u32 oobboutwidth;	/* 0x328 */
+	u32 PAD[5];
+	u32 oobcextwidth;	/* 0x340 */
+	u32 oobcinwidth;	/* 0x344 */
+	u32 oobcoutwidth;	/* 0x348 */
+	u32 PAD[5];
+	u32 oobdextwidth;	/* 0x360 */
+	u32 oobdinwidth;	/* 0x364 */
+	u32 oobdoutwidth;	/* 0x368 */
+	u32 PAD[37];
+	u32 ioctrlset;	/* 0x400 */
+	u32 ioctrlclear;	/* 0x404 */
+	u32 ioctrl;		/* 0x408 */
+	u32 PAD[61];
+	u32 iostatus;	/* 0x500 */
+	u32 PAD[127];
+	u32 ioctrlwidth;	/* 0x700 */
+	u32 iostatuswidth;	/* 0x704 */
+	u32 PAD[62];
+	u32 resetctrl;	/* 0x800 */
+	u32 resetstatus;	/* 0x804 */
+	u32 resetreadid;	/* 0x808 */
+	u32 resetwriteid;	/* 0x80c */
+	u32 PAD[60];
+	u32 errlogctrl;	/* 0x900 */
+	u32 errlogdone;	/* 0x904 */
+	u32 errlogstatus;	/* 0x908 */
+	u32 errlogaddrlo;	/* 0x90c */
+	u32 errlogaddrhi;	/* 0x910 */
+	u32 errlogid;	/* 0x914 */
+	u32 errloguser;	/* 0x918 */
+	u32 errlogflags;	/* 0x91c */
+	u32 PAD[56];
+	u32 intstatus;	/* 0xa00 */
+	u32 PAD[127];
+	u32 config;		/* 0xe00 */
+	u32 PAD[63];
+	u32 itcr;		/* 0xf00 */
+	u32 PAD[3];
+	u32 itipooba;	/* 0xf10 */
+	u32 itipoobb;	/* 0xf14 */
+	u32 itipoobc;	/* 0xf18 */
+	u32 itipoobd;	/* 0xf1c */
+	u32 PAD[4];
+	u32 itipoobaout;	/* 0xf30 */
+	u32 itipoobbout;	/* 0xf34 */
+	u32 itipoobcout;	/* 0xf38 */
+	u32 itipoobdout;	/* 0xf3c */
+	u32 PAD[4];
+	u32 itopooba;	/* 0xf50 */
+	u32 itopoobb;	/* 0xf54 */
+	u32 itopoobc;	/* 0xf58 */
+	u32 itopoobd;	/* 0xf5c */
+	u32 PAD[4];
+	u32 itopoobain;	/* 0xf70 */
+	u32 itopoobbin;	/* 0xf74 */
+	u32 itopoobcin;	/* 0xf78 */
+	u32 itopoobdin;	/* 0xf7c */
+	u32 PAD[4];
+	u32 itopreset;	/* 0xf90 */
+	u32 PAD[15];
+	u32 peripherialid4;	/* 0xfd0 */
+	u32 peripherialid5;	/* 0xfd4 */
+	u32 peripherialid6;	/* 0xfd8 */
+	u32 peripherialid7;	/* 0xfdc */
+	u32 peripherialid0;	/* 0xfe0 */
+	u32 peripherialid1;	/* 0xfe4 */
+	u32 peripherialid2;	/* 0xfe8 */
+	u32 peripherialid3;	/* 0xfec */
+	u32 componentid0;	/* 0xff0 */
+	u32 componentid1;	/* 0xff4 */
+	u32 componentid2;	/* 0xff8 */
+	u32 componentid3;	/* 0xffc */
+};
+
+static bool
+ai_buscore_setup(struct si_info *sii, struct bcma_device *cc)
+{
+	/* no cores found, bail out */
+	if (cc->bus->nr_cores == 0)
+		return false;
+
+	/* get chipcommon rev */
+	sii->pub.ccrev = cc->id.rev;
+
+	/* get chipcommon chipstatus */
+	sii->chipst = bcma_read32(cc, CHIPCREGOFFS(chipstatus));
+
+	/* get chipcommon capabilites */
+	sii->pub.cccaps = bcma_read32(cc, CHIPCREGOFFS(capabilities));
+
+	/* get pmu rev and caps */
+	if (ai_get_cccaps(&sii->pub) & CC_CAP_PMU) {
+		sii->pub.pmucaps = bcma_read32(cc,
+					       CHIPCREGOFFS(pmucapabilities));
+		sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
+	}
+
+	return true;
+}
+
+static struct si_info *ai_doattach(struct si_info *sii,
+				   struct bcma_bus *pbus)
+{
+	struct si_pub *sih = &sii->pub;
+	struct bcma_device *cc;
+
+	sii->icbus = pbus;
+	sii->pcibus = pbus->host_pci;
+
+	/* switch to Chipcommon core */
+	cc = pbus->drv_cc.core;
+
+	sih->chip = pbus->chipinfo.id;
+	sih->chiprev = pbus->chipinfo.rev;
+	sih->chippkg = pbus->chipinfo.pkg;
+	sih->boardvendor = pbus->boardinfo.vendor;
+	sih->boardtype = pbus->boardinfo.type;
+
+	if (!ai_buscore_setup(sii, cc))
+		goto exit;
+
+	/* === NVRAM, clock is ready === */
+	bcma_write32(cc, CHIPCREGOFFS(gpiopullup), 0);
+	bcma_write32(cc, CHIPCREGOFFS(gpiopulldown), 0);
+
+	/* PMU specific initializations */
+	if (ai_get_cccaps(sih) & CC_CAP_PMU) {
+		(void)si_pmu_measure_alpclk(sih);
+	}
+
+	return sii;
+
+ exit:
+
+	return NULL;
+}
+
+/*
+ * Allocate a si handle and do the attach.
+ */
+struct si_pub *
+ai_attach(struct bcma_bus *pbus)
+{
+	struct si_info *sii;
+
+	/* alloc struct si_info */
+	sii = kzalloc(sizeof(struct si_info), GFP_ATOMIC);
+	if (sii == NULL)
+		return NULL;
+
+	if (ai_doattach(sii, pbus) == NULL) {
+		kfree(sii);
+		return NULL;
+	}
+
+	return (struct si_pub *) sii;
+}
+
+/* may be called with core in reset */
+void ai_detach(struct si_pub *sih)
+{
+	struct si_info *sii;
+
+	sii = container_of(sih, struct si_info, pub);
+
+	if (sii == NULL)
+		return;
+
+	kfree(sii);
+}
+
+/*
+ * read/modify chipcommon core register.
+ */
+uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val)
+{
+	struct bcma_device *cc;
+	u32 w;
+	struct si_info *sii;
+
+	sii = container_of(sih, struct si_info, pub);
+	cc = sii->icbus->drv_cc.core;
+
+	/* mask and set */
+	if (mask || val)
+		bcma_maskset32(cc, regoff, ~mask, val);
+
+	/* readback */
+	w = bcma_read32(cc, regoff);
+
+	return w;
+}
+
+/* return the slow clock source - LPO, XTAL, or PCI */
+static uint ai_slowclk_src(struct si_pub *sih, struct bcma_device *cc)
+{
+	return SCC_SS_XTAL;
+}
+
+/*
+* return the ILP (slowclock) min or max frequency
+* precondition: we've established the chip has dynamic clk control
+*/
+static uint ai_slowclk_freq(struct si_pub *sih, bool max_freq,
+			    struct bcma_device *cc)
+{
+	uint div;
+
+	/* Chipc rev 10 is InstaClock */
+	div = bcma_read32(cc, CHIPCREGOFFS(system_clk_ctl));
+	div = 4 * ((div >> SYCC_CD_SHIFT) + 1);
+	return max_freq ? XTALMAXFREQ : (XTALMINFREQ / div);
+}
+
+static void
+ai_clkctl_setdelay(struct si_pub *sih, struct bcma_device *cc)
+{
+	uint slowmaxfreq, pll_delay, slowclk;
+	uint pll_on_delay, fref_sel_delay;
+
+	pll_delay = PLL_DELAY;
+
+	/*
+	 * If the slow clock is not sourced by the xtal then
+	 * add the xtal_on_delay since the xtal will also be
+	 * powered down by dynamic clk control logic.
+	 */
+
+	slowclk = ai_slowclk_src(sih, cc);
+	if (slowclk != SCC_SS_XTAL)
+		pll_delay += XTAL_ON_DELAY;
+
+	/* Starting with 4318 it is ILP that is used for the delays */
+	slowmaxfreq =
+	    ai_slowclk_freq(sih, false, cc);
+
+	pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
+	fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
+
+	bcma_write32(cc, CHIPCREGOFFS(pll_on_delay), pll_on_delay);
+	bcma_write32(cc, CHIPCREGOFFS(fref_sel_delay), fref_sel_delay);
+}
+
+/* initialize power control delay registers */
+void ai_clkctl_init(struct si_pub *sih)
+{
+	struct si_info *sii = container_of(sih, struct si_info, pub);
+	struct bcma_device *cc;
+
+	if (!(ai_get_cccaps(sih) & CC_CAP_PWR_CTL))
+		return;
+
+	cc = sii->icbus->drv_cc.core;
+	if (cc == NULL)
+		return;
+
+	/* set all Instaclk chip ILP to 1 MHz */
+	bcma_maskset32(cc, CHIPCREGOFFS(system_clk_ctl), SYCC_CD_MASK,
+		       (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
+
+	ai_clkctl_setdelay(sih, cc);
+}
+
+/*
+ * return the value suitable for writing to the
+ * dot11 core FAST_PWRUP_DELAY register
+ */
+u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih)
+{
+	struct si_info *sii;
+	struct bcma_device *cc;
+	uint slowminfreq;
+	u16 fpdelay;
+
+	sii = container_of(sih, struct si_info, pub);
+	if (ai_get_cccaps(sih) & CC_CAP_PMU) {
+		fpdelay = si_pmu_fast_pwrup_delay(sih);
+		return fpdelay;
+	}
+
+	if (!(ai_get_cccaps(sih) & CC_CAP_PWR_CTL))
+		return 0;
+
+	fpdelay = 0;
+	cc = sii->icbus->drv_cc.core;
+	if (cc) {
+		slowminfreq = ai_slowclk_freq(sih, false, cc);
+		fpdelay = (((bcma_read32(cc, CHIPCREGOFFS(pll_on_delay)) + 2)
+			    * 1000000) + (slowminfreq - 1)) / slowminfreq;
+	}
+	return fpdelay;
+}
+
+/*
+ *  clock control policy function throught chipcommon
+ *
+ *    set dynamic clk control mode (forceslow, forcefast, dynamic)
+ *    returns true if we are forcing fast clock
+ *    this is a wrapper over the next internal function
+ *      to allow flexible policy settings for outside caller
+ */
+bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode)
+{
+	struct si_info *sii;
+	struct bcma_device *cc;
+
+	sii = container_of(sih, struct si_info, pub);
+
+	cc = sii->icbus->drv_cc.core;
+	bcma_core_set_clockmode(cc, mode);
+	return mode == BCMA_CLKMODE_FAST;
+}
+
+/* Enable BT-COEX & Ex-PA for 4313 */
+void ai_epa_4313war(struct si_pub *sih)
+{
+	struct si_info *sii = container_of(sih, struct si_info, pub);
+	struct bcma_device *cc;
+
+	cc = sii->icbus->drv_cc.core;
+
+	/* EPA Fix */
+	bcma_set32(cc, CHIPCREGOFFS(gpiocontrol), GPIO_CTRL_EPA_EN_MASK);
+}
+
+/* check if the device is removed */
+bool ai_deviceremoved(struct si_pub *sih)
+{
+	u32 w = 0;
+	struct si_info *sii;
+
+	sii = container_of(sih, struct si_info, pub);
+
+	if (sii->icbus->hosttype != BCMA_HOSTTYPE_PCI)
+		return false;
+
+	pci_read_config_dword(sii->pcibus, PCI_VENDOR_ID, &w);
+	if ((w & 0xFFFF) != PCI_VENDOR_ID_BROADCOM)
+		return true;
+
+	return false;
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/aiutils.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/aiutils.h
new file mode 100644
index 0000000..2d08c15
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/aiutils.h
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_BRCM_AIUTILS_H_
+#define	_BRCM_AIUTILS_H_
+
+#include <linux/bcma/bcma.h>
+
+#include "types.h"
+
+/*
+ * SOC Interconnect Address Map.
+ * All regions may not exist on all chips.
+ */
+/* each core gets 4Kbytes for registers */
+#define SI_CORE_SIZE		0x1000
+/*
+ * Max cores (this is arbitrary, for software
+ * convenience and could be changed if we
+ * make any larger chips
+ */
+#define	SI_MAXCORES		16
+
+/* Client Mode sb2pcitranslation2 size in bytes */
+#define SI_PCI_DMA_SZ		0x40000000
+
+/* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), high 32 bits */
+#define SI_PCIE_DMA_H32		0x80000000
+
+/* chipcommon being the first core: */
+#define	SI_CC_IDX		0
+
+/* SOC Interconnect types (aka chip types) */
+#define	SOCI_AI			1
+
+/* A register that is common to all cores to
+ * communicate w/PMU regarding clock control.
+ */
+#define SI_CLK_CTL_ST		0x1e0	/* clock control and status */
+
+/* clk_ctl_st register */
+#define	CCS_FORCEALP		0x00000001	/* force ALP request */
+#define	CCS_FORCEHT		0x00000002	/* force HT request */
+#define	CCS_FORCEILP		0x00000004	/* force ILP request */
+#define	CCS_ALPAREQ		0x00000008	/* ALP Avail Request */
+#define	CCS_HTAREQ		0x00000010	/* HT Avail Request */
+#define	CCS_FORCEHWREQOFF	0x00000020	/* Force HW Clock Request Off */
+#define CCS_ERSRC_REQ_MASK	0x00000700	/* external resource requests */
+#define CCS_ERSRC_REQ_SHIFT	8
+#define	CCS_ALPAVAIL		0x00010000	/* ALP is available */
+#define	CCS_HTAVAIL		0x00020000	/* HT is available */
+#define CCS_BP_ON_APL		0x00040000	/* RO: running on ALP clock */
+#define CCS_BP_ON_HT		0x00080000	/* RO: running on HT clock */
+#define CCS_ERSRC_STS_MASK	0x07000000	/* external resource status */
+#define CCS_ERSRC_STS_SHIFT	24
+
+/* HT avail in chipc and pcmcia on 4328a0 */
+#define	CCS0_HTAVAIL		0x00010000
+/* ALP avail in chipc and pcmcia on 4328a0 */
+#define	CCS0_ALPAVAIL		0x00020000
+
+/* Not really related to SOC Interconnect, but a couple of software
+ * conventions for the use the flash space:
+ */
+
+/* Minumum amount of flash we support */
+#define FLASH_MIN		0x00020000	/* Minimum flash size */
+
+#define	CC_SROM_OTP		0x800	/* SROM/OTP address space */
+
+/* gpiotimerval */
+#define GPIO_ONTIME_SHIFT	16
+
+/* Fields in clkdiv */
+#define	CLKD_OTP		0x000f0000
+#define	CLKD_OTP_SHIFT		16
+
+/* dynamic clock control defines */
+#define	LPOMINFREQ		25000	/* low power oscillator min */
+#define	LPOMAXFREQ		43000	/* low power oscillator max */
+#define	XTALMINFREQ		19800000	/* 20 MHz - 1% */
+#define	XTALMAXFREQ		20200000	/* 20 MHz + 1% */
+#define	PCIMINFREQ		25000000	/* 25 MHz */
+#define	PCIMAXFREQ		34000000	/* 33 MHz + fudge */
+
+#define	ILP_DIV_5MHZ		0	/* ILP = 5 MHz */
+#define	ILP_DIV_1MHZ		4	/* ILP = 1 MHz */
+
+/* clkctl xtal what flags */
+#define	XTAL			0x1	/* primary crystal oscillator (2050) */
+#define	PLL			0x2	/* main chip pll */
+
+/* GPIO usage priorities */
+#define GPIO_DRV_PRIORITY	0	/* Driver */
+#define GPIO_APP_PRIORITY	1	/* Application */
+#define GPIO_HI_PRIORITY	2	/* Highest priority. Ignore GPIO
+					 * reservation
+					 */
+
+/* GPIO pull up/down */
+#define GPIO_PULLUP		0
+#define GPIO_PULLDN		1
+
+/* GPIO event regtype */
+#define GPIO_REGEVT		0	/* GPIO register event */
+#define GPIO_REGEVT_INTMSK	1	/* GPIO register event int mask */
+#define GPIO_REGEVT_INTPOL	2	/* GPIO register event int polarity */
+
+/* device path */
+#define SI_DEVPATH_BUFSZ	16	/* min buffer size in bytes */
+
+/* SI routine enumeration: to be used by update function with multiple hooks */
+#define	SI_DOATTACH	1
+#define SI_PCIDOWN	2
+#define SI_PCIUP	3
+
+/*
+ * Data structure to export all chip specific common variables
+ *   public (read-only) portion of aiutils handle returned by si_attach()
+ */
+struct si_pub {
+	int ccrev;		/* chip common core rev */
+	u32 cccaps;		/* chip common capabilities */
+	int pmurev;		/* pmu core rev */
+	u32 pmucaps;		/* pmu capabilities */
+	uint boardtype;		/* board type */
+	uint boardvendor;	/* board vendor */
+	uint chip;		/* chip number */
+	uint chiprev;		/* chip revision */
+	uint chippkg;		/* chip package option */
+};
+
+struct pci_dev;
+
+struct gpioh_item {
+	void *arg;
+	bool level;
+	void (*handler) (u32 stat, void *arg);
+	u32 event;
+	struct gpioh_item *next;
+};
+
+/* misc si info needed by some of the routines */
+struct si_info {
+	struct si_pub pub;	/* back plane public state (must be first) */
+	struct bcma_bus *icbus;	/* handle to soc interconnect bus */
+	struct pci_dev *pcibus;	/* handle to pci bus */
+
+	u32 chipst;		/* chip status */
+};
+
+/*
+ * Many of the routines below take an 'sih' handle as their first arg.
+ * Allocate this by calling si_attach().  Free it by calling si_detach().
+ * At any one time, the sih is logically focused on one particular si core
+ * (the "current core").
+ * Use si_setcore() or si_setcoreidx() to change the association to another core
+ */
+
+
+/* AMBA Interconnect exported externs */
+u32 ai_core_cflags(struct bcma_device *core, u32 mask, u32 val);
+
+/* === exported functions === */
+struct si_pub *ai_attach(struct bcma_bus *pbus);
+void ai_detach(struct si_pub *sih);
+uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val);
+void ai_clkctl_init(struct si_pub *sih);
+u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih);
+bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode);
+bool ai_deviceremoved(struct si_pub *sih);
+
+/* Enable Ex-PA for 4313 */
+void ai_epa_4313war(struct si_pub *sih);
+
+static inline u32 ai_get_cccaps(struct si_pub *sih)
+{
+	return sih->cccaps;
+}
+
+static inline int ai_get_pmurev(struct si_pub *sih)
+{
+	return sih->pmurev;
+}
+
+static inline u32 ai_get_pmucaps(struct si_pub *sih)
+{
+	return sih->pmucaps;
+}
+
+static inline uint ai_get_boardtype(struct si_pub *sih)
+{
+	return sih->boardtype;
+}
+
+static inline uint ai_get_boardvendor(struct si_pub *sih)
+{
+	return sih->boardvendor;
+}
+
+static inline uint ai_get_chip_id(struct si_pub *sih)
+{
+	return sih->chip;
+}
+
+static inline uint ai_get_chiprev(struct si_pub *sih)
+{
+	return sih->chiprev;
+}
+
+static inline uint ai_get_chippkg(struct si_pub *sih)
+{
+	return sih->chippkg;
+}
+
+#endif				/* _BRCM_AIUTILS_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c
new file mode 100644
index 0000000..fa391e4
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c
@@ -0,0 +1,1144 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <net/mac80211.h>
+
+#include "rate.h"
+#include "scb.h"
+#include "phy/phy_hal.h"
+#include "antsel.h"
+#include "main.h"
+#include "ampdu.h"
+#include "debug.h"
+#include "brcms_trace_events.h"
+
+/* max number of mpdus in an ampdu */
+#define AMPDU_MAX_MPDU			32
+/* max number of mpdus in an ampdu to a legacy */
+#define AMPDU_NUM_MPDU_LEGACY		16
+/* max Tx ba window size (in pdu) */
+#define AMPDU_TX_BA_MAX_WSIZE		64
+/* default Tx ba window size (in pdu) */
+#define AMPDU_TX_BA_DEF_WSIZE		64
+/* default Rx ba window size (in pdu) */
+#define AMPDU_RX_BA_DEF_WSIZE		64
+/* max Rx ba window size (in pdu) */
+#define AMPDU_RX_BA_MAX_WSIZE		64
+/* max dur of tx ampdu (in msec) */
+#define	AMPDU_MAX_DUR			5
+/* default tx retry limit */
+#define AMPDU_DEF_RETRY_LIMIT		5
+/* default tx retry limit at reg rate */
+#define AMPDU_DEF_RR_RETRY_LIMIT	2
+/* default ffpld reserved bytes */
+#define AMPDU_DEF_FFPLD_RSVD		2048
+/* # of inis to be freed on detach */
+#define AMPDU_INI_FREE			10
+/* max # of mpdus released at a time */
+#define	AMPDU_SCB_MAX_RELEASE		20
+
+#define NUM_FFPLD_FIFO 4	/* number of fifo concerned by pre-loading */
+#define FFPLD_TX_MAX_UNFL   200	/* default value of the average number of ampdu
+				 * without underflows
+				 */
+#define FFPLD_MPDU_SIZE 1800	/* estimate of maximum mpdu size */
+#define FFPLD_MAX_MCS 23	/* we don't deal with mcs 32 */
+#define FFPLD_PLD_INCR 1000	/* increments in bytes */
+#define FFPLD_MAX_AMPDU_CNT 5000	/* maximum number of ampdu we
+					 * accumulate between resets.
+					 */
+
+#define AMPDU_DELIMITER_LEN	4
+
+/* max allowed number of mpdus in an ampdu (2 streams) */
+#define AMPDU_NUM_MPDU		16
+
+#define TX_SEQ_TO_INDEX(seq) ((seq) % AMPDU_TX_BA_MAX_WSIZE)
+
+/* max possible overhead per mpdu in the ampdu; 3 is for roundup if needed */
+#define AMPDU_MAX_MPDU_OVERHEAD (FCS_LEN + DOT11_ICV_AES_LEN +\
+	AMPDU_DELIMITER_LEN + 3\
+	+ DOT11_A4_HDR_LEN + DOT11_QOS_LEN + DOT11_IV_MAX_LEN)
+
+/* modulo add/sub, bound = 2^k */
+#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1))
+#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1))
+
+/* structure to hold tx fifo information and pre-loading state
+ * counters specific to tx underflows of ampdus
+ * some counters might be redundant with the ones in wlc or ampdu structures.
+ * This allows to maintain a specific state independently of
+ * how often and/or when the wlc counters are updated.
+ *
+ * ampdu_pld_size: number of bytes to be pre-loaded
+ * mcs2ampdu_table: per-mcs max # of mpdus in an ampdu
+ * prev_txfunfl: num of underflows last read from the HW macstats counter
+ * accum_txfunfl: num of underflows since we modified pld params
+ * accum_txampdu: num of tx ampdu since we modified pld params
+ * prev_txampdu: previous reading of tx ampdu
+ * dmaxferrate: estimated dma avg xfer rate in kbits/sec
+ */
+struct brcms_fifo_info {
+	u16 ampdu_pld_size;
+	u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1];
+	u16 prev_txfunfl;
+	u32 accum_txfunfl;
+	u32 accum_txampdu;
+	u32 prev_txampdu;
+	u32 dmaxferrate;
+};
+
+/* AMPDU module specific state
+ *
+ * wlc: pointer to main wlc structure
+ * scb_handle: scb cubby handle to retrieve data from scb
+ * ini_enable: per-tid initiator enable/disable of ampdu
+ * ba_tx_wsize: Tx ba window size (in pdu)
+ * ba_rx_wsize: Rx ba window size (in pdu)
+ * retry_limit: mpdu transmit retry limit
+ * rr_retry_limit: mpdu transmit retry limit at regular rate
+ * retry_limit_tid: per-tid mpdu transmit retry limit
+ * rr_retry_limit_tid: per-tid mpdu transmit retry limit at regular rate
+ * mpdu_density: min mpdu spacing (0-7) ==> 2^(x-1)/8 usec
+ * max_pdu: max pdus allowed in ampdu
+ * dur: max duration of an ampdu (in msec)
+ * rx_factor: maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes
+ * ffpld_rsvd: number of bytes to reserve for preload
+ * max_txlen: max size of ampdu per mcs, bw and sgi
+ * mfbr: enable multiple fallback rate
+ * tx_max_funl: underflows should be kept such that
+ *		(tx_max_funfl*underflows) < tx frames
+ * fifo_tb: table of fifo infos
+ */
+struct ampdu_info {
+	struct brcms_c_info *wlc;
+	int scb_handle;
+	u8 ini_enable[AMPDU_MAX_SCB_TID];
+	u8 ba_tx_wsize;
+	u8 ba_rx_wsize;
+	u8 retry_limit;
+	u8 rr_retry_limit;
+	u8 retry_limit_tid[AMPDU_MAX_SCB_TID];
+	u8 rr_retry_limit_tid[AMPDU_MAX_SCB_TID];
+	u8 mpdu_density;
+	s8 max_pdu;
+	u8 dur;
+	u8 rx_factor;
+	u32 ffpld_rsvd;
+	u32 max_txlen[MCS_TABLE_SIZE][2][2];
+	bool mfbr;
+	u32 tx_max_funl;
+	struct brcms_fifo_info fifo_tb[NUM_FFPLD_FIFO];
+};
+
+/* used for flushing ampdu packets */
+struct cb_del_ampdu_pars {
+	struct ieee80211_sta *sta;
+	u16 tid;
+};
+
+static void brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur)
+{
+	u32 rate, mcs;
+
+	for (mcs = 0; mcs < MCS_TABLE_SIZE; mcs++) {
+		/* rate is in Kbps; dur is in msec ==> len = (rate * dur) / 8 */
+		/* 20MHz, No SGI */
+		rate = mcs_2_rate(mcs, false, false);
+		ampdu->max_txlen[mcs][0][0] = (rate * dur) >> 3;
+		/* 40 MHz, No SGI */
+		rate = mcs_2_rate(mcs, true, false);
+		ampdu->max_txlen[mcs][1][0] = (rate * dur) >> 3;
+		/* 20MHz, SGI */
+		rate = mcs_2_rate(mcs, false, true);
+		ampdu->max_txlen[mcs][0][1] = (rate * dur) >> 3;
+		/* 40 MHz, SGI */
+		rate = mcs_2_rate(mcs, true, true);
+		ampdu->max_txlen[mcs][1][1] = (rate * dur) >> 3;
+	}
+}
+
+static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu)
+{
+	if (BRCMS_PHY_11N_CAP(ampdu->wlc->band))
+		return true;
+	else
+		return false;
+}
+
+static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on)
+{
+	struct brcms_c_info *wlc = ampdu->wlc;
+	struct bcma_device *core = wlc->hw->d11core;
+
+	wlc->pub->_ampdu = false;
+
+	if (on) {
+		if (!(wlc->pub->_n_enab & SUPPORT_11N)) {
+			brcms_err(core, "wl%d: driver not nmode enabled\n",
+				  wlc->pub->unit);
+			return -ENOTSUPP;
+		}
+		if (!brcms_c_ampdu_cap(ampdu)) {
+			brcms_err(core, "wl%d: device not ampdu capable\n",
+				  wlc->pub->unit);
+			return -ENOTSUPP;
+		}
+		wlc->pub->_ampdu = on;
+	}
+
+	return 0;
+}
+
+static void brcms_c_ffpld_init(struct ampdu_info *ampdu)
+{
+	int i, j;
+	struct brcms_fifo_info *fifo;
+
+	for (j = 0; j < NUM_FFPLD_FIFO; j++) {
+		fifo = (ampdu->fifo_tb + j);
+		fifo->ampdu_pld_size = 0;
+		for (i = 0; i <= FFPLD_MAX_MCS; i++)
+			fifo->mcs2ampdu_table[i] = 255;
+		fifo->dmaxferrate = 0;
+		fifo->accum_txampdu = 0;
+		fifo->prev_txfunfl = 0;
+		fifo->accum_txfunfl = 0;
+
+	}
+}
+
+struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc)
+{
+	struct ampdu_info *ampdu;
+	int i;
+
+	ampdu = kzalloc(sizeof(struct ampdu_info), GFP_ATOMIC);
+	if (!ampdu)
+		return NULL;
+
+	ampdu->wlc = wlc;
+
+	for (i = 0; i < AMPDU_MAX_SCB_TID; i++)
+		ampdu->ini_enable[i] = true;
+	/* Disable ampdu for VO by default */
+	ampdu->ini_enable[PRIO_8021D_VO] = false;
+	ampdu->ini_enable[PRIO_8021D_NC] = false;
+
+	/* Disable ampdu for BK by default since not enough fifo space */
+	ampdu->ini_enable[PRIO_8021D_NONE] = false;
+	ampdu->ini_enable[PRIO_8021D_BK] = false;
+
+	ampdu->ba_tx_wsize = AMPDU_TX_BA_DEF_WSIZE;
+	ampdu->ba_rx_wsize = AMPDU_RX_BA_DEF_WSIZE;
+	ampdu->mpdu_density = AMPDU_DEF_MPDU_DENSITY;
+	ampdu->max_pdu = AUTO;
+	ampdu->dur = AMPDU_MAX_DUR;
+
+	ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD;
+	/*
+	 * bump max ampdu rcv size to 64k for all 11n
+	 * devices except 4321A0 and 4321A1
+	 */
+	if (BRCMS_ISNPHY(wlc->band) && NREV_LT(wlc->band->phyrev, 2))
+		ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_32K;
+	else
+		ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_64K;
+	ampdu->retry_limit = AMPDU_DEF_RETRY_LIMIT;
+	ampdu->rr_retry_limit = AMPDU_DEF_RR_RETRY_LIMIT;
+
+	for (i = 0; i < AMPDU_MAX_SCB_TID; i++) {
+		ampdu->retry_limit_tid[i] = ampdu->retry_limit;
+		ampdu->rr_retry_limit_tid[i] = ampdu->rr_retry_limit;
+	}
+
+	brcms_c_scb_ampdu_update_max_txlen(ampdu, ampdu->dur);
+	ampdu->mfbr = false;
+	/* try to set ampdu to the default value */
+	brcms_c_ampdu_set(ampdu, wlc->pub->_ampdu);
+
+	ampdu->tx_max_funl = FFPLD_TX_MAX_UNFL;
+	brcms_c_ffpld_init(ampdu);
+
+	return ampdu;
+}
+
+void brcms_c_ampdu_detach(struct ampdu_info *ampdu)
+{
+	kfree(ampdu);
+}
+
+static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu,
+					    struct scb *scb)
+{
+	struct scb_ampdu *scb_ampdu = &scb->scb_ampdu;
+	int i;
+
+	scb_ampdu->max_pdu = AMPDU_NUM_MPDU;
+
+	/* go back to legacy size if some preloading is occurring */
+	for (i = 0; i < NUM_FFPLD_FIFO; i++) {
+		if (ampdu->fifo_tb[i].ampdu_pld_size > FFPLD_PLD_INCR)
+			scb_ampdu->max_pdu = AMPDU_NUM_MPDU_LEGACY;
+	}
+
+	/* apply user override */
+	if (ampdu->max_pdu != AUTO)
+		scb_ampdu->max_pdu = (u8) ampdu->max_pdu;
+
+	scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu,
+				   AMPDU_SCB_MAX_RELEASE);
+
+	if (scb_ampdu->max_rx_ampdu_bytes)
+		scb_ampdu->release = min_t(u8, scb_ampdu->release,
+			scb_ampdu->max_rx_ampdu_bytes / 1600);
+
+	scb_ampdu->release = min(scb_ampdu->release,
+				 ampdu->fifo_tb[TX_AC_BE_FIFO].
+				 mcs2ampdu_table[FFPLD_MAX_MCS]);
+}
+
+static void brcms_c_scb_ampdu_update_config_all(struct ampdu_info *ampdu)
+{
+	brcms_c_scb_ampdu_update_config(ampdu, &ampdu->wlc->pri_scb);
+}
+
+static void brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f)
+{
+	int i;
+	u32 phy_rate, dma_rate, tmp;
+	u8 max_mpdu;
+	struct brcms_fifo_info *fifo = (ampdu->fifo_tb + f);
+
+	/* recompute the dma rate */
+	/* note : we divide/multiply by 100 to avoid integer overflows */
+	max_mpdu = min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS],
+			 AMPDU_NUM_MPDU_LEGACY);
+	phy_rate = mcs_2_rate(FFPLD_MAX_MCS, true, false);
+	dma_rate =
+	    (((phy_rate / 100) *
+	      (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
+	     / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
+	fifo->dmaxferrate = dma_rate;
+
+	/* fill up the mcs2ampdu table; do not recalc the last mcs */
+	dma_rate = dma_rate >> 7;
+	for (i = 0; i < FFPLD_MAX_MCS; i++) {
+		/* shifting to keep it within integer range */
+		phy_rate = mcs_2_rate(i, true, false) >> 7;
+		if (phy_rate > dma_rate) {
+			tmp = ((fifo->ampdu_pld_size * phy_rate) /
+			       ((phy_rate - dma_rate) * FFPLD_MPDU_SIZE)) + 1;
+			tmp = min_t(u32, tmp, 255);
+			fifo->mcs2ampdu_table[i] = (u8) tmp;
+		}
+	}
+}
+
+/* evaluate the dma transfer rate using the tx underflows as feedback.
+ * If necessary, increase tx fifo preloading. If not enough,
+ * decrease maximum ampdu size for each mcs till underflows stop
+ * Return 1 if pre-loading not active, -1 if not an underflow event,
+ * 0 if pre-loading module took care of the event.
+ */
+static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
+{
+	struct ampdu_info *ampdu = wlc->ampdu;
+	u32 phy_rate = mcs_2_rate(FFPLD_MAX_MCS, true, false);
+	u32 txunfl_ratio;
+	u8 max_mpdu;
+	u32 current_ampdu_cnt = 0;
+	u16 max_pld_size;
+	u32 new_txunfl;
+	struct brcms_fifo_info *fifo = (ampdu->fifo_tb + fid);
+	uint xmtfifo_sz;
+	u16 cur_txunfl;
+
+	/* return if we got here for a different reason than underflows */
+	cur_txunfl = brcms_b_read_shm(wlc->hw,
+				      M_UCODE_MACSTAT +
+				      offsetof(struct macstat, txfunfl[fid]));
+	new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl);
+	if (new_txunfl == 0) {
+		brcms_dbg_ht(wlc->hw->d11core,
+			     "TX status FRAG set but no tx underflows\n");
+		return -1;
+	}
+	fifo->prev_txfunfl = cur_txunfl;
+
+	if (!ampdu->tx_max_funl)
+		return 1;
+
+	/* check if fifo is big enough */
+	if (brcms_b_xmtfifo_sz_get(wlc->hw, fid, &xmtfifo_sz))
+		return -1;
+
+	if ((TXFIFO_SIZE_UNIT * (u32) xmtfifo_sz) <= ampdu->ffpld_rsvd)
+		return 1;
+
+	max_pld_size = TXFIFO_SIZE_UNIT * xmtfifo_sz - ampdu->ffpld_rsvd;
+	fifo->accum_txfunfl += new_txunfl;
+
+	/* we need to wait for at least 10 underflows */
+	if (fifo->accum_txfunfl < 10)
+		return 0;
+
+	brcms_dbg_ht(wlc->hw->d11core, "ampdu_count %d  tx_underflows %d\n",
+		     current_ampdu_cnt, fifo->accum_txfunfl);
+
+	/*
+	   compute the current ratio of tx unfl per ampdu.
+	   When the current ampdu count becomes too
+	   big while the ratio remains small, we reset
+	   the current count in order to not
+	   introduce too big of a latency in detecting a
+	   large amount of tx underflows later.
+	 */
+
+	txunfl_ratio = current_ampdu_cnt / fifo->accum_txfunfl;
+
+	if (txunfl_ratio > ampdu->tx_max_funl) {
+		if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT)
+			fifo->accum_txfunfl = 0;
+
+		return 0;
+	}
+	max_mpdu = min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS],
+			 AMPDU_NUM_MPDU_LEGACY);
+
+	/* In case max value max_pdu is already lower than
+	   the fifo depth, there is nothing more we can do.
+	 */
+
+	if (fifo->ampdu_pld_size >= max_mpdu * FFPLD_MPDU_SIZE) {
+		fifo->accum_txfunfl = 0;
+		return 0;
+	}
+
+	if (fifo->ampdu_pld_size < max_pld_size) {
+
+		/* increment by TX_FIFO_PLD_INC bytes */
+		fifo->ampdu_pld_size += FFPLD_PLD_INCR;
+		if (fifo->ampdu_pld_size > max_pld_size)
+			fifo->ampdu_pld_size = max_pld_size;
+
+		/* update scb release size */
+		brcms_c_scb_ampdu_update_config_all(ampdu);
+
+		/*
+		 * compute a new dma xfer rate for max_mpdu @ max mcs.
+		 * This is the minimum dma rate that can achieve no
+		 * underflow condition for the current mpdu size.
+		 *
+		 * note : we divide/multiply by 100 to avoid integer overflows
+		 */
+		fifo->dmaxferrate =
+		    (((phy_rate / 100) *
+		      (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
+		     / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
+
+		brcms_dbg_ht(wlc->hw->d11core,
+			     "DMA estimated transfer rate %d; "
+			     "pre-load size %d\n",
+			     fifo->dmaxferrate, fifo->ampdu_pld_size);
+	} else {
+
+		/* decrease ampdu size */
+		if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] > 1) {
+			if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] == 255)
+				fifo->mcs2ampdu_table[FFPLD_MAX_MCS] =
+				    AMPDU_NUM_MPDU_LEGACY - 1;
+			else
+				fifo->mcs2ampdu_table[FFPLD_MAX_MCS] -= 1;
+
+			/* recompute the table */
+			brcms_c_ffpld_calc_mcs2ampdu_table(ampdu, fid);
+
+			/* update scb release size */
+			brcms_c_scb_ampdu_update_config_all(ampdu);
+		}
+	}
+	fifo->accum_txfunfl = 0;
+	return 0;
+}
+
+void
+brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
+	u8 ba_wsize,		/* negotiated ba window size (in pdu) */
+	uint max_rx_ampdu_bytes) /* from ht_cap in beacon */
+{
+	struct scb_ampdu *scb_ampdu;
+	struct scb_ampdu_tid_ini *ini;
+	struct ampdu_info *ampdu = wlc->ampdu;
+	struct scb *scb = &wlc->pri_scb;
+	scb_ampdu = &scb->scb_ampdu;
+
+	if (!ampdu->ini_enable[tid]) {
+		brcms_err(wlc->hw->d11core, "%s: Rejecting tid %d\n",
+			  __func__, tid);
+		return;
+	}
+
+	ini = &scb_ampdu->ini[tid];
+	ini->tid = tid;
+	ini->scb = scb_ampdu->scb;
+	ini->ba_wsize = ba_wsize;
+	scb_ampdu->max_rx_ampdu_bytes = max_rx_ampdu_bytes;
+}
+
+void brcms_c_ampdu_reset_session(struct brcms_ampdu_session *session,
+				 struct brcms_c_info *wlc)
+{
+	session->wlc = wlc;
+	skb_queue_head_init(&session->skb_list);
+	session->max_ampdu_len = 0;    /* determined from first MPDU */
+	session->max_ampdu_frames = 0; /* determined from first MPDU */
+	session->ampdu_len = 0;
+	session->dma_len = 0;
+}
+
+/*
+ * Preps the given packet for AMPDU based on the session data. If the
+ * frame cannot be accomodated in the current session, -ENOSPC is
+ * returned.
+ */
+int brcms_c_ampdu_add_frame(struct brcms_ampdu_session *session,
+			    struct sk_buff *p)
+{
+	struct brcms_c_info *wlc = session->wlc;
+	struct ampdu_info *ampdu = wlc->ampdu;
+	struct scb *scb = &wlc->pri_scb;
+	struct scb_ampdu *scb_ampdu = &scb->scb_ampdu;
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
+	struct ieee80211_tx_rate *txrate = tx_info->status.rates;
+	struct d11txh *txh = (struct d11txh *)p->data;
+	unsigned ampdu_frames;
+	u8 ndelim, tid;
+	u8 *plcp;
+	uint len;
+	u16 mcl;
+	bool fbr_iscck;
+	bool rr;
+
+	ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
+	plcp = (u8 *)(txh + 1);
+	fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x03);
+	len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) :
+			  BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
+	len = roundup(len, 4) + (ndelim + 1) * AMPDU_DELIMITER_LEN;
+
+	ampdu_frames = skb_queue_len(&session->skb_list);
+	if (ampdu_frames != 0) {
+		struct sk_buff *first;
+
+		if (ampdu_frames + 1 > session->max_ampdu_frames ||
+		    session->ampdu_len + len > session->max_ampdu_len)
+			return -ENOSPC;
+
+		/*
+		 * We aren't really out of space if the new frame is of
+		 * a different priority, but we want the same behaviour
+		 * so return -ENOSPC anyway.
+		 *
+		 * XXX: The old AMPDU code did this, but is it really
+		 * necessary?
+		 */
+		first = skb_peek(&session->skb_list);
+		if (p->priority != first->priority)
+			return -ENOSPC;
+	}
+
+	/*
+	 * Now that we're sure this frame can be accomodated, update the
+	 * session information.
+	 */
+	session->ampdu_len += len;
+	session->dma_len += p->len;
+
+	tid = (u8)p->priority;
+
+	/* Handle retry limits */
+	if (txrate[0].count <= ampdu->rr_retry_limit_tid[tid]) {
+		txrate[0].count++;
+		rr = true;
+	} else {
+		txrate[1].count++;
+		rr = false;
+	}
+
+	if (ampdu_frames == 0) {
+		u8 plcp0, plcp3, is40, sgi, mcs;
+		uint fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK;
+		struct brcms_fifo_info *f = &ampdu->fifo_tb[fifo];
+
+		if (rr) {
+			plcp0 = plcp[0];
+			plcp3 = plcp[3];
+		} else {
+			plcp0 = txh->FragPLCPFallback[0];
+			plcp3 = txh->FragPLCPFallback[3];
+
+		}
+
+		/* Limit AMPDU size based on MCS */
+		is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
+		sgi = plcp3_issgi(plcp3) ? 1 : 0;
+		mcs = plcp0 & ~MIMO_PLCP_40MHZ;
+		session->max_ampdu_len = min(scb_ampdu->max_rx_ampdu_bytes,
+					     ampdu->max_txlen[mcs][is40][sgi]);
+
+		session->max_ampdu_frames = scb_ampdu->max_pdu;
+		if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) {
+			session->max_ampdu_frames =
+				min_t(u16, f->mcs2ampdu_table[mcs],
+				      session->max_ampdu_frames);
+		}
+	}
+
+	/*
+	 * Treat all frames as "middle" frames of AMPDU here. First and
+	 * last frames must be fixed up after all MPDUs have been prepped.
+	 */
+	mcl = le16_to_cpu(txh->MacTxControlLow);
+	mcl &= ~TXC_AMPDU_MASK;
+	mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT);
+	mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS);
+	txh->MacTxControlLow = cpu_to_le16(mcl);
+	txh->PreloadSize = 0;	/* always default to 0 */
+
+	skb_queue_tail(&session->skb_list, p);
+
+	return 0;
+}
+
+void brcms_c_ampdu_finalize(struct brcms_ampdu_session *session)
+{
+	struct brcms_c_info *wlc = session->wlc;
+	struct ampdu_info *ampdu = wlc->ampdu;
+	struct sk_buff *first, *last;
+	struct d11txh *txh;
+	struct ieee80211_tx_info *tx_info;
+	struct ieee80211_tx_rate *txrate;
+	u8 ndelim;
+	u8 *plcp;
+	uint len;
+	uint fifo;
+	struct brcms_fifo_info *f;
+	u16 mcl;
+	bool fbr;
+	bool fbr_iscck;
+	struct ieee80211_rts *rts;
+	bool use_rts = false, use_cts = false;
+	u16 dma_len = session->dma_len;
+	u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
+	u32 rspec = 0, rspec_fallback = 0;
+	u32 rts_rspec = 0, rts_rspec_fallback = 0;
+	u8 plcp0, plcp3, is40, sgi, mcs;
+	u16 mch;
+	u8 preamble_type = BRCMS_GF_PREAMBLE;
+	u8 fbr_preamble_type = BRCMS_GF_PREAMBLE;
+	u8 rts_preamble_type = BRCMS_LONG_PREAMBLE;
+	u8 rts_fbr_preamble_type = BRCMS_LONG_PREAMBLE;
+
+	if (skb_queue_empty(&session->skb_list))
+		return;
+
+	first = skb_peek(&session->skb_list);
+	last = skb_peek_tail(&session->skb_list);
+
+	/* Need to fix up last MPDU first to adjust AMPDU length */
+	txh = (struct d11txh *)last->data;
+	fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK;
+	f = &ampdu->fifo_tb[fifo];
+
+	mcl = le16_to_cpu(txh->MacTxControlLow);
+	mcl &= ~TXC_AMPDU_MASK;
+	mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT);
+	txh->MacTxControlLow = cpu_to_le16(mcl);
+
+	/* remove the null delimiter after last mpdu */
+	ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
+	txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0;
+	session->ampdu_len -= ndelim * AMPDU_DELIMITER_LEN;
+
+	/* remove the pad len from last mpdu */
+	fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0);
+	len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) :
+			  BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
+	session->ampdu_len -= roundup(len, 4) - len;
+
+	/* Now fix up the first MPDU */
+	tx_info = IEEE80211_SKB_CB(first);
+	txrate = tx_info->status.rates;
+	txh = (struct d11txh *)first->data;
+	plcp = (u8 *)(txh + 1);
+	rts = (struct ieee80211_rts *)&txh->rts_frame;
+
+	mcl = le16_to_cpu(txh->MacTxControlLow);
+	/* If only one MPDU leave it marked as last */
+	if (first != last) {
+		mcl &= ~TXC_AMPDU_MASK;
+		mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
+	}
+	mcl |= TXC_STARTMSDU;
+	if (ieee80211_is_rts(rts->frame_control)) {
+		mcl |= TXC_SENDRTS;
+		use_rts = true;
+	}
+	if (ieee80211_is_cts(rts->frame_control)) {
+		mcl |= TXC_SENDCTS;
+		use_cts = true;
+	}
+	txh->MacTxControlLow = cpu_to_le16(mcl);
+
+	fbr = txrate[1].count > 0;
+	if (!fbr) {
+		plcp0 = plcp[0];
+		plcp3 = plcp[3];
+	} else {
+		plcp0 = txh->FragPLCPFallback[0];
+		plcp3 = txh->FragPLCPFallback[3];
+	}
+	is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
+	sgi = plcp3_issgi(plcp3) ? 1 : 0;
+	mcs = plcp0 & ~MIMO_PLCP_40MHZ;
+
+	if (is40) {
+		if (CHSPEC_SB_UPPER(wlc_phy_chanspec_get(wlc->band->pi)))
+			mimo_ctlchbw = PHY_TXC1_BW_20MHZ_UP;
+		else
+			mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
+	}
+
+	/* rebuild the rspec and rspec_fallback */
+	rspec = RSPEC_MIMORATE;
+	rspec |= plcp[0] & ~MIMO_PLCP_40MHZ;
+	if (plcp[0] & MIMO_PLCP_40MHZ)
+		rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
+
+	fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x03);
+	if (fbr_iscck) {
+		rspec_fallback =
+			cck_rspec(cck_phy2mac_rate(txh->FragPLCPFallback[0]));
+	} else {
+		rspec_fallback = RSPEC_MIMORATE;
+		rspec_fallback |= txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ;
+		if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ)
+			rspec_fallback |= PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT;
+	}
+
+	if (use_rts || use_cts) {
+		rts_rspec =
+			brcms_c_rspec_to_rts_rspec(wlc, rspec,
+						   false, mimo_ctlchbw);
+		rts_rspec_fallback =
+			brcms_c_rspec_to_rts_rspec(wlc, rspec_fallback,
+						   false, mimo_ctlchbw);
+	}
+
+	BRCMS_SET_MIMO_PLCP_LEN(plcp, session->ampdu_len);
+	/* mark plcp to indicate ampdu */
+	BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
+
+	/* reset the mixed mode header durations */
+	if (txh->MModeLen) {
+		u16 mmodelen = brcms_c_calc_lsig_len(wlc, rspec,
+						     session->ampdu_len);
+		txh->MModeLen = cpu_to_le16(mmodelen);
+		preamble_type = BRCMS_MM_PREAMBLE;
+	}
+	if (txh->MModeFbrLen) {
+		u16 mmfbrlen = brcms_c_calc_lsig_len(wlc, rspec_fallback,
+						     session->ampdu_len);
+		txh->MModeFbrLen = cpu_to_le16(mmfbrlen);
+		fbr_preamble_type = BRCMS_MM_PREAMBLE;
+	}
+
+	/* set the preload length */
+	if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) {
+		dma_len = min(dma_len, f->ampdu_pld_size);
+		txh->PreloadSize = cpu_to_le16(dma_len);
+	} else {
+		txh->PreloadSize = 0;
+	}
+
+	mch = le16_to_cpu(txh->MacTxControlHigh);
+
+	/* update RTS dur fields */
+	if (use_rts || use_cts) {
+		u16 durid;
+		if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) ==
+		    TXC_PREAMBLE_RTS_MAIN_SHORT)
+			rts_preamble_type = BRCMS_SHORT_PREAMBLE;
+
+		if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) ==
+		     TXC_PREAMBLE_RTS_FB_SHORT)
+			rts_fbr_preamble_type = BRCMS_SHORT_PREAMBLE;
+
+		durid = brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec,
+						   rspec, rts_preamble_type,
+						   preamble_type,
+						   session->ampdu_len, true);
+		rts->duration = cpu_to_le16(durid);
+		durid = brcms_c_compute_rtscts_dur(wlc, use_cts,
+						   rts_rspec_fallback,
+						   rspec_fallback,
+						   rts_fbr_preamble_type,
+						   fbr_preamble_type,
+						   session->ampdu_len, true);
+		txh->RTSDurFallback = cpu_to_le16(durid);
+		/* set TxFesTimeNormal */
+		txh->TxFesTimeNormal = rts->duration;
+		/* set fallback rate version of TxFesTimeNormal */
+		txh->TxFesTimeFallback = txh->RTSDurFallback;
+	}
+
+	/* set flag and plcp for fallback rate */
+	if (fbr) {
+		mch |= TXC_AMPDU_FBR;
+		txh->MacTxControlHigh = cpu_to_le16(mch);
+		BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
+		BRCMS_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback);
+	}
+
+	brcms_dbg_ht(wlc->hw->d11core, "wl%d: count %d ampdu_len %d\n",
+		     wlc->pub->unit, skb_queue_len(&session->skb_list),
+		     session->ampdu_len);
+}
+
+static void
+brcms_c_ampdu_rate_status(struct brcms_c_info *wlc,
+			  struct ieee80211_tx_info *tx_info,
+			  struct tx_status *txs, u8 mcs)
+{
+	struct ieee80211_tx_rate *txrate = tx_info->status.rates;
+	int i;
+
+	/* clear the rest of the rates */
+	for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
+		txrate[i].idx = -1;
+		txrate[i].count = 0;
+	}
+}
+
+static void
+brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
+			      struct sk_buff *p, struct tx_status *txs,
+			      u32 s1, u32 s2)
+{
+	struct scb_ampdu *scb_ampdu;
+	struct brcms_c_info *wlc = ampdu->wlc;
+	struct scb_ampdu_tid_ini *ini;
+	u8 bitmap[8], queue, tid;
+	struct d11txh *txh;
+	u8 *plcp;
+	struct ieee80211_hdr *h;
+	u16 seq, start_seq = 0, bindex, index, mcl;
+	u8 mcs = 0;
+	bool ba_recd = false, ack_recd = false;
+	u8 suc_mpdu = 0, tot_mpdu = 0;
+	uint supr_status;
+	bool update_rate = true, retry = true, tx_error = false;
+	u16 mimoantsel = 0;
+	u8 antselid = 0;
+	u8 retry_limit, rr_retry_limit;
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
+
+#ifdef DEBUG
+	u8 hole[AMPDU_MAX_MPDU];
+	memset(hole, 0, sizeof(hole));
+#endif
+
+	scb_ampdu = &scb->scb_ampdu;
+	tid = (u8) (p->priority);
+
+	ini = &scb_ampdu->ini[tid];
+	retry_limit = ampdu->retry_limit_tid[tid];
+	rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
+	memset(bitmap, 0, sizeof(bitmap));
+	queue = txs->frameid & TXFID_QUEUE_MASK;
+	supr_status = txs->status & TX_STATUS_SUPR_MASK;
+
+	if (txs->status & TX_STATUS_ACK_RCV) {
+		if (TX_STATUS_SUPR_UF == supr_status)
+			update_rate = false;
+
+		WARN_ON(!(txs->status & TX_STATUS_INTERMEDIATE));
+		start_seq = txs->sequence >> SEQNUM_SHIFT;
+		bitmap[0] = (txs->status & TX_STATUS_BA_BMAP03_MASK) >>
+		    TX_STATUS_BA_BMAP03_SHIFT;
+
+		WARN_ON(s1 & TX_STATUS_INTERMEDIATE);
+		WARN_ON(!(s1 & TX_STATUS_AMPDU));
+
+		bitmap[0] |=
+		    (s1 & TX_STATUS_BA_BMAP47_MASK) <<
+		    TX_STATUS_BA_BMAP47_SHIFT;
+		bitmap[1] = (s1 >> 8) & 0xff;
+		bitmap[2] = (s1 >> 16) & 0xff;
+		bitmap[3] = (s1 >> 24) & 0xff;
+
+		bitmap[4] = s2 & 0xff;
+		bitmap[5] = (s2 >> 8) & 0xff;
+		bitmap[6] = (s2 >> 16) & 0xff;
+		bitmap[7] = (s2 >> 24) & 0xff;
+
+		ba_recd = true;
+	} else {
+		if (supr_status) {
+			update_rate = false;
+			if (supr_status == TX_STATUS_SUPR_BADCH) {
+				brcms_dbg_ht(wlc->hw->d11core,
+					  "%s: Pkt tx suppressed, illegal channel possibly %d\n",
+					  __func__, CHSPEC_CHANNEL(
+					  wlc->default_bss->chanspec));
+			} else {
+				if (supr_status != TX_STATUS_SUPR_FRAG)
+					brcms_err(wlc->hw->d11core,
+						  "%s: supr_status 0x%x\n",
+						  __func__, supr_status);
+			}
+			/* no need to retry for badch; will fail again */
+			if (supr_status == TX_STATUS_SUPR_BADCH ||
+			    supr_status == TX_STATUS_SUPR_EXPTIME) {
+				retry = false;
+			} else if (supr_status == TX_STATUS_SUPR_EXPTIME) {
+				/* TX underflow:
+				 *   try tuning pre-loading or ampdu size
+				 */
+			} else if (supr_status == TX_STATUS_SUPR_FRAG) {
+				/*
+				 * if there were underflows, but pre-loading
+				 * is not active, notify rate adaptation.
+				 */
+				if (brcms_c_ffpld_check_txfunfl(wlc, queue) > 0)
+					tx_error = true;
+			}
+		} else if (txs->phyerr) {
+			update_rate = false;
+			brcms_dbg_ht(wlc->hw->d11core,
+				     "%s: ampdu tx phy error (0x%x)\n",
+				     __func__, txs->phyerr);
+		}
+	}
+
+	/* loop through all pkts and retry if not acked */
+	while (p) {
+		tx_info = IEEE80211_SKB_CB(p);
+		txh = (struct d11txh *) p->data;
+		mcl = le16_to_cpu(txh->MacTxControlLow);
+		plcp = (u8 *) (txh + 1);
+		h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
+		seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
+
+		trace_brcms_txdesc(&wlc->hw->d11core->dev, txh, sizeof(*txh));
+
+		if (tot_mpdu == 0) {
+			mcs = plcp[0] & MIMO_PLCP_MCS_MASK;
+			mimoantsel = le16_to_cpu(txh->ABI_MimoAntSel);
+		}
+
+		index = TX_SEQ_TO_INDEX(seq);
+		ack_recd = false;
+		if (ba_recd) {
+			bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
+			brcms_dbg_ht(wlc->hw->d11core,
+				     "tid %d seq %d, start_seq %d, bindex %d set %d, index %d\n",
+				     tid, seq, start_seq, bindex,
+				     isset(bitmap, bindex), index);
+			/* if acked then clear bit and free packet */
+			if ((bindex < AMPDU_TX_BA_MAX_WSIZE)
+			    && isset(bitmap, bindex)) {
+				ini->txretry[index] = 0;
+
+				/*
+				 * ampdu_ack_len:
+				 *   number of acked aggregated frames
+				 */
+				/* ampdu_len: number of aggregated frames */
+				brcms_c_ampdu_rate_status(wlc, tx_info, txs,
+							  mcs);
+				tx_info->flags |= IEEE80211_TX_STAT_ACK;
+				tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
+				tx_info->status.ampdu_ack_len =
+					tx_info->status.ampdu_len = 1;
+
+				skb_pull(p, D11_PHY_HDR_LEN);
+				skb_pull(p, D11_TXH_LEN);
+
+				ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
+							    p);
+				ack_recd = true;
+				suc_mpdu++;
+			}
+		}
+		/* either retransmit or send bar if ack not recd */
+		if (!ack_recd) {
+			if (retry && (ini->txretry[index] < (int)retry_limit)) {
+				int ret;
+				ini->txretry[index]++;
+				ret = brcms_c_txfifo(wlc, queue, p);
+				/*
+				 * We shouldn't be out of space in the DMA
+				 * ring here since we're reinserting a frame
+				 * that was just pulled out.
+				 */
+				WARN_ONCE(ret, "queue %d out of txds\n", queue);
+			} else {
+				/* Retry timeout */
+				ieee80211_tx_info_clear_status(tx_info);
+				tx_info->status.ampdu_ack_len = 0;
+				tx_info->status.ampdu_len = 1;
+				tx_info->flags |=
+				    IEEE80211_TX_STAT_AMPDU_NO_BACK;
+				skb_pull(p, D11_PHY_HDR_LEN);
+				skb_pull(p, D11_TXH_LEN);
+				brcms_dbg_ht(wlc->hw->d11core,
+					     "BA Timeout, seq %d\n",
+					     seq);
+				ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
+							    p);
+			}
+		}
+		tot_mpdu++;
+
+		/* break out if last packet of ampdu */
+		if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
+		    TXC_AMPDU_LAST)
+			break;
+
+		p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED);
+	}
+
+	/* update rate state */
+	antselid = brcms_c_antsel_antsel2id(wlc->asi, mimoantsel);
+}
+
+void
+brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
+		     struct sk_buff *p, struct tx_status *txs)
+{
+	struct scb_ampdu *scb_ampdu;
+	struct brcms_c_info *wlc = ampdu->wlc;
+	struct scb_ampdu_tid_ini *ini;
+	u32 s1 = 0, s2 = 0;
+	struct ieee80211_tx_info *tx_info;
+
+	tx_info = IEEE80211_SKB_CB(p);
+
+	/* BMAC_NOTE: For the split driver, second level txstatus comes later
+	 * So if the ACK was received then wait for the second level else just
+	 * call the first one
+	 */
+	if (txs->status & TX_STATUS_ACK_RCV) {
+		u8 status_delay = 0;
+
+		/* wait till the next 8 bytes of txstatus is available */
+		s1 = bcma_read32(wlc->hw->d11core, D11REGOFFS(frmtxstatus));
+		while ((s1 & TXS_V) == 0) {
+			udelay(1);
+			status_delay++;
+			if (status_delay > 10)
+				return; /* error condition */
+			s1 = bcma_read32(wlc->hw->d11core,
+					 D11REGOFFS(frmtxstatus));
+		}
+
+		s2 = bcma_read32(wlc->hw->d11core, D11REGOFFS(frmtxstatus2));
+	}
+
+	if (scb) {
+		scb_ampdu = &scb->scb_ampdu;
+		ini = &scb_ampdu->ini[p->priority];
+		brcms_c_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
+	} else {
+		/* loop through all pkts and free */
+		u8 queue = txs->frameid & TXFID_QUEUE_MASK;
+		struct d11txh *txh;
+		u16 mcl;
+		while (p) {
+			tx_info = IEEE80211_SKB_CB(p);
+			txh = (struct d11txh *) p->data;
+			trace_brcms_txdesc(&wlc->hw->d11core->dev, txh,
+					   sizeof(*txh));
+			mcl = le16_to_cpu(txh->MacTxControlLow);
+			brcmu_pkt_buf_free_skb(p);
+			/* break out if last packet of ampdu */
+			if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
+			    TXC_AMPDU_LAST)
+				break;
+			p = dma_getnexttxp(wlc->hw->di[queue],
+					   DMA_RANGE_TRANSMITTED);
+		}
+	}
+}
+
+void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc)
+{
+	char template[T_RAM_ACCESS_SZ * 2];
+
+	/* driver needs to write the ta in the template; ta is at offset 16 */
+	memset(template, 0, sizeof(template));
+	memcpy(template, wlc->pub->cur_etheraddr, ETH_ALEN);
+	brcms_b_write_template_ram(wlc->hw, (T_BA_TPL_BASE + 16),
+				  (T_RAM_ACCESS_SZ * 2),
+				  template);
+}
+
+bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid)
+{
+	return wlc->ampdu->ini_enable[tid];
+}
+
+void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu)
+{
+	struct brcms_c_info *wlc = ampdu->wlc;
+
+	/*
+	 * Extend ucode internal watchdog timer to
+	 * match larger received frames
+	 */
+	if ((ampdu->rx_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) ==
+	    IEEE80211_HT_MAX_AMPDU_64K) {
+		brcms_b_write_shm(wlc->hw, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX);
+		brcms_b_write_shm(wlc->hw, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX);
+	} else {
+		brcms_b_write_shm(wlc->hw, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF);
+		brcms_b_write_shm(wlc->hw, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF);
+	}
+}
+
+/*
+ * callback function that helps invalidating ampdu packets in a DMA queue
+ */
+static void dma_cb_fn_ampdu(void *txi, void *arg_a)
+{
+	struct ieee80211_sta *sta = arg_a;
+	struct ieee80211_tx_info *tx_info = (struct ieee80211_tx_info *)txi;
+
+	if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
+	    (tx_info->rate_driver_data[0] == sta || sta == NULL))
+		tx_info->rate_driver_data[0] = NULL;
+}
+
+/*
+ * When a remote party is no longer available for ampdu communication, any
+ * pending tx ampdu packets in the driver have to be flushed.
+ */
+void brcms_c_ampdu_flush(struct brcms_c_info *wlc,
+		     struct ieee80211_sta *sta, u16 tid)
+{
+	brcms_c_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu);
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.h
new file mode 100644
index 0000000..03bdcf2
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_AMPDU_H_
+#define _BRCM_AMPDU_H_
+
+/*
+ * Data structure representing an in-progress session for accumulating
+ * frames for AMPDU.
+ *
+ * wlc: pointer to common driver data
+ * skb_list: queue of skb's for AMPDU
+ * max_ampdu_len: maximum length for this AMPDU
+ * max_ampdu_frames: maximum number of frames for this AMPDU
+ * ampdu_len: total number of bytes accumulated for this AMPDU
+ * dma_len: DMA length of this AMPDU
+ */
+struct brcms_ampdu_session {
+	struct brcms_c_info *wlc;
+	struct sk_buff_head skb_list;
+	unsigned max_ampdu_len;
+	u16 max_ampdu_frames;
+	u16 ampdu_len;
+	u16 dma_len;
+};
+
+void brcms_c_ampdu_reset_session(struct brcms_ampdu_session *session,
+				 struct brcms_c_info *wlc);
+int brcms_c_ampdu_add_frame(struct brcms_ampdu_session *session,
+			    struct sk_buff *p);
+void brcms_c_ampdu_finalize(struct brcms_ampdu_session *session);
+
+struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc);
+void brcms_c_ampdu_detach(struct ampdu_info *ampdu);
+void brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
+			      struct sk_buff *p, struct tx_status *txs);
+void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc);
+void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu);
+
+#endif				/* _BRCM_AMPDU_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/antsel.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/antsel.c
new file mode 100644
index 0000000..54c6169
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/antsel.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/slab.h>
+#include <net/mac80211.h>
+
+#include "types.h"
+#include "main.h"
+#include "phy_shim.h"
+#include "antsel.h"
+#include "debug.h"
+
+#define ANT_SELCFG_AUTO		0x80	/* bit indicates antenna sel AUTO */
+#define ANT_SELCFG_MASK		0x33	/* antenna configuration mask */
+#define ANT_SELCFG_TX_UNICAST	0	/* unicast tx antenna configuration */
+#define ANT_SELCFG_RX_UNICAST	1	/* unicast rx antenna configuration */
+#define ANT_SELCFG_TX_DEF	2	/* default tx antenna configuration */
+#define ANT_SELCFG_RX_DEF	3	/* default rx antenna configuration */
+
+/* useful macros */
+#define BRCMS_ANTSEL_11N_0(ant)	((((ant) & ANT_SELCFG_MASK) >> 4) & 0xf)
+#define BRCMS_ANTSEL_11N_1(ant)	(((ant) & ANT_SELCFG_MASK) & 0xf)
+#define BRCMS_ANTIDX_11N(ant)	(((BRCMS_ANTSEL_11N_0(ant)) << 2) +\
+				(BRCMS_ANTSEL_11N_1(ant)))
+#define BRCMS_ANT_ISAUTO_11N(ant) (((ant) & ANT_SELCFG_AUTO) == ANT_SELCFG_AUTO)
+#define BRCMS_ANTSEL_11N(ant)	((ant) & ANT_SELCFG_MASK)
+
+/* antenna switch */
+/* defines for no boardlevel antenna diversity */
+#define ANT_SELCFG_DEF_2x2	0x01	/* default antenna configuration */
+
+/* 2x3 antdiv defines and tables for GPIO communication */
+#define ANT_SELCFG_NUM_2x3	3
+#define ANT_SELCFG_DEF_2x3	0x01	/* default antenna configuration */
+
+/* 2x4 antdiv rev4 defines and tables for GPIO communication */
+#define ANT_SELCFG_NUM_2x4	4
+#define ANT_SELCFG_DEF_2x4	0x02	/* default antenna configuration */
+
+static const u16 mimo_2x4_div_antselpat_tbl[] = {
+	0, 0, 0x9, 0xa,		/* ant0: 0 ant1: 2,3 */
+	0, 0, 0x5, 0x6,		/* ant0: 1 ant1: 2,3 */
+	0, 0, 0, 0,		/* n.a.              */
+	0, 0, 0, 0		/* n.a.              */
+};
+
+static const u8 mimo_2x4_div_antselid_tbl[16] = {
+	0, 0, 0, 0, 0, 2, 3, 0,
+	0, 0, 1, 0, 0, 0, 0, 0	/* pat to antselid */
+};
+
+static const u16 mimo_2x3_div_antselpat_tbl[] = {
+	16, 0, 1, 16,		/* ant0: 0 ant1: 1,2 */
+	16, 16, 16, 16,		/* n.a.              */
+	16, 2, 16, 16,		/* ant0: 2 ant1: 1   */
+	16, 16, 16, 16		/* n.a.              */
+};
+
+static const u8 mimo_2x3_div_antselid_tbl[16] = {
+	0, 1, 2, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0	/* pat to antselid */
+};
+
+/* boardlevel antenna selection: init antenna selection structure */
+static void
+brcms_c_antsel_init_cfg(struct antsel_info *asi, struct brcms_antselcfg *antsel,
+		    bool auto_sel)
+{
+	if (asi->antsel_type == ANTSEL_2x3) {
+		u8 antcfg_def = ANT_SELCFG_DEF_2x3 |
+		    ((asi->antsel_avail && auto_sel) ? ANT_SELCFG_AUTO : 0);
+		antsel->ant_config[ANT_SELCFG_TX_DEF] = antcfg_def;
+		antsel->ant_config[ANT_SELCFG_TX_UNICAST] = antcfg_def;
+		antsel->ant_config[ANT_SELCFG_RX_DEF] = antcfg_def;
+		antsel->ant_config[ANT_SELCFG_RX_UNICAST] = antcfg_def;
+		antsel->num_antcfg = ANT_SELCFG_NUM_2x3;
+
+	} else if (asi->antsel_type == ANTSEL_2x4) {
+
+		antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x4;
+		antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x4;
+		antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x4;
+		antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x4;
+		antsel->num_antcfg = ANT_SELCFG_NUM_2x4;
+
+	} else {		/* no antenna selection available */
+
+		antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x2;
+		antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x2;
+		antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x2;
+		antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x2;
+		antsel->num_antcfg = 0;
+	}
+}
+
+struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc)
+{
+	struct antsel_info *asi;
+	struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom;
+
+	asi = kzalloc(sizeof(struct antsel_info), GFP_ATOMIC);
+	if (!asi)
+		return NULL;
+
+	asi->wlc = wlc;
+	asi->pub = wlc->pub;
+	asi->antsel_type = ANTSEL_NA;
+	asi->antsel_avail = false;
+	asi->antsel_antswitch = sprom->antswitch;
+
+	if ((asi->pub->sromrev >= 4) && (asi->antsel_antswitch != 0)) {
+		switch (asi->antsel_antswitch) {
+		case ANTSWITCH_TYPE_1:
+		case ANTSWITCH_TYPE_2:
+		case ANTSWITCH_TYPE_3:
+			/* 4321/2 board with 2x3 switch logic */
+			asi->antsel_type = ANTSEL_2x3;
+			/* Antenna selection availability */
+			if ((sprom->ant_available_bg == 7) ||
+			    (sprom->ant_available_a == 7)) {
+				asi->antsel_avail = true;
+			} else if (
+				sprom->ant_available_bg == 3 ||
+				sprom->ant_available_a == 3) {
+				asi->antsel_avail = false;
+			} else {
+				asi->antsel_avail = false;
+				brcms_err(wlc->hw->d11core,
+					  "antsel_attach: 2o3 "
+					  "board cfg invalid\n");
+			}
+
+			break;
+		default:
+			break;
+		}
+	} else if ((asi->pub->sromrev == 4) &&
+		   (sprom->ant_available_bg == 7) &&
+		   (sprom->ant_available_a == 0)) {
+		/* hack to match old 4321CB2 cards with 2of3 antenna switch */
+		asi->antsel_type = ANTSEL_2x3;
+		asi->antsel_avail = true;
+	} else if (asi->pub->boardflags2 & BFL2_2X4_DIV) {
+		asi->antsel_type = ANTSEL_2x4;
+		asi->antsel_avail = true;
+	}
+
+	/* Set the antenna selection type for the low driver */
+	brcms_b_antsel_type_set(wlc->hw, asi->antsel_type);
+
+	/* Init (auto/manual) antenna selection */
+	brcms_c_antsel_init_cfg(asi, &asi->antcfg_11n, true);
+	brcms_c_antsel_init_cfg(asi, &asi->antcfg_cur, true);
+
+	return asi;
+}
+
+void brcms_c_antsel_detach(struct antsel_info *asi)
+{
+	kfree(asi);
+}
+
+/*
+ * boardlevel antenna selection:
+ *   convert ant_cfg to mimo_antsel (ucode interface)
+ */
+static u16 brcms_c_antsel_antcfg2antsel(struct antsel_info *asi, u8 ant_cfg)
+{
+	u8 idx = BRCMS_ANTIDX_11N(BRCMS_ANTSEL_11N(ant_cfg));
+	u16 mimo_antsel = 0;
+
+	if (asi->antsel_type == ANTSEL_2x4) {
+		/* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
+		mimo_antsel = (mimo_2x4_div_antselpat_tbl[idx] & 0xf);
+		return mimo_antsel;
+
+	} else if (asi->antsel_type == ANTSEL_2x3) {
+		/* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
+		mimo_antsel = (mimo_2x3_div_antselpat_tbl[idx] & 0xf);
+		return mimo_antsel;
+	}
+
+	return mimo_antsel;
+}
+
+/* boardlevel antenna selection: ucode interface control */
+static int brcms_c_antsel_cfgupd(struct antsel_info *asi,
+				 struct brcms_antselcfg *antsel)
+{
+	struct brcms_c_info *wlc = asi->wlc;
+	u8 ant_cfg;
+	u16 mimo_antsel;
+
+	/* 1) Update TX antconfig for all frames that are not unicast data
+	 *    (aka default TX)
+	 */
+	ant_cfg = antsel->ant_config[ANT_SELCFG_TX_DEF];
+	mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg);
+	brcms_b_write_shm(wlc->hw, M_MIMO_ANTSEL_TXDFLT, mimo_antsel);
+	/*
+	 * Update driver stats for currently selected
+	 * default tx/rx antenna config
+	 */
+	asi->antcfg_cur.ant_config[ANT_SELCFG_TX_DEF] = ant_cfg;
+
+	/* 2) Update RX antconfig for all frames that are not unicast data
+	 *    (aka default RX)
+	 */
+	ant_cfg = antsel->ant_config[ANT_SELCFG_RX_DEF];
+	mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg);
+	brcms_b_write_shm(wlc->hw, M_MIMO_ANTSEL_RXDFLT, mimo_antsel);
+	/*
+	 * Update driver stats for currently selected
+	 * default tx/rx antenna config
+	 */
+	asi->antcfg_cur.ant_config[ANT_SELCFG_RX_DEF] = ant_cfg;
+
+	return 0;
+}
+
+void brcms_c_antsel_init(struct antsel_info *asi)
+{
+	if ((asi->antsel_type == ANTSEL_2x3) ||
+	    (asi->antsel_type == ANTSEL_2x4))
+		brcms_c_antsel_cfgupd(asi, &asi->antcfg_11n);
+}
+
+/* boardlevel antenna selection: convert id to ant_cfg */
+static u8 brcms_c_antsel_id2antcfg(struct antsel_info *asi, u8 id)
+{
+	u8 antcfg = ANT_SELCFG_DEF_2x2;
+
+	if (asi->antsel_type == ANTSEL_2x4) {
+		/* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
+		antcfg = (((id & 0x2) << 3) | ((id & 0x1) + 2));
+		return antcfg;
+
+	} else if (asi->antsel_type == ANTSEL_2x3) {
+		/* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
+		antcfg = (((id & 0x02) << 4) | ((id & 0x1) + 1));
+		return antcfg;
+	}
+
+	return antcfg;
+}
+
+void
+brcms_c_antsel_antcfg_get(struct antsel_info *asi, bool usedef, bool sel,
+		      u8 antselid, u8 fbantselid, u8 *antcfg,
+		      u8 *fbantcfg)
+{
+	u8 ant;
+
+	/* if use default, assign it and return */
+	if (usedef) {
+		*antcfg = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_DEF];
+		*fbantcfg = *antcfg;
+		return;
+	}
+
+	if (!sel) {
+		*antcfg = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST];
+		*fbantcfg = *antcfg;
+
+	} else {
+		ant = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST];
+		if ((ant & ANT_SELCFG_AUTO) == ANT_SELCFG_AUTO) {
+			*antcfg = brcms_c_antsel_id2antcfg(asi, antselid);
+			*fbantcfg = brcms_c_antsel_id2antcfg(asi, fbantselid);
+		} else {
+			*antcfg =
+			    asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST];
+			*fbantcfg = *antcfg;
+		}
+	}
+	return;
+}
+
+/* boardlevel antenna selection: convert mimo_antsel (ucode interface) to id */
+u8 brcms_c_antsel_antsel2id(struct antsel_info *asi, u16 antsel)
+{
+	u8 antselid = 0;
+
+	if (asi->antsel_type == ANTSEL_2x4) {
+		/* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
+		antselid = mimo_2x4_div_antselid_tbl[(antsel & 0xf)];
+		return antselid;
+
+	} else if (asi->antsel_type == ANTSEL_2x3) {
+		/* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
+		antselid = mimo_2x3_div_antselid_tbl[(antsel & 0xf)];
+		return antselid;
+	}
+
+	return antselid;
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/antsel.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/antsel.h
new file mode 100644
index 0000000..a3d487a
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/antsel.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_ANTSEL_H_
+#define _BRCM_ANTSEL_H_
+
+struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc);
+void brcms_c_antsel_detach(struct antsel_info *asi);
+void brcms_c_antsel_init(struct antsel_info *asi);
+void brcms_c_antsel_antcfg_get(struct antsel_info *asi, bool usedef, bool sel,
+			       u8 id, u8 fbid, u8 *antcfg, u8 *fbantcfg);
+u8 brcms_c_antsel_antsel2id(struct antsel_info *asi, u16 antsel);
+
+#endif /* _BRCM_ANTSEL_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac.h
new file mode 100644
index 0000000..a0da324
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if !defined(__TRACE_BRCMSMAC_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __TRACE_BRCMSMAC_H
+
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM brcmsmac
+
+/*
+ * We define a tracepoint, its arguments, its printk format and its
+ * 'fast binary record' layout.
+ */
+TRACE_EVENT(brcms_timer,
+	/* TPPROTO is the prototype of the function called by this tracepoint */
+	TP_PROTO(struct brcms_timer *t),
+	/*
+	 * TPARGS(firstarg, p) are the parameters names, same as found in the
+	 * prototype.
+	 */
+	TP_ARGS(t),
+	/*
+	 * Fast binary tracing: define the trace record via TP_STRUCT__entry().
+	 * You can think about it like a regular C structure local variable
+	 * definition.
+	 */
+	TP_STRUCT__entry(
+		__field(uint, ms)
+		__field(uint, set)
+		__field(uint, periodic)
+	),
+	TP_fast_assign(
+		__entry->ms = t->ms;
+		__entry->set = t->set;
+		__entry->periodic = t->periodic;
+	),
+	TP_printk(
+		"ms=%u set=%u periodic=%u",
+		__entry->ms, __entry->set, __entry->periodic
+	)
+);
+
+TRACE_EVENT(brcms_dpc,
+	TP_PROTO(unsigned long data),
+	TP_ARGS(data),
+	TP_STRUCT__entry(
+		__field(unsigned long, data)
+	),
+	TP_fast_assign(
+		__entry->data = data;
+	),
+	TP_printk(
+		"data=%p",
+		(void *)__entry->data
+	)
+);
+
+TRACE_EVENT(brcms_macintstatus,
+	TP_PROTO(const struct device *dev, int in_isr, u32 macintstatus,
+		 u32 mask),
+	TP_ARGS(dev, in_isr, macintstatus, mask),
+	TP_STRUCT__entry(
+		__string(dev, dev_name(dev))
+		__field(int, in_isr)
+		__field(u32, macintstatus)
+		__field(u32, mask)
+	),
+	TP_fast_assign(
+		__assign_str(dev, dev_name(dev));
+		__entry->in_isr = in_isr;
+		__entry->macintstatus = macintstatus;
+		__entry->mask = mask;
+	),
+	TP_printk("[%s] in_isr=%d macintstatus=%#x mask=%#x", __get_str(dev),
+		  __entry->in_isr, __entry->macintstatus, __entry->mask)
+);
+#endif /* __TRACE_BRCMSMAC_H */
+
+#ifdef CONFIG_BRCM_TRACING
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE brcms_trace_brcmsmac
+#include <trace/define_trace.h>
+
+#endif /* CONFIG_BRCM_TRACING */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h
new file mode 100644
index 0000000..0e8a69a
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if !defined(__TRACE_BRCMSMAC_MSG_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __TRACE_BRCMSMAC_MSG_H
+
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM brcmsmac_msg
+
+#define MAX_MSG_LEN	100
+
+DECLARE_EVENT_CLASS(brcms_msg_event,
+	TP_PROTO(struct va_format *vaf),
+	TP_ARGS(vaf),
+	TP_STRUCT__entry(
+		__dynamic_array(char, msg, MAX_MSG_LEN)
+	),
+	TP_fast_assign(
+		WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
+				       MAX_MSG_LEN, vaf->fmt,
+				       *vaf->va) >= MAX_MSG_LEN);
+	),
+	TP_printk("%s", __get_str(msg))
+);
+
+DEFINE_EVENT(brcms_msg_event, brcms_info,
+	TP_PROTO(struct va_format *vaf),
+	TP_ARGS(vaf)
+);
+
+DEFINE_EVENT(brcms_msg_event, brcms_warn,
+	TP_PROTO(struct va_format *vaf),
+	TP_ARGS(vaf)
+);
+
+DEFINE_EVENT(brcms_msg_event, brcms_err,
+	TP_PROTO(struct va_format *vaf),
+	TP_ARGS(vaf)
+);
+
+DEFINE_EVENT(brcms_msg_event, brcms_crit,
+	TP_PROTO(struct va_format *vaf),
+	TP_ARGS(vaf)
+);
+
+TRACE_EVENT(brcms_dbg,
+	TP_PROTO(u32 level, const char *func, struct va_format *vaf),
+	TP_ARGS(level, func, vaf),
+	TP_STRUCT__entry(
+		__field(u32, level)
+		__string(func, func)
+		__dynamic_array(char, msg, MAX_MSG_LEN)
+	),
+	TP_fast_assign(
+		__entry->level = level;
+		__assign_str(func, func);
+		WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
+				       MAX_MSG_LEN, vaf->fmt,
+				       *vaf->va) >= MAX_MSG_LEN);
+	),
+	TP_printk("%s: %s", __get_str(func), __get_str(msg))
+);
+#endif /* __TRACE_BRCMSMAC_MSG_H */
+
+#ifdef CONFIG_BRCM_TRACING
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE brcms_trace_brcmsmac_msg
+#include <trace/define_trace.h>
+
+#endif /* CONFIG_BRCM_TRACING */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_tx.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_tx.h
new file mode 100644
index 0000000..cf2cc07
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_tx.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if !defined(__TRACE_BRCMSMAC_TX_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __TRACE_BRCMSMAC_TX_H
+
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM brcmsmac_tx
+
+TRACE_EVENT(brcms_txdesc,
+	TP_PROTO(const struct device *dev,
+		 void *txh, size_t txh_len),
+	TP_ARGS(dev, txh, txh_len),
+	TP_STRUCT__entry(
+		__string(dev, dev_name(dev))
+		__dynamic_array(u8, txh, txh_len)
+	),
+	TP_fast_assign(
+		__assign_str(dev, dev_name(dev));
+		memcpy(__get_dynamic_array(txh), txh, txh_len);
+	),
+	TP_printk("[%s] txdesc", __get_str(dev))
+);
+
+TRACE_EVENT(brcms_txstatus,
+	TP_PROTO(const struct device *dev, u16 framelen, u16 frameid,
+		 u16 status, u16 lasttxtime, u16 sequence, u16 phyerr,
+		 u16 ackphyrxsh),
+	TP_ARGS(dev, framelen, frameid, status, lasttxtime, sequence, phyerr,
+		ackphyrxsh),
+	TP_STRUCT__entry(
+		__string(dev, dev_name(dev))
+		__field(u16, framelen)
+		__field(u16, frameid)
+		__field(u16, status)
+		__field(u16, lasttxtime)
+		__field(u16, sequence)
+		__field(u16, phyerr)
+		__field(u16, ackphyrxsh)
+	),
+	TP_fast_assign(
+		__assign_str(dev, dev_name(dev));
+		__entry->framelen = framelen;
+		__entry->frameid = frameid;
+		__entry->status = status;
+		__entry->lasttxtime = lasttxtime;
+		__entry->sequence = sequence;
+		__entry->phyerr = phyerr;
+		__entry->ackphyrxsh = ackphyrxsh;
+	),
+	TP_printk("[%s] FrameId %#04x TxStatus %#04x LastTxTime %#04x "
+		  "Seq %#04x PHYTxStatus %#04x RxAck %#04x",
+		  __get_str(dev), __entry->frameid, __entry->status,
+		  __entry->lasttxtime, __entry->sequence, __entry->phyerr,
+		  __entry->ackphyrxsh)
+);
+
+TRACE_EVENT(brcms_ampdu_session,
+	TP_PROTO(const struct device *dev, unsigned max_ampdu_len,
+		 u16 max_ampdu_frames, u16 ampdu_len, u16 ampdu_frames,
+		 u16 dma_len),
+	TP_ARGS(dev, max_ampdu_len, max_ampdu_frames, ampdu_len, ampdu_frames,
+		dma_len),
+	TP_STRUCT__entry(
+		__string(dev, dev_name(dev))
+		__field(unsigned, max_ampdu_len)
+		__field(u16, max_ampdu_frames)
+		__field(u16, ampdu_len)
+		__field(u16, ampdu_frames)
+		__field(u16, dma_len)
+	),
+	TP_fast_assign(
+		__assign_str(dev, dev_name(dev));
+		__entry->max_ampdu_len = max_ampdu_len;
+		__entry->max_ampdu_frames = max_ampdu_frames;
+		__entry->ampdu_len = ampdu_len;
+		__entry->ampdu_frames = ampdu_frames;
+		__entry->dma_len = dma_len;
+	),
+	TP_printk("[%s] ampdu session max_len=%u max_frames=%u len=%u frames=%u dma_len=%u",
+		  __get_str(dev), __entry->max_ampdu_len,
+		  __entry->max_ampdu_frames, __entry->ampdu_len,
+		  __entry->ampdu_frames, __entry->dma_len)
+);
+#endif /* __TRACE_BRCMSMAC_TX_H */
+
+#ifdef CONFIG_BRCM_TRACING
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE brcms_trace_brcmsmac_tx
+#include <trace/define_trace.h>
+
+#endif /* CONFIG_BRCM_TRACING */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_events.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_events.c
new file mode 100644
index 0000000..52fc9ee
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_events.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/module.h> /* bug in tracepoint.h, it should include this */
+
+#ifndef __CHECKER__
+#include "mac80211_if.h"
+#define CREATE_TRACE_POINTS
+#include "brcms_trace_events.h"
+#endif
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_events.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_events.h
new file mode 100644
index 0000000..cbf2f06
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_events.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __BRCMS_TRACE_EVENTS_H
+#define __BRCMS_TRACE_EVENTS_H
+
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/tracepoint.h>
+#include "mac80211_if.h"
+
+#ifndef CONFIG_BRCM_TRACING
+#undef TRACE_EVENT
+#define TRACE_EVENT(name, proto, ...) \
+static inline void trace_ ## name(proto) {}
+#undef DECLARE_EVENT_CLASS
+#define DECLARE_EVENT_CLASS(...)
+#undef DEFINE_EVENT
+#define DEFINE_EVENT(evt_class, name, proto, ...) \
+static inline void trace_ ## name(proto) {}
+#endif
+
+#include "brcms_trace_brcmsmac.h"
+#include "brcms_trace_brcmsmac_tx.h"
+#include "brcms_trace_brcmsmac_msg.h"
+
+#endif /* __TRACE_BRCMSMAC_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c
new file mode 100644
index 0000000..db783e9
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c
@@ -0,0 +1,773 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/types.h>
+#include <net/cfg80211.h>
+#include <net/mac80211.h>
+#include <net/regulatory.h>
+
+#include <defs.h>
+#include "pub.h"
+#include "phy/phy_hal.h"
+#include "main.h"
+#include "stf.h"
+#include "channel.h"
+#include "mac80211_if.h"
+#include "debug.h"
+
+/* QDB() macro takes a dB value and converts to a quarter dB value */
+#define QDB(n) ((n) * BRCMS_TXPWR_DB_FACTOR)
+
+#define LOCALE_MIMO_IDX_bn		0
+#define LOCALE_MIMO_IDX_11n		0
+
+/* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */
+#define BRCMS_MAXPWR_MIMO_TBL_SIZE	14
+
+/* maxpwr mapping to 5GHz band channels:
+ * maxpwr[0] - channels [34-48]
+ * maxpwr[1] - channels [52-60]
+ * maxpwr[2] - channels [62-64]
+ * maxpwr[3] - channels [100-140]
+ * maxpwr[4] - channels [149-165]
+ */
+#define BAND_5G_PWR_LVLS	5	/* 5 power levels for 5G */
+
+#define LC(id)	LOCALE_MIMO_IDX_ ## id
+
+#define LOCALES(mimo2, mimo5) \
+		{LC(mimo2), LC(mimo5)}
+
+/* macro to get 5 GHz channel group index for tx power */
+#define CHANNEL_POWER_IDX_5G(c) (((c) < 52) ? 0 : \
+				 (((c) < 62) ? 1 : \
+				 (((c) < 100) ? 2 : \
+				 (((c) < 149) ? 3 : 4))))
+
+#define BRCM_2GHZ_2412_2462	REG_RULE(2412-10, 2462+10, 40, 0, 19, 0)
+#define BRCM_2GHZ_2467_2472	REG_RULE(2467-10, 2472+10, 20, 0, 19, \
+					 NL80211_RRF_NO_IR)
+
+#define BRCM_5GHZ_5180_5240	REG_RULE(5180-10, 5240+10, 40, 0, 21, \
+					 NL80211_RRF_NO_IR)
+#define BRCM_5GHZ_5260_5320	REG_RULE(5260-10, 5320+10, 40, 0, 21, \
+					 NL80211_RRF_DFS | \
+					 NL80211_RRF_NO_IR)
+#define BRCM_5GHZ_5500_5700	REG_RULE(5500-10, 5700+10, 40, 0, 21, \
+					 NL80211_RRF_DFS | \
+					 NL80211_RRF_NO_IR)
+#define BRCM_5GHZ_5745_5825	REG_RULE(5745-10, 5825+10, 40, 0, 21, \
+					 NL80211_RRF_NO_IR)
+
+static const struct ieee80211_regdomain brcms_regdom_x2 = {
+	.n_reg_rules = 6,
+	.alpha2 = "X2",
+	.reg_rules = {
+		BRCM_2GHZ_2412_2462,
+		BRCM_2GHZ_2467_2472,
+		BRCM_5GHZ_5180_5240,
+		BRCM_5GHZ_5260_5320,
+		BRCM_5GHZ_5500_5700,
+		BRCM_5GHZ_5745_5825,
+	}
+};
+
+ /* locale per-channel tx power limits for MIMO frames
+  * maxpwr arrays are index by channel for 2.4 GHz limits, and
+  * by sub-band for 5 GHz limits using CHANNEL_POWER_IDX_5G(channel)
+  */
+struct locale_mimo_info {
+	/* tx 20 MHz power limits, qdBm units */
+	s8 maxpwr20[BRCMS_MAXPWR_MIMO_TBL_SIZE];
+	/* tx 40 MHz power limits, qdBm units */
+	s8 maxpwr40[BRCMS_MAXPWR_MIMO_TBL_SIZE];
+};
+
+/* Country names and abbreviations with locale defined from ISO 3166 */
+struct country_info {
+	const u8 locale_mimo_2G;	/* 2.4G mimo info */
+	const u8 locale_mimo_5G;	/* 5G mimo info */
+};
+
+struct brcms_regd {
+	struct country_info country;
+	const struct ieee80211_regdomain *regdomain;
+};
+
+struct brcms_cm_info {
+	struct brcms_pub *pub;
+	struct brcms_c_info *wlc;
+	const struct brcms_regd *world_regd;
+};
+
+/*
+ * MIMO Locale Definitions - 2.4 GHz
+ */
+static const struct locale_mimo_info locale_bn = {
+	{QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
+	 QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
+	 QDB(13), QDB(13), QDB(13)},
+	{0, 0, QDB(13), QDB(13), QDB(13),
+	 QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
+	 QDB(13), 0, 0},
+};
+
+static const struct locale_mimo_info *g_mimo_2g_table[] = {
+	&locale_bn
+};
+
+/*
+ * MIMO Locale Definitions - 5 GHz
+ */
+static const struct locale_mimo_info locale_11n = {
+	{ /* 12.5 dBm */ 50, 50, 50, QDB(15), QDB(15)},
+	{QDB(14), QDB(15), QDB(15), QDB(15), QDB(15)},
+};
+
+static const struct locale_mimo_info *g_mimo_5g_table[] = {
+	&locale_11n
+};
+
+static const struct brcms_regd cntry_locales[] = {
+	/* Worldwide RoW 2, must always be at index 0 */
+	{
+		.country = LOCALES(bn, 11n),
+		.regdomain = &brcms_regdom_x2,
+	},
+};
+
+static const struct locale_mimo_info *brcms_c_get_mimo_2g(u8 locale_idx)
+{
+	if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table))
+		return NULL;
+
+	return g_mimo_2g_table[locale_idx];
+}
+
+static const struct locale_mimo_info *brcms_c_get_mimo_5g(u8 locale_idx)
+{
+	if (locale_idx >= ARRAY_SIZE(g_mimo_5g_table))
+		return NULL;
+
+	return g_mimo_5g_table[locale_idx];
+}
+
+/*
+ * Indicates whether the country provided is valid to pass
+ * to cfg80211 or not.
+ *
+ * returns true if valid; false if not.
+ */
+static bool brcms_c_country_valid(const char *ccode)
+{
+	/*
+	 * only allow ascii alpha uppercase for the first 2
+	 * chars.
+	 */
+	if (!((ccode[0] & 0x80) == 0 && ccode[0] >= 0x41 && ccode[0] <= 0x5A &&
+	      (ccode[1] & 0x80) == 0 && ccode[1] >= 0x41 && ccode[1] <= 0x5A))
+		return false;
+
+	/*
+	 * do not match ISO 3166-1 user assigned country codes
+	 * that may be in the driver table
+	 */
+	if (!strcmp("AA", ccode) ||        /* AA */
+	    !strcmp("ZZ", ccode) ||        /* ZZ */
+	    ccode[0] == 'X' ||             /* XA - XZ */
+	    (ccode[0] == 'Q' &&            /* QM - QZ */
+	     (ccode[1] >= 'M' && ccode[1] <= 'Z')))
+		return false;
+
+	if (!strcmp("NA", ccode))
+		return false;
+
+	return true;
+}
+
+static const struct brcms_regd *brcms_world_regd(const char *regdom, int len)
+{
+	const struct brcms_regd *regd = NULL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(cntry_locales); i++) {
+		if (!strncmp(regdom, cntry_locales[i].regdomain->alpha2, len)) {
+			regd = &cntry_locales[i];
+			break;
+		}
+	}
+
+	return regd;
+}
+
+static const struct brcms_regd *brcms_default_world_regd(void)
+{
+	return &cntry_locales[0];
+}
+
+/* JP, J1 - J10 are Japan ccodes */
+static bool brcms_c_japan_ccode(const char *ccode)
+{
+	return (ccode[0] == 'J' &&
+		(ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9')));
+}
+
+static void
+brcms_c_channel_min_txpower_limits_with_local_constraint(
+		struct brcms_cm_info *wlc_cm, struct txpwr_limits *txpwr,
+		u8 local_constraint_qdbm)
+{
+	int j;
+
+	/* CCK Rates */
+	for (j = 0; j < WL_TX_POWER_CCK_NUM; j++)
+		txpwr->cck[j] = min(txpwr->cck[j], local_constraint_qdbm);
+
+	/* 20 MHz Legacy OFDM SISO */
+	for (j = 0; j < WL_TX_POWER_OFDM_NUM; j++)
+		txpwr->ofdm[j] = min(txpwr->ofdm[j], local_constraint_qdbm);
+
+	/* 20 MHz Legacy OFDM CDD */
+	for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
+		txpwr->ofdm_cdd[j] =
+		    min(txpwr->ofdm_cdd[j], local_constraint_qdbm);
+
+	/* 40 MHz Legacy OFDM SISO */
+	for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
+		txpwr->ofdm_40_siso[j] =
+		    min(txpwr->ofdm_40_siso[j], local_constraint_qdbm);
+
+	/* 40 MHz Legacy OFDM CDD */
+	for (j = 0; j < BRCMS_NUM_RATES_OFDM; j++)
+		txpwr->ofdm_40_cdd[j] =
+		    min(txpwr->ofdm_40_cdd[j], local_constraint_qdbm);
+
+	/* 20MHz MCS 0-7 SISO */
+	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
+		txpwr->mcs_20_siso[j] =
+		    min(txpwr->mcs_20_siso[j], local_constraint_qdbm);
+
+	/* 20MHz MCS 0-7 CDD */
+	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
+		txpwr->mcs_20_cdd[j] =
+		    min(txpwr->mcs_20_cdd[j], local_constraint_qdbm);
+
+	/* 20MHz MCS 0-7 STBC */
+	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
+		txpwr->mcs_20_stbc[j] =
+		    min(txpwr->mcs_20_stbc[j], local_constraint_qdbm);
+
+	/* 20MHz MCS 8-15 MIMO */
+	for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++)
+		txpwr->mcs_20_mimo[j] =
+		    min(txpwr->mcs_20_mimo[j], local_constraint_qdbm);
+
+	/* 40MHz MCS 0-7 SISO */
+	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
+		txpwr->mcs_40_siso[j] =
+		    min(txpwr->mcs_40_siso[j], local_constraint_qdbm);
+
+	/* 40MHz MCS 0-7 CDD */
+	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
+		txpwr->mcs_40_cdd[j] =
+		    min(txpwr->mcs_40_cdd[j], local_constraint_qdbm);
+
+	/* 40MHz MCS 0-7 STBC */
+	for (j = 0; j < BRCMS_NUM_RATES_MCS_1_STREAM; j++)
+		txpwr->mcs_40_stbc[j] =
+		    min(txpwr->mcs_40_stbc[j], local_constraint_qdbm);
+
+	/* 40MHz MCS 8-15 MIMO */
+	for (j = 0; j < BRCMS_NUM_RATES_MCS_2_STREAM; j++)
+		txpwr->mcs_40_mimo[j] =
+		    min(txpwr->mcs_40_mimo[j], local_constraint_qdbm);
+
+	/* 40MHz MCS 32 */
+	txpwr->mcs32 = min(txpwr->mcs32, local_constraint_qdbm);
+
+}
+
+/*
+ * set the driver's current country and regulatory information
+ * using a country code as the source. Look up built in country
+ * information found with the country code.
+ */
+static void
+brcms_c_set_country(struct brcms_cm_info *wlc_cm,
+		    const struct brcms_regd *regd)
+{
+	struct brcms_c_info *wlc = wlc_cm->wlc;
+
+	if ((wlc->pub->_n_enab & SUPPORT_11N) !=
+	    wlc->protection->nmode_user)
+		brcms_c_set_nmode(wlc);
+
+	brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
+	brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
+
+	brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
+
+	return;
+}
+
+struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
+{
+	struct brcms_cm_info *wlc_cm;
+	struct brcms_pub *pub = wlc->pub;
+	struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom;
+	const char *ccode = sprom->alpha2;
+	int ccode_len = sizeof(sprom->alpha2);
+
+	wlc_cm = kzalloc(sizeof(struct brcms_cm_info), GFP_ATOMIC);
+	if (wlc_cm == NULL)
+		return NULL;
+	wlc_cm->pub = pub;
+	wlc_cm->wlc = wlc;
+	wlc->cmi = wlc_cm;
+
+	/* store the country code for passing up as a regulatory hint */
+	wlc_cm->world_regd = brcms_world_regd(ccode, ccode_len);
+	if (brcms_c_country_valid(ccode))
+		strncpy(wlc->pub->srom_ccode, ccode, ccode_len);
+
+	/*
+	 * If no custom world domain is found in the SROM, use the
+	 * default "X2" domain.
+	 */
+	if (!wlc_cm->world_regd) {
+		wlc_cm->world_regd = brcms_default_world_regd();
+		ccode = wlc_cm->world_regd->regdomain->alpha2;
+		ccode_len = BRCM_CNTRY_BUF_SZ - 1;
+	}
+
+	/* save default country for exiting 11d regulatory mode */
+	strncpy(wlc->country_default, ccode, ccode_len);
+
+	/* initialize autocountry_default to driver default */
+	strncpy(wlc->autocountry_default, ccode, ccode_len);
+
+	brcms_c_set_country(wlc_cm, wlc_cm->world_regd);
+
+	return wlc_cm;
+}
+
+void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm)
+{
+	kfree(wlc_cm);
+}
+
+void
+brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,
+			 u8 local_constraint_qdbm)
+{
+	struct brcms_c_info *wlc = wlc_cm->wlc;
+	struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.chandef.chan;
+	struct txpwr_limits txpwr;
+
+	brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr);
+
+	brcms_c_channel_min_txpower_limits_with_local_constraint(
+		wlc_cm, &txpwr, local_constraint_qdbm
+	);
+
+	/* set or restore gmode as required by regulatory */
+	if (ch->flags & IEEE80211_CHAN_NO_OFDM)
+		brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false);
+	else
+		brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false);
+
+	brcms_b_set_chanspec(wlc->hw, chanspec,
+			      !!(ch->flags & IEEE80211_CHAN_NO_IR),
+			      &txpwr);
+}
+
+void
+brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
+		       struct txpwr_limits *txpwr)
+{
+	struct brcms_c_info *wlc = wlc_cm->wlc;
+	struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.chandef.chan;
+	uint i;
+	uint chan;
+	int maxpwr;
+	int delta;
+	const struct country_info *country;
+	struct brcms_band *band;
+	int conducted_max = BRCMS_TXPWR_MAX;
+	const struct locale_mimo_info *li_mimo;
+	int maxpwr20, maxpwr40;
+	int maxpwr_idx;
+	uint j;
+
+	memset(txpwr, 0, sizeof(struct txpwr_limits));
+
+	if (WARN_ON(!ch))
+		return;
+
+	country = &wlc_cm->world_regd->country;
+
+	chan = CHSPEC_CHANNEL(chanspec);
+	band = wlc->bandstate[chspec_bandunit(chanspec)];
+	li_mimo = (band->bandtype == BRCM_BAND_5G) ?
+	    brcms_c_get_mimo_5g(country->locale_mimo_5G) :
+	    brcms_c_get_mimo_2g(country->locale_mimo_2G);
+
+	delta = band->antgain;
+
+	if (band->bandtype == BRCM_BAND_2G)
+		conducted_max = QDB(22);
+
+	maxpwr = QDB(ch->max_power) - delta;
+	maxpwr = max(maxpwr, 0);
+	maxpwr = min(maxpwr, conducted_max);
+
+	/* CCK txpwr limits for 2.4G band */
+	if (band->bandtype == BRCM_BAND_2G) {
+		for (i = 0; i < BRCMS_NUM_RATES_CCK; i++)
+			txpwr->cck[i] = (u8) maxpwr;
+	}
+
+	for (i = 0; i < BRCMS_NUM_RATES_OFDM; i++) {
+		txpwr->ofdm[i] = (u8) maxpwr;
+
+		/*
+		 * OFDM 40 MHz SISO has the same power as the corresponding
+		 * MCS0-7 rate unless overriden by the locale specific code.
+		 * We set this value to 0 as a flag (presumably 0 dBm isn't
+		 * a possibility) and then copy the MCS0-7 value to the 40 MHz
+		 * value if it wasn't explicitly set.
+		 */
+		txpwr->ofdm_40_siso[i] = 0;
+
+		txpwr->ofdm_cdd[i] = (u8) maxpwr;
+
+		txpwr->ofdm_40_cdd[i] = 0;
+	}
+
+	delta = 0;
+	if (band->antgain > QDB(6))
+		delta = band->antgain - QDB(6);	/* Excess over 6 dB */
+
+	if (band->bandtype == BRCM_BAND_2G)
+		maxpwr_idx = (chan - 1);
+	else
+		maxpwr_idx = CHANNEL_POWER_IDX_5G(chan);
+
+	maxpwr20 = li_mimo->maxpwr20[maxpwr_idx];
+	maxpwr40 = li_mimo->maxpwr40[maxpwr_idx];
+
+	maxpwr20 = maxpwr20 - delta;
+	maxpwr20 = max(maxpwr20, 0);
+	maxpwr40 = maxpwr40 - delta;
+	maxpwr40 = max(maxpwr40, 0);
+
+	/* Fill in the MCS 0-7 (SISO) rates */
+	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+
+		/*
+		 * 20 MHz has the same power as the corresponding OFDM rate
+		 * unless overriden by the locale specific code.
+		 */
+		txpwr->mcs_20_siso[i] = txpwr->ofdm[i];
+		txpwr->mcs_40_siso[i] = 0;
+	}
+
+	/* Fill in the MCS 0-7 CDD rates */
+	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+		txpwr->mcs_20_cdd[i] = (u8) maxpwr20;
+		txpwr->mcs_40_cdd[i] = (u8) maxpwr40;
+	}
+
+	/*
+	 * These locales have SISO expressed in the
+	 * table and override CDD later
+	 */
+	if (li_mimo == &locale_bn) {
+		if (li_mimo == &locale_bn) {
+			maxpwr20 = QDB(16);
+			maxpwr40 = 0;
+
+			if (chan >= 3 && chan <= 11)
+				maxpwr40 = QDB(16);
+		}
+
+		for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+			txpwr->mcs_20_siso[i] = (u8) maxpwr20;
+			txpwr->mcs_40_siso[i] = (u8) maxpwr40;
+		}
+	}
+
+	/* Fill in the MCS 0-7 STBC rates */
+	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+		txpwr->mcs_20_stbc[i] = 0;
+		txpwr->mcs_40_stbc[i] = 0;
+	}
+
+	/* Fill in the MCS 8-15 SDM rates */
+	for (i = 0; i < BRCMS_NUM_RATES_MCS_2_STREAM; i++) {
+		txpwr->mcs_20_mimo[i] = (u8) maxpwr20;
+		txpwr->mcs_40_mimo[i] = (u8) maxpwr40;
+	}
+
+	/* Fill in MCS32 */
+	txpwr->mcs32 = (u8) maxpwr40;
+
+	for (i = 0, j = 0; i < BRCMS_NUM_RATES_OFDM; i++, j++) {
+		if (txpwr->ofdm_40_cdd[i] == 0)
+			txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j];
+		if (i == 0) {
+			i = i + 1;
+			if (txpwr->ofdm_40_cdd[i] == 0)
+				txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j];
+		}
+	}
+
+	/*
+	 * Copy the 40 MHZ MCS 0-7 CDD value to the 40 MHZ MCS 0-7 SISO
+	 * value if it wasn't provided explicitly.
+	 */
+	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+		if (txpwr->mcs_40_siso[i] == 0)
+			txpwr->mcs_40_siso[i] = txpwr->mcs_40_cdd[i];
+	}
+
+	for (i = 0, j = 0; i < BRCMS_NUM_RATES_OFDM; i++, j++) {
+		if (txpwr->ofdm_40_siso[i] == 0)
+			txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j];
+		if (i == 0) {
+			i = i + 1;
+			if (txpwr->ofdm_40_siso[i] == 0)
+				txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j];
+		}
+	}
+
+	/*
+	 * Copy the 20 and 40 MHz MCS0-7 CDD values to the corresponding
+	 * STBC values if they weren't provided explicitly.
+	 */
+	for (i = 0; i < BRCMS_NUM_RATES_MCS_1_STREAM; i++) {
+		if (txpwr->mcs_20_stbc[i] == 0)
+			txpwr->mcs_20_stbc[i] = txpwr->mcs_20_cdd[i];
+
+		if (txpwr->mcs_40_stbc[i] == 0)
+			txpwr->mcs_40_stbc[i] = txpwr->mcs_40_cdd[i];
+	}
+
+	return;
+}
+
+/*
+ * Verify the chanspec is using a legal set of parameters, i.e. that the
+ * chanspec specified a band, bw, ctl_sb and channel and that the
+ * combination could be legal given any set of circumstances.
+ * RETURNS: true is the chanspec is malformed, false if it looks good.
+ */
+static bool brcms_c_chspec_malformed(u16 chanspec)
+{
+	/* must be 2G or 5G band */
+	if (!CHSPEC_IS5G(chanspec) && !CHSPEC_IS2G(chanspec))
+		return true;
+	/* must be 20 or 40 bandwidth */
+	if (!CHSPEC_IS40(chanspec) && !CHSPEC_IS20(chanspec))
+		return true;
+
+	/* 20MHZ b/w must have no ctl sb, 40 must have a ctl sb */
+	if (CHSPEC_IS20(chanspec)) {
+		if (!CHSPEC_SB_NONE(chanspec))
+			return true;
+	} else if (!CHSPEC_SB_UPPER(chanspec) && !CHSPEC_SB_LOWER(chanspec)) {
+		return true;
+	}
+
+	return false;
+}
+
+/*
+ * Validate the chanspec for this locale, for 40MHZ we need to also
+ * check that the sidebands are valid 20MZH channels in this locale
+ * and they are also a legal HT combination
+ */
+static bool
+brcms_c_valid_chanspec_ext(struct brcms_cm_info *wlc_cm, u16 chspec)
+{
+	struct brcms_c_info *wlc = wlc_cm->wlc;
+	u8 channel = CHSPEC_CHANNEL(chspec);
+
+	/* check the chanspec */
+	if (brcms_c_chspec_malformed(chspec)) {
+		brcms_err(wlc->hw->d11core, "wl%d: malformed chanspec 0x%x\n",
+			  wlc->pub->unit, chspec);
+		return false;
+	}
+
+	if (CHANNEL_BANDUNIT(wlc_cm->wlc, channel) !=
+	    chspec_bandunit(chspec))
+		return false;
+
+	return true;
+}
+
+bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec)
+{
+	return brcms_c_valid_chanspec_ext(wlc_cm, chspec);
+}
+
+static bool brcms_is_radar_freq(u16 center_freq)
+{
+	return center_freq >= 5260 && center_freq <= 5700;
+}
+
+static void brcms_reg_apply_radar_flags(struct wiphy *wiphy)
+{
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_channel *ch;
+	int i;
+
+	sband = wiphy->bands[NL80211_BAND_5GHZ];
+	if (!sband)
+		return;
+
+	for (i = 0; i < sband->n_channels; i++) {
+		ch = &sband->channels[i];
+
+		if (!brcms_is_radar_freq(ch->center_freq))
+			continue;
+
+		/*
+		 * All channels in this range should be passive and have
+		 * DFS enabled.
+		 */
+		if (!(ch->flags & IEEE80211_CHAN_DISABLED))
+			ch->flags |= IEEE80211_CHAN_RADAR |
+				     IEEE80211_CHAN_NO_IR;
+	}
+}
+
+static void
+brcms_reg_apply_beaconing_flags(struct wiphy *wiphy,
+				enum nl80211_reg_initiator initiator)
+{
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_channel *ch;
+	const struct ieee80211_reg_rule *rule;
+	int band, i;
+
+	for (band = 0; band < NUM_NL80211_BANDS; band++) {
+		sband = wiphy->bands[band];
+		if (!sband)
+			continue;
+
+		for (i = 0; i < sband->n_channels; i++) {
+			ch = &sband->channels[i];
+
+			if (ch->flags &
+			    (IEEE80211_CHAN_DISABLED | IEEE80211_CHAN_RADAR))
+				continue;
+
+			if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
+				rule = freq_reg_info(wiphy,
+						     MHZ_TO_KHZ(ch->center_freq));
+				if (IS_ERR(rule))
+					continue;
+
+				if (!(rule->flags & NL80211_RRF_NO_IR))
+					ch->flags &= ~IEEE80211_CHAN_NO_IR;
+			} else if (ch->beacon_found) {
+				ch->flags &= ~IEEE80211_CHAN_NO_IR;
+			}
+		}
+	}
+}
+
+static void brcms_reg_notifier(struct wiphy *wiphy,
+			       struct regulatory_request *request)
+{
+	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+	struct brcms_info *wl = hw->priv;
+	struct brcms_c_info *wlc = wl->wlc;
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_channel *ch;
+	int band, i;
+	bool ch_found = false;
+
+	brcms_reg_apply_radar_flags(wiphy);
+
+	if (request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
+		brcms_reg_apply_beaconing_flags(wiphy, request->initiator);
+
+	/* Disable radio if all channels disallowed by regulatory */
+	for (band = 0; !ch_found && band < NUM_NL80211_BANDS; band++) {
+		sband = wiphy->bands[band];
+		if (!sband)
+			continue;
+
+		for (i = 0; !ch_found && i < sband->n_channels; i++) {
+			ch = &sband->channels[i];
+
+			if (!(ch->flags & IEEE80211_CHAN_DISABLED))
+				ch_found = true;
+		}
+	}
+
+	if (ch_found) {
+		mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
+	} else {
+		mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
+		brcms_err(wlc->hw->d11core,
+			  "wl%d: %s: no valid channel for \"%s\"\n",
+			  wlc->pub->unit, __func__, request->alpha2);
+	}
+
+	if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G)
+		wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
+					brcms_c_japan_ccode(request->alpha2));
+}
+
+void brcms_c_regd_init(struct brcms_c_info *wlc)
+{
+	struct wiphy *wiphy = wlc->wiphy;
+	const struct brcms_regd *regd = wlc->cmi->world_regd;
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_channel *ch;
+	struct brcms_chanvec sup_chan;
+	struct brcms_band *band;
+	int band_idx, i;
+
+	/* Disable any channels not supported by the phy */
+	for (band_idx = 0; band_idx < wlc->pub->_nbands; band_idx++) {
+		band = wlc->bandstate[band_idx];
+
+		wlc_phy_chanspec_band_validch(band->pi, band->bandtype,
+					      &sup_chan);
+
+		if (band_idx == BAND_2G_INDEX)
+			sband = wiphy->bands[NL80211_BAND_2GHZ];
+		else
+			sband = wiphy->bands[NL80211_BAND_5GHZ];
+
+		for (i = 0; i < sband->n_channels; i++) {
+			ch = &sband->channels[i];
+			if (!isset(sup_chan.vec, ch->hw_value))
+				ch->flags |= IEEE80211_CHAN_DISABLED;
+		}
+	}
+
+	wlc->wiphy->reg_notifier = brcms_reg_notifier;
+	wlc->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
+					REGULATORY_STRICT_REG;
+	wiphy_apply_custom_regulatory(wlc->wiphy, regd->regdomain);
+	brcms_reg_apply_beaconing_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER);
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.h
new file mode 100644
index 0000000..39dd3a5
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_CHANNEL_H_
+#define _BRCM_CHANNEL_H_
+
+/* conversion for phy txpwr calculations that use .25 dB units */
+#define BRCMS_TXPWR_DB_FACTOR 4
+
+/* bits for locale_info flags */
+#define BRCMS_PEAK_CONDUCTED	0x00	/* Peak for locals */
+#define BRCMS_EIRP		0x01	/* Flag for EIRP */
+#define BRCMS_DFS_TPC		0x02	/* Flag for DFS TPC */
+#define BRCMS_NO_OFDM		0x04	/* Flag for No OFDM */
+#define BRCMS_NO_40MHZ		0x08	/* Flag for No MIMO 40MHz */
+#define BRCMS_NO_MIMO		0x10	/* Flag for No MIMO, 20 or 40 MHz */
+#define BRCMS_RADAR_TYPE_EU       0x20	/* Flag for EU */
+#define BRCMS_DFS_FCC             BRCMS_DFS_TPC	/* Flag for DFS FCC */
+
+#define BRCMS_DFS_EU (BRCMS_DFS_TPC | BRCMS_RADAR_TYPE_EU) /* Flag for DFS EU */
+
+struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc);
+
+void brcms_c_channel_mgr_detach(struct brcms_cm_info *wlc_cm);
+
+bool brcms_c_valid_chanspec_db(struct brcms_cm_info *wlc_cm, u16 chspec);
+
+void brcms_c_channel_reg_limits(struct brcms_cm_info *wlc_cm, u16 chanspec,
+				struct txpwr_limits *txpwr);
+void brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,
+				  u8 local_constraint_qdbm);
+void brcms_c_regd_init(struct brcms_c_info *wlc);
+
+#endif				/* _WLC_CHANNEL_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/d11.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/d11.h
new file mode 100644
index 0000000..9035cc4
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/d11.h
@@ -0,0 +1,1902 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_BRCM_D11_H_
+#define	_BRCM_D11_H_
+
+#include <linux/ieee80211.h>
+
+#include <defs.h>
+#include "pub.h"
+#include "dma.h"
+
+/* RX FIFO numbers */
+#define	RX_FIFO			0	/* data and ctl frames */
+#define	RX_TXSTATUS_FIFO	3	/* RX fifo for tx status packages */
+
+/* TX FIFO numbers using WME Access Category */
+#define	TX_AC_BK_FIFO		0	/* Background TX FIFO */
+#define	TX_AC_BE_FIFO		1	/* Best-Effort TX FIFO */
+#define	TX_AC_VI_FIFO		2	/* Video TX FIFO */
+#define	TX_AC_VO_FIFO		3	/* Voice TX FIFO */
+#define	TX_BCMC_FIFO		4	/* Broadcast/Multicast TX FIFO */
+#define	TX_ATIM_FIFO		5	/* TX fifo for ATIM window info */
+
+/* Addr is byte address used by SW; offset is word offset used by uCode */
+
+/* Per AC TX limit settings */
+#define M_AC_TXLMT_BASE_ADDR         (0x180 * 2)
+#define M_AC_TXLMT_ADDR(_ac)         (M_AC_TXLMT_BASE_ADDR + (2 * (_ac)))
+
+/* Legacy TX FIFO numbers */
+#define	TX_DATA_FIFO		TX_AC_BE_FIFO
+#define	TX_CTL_FIFO		TX_AC_VO_FIFO
+
+#define WL_RSSI_ANT_MAX		4	/* max possible rx antennas */
+
+struct intctrlregs {
+	u32 intstatus;
+	u32 intmask;
+};
+
+/* PIO structure,
+ *  support two PIO format: 2 bytes access and 4 bytes access
+ *  basic FIFO register set is per channel(transmit or receive)
+ *  a pair of channels is defined for convenience
+ */
+/* 2byte-wide pio register set per channel(xmt or rcv) */
+struct pio2regs {
+	u16 fifocontrol;
+	u16 fifodata;
+	u16 fifofree;	/* only valid in xmt channel, not in rcv channel */
+	u16 PAD;
+};
+
+/* a pair of pio channels(tx and rx) */
+struct pio2regp {
+	struct pio2regs tx;
+	struct pio2regs rx;
+};
+
+/* 4byte-wide pio register set per channel(xmt or rcv) */
+struct pio4regs {
+	u32 fifocontrol;
+	u32 fifodata;
+};
+
+/* a pair of pio channels(tx and rx) */
+struct pio4regp {
+	struct pio4regs tx;
+	struct pio4regs rx;
+};
+
+/* read: 32-bit register that can be read as 32-bit or as 2 16-bit
+ * write: only low 16b-it half can be written
+ */
+union pmqreg {
+	u32 pmqhostdata;	/* read only! */
+	struct {
+		u16 pmqctrlstatus;	/* read/write */
+		u16 PAD;
+	} w;
+};
+
+struct fifo64 {
+	struct dma64regs dmaxmt;	/* dma tx */
+	struct pio4regs piotx;	/* pio tx */
+	struct dma64regs dmarcv;	/* dma rx */
+	struct pio4regs piorx;	/* pio rx */
+};
+
+/*
+ * Host Interface Registers
+ */
+struct d11regs {
+	/* Device Control ("semi-standard host registers") */
+	u32 PAD[3];		/* 0x0 - 0x8 */
+	u32 biststatus;	/* 0xC */
+	u32 biststatus2;	/* 0x10 */
+	u32 PAD;		/* 0x14 */
+	u32 gptimer;		/* 0x18 */
+	u32 usectimer;	/* 0x1c *//* for corerev >= 26 */
+
+	/* Interrupt Control *//* 0x20 */
+	struct intctrlregs intctrlregs[8];
+
+	u32 PAD[40];		/* 0x60 - 0xFC */
+
+	u32 intrcvlazy[4];	/* 0x100 - 0x10C */
+
+	u32 PAD[4];		/* 0x110 - 0x11c */
+
+	u32 maccontrol;	/* 0x120 */
+	u32 maccommand;	/* 0x124 */
+	u32 macintstatus;	/* 0x128 */
+	u32 macintmask;	/* 0x12C */
+
+	/* Transmit Template Access */
+	u32 tplatewrptr;	/* 0x130 */
+	u32 tplatewrdata;	/* 0x134 */
+	u32 PAD[2];		/* 0x138 - 0x13C */
+
+	/* PMQ registers */
+	union pmqreg pmqreg;	/* 0x140 */
+	u32 pmqpatl;		/* 0x144 */
+	u32 pmqpath;		/* 0x148 */
+	u32 PAD;		/* 0x14C */
+
+	u32 chnstatus;	/* 0x150 */
+	u32 psmdebug;	/* 0x154 */
+	u32 phydebug;	/* 0x158 */
+	u32 machwcap;	/* 0x15C */
+
+	/* Extended Internal Objects */
+	u32 objaddr;		/* 0x160 */
+	u32 objdata;		/* 0x164 */
+	u32 PAD[2];		/* 0x168 - 0x16c */
+
+	u32 frmtxstatus;	/* 0x170 */
+	u32 frmtxstatus2;	/* 0x174 */
+	u32 PAD[2];		/* 0x178 - 0x17c */
+
+	/* TSF host access */
+	u32 tsf_timerlow;	/* 0x180 */
+	u32 tsf_timerhigh;	/* 0x184 */
+	u32 tsf_cfprep;	/* 0x188 */
+	u32 tsf_cfpstart;	/* 0x18c */
+	u32 tsf_cfpmaxdur32;	/* 0x190 */
+	u32 PAD[3];		/* 0x194 - 0x19c */
+
+	u32 maccontrol1;	/* 0x1a0 */
+	u32 machwcap1;	/* 0x1a4 */
+	u32 PAD[14];		/* 0x1a8 - 0x1dc */
+
+	/* Clock control and hardware workarounds*/
+	u32 clk_ctl_st;	/* 0x1e0 */
+	u32 hw_war;
+	u32 d11_phypllctl;	/* the phypll request/avail bits are
+				 * moved to clk_ctl_st
+				 */
+	u32 PAD[5];		/* 0x1ec - 0x1fc */
+
+	/* 0x200-0x37F dma/pio registers */
+	struct fifo64 fifo64regs[6];
+
+	/* FIFO diagnostic port access */
+	struct dma32diag dmafifo;	/* 0x380 - 0x38C */
+
+	u32 aggfifocnt;	/* 0x390 */
+	u32 aggfifodata;	/* 0x394 */
+	u32 PAD[16];		/* 0x398 - 0x3d4 */
+	u16 radioregaddr;	/* 0x3d8 */
+	u16 radioregdata;	/* 0x3da */
+
+	/*
+	 * time delay between the change on rf disable input and
+	 * radio shutdown
+	 */
+	u32 rfdisabledly;	/* 0x3DC */
+
+	/* PHY register access */
+	u16 phyversion;	/* 0x3e0 - 0x0 */
+	u16 phybbconfig;	/* 0x3e2 - 0x1 */
+	u16 phyadcbias;	/* 0x3e4 - 0x2  Bphy only */
+	u16 phyanacore;	/* 0x3e6 - 0x3  pwwrdwn on aphy */
+	u16 phyrxstatus0;	/* 0x3e8 - 0x4 */
+	u16 phyrxstatus1;	/* 0x3ea - 0x5 */
+	u16 phycrsth;	/* 0x3ec - 0x6 */
+	u16 phytxerror;	/* 0x3ee - 0x7 */
+	u16 phychannel;	/* 0x3f0 - 0x8 */
+	u16 PAD[1];		/* 0x3f2 - 0x9 */
+	u16 phytest;		/* 0x3f4 - 0xa */
+	u16 phy4waddr;	/* 0x3f6 - 0xb */
+	u16 phy4wdatahi;	/* 0x3f8 - 0xc */
+	u16 phy4wdatalo;	/* 0x3fa - 0xd */
+	u16 phyregaddr;	/* 0x3fc - 0xe */
+	u16 phyregdata;	/* 0x3fe - 0xf */
+
+	/* IHR *//* 0x400 - 0x7FE */
+
+	/* RXE Block */
+	u16 PAD[3];		/* 0x400 - 0x406 */
+	u16 rcv_fifo_ctl;	/* 0x406 */
+	u16 PAD;		/* 0x408 - 0x40a */
+	u16 rcv_frm_cnt;	/* 0x40a */
+	u16 PAD[4];		/* 0x40a - 0x414 */
+	u16 rssi;		/* 0x414 */
+	u16 PAD[5];		/* 0x414 - 0x420 */
+	u16 rcm_ctl;		/* 0x420 */
+	u16 rcm_mat_data;	/* 0x422 */
+	u16 rcm_mat_mask;	/* 0x424 */
+	u16 rcm_mat_dly;	/* 0x426 */
+	u16 rcm_cond_mask_l;	/* 0x428 */
+	u16 rcm_cond_mask_h;	/* 0x42A */
+	u16 rcm_cond_dly;	/* 0x42C */
+	u16 PAD[1];		/* 0x42E */
+	u16 ext_ihr_addr;	/* 0x430 */
+	u16 ext_ihr_data;	/* 0x432 */
+	u16 rxe_phyrs_2;	/* 0x434 */
+	u16 rxe_phyrs_3;	/* 0x436 */
+	u16 phy_mode;	/* 0x438 */
+	u16 rcmta_ctl;	/* 0x43a */
+	u16 rcmta_size;	/* 0x43c */
+	u16 rcmta_addr0;	/* 0x43e */
+	u16 rcmta_addr1;	/* 0x440 */
+	u16 rcmta_addr2;	/* 0x442 */
+	u16 PAD[30];		/* 0x444 - 0x480 */
+
+	/* PSM Block *//* 0x480 - 0x500 */
+
+	u16 PAD;		/* 0x480 */
+	u16 psm_maccontrol_h;	/* 0x482 */
+	u16 psm_macintstatus_l;	/* 0x484 */
+	u16 psm_macintstatus_h;	/* 0x486 */
+	u16 psm_macintmask_l;	/* 0x488 */
+	u16 psm_macintmask_h;	/* 0x48A */
+	u16 PAD;		/* 0x48C */
+	u16 psm_maccommand;	/* 0x48E */
+	u16 psm_brc;		/* 0x490 */
+	u16 psm_phy_hdr_param;	/* 0x492 */
+	u16 psm_postcard;	/* 0x494 */
+	u16 psm_pcard_loc_l;	/* 0x496 */
+	u16 psm_pcard_loc_h;	/* 0x498 */
+	u16 psm_gpio_in;	/* 0x49A */
+	u16 psm_gpio_out;	/* 0x49C */
+	u16 psm_gpio_oe;	/* 0x49E */
+
+	u16 psm_bred_0;	/* 0x4A0 */
+	u16 psm_bred_1;	/* 0x4A2 */
+	u16 psm_bred_2;	/* 0x4A4 */
+	u16 psm_bred_3;	/* 0x4A6 */
+	u16 psm_brcl_0;	/* 0x4A8 */
+	u16 psm_brcl_1;	/* 0x4AA */
+	u16 psm_brcl_2;	/* 0x4AC */
+	u16 psm_brcl_3;	/* 0x4AE */
+	u16 psm_brpo_0;	/* 0x4B0 */
+	u16 psm_brpo_1;	/* 0x4B2 */
+	u16 psm_brpo_2;	/* 0x4B4 */
+	u16 psm_brpo_3;	/* 0x4B6 */
+	u16 psm_brwk_0;	/* 0x4B8 */
+	u16 psm_brwk_1;	/* 0x4BA */
+	u16 psm_brwk_2;	/* 0x4BC */
+	u16 psm_brwk_3;	/* 0x4BE */
+
+	u16 psm_base_0;	/* 0x4C0 */
+	u16 psm_base_1;	/* 0x4C2 */
+	u16 psm_base_2;	/* 0x4C4 */
+	u16 psm_base_3;	/* 0x4C6 */
+	u16 psm_base_4;	/* 0x4C8 */
+	u16 psm_base_5;	/* 0x4CA */
+	u16 psm_base_6;	/* 0x4CC */
+	u16 psm_pc_reg_0;	/* 0x4CE */
+	u16 psm_pc_reg_1;	/* 0x4D0 */
+	u16 psm_pc_reg_2;	/* 0x4D2 */
+	u16 psm_pc_reg_3;	/* 0x4D4 */
+	u16 PAD[0xD];	/* 0x4D6 - 0x4DE */
+	u16 psm_corectlsts;	/* 0x4f0 *//* Corerev >= 13 */
+	u16 PAD[0x7];	/* 0x4f2 - 0x4fE */
+
+	/* TXE0 Block *//* 0x500 - 0x580 */
+	u16 txe_ctl;		/* 0x500 */
+	u16 txe_aux;		/* 0x502 */
+	u16 txe_ts_loc;	/* 0x504 */
+	u16 txe_time_out;	/* 0x506 */
+	u16 txe_wm_0;	/* 0x508 */
+	u16 txe_wm_1;	/* 0x50A */
+	u16 txe_phyctl;	/* 0x50C */
+	u16 txe_status;	/* 0x50E */
+	u16 txe_mmplcp0;	/* 0x510 */
+	u16 txe_mmplcp1;	/* 0x512 */
+	u16 txe_phyctl1;	/* 0x514 */
+
+	u16 PAD[0x05];	/* 0x510 - 0x51E */
+
+	/* Transmit control */
+	u16 xmtfifodef;	/* 0x520 */
+	u16 xmtfifo_frame_cnt;	/* 0x522 *//* Corerev >= 16 */
+	u16 xmtfifo_byte_cnt;	/* 0x524 *//* Corerev >= 16 */
+	u16 xmtfifo_head;	/* 0x526 *//* Corerev >= 16 */
+	u16 xmtfifo_rd_ptr;	/* 0x528 *//* Corerev >= 16 */
+	u16 xmtfifo_wr_ptr;	/* 0x52A *//* Corerev >= 16 */
+	u16 xmtfifodef1;	/* 0x52C *//* Corerev >= 16 */
+
+	u16 PAD[0x09];	/* 0x52E - 0x53E */
+
+	u16 xmtfifocmd;	/* 0x540 */
+	u16 xmtfifoflush;	/* 0x542 */
+	u16 xmtfifothresh;	/* 0x544 */
+	u16 xmtfifordy;	/* 0x546 */
+	u16 xmtfifoprirdy;	/* 0x548 */
+	u16 xmtfiforqpri;	/* 0x54A */
+	u16 xmttplatetxptr;	/* 0x54C */
+	u16 PAD;		/* 0x54E */
+	u16 xmttplateptr;	/* 0x550 */
+	u16 smpl_clct_strptr;	/* 0x552 *//* Corerev >= 22 */
+	u16 smpl_clct_stpptr;	/* 0x554 *//* Corerev >= 22 */
+	u16 smpl_clct_curptr;	/* 0x556 *//* Corerev >= 22 */
+	u16 PAD[0x04];	/* 0x558 - 0x55E */
+	u16 xmttplatedatalo;	/* 0x560 */
+	u16 xmttplatedatahi;	/* 0x562 */
+
+	u16 PAD[2];		/* 0x564 - 0x566 */
+
+	u16 xmtsel;		/* 0x568 */
+	u16 xmttxcnt;	/* 0x56A */
+	u16 xmttxshmaddr;	/* 0x56C */
+
+	u16 PAD[0x09];	/* 0x56E - 0x57E */
+
+	/* TXE1 Block */
+	u16 PAD[0x40];	/* 0x580 - 0x5FE */
+
+	/* TSF Block */
+	u16 PAD[0X02];	/* 0x600 - 0x602 */
+	u16 tsf_cfpstrt_l;	/* 0x604 */
+	u16 tsf_cfpstrt_h;	/* 0x606 */
+	u16 PAD[0X05];	/* 0x608 - 0x610 */
+	u16 tsf_cfppretbtt;	/* 0x612 */
+	u16 PAD[0XD];	/* 0x614 - 0x62C */
+	u16 tsf_clk_frac_l;	/* 0x62E */
+	u16 tsf_clk_frac_h;	/* 0x630 */
+	u16 PAD[0X14];	/* 0x632 - 0x658 */
+	u16 tsf_random;	/* 0x65A */
+	u16 PAD[0x05];	/* 0x65C - 0x664 */
+	/* GPTimer 2 registers */
+	u16 tsf_gpt2_stat;	/* 0x666 */
+	u16 tsf_gpt2_ctr_l;	/* 0x668 */
+	u16 tsf_gpt2_ctr_h;	/* 0x66A */
+	u16 tsf_gpt2_val_l;	/* 0x66C */
+	u16 tsf_gpt2_val_h;	/* 0x66E */
+	u16 tsf_gptall_stat;	/* 0x670 */
+	u16 PAD[0x07];	/* 0x672 - 0x67E */
+
+	/* IFS Block */
+	u16 ifs_sifs_rx_tx_tx;	/* 0x680 */
+	u16 ifs_sifs_nav_tx;	/* 0x682 */
+	u16 ifs_slot;	/* 0x684 */
+	u16 PAD;		/* 0x686 */
+	u16 ifs_ctl;		/* 0x688 */
+	u16 PAD[0x3];	/* 0x68a - 0x68F */
+	u16 ifsstat;		/* 0x690 */
+	u16 ifsmedbusyctl;	/* 0x692 */
+	u16 iftxdur;		/* 0x694 */
+	u16 PAD[0x3];	/* 0x696 - 0x69b */
+	/* EDCF support in dot11macs */
+	u16 ifs_aifsn;	/* 0x69c */
+	u16 ifs_ctl1;	/* 0x69e */
+
+	/* slow clock registers */
+	u16 scc_ctl;		/* 0x6a0 */
+	u16 scc_timer_l;	/* 0x6a2 */
+	u16 scc_timer_h;	/* 0x6a4 */
+	u16 scc_frac;	/* 0x6a6 */
+	u16 scc_fastpwrup_dly;	/* 0x6a8 */
+	u16 scc_per;		/* 0x6aa */
+	u16 scc_per_frac;	/* 0x6ac */
+	u16 scc_cal_timer_l;	/* 0x6ae */
+	u16 scc_cal_timer_h;	/* 0x6b0 */
+	u16 PAD;		/* 0x6b2 */
+
+	u16 PAD[0x26];
+
+	/* NAV Block */
+	u16 nav_ctl;		/* 0x700 */
+	u16 navstat;		/* 0x702 */
+	u16 PAD[0x3e];	/* 0x702 - 0x77E */
+
+	/* WEP/PMQ Block *//* 0x780 - 0x7FE */
+	u16 PAD[0x20];	/* 0x780 - 0x7BE */
+
+	u16 wepctl;		/* 0x7C0 */
+	u16 wepivloc;	/* 0x7C2 */
+	u16 wepivkey;	/* 0x7C4 */
+	u16 wepwkey;		/* 0x7C6 */
+
+	u16 PAD[4];		/* 0x7C8 - 0x7CE */
+	u16 pcmctl;		/* 0X7D0 */
+	u16 pcmstat;		/* 0X7D2 */
+	u16 PAD[6];		/* 0x7D4 - 0x7DE */
+
+	u16 pmqctl;		/* 0x7E0 */
+	u16 pmqstatus;	/* 0x7E2 */
+	u16 pmqpat0;		/* 0x7E4 */
+	u16 pmqpat1;		/* 0x7E6 */
+	u16 pmqpat2;		/* 0x7E8 */
+
+	u16 pmqdat;		/* 0x7EA */
+	u16 pmqdator;	/* 0x7EC */
+	u16 pmqhst;		/* 0x7EE */
+	u16 pmqpath0;	/* 0x7F0 */
+	u16 pmqpath1;	/* 0x7F2 */
+	u16 pmqpath2;	/* 0x7F4 */
+	u16 pmqdath;		/* 0x7F6 */
+
+	u16 PAD[0x04];	/* 0x7F8 - 0x7FE */
+
+	/* SHM *//* 0x800 - 0xEFE */
+	u16 PAD[0x380];	/* 0x800 - 0xEFE */
+};
+
+/* d11 register field offset */
+#define D11REGOFFS(field)	offsetof(struct d11regs, field)
+
+#define	PIHR_BASE	0x0400	/* byte address of packed IHR region */
+
+/* biststatus */
+#define	BT_DONE		(1U << 31)	/* bist done */
+#define	BT_B2S		(1 << 30)	/* bist2 ram summary bit */
+
+/* intstatus and intmask */
+#define	I_PC		(1 << 10)	/* pci descriptor error */
+#define	I_PD		(1 << 11)	/* pci data error */
+#define	I_DE		(1 << 12)	/* descriptor protocol error */
+#define	I_RU		(1 << 13)	/* receive descriptor underflow */
+#define	I_RO		(1 << 14)	/* receive fifo overflow */
+#define	I_XU		(1 << 15)	/* transmit fifo underflow */
+#define	I_RI		(1 << 16)	/* receive interrupt */
+#define	I_XI		(1 << 24)	/* transmit interrupt */
+
+/* interrupt receive lazy */
+#define	IRL_TO_MASK		0x00ffffff	/* timeout */
+#define	IRL_FC_MASK		0xff000000	/* frame count */
+#define	IRL_FC_SHIFT		24	/* frame count */
+
+/*== maccontrol register ==*/
+#define	MCTL_GMODE		(1U << 31)
+#define	MCTL_DISCARD_PMQ	(1 << 30)
+#define	MCTL_TBTTHOLD		(1 << 28)
+#define	MCTL_WAKE		(1 << 26)
+#define	MCTL_HPS		(1 << 25)
+#define	MCTL_PROMISC		(1 << 24)
+#define	MCTL_KEEPBADFCS		(1 << 23)
+#define	MCTL_KEEPCONTROL	(1 << 22)
+#define	MCTL_PHYLOCK		(1 << 21)
+#define	MCTL_BCNS_PROMISC	(1 << 20)
+#define	MCTL_LOCK_RADIO		(1 << 19)
+#define	MCTL_AP			(1 << 18)
+#define	MCTL_INFRA		(1 << 17)
+#define	MCTL_BIGEND		(1 << 16)
+#define	MCTL_GPOUT_SEL_MASK	(3 << 14)
+#define	MCTL_GPOUT_SEL_SHIFT	14
+#define	MCTL_EN_PSMDBG		(1 << 13)
+#define	MCTL_IHR_EN		(1 << 10)
+#define	MCTL_SHM_UPPER		(1 <<  9)
+#define	MCTL_SHM_EN		(1 <<  8)
+#define	MCTL_PSM_JMP_0		(1 <<  2)
+#define	MCTL_PSM_RUN		(1 <<  1)
+#define	MCTL_EN_MAC		(1 <<  0)
+
+/*== maccommand register ==*/
+#define	MCMD_BCN0VLD		(1 <<  0)
+#define	MCMD_BCN1VLD		(1 <<  1)
+#define	MCMD_DIRFRMQVAL		(1 <<  2)
+#define	MCMD_CCA		(1 <<  3)
+#define	MCMD_BG_NOISE		(1 <<  4)
+#define	MCMD_SKIP_SHMINIT	(1 <<  5)	/* only used for simulation */
+#define MCMD_SAMPLECOLL		MCMD_SKIP_SHMINIT /* reuse for sample collect */
+
+/*== macintstatus/macintmask ==*/
+/* gracefully suspended */
+#define	MI_MACSSPNDD		(1 <<  0)
+/* beacon template available */
+#define	MI_BCNTPL		(1 <<  1)
+/* TBTT indication */
+#define	MI_TBTT			(1 <<  2)
+/* beacon successfully tx'd */
+#define	MI_BCNSUCCESS		(1 <<  3)
+/* beacon canceled (IBSS) */
+#define	MI_BCNCANCLD		(1 <<  4)
+/* end of ATIM-window (IBSS) */
+#define	MI_ATIMWINEND		(1 <<  5)
+/* PMQ entries available */
+#define	MI_PMQ			(1 <<  6)
+/* non-specific gen-stat bits that are set by PSM */
+#define	MI_NSPECGEN_0		(1 <<  7)
+/* non-specific gen-stat bits that are set by PSM */
+#define	MI_NSPECGEN_1		(1 <<  8)
+/* MAC level Tx error */
+#define	MI_MACTXERR		(1 <<  9)
+/* non-specific gen-stat bits that are set by PSM */
+#define	MI_NSPECGEN_3		(1 << 10)
+/* PHY Tx error */
+#define	MI_PHYTXERR		(1 << 11)
+/* Power Management Event */
+#define	MI_PME			(1 << 12)
+/* General-purpose timer0 */
+#define	MI_GP0			(1 << 13)
+/* General-purpose timer1 */
+#define	MI_GP1			(1 << 14)
+/* (ORed) DMA-interrupts */
+#define	MI_DMAINT		(1 << 15)
+/* MAC has completed a TX FIFO Suspend/Flush */
+#define	MI_TXSTOP		(1 << 16)
+/* MAC has completed a CCA measurement */
+#define	MI_CCA			(1 << 17)
+/* MAC has collected background noise samples */
+#define	MI_BG_NOISE		(1 << 18)
+/* MBSS DTIM TBTT indication */
+#define	MI_DTIM_TBTT		(1 << 19)
+/* Probe response queue needs attention */
+#define MI_PRQ			(1 << 20)
+/* Radio/PHY has been powered back up. */
+#define	MI_PWRUP		(1 << 21)
+#define	MI_RESERVED3		(1 << 22)
+#define	MI_RESERVED2		(1 << 23)
+#define MI_RESERVED1		(1 << 25)
+/* MAC detected change on RF Disable input*/
+#define MI_RFDISABLE		(1 << 28)
+/* MAC has completed a TX */
+#define	MI_TFS			(1 << 29)
+/* A phy status change wrt G mode */
+#define	MI_PHYCHANGED		(1 << 30)
+/* general purpose timeout */
+#define	MI_TO			(1U << 31)
+
+/* Mac capabilities registers */
+/*== machwcap ==*/
+#define	MCAP_TKIPMIC		0x80000000	/* TKIP MIC hardware present */
+
+/*== pmqhost data ==*/
+/* data entry of head pmq entry */
+#define	PMQH_DATA_MASK		0xffff0000
+/* PM entry for BSS config */
+#define	PMQH_BSSCFG		0x00100000
+/* PM Mode OFF: power save off */
+#define	PMQH_PMOFF		0x00010000
+/* PM Mode ON: power save on */
+#define	PMQH_PMON		0x00020000
+/* Dis-associated or De-authenticated */
+#define	PMQH_DASAT		0x00040000
+/* ATIM not acknowledged */
+#define	PMQH_ATIMFAIL		0x00080000
+/* delete head entry */
+#define	PMQH_DEL_ENTRY		0x00000001
+/* delete head entry to cur read pointer -1 */
+#define	PMQH_DEL_MULT		0x00000002
+/* pmq overflow indication */
+#define	PMQH_OFLO		0x00000004
+/* entries are present in pmq */
+#define	PMQH_NOT_EMPTY		0x00000008
+
+/*== phydebug ==*/
+/* phy is asserting carrier sense */
+#define	PDBG_CRS		(1 << 0)
+/* phy is taking xmit byte from mac this cycle */
+#define	PDBG_TXA		(1 << 1)
+/* mac is instructing the phy to transmit a frame */
+#define	PDBG_TXF		(1 << 2)
+/* phy is signalling a transmit Error to the mac */
+#define	PDBG_TXE		(1 << 3)
+/* phy detected the end of a valid frame preamble */
+#define	PDBG_RXF		(1 << 4)
+/* phy detected the end of a valid PLCP header */
+#define	PDBG_RXS		(1 << 5)
+/* rx start not asserted */
+#define	PDBG_RXFRG		(1 << 6)
+/* mac is taking receive byte from phy this cycle */
+#define	PDBG_RXV		(1 << 7)
+/* RF portion of the radio is disabled */
+#define	PDBG_RFD		(1 << 16)
+
+/*== objaddr register ==*/
+#define	OBJADDR_SEL_MASK	0x000F0000
+#define	OBJADDR_UCM_SEL		0x00000000
+#define	OBJADDR_SHM_SEL		0x00010000
+#define	OBJADDR_SCR_SEL		0x00020000
+#define	OBJADDR_IHR_SEL		0x00030000
+#define	OBJADDR_RCMTA_SEL	0x00040000
+#define	OBJADDR_SRCHM_SEL	0x00060000
+#define	OBJADDR_WINC		0x01000000
+#define	OBJADDR_RINC		0x02000000
+#define	OBJADDR_AUTO_INC	0x03000000
+
+#define	WEP_PCMADDR		0x07d4
+#define	WEP_PCMDATA		0x07d6
+
+/*== frmtxstatus ==*/
+#define	TXS_V			(1 << 0)	/* valid bit */
+#define	TXS_STATUS_MASK		0xffff
+#define	TXS_FID_MASK		0xffff0000
+#define	TXS_FID_SHIFT		16
+
+/*== frmtxstatus2 ==*/
+#define	TXS_SEQ_MASK		0xffff
+#define	TXS_PTX_MASK		0xff0000
+#define	TXS_PTX_SHIFT		16
+#define	TXS_MU_MASK		0x01000000
+#define	TXS_MU_SHIFT		24
+
+/*== clk_ctl_st ==*/
+#define CCS_ERSRC_REQ_D11PLL	0x00000100	/* d11 core pll request */
+#define CCS_ERSRC_REQ_PHYPLL	0x00000200	/* PHY pll request */
+#define CCS_ERSRC_AVAIL_D11PLL	0x01000000	/* d11 core pll available */
+#define CCS_ERSRC_AVAIL_PHYPLL	0x02000000	/* PHY pll available */
+
+/* HT Cloclk Ctrl and Clock Avail for 4313 */
+#define CCS_ERSRC_REQ_HT    0x00000010	/* HT avail request */
+#define CCS_ERSRC_AVAIL_HT  0x00020000	/* HT clock available */
+
+/* tsf_cfprep register */
+#define	CFPREP_CBI_MASK		0xffffffc0
+#define	CFPREP_CBI_SHIFT	6
+#define	CFPREP_CFPP		0x00000001
+
+/* tx fifo sizes values are in terms of 256 byte blocks */
+#define TXFIFOCMD_RESET_MASK	(1 << 15)	/* reset */
+#define TXFIFOCMD_FIFOSEL_SHIFT	8	/* fifo */
+#define TXFIFO_FIFOTOP_SHIFT	8	/* fifo start */
+
+#define TXFIFO_START_BLK16	 65	/* Base address + 32 * 512 B/P */
+#define TXFIFO_START_BLK	 6	/* Base address + 6 * 256 B */
+#define TXFIFO_SIZE_UNIT	256	/* one unit corresponds to 256 bytes */
+#define MBSS16_TEMPLMEM_MINBLKS	65	/* one unit corresponds to 256 bytes */
+
+/*== phy versions (PhyVersion:Revision field) ==*/
+/* analog block version */
+#define	PV_AV_MASK		0xf000
+/* analog block version bitfield offset */
+#define	PV_AV_SHIFT		12
+/* phy type */
+#define	PV_PT_MASK		0x0f00
+/* phy type bitfield offset */
+#define	PV_PT_SHIFT		8
+/* phy version */
+#define	PV_PV_MASK		0x000f
+#define	PHY_TYPE(v)		((v & PV_PT_MASK) >> PV_PT_SHIFT)
+
+/*== phy types (PhyVersion:PhyType field) ==*/
+#define	PHY_TYPE_N		4	/* N-Phy value */
+#define	PHY_TYPE_SSN		6	/* SSLPN-Phy value */
+#define	PHY_TYPE_LCN		8	/* LCN-Phy value */
+#define	PHY_TYPE_LCNXN		9	/* LCNXN-Phy value */
+#define	PHY_TYPE_NULL		0xf	/* Invalid Phy value */
+
+/*== analog types (PhyVersion:AnalogType field) ==*/
+#define	ANA_11N_013		5
+
+/* 802.11a PLCP header def */
+struct ofdm_phy_hdr {
+	u8 rlpt[3];		/* rate, length, parity, tail */
+	u16 service;
+	u8 pad;
+} __packed;
+
+#define	D11A_PHY_HDR_GRATE(phdr)	((phdr)->rlpt[0] & 0x0f)
+#define	D11A_PHY_HDR_GRES(phdr)		(((phdr)->rlpt[0] >> 4) & 0x01)
+#define	D11A_PHY_HDR_GLENGTH(phdr)	(((u32 *)((phdr)->rlpt) >> 5) & 0x0fff)
+#define	D11A_PHY_HDR_GPARITY(phdr)	(((phdr)->rlpt[3] >> 1) & 0x01)
+#define	D11A_PHY_HDR_GTAIL(phdr)	(((phdr)->rlpt[3] >> 2) & 0x3f)
+
+/* rate encoded per 802.11a-1999 sec 17.3.4.1 */
+#define	D11A_PHY_HDR_SRATE(phdr, rate)		\
+	((phdr)->rlpt[0] = ((phdr)->rlpt[0] & 0xf0) | ((rate) & 0xf))
+/* set reserved field to zero */
+#define	D11A_PHY_HDR_SRES(phdr)		((phdr)->rlpt[0] &= 0xef)
+/* length is number of octets in PSDU */
+#define	D11A_PHY_HDR_SLENGTH(phdr, length)	\
+	(*(u32 *)((phdr)->rlpt) = *(u32 *)((phdr)->rlpt) | \
+	(((length) & 0x0fff) << 5))
+/* set the tail to all zeros */
+#define	D11A_PHY_HDR_STAIL(phdr)	((phdr)->rlpt[3] &= 0x03)
+
+#define	D11A_PHY_HDR_LEN_L	3	/* low-rate part of PLCP header */
+#define	D11A_PHY_HDR_LEN_R	2	/* high-rate part of PLCP header */
+
+#define	D11A_PHY_TX_DELAY	(2)	/* 2.1 usec */
+
+#define	D11A_PHY_HDR_TIME	(4)	/* low-rate part of PLCP header */
+#define	D11A_PHY_PRE_TIME	(16)
+#define	D11A_PHY_PREHDR_TIME	(D11A_PHY_PRE_TIME + D11A_PHY_HDR_TIME)
+
+/* 802.11b PLCP header def */
+struct cck_phy_hdr {
+	u8 signal;
+	u8 service;
+	u16 length;
+	u16 crc;
+} __packed;
+
+#define	D11B_PHY_HDR_LEN	6
+
+#define	D11B_PHY_TX_DELAY	(3)	/* 3.4 usec */
+
+#define	D11B_PHY_LHDR_TIME	(D11B_PHY_HDR_LEN << 3)
+#define	D11B_PHY_LPRE_TIME	(144)
+#define	D11B_PHY_LPREHDR_TIME	(D11B_PHY_LPRE_TIME + D11B_PHY_LHDR_TIME)
+
+#define	D11B_PHY_SHDR_TIME	(D11B_PHY_LHDR_TIME >> 1)
+#define	D11B_PHY_SPRE_TIME	(D11B_PHY_LPRE_TIME >> 1)
+#define	D11B_PHY_SPREHDR_TIME	(D11B_PHY_SPRE_TIME + D11B_PHY_SHDR_TIME)
+
+#define	D11B_PLCP_SIGNAL_LOCKED	(1 << 2)
+#define	D11B_PLCP_SIGNAL_LE	(1 << 7)
+
+#define MIMO_PLCP_MCS_MASK	0x7f	/* mcs index */
+#define MIMO_PLCP_40MHZ		0x80	/* 40 Hz frame */
+#define MIMO_PLCP_AMPDU		0x08	/* ampdu */
+
+#define BRCMS_GET_CCK_PLCP_LEN(plcp) (plcp[4] + (plcp[5] << 8))
+#define BRCMS_GET_MIMO_PLCP_LEN(plcp) (plcp[1] + (plcp[2] << 8))
+#define BRCMS_SET_MIMO_PLCP_LEN(plcp, len) \
+	do { \
+		plcp[1] = len & 0xff; \
+		plcp[2] = ((len >> 8) & 0xff); \
+	} while (0)
+
+#define BRCMS_SET_MIMO_PLCP_AMPDU(plcp) (plcp[3] |= MIMO_PLCP_AMPDU)
+#define BRCMS_CLR_MIMO_PLCP_AMPDU(plcp) (plcp[3] &= ~MIMO_PLCP_AMPDU)
+#define BRCMS_IS_MIMO_PLCP_AMPDU(plcp) (plcp[3] & MIMO_PLCP_AMPDU)
+
+/*
+ * The dot11a PLCP header is 5 bytes.  To simplify the software (so that we
+ * don't need e.g. different tx DMA headers for 11a and 11b), the PLCP header
+ * has padding added in the ucode.
+ */
+#define	D11_PHY_HDR_LEN	6
+
+/* TX DMA buffer header */
+struct d11txh {
+	__le16 MacTxControlLow;	/* 0x0 */
+	__le16 MacTxControlHigh;	/* 0x1 */
+	__le16 MacFrameControl;	/* 0x2 */
+	__le16 TxFesTimeNormal;	/* 0x3 */
+	__le16 PhyTxControlWord;	/* 0x4 */
+	__le16 PhyTxControlWord_1;	/* 0x5 */
+	__le16 PhyTxControlWord_1_Fbr;	/* 0x6 */
+	__le16 PhyTxControlWord_1_Rts;	/* 0x7 */
+	__le16 PhyTxControlWord_1_FbrRts;	/* 0x8 */
+	__le16 MainRates;	/* 0x9 */
+	__le16 XtraFrameTypes;	/* 0xa */
+	u8 IV[16];		/* 0x0b - 0x12 */
+	u8 TxFrameRA[6];	/* 0x13 - 0x15 */
+	__le16 TxFesTimeFallback;	/* 0x16 */
+	u8 RTSPLCPFallback[6];	/* 0x17 - 0x19 */
+	__le16 RTSDurFallback;	/* 0x1a */
+	u8 FragPLCPFallback[6];	/* 0x1b - 1d */
+	__le16 FragDurFallback;	/* 0x1e */
+	__le16 MModeLen;	/* 0x1f */
+	__le16 MModeFbrLen;	/* 0x20 */
+	__le16 TstampLow;	/* 0x21 */
+	__le16 TstampHigh;	/* 0x22 */
+	__le16 ABI_MimoAntSel;	/* 0x23 */
+	__le16 PreloadSize;	/* 0x24 */
+	__le16 AmpduSeqCtl;	/* 0x25 */
+	__le16 TxFrameID;	/* 0x26 */
+	__le16 TxStatus;	/* 0x27 */
+	__le16 MaxNMpdus;	/* 0x28 */
+	__le16 MaxABytes_MRT;	/* 0x29 */
+	__le16 MaxABytes_FBR;	/* 0x2a */
+	__le16 MinMBytes;	/* 0x2b */
+	u8 RTSPhyHeader[D11_PHY_HDR_LEN];	/* 0x2c - 0x2e */
+	struct ieee80211_rts rts_frame;	/* 0x2f - 0x36 */
+	u16 PAD;		/* 0x37 */
+} __packed;
+
+#define	D11_TXH_LEN		112	/* bytes */
+
+/* Frame Types */
+#define FT_CCK	0
+#define FT_OFDM	1
+#define FT_HT	2
+#define FT_N	3
+
+/*
+ * Position of MPDU inside A-MPDU; indicated with bits 10:9
+ * of MacTxControlLow
+ */
+#define TXC_AMPDU_SHIFT		9	/* shift for ampdu settings */
+#define TXC_AMPDU_NONE		0	/* Regular MPDU, not an A-MPDU */
+#define TXC_AMPDU_FIRST		1	/* first MPDU of an A-MPDU */
+#define TXC_AMPDU_MIDDLE	2	/* intermediate MPDU of an A-MPDU */
+#define TXC_AMPDU_LAST		3	/* last (or single) MPDU of an A-MPDU */
+
+/*== MacTxControlLow ==*/
+#define TXC_AMIC		0x8000
+#define	TXC_SENDCTS		0x0800
+#define TXC_AMPDU_MASK		0x0600
+#define TXC_BW_40		0x0100
+#define TXC_FREQBAND_5G		0x0080
+#define	TXC_DFCS		0x0040
+#define	TXC_IGNOREPMQ		0x0020
+#define	TXC_HWSEQ		0x0010
+#define	TXC_STARTMSDU		0x0008
+#define	TXC_SENDRTS		0x0004
+#define	TXC_LONGFRAME		0x0002
+#define	TXC_IMMEDACK		0x0001
+
+/*== MacTxControlHigh ==*/
+/* RTS fallback preamble type 1 = SHORT 0 = LONG */
+#define TXC_PREAMBLE_RTS_FB_SHORT	0x8000
+/* RTS main rate preamble type 1 = SHORT 0 = LONG */
+#define TXC_PREAMBLE_RTS_MAIN_SHORT	0x4000
+/*
+ * Main fallback rate preamble type
+ *   1 = SHORT for OFDM/GF for MIMO
+ *   0 = LONG for CCK/MM for MIMO
+ */
+#define TXC_PREAMBLE_DATA_FB_SHORT	0x2000
+
+/* TXC_PREAMBLE_DATA_MAIN is in PhyTxControl bit 5 */
+/* use fallback rate for this AMPDU */
+#define	TXC_AMPDU_FBR		0x1000
+#define	TXC_SECKEY_MASK		0x0FF0
+#define	TXC_SECKEY_SHIFT	4
+/* Use alternate txpwr defined at loc. M_ALT_TXPWR_IDX */
+#define	TXC_ALT_TXPWR		0x0008
+#define	TXC_SECTYPE_MASK	0x0007
+#define	TXC_SECTYPE_SHIFT	0
+
+/* Null delimiter for Fallback rate */
+#define AMPDU_FBR_NULL_DELIM  5	/* Location of Null delimiter count for AMPDU */
+
+/* PhyTxControl for Mimophy */
+#define	PHY_TXC_PWR_MASK	0xFC00
+#define	PHY_TXC_PWR_SHIFT	10
+#define	PHY_TXC_ANT_MASK	0x03C0	/* bit 6, 7, 8, 9 */
+#define	PHY_TXC_ANT_SHIFT	6
+#define	PHY_TXC_ANT_0_1		0x00C0	/* auto, last rx */
+#define	PHY_TXC_LCNPHY_ANT_LAST	0x0000
+#define	PHY_TXC_ANT_3		0x0200	/* virtual antenna 3 */
+#define	PHY_TXC_ANT_2		0x0100	/* virtual antenna 2 */
+#define	PHY_TXC_ANT_1		0x0080	/* virtual antenna 1 */
+#define	PHY_TXC_ANT_0		0x0040	/* virtual antenna 0 */
+#define	PHY_TXC_SHORT_HDR	0x0010
+
+#define	PHY_TXC_OLD_ANT_0	0x0000
+#define	PHY_TXC_OLD_ANT_1	0x0100
+#define	PHY_TXC_OLD_ANT_LAST	0x0300
+
+/* PhyTxControl_1 for Mimophy */
+#define PHY_TXC1_BW_MASK		0x0007
+#define PHY_TXC1_BW_10MHZ		0
+#define PHY_TXC1_BW_10MHZ_UP		1
+#define PHY_TXC1_BW_20MHZ		2
+#define PHY_TXC1_BW_20MHZ_UP		3
+#define PHY_TXC1_BW_40MHZ		4
+#define PHY_TXC1_BW_40MHZ_DUP		5
+#define PHY_TXC1_MODE_SHIFT		3
+#define PHY_TXC1_MODE_MASK		0x0038
+#define PHY_TXC1_MODE_SISO		0
+#define PHY_TXC1_MODE_CDD		1
+#define PHY_TXC1_MODE_STBC		2
+#define PHY_TXC1_MODE_SDM		3
+
+/* PhyTxControl for HTphy that are different from Mimophy */
+#define	PHY_TXC_HTANT_MASK		0x3fC0	/* bits 6-13 */
+
+/* XtraFrameTypes */
+#define XFTS_RTS_FT_SHIFT	2
+#define XFTS_FBRRTS_FT_SHIFT	4
+#define XFTS_CHANNEL_SHIFT	8
+
+/* Antenna diversity bit in ant_wr_settle */
+#define	PHY_AWS_ANTDIV		0x2000
+
+/* IFS ctl */
+#define IFS_USEEDCF	(1 << 2)
+
+/* IFS ctl1 */
+#define IFS_CTL1_EDCRS	(1 << 3)
+#define IFS_CTL1_EDCRS_20L (1 << 4)
+#define IFS_CTL1_EDCRS_40 (1 << 5)
+
+/* ABI_MimoAntSel */
+#define ABI_MAS_ADDR_BMP_IDX_MASK	0x0f00
+#define ABI_MAS_ADDR_BMP_IDX_SHIFT	8
+#define ABI_MAS_FBR_ANT_PTN_MASK	0x00f0
+#define ABI_MAS_FBR_ANT_PTN_SHIFT	4
+#define ABI_MAS_MRT_ANT_PTN_MASK	0x000f
+
+/* tx status packet */
+struct tx_status {
+	u16 framelen;
+	u16 PAD;
+	u16 frameid;
+	u16 status;
+	u16 lasttxtime;
+	u16 sequence;
+	u16 phyerr;
+	u16 ackphyrxsh;
+} __packed;
+
+#define	TXSTATUS_LEN	16
+
+/* status field bit definitions */
+#define	TX_STATUS_FRM_RTX_MASK	0xF000
+#define	TX_STATUS_FRM_RTX_SHIFT	12
+#define	TX_STATUS_RTS_RTX_MASK	0x0F00
+#define	TX_STATUS_RTS_RTX_SHIFT	8
+#define TX_STATUS_MASK		0x00FE
+#define	TX_STATUS_PMINDCTD	(1 << 7) /* PM mode indicated to AP */
+#define	TX_STATUS_INTERMEDIATE	(1 << 6) /* intermediate or 1st ampdu pkg */
+#define	TX_STATUS_AMPDU		(1 << 5) /* AMPDU status */
+#define TX_STATUS_SUPR_MASK	0x1C	 /* suppress status bits (4:2) */
+#define TX_STATUS_SUPR_SHIFT	2
+#define	TX_STATUS_ACK_RCV	(1 << 1) /* ACK received */
+#define	TX_STATUS_VALID		(1 << 0) /* Tx status valid */
+#define	TX_STATUS_NO_ACK	0
+
+/* suppress status reason codes */
+#define	TX_STATUS_SUPR_PMQ	(1 << 2) /* PMQ entry */
+#define	TX_STATUS_SUPR_FLUSH	(2 << 2) /* flush request */
+#define	TX_STATUS_SUPR_FRAG	(3 << 2) /* previous frag failure */
+#define	TX_STATUS_SUPR_TBTT	(3 << 2) /* SHARED: Probe resp supr for TBTT */
+#define	TX_STATUS_SUPR_BADCH	(4 << 2) /* channel mismatch */
+#define	TX_STATUS_SUPR_EXPTIME	(5 << 2) /* lifetime expiry */
+#define	TX_STATUS_SUPR_UF	(6 << 2) /* underflow */
+
+/* Unexpected tx status for rate update */
+#define TX_STATUS_UNEXP(status) \
+	((((status) & TX_STATUS_INTERMEDIATE) != 0) && \
+	 TX_STATUS_UNEXP_AMPDU(status))
+
+/* Unexpected tx status for A-MPDU rate update */
+#define TX_STATUS_UNEXP_AMPDU(status) \
+	((((status) & TX_STATUS_SUPR_MASK) != 0) && \
+	 (((status) & TX_STATUS_SUPR_MASK) != TX_STATUS_SUPR_EXPTIME))
+
+#define TX_STATUS_BA_BMAP03_MASK	0xF000	/* ba bitmap 0:3 in 1st pkg */
+#define TX_STATUS_BA_BMAP03_SHIFT	12	/* ba bitmap 0:3 in 1st pkg */
+#define TX_STATUS_BA_BMAP47_MASK	0x001E	/* ba bitmap 4:7 in 2nd pkg */
+#define TX_STATUS_BA_BMAP47_SHIFT	3	/* ba bitmap 4:7 in 2nd pkg */
+
+/* RXE (Receive Engine) */
+
+/* RCM_CTL */
+#define	RCM_INC_MASK_H		0x0080
+#define	RCM_INC_MASK_L		0x0040
+#define	RCM_INC_DATA		0x0020
+#define	RCM_INDEX_MASK		0x001F
+#define	RCM_SIZE		15
+
+#define	RCM_MAC_OFFSET		0	/* current MAC address */
+#define	RCM_BSSID_OFFSET	3	/* current BSSID address */
+#define	RCM_F_BSSID_0_OFFSET	6	/* foreign BSS CFP tracking */
+#define	RCM_F_BSSID_1_OFFSET	9	/* foreign BSS CFP tracking */
+#define	RCM_F_BSSID_2_OFFSET	12	/* foreign BSS CFP tracking */
+
+#define RCM_WEP_TA0_OFFSET	16
+#define RCM_WEP_TA1_OFFSET	19
+#define RCM_WEP_TA2_OFFSET	22
+#define RCM_WEP_TA3_OFFSET	25
+
+/* PSM Block */
+
+/* psm_phy_hdr_param bits */
+#define MAC_PHY_RESET		1
+#define MAC_PHY_CLOCK_EN	2
+#define MAC_PHY_FORCE_CLK	4
+
+/* WEP Block */
+
+/* WEP_WKEY */
+#define	WKEY_START		(1 << 8)
+#define	WKEY_SEL_MASK		0x1F
+
+/* WEP data formats */
+
+/* the number of RCMTA entries */
+#define RCMTA_SIZE 50
+
+#define M_ADDR_BMP_BLK		(0x37e * 2)
+#define M_ADDR_BMP_BLK_SZ	12
+
+#define ADDR_BMP_RA		(1 << 0)	/* Receiver Address (RA) */
+#define ADDR_BMP_TA		(1 << 1)	/* Transmitter Address (TA) */
+#define ADDR_BMP_BSSID		(1 << 2)	/* BSSID */
+#define ADDR_BMP_AP		(1 << 3)	/* Infra-BSS Access Point */
+#define ADDR_BMP_STA		(1 << 4)	/* Infra-BSS Station */
+#define ADDR_BMP_RESERVED1	(1 << 5)
+#define ADDR_BMP_RESERVED2	(1 << 6)
+#define ADDR_BMP_RESERVED3	(1 << 7)
+#define ADDR_BMP_BSS_IDX_MASK	(3 << 8)	/* BSS control block index */
+#define ADDR_BMP_BSS_IDX_SHIFT	8
+
+#define	WSEC_MAX_RCMTA_KEYS	54
+
+/* max keys in M_TKMICKEYS_BLK */
+#define	WSEC_MAX_TKMIC_ENGINE_KEYS		12	/* 8 + 4 default */
+
+/* max RXE match registers */
+#define WSEC_MAX_RXE_KEYS	4
+
+/* SECKINDXALGO (Security Key Index & Algorithm Block) word format */
+/* SKL (Security Key Lookup) */
+#define	SKL_ALGO_MASK		0x0007
+#define	SKL_ALGO_SHIFT		0
+#define	SKL_KEYID_MASK		0x0008
+#define	SKL_KEYID_SHIFT		3
+#define	SKL_INDEX_MASK		0x03F0
+#define	SKL_INDEX_SHIFT		4
+#define	SKL_GRP_ALGO_MASK	0x1c00
+#define	SKL_GRP_ALGO_SHIFT	10
+
+/* additional bits defined for IBSS group key support */
+#define	SKL_IBSS_INDEX_MASK	0x01F0
+#define	SKL_IBSS_INDEX_SHIFT	4
+#define	SKL_IBSS_KEYID1_MASK	0x0600
+#define	SKL_IBSS_KEYID1_SHIFT	9
+#define	SKL_IBSS_KEYID2_MASK	0x1800
+#define	SKL_IBSS_KEYID2_SHIFT	11
+#define	SKL_IBSS_KEYALGO_MASK	0xE000
+#define	SKL_IBSS_KEYALGO_SHIFT	13
+
+#define	WSEC_MODE_OFF		0
+#define	WSEC_MODE_HW		1
+#define	WSEC_MODE_SW		2
+
+#define	WSEC_ALGO_OFF		0
+#define	WSEC_ALGO_WEP1		1
+#define	WSEC_ALGO_TKIP		2
+#define	WSEC_ALGO_AES		3
+#define	WSEC_ALGO_WEP128	4
+#define	WSEC_ALGO_AES_LEGACY	5
+#define	WSEC_ALGO_NALG		6
+
+#define	AES_MODE_NONE		0
+#define	AES_MODE_CCM		1
+
+/* WEP_CTL (Rev 0) */
+#define	WECR0_KEYREG_SHIFT	0
+#define	WECR0_KEYREG_MASK	0x7
+#define	WECR0_DECRYPT		(1 << 3)
+#define	WECR0_IVINLINE		(1 << 4)
+#define	WECR0_WEPALG_SHIFT	5
+#define	WECR0_WEPALG_MASK	(0x7 << 5)
+#define	WECR0_WKEYSEL_SHIFT	8
+#define	WECR0_WKEYSEL_MASK	(0x7 << 8)
+#define	WECR0_WKEYSTART		(1 << 11)
+#define	WECR0_WEPINIT		(1 << 14)
+#define	WECR0_ICVERR		(1 << 15)
+
+/* Frame template map byte offsets */
+#define	T_ACTS_TPL_BASE		(0)
+#define	T_NULL_TPL_BASE		(0xc * 2)
+#define	T_QNULL_TPL_BASE	(0x1c * 2)
+#define	T_RR_TPL_BASE		(0x2c * 2)
+#define	T_BCN0_TPL_BASE		(0x34 * 2)
+#define	T_PRS_TPL_BASE		(0x134 * 2)
+#define	T_BCN1_TPL_BASE		(0x234 * 2)
+#define T_TX_FIFO_TXRAM_BASE	(T_ACTS_TPL_BASE + \
+				 (TXFIFO_START_BLK * TXFIFO_SIZE_UNIT))
+
+#define T_BA_TPL_BASE		T_QNULL_TPL_BASE /* template area for BA */
+
+#define T_RAM_ACCESS_SZ		4	/* template ram is 4 byte access only */
+
+/* Shared Mem byte offsets */
+
+/* Location where the ucode expects the corerev */
+#define	M_MACHW_VER		(0x00b * 2)
+
+/* Location where the ucode expects the MAC capabilities */
+#define	M_MACHW_CAP_L		(0x060 * 2)
+#define	M_MACHW_CAP_H	(0x061 * 2)
+
+/* WME shared memory */
+#define M_EDCF_STATUS_OFF	(0x007 * 2)
+#define M_TXF_CUR_INDEX		(0x018 * 2)
+#define M_EDCF_QINFO		(0x120 * 2)
+
+/* PS-mode related parameters */
+#define	M_DOT11_SLOT		(0x008 * 2)
+#define	M_DOT11_DTIMPERIOD	(0x009 * 2)
+#define	M_NOSLPZNATDTIM		(0x026 * 2)
+
+/* Beacon-related parameters */
+#define	M_BCN0_FRM_BYTESZ	(0x00c * 2)	/* Bcn 0 template length */
+#define	M_BCN1_FRM_BYTESZ	(0x00d * 2)	/* Bcn 1 template length */
+#define	M_BCN_TXTSF_OFFSET	(0x00e * 2)
+#define	M_TIMBPOS_INBEACON	(0x00f * 2)
+#define	M_SFRMTXCNTFBRTHSD	(0x022 * 2)
+#define	M_LFRMTXCNTFBRTHSD	(0x023 * 2)
+#define	M_BCN_PCTLWD		(0x02a * 2)
+#define M_BCN_LI		(0x05b * 2)	/* beacon listen interval */
+
+/* MAX Rx Frame len */
+#define M_MAXRXFRM_LEN		(0x010 * 2)
+
+/* ACK/CTS related params */
+#define	M_RSP_PCTLWD		(0x011 * 2)
+
+/* Hardware Power Control */
+#define M_TXPWR_N		(0x012 * 2)
+#define M_TXPWR_TARGET		(0x013 * 2)
+#define M_TXPWR_MAX		(0x014 * 2)
+#define M_TXPWR_CUR		(0x019 * 2)
+
+/* Rx-related parameters */
+#define	M_RX_PAD_DATA_OFFSET	(0x01a * 2)
+
+/* WEP Shared mem data */
+#define	M_SEC_DEFIVLOC		(0x01e * 2)
+#define	M_SEC_VALNUMSOFTMCHTA	(0x01f * 2)
+#define	M_PHYVER		(0x028 * 2)
+#define	M_PHYTYPE		(0x029 * 2)
+#define	M_SECRXKEYS_PTR		(0x02b * 2)
+#define	M_TKMICKEYS_PTR		(0x059 * 2)
+#define	M_SECKINDXALGO_BLK	(0x2ea * 2)
+#define M_SECKINDXALGO_BLK_SZ	54
+#define	M_SECPSMRXTAMCH_BLK	(0x2fa * 2)
+#define	M_TKIP_TSC_TTAK		(0x18c * 2)
+#define	D11_MAX_KEY_SIZE	16
+
+#define	M_MAX_ANTCNT		(0x02e * 2)	/* antenna swap threshold */
+
+/* Probe response related parameters */
+#define	M_SSIDLEN		(0x024 * 2)
+#define	M_PRB_RESP_FRM_LEN	(0x025 * 2)
+#define	M_PRS_MAXTIME		(0x03a * 2)
+#define	M_SSID			(0xb0 * 2)
+#define	M_CTXPRS_BLK		(0xc0 * 2)
+#define	C_CTX_PCTLWD_POS	(0x4 * 2)
+
+/* Delta between OFDM and CCK power in CCK power boost mode */
+#define M_OFDM_OFFSET		(0x027 * 2)
+
+/* TSSI for last 4 11b/g CCK packets transmitted */
+#define	M_B_TSSI_0		(0x02c * 2)
+#define	M_B_TSSI_1		(0x02d * 2)
+
+/* Host flags to turn on ucode options */
+#define	M_HOST_FLAGS1		(0x02f * 2)
+#define	M_HOST_FLAGS2		(0x030 * 2)
+#define	M_HOST_FLAGS3		(0x031 * 2)
+#define	M_HOST_FLAGS4		(0x03c * 2)
+#define	M_HOST_FLAGS5		(0x06a * 2)
+#define	M_HOST_FLAGS_SZ		16
+
+#define M_RADAR_REG		(0x033 * 2)
+
+/* TSSI for last 4 11a OFDM packets transmitted */
+#define	M_A_TSSI_0		(0x034 * 2)
+#define	M_A_TSSI_1		(0x035 * 2)
+
+/* noise interference measurement */
+#define M_NOISE_IF_COUNT	(0x034 * 2)
+#define M_NOISE_IF_TIMEOUT	(0x035 * 2)
+
+#define	M_RF_RX_SP_REG1		(0x036 * 2)
+
+/* TSSI for last 4 11g OFDM packets transmitted */
+#define	M_G_TSSI_0		(0x038 * 2)
+#define	M_G_TSSI_1		(0x039 * 2)
+
+/* Background noise measure */
+#define	M_JSSI_0		(0x44 * 2)
+#define	M_JSSI_1		(0x45 * 2)
+#define	M_JSSI_AUX		(0x46 * 2)
+
+#define	M_CUR_2050_RADIOCODE	(0x47 * 2)
+
+/* TX fifo sizes */
+#define M_FIFOSIZE0		(0x4c * 2)
+#define M_FIFOSIZE1		(0x4d * 2)
+#define M_FIFOSIZE2		(0x4e * 2)
+#define M_FIFOSIZE3		(0x4f * 2)
+#define D11_MAX_TX_FRMS		32	/* max frames allowed in tx fifo */
+
+/* Current channel number plus upper bits */
+#define M_CURCHANNEL		(0x50 * 2)
+#define D11_CURCHANNEL_5G	0x0100;
+#define D11_CURCHANNEL_40	0x0200;
+#define D11_CURCHANNEL_MAX	0x00FF;
+
+/* last posted frameid on the bcmc fifo */
+#define M_BCMC_FID		(0x54 * 2)
+#define INVALIDFID		0xffff
+
+/* extended beacon phyctl bytes for 11N */
+#define	M_BCN_PCTL1WD		(0x058 * 2)
+
+/* idle busy ratio to duty_cycle requirement  */
+#define M_TX_IDLE_BUSY_RATIO_X_16_CCK  (0x52 * 2)
+#define M_TX_IDLE_BUSY_RATIO_X_16_OFDM (0x5A * 2)
+
+/* CW RSSI for LCNPHY */
+#define M_LCN_RSSI_0		0x1332
+#define M_LCN_RSSI_1		0x1338
+#define M_LCN_RSSI_2		0x133e
+#define M_LCN_RSSI_3		0x1344
+
+/* SNR for LCNPHY */
+#define M_LCN_SNR_A_0	0x1334
+#define M_LCN_SNR_B_0	0x1336
+
+#define M_LCN_SNR_A_1	0x133a
+#define M_LCN_SNR_B_1	0x133c
+
+#define M_LCN_SNR_A_2	0x1340
+#define M_LCN_SNR_B_2	0x1342
+
+#define M_LCN_SNR_A_3	0x1346
+#define M_LCN_SNR_B_3	0x1348
+
+#define M_LCN_LAST_RESET	(81*2)
+#define M_LCN_LAST_LOC	(63*2)
+#define M_LCNPHY_RESET_STATUS (4902)
+#define M_LCNPHY_DSC_TIME	(0x98d*2)
+#define M_LCNPHY_RESET_CNT_DSC (0x98b*2)
+#define M_LCNPHY_RESET_CNT	(0x98c*2)
+
+/* Rate table offsets */
+#define	M_RT_DIRMAP_A		(0xe0 * 2)
+#define	M_RT_BBRSMAP_A		(0xf0 * 2)
+#define	M_RT_DIRMAP_B		(0x100 * 2)
+#define	M_RT_BBRSMAP_B		(0x110 * 2)
+
+/* Rate table entry offsets */
+#define	M_RT_PRS_PLCP_POS	10
+#define	M_RT_PRS_DUR_POS	16
+#define	M_RT_OFDM_PCTL1_POS	18
+
+#define M_20IN40_IQ			(0x380 * 2)
+
+/* SHM locations where ucode stores the current power index */
+#define M_CURR_IDX1		(0x384 * 2)
+#define M_CURR_IDX2		(0x387 * 2)
+
+#define M_BSCALE_ANT0	(0x5e * 2)
+#define M_BSCALE_ANT1	(0x5f * 2)
+
+/* Antenna Diversity Testing */
+#define M_MIMO_ANTSEL_RXDFLT	(0x63 * 2)
+#define M_ANTSEL_CLKDIV	(0x61 * 2)
+#define M_MIMO_ANTSEL_TXDFLT	(0x64 * 2)
+
+#define M_MIMO_MAXSYM	(0x5d * 2)
+#define MIMO_MAXSYM_DEF		0x8000	/* 32k */
+#define MIMO_MAXSYM_MAX		0xffff	/* 64k */
+
+#define M_WATCHDOG_8TU		(0x1e * 2)
+#define WATCHDOG_8TU_DEF	5
+#define WATCHDOG_8TU_MAX	10
+
+/* Manufacturing Test Variables */
+/* PER test mode */
+#define M_PKTENG_CTRL		(0x6c * 2)
+/* IFS for TX mode */
+#define M_PKTENG_IFS		(0x6d * 2)
+/* Lower word of tx frmcnt/rx lostcnt */
+#define M_PKTENG_FRMCNT_LO	(0x6e * 2)
+/* Upper word of tx frmcnt/rx lostcnt */
+#define M_PKTENG_FRMCNT_HI	(0x6f * 2)
+
+/* Index variation in vbat ripple */
+#define M_LCN_PWR_IDX_MAX	(0x67 * 2) /* highest index read by ucode */
+#define M_LCN_PWR_IDX_MIN	(0x66 * 2) /* lowest index read by ucode */
+
+/* M_PKTENG_CTRL bit definitions */
+#define M_PKTENG_MODE_TX		0x0001
+#define M_PKTENG_MODE_TX_RIFS	        0x0004
+#define M_PKTENG_MODE_TX_CTS            0x0008
+#define M_PKTENG_MODE_RX		0x0002
+#define M_PKTENG_MODE_RX_WITH_ACK	0x0402
+#define M_PKTENG_MODE_MASK		0x0003
+/* TX frames indicated in the frmcnt reg */
+#define M_PKTENG_FRMCNT_VLD		0x0100
+
+/* Sample Collect parameters (bitmap and type) */
+/* Trigger bitmap for sample collect */
+#define M_SMPL_COL_BMP		(0x37d * 2)
+/* Sample collect type */
+#define M_SMPL_COL_CTL		(0x3b2 * 2)
+
+#define ANTSEL_CLKDIV_4MHZ	6
+#define MIMO_ANTSEL_BUSY	0x4000	/* bit 14 (busy) */
+#define MIMO_ANTSEL_SEL		0x8000	/* bit 15 write the value */
+#define MIMO_ANTSEL_WAIT	50	/* 50us wait */
+#define MIMO_ANTSEL_OVERRIDE	0x8000	/* flag */
+
+struct shm_acparams {
+	u16 txop;
+	u16 cwmin;
+	u16 cwmax;
+	u16 cwcur;
+	u16 aifs;
+	u16 bslots;
+	u16 reggap;
+	u16 status;
+	u16 rsvd[8];
+} __packed;
+#define M_EDCF_QLEN	(16 * 2)
+
+#define WME_STATUS_NEWAC	(1 << 8)
+
+/* M_HOST_FLAGS */
+#define MHFMAX		5	/* Number of valid hostflag half-word (u16) */
+#define MHF1		0	/* Hostflag 1 index */
+#define MHF2		1	/* Hostflag 2 index */
+#define MHF3		2	/* Hostflag 3 index */
+#define MHF4		3	/* Hostflag 4 index */
+#define MHF5		4	/* Hostflag 5 index */
+
+/* Flags in M_HOST_FLAGS */
+/* Enable ucode antenna diversity help */
+#define	MHF1_ANTDIV		0x0001
+/* Enable EDCF access control */
+#define	MHF1_EDCF		0x0100
+#define MHF1_IQSWAP_WAR		0x0200
+/* Disable Slow clock request, for corerev < 11 */
+#define	MHF1_FORCEFASTCLK	0x0400
+
+/* Flags in M_HOST_FLAGS2 */
+
+/* Flush BCMC FIFO immediately */
+#define MHF2_TXBCMC_NOW		0x0040
+/* Enable ucode/hw power control */
+#define MHF2_HWPWRCTL		0x0080
+#define MHF2_NPHY40MHZ_WAR	0x0800
+
+/* Flags in M_HOST_FLAGS3 */
+/* enabled mimo antenna selection */
+#define MHF3_ANTSEL_EN		0x0001
+/* antenna selection mode: 0: 2x3, 1: 2x4 */
+#define MHF3_ANTSEL_MODE	0x0002
+#define MHF3_RESERVED1		0x0004
+#define MHF3_RESERVED2		0x0008
+#define MHF3_NPHY_MLADV_WAR	0x0010
+
+/* Flags in M_HOST_FLAGS4 */
+/* force bphy Tx on core 0 (board level WAR) */
+#define MHF4_BPHY_TXCORE0	0x0080
+/* for 4313A0 FEM boards */
+#define MHF4_EXTPA_ENABLE	0x4000
+
+/* Flags in M_HOST_FLAGS5 */
+#define MHF5_4313_GPIOCTRL	0x0001
+#define MHF5_RESERVED1		0x0002
+#define MHF5_RESERVED2		0x0004
+/* Radio power setting for ucode */
+#define	M_RADIO_PWR		(0x32 * 2)
+
+/* phy noise recorded by ucode right after tx */
+#define	M_PHY_NOISE		(0x037 * 2)
+#define	PHY_NOISE_MASK		0x00ff
+
+/*
+ * Receive Frame Data Header for 802.11b DCF-only frames
+ *
+ * RxFrameSize: Actual byte length of the frame data received
+ * PAD: padding (not used)
+ * PhyRxStatus_0: PhyRxStatus 15:0
+ * PhyRxStatus_1: PhyRxStatus 31:16
+ * PhyRxStatus_2: PhyRxStatus 47:32
+ * PhyRxStatus_3: PhyRxStatus 63:48
+ * PhyRxStatus_4: PhyRxStatus 79:64
+ * PhyRxStatus_5: PhyRxStatus 95:80
+ * RxStatus1: MAC Rx Status
+ * RxStatus2: extended MAC Rx status
+ * RxTSFTime: RxTSFTime time of first MAC symbol + M_PHY_PLCPRX_DLY
+ * RxChan: gain code, channel radio code, and phy type
+ */
+struct d11rxhdr_le {
+	__le16 RxFrameSize;
+	u16 PAD;
+	__le16 PhyRxStatus_0;
+	__le16 PhyRxStatus_1;
+	__le16 PhyRxStatus_2;
+	__le16 PhyRxStatus_3;
+	__le16 PhyRxStatus_4;
+	__le16 PhyRxStatus_5;
+	__le16 RxStatus1;
+	__le16 RxStatus2;
+	__le16 RxTSFTime;
+	__le16 RxChan;
+} __packed;
+
+struct d11rxhdr {
+	u16 RxFrameSize;
+	u16 PAD;
+	u16 PhyRxStatus_0;
+	u16 PhyRxStatus_1;
+	u16 PhyRxStatus_2;
+	u16 PhyRxStatus_3;
+	u16 PhyRxStatus_4;
+	u16 PhyRxStatus_5;
+	u16 RxStatus1;
+	u16 RxStatus2;
+	u16 RxTSFTime;
+	u16 RxChan;
+} __packed;
+
+/* PhyRxStatus_0: */
+/* NPHY only: CCK, OFDM, preN, N */
+#define	PRXS0_FT_MASK		0x0003
+/* NPHY only: clip count adjustment steps by AGC */
+#define	PRXS0_CLIP_MASK		0x000C
+#define	PRXS0_CLIP_SHIFT	2
+/* PHY received a frame with unsupported rate */
+#define	PRXS0_UNSRATE		0x0010
+/* GPHY: rx ant, NPHY: upper sideband */
+#define	PRXS0_RXANT_UPSUBBAND	0x0020
+/* CCK frame only: lost crs during cck frame reception */
+#define	PRXS0_LCRS		0x0040
+/* Short Preamble */
+#define	PRXS0_SHORTH		0x0080
+/* PLCP violation */
+#define	PRXS0_PLCPFV		0x0100
+/* PLCP header integrity check failed */
+#define	PRXS0_PLCPHCF		0x0200
+/* legacy PHY gain control */
+#define	PRXS0_GAIN_CTL		0x4000
+/* NPHY: Antennas used for received frame, bitmask */
+#define PRXS0_ANTSEL_MASK	0xF000
+#define PRXS0_ANTSEL_SHIFT	0x12
+
+/* subfield PRXS0_FT_MASK */
+#define	PRXS0_CCK		0x0000
+/* valid only for G phy, use rxh->RxChan for A phy */
+#define	PRXS0_OFDM		0x0001
+#define	PRXS0_PREN		0x0002
+#define	PRXS0_STDN		0x0003
+
+/* subfield PRXS0_ANTSEL_MASK */
+#define PRXS0_ANTSEL_0		0x0	/* antenna 0 is used */
+#define PRXS0_ANTSEL_1		0x2	/* antenna 1 is used */
+#define PRXS0_ANTSEL_2		0x4	/* antenna 2 is used */
+#define PRXS0_ANTSEL_3		0x8	/* antenna 3 is used */
+
+/* PhyRxStatus_1: */
+#define	PRXS1_JSSI_MASK		0x00FF
+#define	PRXS1_JSSI_SHIFT	0
+#define	PRXS1_SQ_MASK		0xFF00
+#define	PRXS1_SQ_SHIFT		8
+
+/* nphy PhyRxStatus_1: */
+#define PRXS1_nphy_PWR0_MASK	0x00FF
+#define PRXS1_nphy_PWR1_MASK	0xFF00
+
+/* HTPHY Rx Status defines */
+/* htphy PhyRxStatus_0: those bit are overlapped with PhyRxStatus_0 */
+#define PRXS0_BAND	        0x0400	/* 0 = 2.4G, 1 = 5G */
+#define PRXS0_RSVD	        0x0800	/* reserved; set to 0 */
+#define PRXS0_UNUSED	        0xF000	/* unused and not defined; set to 0 */
+
+/* htphy PhyRxStatus_1: */
+/* core enables for {3..0}, 0=disabled, 1=enabled */
+#define PRXS1_HTPHY_CORE_MASK	0x000F
+/* antenna configation */
+#define PRXS1_HTPHY_ANTCFG_MASK	0x00F0
+/* Mixmode PLCP Length low byte mask */
+#define PRXS1_HTPHY_MMPLCPLenL_MASK	0xFF00
+
+/* htphy PhyRxStatus_2: */
+/* Mixmode PLCP Length high byte maskw */
+#define PRXS2_HTPHY_MMPLCPLenH_MASK	0x000F
+/* Mixmode PLCP rate mask */
+#define PRXS2_HTPHY_MMPLCH_RATE_MASK	0x00F0
+/* Rx power on core 0 */
+#define PRXS2_HTPHY_RXPWR_ANT0	0xFF00
+
+/* htphy PhyRxStatus_3: */
+/* Rx power on core 1 */
+#define PRXS3_HTPHY_RXPWR_ANT1	0x00FF
+/* Rx power on core 2 */
+#define PRXS3_HTPHY_RXPWR_ANT2	0xFF00
+
+/* htphy PhyRxStatus_4: */
+/* Rx power on core 3 */
+#define PRXS4_HTPHY_RXPWR_ANT3	0x00FF
+/* Coarse frequency offset */
+#define PRXS4_HTPHY_CFO		0xFF00
+
+/* htphy PhyRxStatus_5: */
+/* Fine frequency offset */
+#define PRXS5_HTPHY_FFO	        0x00FF
+/* Advance Retard */
+#define PRXS5_HTPHY_AR	        0xFF00
+
+#define HTPHY_MMPLCPLen(rxs) \
+	((((rxs)->PhyRxStatus_1 & PRXS1_HTPHY_MMPLCPLenL_MASK) >> 8) | \
+	(((rxs)->PhyRxStatus_2 & PRXS2_HTPHY_MMPLCPLenH_MASK) << 8))
+/* Get Rx power on core 0 */
+#define HTPHY_RXPWR_ANT0(rxs) \
+	((((rxs)->PhyRxStatus_2) & PRXS2_HTPHY_RXPWR_ANT0) >> 8)
+/* Get Rx power on core 1 */
+#define HTPHY_RXPWR_ANT1(rxs) \
+	(((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT1)
+/* Get Rx power on core 2 */
+#define HTPHY_RXPWR_ANT2(rxs) \
+	((((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT2) >> 8)
+
+/* ucode RxStatus1: */
+#define	RXS_BCNSENT		0x8000
+#define	RXS_SECKINDX_MASK	0x07e0
+#define	RXS_SECKINDX_SHIFT	5
+#define	RXS_DECERR		(1 << 4)
+#define	RXS_DECATMPT		(1 << 3)
+/* PAD bytes to make IP data 4 bytes aligned */
+#define	RXS_PBPRES		(1 << 2)
+#define	RXS_RESPFRAMETX		(1 << 1)
+#define	RXS_FCSERR		(1 << 0)
+
+/* ucode RxStatus2: */
+#define RXS_AMSDU_MASK		1
+#define	RXS_AGGTYPE_MASK	0x6
+#define	RXS_AGGTYPE_SHIFT	1
+#define	RXS_PHYRXST_VALID	(1 << 8)
+#define RXS_RXANT_MASK		0x3
+#define RXS_RXANT_SHIFT		12
+
+/* RxChan */
+#define RXS_CHAN_40		0x1000
+#define RXS_CHAN_5G		0x0800
+#define	RXS_CHAN_ID_MASK	0x07f8
+#define	RXS_CHAN_ID_SHIFT	3
+#define	RXS_CHAN_PHYTYPE_MASK	0x0007
+#define	RXS_CHAN_PHYTYPE_SHIFT	0
+
+/* Index of attenuations used during ucode power control. */
+#define M_PWRIND_BLKS	(0x184 * 2)
+#define M_PWRIND_MAP0	(M_PWRIND_BLKS + 0x0)
+#define M_PWRIND_MAP1	(M_PWRIND_BLKS + 0x2)
+#define M_PWRIND_MAP2	(M_PWRIND_BLKS + 0x4)
+#define M_PWRIND_MAP3	(M_PWRIND_BLKS + 0x6)
+/* M_PWRIND_MAP(core) macro */
+#define M_PWRIND_MAP(core)  (M_PWRIND_BLKS + ((core)<<1))
+
+/* PSM SHM variable offsets */
+#define	M_PSM_SOFT_REGS	0x0
+#define	M_BOM_REV_MAJOR	(M_PSM_SOFT_REGS + 0x0)
+#define	M_BOM_REV_MINOR	(M_PSM_SOFT_REGS + 0x2)
+#define	M_UCODE_DBGST	(M_PSM_SOFT_REGS + 0x40) /* ucode debug status code */
+#define	M_UCODE_MACSTAT	(M_PSM_SOFT_REGS + 0xE0) /* macstat counters */
+
+#define M_AGING_THRSH	(0x3e * 2) /* max time waiting for medium before tx */
+#define	M_MBURST_SIZE	(0x40 * 2) /* max frames in a frameburst */
+#define	M_MBURST_TXOP	(0x41 * 2) /* max frameburst TXOP in unit of us */
+#define M_SYNTHPU_DLY	(0x4a * 2) /* pre-wakeup for synthpu, default: 500 */
+#define	M_PRETBTT	(0x4b * 2)
+
+/* offset to the target txpwr */
+#define M_ALT_TXPWR_IDX		(M_PSM_SOFT_REGS + (0x3b * 2))
+#define M_PHY_TX_FLT_PTR	(M_PSM_SOFT_REGS + (0x3d * 2))
+#define M_CTS_DURATION		(M_PSM_SOFT_REGS + (0x5c * 2))
+#define M_LP_RCCAL_OVR		(M_PSM_SOFT_REGS + (0x6b * 2))
+
+/* PKTENG Rx Stats Block */
+#define M_RXSTATS_BLK_PTR	(M_PSM_SOFT_REGS + (0x65 * 2))
+
+/* ucode debug status codes */
+/* not valid really */
+#define	DBGST_INACTIVE		0
+/* after zeroing SHM, before suspending at init */
+#define	DBGST_INIT		1
+/* "normal" state */
+#define	DBGST_ACTIVE		2
+/* suspended */
+#define	DBGST_SUSPENDED		3
+/* asleep (PS mode) */
+#define	DBGST_ASLEEP		4
+
+/* Scratch Reg defs */
+enum _ePsmScratchPadRegDefinitions {
+	S_RSV0 = 0,
+	S_RSV1,
+	S_RSV2,
+
+	/* offset 0x03: scratch registers for Dot11-contants */
+	S_DOT11_CWMIN,		/* CW-minimum */
+	S_DOT11_CWMAX,		/* CW-maximum */
+	S_DOT11_CWCUR,		/* CW-current */
+	S_DOT11_SRC_LMT,	/* short retry count limit */
+	S_DOT11_LRC_LMT,	/* long retry count limit */
+	S_DOT11_DTIMCOUNT,	/* DTIM-count */
+
+	/* offset 0x09: Tx-side scratch registers */
+	S_SEQ_NUM,		/* hardware sequence number reg */
+	S_SEQ_NUM_FRAG,		/* seq num for frags (at the start of MSDU) */
+	S_FRMRETX_CNT,		/* frame retx count */
+	S_SSRC,			/* Station short retry count */
+	S_SLRC,			/* Station long retry count */
+	S_EXP_RSP,		/* Expected response frame */
+	S_OLD_BREM,		/* Remaining backoff ctr */
+	S_OLD_CWWIN,		/* saved-off CW-cur */
+	S_TXECTL,		/* TXE-Ctl word constructed in scr-pad */
+	S_CTXTST,		/* frm type-subtype as read from Tx-descr */
+
+	/* offset 0x13: Rx-side scratch registers */
+	S_RXTST,		/* Type and subtype in Rxframe */
+
+	/* Global state register */
+	S_STREG,		/* state storage actual bit maps below */
+
+	S_TXPWR_SUM,		/* Tx power control: accumulator */
+	S_TXPWR_ITER,		/* Tx power control: iteration */
+	S_RX_FRMTYPE,		/* Rate and PHY type for frames */
+	S_THIS_AGG,		/* Size of this AGG (A-MSDU) */
+
+	S_KEYINDX,
+	S_RXFRMLEN,		/* Receive MPDU length in bytes */
+
+	/* offset 0x1B: Receive TSF time stored in SCR */
+	S_RXTSFTMRVAL_WD3,	/* TSF value at the start of rx */
+	S_RXTSFTMRVAL_WD2,	/* TSF value at the start of rx */
+	S_RXTSFTMRVAL_WD1,	/* TSF value at the start of rx */
+	S_RXTSFTMRVAL_WD0,	/* TSF value at the start of rx */
+	S_RXSSN,		/* Received start seq number for A-MPDU BA */
+	S_RXQOSFLD,		/* Rx-QoS field (if present) */
+
+	/* offset 0x21: Scratch pad regs used in microcode as temp storage */
+	S_TMP0,			/* stmp0 */
+	S_TMP1,			/* stmp1 */
+	S_TMP2,			/* stmp2 */
+	S_TMP3,			/* stmp3 */
+	S_TMP4,			/* stmp4 */
+	S_TMP5,			/* stmp5 */
+	S_PRQPENALTY_CTR,	/* Probe response queue penalty counter */
+	S_ANTCNT,		/* unsuccessful attempts on current ant. */
+	S_SYMBOL,		/* flag for possible symbol ctl frames */
+	S_RXTP,			/* rx frame type */
+	S_STREG2,		/* extra state storage */
+	S_STREG3,		/* even more extra state storage */
+	S_STREG4,		/* ... */
+	S_STREG5,		/* remember to initialize it to zero */
+
+	S_ADJPWR_IDX,
+	S_CUR_PTR,		/* Temp pointer for A-MPDU re-Tx SHM table */
+	S_REVID4,		/* 0x33 */
+	S_INDX,			/* 0x34 */
+	S_ADDR0,		/* 0x35 */
+	S_ADDR1,		/* 0x36 */
+	S_ADDR2,		/* 0x37 */
+	S_ADDR3,		/* 0x38 */
+	S_ADDR4,		/* 0x39 */
+	S_ADDR5,		/* 0x3A */
+	S_TMP6,			/* 0x3B */
+	S_KEYINDX_BU,		/* Backup for Key index */
+	S_MFGTEST_TMP0,		/* Temp regs used for RX test calculations */
+	S_RXESN,		/* Received end sequence number for A-MPDU BA */
+	S_STREG6,		/* 0x3F */
+};
+
+#define S_BEACON_INDX	S_OLD_BREM
+#define S_PRS_INDX	S_OLD_CWWIN
+#define S_PHYTYPE	S_SSRC
+#define S_PHYVER	S_SLRC
+
+/* IHR SLOW_CTRL values */
+#define SLOW_CTRL_PDE		(1 << 0)
+#define SLOW_CTRL_FD		(1 << 8)
+
+/* ucode mac statistic counters in shared memory */
+struct macstat {
+	u16 txallfrm;	/* 0x80 */
+	u16 txrtsfrm;	/* 0x82 */
+	u16 txctsfrm;	/* 0x84 */
+	u16 txackfrm;	/* 0x86 */
+	u16 txdnlfrm;	/* 0x88 */
+	u16 txbcnfrm;	/* 0x8a */
+	u16 txfunfl[8];	/* 0x8c - 0x9b */
+	u16 txtplunfl;	/* 0x9c */
+	u16 txphyerr;	/* 0x9e */
+	u16 pktengrxducast;	/* 0xa0 */
+	u16 pktengrxdmcast;	/* 0xa2 */
+	u16 rxfrmtoolong;	/* 0xa4 */
+	u16 rxfrmtooshrt;	/* 0xa6 */
+	u16 rxinvmachdr;	/* 0xa8 */
+	u16 rxbadfcs;	/* 0xaa */
+	u16 rxbadplcp;	/* 0xac */
+	u16 rxcrsglitch;	/* 0xae */
+	u16 rxstrt;		/* 0xb0 */
+	u16 rxdfrmucastmbss;	/* 0xb2 */
+	u16 rxmfrmucastmbss;	/* 0xb4 */
+	u16 rxcfrmucast;	/* 0xb6 */
+	u16 rxrtsucast;	/* 0xb8 */
+	u16 rxctsucast;	/* 0xba */
+	u16 rxackucast;	/* 0xbc */
+	u16 rxdfrmocast;	/* 0xbe */
+	u16 rxmfrmocast;	/* 0xc0 */
+	u16 rxcfrmocast;	/* 0xc2 */
+	u16 rxrtsocast;	/* 0xc4 */
+	u16 rxctsocast;	/* 0xc6 */
+	u16 rxdfrmmcast;	/* 0xc8 */
+	u16 rxmfrmmcast;	/* 0xca */
+	u16 rxcfrmmcast;	/* 0xcc */
+	u16 rxbeaconmbss;	/* 0xce */
+	u16 rxdfrmucastobss;	/* 0xd0 */
+	u16 rxbeaconobss;	/* 0xd2 */
+	u16 rxrsptmout;	/* 0xd4 */
+	u16 bcntxcancl;	/* 0xd6 */
+	u16 PAD;
+	u16 rxf0ovfl;	/* 0xda */
+	u16 rxf1ovfl;	/* 0xdc */
+	u16 rxf2ovfl;	/* 0xde */
+	u16 txsfovfl;	/* 0xe0 */
+	u16 pmqovfl;		/* 0xe2 */
+	u16 rxcgprqfrm;	/* 0xe4 */
+	u16 rxcgprsqovfl;	/* 0xe6 */
+	u16 txcgprsfail;	/* 0xe8 */
+	u16 txcgprssuc;	/* 0xea */
+	u16 prs_timeout;	/* 0xec */
+	u16 rxnack;
+	u16 frmscons;
+	u16 txnack;
+	u16 txglitch_nack;
+	u16 txburst;		/* 0xf6 # tx bursts */
+	u16 bphy_rxcrsglitch;	/* bphy rx crs glitch */
+	u16 phywatchdog;	/* 0xfa # of phy watchdog events */
+	u16 PAD;
+	u16 bphy_badplcp;	/* bphy bad plcp */
+};
+
+/* dot11 core-specific control flags */
+#define	SICF_PCLKE		0x0004	/* PHY clock enable */
+#define	SICF_PRST		0x0008	/* PHY reset */
+#define	SICF_MPCLKE		0x0010	/* MAC PHY clockcontrol enable */
+#define	SICF_FREF		0x0020	/* PLL FreqRefSelect */
+/* NOTE: the following bw bits only apply when the core is attached
+ * to a NPHY
+ */
+#define	SICF_BWMASK		0x00c0	/* phy clock mask (b6 & b7) */
+#define	SICF_BW40		0x0080	/* 40MHz BW (160MHz phyclk) */
+#define	SICF_BW20		0x0040	/* 20MHz BW (80MHz phyclk) */
+#define	SICF_BW10		0x0000	/* 10MHz BW (40MHz phyclk) */
+#define	SICF_GMODE		0x2000	/* gmode enable */
+
+/* dot11 core-specific status flags */
+#define	SISF_2G_PHY		0x0001	/* 2.4G capable phy */
+#define	SISF_5G_PHY		0x0002	/* 5G capable phy */
+#define	SISF_FCLKA		0x0004	/* FastClkAvailable */
+#define	SISF_DB_PHY		0x0008	/* Dualband phy */
+
+/* === End of MAC reg, Beginning of PHY(b/a/g/n) reg === */
+/* radio and LPPHY regs are separated */
+
+#define	BPHY_REG_OFT_BASE	0x0
+/* offsets for indirect access to bphy registers */
+#define	BPHY_BB_CONFIG		0x01
+#define	BPHY_ADCBIAS		0x02
+#define	BPHY_ANACORE		0x03
+#define	BPHY_PHYCRSTH		0x06
+#define	BPHY_TEST		0x0a
+#define	BPHY_PA_TX_TO		0x10
+#define	BPHY_SYNTH_DC_TO	0x11
+#define	BPHY_PA_TX_TIME_UP	0x12
+#define	BPHY_RX_FLTR_TIME_UP	0x13
+#define	BPHY_TX_POWER_OVERRIDE	0x14
+#define	BPHY_RF_OVERRIDE	0x15
+#define	BPHY_RF_TR_LOOKUP1	0x16
+#define	BPHY_RF_TR_LOOKUP2	0x17
+#define	BPHY_COEFFS		0x18
+#define	BPHY_PLL_OUT		0x19
+#define	BPHY_REFRESH_MAIN	0x1a
+#define	BPHY_REFRESH_TO0	0x1b
+#define	BPHY_REFRESH_TO1	0x1c
+#define	BPHY_RSSI_TRESH		0x20
+#define	BPHY_IQ_TRESH_HH	0x21
+#define	BPHY_IQ_TRESH_H		0x22
+#define	BPHY_IQ_TRESH_L		0x23
+#define	BPHY_IQ_TRESH_LL	0x24
+#define	BPHY_GAIN		0x25
+#define	BPHY_LNA_GAIN_RANGE	0x26
+#define	BPHY_JSSI		0x27
+#define	BPHY_TSSI_CTL		0x28
+#define	BPHY_TSSI		0x29
+#define	BPHY_TR_LOSS_CTL	0x2a
+#define	BPHY_LO_LEAKAGE		0x2b
+#define	BPHY_LO_RSSI_ACC	0x2c
+#define	BPHY_LO_IQMAG_ACC	0x2d
+#define	BPHY_TX_DC_OFF1		0x2e
+#define	BPHY_TX_DC_OFF2		0x2f
+#define	BPHY_PEAK_CNT_THRESH	0x30
+#define	BPHY_FREQ_OFFSET	0x31
+#define	BPHY_DIVERSITY_CTL	0x32
+#define	BPHY_PEAK_ENERGY_LO	0x33
+#define	BPHY_PEAK_ENERGY_HI	0x34
+#define	BPHY_SYNC_CTL		0x35
+#define	BPHY_TX_PWR_CTRL	0x36
+#define BPHY_TX_EST_PWR		0x37
+#define	BPHY_STEP		0x38
+#define	BPHY_WARMUP		0x39
+#define	BPHY_LMS_CFF_READ	0x3a
+#define	BPHY_LMS_COEFF_I	0x3b
+#define	BPHY_LMS_COEFF_Q	0x3c
+#define	BPHY_SIG_POW		0x3d
+#define	BPHY_RFDC_CANCEL_CTL	0x3e
+#define	BPHY_HDR_TYPE		0x40
+#define	BPHY_SFD_TO		0x41
+#define	BPHY_SFD_CTL		0x42
+#define	BPHY_DEBUG		0x43
+#define	BPHY_RX_DELAY_COMP	0x44
+#define	BPHY_CRS_DROP_TO	0x45
+#define	BPHY_SHORT_SFD_NZEROS	0x46
+#define	BPHY_DSSS_COEFF1	0x48
+#define	BPHY_DSSS_COEFF2	0x49
+#define	BPHY_CCK_COEFF1		0x4a
+#define	BPHY_CCK_COEFF2		0x4b
+#define	BPHY_TR_CORR		0x4c
+#define	BPHY_ANGLE_SCALE	0x4d
+#define	BPHY_TX_PWR_BASE_IDX	0x4e
+#define	BPHY_OPTIONAL_MODES2	0x4f
+#define	BPHY_CCK_LMS_STEP	0x50
+#define	BPHY_BYPASS		0x51
+#define	BPHY_CCK_DELAY_LONG	0x52
+#define	BPHY_CCK_DELAY_SHORT	0x53
+#define	BPHY_PPROC_CHAN_DELAY	0x54
+#define	BPHY_DDFS_ENABLE	0x58
+#define	BPHY_PHASE_SCALE	0x59
+#define	BPHY_FREQ_CONTROL	0x5a
+#define	BPHY_LNA_GAIN_RANGE_10	0x5b
+#define	BPHY_LNA_GAIN_RANGE_32	0x5c
+#define	BPHY_OPTIONAL_MODES	0x5d
+#define	BPHY_RX_STATUS2		0x5e
+#define	BPHY_RX_STATUS3		0x5f
+#define	BPHY_DAC_CONTROL	0x60
+#define	BPHY_ANA11G_FILT_CTRL	0x62
+#define	BPHY_REFRESH_CTRL	0x64
+#define	BPHY_RF_OVERRIDE2	0x65
+#define	BPHY_SPUR_CANCEL_CTRL	0x66
+#define	BPHY_FINE_DIGIGAIN_CTRL	0x67
+#define	BPHY_RSSI_LUT		0x88
+#define	BPHY_RSSI_LUT_END	0xa7
+#define	BPHY_TSSI_LUT		0xa8
+#define	BPHY_TSSI_LUT_END	0xc7
+#define	BPHY_TSSI2PWR_LUT	0x380
+#define	BPHY_TSSI2PWR_LUT_END	0x39f
+#define	BPHY_LOCOMP_LUT		0x3a0
+#define	BPHY_LOCOMP_LUT_END	0x3bf
+#define	BPHY_TXGAIN_LUT		0x3c0
+#define	BPHY_TXGAIN_LUT_END	0x3ff
+
+/* Bits in BB_CONFIG: */
+#define	PHY_BBC_ANT_MASK	0x0180
+#define	PHY_BBC_ANT_SHIFT	7
+#define	BB_DARWIN		0x1000
+#define BBCFG_RESETCCA		0x4000
+#define BBCFG_RESETRX		0x8000
+
+/* Bits in phytest(0x0a): */
+#define	TST_DDFS		0x2000
+#define	TST_TXFILT1		0x0800
+#define	TST_UNSCRAM		0x0400
+#define	TST_CARR_SUPP		0x0200
+#define	TST_DC_COMP_LOOP	0x0100
+#define	TST_LOOPBACK		0x0080
+#define	TST_TXFILT0		0x0040
+#define	TST_TXTEST_ENABLE	0x0020
+#define	TST_TXTEST_RATE		0x0018
+#define	TST_TXTEST_PHASE	0x0007
+
+/* phytest txTestRate values */
+#define	TST_TXTEST_RATE_1MBPS	0
+#define	TST_TXTEST_RATE_2MBPS	1
+#define	TST_TXTEST_RATE_5_5MBPS	2
+#define	TST_TXTEST_RATE_11MBPS	3
+#define	TST_TXTEST_RATE_SHIFT	3
+
+#define SHM_BYT_CNT	0x2	/* IHR location */
+#define MAX_BYT_CNT	0x600	/* Maximum frame len */
+
+struct d11cnt {
+	u32 txfrag;
+	u32 txmulti;
+	u32 txfail;
+	u32 txretry;
+	u32 txretrie;
+	u32 rxdup;
+	u32 txrts;
+	u32 txnocts;
+	u32 txnoack;
+	u32 rxfrag;
+	u32 rxmulti;
+	u32 rxcrc;
+	u32 txfrmsnt;
+	u32 rxundec;
+};
+
+#endif				/* _BRCM_D11_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.c
new file mode 100644
index 0000000..2fe1f68
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ * Copyright (c) 2012 Canonical Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/debugfs.h>
+#include <linux/if_ether.h>
+#include <linux/if.h>
+#include <linux/net.h>
+#include <linux/netdevice.h>
+#include <linux/ieee80211.h>
+#include <linux/module.h>
+#include <net/mac80211.h>
+
+#include <defs.h>
+#include <brcmu_wifi.h>
+#include <brcmu_utils.h>
+#include "types.h"
+#include "main.h"
+#include "debug.h"
+#include "brcms_trace_events.h"
+#include "phy/phy_int.h"
+
+static struct dentry *root_folder;
+
+void brcms_debugfs_init(void)
+{
+	root_folder = debugfs_create_dir(KBUILD_MODNAME, NULL);
+	if (IS_ERR(root_folder))
+		root_folder = NULL;
+}
+
+void brcms_debugfs_exit(void)
+{
+	if (!root_folder)
+		return;
+
+	debugfs_remove_recursive(root_folder);
+	root_folder = NULL;
+}
+
+int brcms_debugfs_attach(struct brcms_pub *drvr)
+{
+	if (!root_folder)
+		return -ENODEV;
+
+	drvr->dbgfs_dir = debugfs_create_dir(
+		 dev_name(&drvr->wlc->hw->d11core->dev), root_folder);
+	return PTR_ERR_OR_ZERO(drvr->dbgfs_dir);
+}
+
+void brcms_debugfs_detach(struct brcms_pub *drvr)
+{
+	if (!IS_ERR_OR_NULL(drvr->dbgfs_dir))
+		debugfs_remove_recursive(drvr->dbgfs_dir);
+}
+
+struct dentry *brcms_debugfs_get_devdir(struct brcms_pub *drvr)
+{
+	return drvr->dbgfs_dir;
+}
+
+static
+int brcms_debugfs_hardware_read(struct seq_file *s, void *data)
+{
+	struct brcms_pub *drvr = s->private;
+	struct brcms_hardware *hw = drvr->wlc->hw;
+	struct bcma_device *core = hw->d11core;
+	struct bcma_bus *bus = core->bus;
+	char boardrev[BRCMU_BOARDREV_LEN];
+
+	seq_printf(s, "chipnum 0x%x\n"
+		   "chiprev 0x%x\n"
+		   "chippackage 0x%x\n"
+		   "corerev 0x%x\n"
+		   "boardid 0x%x\n"
+		   "boardvendor 0x%x\n"
+		   "boardrev %s\n"
+		   "boardflags 0x%x\n"
+		   "boardflags2 0x%x\n"
+		   "ucoderev 0x%x\n"
+		   "radiorev 0x%x\n"
+		   "phytype 0x%x\n"
+		   "phyrev 0x%x\n"
+		   "anarev 0x%x\n"
+		   "nvramrev %d\n",
+		   bus->chipinfo.id, bus->chipinfo.rev, bus->chipinfo.pkg,
+		   core->id.rev, bus->boardinfo.type, bus->boardinfo.vendor,
+		   brcmu_boardrev_str(hw->boardrev, boardrev),
+		   drvr->wlc->hw->boardflags, drvr->wlc->hw->boardflags2,
+		   drvr->wlc->ucode_rev, hw->band->radiorev,
+		   hw->band->phytype, hw->band->phyrev, hw->band->pi->ana_rev,
+		   hw->sromrev);
+	return 0;
+}
+
+static int brcms_debugfs_macstat_read(struct seq_file *s, void *data)
+{
+	struct brcms_pub *drvr = s->private;
+	struct brcms_info *wl = drvr->ieee_hw->priv;
+	struct macstat stats;
+	int i;
+
+	spin_lock_bh(&wl->lock);
+	stats = *(drvr->wlc->core->macstat_snapshot);
+	spin_unlock_bh(&wl->lock);
+
+	seq_printf(s, "txallfrm: %d\n", stats.txallfrm);
+	seq_printf(s, "txrtsfrm: %d\n", stats.txrtsfrm);
+	seq_printf(s, "txctsfrm: %d\n", stats.txctsfrm);
+	seq_printf(s, "txackfrm: %d\n", stats.txackfrm);
+	seq_printf(s, "txdnlfrm: %d\n", stats.txdnlfrm);
+	seq_printf(s, "txbcnfrm: %d\n", stats.txbcnfrm);
+	seq_printf(s, "txfunfl[8]:");
+	for (i = 0; i < ARRAY_SIZE(stats.txfunfl); i++)
+		seq_printf(s, " %d", stats.txfunfl[i]);
+	seq_printf(s, "\ntxtplunfl: %d\n", stats.txtplunfl);
+	seq_printf(s, "txphyerr: %d\n", stats.txphyerr);
+	seq_printf(s, "pktengrxducast: %d\n", stats.pktengrxducast);
+	seq_printf(s, "pktengrxdmcast: %d\n", stats.pktengrxdmcast);
+	seq_printf(s, "rxfrmtoolong: %d\n", stats.rxfrmtoolong);
+	seq_printf(s, "rxfrmtooshrt: %d\n", stats.rxfrmtooshrt);
+	seq_printf(s, "rxinvmachdr: %d\n", stats.rxinvmachdr);
+	seq_printf(s, "rxbadfcs: %d\n", stats.rxbadfcs);
+	seq_printf(s, "rxbadplcp: %d\n", stats.rxbadplcp);
+	seq_printf(s, "rxcrsglitch: %d\n", stats.rxcrsglitch);
+	seq_printf(s, "rxstrt: %d\n", stats.rxstrt);
+	seq_printf(s, "rxdfrmucastmbss: %d\n", stats.rxdfrmucastmbss);
+	seq_printf(s, "rxmfrmucastmbss: %d\n", stats.rxmfrmucastmbss);
+	seq_printf(s, "rxcfrmucast: %d\n", stats.rxcfrmucast);
+	seq_printf(s, "rxrtsucast: %d\n", stats.rxrtsucast);
+	seq_printf(s, "rxctsucast: %d\n", stats.rxctsucast);
+	seq_printf(s, "rxackucast: %d\n", stats.rxackucast);
+	seq_printf(s, "rxdfrmocast: %d\n", stats.rxdfrmocast);
+	seq_printf(s, "rxmfrmocast: %d\n", stats.rxmfrmocast);
+	seq_printf(s, "rxcfrmocast: %d\n", stats.rxcfrmocast);
+	seq_printf(s, "rxrtsocast: %d\n", stats.rxrtsocast);
+	seq_printf(s, "rxctsocast: %d\n", stats.rxctsocast);
+	seq_printf(s, "rxdfrmmcast: %d\n", stats.rxdfrmmcast);
+	seq_printf(s, "rxmfrmmcast: %d\n", stats.rxmfrmmcast);
+	seq_printf(s, "rxcfrmmcast: %d\n", stats.rxcfrmmcast);
+	seq_printf(s, "rxbeaconmbss: %d\n", stats.rxbeaconmbss);
+	seq_printf(s, "rxdfrmucastobss: %d\n", stats.rxdfrmucastobss);
+	seq_printf(s, "rxbeaconobss: %d\n", stats.rxbeaconobss);
+	seq_printf(s, "rxrsptmout: %d\n", stats.rxrsptmout);
+	seq_printf(s, "bcntxcancl: %d\n", stats.bcntxcancl);
+	seq_printf(s, "rxf0ovfl: %d\n", stats.rxf0ovfl);
+	seq_printf(s, "rxf1ovfl: %d\n", stats.rxf1ovfl);
+	seq_printf(s, "rxf2ovfl: %d\n", stats.rxf2ovfl);
+	seq_printf(s, "txsfovfl: %d\n", stats.txsfovfl);
+	seq_printf(s, "pmqovfl: %d\n", stats.pmqovfl);
+	seq_printf(s, "rxcgprqfrm: %d\n", stats.rxcgprqfrm);
+	seq_printf(s, "rxcgprsqovfl: %d\n", stats.rxcgprsqovfl);
+	seq_printf(s, "txcgprsfail: %d\n", stats.txcgprsfail);
+	seq_printf(s, "txcgprssuc: %d\n", stats.txcgprssuc);
+	seq_printf(s, "prs_timeout: %d\n", stats.prs_timeout);
+	seq_printf(s, "rxnack: %d\n", stats.rxnack);
+	seq_printf(s, "frmscons: %d\n", stats.frmscons);
+	seq_printf(s, "txnack: %d\n", stats.txnack);
+	seq_printf(s, "txglitch_nack: %d\n", stats.txglitch_nack);
+	seq_printf(s, "txburst: %d\n", stats.txburst);
+	seq_printf(s, "bphy_rxcrsglitch: %d\n", stats.bphy_rxcrsglitch);
+	seq_printf(s, "phywatchdog: %d\n", stats.phywatchdog);
+	seq_printf(s, "bphy_badplcp: %d\n", stats.bphy_badplcp);
+	return 0;
+}
+
+struct brcms_debugfs_entry {
+	int (*read)(struct seq_file *seq, void *data);
+	struct brcms_pub *drvr;
+};
+
+static int brcms_debugfs_entry_open(struct inode *inode, struct file *f)
+{
+	struct brcms_debugfs_entry *entry = inode->i_private;
+
+	return single_open(f, entry->read, entry->drvr);
+}
+
+static const struct file_operations brcms_debugfs_def_ops = {
+	.owner = THIS_MODULE,
+	.open = brcms_debugfs_entry_open,
+	.release = single_release,
+	.read = seq_read,
+	.llseek = seq_lseek
+};
+
+static int
+brcms_debugfs_add_entry(struct brcms_pub *drvr, const char *fn,
+			int (*read_fn)(struct seq_file *seq, void *data))
+{
+	struct device *dev = &drvr->wlc->hw->d11core->dev;
+	struct dentry *dentry =  drvr->dbgfs_dir;
+	struct brcms_debugfs_entry *entry;
+
+	if (IS_ERR_OR_NULL(dentry))
+		return -ENOENT;
+
+	entry = devm_kzalloc(dev, sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		return -ENOMEM;
+
+	entry->read = read_fn;
+	entry->drvr = drvr;
+
+	dentry = debugfs_create_file(fn, 0444, dentry, entry,
+				     &brcms_debugfs_def_ops);
+
+	return PTR_ERR_OR_ZERO(dentry);
+}
+
+void brcms_debugfs_create_files(struct brcms_pub *drvr)
+{
+	if (IS_ERR_OR_NULL(drvr->dbgfs_dir))
+		return;
+
+	brcms_debugfs_add_entry(drvr, "hardware", brcms_debugfs_hardware_read);
+	brcms_debugfs_add_entry(drvr, "macstat", brcms_debugfs_macstat_read);
+}
+
+#define __brcms_fn(fn)						\
+void __brcms_ ##fn(struct device *dev, const char *fmt, ...)	\
+{								\
+	struct va_format vaf = {				\
+		.fmt = fmt,					\
+	};							\
+	va_list args;						\
+								\
+	va_start(args, fmt);					\
+	vaf.va = &args;						\
+	dev_ ##fn(dev, "%pV", &vaf);				\
+	trace_brcms_ ##fn(&vaf);				\
+	va_end(args);						\
+}
+
+__brcms_fn(info)
+__brcms_fn(warn)
+__brcms_fn(err)
+__brcms_fn(crit)
+
+#if defined(CONFIG_BRCMDBG) || defined(CONFIG_BRCM_TRACING)
+void __brcms_dbg(struct device *dev, u32 level, const char *func,
+		 const char *fmt, ...)
+{
+	struct va_format vaf = {
+		.fmt = fmt,
+	};
+	va_list args;
+
+	va_start(args, fmt);
+	vaf.va = &args;
+#ifdef CONFIG_BRCMDBG
+	if ((brcm_msg_level & level) && net_ratelimit())
+		dev_err(dev, "%s %pV", func, &vaf);
+#endif
+	trace_brcms_dbg(level, func, &vaf);
+	va_end(args);
+}
+#endif
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.h
new file mode 100644
index 0000000..822781c
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/debug.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ * Copyright (c) 2012 Canonical Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef _BRCMS_DEBUG_H_
+#define _BRCMS_DEBUG_H_
+
+#include <linux/device.h>
+#include <linux/bcma/bcma.h>
+#include <net/cfg80211.h>
+#include <net/mac80211.h>
+#include "main.h"
+#include "mac80211_if.h"
+
+__printf(2, 3)
+void __brcms_info(struct device *dev, const char *fmt, ...);
+__printf(2, 3)
+void __brcms_warn(struct device *dev, const char *fmt, ...);
+__printf(2, 3)
+void __brcms_err(struct device *dev, const char *fmt, ...);
+__printf(2, 3)
+void __brcms_crit(struct device *dev, const char *fmt, ...);
+
+#if defined(CONFIG_BRCMDBG) || defined(CONFIG_BRCM_TRACING)
+__printf(4, 5)
+void __brcms_dbg(struct device *dev, u32 level, const char *func,
+		 const char *fmt, ...);
+#else
+static inline __printf(4, 5)
+void __brcms_dbg(struct device *dev, u32 level, const char *func,
+		 const char *fmt, ...)
+{
+}
+#endif
+
+/*
+ * Debug macros cannot be used when wlc is uninitialized. Generally
+ * this means any code that could run before brcms_c_attach() has
+ * returned successfully probably shouldn't use the following macros.
+ */
+
+#define brcms_dbg(core, l, f, a...)	__brcms_dbg(&(core)->dev, l, __func__, f, ##a)
+#define brcms_info(core, f, a...)	__brcms_info(&(core)->dev, f, ##a)
+#define brcms_warn(core, f, a...)	__brcms_warn(&(core)->dev, f, ##a)
+#define brcms_err(core, f, a...)	__brcms_err(&(core)->dev, f, ##a)
+#define brcms_crit(core, f, a...)	__brcms_crit(&(core)->dev, f, ##a)
+
+#define brcms_dbg_info(core, f, a...)		brcms_dbg(core, BRCM_DL_INFO, f, ##a)
+#define brcms_dbg_mac80211(core, f, a...)	brcms_dbg(core, BRCM_DL_MAC80211, f, ##a)
+#define brcms_dbg_rx(core, f, a...)		brcms_dbg(core, BRCM_DL_RX, f, ##a)
+#define brcms_dbg_tx(core, f, a...)		brcms_dbg(core, BRCM_DL_TX, f, ##a)
+#define brcms_dbg_int(core, f, a...)		brcms_dbg(core, BRCM_DL_INT, f, ##a)
+#define brcms_dbg_dma(core, f, a...)		brcms_dbg(core, BRCM_DL_DMA, f, ##a)
+#define brcms_dbg_ht(core, f, a...)		brcms_dbg(core, BRCM_DL_HT, f, ##a)
+
+struct brcms_pub;
+void brcms_debugfs_init(void);
+void brcms_debugfs_exit(void);
+int brcms_debugfs_attach(struct brcms_pub *drvr);
+void brcms_debugfs_detach(struct brcms_pub *drvr);
+struct dentry *brcms_debugfs_get_devdir(struct brcms_pub *drvr);
+void brcms_debugfs_create_files(struct brcms_pub *drvr);
+
+#endif /* _BRCMS_DEBUG_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c
new file mode 100644
index 0000000..b7df576
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c
@@ -0,0 +1,1566 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <net/cfg80211.h>
+#include <net/mac80211.h>
+
+#include <brcmu_utils.h>
+#include <aiutils.h>
+#include "types.h"
+#include "main.h"
+#include "dma.h"
+#include "soc.h"
+#include "scb.h"
+#include "ampdu.h"
+#include "debug.h"
+#include "brcms_trace_events.h"
+
+/*
+ * dma register field offset calculation
+ */
+#define DMA64REGOFFS(field)		offsetof(struct dma64regs, field)
+#define DMA64TXREGOFFS(di, field)	(di->d64txregbase + DMA64REGOFFS(field))
+#define DMA64RXREGOFFS(di, field)	(di->d64rxregbase + DMA64REGOFFS(field))
+
+/*
+ * DMA hardware requires each descriptor ring to be 8kB aligned, and fit within
+ * a contiguous 8kB physical address.
+ */
+#define D64RINGALIGN_BITS	13
+#define	D64MAXRINGSZ		(1 << D64RINGALIGN_BITS)
+#define	D64RINGALIGN		(1 << D64RINGALIGN_BITS)
+
+#define	D64MAXDD	(D64MAXRINGSZ / sizeof(struct dma64desc))
+
+/* transmit channel control */
+#define	D64_XC_XE		0x00000001	/* transmit enable */
+#define	D64_XC_SE		0x00000002	/* transmit suspend request */
+#define	D64_XC_LE		0x00000004	/* loopback enable */
+#define	D64_XC_FL		0x00000010	/* flush request */
+#define	D64_XC_PD		0x00000800	/* parity check disable */
+#define	D64_XC_AE		0x00030000	/* address extension bits */
+#define	D64_XC_AE_SHIFT		16
+
+/* transmit descriptor table pointer */
+#define	D64_XP_LD_MASK		0x00000fff	/* last valid descriptor */
+
+/* transmit channel status */
+#define	D64_XS0_CD_MASK		0x00001fff	/* current descriptor pointer */
+#define	D64_XS0_XS_MASK		0xf0000000	/* transmit state */
+#define	D64_XS0_XS_SHIFT		28
+#define	D64_XS0_XS_DISABLED	0x00000000	/* disabled */
+#define	D64_XS0_XS_ACTIVE	0x10000000	/* active */
+#define	D64_XS0_XS_IDLE		0x20000000	/* idle wait */
+#define	D64_XS0_XS_STOPPED	0x30000000	/* stopped */
+#define	D64_XS0_XS_SUSP		0x40000000	/* suspend pending */
+
+#define	D64_XS1_AD_MASK		0x00001fff	/* active descriptor */
+#define	D64_XS1_XE_MASK		0xf0000000	/* transmit errors */
+#define	D64_XS1_XE_SHIFT		28
+#define	D64_XS1_XE_NOERR	0x00000000	/* no error */
+#define	D64_XS1_XE_DPE		0x10000000	/* descriptor protocol error */
+#define	D64_XS1_XE_DFU		0x20000000	/* data fifo underrun */
+#define	D64_XS1_XE_DTE		0x30000000	/* data transfer error */
+#define	D64_XS1_XE_DESRE	0x40000000	/* descriptor read error */
+#define	D64_XS1_XE_COREE	0x50000000	/* core error */
+
+/* receive channel control */
+/* receive enable */
+#define	D64_RC_RE		0x00000001
+/* receive frame offset */
+#define	D64_RC_RO_MASK		0x000000fe
+#define	D64_RC_RO_SHIFT		1
+/* direct fifo receive (pio) mode */
+#define	D64_RC_FM		0x00000100
+/* separate rx header descriptor enable */
+#define	D64_RC_SH		0x00000200
+/* overflow continue */
+#define	D64_RC_OC		0x00000400
+/* parity check disable */
+#define	D64_RC_PD		0x00000800
+/* address extension bits */
+#define	D64_RC_AE		0x00030000
+#define	D64_RC_AE_SHIFT		16
+
+/* flags for dma controller */
+/* partity enable */
+#define DMA_CTRL_PEN		(1 << 0)
+/* rx overflow continue */
+#define DMA_CTRL_ROC		(1 << 1)
+/* allow rx scatter to multiple descriptors */
+#define DMA_CTRL_RXMULTI	(1 << 2)
+/* Unframed Rx/Tx data */
+#define DMA_CTRL_UNFRAMED	(1 << 3)
+
+/* receive descriptor table pointer */
+#define	D64_RP_LD_MASK		0x00000fff	/* last valid descriptor */
+
+/* receive channel status */
+#define	D64_RS0_CD_MASK		0x00001fff	/* current descriptor pointer */
+#define	D64_RS0_RS_MASK		0xf0000000	/* receive state */
+#define	D64_RS0_RS_SHIFT		28
+#define	D64_RS0_RS_DISABLED	0x00000000	/* disabled */
+#define	D64_RS0_RS_ACTIVE	0x10000000	/* active */
+#define	D64_RS0_RS_IDLE		0x20000000	/* idle wait */
+#define	D64_RS0_RS_STOPPED	0x30000000	/* stopped */
+#define	D64_RS0_RS_SUSP		0x40000000	/* suspend pending */
+
+#define	D64_RS1_AD_MASK		0x0001ffff	/* active descriptor */
+#define	D64_RS1_RE_MASK		0xf0000000	/* receive errors */
+#define	D64_RS1_RE_SHIFT		28
+#define	D64_RS1_RE_NOERR	0x00000000	/* no error */
+#define	D64_RS1_RE_DPO		0x10000000	/* descriptor protocol error */
+#define	D64_RS1_RE_DFU		0x20000000	/* data fifo overflow */
+#define	D64_RS1_RE_DTE		0x30000000	/* data transfer error */
+#define	D64_RS1_RE_DESRE	0x40000000	/* descriptor read error */
+#define	D64_RS1_RE_COREE	0x50000000	/* core error */
+
+/* fifoaddr */
+#define	D64_FA_OFF_MASK		0xffff	/* offset */
+#define	D64_FA_SEL_MASK		0xf0000	/* select */
+#define	D64_FA_SEL_SHIFT	16
+#define	D64_FA_SEL_XDD		0x00000	/* transmit dma data */
+#define	D64_FA_SEL_XDP		0x10000	/* transmit dma pointers */
+#define	D64_FA_SEL_RDD		0x40000	/* receive dma data */
+#define	D64_FA_SEL_RDP		0x50000	/* receive dma pointers */
+#define	D64_FA_SEL_XFD		0x80000	/* transmit fifo data */
+#define	D64_FA_SEL_XFP		0x90000	/* transmit fifo pointers */
+#define	D64_FA_SEL_RFD		0xc0000	/* receive fifo data */
+#define	D64_FA_SEL_RFP		0xd0000	/* receive fifo pointers */
+#define	D64_FA_SEL_RSD		0xe0000	/* receive frame status data */
+#define	D64_FA_SEL_RSP		0xf0000	/* receive frame status pointers */
+
+/* descriptor control flags 1 */
+#define D64_CTRL_COREFLAGS	0x0ff00000	/* core specific flags */
+#define	D64_CTRL1_EOT		((u32)1 << 28)	/* end of descriptor table */
+#define	D64_CTRL1_IOC		((u32)1 << 29)	/* interrupt on completion */
+#define	D64_CTRL1_EOF		((u32)1 << 30)	/* end of frame */
+#define	D64_CTRL1_SOF		((u32)1 << 31)	/* start of frame */
+
+/* descriptor control flags 2 */
+/* buffer byte count. real data len must <= 16KB */
+#define	D64_CTRL2_BC_MASK	0x00007fff
+/* address extension bits */
+#define	D64_CTRL2_AE		0x00030000
+#define	D64_CTRL2_AE_SHIFT	16
+/* parity bit */
+#define D64_CTRL2_PARITY	0x00040000
+
+/* control flags in the range [27:20] are core-specific and not defined here */
+#define	D64_CTRL_CORE_MASK	0x0ff00000
+
+#define D64_RX_FRM_STS_LEN	0x0000ffff	/* frame length mask */
+#define D64_RX_FRM_STS_OVFL	0x00800000	/* RxOverFlow */
+#define D64_RX_FRM_STS_DSCRCNT	0x0f000000  /* no. of descriptors used - 1 */
+#define D64_RX_FRM_STS_DATATYPE	0xf0000000	/* core-dependent data type */
+
+/*
+ * packet headroom necessary to accommodate the largest header
+ * in the system, (i.e TXOFF). By doing, we avoid the need to
+ * allocate an extra buffer for the header when bridging to WL.
+ * There is a compile time check in wlc.c which ensure that this
+ * value is at least as big as TXOFF. This value is used in
+ * dma_rxfill().
+ */
+
+#define BCMEXTRAHDROOM 172
+
+#define	MAXNAMEL	8	/* 8 char names */
+
+/* macros to convert between byte offsets and indexes */
+#define	B2I(bytes, type)	((bytes) / sizeof(type))
+#define	I2B(index, type)	((index) * sizeof(type))
+
+#define	PCI32ADDR_HIGH		0xc0000000	/* address[31:30] */
+#define	PCI32ADDR_HIGH_SHIFT	30	/* address[31:30] */
+
+#define	PCI64ADDR_HIGH		0x80000000	/* address[63] */
+#define	PCI64ADDR_HIGH_SHIFT	31	/* address[63] */
+
+/*
+ * DMA Descriptor
+ * Descriptors are only read by the hardware, never written back.
+ */
+struct dma64desc {
+	__le32 ctrl1;	/* misc control bits & bufcount */
+	__le32 ctrl2;	/* buffer count and address extension */
+	__le32 addrlow;	/* memory address of the date buffer, bits 31:0 */
+	__le32 addrhigh; /* memory address of the date buffer, bits 63:32 */
+};
+
+/* dma engine software state */
+struct dma_info {
+	struct dma_pub dma; /* exported structure */
+	char name[MAXNAMEL];	/* callers name for diag msgs */
+
+	struct bcma_device *core;
+	struct device *dmadev;
+
+	/* session information for AMPDU */
+	struct brcms_ampdu_session ampdu_session;
+
+	bool dma64;	/* this dma engine is operating in 64-bit mode */
+	bool addrext;	/* this dma engine supports DmaExtendedAddrChanges */
+
+	/* 64-bit dma tx engine registers */
+	uint d64txregbase;
+	/* 64-bit dma rx engine registers */
+	uint d64rxregbase;
+	/* pointer to dma64 tx descriptor ring */
+	struct dma64desc *txd64;
+	/* pointer to dma64 rx descriptor ring */
+	struct dma64desc *rxd64;
+
+	u16 dmadesc_align;	/* alignment requirement for dma descriptors */
+
+	u16 ntxd;		/* # tx descriptors tunable */
+	u16 txin;		/* index of next descriptor to reclaim */
+	u16 txout;		/* index of next descriptor to post */
+	/* pointer to parallel array of pointers to packets */
+	struct sk_buff **txp;
+	/* Aligned physical address of descriptor ring */
+	dma_addr_t txdpa;
+	/* Original physical address of descriptor ring */
+	dma_addr_t txdpaorig;
+	u16 txdalign;	/* #bytes added to alloc'd mem to align txd */
+	u32 txdalloc;	/* #bytes allocated for the ring */
+	u32 xmtptrbase;	/* When using unaligned descriptors, the ptr register
+			 * is not just an index, it needs all 13 bits to be
+			 * an offset from the addr register.
+			 */
+
+	u16 nrxd;	/* # rx descriptors tunable */
+	u16 rxin;	/* index of next descriptor to reclaim */
+	u16 rxout;	/* index of next descriptor to post */
+	/* pointer to parallel array of pointers to packets */
+	struct sk_buff **rxp;
+	/* Aligned physical address of descriptor ring */
+	dma_addr_t rxdpa;
+	/* Original physical address of descriptor ring */
+	dma_addr_t rxdpaorig;
+	u16 rxdalign;	/* #bytes added to alloc'd mem to align rxd */
+	u32 rxdalloc;	/* #bytes allocated for the ring */
+	u32 rcvptrbase;	/* Base for ptr reg when using unaligned descriptors */
+
+	/* tunables */
+	unsigned int rxbufsize;	/* rx buffer size in bytes, not including
+				 * the extra headroom
+				 */
+	uint rxextrahdrroom;	/* extra rx headroom, reverseved to assist upper
+				 * stack, e.g. some rx pkt buffers will be
+				 * bridged to tx side without byte copying.
+				 * The extra headroom needs to be large enough
+				 * to fit txheader needs. Some dongle driver may
+				 * not need it.
+				 */
+	uint nrxpost;		/* # rx buffers to keep posted */
+	unsigned int rxoffset;	/* rxcontrol offset */
+	/* add to get dma address of descriptor ring, low 32 bits */
+	uint ddoffsetlow;
+	/*   high 32 bits */
+	uint ddoffsethigh;
+	/* add to get dma address of data buffer, low 32 bits */
+	uint dataoffsetlow;
+	/*   high 32 bits */
+	uint dataoffsethigh;
+	/* descriptor base need to be aligned or not */
+	bool aligndesc_4k;
+};
+
+/* Check for odd number of 1's */
+static u32 parity32(__le32 data)
+{
+	/* no swap needed for counting 1's */
+	u32 par_data = *(u32 *)&data;
+
+	par_data ^= par_data >> 16;
+	par_data ^= par_data >> 8;
+	par_data ^= par_data >> 4;
+	par_data ^= par_data >> 2;
+	par_data ^= par_data >> 1;
+
+	return par_data & 1;
+}
+
+static bool dma64_dd_parity(struct dma64desc *dd)
+{
+	return parity32(dd->addrlow ^ dd->addrhigh ^ dd->ctrl1 ^ dd->ctrl2);
+}
+
+/* descriptor bumping functions */
+
+static uint xxd(uint x, uint n)
+{
+	return x & (n - 1); /* faster than %, but n must be power of 2 */
+}
+
+static uint txd(struct dma_info *di, uint x)
+{
+	return xxd(x, di->ntxd);
+}
+
+static uint rxd(struct dma_info *di, uint x)
+{
+	return xxd(x, di->nrxd);
+}
+
+static uint nexttxd(struct dma_info *di, uint i)
+{
+	return txd(di, i + 1);
+}
+
+static uint prevtxd(struct dma_info *di, uint i)
+{
+	return txd(di, i - 1);
+}
+
+static uint nextrxd(struct dma_info *di, uint i)
+{
+	return rxd(di, i + 1);
+}
+
+static uint ntxdactive(struct dma_info *di, uint h, uint t)
+{
+	return txd(di, t-h);
+}
+
+static uint nrxdactive(struct dma_info *di, uint h, uint t)
+{
+	return rxd(di, t-h);
+}
+
+static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags)
+{
+	uint dmactrlflags;
+
+	if (di == NULL)
+		return 0;
+
+	dmactrlflags = di->dma.dmactrlflags;
+	dmactrlflags &= ~mask;
+	dmactrlflags |= flags;
+
+	/* If trying to enable parity, check if parity is actually supported */
+	if (dmactrlflags & DMA_CTRL_PEN) {
+		u32 control;
+
+		control = bcma_read32(di->core, DMA64TXREGOFFS(di, control));
+		bcma_write32(di->core, DMA64TXREGOFFS(di, control),
+		      control | D64_XC_PD);
+		if (bcma_read32(di->core, DMA64TXREGOFFS(di, control)) &
+		    D64_XC_PD)
+			/* We *can* disable it so it is supported,
+			 * restore control register
+			 */
+			bcma_write32(di->core, DMA64TXREGOFFS(di, control),
+				     control);
+		else
+			/* Not supported, don't allow it to be enabled */
+			dmactrlflags &= ~DMA_CTRL_PEN;
+	}
+
+	di->dma.dmactrlflags = dmactrlflags;
+
+	return dmactrlflags;
+}
+
+static bool _dma64_addrext(struct dma_info *di, uint ctrl_offset)
+{
+	u32 w;
+	bcma_set32(di->core, ctrl_offset, D64_XC_AE);
+	w = bcma_read32(di->core, ctrl_offset);
+	bcma_mask32(di->core, ctrl_offset, ~D64_XC_AE);
+	return (w & D64_XC_AE) == D64_XC_AE;
+}
+
+/*
+ * return true if this dma engine supports DmaExtendedAddrChanges,
+ * otherwise false
+ */
+static bool _dma_isaddrext(struct dma_info *di)
+{
+	/* DMA64 supports full 32- or 64-bit operation. AE is always valid */
+
+	/* not all tx or rx channel are available */
+	if (di->d64txregbase != 0) {
+		if (!_dma64_addrext(di, DMA64TXREGOFFS(di, control)))
+			brcms_dbg_dma(di->core,
+				      "%s: DMA64 tx doesn't have AE set\n",
+				      di->name);
+		return true;
+	} else if (di->d64rxregbase != 0) {
+		if (!_dma64_addrext(di, DMA64RXREGOFFS(di, control)))
+			brcms_dbg_dma(di->core,
+				      "%s: DMA64 rx doesn't have AE set\n",
+				      di->name);
+		return true;
+	}
+
+	return false;
+}
+
+static bool _dma_descriptor_align(struct dma_info *di)
+{
+	u32 addrl;
+
+	/* Check to see if the descriptors need to be aligned on 4K/8K or not */
+	if (di->d64txregbase != 0) {
+		bcma_write32(di->core, DMA64TXREGOFFS(di, addrlow), 0xff0);
+		addrl = bcma_read32(di->core, DMA64TXREGOFFS(di, addrlow));
+		if (addrl != 0)
+			return false;
+	} else if (di->d64rxregbase != 0) {
+		bcma_write32(di->core, DMA64RXREGOFFS(di, addrlow), 0xff0);
+		addrl = bcma_read32(di->core, DMA64RXREGOFFS(di, addrlow));
+		if (addrl != 0)
+			return false;
+	}
+	return true;
+}
+
+/*
+ * Descriptor table must start at the DMA hardware dictated alignment, so
+ * allocated memory must be large enough to support this requirement.
+ */
+static void *dma_alloc_consistent(struct dma_info *di, uint size,
+				  u16 align_bits, uint *alloced,
+				  dma_addr_t *pap)
+{
+	if (align_bits) {
+		u16 align = (1 << align_bits);
+		if (!IS_ALIGNED(PAGE_SIZE, align))
+			size += align;
+		*alloced = size;
+	}
+	return dma_alloc_coherent(di->dmadev, size, pap, GFP_ATOMIC);
+}
+
+static
+u8 dma_align_sizetobits(uint size)
+{
+	u8 bitpos = 0;
+	while (size >>= 1)
+		bitpos++;
+	return bitpos;
+}
+
+/* This function ensures that the DMA descriptor ring will not get allocated
+ * across Page boundary. If the allocation is done across the page boundary
+ * at the first time, then it is freed and the allocation is done at
+ * descriptor ring size aligned location. This will ensure that the ring will
+ * not cross page boundary
+ */
+static void *dma_ringalloc(struct dma_info *di, u32 boundary, uint size,
+			   u16 *alignbits, uint *alloced,
+			   dma_addr_t *descpa)
+{
+	void *va;
+	u32 desc_strtaddr;
+	u32 alignbytes = 1 << *alignbits;
+
+	va = dma_alloc_consistent(di, size, *alignbits, alloced, descpa);
+
+	if (NULL == va)
+		return NULL;
+
+	desc_strtaddr = (u32) roundup((unsigned long)va, alignbytes);
+	if (((desc_strtaddr + size - 1) & boundary) != (desc_strtaddr
+							& boundary)) {
+		*alignbits = dma_align_sizetobits(size);
+		dma_free_coherent(di->dmadev, size, va, *descpa);
+		va = dma_alloc_consistent(di, size, *alignbits,
+			alloced, descpa);
+	}
+	return va;
+}
+
+static bool dma64_alloc(struct dma_info *di, uint direction)
+{
+	u16 size;
+	uint ddlen;
+	void *va;
+	uint alloced = 0;
+	u16 align;
+	u16 align_bits;
+
+	ddlen = sizeof(struct dma64desc);
+
+	size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen);
+	align_bits = di->dmadesc_align;
+	align = (1 << align_bits);
+
+	if (direction == DMA_TX) {
+		va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
+			&alloced, &di->txdpaorig);
+		if (va == NULL) {
+			brcms_dbg_dma(di->core,
+				      "%s: DMA_ALLOC_CONSISTENT(ntxd) failed\n",
+				      di->name);
+			return false;
+		}
+		align = (1 << align_bits);
+		di->txd64 = (struct dma64desc *)
+					roundup((unsigned long)va, align);
+		di->txdalign = (uint) ((s8 *)di->txd64 - (s8 *) va);
+		di->txdpa = di->txdpaorig + di->txdalign;
+		di->txdalloc = alloced;
+	} else {
+		va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
+			&alloced, &di->rxdpaorig);
+		if (va == NULL) {
+			brcms_dbg_dma(di->core,
+				      "%s: DMA_ALLOC_CONSISTENT(nrxd) failed\n",
+				      di->name);
+			return false;
+		}
+		align = (1 << align_bits);
+		di->rxd64 = (struct dma64desc *)
+					roundup((unsigned long)va, align);
+		di->rxdalign = (uint) ((s8 *)di->rxd64 - (s8 *) va);
+		di->rxdpa = di->rxdpaorig + di->rxdalign;
+		di->rxdalloc = alloced;
+	}
+
+	return true;
+}
+
+static bool _dma_alloc(struct dma_info *di, uint direction)
+{
+	return dma64_alloc(di, direction);
+}
+
+struct dma_pub *dma_attach(char *name, struct brcms_c_info *wlc,
+			   uint txregbase, uint rxregbase, uint ntxd, uint nrxd,
+			   uint rxbufsize, int rxextheadroom,
+			   uint nrxpost, uint rxoffset)
+{
+	struct si_pub *sih = wlc->hw->sih;
+	struct bcma_device *core = wlc->hw->d11core;
+	struct dma_info *di;
+	u8 rev = core->id.rev;
+	uint size;
+	struct si_info *sii = container_of(sih, struct si_info, pub);
+
+	/* allocate private info structure */
+	di = kzalloc(sizeof(struct dma_info), GFP_ATOMIC);
+	if (di == NULL)
+		return NULL;
+
+	di->dma64 =
+		((bcma_aread32(core, BCMA_IOST) & SISF_DMA64) == SISF_DMA64);
+
+	/* init dma reg info */
+	di->core = core;
+	di->d64txregbase = txregbase;
+	di->d64rxregbase = rxregbase;
+
+	/*
+	 * Default flags (which can be changed by the driver calling
+	 * dma_ctrlflags before enable): For backwards compatibility
+	 * both Rx Overflow Continue and Parity are DISABLED.
+	 */
+	_dma_ctrlflags(di, DMA_CTRL_ROC | DMA_CTRL_PEN, 0);
+
+	brcms_dbg_dma(di->core, "%s: %s flags 0x%x ntxd %d nrxd %d "
+		      "rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d "
+		      "txregbase %u rxregbase %u\n", name, "DMA64",
+		      di->dma.dmactrlflags, ntxd, nrxd, rxbufsize,
+		      rxextheadroom, nrxpost, rxoffset, txregbase, rxregbase);
+
+	/* make a private copy of our callers name */
+	strncpy(di->name, name, MAXNAMEL);
+	di->name[MAXNAMEL - 1] = '\0';
+
+	di->dmadev = core->dma_dev;
+
+	/* save tunables */
+	di->ntxd = (u16) ntxd;
+	di->nrxd = (u16) nrxd;
+
+	/* the actual dma size doesn't include the extra headroom */
+	di->rxextrahdrroom =
+	    (rxextheadroom == -1) ? BCMEXTRAHDROOM : rxextheadroom;
+	if (rxbufsize > BCMEXTRAHDROOM)
+		di->rxbufsize = (u16) (rxbufsize - di->rxextrahdrroom);
+	else
+		di->rxbufsize = (u16) rxbufsize;
+
+	di->nrxpost = (u16) nrxpost;
+	di->rxoffset = (u8) rxoffset;
+
+	/*
+	 * figure out the DMA physical address offset for dd and data
+	 *     PCI/PCIE: they map silicon backplace address to zero
+	 *     based memory, need offset
+	 *     Other bus: use zero SI_BUS BIGENDIAN kludge: use sdram
+	 *     swapped region for data buffer, not descriptor
+	 */
+	di->ddoffsetlow = 0;
+	di->dataoffsetlow = 0;
+	/* for pci bus, add offset */
+	if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) {
+		/* add offset for pcie with DMA64 bus */
+		di->ddoffsetlow = 0;
+		di->ddoffsethigh = SI_PCIE_DMA_H32;
+	}
+	di->dataoffsetlow = di->ddoffsetlow;
+	di->dataoffsethigh = di->ddoffsethigh;
+
+	/* WAR64450 : DMACtl.Addr ext fields are not supported in SDIOD core. */
+	if ((core->id.id == BCMA_CORE_SDIO_DEV)
+	    && ((rev > 0) && (rev <= 2)))
+		di->addrext = false;
+	else if ((core->id.id == BCMA_CORE_I2S) &&
+		 ((rev == 0) || (rev == 1)))
+		di->addrext = false;
+	else
+		di->addrext = _dma_isaddrext(di);
+
+	/* does the descriptor need to be aligned and if yes, on 4K/8K or not */
+	di->aligndesc_4k = _dma_descriptor_align(di);
+	if (di->aligndesc_4k) {
+		di->dmadesc_align = D64RINGALIGN_BITS;
+		if ((ntxd < D64MAXDD / 2) && (nrxd < D64MAXDD / 2))
+			/* for smaller dd table, HW relax alignment reqmnt */
+			di->dmadesc_align = D64RINGALIGN_BITS - 1;
+	} else {
+		di->dmadesc_align = 4;	/* 16 byte alignment */
+	}
+
+	brcms_dbg_dma(di->core, "DMA descriptor align_needed %d, align %d\n",
+		      di->aligndesc_4k, di->dmadesc_align);
+
+	/* allocate tx packet pointer vector */
+	if (ntxd) {
+		size = ntxd * sizeof(void *);
+		di->txp = kzalloc(size, GFP_ATOMIC);
+		if (di->txp == NULL)
+			goto fail;
+	}
+
+	/* allocate rx packet pointer vector */
+	if (nrxd) {
+		size = nrxd * sizeof(void *);
+		di->rxp = kzalloc(size, GFP_ATOMIC);
+		if (di->rxp == NULL)
+			goto fail;
+	}
+
+	/*
+	 * allocate transmit descriptor ring, only need ntxd descriptors
+	 * but it must be aligned
+	 */
+	if (ntxd) {
+		if (!_dma_alloc(di, DMA_TX))
+			goto fail;
+	}
+
+	/*
+	 * allocate receive descriptor ring, only need nrxd descriptors
+	 * but it must be aligned
+	 */
+	if (nrxd) {
+		if (!_dma_alloc(di, DMA_RX))
+			goto fail;
+	}
+
+	if ((di->ddoffsetlow != 0) && !di->addrext) {
+		if (di->txdpa > SI_PCI_DMA_SZ) {
+			brcms_dbg_dma(di->core,
+				      "%s: txdpa 0x%x: addrext not supported\n",
+				      di->name, (u32)di->txdpa);
+			goto fail;
+		}
+		if (di->rxdpa > SI_PCI_DMA_SZ) {
+			brcms_dbg_dma(di->core,
+				      "%s: rxdpa 0x%x: addrext not supported\n",
+				      di->name, (u32)di->rxdpa);
+			goto fail;
+		}
+	}
+
+	/* Initialize AMPDU session */
+	brcms_c_ampdu_reset_session(&di->ampdu_session, wlc);
+
+	brcms_dbg_dma(di->core,
+		      "ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x dataoffsethigh 0x%x addrext %d\n",
+		      di->ddoffsetlow, di->ddoffsethigh,
+		      di->dataoffsetlow, di->dataoffsethigh,
+		      di->addrext);
+
+	return (struct dma_pub *) di;
+
+ fail:
+	dma_detach((struct dma_pub *)di);
+	return NULL;
+}
+
+static inline void
+dma64_dd_upd(struct dma_info *di, struct dma64desc *ddring,
+	     dma_addr_t pa, uint outidx, u32 *flags, u32 bufcount)
+{
+	u32 ctrl2 = bufcount & D64_CTRL2_BC_MASK;
+
+	/* PCI bus with big(>1G) physical address, use address extension */
+	if ((di->dataoffsetlow == 0) || !(pa & PCI32ADDR_HIGH)) {
+		ddring[outidx].addrlow = cpu_to_le32(pa + di->dataoffsetlow);
+		ddring[outidx].addrhigh = cpu_to_le32(di->dataoffsethigh);
+		ddring[outidx].ctrl1 = cpu_to_le32(*flags);
+		ddring[outidx].ctrl2 = cpu_to_le32(ctrl2);
+	} else {
+		/* address extension for 32-bit PCI */
+		u32 ae;
+
+		ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT;
+		pa &= ~PCI32ADDR_HIGH;
+
+		ctrl2 |= (ae << D64_CTRL2_AE_SHIFT) & D64_CTRL2_AE;
+		ddring[outidx].addrlow = cpu_to_le32(pa + di->dataoffsetlow);
+		ddring[outidx].addrhigh = cpu_to_le32(di->dataoffsethigh);
+		ddring[outidx].ctrl1 = cpu_to_le32(*flags);
+		ddring[outidx].ctrl2 = cpu_to_le32(ctrl2);
+	}
+	if (di->dma.dmactrlflags & DMA_CTRL_PEN) {
+		if (dma64_dd_parity(&ddring[outidx]))
+			ddring[outidx].ctrl2 =
+			     cpu_to_le32(ctrl2 | D64_CTRL2_PARITY);
+	}
+}
+
+/* !! may be called with core in reset */
+void dma_detach(struct dma_pub *pub)
+{
+	struct dma_info *di = container_of(pub, struct dma_info, dma);
+
+	brcms_dbg_dma(di->core, "%s:\n", di->name);
+
+	/* free dma descriptor rings */
+	if (di->txd64)
+		dma_free_coherent(di->dmadev, di->txdalloc,
+				  ((s8 *)di->txd64 - di->txdalign),
+				  (di->txdpaorig));
+	if (di->rxd64)
+		dma_free_coherent(di->dmadev, di->rxdalloc,
+				  ((s8 *)di->rxd64 - di->rxdalign),
+				  (di->rxdpaorig));
+
+	/* free packet pointer vectors */
+	kfree(di->txp);
+	kfree(di->rxp);
+
+	/* free our private info structure */
+	kfree(di);
+
+}
+
+/* initialize descriptor table base address */
+static void
+_dma_ddtable_init(struct dma_info *di, uint direction, dma_addr_t pa)
+{
+	if (!di->aligndesc_4k) {
+		if (direction == DMA_TX)
+			di->xmtptrbase = pa;
+		else
+			di->rcvptrbase = pa;
+	}
+
+	if ((di->ddoffsetlow == 0)
+	    || !(pa & PCI32ADDR_HIGH)) {
+		if (direction == DMA_TX) {
+			bcma_write32(di->core, DMA64TXREGOFFS(di, addrlow),
+				     pa + di->ddoffsetlow);
+			bcma_write32(di->core, DMA64TXREGOFFS(di, addrhigh),
+				     di->ddoffsethigh);
+		} else {
+			bcma_write32(di->core, DMA64RXREGOFFS(di, addrlow),
+				     pa + di->ddoffsetlow);
+			bcma_write32(di->core, DMA64RXREGOFFS(di, addrhigh),
+				     di->ddoffsethigh);
+		}
+	} else {
+		/* DMA64 32bits address extension */
+		u32 ae;
+
+		/* shift the high bit(s) from pa to ae */
+		ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT;
+		pa &= ~PCI32ADDR_HIGH;
+
+		if (direction == DMA_TX) {
+			bcma_write32(di->core, DMA64TXREGOFFS(di, addrlow),
+				     pa + di->ddoffsetlow);
+			bcma_write32(di->core, DMA64TXREGOFFS(di, addrhigh),
+				     di->ddoffsethigh);
+			bcma_maskset32(di->core, DMA64TXREGOFFS(di, control),
+				       D64_XC_AE, (ae << D64_XC_AE_SHIFT));
+		} else {
+			bcma_write32(di->core, DMA64RXREGOFFS(di, addrlow),
+				     pa + di->ddoffsetlow);
+			bcma_write32(di->core, DMA64RXREGOFFS(di, addrhigh),
+				     di->ddoffsethigh);
+			bcma_maskset32(di->core, DMA64RXREGOFFS(di, control),
+				       D64_RC_AE, (ae << D64_RC_AE_SHIFT));
+		}
+	}
+}
+
+static void _dma_rxenable(struct dma_info *di)
+{
+	uint dmactrlflags = di->dma.dmactrlflags;
+	u32 control;
+
+	brcms_dbg_dma(di->core, "%s:\n", di->name);
+
+	control = D64_RC_RE | (bcma_read32(di->core,
+					   DMA64RXREGOFFS(di, control)) &
+			       D64_RC_AE);
+
+	if ((dmactrlflags & DMA_CTRL_PEN) == 0)
+		control |= D64_RC_PD;
+
+	if (dmactrlflags & DMA_CTRL_ROC)
+		control |= D64_RC_OC;
+
+	bcma_write32(di->core, DMA64RXREGOFFS(di, control),
+		((di->rxoffset << D64_RC_RO_SHIFT) | control));
+}
+
+void dma_rxinit(struct dma_pub *pub)
+{
+	struct dma_info *di = container_of(pub, struct dma_info, dma);
+
+	brcms_dbg_dma(di->core, "%s:\n", di->name);
+
+	if (di->nrxd == 0)
+		return;
+
+	di->rxin = di->rxout = 0;
+
+	/* clear rx descriptor ring */
+	memset(di->rxd64, '\0', di->nrxd * sizeof(struct dma64desc));
+
+	/* DMA engine with out alignment requirement requires table to be inited
+	 * before enabling the engine
+	 */
+	if (!di->aligndesc_4k)
+		_dma_ddtable_init(di, DMA_RX, di->rxdpa);
+
+	_dma_rxenable(di);
+
+	if (di->aligndesc_4k)
+		_dma_ddtable_init(di, DMA_RX, di->rxdpa);
+}
+
+static struct sk_buff *dma64_getnextrxp(struct dma_info *di, bool forceall)
+{
+	uint i, curr;
+	struct sk_buff *rxp;
+	dma_addr_t pa;
+
+	i = di->rxin;
+
+	/* return if no packets posted */
+	if (i == di->rxout)
+		return NULL;
+
+	curr =
+	    B2I(((bcma_read32(di->core,
+			      DMA64RXREGOFFS(di, status0)) & D64_RS0_CD_MASK) -
+		 di->rcvptrbase) & D64_RS0_CD_MASK, struct dma64desc);
+
+	/* ignore curr if forceall */
+	if (!forceall && (i == curr))
+		return NULL;
+
+	/* get the packet pointer that corresponds to the rx descriptor */
+	rxp = di->rxp[i];
+	di->rxp[i] = NULL;
+
+	pa = le32_to_cpu(di->rxd64[i].addrlow) - di->dataoffsetlow;
+
+	/* clear this packet from the descriptor ring */
+	dma_unmap_single(di->dmadev, pa, di->rxbufsize, DMA_FROM_DEVICE);
+
+	di->rxd64[i].addrlow = cpu_to_le32(0xdeadbeef);
+	di->rxd64[i].addrhigh = cpu_to_le32(0xdeadbeef);
+
+	di->rxin = nextrxd(di, i);
+
+	return rxp;
+}
+
+static struct sk_buff *_dma_getnextrxp(struct dma_info *di, bool forceall)
+{
+	if (di->nrxd == 0)
+		return NULL;
+
+	return dma64_getnextrxp(di, forceall);
+}
+
+/*
+ * !! rx entry routine
+ * returns the number packages in the next frame, or 0 if there are no more
+ *   if DMA_CTRL_RXMULTI is defined, DMA scattering(multiple buffers) is
+ *   supported with pkts chain
+ *   otherwise, it's treated as giant pkt and will be tossed.
+ *   The DMA scattering starts with normal DMA header, followed by first
+ *   buffer data. After it reaches the max size of buffer, the data continues
+ *   in next DMA descriptor buffer WITHOUT DMA header
+ */
+int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list)
+{
+	struct dma_info *di = container_of(pub, struct dma_info, dma);
+	struct sk_buff_head dma_frames;
+	struct sk_buff *p, *next;
+	uint len;
+	uint pkt_len;
+	int resid = 0;
+	int pktcnt = 1;
+
+	skb_queue_head_init(&dma_frames);
+ next_frame:
+	p = _dma_getnextrxp(di, false);
+	if (p == NULL)
+		return 0;
+
+	len = le16_to_cpu(*(__le16 *) (p->data));
+	brcms_dbg_dma(di->core, "%s: dma_rx len %d\n", di->name, len);
+	dma_spin_for_len(len, p);
+
+	/* set actual length */
+	pkt_len = min((di->rxoffset + len), di->rxbufsize);
+	__skb_trim(p, pkt_len);
+	skb_queue_tail(&dma_frames, p);
+	resid = len - (di->rxbufsize - di->rxoffset);
+
+	/* check for single or multi-buffer rx */
+	if (resid > 0) {
+		while ((resid > 0) && (p = _dma_getnextrxp(di, false))) {
+			pkt_len = min_t(uint, resid, di->rxbufsize);
+			__skb_trim(p, pkt_len);
+			skb_queue_tail(&dma_frames, p);
+			resid -= di->rxbufsize;
+			pktcnt++;
+		}
+
+#ifdef DEBUG
+		if (resid > 0) {
+			uint cur;
+			cur =
+			    B2I(((bcma_read32(di->core,
+					      DMA64RXREGOFFS(di, status0)) &
+				  D64_RS0_CD_MASK) - di->rcvptrbase) &
+				D64_RS0_CD_MASK, struct dma64desc);
+			brcms_dbg_dma(di->core,
+				      "rxin %d rxout %d, hw_curr %d\n",
+				      di->rxin, di->rxout, cur);
+		}
+#endif				/* DEBUG */
+
+		if ((di->dma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) {
+			brcms_dbg_dma(di->core, "%s: bad frame length (%d)\n",
+				      di->name, len);
+			skb_queue_walk_safe(&dma_frames, p, next) {
+				skb_unlink(p, &dma_frames);
+				brcmu_pkt_buf_free_skb(p);
+			}
+			di->dma.rxgiants++;
+			pktcnt = 1;
+			goto next_frame;
+		}
+	}
+
+	skb_queue_splice_tail(&dma_frames, skb_list);
+	return pktcnt;
+}
+
+static bool dma64_rxidle(struct dma_info *di)
+{
+	brcms_dbg_dma(di->core, "%s:\n", di->name);
+
+	if (di->nrxd == 0)
+		return true;
+
+	return ((bcma_read32(di->core,
+			     DMA64RXREGOFFS(di, status0)) & D64_RS0_CD_MASK) ==
+		(bcma_read32(di->core, DMA64RXREGOFFS(di, ptr)) &
+		 D64_RS0_CD_MASK));
+}
+
+static bool dma64_txidle(struct dma_info *di)
+{
+	if (di->ntxd == 0)
+		return true;
+
+	return ((bcma_read32(di->core,
+			     DMA64TXREGOFFS(di, status0)) & D64_XS0_CD_MASK) ==
+		(bcma_read32(di->core, DMA64TXREGOFFS(di, ptr)) &
+		 D64_XS0_CD_MASK));
+}
+
+/*
+ * post receive buffers
+ *  Return false if refill failed completely or dma mapping failed. The ring
+ *  is empty, which will stall the rx dma and user might want to call rxfill
+ *  again asap. This is unlikely to happen on a memory-rich NIC, but often on
+ *  memory-constrained dongle.
+ */
+bool dma_rxfill(struct dma_pub *pub)
+{
+	struct dma_info *di = container_of(pub, struct dma_info, dma);
+	struct sk_buff *p;
+	u16 rxin, rxout;
+	u32 flags = 0;
+	uint n;
+	uint i;
+	dma_addr_t pa;
+	uint extra_offset = 0;
+	bool ring_empty;
+
+	ring_empty = false;
+
+	/*
+	 * Determine how many receive buffers we're lacking
+	 * from the full complement, allocate, initialize,
+	 * and post them, then update the chip rx lastdscr.
+	 */
+
+	rxin = di->rxin;
+	rxout = di->rxout;
+
+	n = di->nrxpost - nrxdactive(di, rxin, rxout);
+
+	brcms_dbg_dma(di->core, "%s: post %d\n", di->name, n);
+
+	if (di->rxbufsize > BCMEXTRAHDROOM)
+		extra_offset = di->rxextrahdrroom;
+
+	for (i = 0; i < n; i++) {
+		/*
+		 * the di->rxbufsize doesn't include the extra headroom,
+		 * we need to add it to the size to be allocated
+		 */
+		p = brcmu_pkt_buf_get_skb(di->rxbufsize + extra_offset);
+
+		if (p == NULL) {
+			brcms_dbg_dma(di->core, "%s: out of rxbufs\n",
+				      di->name);
+			if (i == 0 && dma64_rxidle(di)) {
+				brcms_dbg_dma(di->core, "%s: ring is empty !\n",
+					      di->name);
+				ring_empty = true;
+			}
+			di->dma.rxnobuf++;
+			break;
+		}
+		/* reserve an extra headroom, if applicable */
+		if (extra_offset)
+			skb_pull(p, extra_offset);
+
+		/* Do a cached write instead of uncached write since DMA_MAP
+		 * will flush the cache.
+		 */
+		*(u32 *) (p->data) = 0;
+
+		pa = dma_map_single(di->dmadev, p->data, di->rxbufsize,
+				    DMA_FROM_DEVICE);
+		if (dma_mapping_error(di->dmadev, pa)) {
+			brcmu_pkt_buf_free_skb(p);
+			return false;
+		}
+
+		/* save the free packet pointer */
+		di->rxp[rxout] = p;
+
+		/* reset flags for each descriptor */
+		flags = 0;
+		if (rxout == (di->nrxd - 1))
+			flags = D64_CTRL1_EOT;
+
+		dma64_dd_upd(di, di->rxd64, pa, rxout, &flags,
+			     di->rxbufsize);
+		rxout = nextrxd(di, rxout);
+	}
+
+	di->rxout = rxout;
+
+	/* update the chip lastdscr pointer */
+	bcma_write32(di->core, DMA64RXREGOFFS(di, ptr),
+	      di->rcvptrbase + I2B(rxout, struct dma64desc));
+
+	return ring_empty;
+}
+
+void dma_rxreclaim(struct dma_pub *pub)
+{
+	struct dma_info *di = container_of(pub, struct dma_info, dma);
+	struct sk_buff *p;
+
+	brcms_dbg_dma(di->core, "%s:\n", di->name);
+
+	while ((p = _dma_getnextrxp(di, true)))
+		brcmu_pkt_buf_free_skb(p);
+}
+
+void dma_counterreset(struct dma_pub *pub)
+{
+	/* reset all software counters */
+	pub->rxgiants = 0;
+	pub->rxnobuf = 0;
+	pub->txnobuf = 0;
+}
+
+/* get the address of the var in order to change later */
+unsigned long dma_getvar(struct dma_pub *pub, const char *name)
+{
+	struct dma_info *di = container_of(pub, struct dma_info, dma);
+
+	if (!strcmp(name, "&txavail"))
+		return (unsigned long)&(di->dma.txavail);
+	return 0;
+}
+
+/* 64-bit DMA functions */
+
+void dma_txinit(struct dma_pub *pub)
+{
+	struct dma_info *di = container_of(pub, struct dma_info, dma);
+	u32 control = D64_XC_XE;
+
+	brcms_dbg_dma(di->core, "%s:\n", di->name);
+
+	if (di->ntxd == 0)
+		return;
+
+	di->txin = di->txout = 0;
+	di->dma.txavail = di->ntxd - 1;
+
+	/* clear tx descriptor ring */
+	memset(di->txd64, '\0', (di->ntxd * sizeof(struct dma64desc)));
+
+	/* DMA engine with out alignment requirement requires table to be inited
+	 * before enabling the engine
+	 */
+	if (!di->aligndesc_4k)
+		_dma_ddtable_init(di, DMA_TX, di->txdpa);
+
+	if ((di->dma.dmactrlflags & DMA_CTRL_PEN) == 0)
+		control |= D64_XC_PD;
+	bcma_set32(di->core, DMA64TXREGOFFS(di, control), control);
+
+	/* DMA engine with alignment requirement requires table to be inited
+	 * before enabling the engine
+	 */
+	if (di->aligndesc_4k)
+		_dma_ddtable_init(di, DMA_TX, di->txdpa);
+}
+
+void dma_txsuspend(struct dma_pub *pub)
+{
+	struct dma_info *di = container_of(pub, struct dma_info, dma);
+
+	brcms_dbg_dma(di->core, "%s:\n", di->name);
+
+	if (di->ntxd == 0)
+		return;
+
+	bcma_set32(di->core, DMA64TXREGOFFS(di, control), D64_XC_SE);
+}
+
+void dma_txresume(struct dma_pub *pub)
+{
+	struct dma_info *di = container_of(pub, struct dma_info, dma);
+
+	brcms_dbg_dma(di->core, "%s:\n", di->name);
+
+	if (di->ntxd == 0)
+		return;
+
+	bcma_mask32(di->core, DMA64TXREGOFFS(di, control), ~D64_XC_SE);
+}
+
+bool dma_txsuspended(struct dma_pub *pub)
+{
+	struct dma_info *di = container_of(pub, struct dma_info, dma);
+
+	return (di->ntxd == 0) ||
+	       ((bcma_read32(di->core,
+			     DMA64TXREGOFFS(di, control)) & D64_XC_SE) ==
+		D64_XC_SE);
+}
+
+void dma_txreclaim(struct dma_pub *pub, enum txd_range range)
+{
+	struct dma_info *di = container_of(pub, struct dma_info, dma);
+	struct sk_buff *p;
+
+	brcms_dbg_dma(di->core, "%s: %s\n",
+		      di->name,
+		      range == DMA_RANGE_ALL ? "all" :
+		      range == DMA_RANGE_TRANSMITTED ? "transmitted" :
+		      "transferred");
+
+	if (di->txin == di->txout)
+		return;
+
+	while ((p = dma_getnexttxp(pub, range))) {
+		/* For unframed data, we don't have any packets to free */
+		if (!(di->dma.dmactrlflags & DMA_CTRL_UNFRAMED))
+			brcmu_pkt_buf_free_skb(p);
+	}
+}
+
+bool dma_txreset(struct dma_pub *pub)
+{
+	struct dma_info *di = container_of(pub, struct dma_info, dma);
+	u32 status;
+
+	if (di->ntxd == 0)
+		return true;
+
+	/* suspend tx DMA first */
+	bcma_write32(di->core, DMA64TXREGOFFS(di, control), D64_XC_SE);
+	SPINWAIT(((status =
+		   (bcma_read32(di->core, DMA64TXREGOFFS(di, status0)) &
+		    D64_XS0_XS_MASK)) != D64_XS0_XS_DISABLED) &&
+		  (status != D64_XS0_XS_IDLE) && (status != D64_XS0_XS_STOPPED),
+		 10000);
+
+	bcma_write32(di->core, DMA64TXREGOFFS(di, control), 0);
+	SPINWAIT(((status =
+		   (bcma_read32(di->core, DMA64TXREGOFFS(di, status0)) &
+		    D64_XS0_XS_MASK)) != D64_XS0_XS_DISABLED), 10000);
+
+	/* wait for the last transaction to complete */
+	udelay(300);
+
+	return status == D64_XS0_XS_DISABLED;
+}
+
+bool dma_rxreset(struct dma_pub *pub)
+{
+	struct dma_info *di = container_of(pub, struct dma_info, dma);
+	u32 status;
+
+	if (di->nrxd == 0)
+		return true;
+
+	bcma_write32(di->core, DMA64RXREGOFFS(di, control), 0);
+	SPINWAIT(((status =
+		   (bcma_read32(di->core, DMA64RXREGOFFS(di, status0)) &
+		    D64_RS0_RS_MASK)) != D64_RS0_RS_DISABLED), 10000);
+
+	return status == D64_RS0_RS_DISABLED;
+}
+
+static void dma_txenq(struct dma_info *di, struct sk_buff *p)
+{
+	unsigned char *data;
+	uint len;
+	u16 txout;
+	u32 flags = 0;
+	dma_addr_t pa;
+
+	txout = di->txout;
+
+	if (WARN_ON(nexttxd(di, txout) == di->txin))
+		return;
+
+	/*
+	 * obtain and initialize transmit descriptor entry.
+	 */
+	data = p->data;
+	len = p->len;
+
+	/* get physical address of buffer start */
+	pa = dma_map_single(di->dmadev, data, len, DMA_TO_DEVICE);
+	/* if mapping failed, free skb */
+	if (dma_mapping_error(di->dmadev, pa)) {
+		brcmu_pkt_buf_free_skb(p);
+		return;
+	}
+	/* With a DMA segment list, Descriptor table is filled
+	 * using the segment list instead of looping over
+	 * buffers in multi-chain DMA. Therefore, EOF for SGLIST
+	 * is when end of segment list is reached.
+	 */
+	flags = D64_CTRL1_SOF | D64_CTRL1_IOC | D64_CTRL1_EOF;
+	if (txout == (di->ntxd - 1))
+		flags |= D64_CTRL1_EOT;
+
+	dma64_dd_upd(di, di->txd64, pa, txout, &flags, len);
+
+	txout = nexttxd(di, txout);
+
+	/* save the packet */
+	di->txp[prevtxd(di, txout)] = p;
+
+	/* bump the tx descriptor index */
+	di->txout = txout;
+}
+
+static void ampdu_finalize(struct dma_info *di)
+{
+	struct brcms_ampdu_session *session = &di->ampdu_session;
+	struct sk_buff *p;
+
+	trace_brcms_ampdu_session(&session->wlc->hw->d11core->dev,
+				  session->max_ampdu_len,
+				  session->max_ampdu_frames,
+				  session->ampdu_len,
+				  skb_queue_len(&session->skb_list),
+				  session->dma_len);
+
+	if (WARN_ON(skb_queue_empty(&session->skb_list)))
+		return;
+
+	brcms_c_ampdu_finalize(session);
+
+	while (!skb_queue_empty(&session->skb_list)) {
+		p = skb_dequeue(&session->skb_list);
+		dma_txenq(di, p);
+	}
+
+	bcma_write32(di->core, DMA64TXREGOFFS(di, ptr),
+		     di->xmtptrbase + I2B(di->txout, struct dma64desc));
+	brcms_c_ampdu_reset_session(session, session->wlc);
+}
+
+static void prep_ampdu_frame(struct dma_info *di, struct sk_buff *p)
+{
+	struct brcms_ampdu_session *session = &di->ampdu_session;
+	int ret;
+
+	ret = brcms_c_ampdu_add_frame(session, p);
+	if (ret == -ENOSPC) {
+		/*
+		 * AMPDU cannot accomodate this frame. Close out the in-
+		 * progress AMPDU session and start a new one.
+		 */
+		ampdu_finalize(di);
+		ret = brcms_c_ampdu_add_frame(session, p);
+	}
+
+	WARN_ON(ret);
+}
+
+/* Update count of available tx descriptors based on current DMA state */
+static void dma_update_txavail(struct dma_info *di)
+{
+	/*
+	 * Available space is number of descriptors less the number of
+	 * active descriptors and the number of queued AMPDU frames.
+	 */
+	di->dma.txavail = di->ntxd - ntxdactive(di, di->txin, di->txout) -
+			  skb_queue_len(&di->ampdu_session.skb_list) - 1;
+}
+
+/*
+ * !! tx entry routine
+ * WARNING: call must check the return value for error.
+ *   the error(toss frames) could be fatal and cause many subsequent hard
+ *   to debug problems
+ */
+int dma_txfast(struct brcms_c_info *wlc, struct dma_pub *pub,
+	       struct sk_buff *p)
+{
+	struct dma_info *di = container_of(pub, struct dma_info, dma);
+	struct brcms_ampdu_session *session = &di->ampdu_session;
+	struct ieee80211_tx_info *tx_info;
+	bool is_ampdu;
+
+	/* no use to transmit a zero length packet */
+	if (p->len == 0)
+		return 0;
+
+	/* return nonzero if out of tx descriptors */
+	if (di->dma.txavail == 0 || nexttxd(di, di->txout) == di->txin)
+		goto outoftxd;
+
+	tx_info = IEEE80211_SKB_CB(p);
+	is_ampdu = tx_info->flags & IEEE80211_TX_CTL_AMPDU;
+	if (is_ampdu)
+		prep_ampdu_frame(di, p);
+	else
+		dma_txenq(di, p);
+
+	/* tx flow control */
+	dma_update_txavail(di);
+
+	/* kick the chip */
+	if (is_ampdu) {
+		/*
+		 * Start sending data if we've got a full AMPDU, there's
+		 * no more space in the DMA ring, or the ring isn't
+		 * currently transmitting.
+		 */
+		if (skb_queue_len(&session->skb_list) == session->max_ampdu_frames ||
+		    di->dma.txavail == 0 || dma64_txidle(di))
+			ampdu_finalize(di);
+	} else {
+		bcma_write32(di->core, DMA64TXREGOFFS(di, ptr),
+			     di->xmtptrbase + I2B(di->txout, struct dma64desc));
+	}
+
+	return 0;
+
+ outoftxd:
+	brcms_dbg_dma(di->core, "%s: out of txds !!!\n", di->name);
+	brcmu_pkt_buf_free_skb(p);
+	di->dma.txavail = 0;
+	di->dma.txnobuf++;
+	return -ENOSPC;
+}
+
+void dma_txflush(struct dma_pub *pub)
+{
+	struct dma_info *di = container_of(pub, struct dma_info, dma);
+	struct brcms_ampdu_session *session = &di->ampdu_session;
+
+	if (!skb_queue_empty(&session->skb_list))
+		ampdu_finalize(di);
+}
+
+int dma_txpending(struct dma_pub *pub)
+{
+	struct dma_info *di = container_of(pub, struct dma_info, dma);
+	return ntxdactive(di, di->txin, di->txout);
+}
+
+/*
+ * If we have an active AMPDU session and are not transmitting,
+ * this function will force tx to start.
+ */
+void dma_kick_tx(struct dma_pub *pub)
+{
+	struct dma_info *di = container_of(pub, struct dma_info, dma);
+	struct brcms_ampdu_session *session = &di->ampdu_session;
+
+	if (!skb_queue_empty(&session->skb_list) && dma64_txidle(di))
+		ampdu_finalize(di);
+}
+
+/*
+ * Reclaim next completed txd (txds if using chained buffers) in the range
+ * specified and return associated packet.
+ * If range is DMA_RANGE_TRANSMITTED, reclaim descriptors that have be
+ * transmitted as noted by the hardware "CurrDescr" pointer.
+ * If range is DMA_RANGE_TRANSFERED, reclaim descriptors that have be
+ * transferred by the DMA as noted by the hardware "ActiveDescr" pointer.
+ * If range is DMA_RANGE_ALL, reclaim all txd(s) posted to the ring and
+ * return associated packet regardless of the value of hardware pointers.
+ */
+struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range)
+{
+	struct dma_info *di = container_of(pub, struct dma_info, dma);
+	u16 start, end, i;
+	u16 active_desc;
+	struct sk_buff *txp;
+
+	brcms_dbg_dma(di->core, "%s: %s\n",
+		      di->name,
+		      range == DMA_RANGE_ALL ? "all" :
+		      range == DMA_RANGE_TRANSMITTED ? "transmitted" :
+		      "transferred");
+
+	if (di->ntxd == 0)
+		return NULL;
+
+	txp = NULL;
+
+	start = di->txin;
+	if (range == DMA_RANGE_ALL)
+		end = di->txout;
+	else {
+		end = (u16) (B2I(((bcma_read32(di->core,
+					       DMA64TXREGOFFS(di, status0)) &
+				   D64_XS0_CD_MASK) - di->xmtptrbase) &
+				 D64_XS0_CD_MASK, struct dma64desc));
+
+		if (range == DMA_RANGE_TRANSFERED) {
+			active_desc =
+				(u16)(bcma_read32(di->core,
+						  DMA64TXREGOFFS(di, status1)) &
+				      D64_XS1_AD_MASK);
+			active_desc =
+			    (active_desc - di->xmtptrbase) & D64_XS0_CD_MASK;
+			active_desc = B2I(active_desc, struct dma64desc);
+			if (end != active_desc)
+				end = prevtxd(di, active_desc);
+		}
+	}
+
+	if ((start == 0) && (end > di->txout))
+		goto bogus;
+
+	for (i = start; i != end && !txp; i = nexttxd(di, i)) {
+		dma_addr_t pa;
+		uint size;
+
+		pa = le32_to_cpu(di->txd64[i].addrlow) - di->dataoffsetlow;
+
+		size =
+		    (le32_to_cpu(di->txd64[i].ctrl2) &
+		     D64_CTRL2_BC_MASK);
+
+		di->txd64[i].addrlow = cpu_to_le32(0xdeadbeef);
+		di->txd64[i].addrhigh = cpu_to_le32(0xdeadbeef);
+
+		txp = di->txp[i];
+		di->txp[i] = NULL;
+
+		dma_unmap_single(di->dmadev, pa, size, DMA_TO_DEVICE);
+	}
+
+	di->txin = i;
+
+	/* tx flow control */
+	dma_update_txavail(di);
+
+	return txp;
+
+ bogus:
+	brcms_dbg_dma(di->core, "bogus curr: start %d end %d txout %d\n",
+		      start, end, di->txout);
+	return NULL;
+}
+
+/*
+ * Mac80211 initiated actions sometimes require packets in the DMA queue to be
+ * modified. The modified portion of the packet is not under control of the DMA
+ * engine. This function calls a caller-supplied function for each packet in
+ * the caller specified dma chain.
+ */
+void dma_walk_packets(struct dma_pub *dmah, void (*callback_fnc)
+		      (void *pkt, void *arg_a), void *arg_a)
+{
+	struct dma_info *di = container_of(dmah, struct dma_info, dma);
+	uint i =   di->txin;
+	uint end = di->txout;
+	struct sk_buff *skb;
+	struct ieee80211_tx_info *tx_info;
+
+	while (i != end) {
+		skb = di->txp[i];
+		if (skb != NULL) {
+			tx_info = (struct ieee80211_tx_info *)skb->cb;
+			(callback_fnc)(tx_info, arg_a);
+		}
+		i = nexttxd(di, i);
+	}
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.h
new file mode 100644
index 0000000..ff5b80b
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_BRCM_DMA_H_
+#define	_BRCM_DMA_H_
+
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+#include "types.h"		/* forward structure declarations */
+
+/* map/unmap direction */
+#define	DMA_TX	1		/* TX direction for DMA */
+#define	DMA_RX	2		/* RX direction for DMA */
+
+/* DMA structure:
+ *  support two DMA engines: 32 bits address or 64 bit addressing
+ *  basic DMA register set is per channel(transmit or receive)
+ *  a pair of channels is defined for convenience
+ */
+
+/* 32 bits addressing */
+
+struct dma32diag {	/* diag access */
+	u32 fifoaddr;	/* diag address */
+	u32 fifodatalow;	/* low 32bits of data */
+	u32 fifodatahigh;	/* high 32bits of data */
+	u32 pad;		/* reserved */
+};
+
+/* 64 bits addressing */
+
+/* dma registers per channel(xmt or rcv) */
+struct dma64regs {
+	u32 control;	/* enable, et al */
+	u32 ptr;	/* last descriptor posted to chip */
+	u32 addrlow;	/* desc ring base address low 32-bits (8K aligned) */
+	u32 addrhigh;	/* desc ring base address bits 63:32 (8K aligned) */
+	u32 status0;	/* current descriptor, xmt state */
+	u32 status1;	/* active descriptor, xmt error */
+};
+
+/* range param for dma_getnexttxp() and dma_txreclaim */
+enum txd_range {
+	DMA_RANGE_ALL = 1,
+	DMA_RANGE_TRANSMITTED,
+	DMA_RANGE_TRANSFERED
+};
+
+/*
+ * Exported data structure (read-only)
+ */
+/* export structure */
+struct dma_pub {
+	uint txavail;		/* # free tx descriptors */
+	uint dmactrlflags;	/* dma control flags */
+
+	/* rx error counters */
+	uint rxgiants;		/* rx giant frames */
+	uint rxnobuf;		/* rx out of dma descriptors */
+	/* tx error counters */
+	uint txnobuf;		/* tx out of dma descriptors */
+};
+
+extern struct dma_pub *dma_attach(char *name, struct brcms_c_info *wlc,
+				  uint txregbase, uint rxregbase,
+				  uint ntxd, uint nrxd,
+				  uint rxbufsize, int rxextheadroom,
+				  uint nrxpost, uint rxoffset);
+
+void dma_rxinit(struct dma_pub *pub);
+int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list);
+bool dma_rxfill(struct dma_pub *pub);
+bool dma_rxreset(struct dma_pub *pub);
+bool dma_txreset(struct dma_pub *pub);
+void dma_txinit(struct dma_pub *pub);
+int dma_txfast(struct brcms_c_info *wlc, struct dma_pub *pub,
+	       struct sk_buff *p0);
+void dma_txflush(struct dma_pub *pub);
+int dma_txpending(struct dma_pub *pub);
+void dma_kick_tx(struct dma_pub *pub);
+void dma_txsuspend(struct dma_pub *pub);
+bool dma_txsuspended(struct dma_pub *pub);
+void dma_txresume(struct dma_pub *pub);
+void dma_txreclaim(struct dma_pub *pub, enum txd_range range);
+void dma_rxreclaim(struct dma_pub *pub);
+void dma_detach(struct dma_pub *pub);
+unsigned long dma_getvar(struct dma_pub *pub, const char *name);
+struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range);
+void dma_counterreset(struct dma_pub *pub);
+
+void dma_walk_packets(struct dma_pub *dmah, void (*callback_fnc)
+		      (void *pkt, void *arg_a), void *arg_a);
+
+/*
+ * DMA(Bug) on bcm47xx chips seems to declare that the packet is ready, but
+ * the packet length is not updated yet (by DMA) on the expected time.
+ * Workaround is to hold processor till DMA updates the length, and stay off
+ * the bus to allow DMA update the length in buffer
+ */
+static inline void dma_spin_for_len(uint len, struct sk_buff *head)
+{
+#if defined(CONFIG_BCM47XX)
+	if (!len) {
+		while (!(len = *(u16 *) KSEG1ADDR(head->data)))
+			udelay(1);
+
+		*(u16 *) (head->data) = cpu_to_le16((u16) len);
+	}
+#endif				/* defined(CONFIG_BCM47XX) */
+}
+
+#endif				/* _BRCM_DMA_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.c
new file mode 100644
index 0000000..c0a5449
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.c
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <net/mac80211.h>
+#include <linux/bcma/bcma_driver_chipcommon.h>
+#include <linux/gpio.h>
+
+#include "mac80211_if.h"
+#include "pub.h"
+#include "main.h"
+#include "led.h"
+
+	/* number of leds */
+#define  BRCMS_LED_NO		4
+	/* behavior mask */
+#define  BRCMS_LED_BEH_MASK	0x7f
+	/* activelow (polarity) bit */
+#define  BRCMS_LED_AL_MASK	0x80
+	/* radio enabled */
+#define  BRCMS_LED_RADIO	3
+
+static void brcms_radio_led_ctrl(struct brcms_info *wl, bool state)
+{
+	if (wl->radio_led.gpio == -1)
+		return;
+
+	if (wl->radio_led.active_low)
+		state = !state;
+
+	if (state)
+		gpio_set_value(wl->radio_led.gpio, 1);
+	else
+		gpio_set_value(wl->radio_led.gpio, 0);
+}
+
+
+/* Callback from the LED subsystem. */
+static void brcms_led_brightness_set(struct led_classdev *led_dev,
+				   enum led_brightness brightness)
+{
+	struct brcms_info *wl = container_of(led_dev,
+		struct brcms_info, led_dev);
+	brcms_radio_led_ctrl(wl, brightness);
+}
+
+void brcms_led_unregister(struct brcms_info *wl)
+{
+	if (wl->led_dev.dev)
+		led_classdev_unregister(&wl->led_dev);
+	if (wl->radio_led.gpio != -1)
+		gpio_free(wl->radio_led.gpio);
+}
+
+int brcms_led_register(struct brcms_info *wl)
+{
+	int i, err;
+	struct brcms_led *radio_led = &wl->radio_led;
+	/* get CC core */
+	struct bcma_drv_cc *cc_drv  = &wl->wlc->hw->d11core->bus->drv_cc;
+	struct gpio_chip *bcma_gpio = &cc_drv->gpio;
+	struct ssb_sprom *sprom = &wl->wlc->hw->d11core->bus->sprom;
+	u8 *leds[] = { &sprom->gpio0,
+		&sprom->gpio1,
+		&sprom->gpio2,
+		&sprom->gpio3 };
+	unsigned gpio = -1;
+	bool active_low = false;
+
+	/* none by default */
+	radio_led->gpio = -1;
+	radio_led->active_low = false;
+
+	if (!bcma_gpio || !gpio_is_valid(bcma_gpio->base))
+		return -ENODEV;
+
+	/* find radio enabled LED */
+	for (i = 0; i < BRCMS_LED_NO; i++) {
+		u8 led = *leds[i];
+		if ((led & BRCMS_LED_BEH_MASK) == BRCMS_LED_RADIO) {
+			gpio = bcma_gpio->base + i;
+			if (led & BRCMS_LED_AL_MASK)
+				active_low = true;
+			break;
+		}
+	}
+
+	if (gpio == -1 || !gpio_is_valid(gpio))
+		return -ENODEV;
+
+	/* request and configure LED gpio */
+	err = gpio_request_one(gpio,
+				active_low ? GPIOF_OUT_INIT_HIGH
+					: GPIOF_OUT_INIT_LOW,
+				"radio on");
+	if (err) {
+		wiphy_err(wl->wiphy, "requesting led gpio %d failed (err: %d)\n",
+			  gpio, err);
+		return err;
+	}
+	err = gpio_direction_output(gpio, 1);
+	if (err) {
+		wiphy_err(wl->wiphy, "cannot set led gpio %d to output (err: %d)\n",
+			  gpio, err);
+		return err;
+	}
+
+	snprintf(wl->radio_led.name, sizeof(wl->radio_led.name),
+		 "brcmsmac-%s:radio", wiphy_name(wl->wiphy));
+
+	wl->led_dev.name = wl->radio_led.name;
+	wl->led_dev.default_trigger =
+		ieee80211_get_radio_led_name(wl->pub->ieee_hw);
+	wl->led_dev.brightness_set = brcms_led_brightness_set;
+	err = led_classdev_register(wiphy_dev(wl->wiphy), &wl->led_dev);
+
+	if (err) {
+		wiphy_err(wl->wiphy, "cannot register led device: %s (err: %d)\n",
+			  wl->radio_led.name, err);
+		return err;
+	}
+
+	wiphy_info(wl->wiphy, "registered radio enabled led device: %s gpio: %d\n",
+		   wl->radio_led.name,
+		   gpio);
+	radio_led->gpio = gpio;
+	radio_led->active_low = active_low;
+
+	return 0;
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.h
new file mode 100644
index 0000000..17a0b1f
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_LED_H_
+#define _BRCM_LED_H_
+struct brcms_led {
+	char name[32];
+	unsigned gpio;
+	bool active_low;
+};
+
+#ifdef CONFIG_BCMA_DRIVER_GPIO
+void brcms_led_unregister(struct brcms_info *wl);
+int brcms_led_register(struct brcms_info *wl);
+#else
+static inline void brcms_led_unregister(struct brcms_info *wl) {};
+static inline int brcms_led_register(struct brcms_info *wl)
+{
+	return -ENOTSUPP;
+};
+#endif
+
+#endif /* _BRCM_LED_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
new file mode 100644
index 0000000..ecc89e7
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
@@ -0,0 +1,1704 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ * Copyright (c) 2013 Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define __UNDEF_NO_VERSION__
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/etherdevice.h>
+#include <linux/sched.h>
+#include <linux/firmware.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/bcma/bcma.h>
+#include <net/mac80211.h>
+#include <defs.h>
+#include "phy/phy_int.h"
+#include "d11.h"
+#include "channel.h"
+#include "scb.h"
+#include "pub.h"
+#include "ucode_loader.h"
+#include "mac80211_if.h"
+#include "main.h"
+#include "debug.h"
+#include "led.h"
+
+#define N_TX_QUEUES	4 /* #tx queues on mac80211<->driver interface */
+#define BRCMS_FLUSH_TIMEOUT	500 /* msec */
+
+/* Flags we support */
+#define MAC_FILTERS (FIF_ALLMULTI | \
+	FIF_FCSFAIL | \
+	FIF_CONTROL | \
+	FIF_OTHER_BSS | \
+	FIF_BCN_PRBRESP_PROMISC | \
+	FIF_PSPOLL)
+
+#define CHAN2GHZ(channel, freqency, chflags)  { \
+	.band = NL80211_BAND_2GHZ, \
+	.center_freq = (freqency), \
+	.hw_value = (channel), \
+	.flags = chflags, \
+	.max_antenna_gain = 0, \
+	.max_power = 19, \
+}
+
+#define CHAN5GHZ(channel, chflags)  { \
+	.band = NL80211_BAND_5GHZ, \
+	.center_freq = 5000 + 5*(channel), \
+	.hw_value = (channel), \
+	.flags = chflags, \
+	.max_antenna_gain = 0, \
+	.max_power = 21, \
+}
+
+#define RATE(rate100m, _flags) { \
+	.bitrate = (rate100m), \
+	.flags = (_flags), \
+	.hw_value = (rate100m / 5), \
+}
+
+struct firmware_hdr {
+	__le32 offset;
+	__le32 len;
+	__le32 idx;
+};
+
+static const char * const brcms_firmwares[MAX_FW_IMAGES] = {
+	"brcm/bcm43xx",
+	NULL
+};
+
+static int n_adapters_found;
+
+MODULE_AUTHOR("Broadcom Corporation");
+MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver.");
+MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards");
+MODULE_LICENSE("Dual BSD/GPL");
+/* This needs to be adjusted when brcms_firmwares changes */
+MODULE_FIRMWARE("brcm/bcm43xx-0.fw");
+MODULE_FIRMWARE("brcm/bcm43xx_hdr-0.fw");
+
+/* recognized BCMA Core IDs */
+static struct bcma_device_id brcms_coreid_table[] = {
+	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 17, BCMA_ANY_CLASS),
+	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 23, BCMA_ANY_CLASS),
+	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 24, BCMA_ANY_CLASS),
+	{},
+};
+MODULE_DEVICE_TABLE(bcma, brcms_coreid_table);
+
+#if defined(CONFIG_BRCMDBG)
+/*
+ * Module parameter for setting the debug message level. Available
+ * flags are specified by the BRCM_DL_* macros in
+ * drivers/net/wireless/brcm80211/include/defs.h.
+ */
+module_param_named(debug, brcm_msg_level, uint, 0644);
+#endif
+
+static struct ieee80211_channel brcms_2ghz_chantable[] = {
+	CHAN2GHZ(1, 2412, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN2GHZ(2, 2417, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN2GHZ(3, 2422, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN2GHZ(4, 2427, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN2GHZ(5, 2432, 0),
+	CHAN2GHZ(6, 2437, 0),
+	CHAN2GHZ(7, 2442, 0),
+	CHAN2GHZ(8, 2447, IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN2GHZ(9, 2452, IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN2GHZ(10, 2457, IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN2GHZ(11, 2462, IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN2GHZ(12, 2467,
+		 IEEE80211_CHAN_NO_IR |
+		 IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN2GHZ(13, 2472,
+		 IEEE80211_CHAN_NO_IR |
+		 IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN2GHZ(14, 2484,
+		 IEEE80211_CHAN_NO_IR |
+		 IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS |
+		 IEEE80211_CHAN_NO_OFDM)
+};
+
+static struct ieee80211_channel brcms_5ghz_nphy_chantable[] = {
+	/* UNII-1 */
+	CHAN5GHZ(36, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(40, IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(44, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(48, IEEE80211_CHAN_NO_HT40PLUS),
+	/* UNII-2 */
+	CHAN5GHZ(52,
+		 IEEE80211_CHAN_RADAR |
+		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(56,
+		 IEEE80211_CHAN_RADAR |
+		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(60,
+		 IEEE80211_CHAN_RADAR |
+		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(64,
+		 IEEE80211_CHAN_RADAR |
+		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),
+	/* MID */
+	CHAN5GHZ(100,
+		 IEEE80211_CHAN_RADAR |
+		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(104,
+		 IEEE80211_CHAN_RADAR |
+		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(108,
+		 IEEE80211_CHAN_RADAR |
+		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(112,
+		 IEEE80211_CHAN_RADAR |
+		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(116,
+		 IEEE80211_CHAN_RADAR |
+		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(120,
+		 IEEE80211_CHAN_RADAR |
+		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(124,
+		 IEEE80211_CHAN_RADAR |
+		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(128,
+		 IEEE80211_CHAN_RADAR |
+		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(132,
+		 IEEE80211_CHAN_RADAR |
+		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(136,
+		 IEEE80211_CHAN_RADAR |
+		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(140,
+		 IEEE80211_CHAN_RADAR |
+		 IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_NO_HT40PLUS |
+		 IEEE80211_CHAN_NO_HT40MINUS),
+	/* UNII-3 */
+	CHAN5GHZ(149, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(153, IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(157, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(161, IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(165, IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
+};
+
+/*
+ * The rate table is used for both 2.4G and 5G rates. The
+ * latter being a subset as it does not support CCK rates.
+ */
+static struct ieee80211_rate legacy_ratetable[] = {
+	RATE(10, 0),
+	RATE(20, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATE(55, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATE(110, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATE(60, 0),
+	RATE(90, 0),
+	RATE(120, 0),
+	RATE(180, 0),
+	RATE(240, 0),
+	RATE(360, 0),
+	RATE(480, 0),
+	RATE(540, 0),
+};
+
+static const struct ieee80211_supported_band brcms_band_2GHz_nphy_template = {
+	.band = NL80211_BAND_2GHZ,
+	.channels = brcms_2ghz_chantable,
+	.n_channels = ARRAY_SIZE(brcms_2ghz_chantable),
+	.bitrates = legacy_ratetable,
+	.n_bitrates = ARRAY_SIZE(legacy_ratetable),
+	.ht_cap = {
+		   /* from include/linux/ieee80211.h */
+		   .cap = IEEE80211_HT_CAP_GRN_FLD |
+			  IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40,
+		   .ht_supported = true,
+		   .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
+		   .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
+		   .mcs = {
+			   /* placeholders for now */
+			   .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
+			   .rx_highest = cpu_to_le16(500),
+			   .tx_params = IEEE80211_HT_MCS_TX_DEFINED}
+		   }
+};
+
+static const struct ieee80211_supported_band brcms_band_5GHz_nphy_template = {
+	.band = NL80211_BAND_5GHZ,
+	.channels = brcms_5ghz_nphy_chantable,
+	.n_channels = ARRAY_SIZE(brcms_5ghz_nphy_chantable),
+	.bitrates = legacy_ratetable + BRCMS_LEGACY_5G_RATE_OFFSET,
+	.n_bitrates = ARRAY_SIZE(legacy_ratetable) -
+			BRCMS_LEGACY_5G_RATE_OFFSET,
+	.ht_cap = {
+		   .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 |
+			  IEEE80211_HT_CAP_SGI_40,
+		   .ht_supported = true,
+		   .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
+		   .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
+		   .mcs = {
+			   /* placeholders for now */
+			   .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
+			   .rx_highest = cpu_to_le16(500),
+			   .tx_params = IEEE80211_HT_MCS_TX_DEFINED}
+		   }
+};
+
+/* flags the given rate in rateset as requested */
+static void brcms_set_basic_rate(struct brcm_rateset *rs, u16 rate, bool is_br)
+{
+	u32 i;
+
+	for (i = 0; i < rs->count; i++) {
+		if (rate != (rs->rates[i] & 0x7f))
+			continue;
+
+		if (is_br)
+			rs->rates[i] |= BRCMS_RATE_FLAG;
+		else
+			rs->rates[i] &= BRCMS_RATE_MASK;
+		return;
+	}
+}
+
+/**
+ * This function frees the WL per-device resources.
+ *
+ * This function frees resources owned by the WL device pointed to
+ * by the wl parameter.
+ *
+ * precondition: can both be called locked and unlocked
+ *
+ */
+static void brcms_free(struct brcms_info *wl)
+{
+	struct brcms_timer *t, *next;
+
+	/* free ucode data */
+	if (wl->fw.fw_cnt)
+		brcms_ucode_data_free(&wl->ucode);
+	if (wl->irq)
+		free_irq(wl->irq, wl);
+
+	/* kill dpc */
+	tasklet_kill(&wl->tasklet);
+
+	if (wl->pub) {
+		brcms_debugfs_detach(wl->pub);
+		brcms_c_module_unregister(wl->pub, "linux", wl);
+	}
+
+	/* free common resources */
+	if (wl->wlc) {
+		brcms_c_detach(wl->wlc);
+		wl->wlc = NULL;
+		wl->pub = NULL;
+	}
+
+	/* virtual interface deletion is deferred so we cannot spinwait */
+
+	/* wait for all pending callbacks to complete */
+	while (atomic_read(&wl->callbacks) > 0)
+		schedule();
+
+	/* free timers */
+	for (t = wl->timers; t; t = next) {
+		next = t->next;
+#ifdef DEBUG
+		kfree(t->name);
+#endif
+		kfree(t);
+	}
+}
+
+/*
+* called from both kernel as from this kernel module (error flow on attach)
+* precondition: perimeter lock is not acquired.
+*/
+static void brcms_remove(struct bcma_device *pdev)
+{
+	struct ieee80211_hw *hw = bcma_get_drvdata(pdev);
+	struct brcms_info *wl = hw->priv;
+
+	if (wl->wlc) {
+		brcms_led_unregister(wl);
+		wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
+		wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
+		ieee80211_unregister_hw(hw);
+	}
+
+	brcms_free(wl);
+
+	bcma_set_drvdata(pdev, NULL);
+	ieee80211_free_hw(hw);
+}
+
+/*
+ * Precondition: Since this function is called in brcms_pci_probe() context,
+ * no locking is required.
+ */
+static void brcms_release_fw(struct brcms_info *wl)
+{
+	int i;
+	for (i = 0; i < MAX_FW_IMAGES; i++) {
+		release_firmware(wl->fw.fw_bin[i]);
+		release_firmware(wl->fw.fw_hdr[i]);
+	}
+}
+
+/*
+ * Precondition: Since this function is called in brcms_pci_probe() context,
+ * no locking is required.
+ */
+static int brcms_request_fw(struct brcms_info *wl, struct bcma_device *pdev)
+{
+	int status;
+	struct device *device = &pdev->dev;
+	char fw_name[100];
+	int i;
+
+	memset(&wl->fw, 0, sizeof(struct brcms_firmware));
+	for (i = 0; i < MAX_FW_IMAGES; i++) {
+		if (brcms_firmwares[i] == NULL)
+			break;
+		sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i],
+			UCODE_LOADER_API_VER);
+		status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
+		if (status) {
+			wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
+				  KBUILD_MODNAME, fw_name);
+			return status;
+		}
+		sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i],
+			UCODE_LOADER_API_VER);
+		status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
+		if (status) {
+			wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
+				  KBUILD_MODNAME, fw_name);
+			return status;
+		}
+		wl->fw.hdr_num_entries[i] =
+		    wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr));
+	}
+	wl->fw.fw_cnt = i;
+	status = brcms_ucode_data_init(wl, &wl->ucode);
+	brcms_release_fw(wl);
+	return status;
+}
+
+static void brcms_ops_tx(struct ieee80211_hw *hw,
+			 struct ieee80211_tx_control *control,
+			 struct sk_buff *skb)
+{
+	struct brcms_info *wl = hw->priv;
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+
+	spin_lock_bh(&wl->lock);
+	if (!wl->pub->up) {
+		brcms_err(wl->wlc->hw->d11core, "ops->tx called while down\n");
+		kfree_skb(skb);
+		goto done;
+	}
+	if (brcms_c_sendpkt_mac80211(wl->wlc, skb, hw))
+		tx_info->rate_driver_data[0] = control->sta;
+ done:
+	spin_unlock_bh(&wl->lock);
+}
+
+static int brcms_ops_start(struct ieee80211_hw *hw)
+{
+	struct brcms_info *wl = hw->priv;
+	bool blocked;
+	int err;
+
+	if (!wl->ucode.bcm43xx_bomminor) {
+		err = brcms_request_fw(wl, wl->wlc->hw->d11core);
+		if (err)
+			return -ENOENT;
+	}
+
+	ieee80211_wake_queues(hw);
+	spin_lock_bh(&wl->lock);
+	blocked = brcms_rfkill_set_hw_state(wl);
+	spin_unlock_bh(&wl->lock);
+	if (!blocked)
+		wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
+
+	spin_lock_bh(&wl->lock);
+	/* avoid acknowledging frames before a non-monitor device is added */
+	wl->mute_tx = true;
+
+	if (!wl->pub->up)
+		if (!blocked)
+			err = brcms_up(wl);
+		else
+			err = -ERFKILL;
+	else
+		err = -ENODEV;
+	spin_unlock_bh(&wl->lock);
+
+	if (err != 0)
+		brcms_err(wl->wlc->hw->d11core, "%s: brcms_up() returned %d\n",
+			  __func__, err);
+
+	bcma_core_pci_power_save(wl->wlc->hw->d11core->bus, true);
+	return err;
+}
+
+static void brcms_ops_stop(struct ieee80211_hw *hw)
+{
+	struct brcms_info *wl = hw->priv;
+	int status;
+
+	ieee80211_stop_queues(hw);
+
+	if (wl->wlc == NULL)
+		return;
+
+	spin_lock_bh(&wl->lock);
+	status = brcms_c_chipmatch(wl->wlc->hw->d11core);
+	spin_unlock_bh(&wl->lock);
+	if (!status) {
+		brcms_err(wl->wlc->hw->d11core,
+			  "wl: brcms_ops_stop: chipmatch failed\n");
+		return;
+	}
+
+	bcma_core_pci_power_save(wl->wlc->hw->d11core->bus, false);
+
+	/* put driver in down state */
+	spin_lock_bh(&wl->lock);
+	brcms_down(wl);
+	spin_unlock_bh(&wl->lock);
+}
+
+static int
+brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+	struct brcms_info *wl = hw->priv;
+
+	/* Just STA, AP and ADHOC for now */
+	if (vif->type != NL80211_IFTYPE_STATION &&
+	    vif->type != NL80211_IFTYPE_AP &&
+	    vif->type != NL80211_IFTYPE_ADHOC) {
+		brcms_err(wl->wlc->hw->d11core,
+			  "%s: Attempt to add type %d, only STA, AP and AdHoc for now\n",
+			  __func__, vif->type);
+		return -EOPNOTSUPP;
+	}
+
+	spin_lock_bh(&wl->lock);
+	wl->mute_tx = false;
+	brcms_c_mute(wl->wlc, false);
+	if (vif->type == NL80211_IFTYPE_STATION)
+		brcms_c_start_station(wl->wlc, vif->addr);
+	else if (vif->type == NL80211_IFTYPE_AP)
+		brcms_c_start_ap(wl->wlc, vif->addr, vif->bss_conf.bssid,
+				 vif->bss_conf.ssid, vif->bss_conf.ssid_len);
+	else if (vif->type == NL80211_IFTYPE_ADHOC)
+		brcms_c_start_adhoc(wl->wlc, vif->addr);
+	spin_unlock_bh(&wl->lock);
+
+	return 0;
+}
+
+static void
+brcms_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+}
+
+static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed)
+{
+	struct ieee80211_conf *conf = &hw->conf;
+	struct brcms_info *wl = hw->priv;
+	struct bcma_device *core = wl->wlc->hw->d11core;
+	int err = 0;
+	int new_int;
+
+	spin_lock_bh(&wl->lock);
+	if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
+		brcms_c_set_beacon_listen_interval(wl->wlc,
+						   conf->listen_interval);
+	}
+	if (changed & IEEE80211_CONF_CHANGE_MONITOR)
+		brcms_dbg_info(core, "%s: change monitor mode: %s\n",
+			       __func__, conf->flags & IEEE80211_CONF_MONITOR ?
+			       "true" : "false");
+	if (changed & IEEE80211_CONF_CHANGE_PS)
+		brcms_err(core, "%s: change power-save mode: %s (implement)\n",
+			  __func__, conf->flags & IEEE80211_CONF_PS ?
+			  "true" : "false");
+
+	if (changed & IEEE80211_CONF_CHANGE_POWER) {
+		err = brcms_c_set_tx_power(wl->wlc, conf->power_level);
+		if (err < 0) {
+			brcms_err(core, "%s: Error setting power_level\n",
+				  __func__);
+			goto config_out;
+		}
+		new_int = brcms_c_get_tx_power(wl->wlc);
+		if (new_int != conf->power_level)
+			brcms_err(core,
+				  "%s: Power level req != actual, %d %d\n",
+				  __func__, conf->power_level,
+				  new_int);
+	}
+	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+		if (conf->chandef.width == NL80211_CHAN_WIDTH_20 ||
+		    conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
+			err = brcms_c_set_channel(wl->wlc,
+						  conf->chandef.chan->hw_value);
+		else
+			err = -ENOTSUPP;
+	}
+	if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+		err = brcms_c_set_rate_limit(wl->wlc,
+					     conf->short_frame_max_tx_count,
+					     conf->long_frame_max_tx_count);
+
+ config_out:
+	spin_unlock_bh(&wl->lock);
+	return err;
+}
+
+static void
+brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
+			struct ieee80211_vif *vif,
+			struct ieee80211_bss_conf *info, u32 changed)
+{
+	struct brcms_info *wl = hw->priv;
+	struct bcma_device *core = wl->wlc->hw->d11core;
+
+	if (changed & BSS_CHANGED_ASSOC) {
+		/* association status changed (associated/disassociated)
+		 * also implies a change in the AID.
+		 */
+		brcms_err(core, "%s: %s: %sassociated\n", KBUILD_MODNAME,
+			  __func__, info->assoc ? "" : "dis");
+		spin_lock_bh(&wl->lock);
+		brcms_c_associate_upd(wl->wlc, info->assoc);
+		spin_unlock_bh(&wl->lock);
+	}
+	if (changed & BSS_CHANGED_ERP_SLOT) {
+		s8 val;
+
+		/* slot timing changed */
+		if (info->use_short_slot)
+			val = 1;
+		else
+			val = 0;
+		spin_lock_bh(&wl->lock);
+		brcms_c_set_shortslot_override(wl->wlc, val);
+		spin_unlock_bh(&wl->lock);
+	}
+
+	if (changed & BSS_CHANGED_HT) {
+		/* 802.11n parameters changed */
+		u16 mode = info->ht_operation_mode;
+
+		spin_lock_bh(&wl->lock);
+		brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_CFG,
+			mode & IEEE80211_HT_OP_MODE_PROTECTION);
+		brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_NONGF,
+			mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
+		brcms_c_protection_upd(wl->wlc, BRCMS_PROT_N_OBSS,
+			mode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT);
+		spin_unlock_bh(&wl->lock);
+	}
+	if (changed & BSS_CHANGED_BASIC_RATES) {
+		struct ieee80211_supported_band *bi;
+		u32 br_mask, i;
+		u16 rate;
+		struct brcm_rateset rs;
+		int error;
+
+		/* retrieve the current rates */
+		spin_lock_bh(&wl->lock);
+		brcms_c_get_current_rateset(wl->wlc, &rs);
+		spin_unlock_bh(&wl->lock);
+
+		br_mask = info->basic_rates;
+		bi = hw->wiphy->bands[brcms_c_get_curband(wl->wlc)];
+		for (i = 0; i < bi->n_bitrates; i++) {
+			/* convert to internal rate value */
+			rate = (bi->bitrates[i].bitrate << 1) / 10;
+
+			/* set/clear basic rate flag */
+			brcms_set_basic_rate(&rs, rate, br_mask & 1);
+			br_mask >>= 1;
+		}
+
+		/* update the rate set */
+		spin_lock_bh(&wl->lock);
+		error = brcms_c_set_rateset(wl->wlc, &rs);
+		spin_unlock_bh(&wl->lock);
+		if (error)
+			brcms_err(core, "changing basic rates failed: %d\n",
+				  error);
+	}
+	if (changed & BSS_CHANGED_BEACON_INT) {
+		/* Beacon interval changed */
+		spin_lock_bh(&wl->lock);
+		brcms_c_set_beacon_period(wl->wlc, info->beacon_int);
+		spin_unlock_bh(&wl->lock);
+	}
+	if (changed & BSS_CHANGED_BSSID) {
+		/* BSSID changed, for whatever reason (IBSS and managed mode) */
+		spin_lock_bh(&wl->lock);
+		brcms_c_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET, info->bssid);
+		spin_unlock_bh(&wl->lock);
+	}
+	if (changed & BSS_CHANGED_SSID) {
+		/* BSSID changed, for whatever reason (IBSS and managed mode) */
+		spin_lock_bh(&wl->lock);
+		brcms_c_set_ssid(wl->wlc, info->ssid, info->ssid_len);
+		spin_unlock_bh(&wl->lock);
+	}
+	if (changed & BSS_CHANGED_BEACON) {
+		/* Beacon data changed, retrieve new beacon (beaconing modes) */
+		struct sk_buff *beacon;
+		u16 tim_offset = 0;
+
+		spin_lock_bh(&wl->lock);
+		beacon = ieee80211_beacon_get_tim(hw, vif, &tim_offset, NULL);
+		brcms_c_set_new_beacon(wl->wlc, beacon, tim_offset,
+				       info->dtim_period);
+		spin_unlock_bh(&wl->lock);
+	}
+
+	if (changed & BSS_CHANGED_AP_PROBE_RESP) {
+		struct sk_buff *probe_resp;
+
+		spin_lock_bh(&wl->lock);
+		probe_resp = ieee80211_proberesp_get(hw, vif);
+		brcms_c_set_new_probe_resp(wl->wlc, probe_resp);
+		spin_unlock_bh(&wl->lock);
+	}
+
+	if (changed & BSS_CHANGED_BEACON_ENABLED) {
+		/* Beaconing should be enabled/disabled (beaconing modes) */
+		brcms_err(core, "%s: Beacon enabled: %s\n", __func__,
+			  info->enable_beacon ? "true" : "false");
+		if (info->enable_beacon &&
+		    hw->wiphy->flags & WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD) {
+			brcms_c_enable_probe_resp(wl->wlc, true);
+		} else {
+			brcms_c_enable_probe_resp(wl->wlc, false);
+		}
+	}
+
+	if (changed & BSS_CHANGED_CQM) {
+		/* Connection quality monitor config changed */
+		brcms_err(core, "%s: cqm change: threshold %d, hys %d "
+			  " (implement)\n", __func__, info->cqm_rssi_thold,
+			  info->cqm_rssi_hyst);
+	}
+
+	if (changed & BSS_CHANGED_IBSS) {
+		/* IBSS join status changed */
+		brcms_err(core, "%s: IBSS joined: %s (implement)\n",
+			  __func__, info->ibss_joined ? "true" : "false");
+	}
+
+	if (changed & BSS_CHANGED_ARP_FILTER) {
+		/* Hardware ARP filter address list or state changed */
+		brcms_err(core, "%s: arp filtering: %d addresses"
+			  " (implement)\n", __func__, info->arp_addr_cnt);
+	}
+
+	if (changed & BSS_CHANGED_QOS) {
+		/*
+		 * QoS for this association was enabled/disabled.
+		 * Note that it is only ever disabled for station mode.
+		 */
+		brcms_err(core, "%s: qos enabled: %s (implement)\n",
+			  __func__, info->qos ? "true" : "false");
+	}
+	return;
+}
+
+static void
+brcms_ops_configure_filter(struct ieee80211_hw *hw,
+			unsigned int changed_flags,
+			unsigned int *total_flags, u64 multicast)
+{
+	struct brcms_info *wl = hw->priv;
+	struct bcma_device *core = wl->wlc->hw->d11core;
+
+	changed_flags &= MAC_FILTERS;
+	*total_flags &= MAC_FILTERS;
+
+	if (changed_flags & FIF_ALLMULTI)
+		brcms_dbg_info(core, "FIF_ALLMULTI\n");
+	if (changed_flags & FIF_FCSFAIL)
+		brcms_dbg_info(core, "FIF_FCSFAIL\n");
+	if (changed_flags & FIF_CONTROL)
+		brcms_dbg_info(core, "FIF_CONTROL\n");
+	if (changed_flags & FIF_OTHER_BSS)
+		brcms_dbg_info(core, "FIF_OTHER_BSS\n");
+	if (changed_flags & FIF_PSPOLL)
+		brcms_dbg_info(core, "FIF_PSPOLL\n");
+	if (changed_flags & FIF_BCN_PRBRESP_PROMISC)
+		brcms_dbg_info(core, "FIF_BCN_PRBRESP_PROMISC\n");
+
+	spin_lock_bh(&wl->lock);
+	brcms_c_mac_promisc(wl->wlc, *total_flags);
+	spin_unlock_bh(&wl->lock);
+	return;
+}
+
+static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw,
+				    struct ieee80211_vif *vif,
+				    const u8 *mac_addr)
+{
+	struct brcms_info *wl = hw->priv;
+	spin_lock_bh(&wl->lock);
+	brcms_c_scan_start(wl->wlc);
+	spin_unlock_bh(&wl->lock);
+	return;
+}
+
+static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw,
+				       struct ieee80211_vif *vif)
+{
+	struct brcms_info *wl = hw->priv;
+	spin_lock_bh(&wl->lock);
+	brcms_c_scan_stop(wl->wlc);
+	spin_unlock_bh(&wl->lock);
+	return;
+}
+
+static int
+brcms_ops_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
+		  const struct ieee80211_tx_queue_params *params)
+{
+	struct brcms_info *wl = hw->priv;
+
+	spin_lock_bh(&wl->lock);
+	brcms_c_wme_setparams(wl->wlc, queue, params, true);
+	spin_unlock_bh(&wl->lock);
+
+	return 0;
+}
+
+static int
+brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+	       struct ieee80211_sta *sta)
+{
+	struct brcms_info *wl = hw->priv;
+	struct scb *scb = &wl->wlc->pri_scb;
+
+	brcms_c_init_scb(scb);
+
+	wl->pub->global_ampdu = &(scb->scb_ampdu);
+	wl->pub->global_ampdu->scb = scb;
+	wl->pub->global_ampdu->max_pdu = 16;
+
+	/*
+	 * minstrel_ht initiates addBA on our behalf by calling
+	 * ieee80211_start_tx_ba_session()
+	 */
+	return 0;
+}
+
+static int
+brcms_ops_ampdu_action(struct ieee80211_hw *hw,
+		    struct ieee80211_vif *vif,
+		    struct ieee80211_ampdu_params *params)
+{
+	struct brcms_info *wl = hw->priv;
+	struct scb *scb = &wl->wlc->pri_scb;
+	int status;
+	struct ieee80211_sta *sta = params->sta;
+	enum ieee80211_ampdu_mlme_action action = params->action;
+	u16 tid = params->tid;
+	u8 buf_size = params->buf_size;
+
+	if (WARN_ON(scb->magic != SCB_MAGIC))
+		return -EIDRM;
+	switch (action) {
+	case IEEE80211_AMPDU_RX_START:
+		break;
+	case IEEE80211_AMPDU_RX_STOP:
+		break;
+	case IEEE80211_AMPDU_TX_START:
+		spin_lock_bh(&wl->lock);
+		status = brcms_c_aggregatable(wl->wlc, tid);
+		spin_unlock_bh(&wl->lock);
+		if (!status) {
+			brcms_err(wl->wlc->hw->d11core,
+				  "START: tid %d is not agg\'able\n", tid);
+			return -EINVAL;
+		}
+		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+		break;
+
+	case IEEE80211_AMPDU_TX_STOP_CONT:
+	case IEEE80211_AMPDU_TX_STOP_FLUSH:
+	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
+		spin_lock_bh(&wl->lock);
+		brcms_c_ampdu_flush(wl->wlc, sta, tid);
+		spin_unlock_bh(&wl->lock);
+		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+		break;
+	case IEEE80211_AMPDU_TX_OPERATIONAL:
+		/*
+		 * BA window size from ADDBA response ('buf_size') defines how
+		 * many outstanding MPDUs are allowed for the BA stream by
+		 * recipient and traffic class. 'ampdu_factor' gives maximum
+		 * AMPDU size.
+		 */
+		spin_lock_bh(&wl->lock);
+		brcms_c_ampdu_tx_operational(wl->wlc, tid, buf_size,
+			(1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
+			 sta->ht_cap.ampdu_factor)) - 1);
+		spin_unlock_bh(&wl->lock);
+		/* Power save wakeup */
+		break;
+	default:
+		brcms_err(wl->wlc->hw->d11core,
+			  "%s: Invalid command, ignoring\n", __func__);
+	}
+
+	return 0;
+}
+
+static void brcms_ops_rfkill_poll(struct ieee80211_hw *hw)
+{
+	struct brcms_info *wl = hw->priv;
+	bool blocked;
+
+	spin_lock_bh(&wl->lock);
+	blocked = brcms_c_check_radio_disabled(wl->wlc);
+	spin_unlock_bh(&wl->lock);
+
+	wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
+}
+
+static bool brcms_tx_flush_completed(struct brcms_info *wl)
+{
+	bool result;
+
+	spin_lock_bh(&wl->lock);
+	result = brcms_c_tx_flush_completed(wl->wlc);
+	spin_unlock_bh(&wl->lock);
+	return result;
+}
+
+static void brcms_ops_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+			    u32 queues, bool drop)
+{
+	struct brcms_info *wl = hw->priv;
+	int ret;
+
+	no_printk("%s: drop = %s\n", __func__, drop ? "true" : "false");
+
+	ret = wait_event_timeout(wl->tx_flush_wq,
+				 brcms_tx_flush_completed(wl),
+				 msecs_to_jiffies(BRCMS_FLUSH_TIMEOUT));
+
+	brcms_dbg_mac80211(wl->wlc->hw->d11core,
+			   "ret=%d\n", jiffies_to_msecs(ret));
+}
+
+static u64 brcms_ops_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+	struct brcms_info *wl = hw->priv;
+	u64 tsf;
+
+	spin_lock_bh(&wl->lock);
+	tsf = brcms_c_tsf_get(wl->wlc);
+	spin_unlock_bh(&wl->lock);
+
+	return tsf;
+}
+
+static void brcms_ops_set_tsf(struct ieee80211_hw *hw,
+			   struct ieee80211_vif *vif, u64 tsf)
+{
+	struct brcms_info *wl = hw->priv;
+
+	spin_lock_bh(&wl->lock);
+	brcms_c_tsf_set(wl->wlc, tsf);
+	spin_unlock_bh(&wl->lock);
+}
+
+static const struct ieee80211_ops brcms_ops = {
+	.tx = brcms_ops_tx,
+	.start = brcms_ops_start,
+	.stop = brcms_ops_stop,
+	.add_interface = brcms_ops_add_interface,
+	.remove_interface = brcms_ops_remove_interface,
+	.config = brcms_ops_config,
+	.bss_info_changed = brcms_ops_bss_info_changed,
+	.configure_filter = brcms_ops_configure_filter,
+	.sw_scan_start = brcms_ops_sw_scan_start,
+	.sw_scan_complete = brcms_ops_sw_scan_complete,
+	.conf_tx = brcms_ops_conf_tx,
+	.sta_add = brcms_ops_sta_add,
+	.ampdu_action = brcms_ops_ampdu_action,
+	.rfkill_poll = brcms_ops_rfkill_poll,
+	.flush = brcms_ops_flush,
+	.get_tsf = brcms_ops_get_tsf,
+	.set_tsf = brcms_ops_set_tsf,
+};
+
+void brcms_dpc(unsigned long data)
+{
+	struct brcms_info *wl;
+
+	wl = (struct brcms_info *) data;
+
+	spin_lock_bh(&wl->lock);
+
+	/* call the common second level interrupt handler */
+	if (wl->pub->up) {
+		if (wl->resched) {
+			unsigned long flags;
+
+			spin_lock_irqsave(&wl->isr_lock, flags);
+			brcms_c_intrsupd(wl->wlc);
+			spin_unlock_irqrestore(&wl->isr_lock, flags);
+		}
+
+		wl->resched = brcms_c_dpc(wl->wlc, true);
+	}
+
+	/* brcms_c_dpc() may bring the driver down */
+	if (!wl->pub->up)
+		goto done;
+
+	/* re-schedule dpc */
+	if (wl->resched)
+		tasklet_schedule(&wl->tasklet);
+	else
+		/* re-enable interrupts */
+		brcms_intrson(wl);
+
+ done:
+	spin_unlock_bh(&wl->lock);
+	wake_up(&wl->tx_flush_wq);
+}
+
+static irqreturn_t brcms_isr(int irq, void *dev_id)
+{
+	struct brcms_info *wl;
+	irqreturn_t ret = IRQ_NONE;
+
+	wl = (struct brcms_info *) dev_id;
+
+	spin_lock(&wl->isr_lock);
+
+	/* call common first level interrupt handler */
+	if (brcms_c_isr(wl->wlc)) {
+		/* schedule second level handler */
+		tasklet_schedule(&wl->tasklet);
+		ret = IRQ_HANDLED;
+	}
+
+	spin_unlock(&wl->isr_lock);
+
+	return ret;
+}
+
+/*
+ * is called in brcms_pci_probe() context, therefore no locking required.
+ */
+static int ieee_hw_rate_init(struct ieee80211_hw *hw)
+{
+	struct brcms_info *wl = hw->priv;
+	struct brcms_c_info *wlc = wl->wlc;
+	struct ieee80211_supported_band *band;
+	int has_5g = 0;
+	u16 phy_type;
+
+	hw->wiphy->bands[NL80211_BAND_2GHZ] = NULL;
+	hw->wiphy->bands[NL80211_BAND_5GHZ] = NULL;
+
+	phy_type = brcms_c_get_phy_type(wl->wlc, 0);
+	if (phy_type == PHY_TYPE_N || phy_type == PHY_TYPE_LCN) {
+		band = &wlc->bandstate[BAND_2G_INDEX]->band;
+		*band = brcms_band_2GHz_nphy_template;
+		if (phy_type == PHY_TYPE_LCN) {
+			/* Single stream */
+			band->ht_cap.mcs.rx_mask[1] = 0;
+			band->ht_cap.mcs.rx_highest = cpu_to_le16(72);
+		}
+		hw->wiphy->bands[NL80211_BAND_2GHZ] = band;
+	} else {
+		return -EPERM;
+	}
+
+	/* Assume all bands use the same phy.  True for 11n devices. */
+	if (wl->pub->_nbands > 1) {
+		has_5g++;
+		if (phy_type == PHY_TYPE_N || phy_type == PHY_TYPE_LCN) {
+			band = &wlc->bandstate[BAND_5G_INDEX]->band;
+			*band = brcms_band_5GHz_nphy_template;
+			hw->wiphy->bands[NL80211_BAND_5GHZ] = band;
+		} else {
+			return -EPERM;
+		}
+	}
+	return 0;
+}
+
+/*
+ * is called in brcms_pci_probe() context, therefore no locking required.
+ */
+static int ieee_hw_init(struct ieee80211_hw *hw)
+{
+	ieee80211_hw_set(hw, AMPDU_AGGREGATION);
+	ieee80211_hw_set(hw, SIGNAL_DBM);
+	ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
+
+	hw->extra_tx_headroom = brcms_c_get_header_len();
+	hw->queues = N_TX_QUEUES;
+	hw->max_rates = 2;	/* Primary rate and 1 fallback rate */
+
+	/* channel change time is dependent on chip and band  */
+	hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+				     BIT(NL80211_IFTYPE_AP) |
+				     BIT(NL80211_IFTYPE_ADHOC);
+
+	/*
+	 * deactivate sending probe responses by ucude, because this will
+	 * cause problems when WPS is used.
+	 *
+	 * hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
+	 */
+
+	wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
+
+	hw->rate_control_algorithm = "minstrel_ht";
+
+	hw->sta_data_size = 0;
+	return ieee_hw_rate_init(hw);
+}
+
+/**
+ * attach to the WL device.
+ *
+ * Attach to the WL device identified by vendor and device parameters.
+ * regs is a host accessible memory address pointing to WL device registers.
+ *
+ * is called in brcms_bcma_probe() context, therefore no locking required.
+ */
+static struct brcms_info *brcms_attach(struct bcma_device *pdev)
+{
+	struct brcms_info *wl = NULL;
+	int unit, err;
+	struct ieee80211_hw *hw;
+	u8 perm[ETH_ALEN];
+
+	unit = n_adapters_found;
+	err = 0;
+
+	if (unit < 0)
+		return NULL;
+
+	/* allocate private info */
+	hw = bcma_get_drvdata(pdev);
+	if (hw != NULL)
+		wl = hw->priv;
+	if (WARN_ON(hw == NULL) || WARN_ON(wl == NULL))
+		return NULL;
+	wl->wiphy = hw->wiphy;
+
+	atomic_set(&wl->callbacks, 0);
+
+	init_waitqueue_head(&wl->tx_flush_wq);
+
+	/* setup the bottom half handler */
+	tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl);
+
+	spin_lock_init(&wl->lock);
+	spin_lock_init(&wl->isr_lock);
+
+	/* common load-time initialization */
+	wl->wlc = brcms_c_attach((void *)wl, pdev, unit, false, &err);
+	if (!wl->wlc) {
+		wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n",
+			  KBUILD_MODNAME, err);
+		goto fail;
+	}
+	wl->pub = brcms_c_pub(wl->wlc);
+
+	wl->pub->ieee_hw = hw;
+
+	/* register our interrupt handler */
+	if (request_irq(pdev->irq, brcms_isr,
+			IRQF_SHARED, KBUILD_MODNAME, wl)) {
+		wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit);
+		goto fail;
+	}
+	wl->irq = pdev->irq;
+
+	/* register module */
+	brcms_c_module_register(wl->pub, "linux", wl, NULL);
+
+	if (ieee_hw_init(hw)) {
+		wiphy_err(wl->wiphy, "wl%d: %s: ieee_hw_init failed!\n", unit,
+			  __func__);
+		goto fail;
+	}
+
+	brcms_c_regd_init(wl->wlc);
+
+	memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN);
+	if (WARN_ON(!is_valid_ether_addr(perm)))
+		goto fail;
+	SET_IEEE80211_PERM_ADDR(hw, perm);
+
+	err = ieee80211_register_hw(hw);
+	if (err)
+		wiphy_err(wl->wiphy, "%s: ieee80211_register_hw failed, status"
+			  "%d\n", __func__, err);
+
+	if (wl->pub->srom_ccode[0] &&
+	    regulatory_hint(wl->wiphy, wl->pub->srom_ccode))
+		wiphy_err(wl->wiphy, "%s: regulatory hint failed\n", __func__);
+
+	brcms_debugfs_attach(wl->pub);
+	brcms_debugfs_create_files(wl->pub);
+	n_adapters_found++;
+	return wl;
+
+fail:
+	brcms_free(wl);
+	return NULL;
+}
+
+
+
+/**
+ * determines if a device is a WL device, and if so, attaches it.
+ *
+ * This function determines if a device pointed to by pdev is a WL device,
+ * and if so, performs a brcms_attach() on it.
+ *
+ * Perimeter lock is initialized in the course of this function.
+ */
+static int brcms_bcma_probe(struct bcma_device *pdev)
+{
+	struct brcms_info *wl;
+	struct ieee80211_hw *hw;
+
+	dev_info(&pdev->dev, "mfg %x core %x rev %d class %d irq %d\n",
+		 pdev->id.manuf, pdev->id.id, pdev->id.rev, pdev->id.class,
+		 pdev->irq);
+
+	if ((pdev->id.manuf != BCMA_MANUF_BCM) ||
+	    (pdev->id.id != BCMA_CORE_80211))
+		return -ENODEV;
+
+	hw = ieee80211_alloc_hw(sizeof(struct brcms_info), &brcms_ops);
+	if (!hw) {
+		pr_err("%s: ieee80211_alloc_hw failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	SET_IEEE80211_DEV(hw, &pdev->dev);
+
+	bcma_set_drvdata(pdev, hw);
+
+	memset(hw->priv, 0, sizeof(*wl));
+
+	wl = brcms_attach(pdev);
+	if (!wl) {
+		pr_err("%s: brcms_attach failed!\n", __func__);
+		return -ENODEV;
+	}
+	brcms_led_register(wl);
+
+	return 0;
+}
+
+static int brcms_suspend(struct bcma_device *pdev)
+{
+	struct brcms_info *wl;
+	struct ieee80211_hw *hw;
+
+	hw = bcma_get_drvdata(pdev);
+	wl = hw->priv;
+	if (!wl) {
+		pr_err("%s: %s: no driver private struct!\n", KBUILD_MODNAME,
+		       __func__);
+		return -ENODEV;
+	}
+
+	/* only need to flag hw is down for proper resume */
+	spin_lock_bh(&wl->lock);
+	wl->pub->hw_up = false;
+	spin_unlock_bh(&wl->lock);
+
+	brcms_dbg_info(wl->wlc->hw->d11core, "brcms_suspend ok\n");
+
+	return 0;
+}
+
+static int brcms_resume(struct bcma_device *pdev)
+{
+	return 0;
+}
+
+static struct bcma_driver brcms_bcma_driver = {
+	.name     = KBUILD_MODNAME,
+	.probe    = brcms_bcma_probe,
+	.suspend  = brcms_suspend,
+	.resume   = brcms_resume,
+	.remove   = brcms_remove,
+	.id_table = brcms_coreid_table,
+};
+
+/**
+ * This is the main entry point for the brcmsmac driver.
+ *
+ * This function is scheduled upon module initialization and
+ * does the driver registration, which result in brcms_bcma_probe()
+ * call resulting in the driver bringup.
+ */
+static void brcms_driver_init(struct work_struct *work)
+{
+	int error;
+
+	error = bcma_driver_register(&brcms_bcma_driver);
+	if (error)
+		pr_err("%s: register returned %d\n", __func__, error);
+}
+
+static DECLARE_WORK(brcms_driver_work, brcms_driver_init);
+
+static int __init brcms_module_init(void)
+{
+	brcms_debugfs_init();
+	if (!schedule_work(&brcms_driver_work))
+		return -EBUSY;
+
+	return 0;
+}
+
+/**
+ * This function unloads the brcmsmac driver from the system.
+ *
+ * This function unconditionally unloads the brcmsmac driver module from the
+ * system.
+ *
+ */
+static void __exit brcms_module_exit(void)
+{
+	cancel_work_sync(&brcms_driver_work);
+	bcma_driver_unregister(&brcms_bcma_driver);
+	brcms_debugfs_exit();
+}
+
+module_init(brcms_module_init);
+module_exit(brcms_module_exit);
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif,
+			 bool state, int prio)
+{
+	brcms_err(wl->wlc->hw->d11core, "Shouldn't be here %s\n", __func__);
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+void brcms_init(struct brcms_info *wl)
+{
+	brcms_dbg_info(wl->wlc->hw->d11core, "Initializing wl%d\n",
+		       wl->pub->unit);
+	brcms_reset(wl);
+	brcms_c_init(wl->wlc, wl->mute_tx);
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+uint brcms_reset(struct brcms_info *wl)
+{
+	brcms_dbg_info(wl->wlc->hw->d11core, "Resetting wl%d\n", wl->pub->unit);
+	brcms_c_reset(wl->wlc);
+
+	/* dpc will not be rescheduled */
+	wl->resched = false;
+
+	/* inform publicly that interface is down */
+	wl->pub->up = false;
+
+	return 0;
+}
+
+void brcms_fatal_error(struct brcms_info *wl)
+{
+	brcms_err(wl->wlc->hw->d11core, "wl%d: fatal error, reinitializing\n",
+		  wl->wlc->pub->unit);
+	brcms_reset(wl);
+	ieee80211_restart_hw(wl->pub->ieee_hw);
+}
+
+/*
+ * These are interrupt on/off entry points. Disable interrupts
+ * during interrupt state transition.
+ */
+void brcms_intrson(struct brcms_info *wl)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&wl->isr_lock, flags);
+	brcms_c_intrson(wl->wlc);
+	spin_unlock_irqrestore(&wl->isr_lock, flags);
+}
+
+u32 brcms_intrsoff(struct brcms_info *wl)
+{
+	unsigned long flags;
+	u32 status;
+
+	spin_lock_irqsave(&wl->isr_lock, flags);
+	status = brcms_c_intrsoff(wl->wlc);
+	spin_unlock_irqrestore(&wl->isr_lock, flags);
+	return status;
+}
+
+void brcms_intrsrestore(struct brcms_info *wl, u32 macintmask)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&wl->isr_lock, flags);
+	brcms_c_intrsrestore(wl->wlc, macintmask);
+	spin_unlock_irqrestore(&wl->isr_lock, flags);
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+int brcms_up(struct brcms_info *wl)
+{
+	int error = 0;
+
+	if (wl->pub->up)
+		return 0;
+
+	error = brcms_c_up(wl->wlc);
+
+	return error;
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+void brcms_down(struct brcms_info *wl)
+{
+	uint callbacks, ret_val = 0;
+
+	/* call common down function */
+	ret_val = brcms_c_down(wl->wlc);
+	callbacks = atomic_read(&wl->callbacks) - ret_val;
+
+	/* wait for down callbacks to complete */
+	spin_unlock_bh(&wl->lock);
+
+	/* For HIGH_only driver, it's important to actually schedule other work,
+	 * not just spin wait since everything runs at schedule level
+	 */
+	SPINWAIT((atomic_read(&wl->callbacks) > callbacks), 100 * 1000);
+
+	spin_lock_bh(&wl->lock);
+}
+
+/*
+* precondition: perimeter lock is not acquired
+ */
+static void _brcms_timer(struct work_struct *work)
+{
+	struct brcms_timer *t = container_of(work, struct brcms_timer,
+					     dly_wrk.work);
+
+	spin_lock_bh(&t->wl->lock);
+
+	if (t->set) {
+		if (t->periodic) {
+			atomic_inc(&t->wl->callbacks);
+			ieee80211_queue_delayed_work(t->wl->pub->ieee_hw,
+						     &t->dly_wrk,
+						     msecs_to_jiffies(t->ms));
+		} else {
+			t->set = false;
+		}
+
+		t->fn(t->arg);
+	}
+
+	atomic_dec(&t->wl->callbacks);
+
+	spin_unlock_bh(&t->wl->lock);
+}
+
+/*
+ * Adds a timer to the list. Caller supplies a timer function.
+ * Is called from wlc.
+ *
+ * precondition: perimeter lock has been acquired
+ */
+struct brcms_timer *brcms_init_timer(struct brcms_info *wl,
+				     void (*fn) (void *arg),
+				     void *arg, const char *name)
+{
+	struct brcms_timer *t;
+
+	t = kzalloc(sizeof(struct brcms_timer), GFP_ATOMIC);
+	if (!t)
+		return NULL;
+
+	INIT_DELAYED_WORK(&t->dly_wrk, _brcms_timer);
+	t->wl = wl;
+	t->fn = fn;
+	t->arg = arg;
+	t->next = wl->timers;
+	wl->timers = t;
+
+#ifdef DEBUG
+	t->name = kstrdup(name, GFP_ATOMIC);
+#endif
+
+	return t;
+}
+
+/*
+ * adds only the kernel timer since it's going to be more accurate
+ * as well as it's easier to make it periodic
+ *
+ * precondition: perimeter lock has been acquired
+ */
+void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic)
+{
+	struct ieee80211_hw *hw = t->wl->pub->ieee_hw;
+
+#ifdef DEBUG
+	if (t->set)
+		brcms_dbg_info(t->wl->wlc->hw->d11core,
+			       "%s: Already set. Name: %s, per %d\n",
+			       __func__, t->name, periodic);
+#endif
+	t->ms = ms;
+	t->periodic = (bool) periodic;
+	if (!t->set) {
+		t->set = true;
+		atomic_inc(&t->wl->callbacks);
+	}
+
+	ieee80211_queue_delayed_work(hw, &t->dly_wrk, msecs_to_jiffies(ms));
+}
+
+/*
+ * return true if timer successfully deleted, false if still pending
+ *
+ * precondition: perimeter lock has been acquired
+ */
+bool brcms_del_timer(struct brcms_timer *t)
+{
+	if (t->set) {
+		t->set = false;
+		if (!cancel_delayed_work(&t->dly_wrk))
+			return false;
+
+		atomic_dec(&t->wl->callbacks);
+	}
+
+	return true;
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+void brcms_free_timer(struct brcms_timer *t)
+{
+	struct brcms_info *wl = t->wl;
+	struct brcms_timer *tmp;
+
+	/* delete the timer in case it is active */
+	brcms_del_timer(t);
+
+	if (wl->timers == t) {
+		wl->timers = wl->timers->next;
+#ifdef DEBUG
+		kfree(t->name);
+#endif
+		kfree(t);
+		return;
+
+	}
+
+	tmp = wl->timers;
+	while (tmp) {
+		if (tmp->next == t) {
+			tmp->next = t->next;
+#ifdef DEBUG
+			kfree(t->name);
+#endif
+			kfree(t);
+			return;
+		}
+		tmp = tmp->next;
+	}
+
+}
+
+/*
+ * precondition: no locking required
+ */
+int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, u32 idx)
+{
+	int i, entry;
+	const u8 *pdata;
+	struct firmware_hdr *hdr;
+	for (i = 0; i < wl->fw.fw_cnt; i++) {
+		hdr = (struct firmware_hdr *)wl->fw.fw_hdr[i]->data;
+		for (entry = 0; entry < wl->fw.hdr_num_entries[i];
+		     entry++, hdr++) {
+			u32 len = le32_to_cpu(hdr->len);
+			if (le32_to_cpu(hdr->idx) == idx) {
+				pdata = wl->fw.fw_bin[i]->data +
+					le32_to_cpu(hdr->offset);
+				*pbuf = kmemdup(pdata, len, GFP_KERNEL);
+				if (*pbuf == NULL)
+					goto fail;
+
+				return 0;
+			}
+		}
+	}
+	brcms_err(wl->wlc->hw->d11core,
+		  "ERROR: ucode buf tag:%d can not be found!\n", idx);
+	*pbuf = NULL;
+fail:
+	return -ENODATA;
+}
+
+/*
+ * Precondition: Since this function is called in brcms_bcma_probe() context,
+ * no locking is required.
+ */
+int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, u32 idx)
+{
+	int i, entry;
+	const u8 *pdata;
+	struct firmware_hdr *hdr;
+	for (i = 0; i < wl->fw.fw_cnt; i++) {
+		hdr = (struct firmware_hdr *)wl->fw.fw_hdr[i]->data;
+		for (entry = 0; entry < wl->fw.hdr_num_entries[i];
+		     entry++, hdr++) {
+			if (le32_to_cpu(hdr->idx) == idx) {
+				pdata = wl->fw.fw_bin[i]->data +
+					le32_to_cpu(hdr->offset);
+				if (le32_to_cpu(hdr->len) != 4) {
+					brcms_err(wl->wlc->hw->d11core,
+						  "ERROR: fw hdr len\n");
+					return -ENOMSG;
+				}
+				*n_bytes = le32_to_cpu(*((__le32 *) pdata));
+				return 0;
+			}
+		}
+	}
+	brcms_err(wl->wlc->hw->d11core,
+		  "ERROR: ucode tag:%d can not be found!\n", idx);
+	return -ENOMSG;
+}
+
+/*
+ * precondition: can both be called locked and unlocked
+ */
+void brcms_ucode_free_buf(void *p)
+{
+	kfree(p);
+}
+
+/*
+ * checks validity of all firmware images loaded from user space
+ *
+ * Precondition: Since this function is called in brcms_bcma_probe() context,
+ * no locking is required.
+ */
+int brcms_check_firmwares(struct brcms_info *wl)
+{
+	int i;
+	int entry;
+	int rc = 0;
+	const struct firmware *fw;
+	const struct firmware *fw_hdr;
+	struct firmware_hdr *ucode_hdr;
+	for (i = 0; i < MAX_FW_IMAGES && rc == 0; i++) {
+		fw =  wl->fw.fw_bin[i];
+		fw_hdr = wl->fw.fw_hdr[i];
+		if (fw == NULL && fw_hdr == NULL) {
+			break;
+		} else if (fw == NULL || fw_hdr == NULL) {
+			wiphy_err(wl->wiphy, "%s: invalid bin/hdr fw\n",
+				  __func__);
+			rc = -EBADF;
+		} else if (fw_hdr->size % sizeof(struct firmware_hdr)) {
+			wiphy_err(wl->wiphy, "%s: non integral fw hdr file "
+				"size %zu/%zu\n", __func__, fw_hdr->size,
+				sizeof(struct firmware_hdr));
+			rc = -EBADF;
+		} else if (fw->size < MIN_FW_SIZE || fw->size > MAX_FW_SIZE) {
+			wiphy_err(wl->wiphy, "%s: out of bounds fw file size %zu\n",
+				  __func__, fw->size);
+			rc = -EBADF;
+		} else {
+			/* check if ucode section overruns firmware image */
+			ucode_hdr = (struct firmware_hdr *)fw_hdr->data;
+			for (entry = 0; entry < wl->fw.hdr_num_entries[i] &&
+			     !rc; entry++, ucode_hdr++) {
+				if (le32_to_cpu(ucode_hdr->offset) +
+				    le32_to_cpu(ucode_hdr->len) >
+				    fw->size) {
+					wiphy_err(wl->wiphy,
+						  "%s: conflicting bin/hdr\n",
+						  __func__);
+					rc = -EBADF;
+				}
+			}
+		}
+	}
+	if (rc == 0 && wl->fw.fw_cnt != i) {
+		wiphy_err(wl->wiphy, "%s: invalid fw_cnt=%d\n", __func__,
+			wl->fw.fw_cnt);
+		rc = -EBADF;
+	}
+	return rc;
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+bool brcms_rfkill_set_hw_state(struct brcms_info *wl)
+{
+	bool blocked = brcms_c_check_radio_disabled(wl->wlc);
+
+	spin_unlock_bh(&wl->lock);
+	wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
+	if (blocked)
+		wiphy_rfkill_start_polling(wl->pub->ieee_hw->wiphy);
+	spin_lock_bh(&wl->lock);
+	return blocked;
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.h
new file mode 100644
index 0000000..198053d
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_MAC80211_IF_H_
+#define _BRCM_MAC80211_IF_H_
+
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/leds.h>
+
+#include "ucode_loader.h"
+#include "led.h"
+/*
+ * Starting index for 5G rates in the
+ * legacy rate table.
+ */
+#define BRCMS_LEGACY_5G_RATE_OFFSET	4
+
+/* softmac ioctl definitions */
+#define BRCMS_SET_SHORTSLOT_OVERRIDE		146
+
+struct brcms_timer {
+	struct delayed_work dly_wrk;
+	struct brcms_info *wl;
+	void (*fn) (void *);	/* function called upon expiration */
+	void *arg;		/* fixed argument provided to called function */
+	uint ms;
+	bool periodic;
+	bool set;		/* indicates if timer is active */
+	struct brcms_timer *next;	/* for freeing on unload */
+#ifdef DEBUG
+	char *name;		/* Description of the timer */
+#endif
+};
+
+struct brcms_if {
+	uint subunit;		/* WDS/BSS unit */
+	struct pci_dev *pci_dev;
+};
+
+#define MAX_FW_IMAGES		4
+struct brcms_firmware {
+	u32 fw_cnt;
+	const struct firmware *fw_bin[MAX_FW_IMAGES];
+	const struct firmware *fw_hdr[MAX_FW_IMAGES];
+	u32 hdr_num_entries[MAX_FW_IMAGES];
+};
+
+struct brcms_info {
+	struct brcms_pub *pub;		/* pointer to public wlc state */
+	struct brcms_c_info *wlc;	/* pointer to private common data */
+	u32 magic;
+
+	int irq;
+
+	spinlock_t lock;	/* per-device perimeter lock */
+	spinlock_t isr_lock;	/* per-device ISR synchronization lock */
+
+	/* tx flush */
+	wait_queue_head_t tx_flush_wq;
+
+	/* timer related fields */
+	atomic_t callbacks;	/* # outstanding callback functions */
+	struct brcms_timer *timers;	/* timer cleanup queue */
+
+	struct tasklet_struct tasklet;	/* dpc tasklet */
+	bool resched;		/* dpc needs to be and is rescheduled */
+	struct brcms_firmware fw;
+	struct wiphy *wiphy;
+	struct brcms_ucode ucode;
+	bool mute_tx;
+	struct brcms_led radio_led;
+	struct led_classdev led_dev;
+};
+
+/* misc callbacks */
+void brcms_init(struct brcms_info *wl);
+uint brcms_reset(struct brcms_info *wl);
+void brcms_intrson(struct brcms_info *wl);
+u32 brcms_intrsoff(struct brcms_info *wl);
+void brcms_intrsrestore(struct brcms_info *wl, u32 macintmask);
+int brcms_up(struct brcms_info *wl);
+void brcms_down(struct brcms_info *wl);
+void brcms_txflowcontrol(struct brcms_info *wl, struct brcms_if *wlif,
+			 bool state, int prio);
+bool brcms_rfkill_set_hw_state(struct brcms_info *wl);
+
+/* timer functions */
+struct brcms_timer *brcms_init_timer(struct brcms_info *wl,
+				     void (*fn) (void *arg), void *arg,
+				     const char *name);
+void brcms_free_timer(struct brcms_timer *timer);
+void brcms_add_timer(struct brcms_timer *timer, uint ms, int periodic);
+bool brcms_del_timer(struct brcms_timer *timer);
+void brcms_dpc(unsigned long data);
+void brcms_timer(struct brcms_timer *t);
+void brcms_fatal_error(struct brcms_info *wl);
+
+#endif				/* _BRCM_MAC80211_IF_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c
new file mode 100644
index 0000000..7d4e8f5
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c
@@ -0,0 +1,8140 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ * Copyright (c) 2013 Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/pci_ids.h>
+#include <linux/if_ether.h>
+#include <net/cfg80211.h>
+#include <net/mac80211.h>
+#include <brcm_hw_ids.h>
+#include <aiutils.h>
+#include <chipcommon.h>
+#include "rate.h"
+#include "scb.h"
+#include "phy/phy_hal.h"
+#include "channel.h"
+#include "antsel.h"
+#include "stf.h"
+#include "ampdu.h"
+#include "mac80211_if.h"
+#include "ucode_loader.h"
+#include "main.h"
+#include "soc.h"
+#include "dma.h"
+#include "debug.h"
+#include "brcms_trace_events.h"
+
+/* watchdog timer, in unit of ms */
+#define TIMER_INTERVAL_WATCHDOG		1000
+/* radio monitor timer, in unit of ms */
+#define TIMER_INTERVAL_RADIOCHK		800
+
+/* beacon interval, in unit of 1024TU */
+#define BEACON_INTERVAL_DEFAULT		100
+
+/* n-mode support capability */
+/* 2x2 includes both 1x1 & 2x2 devices
+ * reserved #define 2 for future when we want to separate 1x1 & 2x2 and
+ * control it independently
+ */
+#define WL_11N_2x2			1
+#define WL_11N_3x3			3
+#define WL_11N_4x4			4
+
+#define EDCF_ACI_MASK			0x60
+#define EDCF_ACI_SHIFT			5
+#define EDCF_ECWMIN_MASK		0x0f
+#define EDCF_ECWMAX_SHIFT		4
+#define EDCF_AIFSN_MASK			0x0f
+#define EDCF_AIFSN_MAX			15
+#define EDCF_ECWMAX_MASK		0xf0
+
+#define EDCF_AC_BE_TXOP_STA		0x0000
+#define EDCF_AC_BK_TXOP_STA		0x0000
+#define EDCF_AC_VO_ACI_STA		0x62
+#define EDCF_AC_VO_ECW_STA		0x32
+#define EDCF_AC_VI_ACI_STA		0x42
+#define EDCF_AC_VI_ECW_STA		0x43
+#define EDCF_AC_BK_ECW_STA		0xA4
+#define EDCF_AC_VI_TXOP_STA		0x005e
+#define EDCF_AC_VO_TXOP_STA		0x002f
+#define EDCF_AC_BE_ACI_STA		0x03
+#define EDCF_AC_BE_ECW_STA		0xA4
+#define EDCF_AC_BK_ACI_STA		0x27
+#define EDCF_AC_VO_TXOP_AP		0x002f
+
+#define EDCF_TXOP2USEC(txop)		((txop) << 5)
+#define EDCF_ECW2CW(exp)		((1 << (exp)) - 1)
+
+#define APHY_SYMBOL_TIME		4
+#define APHY_PREAMBLE_TIME		16
+#define APHY_SIGNAL_TIME		4
+#define APHY_SIFS_TIME			16
+#define APHY_SERVICE_NBITS		16
+#define APHY_TAIL_NBITS			6
+#define BPHY_SIFS_TIME			10
+#define BPHY_PLCP_SHORT_TIME		96
+
+#define PREN_PREAMBLE			24
+#define PREN_MM_EXT			12
+#define PREN_PREAMBLE_EXT		4
+
+#define DOT11_MAC_HDR_LEN		24
+#define DOT11_ACK_LEN			10
+#define DOT11_BA_LEN			4
+#define DOT11_OFDM_SIGNAL_EXTENSION	6
+#define DOT11_MIN_FRAG_LEN		256
+#define DOT11_RTS_LEN			16
+#define DOT11_CTS_LEN			10
+#define DOT11_BA_BITMAP_LEN		128
+#define DOT11_MAXNUMFRAGS		16
+#define DOT11_MAX_FRAG_LEN		2346
+
+#define BPHY_PLCP_TIME			192
+#define RIFS_11N_TIME			2
+
+/* length of the BCN template area */
+#define BCN_TMPL_LEN			512
+
+/* brcms_bss_info flag bit values */
+#define BRCMS_BSS_HT			0x0020	/* BSS is HT (MIMO) capable */
+
+/* chip rx buffer offset */
+#define BRCMS_HWRXOFF			38
+
+/* rfdisable delay timer 500 ms, runs of ALP clock */
+#define RFDISABLE_DEFAULT		10000000
+
+#define BRCMS_TEMPSENSE_PERIOD		10	/* 10 second timeout */
+
+/* synthpu_dly times in us */
+#define SYNTHPU_DLY_APHY_US		3700
+#define SYNTHPU_DLY_BPHY_US		1050
+#define SYNTHPU_DLY_NPHY_US		2048
+#define SYNTHPU_DLY_LPPHY_US		300
+
+#define ANTCNT				10	/* vanilla M_MAX_ANTCNT val */
+
+/* Per-AC retry limit register definitions; uses defs.h bitfield macros */
+#define EDCF_SHORT_S			0
+#define EDCF_SFB_S			4
+#define EDCF_LONG_S			8
+#define EDCF_LFB_S			12
+#define EDCF_SHORT_M			BITFIELD_MASK(4)
+#define EDCF_SFB_M			BITFIELD_MASK(4)
+#define EDCF_LONG_M			BITFIELD_MASK(4)
+#define EDCF_LFB_M			BITFIELD_MASK(4)
+
+#define RETRY_SHORT_DEF			7	/* Default Short retry Limit */
+#define RETRY_SHORT_MAX			255	/* Maximum Short retry Limit */
+#define RETRY_LONG_DEF			4	/* Default Long retry count */
+#define RETRY_SHORT_FB			3	/* Short count for fb rate */
+#define RETRY_LONG_FB			2	/* Long count for fb rate */
+
+#define APHY_CWMIN			15
+#define PHY_CWMAX			1023
+
+#define EDCF_AIFSN_MIN			1
+
+#define FRAGNUM_MASK			0xF
+
+#define APHY_SLOT_TIME			9
+#define BPHY_SLOT_TIME			20
+
+#define WL_SPURAVOID_OFF		0
+#define WL_SPURAVOID_ON1		1
+#define WL_SPURAVOID_ON2		2
+
+/* invalid core flags, use the saved coreflags */
+#define BRCMS_USE_COREFLAGS		0xffffffff
+
+/* values for PLCPHdr_override */
+#define BRCMS_PLCP_AUTO			-1
+#define BRCMS_PLCP_SHORT		0
+#define BRCMS_PLCP_LONG			1
+
+/* values for g_protection_override and n_protection_override */
+#define BRCMS_PROTECTION_AUTO		-1
+#define BRCMS_PROTECTION_OFF		0
+#define BRCMS_PROTECTION_ON		1
+#define BRCMS_PROTECTION_MMHDR_ONLY	2
+#define BRCMS_PROTECTION_CTS_ONLY	3
+
+/* values for g_protection_control and n_protection_control */
+#define BRCMS_PROTECTION_CTL_OFF	0
+#define BRCMS_PROTECTION_CTL_LOCAL	1
+#define BRCMS_PROTECTION_CTL_OVERLAP	2
+
+/* values for n_protection */
+#define BRCMS_N_PROTECTION_OFF		0
+#define BRCMS_N_PROTECTION_OPTIONAL	1
+#define BRCMS_N_PROTECTION_20IN40	2
+#define BRCMS_N_PROTECTION_MIXEDMODE	3
+
+/* values for band specific 40MHz capabilities */
+#define BRCMS_N_BW_20ALL		0
+#define BRCMS_N_BW_40ALL		1
+#define BRCMS_N_BW_20IN2G_40IN5G	2
+
+/* bitflags for SGI support (sgi_rx iovar) */
+#define BRCMS_N_SGI_20			0x01
+#define BRCMS_N_SGI_40			0x02
+
+/* defines used by the nrate iovar */
+/* MSC in use,indicates b0-6 holds an mcs */
+#define NRATE_MCS_INUSE			0x00000080
+/* rate/mcs value */
+#define NRATE_RATE_MASK			0x0000007f
+/* stf mode mask: siso, cdd, stbc, sdm */
+#define NRATE_STF_MASK			0x0000ff00
+/* stf mode shift */
+#define NRATE_STF_SHIFT			8
+/* bit indicate to override mcs only */
+#define NRATE_OVERRIDE_MCS_ONLY		0x40000000
+#define NRATE_SGI_MASK			0x00800000	/* sgi mode */
+#define NRATE_SGI_SHIFT			23		/* sgi mode */
+#define NRATE_LDPC_CODING		0x00400000	/* adv coding in use */
+#define NRATE_LDPC_SHIFT		22		/* ldpc shift */
+
+#define NRATE_STF_SISO			0		/* stf mode SISO */
+#define NRATE_STF_CDD			1		/* stf mode CDD */
+#define NRATE_STF_STBC			2		/* stf mode STBC */
+#define NRATE_STF_SDM			3		/* stf mode SDM */
+
+#define MAX_DMA_SEGS			4
+
+/* # of entries in Tx FIFO */
+#define NTXD				64
+/* Max # of entries in Rx FIFO based on 4kb page size */
+#define NRXD				256
+
+/* Amount of headroom to leave in Tx FIFO */
+#define TX_HEADROOM			4
+
+/* try to keep this # rbufs posted to the chip */
+#define NRXBUFPOST			32
+
+/* max # frames to process in brcms_c_recv() */
+#define RXBND				8
+/* max # tx status to process in wlc_txstatus() */
+#define TXSBND				8
+
+/* brcmu_format_flags() bit description structure */
+struct brcms_c_bit_desc {
+	u32 bit;
+	const char *name;
+};
+
+/*
+ * The following table lists the buffer memory allocated to xmt fifos in HW.
+ * the size is in units of 256bytes(one block), total size is HW dependent
+ * ucode has default fifo partition, sw can overwrite if necessary
+ *
+ * This is documented in twiki under the topic UcodeTxFifo. Please ensure
+ * the twiki is updated before making changes.
+ */
+
+/* Starting corerev for the fifo size table */
+#define XMTFIFOTBL_STARTREV	17
+
+struct d11init {
+	__le16 addr;
+	__le16 size;
+	__le32 value;
+};
+
+struct edcf_acparam {
+	u8 ACI;
+	u8 ECW;
+	u16 TXOP;
+} __packed;
+
+/* debug/trace */
+uint brcm_msg_level;
+
+/* TX FIFO number to WME/802.1E Access Category */
+static const u8 wme_fifo2ac[] = {
+	IEEE80211_AC_BK,
+	IEEE80211_AC_BE,
+	IEEE80211_AC_VI,
+	IEEE80211_AC_VO,
+	IEEE80211_AC_BE,
+	IEEE80211_AC_BE
+};
+
+/* ieee80211 Access Category to TX FIFO number */
+static const u8 wme_ac2fifo[] = {
+	TX_AC_VO_FIFO,
+	TX_AC_VI_FIFO,
+	TX_AC_BE_FIFO,
+	TX_AC_BK_FIFO
+};
+
+static const u16 xmtfifo_sz[][NFIFO] = {
+	/* corerev 17: 5120, 49152, 49152, 5376, 4352, 1280 */
+	{20, 192, 192, 21, 17, 5},
+	/* corerev 18: */
+	{0, 0, 0, 0, 0, 0},
+	/* corerev 19: */
+	{0, 0, 0, 0, 0, 0},
+	/* corerev 20: 5120, 49152, 49152, 5376, 4352, 1280 */
+	{20, 192, 192, 21, 17, 5},
+	/* corerev 21: 2304, 14848, 5632, 3584, 3584, 1280 */
+	{9, 58, 22, 14, 14, 5},
+	/* corerev 22: 5120, 49152, 49152, 5376, 4352, 1280 */
+	{20, 192, 192, 21, 17, 5},
+	/* corerev 23: 5120, 49152, 49152, 5376, 4352, 1280 */
+	{20, 192, 192, 21, 17, 5},
+	/* corerev 24: 2304, 14848, 5632, 3584, 3584, 1280 */
+	{9, 58, 22, 14, 14, 5},
+	/* corerev 25: */
+	{0, 0, 0, 0, 0, 0},
+	/* corerev 26: */
+	{0, 0, 0, 0, 0, 0},
+	/* corerev 27: */
+	{0, 0, 0, 0, 0, 0},
+	/* corerev 28: 2304, 14848, 5632, 3584, 3584, 1280 */
+	{9, 58, 22, 14, 14, 5},
+};
+
+#ifdef DEBUG
+static const char * const fifo_names[] = {
+	"AC_BK", "AC_BE", "AC_VI", "AC_VO", "BCMC", "ATIM" };
+#else
+static const char fifo_names[6][1];
+#endif
+
+#ifdef DEBUG
+/* pointer to most recently allocated wl/wlc */
+static struct brcms_c_info *wlc_info_dbg = (struct brcms_c_info *) (NULL);
+#endif
+
+/* Mapping of ieee80211 AC numbers to tx fifos */
+static const u8 ac_to_fifo_mapping[IEEE80211_NUM_ACS] = {
+	[IEEE80211_AC_VO]	= TX_AC_VO_FIFO,
+	[IEEE80211_AC_VI]	= TX_AC_VI_FIFO,
+	[IEEE80211_AC_BE]	= TX_AC_BE_FIFO,
+	[IEEE80211_AC_BK]	= TX_AC_BK_FIFO,
+};
+
+/* Mapping of tx fifos to ieee80211 AC numbers */
+static const u8 fifo_to_ac_mapping[IEEE80211_NUM_ACS] = {
+	[TX_AC_BK_FIFO]	= IEEE80211_AC_BK,
+	[TX_AC_BE_FIFO]	= IEEE80211_AC_BE,
+	[TX_AC_VI_FIFO]	= IEEE80211_AC_VI,
+	[TX_AC_VO_FIFO]	= IEEE80211_AC_VO,
+};
+
+static u8 brcms_ac_to_fifo(u8 ac)
+{
+	if (ac >= ARRAY_SIZE(ac_to_fifo_mapping))
+		return TX_AC_BE_FIFO;
+	return ac_to_fifo_mapping[ac];
+}
+
+static u8 brcms_fifo_to_ac(u8 fifo)
+{
+	if (fifo >= ARRAY_SIZE(fifo_to_ac_mapping))
+		return IEEE80211_AC_BE;
+	return fifo_to_ac_mapping[fifo];
+}
+
+/* Find basic rate for a given rate */
+static u8 brcms_basic_rate(struct brcms_c_info *wlc, u32 rspec)
+{
+	if (is_mcs_rate(rspec))
+		return wlc->band->basic_rate[mcs_table[rspec & RSPEC_RATE_MASK]
+		       .leg_ofdm];
+	return wlc->band->basic_rate[rspec & RSPEC_RATE_MASK];
+}
+
+static u16 frametype(u32 rspec, u8 mimoframe)
+{
+	if (is_mcs_rate(rspec))
+		return mimoframe;
+	return is_cck_rate(rspec) ? FT_CCK : FT_OFDM;
+}
+
+/* currently the best mechanism for determining SIFS is the band in use */
+static u16 get_sifs(struct brcms_band *band)
+{
+	return band->bandtype == BRCM_BAND_5G ? APHY_SIFS_TIME :
+				 BPHY_SIFS_TIME;
+}
+
+/*
+ * Detect Card removed.
+ * Even checking an sbconfig register read will not false trigger when the core
+ * is in reset it breaks CF address mechanism. Accessing gphy phyversion will
+ * cause SB error if aphy is in reset on 4306B0-DB. Need a simple accessible
+ * reg with fixed 0/1 pattern (some platforms return all 0).
+ * If clocks are present, call the sb routine which will figure out if the
+ * device is removed.
+ */
+static bool brcms_deviceremoved(struct brcms_c_info *wlc)
+{
+	u32 macctrl;
+
+	if (!wlc->hw->clk)
+		return ai_deviceremoved(wlc->hw->sih);
+	macctrl = bcma_read32(wlc->hw->d11core,
+			      D11REGOFFS(maccontrol));
+	return (macctrl & (MCTL_PSM_JMP_0 | MCTL_IHR_EN)) != MCTL_IHR_EN;
+}
+
+/* sum the individual fifo tx pending packet counts */
+static int brcms_txpktpendtot(struct brcms_c_info *wlc)
+{
+	int i;
+	int pending = 0;
+
+	for (i = 0; i < ARRAY_SIZE(wlc->hw->di); i++)
+		if (wlc->hw->di[i])
+			pending += dma_txpending(wlc->hw->di[i]);
+	return pending;
+}
+
+static bool brcms_is_mband_unlocked(struct brcms_c_info *wlc)
+{
+	return wlc->pub->_nbands > 1 && !wlc->bandlocked;
+}
+
+static int brcms_chspec_bw(u16 chanspec)
+{
+	if (CHSPEC_IS40(chanspec))
+		return BRCMS_40_MHZ;
+	if (CHSPEC_IS20(chanspec))
+		return BRCMS_20_MHZ;
+
+	return BRCMS_10_MHZ;
+}
+
+static void brcms_c_bsscfg_mfree(struct brcms_bss_cfg *cfg)
+{
+	if (cfg == NULL)
+		return;
+
+	kfree(cfg->current_bss);
+	kfree(cfg);
+}
+
+static void brcms_c_detach_mfree(struct brcms_c_info *wlc)
+{
+	if (wlc == NULL)
+		return;
+
+	brcms_c_bsscfg_mfree(wlc->bsscfg);
+	kfree(wlc->pub);
+	kfree(wlc->modulecb);
+	kfree(wlc->default_bss);
+	kfree(wlc->protection);
+	kfree(wlc->stf);
+	kfree(wlc->bandstate[0]);
+	if (wlc->corestate)
+		kfree(wlc->corestate->macstat_snapshot);
+	kfree(wlc->corestate);
+	if (wlc->hw)
+		kfree(wlc->hw->bandstate[0]);
+	kfree(wlc->hw);
+	if (wlc->beacon)
+		dev_kfree_skb_any(wlc->beacon);
+	if (wlc->probe_resp)
+		dev_kfree_skb_any(wlc->probe_resp);
+
+	kfree(wlc);
+}
+
+static struct brcms_bss_cfg *brcms_c_bsscfg_malloc(uint unit)
+{
+	struct brcms_bss_cfg *cfg;
+
+	cfg = kzalloc(sizeof(struct brcms_bss_cfg), GFP_ATOMIC);
+	if (cfg == NULL)
+		goto fail;
+
+	cfg->current_bss = kzalloc(sizeof(struct brcms_bss_info), GFP_ATOMIC);
+	if (cfg->current_bss == NULL)
+		goto fail;
+
+	return cfg;
+
+ fail:
+	brcms_c_bsscfg_mfree(cfg);
+	return NULL;
+}
+
+static struct brcms_c_info *
+brcms_c_attach_malloc(uint unit, uint *err, uint devid)
+{
+	struct brcms_c_info *wlc;
+
+	wlc = kzalloc(sizeof(struct brcms_c_info), GFP_ATOMIC);
+	if (wlc == NULL) {
+		*err = 1002;
+		goto fail;
+	}
+
+	/* allocate struct brcms_c_pub state structure */
+	wlc->pub = kzalloc(sizeof(struct brcms_pub), GFP_ATOMIC);
+	if (wlc->pub == NULL) {
+		*err = 1003;
+		goto fail;
+	}
+	wlc->pub->wlc = wlc;
+
+	/* allocate struct brcms_hardware state structure */
+
+	wlc->hw = kzalloc(sizeof(struct brcms_hardware), GFP_ATOMIC);
+	if (wlc->hw == NULL) {
+		*err = 1005;
+		goto fail;
+	}
+	wlc->hw->wlc = wlc;
+
+	wlc->hw->bandstate[0] =
+		kcalloc(MAXBANDS, sizeof(struct brcms_hw_band), GFP_ATOMIC);
+	if (wlc->hw->bandstate[0] == NULL) {
+		*err = 1006;
+		goto fail;
+	} else {
+		int i;
+
+		for (i = 1; i < MAXBANDS; i++)
+			wlc->hw->bandstate[i] = (struct brcms_hw_band *)
+			    ((unsigned long)wlc->hw->bandstate[0] +
+			     (sizeof(struct brcms_hw_band) * i));
+	}
+
+	wlc->modulecb =
+		kcalloc(BRCMS_MAXMODULES, sizeof(struct modulecb),
+			GFP_ATOMIC);
+	if (wlc->modulecb == NULL) {
+		*err = 1009;
+		goto fail;
+	}
+
+	wlc->default_bss = kzalloc(sizeof(struct brcms_bss_info), GFP_ATOMIC);
+	if (wlc->default_bss == NULL) {
+		*err = 1010;
+		goto fail;
+	}
+
+	wlc->bsscfg = brcms_c_bsscfg_malloc(unit);
+	if (wlc->bsscfg == NULL) {
+		*err = 1011;
+		goto fail;
+	}
+
+	wlc->protection = kzalloc(sizeof(struct brcms_protection),
+				  GFP_ATOMIC);
+	if (wlc->protection == NULL) {
+		*err = 1016;
+		goto fail;
+	}
+
+	wlc->stf = kzalloc(sizeof(struct brcms_stf), GFP_ATOMIC);
+	if (wlc->stf == NULL) {
+		*err = 1017;
+		goto fail;
+	}
+
+	wlc->bandstate[0] =
+		kcalloc(MAXBANDS, sizeof(struct brcms_band), GFP_ATOMIC);
+	if (wlc->bandstate[0] == NULL) {
+		*err = 1025;
+		goto fail;
+	} else {
+		int i;
+
+		for (i = 1; i < MAXBANDS; i++)
+			wlc->bandstate[i] = (struct brcms_band *)
+				((unsigned long)wlc->bandstate[0]
+				+ (sizeof(struct brcms_band)*i));
+	}
+
+	wlc->corestate = kzalloc(sizeof(struct brcms_core), GFP_ATOMIC);
+	if (wlc->corestate == NULL) {
+		*err = 1026;
+		goto fail;
+	}
+
+	wlc->corestate->macstat_snapshot =
+		kzalloc(sizeof(struct macstat), GFP_ATOMIC);
+	if (wlc->corestate->macstat_snapshot == NULL) {
+		*err = 1027;
+		goto fail;
+	}
+
+	return wlc;
+
+ fail:
+	brcms_c_detach_mfree(wlc);
+	return NULL;
+}
+
+/*
+ * Update the slot timing for standard 11b/g (20us slots)
+ * or shortslot 11g (9us slots)
+ * The PSM needs to be suspended for this call.
+ */
+static void brcms_b_update_slot_timing(struct brcms_hardware *wlc_hw,
+					bool shortslot)
+{
+	struct bcma_device *core = wlc_hw->d11core;
+
+	if (shortslot) {
+		/* 11g short slot: 11a timing */
+		bcma_write16(core, D11REGOFFS(ifs_slot), 0x0207);
+		brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, APHY_SLOT_TIME);
+	} else {
+		/* 11g long slot: 11b timing */
+		bcma_write16(core, D11REGOFFS(ifs_slot), 0x0212);
+		brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, BPHY_SLOT_TIME);
+	}
+}
+
+/*
+ * calculate frame duration of a given rate and length, return
+ * time in usec unit
+ */
+static uint brcms_c_calc_frame_time(struct brcms_c_info *wlc, u32 ratespec,
+				    u8 preamble_type, uint mac_len)
+{
+	uint nsyms, dur = 0, Ndps, kNdps;
+	uint rate = rspec2rate(ratespec);
+
+	if (rate == 0) {
+		brcms_err(wlc->hw->d11core, "wl%d: WAR: using rate of 1 mbps\n",
+			  wlc->pub->unit);
+		rate = BRCM_RATE_1M;
+	}
+
+	if (is_mcs_rate(ratespec)) {
+		uint mcs = ratespec & RSPEC_RATE_MASK;
+		int tot_streams = mcs_2_txstreams(mcs) + rspec_stc(ratespec);
+
+		dur = PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT);
+		if (preamble_type == BRCMS_MM_PREAMBLE)
+			dur += PREN_MM_EXT;
+		/* 1000Ndbps = kbps * 4 */
+		kNdps = mcs_2_rate(mcs, rspec_is40mhz(ratespec),
+				   rspec_issgi(ratespec)) * 4;
+
+		if (rspec_stc(ratespec) == 0)
+			nsyms =
+			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
+				  APHY_TAIL_NBITS) * 1000, kNdps);
+		else
+			/* STBC needs to have even number of symbols */
+			nsyms =
+			    2 *
+			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
+				  APHY_TAIL_NBITS) * 1000, 2 * kNdps);
+
+		dur += APHY_SYMBOL_TIME * nsyms;
+		if (wlc->band->bandtype == BRCM_BAND_2G)
+			dur += DOT11_OFDM_SIGNAL_EXTENSION;
+	} else if (is_ofdm_rate(rate)) {
+		dur = APHY_PREAMBLE_TIME;
+		dur += APHY_SIGNAL_TIME;
+		/* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */
+		Ndps = rate * 2;
+		/* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
+		nsyms =
+		    CEIL((APHY_SERVICE_NBITS + 8 * mac_len + APHY_TAIL_NBITS),
+			 Ndps);
+		dur += APHY_SYMBOL_TIME * nsyms;
+		if (wlc->band->bandtype == BRCM_BAND_2G)
+			dur += DOT11_OFDM_SIGNAL_EXTENSION;
+	} else {
+		/*
+		 * calc # bits * 2 so factor of 2 in rate (1/2 mbps)
+		 * will divide out
+		 */
+		mac_len = mac_len * 8 * 2;
+		/* calc ceiling of bits/rate = microseconds of air time */
+		dur = (mac_len + rate - 1) / rate;
+		if (preamble_type & BRCMS_SHORT_PREAMBLE)
+			dur += BPHY_PLCP_SHORT_TIME;
+		else
+			dur += BPHY_PLCP_TIME;
+	}
+	return dur;
+}
+
+static void brcms_c_write_inits(struct brcms_hardware *wlc_hw,
+				const struct d11init *inits)
+{
+	struct bcma_device *core = wlc_hw->d11core;
+	int i;
+	uint offset;
+	u16 size;
+	u32 value;
+
+	brcms_dbg_info(wlc_hw->d11core, "wl%d\n", wlc_hw->unit);
+
+	for (i = 0; inits[i].addr != cpu_to_le16(0xffff); i++) {
+		size = le16_to_cpu(inits[i].size);
+		offset = le16_to_cpu(inits[i].addr);
+		value = le32_to_cpu(inits[i].value);
+		if (size == 2)
+			bcma_write16(core, offset, value);
+		else if (size == 4)
+			bcma_write32(core, offset, value);
+		else
+			break;
+	}
+}
+
+static void brcms_c_write_mhf(struct brcms_hardware *wlc_hw, u16 *mhfs)
+{
+	u8 idx;
+	u16 addr[] = {
+		M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4,
+		M_HOST_FLAGS5
+	};
+
+	for (idx = 0; idx < MHFMAX; idx++)
+		brcms_b_write_shm(wlc_hw, addr[idx], mhfs[idx]);
+}
+
+static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw)
+{
+	struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode;
+
+	/* init microcode host flags */
+	brcms_c_write_mhf(wlc_hw, wlc_hw->band->mhfs);
+
+	/* do band-specific ucode IHR, SHM, and SCR inits */
+	if (D11REV_IS(wlc_hw->corerev, 17) || D11REV_IS(wlc_hw->corerev, 23)) {
+		if (BRCMS_ISNPHY(wlc_hw->band))
+			brcms_c_write_inits(wlc_hw, ucode->d11n0bsinitvals16);
+		else
+			brcms_err(wlc_hw->d11core,
+				  "%s: wl%d: unsupported phy in corerev %d\n",
+				  __func__, wlc_hw->unit,
+				  wlc_hw->corerev);
+	} else {
+		if (D11REV_IS(wlc_hw->corerev, 24)) {
+			if (BRCMS_ISLCNPHY(wlc_hw->band))
+				brcms_c_write_inits(wlc_hw,
+						    ucode->d11lcn0bsinitvals24);
+			else
+				brcms_err(wlc_hw->d11core,
+					  "%s: wl%d: unsupported phy in core rev %d\n",
+					  __func__, wlc_hw->unit,
+					  wlc_hw->corerev);
+		} else {
+			brcms_err(wlc_hw->d11core,
+				  "%s: wl%d: unsupported corerev %d\n",
+				  __func__, wlc_hw->unit, wlc_hw->corerev);
+		}
+	}
+}
+
+static void brcms_b_core_ioctl(struct brcms_hardware *wlc_hw, u32 m, u32 v)
+{
+	struct bcma_device *core = wlc_hw->d11core;
+	u32 ioctl = bcma_aread32(core, BCMA_IOCTL) & ~m;
+
+	bcma_awrite32(core, BCMA_IOCTL, ioctl | v);
+}
+
+static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk)
+{
+	brcms_dbg_info(wlc_hw->d11core, "wl%d: clk %d\n", wlc_hw->unit, clk);
+
+	wlc_hw->phyclk = clk;
+
+	if (OFF == clk) {	/* clear gmode bit, put phy into reset */
+
+		brcms_b_core_ioctl(wlc_hw, (SICF_PRST | SICF_FGC | SICF_GMODE),
+				   (SICF_PRST | SICF_FGC));
+		udelay(1);
+		brcms_b_core_ioctl(wlc_hw, (SICF_PRST | SICF_FGC), SICF_PRST);
+		udelay(1);
+
+	} else {		/* take phy out of reset */
+
+		brcms_b_core_ioctl(wlc_hw, (SICF_PRST | SICF_FGC), SICF_FGC);
+		udelay(1);
+		brcms_b_core_ioctl(wlc_hw, SICF_FGC, 0);
+		udelay(1);
+
+	}
+}
+
+/* low-level band switch utility routine */
+static void brcms_c_setxband(struct brcms_hardware *wlc_hw, uint bandunit)
+{
+	brcms_dbg_mac80211(wlc_hw->d11core, "wl%d: bandunit %d\n", wlc_hw->unit,
+			   bandunit);
+
+	wlc_hw->band = wlc_hw->bandstate[bandunit];
+
+	/*
+	 * BMAC_NOTE:
+	 *   until we eliminate need for wlc->band refs in low level code
+	 */
+	wlc_hw->wlc->band = wlc_hw->wlc->bandstate[bandunit];
+
+	/* set gmode core flag */
+	if (wlc_hw->sbclk && !wlc_hw->noreset) {
+		u32 gmode = 0;
+
+		if (bandunit == 0)
+			gmode = SICF_GMODE;
+
+		brcms_b_core_ioctl(wlc_hw, SICF_GMODE, gmode);
+	}
+}
+
+/* switch to new band but leave it inactive */
+static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, uint bandunit)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	u32 macintmask;
+	u32 macctrl;
+
+	brcms_dbg_mac80211(wlc_hw->d11core, "wl%d\n", wlc_hw->unit);
+	macctrl = bcma_read32(wlc_hw->d11core,
+			      D11REGOFFS(maccontrol));
+	WARN_ON((macctrl & MCTL_EN_MAC) != 0);
+
+	/* disable interrupts */
+	macintmask = brcms_intrsoff(wlc->wl);
+
+	/* radio off */
+	wlc_phy_switch_radio(wlc_hw->band->pi, OFF);
+
+	brcms_b_core_phy_clk(wlc_hw, OFF);
+
+	brcms_c_setxband(wlc_hw, bandunit);
+
+	return macintmask;
+}
+
+/* process an individual struct tx_status */
+static bool
+brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
+{
+	struct sk_buff *p = NULL;
+	uint queue = NFIFO;
+	struct dma_pub *dma = NULL;
+	struct d11txh *txh = NULL;
+	struct scb *scb = NULL;
+	bool free_pdu;
+	int tx_rts, tx_frame_count, tx_rts_count;
+	uint totlen, supr_status;
+	bool lastframe;
+	struct ieee80211_hdr *h;
+	u16 mcl;
+	struct ieee80211_tx_info *tx_info;
+	struct ieee80211_tx_rate *txrate;
+	int i;
+	bool fatal = true;
+
+	trace_brcms_txstatus(&wlc->hw->d11core->dev, txs->framelen,
+			     txs->frameid, txs->status, txs->lasttxtime,
+			     txs->sequence, txs->phyerr, txs->ackphyrxsh);
+
+	/* discard intermediate indications for ucode with one legitimate case:
+	 *   e.g. if "useRTS" is set. ucode did a successful rts/cts exchange,
+	 *   but the subsequent tx of DATA failed. so it will start rts/cts
+	 *   from the beginning (resetting the rts transmission count)
+	 */
+	if (!(txs->status & TX_STATUS_AMPDU)
+	    && (txs->status & TX_STATUS_INTERMEDIATE)) {
+		brcms_dbg_tx(wlc->hw->d11core, "INTERMEDIATE but not AMPDU\n");
+		fatal = false;
+		goto out;
+	}
+
+	queue = txs->frameid & TXFID_QUEUE_MASK;
+	if (queue >= NFIFO) {
+		brcms_err(wlc->hw->d11core, "queue %u >= NFIFO\n", queue);
+		goto out;
+	}
+
+	dma = wlc->hw->di[queue];
+
+	p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED);
+	if (p == NULL) {
+		brcms_err(wlc->hw->d11core, "dma_getnexttxp returned null!\n");
+		goto out;
+	}
+
+	txh = (struct d11txh *) (p->data);
+	mcl = le16_to_cpu(txh->MacTxControlLow);
+
+	if (txs->phyerr)
+		brcms_dbg_tx(wlc->hw->d11core, "phyerr 0x%x, rate 0x%x\n",
+			     txs->phyerr, txh->MainRates);
+
+	if (txs->frameid != le16_to_cpu(txh->TxFrameID)) {
+		brcms_err(wlc->hw->d11core, "frameid != txh->TxFrameID\n");
+		goto out;
+	}
+	tx_info = IEEE80211_SKB_CB(p);
+	h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
+
+	if (tx_info->rate_driver_data[0])
+		scb = &wlc->pri_scb;
+
+	if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
+		brcms_c_ampdu_dotxstatus(wlc->ampdu, scb, p, txs);
+		fatal = false;
+		goto out;
+	}
+
+	/*
+	 * brcms_c_ampdu_dotxstatus() will trace tx descriptors for AMPDU
+	 * frames; this traces them for the rest.
+	 */
+	trace_brcms_txdesc(&wlc->hw->d11core->dev, txh, sizeof(*txh));
+
+	supr_status = txs->status & TX_STATUS_SUPR_MASK;
+	if (supr_status == TX_STATUS_SUPR_BADCH) {
+		unsigned xfts = le16_to_cpu(txh->XtraFrameTypes);
+		brcms_dbg_tx(wlc->hw->d11core,
+			     "Pkt tx suppressed, dest chan %u, current %d\n",
+			     (xfts >> XFTS_CHANNEL_SHIFT) & 0xff,
+			     CHSPEC_CHANNEL(wlc->default_bss->chanspec));
+	}
+
+	tx_rts = le16_to_cpu(txh->MacTxControlLow) & TXC_SENDRTS;
+	tx_frame_count =
+	    (txs->status & TX_STATUS_FRM_RTX_MASK) >> TX_STATUS_FRM_RTX_SHIFT;
+	tx_rts_count =
+	    (txs->status & TX_STATUS_RTS_RTX_MASK) >> TX_STATUS_RTS_RTX_SHIFT;
+
+	lastframe = !ieee80211_has_morefrags(h->frame_control);
+
+	if (!lastframe) {
+		brcms_err(wlc->hw->d11core, "Not last frame!\n");
+	} else {
+		/*
+		 * Set information to be consumed by Minstrel ht.
+		 *
+		 * The "fallback limit" is the number of tx attempts a given
+		 * MPDU is sent at the "primary" rate. Tx attempts beyond that
+		 * limit are sent at the "secondary" rate.
+		 * A 'short frame' does not exceed RTS treshold.
+		 */
+		u16 sfbl,	/* Short Frame Rate Fallback Limit */
+		    lfbl,	/* Long Frame Rate Fallback Limit */
+		    fbl;
+
+		if (queue < IEEE80211_NUM_ACS) {
+			sfbl = GFIELD(wlc->wme_retries[wme_fifo2ac[queue]],
+				      EDCF_SFB);
+			lfbl = GFIELD(wlc->wme_retries[wme_fifo2ac[queue]],
+				      EDCF_LFB);
+		} else {
+			sfbl = wlc->SFBL;
+			lfbl = wlc->LFBL;
+		}
+
+		txrate = tx_info->status.rates;
+		if (txrate[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
+			fbl = lfbl;
+		else
+			fbl = sfbl;
+
+		ieee80211_tx_info_clear_status(tx_info);
+
+		if ((tx_frame_count > fbl) && (txrate[1].idx >= 0)) {
+			/*
+			 * rate selection requested a fallback rate
+			 * and we used it
+			 */
+			txrate[0].count = fbl;
+			txrate[1].count = tx_frame_count - fbl;
+		} else {
+			/*
+			 * rate selection did not request fallback rate, or
+			 * we didn't need it
+			 */
+			txrate[0].count = tx_frame_count;
+			/*
+			 * rc80211_minstrel.c:minstrel_tx_status() expects
+			 * unused rates to be marked with idx = -1
+			 */
+			txrate[1].idx = -1;
+			txrate[1].count = 0;
+		}
+
+		/* clear the rest of the rates */
+		for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
+			txrate[i].idx = -1;
+			txrate[i].count = 0;
+		}
+
+		if (txs->status & TX_STATUS_ACK_RCV)
+			tx_info->flags |= IEEE80211_TX_STAT_ACK;
+	}
+
+	totlen = p->len;
+	free_pdu = true;
+
+	if (lastframe) {
+		/* remove PLCP & Broadcom tx descriptor header */
+		skb_pull(p, D11_PHY_HDR_LEN);
+		skb_pull(p, D11_TXH_LEN);
+		ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, p);
+	} else {
+		brcms_err(wlc->hw->d11core,
+			  "%s: Not last frame => not calling tx_status\n",
+			  __func__);
+	}
+
+	fatal = false;
+
+ out:
+	if (fatal) {
+		if (txh)
+			trace_brcms_txdesc(&wlc->hw->d11core->dev, txh,
+					   sizeof(*txh));
+		brcmu_pkt_buf_free_skb(p);
+	}
+
+	if (dma && queue < NFIFO) {
+		u16 ac_queue = brcms_fifo_to_ac(queue);
+		if (dma->txavail > TX_HEADROOM && queue < TX_BCMC_FIFO &&
+		    ieee80211_queue_stopped(wlc->pub->ieee_hw, ac_queue))
+			ieee80211_wake_queue(wlc->pub->ieee_hw, ac_queue);
+		dma_kick_tx(dma);
+	}
+
+	return fatal;
+}
+
+/* process tx completion events in BMAC
+ * Return true if more tx status need to be processed. false otherwise.
+ */
+static bool
+brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
+{
+	struct bcma_device *core;
+	struct tx_status txstatus, *txs;
+	u32 s1, s2;
+	uint n = 0;
+	/*
+	 * Param 'max_tx_num' indicates max. # tx status to process before
+	 * break out.
+	 */
+	uint max_tx_num = bound ? TXSBND : -1;
+
+	txs = &txstatus;
+	core = wlc_hw->d11core;
+	*fatal = false;
+
+	while (n < max_tx_num) {
+		s1 = bcma_read32(core, D11REGOFFS(frmtxstatus));
+		if (s1 == 0xffffffff) {
+			brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit,
+				  __func__);
+			*fatal = true;
+			return false;
+		}
+		/* only process when valid */
+		if (!(s1 & TXS_V))
+			break;
+
+		s2 = bcma_read32(core, D11REGOFFS(frmtxstatus2));
+		txs->status = s1 & TXS_STATUS_MASK;
+		txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT;
+		txs->sequence = s2 & TXS_SEQ_MASK;
+		txs->phyerr = (s2 & TXS_PTX_MASK) >> TXS_PTX_SHIFT;
+		txs->lasttxtime = 0;
+
+		*fatal = brcms_c_dotxstatus(wlc_hw->wlc, txs);
+		if (*fatal == true)
+			return false;
+		n++;
+	}
+
+	return n >= max_tx_num;
+}
+
+static void brcms_c_tbtt(struct brcms_c_info *wlc)
+{
+	if (wlc->bsscfg->type == BRCMS_TYPE_ADHOC)
+		/*
+		 * DirFrmQ is now valid...defer setting until end
+		 * of ATIM window
+		 */
+		wlc->qvalid |= MCMD_DIRFRMQVAL;
+}
+
+/* set initial host flags value */
+static void
+brcms_c_mhfdef(struct brcms_c_info *wlc, u16 *mhfs, u16 mhf2_init)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+
+	memset(mhfs, 0, MHFMAX * sizeof(u16));
+
+	mhfs[MHF2] |= mhf2_init;
+
+	/* prohibit use of slowclock on multifunction boards */
+	if (wlc_hw->boardflags & BFL_NOPLLDOWN)
+		mhfs[MHF1] |= MHF1_FORCEFASTCLK;
+
+	if (BRCMS_ISNPHY(wlc_hw->band) && NREV_LT(wlc_hw->band->phyrev, 2)) {
+		mhfs[MHF2] |= MHF2_NPHY40MHZ_WAR;
+		mhfs[MHF1] |= MHF1_IQSWAP_WAR;
+	}
+}
+
+static uint
+dmareg(uint direction, uint fifonum)
+{
+	if (direction == DMA_TX)
+		return offsetof(struct d11regs, fifo64regs[fifonum].dmaxmt);
+	return offsetof(struct d11regs, fifo64regs[fifonum].dmarcv);
+}
+
+static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme)
+{
+	uint i;
+	char name[8];
+	/*
+	 * ucode host flag 2 needed for pio mode, independent of band and fifo
+	 */
+	u16 pio_mhf2 = 0;
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	uint unit = wlc_hw->unit;
+
+	/* name and offsets for dma_attach */
+	snprintf(name, sizeof(name), "wl%d", unit);
+
+	if (wlc_hw->di[0] == NULL) {	/* Init FIFOs */
+		int dma_attach_err = 0;
+
+		/*
+		 * FIFO 0
+		 * TX: TX_AC_BK_FIFO (TX AC Background data packets)
+		 * RX: RX_FIFO (RX data packets)
+		 */
+		wlc_hw->di[0] = dma_attach(name, wlc,
+					   (wme ? dmareg(DMA_TX, 0) : 0),
+					   dmareg(DMA_RX, 0),
+					   (wme ? NTXD : 0), NRXD,
+					   RXBUFSZ, -1, NRXBUFPOST,
+					   BRCMS_HWRXOFF);
+		dma_attach_err |= (NULL == wlc_hw->di[0]);
+
+		/*
+		 * FIFO 1
+		 * TX: TX_AC_BE_FIFO (TX AC Best-Effort data packets)
+		 *   (legacy) TX_DATA_FIFO (TX data packets)
+		 * RX: UNUSED
+		 */
+		wlc_hw->di[1] = dma_attach(name, wlc,
+					   dmareg(DMA_TX, 1), 0,
+					   NTXD, 0, 0, -1, 0, 0);
+		dma_attach_err |= (NULL == wlc_hw->di[1]);
+
+		/*
+		 * FIFO 2
+		 * TX: TX_AC_VI_FIFO (TX AC Video data packets)
+		 * RX: UNUSED
+		 */
+		wlc_hw->di[2] = dma_attach(name, wlc,
+					   dmareg(DMA_TX, 2), 0,
+					   NTXD, 0, 0, -1, 0, 0);
+		dma_attach_err |= (NULL == wlc_hw->di[2]);
+		/*
+		 * FIFO 3
+		 * TX: TX_AC_VO_FIFO (TX AC Voice data packets)
+		 *   (legacy) TX_CTL_FIFO (TX control & mgmt packets)
+		 */
+		wlc_hw->di[3] = dma_attach(name, wlc,
+					   dmareg(DMA_TX, 3),
+					   0, NTXD, 0, 0, -1,
+					   0, 0);
+		dma_attach_err |= (NULL == wlc_hw->di[3]);
+/* Cleaner to leave this as if with AP defined */
+
+		if (dma_attach_err) {
+			brcms_err(wlc_hw->d11core,
+				  "wl%d: wlc_attach: dma_attach failed\n",
+				  unit);
+			return false;
+		}
+
+		/* get pointer to dma engine tx flow control variable */
+		for (i = 0; i < NFIFO; i++)
+			if (wlc_hw->di[i])
+				wlc_hw->txavail[i] =
+				    (uint *) dma_getvar(wlc_hw->di[i],
+							"&txavail");
+	}
+
+	/* initial ucode host flags */
+	brcms_c_mhfdef(wlc, wlc_hw->band->mhfs, pio_mhf2);
+
+	return true;
+}
+
+static void brcms_b_detach_dmapio(struct brcms_hardware *wlc_hw)
+{
+	uint j;
+
+	for (j = 0; j < NFIFO; j++) {
+		if (wlc_hw->di[j]) {
+			dma_detach(wlc_hw->di[j]);
+			wlc_hw->di[j] = NULL;
+		}
+	}
+}
+
+/*
+ * Initialize brcms_c_info default values ...
+ * may get overrides later in this function
+ *  BMAC_NOTES, move low out and resolve the dangling ones
+ */
+static void brcms_b_info_init(struct brcms_hardware *wlc_hw)
+{
+	struct brcms_c_info *wlc = wlc_hw->wlc;
+
+	/* set default sw macintmask value */
+	wlc->defmacintmask = DEF_MACINTMASK;
+
+	/* various 802.11g modes */
+	wlc_hw->shortslot = false;
+
+	wlc_hw->SFBL = RETRY_SHORT_FB;
+	wlc_hw->LFBL = RETRY_LONG_FB;
+
+	/* default mac retry limits */
+	wlc_hw->SRL = RETRY_SHORT_DEF;
+	wlc_hw->LRL = RETRY_LONG_DEF;
+	wlc_hw->chanspec = ch20mhz_chspec(1);
+}
+
+static void brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw)
+{
+	/* delay before first read of ucode state */
+	udelay(40);
+
+	/* wait until ucode is no longer asleep */
+	SPINWAIT((brcms_b_read_shm(wlc_hw, M_UCODE_DBGST) ==
+		  DBGST_ASLEEP), wlc_hw->wlc->fastpwrup_dly);
+}
+
+/* control chip clock to save power, enable dynamic clock or force fast clock */
+static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, enum bcma_clkmode mode)
+{
+	if (ai_get_cccaps(wlc_hw->sih) & CC_CAP_PMU) {
+		/* new chips with PMU, CCS_FORCEHT will distribute the HT clock
+		 * on backplane, but mac core will still run on ALP(not HT) when
+		 * it enters powersave mode, which means the FCA bit may not be
+		 * set. Should wakeup mac if driver wants it to run on HT.
+		 */
+
+		if (wlc_hw->clk) {
+			if (mode == BCMA_CLKMODE_FAST) {
+				bcma_set32(wlc_hw->d11core,
+					   D11REGOFFS(clk_ctl_st),
+					   CCS_FORCEHT);
+
+				udelay(64);
+
+				SPINWAIT(
+				    ((bcma_read32(wlc_hw->d11core,
+				      D11REGOFFS(clk_ctl_st)) &
+				      CCS_HTAVAIL) == 0),
+				      PMU_MAX_TRANSITION_DLY);
+				WARN_ON(!(bcma_read32(wlc_hw->d11core,
+					D11REGOFFS(clk_ctl_st)) &
+					CCS_HTAVAIL));
+			} else {
+				if ((ai_get_pmurev(wlc_hw->sih) == 0) &&
+				    (bcma_read32(wlc_hw->d11core,
+					D11REGOFFS(clk_ctl_st)) &
+					(CCS_FORCEHT | CCS_HTAREQ)))
+					SPINWAIT(
+					    ((bcma_read32(wlc_hw->d11core,
+					      offsetof(struct d11regs,
+						       clk_ctl_st)) &
+					      CCS_HTAVAIL) == 0),
+					      PMU_MAX_TRANSITION_DLY);
+				bcma_mask32(wlc_hw->d11core,
+					D11REGOFFS(clk_ctl_st),
+					~CCS_FORCEHT);
+			}
+		}
+		wlc_hw->forcefastclk = (mode == BCMA_CLKMODE_FAST);
+	} else {
+
+		/* old chips w/o PMU, force HT through cc,
+		 * then use FCA to verify mac is running fast clock
+		 */
+
+		wlc_hw->forcefastclk = ai_clkctl_cc(wlc_hw->sih, mode);
+
+		/* check fast clock is available (if core is not in reset) */
+		if (wlc_hw->forcefastclk && wlc_hw->clk)
+			WARN_ON(!(bcma_aread32(wlc_hw->d11core, BCMA_IOST) &
+				  SISF_FCLKA));
+
+		/*
+		 * keep the ucode wake bit on if forcefastclk is on since we
+		 * do not want ucode to put us back to slow clock when it dozes
+		 * for PM mode. Code below matches the wake override bit with
+		 * current forcefastclk state. Only setting bit in wake_override
+		 * instead of waking ucode immediately since old code had this
+		 * behavior. Older code set wlc->forcefastclk but only had the
+		 * wake happen if the wakup_ucode work (protected by an up
+		 * check) was executed just below.
+		 */
+		if (wlc_hw->forcefastclk)
+			mboolset(wlc_hw->wake_override,
+				 BRCMS_WAKE_OVERRIDE_FORCEFAST);
+		else
+			mboolclr(wlc_hw->wake_override,
+				 BRCMS_WAKE_OVERRIDE_FORCEFAST);
+	}
+}
+
+/* set or clear ucode host flag bits
+ * it has an optimization for no-change write
+ * it only writes through shared memory when the core has clock;
+ * pre-CLK changes should use wlc_write_mhf to get around the optimization
+ *
+ *
+ * bands values are: BRCM_BAND_AUTO <--- Current band only
+ *                   BRCM_BAND_5G   <--- 5G band only
+ *                   BRCM_BAND_2G   <--- 2G band only
+ *                   BRCM_BAND_ALL  <--- All bands
+ */
+void
+brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask, u16 val,
+	     int bands)
+{
+	u16 save;
+	u16 addr[MHFMAX] = {
+		M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4,
+		M_HOST_FLAGS5
+	};
+	struct brcms_hw_band *band;
+
+	if ((val & ~mask) || idx >= MHFMAX)
+		return; /* error condition */
+
+	switch (bands) {
+		/* Current band only or all bands,
+		 * then set the band to current band
+		 */
+	case BRCM_BAND_AUTO:
+	case BRCM_BAND_ALL:
+		band = wlc_hw->band;
+		break;
+	case BRCM_BAND_5G:
+		band = wlc_hw->bandstate[BAND_5G_INDEX];
+		break;
+	case BRCM_BAND_2G:
+		band = wlc_hw->bandstate[BAND_2G_INDEX];
+		break;
+	default:
+		band = NULL;	/* error condition */
+	}
+
+	if (band) {
+		save = band->mhfs[idx];
+		band->mhfs[idx] = (band->mhfs[idx] & ~mask) | val;
+
+		/* optimization: only write through if changed, and
+		 * changed band is the current band
+		 */
+		if (wlc_hw->clk && (band->mhfs[idx] != save)
+		    && (band == wlc_hw->band))
+			brcms_b_write_shm(wlc_hw, addr[idx],
+					   (u16) band->mhfs[idx]);
+	}
+
+	if (bands == BRCM_BAND_ALL) {
+		wlc_hw->bandstate[0]->mhfs[idx] =
+		    (wlc_hw->bandstate[0]->mhfs[idx] & ~mask) | val;
+		wlc_hw->bandstate[1]->mhfs[idx] =
+		    (wlc_hw->bandstate[1]->mhfs[idx] & ~mask) | val;
+	}
+}
+
+/* set the maccontrol register to desired reset state and
+ * initialize the sw cache of the register
+ */
+static void brcms_c_mctrl_reset(struct brcms_hardware *wlc_hw)
+{
+	/* IHR accesses are always enabled, PSM disabled, HPS off and WAKE on */
+	wlc_hw->maccontrol = 0;
+	wlc_hw->suspended_fifos = 0;
+	wlc_hw->wake_override = 0;
+	wlc_hw->mute_override = 0;
+	brcms_b_mctrl(wlc_hw, ~0, MCTL_IHR_EN | MCTL_WAKE);
+}
+
+/*
+ * write the software state of maccontrol and
+ * overrides to the maccontrol register
+ */
+static void brcms_c_mctrl_write(struct brcms_hardware *wlc_hw)
+{
+	u32 maccontrol = wlc_hw->maccontrol;
+
+	/* OR in the wake bit if overridden */
+	if (wlc_hw->wake_override)
+		maccontrol |= MCTL_WAKE;
+
+	/* set AP and INFRA bits for mute if needed */
+	if (wlc_hw->mute_override) {
+		maccontrol &= ~(MCTL_AP);
+		maccontrol |= MCTL_INFRA;
+	}
+
+	bcma_write32(wlc_hw->d11core, D11REGOFFS(maccontrol),
+		     maccontrol);
+}
+
+/* set or clear maccontrol bits */
+void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val)
+{
+	u32 maccontrol;
+	u32 new_maccontrol;
+
+	if (val & ~mask)
+		return; /* error condition */
+	maccontrol = wlc_hw->maccontrol;
+	new_maccontrol = (maccontrol & ~mask) | val;
+
+	/* if the new maccontrol value is the same as the old, nothing to do */
+	if (new_maccontrol == maccontrol)
+		return;
+
+	/* something changed, cache the new value */
+	wlc_hw->maccontrol = new_maccontrol;
+
+	/* write the new values with overrides applied */
+	brcms_c_mctrl_write(wlc_hw);
+}
+
+void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw,
+				 u32 override_bit)
+{
+	if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE)) {
+		mboolset(wlc_hw->wake_override, override_bit);
+		return;
+	}
+
+	mboolset(wlc_hw->wake_override, override_bit);
+
+	brcms_c_mctrl_write(wlc_hw);
+	brcms_b_wait_for_wake(wlc_hw);
+}
+
+void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw,
+				   u32 override_bit)
+{
+	mboolclr(wlc_hw->wake_override, override_bit);
+
+	if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE))
+		return;
+
+	brcms_c_mctrl_write(wlc_hw);
+}
+
+/* When driver needs ucode to stop beaconing, it has to make sure that
+ * MCTL_AP is clear and MCTL_INFRA is set
+ * Mode           MCTL_AP        MCTL_INFRA
+ * AP                1              1
+ * STA               0              1 <--- This will ensure no beacons
+ * IBSS              0              0
+ */
+static void brcms_c_ucode_mute_override_set(struct brcms_hardware *wlc_hw)
+{
+	wlc_hw->mute_override = 1;
+
+	/* if maccontrol already has AP == 0 and INFRA == 1 without this
+	 * override, then there is no change to write
+	 */
+	if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA)
+		return;
+
+	brcms_c_mctrl_write(wlc_hw);
+}
+
+/* Clear the override on AP and INFRA bits */
+static void brcms_c_ucode_mute_override_clear(struct brcms_hardware *wlc_hw)
+{
+	if (wlc_hw->mute_override == 0)
+		return;
+
+	wlc_hw->mute_override = 0;
+
+	/* if maccontrol already has AP == 0 and INFRA == 1 without this
+	 * override, then there is no change to write
+	 */
+	if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA)
+		return;
+
+	brcms_c_mctrl_write(wlc_hw);
+}
+
+/*
+ * Write a MAC address to the given match reg offset in the RXE match engine.
+ */
+static void
+brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw, int match_reg_offset,
+		       const u8 *addr)
+{
+	struct bcma_device *core = wlc_hw->d11core;
+	u16 mac_l;
+	u16 mac_m;
+	u16 mac_h;
+
+	brcms_dbg_rx(core, "wl%d: brcms_b_set_addrmatch\n", wlc_hw->unit);
+
+	mac_l = addr[0] | (addr[1] << 8);
+	mac_m = addr[2] | (addr[3] << 8);
+	mac_h = addr[4] | (addr[5] << 8);
+
+	/* enter the MAC addr into the RXE match registers */
+	bcma_write16(core, D11REGOFFS(rcm_ctl),
+		     RCM_INC_DATA | match_reg_offset);
+	bcma_write16(core, D11REGOFFS(rcm_mat_data), mac_l);
+	bcma_write16(core, D11REGOFFS(rcm_mat_data), mac_m);
+	bcma_write16(core, D11REGOFFS(rcm_mat_data), mac_h);
+}
+
+void
+brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset, int len,
+			    void *buf)
+{
+	struct bcma_device *core = wlc_hw->d11core;
+	u32 word;
+	__le32 word_le;
+	__be32 word_be;
+	bool be_bit;
+	brcms_dbg_info(core, "wl%d\n", wlc_hw->unit);
+
+	bcma_write32(core, D11REGOFFS(tplatewrptr), offset);
+
+	/* if MCTL_BIGEND bit set in mac control register,
+	 * the chip swaps data in fifo, as well as data in
+	 * template ram
+	 */
+	be_bit = (bcma_read32(core, D11REGOFFS(maccontrol)) & MCTL_BIGEND) != 0;
+
+	while (len > 0) {
+		memcpy(&word, buf, sizeof(u32));
+
+		if (be_bit) {
+			word_be = cpu_to_be32(word);
+			word = *(u32 *)&word_be;
+		} else {
+			word_le = cpu_to_le32(word);
+			word = *(u32 *)&word_le;
+		}
+
+		bcma_write32(core, D11REGOFFS(tplatewrdata), word);
+
+		buf = (u8 *) buf + sizeof(u32);
+		len -= sizeof(u32);
+	}
+}
+
+static void brcms_b_set_cwmin(struct brcms_hardware *wlc_hw, u16 newmin)
+{
+	wlc_hw->band->CWmin = newmin;
+
+	bcma_write32(wlc_hw->d11core, D11REGOFFS(objaddr),
+		     OBJADDR_SCR_SEL | S_DOT11_CWMIN);
+	(void)bcma_read32(wlc_hw->d11core, D11REGOFFS(objaddr));
+	bcma_write32(wlc_hw->d11core, D11REGOFFS(objdata), newmin);
+}
+
+static void brcms_b_set_cwmax(struct brcms_hardware *wlc_hw, u16 newmax)
+{
+	wlc_hw->band->CWmax = newmax;
+
+	bcma_write32(wlc_hw->d11core, D11REGOFFS(objaddr),
+		     OBJADDR_SCR_SEL | S_DOT11_CWMAX);
+	(void)bcma_read32(wlc_hw->d11core, D11REGOFFS(objaddr));
+	bcma_write32(wlc_hw->d11core, D11REGOFFS(objdata), newmax);
+}
+
+void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw)
+{
+	bool fastclk;
+
+	/* request FAST clock if not on */
+	fastclk = wlc_hw->forcefastclk;
+	if (!fastclk)
+		brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST);
+
+	wlc_phy_bw_state_set(wlc_hw->band->pi, bw);
+
+	brcms_b_phy_reset(wlc_hw);
+	wlc_phy_init(wlc_hw->band->pi, wlc_phy_chanspec_get(wlc_hw->band->pi));
+
+	/* restore the clk */
+	if (!fastclk)
+		brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_DYNAMIC);
+}
+
+static void brcms_b_upd_synthpu(struct brcms_hardware *wlc_hw)
+{
+	u16 v;
+	struct brcms_c_info *wlc = wlc_hw->wlc;
+	/* update SYNTHPU_DLY */
+
+	if (BRCMS_ISLCNPHY(wlc->band))
+		v = SYNTHPU_DLY_LPPHY_US;
+	else if (BRCMS_ISNPHY(wlc->band) && (NREV_GE(wlc->band->phyrev, 3)))
+		v = SYNTHPU_DLY_NPHY_US;
+	else
+		v = SYNTHPU_DLY_BPHY_US;
+
+	brcms_b_write_shm(wlc_hw, M_SYNTHPU_DLY, v);
+}
+
+static void brcms_c_ucode_txant_set(struct brcms_hardware *wlc_hw)
+{
+	u16 phyctl;
+	u16 phytxant = wlc_hw->bmac_phytxant;
+	u16 mask = PHY_TXC_ANT_MASK;
+
+	/* set the Probe Response frame phy control word */
+	phyctl = brcms_b_read_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS);
+	phyctl = (phyctl & ~mask) | phytxant;
+	brcms_b_write_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS, phyctl);
+
+	/* set the Response (ACK/CTS) frame phy control word */
+	phyctl = brcms_b_read_shm(wlc_hw, M_RSP_PCTLWD);
+	phyctl = (phyctl & ~mask) | phytxant;
+	brcms_b_write_shm(wlc_hw, M_RSP_PCTLWD, phyctl);
+}
+
+static u16 brcms_b_ofdm_ratetable_offset(struct brcms_hardware *wlc_hw,
+					 u8 rate)
+{
+	uint i;
+	u8 plcp_rate = 0;
+	struct plcp_signal_rate_lookup {
+		u8 rate;
+		u8 signal_rate;
+	};
+	/* OFDM RATE sub-field of PLCP SIGNAL field, per 802.11 sec 17.3.4.1 */
+	const struct plcp_signal_rate_lookup rate_lookup[] = {
+		{BRCM_RATE_6M, 0xB},
+		{BRCM_RATE_9M, 0xF},
+		{BRCM_RATE_12M, 0xA},
+		{BRCM_RATE_18M, 0xE},
+		{BRCM_RATE_24M, 0x9},
+		{BRCM_RATE_36M, 0xD},
+		{BRCM_RATE_48M, 0x8},
+		{BRCM_RATE_54M, 0xC}
+	};
+
+	for (i = 0; i < ARRAY_SIZE(rate_lookup); i++) {
+		if (rate == rate_lookup[i].rate) {
+			plcp_rate = rate_lookup[i].signal_rate;
+			break;
+		}
+	}
+
+	/* Find the SHM pointer to the rate table entry by looking in the
+	 * Direct-map Table
+	 */
+	return 2 * brcms_b_read_shm(wlc_hw, M_RT_DIRMAP_A + (plcp_rate * 2));
+}
+
+static void brcms_upd_ofdm_pctl1_table(struct brcms_hardware *wlc_hw)
+{
+	u8 rate;
+	u8 rates[8] = {
+		BRCM_RATE_6M, BRCM_RATE_9M, BRCM_RATE_12M, BRCM_RATE_18M,
+		BRCM_RATE_24M, BRCM_RATE_36M, BRCM_RATE_48M, BRCM_RATE_54M
+	};
+	u16 entry_ptr;
+	u16 pctl1;
+	uint i;
+
+	if (!BRCMS_PHY_11N_CAP(wlc_hw->band))
+		return;
+
+	/* walk the phy rate table and update the entries */
+	for (i = 0; i < ARRAY_SIZE(rates); i++) {
+		rate = rates[i];
+
+		entry_ptr = brcms_b_ofdm_ratetable_offset(wlc_hw, rate);
+
+		/* read the SHM Rate Table entry OFDM PCTL1 values */
+		pctl1 =
+		    brcms_b_read_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS);
+
+		/* modify the value */
+		pctl1 &= ~PHY_TXC1_MODE_MASK;
+		pctl1 |= (wlc_hw->hw_stf_ss_opmode << PHY_TXC1_MODE_SHIFT);
+
+		/* Update the SHM Rate Table entry OFDM PCTL1 values */
+		brcms_b_write_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS,
+				   pctl1);
+	}
+}
+
+/* band-specific init */
+static void brcms_b_bsinit(struct brcms_c_info *wlc, u16 chanspec)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+
+	brcms_dbg_mac80211(wlc_hw->d11core, "wl%d: bandunit %d\n", wlc_hw->unit,
+			   wlc_hw->band->bandunit);
+
+	brcms_c_ucode_bsinit(wlc_hw);
+
+	wlc_phy_init(wlc_hw->band->pi, chanspec);
+
+	brcms_c_ucode_txant_set(wlc_hw);
+
+	/*
+	 * cwmin is band-specific, update hardware
+	 * with value for current band
+	 */
+	brcms_b_set_cwmin(wlc_hw, wlc_hw->band->CWmin);
+	brcms_b_set_cwmax(wlc_hw, wlc_hw->band->CWmax);
+
+	brcms_b_update_slot_timing(wlc_hw,
+				   wlc_hw->band->bandtype == BRCM_BAND_5G ?
+				   true : wlc_hw->shortslot);
+
+	/* write phytype and phyvers */
+	brcms_b_write_shm(wlc_hw, M_PHYTYPE, (u16) wlc_hw->band->phytype);
+	brcms_b_write_shm(wlc_hw, M_PHYVER, (u16) wlc_hw->band->phyrev);
+
+	/*
+	 * initialize the txphyctl1 rate table since
+	 * shmem is shared between bands
+	 */
+	brcms_upd_ofdm_pctl1_table(wlc_hw);
+
+	brcms_b_upd_synthpu(wlc_hw);
+}
+
+/* Perform a soft reset of the PHY PLL */
+void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw)
+{
+	ai_cc_reg(wlc_hw->sih, offsetof(struct chipcregs, chipcontrol_addr),
+		  ~0, 0);
+	udelay(1);
+	ai_cc_reg(wlc_hw->sih, offsetof(struct chipcregs, chipcontrol_data),
+		  0x4, 0);
+	udelay(1);
+	ai_cc_reg(wlc_hw->sih, offsetof(struct chipcregs, chipcontrol_data),
+		  0x4, 4);
+	udelay(1);
+	ai_cc_reg(wlc_hw->sih, offsetof(struct chipcregs, chipcontrol_data),
+		  0x4, 0);
+	udelay(1);
+}
+
+/* light way to turn on phy clock without reset for NPHY only
+ *  refer to brcms_b_core_phy_clk for full version
+ */
+void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk)
+{
+	/* support(necessary for NPHY and HYPHY) only */
+	if (!BRCMS_ISNPHY(wlc_hw->band))
+		return;
+
+	if (ON == clk)
+		brcms_b_core_ioctl(wlc_hw, SICF_FGC, SICF_FGC);
+	else
+		brcms_b_core_ioctl(wlc_hw, SICF_FGC, 0);
+
+}
+
+void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk)
+{
+	if (ON == clk)
+		brcms_b_core_ioctl(wlc_hw, SICF_MPCLKE, SICF_MPCLKE);
+	else
+		brcms_b_core_ioctl(wlc_hw, SICF_MPCLKE, 0);
+}
+
+void brcms_b_phy_reset(struct brcms_hardware *wlc_hw)
+{
+	struct brcms_phy_pub *pih = wlc_hw->band->pi;
+	u32 phy_bw_clkbits;
+	bool phy_in_reset = false;
+
+	brcms_dbg_info(wlc_hw->d11core, "wl%d: reset phy\n", wlc_hw->unit);
+
+	if (pih == NULL)
+		return;
+
+	phy_bw_clkbits = wlc_phy_clk_bwbits(wlc_hw->band->pi);
+
+	/* Specific reset sequence required for NPHY rev 3 and 4 */
+	if (BRCMS_ISNPHY(wlc_hw->band) && NREV_GE(wlc_hw->band->phyrev, 3) &&
+	    NREV_LE(wlc_hw->band->phyrev, 4)) {
+		/* Set the PHY bandwidth */
+		brcms_b_core_ioctl(wlc_hw, SICF_BWMASK, phy_bw_clkbits);
+
+		udelay(1);
+
+		/* Perform a soft reset of the PHY PLL */
+		brcms_b_core_phypll_reset(wlc_hw);
+
+		/* reset the PHY */
+		brcms_b_core_ioctl(wlc_hw, (SICF_PRST | SICF_PCLKE),
+				   (SICF_PRST | SICF_PCLKE));
+		phy_in_reset = true;
+	} else {
+		brcms_b_core_ioctl(wlc_hw,
+				   (SICF_PRST | SICF_PCLKE | SICF_BWMASK),
+				   (SICF_PRST | SICF_PCLKE | phy_bw_clkbits));
+	}
+
+	udelay(2);
+	brcms_b_core_phy_clk(wlc_hw, ON);
+
+	if (pih)
+		wlc_phy_anacore(pih, ON);
+}
+
+/* switch to and initialize new band */
+static void brcms_b_setband(struct brcms_hardware *wlc_hw, uint bandunit,
+			    u16 chanspec) {
+	struct brcms_c_info *wlc = wlc_hw->wlc;
+	u32 macintmask;
+
+	/* Enable the d11 core before accessing it */
+	if (!bcma_core_is_enabled(wlc_hw->d11core)) {
+		bcma_core_enable(wlc_hw->d11core, 0);
+		brcms_c_mctrl_reset(wlc_hw);
+	}
+
+	macintmask = brcms_c_setband_inact(wlc, bandunit);
+
+	if (!wlc_hw->up)
+		return;
+
+	brcms_b_core_phy_clk(wlc_hw, ON);
+
+	/* band-specific initializations */
+	brcms_b_bsinit(wlc, chanspec);
+
+	/*
+	 * If there are any pending software interrupt bits,
+	 * then replace these with a harmless nonzero value
+	 * so brcms_c_dpc() will re-enable interrupts when done.
+	 */
+	if (wlc->macintstatus)
+		wlc->macintstatus = MI_DMAINT;
+
+	/* restore macintmask */
+	brcms_intrsrestore(wlc->wl, macintmask);
+
+	/* ucode should still be suspended.. */
+	WARN_ON((bcma_read32(wlc_hw->d11core, D11REGOFFS(maccontrol)) &
+		 MCTL_EN_MAC) != 0);
+}
+
+static bool brcms_c_isgoodchip(struct brcms_hardware *wlc_hw)
+{
+
+	/* reject unsupported corerev */
+	if (!CONF_HAS(D11CONF, wlc_hw->corerev)) {
+		wiphy_err(wlc_hw->wlc->wiphy, "unsupported core rev %d\n",
+			  wlc_hw->corerev);
+		return false;
+	}
+
+	return true;
+}
+
+/* Validate some board info parameters */
+static bool brcms_c_validboardtype(struct brcms_hardware *wlc_hw)
+{
+	uint boardrev = wlc_hw->boardrev;
+
+	/* 4 bits each for board type, major, minor, and tiny version */
+	uint brt = (boardrev & 0xf000) >> 12;
+	uint b0 = (boardrev & 0xf00) >> 8;
+	uint b1 = (boardrev & 0xf0) >> 4;
+	uint b2 = boardrev & 0xf;
+
+	/* voards from other vendors are always considered valid */
+	if (ai_get_boardvendor(wlc_hw->sih) != PCI_VENDOR_ID_BROADCOM)
+		return true;
+
+	/* do some boardrev sanity checks when boardvendor is Broadcom */
+	if (boardrev == 0)
+		return false;
+
+	if (boardrev <= 0xff)
+		return true;
+
+	if ((brt > 2) || (brt == 0) || (b0 > 9) || (b0 == 0) || (b1 > 9)
+		|| (b2 > 9))
+		return false;
+
+	return true;
+}
+
+static void brcms_c_get_macaddr(struct brcms_hardware *wlc_hw, u8 etheraddr[ETH_ALEN])
+{
+	struct ssb_sprom *sprom = &wlc_hw->d11core->bus->sprom;
+
+	/* If macaddr exists, use it (Sromrev4, CIS, ...). */
+	if (!is_zero_ether_addr(sprom->il0mac)) {
+		memcpy(etheraddr, sprom->il0mac, ETH_ALEN);
+		return;
+	}
+
+	if (wlc_hw->_nbands > 1)
+		memcpy(etheraddr, sprom->et1mac, ETH_ALEN);
+	else
+		memcpy(etheraddr, sprom->il0mac, ETH_ALEN);
+}
+
+/* power both the pll and external oscillator on/off */
+static void brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want)
+{
+	brcms_dbg_info(wlc_hw->d11core, "wl%d: want %d\n", wlc_hw->unit, want);
+
+	/*
+	 * dont power down if plldown is false or
+	 * we must poll hw radio disable
+	 */
+	if (!want && wlc_hw->pllreq)
+		return;
+
+	wlc_hw->sbclk = want;
+	if (!wlc_hw->sbclk) {
+		wlc_hw->clk = false;
+		if (wlc_hw->band && wlc_hw->band->pi)
+			wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
+	}
+}
+
+/*
+ * Return true if radio is disabled, otherwise false.
+ * hw radio disable signal is an external pin, users activate it asynchronously
+ * this function could be called when driver is down and w/o clock
+ * it operates on different registers depending on corerev and boardflag.
+ */
+static bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw)
+{
+	bool v, clk, xtal;
+	u32 flags = 0;
+
+	xtal = wlc_hw->sbclk;
+	if (!xtal)
+		brcms_b_xtal(wlc_hw, ON);
+
+	/* may need to take core out of reset first */
+	clk = wlc_hw->clk;
+	if (!clk) {
+		/*
+		 * mac no longer enables phyclk automatically when driver
+		 * accesses phyreg throughput mac. This can be skipped since
+		 * only mac reg is accessed below
+		 */
+		if (D11REV_GE(wlc_hw->corerev, 18))
+			flags |= SICF_PCLKE;
+
+		/*
+		 * TODO: test suspend/resume
+		 *
+		 * AI chip doesn't restore bar0win2 on
+		 * hibernation/resume, need sw fixup
+		 */
+
+		bcma_core_enable(wlc_hw->d11core, flags);
+		brcms_c_mctrl_reset(wlc_hw);
+	}
+
+	v = ((bcma_read32(wlc_hw->d11core,
+			  D11REGOFFS(phydebug)) & PDBG_RFD) != 0);
+
+	/* put core back into reset */
+	if (!clk)
+		bcma_core_disable(wlc_hw->d11core, 0);
+
+	if (!xtal)
+		brcms_b_xtal(wlc_hw, OFF);
+
+	return v;
+}
+
+static bool wlc_dma_rxreset(struct brcms_hardware *wlc_hw, uint fifo)
+{
+	struct dma_pub *di = wlc_hw->di[fifo];
+	return dma_rxreset(di);
+}
+
+/* d11 core reset
+ *   ensure fask clock during reset
+ *   reset dma
+ *   reset d11(out of reset)
+ *   reset phy(out of reset)
+ *   clear software macintstatus for fresh new start
+ * one testing hack wlc_hw->noreset will bypass the d11/phy reset
+ */
+void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags)
+{
+	uint i;
+	bool fastclk;
+
+	if (flags == BRCMS_USE_COREFLAGS)
+		flags = (wlc_hw->band->pi ? wlc_hw->band->core_flags : 0);
+
+	brcms_dbg_info(wlc_hw->d11core, "wl%d: core reset\n", wlc_hw->unit);
+
+	/* request FAST clock if not on  */
+	fastclk = wlc_hw->forcefastclk;
+	if (!fastclk)
+		brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST);
+
+	/* reset the dma engines except first time thru */
+	if (bcma_core_is_enabled(wlc_hw->d11core)) {
+		for (i = 0; i < NFIFO; i++)
+			if ((wlc_hw->di[i]) && (!dma_txreset(wlc_hw->di[i])))
+				brcms_err(wlc_hw->d11core, "wl%d: %s: "
+					  "dma_txreset[%d]: cannot stop dma\n",
+					   wlc_hw->unit, __func__, i);
+
+		if ((wlc_hw->di[RX_FIFO])
+		    && (!wlc_dma_rxreset(wlc_hw, RX_FIFO)))
+			brcms_err(wlc_hw->d11core, "wl%d: %s: dma_rxreset"
+				  "[%d]: cannot stop dma\n",
+				  wlc_hw->unit, __func__, RX_FIFO);
+	}
+	/* if noreset, just stop the psm and return */
+	if (wlc_hw->noreset) {
+		wlc_hw->wlc->macintstatus = 0;	/* skip wl_dpc after down */
+		brcms_b_mctrl(wlc_hw, MCTL_PSM_RUN | MCTL_EN_MAC, 0);
+		return;
+	}
+
+	/*
+	 * mac no longer enables phyclk automatically when driver accesses
+	 * phyreg throughput mac, AND phy_reset is skipped at early stage when
+	 * band->pi is invalid. need to enable PHY CLK
+	 */
+	if (D11REV_GE(wlc_hw->corerev, 18))
+		flags |= SICF_PCLKE;
+
+	/*
+	 * reset the core
+	 * In chips with PMU, the fastclk request goes through d11 core
+	 * reg 0x1e0, which is cleared by the core_reset. have to re-request it.
+	 *
+	 * This adds some delay and we can optimize it by also requesting
+	 * fastclk through chipcommon during this period if necessary. But
+	 * that has to work coordinate with other driver like mips/arm since
+	 * they may touch chipcommon as well.
+	 */
+	wlc_hw->clk = false;
+	bcma_core_enable(wlc_hw->d11core, flags);
+	wlc_hw->clk = true;
+	if (wlc_hw->band && wlc_hw->band->pi)
+		wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, true);
+
+	brcms_c_mctrl_reset(wlc_hw);
+
+	if (ai_get_cccaps(wlc_hw->sih) & CC_CAP_PMU)
+		brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST);
+
+	brcms_b_phy_reset(wlc_hw);
+
+	/* turn on PHY_PLL */
+	brcms_b_core_phypll_ctl(wlc_hw, true);
+
+	/* clear sw intstatus */
+	wlc_hw->wlc->macintstatus = 0;
+
+	/* restore the clk setting */
+	if (!fastclk)
+		brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_DYNAMIC);
+}
+
+/* txfifo sizes needs to be modified(increased) since the newer cores
+ * have more memory.
+ */
+static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw)
+{
+	struct bcma_device *core = wlc_hw->d11core;
+	u16 fifo_nu;
+	u16 txfifo_startblk = TXFIFO_START_BLK, txfifo_endblk;
+	u16 txfifo_def, txfifo_def1;
+	u16 txfifo_cmd;
+
+	/* tx fifos start at TXFIFO_START_BLK from the Base address */
+	txfifo_startblk = TXFIFO_START_BLK;
+
+	/* sequence of operations:  reset fifo, set fifo size, reset fifo */
+	for (fifo_nu = 0; fifo_nu < NFIFO; fifo_nu++) {
+
+		txfifo_endblk = txfifo_startblk + wlc_hw->xmtfifo_sz[fifo_nu];
+		txfifo_def = (txfifo_startblk & 0xff) |
+		    (((txfifo_endblk - 1) & 0xff) << TXFIFO_FIFOTOP_SHIFT);
+		txfifo_def1 = ((txfifo_startblk >> 8) & 0x1) |
+		    ((((txfifo_endblk -
+			1) >> 8) & 0x1) << TXFIFO_FIFOTOP_SHIFT);
+		txfifo_cmd =
+		    TXFIFOCMD_RESET_MASK | (fifo_nu << TXFIFOCMD_FIFOSEL_SHIFT);
+
+		bcma_write16(core, D11REGOFFS(xmtfifocmd), txfifo_cmd);
+		bcma_write16(core, D11REGOFFS(xmtfifodef), txfifo_def);
+		bcma_write16(core, D11REGOFFS(xmtfifodef1), txfifo_def1);
+
+		bcma_write16(core, D11REGOFFS(xmtfifocmd), txfifo_cmd);
+
+		txfifo_startblk += wlc_hw->xmtfifo_sz[fifo_nu];
+	}
+	/*
+	 * need to propagate to shm location to be in sync since ucode/hw won't
+	 * do this
+	 */
+	brcms_b_write_shm(wlc_hw, M_FIFOSIZE0,
+			   wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]);
+	brcms_b_write_shm(wlc_hw, M_FIFOSIZE1,
+			   wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]);
+	brcms_b_write_shm(wlc_hw, M_FIFOSIZE2,
+			   ((wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO] << 8) | wlc_hw->
+			    xmtfifo_sz[TX_AC_BK_FIFO]));
+	brcms_b_write_shm(wlc_hw, M_FIFOSIZE3,
+			   ((wlc_hw->xmtfifo_sz[TX_ATIM_FIFO] << 8) | wlc_hw->
+			    xmtfifo_sz[TX_BCMC_FIFO]));
+}
+
+/* This function is used for changing the tsf frac register
+ * If spur avoidance mode is off, the mac freq will be 80/120/160Mhz
+ * If spur avoidance mode is on1, the mac freq will be 82/123/164Mhz
+ * If spur avoidance mode is on2, the mac freq will be 84/126/168Mhz
+ * HTPHY Formula is 2^26/freq(MHz) e.g.
+ * For spuron2 - 126MHz -> 2^26/126 = 532610.0
+ *  - 532610 = 0x82082 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x2082
+ * For spuron: 123MHz -> 2^26/123    = 545600.5
+ *  - 545601 = 0x85341 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x5341
+ * For spur off: 120MHz -> 2^26/120    = 559240.5
+ *  - 559241 = 0x88889 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x8889
+ */
+
+void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode)
+{
+	struct bcma_device *core = wlc_hw->d11core;
+
+	if ((ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM43224) ||
+	    (ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM43225)) {
+		if (spurmode == WL_SPURAVOID_ON2) {	/* 126Mhz */
+			bcma_write16(core, D11REGOFFS(tsf_clk_frac_l), 0x2082);
+			bcma_write16(core, D11REGOFFS(tsf_clk_frac_h), 0x8);
+		} else if (spurmode == WL_SPURAVOID_ON1) {	/* 123Mhz */
+			bcma_write16(core, D11REGOFFS(tsf_clk_frac_l), 0x5341);
+			bcma_write16(core, D11REGOFFS(tsf_clk_frac_h), 0x8);
+		} else {	/* 120Mhz */
+			bcma_write16(core, D11REGOFFS(tsf_clk_frac_l), 0x8889);
+			bcma_write16(core, D11REGOFFS(tsf_clk_frac_h), 0x8);
+		}
+	} else if (BRCMS_ISLCNPHY(wlc_hw->band)) {
+		if (spurmode == WL_SPURAVOID_ON1) {	/* 82Mhz */
+			bcma_write16(core, D11REGOFFS(tsf_clk_frac_l), 0x7CE0);
+			bcma_write16(core, D11REGOFFS(tsf_clk_frac_h), 0xC);
+		} else {	/* 80Mhz */
+			bcma_write16(core, D11REGOFFS(tsf_clk_frac_l), 0xCCCD);
+			bcma_write16(core, D11REGOFFS(tsf_clk_frac_h), 0xC);
+		}
+	}
+}
+
+void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr)
+{
+	memcpy(wlc->pub->cur_etheraddr, addr, sizeof(wlc->pub->cur_etheraddr));
+	wlc->bsscfg->type = BRCMS_TYPE_STATION;
+}
+
+void brcms_c_start_ap(struct brcms_c_info *wlc, u8 *addr, const u8 *bssid,
+		      u8 *ssid, size_t ssid_len)
+{
+	brcms_c_set_ssid(wlc, ssid, ssid_len);
+
+	memcpy(wlc->pub->cur_etheraddr, addr, sizeof(wlc->pub->cur_etheraddr));
+	memcpy(wlc->bsscfg->BSSID, bssid, sizeof(wlc->bsscfg->BSSID));
+	wlc->bsscfg->type = BRCMS_TYPE_AP;
+
+	brcms_b_mctrl(wlc->hw, MCTL_AP | MCTL_INFRA, MCTL_AP | MCTL_INFRA);
+}
+
+void brcms_c_start_adhoc(struct brcms_c_info *wlc, u8 *addr)
+{
+	memcpy(wlc->pub->cur_etheraddr, addr, sizeof(wlc->pub->cur_etheraddr));
+	wlc->bsscfg->type = BRCMS_TYPE_ADHOC;
+
+	brcms_b_mctrl(wlc->hw, MCTL_AP | MCTL_INFRA, 0);
+}
+
+/* Initialize GPIOs that are controlled by D11 core */
+static void brcms_c_gpio_init(struct brcms_c_info *wlc)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	u32 gc, gm;
+
+	/* use GPIO select 0 to get all gpio signals from the gpio out reg */
+	brcms_b_mctrl(wlc_hw, MCTL_GPOUT_SEL_MASK, 0);
+
+	/*
+	 * Common GPIO setup:
+	 *      G0 = LED 0 = WLAN Activity
+	 *      G1 = LED 1 = WLAN 2.4 GHz Radio State
+	 *      G2 = LED 2 = WLAN 5 GHz Radio State
+	 *      G4 = radio disable input (HI enabled, LO disabled)
+	 */
+
+	gc = gm = 0;
+
+	/* Allocate GPIOs for mimo antenna diversity feature */
+	if (wlc_hw->antsel_type == ANTSEL_2x3) {
+		/* Enable antenna diversity, use 2x3 mode */
+		brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
+			     MHF3_ANTSEL_EN, BRCM_BAND_ALL);
+		brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE,
+			     MHF3_ANTSEL_MODE, BRCM_BAND_ALL);
+
+		/* init superswitch control */
+		wlc_phy_antsel_init(wlc_hw->band->pi, false);
+
+	} else if (wlc_hw->antsel_type == ANTSEL_2x4) {
+		gm |= gc |= (BOARD_GPIO_12 | BOARD_GPIO_13);
+		/*
+		 * The board itself is powered by these GPIOs
+		 * (when not sending pattern) so set them high
+		 */
+		bcma_set16(wlc_hw->d11core, D11REGOFFS(psm_gpio_oe),
+			   (BOARD_GPIO_12 | BOARD_GPIO_13));
+		bcma_set16(wlc_hw->d11core, D11REGOFFS(psm_gpio_out),
+			   (BOARD_GPIO_12 | BOARD_GPIO_13));
+
+		/* Enable antenna diversity, use 2x4 mode */
+		brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
+			     MHF3_ANTSEL_EN, BRCM_BAND_ALL);
+		brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE, 0,
+			     BRCM_BAND_ALL);
+
+		/* Configure the desired clock to be 4Mhz */
+		brcms_b_write_shm(wlc_hw, M_ANTSEL_CLKDIV,
+				   ANTSEL_CLKDIV_4MHZ);
+	}
+
+	/*
+	 * gpio 9 controls the PA. ucode is responsible
+	 * for wiggling out and oe
+	 */
+	if (wlc_hw->boardflags & BFL_PACTRL)
+		gm |= gc |= BOARD_GPIO_PACTRL;
+
+	/* apply to gpiocontrol register */
+	bcma_chipco_gpio_control(&wlc_hw->d11core->bus->drv_cc, gm, gc);
+}
+
+static void brcms_ucode_write(struct brcms_hardware *wlc_hw,
+			      const __le32 ucode[], const size_t nbytes)
+{
+	struct bcma_device *core = wlc_hw->d11core;
+	uint i;
+	uint count;
+
+	brcms_dbg_info(wlc_hw->d11core, "wl%d\n", wlc_hw->unit);
+
+	count = (nbytes / sizeof(u32));
+
+	bcma_write32(core, D11REGOFFS(objaddr),
+		     OBJADDR_AUTO_INC | OBJADDR_UCM_SEL);
+	(void)bcma_read32(core, D11REGOFFS(objaddr));
+	for (i = 0; i < count; i++)
+		bcma_write32(core, D11REGOFFS(objdata), le32_to_cpu(ucode[i]));
+
+}
+
+static void brcms_ucode_download(struct brcms_hardware *wlc_hw)
+{
+	struct brcms_c_info *wlc;
+	struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode;
+
+	wlc = wlc_hw->wlc;
+
+	if (wlc_hw->ucode_loaded)
+		return;
+
+	if (D11REV_IS(wlc_hw->corerev, 17) || D11REV_IS(wlc_hw->corerev, 23)) {
+		if (BRCMS_ISNPHY(wlc_hw->band)) {
+			brcms_ucode_write(wlc_hw, ucode->bcm43xx_16_mimo,
+					  ucode->bcm43xx_16_mimosz);
+			wlc_hw->ucode_loaded = true;
+		} else
+			brcms_err(wlc_hw->d11core,
+				  "%s: wl%d: unsupported phy in corerev %d\n",
+				  __func__, wlc_hw->unit, wlc_hw->corerev);
+	} else if (D11REV_IS(wlc_hw->corerev, 24)) {
+		if (BRCMS_ISLCNPHY(wlc_hw->band)) {
+			brcms_ucode_write(wlc_hw, ucode->bcm43xx_24_lcn,
+					  ucode->bcm43xx_24_lcnsz);
+			wlc_hw->ucode_loaded = true;
+		} else {
+			brcms_err(wlc_hw->d11core,
+				  "%s: wl%d: unsupported phy in corerev %d\n",
+				  __func__, wlc_hw->unit, wlc_hw->corerev);
+		}
+	}
+}
+
+void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant)
+{
+	/* update sw state */
+	wlc_hw->bmac_phytxant = phytxant;
+
+	/* push to ucode if up */
+	if (!wlc_hw->up)
+		return;
+	brcms_c_ucode_txant_set(wlc_hw);
+
+}
+
+u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw)
+{
+	return (u16) wlc_hw->wlc->stf->txant;
+}
+
+void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, u8 antsel_type)
+{
+	wlc_hw->antsel_type = antsel_type;
+
+	/* Update the antsel type for phy module to use */
+	wlc_phy_antsel_type_set(wlc_hw->band->pi, antsel_type);
+}
+
+static void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw)
+{
+	bool fatal = false;
+	uint unit;
+	uint intstatus, idx;
+	struct bcma_device *core = wlc_hw->d11core;
+
+	unit = wlc_hw->unit;
+
+	for (idx = 0; idx < NFIFO; idx++) {
+		/* read intstatus register and ignore any non-error bits */
+		intstatus =
+			bcma_read32(core,
+				    D11REGOFFS(intctrlregs[idx].intstatus)) &
+			I_ERRORS;
+		if (!intstatus)
+			continue;
+
+		brcms_dbg_int(core, "wl%d: intstatus%d 0x%x\n",
+			      unit, idx, intstatus);
+
+		if (intstatus & I_RO) {
+			brcms_err(core, "wl%d: fifo %d: receive fifo "
+				  "overflow\n", unit, idx);
+			fatal = true;
+		}
+
+		if (intstatus & I_PC) {
+			brcms_err(core, "wl%d: fifo %d: descriptor error\n",
+				  unit, idx);
+			fatal = true;
+		}
+
+		if (intstatus & I_PD) {
+			brcms_err(core, "wl%d: fifo %d: data error\n", unit,
+				  idx);
+			fatal = true;
+		}
+
+		if (intstatus & I_DE) {
+			brcms_err(core, "wl%d: fifo %d: descriptor protocol "
+				  "error\n", unit, idx);
+			fatal = true;
+		}
+
+		if (intstatus & I_RU)
+			brcms_err(core, "wl%d: fifo %d: receive descriptor "
+				  "underflow\n", idx, unit);
+
+		if (intstatus & I_XU) {
+			brcms_err(core, "wl%d: fifo %d: transmit fifo "
+				  "underflow\n", idx, unit);
+			fatal = true;
+		}
+
+		if (fatal) {
+			brcms_fatal_error(wlc_hw->wlc->wl); /* big hammer */
+			break;
+		} else
+			bcma_write32(core,
+				     D11REGOFFS(intctrlregs[idx].intstatus),
+				     intstatus);
+	}
+}
+
+void brcms_c_intrson(struct brcms_c_info *wlc)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	wlc->macintmask = wlc->defmacintmask;
+	bcma_write32(wlc_hw->d11core, D11REGOFFS(macintmask), wlc->macintmask);
+}
+
+u32 brcms_c_intrsoff(struct brcms_c_info *wlc)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	u32 macintmask;
+
+	if (!wlc_hw->clk)
+		return 0;
+
+	macintmask = wlc->macintmask;	/* isr can still happen */
+
+	bcma_write32(wlc_hw->d11core, D11REGOFFS(macintmask), 0);
+	(void)bcma_read32(wlc_hw->d11core, D11REGOFFS(macintmask));
+	udelay(1);		/* ensure int line is no longer driven */
+	wlc->macintmask = 0;
+
+	/* return previous macintmask; resolve race between us and our isr */
+	return wlc->macintstatus ? 0 : macintmask;
+}
+
+void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	if (!wlc_hw->clk)
+		return;
+
+	wlc->macintmask = macintmask;
+	bcma_write32(wlc_hw->d11core, D11REGOFFS(macintmask), wlc->macintmask);
+}
+
+/* assumes that the d11 MAC is enabled */
+static void brcms_b_tx_fifo_suspend(struct brcms_hardware *wlc_hw,
+				    uint tx_fifo)
+{
+	u8 fifo = 1 << tx_fifo;
+
+	/* Two clients of this code, 11h Quiet period and scanning. */
+
+	/* only suspend if not already suspended */
+	if ((wlc_hw->suspended_fifos & fifo) == fifo)
+		return;
+
+	/* force the core awake only if not already */
+	if (wlc_hw->suspended_fifos == 0)
+		brcms_c_ucode_wake_override_set(wlc_hw,
+						BRCMS_WAKE_OVERRIDE_TXFIFO);
+
+	wlc_hw->suspended_fifos |= fifo;
+
+	if (wlc_hw->di[tx_fifo]) {
+		/*
+		 * Suspending AMPDU transmissions in the middle can cause
+		 * underflow which may result in mismatch between ucode and
+		 * driver so suspend the mac before suspending the FIFO
+		 */
+		if (BRCMS_PHY_11N_CAP(wlc_hw->band))
+			brcms_c_suspend_mac_and_wait(wlc_hw->wlc);
+
+		dma_txsuspend(wlc_hw->di[tx_fifo]);
+
+		if (BRCMS_PHY_11N_CAP(wlc_hw->band))
+			brcms_c_enable_mac(wlc_hw->wlc);
+	}
+}
+
+static void brcms_b_tx_fifo_resume(struct brcms_hardware *wlc_hw,
+				   uint tx_fifo)
+{
+	/* BMAC_NOTE: BRCMS_TX_FIFO_ENAB is done in brcms_c_dpc() for DMA case
+	 * but need to be done here for PIO otherwise the watchdog will catch
+	 * the inconsistency and fire
+	 */
+	/* Two clients of this code, 11h Quiet period and scanning. */
+	if (wlc_hw->di[tx_fifo])
+		dma_txresume(wlc_hw->di[tx_fifo]);
+
+	/* allow core to sleep again */
+	if (wlc_hw->suspended_fifos == 0)
+		return;
+	else {
+		wlc_hw->suspended_fifos &= ~(1 << tx_fifo);
+		if (wlc_hw->suspended_fifos == 0)
+			brcms_c_ucode_wake_override_clear(wlc_hw,
+						BRCMS_WAKE_OVERRIDE_TXFIFO);
+	}
+}
+
+/* precondition: requires the mac core to be enabled */
+static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool mute_tx)
+{
+	static const u8 null_ether_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
+	u8 *ethaddr = wlc_hw->wlc->pub->cur_etheraddr;
+
+	if (mute_tx) {
+		/* suspend tx fifos */
+		brcms_b_tx_fifo_suspend(wlc_hw, TX_DATA_FIFO);
+		brcms_b_tx_fifo_suspend(wlc_hw, TX_CTL_FIFO);
+		brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_BK_FIFO);
+		brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_VI_FIFO);
+
+		/* zero the address match register so we do not send ACKs */
+		brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET, null_ether_addr);
+	} else {
+		/* resume tx fifos */
+		brcms_b_tx_fifo_resume(wlc_hw, TX_DATA_FIFO);
+		brcms_b_tx_fifo_resume(wlc_hw, TX_CTL_FIFO);
+		brcms_b_tx_fifo_resume(wlc_hw, TX_AC_BK_FIFO);
+		brcms_b_tx_fifo_resume(wlc_hw, TX_AC_VI_FIFO);
+
+		/* Restore address */
+		brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET, ethaddr);
+	}
+
+	wlc_phy_mute_upd(wlc_hw->band->pi, mute_tx, 0);
+
+	if (mute_tx)
+		brcms_c_ucode_mute_override_set(wlc_hw);
+	else
+		brcms_c_ucode_mute_override_clear(wlc_hw);
+}
+
+void
+brcms_c_mute(struct brcms_c_info *wlc, bool mute_tx)
+{
+	brcms_b_mute(wlc->hw, mute_tx);
+}
+
+/*
+ * Read and clear macintmask and macintstatus and intstatus registers.
+ * This routine should be called with interrupts off
+ * Return:
+ *   -1 if brcms_deviceremoved(wlc) evaluates to true;
+ *   0 if the interrupt is not for us, or we are in some special cases;
+ *   device interrupt status bits otherwise.
+ */
+static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	struct bcma_device *core = wlc_hw->d11core;
+	u32 macintstatus, mask;
+
+	/* macintstatus includes a DMA interrupt summary bit */
+	macintstatus = bcma_read32(core, D11REGOFFS(macintstatus));
+	mask = in_isr ? wlc->macintmask : wlc->defmacintmask;
+
+	trace_brcms_macintstatus(&core->dev, in_isr, macintstatus, mask);
+
+	/* detect cardbus removed, in power down(suspend) and in reset */
+	if (brcms_deviceremoved(wlc))
+		return -1;
+
+	/* brcms_deviceremoved() succeeds even when the core is still resetting,
+	 * handle that case here.
+	 */
+	if (macintstatus == 0xffffffff)
+		return 0;
+
+	/* defer unsolicited interrupts */
+	macintstatus &= mask;
+
+	/* if not for us */
+	if (macintstatus == 0)
+		return 0;
+
+	/* turn off the interrupts */
+	bcma_write32(core, D11REGOFFS(macintmask), 0);
+	(void)bcma_read32(core, D11REGOFFS(macintmask));
+	wlc->macintmask = 0;
+
+	/* clear device interrupts */
+	bcma_write32(core, D11REGOFFS(macintstatus), macintstatus);
+
+	/* MI_DMAINT is indication of non-zero intstatus */
+	if (macintstatus & MI_DMAINT)
+		/*
+		 * only fifo interrupt enabled is I_RI in
+		 * RX_FIFO. If MI_DMAINT is set, assume it
+		 * is set and clear the interrupt.
+		 */
+		bcma_write32(core, D11REGOFFS(intctrlregs[RX_FIFO].intstatus),
+			     DEF_RXINTMASK);
+
+	return macintstatus;
+}
+
+/* Update wlc->macintstatus and wlc->intstatus[]. */
+/* Return true if they are updated successfully. false otherwise */
+bool brcms_c_intrsupd(struct brcms_c_info *wlc)
+{
+	u32 macintstatus;
+
+	/* read and clear macintstatus and intstatus registers */
+	macintstatus = wlc_intstatus(wlc, false);
+
+	/* device is removed */
+	if (macintstatus == 0xffffffff)
+		return false;
+
+	/* update interrupt status in software */
+	wlc->macintstatus |= macintstatus;
+
+	return true;
+}
+
+/*
+ * First-level interrupt processing.
+ * Return true if this was our interrupt
+ * and if further brcms_c_dpc() processing is required,
+ * false otherwise.
+ */
+bool brcms_c_isr(struct brcms_c_info *wlc)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	u32 macintstatus;
+
+	if (!wlc_hw->up || !wlc->macintmask)
+		return false;
+
+	/* read and clear macintstatus and intstatus registers */
+	macintstatus = wlc_intstatus(wlc, true);
+
+	if (macintstatus == 0xffffffff) {
+		brcms_err(wlc_hw->d11core,
+			  "DEVICEREMOVED detected in the ISR code path\n");
+		return false;
+	}
+
+	/* it is not for us */
+	if (macintstatus == 0)
+		return false;
+
+	/* save interrupt status bits */
+	wlc->macintstatus = macintstatus;
+
+	return true;
+
+}
+
+void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	struct bcma_device *core = wlc_hw->d11core;
+	u32 mc, mi;
+
+	brcms_dbg_mac80211(core, "wl%d: bandunit %d\n", wlc_hw->unit,
+			   wlc_hw->band->bandunit);
+
+	/*
+	 * Track overlapping suspend requests
+	 */
+	wlc_hw->mac_suspend_depth++;
+	if (wlc_hw->mac_suspend_depth > 1)
+		return;
+
+	/* force the core awake */
+	brcms_c_ucode_wake_override_set(wlc_hw, BRCMS_WAKE_OVERRIDE_MACSUSPEND);
+
+	mc = bcma_read32(core, D11REGOFFS(maccontrol));
+
+	if (mc == 0xffffffff) {
+		brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit,
+			  __func__);
+		brcms_down(wlc->wl);
+		return;
+	}
+	WARN_ON(mc & MCTL_PSM_JMP_0);
+	WARN_ON(!(mc & MCTL_PSM_RUN));
+	WARN_ON(!(mc & MCTL_EN_MAC));
+
+	mi = bcma_read32(core, D11REGOFFS(macintstatus));
+	if (mi == 0xffffffff) {
+		brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit,
+			  __func__);
+		brcms_down(wlc->wl);
+		return;
+	}
+	WARN_ON(mi & MI_MACSSPNDD);
+
+	brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, 0);
+
+	SPINWAIT(!(bcma_read32(core, D11REGOFFS(macintstatus)) & MI_MACSSPNDD),
+		 BRCMS_MAX_MAC_SUSPEND);
+
+	if (!(bcma_read32(core, D11REGOFFS(macintstatus)) & MI_MACSSPNDD)) {
+		brcms_err(core, "wl%d: wlc_suspend_mac_and_wait: waited %d uS"
+			  " and MI_MACSSPNDD is still not on.\n",
+			  wlc_hw->unit, BRCMS_MAX_MAC_SUSPEND);
+		brcms_err(core, "wl%d: psmdebug 0x%08x, phydebug 0x%08x, "
+			  "psm_brc 0x%04x\n", wlc_hw->unit,
+			  bcma_read32(core, D11REGOFFS(psmdebug)),
+			  bcma_read32(core, D11REGOFFS(phydebug)),
+			  bcma_read16(core, D11REGOFFS(psm_brc)));
+	}
+
+	mc = bcma_read32(core, D11REGOFFS(maccontrol));
+	if (mc == 0xffffffff) {
+		brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit,
+			  __func__);
+		brcms_down(wlc->wl);
+		return;
+	}
+	WARN_ON(mc & MCTL_PSM_JMP_0);
+	WARN_ON(!(mc & MCTL_PSM_RUN));
+	WARN_ON(mc & MCTL_EN_MAC);
+}
+
+void brcms_c_enable_mac(struct brcms_c_info *wlc)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	struct bcma_device *core = wlc_hw->d11core;
+	u32 mc, mi;
+
+	brcms_dbg_mac80211(core, "wl%d: bandunit %d\n", wlc_hw->unit,
+			   wlc->band->bandunit);
+
+	/*
+	 * Track overlapping suspend requests
+	 */
+	wlc_hw->mac_suspend_depth--;
+	if (wlc_hw->mac_suspend_depth > 0)
+		return;
+
+	mc = bcma_read32(core, D11REGOFFS(maccontrol));
+	WARN_ON(mc & MCTL_PSM_JMP_0);
+	WARN_ON(mc & MCTL_EN_MAC);
+	WARN_ON(!(mc & MCTL_PSM_RUN));
+
+	brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, MCTL_EN_MAC);
+	bcma_write32(core, D11REGOFFS(macintstatus), MI_MACSSPNDD);
+
+	mc = bcma_read32(core, D11REGOFFS(maccontrol));
+	WARN_ON(mc & MCTL_PSM_JMP_0);
+	WARN_ON(!(mc & MCTL_EN_MAC));
+	WARN_ON(!(mc & MCTL_PSM_RUN));
+
+	mi = bcma_read32(core, D11REGOFFS(macintstatus));
+	WARN_ON(mi & MI_MACSSPNDD);
+
+	brcms_c_ucode_wake_override_clear(wlc_hw,
+					  BRCMS_WAKE_OVERRIDE_MACSUSPEND);
+}
+
+void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, u8 stf_mode)
+{
+	wlc_hw->hw_stf_ss_opmode = stf_mode;
+
+	if (wlc_hw->clk)
+		brcms_upd_ofdm_pctl1_table(wlc_hw);
+}
+
+static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw)
+{
+	struct bcma_device *core = wlc_hw->d11core;
+	u32 w, val;
+	struct wiphy *wiphy = wlc_hw->wlc->wiphy;
+
+	/* Validate dchip register access */
+
+	bcma_write32(core, D11REGOFFS(objaddr), OBJADDR_SHM_SEL | 0);
+	(void)bcma_read32(core, D11REGOFFS(objaddr));
+	w = bcma_read32(core, D11REGOFFS(objdata));
+
+	/* Can we write and read back a 32bit register? */
+	bcma_write32(core, D11REGOFFS(objaddr), OBJADDR_SHM_SEL | 0);
+	(void)bcma_read32(core, D11REGOFFS(objaddr));
+	bcma_write32(core, D11REGOFFS(objdata), (u32) 0xaa5555aa);
+
+	bcma_write32(core, D11REGOFFS(objaddr), OBJADDR_SHM_SEL | 0);
+	(void)bcma_read32(core, D11REGOFFS(objaddr));
+	val = bcma_read32(core, D11REGOFFS(objdata));
+	if (val != (u32) 0xaa5555aa) {
+		wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, "
+			  "expected 0xaa5555aa\n", wlc_hw->unit, val);
+		return false;
+	}
+
+	bcma_write32(core, D11REGOFFS(objaddr), OBJADDR_SHM_SEL | 0);
+	(void)bcma_read32(core, D11REGOFFS(objaddr));
+	bcma_write32(core, D11REGOFFS(objdata), (u32) 0x55aaaa55);
+
+	bcma_write32(core, D11REGOFFS(objaddr), OBJADDR_SHM_SEL | 0);
+	(void)bcma_read32(core, D11REGOFFS(objaddr));
+	val = bcma_read32(core, D11REGOFFS(objdata));
+	if (val != (u32) 0x55aaaa55) {
+		wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, "
+			  "expected 0x55aaaa55\n", wlc_hw->unit, val);
+		return false;
+	}
+
+	bcma_write32(core, D11REGOFFS(objaddr), OBJADDR_SHM_SEL | 0);
+	(void)bcma_read32(core, D11REGOFFS(objaddr));
+	bcma_write32(core, D11REGOFFS(objdata), w);
+
+	/* clear CFPStart */
+	bcma_write32(core, D11REGOFFS(tsf_cfpstart), 0);
+
+	w = bcma_read32(core, D11REGOFFS(maccontrol));
+	if ((w != (MCTL_IHR_EN | MCTL_WAKE)) &&
+	    (w != (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE))) {
+		wiphy_err(wiphy, "wl%d: validate_chip_access: maccontrol = "
+			  "0x%x, expected 0x%x or 0x%x\n", wlc_hw->unit, w,
+			  (MCTL_IHR_EN | MCTL_WAKE),
+			  (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE));
+		return false;
+	}
+
+	return true;
+}
+
+#define PHYPLL_WAIT_US	100000
+
+void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on)
+{
+	struct bcma_device *core = wlc_hw->d11core;
+	u32 tmp;
+
+	brcms_dbg_info(core, "wl%d\n", wlc_hw->unit);
+
+	tmp = 0;
+
+	if (on) {
+		if ((ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM4313)) {
+			bcma_set32(core, D11REGOFFS(clk_ctl_st),
+				   CCS_ERSRC_REQ_HT |
+				   CCS_ERSRC_REQ_D11PLL |
+				   CCS_ERSRC_REQ_PHYPLL);
+			SPINWAIT((bcma_read32(core, D11REGOFFS(clk_ctl_st)) &
+				  CCS_ERSRC_AVAIL_HT) != CCS_ERSRC_AVAIL_HT,
+				 PHYPLL_WAIT_US);
+
+			tmp = bcma_read32(core, D11REGOFFS(clk_ctl_st));
+			if ((tmp & CCS_ERSRC_AVAIL_HT) != CCS_ERSRC_AVAIL_HT)
+				brcms_err(core, "%s: turn on PHY PLL failed\n",
+					  __func__);
+		} else {
+			bcma_set32(core, D11REGOFFS(clk_ctl_st),
+				   tmp | CCS_ERSRC_REQ_D11PLL |
+				   CCS_ERSRC_REQ_PHYPLL);
+			SPINWAIT((bcma_read32(core, D11REGOFFS(clk_ctl_st)) &
+				  (CCS_ERSRC_AVAIL_D11PLL |
+				   CCS_ERSRC_AVAIL_PHYPLL)) !=
+				 (CCS_ERSRC_AVAIL_D11PLL |
+				  CCS_ERSRC_AVAIL_PHYPLL), PHYPLL_WAIT_US);
+
+			tmp = bcma_read32(core, D11REGOFFS(clk_ctl_st));
+			if ((tmp &
+			     (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL))
+			    !=
+			    (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL))
+				brcms_err(core, "%s: turn on PHY PLL failed\n",
+					  __func__);
+		}
+	} else {
+		/*
+		 * Since the PLL may be shared, other cores can still
+		 * be requesting it; so we'll deassert the request but
+		 * not wait for status to comply.
+		 */
+		bcma_mask32(core, D11REGOFFS(clk_ctl_st),
+			    ~CCS_ERSRC_REQ_PHYPLL);
+		(void)bcma_read32(core, D11REGOFFS(clk_ctl_st));
+	}
+}
+
+static void brcms_c_coredisable(struct brcms_hardware *wlc_hw)
+{
+	bool dev_gone;
+
+	brcms_dbg_info(wlc_hw->d11core, "wl%d: disable core\n", wlc_hw->unit);
+
+	dev_gone = brcms_deviceremoved(wlc_hw->wlc);
+
+	if (dev_gone)
+		return;
+
+	if (wlc_hw->noreset)
+		return;
+
+	/* radio off */
+	wlc_phy_switch_radio(wlc_hw->band->pi, OFF);
+
+	/* turn off analog core */
+	wlc_phy_anacore(wlc_hw->band->pi, OFF);
+
+	/* turn off PHYPLL to save power */
+	brcms_b_core_phypll_ctl(wlc_hw, false);
+
+	wlc_hw->clk = false;
+	bcma_core_disable(wlc_hw->d11core, 0);
+	wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
+}
+
+static void brcms_c_flushqueues(struct brcms_c_info *wlc)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	uint i;
+
+	/* free any posted tx packets */
+	for (i = 0; i < NFIFO; i++) {
+		if (wlc_hw->di[i]) {
+			dma_txreclaim(wlc_hw->di[i], DMA_RANGE_ALL);
+			if (i < TX_BCMC_FIFO)
+				ieee80211_wake_queue(wlc->pub->ieee_hw,
+						     brcms_fifo_to_ac(i));
+		}
+	}
+
+	/* free any posted rx packets */
+	dma_rxreclaim(wlc_hw->di[RX_FIFO]);
+}
+
+static u16
+brcms_b_read_objmem(struct brcms_hardware *wlc_hw, uint offset, u32 sel)
+{
+	struct bcma_device *core = wlc_hw->d11core;
+	u16 objoff = D11REGOFFS(objdata);
+
+	bcma_write32(core, D11REGOFFS(objaddr), sel | (offset >> 2));
+	(void)bcma_read32(core, D11REGOFFS(objaddr));
+	if (offset & 2)
+		objoff += 2;
+
+	return bcma_read16(core, objoff);
+}
+
+static void
+brcms_b_write_objmem(struct brcms_hardware *wlc_hw, uint offset, u16 v,
+		     u32 sel)
+{
+	struct bcma_device *core = wlc_hw->d11core;
+	u16 objoff = D11REGOFFS(objdata);
+
+	bcma_write32(core, D11REGOFFS(objaddr), sel | (offset >> 2));
+	(void)bcma_read32(core, D11REGOFFS(objaddr));
+	if (offset & 2)
+		objoff += 2;
+
+	bcma_wflush16(core, objoff, v);
+}
+
+/*
+ * Read a single u16 from shared memory.
+ * SHM 'offset' needs to be an even address
+ */
+u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset)
+{
+	return brcms_b_read_objmem(wlc_hw, offset, OBJADDR_SHM_SEL);
+}
+
+/*
+ * Write a single u16 to shared memory.
+ * SHM 'offset' needs to be an even address
+ */
+void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset, u16 v)
+{
+	brcms_b_write_objmem(wlc_hw, offset, v, OBJADDR_SHM_SEL);
+}
+
+/*
+ * Copy a buffer to shared memory of specified type .
+ * SHM 'offset' needs to be an even address and
+ * Buffer length 'len' must be an even number of bytes
+ * 'sel' selects the type of memory
+ */
+void
+brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw, uint offset,
+		      const void *buf, int len, u32 sel)
+{
+	u16 v;
+	const u8 *p = (const u8 *)buf;
+	int i;
+
+	if (len <= 0 || (offset & 1) || (len & 1))
+		return;
+
+	for (i = 0; i < len; i += 2) {
+		v = p[i] | (p[i + 1] << 8);
+		brcms_b_write_objmem(wlc_hw, offset + i, v, sel);
+	}
+}
+
+/*
+ * Copy a piece of shared memory of specified type to a buffer .
+ * SHM 'offset' needs to be an even address and
+ * Buffer length 'len' must be an even number of bytes
+ * 'sel' selects the type of memory
+ */
+void
+brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset, void *buf,
+			 int len, u32 sel)
+{
+	u16 v;
+	u8 *p = (u8 *) buf;
+	int i;
+
+	if (len <= 0 || (offset & 1) || (len & 1))
+		return;
+
+	for (i = 0; i < len; i += 2) {
+		v = brcms_b_read_objmem(wlc_hw, offset + i, sel);
+		p[i] = v & 0xFF;
+		p[i + 1] = (v >> 8) & 0xFF;
+	}
+}
+
+/* Copy a buffer to shared memory.
+ * SHM 'offset' needs to be an even address and
+ * Buffer length 'len' must be an even number of bytes
+ */
+static void brcms_c_copyto_shm(struct brcms_c_info *wlc, uint offset,
+			const void *buf, int len)
+{
+	brcms_b_copyto_objmem(wlc->hw, offset, buf, len, OBJADDR_SHM_SEL);
+}
+
+static void brcms_b_retrylimit_upd(struct brcms_hardware *wlc_hw,
+				   u16 SRL, u16 LRL)
+{
+	wlc_hw->SRL = SRL;
+	wlc_hw->LRL = LRL;
+
+	/* write retry limit to SCR, shouldn't need to suspend */
+	if (wlc_hw->up) {
+		bcma_write32(wlc_hw->d11core, D11REGOFFS(objaddr),
+			     OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
+		(void)bcma_read32(wlc_hw->d11core, D11REGOFFS(objaddr));
+		bcma_write32(wlc_hw->d11core, D11REGOFFS(objdata), wlc_hw->SRL);
+		bcma_write32(wlc_hw->d11core, D11REGOFFS(objaddr),
+			     OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
+		(void)bcma_read32(wlc_hw->d11core, D11REGOFFS(objaddr));
+		bcma_write32(wlc_hw->d11core, D11REGOFFS(objdata), wlc_hw->LRL);
+	}
+}
+
+static void brcms_b_pllreq(struct brcms_hardware *wlc_hw, bool set, u32 req_bit)
+{
+	if (set) {
+		if (mboolisset(wlc_hw->pllreq, req_bit))
+			return;
+
+		mboolset(wlc_hw->pllreq, req_bit);
+
+		if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) {
+			if (!wlc_hw->sbclk)
+				brcms_b_xtal(wlc_hw, ON);
+		}
+	} else {
+		if (!mboolisset(wlc_hw->pllreq, req_bit))
+			return;
+
+		mboolclr(wlc_hw->pllreq, req_bit);
+
+		if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) {
+			if (wlc_hw->sbclk)
+				brcms_b_xtal(wlc_hw, OFF);
+		}
+	}
+}
+
+static void brcms_b_antsel_set(struct brcms_hardware *wlc_hw, u32 antsel_avail)
+{
+	wlc_hw->antsel_avail = antsel_avail;
+}
+
+/*
+ * conditions under which the PM bit should be set in outgoing frames
+ * and STAY_AWAKE is meaningful
+ */
+static bool brcms_c_ps_allowed(struct brcms_c_info *wlc)
+{
+	/* not supporting PS so always return false for now */
+	return false;
+}
+
+static void brcms_c_statsupd(struct brcms_c_info *wlc)
+{
+	int i;
+	struct macstat *macstats;
+#ifdef DEBUG
+	u16 delta;
+	u16 rxf0ovfl;
+	u16 txfunfl[NFIFO];
+#endif				/* DEBUG */
+
+	/* if driver down, make no sense to update stats */
+	if (!wlc->pub->up)
+		return;
+
+	macstats = wlc->core->macstat_snapshot;
+
+#ifdef DEBUG
+	/* save last rx fifo 0 overflow count */
+	rxf0ovfl = macstats->rxf0ovfl;
+
+	/* save last tx fifo  underflow count */
+	for (i = 0; i < NFIFO; i++)
+		txfunfl[i] = macstats->txfunfl[i];
+#endif				/* DEBUG */
+
+	/* Read mac stats from contiguous shared memory */
+	brcms_b_copyfrom_objmem(wlc->hw, M_UCODE_MACSTAT, macstats,
+				sizeof(*macstats), OBJADDR_SHM_SEL);
+
+#ifdef DEBUG
+	/* check for rx fifo 0 overflow */
+	delta = (u16)(macstats->rxf0ovfl - rxf0ovfl);
+	if (delta)
+		brcms_err(wlc->hw->d11core, "wl%d: %u rx fifo 0 overflows!\n",
+			  wlc->pub->unit, delta);
+
+	/* check for tx fifo underflows */
+	for (i = 0; i < NFIFO; i++) {
+		delta = macstats->txfunfl[i] - txfunfl[i];
+		if (delta)
+			brcms_err(wlc->hw->d11core,
+				  "wl%d: %u tx fifo %d underflows!\n",
+				  wlc->pub->unit, delta, i);
+	}
+#endif				/* DEBUG */
+
+	/* merge counters from dma module */
+	for (i = 0; i < NFIFO; i++) {
+		if (wlc->hw->di[i])
+			dma_counterreset(wlc->hw->di[i]);
+	}
+}
+
+static void brcms_b_reset(struct brcms_hardware *wlc_hw)
+{
+	/* reset the core */
+	if (!brcms_deviceremoved(wlc_hw->wlc))
+		brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
+
+	/* purge the dma rings */
+	brcms_c_flushqueues(wlc_hw->wlc);
+}
+
+void brcms_c_reset(struct brcms_c_info *wlc)
+{
+	brcms_dbg_info(wlc->hw->d11core, "wl%d\n", wlc->pub->unit);
+
+	/* slurp up hw mac counters before core reset */
+	brcms_c_statsupd(wlc);
+
+	/* reset our snapshot of macstat counters */
+	memset(wlc->core->macstat_snapshot, 0, sizeof(struct macstat));
+
+	brcms_b_reset(wlc->hw);
+}
+
+void brcms_c_init_scb(struct scb *scb)
+{
+	int i;
+
+	memset(scb, 0, sizeof(struct scb));
+	scb->flags = SCB_WMECAP | SCB_HTCAP;
+	for (i = 0; i < NUMPRIO; i++) {
+		scb->seqnum[i] = 0;
+		scb->seqctl[i] = 0xFFFF;
+	}
+
+	scb->seqctl_nonqos = 0xFFFF;
+	scb->magic = SCB_MAGIC;
+}
+
+/* d11 core init
+ *   reset PSM
+ *   download ucode/PCM
+ *   let ucode run to suspended
+ *   download ucode inits
+ *   config other core registers
+ *   init dma
+ */
+static void brcms_b_coreinit(struct brcms_c_info *wlc)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	struct bcma_device *core = wlc_hw->d11core;
+	u32 sflags;
+	u32 bcnint_us;
+	uint i = 0;
+	bool fifosz_fixup = false;
+	int err = 0;
+	u16 buf[NFIFO];
+	struct brcms_ucode *ucode = &wlc_hw->wlc->wl->ucode;
+
+	brcms_dbg_info(core, "wl%d: core init\n", wlc_hw->unit);
+
+	/* reset PSM */
+	brcms_b_mctrl(wlc_hw, ~0, (MCTL_IHR_EN | MCTL_PSM_JMP_0 | MCTL_WAKE));
+
+	brcms_ucode_download(wlc_hw);
+	/*
+	 * FIFOSZ fixup. driver wants to controls the fifo allocation.
+	 */
+	fifosz_fixup = true;
+
+	/* let the PSM run to the suspended state, set mode to BSS STA */
+	bcma_write32(core, D11REGOFFS(macintstatus), -1);
+	brcms_b_mctrl(wlc_hw, ~0,
+		       (MCTL_IHR_EN | MCTL_INFRA | MCTL_PSM_RUN | MCTL_WAKE));
+
+	/* wait for ucode to self-suspend after auto-init */
+	SPINWAIT(((bcma_read32(core, D11REGOFFS(macintstatus)) &
+		   MI_MACSSPNDD) == 0), 1000 * 1000);
+	if ((bcma_read32(core, D11REGOFFS(macintstatus)) & MI_MACSSPNDD) == 0)
+		brcms_err(core, "wl%d: wlc_coreinit: ucode did not self-"
+			  "suspend!\n", wlc_hw->unit);
+
+	brcms_c_gpio_init(wlc);
+
+	sflags = bcma_aread32(core, BCMA_IOST);
+
+	if (D11REV_IS(wlc_hw->corerev, 17) || D11REV_IS(wlc_hw->corerev, 23)) {
+		if (BRCMS_ISNPHY(wlc_hw->band))
+			brcms_c_write_inits(wlc_hw, ucode->d11n0initvals16);
+		else
+			brcms_err(core, "%s: wl%d: unsupported phy in corerev"
+				  " %d\n", __func__, wlc_hw->unit,
+				  wlc_hw->corerev);
+	} else if (D11REV_IS(wlc_hw->corerev, 24)) {
+		if (BRCMS_ISLCNPHY(wlc_hw->band))
+			brcms_c_write_inits(wlc_hw, ucode->d11lcn0initvals24);
+		else
+			brcms_err(core, "%s: wl%d: unsupported phy in corerev"
+				  " %d\n", __func__, wlc_hw->unit,
+				  wlc_hw->corerev);
+	} else {
+		brcms_err(core, "%s: wl%d: unsupported corerev %d\n",
+			  __func__, wlc_hw->unit, wlc_hw->corerev);
+	}
+
+	/* For old ucode, txfifo sizes needs to be modified(increased) */
+	if (fifosz_fixup)
+		brcms_b_corerev_fifofixup(wlc_hw);
+
+	/* check txfifo allocations match between ucode and driver */
+	buf[TX_AC_BE_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE0);
+	if (buf[TX_AC_BE_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]) {
+		i = TX_AC_BE_FIFO;
+		err = -1;
+	}
+	buf[TX_AC_VI_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE1);
+	if (buf[TX_AC_VI_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]) {
+		i = TX_AC_VI_FIFO;
+		err = -1;
+	}
+	buf[TX_AC_BK_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE2);
+	buf[TX_AC_VO_FIFO] = (buf[TX_AC_BK_FIFO] >> 8) & 0xff;
+	buf[TX_AC_BK_FIFO] &= 0xff;
+	if (buf[TX_AC_BK_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BK_FIFO]) {
+		i = TX_AC_BK_FIFO;
+		err = -1;
+	}
+	if (buf[TX_AC_VO_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO]) {
+		i = TX_AC_VO_FIFO;
+		err = -1;
+	}
+	buf[TX_BCMC_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE3);
+	buf[TX_ATIM_FIFO] = (buf[TX_BCMC_FIFO] >> 8) & 0xff;
+	buf[TX_BCMC_FIFO] &= 0xff;
+	if (buf[TX_BCMC_FIFO] != wlc_hw->xmtfifo_sz[TX_BCMC_FIFO]) {
+		i = TX_BCMC_FIFO;
+		err = -1;
+	}
+	if (buf[TX_ATIM_FIFO] != wlc_hw->xmtfifo_sz[TX_ATIM_FIFO]) {
+		i = TX_ATIM_FIFO;
+		err = -1;
+	}
+	if (err != 0)
+		brcms_err(core, "wlc_coreinit: txfifo mismatch: ucode size %d"
+			  " driver size %d index %d\n", buf[i],
+			  wlc_hw->xmtfifo_sz[i], i);
+
+	/* make sure we can still talk to the mac */
+	WARN_ON(bcma_read32(core, D11REGOFFS(maccontrol)) == 0xffffffff);
+
+	/* band-specific inits done by wlc_bsinit() */
+
+	/* Set up frame burst size and antenna swap threshold init values */
+	brcms_b_write_shm(wlc_hw, M_MBURST_SIZE, MAXTXFRAMEBURST);
+	brcms_b_write_shm(wlc_hw, M_MAX_ANTCNT, ANTCNT);
+
+	/* enable one rx interrupt per received frame */
+	bcma_write32(core, D11REGOFFS(intrcvlazy[0]), (1 << IRL_FC_SHIFT));
+
+	/* set the station mode (BSS STA) */
+	brcms_b_mctrl(wlc_hw,
+		       (MCTL_INFRA | MCTL_DISCARD_PMQ | MCTL_AP),
+		       (MCTL_INFRA | MCTL_DISCARD_PMQ));
+
+	/* set up Beacon interval */
+	bcnint_us = 0x8000 << 10;
+	bcma_write32(core, D11REGOFFS(tsf_cfprep),
+		     (bcnint_us << CFPREP_CBI_SHIFT));
+	bcma_write32(core, D11REGOFFS(tsf_cfpstart), bcnint_us);
+	bcma_write32(core, D11REGOFFS(macintstatus), MI_GP1);
+
+	/* write interrupt mask */
+	bcma_write32(core, D11REGOFFS(intctrlregs[RX_FIFO].intmask),
+		     DEF_RXINTMASK);
+
+	/* allow the MAC to control the PHY clock (dynamic on/off) */
+	brcms_b_macphyclk_set(wlc_hw, ON);
+
+	/* program dynamic clock control fast powerup delay register */
+	wlc->fastpwrup_dly = ai_clkctl_fast_pwrup_delay(wlc_hw->sih);
+	bcma_write16(core, D11REGOFFS(scc_fastpwrup_dly), wlc->fastpwrup_dly);
+
+	/* tell the ucode the corerev */
+	brcms_b_write_shm(wlc_hw, M_MACHW_VER, (u16) wlc_hw->corerev);
+
+	/* tell the ucode MAC capabilities */
+	brcms_b_write_shm(wlc_hw, M_MACHW_CAP_L,
+			   (u16) (wlc_hw->machwcap & 0xffff));
+	brcms_b_write_shm(wlc_hw, M_MACHW_CAP_H,
+			   (u16) ((wlc_hw->
+				      machwcap >> 16) & 0xffff));
+
+	/* write retry limits to SCR, this done after PSM init */
+	bcma_write32(core, D11REGOFFS(objaddr),
+		     OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
+	(void)bcma_read32(core, D11REGOFFS(objaddr));
+	bcma_write32(core, D11REGOFFS(objdata), wlc_hw->SRL);
+	bcma_write32(core, D11REGOFFS(objaddr),
+		     OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
+	(void)bcma_read32(core, D11REGOFFS(objaddr));
+	bcma_write32(core, D11REGOFFS(objdata), wlc_hw->LRL);
+
+	/* write rate fallback retry limits */
+	brcms_b_write_shm(wlc_hw, M_SFRMTXCNTFBRTHSD, wlc_hw->SFBL);
+	brcms_b_write_shm(wlc_hw, M_LFRMTXCNTFBRTHSD, wlc_hw->LFBL);
+
+	bcma_mask16(core, D11REGOFFS(ifs_ctl), 0x0FFF);
+	bcma_write16(core, D11REGOFFS(ifs_aifsn), EDCF_AIFSN_MIN);
+
+	/* init the tx dma engines */
+	for (i = 0; i < NFIFO; i++) {
+		if (wlc_hw->di[i])
+			dma_txinit(wlc_hw->di[i]);
+	}
+
+	/* init the rx dma engine(s) and post receive buffers */
+	dma_rxinit(wlc_hw->di[RX_FIFO]);
+	dma_rxfill(wlc_hw->di[RX_FIFO]);
+}
+
+static void brcms_b_init(struct brcms_hardware *wlc_hw, u16 chanspec)
+{
+	u32 macintmask;
+	bool fastclk;
+	struct brcms_c_info *wlc = wlc_hw->wlc;
+
+	/* request FAST clock if not on */
+	fastclk = wlc_hw->forcefastclk;
+	if (!fastclk)
+		brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST);
+
+	/* disable interrupts */
+	macintmask = brcms_intrsoff(wlc->wl);
+
+	/* set up the specified band and chanspec */
+	brcms_c_setxband(wlc_hw, chspec_bandunit(chanspec));
+	wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec);
+
+	/* do one-time phy inits and calibration */
+	wlc_phy_cal_init(wlc_hw->band->pi);
+
+	/* core-specific initialization */
+	brcms_b_coreinit(wlc);
+
+	/* band-specific inits */
+	brcms_b_bsinit(wlc, chanspec);
+
+	/* restore macintmask */
+	brcms_intrsrestore(wlc->wl, macintmask);
+
+	/* seed wake_override with BRCMS_WAKE_OVERRIDE_MACSUSPEND since the mac
+	 * is suspended and brcms_c_enable_mac() will clear this override bit.
+	 */
+	mboolset(wlc_hw->wake_override, BRCMS_WAKE_OVERRIDE_MACSUSPEND);
+
+	/*
+	 * initialize mac_suspend_depth to 1 to match ucode
+	 * initial suspended state
+	 */
+	wlc_hw->mac_suspend_depth = 1;
+
+	/* restore the clk */
+	if (!fastclk)
+		brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_DYNAMIC);
+}
+
+static void brcms_c_set_phy_chanspec(struct brcms_c_info *wlc,
+				     u16 chanspec)
+{
+	/* Save our copy of the chanspec */
+	wlc->chanspec = chanspec;
+
+	/* Set the chanspec and power limits for this locale */
+	brcms_c_channel_set_chanspec(wlc->cmi, chanspec, BRCMS_TXPWR_MAX);
+
+	if (wlc->stf->ss_algosel_auto)
+		brcms_c_stf_ss_algo_channel_get(wlc, &wlc->stf->ss_algo_channel,
+					    chanspec);
+
+	brcms_c_stf_ss_update(wlc, wlc->band);
+}
+
+static void
+brcms_default_rateset(struct brcms_c_info *wlc, struct brcms_c_rateset *rs)
+{
+	brcms_c_rateset_default(rs, NULL, wlc->band->phytype,
+		wlc->band->bandtype, false, BRCMS_RATE_MASK_FULL,
+		(bool) (wlc->pub->_n_enab & SUPPORT_11N),
+		brcms_chspec_bw(wlc->default_bss->chanspec),
+		wlc->stf->txstreams);
+}
+
+/* derive wlc->band->basic_rate[] table from 'rateset' */
+static void brcms_c_rate_lookup_init(struct brcms_c_info *wlc,
+			      struct brcms_c_rateset *rateset)
+{
+	u8 rate;
+	u8 mandatory;
+	u8 cck_basic = 0;
+	u8 ofdm_basic = 0;
+	u8 *br = wlc->band->basic_rate;
+	uint i;
+
+	/* incoming rates are in 500kbps units as in 802.11 Supported Rates */
+	memset(br, 0, BRCM_MAXRATE + 1);
+
+	/* For each basic rate in the rates list, make an entry in the
+	 * best basic lookup.
+	 */
+	for (i = 0; i < rateset->count; i++) {
+		/* only make an entry for a basic rate */
+		if (!(rateset->rates[i] & BRCMS_RATE_FLAG))
+			continue;
+
+		/* mask off basic bit */
+		rate = (rateset->rates[i] & BRCMS_RATE_MASK);
+
+		if (rate > BRCM_MAXRATE) {
+			brcms_err(wlc->hw->d11core, "brcms_c_rate_lookup_init: "
+				  "invalid rate 0x%X in rate set\n",
+				  rateset->rates[i]);
+			continue;
+		}
+
+		br[rate] = rate;
+	}
+
+	/* The rate lookup table now has non-zero entries for each
+	 * basic rate, equal to the basic rate: br[basicN] = basicN
+	 *
+	 * To look up the best basic rate corresponding to any
+	 * particular rate, code can use the basic_rate table
+	 * like this
+	 *
+	 * basic_rate = wlc->band->basic_rate[tx_rate]
+	 *
+	 * Make sure there is a best basic rate entry for
+	 * every rate by walking up the table from low rates
+	 * to high, filling in holes in the lookup table
+	 */
+
+	for (i = 0; i < wlc->band->hw_rateset.count; i++) {
+		rate = wlc->band->hw_rateset.rates[i];
+
+		if (br[rate] != 0) {
+			/* This rate is a basic rate.
+			 * Keep track of the best basic rate so far by
+			 * modulation type.
+			 */
+			if (is_ofdm_rate(rate))
+				ofdm_basic = rate;
+			else
+				cck_basic = rate;
+
+			continue;
+		}
+
+		/* This rate is not a basic rate so figure out the
+		 * best basic rate less than this rate and fill in
+		 * the hole in the table
+		 */
+
+		br[rate] = is_ofdm_rate(rate) ? ofdm_basic : cck_basic;
+
+		if (br[rate] != 0)
+			continue;
+
+		if (is_ofdm_rate(rate)) {
+			/*
+			 * In 11g and 11a, the OFDM mandatory rates
+			 * are 6, 12, and 24 Mbps
+			 */
+			if (rate >= BRCM_RATE_24M)
+				mandatory = BRCM_RATE_24M;
+			else if (rate >= BRCM_RATE_12M)
+				mandatory = BRCM_RATE_12M;
+			else
+				mandatory = BRCM_RATE_6M;
+		} else {
+			/* In 11b, all CCK rates are mandatory 1 - 11 Mbps */
+			mandatory = rate;
+		}
+
+		br[rate] = mandatory;
+	}
+}
+
+static void brcms_c_bandinit_ordered(struct brcms_c_info *wlc,
+				     u16 chanspec)
+{
+	struct brcms_c_rateset default_rateset;
+	uint parkband;
+	uint i, band_order[2];
+
+	/*
+	 * We might have been bandlocked during down and the chip
+	 * power-cycled (hibernate). Figure out the right band to park on
+	 */
+	if (wlc->bandlocked || wlc->pub->_nbands == 1) {
+		/* updated in brcms_c_bandlock() */
+		parkband = wlc->band->bandunit;
+		band_order[0] = band_order[1] = parkband;
+	} else {
+		/* park on the band of the specified chanspec */
+		parkband = chspec_bandunit(chanspec);
+
+		/* order so that parkband initialize last */
+		band_order[0] = parkband ^ 1;
+		band_order[1] = parkband;
+	}
+
+	/* make each band operational, software state init */
+	for (i = 0; i < wlc->pub->_nbands; i++) {
+		uint j = band_order[i];
+
+		wlc->band = wlc->bandstate[j];
+
+		brcms_default_rateset(wlc, &default_rateset);
+
+		/* fill in hw_rate */
+		brcms_c_rateset_filter(&default_rateset, &wlc->band->hw_rateset,
+				   false, BRCMS_RATES_CCK_OFDM, BRCMS_RATE_MASK,
+				   (bool) (wlc->pub->_n_enab & SUPPORT_11N));
+
+		/* init basic rate lookup */
+		brcms_c_rate_lookup_init(wlc, &default_rateset);
+	}
+
+	/* sync up phy/radio chanspec */
+	brcms_c_set_phy_chanspec(wlc, chanspec);
+}
+
+/*
+ * Set or clear filtering related maccontrol bits based on
+ * specified filter flags
+ */
+void brcms_c_mac_promisc(struct brcms_c_info *wlc, uint filter_flags)
+{
+	u32 promisc_bits = 0;
+
+	wlc->filter_flags = filter_flags;
+
+	if (filter_flags & FIF_OTHER_BSS)
+		promisc_bits |= MCTL_PROMISC;
+
+	if (filter_flags & FIF_BCN_PRBRESP_PROMISC)
+		promisc_bits |= MCTL_BCNS_PROMISC;
+
+	if (filter_flags & FIF_FCSFAIL)
+		promisc_bits |= MCTL_KEEPBADFCS;
+
+	if (filter_flags & (FIF_CONTROL | FIF_PSPOLL))
+		promisc_bits |= MCTL_KEEPCONTROL;
+
+	brcms_b_mctrl(wlc->hw,
+		MCTL_PROMISC | MCTL_BCNS_PROMISC |
+		MCTL_KEEPCONTROL | MCTL_KEEPBADFCS,
+		promisc_bits);
+}
+
+/*
+ * ucode, hwmac update
+ *    Channel dependent updates for ucode and hw
+ */
+static void brcms_c_ucode_mac_upd(struct brcms_c_info *wlc)
+{
+	/* enable or disable any active IBSSs depending on whether or not
+	 * we are on the home channel
+	 */
+	if (wlc->home_chanspec == wlc_phy_chanspec_get(wlc->band->pi)) {
+		if (wlc->pub->associated) {
+			/*
+			 * BMAC_NOTE: This is something that should be fixed
+			 * in ucode inits. I think that the ucode inits set
+			 * up the bcn templates and shm values with a bogus
+			 * beacon. This should not be done in the inits. If
+			 * ucode needs to set up a beacon for testing, the
+			 * test routines should write it down, not expect the
+			 * inits to populate a bogus beacon.
+			 */
+			if (BRCMS_PHY_11N_CAP(wlc->band))
+				brcms_b_write_shm(wlc->hw,
+						M_BCN_TXTSF_OFFSET, 0);
+		}
+	} else {
+		/* disable an active IBSS if we are not on the home channel */
+	}
+}
+
+static void brcms_c_write_rate_shm(struct brcms_c_info *wlc, u8 rate,
+				   u8 basic_rate)
+{
+	u8 phy_rate, index;
+	u8 basic_phy_rate, basic_index;
+	u16 dir_table, basic_table;
+	u16 basic_ptr;
+
+	/* Shared memory address for the table we are reading */
+	dir_table = is_ofdm_rate(basic_rate) ? M_RT_DIRMAP_A : M_RT_DIRMAP_B;
+
+	/* Shared memory address for the table we are writing */
+	basic_table = is_ofdm_rate(rate) ? M_RT_BBRSMAP_A : M_RT_BBRSMAP_B;
+
+	/*
+	 * for a given rate, the LS-nibble of the PLCP SIGNAL field is
+	 * the index into the rate table.
+	 */
+	phy_rate = rate_info[rate] & BRCMS_RATE_MASK;
+	basic_phy_rate = rate_info[basic_rate] & BRCMS_RATE_MASK;
+	index = phy_rate & 0xf;
+	basic_index = basic_phy_rate & 0xf;
+
+	/* Find the SHM pointer to the ACK rate entry by looking in the
+	 * Direct-map Table
+	 */
+	basic_ptr = brcms_b_read_shm(wlc->hw, (dir_table + basic_index * 2));
+
+	/* Update the SHM BSS-basic-rate-set mapping table with the pointer
+	 * to the correct basic rate for the given incoming rate
+	 */
+	brcms_b_write_shm(wlc->hw, (basic_table + index * 2), basic_ptr);
+}
+
+static const struct brcms_c_rateset *
+brcms_c_rateset_get_hwrs(struct brcms_c_info *wlc)
+{
+	const struct brcms_c_rateset *rs_dflt;
+
+	if (BRCMS_PHY_11N_CAP(wlc->band)) {
+		if (wlc->band->bandtype == BRCM_BAND_5G)
+			rs_dflt = &ofdm_mimo_rates;
+		else
+			rs_dflt = &cck_ofdm_mimo_rates;
+	} else if (wlc->band->gmode)
+		rs_dflt = &cck_ofdm_rates;
+	else
+		rs_dflt = &cck_rates;
+
+	return rs_dflt;
+}
+
+static void brcms_c_set_ratetable(struct brcms_c_info *wlc)
+{
+	const struct brcms_c_rateset *rs_dflt;
+	struct brcms_c_rateset rs;
+	u8 rate, basic_rate;
+	uint i;
+
+	rs_dflt = brcms_c_rateset_get_hwrs(wlc);
+
+	brcms_c_rateset_copy(rs_dflt, &rs);
+	brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams);
+
+	/* walk the phy rate table and update SHM basic rate lookup table */
+	for (i = 0; i < rs.count; i++) {
+		rate = rs.rates[i] & BRCMS_RATE_MASK;
+
+		/* for a given rate brcms_basic_rate returns the rate at
+		 * which a response ACK/CTS should be sent.
+		 */
+		basic_rate = brcms_basic_rate(wlc, rate);
+		if (basic_rate == 0)
+			/* This should only happen if we are using a
+			 * restricted rateset.
+			 */
+			basic_rate = rs.rates[0] & BRCMS_RATE_MASK;
+
+		brcms_c_write_rate_shm(wlc, rate, basic_rate);
+	}
+}
+
+/* band-specific init */
+static void brcms_c_bsinit(struct brcms_c_info *wlc)
+{
+	brcms_dbg_info(wlc->hw->d11core, "wl%d: bandunit %d\n",
+		       wlc->pub->unit, wlc->band->bandunit);
+
+	/* write ucode ACK/CTS rate table */
+	brcms_c_set_ratetable(wlc);
+
+	/* update some band specific mac configuration */
+	brcms_c_ucode_mac_upd(wlc);
+
+	/* init antenna selection */
+	brcms_c_antsel_init(wlc->asi);
+
+}
+
+/* formula:  IDLE_BUSY_RATIO_X_16 = (100-duty_cycle)/duty_cycle*16 */
+static int
+brcms_c_duty_cycle_set(struct brcms_c_info *wlc, int duty_cycle, bool isOFDM,
+		   bool writeToShm)
+{
+	int idle_busy_ratio_x_16 = 0;
+	uint offset =
+	    isOFDM ? M_TX_IDLE_BUSY_RATIO_X_16_OFDM :
+	    M_TX_IDLE_BUSY_RATIO_X_16_CCK;
+	if (duty_cycle > 100 || duty_cycle < 0) {
+		brcms_err(wlc->hw->d11core,
+			  "wl%d:  duty cycle value off limit\n",
+			  wlc->pub->unit);
+		return -EINVAL;
+	}
+	if (duty_cycle)
+		idle_busy_ratio_x_16 = (100 - duty_cycle) * 16 / duty_cycle;
+	/* Only write to shared memory  when wl is up */
+	if (writeToShm)
+		brcms_b_write_shm(wlc->hw, offset, (u16) idle_busy_ratio_x_16);
+
+	if (isOFDM)
+		wlc->tx_duty_cycle_ofdm = (u16) duty_cycle;
+	else
+		wlc->tx_duty_cycle_cck = (u16) duty_cycle;
+
+	return 0;
+}
+
+/* push sw hps and wake state through hardware */
+static void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc)
+{
+	u32 v1, v2;
+	bool hps;
+	bool awake_before;
+
+	hps = brcms_c_ps_allowed(wlc);
+
+	brcms_dbg_mac80211(wlc->hw->d11core, "wl%d: hps %d\n", wlc->pub->unit,
+			   hps);
+
+	v1 = bcma_read32(wlc->hw->d11core, D11REGOFFS(maccontrol));
+	v2 = MCTL_WAKE;
+	if (hps)
+		v2 |= MCTL_HPS;
+
+	brcms_b_mctrl(wlc->hw, MCTL_WAKE | MCTL_HPS, v2);
+
+	awake_before = ((v1 & MCTL_WAKE) || ((v1 & MCTL_HPS) == 0));
+
+	if (!awake_before)
+		brcms_b_wait_for_wake(wlc->hw);
+}
+
+/*
+ * Write this BSS config's MAC address to core.
+ * Updates RXE match engine.
+ */
+static int brcms_c_set_mac(struct brcms_bss_cfg *bsscfg)
+{
+	int err = 0;
+	struct brcms_c_info *wlc = bsscfg->wlc;
+
+	/* enter the MAC addr into the RXE match registers */
+	brcms_c_set_addrmatch(wlc, RCM_MAC_OFFSET, wlc->pub->cur_etheraddr);
+
+	brcms_c_ampdu_macaddr_upd(wlc);
+
+	return err;
+}
+
+/* Write the BSS config's BSSID address to core (set_bssid in d11procs.tcl).
+ * Updates RXE match engine.
+ */
+static void brcms_c_set_bssid(struct brcms_bss_cfg *bsscfg)
+{
+	/* we need to update BSSID in RXE match registers */
+	brcms_c_set_addrmatch(bsscfg->wlc, RCM_BSSID_OFFSET, bsscfg->BSSID);
+}
+
+void brcms_c_set_ssid(struct brcms_c_info *wlc, u8 *ssid, size_t ssid_len)
+{
+	u8 len = min_t(u8, sizeof(wlc->bsscfg->SSID), ssid_len);
+	memset(wlc->bsscfg->SSID, 0, sizeof(wlc->bsscfg->SSID));
+
+	memcpy(wlc->bsscfg->SSID, ssid, len);
+	wlc->bsscfg->SSID_len = len;
+}
+
+static void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, bool shortslot)
+{
+	wlc_hw->shortslot = shortslot;
+
+	if (wlc_hw->band->bandtype == BRCM_BAND_2G && wlc_hw->up) {
+		brcms_c_suspend_mac_and_wait(wlc_hw->wlc);
+		brcms_b_update_slot_timing(wlc_hw, shortslot);
+		brcms_c_enable_mac(wlc_hw->wlc);
+	}
+}
+
+/*
+ * Suspend the the MAC and update the slot timing
+ * for standard 11b/g (20us slots) or shortslot 11g (9us slots).
+ */
+static void brcms_c_switch_shortslot(struct brcms_c_info *wlc, bool shortslot)
+{
+	/* use the override if it is set */
+	if (wlc->shortslot_override != BRCMS_SHORTSLOT_AUTO)
+		shortslot = (wlc->shortslot_override == BRCMS_SHORTSLOT_ON);
+
+	if (wlc->shortslot == shortslot)
+		return;
+
+	wlc->shortslot = shortslot;
+
+	brcms_b_set_shortslot(wlc->hw, shortslot);
+}
+
+static void brcms_c_set_home_chanspec(struct brcms_c_info *wlc, u16 chanspec)
+{
+	if (wlc->home_chanspec != chanspec) {
+		wlc->home_chanspec = chanspec;
+
+		if (wlc->pub->associated)
+			wlc->bsscfg->current_bss->chanspec = chanspec;
+	}
+}
+
+void
+brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, u16 chanspec,
+		      bool mute_tx, struct txpwr_limits *txpwr)
+{
+	uint bandunit;
+
+	brcms_dbg_mac80211(wlc_hw->d11core, "wl%d: 0x%x\n", wlc_hw->unit,
+			   chanspec);
+
+	wlc_hw->chanspec = chanspec;
+
+	/* Switch bands if necessary */
+	if (wlc_hw->_nbands > 1) {
+		bandunit = chspec_bandunit(chanspec);
+		if (wlc_hw->band->bandunit != bandunit) {
+			/* brcms_b_setband disables other bandunit,
+			 *  use light band switch if not up yet
+			 */
+			if (wlc_hw->up) {
+				wlc_phy_chanspec_radio_set(wlc_hw->
+							   bandstate[bandunit]->
+							   pi, chanspec);
+				brcms_b_setband(wlc_hw, bandunit, chanspec);
+			} else {
+				brcms_c_setxband(wlc_hw, bandunit);
+			}
+		}
+	}
+
+	wlc_phy_initcal_enable(wlc_hw->band->pi, !mute_tx);
+
+	if (!wlc_hw->up) {
+		if (wlc_hw->clk)
+			wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr,
+						  chanspec);
+		wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec);
+	} else {
+		wlc_phy_chanspec_set(wlc_hw->band->pi, chanspec);
+		wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr, chanspec);
+
+		/* Update muting of the channel */
+		brcms_b_mute(wlc_hw, mute_tx);
+	}
+}
+
+/* switch to and initialize new band */
+static void brcms_c_setband(struct brcms_c_info *wlc,
+					   uint bandunit)
+{
+	wlc->band = wlc->bandstate[bandunit];
+
+	if (!wlc->pub->up)
+		return;
+
+	/* wait for at least one beacon before entering sleeping state */
+	brcms_c_set_ps_ctrl(wlc);
+
+	/* band-specific initializations */
+	brcms_c_bsinit(wlc);
+}
+
+static void brcms_c_set_chanspec(struct brcms_c_info *wlc, u16 chanspec)
+{
+	uint bandunit;
+	bool switchband = false;
+	u16 old_chanspec = wlc->chanspec;
+
+	if (!brcms_c_valid_chanspec_db(wlc->cmi, chanspec)) {
+		brcms_err(wlc->hw->d11core, "wl%d: %s: Bad channel %d\n",
+			  wlc->pub->unit, __func__, CHSPEC_CHANNEL(chanspec));
+		return;
+	}
+
+	/* Switch bands if necessary */
+	if (wlc->pub->_nbands > 1) {
+		bandunit = chspec_bandunit(chanspec);
+		if (wlc->band->bandunit != bandunit || wlc->bandinit_pending) {
+			switchband = true;
+			if (wlc->bandlocked) {
+				brcms_err(wlc->hw->d11core,
+					  "wl%d: %s: chspec %d band is locked!\n",
+					  wlc->pub->unit, __func__,
+					  CHSPEC_CHANNEL(chanspec));
+				return;
+			}
+			/*
+			 * should the setband call come after the
+			 * brcms_b_chanspec() ? if the setband updates
+			 * (brcms_c_bsinit) use low level calls to inspect and
+			 * set state, the state inspected may be from the wrong
+			 * band, or the following brcms_b_set_chanspec() may
+			 * undo the work.
+			 */
+			brcms_c_setband(wlc, bandunit);
+		}
+	}
+
+	/* sync up phy/radio chanspec */
+	brcms_c_set_phy_chanspec(wlc, chanspec);
+
+	/* init antenna selection */
+	if (brcms_chspec_bw(old_chanspec) != brcms_chspec_bw(chanspec)) {
+		brcms_c_antsel_init(wlc->asi);
+
+		/* Fix the hardware rateset based on bw.
+		 * Mainly add MCS32 for 40Mhz, remove MCS 32 for 20Mhz
+		 */
+		brcms_c_rateset_bw_mcs_filter(&wlc->band->hw_rateset,
+			wlc->band->mimo_cap_40 ? brcms_chspec_bw(chanspec) : 0);
+	}
+
+	/* update some mac configuration since chanspec changed */
+	brcms_c_ucode_mac_upd(wlc);
+}
+
+/*
+ * This function changes the phytxctl for beacon based on current
+ * beacon ratespec AND txant setting as per this table:
+ *  ratespec     CCK		ant = wlc->stf->txant
+ *		OFDM		ant = 3
+ */
+void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc,
+				       u32 bcn_rspec)
+{
+	u16 phyctl;
+	u16 phytxant = wlc->stf->phytxant;
+	u16 mask = PHY_TXC_ANT_MASK;
+
+	/* for non-siso rates or default setting, use the available chains */
+	if (BRCMS_PHY_11N_CAP(wlc->band))
+		phytxant = brcms_c_stf_phytxchain_sel(wlc, bcn_rspec);
+
+	phyctl = brcms_b_read_shm(wlc->hw, M_BCN_PCTLWD);
+	phyctl = (phyctl & ~mask) | phytxant;
+	brcms_b_write_shm(wlc->hw, M_BCN_PCTLWD, phyctl);
+}
+
+/*
+ * centralized protection config change function to simplify debugging, no
+ * consistency checking this should be called only on changes to avoid overhead
+ * in periodic function
+ */
+void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx, int val)
+{
+	/*
+	 * Cannot use brcms_dbg_* here because this function is called
+	 * before wlc is sufficiently initialized.
+	 */
+	BCMMSG(wlc->wiphy, "idx %d, val %d\n", idx, val);
+
+	switch (idx) {
+	case BRCMS_PROT_G_SPEC:
+		wlc->protection->_g = (bool) val;
+		break;
+	case BRCMS_PROT_G_OVR:
+		wlc->protection->g_override = (s8) val;
+		break;
+	case BRCMS_PROT_G_USER:
+		wlc->protection->gmode_user = (u8) val;
+		break;
+	case BRCMS_PROT_OVERLAP:
+		wlc->protection->overlap = (s8) val;
+		break;
+	case BRCMS_PROT_N_USER:
+		wlc->protection->nmode_user = (s8) val;
+		break;
+	case BRCMS_PROT_N_CFG:
+		wlc->protection->n_cfg = (s8) val;
+		break;
+	case BRCMS_PROT_N_CFG_OVR:
+		wlc->protection->n_cfg_override = (s8) val;
+		break;
+	case BRCMS_PROT_N_NONGF:
+		wlc->protection->nongf = (bool) val;
+		break;
+	case BRCMS_PROT_N_NONGF_OVR:
+		wlc->protection->nongf_override = (s8) val;
+		break;
+	case BRCMS_PROT_N_PAM_OVR:
+		wlc->protection->n_pam_override = (s8) val;
+		break;
+	case BRCMS_PROT_N_OBSS:
+		wlc->protection->n_obss = (bool) val;
+		break;
+
+	default:
+		break;
+	}
+
+}
+
+static void brcms_c_ht_update_sgi_rx(struct brcms_c_info *wlc, int val)
+{
+	if (wlc->pub->up) {
+		brcms_c_update_beacon(wlc);
+		brcms_c_update_probe_resp(wlc, true);
+	}
+}
+
+static void brcms_c_ht_update_ldpc(struct brcms_c_info *wlc, s8 val)
+{
+	wlc->stf->ldpc = val;
+
+	if (wlc->pub->up) {
+		brcms_c_update_beacon(wlc);
+		brcms_c_update_probe_resp(wlc, true);
+		wlc_phy_ldpc_override_set(wlc->band->pi, (val ? true : false));
+	}
+}
+
+void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
+		       const struct ieee80211_tx_queue_params *params,
+		       bool suspend)
+{
+	int i;
+	struct shm_acparams acp_shm;
+	u16 *shm_entry;
+
+	/* Only apply params if the core is out of reset and has clocks */
+	if (!wlc->clk) {
+		brcms_err(wlc->hw->d11core, "wl%d: %s : no-clock\n",
+			  wlc->pub->unit, __func__);
+		return;
+	}
+
+	memset(&acp_shm, 0, sizeof(struct shm_acparams));
+	/* fill in shm ac params struct */
+	acp_shm.txop = params->txop;
+	/* convert from units of 32us to us for ucode */
+	wlc->edcf_txop[aci & 0x3] = acp_shm.txop =
+	    EDCF_TXOP2USEC(acp_shm.txop);
+	acp_shm.aifs = (params->aifs & EDCF_AIFSN_MASK);
+
+	if (aci == IEEE80211_AC_VI && acp_shm.txop == 0
+	    && acp_shm.aifs < EDCF_AIFSN_MAX)
+		acp_shm.aifs++;
+
+	if (acp_shm.aifs < EDCF_AIFSN_MIN
+	    || acp_shm.aifs > EDCF_AIFSN_MAX) {
+		brcms_err(wlc->hw->d11core, "wl%d: edcf_setparams: bad "
+			  "aifs %d\n", wlc->pub->unit, acp_shm.aifs);
+	} else {
+		acp_shm.cwmin = params->cw_min;
+		acp_shm.cwmax = params->cw_max;
+		acp_shm.cwcur = acp_shm.cwmin;
+		acp_shm.bslots =
+			bcma_read16(wlc->hw->d11core, D11REGOFFS(tsf_random)) &
+			acp_shm.cwcur;
+		acp_shm.reggap = acp_shm.bslots + acp_shm.aifs;
+		/* Indicate the new params to the ucode */
+		acp_shm.status = brcms_b_read_shm(wlc->hw, (M_EDCF_QINFO +
+						  wme_ac2fifo[aci] *
+						  M_EDCF_QLEN +
+						  M_EDCF_STATUS_OFF));
+		acp_shm.status |= WME_STATUS_NEWAC;
+
+		/* Fill in shm acparam table */
+		shm_entry = (u16 *) &acp_shm;
+		for (i = 0; i < (int)sizeof(struct shm_acparams); i += 2)
+			brcms_b_write_shm(wlc->hw,
+					  M_EDCF_QINFO +
+					  wme_ac2fifo[aci] * M_EDCF_QLEN + i,
+					  *shm_entry++);
+	}
+
+	if (suspend)
+		brcms_c_suspend_mac_and_wait(wlc);
+
+	brcms_c_update_beacon(wlc);
+	brcms_c_update_probe_resp(wlc, false);
+
+	if (suspend)
+		brcms_c_enable_mac(wlc);
+}
+
+static void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend)
+{
+	u16 aci;
+	int i_ac;
+	struct ieee80211_tx_queue_params txq_pars;
+	static const struct edcf_acparam default_edcf_acparams[] = {
+		 {EDCF_AC_BE_ACI_STA, EDCF_AC_BE_ECW_STA, EDCF_AC_BE_TXOP_STA},
+		 {EDCF_AC_BK_ACI_STA, EDCF_AC_BK_ECW_STA, EDCF_AC_BK_TXOP_STA},
+		 {EDCF_AC_VI_ACI_STA, EDCF_AC_VI_ECW_STA, EDCF_AC_VI_TXOP_STA},
+		 {EDCF_AC_VO_ACI_STA, EDCF_AC_VO_ECW_STA, EDCF_AC_VO_TXOP_STA}
+	}; /* ucode needs these parameters during its initialization */
+	const struct edcf_acparam *edcf_acp = &default_edcf_acparams[0];
+
+	for (i_ac = 0; i_ac < IEEE80211_NUM_ACS; i_ac++, edcf_acp++) {
+		/* find out which ac this set of params applies to */
+		aci = (edcf_acp->ACI & EDCF_ACI_MASK) >> EDCF_ACI_SHIFT;
+
+		/* fill in shm ac params struct */
+		txq_pars.txop = edcf_acp->TXOP;
+		txq_pars.aifs = edcf_acp->ACI;
+
+		/* CWmin = 2^(ECWmin) - 1 */
+		txq_pars.cw_min = EDCF_ECW2CW(edcf_acp->ECW & EDCF_ECWMIN_MASK);
+		/* CWmax = 2^(ECWmax) - 1 */
+		txq_pars.cw_max = EDCF_ECW2CW((edcf_acp->ECW & EDCF_ECWMAX_MASK)
+					    >> EDCF_ECWMAX_SHIFT);
+		brcms_c_wme_setparams(wlc, aci, &txq_pars, suspend);
+	}
+
+	if (suspend) {
+		brcms_c_suspend_mac_and_wait(wlc);
+		brcms_c_enable_mac(wlc);
+	}
+}
+
+static void brcms_c_radio_monitor_start(struct brcms_c_info *wlc)
+{
+	/* Don't start the timer if HWRADIO feature is disabled */
+	if (wlc->radio_monitor)
+		return;
+
+	wlc->radio_monitor = true;
+	brcms_b_pllreq(wlc->hw, true, BRCMS_PLLREQ_RADIO_MON);
+	brcms_add_timer(wlc->radio_timer, TIMER_INTERVAL_RADIOCHK, true);
+}
+
+static bool brcms_c_radio_monitor_stop(struct brcms_c_info *wlc)
+{
+	if (!wlc->radio_monitor)
+		return true;
+
+	wlc->radio_monitor = false;
+	brcms_b_pllreq(wlc->hw, false, BRCMS_PLLREQ_RADIO_MON);
+	return brcms_del_timer(wlc->radio_timer);
+}
+
+/* read hwdisable state and propagate to wlc flag */
+static void brcms_c_radio_hwdisable_upd(struct brcms_c_info *wlc)
+{
+	if (wlc->pub->hw_off)
+		return;
+
+	if (brcms_b_radio_read_hwdisabled(wlc->hw))
+		mboolset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE);
+	else
+		mboolclr(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE);
+}
+
+/* update hwradio status and return it */
+bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc)
+{
+	brcms_c_radio_hwdisable_upd(wlc);
+
+	return mboolisset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE) ?
+			true : false;
+}
+
+/* periodical query hw radio button while driver is "down" */
+static void brcms_c_radio_timer(void *arg)
+{
+	struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
+
+	if (brcms_deviceremoved(wlc)) {
+		brcms_err(wlc->hw->d11core, "wl%d: %s: dead chip\n",
+			  wlc->pub->unit, __func__);
+		brcms_down(wlc->wl);
+		return;
+	}
+
+	brcms_c_radio_hwdisable_upd(wlc);
+}
+
+/* common low-level watchdog code */
+static void brcms_b_watchdog(struct brcms_c_info *wlc)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+
+	if (!wlc_hw->up)
+		return;
+
+	/* increment second count */
+	wlc_hw->now++;
+
+	/* Check for FIFO error interrupts */
+	brcms_b_fifoerrors(wlc_hw);
+
+	/* make sure RX dma has buffers */
+	dma_rxfill(wlc->hw->di[RX_FIFO]);
+
+	wlc_phy_watchdog(wlc_hw->band->pi);
+}
+
+/* common watchdog code */
+static void brcms_c_watchdog(struct brcms_c_info *wlc)
+{
+	brcms_dbg_info(wlc->hw->d11core, "wl%d\n", wlc->pub->unit);
+
+	if (!wlc->pub->up)
+		return;
+
+	if (brcms_deviceremoved(wlc)) {
+		brcms_err(wlc->hw->d11core, "wl%d: %s: dead chip\n",
+			  wlc->pub->unit, __func__);
+		brcms_down(wlc->wl);
+		return;
+	}
+
+	/* increment second count */
+	wlc->pub->now++;
+
+	brcms_c_radio_hwdisable_upd(wlc);
+	/* if radio is disable, driver may be down, quit here */
+	if (wlc->pub->radio_disabled)
+		return;
+
+	brcms_b_watchdog(wlc);
+
+	/*
+	 * occasionally sample mac stat counters to
+	 * detect 16-bit counter wrap
+	 */
+	if ((wlc->pub->now % SW_TIMER_MAC_STAT_UPD) == 0)
+		brcms_c_statsupd(wlc);
+
+	if (BRCMS_ISNPHY(wlc->band) &&
+	    ((wlc->pub->now - wlc->tempsense_lasttime) >=
+	     BRCMS_TEMPSENSE_PERIOD)) {
+		wlc->tempsense_lasttime = wlc->pub->now;
+		brcms_c_tempsense_upd(wlc);
+	}
+}
+
+static void brcms_c_watchdog_by_timer(void *arg)
+{
+	struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
+
+	brcms_c_watchdog(wlc);
+}
+
+static bool brcms_c_timers_init(struct brcms_c_info *wlc, int unit)
+{
+	wlc->wdtimer = brcms_init_timer(wlc->wl, brcms_c_watchdog_by_timer,
+		wlc, "watchdog");
+	if (!wlc->wdtimer) {
+		wiphy_err(wlc->wiphy, "wl%d:  wl_init_timer for wdtimer "
+			  "failed\n", unit);
+		goto fail;
+	}
+
+	wlc->radio_timer = brcms_init_timer(wlc->wl, brcms_c_radio_timer,
+		wlc, "radio");
+	if (!wlc->radio_timer) {
+		wiphy_err(wlc->wiphy, "wl%d:  wl_init_timer for radio_timer "
+			  "failed\n", unit);
+		goto fail;
+	}
+
+	return true;
+
+ fail:
+	return false;
+}
+
+/*
+ * Initialize brcms_c_info default values ...
+ * may get overrides later in this function
+ */
+static void brcms_c_info_init(struct brcms_c_info *wlc, int unit)
+{
+	int i;
+
+	/* Save our copy of the chanspec */
+	wlc->chanspec = ch20mhz_chspec(1);
+
+	/* various 802.11g modes */
+	wlc->shortslot = false;
+	wlc->shortslot_override = BRCMS_SHORTSLOT_AUTO;
+
+	brcms_c_protection_upd(wlc, BRCMS_PROT_G_OVR, BRCMS_PROTECTION_AUTO);
+	brcms_c_protection_upd(wlc, BRCMS_PROT_G_SPEC, false);
+
+	brcms_c_protection_upd(wlc, BRCMS_PROT_N_CFG_OVR,
+			       BRCMS_PROTECTION_AUTO);
+	brcms_c_protection_upd(wlc, BRCMS_PROT_N_CFG, BRCMS_N_PROTECTION_OFF);
+	brcms_c_protection_upd(wlc, BRCMS_PROT_N_NONGF_OVR,
+			       BRCMS_PROTECTION_AUTO);
+	brcms_c_protection_upd(wlc, BRCMS_PROT_N_NONGF, false);
+	brcms_c_protection_upd(wlc, BRCMS_PROT_N_PAM_OVR, AUTO);
+
+	brcms_c_protection_upd(wlc, BRCMS_PROT_OVERLAP,
+			       BRCMS_PROTECTION_CTL_OVERLAP);
+
+	/* 802.11g draft 4.0 NonERP elt advertisement */
+	wlc->include_legacy_erp = true;
+
+	wlc->stf->ant_rx_ovr = ANT_RX_DIV_DEF;
+	wlc->stf->txant = ANT_TX_DEF;
+
+	wlc->prb_resp_timeout = BRCMS_PRB_RESP_TIMEOUT;
+
+	wlc->usr_fragthresh = DOT11_DEFAULT_FRAG_LEN;
+	for (i = 0; i < NFIFO; i++)
+		wlc->fragthresh[i] = DOT11_DEFAULT_FRAG_LEN;
+	wlc->RTSThresh = DOT11_DEFAULT_RTS_LEN;
+
+	/* default rate fallback retry limits */
+	wlc->SFBL = RETRY_SHORT_FB;
+	wlc->LFBL = RETRY_LONG_FB;
+
+	/* default mac retry limits */
+	wlc->SRL = RETRY_SHORT_DEF;
+	wlc->LRL = RETRY_LONG_DEF;
+
+	/* WME QoS mode is Auto by default */
+	wlc->pub->_ampdu = AMPDU_AGG_HOST;
+}
+
+static uint brcms_c_attach_module(struct brcms_c_info *wlc)
+{
+	uint err = 0;
+	uint unit;
+	unit = wlc->pub->unit;
+
+	wlc->asi = brcms_c_antsel_attach(wlc);
+	if (wlc->asi == NULL) {
+		wiphy_err(wlc->wiphy, "wl%d: attach: antsel_attach "
+			  "failed\n", unit);
+		err = 44;
+		goto fail;
+	}
+
+	wlc->ampdu = brcms_c_ampdu_attach(wlc);
+	if (wlc->ampdu == NULL) {
+		wiphy_err(wlc->wiphy, "wl%d: attach: ampdu_attach "
+			  "failed\n", unit);
+		err = 50;
+		goto fail;
+	}
+
+	if ((brcms_c_stf_attach(wlc) != 0)) {
+		wiphy_err(wlc->wiphy, "wl%d: attach: stf_attach "
+			  "failed\n", unit);
+		err = 68;
+		goto fail;
+	}
+ fail:
+	return err;
+}
+
+struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc)
+{
+	return wlc->pub;
+}
+
+/* low level attach
+ *    run backplane attach, init nvram
+ *    run phy attach
+ *    initialize software state for each core and band
+ *    put the whole chip in reset(driver down state), no clock
+ */
+static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
+			  uint unit, bool piomode)
+{
+	struct brcms_hardware *wlc_hw;
+	uint err = 0;
+	uint j;
+	bool wme = false;
+	struct shared_phy_params sha_params;
+	struct wiphy *wiphy = wlc->wiphy;
+	struct pci_dev *pcidev = core->bus->host_pci;
+	struct ssb_sprom *sprom = &core->bus->sprom;
+
+	if (core->bus->hosttype == BCMA_HOSTTYPE_PCI)
+		brcms_dbg_info(core, "wl%d: vendor 0x%x device 0x%x\n", unit,
+			       pcidev->vendor,
+			       pcidev->device);
+	else
+		brcms_dbg_info(core, "wl%d: vendor 0x%x device 0x%x\n", unit,
+			       core->bus->boardinfo.vendor,
+			       core->bus->boardinfo.type);
+
+	wme = true;
+
+	wlc_hw = wlc->hw;
+	wlc_hw->wlc = wlc;
+	wlc_hw->unit = unit;
+	wlc_hw->band = wlc_hw->bandstate[0];
+	wlc_hw->_piomode = piomode;
+
+	/* populate struct brcms_hardware with default values  */
+	brcms_b_info_init(wlc_hw);
+
+	/*
+	 * Do the hardware portion of the attach. Also initialize software
+	 * state that depends on the particular hardware we are running.
+	 */
+	wlc_hw->sih = ai_attach(core->bus);
+	if (wlc_hw->sih == NULL) {
+		wiphy_err(wiphy, "wl%d: brcms_b_attach: si_attach failed\n",
+			  unit);
+		err = 11;
+		goto fail;
+	}
+
+	/* verify again the device is supported */
+	if (!brcms_c_chipmatch(core)) {
+		wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported device\n",
+			 unit);
+		err = 12;
+		goto fail;
+	}
+
+	if (core->bus->hosttype == BCMA_HOSTTYPE_PCI) {
+		wlc_hw->vendorid = pcidev->vendor;
+		wlc_hw->deviceid = pcidev->device;
+	} else {
+		wlc_hw->vendorid = core->bus->boardinfo.vendor;
+		wlc_hw->deviceid = core->bus->boardinfo.type;
+	}
+
+	wlc_hw->d11core = core;
+	wlc_hw->corerev = core->id.rev;
+
+	/* validate chip, chiprev and corerev */
+	if (!brcms_c_isgoodchip(wlc_hw)) {
+		err = 13;
+		goto fail;
+	}
+
+	/* initialize power control registers */
+	ai_clkctl_init(wlc_hw->sih);
+
+	/* request fastclock and force fastclock for the rest of attach
+	 * bring the d11 core out of reset.
+	 *   For PMU chips, the first wlc_clkctl_clk is no-op since core-clk
+	 *   is still false; But it will be called again inside wlc_corereset,
+	 *   after d11 is out of reset.
+	 */
+	brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST);
+	brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
+
+	if (!brcms_b_validate_chip_access(wlc_hw)) {
+		wiphy_err(wiphy, "wl%d: brcms_b_attach: validate_chip_access "
+			"failed\n", unit);
+		err = 14;
+		goto fail;
+	}
+
+	/* get the board rev, used just below */
+	j = sprom->board_rev;
+	/* promote srom boardrev of 0xFF to 1 */
+	if (j == BOARDREV_PROMOTABLE)
+		j = BOARDREV_PROMOTED;
+	wlc_hw->boardrev = (u16) j;
+	if (!brcms_c_validboardtype(wlc_hw)) {
+		wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported Broadcom "
+			  "board type (0x%x)" " or revision level (0x%x)\n",
+			  unit, ai_get_boardtype(wlc_hw->sih),
+			  wlc_hw->boardrev);
+		err = 15;
+		goto fail;
+	}
+	wlc_hw->sromrev = sprom->revision;
+	wlc_hw->boardflags = sprom->boardflags_lo + (sprom->boardflags_hi << 16);
+	wlc_hw->boardflags2 = sprom->boardflags2_lo + (sprom->boardflags2_hi << 16);
+
+	if (wlc_hw->boardflags & BFL_NOPLLDOWN)
+		brcms_b_pllreq(wlc_hw, true, BRCMS_PLLREQ_SHARED);
+
+	/* check device id(srom, nvram etc.) to set bands */
+	if (wlc_hw->deviceid == BCM43224_D11N_ID ||
+	    wlc_hw->deviceid == BCM43224_D11N_ID_VEN1 ||
+	    wlc_hw->deviceid == BCM43224_CHIP_ID)
+		/* Dualband boards */
+		wlc_hw->_nbands = 2;
+	else
+		wlc_hw->_nbands = 1;
+
+	if ((ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM43225))
+		wlc_hw->_nbands = 1;
+
+	/* BMAC_NOTE: remove init of pub values when brcms_c_attach()
+	 * unconditionally does the init of these values
+	 */
+	wlc->vendorid = wlc_hw->vendorid;
+	wlc->deviceid = wlc_hw->deviceid;
+	wlc->pub->sih = wlc_hw->sih;
+	wlc->pub->corerev = wlc_hw->corerev;
+	wlc->pub->sromrev = wlc_hw->sromrev;
+	wlc->pub->boardrev = wlc_hw->boardrev;
+	wlc->pub->boardflags = wlc_hw->boardflags;
+	wlc->pub->boardflags2 = wlc_hw->boardflags2;
+	wlc->pub->_nbands = wlc_hw->_nbands;
+
+	wlc_hw->physhim = wlc_phy_shim_attach(wlc_hw, wlc->wl, wlc);
+
+	if (wlc_hw->physhim == NULL) {
+		wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_shim_attach "
+			"failed\n", unit);
+		err = 25;
+		goto fail;
+	}
+
+	/* pass all the parameters to wlc_phy_shared_attach in one struct */
+	sha_params.sih = wlc_hw->sih;
+	sha_params.physhim = wlc_hw->physhim;
+	sha_params.unit = unit;
+	sha_params.corerev = wlc_hw->corerev;
+	sha_params.vid = wlc_hw->vendorid;
+	sha_params.did = wlc_hw->deviceid;
+	sha_params.chip = ai_get_chip_id(wlc_hw->sih);
+	sha_params.chiprev = ai_get_chiprev(wlc_hw->sih);
+	sha_params.chippkg = ai_get_chippkg(wlc_hw->sih);
+	sha_params.sromrev = wlc_hw->sromrev;
+	sha_params.boardtype = ai_get_boardtype(wlc_hw->sih);
+	sha_params.boardrev = wlc_hw->boardrev;
+	sha_params.boardflags = wlc_hw->boardflags;
+	sha_params.boardflags2 = wlc_hw->boardflags2;
+
+	/* alloc and save pointer to shared phy state area */
+	wlc_hw->phy_sh = wlc_phy_shared_attach(&sha_params);
+	if (!wlc_hw->phy_sh) {
+		err = 16;
+		goto fail;
+	}
+
+	/* initialize software state for each core and band */
+	for (j = 0; j < wlc_hw->_nbands; j++) {
+		/*
+		 * band0 is always 2.4Ghz
+		 * band1, if present, is 5Ghz
+		 */
+
+		brcms_c_setxband(wlc_hw, j);
+
+		wlc_hw->band->bandunit = j;
+		wlc_hw->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G;
+		wlc->band->bandunit = j;
+		wlc->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G;
+		wlc->core->coreidx = core->core_index;
+
+		wlc_hw->machwcap = bcma_read32(core, D11REGOFFS(machwcap));
+		wlc_hw->machwcap_backup = wlc_hw->machwcap;
+
+		/* init tx fifo size */
+		WARN_ON(wlc_hw->corerev < XMTFIFOTBL_STARTREV ||
+			(wlc_hw->corerev - XMTFIFOTBL_STARTREV) >
+				ARRAY_SIZE(xmtfifo_sz));
+		wlc_hw->xmtfifo_sz =
+		    xmtfifo_sz[(wlc_hw->corerev - XMTFIFOTBL_STARTREV)];
+		WARN_ON(!wlc_hw->xmtfifo_sz[0]);
+
+		/* Get a phy for this band */
+		wlc_hw->band->pi =
+			wlc_phy_attach(wlc_hw->phy_sh, core,
+				       wlc_hw->band->bandtype,
+				       wlc->wiphy);
+		if (wlc_hw->band->pi == NULL) {
+			wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_"
+				  "attach failed\n", unit);
+			err = 17;
+			goto fail;
+		}
+
+		wlc_phy_machwcap_set(wlc_hw->band->pi, wlc_hw->machwcap);
+
+		wlc_phy_get_phyversion(wlc_hw->band->pi, &wlc_hw->band->phytype,
+				       &wlc_hw->band->phyrev,
+				       &wlc_hw->band->radioid,
+				       &wlc_hw->band->radiorev);
+		wlc_hw->band->abgphy_encore =
+		    wlc_phy_get_encore(wlc_hw->band->pi);
+		wlc->band->abgphy_encore = wlc_phy_get_encore(wlc_hw->band->pi);
+		wlc_hw->band->core_flags =
+		    wlc_phy_get_coreflags(wlc_hw->band->pi);
+
+		/* verify good phy_type & supported phy revision */
+		if (BRCMS_ISNPHY(wlc_hw->band)) {
+			if (NCONF_HAS(wlc_hw->band->phyrev))
+				goto good_phy;
+			else
+				goto bad_phy;
+		} else if (BRCMS_ISLCNPHY(wlc_hw->band)) {
+			if (LCNCONF_HAS(wlc_hw->band->phyrev))
+				goto good_phy;
+			else
+				goto bad_phy;
+		} else {
+ bad_phy:
+			wiphy_err(wiphy, "wl%d: brcms_b_attach: unsupported "
+				  "phy type/rev (%d/%d)\n", unit,
+				  wlc_hw->band->phytype, wlc_hw->band->phyrev);
+			err = 18;
+			goto fail;
+		}
+
+ good_phy:
+		/*
+		 * BMAC_NOTE: wlc->band->pi should not be set below and should
+		 * be done in the high level attach. However we can not make
+		 * that change until all low level access is changed to
+		 * wlc_hw->band->pi. Instead do the wlc->band->pi init below,
+		 * keeping wlc_hw->band->pi as well for incremental update of
+		 * low level fns, and cut over low only init when all fns
+		 * updated.
+		 */
+		wlc->band->pi = wlc_hw->band->pi;
+		wlc->band->phytype = wlc_hw->band->phytype;
+		wlc->band->phyrev = wlc_hw->band->phyrev;
+		wlc->band->radioid = wlc_hw->band->radioid;
+		wlc->band->radiorev = wlc_hw->band->radiorev;
+		brcms_dbg_info(core, "wl%d: phy %u/%u radio %x/%u\n", unit,
+			       wlc->band->phytype, wlc->band->phyrev,
+			       wlc->band->radioid, wlc->band->radiorev);
+		/* default contention windows size limits */
+		wlc_hw->band->CWmin = APHY_CWMIN;
+		wlc_hw->band->CWmax = PHY_CWMAX;
+
+		if (!brcms_b_attach_dmapio(wlc, j, wme)) {
+			err = 19;
+			goto fail;
+		}
+	}
+
+	/* disable core to match driver "down" state */
+	brcms_c_coredisable(wlc_hw);
+
+	/* Match driver "down" state */
+	bcma_host_pci_down(wlc_hw->d11core->bus);
+
+	/* turn off pll and xtal to match driver "down" state */
+	brcms_b_xtal(wlc_hw, OFF);
+
+	/* *******************************************************************
+	 * The hardware is in the DOWN state at this point. D11 core
+	 * or cores are in reset with clocks off, and the board PLLs
+	 * are off if possible.
+	 *
+	 * Beyond this point, wlc->sbclk == false and chip registers
+	 * should not be touched.
+	 *********************************************************************
+	 */
+
+	/* init etheraddr state variables */
+	brcms_c_get_macaddr(wlc_hw, wlc_hw->etheraddr);
+
+	if (is_broadcast_ether_addr(wlc_hw->etheraddr) ||
+	    is_zero_ether_addr(wlc_hw->etheraddr)) {
+		wiphy_err(wiphy, "wl%d: brcms_b_attach: bad macaddr\n",
+			  unit);
+		err = 22;
+		goto fail;
+	}
+
+	brcms_dbg_info(wlc_hw->d11core, "deviceid 0x%x nbands %d board 0x%x\n",
+		       wlc_hw->deviceid, wlc_hw->_nbands,
+		       ai_get_boardtype(wlc_hw->sih));
+
+	return err;
+
+ fail:
+	wiphy_err(wiphy, "wl%d: brcms_b_attach: failed with err %d\n", unit,
+		  err);
+	return err;
+}
+
+static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc)
+{
+	int aa;
+	uint unit;
+	int bandtype;
+	struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom;
+
+	unit = wlc->pub->unit;
+	bandtype = wlc->band->bandtype;
+
+	/* get antennas available */
+	if (bandtype == BRCM_BAND_5G)
+		aa = sprom->ant_available_a;
+	else
+		aa = sprom->ant_available_bg;
+
+	if ((aa < 1) || (aa > 15)) {
+		wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in"
+			  " srom (0x%x), using 3\n", unit, __func__, aa);
+		aa = 3;
+	}
+
+	/* reset the defaults if we have a single antenna */
+	if (aa == 1) {
+		wlc->stf->ant_rx_ovr = ANT_RX_DIV_FORCE_0;
+		wlc->stf->txant = ANT_TX_FORCE_0;
+	} else if (aa == 2) {
+		wlc->stf->ant_rx_ovr = ANT_RX_DIV_FORCE_1;
+		wlc->stf->txant = ANT_TX_FORCE_1;
+	} else {
+	}
+
+	/* Compute Antenna Gain */
+	if (bandtype == BRCM_BAND_5G)
+		wlc->band->antgain = sprom->antenna_gain.a1;
+	else
+		wlc->band->antgain = sprom->antenna_gain.a0;
+
+	return true;
+}
+
+static void brcms_c_bss_default_init(struct brcms_c_info *wlc)
+{
+	u16 chanspec;
+	struct brcms_band *band;
+	struct brcms_bss_info *bi = wlc->default_bss;
+
+	/* init default and target BSS with some sane initial values */
+	memset(bi, 0, sizeof(*bi));
+	bi->beacon_period = BEACON_INTERVAL_DEFAULT;
+
+	/* fill the default channel as the first valid channel
+	 * starting from the 2G channels
+	 */
+	chanspec = ch20mhz_chspec(1);
+	wlc->home_chanspec = bi->chanspec = chanspec;
+
+	/* find the band of our default channel */
+	band = wlc->band;
+	if (wlc->pub->_nbands > 1 &&
+	    band->bandunit != chspec_bandunit(chanspec))
+		band = wlc->bandstate[OTHERBANDUNIT(wlc)];
+
+	/* init bss rates to the band specific default rate set */
+	brcms_c_rateset_default(&bi->rateset, NULL, band->phytype,
+		band->bandtype, false, BRCMS_RATE_MASK_FULL,
+		(bool) (wlc->pub->_n_enab & SUPPORT_11N),
+		brcms_chspec_bw(chanspec), wlc->stf->txstreams);
+
+	if (wlc->pub->_n_enab & SUPPORT_11N)
+		bi->flags |= BRCMS_BSS_HT;
+}
+
+static void brcms_c_update_mimo_band_bwcap(struct brcms_c_info *wlc, u8 bwcap)
+{
+	uint i;
+	struct brcms_band *band;
+
+	for (i = 0; i < wlc->pub->_nbands; i++) {
+		band = wlc->bandstate[i];
+		if (band->bandtype == BRCM_BAND_5G) {
+			if ((bwcap == BRCMS_N_BW_40ALL)
+			    || (bwcap == BRCMS_N_BW_20IN2G_40IN5G))
+				band->mimo_cap_40 = true;
+			else
+				band->mimo_cap_40 = false;
+		} else {
+			if (bwcap == BRCMS_N_BW_40ALL)
+				band->mimo_cap_40 = true;
+			else
+				band->mimo_cap_40 = false;
+		}
+	}
+}
+
+static void brcms_c_timers_deinit(struct brcms_c_info *wlc)
+{
+	/* free timer state */
+	if (wlc->wdtimer) {
+		brcms_free_timer(wlc->wdtimer);
+		wlc->wdtimer = NULL;
+	}
+	if (wlc->radio_timer) {
+		brcms_free_timer(wlc->radio_timer);
+		wlc->radio_timer = NULL;
+	}
+}
+
+static void brcms_c_detach_module(struct brcms_c_info *wlc)
+{
+	if (wlc->asi) {
+		brcms_c_antsel_detach(wlc->asi);
+		wlc->asi = NULL;
+	}
+
+	if (wlc->ampdu) {
+		brcms_c_ampdu_detach(wlc->ampdu);
+		wlc->ampdu = NULL;
+	}
+
+	brcms_c_stf_detach(wlc);
+}
+
+/*
+ * low level detach
+ */
+static void brcms_b_detach(struct brcms_c_info *wlc)
+{
+	uint i;
+	struct brcms_hw_band *band;
+	struct brcms_hardware *wlc_hw = wlc->hw;
+
+	brcms_b_detach_dmapio(wlc_hw);
+
+	band = wlc_hw->band;
+	for (i = 0; i < wlc_hw->_nbands; i++) {
+		if (band->pi) {
+			/* Detach this band's phy */
+			wlc_phy_detach(band->pi);
+			band->pi = NULL;
+		}
+		band = wlc_hw->bandstate[OTHERBANDUNIT(wlc)];
+	}
+
+	/* Free shared phy state */
+	kfree(wlc_hw->phy_sh);
+
+	wlc_phy_shim_detach(wlc_hw->physhim);
+
+	if (wlc_hw->sih) {
+		ai_detach(wlc_hw->sih);
+		wlc_hw->sih = NULL;
+	}
+}
+
+/*
+ * Return a count of the number of driver callbacks still pending.
+ *
+ * General policy is that brcms_c_detach can only dealloc/free software states.
+ * It can NOT touch hardware registers since the d11core may be in reset and
+ * clock may not be available.
+ * One exception is sb register access, which is possible if crystal is turned
+ * on after "down" state, driver should avoid software timer with the exception
+ * of radio_monitor.
+ */
+uint brcms_c_detach(struct brcms_c_info *wlc)
+{
+	uint callbacks;
+
+	if (wlc == NULL)
+		return 0;
+
+	brcms_b_detach(wlc);
+
+	/* delete software timers */
+	callbacks = 0;
+	if (!brcms_c_radio_monitor_stop(wlc))
+		callbacks++;
+
+	brcms_c_channel_mgr_detach(wlc->cmi);
+
+	brcms_c_timers_deinit(wlc);
+
+	brcms_c_detach_module(wlc);
+
+	brcms_c_detach_mfree(wlc);
+	return callbacks;
+}
+
+/* update state that depends on the current value of "ap" */
+static void brcms_c_ap_upd(struct brcms_c_info *wlc)
+{
+	/* STA-BSS; short capable */
+	wlc->PLCPHdr_override = BRCMS_PLCP_SHORT;
+}
+
+/* Initialize just the hardware when coming out of POR or S3/S5 system states */
+static void brcms_b_hw_up(struct brcms_hardware *wlc_hw)
+{
+	if (wlc_hw->wlc->pub->hw_up)
+		return;
+
+	brcms_dbg_info(wlc_hw->d11core, "wl%d\n", wlc_hw->unit);
+
+	/*
+	 * Enable pll and xtal, initialize the power control registers,
+	 * and force fastclock for the remainder of brcms_c_up().
+	 */
+	brcms_b_xtal(wlc_hw, ON);
+	ai_clkctl_init(wlc_hw->sih);
+	brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST);
+
+	/*
+	 * TODO: test suspend/resume
+	 *
+	 * AI chip doesn't restore bar0win2 on
+	 * hibernation/resume, need sw fixup
+	 */
+
+	/*
+	 * Inform phy that a POR reset has occurred so
+	 * it does a complete phy init
+	 */
+	wlc_phy_por_inform(wlc_hw->band->pi);
+
+	wlc_hw->ucode_loaded = false;
+	wlc_hw->wlc->pub->hw_up = true;
+
+	if ((wlc_hw->boardflags & BFL_FEM)
+	    && (ai_get_chip_id(wlc_hw->sih) == BCMA_CHIP_ID_BCM4313)) {
+		if (!
+		    (wlc_hw->boardrev >= 0x1250
+		     && (wlc_hw->boardflags & BFL_FEM_BT)))
+			ai_epa_4313war(wlc_hw->sih);
+	}
+}
+
+static int brcms_b_up_prep(struct brcms_hardware *wlc_hw)
+{
+	brcms_dbg_info(wlc_hw->d11core, "wl%d\n", wlc_hw->unit);
+
+	/*
+	 * Enable pll and xtal, initialize the power control registers,
+	 * and force fastclock for the remainder of brcms_c_up().
+	 */
+	brcms_b_xtal(wlc_hw, ON);
+	ai_clkctl_init(wlc_hw->sih);
+	brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST);
+
+	/*
+	 * Configure pci/pcmcia here instead of in brcms_c_attach()
+	 * to allow mfg hotswap:  down, hotswap (chip power cycle), up.
+	 */
+	bcma_host_pci_irq_ctl(wlc_hw->d11core->bus, wlc_hw->d11core,
+			      true);
+
+	/*
+	 * Need to read the hwradio status here to cover the case where the
+	 * system is loaded with the hw radio disabled. We do not want to
+	 * bring the driver up in this case.
+	 */
+	if (brcms_b_radio_read_hwdisabled(wlc_hw)) {
+		/* put SB PCI in down state again */
+		bcma_host_pci_down(wlc_hw->d11core->bus);
+		brcms_b_xtal(wlc_hw, OFF);
+		return -ENOMEDIUM;
+	}
+
+	bcma_host_pci_up(wlc_hw->d11core->bus);
+
+	/* reset the d11 core */
+	brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
+
+	return 0;
+}
+
+static int brcms_b_up_finish(struct brcms_hardware *wlc_hw)
+{
+	wlc_hw->up = true;
+	wlc_phy_hw_state_upd(wlc_hw->band->pi, true);
+
+	/* FULLY enable dynamic power control and d11 core interrupt */
+	brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_DYNAMIC);
+	brcms_intrson(wlc_hw->wlc->wl);
+	return 0;
+}
+
+/*
+ * Write WME tunable parameters for retransmit/max rate
+ * from wlc struct to ucode
+ */
+static void brcms_c_wme_retries_write(struct brcms_c_info *wlc)
+{
+	int ac;
+
+	/* Need clock to do this */
+	if (!wlc->clk)
+		return;
+
+	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
+		brcms_b_write_shm(wlc->hw, M_AC_TXLMT_ADDR(ac),
+				  wlc->wme_retries[ac]);
+}
+
+/* make interface operational */
+int brcms_c_up(struct brcms_c_info *wlc)
+{
+	struct ieee80211_channel *ch;
+
+	brcms_dbg_info(wlc->hw->d11core, "wl%d\n", wlc->pub->unit);
+
+	/* HW is turned off so don't try to access it */
+	if (wlc->pub->hw_off || brcms_deviceremoved(wlc))
+		return -ENOMEDIUM;
+
+	if (!wlc->pub->hw_up) {
+		brcms_b_hw_up(wlc->hw);
+		wlc->pub->hw_up = true;
+	}
+
+	if ((wlc->pub->boardflags & BFL_FEM)
+	    && (ai_get_chip_id(wlc->hw->sih) == BCMA_CHIP_ID_BCM4313)) {
+		if (wlc->pub->boardrev >= 0x1250
+		    && (wlc->pub->boardflags & BFL_FEM_BT))
+			brcms_b_mhf(wlc->hw, MHF5, MHF5_4313_GPIOCTRL,
+				MHF5_4313_GPIOCTRL, BRCM_BAND_ALL);
+		else
+			brcms_b_mhf(wlc->hw, MHF4, MHF4_EXTPA_ENABLE,
+				    MHF4_EXTPA_ENABLE, BRCM_BAND_ALL);
+	}
+
+	/*
+	 * Need to read the hwradio status here to cover the case where the
+	 * system is loaded with the hw radio disabled. We do not want to bring
+	 * the driver up in this case. If radio is disabled, abort up, lower
+	 * power, start radio timer and return 0(for NDIS) don't call
+	 * radio_update to avoid looping brcms_c_up.
+	 *
+	 * brcms_b_up_prep() returns either 0 or -BCME_RADIOOFF only
+	 */
+	if (!wlc->pub->radio_disabled) {
+		int status = brcms_b_up_prep(wlc->hw);
+		if (status == -ENOMEDIUM) {
+			if (!mboolisset
+			    (wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE)) {
+				struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
+				mboolset(wlc->pub->radio_disabled,
+					 WL_RADIO_HW_DISABLE);
+				if (bsscfg->type == BRCMS_TYPE_STATION ||
+				    bsscfg->type == BRCMS_TYPE_ADHOC)
+					brcms_err(wlc->hw->d11core,
+						  "wl%d: up: rfdisable -> "
+						  "bsscfg_disable()\n",
+						   wlc->pub->unit);
+			}
+		}
+	}
+
+	if (wlc->pub->radio_disabled) {
+		brcms_c_radio_monitor_start(wlc);
+		return 0;
+	}
+
+	/* brcms_b_up_prep has done brcms_c_corereset(). so clk is on, set it */
+	wlc->clk = true;
+
+	brcms_c_radio_monitor_stop(wlc);
+
+	/* Set EDCF hostflags */
+	brcms_b_mhf(wlc->hw, MHF1, MHF1_EDCF, MHF1_EDCF, BRCM_BAND_ALL);
+
+	brcms_init(wlc->wl);
+	wlc->pub->up = true;
+
+	if (wlc->bandinit_pending) {
+		ch = wlc->pub->ieee_hw->conf.chandef.chan;
+		brcms_c_suspend_mac_and_wait(wlc);
+		brcms_c_set_chanspec(wlc, ch20mhz_chspec(ch->hw_value));
+		wlc->bandinit_pending = false;
+		brcms_c_enable_mac(wlc);
+	}
+
+	brcms_b_up_finish(wlc->hw);
+
+	/* Program the TX wme params with the current settings */
+	brcms_c_wme_retries_write(wlc);
+
+	/* start one second watchdog timer */
+	brcms_add_timer(wlc->wdtimer, TIMER_INTERVAL_WATCHDOG, true);
+	wlc->WDarmed = true;
+
+	/* ensure antenna config is up to date */
+	brcms_c_stf_phy_txant_upd(wlc);
+	/* ensure LDPC config is in sync */
+	brcms_c_ht_update_ldpc(wlc, wlc->stf->ldpc);
+
+	return 0;
+}
+
+static uint brcms_c_down_del_timer(struct brcms_c_info *wlc)
+{
+	uint callbacks = 0;
+
+	return callbacks;
+}
+
+static int brcms_b_bmac_down_prep(struct brcms_hardware *wlc_hw)
+{
+	bool dev_gone;
+	uint callbacks = 0;
+
+	if (!wlc_hw->up)
+		return callbacks;
+
+	dev_gone = brcms_deviceremoved(wlc_hw->wlc);
+
+	/* disable interrupts */
+	if (dev_gone)
+		wlc_hw->wlc->macintmask = 0;
+	else {
+		/* now disable interrupts */
+		brcms_intrsoff(wlc_hw->wlc->wl);
+
+		/* ensure we're running on the pll clock again */
+		brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST);
+	}
+	/* down phy at the last of this stage */
+	callbacks += wlc_phy_down(wlc_hw->band->pi);
+
+	return callbacks;
+}
+
+static int brcms_b_down_finish(struct brcms_hardware *wlc_hw)
+{
+	uint callbacks = 0;
+	bool dev_gone;
+
+	if (!wlc_hw->up)
+		return callbacks;
+
+	wlc_hw->up = false;
+	wlc_phy_hw_state_upd(wlc_hw->band->pi, false);
+
+	dev_gone = brcms_deviceremoved(wlc_hw->wlc);
+
+	if (dev_gone) {
+		wlc_hw->sbclk = false;
+		wlc_hw->clk = false;
+		wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
+
+		/* reclaim any posted packets */
+		brcms_c_flushqueues(wlc_hw->wlc);
+	} else {
+
+		/* Reset and disable the core */
+		if (bcma_core_is_enabled(wlc_hw->d11core)) {
+			if (bcma_read32(wlc_hw->d11core,
+					D11REGOFFS(maccontrol)) & MCTL_EN_MAC)
+				brcms_c_suspend_mac_and_wait(wlc_hw->wlc);
+			callbacks += brcms_reset(wlc_hw->wlc->wl);
+			brcms_c_coredisable(wlc_hw);
+		}
+
+		/* turn off primary xtal and pll */
+		if (!wlc_hw->noreset) {
+			bcma_host_pci_down(wlc_hw->d11core->bus);
+			brcms_b_xtal(wlc_hw, OFF);
+		}
+	}
+
+	return callbacks;
+}
+
+/*
+ * Mark the interface nonoperational, stop the software mechanisms,
+ * disable the hardware, free any transient buffer state.
+ * Return a count of the number of driver callbacks still pending.
+ */
+uint brcms_c_down(struct brcms_c_info *wlc)
+{
+
+	uint callbacks = 0;
+	int i;
+	bool dev_gone = false;
+
+	brcms_dbg_info(wlc->hw->d11core, "wl%d\n", wlc->pub->unit);
+
+	/* check if we are already in the going down path */
+	if (wlc->going_down) {
+		brcms_err(wlc->hw->d11core,
+			  "wl%d: %s: Driver going down so return\n",
+			  wlc->pub->unit, __func__);
+		return 0;
+	}
+	if (!wlc->pub->up)
+		return callbacks;
+
+	wlc->going_down = true;
+
+	callbacks += brcms_b_bmac_down_prep(wlc->hw);
+
+	dev_gone = brcms_deviceremoved(wlc);
+
+	/* Call any registered down handlers */
+	for (i = 0; i < BRCMS_MAXMODULES; i++) {
+		if (wlc->modulecb[i].down_fn)
+			callbacks +=
+			    wlc->modulecb[i].down_fn(wlc->modulecb[i].hdl);
+	}
+
+	/* cancel the watchdog timer */
+	if (wlc->WDarmed) {
+		if (!brcms_del_timer(wlc->wdtimer))
+			callbacks++;
+		wlc->WDarmed = false;
+	}
+	/* cancel all other timers */
+	callbacks += brcms_c_down_del_timer(wlc);
+
+	wlc->pub->up = false;
+
+	wlc_phy_mute_upd(wlc->band->pi, false, PHY_MUTE_ALL);
+
+	callbacks += brcms_b_down_finish(wlc->hw);
+
+	/* brcms_b_down_finish has done brcms_c_coredisable(). so clk is off */
+	wlc->clk = false;
+
+	wlc->going_down = false;
+	return callbacks;
+}
+
+/* Set the current gmode configuration */
+int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config)
+{
+	int ret = 0;
+	uint i;
+	struct brcms_c_rateset rs;
+	/* Default to 54g Auto */
+	/* Advertise and use shortslot (-1/0/1 Auto/Off/On) */
+	s8 shortslot = BRCMS_SHORTSLOT_AUTO;
+	bool shortslot_restrict = false; /* Restrict association to stations
+					  * that support shortslot
+					  */
+	bool ofdm_basic = false;	/* Make 6, 12, and 24 basic rates */
+	/* Advertise and use short preambles (-1/0/1 Auto/Off/On) */
+	int preamble = BRCMS_PLCP_LONG;
+	bool preamble_restrict = false;	/* Restrict association to stations
+					 * that support short preambles
+					 */
+	struct brcms_band *band;
+
+	/* if N-support is enabled, allow Gmode set as long as requested
+	 * Gmode is not GMODE_LEGACY_B
+	 */
+	if ((wlc->pub->_n_enab & SUPPORT_11N) && gmode == GMODE_LEGACY_B)
+		return -ENOTSUPP;
+
+	/* verify that we are dealing with 2G band and grab the band pointer */
+	if (wlc->band->bandtype == BRCM_BAND_2G)
+		band = wlc->band;
+	else if ((wlc->pub->_nbands > 1) &&
+		 (wlc->bandstate[OTHERBANDUNIT(wlc)]->bandtype == BRCM_BAND_2G))
+		band = wlc->bandstate[OTHERBANDUNIT(wlc)];
+	else
+		return -EINVAL;
+
+	/* update configuration value */
+	if (config)
+		brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER, gmode);
+
+	/* Clear rateset override */
+	memset(&rs, 0, sizeof(rs));
+
+	switch (gmode) {
+	case GMODE_LEGACY_B:
+		shortslot = BRCMS_SHORTSLOT_OFF;
+		brcms_c_rateset_copy(&gphy_legacy_rates, &rs);
+
+		break;
+
+	case GMODE_LRS:
+		break;
+
+	case GMODE_AUTO:
+		/* Accept defaults */
+		break;
+
+	case GMODE_ONLY:
+		ofdm_basic = true;
+		preamble = BRCMS_PLCP_SHORT;
+		preamble_restrict = true;
+		break;
+
+	case GMODE_PERFORMANCE:
+		shortslot = BRCMS_SHORTSLOT_ON;
+		shortslot_restrict = true;
+		ofdm_basic = true;
+		preamble = BRCMS_PLCP_SHORT;
+		preamble_restrict = true;
+		break;
+
+	default:
+		/* Error */
+		brcms_err(wlc->hw->d11core, "wl%d: %s: invalid gmode %d\n",
+			  wlc->pub->unit, __func__, gmode);
+		return -ENOTSUPP;
+	}
+
+	band->gmode = gmode;
+
+	wlc->shortslot_override = shortslot;
+
+	/* Use the default 11g rateset */
+	if (!rs.count)
+		brcms_c_rateset_copy(&cck_ofdm_rates, &rs);
+
+	if (ofdm_basic) {
+		for (i = 0; i < rs.count; i++) {
+			if (rs.rates[i] == BRCM_RATE_6M
+			    || rs.rates[i] == BRCM_RATE_12M
+			    || rs.rates[i] == BRCM_RATE_24M)
+				rs.rates[i] |= BRCMS_RATE_FLAG;
+		}
+	}
+
+	/* Set default bss rateset */
+	wlc->default_bss->rateset.count = rs.count;
+	memcpy(wlc->default_bss->rateset.rates, rs.rates,
+	       sizeof(wlc->default_bss->rateset.rates));
+
+	return ret;
+}
+
+int brcms_c_set_nmode(struct brcms_c_info *wlc)
+{
+	uint i;
+	s32 nmode = AUTO;
+
+	if (wlc->stf->txstreams == WL_11N_3x3)
+		nmode = WL_11N_3x3;
+	else
+		nmode = WL_11N_2x2;
+
+	/* force GMODE_AUTO if NMODE is ON */
+	brcms_c_set_gmode(wlc, GMODE_AUTO, true);
+	if (nmode == WL_11N_3x3)
+		wlc->pub->_n_enab = SUPPORT_HT;
+	else
+		wlc->pub->_n_enab = SUPPORT_11N;
+	wlc->default_bss->flags |= BRCMS_BSS_HT;
+	/* add the mcs rates to the default and hw ratesets */
+	brcms_c_rateset_mcs_build(&wlc->default_bss->rateset,
+			      wlc->stf->txstreams);
+	for (i = 0; i < wlc->pub->_nbands; i++)
+		memcpy(wlc->bandstate[i]->hw_rateset.mcs,
+		       wlc->default_bss->rateset.mcs, MCSSET_LEN);
+
+	return 0;
+}
+
+static int
+brcms_c_set_internal_rateset(struct brcms_c_info *wlc,
+			     struct brcms_c_rateset *rs_arg)
+{
+	struct brcms_c_rateset rs, new;
+	uint bandunit;
+
+	memcpy(&rs, rs_arg, sizeof(struct brcms_c_rateset));
+
+	/* check for bad count value */
+	if ((rs.count == 0) || (rs.count > BRCMS_NUMRATES))
+		return -EINVAL;
+
+	/* try the current band */
+	bandunit = wlc->band->bandunit;
+	memcpy(&new, &rs, sizeof(struct brcms_c_rateset));
+	if (brcms_c_rate_hwrs_filter_sort_validate
+	    (&new, &wlc->bandstate[bandunit]->hw_rateset, true,
+	     wlc->stf->txstreams))
+		goto good;
+
+	/* try the other band */
+	if (brcms_is_mband_unlocked(wlc)) {
+		bandunit = OTHERBANDUNIT(wlc);
+		memcpy(&new, &rs, sizeof(struct brcms_c_rateset));
+		if (brcms_c_rate_hwrs_filter_sort_validate(&new,
+						       &wlc->
+						       bandstate[bandunit]->
+						       hw_rateset, true,
+						       wlc->stf->txstreams))
+			goto good;
+	}
+
+	return -EBADE;
+
+ good:
+	/* apply new rateset */
+	memcpy(&wlc->default_bss->rateset, &new,
+	       sizeof(struct brcms_c_rateset));
+	memcpy(&wlc->bandstate[bandunit]->defrateset, &new,
+	       sizeof(struct brcms_c_rateset));
+	return 0;
+}
+
+static void brcms_c_ofdm_rateset_war(struct brcms_c_info *wlc)
+{
+	u8 r;
+	bool war = false;
+
+	if (wlc->pub->associated)
+		r = wlc->bsscfg->current_bss->rateset.rates[0];
+	else
+		r = wlc->default_bss->rateset.rates[0];
+
+	wlc_phy_ofdm_rateset_war(wlc->band->pi, war);
+}
+
+int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel)
+{
+	u16 chspec = ch20mhz_chspec(channel);
+
+	if (channel < 0 || channel > MAXCHANNEL)
+		return -EINVAL;
+
+	if (!brcms_c_valid_chanspec_db(wlc->cmi, chspec))
+		return -EINVAL;
+
+
+	if (!wlc->pub->up && brcms_is_mband_unlocked(wlc)) {
+		if (wlc->band->bandunit != chspec_bandunit(chspec))
+			wlc->bandinit_pending = true;
+		else
+			wlc->bandinit_pending = false;
+	}
+
+	wlc->default_bss->chanspec = chspec;
+	/* brcms_c_BSSinit() will sanitize the rateset before
+	 * using it.. */
+	if (wlc->pub->up && (wlc_phy_chanspec_get(wlc->band->pi) != chspec)) {
+		brcms_c_set_home_chanspec(wlc, chspec);
+		brcms_c_suspend_mac_and_wait(wlc);
+		brcms_c_set_chanspec(wlc, chspec);
+		brcms_c_enable_mac(wlc);
+	}
+	return 0;
+}
+
+int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl)
+{
+	int ac;
+
+	if (srl < 1 || srl > RETRY_SHORT_MAX ||
+	    lrl < 1 || lrl > RETRY_SHORT_MAX)
+		return -EINVAL;
+
+	wlc->SRL = srl;
+	wlc->LRL = lrl;
+
+	brcms_b_retrylimit_upd(wlc->hw, wlc->SRL, wlc->LRL);
+
+	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+		wlc->wme_retries[ac] =	SFIELD(wlc->wme_retries[ac],
+					       EDCF_SHORT,  wlc->SRL);
+		wlc->wme_retries[ac] =	SFIELD(wlc->wme_retries[ac],
+					       EDCF_LONG, wlc->LRL);
+	}
+	brcms_c_wme_retries_write(wlc);
+
+	return 0;
+}
+
+void brcms_c_get_current_rateset(struct brcms_c_info *wlc,
+				 struct brcm_rateset *currs)
+{
+	struct brcms_c_rateset *rs;
+
+	if (wlc->pub->associated)
+		rs = &wlc->bsscfg->current_bss->rateset;
+	else
+		rs = &wlc->default_bss->rateset;
+
+	/* Copy only legacy rateset section */
+	currs->count = rs->count;
+	memcpy(&currs->rates, &rs->rates, rs->count);
+}
+
+int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs)
+{
+	struct brcms_c_rateset internal_rs;
+	int bcmerror;
+
+	if (rs->count > BRCMS_NUMRATES)
+		return -ENOBUFS;
+
+	memset(&internal_rs, 0, sizeof(internal_rs));
+
+	/* Copy only legacy rateset section */
+	internal_rs.count = rs->count;
+	memcpy(&internal_rs.rates, &rs->rates, internal_rs.count);
+
+	/* merge rateset coming in with the current mcsset */
+	if (wlc->pub->_n_enab & SUPPORT_11N) {
+		struct brcms_bss_info *mcsset_bss;
+		if (wlc->pub->associated)
+			mcsset_bss = wlc->bsscfg->current_bss;
+		else
+			mcsset_bss = wlc->default_bss;
+		memcpy(internal_rs.mcs, &mcsset_bss->rateset.mcs[0],
+		       MCSSET_LEN);
+	}
+
+	bcmerror = brcms_c_set_internal_rateset(wlc, &internal_rs);
+	if (!bcmerror)
+		brcms_c_ofdm_rateset_war(wlc);
+
+	return bcmerror;
+}
+
+static void brcms_c_time_lock(struct brcms_c_info *wlc)
+{
+	bcma_set32(wlc->hw->d11core, D11REGOFFS(maccontrol), MCTL_TBTTHOLD);
+	/* Commit the write */
+	bcma_read32(wlc->hw->d11core, D11REGOFFS(maccontrol));
+}
+
+static void brcms_c_time_unlock(struct brcms_c_info *wlc)
+{
+	bcma_mask32(wlc->hw->d11core, D11REGOFFS(maccontrol), ~MCTL_TBTTHOLD);
+	/* Commit the write */
+	bcma_read32(wlc->hw->d11core, D11REGOFFS(maccontrol));
+}
+
+int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period)
+{
+	u32 bcnint_us;
+
+	if (period == 0)
+		return -EINVAL;
+
+	wlc->default_bss->beacon_period = period;
+
+	bcnint_us = period << 10;
+	brcms_c_time_lock(wlc);
+	bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_cfprep),
+		     (bcnint_us << CFPREP_CBI_SHIFT));
+	bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_cfpstart), bcnint_us);
+	brcms_c_time_unlock(wlc);
+
+	return 0;
+}
+
+u16 brcms_c_get_phy_type(struct brcms_c_info *wlc, int phyidx)
+{
+	return wlc->band->phytype;
+}
+
+void brcms_c_set_shortslot_override(struct brcms_c_info *wlc, s8 sslot_override)
+{
+	wlc->shortslot_override = sslot_override;
+
+	/*
+	 * shortslot is an 11g feature, so no more work if we are
+	 * currently on the 5G band
+	 */
+	if (wlc->band->bandtype == BRCM_BAND_5G)
+		return;
+
+	if (wlc->pub->up && wlc->pub->associated) {
+		/* let watchdog or beacon processing update shortslot */
+	} else if (wlc->pub->up) {
+		/* unassociated shortslot is off */
+		brcms_c_switch_shortslot(wlc, false);
+	} else {
+		/* driver is down, so just update the brcms_c_info
+		 * value */
+		if (wlc->shortslot_override == BRCMS_SHORTSLOT_AUTO)
+			wlc->shortslot = false;
+		else
+			wlc->shortslot =
+			    (wlc->shortslot_override ==
+			     BRCMS_SHORTSLOT_ON);
+	}
+}
+
+/*
+ * register watchdog and down handlers.
+ */
+int brcms_c_module_register(struct brcms_pub *pub,
+			    const char *name, struct brcms_info *hdl,
+			    int (*d_fn)(void *handle))
+{
+	struct brcms_c_info *wlc = (struct brcms_c_info *) pub->wlc;
+	int i;
+
+	/* find an empty entry and just add, no duplication check! */
+	for (i = 0; i < BRCMS_MAXMODULES; i++) {
+		if (wlc->modulecb[i].name[0] == '\0') {
+			strncpy(wlc->modulecb[i].name, name,
+				sizeof(wlc->modulecb[i].name) - 1);
+			wlc->modulecb[i].hdl = hdl;
+			wlc->modulecb[i].down_fn = d_fn;
+			return 0;
+		}
+	}
+
+	return -ENOSR;
+}
+
+/* unregister module callbacks */
+int brcms_c_module_unregister(struct brcms_pub *pub, const char *name,
+			      struct brcms_info *hdl)
+{
+	struct brcms_c_info *wlc = (struct brcms_c_info *) pub->wlc;
+	int i;
+
+	if (wlc == NULL)
+		return -ENODATA;
+
+	for (i = 0; i < BRCMS_MAXMODULES; i++) {
+		if (!strcmp(wlc->modulecb[i].name, name) &&
+		    (wlc->modulecb[i].hdl == hdl)) {
+			memset(&wlc->modulecb[i], 0, sizeof(wlc->modulecb[i]));
+			return 0;
+		}
+	}
+
+	/* table not found! */
+	return -ENODATA;
+}
+
+static bool brcms_c_chipmatch_pci(struct bcma_device *core)
+{
+	struct pci_dev *pcidev = core->bus->host_pci;
+	u16 vendor = pcidev->vendor;
+	u16 device = pcidev->device;
+
+	if (vendor != PCI_VENDOR_ID_BROADCOM) {
+		pr_err("unknown vendor id %04x\n", vendor);
+		return false;
+	}
+
+	if (device == BCM43224_D11N_ID_VEN1 || device == BCM43224_CHIP_ID)
+		return true;
+	if ((device == BCM43224_D11N_ID) || (device == BCM43225_D11N2G_ID))
+		return true;
+	if (device == BCM4313_D11N2G_ID || device == BCM4313_CHIP_ID)
+		return true;
+	if ((device == BCM43236_D11N_ID) || (device == BCM43236_D11N2G_ID))
+		return true;
+
+	pr_err("unknown device id %04x\n", device);
+	return false;
+}
+
+static bool brcms_c_chipmatch_soc(struct bcma_device *core)
+{
+	struct bcma_chipinfo *chipinfo = &core->bus->chipinfo;
+
+	if (chipinfo->id == BCMA_CHIP_ID_BCM4716)
+		return true;
+
+	pr_err("unknown chip id %04x\n", chipinfo->id);
+	return false;
+}
+
+bool brcms_c_chipmatch(struct bcma_device *core)
+{
+	switch (core->bus->hosttype) {
+	case BCMA_HOSTTYPE_PCI:
+		return brcms_c_chipmatch_pci(core);
+	case BCMA_HOSTTYPE_SOC:
+		return brcms_c_chipmatch_soc(core);
+	default:
+		pr_err("unknown host type: %i\n", core->bus->hosttype);
+		return false;
+	}
+}
+
+u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate)
+{
+	u16 table_ptr;
+	u8 phy_rate, index;
+
+	/* get the phy specific rate encoding for the PLCP SIGNAL field */
+	if (is_ofdm_rate(rate))
+		table_ptr = M_RT_DIRMAP_A;
+	else
+		table_ptr = M_RT_DIRMAP_B;
+
+	/* for a given rate, the LS-nibble of the PLCP SIGNAL field is
+	 * the index into the rate table.
+	 */
+	phy_rate = rate_info[rate] & BRCMS_RATE_MASK;
+	index = phy_rate & 0xf;
+
+	/* Find the SHM pointer to the rate table entry by looking in the
+	 * Direct-map Table
+	 */
+	return 2 * brcms_b_read_shm(wlc_hw, table_ptr + (index * 2));
+}
+
+/*
+ * bcmc_fid_generate:
+ * Generate frame ID for a BCMC packet.  The frag field is not used
+ * for MC frames so is used as part of the sequence number.
+ */
+static inline u16
+bcmc_fid_generate(struct brcms_c_info *wlc, struct brcms_bss_cfg *bsscfg,
+		  struct d11txh *txh)
+{
+	u16 frameid;
+
+	frameid = le16_to_cpu(txh->TxFrameID) & ~(TXFID_SEQ_MASK |
+						  TXFID_QUEUE_MASK);
+	frameid |=
+	    (((wlc->
+	       mc_fid_counter++) << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) |
+	    TX_BCMC_FIFO;
+
+	return frameid;
+}
+
+static uint
+brcms_c_calc_ack_time(struct brcms_c_info *wlc, u32 rspec,
+		      u8 preamble_type)
+{
+	uint dur = 0;
+
+	/*
+	 * Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that
+	 * is less than or equal to the rate of the immediately previous
+	 * frame in the FES
+	 */
+	rspec = brcms_basic_rate(wlc, rspec);
+	/* ACK frame len == 14 == 2(fc) + 2(dur) + 6(ra) + 4(fcs) */
+	dur =
+	    brcms_c_calc_frame_time(wlc, rspec, preamble_type,
+				(DOT11_ACK_LEN + FCS_LEN));
+	return dur;
+}
+
+static uint
+brcms_c_calc_cts_time(struct brcms_c_info *wlc, u32 rspec,
+		      u8 preamble_type)
+{
+	return brcms_c_calc_ack_time(wlc, rspec, preamble_type);
+}
+
+static uint
+brcms_c_calc_ba_time(struct brcms_c_info *wlc, u32 rspec,
+		     u8 preamble_type)
+{
+	/*
+	 * Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that
+	 * is less than or equal to the rate of the immediately previous
+	 * frame in the FES
+	 */
+	rspec = brcms_basic_rate(wlc, rspec);
+	/* BA len == 32 == 16(ctl hdr) + 4(ba len) + 8(bitmap) + 4(fcs) */
+	return brcms_c_calc_frame_time(wlc, rspec, preamble_type,
+				   (DOT11_BA_LEN + DOT11_BA_BITMAP_LEN +
+				    FCS_LEN));
+}
+
+/* brcms_c_compute_frame_dur()
+ *
+ * Calculate the 802.11 MAC header DUR field for MPDU
+ * DUR for a single frame = 1 SIFS + 1 ACK
+ * DUR for a frame with following frags = 3 SIFS + 2 ACK + next frag time
+ *
+ * rate			MPDU rate in unit of 500kbps
+ * next_frag_len	next MPDU length in bytes
+ * preamble_type	use short/GF or long/MM PLCP header
+ */
+static u16
+brcms_c_compute_frame_dur(struct brcms_c_info *wlc, u32 rate,
+		      u8 preamble_type, uint next_frag_len)
+{
+	u16 dur, sifs;
+
+	sifs = get_sifs(wlc->band);
+
+	dur = sifs;
+	dur += (u16) brcms_c_calc_ack_time(wlc, rate, preamble_type);
+
+	if (next_frag_len) {
+		/* Double the current DUR to get 2 SIFS + 2 ACKs */
+		dur *= 2;
+		/* add another SIFS and the frag time */
+		dur += sifs;
+		dur +=
+		    (u16) brcms_c_calc_frame_time(wlc, rate, preamble_type,
+						 next_frag_len);
+	}
+	return dur;
+}
+
+/* The opposite of brcms_c_calc_frame_time */
+static uint
+brcms_c_calc_frame_len(struct brcms_c_info *wlc, u32 ratespec,
+		   u8 preamble_type, uint dur)
+{
+	uint nsyms, mac_len, Ndps, kNdps;
+	uint rate = rspec2rate(ratespec);
+
+	if (is_mcs_rate(ratespec)) {
+		uint mcs = ratespec & RSPEC_RATE_MASK;
+		int tot_streams = mcs_2_txstreams(mcs) + rspec_stc(ratespec);
+		dur -= PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT);
+		/* payload calculation matches that of regular ofdm */
+		if (wlc->band->bandtype == BRCM_BAND_2G)
+			dur -= DOT11_OFDM_SIGNAL_EXTENSION;
+		/* kNdbps = kbps * 4 */
+		kNdps =	mcs_2_rate(mcs, rspec_is40mhz(ratespec),
+				   rspec_issgi(ratespec)) * 4;
+		nsyms = dur / APHY_SYMBOL_TIME;
+		mac_len =
+		    ((nsyms * kNdps) -
+		     ((APHY_SERVICE_NBITS + APHY_TAIL_NBITS) * 1000)) / 8000;
+	} else if (is_ofdm_rate(ratespec)) {
+		dur -= APHY_PREAMBLE_TIME;
+		dur -= APHY_SIGNAL_TIME;
+		/* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */
+		Ndps = rate * 2;
+		nsyms = dur / APHY_SYMBOL_TIME;
+		mac_len =
+		    ((nsyms * Ndps) -
+		     (APHY_SERVICE_NBITS + APHY_TAIL_NBITS)) / 8;
+	} else {
+		if (preamble_type & BRCMS_SHORT_PREAMBLE)
+			dur -= BPHY_PLCP_SHORT_TIME;
+		else
+			dur -= BPHY_PLCP_TIME;
+		mac_len = dur * rate;
+		/* divide out factor of 2 in rate (1/2 mbps) */
+		mac_len = mac_len / 8 / 2;
+	}
+	return mac_len;
+}
+
+/*
+ * Return true if the specified rate is supported by the specified band.
+ * BRCM_BAND_AUTO indicates the current band.
+ */
+static bool brcms_c_valid_rate(struct brcms_c_info *wlc, u32 rspec, int band,
+		    bool verbose)
+{
+	struct brcms_c_rateset *hw_rateset;
+	uint i;
+
+	if ((band == BRCM_BAND_AUTO) || (band == wlc->band->bandtype))
+		hw_rateset = &wlc->band->hw_rateset;
+	else if (wlc->pub->_nbands > 1)
+		hw_rateset = &wlc->bandstate[OTHERBANDUNIT(wlc)]->hw_rateset;
+	else
+		/* other band specified and we are a single band device */
+		return false;
+
+	/* check if this is a mimo rate */
+	if (is_mcs_rate(rspec)) {
+		if ((rspec & RSPEC_RATE_MASK) >= MCS_TABLE_SIZE)
+			goto error;
+
+		return isset(hw_rateset->mcs, (rspec & RSPEC_RATE_MASK));
+	}
+
+	for (i = 0; i < hw_rateset->count; i++)
+		if (hw_rateset->rates[i] == rspec2rate(rspec))
+			return true;
+ error:
+	if (verbose)
+		brcms_err(wlc->hw->d11core, "wl%d: valid_rate: rate spec 0x%x "
+			  "not in hw_rateset\n", wlc->pub->unit, rspec);
+
+	return false;
+}
+
+static u32
+mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band,
+		       u32 int_val)
+{
+	struct bcma_device *core = wlc->hw->d11core;
+	u8 stf = (int_val & NRATE_STF_MASK) >> NRATE_STF_SHIFT;
+	u8 rate = int_val & NRATE_RATE_MASK;
+	u32 rspec;
+	bool ismcs = ((int_val & NRATE_MCS_INUSE) == NRATE_MCS_INUSE);
+	bool issgi = ((int_val & NRATE_SGI_MASK) >> NRATE_SGI_SHIFT);
+	bool override_mcs_only = ((int_val & NRATE_OVERRIDE_MCS_ONLY)
+				  == NRATE_OVERRIDE_MCS_ONLY);
+	int bcmerror = 0;
+
+	if (!ismcs)
+		return (u32) rate;
+
+	/* validate the combination of rate/mcs/stf is allowed */
+	if ((wlc->pub->_n_enab & SUPPORT_11N) && ismcs) {
+		/* mcs only allowed when nmode */
+		if (stf > PHY_TXC1_MODE_SDM) {
+			brcms_err(core, "wl%d: %s: Invalid stf\n",
+				  wlc->pub->unit, __func__);
+			bcmerror = -EINVAL;
+			goto done;
+		}
+
+		/* mcs 32 is a special case, DUP mode 40 only */
+		if (rate == 32) {
+			if (!CHSPEC_IS40(wlc->home_chanspec) ||
+			    ((stf != PHY_TXC1_MODE_SISO)
+			     && (stf != PHY_TXC1_MODE_CDD))) {
+				brcms_err(core, "wl%d: %s: Invalid mcs 32\n",
+					  wlc->pub->unit, __func__);
+				bcmerror = -EINVAL;
+				goto done;
+			}
+			/* mcs > 7 must use stf SDM */
+		} else if (rate > HIGHEST_SINGLE_STREAM_MCS) {
+			/* mcs > 7 must use stf SDM */
+			if (stf != PHY_TXC1_MODE_SDM) {
+				brcms_dbg_mac80211(core, "wl%d: enabling "
+						   "SDM mode for mcs %d\n",
+						   wlc->pub->unit, rate);
+				stf = PHY_TXC1_MODE_SDM;
+			}
+		} else {
+			/*
+			 * MCS 0-7 may use SISO, CDD, and for
+			 * phy_rev >= 3 STBC
+			 */
+			if ((stf > PHY_TXC1_MODE_STBC) ||
+			    (!BRCMS_STBC_CAP_PHY(wlc)
+			     && (stf == PHY_TXC1_MODE_STBC))) {
+				brcms_err(core, "wl%d: %s: Invalid STBC\n",
+					  wlc->pub->unit, __func__);
+				bcmerror = -EINVAL;
+				goto done;
+			}
+		}
+	} else if (is_ofdm_rate(rate)) {
+		if ((stf != PHY_TXC1_MODE_CDD) && (stf != PHY_TXC1_MODE_SISO)) {
+			brcms_err(core, "wl%d: %s: Invalid OFDM\n",
+				  wlc->pub->unit, __func__);
+			bcmerror = -EINVAL;
+			goto done;
+		}
+	} else if (is_cck_rate(rate)) {
+		if ((cur_band->bandtype != BRCM_BAND_2G)
+		    || (stf != PHY_TXC1_MODE_SISO)) {
+			brcms_err(core, "wl%d: %s: Invalid CCK\n",
+				  wlc->pub->unit, __func__);
+			bcmerror = -EINVAL;
+			goto done;
+		}
+	} else {
+		brcms_err(core, "wl%d: %s: Unknown rate type\n",
+			  wlc->pub->unit, __func__);
+		bcmerror = -EINVAL;
+		goto done;
+	}
+	/* make sure multiple antennae are available for non-siso rates */
+	if ((stf != PHY_TXC1_MODE_SISO) && (wlc->stf->txstreams == 1)) {
+		brcms_err(core, "wl%d: %s: SISO antenna but !SISO "
+			  "request\n", wlc->pub->unit, __func__);
+		bcmerror = -EINVAL;
+		goto done;
+	}
+
+	rspec = rate;
+	if (ismcs) {
+		rspec |= RSPEC_MIMORATE;
+		/* For STBC populate the STC field of the ratespec */
+		if (stf == PHY_TXC1_MODE_STBC) {
+			u8 stc;
+			stc = 1;	/* Nss for single stream is always 1 */
+			rspec |= (stc << RSPEC_STC_SHIFT);
+		}
+	}
+
+	rspec |= (stf << RSPEC_STF_SHIFT);
+
+	if (override_mcs_only)
+		rspec |= RSPEC_OVERRIDE_MCS_ONLY;
+
+	if (issgi)
+		rspec |= RSPEC_SHORT_GI;
+
+	if ((rate != 0)
+	    && !brcms_c_valid_rate(wlc, rspec, cur_band->bandtype, true))
+		return rate;
+
+	return rspec;
+done:
+	return rate;
+}
+
+/*
+ * Compute PLCP, but only requires actual rate and length of pkt.
+ * Rate is given in the driver standard multiple of 500 kbps.
+ * le is set for 11 Mbps rate if necessary.
+ * Broken out for PRQ.
+ */
+
+static void brcms_c_cck_plcp_set(struct brcms_c_info *wlc, int rate_500,
+			     uint length, u8 *plcp)
+{
+	u16 usec = 0;
+	u8 le = 0;
+
+	switch (rate_500) {
+	case BRCM_RATE_1M:
+		usec = length << 3;
+		break;
+	case BRCM_RATE_2M:
+		usec = length << 2;
+		break;
+	case BRCM_RATE_5M5:
+		usec = (length << 4) / 11;
+		if ((length << 4) - (usec * 11) > 0)
+			usec++;
+		break;
+	case BRCM_RATE_11M:
+		usec = (length << 3) / 11;
+		if ((length << 3) - (usec * 11) > 0) {
+			usec++;
+			if ((usec * 11) - (length << 3) >= 8)
+				le = D11B_PLCP_SIGNAL_LE;
+		}
+		break;
+
+	default:
+		brcms_err(wlc->hw->d11core,
+			  "brcms_c_cck_plcp_set: unsupported rate %d\n",
+			  rate_500);
+		rate_500 = BRCM_RATE_1M;
+		usec = length << 3;
+		break;
+	}
+	/* PLCP signal byte */
+	plcp[0] = rate_500 * 5;	/* r (500kbps) * 5 == r (100kbps) */
+	/* PLCP service byte */
+	plcp[1] = (u8) (le | D11B_PLCP_SIGNAL_LOCKED);
+	/* PLCP length u16, little endian */
+	plcp[2] = usec & 0xff;
+	plcp[3] = (usec >> 8) & 0xff;
+	/* PLCP CRC16 */
+	plcp[4] = 0;
+	plcp[5] = 0;
+}
+
+/* Rate: 802.11 rate code, length: PSDU length in octets */
+static void brcms_c_compute_mimo_plcp(u32 rspec, uint length, u8 *plcp)
+{
+	u8 mcs = (u8) (rspec & RSPEC_RATE_MASK);
+	plcp[0] = mcs;
+	if (rspec_is40mhz(rspec) || (mcs == 32))
+		plcp[0] |= MIMO_PLCP_40MHZ;
+	BRCMS_SET_MIMO_PLCP_LEN(plcp, length);
+	plcp[3] = rspec_mimoplcp3(rspec); /* rspec already holds this byte */
+	plcp[3] |= 0x7; /* set smoothing, not sounding ppdu & reserved */
+	plcp[4] = 0; /* number of extension spatial streams bit 0 & 1 */
+	plcp[5] = 0;
+}
+
+/* Rate: 802.11 rate code, length: PSDU length in octets */
+static void
+brcms_c_compute_ofdm_plcp(u32 rspec, u32 length, u8 *plcp)
+{
+	u8 rate_signal;
+	u32 tmp = 0;
+	int rate = rspec2rate(rspec);
+
+	/*
+	 * encode rate per 802.11a-1999 sec 17.3.4.1, with lsb
+	 * transmitted first
+	 */
+	rate_signal = rate_info[rate] & BRCMS_RATE_MASK;
+	memset(plcp, 0, D11_PHY_HDR_LEN);
+	D11A_PHY_HDR_SRATE((struct ofdm_phy_hdr *) plcp, rate_signal);
+
+	tmp = (length & 0xfff) << 5;
+	plcp[2] |= (tmp >> 16) & 0xff;
+	plcp[1] |= (tmp >> 8) & 0xff;
+	plcp[0] |= tmp & 0xff;
+}
+
+/* Rate: 802.11 rate code, length: PSDU length in octets */
+static void brcms_c_compute_cck_plcp(struct brcms_c_info *wlc, u32 rspec,
+				 uint length, u8 *plcp)
+{
+	int rate = rspec2rate(rspec);
+
+	brcms_c_cck_plcp_set(wlc, rate, length, plcp);
+}
+
+static void
+brcms_c_compute_plcp(struct brcms_c_info *wlc, u32 rspec,
+		     uint length, u8 *plcp)
+{
+	if (is_mcs_rate(rspec))
+		brcms_c_compute_mimo_plcp(rspec, length, plcp);
+	else if (is_ofdm_rate(rspec))
+		brcms_c_compute_ofdm_plcp(rspec, length, plcp);
+	else
+		brcms_c_compute_cck_plcp(wlc, rspec, length, plcp);
+}
+
+/* brcms_c_compute_rtscts_dur()
+ *
+ * Calculate the 802.11 MAC header DUR field for an RTS or CTS frame
+ * DUR for normal RTS/CTS w/ frame = 3 SIFS + 1 CTS + next frame time + 1 ACK
+ * DUR for CTS-TO-SELF w/ frame    = 2 SIFS         + next frame time + 1 ACK
+ *
+ * cts			cts-to-self or rts/cts
+ * rts_rate		rts or cts rate in unit of 500kbps
+ * rate			next MPDU rate in unit of 500kbps
+ * frame_len		next MPDU frame length in bytes
+ */
+u16
+brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only,
+			   u32 rts_rate,
+			   u32 frame_rate, u8 rts_preamble_type,
+			   u8 frame_preamble_type, uint frame_len, bool ba)
+{
+	u16 dur, sifs;
+
+	sifs = get_sifs(wlc->band);
+
+	if (!cts_only) {
+		/* RTS/CTS */
+		dur = 3 * sifs;
+		dur +=
+		    (u16) brcms_c_calc_cts_time(wlc, rts_rate,
+					       rts_preamble_type);
+	} else {
+		/* CTS-TO-SELF */
+		dur = 2 * sifs;
+	}
+
+	dur +=
+	    (u16) brcms_c_calc_frame_time(wlc, frame_rate, frame_preamble_type,
+					 frame_len);
+	if (ba)
+		dur +=
+		    (u16) brcms_c_calc_ba_time(wlc, frame_rate,
+					      BRCMS_SHORT_PREAMBLE);
+	else
+		dur +=
+		    (u16) brcms_c_calc_ack_time(wlc, frame_rate,
+					       frame_preamble_type);
+	return dur;
+}
+
+static u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, u32 rspec)
+{
+	u16 phyctl1 = 0;
+	u16 bw;
+
+	if (BRCMS_ISLCNPHY(wlc->band)) {
+		bw = PHY_TXC1_BW_20MHZ;
+	} else {
+		bw = rspec_get_bw(rspec);
+		/* 10Mhz is not supported yet */
+		if (bw < PHY_TXC1_BW_20MHZ) {
+			brcms_err(wlc->hw->d11core, "phytxctl1_calc: bw %d is "
+				  "not supported yet, set to 20L\n", bw);
+			bw = PHY_TXC1_BW_20MHZ;
+		}
+	}
+
+	if (is_mcs_rate(rspec)) {
+		uint mcs = rspec & RSPEC_RATE_MASK;
+
+		/* bw, stf, coding-type is part of rspec_phytxbyte2 returns */
+		phyctl1 = rspec_phytxbyte2(rspec);
+		/* set the upper byte of phyctl1 */
+		phyctl1 |= (mcs_table[mcs].tx_phy_ctl3 << 8);
+	} else if (is_cck_rate(rspec) && !BRCMS_ISLCNPHY(wlc->band)
+		   && !BRCMS_ISSSLPNPHY(wlc->band)) {
+		/*
+		 * In CCK mode LPPHY overloads OFDM Modulation bits with CCK
+		 * Data Rate. Eventually MIMOPHY would also be converted to
+		 * this format
+		 */
+		/* 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps */
+		phyctl1 = (bw | (rspec_stf(rspec) << PHY_TXC1_MODE_SHIFT));
+	} else {		/* legacy OFDM/CCK */
+		s16 phycfg;
+		/* get the phyctl byte from rate phycfg table */
+		phycfg = brcms_c_rate_legacy_phyctl(rspec2rate(rspec));
+		if (phycfg == -1) {
+			brcms_err(wlc->hw->d11core, "phytxctl1_calc: wrong "
+				  "legacy OFDM/CCK rate\n");
+			phycfg = 0;
+		}
+		/* set the upper byte of phyctl1 */
+		phyctl1 =
+		    (bw | (phycfg << 8) |
+		     (rspec_stf(rspec) << PHY_TXC1_MODE_SHIFT));
+	}
+	return phyctl1;
+}
+
+/*
+ * Add struct d11txh, struct cck_phy_hdr.
+ *
+ * 'p' data must start with 802.11 MAC header
+ * 'p' must allow enough bytes of local headers to be "pushed" onto the packet
+ *
+ * headroom == D11_PHY_HDR_LEN + D11_TXH_LEN (D11_TXH_LEN is now 104 bytes)
+ *
+ */
+static u16
+brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
+		     struct sk_buff *p, struct scb *scb, uint frag,
+		     uint nfrags, uint queue, uint next_frag_len)
+{
+	struct ieee80211_hdr *h;
+	struct d11txh *txh;
+	u8 *plcp, plcp_fallback[D11_PHY_HDR_LEN];
+	int len, phylen, rts_phylen;
+	u16 mch, phyctl, xfts, mainrates;
+	u16 seq = 0, mcl = 0, status = 0, frameid = 0;
+	u32 rspec[2] = { BRCM_RATE_1M, BRCM_RATE_1M };
+	u32 rts_rspec[2] = { BRCM_RATE_1M, BRCM_RATE_1M };
+	bool use_rts = false;
+	bool use_cts = false;
+	bool use_rifs = false;
+	bool short_preamble[2] = { false, false };
+	u8 preamble_type[2] = { BRCMS_LONG_PREAMBLE, BRCMS_LONG_PREAMBLE };
+	u8 rts_preamble_type[2] = { BRCMS_LONG_PREAMBLE, BRCMS_LONG_PREAMBLE };
+	u8 *rts_plcp, rts_plcp_fallback[D11_PHY_HDR_LEN];
+	struct ieee80211_rts *rts = NULL;
+	bool qos;
+	uint ac;
+	bool hwtkmic = false;
+	u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
+#define ANTCFG_NONE 0xFF
+	u8 antcfg = ANTCFG_NONE;
+	u8 fbantcfg = ANTCFG_NONE;
+	uint phyctl1_stf = 0;
+	u16 durid = 0;
+	struct ieee80211_tx_rate *txrate[2];
+	int k;
+	struct ieee80211_tx_info *tx_info;
+	bool is_mcs;
+	u16 mimo_txbw;
+	u8 mimo_preamble_type;
+
+	/* locate 802.11 MAC header */
+	h = (struct ieee80211_hdr *)(p->data);
+	qos = ieee80211_is_data_qos(h->frame_control);
+
+	/* compute length of frame in bytes for use in PLCP computations */
+	len = p->len;
+	phylen = len + FCS_LEN;
+
+	/* Get tx_info */
+	tx_info = IEEE80211_SKB_CB(p);
+
+	/* add PLCP */
+	plcp = skb_push(p, D11_PHY_HDR_LEN);
+
+	/* add Broadcom tx descriptor header */
+	txh = (struct d11txh *) skb_push(p, D11_TXH_LEN);
+	memset(txh, 0, D11_TXH_LEN);
+
+	/* setup frameid */
+	if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
+		/* non-AP STA should never use BCMC queue */
+		if (queue == TX_BCMC_FIFO) {
+			brcms_err(wlc->hw->d11core,
+				  "wl%d: %s: ASSERT queue == TX_BCMC!\n",
+				  wlc->pub->unit, __func__);
+			frameid = bcmc_fid_generate(wlc, NULL, txh);
+		} else {
+			/* Increment the counter for first fragment */
+			if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
+				scb->seqnum[p->priority]++;
+
+			/* extract fragment number from frame first */
+			seq = le16_to_cpu(h->seq_ctrl) & FRAGNUM_MASK;
+			seq |= (scb->seqnum[p->priority] << SEQNUM_SHIFT);
+			h->seq_ctrl = cpu_to_le16(seq);
+
+			frameid = ((seq << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) |
+			    (queue & TXFID_QUEUE_MASK);
+		}
+	}
+	frameid |= queue & TXFID_QUEUE_MASK;
+
+	/* set the ignpmq bit for all pkts tx'd in PS mode and for beacons */
+	if (ieee80211_is_beacon(h->frame_control))
+		mcl |= TXC_IGNOREPMQ;
+
+	txrate[0] = tx_info->control.rates;
+	txrate[1] = txrate[0] + 1;
+
+	/*
+	 * if rate control algorithm didn't give us a fallback
+	 * rate, use the primary rate
+	 */
+	if (txrate[1]->idx < 0)
+		txrate[1] = txrate[0];
+
+	for (k = 0; k < hw->max_rates; k++) {
+		is_mcs = txrate[k]->flags & IEEE80211_TX_RC_MCS ? true : false;
+		if (!is_mcs) {
+			if ((txrate[k]->idx >= 0)
+			    && (txrate[k]->idx <
+				hw->wiphy->bands[tx_info->band]->n_bitrates)) {
+				rspec[k] =
+				    hw->wiphy->bands[tx_info->band]->
+				    bitrates[txrate[k]->idx].hw_value;
+				short_preamble[k] =
+				    txrate[k]->
+				    flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE ?
+				    true : false;
+			} else {
+				rspec[k] = BRCM_RATE_1M;
+			}
+		} else {
+			rspec[k] = mac80211_wlc_set_nrate(wlc, wlc->band,
+					NRATE_MCS_INUSE | txrate[k]->idx);
+		}
+
+		/*
+		 * Currently only support same setting for primay and
+		 * fallback rates. Unify flags for each rate into a
+		 * single value for the frame
+		 */
+		use_rts |=
+		    txrate[k]->
+		    flags & IEEE80211_TX_RC_USE_RTS_CTS ? true : false;
+		use_cts |=
+		    txrate[k]->
+		    flags & IEEE80211_TX_RC_USE_CTS_PROTECT ? true : false;
+
+
+		/*
+		 * (1) RATE:
+		 *   determine and validate primary rate
+		 *   and fallback rates
+		 */
+		if (!rspec_active(rspec[k])) {
+			rspec[k] = BRCM_RATE_1M;
+		} else {
+			if (!is_multicast_ether_addr(h->addr1)) {
+				/* set tx antenna config */
+				brcms_c_antsel_antcfg_get(wlc->asi, false,
+					false, 0, 0, &antcfg, &fbantcfg);
+			}
+		}
+	}
+
+	phyctl1_stf = wlc->stf->ss_opmode;
+
+	if (wlc->pub->_n_enab & SUPPORT_11N) {
+		for (k = 0; k < hw->max_rates; k++) {
+			/*
+			 * apply siso/cdd to single stream mcs's or ofdm
+			 * if rspec is auto selected
+			 */
+			if (((is_mcs_rate(rspec[k]) &&
+			      is_single_stream(rspec[k] & RSPEC_RATE_MASK)) ||
+			     is_ofdm_rate(rspec[k]))
+			    && ((rspec[k] & RSPEC_OVERRIDE_MCS_ONLY)
+				|| !(rspec[k] & RSPEC_OVERRIDE))) {
+				rspec[k] &= ~(RSPEC_STF_MASK | RSPEC_STC_MASK);
+
+				/* For SISO MCS use STBC if possible */
+				if (is_mcs_rate(rspec[k])
+				    && BRCMS_STF_SS_STBC_TX(wlc, scb)) {
+					u8 stc;
+
+					/* Nss for single stream is always 1 */
+					stc = 1;
+					rspec[k] |= (PHY_TXC1_MODE_STBC <<
+							RSPEC_STF_SHIFT) |
+						    (stc << RSPEC_STC_SHIFT);
+				} else
+					rspec[k] |=
+					    (phyctl1_stf << RSPEC_STF_SHIFT);
+			}
+
+			/*
+			 * Is the phy configured to use 40MHZ frames? If
+			 * so then pick the desired txbw
+			 */
+			if (brcms_chspec_bw(wlc->chanspec) == BRCMS_40_MHZ) {
+				/* default txbw is 20in40 SB */
+				mimo_ctlchbw = mimo_txbw =
+				   CHSPEC_SB_UPPER(wlc_phy_chanspec_get(
+								 wlc->band->pi))
+				   ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
+
+				if (is_mcs_rate(rspec[k])) {
+					/* mcs 32 must be 40b/w DUP */
+					if ((rspec[k] & RSPEC_RATE_MASK)
+					    == 32) {
+						mimo_txbw =
+						    PHY_TXC1_BW_40MHZ_DUP;
+						/* use override */
+					} else if (wlc->mimo_40txbw != AUTO)
+						mimo_txbw = wlc->mimo_40txbw;
+					/* else check if dst is using 40 Mhz */
+					else if (scb->flags & SCB_IS40)
+						mimo_txbw = PHY_TXC1_BW_40MHZ;
+				} else if (is_ofdm_rate(rspec[k])) {
+					if (wlc->ofdm_40txbw != AUTO)
+						mimo_txbw = wlc->ofdm_40txbw;
+				} else if (wlc->cck_40txbw != AUTO) {
+					mimo_txbw = wlc->cck_40txbw;
+				}
+			} else {
+				/*
+				 * mcs32 is 40 b/w only.
+				 * This is possible for probe packets on
+				 * a STA during SCAN
+				 */
+				if ((rspec[k] & RSPEC_RATE_MASK) == 32)
+					/* mcs 0 */
+					rspec[k] = RSPEC_MIMORATE;
+
+				mimo_txbw = PHY_TXC1_BW_20MHZ;
+			}
+
+			/* Set channel width */
+			rspec[k] &= ~RSPEC_BW_MASK;
+			if ((k == 0) || ((k > 0) && is_mcs_rate(rspec[k])))
+				rspec[k] |= (mimo_txbw << RSPEC_BW_SHIFT);
+			else
+				rspec[k] |= (mimo_ctlchbw << RSPEC_BW_SHIFT);
+
+			/* Disable short GI, not supported yet */
+			rspec[k] &= ~RSPEC_SHORT_GI;
+
+			mimo_preamble_type = BRCMS_MM_PREAMBLE;
+			if (txrate[k]->flags & IEEE80211_TX_RC_GREEN_FIELD)
+				mimo_preamble_type = BRCMS_GF_PREAMBLE;
+
+			if ((txrate[k]->flags & IEEE80211_TX_RC_MCS)
+			    && (!is_mcs_rate(rspec[k]))) {
+				brcms_warn(wlc->hw->d11core,
+					   "wl%d: %s: IEEE80211_TX_RC_MCS != is_mcs_rate(rspec)\n",
+					   wlc->pub->unit, __func__);
+			}
+
+			if (is_mcs_rate(rspec[k])) {
+				preamble_type[k] = mimo_preamble_type;
+
+				/*
+				 * if SGI is selected, then forced mm
+				 * for single stream
+				 */
+				if ((rspec[k] & RSPEC_SHORT_GI)
+				    && is_single_stream(rspec[k] &
+							RSPEC_RATE_MASK))
+					preamble_type[k] = BRCMS_MM_PREAMBLE;
+			}
+
+			/* should be better conditionalized */
+			if (!is_mcs_rate(rspec[0])
+			    && (tx_info->control.rates[0].
+				flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE))
+				preamble_type[k] = BRCMS_SHORT_PREAMBLE;
+		}
+	} else {
+		for (k = 0; k < hw->max_rates; k++) {
+			/* Set ctrlchbw as 20Mhz */
+			rspec[k] &= ~RSPEC_BW_MASK;
+			rspec[k] |= (PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT);
+
+			/* for nphy, stf of ofdm frames must follow policies */
+			if (BRCMS_ISNPHY(wlc->band) && is_ofdm_rate(rspec[k])) {
+				rspec[k] &= ~RSPEC_STF_MASK;
+				rspec[k] |= phyctl1_stf << RSPEC_STF_SHIFT;
+			}
+		}
+	}
+
+	/* Reset these for use with AMPDU's */
+	txrate[0]->count = 0;
+	txrate[1]->count = 0;
+
+	/* (2) PROTECTION, may change rspec */
+	if ((ieee80211_is_data(h->frame_control) ||
+	    ieee80211_is_mgmt(h->frame_control)) &&
+	    (phylen > wlc->RTSThresh) && !is_multicast_ether_addr(h->addr1))
+		use_rts = true;
+
+	/* (3) PLCP: determine PLCP header and MAC duration,
+	 * fill struct d11txh */
+	brcms_c_compute_plcp(wlc, rspec[0], phylen, plcp);
+	brcms_c_compute_plcp(wlc, rspec[1], phylen, plcp_fallback);
+	memcpy(&txh->FragPLCPFallback,
+	       plcp_fallback, sizeof(txh->FragPLCPFallback));
+
+	/* Length field now put in CCK FBR CRC field */
+	if (is_cck_rate(rspec[1])) {
+		txh->FragPLCPFallback[4] = phylen & 0xff;
+		txh->FragPLCPFallback[5] = (phylen & 0xff00) >> 8;
+	}
+
+	/* MIMO-RATE: need validation ?? */
+	mainrates = is_ofdm_rate(rspec[0]) ?
+			D11A_PHY_HDR_GRATE((struct ofdm_phy_hdr *) plcp) :
+			plcp[0];
+
+	/* DUR field for main rate */
+	if (!ieee80211_is_pspoll(h->frame_control) &&
+	    !is_multicast_ether_addr(h->addr1) && !use_rifs) {
+		durid =
+		    brcms_c_compute_frame_dur(wlc, rspec[0], preamble_type[0],
+					  next_frag_len);
+		h->duration_id = cpu_to_le16(durid);
+	} else if (use_rifs) {
+		/* NAV protect to end of next max packet size */
+		durid =
+		    (u16) brcms_c_calc_frame_time(wlc, rspec[0],
+						 preamble_type[0],
+						 DOT11_MAX_FRAG_LEN);
+		durid += RIFS_11N_TIME;
+		h->duration_id = cpu_to_le16(durid);
+	}
+
+	/* DUR field for fallback rate */
+	if (ieee80211_is_pspoll(h->frame_control))
+		txh->FragDurFallback = h->duration_id;
+	else if (is_multicast_ether_addr(h->addr1) || use_rifs)
+		txh->FragDurFallback = 0;
+	else {
+		durid = brcms_c_compute_frame_dur(wlc, rspec[1],
+					      preamble_type[1], next_frag_len);
+		txh->FragDurFallback = cpu_to_le16(durid);
+	}
+
+	/* (4) MAC-HDR: MacTxControlLow */
+	if (frag == 0)
+		mcl |= TXC_STARTMSDU;
+
+	if (!is_multicast_ether_addr(h->addr1))
+		mcl |= TXC_IMMEDACK;
+
+	if (wlc->band->bandtype == BRCM_BAND_5G)
+		mcl |= TXC_FREQBAND_5G;
+
+	if (CHSPEC_IS40(wlc_phy_chanspec_get(wlc->band->pi)))
+		mcl |= TXC_BW_40;
+
+	/* set AMIC bit if using hardware TKIP MIC */
+	if (hwtkmic)
+		mcl |= TXC_AMIC;
+
+	txh->MacTxControlLow = cpu_to_le16(mcl);
+
+	/* MacTxControlHigh */
+	mch = 0;
+
+	/* Set fallback rate preamble type */
+	if ((preamble_type[1] == BRCMS_SHORT_PREAMBLE) ||
+	    (preamble_type[1] == BRCMS_GF_PREAMBLE)) {
+		if (rspec2rate(rspec[1]) != BRCM_RATE_1M)
+			mch |= TXC_PREAMBLE_DATA_FB_SHORT;
+	}
+
+	/* MacFrameControl */
+	memcpy(&txh->MacFrameControl, &h->frame_control, sizeof(u16));
+	txh->TxFesTimeNormal = cpu_to_le16(0);
+
+	txh->TxFesTimeFallback = cpu_to_le16(0);
+
+	/* TxFrameRA */
+	memcpy(&txh->TxFrameRA, &h->addr1, ETH_ALEN);
+
+	/* TxFrameID */
+	txh->TxFrameID = cpu_to_le16(frameid);
+
+	/*
+	 * TxStatus, Note the case of recreating the first frag of a suppressed
+	 * frame then we may need to reset the retry cnt's via the status reg
+	 */
+	txh->TxStatus = cpu_to_le16(status);
+
+	/*
+	 * extra fields for ucode AMPDU aggregation, the new fields are added to
+	 * the END of previous structure so that it's compatible in driver.
+	 */
+	txh->MaxNMpdus = cpu_to_le16(0);
+	txh->MaxABytes_MRT = cpu_to_le16(0);
+	txh->MaxABytes_FBR = cpu_to_le16(0);
+	txh->MinMBytes = cpu_to_le16(0);
+
+	/* (5) RTS/CTS: determine RTS/CTS PLCP header and MAC duration,
+	 * furnish struct d11txh */
+	/* RTS PLCP header and RTS frame */
+	if (use_rts || use_cts) {
+		if (use_rts && use_cts)
+			use_cts = false;
+
+		for (k = 0; k < 2; k++) {
+			rts_rspec[k] = brcms_c_rspec_to_rts_rspec(wlc, rspec[k],
+							      false,
+							      mimo_ctlchbw);
+		}
+
+		if (!is_ofdm_rate(rts_rspec[0]) &&
+		    !((rspec2rate(rts_rspec[0]) == BRCM_RATE_1M) ||
+		      (wlc->PLCPHdr_override == BRCMS_PLCP_LONG))) {
+			rts_preamble_type[0] = BRCMS_SHORT_PREAMBLE;
+			mch |= TXC_PREAMBLE_RTS_MAIN_SHORT;
+		}
+
+		if (!is_ofdm_rate(rts_rspec[1]) &&
+		    !((rspec2rate(rts_rspec[1]) == BRCM_RATE_1M) ||
+		      (wlc->PLCPHdr_override == BRCMS_PLCP_LONG))) {
+			rts_preamble_type[1] = BRCMS_SHORT_PREAMBLE;
+			mch |= TXC_PREAMBLE_RTS_FB_SHORT;
+		}
+
+		/* RTS/CTS additions to MacTxControlLow */
+		if (use_cts) {
+			txh->MacTxControlLow |= cpu_to_le16(TXC_SENDCTS);
+		} else {
+			txh->MacTxControlLow |= cpu_to_le16(TXC_SENDRTS);
+			txh->MacTxControlLow |= cpu_to_le16(TXC_LONGFRAME);
+		}
+
+		/* RTS PLCP header */
+		rts_plcp = txh->RTSPhyHeader;
+		if (use_cts)
+			rts_phylen = DOT11_CTS_LEN + FCS_LEN;
+		else
+			rts_phylen = DOT11_RTS_LEN + FCS_LEN;
+
+		brcms_c_compute_plcp(wlc, rts_rspec[0], rts_phylen, rts_plcp);
+
+		/* fallback rate version of RTS PLCP header */
+		brcms_c_compute_plcp(wlc, rts_rspec[1], rts_phylen,
+				 rts_plcp_fallback);
+		memcpy(&txh->RTSPLCPFallback, rts_plcp_fallback,
+		       sizeof(txh->RTSPLCPFallback));
+
+		/* RTS frame fields... */
+		rts = (struct ieee80211_rts *)&txh->rts_frame;
+
+		durid = brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec[0],
+					       rspec[0], rts_preamble_type[0],
+					       preamble_type[0], phylen, false);
+		rts->duration = cpu_to_le16(durid);
+		/* fallback rate version of RTS DUR field */
+		durid = brcms_c_compute_rtscts_dur(wlc, use_cts,
+					       rts_rspec[1], rspec[1],
+					       rts_preamble_type[1],
+					       preamble_type[1], phylen, false);
+		txh->RTSDurFallback = cpu_to_le16(durid);
+
+		if (use_cts) {
+			rts->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
+							 IEEE80211_STYPE_CTS);
+
+			memcpy(&rts->ra, &h->addr2, ETH_ALEN);
+		} else {
+			rts->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
+							 IEEE80211_STYPE_RTS);
+
+			memcpy(&rts->ra, &h->addr1, 2 * ETH_ALEN);
+		}
+
+		/* mainrate
+		 *    low 8 bits: main frag rate/mcs,
+		 *    high 8 bits: rts/cts rate/mcs
+		 */
+		mainrates |= (is_ofdm_rate(rts_rspec[0]) ?
+				D11A_PHY_HDR_GRATE(
+					(struct ofdm_phy_hdr *) rts_plcp) :
+				rts_plcp[0]) << 8;
+	} else {
+		memset(txh->RTSPhyHeader, 0, D11_PHY_HDR_LEN);
+		memset(&txh->rts_frame, 0, sizeof(struct ieee80211_rts));
+		memset(txh->RTSPLCPFallback, 0, sizeof(txh->RTSPLCPFallback));
+		txh->RTSDurFallback = 0;
+	}
+
+#ifdef SUPPORT_40MHZ
+	/* add null delimiter count */
+	if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && is_mcs_rate(rspec))
+		txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] =
+		   brcm_c_ampdu_null_delim_cnt(wlc->ampdu, scb, rspec, phylen);
+
+#endif
+
+	/*
+	 * Now that RTS/RTS FB preamble types are updated, write
+	 * the final value
+	 */
+	txh->MacTxControlHigh = cpu_to_le16(mch);
+
+	/*
+	 * MainRates (both the rts and frag plcp rates have
+	 * been calculated now)
+	 */
+	txh->MainRates = cpu_to_le16(mainrates);
+
+	/* XtraFrameTypes */
+	xfts = frametype(rspec[1], wlc->mimoft);
+	xfts |= (frametype(rts_rspec[0], wlc->mimoft) << XFTS_RTS_FT_SHIFT);
+	xfts |= (frametype(rts_rspec[1], wlc->mimoft) << XFTS_FBRRTS_FT_SHIFT);
+	xfts |= CHSPEC_CHANNEL(wlc_phy_chanspec_get(wlc->band->pi)) <<
+							     XFTS_CHANNEL_SHIFT;
+	txh->XtraFrameTypes = cpu_to_le16(xfts);
+
+	/* PhyTxControlWord */
+	phyctl = frametype(rspec[0], wlc->mimoft);
+	if ((preamble_type[0] == BRCMS_SHORT_PREAMBLE) ||
+	    (preamble_type[0] == BRCMS_GF_PREAMBLE)) {
+		if (rspec2rate(rspec[0]) != BRCM_RATE_1M)
+			phyctl |= PHY_TXC_SHORT_HDR;
+	}
+
+	/* phytxant is properly bit shifted */
+	phyctl |= brcms_c_stf_d11hdrs_phyctl_txant(wlc, rspec[0]);
+	txh->PhyTxControlWord = cpu_to_le16(phyctl);
+
+	/* PhyTxControlWord_1 */
+	if (BRCMS_PHY_11N_CAP(wlc->band)) {
+		u16 phyctl1 = 0;
+
+		phyctl1 = brcms_c_phytxctl1_calc(wlc, rspec[0]);
+		txh->PhyTxControlWord_1 = cpu_to_le16(phyctl1);
+		phyctl1 = brcms_c_phytxctl1_calc(wlc, rspec[1]);
+		txh->PhyTxControlWord_1_Fbr = cpu_to_le16(phyctl1);
+
+		if (use_rts || use_cts) {
+			phyctl1 = brcms_c_phytxctl1_calc(wlc, rts_rspec[0]);
+			txh->PhyTxControlWord_1_Rts = cpu_to_le16(phyctl1);
+			phyctl1 = brcms_c_phytxctl1_calc(wlc, rts_rspec[1]);
+			txh->PhyTxControlWord_1_FbrRts = cpu_to_le16(phyctl1);
+		}
+
+		/*
+		 * For mcs frames, if mixedmode(overloaded with long preamble)
+		 * is going to be set, fill in non-zero MModeLen and/or
+		 * MModeFbrLen it will be unnecessary if they are separated
+		 */
+		if (is_mcs_rate(rspec[0]) &&
+		    (preamble_type[0] == BRCMS_MM_PREAMBLE)) {
+			u16 mmodelen =
+			    brcms_c_calc_lsig_len(wlc, rspec[0], phylen);
+			txh->MModeLen = cpu_to_le16(mmodelen);
+		}
+
+		if (is_mcs_rate(rspec[1]) &&
+		    (preamble_type[1] == BRCMS_MM_PREAMBLE)) {
+			u16 mmodefbrlen =
+			    brcms_c_calc_lsig_len(wlc, rspec[1], phylen);
+			txh->MModeFbrLen = cpu_to_le16(mmodefbrlen);
+		}
+	}
+
+	ac = skb_get_queue_mapping(p);
+	if ((scb->flags & SCB_WMECAP) && qos && wlc->edcf_txop[ac]) {
+		uint frag_dur, dur, dur_fallback;
+
+		/* WME: Update TXOP threshold */
+		if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU) && frag == 0) {
+			frag_dur =
+			    brcms_c_calc_frame_time(wlc, rspec[0],
+					preamble_type[0], phylen);
+
+			if (rts) {
+				/* 1 RTS or CTS-to-self frame */
+				dur =
+				    brcms_c_calc_cts_time(wlc, rts_rspec[0],
+						      rts_preamble_type[0]);
+				dur_fallback =
+				    brcms_c_calc_cts_time(wlc, rts_rspec[1],
+						      rts_preamble_type[1]);
+				/* (SIFS + CTS) + SIFS + frame + SIFS + ACK */
+				dur += le16_to_cpu(rts->duration);
+				dur_fallback +=
+					le16_to_cpu(txh->RTSDurFallback);
+			} else if (use_rifs) {
+				dur = frag_dur;
+				dur_fallback = 0;
+			} else {
+				/* frame + SIFS + ACK */
+				dur = frag_dur;
+				dur +=
+				    brcms_c_compute_frame_dur(wlc, rspec[0],
+							  preamble_type[0], 0);
+
+				dur_fallback =
+				    brcms_c_calc_frame_time(wlc, rspec[1],
+							preamble_type[1],
+							phylen);
+				dur_fallback +=
+				    brcms_c_compute_frame_dur(wlc, rspec[1],
+							  preamble_type[1], 0);
+			}
+			/* NEED to set TxFesTimeNormal (hard) */
+			txh->TxFesTimeNormal = cpu_to_le16((u16) dur);
+			/*
+			 * NEED to set fallback rate version of
+			 * TxFesTimeNormal (hard)
+			 */
+			txh->TxFesTimeFallback =
+				cpu_to_le16((u16) dur_fallback);
+
+			/*
+			 * update txop byte threshold (txop minus intraframe
+			 * overhead)
+			 */
+			if (wlc->edcf_txop[ac] >= (dur - frag_dur)) {
+				uint newfragthresh;
+
+				newfragthresh =
+				    brcms_c_calc_frame_len(wlc,
+					rspec[0], preamble_type[0],
+					(wlc->edcf_txop[ac] -
+						(dur - frag_dur)));
+				/* range bound the fragthreshold */
+				if (newfragthresh < DOT11_MIN_FRAG_LEN)
+					newfragthresh =
+					    DOT11_MIN_FRAG_LEN;
+				else if (newfragthresh >
+					 wlc->usr_fragthresh)
+					newfragthresh =
+					    wlc->usr_fragthresh;
+				/* update the fragthresh and do txc update */
+				if (wlc->fragthresh[queue] !=
+				    (u16) newfragthresh)
+					wlc->fragthresh[queue] =
+					    (u16) newfragthresh;
+			} else {
+				brcms_warn(wlc->hw->d11core,
+					   "wl%d: %s txop invalid for rate %d\n",
+					   wlc->pub->unit, fifo_names[queue],
+					   rspec2rate(rspec[0]));
+			}
+
+			if (dur > wlc->edcf_txop[ac])
+				brcms_warn(wlc->hw->d11core,
+					   "wl%d: %s: %s txop exceeded phylen %d/%d dur %d/%d\n",
+					   wlc->pub->unit, __func__,
+					   fifo_names[queue],
+					   phylen, wlc->fragthresh[queue],
+					   dur, wlc->edcf_txop[ac]);
+		}
+	}
+
+	return 0;
+}
+
+static int brcms_c_tx(struct brcms_c_info *wlc, struct sk_buff *skb)
+{
+	struct dma_pub *dma;
+	int fifo, ret = -ENOSPC;
+	struct d11txh *txh;
+	u16 frameid = INVALIDFID;
+
+	fifo = brcms_ac_to_fifo(skb_get_queue_mapping(skb));
+	dma = wlc->hw->di[fifo];
+	txh = (struct d11txh *)(skb->data);
+
+	if (dma->txavail == 0) {
+		/*
+		 * We sometimes get a frame from mac80211 after stopping
+		 * the queues. This only ever seems to be a single frame
+		 * and is seems likely to be a race. TX_HEADROOM should
+		 * ensure that we have enough space to handle these stray
+		 * packets, so warn if there isn't. If we're out of space
+		 * in the tx ring and the tx queue isn't stopped then
+		 * we've really got a bug; warn loudly if that happens.
+		 */
+		brcms_warn(wlc->hw->d11core,
+			   "Received frame for tx with no space in DMA ring\n");
+		WARN_ON(!ieee80211_queue_stopped(wlc->pub->ieee_hw,
+						 skb_get_queue_mapping(skb)));
+		return -ENOSPC;
+	}
+
+	/* When a BC/MC frame is being committed to the BCMC fifo
+	 * via DMA (NOT PIO), update ucode or BSS info as appropriate.
+	 */
+	if (fifo == TX_BCMC_FIFO)
+		frameid = le16_to_cpu(txh->TxFrameID);
+
+	/* Commit BCMC sequence number in the SHM frame ID location */
+	if (frameid != INVALIDFID) {
+		/*
+		 * To inform the ucode of the last mcast frame posted
+		 * so that it can clear moredata bit
+		 */
+		brcms_b_write_shm(wlc->hw, M_BCMC_FID, frameid);
+	}
+
+	ret = brcms_c_txfifo(wlc, fifo, skb);
+	/*
+	 * The only reason for brcms_c_txfifo to fail is because
+	 * there weren't any DMA descriptors, but we've already
+	 * checked for that. So if it does fail yell loudly.
+	 */
+	WARN_ON_ONCE(ret);
+
+	return ret;
+}
+
+bool brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu,
+			      struct ieee80211_hw *hw)
+{
+	uint fifo;
+	struct scb *scb = &wlc->pri_scb;
+
+	fifo = brcms_ac_to_fifo(skb_get_queue_mapping(sdu));
+	brcms_c_d11hdrs_mac80211(wlc, hw, sdu, scb, 0, 1, fifo, 0);
+	if (!brcms_c_tx(wlc, sdu))
+		return true;
+
+	/* packet discarded */
+	dev_kfree_skb_any(sdu);
+	return false;
+}
+
+int
+brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p)
+{
+	struct dma_pub *dma = wlc->hw->di[fifo];
+	int ret;
+	u16 queue;
+
+	ret = dma_txfast(wlc, dma, p);
+	if (ret	< 0)
+		wiphy_err(wlc->wiphy, "txfifo: fatal, toss frames !!!\n");
+
+	/*
+	 * Stop queue if DMA ring is full. Reserve some free descriptors,
+	 * as we sometimes receive a frame from mac80211 after the queues
+	 * are stopped.
+	 */
+	queue = skb_get_queue_mapping(p);
+	if (dma->txavail <= TX_HEADROOM && fifo < TX_BCMC_FIFO &&
+	    !ieee80211_queue_stopped(wlc->pub->ieee_hw, queue))
+		ieee80211_stop_queue(wlc->pub->ieee_hw, queue);
+
+	return ret;
+}
+
+u32
+brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, u32 rspec,
+			   bool use_rspec, u16 mimo_ctlchbw)
+{
+	u32 rts_rspec = 0;
+
+	if (use_rspec)
+		/* use frame rate as rts rate */
+		rts_rspec = rspec;
+	else if (wlc->band->gmode && wlc->protection->_g && !is_cck_rate(rspec))
+		/* Use 11Mbps as the g protection RTS target rate and fallback.
+		 * Use the brcms_basic_rate() lookup to find the best basic rate
+		 * under the target in case 11 Mbps is not Basic.
+		 * 6 and 9 Mbps are not usually selected by rate selection, but
+		 * even if the OFDM rate we are protecting is 6 or 9 Mbps, 11
+		 * is more robust.
+		 */
+		rts_rspec = brcms_basic_rate(wlc, BRCM_RATE_11M);
+	else
+		/* calculate RTS rate and fallback rate based on the frame rate
+		 * RTS must be sent at a basic rate since it is a
+		 * control frame, sec 9.6 of 802.11 spec
+		 */
+		rts_rspec = brcms_basic_rate(wlc, rspec);
+
+	if (BRCMS_PHY_11N_CAP(wlc->band)) {
+		/* set rts txbw to correct side band */
+		rts_rspec &= ~RSPEC_BW_MASK;
+
+		/*
+		 * if rspec/rspec_fallback is 40MHz, then send RTS on both
+		 * 20MHz channel (DUP), otherwise send RTS on control channel
+		 */
+		if (rspec_is40mhz(rspec) && !is_cck_rate(rts_rspec))
+			rts_rspec |= (PHY_TXC1_BW_40MHZ_DUP << RSPEC_BW_SHIFT);
+		else
+			rts_rspec |= (mimo_ctlchbw << RSPEC_BW_SHIFT);
+
+		/* pick siso/cdd as default for ofdm */
+		if (is_ofdm_rate(rts_rspec)) {
+			rts_rspec &= ~RSPEC_STF_MASK;
+			rts_rspec |= (wlc->stf->ss_opmode << RSPEC_STF_SHIFT);
+		}
+	}
+	return rts_rspec;
+}
+
+/* Update beacon listen interval in shared memory */
+static void brcms_c_bcn_li_upd(struct brcms_c_info *wlc)
+{
+	/* wake up every DTIM is the default */
+	if (wlc->bcn_li_dtim == 1)
+		brcms_b_write_shm(wlc->hw, M_BCN_LI, 0);
+	else
+		brcms_b_write_shm(wlc->hw, M_BCN_LI,
+			      (wlc->bcn_li_dtim << 8) | wlc->bcn_li_bcn);
+}
+
+static void
+brcms_b_read_tsf(struct brcms_hardware *wlc_hw, u32 *tsf_l_ptr,
+		  u32 *tsf_h_ptr)
+{
+	struct bcma_device *core = wlc_hw->d11core;
+
+	/* read the tsf timer low, then high to get an atomic read */
+	*tsf_l_ptr = bcma_read32(core, D11REGOFFS(tsf_timerlow));
+	*tsf_h_ptr = bcma_read32(core, D11REGOFFS(tsf_timerhigh));
+}
+
+/*
+ * recover 64bit TSF value from the 16bit TSF value in the rx header
+ * given the assumption that the TSF passed in header is within 65ms
+ * of the current tsf.
+ *
+ * 6       5       4       4       3       2       1
+ * 3.......6.......8.......0.......2.......4.......6.......8......0
+ * |<---------- tsf_h ----------->||<--- tsf_l -->||<-RxTSFTime ->|
+ *
+ * The RxTSFTime are the lowest 16 bits and provided by the ucode. The
+ * tsf_l is filled in by brcms_b_recv, which is done earlier in the
+ * receive call sequence after rx interrupt. Only the higher 16 bits
+ * are used. Finally, the tsf_h is read from the tsf register.
+ */
+static u64 brcms_c_recover_tsf64(struct brcms_c_info *wlc,
+				 struct d11rxhdr *rxh)
+{
+	u32 tsf_h, tsf_l;
+	u16 rx_tsf_0_15, rx_tsf_16_31;
+
+	brcms_b_read_tsf(wlc->hw, &tsf_l, &tsf_h);
+
+	rx_tsf_16_31 = (u16)(tsf_l >> 16);
+	rx_tsf_0_15 = rxh->RxTSFTime;
+
+	/*
+	 * a greater tsf time indicates the low 16 bits of
+	 * tsf_l wrapped, so decrement the high 16 bits.
+	 */
+	if ((u16)tsf_l < rx_tsf_0_15) {
+		rx_tsf_16_31 -= 1;
+		if (rx_tsf_16_31 == 0xffff)
+			tsf_h -= 1;
+	}
+
+	return ((u64)tsf_h << 32) | (((u32)rx_tsf_16_31 << 16) + rx_tsf_0_15);
+}
+
+static void
+prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
+		     struct sk_buff *p,
+		     struct ieee80211_rx_status *rx_status)
+{
+	int channel;
+	u32 rspec;
+	unsigned char *plcp;
+
+	/* fill in TSF and flag its presence */
+	rx_status->mactime = brcms_c_recover_tsf64(wlc, rxh);
+	rx_status->flag |= RX_FLAG_MACTIME_START;
+
+	channel = BRCMS_CHAN_CHANNEL(rxh->RxChan);
+
+	rx_status->band =
+		channel > 14 ? NL80211_BAND_5GHZ : NL80211_BAND_2GHZ;
+	rx_status->freq =
+		ieee80211_channel_to_frequency(channel, rx_status->band);
+
+	rx_status->signal = wlc_phy_rssi_compute(wlc->hw->band->pi, rxh);
+
+	/* noise */
+	/* qual */
+	rx_status->antenna =
+		(rxh->PhyRxStatus_0 & PRXS0_RXANT_UPSUBBAND) ? 1 : 0;
+
+	plcp = p->data;
+
+	rspec = brcms_c_compute_rspec(rxh, plcp);
+	if (is_mcs_rate(rspec)) {
+		rx_status->rate_idx = rspec & RSPEC_RATE_MASK;
+		rx_status->encoding = RX_ENC_HT;
+		if (rspec_is40mhz(rspec))
+			rx_status->bw = RATE_INFO_BW_40;
+	} else {
+		switch (rspec2rate(rspec)) {
+		case BRCM_RATE_1M:
+			rx_status->rate_idx = 0;
+			break;
+		case BRCM_RATE_2M:
+			rx_status->rate_idx = 1;
+			break;
+		case BRCM_RATE_5M5:
+			rx_status->rate_idx = 2;
+			break;
+		case BRCM_RATE_11M:
+			rx_status->rate_idx = 3;
+			break;
+		case BRCM_RATE_6M:
+			rx_status->rate_idx = 4;
+			break;
+		case BRCM_RATE_9M:
+			rx_status->rate_idx = 5;
+			break;
+		case BRCM_RATE_12M:
+			rx_status->rate_idx = 6;
+			break;
+		case BRCM_RATE_18M:
+			rx_status->rate_idx = 7;
+			break;
+		case BRCM_RATE_24M:
+			rx_status->rate_idx = 8;
+			break;
+		case BRCM_RATE_36M:
+			rx_status->rate_idx = 9;
+			break;
+		case BRCM_RATE_48M:
+			rx_status->rate_idx = 10;
+			break;
+		case BRCM_RATE_54M:
+			rx_status->rate_idx = 11;
+			break;
+		default:
+			brcms_err(wlc->hw->d11core,
+				  "%s: Unknown rate\n", __func__);
+		}
+
+		/*
+		 * For 5GHz, we should decrease the index as it is
+		 * a subset of the 2.4G rates. See bitrates field
+		 * of brcms_band_5GHz_nphy (in mac80211_if.c).
+		 */
+		if (rx_status->band == NL80211_BAND_5GHZ)
+			rx_status->rate_idx -= BRCMS_LEGACY_5G_RATE_OFFSET;
+
+		/* Determine short preamble and rate_idx */
+		if (is_cck_rate(rspec)) {
+			if (rxh->PhyRxStatus_0 & PRXS0_SHORTH)
+				rx_status->enc_flags |= RX_ENC_FLAG_SHORTPRE;
+		} else if (is_ofdm_rate(rspec)) {
+			rx_status->enc_flags |= RX_ENC_FLAG_SHORTPRE;
+		} else {
+			brcms_err(wlc->hw->d11core, "%s: Unknown modulation\n",
+				  __func__);
+		}
+	}
+
+	if (plcp3_issgi(plcp[3]))
+		rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
+
+	if (rxh->RxStatus1 & RXS_DECERR) {
+		rx_status->flag |= RX_FLAG_FAILED_PLCP_CRC;
+		brcms_err(wlc->hw->d11core, "%s:  RX_FLAG_FAILED_PLCP_CRC\n",
+			  __func__);
+	}
+	if (rxh->RxStatus1 & RXS_FCSERR) {
+		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+		brcms_err(wlc->hw->d11core, "%s:  RX_FLAG_FAILED_FCS_CRC\n",
+			  __func__);
+	}
+}
+
+static void
+brcms_c_recvctl(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
+		struct sk_buff *p)
+{
+	int len_mpdu;
+	struct ieee80211_rx_status rx_status;
+	struct ieee80211_hdr *hdr;
+
+	memset(&rx_status, 0, sizeof(rx_status));
+	prep_mac80211_status(wlc, rxh, p, &rx_status);
+
+	/* mac header+body length, exclude CRC and plcp header */
+	len_mpdu = p->len - D11_PHY_HDR_LEN - FCS_LEN;
+	skb_pull(p, D11_PHY_HDR_LEN);
+	__skb_trim(p, len_mpdu);
+
+	/* unmute transmit */
+	if (wlc->hw->suspended_fifos) {
+		hdr = (struct ieee80211_hdr *)p->data;
+		if (ieee80211_is_beacon(hdr->frame_control))
+			brcms_b_mute(wlc->hw, false);
+	}
+
+	memcpy(IEEE80211_SKB_RXCB(p), &rx_status, sizeof(rx_status));
+	ieee80211_rx_irqsafe(wlc->pub->ieee_hw, p);
+}
+
+/* calculate frame duration for Mixed-mode L-SIG spoofing, return
+ * number of bytes goes in the length field
+ *
+ * Formula given by HT PHY Spec v 1.13
+ *   len = 3(nsyms + nstream + 3) - 3
+ */
+u16
+brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec,
+		      uint mac_len)
+{
+	uint nsyms, len = 0, kNdps;
+
+	if (is_mcs_rate(ratespec)) {
+		uint mcs = ratespec & RSPEC_RATE_MASK;
+		int tot_streams = (mcs_2_txstreams(mcs) + 1) +
+				  rspec_stc(ratespec);
+
+		/*
+		 * the payload duration calculation matches that
+		 * of regular ofdm
+		 */
+		/* 1000Ndbps = kbps * 4 */
+		kNdps = mcs_2_rate(mcs, rspec_is40mhz(ratespec),
+				   rspec_issgi(ratespec)) * 4;
+
+		if (rspec_stc(ratespec) == 0)
+			nsyms =
+			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
+				  APHY_TAIL_NBITS) * 1000, kNdps);
+		else
+			/* STBC needs to have even number of symbols */
+			nsyms =
+			    2 *
+			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
+				  APHY_TAIL_NBITS) * 1000, 2 * kNdps);
+
+		/* (+3) account for HT-SIG(2) and HT-STF(1) */
+		nsyms += (tot_streams + 3);
+		/*
+		 * 3 bytes/symbol @ legacy 6Mbps rate
+		 * (-3) excluding service bits and tail bits
+		 */
+		len = (3 * nsyms) - 3;
+	}
+
+	return (u16) len;
+}
+
+static void
+brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len)
+{
+	const struct brcms_c_rateset *rs_dflt;
+	struct brcms_c_rateset rs;
+	u8 rate;
+	u16 entry_ptr;
+	u8 plcp[D11_PHY_HDR_LEN];
+	u16 dur, sifs;
+	uint i;
+
+	sifs = get_sifs(wlc->band);
+
+	rs_dflt = brcms_c_rateset_get_hwrs(wlc);
+
+	brcms_c_rateset_copy(rs_dflt, &rs);
+	brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams);
+
+	/*
+	 * walk the phy rate table and update MAC core SHM
+	 * basic rate table entries
+	 */
+	for (i = 0; i < rs.count; i++) {
+		rate = rs.rates[i] & BRCMS_RATE_MASK;
+
+		entry_ptr = brcms_b_rate_shm_offset(wlc->hw, rate);
+
+		/* Calculate the Probe Response PLCP for the given rate */
+		brcms_c_compute_plcp(wlc, rate, frame_len, plcp);
+
+		/*
+		 * Calculate the duration of the Probe Response
+		 * frame plus SIFS for the MAC
+		 */
+		dur = (u16) brcms_c_calc_frame_time(wlc, rate,
+						BRCMS_LONG_PREAMBLE, frame_len);
+		dur += sifs;
+
+		/* Update the SHM Rate Table entry Probe Response values */
+		brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_PLCP_POS,
+			      (u16) (plcp[0] + (plcp[1] << 8)));
+		brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_PLCP_POS + 2,
+			      (u16) (plcp[2] + (plcp[3] << 8)));
+		brcms_b_write_shm(wlc->hw, entry_ptr + M_RT_PRS_DUR_POS, dur);
+	}
+}
+
+int brcms_c_get_header_len(void)
+{
+	return TXOFF;
+}
+
+static void brcms_c_beacon_write(struct brcms_c_info *wlc,
+				 struct sk_buff *beacon, u16 tim_offset,
+				 u16 dtim_period, bool bcn0, bool bcn1)
+{
+	size_t len;
+	struct ieee80211_tx_info *tx_info;
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	struct ieee80211_hw *ieee_hw = brcms_c_pub(wlc)->ieee_hw;
+
+	/* Get tx_info */
+	tx_info = IEEE80211_SKB_CB(beacon);
+
+	len = min_t(size_t, beacon->len, BCN_TMPL_LEN);
+	wlc->bcn_rspec = ieee80211_get_tx_rate(ieee_hw, tx_info)->hw_value;
+
+	brcms_c_compute_plcp(wlc, wlc->bcn_rspec,
+			     len + FCS_LEN - D11_PHY_HDR_LEN, beacon->data);
+
+	/* "Regular" and 16 MBSS but not for 4 MBSS */
+	/* Update the phytxctl for the beacon based on the rspec */
+	brcms_c_beacon_phytxctl_txant_upd(wlc, wlc->bcn_rspec);
+
+	if (bcn0) {
+		/* write the probe response into the template region */
+		brcms_b_write_template_ram(wlc_hw, T_BCN0_TPL_BASE,
+					    (len + 3) & ~3, beacon->data);
+
+		/* write beacon length to SCR */
+		brcms_b_write_shm(wlc_hw, M_BCN0_FRM_BYTESZ, (u16) len);
+	}
+	if (bcn1) {
+		/* write the probe response into the template region */
+		brcms_b_write_template_ram(wlc_hw, T_BCN1_TPL_BASE,
+					    (len + 3) & ~3, beacon->data);
+
+		/* write beacon length to SCR */
+		brcms_b_write_shm(wlc_hw, M_BCN1_FRM_BYTESZ, (u16) len);
+	}
+
+	if (tim_offset != 0) {
+		brcms_b_write_shm(wlc_hw, M_TIMBPOS_INBEACON,
+				  tim_offset + D11B_PHY_HDR_LEN);
+		brcms_b_write_shm(wlc_hw, M_DOT11_DTIMPERIOD, dtim_period);
+	} else {
+		brcms_b_write_shm(wlc_hw, M_TIMBPOS_INBEACON,
+				  len + D11B_PHY_HDR_LEN);
+		brcms_b_write_shm(wlc_hw, M_DOT11_DTIMPERIOD, 0);
+	}
+}
+
+static void brcms_c_update_beacon_hw(struct brcms_c_info *wlc,
+				     struct sk_buff *beacon, u16 tim_offset,
+				     u16 dtim_period)
+{
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	struct bcma_device *core = wlc_hw->d11core;
+
+	/* Hardware beaconing for this config */
+	u32 both_valid = MCMD_BCN0VLD | MCMD_BCN1VLD;
+
+	/* Check if both templates are in use, if so sched. an interrupt
+	 *      that will call back into this routine
+	 */
+	if ((bcma_read32(core, D11REGOFFS(maccommand)) & both_valid) == both_valid)
+		/* clear any previous status */
+		bcma_write32(core, D11REGOFFS(macintstatus), MI_BCNTPL);
+
+	if (wlc->beacon_template_virgin) {
+		wlc->beacon_template_virgin = false;
+		brcms_c_beacon_write(wlc, beacon, tim_offset, dtim_period, true,
+				     true);
+		/* mark beacon0 valid */
+		bcma_set32(core, D11REGOFFS(maccommand), MCMD_BCN0VLD);
+		return;
+	}
+
+	/* Check that after scheduling the interrupt both of the
+	 *      templates are still busy. if not clear the int. & remask
+	 */
+	if ((bcma_read32(core, D11REGOFFS(maccommand)) & both_valid) == both_valid) {
+		wlc->defmacintmask |= MI_BCNTPL;
+		return;
+	}
+
+	if (!(bcma_read32(core, D11REGOFFS(maccommand)) & MCMD_BCN0VLD)) {
+		brcms_c_beacon_write(wlc, beacon, tim_offset, dtim_period, true,
+				     false);
+		/* mark beacon0 valid */
+		bcma_set32(core, D11REGOFFS(maccommand), MCMD_BCN0VLD);
+		return;
+	}
+	if (!(bcma_read32(core, D11REGOFFS(maccommand)) & MCMD_BCN1VLD)) {
+		brcms_c_beacon_write(wlc, beacon, tim_offset, dtim_period,
+				     false, true);
+		/* mark beacon0 valid */
+		bcma_set32(core, D11REGOFFS(maccommand), MCMD_BCN1VLD);
+		return;
+	}
+	return;
+}
+
+/*
+ * Update all beacons for the system.
+ */
+void brcms_c_update_beacon(struct brcms_c_info *wlc)
+{
+	struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
+
+	if (wlc->pub->up && (bsscfg->type == BRCMS_TYPE_AP ||
+			     bsscfg->type == BRCMS_TYPE_ADHOC)) {
+		/* Clear the soft intmask */
+		wlc->defmacintmask &= ~MI_BCNTPL;
+		if (!wlc->beacon)
+			return;
+		brcms_c_update_beacon_hw(wlc, wlc->beacon,
+					 wlc->beacon_tim_offset,
+					 wlc->beacon_dtim_period);
+	}
+}
+
+void brcms_c_set_new_beacon(struct brcms_c_info *wlc, struct sk_buff *beacon,
+			    u16 tim_offset, u16 dtim_period)
+{
+	if (!beacon)
+		return;
+	if (wlc->beacon)
+		dev_kfree_skb_any(wlc->beacon);
+	wlc->beacon = beacon;
+
+	/* add PLCP */
+	skb_push(wlc->beacon, D11_PHY_HDR_LEN);
+	wlc->beacon_tim_offset = tim_offset;
+	wlc->beacon_dtim_period = dtim_period;
+	brcms_c_update_beacon(wlc);
+}
+
+void brcms_c_set_new_probe_resp(struct brcms_c_info *wlc,
+				struct sk_buff *probe_resp)
+{
+	if (!probe_resp)
+		return;
+	if (wlc->probe_resp)
+		dev_kfree_skb_any(wlc->probe_resp);
+	wlc->probe_resp = probe_resp;
+
+	/* add PLCP */
+	skb_push(wlc->probe_resp, D11_PHY_HDR_LEN);
+	brcms_c_update_probe_resp(wlc, false);
+}
+
+void brcms_c_enable_probe_resp(struct brcms_c_info *wlc, bool enable)
+{
+	/*
+	 * prevent ucode from sending probe responses by setting the timeout
+	 * to 1, it can not send it in that time frame.
+	 */
+	wlc->prb_resp_timeout = enable ? BRCMS_PRB_RESP_TIMEOUT : 1;
+	brcms_b_write_shm(wlc->hw, M_PRS_MAXTIME, wlc->prb_resp_timeout);
+	/* TODO: if (enable) => also deactivate receiving of probe request */
+}
+
+/* Write ssid into shared memory */
+static void
+brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg)
+{
+	u8 *ssidptr = cfg->SSID;
+	u16 base = M_SSID;
+	u8 ssidbuf[IEEE80211_MAX_SSID_LEN];
+
+	/* padding the ssid with zero and copy it into shm */
+	memset(ssidbuf, 0, IEEE80211_MAX_SSID_LEN);
+	memcpy(ssidbuf, ssidptr, cfg->SSID_len);
+
+	brcms_c_copyto_shm(wlc, base, ssidbuf, IEEE80211_MAX_SSID_LEN);
+	brcms_b_write_shm(wlc->hw, M_SSIDLEN, (u16) cfg->SSID_len);
+}
+
+static void
+brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
+			      struct brcms_bss_cfg *cfg,
+			      struct sk_buff *probe_resp,
+			      bool suspend)
+{
+	int len;
+
+	len = min_t(size_t, probe_resp->len, BCN_TMPL_LEN);
+
+	if (suspend)
+		brcms_c_suspend_mac_and_wait(wlc);
+
+	/* write the probe response into the template region */
+	brcms_b_write_template_ram(wlc->hw, T_PRS_TPL_BASE,
+				    (len + 3) & ~3, probe_resp->data);
+
+	/* write the length of the probe response frame (+PLCP/-FCS) */
+	brcms_b_write_shm(wlc->hw, M_PRB_RESP_FRM_LEN, (u16) len);
+
+	/* write the SSID and SSID length */
+	brcms_c_shm_ssid_upd(wlc, cfg);
+
+	/*
+	 * Write PLCP headers and durations for probe response frames
+	 * at all rates. Use the actual frame length covered by the
+	 * PLCP header for the call to brcms_c_mod_prb_rsp_rate_table()
+	 * by subtracting the PLCP len and adding the FCS.
+	 */
+	brcms_c_mod_prb_rsp_rate_table(wlc,
+				      (u16)len + FCS_LEN - D11_PHY_HDR_LEN);
+
+	if (suspend)
+		brcms_c_enable_mac(wlc);
+}
+
+void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
+{
+	struct brcms_bss_cfg *bsscfg = wlc->bsscfg;
+
+	/* update AP or IBSS probe responses */
+	if (wlc->pub->up && (bsscfg->type == BRCMS_TYPE_AP ||
+			     bsscfg->type == BRCMS_TYPE_ADHOC)) {
+		if (!wlc->probe_resp)
+			return;
+		brcms_c_bss_update_probe_resp(wlc, bsscfg, wlc->probe_resp,
+					      suspend);
+	}
+}
+
+int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
+			   uint *blocks)
+{
+	if (fifo >= NFIFO)
+		return -EINVAL;
+
+	*blocks = wlc_hw->xmtfifo_sz[fifo];
+
+	return 0;
+}
+
+void
+brcms_c_set_addrmatch(struct brcms_c_info *wlc, int match_reg_offset,
+		  const u8 *addr)
+{
+	brcms_b_set_addrmatch(wlc->hw, match_reg_offset, addr);
+	if (match_reg_offset == RCM_BSSID_OFFSET)
+		memcpy(wlc->bsscfg->BSSID, addr, ETH_ALEN);
+}
+
+/*
+ * Flag 'scan in progress' to withhold dynamic phy calibration
+ */
+void brcms_c_scan_start(struct brcms_c_info *wlc)
+{
+	wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, true);
+}
+
+void brcms_c_scan_stop(struct brcms_c_info *wlc)
+{
+	wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, false);
+}
+
+void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state)
+{
+	wlc->pub->associated = state;
+}
+
+/*
+ * When a remote STA/AP is removed by Mac80211, or when it can no longer accept
+ * AMPDU traffic, packets pending in hardware have to be invalidated so that
+ * when later on hardware releases them, they can be handled appropriately.
+ */
+void brcms_c_inval_dma_pkts(struct brcms_hardware *hw,
+			       struct ieee80211_sta *sta,
+			       void (*dma_callback_fn))
+{
+	struct dma_pub *dmah;
+	int i;
+	for (i = 0; i < NFIFO; i++) {
+		dmah = hw->di[i];
+		if (dmah != NULL)
+			dma_walk_packets(dmah, dma_callback_fn, sta);
+	}
+}
+
+int brcms_c_get_curband(struct brcms_c_info *wlc)
+{
+	return wlc->band->bandunit;
+}
+
+bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc)
+{
+	int i;
+
+	/* Kick DMA to send any pending AMPDU */
+	for (i = 0; i < ARRAY_SIZE(wlc->hw->di); i++)
+		if (wlc->hw->di[i])
+			dma_kick_tx(wlc->hw->di[i]);
+
+	return !brcms_txpktpendtot(wlc);
+}
+
+void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval)
+{
+	wlc->bcn_li_bcn = interval;
+	if (wlc->pub->up)
+		brcms_c_bcn_li_upd(wlc);
+}
+
+u64 brcms_c_tsf_get(struct brcms_c_info *wlc)
+{
+	u32 tsf_h, tsf_l;
+	u64 tsf;
+
+	brcms_b_read_tsf(wlc->hw, &tsf_l, &tsf_h);
+
+	tsf = tsf_h;
+	tsf <<= 32;
+	tsf |= tsf_l;
+
+	return tsf;
+}
+
+void brcms_c_tsf_set(struct brcms_c_info *wlc, u64 tsf)
+{
+	u32 tsf_h, tsf_l;
+
+	brcms_c_time_lock(wlc);
+
+	tsf_l = tsf;
+	tsf_h = (tsf >> 32);
+
+	/* read the tsf timer low, then high to get an atomic read */
+	bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_timerlow), tsf_l);
+	bcma_write32(wlc->hw->d11core, D11REGOFFS(tsf_timerhigh), tsf_h);
+
+	brcms_c_time_unlock(wlc);
+}
+
+int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr)
+{
+	uint qdbm;
+
+	/* Remove override bit and clip to max qdbm value */
+	qdbm = min_t(uint, txpwr * BRCMS_TXPWR_DB_FACTOR, 0xff);
+	return wlc_phy_txpower_set(wlc->band->pi, qdbm, false);
+}
+
+int brcms_c_get_tx_power(struct brcms_c_info *wlc)
+{
+	uint qdbm;
+	bool override;
+
+	wlc_phy_txpower_get(wlc->band->pi, &qdbm, &override);
+
+	/* Return qdbm units */
+	return (int)(qdbm / BRCMS_TXPWR_DB_FACTOR);
+}
+
+/* Process received frames */
+/*
+ * Return true if more frames need to be processed. false otherwise.
+ * Param 'bound' indicates max. # frames to process before break out.
+ */
+static void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p)
+{
+	struct d11rxhdr *rxh;
+	struct ieee80211_hdr *h;
+	uint len;
+	bool is_amsdu;
+
+	/* frame starts with rxhdr */
+	rxh = (struct d11rxhdr *) (p->data);
+
+	/* strip off rxhdr */
+	skb_pull(p, BRCMS_HWRXOFF);
+
+	/* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU subframes */
+	if (rxh->RxStatus1 & RXS_PBPRES) {
+		if (p->len < 2) {
+			brcms_err(wlc->hw->d11core,
+				  "wl%d: recv: rcvd runt of len %d\n",
+				  wlc->pub->unit, p->len);
+			goto toss;
+		}
+		skb_pull(p, 2);
+	}
+
+	h = (struct ieee80211_hdr *)(p->data + D11_PHY_HDR_LEN);
+	len = p->len;
+
+	if (rxh->RxStatus1 & RXS_FCSERR) {
+		if (!(wlc->filter_flags & FIF_FCSFAIL))
+			goto toss;
+	}
+
+	/* check received pkt has at least frame control field */
+	if (len < D11_PHY_HDR_LEN + sizeof(h->frame_control))
+		goto toss;
+
+	/* not supporting A-MSDU */
+	is_amsdu = rxh->RxStatus2 & RXS_AMSDU_MASK;
+	if (is_amsdu)
+		goto toss;
+
+	brcms_c_recvctl(wlc, rxh, p);
+	return;
+
+ toss:
+	brcmu_pkt_buf_free_skb(p);
+}
+
+/* Process received frames */
+/*
+ * Return true if more frames need to be processed. false otherwise.
+ * Param 'bound' indicates max. # frames to process before break out.
+ */
+static bool
+brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound)
+{
+	struct sk_buff *p;
+	struct sk_buff *next = NULL;
+	struct sk_buff_head recv_frames;
+
+	uint n = 0;
+	uint bound_limit = bound ? RXBND : -1;
+	bool morepending = false;
+
+	skb_queue_head_init(&recv_frames);
+
+	/* gather received frames */
+	do {
+		/* !give others some time to run! */
+		if (n >= bound_limit)
+			break;
+
+		morepending = dma_rx(wlc_hw->di[fifo], &recv_frames);
+		n++;
+	} while (morepending);
+
+	/* post more rbufs */
+	dma_rxfill(wlc_hw->di[fifo]);
+
+	/* process each frame */
+	skb_queue_walk_safe(&recv_frames, p, next) {
+		struct d11rxhdr_le *rxh_le;
+		struct d11rxhdr *rxh;
+
+		skb_unlink(p, &recv_frames);
+		rxh_le = (struct d11rxhdr_le *)p->data;
+		rxh = (struct d11rxhdr *)p->data;
+
+		/* fixup rx header endianness */
+		rxh->RxFrameSize = le16_to_cpu(rxh_le->RxFrameSize);
+		rxh->PhyRxStatus_0 = le16_to_cpu(rxh_le->PhyRxStatus_0);
+		rxh->PhyRxStatus_1 = le16_to_cpu(rxh_le->PhyRxStatus_1);
+		rxh->PhyRxStatus_2 = le16_to_cpu(rxh_le->PhyRxStatus_2);
+		rxh->PhyRxStatus_3 = le16_to_cpu(rxh_le->PhyRxStatus_3);
+		rxh->PhyRxStatus_4 = le16_to_cpu(rxh_le->PhyRxStatus_4);
+		rxh->PhyRxStatus_5 = le16_to_cpu(rxh_le->PhyRxStatus_5);
+		rxh->RxStatus1 = le16_to_cpu(rxh_le->RxStatus1);
+		rxh->RxStatus2 = le16_to_cpu(rxh_le->RxStatus2);
+		rxh->RxTSFTime = le16_to_cpu(rxh_le->RxTSFTime);
+		rxh->RxChan = le16_to_cpu(rxh_le->RxChan);
+
+		brcms_c_recv(wlc_hw->wlc, p);
+	}
+
+	return morepending;
+}
+
+/* second-level interrupt processing
+ *   Return true if another dpc needs to be re-scheduled. false otherwise.
+ *   Param 'bounded' indicates if applicable loops should be bounded.
+ */
+bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
+{
+	u32 macintstatus;
+	struct brcms_hardware *wlc_hw = wlc->hw;
+	struct bcma_device *core = wlc_hw->d11core;
+
+	if (brcms_deviceremoved(wlc)) {
+		brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit,
+			  __func__);
+		brcms_down(wlc->wl);
+		return false;
+	}
+
+	/* grab and clear the saved software intstatus bits */
+	macintstatus = wlc->macintstatus;
+	wlc->macintstatus = 0;
+
+	brcms_dbg_int(core, "wl%d: macintstatus 0x%x\n",
+		      wlc_hw->unit, macintstatus);
+
+	WARN_ON(macintstatus & MI_PRQ); /* PRQ Interrupt in non-MBSS */
+
+	/* tx status */
+	if (macintstatus & MI_TFS) {
+		bool fatal;
+		if (brcms_b_txstatus(wlc->hw, bounded, &fatal))
+			wlc->macintstatus |= MI_TFS;
+		if (fatal) {
+			brcms_err(core, "MI_TFS: fatal\n");
+			goto fatal;
+		}
+	}
+
+	if (macintstatus & (MI_TBTT | MI_DTIM_TBTT))
+		brcms_c_tbtt(wlc);
+
+	/* ATIM window end */
+	if (macintstatus & MI_ATIMWINEND) {
+		brcms_dbg_info(core, "end of ATIM window\n");
+		bcma_set32(core, D11REGOFFS(maccommand), wlc->qvalid);
+		wlc->qvalid = 0;
+	}
+
+	/*
+	 * received data or control frame, MI_DMAINT is
+	 * indication of RX_FIFO interrupt
+	 */
+	if (macintstatus & MI_DMAINT)
+		if (brcms_b_recv(wlc_hw, RX_FIFO, bounded))
+			wlc->macintstatus |= MI_DMAINT;
+
+	/* noise sample collected */
+	if (macintstatus & MI_BG_NOISE)
+		wlc_phy_noise_sample_intr(wlc_hw->band->pi);
+
+	if (macintstatus & MI_GP0) {
+		brcms_err(core, "wl%d: PSM microcode watchdog fired at %d "
+			  "(seconds). Resetting.\n", wlc_hw->unit, wlc_hw->now);
+
+		printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n",
+			    __func__, ai_get_chip_id(wlc_hw->sih),
+			    ai_get_chiprev(wlc_hw->sih));
+		brcms_fatal_error(wlc_hw->wlc->wl);
+	}
+
+	/* gptimer timeout */
+	if (macintstatus & MI_TO)
+		bcma_write32(core, D11REGOFFS(gptimer), 0);
+
+	if (macintstatus & MI_RFDISABLE) {
+		brcms_dbg_info(core, "wl%d: BMAC Detected a change on the"
+			       " RF Disable Input\n", wlc_hw->unit);
+		brcms_rfkill_set_hw_state(wlc->wl);
+	}
+
+	/* BCN template is available */
+	if (macintstatus & MI_BCNTPL)
+		brcms_c_update_beacon(wlc);
+
+	/* it isn't done and needs to be resched if macintstatus is non-zero */
+	return wlc->macintstatus != 0;
+
+ fatal:
+	brcms_fatal_error(wlc_hw->wlc->wl);
+	return wlc->macintstatus != 0;
+}
+
+void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
+{
+	struct bcma_device *core = wlc->hw->d11core;
+	struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.chandef.chan;
+	u16 chanspec;
+
+	brcms_dbg_info(core, "wl%d\n", wlc->pub->unit);
+
+	chanspec = ch20mhz_chspec(ch->hw_value);
+
+	brcms_b_init(wlc->hw, chanspec);
+
+	/* update beacon listen interval */
+	brcms_c_bcn_li_upd(wlc);
+
+	/* write ethernet address to core */
+	brcms_c_set_mac(wlc->bsscfg);
+	brcms_c_set_bssid(wlc->bsscfg);
+
+	/* Update tsf_cfprep if associated and up */
+	if (wlc->pub->associated && wlc->pub->up) {
+		u32 bi;
+
+		/* get beacon period and convert to uS */
+		bi = wlc->bsscfg->current_bss->beacon_period << 10;
+		/*
+		 * update since init path would reset
+		 * to default value
+		 */
+		bcma_write32(core, D11REGOFFS(tsf_cfprep),
+			     bi << CFPREP_CBI_SHIFT);
+
+		/* Update maccontrol PM related bits */
+		brcms_c_set_ps_ctrl(wlc);
+	}
+
+	brcms_c_bandinit_ordered(wlc, chanspec);
+
+	/* init probe response timeout */
+	brcms_b_write_shm(wlc->hw, M_PRS_MAXTIME, wlc->prb_resp_timeout);
+
+	/* init max burst txop (framebursting) */
+	brcms_b_write_shm(wlc->hw, M_MBURST_TXOP,
+		      (wlc->
+		       _rifs ? (EDCF_AC_VO_TXOP_AP << 5) : MAXFRAMEBURST_TXOP));
+
+	/* initialize maximum allowed duty cycle */
+	brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_ofdm, true, true);
+	brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_cck, false, true);
+
+	/*
+	 * Update some shared memory locations related to
+	 * max AMPDU size allowed to received
+	 */
+	brcms_c_ampdu_shm_upd(wlc->ampdu);
+
+	/* band-specific inits */
+	brcms_c_bsinit(wlc);
+
+	/* Enable EDCF mode (while the MAC is suspended) */
+	bcma_set16(core, D11REGOFFS(ifs_ctl), IFS_USEEDCF);
+	brcms_c_edcf_setparams(wlc, false);
+
+	/* read the ucode version if we have not yet done so */
+	if (wlc->ucode_rev == 0) {
+		u16 rev;
+		u16 patch;
+
+		rev = brcms_b_read_shm(wlc->hw, M_BOM_REV_MAJOR);
+		patch = brcms_b_read_shm(wlc->hw, M_BOM_REV_MINOR);
+		wlc->ucode_rev = (rev << NBITS(u16)) | patch;
+		snprintf(wlc->wiphy->fw_version,
+			 sizeof(wlc->wiphy->fw_version), "%u.%u", rev, patch);
+	}
+
+	/* ..now really unleash hell (allow the MAC out of suspend) */
+	brcms_c_enable_mac(wlc);
+
+	/* suspend the tx fifos and mute the phy for preism cac time */
+	if (mute_tx)
+		brcms_b_mute(wlc->hw, true);
+
+	/* enable the RF Disable Delay timer */
+	bcma_write32(core, D11REGOFFS(rfdisabledly), RFDISABLE_DEFAULT);
+
+	/*
+	 * Initialize WME parameters; if they haven't been set by some other
+	 * mechanism (IOVar, etc) then read them from the hardware.
+	 */
+	if (GFIELD(wlc->wme_retries[0], EDCF_SHORT) == 0) {
+		/* Uninitialized; read from HW */
+		int ac;
+
+		for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
+			wlc->wme_retries[ac] =
+			    brcms_b_read_shm(wlc->hw, M_AC_TXLMT_ADDR(ac));
+	}
+}
+
+/*
+ * The common driver entry routine. Error codes should be unique
+ */
+struct brcms_c_info *
+brcms_c_attach(struct brcms_info *wl, struct bcma_device *core, uint unit,
+	       bool piomode, uint *perr)
+{
+	struct brcms_c_info *wlc;
+	uint err = 0;
+	uint i, j;
+	struct brcms_pub *pub;
+
+	/* allocate struct brcms_c_info state and its substructures */
+	wlc = brcms_c_attach_malloc(unit, &err, 0);
+	if (wlc == NULL)
+		goto fail;
+	wlc->wiphy = wl->wiphy;
+	pub = wlc->pub;
+
+#if defined(DEBUG)
+	wlc_info_dbg = wlc;
+#endif
+
+	wlc->band = wlc->bandstate[0];
+	wlc->core = wlc->corestate;
+	wlc->wl = wl;
+	pub->unit = unit;
+	pub->_piomode = piomode;
+	wlc->bandinit_pending = false;
+	wlc->beacon_template_virgin = true;
+
+	/* populate struct brcms_c_info with default values  */
+	brcms_c_info_init(wlc, unit);
+
+	/* update sta/ap related parameters */
+	brcms_c_ap_upd(wlc);
+
+	/*
+	 * low level attach steps(all hw accesses go
+	 * inside, no more in rest of the attach)
+	 */
+	err = brcms_b_attach(wlc, core, unit, piomode);
+	if (err)
+		goto fail;
+
+	brcms_c_protection_upd(wlc, BRCMS_PROT_N_PAM_OVR, OFF);
+
+	pub->phy_11ncapable = BRCMS_PHY_11N_CAP(wlc->band);
+
+	/* disable allowed duty cycle */
+	wlc->tx_duty_cycle_ofdm = 0;
+	wlc->tx_duty_cycle_cck = 0;
+
+	brcms_c_stf_phy_chain_calc(wlc);
+
+	/* txchain 1: txant 0, txchain 2: txant 1 */
+	if (BRCMS_ISNPHY(wlc->band) && (wlc->stf->txstreams == 1))
+		wlc->stf->txant = wlc->stf->hw_txchain - 1;
+
+	/* push to BMAC driver */
+	wlc_phy_stf_chain_init(wlc->band->pi, wlc->stf->hw_txchain,
+			       wlc->stf->hw_rxchain);
+
+	/* pull up some info resulting from the low attach */
+	for (i = 0; i < NFIFO; i++)
+		wlc->core->txavail[i] = wlc->hw->txavail[i];
+
+	memcpy(&wlc->perm_etheraddr, &wlc->hw->etheraddr, ETH_ALEN);
+	memcpy(&pub->cur_etheraddr, &wlc->hw->etheraddr, ETH_ALEN);
+
+	for (j = 0; j < wlc->pub->_nbands; j++) {
+		wlc->band = wlc->bandstate[j];
+
+		if (!brcms_c_attach_stf_ant_init(wlc)) {
+			err = 24;
+			goto fail;
+		}
+
+		/* default contention windows size limits */
+		wlc->band->CWmin = APHY_CWMIN;
+		wlc->band->CWmax = PHY_CWMAX;
+
+		/* init gmode value */
+		if (wlc->band->bandtype == BRCM_BAND_2G) {
+			wlc->band->gmode = GMODE_AUTO;
+			brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER,
+					   wlc->band->gmode);
+		}
+
+		/* init _n_enab supported mode */
+		if (BRCMS_PHY_11N_CAP(wlc->band)) {
+			pub->_n_enab = SUPPORT_11N;
+			brcms_c_protection_upd(wlc, BRCMS_PROT_N_USER,
+						   ((pub->_n_enab ==
+						     SUPPORT_11N) ? WL_11N_2x2 :
+						    WL_11N_3x3));
+		}
+
+		/* init per-band default rateset, depend on band->gmode */
+		brcms_default_rateset(wlc, &wlc->band->defrateset);
+
+		/* fill in hw_rateset */
+		brcms_c_rateset_filter(&wlc->band->defrateset,
+				   &wlc->band->hw_rateset, false,
+				   BRCMS_RATES_CCK_OFDM, BRCMS_RATE_MASK,
+				   (bool) (wlc->pub->_n_enab & SUPPORT_11N));
+	}
+
+	/*
+	 * update antenna config due to
+	 * wlc->stf->txant/txchain/ant_rx_ovr change
+	 */
+	brcms_c_stf_phy_txant_upd(wlc);
+
+	/* attach each modules */
+	err = brcms_c_attach_module(wlc);
+	if (err != 0)
+		goto fail;
+
+	if (!brcms_c_timers_init(wlc, unit)) {
+		wiphy_err(wl->wiphy, "wl%d: %s: init_timer failed\n", unit,
+			  __func__);
+		err = 32;
+		goto fail;
+	}
+
+	/* depend on rateset, gmode */
+	wlc->cmi = brcms_c_channel_mgr_attach(wlc);
+	if (!wlc->cmi) {
+		wiphy_err(wl->wiphy, "wl%d: %s: channel_mgr_attach failed"
+			  "\n", unit, __func__);
+		err = 33;
+		goto fail;
+	}
+
+	/* init default when all parameters are ready, i.e. ->rateset */
+	brcms_c_bss_default_init(wlc);
+
+	/*
+	 * Complete the wlc default state initializations..
+	 */
+
+	wlc->bsscfg->wlc = wlc;
+
+	wlc->mimoft = FT_HT;
+	wlc->mimo_40txbw = AUTO;
+	wlc->ofdm_40txbw = AUTO;
+	wlc->cck_40txbw = AUTO;
+	brcms_c_update_mimo_band_bwcap(wlc, BRCMS_N_BW_20IN2G_40IN5G);
+
+	/* Set default values of SGI */
+	if (BRCMS_SGI_CAP_PHY(wlc)) {
+		brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 |
+					       BRCMS_N_SGI_40));
+	} else if (BRCMS_ISSSLPNPHY(wlc->band)) {
+		brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 |
+					       BRCMS_N_SGI_40));
+	} else {
+		brcms_c_ht_update_sgi_rx(wlc, 0);
+	}
+
+	brcms_b_antsel_set(wlc->hw, wlc->asi->antsel_avail);
+
+	if (perr)
+		*perr = 0;
+
+	return wlc;
+
+ fail:
+	wiphy_err(wl->wiphy, "wl%d: %s: failed with err %d\n",
+		  unit, __func__, err);
+	if (wlc)
+		brcms_c_detach(wlc);
+
+	if (perr)
+		*perr = err;
+	return NULL;
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.h
new file mode 100644
index 0000000..c4d135c
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.h
@@ -0,0 +1,669 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_MAIN_H_
+#define _BRCM_MAIN_H_
+
+#include <linux/etherdevice.h>
+
+#include <brcmu_utils.h>
+#include "types.h"
+#include "d11.h"
+#include "scb.h"
+
+#define	INVCHANNEL		255	/* invalid channel */
+
+/* max # brcms_c_module_register() calls */
+#define BRCMS_MAXMODULES	22
+
+#define SEQNUM_SHIFT		4
+#define SEQNUM_MAX		0x1000
+
+#define NTXRATE			64	/* # tx MPDUs rate is reported for */
+
+/* Maximum wait time for a MAC suspend */
+/* uS: 83mS is max packet time (64KB ampdu @ 6Mbps) */
+#define	BRCMS_MAX_MAC_SUSPEND	83000
+
+/* responses for probe requests older that this are tossed, zero to disable */
+#define BRCMS_PRB_RESP_TIMEOUT	0	/* Disable probe response timeout */
+
+/* transmit buffer max headroom for protocol headers */
+#define TXOFF (D11_TXH_LEN + D11_PHY_HDR_LEN)
+
+/* Macros for doing definition and get/set of bitfields
+ * Usage example, e.g. a three-bit field (bits 4-6):
+ *    #define <NAME>_M	BITFIELD_MASK(3)
+ *    #define <NAME>_S	4
+ * ...
+ *    regval = R_REG(osh, &regs->regfoo);
+ *    field = GFIELD(regval, <NAME>);
+ *    regval = SFIELD(regval, <NAME>, 1);
+ *    W_REG(osh, &regs->regfoo, regval);
+ */
+#define BITFIELD_MASK(width) \
+		(((unsigned)1 << (width)) - 1)
+#define GFIELD(val, field) \
+		(((val) >> field ## _S) & field ## _M)
+#define SFIELD(val, field, bits) \
+		(((val) & (~(field ## _M << field ## _S))) | \
+		 ((unsigned)(bits) << field ## _S))
+
+#define	SW_TIMER_MAC_STAT_UPD		30	/* periodic MAC stats update */
+
+/* max # supported core revisions (0 .. MAXCOREREV - 1) */
+#define	MAXCOREREV		28
+
+/* Double check that unsupported cores are not enabled */
+#if CONF_MSK(D11CONF, 0x4f) || CONF_GE(D11CONF, MAXCOREREV)
+#error "Configuration for D11CONF includes unsupported versions."
+#endif				/* Bad versions */
+
+/* values for shortslot_override */
+#define BRCMS_SHORTSLOT_AUTO	-1 /* Driver will manage Shortslot setting */
+#define BRCMS_SHORTSLOT_OFF	0  /* Turn off short slot */
+#define BRCMS_SHORTSLOT_ON	1  /* Turn on short slot */
+
+/* value for short/long and mixmode/greenfield preamble */
+#define BRCMS_LONG_PREAMBLE	(0)
+#define BRCMS_SHORT_PREAMBLE	(1 << 0)
+#define BRCMS_GF_PREAMBLE		(1 << 1)
+#define BRCMS_MM_PREAMBLE		(1 << 2)
+#define BRCMS_IS_MIMO_PREAMBLE(_pre) (((_pre) == BRCMS_GF_PREAMBLE) || \
+				      ((_pre) == BRCMS_MM_PREAMBLE))
+
+/* TxFrameID */
+/* seq and frag bits: SEQNUM_SHIFT, FRAGNUM_MASK (802.11.h) */
+/* rate epoch bits: TXFID_RATE_SHIFT, TXFID_RATE_MASK ((wlc_rate.c) */
+#define TXFID_QUEUE_MASK	0x0007	/* Bits 0-2 */
+#define TXFID_SEQ_MASK		0x7FE0	/* Bits 5-15 */
+#define TXFID_SEQ_SHIFT		5	/* Number of bit shifts */
+#define	TXFID_RATE_PROBE_MASK	0x8000	/* Bit 15 for rate probe */
+#define TXFID_RATE_MASK		0x0018	/* Mask for bits 3 and 4 */
+#define TXFID_RATE_SHIFT	3	/* Shift 3 bits for rate mask */
+
+/* promote boardrev */
+#define BOARDREV_PROMOTABLE	0xFF	/* from */
+#define BOARDREV_PROMOTED	1	/* to */
+
+#define DATA_BLOCK_TX_SUPR	(1 << 4)
+
+/* Ucode MCTL_WAKE override bits */
+#define BRCMS_WAKE_OVERRIDE_CLKCTL	0x01
+#define BRCMS_WAKE_OVERRIDE_PHYREG	0x02
+#define BRCMS_WAKE_OVERRIDE_MACSUSPEND	0x04
+#define BRCMS_WAKE_OVERRIDE_TXFIFO	0x08
+#define BRCMS_WAKE_OVERRIDE_FORCEFAST	0x10
+
+/* stuff pulled in from wlc.c */
+
+/* Interrupt bit error summary.  Don't include I_RU: we refill DMA at other
+ * times; and if we run out, constant I_RU interrupts may cause lockup.  We
+ * will still get error counts from rx0ovfl.
+ */
+#define	I_ERRORS	(I_PC | I_PD | I_DE | I_RO | I_XU)
+/* default software intmasks */
+#define	DEF_RXINTMASK	(I_RI)	/* enable rx int on rxfifo only */
+#define	DEF_MACINTMASK	(MI_TXSTOP | MI_TBTT | MI_ATIMWINEND | MI_PMQ | \
+			 MI_PHYTXERR | MI_DMAINT | MI_TFS | MI_BG_NOISE | \
+			 MI_CCA | MI_TO | MI_GP0 | MI_RFDISABLE | MI_PWRUP)
+
+#define	MAXTXPKTS		6	/* max # pkts pending */
+
+/* frameburst */
+#define	MAXTXFRAMEBURST		8 /* vanilla xpress mode: max frames/burst */
+#define	MAXFRAMEBURST_TXOP	10000	/* Frameburst TXOP in usec */
+
+#define	NFIFO			6	/* # tx/rx fifopairs */
+
+/* PLL requests */
+
+/* pll is shared on old chips */
+#define BRCMS_PLLREQ_SHARED	0x1
+/* hold pll for radio monitor register checking */
+#define BRCMS_PLLREQ_RADIO_MON	0x2
+/* hold/release pll for some short operation */
+#define BRCMS_PLLREQ_FLIP		0x4
+
+#define	CHANNEL_BANDUNIT(wlc, ch) \
+	(((ch) <= CH_MAX_2G_CHANNEL) ? BAND_2G_INDEX : BAND_5G_INDEX)
+
+#define	OTHERBANDUNIT(wlc) \
+	((uint)((wlc)->band->bandunit ? BAND_2G_INDEX : BAND_5G_INDEX))
+
+/*
+ * 802.11 protection information
+ *
+ * _g: use g spec protection, driver internal.
+ * g_override: override for use of g spec protection.
+ * gmode_user: user config gmode, operating band->gmode is different.
+ * overlap: Overlap BSS/IBSS protection for both 11g and 11n.
+ * nmode_user: user config nmode, operating pub->nmode is different.
+ * n_cfg: use OFDM protection on MIMO frames.
+ * n_cfg_override: override for use of N protection.
+ * nongf: non-GF present protection.
+ * nongf_override: override for use of GF protection.
+ * n_pam_override: override for preamble: MM or GF.
+ * n_obss: indicated OBSS Non-HT STA present.
+*/
+struct brcms_protection {
+	bool _g;
+	s8 g_override;
+	u8 gmode_user;
+	s8 overlap;
+	s8 nmode_user;
+	s8 n_cfg;
+	s8 n_cfg_override;
+	bool nongf;
+	s8 nongf_override;
+	s8 n_pam_override;
+	bool n_obss;
+};
+
+/*
+ * anything affecting the single/dual streams/antenna operation
+ *
+ * hw_txchain: HW txchain bitmap cfg.
+ * txchain: txchain bitmap being used.
+ * txstreams: number of txchains being used.
+ * hw_rxchain: HW rxchain bitmap cfg.
+ * rxchain: rxchain bitmap being used.
+ * rxstreams: number of rxchains being used.
+ * ant_rx_ovr: rx antenna override.
+ * txant: userTx antenna setting.
+ * phytxant: phyTx antenna setting in txheader.
+ * ss_opmode: singlestream Operational mode, 0:siso; 1:cdd.
+ * ss_algosel_auto: if true, use wlc->stf->ss_algo_channel;
+ *			else use wlc->band->stf->ss_mode_band.
+ * ss_algo_channel: ss based on per-channel algo: 0: SISO, 1: CDD 2: STBC.
+ * rxchain_restore_delay: delay time to restore default rxchain.
+ * ldpc: AUTO/ON/OFF ldpc cap supported.
+ * txcore[MAX_STREAMS_SUPPORTED + 1]: bitmap of selected core for each Nsts.
+ * spatial_policy:
+ */
+struct brcms_stf {
+	u8 hw_txchain;
+	u8 txchain;
+	u8 txstreams;
+	u8 hw_rxchain;
+	u8 rxchain;
+	u8 rxstreams;
+	u8 ant_rx_ovr;
+	s8 txant;
+	u16 phytxant;
+	u8 ss_opmode;
+	bool ss_algosel_auto;
+	u16 ss_algo_channel;
+	u8 rxchain_restore_delay;
+	s8 ldpc;
+	u8 txcore[MAX_STREAMS_SUPPORTED + 1];
+	s8 spatial_policy;
+};
+
+#define BRCMS_STF_SS_STBC_TX(wlc, scb) \
+	(((wlc)->stf->txstreams > 1) && (((wlc)->band->band_stf_stbc_tx == ON) \
+	 || (((scb)->flags & SCB_STBCCAP) && \
+	     (wlc)->band->band_stf_stbc_tx == AUTO && \
+	     isset(&((wlc)->stf->ss_algo_channel), PHY_TXC1_MODE_STBC))))
+
+#define BRCMS_STBC_CAP_PHY(wlc) (BRCMS_ISNPHY(wlc->band) && \
+				 NREV_GE(wlc->band->phyrev, 3))
+
+#define BRCMS_SGI_CAP_PHY(wlc) ((BRCMS_ISNPHY(wlc->band) && \
+				 NREV_GE(wlc->band->phyrev, 3)) || \
+				BRCMS_ISLCNPHY(wlc->band))
+
+#define BRCMS_CHAN_PHYTYPE(x)     (((x) & RXS_CHAN_PHYTYPE_MASK) \
+				   >> RXS_CHAN_PHYTYPE_SHIFT)
+#define BRCMS_CHAN_CHANNEL(x)     (((x) & RXS_CHAN_ID_MASK) \
+				   >> RXS_CHAN_ID_SHIFT)
+
+/*
+ * core state (mac)
+ */
+struct brcms_core {
+	uint coreidx;		/* # sb enumerated core */
+
+	/* fifo */
+	uint *txavail[NFIFO];	/* # tx descriptors available */
+
+	struct macstat *macstat_snapshot;	/* mac hw prev read values */
+};
+
+/*
+ * band state (phy+ana+radio)
+ */
+struct brcms_band {
+	int bandtype;		/* BRCM_BAND_2G, BRCM_BAND_5G */
+	uint bandunit;		/* bandstate[] index */
+
+	u16 phytype;		/* phytype */
+	u16 phyrev;
+	u16 radioid;
+	u16 radiorev;
+	struct brcms_phy_pub *pi; /* pointer to phy specific information */
+	bool abgphy_encore;
+
+	u8 gmode;		/* currently active gmode */
+
+	struct scb *hwrs_scb;	/* permanent scb for hw rateset */
+
+	/* band-specific copy of default_bss.rateset */
+	struct brcms_c_rateset defrateset;
+
+	u8 band_stf_ss_mode;	/* Configured STF type, 0:siso; 1:cdd */
+	s8 band_stf_stbc_tx;	/* STBC TX 0:off; 1:force on; -1:auto */
+	/* rates supported by chip (phy-specific) */
+	struct brcms_c_rateset hw_rateset;
+	u8 basic_rate[BRCM_MAXRATE + 1]; /* basic rates indexed by rate */
+	bool mimo_cap_40;	/* 40 MHz cap enabled on this band */
+	s8 antgain;		/* antenna gain from srom */
+
+	u16 CWmin; /* minimum size of contention window, in unit of aSlotTime */
+	u16 CWmax; /* maximum size of contention window, in unit of aSlotTime */
+	struct ieee80211_supported_band band;
+};
+
+/* module control blocks */
+struct modulecb {
+	/* module name : NULL indicates empty array member */
+	char name[32];
+	/* handle passed when handler 'doiovar' is called */
+	struct brcms_info *hdl;
+
+	int (*down_fn)(void *handle); /* down handler. Note: the int returned
+				       * by the down function is a count of the
+				       * number of timers that could not be
+				       * freed.
+				       */
+
+};
+
+struct brcms_hw_band {
+	int bandtype;		/* BRCM_BAND_2G, BRCM_BAND_5G */
+	uint bandunit;		/* bandstate[] index */
+	u16 mhfs[MHFMAX];	/* MHF array shadow */
+	u8 bandhw_stf_ss_mode;	/* HW configured STF type, 0:siso; 1:cdd */
+	u16 CWmin;
+	u16 CWmax;
+	u32 core_flags;
+
+	u16 phytype;		/* phytype */
+	u16 phyrev;
+	u16 radioid;
+	u16 radiorev;
+	struct brcms_phy_pub *pi; /* pointer to phy specific information */
+	bool abgphy_encore;
+};
+
+struct brcms_hardware {
+	bool _piomode;		/* true if pio mode */
+	struct brcms_c_info *wlc;
+
+	/* fifo */
+	struct dma_pub *di[NFIFO];	/* dma handles, per fifo */
+
+	uint unit;		/* device instance number */
+
+	/* version info */
+	u16 vendorid;	/* PCI vendor id */
+	u16 deviceid;	/* PCI device id */
+	uint corerev;		/* core revision */
+	u8 sromrev;		/* version # of the srom */
+	u16 boardrev;	/* version # of particular board */
+	u32 boardflags;	/* Board specific flags from srom */
+	u32 boardflags2;	/* More board flags if sromrev >= 4 */
+	u32 machwcap;	/* MAC capabilities */
+	u32 machwcap_backup;	/* backup of machwcap */
+
+	struct si_pub *sih;	/* SI handle (cookie for siutils calls) */
+	struct bcma_device *d11core;	/* pointer to 802.11 core */
+	struct phy_shim_info *physhim; /* phy shim layer handler */
+	struct shared_phy *phy_sh;	/* pointer to shared phy state */
+	struct brcms_hw_band *band;/* pointer to active per-band state */
+	/* band state per phy/radio */
+	struct brcms_hw_band *bandstate[MAXBANDS];
+	u16 bmac_phytxant;	/* cache of high phytxant state */
+	bool shortslot;		/* currently using 11g ShortSlot timing */
+	u16 SRL;		/* 802.11 dot11ShortRetryLimit */
+	u16 LRL;		/* 802.11 dot11LongRetryLimit */
+	u16 SFBL;		/* Short Frame Rate Fallback Limit */
+	u16 LFBL;		/* Long Frame Rate Fallback Limit */
+
+	bool up;		/* d11 hardware up and running */
+	uint now;		/* # elapsed seconds */
+	uint _nbands;		/* # bands supported */
+	u16 chanspec;	/* bmac chanspec shadow */
+
+	uint *txavail[NFIFO];	/* # tx descriptors available */
+	const u16 *xmtfifo_sz;	/* fifo size in 256B for each xmt fifo */
+
+	u32 pllreq;		/* pll requests to keep PLL on */
+
+	u8 suspended_fifos;	/* Which TX fifo to remain awake for */
+	u32 maccontrol;	/* Cached value of maccontrol */
+	uint mac_suspend_depth;	/* current depth of mac_suspend levels */
+	u32 wake_override;	/* bit flags to force MAC to WAKE mode */
+	u32 mute_override;	/* Prevent ucode from sending beacons */
+	u8 etheraddr[ETH_ALEN];	/* currently configured ethernet address */
+	bool noreset;		/* true= do not reset hw, used by WLC_OUT */
+	bool forcefastclk;	/* true if h/w is forcing to use fast clk */
+	bool clk;		/* core is out of reset and has clock */
+	bool sbclk;		/* sb has clock */
+	bool phyclk;		/* phy is out of reset and has clock */
+
+	bool ucode_loaded;	/* true after ucode downloaded */
+
+
+	u8 hw_stf_ss_opmode;	/* STF single stream operation mode */
+	u8 antsel_type;	/* Type of boardlevel mimo antenna switch-logic
+				 * 0 = N/A, 1 = 2x4 board, 2 = 2x3 CB2 board
+				 */
+	u32 antsel_avail;	/*
+				 * put struct antsel_info here if more info is
+				 * needed
+				 */
+};
+
+/*
+ * Principal common driver data structure.
+ *
+ * pub: pointer to driver public state.
+ * wl: pointer to specific private state.
+ * hw: HW related state.
+ * clkreq_override: setting for clkreq for PCIE : Auto, 0, 1.
+ * fastpwrup_dly: time in us needed to bring up d11 fast clock.
+ * macintstatus: bit channel between isr and dpc.
+ * macintmask: sw runtime master macintmask value.
+ * defmacintmask: default "on" macintmask value.
+ * clk: core is out of reset and has clock.
+ * core: pointer to active io core.
+ * band: pointer to active per-band state.
+ * corestate: per-core state (one per hw core).
+ * bandstate: per-band state (one per phy/radio).
+ * qvalid: DirFrmQValid and BcMcFrmQValid.
+ * ampdu: ampdu module handler.
+ * asi: antsel module handler.
+ * cmi: channel manager module handler.
+ * vendorid: PCI vendor id.
+ * deviceid: PCI device id.
+ * ucode_rev: microcode revision.
+ * machwcap: MAC capabilities, BMAC shadow.
+ * perm_etheraddr: original sprom local ethernet address.
+ * bandlocked: disable auto multi-band switching.
+ * bandinit_pending: track band init in auto band.
+ * radio_monitor: radio timer is running.
+ * going_down: down path intermediate variable.
+ * wdtimer: timer for watchdog routine.
+ * radio_timer: timer for hw radio button monitor routine.
+ * monitor: monitor (MPDU sniffing) mode.
+ * bcnmisc_monitor: bcns promisc mode override for monitor.
+ * _rifs: enable per-packet rifs.
+ * bcn_li_bcn: beacon listen interval in # beacons.
+ * bcn_li_dtim: beacon listen interval in # dtims.
+ * WDarmed: watchdog timer is armed.
+ * WDlast: last time wlc_watchdog() was called.
+ * edcf_txop[IEEE80211_NUM_ACS]: current txop for each ac.
+ * wme_retries: per-AC retry limits.
+ * bsscfg: set of BSS configurations, idx 0 is default and always valid.
+ * cfg: the primary bsscfg (can be AP or STA).
+ * modulecb:
+ * mimoft: SIGN or 11N.
+ * cck_40txbw: 11N, cck tx b/w override when in 40MHZ mode.
+ * ofdm_40txbw: 11N, ofdm tx b/w override when in 40MHZ mode.
+ * mimo_40txbw: 11N, mimo tx b/w override when in 40MHZ mode.
+ * default_bss: configured BSS parameters.
+ * mc_fid_counter: BC/MC FIFO frame ID counter.
+ * country_default: saved country for leaving 802.11d auto-country mode.
+ * autocountry_default: initial country for 802.11d auto-country mode.
+ * prb_resp_timeout: do not send prb resp if request older
+ *		     than this, 0 = disable.
+ * home_chanspec: shared home chanspec.
+ * chanspec: target operational channel.
+ * usr_fragthresh: user configured fragmentation threshold.
+ * fragthresh[NFIFO]: per-fifo fragmentation thresholds.
+ * RTSThresh: 802.11 dot11RTSThreshold.
+ * SRL: 802.11 dot11ShortRetryLimit.
+ * LRL: 802.11 dot11LongRetryLimit.
+ * SFBL: Short Frame Rate Fallback Limit.
+ * LFBL: Long Frame Rate Fallback Limit.
+ * shortslot: currently using 11g ShortSlot timing.
+ * shortslot_override: 11g ShortSlot override.
+ * include_legacy_erp: include Legacy ERP info elt ID 47 as well as g ID 42.
+ * PLCPHdr_override: 802.11b Preamble Type override.
+ * stf:
+ * bcn_rspec: save bcn ratespec purpose.
+ * tempsense_lasttime;
+ * tx_duty_cycle_ofdm: maximum allowed duty cycle for OFDM.
+ * tx_duty_cycle_cck: maximum allowed duty cycle for CCK.
+ * wiphy:
+ * pri_scb: primary Station Control Block
+ */
+struct brcms_c_info {
+	struct brcms_pub *pub;
+	struct brcms_info *wl;
+	struct brcms_hardware *hw;
+
+	/* clock */
+	u16 fastpwrup_dly;
+
+	/* interrupt */
+	u32 macintstatus;
+	u32 macintmask;
+	u32 defmacintmask;
+
+	bool clk;
+
+	/* multiband */
+	struct brcms_core *core;
+	struct brcms_band *band;
+	struct brcms_core *corestate;
+	struct brcms_band *bandstate[MAXBANDS];
+
+	/* packet queue */
+	uint qvalid;
+
+	struct ampdu_info *ampdu;
+	struct antsel_info *asi;
+	struct brcms_cm_info *cmi;
+
+	u16 vendorid;
+	u16 deviceid;
+	uint ucode_rev;
+
+	u8 perm_etheraddr[ETH_ALEN];
+
+	bool bandlocked;
+	bool bandinit_pending;
+
+	bool radio_monitor;
+	bool going_down;
+
+	bool beacon_template_virgin;
+
+	struct brcms_timer *wdtimer;
+	struct brcms_timer *radio_timer;
+
+	/* promiscuous */
+	uint filter_flags;
+
+	/* driver feature */
+	bool _rifs;
+
+	/* AP-STA synchronization, power save */
+	u8 bcn_li_bcn;
+	u8 bcn_li_dtim;
+
+	bool WDarmed;
+	u32 WDlast;
+
+	/* WME */
+	u16 edcf_txop[IEEE80211_NUM_ACS];
+
+	u16 wme_retries[IEEE80211_NUM_ACS];
+
+	struct brcms_bss_cfg *bsscfg;
+
+	struct modulecb *modulecb;
+
+	u8 mimoft;
+	s8 cck_40txbw;
+	s8 ofdm_40txbw;
+	s8 mimo_40txbw;
+
+	struct brcms_bss_info *default_bss;
+
+	u16 mc_fid_counter;
+
+	char country_default[BRCM_CNTRY_BUF_SZ];
+	char autocountry_default[BRCM_CNTRY_BUF_SZ];
+	u16 prb_resp_timeout;
+
+	u16 home_chanspec;
+
+	/* PHY parameters */
+	u16 chanspec;
+	u16 usr_fragthresh;
+	u16 fragthresh[NFIFO];
+	u16 RTSThresh;
+	u16 SRL;
+	u16 LRL;
+	u16 SFBL;
+	u16 LFBL;
+
+	/* network config */
+	bool shortslot;
+	s8 shortslot_override;
+	bool include_legacy_erp;
+
+	struct brcms_protection *protection;
+	s8 PLCPHdr_override;
+
+	struct brcms_stf *stf;
+
+	u32 bcn_rspec;
+
+	uint tempsense_lasttime;
+
+	u16 tx_duty_cycle_ofdm;
+	u16 tx_duty_cycle_cck;
+
+	struct wiphy *wiphy;
+	struct scb pri_scb;
+
+	struct sk_buff *beacon;
+	u16 beacon_tim_offset;
+	u16 beacon_dtim_period;
+	struct sk_buff *probe_resp;
+};
+
+/* antsel module specific state */
+struct antsel_info {
+	struct brcms_c_info *wlc;	/* pointer to main wlc structure */
+	struct brcms_pub *pub;		/* pointer to public fn */
+	u8 antsel_type;	/* Type of boardlevel mimo antenna switch-logic
+				 * 0 = N/A, 1 = 2x4 board, 2 = 2x3 CB2 board
+				 */
+	u8 antsel_antswitch;	/* board level antenna switch type */
+	bool antsel_avail;	/* Ant selection availability (SROM based) */
+	struct brcms_antselcfg antcfg_11n; /* antenna configuration */
+	struct brcms_antselcfg antcfg_cur; /* current antenna config (auto) */
+};
+
+enum brcms_bss_type {
+	BRCMS_TYPE_STATION,
+	BRCMS_TYPE_AP,
+	BRCMS_TYPE_ADHOC,
+};
+
+/*
+ * BSS configuration state
+ *
+ * wlc: wlc to which this bsscfg belongs to.
+ * type: interface type
+ * SSID_len: the length of SSID
+ * SSID: SSID string
+ *
+ *
+ * BSSID: BSSID (associated)
+ * cur_etheraddr: h/w address
+ * flags: BSSCFG flags; see below
+ *
+ * current_bss: BSS parms in ASSOCIATED state
+ *
+ *
+ * ID: 'unique' ID of this bsscfg, assigned at bsscfg allocation
+ */
+struct brcms_bss_cfg {
+	struct brcms_c_info *wlc;
+	enum brcms_bss_type type;
+	u8 SSID_len;
+	u8 SSID[IEEE80211_MAX_SSID_LEN];
+	u8 BSSID[ETH_ALEN];
+	struct brcms_bss_info *current_bss;
+};
+
+int brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p);
+int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
+			   uint *blocks);
+
+int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config);
+void brcms_c_mac_promisc(struct brcms_c_info *wlc, uint filter_flags);
+u16 brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec, uint mac_len);
+u32 brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, u32 rspec,
+			       bool use_rspec, u16 mimo_ctlchbw);
+u16 brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only,
+			       u32 rts_rate, u32 frame_rate,
+			       u8 rts_preamble_type, u8 frame_preamble_type,
+			       uint frame_len, bool ba);
+void brcms_c_inval_dma_pkts(struct brcms_hardware *hw,
+			    struct ieee80211_sta *sta, void (*dma_callback_fn));
+void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend);
+int brcms_c_set_nmode(struct brcms_c_info *wlc);
+void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc, u32 bcn_rate);
+void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, u8 antsel_type);
+void brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, u16 chanspec,
+			  bool mute, struct txpwr_limits *txpwr);
+void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset, u16 v);
+u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset);
+void brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask, u16 val,
+		 int bands);
+void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags);
+void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val);
+void brcms_b_phy_reset(struct brcms_hardware *wlc_hw);
+void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw);
+void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw);
+void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw,
+				     u32 override_bit);
+void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw,
+				       u32 override_bit);
+void brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset,
+				int len, void *buf);
+u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate);
+void brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw, uint offset,
+			   const void *buf, int len, u32 sel);
+void brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset,
+			     void *buf, int len, u32 sel);
+void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode);
+u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw);
+void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk);
+void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk);
+void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on);
+void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant);
+void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, u8 stf_mode);
+void brcms_c_init_scb(struct scb *scb);
+
+#endif				/* _BRCM_MAIN_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_cmn.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_cmn.c
new file mode 100644
index 0000000..35e3b10
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_cmn.c
@@ -0,0 +1,2953 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+
+#include <brcm_hw_ids.h>
+#include <chipcommon.h>
+#include <aiutils.h>
+#include <d11.h>
+#include <phy_shim.h>
+#include "phy_hal.h"
+#include "phy_int.h"
+#include "phy_radio.h"
+#include "phy_lcn.h"
+#include "phyreg_n.h"
+
+#define VALID_N_RADIO(radioid) ((radioid == BCM2055_ID) || \
+				 (radioid == BCM2056_ID) || \
+				 (radioid == BCM2057_ID))
+
+#define VALID_LCN_RADIO(radioid)	(radioid == BCM2064_ID)
+
+#define VALID_RADIO(pi, radioid)        ( \
+		(ISNPHY(pi) ? VALID_N_RADIO(radioid) : false) || \
+		(ISLCNPHY(pi) ? VALID_LCN_RADIO(radioid) : false))
+
+/* basic mux operation - can be optimized on several architectures */
+#define MUX(pred, true, false) ((pred) ? (true) : (false))
+
+/* modulo inc/dec - assumes x E [0, bound - 1] */
+#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1)
+
+/* modulo inc/dec, bound = 2^k */
+#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1))
+#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1))
+
+struct chan_info_basic {
+	u16 chan;
+	u16 freq;
+};
+
+static const struct chan_info_basic chan_info_all[] = {
+	{1, 2412},
+	{2, 2417},
+	{3, 2422},
+	{4, 2427},
+	{5, 2432},
+	{6, 2437},
+	{7, 2442},
+	{8, 2447},
+	{9, 2452},
+	{10, 2457},
+	{11, 2462},
+	{12, 2467},
+	{13, 2472},
+	{14, 2484},
+
+	{34, 5170},
+	{38, 5190},
+	{42, 5210},
+	{46, 5230},
+
+	{36, 5180},
+	{40, 5200},
+	{44, 5220},
+	{48, 5240},
+	{52, 5260},
+	{56, 5280},
+	{60, 5300},
+	{64, 5320},
+
+	{100, 5500},
+	{104, 5520},
+	{108, 5540},
+	{112, 5560},
+	{116, 5580},
+	{120, 5600},
+	{124, 5620},
+	{128, 5640},
+	{132, 5660},
+	{136, 5680},
+	{140, 5700},
+
+	{149, 5745},
+	{153, 5765},
+	{157, 5785},
+	{161, 5805},
+	{165, 5825},
+
+	{184, 4920},
+	{188, 4940},
+	{192, 4960},
+	{196, 4980},
+	{200, 5000},
+	{204, 5020},
+	{208, 5040},
+	{212, 5060},
+	{216, 5080}
+};
+
+static const u8 ofdm_rate_lookup[] = {
+
+	BRCM_RATE_48M,
+	BRCM_RATE_24M,
+	BRCM_RATE_12M,
+	BRCM_RATE_6M,
+	BRCM_RATE_54M,
+	BRCM_RATE_36M,
+	BRCM_RATE_18M,
+	BRCM_RATE_9M
+};
+
+#define PHY_WREG_LIMIT  24
+
+void wlc_phyreg_enter(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+	wlapi_bmac_ucode_wake_override_phyreg_set(pi->sh->physhim);
+}
+
+void wlc_phyreg_exit(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+	wlapi_bmac_ucode_wake_override_phyreg_clear(pi->sh->physhim);
+}
+
+void wlc_radioreg_enter(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+	wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, MCTL_LOCK_RADIO);
+
+	udelay(10);
+}
+
+void wlc_radioreg_exit(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+
+	(void)bcma_read16(pi->d11core, D11REGOFFS(phyversion));
+	pi->phy_wreg = 0;
+	wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, 0);
+}
+
+u16 read_radio_reg(struct brcms_phy *pi, u16 addr)
+{
+	u16 data;
+
+	if (addr == RADIO_IDCODE)
+		return 0xffff;
+
+	switch (pi->pubpi.phy_type) {
+	case PHY_TYPE_N:
+		if (!CONF_HAS(PHYTYPE, PHY_TYPE_N))
+			break;
+		if (NREV_GE(pi->pubpi.phy_rev, 7))
+			addr |= RADIO_2057_READ_OFF;
+		else
+			addr |= RADIO_2055_READ_OFF;
+		break;
+
+	case PHY_TYPE_LCN:
+		if (!CONF_HAS(PHYTYPE, PHY_TYPE_LCN))
+			break;
+		addr |= RADIO_2064_READ_OFF;
+		break;
+
+	default:
+		break;
+	}
+
+	if ((D11REV_GE(pi->sh->corerev, 24)) ||
+	    (D11REV_IS(pi->sh->corerev, 22)
+	     && (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
+		bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), addr);
+		data = bcma_read16(pi->d11core, D11REGOFFS(radioregdata));
+	} else {
+		bcma_wflush16(pi->d11core, D11REGOFFS(phy4waddr), addr);
+		data = bcma_read16(pi->d11core, D11REGOFFS(phy4wdatalo));
+	}
+	pi->phy_wreg = 0;
+
+	return data;
+}
+
+void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
+{
+	if ((D11REV_GE(pi->sh->corerev, 24)) ||
+	    (D11REV_IS(pi->sh->corerev, 22)
+	     && (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
+
+		bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), addr);
+		bcma_write16(pi->d11core, D11REGOFFS(radioregdata), val);
+	} else {
+		bcma_wflush16(pi->d11core, D11REGOFFS(phy4waddr), addr);
+		bcma_write16(pi->d11core, D11REGOFFS(phy4wdatalo), val);
+	}
+
+	if ((pi->d11core->bus->hosttype == BCMA_HOSTTYPE_PCI) &&
+	    (++pi->phy_wreg >= pi->phy_wreg_limit)) {
+		(void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
+		pi->phy_wreg = 0;
+	}
+}
+
+static u32 read_radio_id(struct brcms_phy *pi)
+{
+	u32 id;
+
+	if (D11REV_GE(pi->sh->corerev, 24)) {
+		u32 b0, b1, b2;
+
+		bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), 0);
+		b0 = (u32) bcma_read16(pi->d11core, D11REGOFFS(radioregdata));
+		bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), 1);
+		b1 = (u32) bcma_read16(pi->d11core, D11REGOFFS(radioregdata));
+		bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), 2);
+		b2 = (u32) bcma_read16(pi->d11core, D11REGOFFS(radioregdata));
+
+		id = ((b0 & 0xf) << 28) | (((b2 << 8) | b1) << 12) | ((b0 >> 4)
+								      & 0xf);
+	} else {
+		bcma_wflush16(pi->d11core, D11REGOFFS(phy4waddr), RADIO_IDCODE);
+		id = (u32) bcma_read16(pi->d11core, D11REGOFFS(phy4wdatalo));
+		id |= (u32) bcma_read16(pi->d11core,
+					D11REGOFFS(phy4wdatahi)) << 16;
+	}
+	pi->phy_wreg = 0;
+	return id;
+}
+
+void and_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
+{
+	u16 rval;
+
+	rval = read_radio_reg(pi, addr);
+	write_radio_reg(pi, addr, (rval & val));
+}
+
+void or_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
+{
+	u16 rval;
+
+	rval = read_radio_reg(pi, addr);
+	write_radio_reg(pi, addr, (rval | val));
+}
+
+void xor_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask)
+{
+	u16 rval;
+
+	rval = read_radio_reg(pi, addr);
+	write_radio_reg(pi, addr, (rval ^ mask));
+}
+
+void mod_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val)
+{
+	u16 rval;
+
+	rval = read_radio_reg(pi, addr);
+	write_radio_reg(pi, addr, (rval & ~mask) | (val & mask));
+}
+
+void write_phy_channel_reg(struct brcms_phy *pi, uint val)
+{
+	bcma_write16(pi->d11core, D11REGOFFS(phychannel), val);
+}
+
+u16 read_phy_reg(struct brcms_phy *pi, u16 addr)
+{
+	bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr);
+
+	pi->phy_wreg = 0;
+	return bcma_read16(pi->d11core, D11REGOFFS(phyregdata));
+}
+
+void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
+{
+#ifdef CONFIG_BCM47XX
+	bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr);
+	bcma_write16(pi->d11core, D11REGOFFS(phyregdata), val);
+	if (addr == 0x72)
+		(void)bcma_read16(pi->d11core, D11REGOFFS(phyregdata));
+#else
+	bcma_write32(pi->d11core, D11REGOFFS(phyregaddr), addr | (val << 16));
+	if ((pi->d11core->bus->hosttype == BCMA_HOSTTYPE_PCI) &&
+	    (++pi->phy_wreg >= pi->phy_wreg_limit)) {
+		pi->phy_wreg = 0;
+		(void)bcma_read16(pi->d11core, D11REGOFFS(phyversion));
+	}
+#endif
+}
+
+void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
+{
+	bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr);
+	bcma_mask16(pi->d11core, D11REGOFFS(phyregdata), val);
+	pi->phy_wreg = 0;
+}
+
+void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
+{
+	bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr);
+	bcma_set16(pi->d11core, D11REGOFFS(phyregdata), val);
+	pi->phy_wreg = 0;
+}
+
+void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val)
+{
+	val &= mask;
+	bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr);
+	bcma_maskset16(pi->d11core, D11REGOFFS(phyregdata), ~mask, val);
+	pi->phy_wreg = 0;
+}
+
+static void wlc_set_phy_uninitted(struct brcms_phy *pi)
+{
+	int i, j;
+
+	pi->initialized = false;
+
+	pi->tx_vos = 0xffff;
+	pi->nrssi_table_delta = 0x7fffffff;
+	pi->rc_cal = 0xffff;
+	pi->mintxbias = 0xffff;
+	pi->txpwridx = -1;
+	if (ISNPHY(pi)) {
+		pi->phy_spuravoid = SPURAVOID_DISABLE;
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)
+		    && NREV_LT(pi->pubpi.phy_rev, 7))
+			pi->phy_spuravoid = SPURAVOID_AUTO;
+
+		pi->nphy_papd_skip = 0;
+		pi->nphy_papd_epsilon_offset[0] = 0xf588;
+		pi->nphy_papd_epsilon_offset[1] = 0xf588;
+		pi->nphy_txpwr_idx[0] = 128;
+		pi->nphy_txpwr_idx[1] = 128;
+		pi->nphy_txpwrindex[0].index_internal = 40;
+		pi->nphy_txpwrindex[1].index_internal = 40;
+		pi->phy_pabias = 0;
+	} else {
+		pi->phy_spuravoid = SPURAVOID_AUTO;
+	}
+	pi->radiopwr = 0xffff;
+	for (i = 0; i < STATIC_NUM_RF; i++) {
+		for (j = 0; j < STATIC_NUM_BB; j++)
+			pi->stats_11b_txpower[i][j] = -1;
+	}
+}
+
+struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp)
+{
+	struct shared_phy *sh;
+
+	sh = kzalloc(sizeof(struct shared_phy), GFP_ATOMIC);
+	if (sh == NULL)
+		return NULL;
+
+	sh->physhim = shp->physhim;
+	sh->unit = shp->unit;
+	sh->corerev = shp->corerev;
+
+	sh->vid = shp->vid;
+	sh->did = shp->did;
+	sh->chip = shp->chip;
+	sh->chiprev = shp->chiprev;
+	sh->chippkg = shp->chippkg;
+	sh->sromrev = shp->sromrev;
+	sh->boardtype = shp->boardtype;
+	sh->boardrev = shp->boardrev;
+	sh->boardflags = shp->boardflags;
+	sh->boardflags2 = shp->boardflags2;
+
+	sh->fast_timer = PHY_SW_TIMER_FAST;
+	sh->slow_timer = PHY_SW_TIMER_SLOW;
+	sh->glacial_timer = PHY_SW_TIMER_GLACIAL;
+
+	sh->rssi_mode = RSSI_ANT_MERGE_MAX;
+
+	return sh;
+}
+
+static void wlc_phy_timercb_phycal(struct brcms_phy *pi)
+{
+	uint delay = 5;
+
+	if (PHY_PERICAL_MPHASE_PENDING(pi)) {
+		if (!pi->sh->up) {
+			wlc_phy_cal_perical_mphase_reset(pi);
+			return;
+		}
+
+		if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)) {
+
+			delay = 1000;
+			wlc_phy_cal_perical_mphase_restart(pi);
+		} else
+			wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_AUTO);
+		wlapi_add_timer(pi->phycal_timer, delay, 0);
+		return;
+	}
+
+}
+
+static u32 wlc_phy_get_radio_ver(struct brcms_phy *pi)
+{
+	u32 ver;
+
+	ver = read_radio_id(pi);
+
+	return ver;
+}
+
+struct brcms_phy_pub *
+wlc_phy_attach(struct shared_phy *sh, struct bcma_device *d11core,
+	       int bandtype, struct wiphy *wiphy)
+{
+	struct brcms_phy *pi;
+	u32 sflags = 0;
+	uint phyversion;
+	u32 idcode;
+	int i;
+
+	if (D11REV_IS(sh->corerev, 4))
+		sflags = SISF_2G_PHY | SISF_5G_PHY;
+	else
+		sflags = bcma_aread32(d11core, BCMA_IOST);
+
+	if (bandtype == BRCM_BAND_5G) {
+		if ((sflags & (SISF_5G_PHY | SISF_DB_PHY)) == 0)
+			return NULL;
+	}
+
+	pi = sh->phy_head;
+	if ((sflags & SISF_DB_PHY) && pi) {
+		wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags);
+		pi->refcnt++;
+		return &pi->pubpi_ro;
+	}
+
+	pi = kzalloc(sizeof(struct brcms_phy), GFP_ATOMIC);
+	if (pi == NULL)
+		return NULL;
+	pi->wiphy = wiphy;
+	pi->d11core = d11core;
+	pi->sh = sh;
+	pi->phy_init_por = true;
+	pi->phy_wreg_limit = PHY_WREG_LIMIT;
+
+	pi->txpwr_percent = 100;
+
+	pi->do_initcal = true;
+
+	pi->phycal_tempdelta = 0;
+
+	if (bandtype == BRCM_BAND_2G && (sflags & SISF_2G_PHY))
+		pi->pubpi.coreflags = SICF_GMODE;
+
+	wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags);
+	phyversion = bcma_read16(pi->d11core, D11REGOFFS(phyversion));
+
+	pi->pubpi.phy_type = PHY_TYPE(phyversion);
+	pi->pubpi.phy_rev = phyversion & PV_PV_MASK;
+
+	if (pi->pubpi.phy_type == PHY_TYPE_LCNXN) {
+		pi->pubpi.phy_type = PHY_TYPE_N;
+		pi->pubpi.phy_rev += LCNXN_BASEREV;
+	}
+	pi->pubpi.phy_corenum = PHY_CORE_NUM_2;
+	pi->pubpi.ana_rev = (phyversion & PV_AV_MASK) >> PV_AV_SHIFT;
+
+	if (pi->pubpi.phy_type != PHY_TYPE_N &&
+	    pi->pubpi.phy_type != PHY_TYPE_LCN)
+		goto err;
+
+	if (bandtype == BRCM_BAND_5G) {
+		if (!ISNPHY(pi))
+			goto err;
+	} else if (!ISNPHY(pi) && !ISLCNPHY(pi)) {
+		goto err;
+	}
+
+	wlc_phy_anacore((struct brcms_phy_pub *) pi, ON);
+
+	idcode = wlc_phy_get_radio_ver(pi);
+	pi->pubpi.radioid =
+		(idcode & IDCODE_ID_MASK) >> IDCODE_ID_SHIFT;
+	pi->pubpi.radiorev =
+		(idcode & IDCODE_REV_MASK) >> IDCODE_REV_SHIFT;
+	pi->pubpi.radiover =
+		(idcode & IDCODE_VER_MASK) >> IDCODE_VER_SHIFT;
+	if (!VALID_RADIO(pi, pi->pubpi.radioid))
+		goto err;
+
+	wlc_phy_switch_radio((struct brcms_phy_pub *) pi, OFF);
+
+	wlc_set_phy_uninitted(pi);
+
+	pi->bw = WL_CHANSPEC_BW_20;
+	pi->radio_chanspec = (bandtype == BRCM_BAND_2G) ?
+			     ch20mhz_chspec(1) : ch20mhz_chspec(36);
+
+	pi->rxiq_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY;
+	pi->rxiq_antsel = ANT_RX_DIV_DEF;
+
+	pi->watchdog_override = true;
+
+	pi->cal_type_override = PHY_PERICAL_AUTO;
+
+	pi->nphy_saved_noisevars.bufcount = 0;
+
+	if (ISNPHY(pi))
+		pi->min_txpower = PHY_TXPWR_MIN_NPHY;
+	else
+		pi->min_txpower = PHY_TXPWR_MIN;
+
+	pi->sh->phyrxchain = 0x3;
+
+	pi->rx2tx_biasentry = -1;
+
+	pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP;
+	pi->phy_txcore_enable_temp =
+		PHY_CHAIN_TX_DISABLE_TEMP - PHY_HYSTERESIS_DELTATEMP;
+	pi->phy_tempsense_offset = 0;
+	pi->phy_txcore_heatedup = false;
+
+	pi->nphy_lastcal_temp = -50;
+
+	pi->phynoise_polling = true;
+	if (ISNPHY(pi) || ISLCNPHY(pi))
+		pi->phynoise_polling = false;
+
+	for (i = 0; i < TXP_NUM_RATES; i++) {
+		pi->txpwr_limit[i] = BRCMS_TXPWR_MAX;
+		pi->txpwr_env_limit[i] = BRCMS_TXPWR_MAX;
+		pi->tx_user_target[i] = BRCMS_TXPWR_MAX;
+	}
+
+	pi->radiopwr_override = RADIOPWR_OVERRIDE_DEF;
+
+	pi->user_txpwr_at_rfport = false;
+
+	if (ISNPHY(pi)) {
+
+		pi->phycal_timer = wlapi_init_timer(pi->sh->physhim,
+						    wlc_phy_timercb_phycal,
+						    pi, "phycal");
+		if (!pi->phycal_timer)
+			goto err;
+
+		if (!wlc_phy_attach_nphy(pi))
+			goto err;
+
+	} else if (ISLCNPHY(pi)) {
+		if (!wlc_phy_attach_lcnphy(pi))
+			goto err;
+
+	}
+
+	pi->refcnt++;
+	pi->next = pi->sh->phy_head;
+	sh->phy_head = pi;
+
+	memcpy(&pi->pubpi_ro, &pi->pubpi, sizeof(struct brcms_phy_pub));
+
+	return &pi->pubpi_ro;
+
+err:
+	kfree(pi);
+	return NULL;
+}
+
+void wlc_phy_detach(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+
+	if (pih) {
+		if (--pi->refcnt)
+			return;
+
+		if (pi->phycal_timer) {
+			wlapi_free_timer(pi->phycal_timer);
+			pi->phycal_timer = NULL;
+		}
+
+		if (pi->sh->phy_head == pi)
+			pi->sh->phy_head = pi->next;
+		else if (pi->sh->phy_head->next == pi)
+			pi->sh->phy_head->next = NULL;
+
+		if (pi->pi_fptr.detach)
+			(pi->pi_fptr.detach)(pi);
+
+		kfree(pi);
+	}
+}
+
+bool
+wlc_phy_get_phyversion(struct brcms_phy_pub *pih, u16 *phytype, u16 *phyrev,
+		       u16 *radioid, u16 *radiover)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+	*phytype = (u16) pi->pubpi.phy_type;
+	*phyrev = (u16) pi->pubpi.phy_rev;
+	*radioid = pi->pubpi.radioid;
+	*radiover = pi->pubpi.radiorev;
+
+	return true;
+}
+
+bool wlc_phy_get_encore(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+	return pi->pubpi.abgphy_encore;
+}
+
+u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+	return pi->pubpi.coreflags;
+}
+
+void wlc_phy_anacore(struct brcms_phy_pub *pih, bool on)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+
+	if (ISNPHY(pi)) {
+		if (on) {
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				write_phy_reg(pi, 0xa6, 0x0d);
+				write_phy_reg(pi, 0x8f, 0x0);
+				write_phy_reg(pi, 0xa7, 0x0d);
+				write_phy_reg(pi, 0xa5, 0x0);
+			} else {
+				write_phy_reg(pi, 0xa5, 0x0);
+			}
+		} else {
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				write_phy_reg(pi, 0x8f, 0x07ff);
+				write_phy_reg(pi, 0xa6, 0x0fd);
+				write_phy_reg(pi, 0xa5, 0x07ff);
+				write_phy_reg(pi, 0xa7, 0x0fd);
+			} else {
+				write_phy_reg(pi, 0xa5, 0x7fff);
+			}
+		}
+	} else if (ISLCNPHY(pi)) {
+		if (on) {
+			and_phy_reg(pi, 0x43b,
+				    ~((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
+		} else {
+			or_phy_reg(pi, 0x43c,
+				   (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
+			or_phy_reg(pi, 0x43b,
+				   (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
+		}
+	}
+}
+
+u32 wlc_phy_clk_bwbits(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+
+	u32 phy_bw_clkbits = 0;
+
+	if (pi && (ISNPHY(pi) || ISLCNPHY(pi))) {
+		switch (pi->bw) {
+		case WL_CHANSPEC_BW_10:
+			phy_bw_clkbits = SICF_BW10;
+			break;
+		case WL_CHANSPEC_BW_20:
+			phy_bw_clkbits = SICF_BW20;
+			break;
+		case WL_CHANSPEC_BW_40:
+			phy_bw_clkbits = SICF_BW40;
+			break;
+		default:
+			break;
+		}
+	}
+
+	return phy_bw_clkbits;
+}
+
+void wlc_phy_por_inform(struct brcms_phy_pub *ppi)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+
+	pi->phy_init_por = true;
+}
+
+void wlc_phy_edcrs_lock(struct brcms_phy_pub *pih, bool lock)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+
+	pi->edcrs_threshold_lock = lock;
+
+	write_phy_reg(pi, 0x22c, 0x46b);
+	write_phy_reg(pi, 0x22d, 0x46b);
+	write_phy_reg(pi, 0x22e, 0x3c0);
+	write_phy_reg(pi, 0x22f, 0x3c0);
+}
+
+void wlc_phy_initcal_enable(struct brcms_phy_pub *pih, bool initcal)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+
+	pi->do_initcal = initcal;
+}
+
+void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub *pih, bool newstate)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+
+	if (!pi || !pi->sh)
+		return;
+
+	pi->sh->clk = newstate;
+}
+
+void wlc_phy_hw_state_upd(struct brcms_phy_pub *pih, bool newstate)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+
+	if (!pi || !pi->sh)
+		return;
+
+	pi->sh->up = newstate;
+}
+
+void wlc_phy_init(struct brcms_phy_pub *pih, u16 chanspec)
+{
+	u32 mc;
+	void (*phy_init)(struct brcms_phy *) = NULL;
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+
+	if (pi->init_in_progress)
+		return;
+
+	pi->init_in_progress = true;
+
+	pi->radio_chanspec = chanspec;
+
+	mc = bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
+	if (WARN(mc & MCTL_EN_MAC, "HW error MAC running on init"))
+		return;
+
+	if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN))
+		pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
+
+	if (WARN(!(bcma_aread32(pi->d11core, BCMA_IOST) & SISF_FCLKA),
+		 "HW error SISF_FCLKA\n"))
+		return;
+
+	phy_init = pi->pi_fptr.init;
+
+	if (phy_init == NULL)
+		return;
+
+	wlc_phy_anacore(pih, ON);
+
+	if (CHSPEC_BW(pi->radio_chanspec) != pi->bw)
+		wlapi_bmac_bw_set(pi->sh->physhim,
+				  CHSPEC_BW(pi->radio_chanspec));
+
+	pi->nphy_gain_boost = true;
+
+	wlc_phy_switch_radio((struct brcms_phy_pub *) pi, ON);
+
+	(*phy_init)(pi);
+
+	pi->phy_init_por = false;
+
+	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
+		wlc_phy_do_dummy_tx(pi, true, OFF);
+
+	if (!(ISNPHY(pi)))
+		wlc_phy_txpower_update_shm(pi);
+
+	wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi, pi->sh->rx_antdiv);
+
+	pi->init_in_progress = false;
+}
+
+void wlc_phy_cal_init(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+	void (*cal_init)(struct brcms_phy *) = NULL;
+
+	if (WARN((bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
+		  MCTL_EN_MAC) != 0, "HW error: MAC enabled during phy cal\n"))
+		return;
+
+	if (!pi->initialized) {
+		cal_init = pi->pi_fptr.calinit;
+		if (cal_init)
+			(*cal_init)(pi);
+
+		pi->initialized = true;
+	}
+}
+
+int wlc_phy_down(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+	int callbacks = 0;
+
+	if (pi->phycal_timer
+	    && !wlapi_del_timer(pi->phycal_timer))
+		callbacks++;
+
+	pi->nphy_iqcal_chanspec_2G = 0;
+	pi->nphy_iqcal_chanspec_5G = 0;
+
+	return callbacks;
+}
+
+void
+wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, uint tbl_offset,
+		   u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
+{
+	write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
+
+	pi->tbl_data_hi = tblDataHi;
+	pi->tbl_data_lo = tblDataLo;
+
+	if (pi->sh->chip == BCMA_CHIP_ID_BCM43224 &&
+	    pi->sh->chiprev == 1) {
+		pi->tbl_addr = tblAddr;
+		pi->tbl_save_id = tbl_id;
+		pi->tbl_save_offset = tbl_offset;
+	}
+}
+
+void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val)
+{
+	if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) &&
+	    (pi->sh->chiprev == 1) &&
+	    (pi->tbl_save_id == NPHY_TBL_ID_ANTSWCTRLLUT)) {
+		read_phy_reg(pi, pi->tbl_data_lo);
+
+		write_phy_reg(pi, pi->tbl_addr,
+			      (pi->tbl_save_id << 10) | pi->tbl_save_offset);
+		pi->tbl_save_offset++;
+	}
+
+	if (width == 32) {
+		write_phy_reg(pi, pi->tbl_data_hi, (u16) (val >> 16));
+		write_phy_reg(pi, pi->tbl_data_lo, (u16) val);
+	} else {
+		write_phy_reg(pi, pi->tbl_data_lo, (u16) val);
+	}
+}
+
+void
+wlc_phy_write_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info,
+		    u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
+{
+	uint idx;
+	uint tbl_id = ptbl_info->tbl_id;
+	uint tbl_offset = ptbl_info->tbl_offset;
+	uint tbl_width = ptbl_info->tbl_width;
+	const u8 *ptbl_8b = (const u8 *)ptbl_info->tbl_ptr;
+	const u16 *ptbl_16b = (const u16 *)ptbl_info->tbl_ptr;
+	const u32 *ptbl_32b = (const u32 *)ptbl_info->tbl_ptr;
+
+	write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
+
+	for (idx = 0; idx < ptbl_info->tbl_len; idx++) {
+
+		if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) &&
+		    (pi->sh->chiprev == 1) &&
+		    (tbl_id == NPHY_TBL_ID_ANTSWCTRLLUT)) {
+			read_phy_reg(pi, tblDataLo);
+
+			write_phy_reg(pi, tblAddr,
+				      (tbl_id << 10) | (tbl_offset + idx));
+		}
+
+		if (tbl_width == 32) {
+			write_phy_reg(pi, tblDataHi,
+				      (u16) (ptbl_32b[idx] >> 16));
+			write_phy_reg(pi, tblDataLo, (u16) ptbl_32b[idx]);
+		} else if (tbl_width == 16) {
+			write_phy_reg(pi, tblDataLo, ptbl_16b[idx]);
+		} else {
+			write_phy_reg(pi, tblDataLo, ptbl_8b[idx]);
+		}
+	}
+}
+
+void
+wlc_phy_read_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info,
+		   u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
+{
+	uint idx;
+	uint tbl_id = ptbl_info->tbl_id;
+	uint tbl_offset = ptbl_info->tbl_offset;
+	uint tbl_width = ptbl_info->tbl_width;
+	u8 *ptbl_8b = (u8 *)ptbl_info->tbl_ptr;
+	u16 *ptbl_16b = (u16 *)ptbl_info->tbl_ptr;
+	u32 *ptbl_32b = (u32 *)ptbl_info->tbl_ptr;
+
+	write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
+
+	for (idx = 0; idx < ptbl_info->tbl_len; idx++) {
+
+		if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) &&
+		    (pi->sh->chiprev == 1)) {
+			(void)read_phy_reg(pi, tblDataLo);
+
+			write_phy_reg(pi, tblAddr,
+				      (tbl_id << 10) | (tbl_offset + idx));
+		}
+
+		if (tbl_width == 32) {
+			ptbl_32b[idx] = read_phy_reg(pi, tblDataLo);
+			ptbl_32b[idx] |= (read_phy_reg(pi, tblDataHi) << 16);
+		} else if (tbl_width == 16) {
+			ptbl_16b[idx] = read_phy_reg(pi, tblDataLo);
+		} else {
+			ptbl_8b[idx] = (u8) read_phy_reg(pi, tblDataLo);
+		}
+	}
+}
+
+uint
+wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi,
+				 struct radio_20xx_regs *radioregs)
+{
+	uint i = 0;
+
+	do {
+		if (radioregs[i].do_init)
+			write_radio_reg(pi, radioregs[i].address,
+					(u16) radioregs[i].init);
+
+		i++;
+	} while (radioregs[i].address != 0xffff);
+
+	return i;
+}
+
+uint
+wlc_phy_init_radio_regs(struct brcms_phy *pi,
+			const struct radio_regs *radioregs,
+			u16 core_offset)
+{
+	uint i = 0;
+	uint count = 0;
+
+	do {
+		if (CHSPEC_IS5G(pi->radio_chanspec)) {
+			if (radioregs[i].do_init_a) {
+				write_radio_reg(pi,
+						radioregs[i].
+						address | core_offset,
+						(u16) radioregs[i].init_a);
+				if (ISNPHY(pi) && (++count % 4 == 0))
+					BRCMS_PHY_WAR_PR51571(pi);
+			}
+		} else {
+			if (radioregs[i].do_init_g) {
+				write_radio_reg(pi,
+						radioregs[i].
+						address | core_offset,
+						(u16) radioregs[i].init_g);
+				if (ISNPHY(pi) && (++count % 4 == 0))
+					BRCMS_PHY_WAR_PR51571(pi);
+			}
+		}
+
+		i++;
+	} while (radioregs[i].address != 0xffff);
+
+	return i;
+}
+
+void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on)
+{
+#define DUMMY_PKT_LEN   20
+	struct bcma_device *core = pi->d11core;
+	int i, count;
+	u8 ofdmpkt[DUMMY_PKT_LEN] = {
+		0xcc, 0x01, 0x02, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
+	};
+	u8 cckpkt[DUMMY_PKT_LEN] = {
+		0x6e, 0x84, 0x0b, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
+	};
+	u32 *dummypkt;
+
+	dummypkt = (u32 *) (ofdm ? ofdmpkt : cckpkt);
+	wlapi_bmac_write_template_ram(pi->sh->physhim, 0, DUMMY_PKT_LEN,
+				      dummypkt);
+
+	bcma_write16(core, D11REGOFFS(xmtsel), 0);
+
+	if (D11REV_GE(pi->sh->corerev, 11))
+		bcma_write16(core, D11REGOFFS(wepctl), 0x100);
+	else
+		bcma_write16(core, D11REGOFFS(wepctl), 0);
+
+	bcma_write16(core, D11REGOFFS(txe_phyctl),
+		     (ofdm ? 1 : 0) | PHY_TXC_ANT_0);
+	if (ISNPHY(pi) || ISLCNPHY(pi))
+		bcma_write16(core, D11REGOFFS(txe_phyctl1), 0x1A02);
+
+	bcma_write16(core, D11REGOFFS(txe_wm_0), 0);
+	bcma_write16(core, D11REGOFFS(txe_wm_1), 0);
+
+	bcma_write16(core, D11REGOFFS(xmttplatetxptr), 0);
+	bcma_write16(core, D11REGOFFS(xmttxcnt), DUMMY_PKT_LEN);
+
+	bcma_write16(core, D11REGOFFS(xmtsel),
+		     ((8 << 8) | (1 << 5) | (1 << 2) | 2));
+
+	bcma_write16(core, D11REGOFFS(txe_ctl), 0);
+
+	if (!pa_on) {
+		if (ISNPHY(pi))
+			wlc_phy_pa_override_nphy(pi, OFF);
+	}
+
+	if (ISNPHY(pi) || ISLCNPHY(pi))
+		bcma_write16(core, D11REGOFFS(txe_aux), 0xD0);
+	else
+		bcma_write16(core, D11REGOFFS(txe_aux), ((1 << 5) | (1 << 4)));
+
+	(void)bcma_read16(core, D11REGOFFS(txe_aux));
+
+	i = 0;
+	count = ofdm ? 30 : 250;
+	while ((i++ < count)
+	       && (bcma_read16(core, D11REGOFFS(txe_status)) & (1 << 7)))
+		udelay(10);
+
+	i = 0;
+
+	while ((i++ < 10) &&
+	       ((bcma_read16(core, D11REGOFFS(txe_status)) & (1 << 10)) == 0))
+		udelay(10);
+
+	i = 0;
+
+	while ((i++ < 10) &&
+	       ((bcma_read16(core, D11REGOFFS(ifsstat)) & (1 << 8))))
+		udelay(10);
+
+	if (!pa_on) {
+		if (ISNPHY(pi))
+			wlc_phy_pa_override_nphy(pi, ON);
+	}
+}
+
+void wlc_phy_hold_upd(struct brcms_phy_pub *pih, u32 id, bool set)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+
+	if (set)
+		mboolset(pi->measure_hold, id);
+	else
+		mboolclr(pi->measure_hold, id);
+
+	return;
+}
+
+void wlc_phy_mute_upd(struct brcms_phy_pub *pih, bool mute, u32 flags)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+
+	if (mute)
+		mboolset(pi->measure_hold, PHY_HOLD_FOR_MUTE);
+	else
+		mboolclr(pi->measure_hold, PHY_HOLD_FOR_MUTE);
+
+	if (!mute && (flags & PHY_MUTE_FOR_PREISM))
+		pi->nphy_perical_last = pi->sh->now - pi->sh->glacial_timer;
+	return;
+}
+
+void wlc_phy_clear_tssi(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+
+	if (ISNPHY(pi)) {
+		return;
+	} else {
+		wlapi_bmac_write_shm(pi->sh->physhim, M_B_TSSI_0, NULL_TSSI_W);
+		wlapi_bmac_write_shm(pi->sh->physhim, M_B_TSSI_1, NULL_TSSI_W);
+		wlapi_bmac_write_shm(pi->sh->physhim, M_G_TSSI_0, NULL_TSSI_W);
+		wlapi_bmac_write_shm(pi->sh->physhim, M_G_TSSI_1, NULL_TSSI_W);
+	}
+}
+
+static bool wlc_phy_cal_txpower_recalc_sw(struct brcms_phy *pi)
+{
+	return false;
+}
+
+void wlc_phy_switch_radio(struct brcms_phy_pub *pih, bool on)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+	(void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
+
+	if (ISNPHY(pi)) {
+		wlc_phy_switch_radio_nphy(pi, on);
+	} else if (ISLCNPHY(pi)) {
+		if (on) {
+			and_phy_reg(pi, 0x44c,
+				    ~((0x1 << 8) |
+				      (0x1 << 9) |
+				      (0x1 << 10) | (0x1 << 11) | (0x1 << 12)));
+			and_phy_reg(pi, 0x4b0, ~((0x1 << 3) | (0x1 << 11)));
+			and_phy_reg(pi, 0x4f9, ~(0x1 << 3));
+		} else {
+			and_phy_reg(pi, 0x44d,
+				    ~((0x1 << 10) |
+				      (0x1 << 11) |
+				      (0x1 << 12) | (0x1 << 13) | (0x1 << 14)));
+			or_phy_reg(pi, 0x44c,
+				   (0x1 << 8) |
+				   (0x1 << 9) |
+				   (0x1 << 10) | (0x1 << 11) | (0x1 << 12));
+
+			and_phy_reg(pi, 0x4b7, ~((0x7f << 8)));
+			and_phy_reg(pi, 0x4b1, ~((0x1 << 13)));
+			or_phy_reg(pi, 0x4b0, (0x1 << 3) | (0x1 << 11));
+			and_phy_reg(pi, 0x4fa, ~((0x1 << 3)));
+			or_phy_reg(pi, 0x4f9, (0x1 << 3));
+		}
+	}
+}
+
+u16 wlc_phy_bw_state_get(struct brcms_phy_pub *ppi)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+
+	return pi->bw;
+}
+
+void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+
+	pi->bw = bw;
+}
+
+void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, u16 newch)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+	pi->radio_chanspec = newch;
+
+}
+
+u16 wlc_phy_chanspec_get(struct brcms_phy_pub *ppi)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+
+	return pi->radio_chanspec;
+}
+
+void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, u16 chanspec)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+	u16 m_cur_channel;
+	void (*chanspec_set)(struct brcms_phy *, u16) = NULL;
+	m_cur_channel = CHSPEC_CHANNEL(chanspec);
+	if (CHSPEC_IS5G(chanspec))
+		m_cur_channel |= D11_CURCHANNEL_5G;
+	if (CHSPEC_IS40(chanspec))
+		m_cur_channel |= D11_CURCHANNEL_40;
+	wlapi_bmac_write_shm(pi->sh->physhim, M_CURCHANNEL, m_cur_channel);
+
+	chanspec_set = pi->pi_fptr.chanset;
+	if (chanspec_set)
+		(*chanspec_set)(pi, chanspec);
+
+}
+
+int wlc_phy_chanspec_freq2bandrange_lpssn(uint freq)
+{
+	int range = -1;
+
+	if (freq < 2500)
+		range = WL_CHAN_FREQ_RANGE_2G;
+	else if (freq <= 5320)
+		range = WL_CHAN_FREQ_RANGE_5GL;
+	else if (freq <= 5700)
+		range = WL_CHAN_FREQ_RANGE_5GM;
+	else
+		range = WL_CHAN_FREQ_RANGE_5GH;
+
+	return range;
+}
+
+int wlc_phy_chanspec_bandrange_get(struct brcms_phy *pi, u16 chanspec)
+{
+	int range = -1;
+	uint channel = CHSPEC_CHANNEL(chanspec);
+	uint freq = wlc_phy_channel2freq(channel);
+
+	if (ISNPHY(pi))
+		range = wlc_phy_get_chan_freq_range_nphy(pi, channel);
+	else if (ISLCNPHY(pi))
+		range = wlc_phy_chanspec_freq2bandrange_lpssn(freq);
+
+	return range;
+}
+
+void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub *ppi,
+					  bool wide_filter)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+
+	pi->channel_14_wide_filter = wide_filter;
+
+}
+
+int wlc_phy_channel2freq(uint channel)
+{
+	uint i;
+
+	for (i = 0; i < ARRAY_SIZE(chan_info_all); i++)
+		if (chan_info_all[i].chan == channel)
+			return chan_info_all[i].freq;
+	return 0;
+}
+
+void
+wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band,
+			      struct brcms_chanvec *channels)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+	uint i;
+	uint channel;
+
+	memset(channels, 0, sizeof(struct brcms_chanvec));
+
+	for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
+		channel = chan_info_all[i].chan;
+
+		if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM)
+		    && (channel <= LAST_REF5_CHANNUM))
+			continue;
+
+		if ((band == BRCM_BAND_2G && channel <= CH_MAX_2G_CHANNEL) ||
+		    (band == BRCM_BAND_5G && channel > CH_MAX_2G_CHANNEL))
+			setbit(channels->vec, channel);
+	}
+}
+
+u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+	uint i;
+	uint channel;
+	u16 chspec;
+
+	for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
+		channel = chan_info_all[i].chan;
+
+		if (ISNPHY(pi) && pi->bw == WL_CHANSPEC_BW_40) {
+			uint j;
+
+			for (j = 0; j < ARRAY_SIZE(chan_info_all); j++) {
+				if (chan_info_all[j].chan ==
+				    channel + CH_10MHZ_APART)
+					break;
+			}
+
+			if (j == ARRAY_SIZE(chan_info_all))
+				continue;
+
+			channel = upper_20_sb(channel);
+			chspec =  channel | WL_CHANSPEC_BW_40 |
+				  WL_CHANSPEC_CTL_SB_LOWER;
+			if (band == BRCM_BAND_2G)
+				chspec |= WL_CHANSPEC_BAND_2G;
+			else
+				chspec |= WL_CHANSPEC_BAND_5G;
+		} else
+			chspec = ch20mhz_chspec(channel);
+
+		if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM)
+		    && (channel <= LAST_REF5_CHANNUM))
+			continue;
+
+		if ((band == BRCM_BAND_2G && channel <= CH_MAX_2G_CHANNEL) ||
+		    (band == BRCM_BAND_5G && channel > CH_MAX_2G_CHANNEL))
+			return chspec;
+	}
+
+	return (u16) INVCHANSPEC;
+}
+
+int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm, bool *override)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+
+	*qdbm = pi->tx_user_target[0];
+	if (override != NULL)
+		*override = pi->txpwroverride;
+	return 0;
+}
+
+void wlc_phy_txpower_target_set(struct brcms_phy_pub *ppi,
+				struct txpwr_limits *txpwr)
+{
+	bool mac_enabled = false;
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+
+	memcpy(&pi->tx_user_target[TXP_FIRST_CCK],
+	       &txpwr->cck[0], BRCMS_NUM_RATES_CCK);
+
+	memcpy(&pi->tx_user_target[TXP_FIRST_OFDM],
+	       &txpwr->ofdm[0], BRCMS_NUM_RATES_OFDM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_20_CDD],
+	       &txpwr->ofdm_cdd[0], BRCMS_NUM_RATES_OFDM);
+
+	memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_40_SISO],
+	       &txpwr->ofdm_40_siso[0], BRCMS_NUM_RATES_OFDM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_40_CDD],
+	       &txpwr->ofdm_40_cdd[0], BRCMS_NUM_RATES_OFDM);
+
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_SISO],
+	       &txpwr->mcs_20_siso[0], BRCMS_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_CDD],
+	       &txpwr->mcs_20_cdd[0], BRCMS_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_STBC],
+	       &txpwr->mcs_20_stbc[0], BRCMS_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_SDM],
+	       &txpwr->mcs_20_mimo[0], BRCMS_NUM_RATES_MCS_2_STREAM);
+
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SISO],
+	       &txpwr->mcs_40_siso[0], BRCMS_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_CDD],
+	       &txpwr->mcs_40_cdd[0], BRCMS_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_STBC],
+	       &txpwr->mcs_40_stbc[0], BRCMS_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SDM],
+	       &txpwr->mcs_40_mimo[0], BRCMS_NUM_RATES_MCS_2_STREAM);
+
+	if (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & MCTL_EN_MAC)
+		mac_enabled = true;
+
+	if (mac_enabled)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	wlc_phy_txpower_recalc_target(pi);
+	wlc_phy_cal_txpower_recalc_sw(pi);
+
+	if (mac_enabled)
+		wlapi_enable_mac(pi->sh->physhim);
+}
+
+int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, bool override)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+	int i;
+
+	if (qdbm > 127)
+		return -EINVAL;
+
+	for (i = 0; i < TXP_NUM_RATES; i++)
+		pi->tx_user_target[i] = (u8) qdbm;
+
+	pi->txpwroverride = false;
+
+	if (pi->sh->up) {
+		if (!SCAN_INPROG_PHY(pi)) {
+			bool suspend;
+
+			suspend = (0 == (bcma_read32(pi->d11core,
+						     D11REGOFFS(maccontrol)) &
+					 MCTL_EN_MAC));
+
+			if (!suspend)
+				wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+			wlc_phy_txpower_recalc_target(pi);
+			wlc_phy_cal_txpower_recalc_sw(pi);
+
+			if (!suspend)
+				wlapi_enable_mac(pi->sh->physhim);
+		}
+	}
+	return 0;
+}
+
+void
+wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint channel, u8 *min_pwr,
+			  u8 *max_pwr, int txp_rate_idx)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+	uint i;
+
+	*min_pwr = pi->min_txpower * BRCMS_TXPWR_DB_FACTOR;
+
+	if (ISNPHY(pi)) {
+		if (txp_rate_idx < 0)
+			txp_rate_idx = TXP_FIRST_CCK;
+		wlc_phy_txpower_sromlimit_get_nphy(pi, channel, max_pwr,
+						   (u8) txp_rate_idx);
+
+	} else if ((channel <= CH_MAX_2G_CHANNEL)) {
+		if (txp_rate_idx < 0)
+			txp_rate_idx = TXP_FIRST_CCK;
+		*max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx];
+	} else {
+
+		*max_pwr = BRCMS_TXPWR_MAX;
+
+		if (txp_rate_idx < 0)
+			txp_rate_idx = TXP_FIRST_OFDM;
+
+		for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
+			if (channel == chan_info_all[i].chan)
+				break;
+		}
+
+		if (pi->hwtxpwr) {
+			*max_pwr = pi->hwtxpwr[i];
+		} else {
+
+			if ((i >= FIRST_MID_5G_CHAN) && (i <= LAST_MID_5G_CHAN))
+				*max_pwr =
+				    pi->tx_srom_max_rate_5g_mid[txp_rate_idx];
+			if ((i >= FIRST_HIGH_5G_CHAN)
+			    && (i <= LAST_HIGH_5G_CHAN))
+				*max_pwr =
+				    pi->tx_srom_max_rate_5g_hi[txp_rate_idx];
+			if ((i >= FIRST_LOW_5G_CHAN) && (i <= LAST_LOW_5G_CHAN))
+				*max_pwr =
+				    pi->tx_srom_max_rate_5g_low[txp_rate_idx];
+		}
+	}
+}
+
+void
+wlc_phy_txpower_sromlimit_max_get(struct brcms_phy_pub *ppi, uint chan,
+				  u8 *max_txpwr, u8 *min_txpwr)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+	u8 tx_pwr_max = 0;
+	u8 tx_pwr_min = 255;
+	u8 max_num_rate;
+	u8 maxtxpwr, mintxpwr, rate, pactrl;
+
+	pactrl = 0;
+
+	max_num_rate = ISNPHY(pi) ? TXP_NUM_RATES :
+		       ISLCNPHY(pi) ? (TXP_LAST_SISO_MCS_20 +
+				       1) : (TXP_LAST_OFDM + 1);
+
+	for (rate = 0; rate < max_num_rate; rate++) {
+
+		wlc_phy_txpower_sromlimit(ppi, chan, &mintxpwr, &maxtxpwr,
+					  rate);
+
+		maxtxpwr = (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0;
+
+		maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0;
+
+		tx_pwr_max = max(tx_pwr_max, maxtxpwr);
+		tx_pwr_min = min(tx_pwr_min, maxtxpwr);
+	}
+	*max_txpwr = tx_pwr_max;
+	*min_txpwr = tx_pwr_min;
+}
+
+void
+wlc_phy_txpower_boardlimit_band(struct brcms_phy_pub *ppi, uint bandunit,
+				s32 *max_pwr, s32 *min_pwr, u32 *step_pwr)
+{
+	return;
+}
+
+u8 wlc_phy_txpower_get_target_min(struct brcms_phy_pub *ppi)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+
+	return pi->tx_power_min;
+}
+
+u8 wlc_phy_txpower_get_target_max(struct brcms_phy_pub *ppi)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+
+	return pi->tx_power_max;
+}
+
+static s8 wlc_phy_env_measure_vbat(struct brcms_phy *pi)
+{
+	if (ISLCNPHY(pi))
+		return wlc_lcnphy_vbatsense(pi, 0);
+	else
+		return 0;
+}
+
+static s8 wlc_phy_env_measure_temperature(struct brcms_phy *pi)
+{
+	if (ISLCNPHY(pi))
+		return wlc_lcnphy_tempsense_degree(pi, 0);
+	else
+		return 0;
+}
+
+static void wlc_phy_upd_env_txpwr_rate_limits(struct brcms_phy *pi, u32 band)
+{
+	u8 i;
+	s8 temp, vbat;
+
+	for (i = 0; i < TXP_NUM_RATES; i++)
+		pi->txpwr_env_limit[i] = BRCMS_TXPWR_MAX;
+
+	vbat = wlc_phy_env_measure_vbat(pi);
+	temp = wlc_phy_env_measure_temperature(pi);
+
+}
+
+static s8
+wlc_user_txpwr_antport_to_rfport(struct brcms_phy *pi, uint chan, u32 band,
+				 u8 rate)
+{
+	return 0;
+}
+
+void wlc_phy_txpower_recalc_target(struct brcms_phy *pi)
+{
+	u8 maxtxpwr, mintxpwr, rate, pactrl;
+	uint target_chan;
+	u8 tx_pwr_target[TXP_NUM_RATES];
+	u8 tx_pwr_max = 0;
+	u8 tx_pwr_min = 255;
+	u8 tx_pwr_max_rate_ind = 0;
+	u8 max_num_rate;
+	u8 start_rate = 0;
+	u16 chspec;
+	u32 band = CHSPEC2BAND(pi->radio_chanspec);
+	void (*txpwr_recalc_fn)(struct brcms_phy *) = NULL;
+
+	chspec = pi->radio_chanspec;
+	if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE)
+		target_chan = CHSPEC_CHANNEL(chspec);
+	else if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER)
+		target_chan = upper_20_sb(CHSPEC_CHANNEL(chspec));
+	else
+		target_chan = lower_20_sb(CHSPEC_CHANNEL(chspec));
+
+	pactrl = 0;
+	if (ISLCNPHY(pi)) {
+		u32 offset_mcs, i;
+
+		if (CHSPEC_IS40(pi->radio_chanspec)) {
+			offset_mcs = pi->mcs40_po;
+			for (i = TXP_FIRST_SISO_MCS_20;
+			     i <= TXP_LAST_SISO_MCS_20; i++) {
+				pi->tx_srom_max_rate_2g[i - 8] =
+					pi->tx_srom_max_2g -
+					((offset_mcs & 0xf) * 2);
+				offset_mcs >>= 4;
+			}
+		} else {
+			offset_mcs = pi->mcs20_po;
+			for (i = TXP_FIRST_SISO_MCS_20;
+			     i <= TXP_LAST_SISO_MCS_20; i++) {
+				pi->tx_srom_max_rate_2g[i - 8] =
+					pi->tx_srom_max_2g -
+					((offset_mcs & 0xf) * 2);
+				offset_mcs >>= 4;
+			}
+		}
+	}
+
+	max_num_rate = ((ISNPHY(pi)) ? (TXP_NUM_RATES) :
+			((ISLCNPHY(pi)) ?
+			 (TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1)));
+
+	wlc_phy_upd_env_txpwr_rate_limits(pi, band);
+
+	for (rate = start_rate; rate < max_num_rate; rate++) {
+
+		tx_pwr_target[rate] = pi->tx_user_target[rate];
+
+		if (pi->user_txpwr_at_rfport)
+			tx_pwr_target[rate] +=
+				wlc_user_txpwr_antport_to_rfport(pi,
+								 target_chan,
+								 band,
+								 rate);
+
+		wlc_phy_txpower_sromlimit((struct brcms_phy_pub *) pi,
+					  target_chan,
+					  &mintxpwr, &maxtxpwr, rate);
+
+		maxtxpwr = min(maxtxpwr, pi->txpwr_limit[rate]);
+
+		maxtxpwr = (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0;
+
+		maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0;
+
+		maxtxpwr = min(maxtxpwr, tx_pwr_target[rate]);
+
+		if (pi->txpwr_percent <= 100)
+			maxtxpwr = (maxtxpwr * pi->txpwr_percent) / 100;
+
+		tx_pwr_target[rate] = max(maxtxpwr, mintxpwr);
+
+		tx_pwr_target[rate] =
+			min(tx_pwr_target[rate], pi->txpwr_env_limit[rate]);
+
+		if (tx_pwr_target[rate] > tx_pwr_max)
+			tx_pwr_max_rate_ind = rate;
+
+		tx_pwr_max = max(tx_pwr_max, tx_pwr_target[rate]);
+		tx_pwr_min = min(tx_pwr_min, tx_pwr_target[rate]);
+	}
+
+	memset(pi->tx_power_offset, 0, sizeof(pi->tx_power_offset));
+	pi->tx_power_max = tx_pwr_max;
+	pi->tx_power_min = tx_pwr_min;
+	pi->tx_power_max_rate_ind = tx_pwr_max_rate_ind;
+	for (rate = 0; rate < max_num_rate; rate++) {
+
+		pi->tx_power_target[rate] = tx_pwr_target[rate];
+
+		if (!pi->hwpwrctrl || ISNPHY(pi))
+			pi->tx_power_offset[rate] =
+				pi->tx_power_max - pi->tx_power_target[rate];
+		else
+			pi->tx_power_offset[rate] =
+				pi->tx_power_target[rate] - pi->tx_power_min;
+	}
+
+	txpwr_recalc_fn = pi->pi_fptr.txpwrrecalc;
+	if (txpwr_recalc_fn)
+		(*txpwr_recalc_fn)(pi);
+}
+
+static void
+wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr,
+			       u16 chanspec)
+{
+	u8 tmp_txpwr_limit[2 * BRCMS_NUM_RATES_OFDM];
+	u8 *txpwr_ptr1 = NULL, *txpwr_ptr2 = NULL;
+	int rate_start_index = 0, rate1, rate2, k;
+
+	for (rate1 = WL_TX_POWER_CCK_FIRST, rate2 = 0;
+	     rate2 < WL_TX_POWER_CCK_NUM; rate1++, rate2++)
+		pi->txpwr_limit[rate1] = txpwr->cck[rate2];
+
+	for (rate1 = WL_TX_POWER_OFDM_FIRST, rate2 = 0;
+	     rate2 < WL_TX_POWER_OFDM_NUM; rate1++, rate2++)
+		pi->txpwr_limit[rate1] = txpwr->ofdm[rate2];
+
+	if (ISNPHY(pi)) {
+
+		for (k = 0; k < 4; k++) {
+			switch (k) {
+			case 0:
+
+				txpwr_ptr1 = txpwr->mcs_20_siso;
+				txpwr_ptr2 = txpwr->ofdm;
+				rate_start_index = WL_TX_POWER_OFDM_FIRST;
+				break;
+			case 1:
+
+				txpwr_ptr1 = txpwr->mcs_20_cdd;
+				txpwr_ptr2 = txpwr->ofdm_cdd;
+				rate_start_index = WL_TX_POWER_OFDM20_CDD_FIRST;
+				break;
+			case 2:
+
+				txpwr_ptr1 = txpwr->mcs_40_siso;
+				txpwr_ptr2 = txpwr->ofdm_40_siso;
+				rate_start_index =
+					WL_TX_POWER_OFDM40_SISO_FIRST;
+				break;
+			case 3:
+
+				txpwr_ptr1 = txpwr->mcs_40_cdd;
+				txpwr_ptr2 = txpwr->ofdm_40_cdd;
+				rate_start_index = WL_TX_POWER_OFDM40_CDD_FIRST;
+				break;
+			}
+
+			for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM;
+			     rate2++) {
+				tmp_txpwr_limit[rate2] = 0;
+				tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] =
+					txpwr_ptr1[rate2];
+			}
+			wlc_phy_mcs_to_ofdm_powers_nphy(
+				tmp_txpwr_limit, 0,
+				BRCMS_NUM_RATES_OFDM -
+				1, BRCMS_NUM_RATES_OFDM);
+			for (rate1 = rate_start_index, rate2 = 0;
+			     rate2 < BRCMS_NUM_RATES_OFDM; rate1++, rate2++)
+				pi->txpwr_limit[rate1] =
+					min(txpwr_ptr2[rate2],
+					    tmp_txpwr_limit[rate2]);
+		}
+
+		for (k = 0; k < 4; k++) {
+			switch (k) {
+			case 0:
+
+				txpwr_ptr1 = txpwr->ofdm;
+				txpwr_ptr2 = txpwr->mcs_20_siso;
+				rate_start_index = WL_TX_POWER_MCS20_SISO_FIRST;
+				break;
+			case 1:
+
+				txpwr_ptr1 = txpwr->ofdm_cdd;
+				txpwr_ptr2 = txpwr->mcs_20_cdd;
+				rate_start_index = WL_TX_POWER_MCS20_CDD_FIRST;
+				break;
+			case 2:
+
+				txpwr_ptr1 = txpwr->ofdm_40_siso;
+				txpwr_ptr2 = txpwr->mcs_40_siso;
+				rate_start_index = WL_TX_POWER_MCS40_SISO_FIRST;
+				break;
+			case 3:
+
+				txpwr_ptr1 = txpwr->ofdm_40_cdd;
+				txpwr_ptr2 = txpwr->mcs_40_cdd;
+				rate_start_index = WL_TX_POWER_MCS40_CDD_FIRST;
+				break;
+			}
+			for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM;
+			     rate2++) {
+				tmp_txpwr_limit[rate2] = 0;
+				tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] =
+					txpwr_ptr1[rate2];
+			}
+			wlc_phy_ofdm_to_mcs_powers_nphy(
+				tmp_txpwr_limit, 0,
+				BRCMS_NUM_RATES_OFDM -
+				1, BRCMS_NUM_RATES_OFDM);
+			for (rate1 = rate_start_index, rate2 = 0;
+			     rate2 < BRCMS_NUM_RATES_MCS_1_STREAM;
+			     rate1++, rate2++)
+				pi->txpwr_limit[rate1] =
+					min(txpwr_ptr2[rate2],
+					    tmp_txpwr_limit[rate2]);
+		}
+
+		for (k = 0; k < 2; k++) {
+			switch (k) {
+			case 0:
+
+				rate_start_index = WL_TX_POWER_MCS20_STBC_FIRST;
+				txpwr_ptr1 = txpwr->mcs_20_stbc;
+				break;
+			case 1:
+
+				rate_start_index = WL_TX_POWER_MCS40_STBC_FIRST;
+				txpwr_ptr1 = txpwr->mcs_40_stbc;
+				break;
+			}
+			for (rate1 = rate_start_index, rate2 = 0;
+			     rate2 < BRCMS_NUM_RATES_MCS_1_STREAM;
+			     rate1++, rate2++)
+				pi->txpwr_limit[rate1] = txpwr_ptr1[rate2];
+		}
+
+		for (k = 0; k < 2; k++) {
+			switch (k) {
+			case 0:
+
+				rate_start_index = WL_TX_POWER_MCS20_SDM_FIRST;
+				txpwr_ptr1 = txpwr->mcs_20_mimo;
+				break;
+			case 1:
+
+				rate_start_index = WL_TX_POWER_MCS40_SDM_FIRST;
+				txpwr_ptr1 = txpwr->mcs_40_mimo;
+				break;
+			}
+			for (rate1 = rate_start_index, rate2 = 0;
+			     rate2 < BRCMS_NUM_RATES_MCS_2_STREAM;
+			     rate1++, rate2++)
+				pi->txpwr_limit[rate1] = txpwr_ptr1[rate2];
+		}
+
+		pi->txpwr_limit[WL_TX_POWER_MCS_32] = txpwr->mcs32;
+
+		pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST] =
+			min(pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST],
+			    pi->txpwr_limit[WL_TX_POWER_MCS_32]);
+		pi->txpwr_limit[WL_TX_POWER_MCS_32] =
+			pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST];
+	}
+}
+
+void wlc_phy_txpwr_percent_set(struct brcms_phy_pub *ppi, u8 txpwr_percent)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+
+	pi->txpwr_percent = txpwr_percent;
+}
+
+void wlc_phy_machwcap_set(struct brcms_phy_pub *ppi, u32 machwcap)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+
+	pi->sh->machwcap = machwcap;
+}
+
+void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+	u16 rxc;
+	rxc = 0;
+
+	if (start_end == ON) {
+		if (!ISNPHY(pi))
+			return;
+
+		if (NREV_IS(pi->pubpi.phy_rev, 3)
+		    || NREV_IS(pi->pubpi.phy_rev, 4)) {
+			bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr),
+				      0xa0);
+			bcma_set16(pi->d11core, D11REGOFFS(phyregdata),
+				   0x1 << 15);
+		}
+	} else {
+		if (NREV_IS(pi->pubpi.phy_rev, 3)
+		    || NREV_IS(pi->pubpi.phy_rev, 4)) {
+			bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr),
+				      0xa0);
+			bcma_write16(pi->d11core, D11REGOFFS(phyregdata), rxc);
+		}
+
+		wlc_phy_por_inform(ppi);
+	}
+}
+
+void
+wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi, struct txpwr_limits *txpwr,
+			  u16 chanspec)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+
+	wlc_phy_txpower_reg_limit_calc(pi, txpwr, chanspec);
+
+	if (ISLCNPHY(pi)) {
+		int i, j;
+		for (i = TXP_FIRST_OFDM_20_CDD, j = 0;
+		     j < BRCMS_NUM_RATES_MCS_1_STREAM; i++, j++) {
+			if (txpwr->mcs_20_siso[j])
+				pi->txpwr_limit[i] = txpwr->mcs_20_siso[j];
+			else
+				pi->txpwr_limit[i] = txpwr->ofdm[j];
+		}
+	}
+
+	wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	wlc_phy_txpower_recalc_target(pi);
+	wlc_phy_cal_txpower_recalc_sw(pi);
+	wlapi_enable_mac(pi->sh->physhim);
+}
+
+void wlc_phy_ofdm_rateset_war(struct brcms_phy_pub *pih, bool war)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+
+	pi->ofdm_rateset_war = war;
+}
+
+void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih, bool bf_preempt)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+
+	pi->bf_preempt_4306 = bf_preempt;
+}
+
+void wlc_phy_txpower_update_shm(struct brcms_phy *pi)
+{
+	int j;
+	if (ISNPHY(pi))
+		return;
+
+	if (!pi->sh->clk)
+		return;
+
+	if (pi->hwpwrctrl) {
+		u16 offset;
+
+		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_MAX, 63);
+		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_N,
+				     1 << NUM_TSSI_FRAMES);
+
+		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_TARGET,
+				     pi->tx_power_min << NUM_TSSI_FRAMES);
+
+		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_CUR,
+				     pi->hwpwr_txcur);
+
+		for (j = TXP_FIRST_OFDM; j <= TXP_LAST_OFDM; j++) {
+			static const u8 ucode_ofdm_rates[] = {
+				0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c
+			};
+			offset = wlapi_bmac_rate_shm_offset(
+				pi->sh->physhim,
+				ucode_ofdm_rates[j - TXP_FIRST_OFDM]);
+			wlapi_bmac_write_shm(pi->sh->physhim, offset + 6,
+					     pi->tx_power_offset[j]);
+			wlapi_bmac_write_shm(pi->sh->physhim, offset + 14,
+					     -(pi->tx_power_offset[j] / 2));
+		}
+
+		wlapi_bmac_mhf(pi->sh->physhim, MHF2, MHF2_HWPWRCTL,
+			       MHF2_HWPWRCTL, BRCM_BAND_ALL);
+	} else {
+		int i;
+
+		for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++)
+			pi->tx_power_offset[i] =
+				(u8) roundup(pi->tx_power_offset[i], 8);
+		wlapi_bmac_write_shm(pi->sh->physhim, M_OFDM_OFFSET,
+				     (u16)
+				     ((pi->tx_power_offset[TXP_FIRST_OFDM]
+				       + 7) >> 3));
+	}
+}
+
+bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+
+	if (ISNPHY(pi))
+		return pi->nphy_txpwrctrl;
+	else
+		return pi->hwpwrctrl;
+}
+
+void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi, bool hwpwrctrl)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+	bool suspend;
+
+	if (!pi->hwpwrctrl_capable)
+		return;
+
+	pi->hwpwrctrl = hwpwrctrl;
+	pi->nphy_txpwrctrl = hwpwrctrl;
+	pi->txpwrctrl = hwpwrctrl;
+
+	if (ISNPHY(pi)) {
+		suspend = (0 == (bcma_read32(pi->d11core,
+					     D11REGOFFS(maccontrol)) &
+				 MCTL_EN_MAC));
+		if (!suspend)
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+		wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl);
+		if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF)
+			wlc_phy_txpwr_fixpower_nphy(pi);
+		else
+			mod_phy_reg(pi, 0x1e7, (0x7f << 0),
+				    pi->saved_txpwr_idx);
+
+		if (!suspend)
+			wlapi_enable_mac(pi->sh->physhim);
+	}
+}
+
+void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi)
+{
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		pi->ipa2g_on = (pi->srom_fem2g.extpagain == 2);
+		pi->ipa5g_on = (pi->srom_fem5g.extpagain == 2);
+	} else {
+		pi->ipa2g_on = false;
+		pi->ipa5g_on = false;
+	}
+}
+
+static u32 wlc_phy_txpower_est_power_nphy(struct brcms_phy *pi)
+{
+	s16 tx0_status, tx1_status;
+	u16 estPower1, estPower2;
+	u8 pwr0, pwr1, adj_pwr0, adj_pwr1;
+	u32 est_pwr;
+
+	estPower1 = read_phy_reg(pi, 0x118);
+	estPower2 = read_phy_reg(pi, 0x119);
+
+	if ((estPower1 & (0x1 << 8)) == (0x1 << 8))
+		pwr0 = (u8) (estPower1 & (0xff << 0)) >> 0;
+	else
+		pwr0 = 0x80;
+
+	if ((estPower2 & (0x1 << 8)) == (0x1 << 8))
+		pwr1 = (u8) (estPower2 & (0xff << 0)) >> 0;
+	else
+		pwr1 = 0x80;
+
+	tx0_status = read_phy_reg(pi, 0x1ed);
+	tx1_status = read_phy_reg(pi, 0x1ee);
+
+	if ((tx0_status & (0x1 << 15)) == (0x1 << 15))
+		adj_pwr0 = (u8) (tx0_status & (0xff << 0)) >> 0;
+	else
+		adj_pwr0 = 0x80;
+	if ((tx1_status & (0x1 << 15)) == (0x1 << 15))
+		adj_pwr1 = (u8) (tx1_status & (0xff << 0)) >> 0;
+	else
+		adj_pwr1 = 0x80;
+
+	est_pwr = (u32) ((pwr0 << 24) | (pwr1 << 16) | (adj_pwr0 << 8) |
+			 adj_pwr1);
+
+	return est_pwr;
+}
+
+void
+wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi, struct tx_power *power,
+			    uint channel)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+	uint rate, num_rates;
+	u8 min_pwr, max_pwr;
+
+#if WL_TX_POWER_RATES != TXP_NUM_RATES
+#error "struct tx_power out of sync with this fn"
+#endif
+
+	if (ISNPHY(pi)) {
+		power->rf_cores = 2;
+		power->flags |= (WL_TX_POWER_F_MIMO);
+		if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON)
+			power->flags |=
+				(WL_TX_POWER_F_ENABLED | WL_TX_POWER_F_HW);
+	} else if (ISLCNPHY(pi)) {
+		power->rf_cores = 1;
+		power->flags |= (WL_TX_POWER_F_SISO);
+		if (pi->radiopwr_override == RADIOPWR_OVERRIDE_DEF)
+			power->flags |= WL_TX_POWER_F_ENABLED;
+		if (pi->hwpwrctrl)
+			power->flags |= WL_TX_POWER_F_HW;
+	}
+
+	num_rates = ((ISNPHY(pi)) ? (TXP_NUM_RATES) :
+		     ((ISLCNPHY(pi)) ?
+		      (TXP_LAST_OFDM_20_CDD + 1) : (TXP_LAST_OFDM + 1)));
+
+	for (rate = 0; rate < num_rates; rate++) {
+		power->user_limit[rate] = pi->tx_user_target[rate];
+		wlc_phy_txpower_sromlimit(ppi, channel, &min_pwr, &max_pwr,
+					  rate);
+		power->board_limit[rate] = (u8) max_pwr;
+		power->target[rate] = pi->tx_power_target[rate];
+	}
+
+	if (ISNPHY(pi)) {
+		u32 est_pout;
+
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+		wlc_phyreg_enter((struct brcms_phy_pub *) pi);
+		est_pout = wlc_phy_txpower_est_power_nphy(pi);
+		wlc_phyreg_exit((struct brcms_phy_pub *) pi);
+		wlapi_enable_mac(pi->sh->physhim);
+
+		power->est_Pout[0] = (est_pout >> 8) & 0xff;
+		power->est_Pout[1] = est_pout & 0xff;
+
+		power->est_Pout_act[0] = est_pout >> 24;
+		power->est_Pout_act[1] = (est_pout >> 16) & 0xff;
+
+		if (power->est_Pout[0] == 0x80)
+			power->est_Pout[0] = 0;
+		if (power->est_Pout[1] == 0x80)
+			power->est_Pout[1] = 0;
+
+		if (power->est_Pout_act[0] == 0x80)
+			power->est_Pout_act[0] = 0;
+		if (power->est_Pout_act[1] == 0x80)
+			power->est_Pout_act[1] = 0;
+
+		power->est_Pout_cck = 0;
+
+		power->tx_power_max[0] = pi->tx_power_max;
+		power->tx_power_max[1] = pi->tx_power_max;
+
+		power->tx_power_max_rate_ind[0] = pi->tx_power_max_rate_ind;
+		power->tx_power_max_rate_ind[1] = pi->tx_power_max_rate_ind;
+	} else if (pi->hwpwrctrl && pi->sh->up) {
+
+		wlc_phyreg_enter(ppi);
+		if (ISLCNPHY(pi)) {
+
+			power->tx_power_max[0] = pi->tx_power_max;
+			power->tx_power_max[1] = pi->tx_power_max;
+
+			power->tx_power_max_rate_ind[0] =
+				pi->tx_power_max_rate_ind;
+			power->tx_power_max_rate_ind[1] =
+				pi->tx_power_max_rate_ind;
+
+			if (wlc_phy_tpc_isenabled_lcnphy(pi))
+				power->flags |=
+					(WL_TX_POWER_F_HW |
+					 WL_TX_POWER_F_ENABLED);
+			else
+				power->flags &=
+					~(WL_TX_POWER_F_HW |
+					  WL_TX_POWER_F_ENABLED);
+
+			wlc_lcnphy_get_tssi(pi, (s8 *) &power->est_Pout[0],
+					    (s8 *) &power->est_Pout_cck);
+		}
+		wlc_phyreg_exit(ppi);
+	}
+}
+
+void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+
+	pi->antsel_type = antsel_type;
+}
+
+bool wlc_phy_test_ison(struct brcms_phy_pub *ppi)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+
+	return pi->phytest_on;
+}
+
+void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+	bool suspend;
+
+	pi->sh->rx_antdiv = val;
+
+	if (!(ISNPHY(pi) && D11REV_IS(pi->sh->corerev, 16))) {
+		if (val > ANT_RX_DIV_FORCE_1)
+			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV,
+				       MHF1_ANTDIV, BRCM_BAND_ALL);
+		else
+			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV, 0,
+				       BRCM_BAND_ALL);
+	}
+
+	if (ISNPHY(pi))
+		return;
+
+	if (!pi->sh->clk)
+		return;
+
+	suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
+			 MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	if (ISLCNPHY(pi)) {
+		if (val > ANT_RX_DIV_FORCE_1) {
+			mod_phy_reg(pi, 0x410, (0x1 << 1), 0x01 << 1);
+			mod_phy_reg(pi, 0x410,
+				    (0x1 << 0),
+				    ((ANT_RX_DIV_START_1 == val) ? 1 : 0) << 0);
+		} else {
+			mod_phy_reg(pi, 0x410, (0x1 << 1), 0x00 << 1);
+			mod_phy_reg(pi, 0x410, (0x1 << 0), (u16) val << 0);
+		}
+	}
+
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+
+	return;
+}
+
+static bool
+wlc_phy_noise_calc_phy(struct brcms_phy *pi, u32 *cmplx_pwr, s8 *pwr_ant)
+{
+	s8 cmplx_pwr_dbm[PHY_CORE_MAX];
+	u8 i;
+
+	memset((u8 *) cmplx_pwr_dbm, 0, sizeof(cmplx_pwr_dbm));
+	wlc_phy_compute_dB(cmplx_pwr, cmplx_pwr_dbm, pi->pubpi.phy_corenum);
+
+	for (i = 0; i < pi->pubpi.phy_corenum; i++) {
+		if (NREV_GE(pi->pubpi.phy_rev, 3))
+			cmplx_pwr_dbm[i] += (s8) PHY_NOISE_OFFSETFACT_4322;
+		else
+
+			cmplx_pwr_dbm[i] += (s8) (16 - (15) * 3 - 70);
+	}
+
+	for (i = 0; i < pi->pubpi.phy_corenum; i++) {
+		pi->nphy_noise_win[i][pi->nphy_noise_index] = cmplx_pwr_dbm[i];
+		pwr_ant[i] = cmplx_pwr_dbm[i];
+	}
+	pi->nphy_noise_index =
+		MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
+	return true;
+}
+
+static void wlc_phy_noise_cb(struct brcms_phy *pi, u8 channel, s8 noise_dbm)
+{
+	if (!pi->phynoise_state)
+		return;
+
+	if (pi->phynoise_state & PHY_NOISE_STATE_MON) {
+		if (pi->phynoise_chan_watchdog == channel) {
+			pi->sh->phy_noise_window[pi->sh->phy_noise_index] =
+				noise_dbm;
+			pi->sh->phy_noise_index =
+				MODINC(pi->sh->phy_noise_index, MA_WINDOW_SZ);
+		}
+		pi->phynoise_state &= ~PHY_NOISE_STATE_MON;
+	}
+
+	if (pi->phynoise_state & PHY_NOISE_STATE_EXTERNAL)
+		pi->phynoise_state &= ~PHY_NOISE_STATE_EXTERNAL;
+
+}
+
+static s8 wlc_phy_noise_read_shmem(struct brcms_phy *pi)
+{
+	u32 cmplx_pwr[PHY_CORE_MAX];
+	s8 noise_dbm_ant[PHY_CORE_MAX];
+	u16 lo, hi;
+	u32 cmplx_pwr_tot = 0;
+	s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
+	u8 idx, core;
+
+	memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr));
+	memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant));
+
+	for (idx = 0, core = 0; core < pi->pubpi.phy_corenum; idx += 2,
+	     core++) {
+		lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP(idx));
+		hi = wlapi_bmac_read_shm(pi->sh->physhim,
+					 M_PWRIND_MAP(idx + 1));
+		cmplx_pwr[core] = (hi << 16) + lo;
+		cmplx_pwr_tot += cmplx_pwr[core];
+		if (cmplx_pwr[core] == 0)
+			noise_dbm_ant[core] = PHY_NOISE_FIXED_VAL_NPHY;
+		else
+			cmplx_pwr[core] >>= PHY_NOISE_SAMPLE_LOG_NUM_UCODE;
+	}
+
+	if (cmplx_pwr_tot != 0)
+		wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+		pi->nphy_noise_win[core][pi->nphy_noise_index] =
+			noise_dbm_ant[core];
+
+		if (noise_dbm_ant[core] > noise_dbm)
+			noise_dbm = noise_dbm_ant[core];
+	}
+	pi->nphy_noise_index =
+		MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
+
+	return noise_dbm;
+
+}
+
+void wlc_phy_noise_sample_intr(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+	u16 jssi_aux;
+	u8 channel = 0;
+	s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
+
+	if (ISLCNPHY(pi)) {
+		u32 cmplx_pwr, cmplx_pwr0, cmplx_pwr1;
+		u16 lo, hi;
+		s32 pwr_offset_dB, gain_dB;
+		u16 status_0, status_1;
+
+		jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
+		channel = jssi_aux & D11_CURCHANNEL_MAX;
+
+		lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP0);
+		hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP1);
+		cmplx_pwr0 = (hi << 16) + lo;
+
+		lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP2);
+		hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP3);
+		cmplx_pwr1 = (hi << 16) + lo;
+		cmplx_pwr = (cmplx_pwr0 + cmplx_pwr1) >> 6;
+
+		status_0 = 0x44;
+		status_1 = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_0);
+		if ((cmplx_pwr > 0 && cmplx_pwr < 500)
+		    && ((status_1 & 0xc000) == 0x4000)) {
+
+			wlc_phy_compute_dB(&cmplx_pwr, &noise_dbm,
+					   pi->pubpi.phy_corenum);
+			pwr_offset_dB = (read_phy_reg(pi, 0x434) & 0xFF);
+			if (pwr_offset_dB > 127)
+				pwr_offset_dB -= 256;
+
+			noise_dbm += (s8) (pwr_offset_dB - 30);
+
+			gain_dB = (status_0 & 0x1ff);
+			noise_dbm -= (s8) (gain_dB);
+		} else {
+			noise_dbm = PHY_NOISE_FIXED_VAL_LCNPHY;
+		}
+	} else if (ISNPHY(pi)) {
+
+		jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
+		channel = jssi_aux & D11_CURCHANNEL_MAX;
+
+		noise_dbm = wlc_phy_noise_read_shmem(pi);
+	}
+
+	wlc_phy_noise_cb(pi, channel, noise_dbm);
+
+}
+
+static void
+wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+	s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
+	bool sampling_in_progress = (pi->phynoise_state != 0);
+	bool wait_for_intr = true;
+
+	switch (reason) {
+	case PHY_NOISE_SAMPLE_MON:
+		pi->phynoise_chan_watchdog = ch;
+		pi->phynoise_state |= PHY_NOISE_STATE_MON;
+		break;
+
+	case PHY_NOISE_SAMPLE_EXTERNAL:
+		pi->phynoise_state |= PHY_NOISE_STATE_EXTERNAL;
+		break;
+
+	default:
+		break;
+	}
+
+	if (sampling_in_progress)
+		return;
+
+	pi->phynoise_now = pi->sh->now;
+
+	if (pi->phy_fixed_noise) {
+		if (ISNPHY(pi)) {
+			pi->nphy_noise_win[WL_ANT_IDX_1][pi->nphy_noise_index] =
+				PHY_NOISE_FIXED_VAL_NPHY;
+			pi->nphy_noise_win[WL_ANT_IDX_2][pi->nphy_noise_index] =
+				PHY_NOISE_FIXED_VAL_NPHY;
+			pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index,
+							   PHY_NOISE_WINDOW_SZ);
+			noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
+		} else {
+			noise_dbm = PHY_NOISE_FIXED_VAL;
+		}
+
+		wait_for_intr = false;
+		goto done;
+	}
+
+	if (ISLCNPHY(pi)) {
+		if (!pi->phynoise_polling
+		    || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) {
+			wlapi_bmac_write_shm(pi->sh->physhim, M_JSSI_0, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0);
+
+			bcma_set32(pi->d11core, D11REGOFFS(maccommand),
+				   MCMD_BG_NOISE);
+		} else {
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+			wlc_lcnphy_deaf_mode(pi, (bool) 0);
+			noise_dbm = (s8) wlc_lcnphy_rx_signal_power(pi, 20);
+			wlc_lcnphy_deaf_mode(pi, (bool) 1);
+			wlapi_enable_mac(pi->sh->physhim);
+			wait_for_intr = false;
+		}
+	} else if (ISNPHY(pi)) {
+		if (!pi->phynoise_polling
+		    || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) {
+
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0);
+
+			bcma_set32(pi->d11core, D11REGOFFS(maccommand),
+				   MCMD_BG_NOISE);
+		} else {
+			struct phy_iq_est est[PHY_CORE_MAX];
+			u32 cmplx_pwr[PHY_CORE_MAX];
+			s8 noise_dbm_ant[PHY_CORE_MAX];
+			u16 log_num_samps, num_samps, classif_state = 0;
+			u8 wait_time = 32;
+			u8 wait_crs = 0;
+			u8 i;
+
+			memset((u8 *) est, 0, sizeof(est));
+			memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr));
+			memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant));
+
+			log_num_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY;
+			num_samps = 1 << log_num_samps;
+
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+			classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
+			wlc_phy_classifier_nphy(pi, 3, 0);
+			wlc_phy_rx_iq_est_nphy(pi, est, num_samps, wait_time,
+					       wait_crs);
+			wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
+			wlapi_enable_mac(pi->sh->physhim);
+
+			for (i = 0; i < pi->pubpi.phy_corenum; i++)
+				cmplx_pwr[i] = (est[i].i_pwr + est[i].q_pwr) >>
+					       log_num_samps;
+
+			wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
+
+			for (i = 0; i < pi->pubpi.phy_corenum; i++) {
+				pi->nphy_noise_win[i][pi->nphy_noise_index] =
+					noise_dbm_ant[i];
+
+				if (noise_dbm_ant[i] > noise_dbm)
+					noise_dbm = noise_dbm_ant[i];
+			}
+			pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index,
+							   PHY_NOISE_WINDOW_SZ);
+
+			wait_for_intr = false;
+		}
+	}
+
+done:
+
+	if (!wait_for_intr)
+		wlc_phy_noise_cb(pi, ch, noise_dbm);
+
+}
+
+void wlc_phy_noise_sample_request_external(struct brcms_phy_pub *pih)
+{
+	u8 channel;
+
+	channel = CHSPEC_CHANNEL(wlc_phy_chanspec_get(pih));
+
+	wlc_phy_noise_sample_request(pih, PHY_NOISE_SAMPLE_EXTERNAL, channel);
+}
+
+static const s8 lcnphy_gain_index_offset_for_pkt_rssi[] = {
+	8,
+	8,
+	8,
+	8,
+	8,
+	8,
+	8,
+	9,
+	10,
+	8,
+	8,
+	7,
+	7,
+	1,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	1,
+	1,
+	0,
+	0,
+	0,
+	0
+};
+
+void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_cmplx_pwr_dB, u8 core)
+{
+	u8 msb, secondmsb, i;
+	u32 tmp;
+
+	for (i = 0; i < core; i++) {
+		secondmsb = 0;
+		tmp = cmplx_pwr[i];
+		msb = fls(tmp);
+		if (msb)
+			secondmsb = (u8) ((tmp >> (--msb - 1)) & 1);
+		p_cmplx_pwr_dB[i] = (s8) (3 * msb + 2 * secondmsb);
+	}
+}
+
+int wlc_phy_rssi_compute(struct brcms_phy_pub *pih,
+			 struct d11rxhdr *rxh)
+{
+	int rssi = rxh->PhyRxStatus_1 & PRXS1_JSSI_MASK;
+	uint radioid = pih->radioid;
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+
+	if ((pi->sh->corerev >= 11)
+	    && !(rxh->RxStatus2 & RXS_PHYRXST_VALID)) {
+		rssi = BRCMS_RSSI_INVALID;
+		goto end;
+	}
+
+	if (ISLCNPHY(pi)) {
+		u8 gidx = (rxh->PhyRxStatus_2 & 0xFC00) >> 10;
+		struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+		if (rssi > 127)
+			rssi -= 256;
+
+		rssi = rssi + lcnphy_gain_index_offset_for_pkt_rssi[gidx];
+		if ((rssi > -46) && (gidx > 18))
+			rssi = rssi + 7;
+
+		rssi = rssi + pi_lcn->lcnphy_pkteng_rssi_slope;
+
+		rssi = rssi + 2;
+
+	}
+
+	if (ISLCNPHY(pi)) {
+		if (rssi > 127)
+			rssi -= 256;
+	} else if (radioid == BCM2055_ID || radioid == BCM2056_ID
+		   || radioid == BCM2057_ID) {
+		rssi = wlc_phy_rssi_compute_nphy(pi, rxh);
+	}
+
+end:
+	return rssi;
+}
+
+void wlc_phy_freqtrack_start(struct brcms_phy_pub *pih)
+{
+	return;
+}
+
+void wlc_phy_freqtrack_end(struct brcms_phy_pub *pih)
+{
+	return;
+}
+
+void wlc_phy_set_deaf(struct brcms_phy_pub *ppi, bool user_flag)
+{
+	struct brcms_phy *pi;
+	pi = (struct brcms_phy *) ppi;
+
+	if (ISLCNPHY(pi))
+		wlc_lcnphy_deaf_mode(pi, true);
+	else if (ISNPHY(pi))
+		wlc_nphy_deaf_mode(pi, true);
+}
+
+void wlc_phy_watchdog(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+	bool delay_phy_cal = false;
+	pi->sh->now++;
+
+	if (!pi->watchdog_override)
+		return;
+
+	if (!(SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)))
+		wlc_phy_noise_sample_request((struct brcms_phy_pub *) pi,
+					     PHY_NOISE_SAMPLE_MON,
+					     CHSPEC_CHANNEL(pi->
+							    radio_chanspec));
+
+	if (pi->phynoise_state && (pi->sh->now - pi->phynoise_now) > 5)
+		pi->phynoise_state = 0;
+
+	if ((!pi->phycal_txpower) ||
+	    ((pi->sh->now - pi->phycal_txpower) >= pi->sh->fast_timer)) {
+
+		if (!SCAN_INPROG_PHY(pi) && wlc_phy_cal_txpower_recalc_sw(pi))
+			pi->phycal_txpower = pi->sh->now;
+	}
+
+	if ((SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)
+	     || ASSOC_INPROG_PHY(pi)))
+		return;
+
+	if (ISNPHY(pi) && !pi->disable_percal && !delay_phy_cal) {
+
+		if ((pi->nphy_perical != PHY_PERICAL_DISABLE) &&
+		    (pi->nphy_perical != PHY_PERICAL_MANUAL) &&
+		    ((pi->sh->now - pi->nphy_perical_last) >=
+		     pi->sh->glacial_timer))
+			wlc_phy_cal_perical((struct brcms_phy_pub *) pi,
+					    PHY_PERICAL_WATCHDOG);
+
+		wlc_phy_txpwr_papd_cal_nphy(pi);
+	}
+
+	if (ISLCNPHY(pi)) {
+		if (pi->phy_forcecal ||
+		    ((pi->sh->now - pi->phy_lastcal) >=
+		     pi->sh->glacial_timer)) {
+			if (!(SCAN_RM_IN_PROGRESS(pi) || ASSOC_INPROG_PHY(pi)))
+				wlc_lcnphy_calib_modes(
+					pi,
+					LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
+			if (!
+			    (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)
+			     || ASSOC_INPROG_PHY(pi)
+			     || pi->carrier_suppr_disable
+			     || pi->disable_percal))
+				wlc_lcnphy_calib_modes(pi,
+						       PHY_PERICAL_WATCHDOG);
+		}
+	}
+}
+
+void wlc_phy_BSSinit(struct brcms_phy_pub *pih, bool bonlyap, int rssi)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+	uint i;
+	uint k;
+
+	for (i = 0; i < MA_WINDOW_SZ; i++)
+		pi->sh->phy_noise_window[i] = (s8) (rssi & 0xff);
+	if (ISLCNPHY(pi)) {
+		for (i = 0; i < MA_WINDOW_SZ; i++)
+			pi->sh->phy_noise_window[i] =
+				PHY_NOISE_FIXED_VAL_LCNPHY;
+	}
+	pi->sh->phy_noise_index = 0;
+
+	for (i = 0; i < PHY_NOISE_WINDOW_SZ; i++) {
+		for (k = WL_ANT_IDX_1; k < WL_ANT_RX_MAX; k++)
+			pi->nphy_noise_win[k][i] = PHY_NOISE_FIXED_VAL_NPHY;
+	}
+	pi->nphy_noise_index = 0;
+}
+
+void
+wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, s32 *eps_imag)
+{
+	*eps_imag = (epsilon >> 13);
+	if (*eps_imag > 0xfff)
+		*eps_imag -= 0x2000;
+
+	*eps_real = (epsilon & 0x1fff);
+	if (*eps_real > 0xfff)
+		*eps_real -= 0x2000;
+}
+
+void wlc_phy_cal_perical_mphase_reset(struct brcms_phy *pi)
+{
+	wlapi_del_timer(pi->phycal_timer);
+
+	pi->cal_type_override = PHY_PERICAL_AUTO;
+	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE;
+	pi->mphase_txcal_cmdidx = 0;
+}
+
+static void
+wlc_phy_cal_perical_mphase_schedule(struct brcms_phy *pi, uint delay)
+{
+
+	if ((pi->nphy_perical != PHY_PERICAL_MPHASE) &&
+	    (pi->nphy_perical != PHY_PERICAL_MANUAL))
+		return;
+
+	wlapi_del_timer(pi->phycal_timer);
+
+	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT;
+	wlapi_add_timer(pi->phycal_timer, delay, 0);
+}
+
+void wlc_phy_cal_perical(struct brcms_phy_pub *pih, u8 reason)
+{
+	s16 nphy_currtemp = 0;
+	s16 delta_temp = 0;
+	bool do_periodic_cal = true;
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+
+	if (!ISNPHY(pi))
+		return;
+
+	if ((pi->nphy_perical == PHY_PERICAL_DISABLE) ||
+	    (pi->nphy_perical == PHY_PERICAL_MANUAL))
+		return;
+
+	switch (reason) {
+	case PHY_PERICAL_DRIVERUP:
+		break;
+
+	case PHY_PERICAL_PHYINIT:
+		if (pi->nphy_perical == PHY_PERICAL_MPHASE) {
+			if (PHY_PERICAL_MPHASE_PENDING(pi))
+				wlc_phy_cal_perical_mphase_reset(pi);
+
+			wlc_phy_cal_perical_mphase_schedule(
+				pi,
+				PHY_PERICAL_INIT_DELAY);
+		}
+		break;
+
+	case PHY_PERICAL_JOIN_BSS:
+	case PHY_PERICAL_START_IBSS:
+	case PHY_PERICAL_UP_BSS:
+		if ((pi->nphy_perical == PHY_PERICAL_MPHASE) &&
+		    PHY_PERICAL_MPHASE_PENDING(pi))
+			wlc_phy_cal_perical_mphase_reset(pi);
+
+		pi->first_cal_after_assoc = true;
+
+		pi->cal_type_override = PHY_PERICAL_FULL;
+
+		if (pi->phycal_tempdelta)
+			pi->nphy_lastcal_temp = wlc_phy_tempsense_nphy(pi);
+
+		wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_FULL);
+		break;
+
+	case PHY_PERICAL_WATCHDOG:
+		if (pi->phycal_tempdelta) {
+			nphy_currtemp = wlc_phy_tempsense_nphy(pi);
+			delta_temp =
+				(nphy_currtemp > pi->nphy_lastcal_temp) ?
+				nphy_currtemp - pi->nphy_lastcal_temp :
+				pi->nphy_lastcal_temp - nphy_currtemp;
+
+			if ((delta_temp < (s16) pi->phycal_tempdelta) &&
+			    (pi->nphy_txiqlocal_chanspec ==
+			     pi->radio_chanspec))
+				do_periodic_cal = false;
+			else
+				pi->nphy_lastcal_temp = nphy_currtemp;
+		}
+
+		if (do_periodic_cal) {
+			if (pi->nphy_perical == PHY_PERICAL_MPHASE) {
+				if (!PHY_PERICAL_MPHASE_PENDING(pi))
+					wlc_phy_cal_perical_mphase_schedule(
+						pi,
+						PHY_PERICAL_WDOG_DELAY);
+			} else if (pi->nphy_perical == PHY_PERICAL_SPHASE)
+				wlc_phy_cal_perical_nphy_run(pi,
+							     PHY_PERICAL_AUTO);
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+void wlc_phy_cal_perical_mphase_restart(struct brcms_phy *pi)
+{
+	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT;
+	pi->mphase_txcal_cmdidx = 0;
+}
+
+u8 wlc_phy_nbits(s32 value)
+{
+	s32 abs_val;
+	u8 nbits = 0;
+
+	abs_val = abs(value);
+	while ((abs_val >> nbits) > 0)
+		nbits++;
+
+	return nbits;
+}
+
+void wlc_phy_stf_chain_init(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+
+	pi->sh->hw_phytxchain = txchain;
+	pi->sh->hw_phyrxchain = rxchain;
+	pi->sh->phytxchain = txchain;
+	pi->sh->phyrxchain = rxchain;
+	pi->pubpi.phy_corenum = (u8)hweight8(pi->sh->phyrxchain);
+}
+
+void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+
+	pi->sh->phytxchain = txchain;
+
+	if (ISNPHY(pi))
+		wlc_phy_rxcore_setstate_nphy(pih, rxchain);
+
+	pi->pubpi.phy_corenum = (u8)hweight8(pi->sh->phyrxchain);
+}
+
+void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain, u8 *rxchain)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+
+	*txchain = pi->sh->phytxchain;
+	*rxchain = pi->sh->phyrxchain;
+}
+
+u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih)
+{
+	s16 nphy_currtemp;
+	u8 active_bitmap;
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+
+	active_bitmap = (pi->phy_txcore_heatedup) ? 0x31 : 0x33;
+
+	if (!pi->watchdog_override)
+		return active_bitmap;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+		nphy_currtemp = wlc_phy_tempsense_nphy(pi);
+		wlapi_enable_mac(pi->sh->physhim);
+
+		if (!pi->phy_txcore_heatedup) {
+			if (nphy_currtemp >= pi->phy_txcore_disable_temp) {
+				active_bitmap &= 0xFD;
+				pi->phy_txcore_heatedup = true;
+			}
+		} else {
+			if (nphy_currtemp <= pi->phy_txcore_enable_temp) {
+				active_bitmap |= 0x2;
+				pi->phy_txcore_heatedup = false;
+			}
+		}
+	}
+
+	return active_bitmap;
+}
+
+s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, u16 chanspec)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+	u8 siso_mcs_id, cdd_mcs_id;
+
+	siso_mcs_id =
+		(CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_SISO :
+		TXP_FIRST_MCS_20_SISO;
+	cdd_mcs_id =
+		(CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_CDD :
+		TXP_FIRST_MCS_20_CDD;
+
+	if (pi->tx_power_target[siso_mcs_id] >
+	    (pi->tx_power_target[cdd_mcs_id] + 12))
+		return PHY_TXC1_MODE_SISO;
+	else
+		return PHY_TXC1_MODE_CDD;
+}
+
+const u8 *wlc_phy_get_ofdm_rate_lookup(void)
+{
+	return ofdm_rate_lookup;
+}
+
+void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode)
+{
+	if ((pi->sh->chip == BCMA_CHIP_ID_BCM4313) &&
+	    (pi->sh->boardflags & BFL_FEM)) {
+		if (mode) {
+			u16 txant = 0;
+			txant = wlapi_bmac_get_txant(pi->sh->physhim);
+			if (txant == 1) {
+				mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2);
+
+				mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2);
+
+			}
+
+			bcma_chipco_gpio_control(&pi->d11core->bus->drv_cc,
+						 0x0, 0x0);
+			bcma_chipco_gpio_out(&pi->d11core->bus->drv_cc,
+					     ~0x40, 0x40);
+			bcma_chipco_gpio_outen(&pi->d11core->bus->drv_cc,
+					       ~0x40, 0x40);
+		} else {
+			mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2);
+
+			mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2);
+
+			bcma_chipco_gpio_out(&pi->d11core->bus->drv_cc,
+					     ~0x40, 0x00);
+			bcma_chipco_gpio_outen(&pi->d11core->bus->drv_cc,
+					       ~0x40, 0x00);
+			bcma_chipco_gpio_control(&pi->d11core->bus->drv_cc,
+						 0x0, 0x40);
+		}
+	}
+}
+
+void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool ldpc)
+{
+	return;
+}
+
+void
+wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset, s8 *ofdmoffset)
+{
+	*cckoffset = 0;
+	*ofdmoffset = 0;
+}
+
+s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, u16 chanspec)
+{
+
+	return rssi;
+}
+
+bool wlc_phy_txpower_ipa_ison(struct brcms_phy_pub *ppi)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+
+	if (ISNPHY(pi))
+		return wlc_phy_n_txpower_ipa_ison(pi);
+	else
+		return false;
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_hal.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_hal.h
new file mode 100644
index 0000000..4d3734f
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_hal.h
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * phy_hal.h:  functionality exported from the phy to higher layers
+ */
+
+#ifndef _BRCM_PHY_HAL_H_
+#define _BRCM_PHY_HAL_H_
+
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+#include <phy_shim.h>
+
+#define	IDCODE_VER_MASK		0x0000000f
+#define	IDCODE_VER_SHIFT	0
+#define	IDCODE_MFG_MASK		0x00000fff
+#define	IDCODE_MFG_SHIFT	0
+#define	IDCODE_ID_MASK		0x0ffff000
+#define	IDCODE_ID_SHIFT		12
+#define	IDCODE_REV_MASK		0xf0000000
+#define	IDCODE_REV_SHIFT	28
+
+#define	NORADIO_ID		0xe4f5
+#define	NORADIO_IDCODE		0x4e4f5246
+
+#define BCM2055_ID		0x2055
+#define BCM2055_IDCODE		0x02055000
+#define BCM2055A0_IDCODE	0x1205517f
+
+#define BCM2056_ID		0x2056
+#define BCM2056_IDCODE		0x02056000
+#define BCM2056A0_IDCODE	0x1205617f
+
+#define BCM2057_ID		0x2057
+#define BCM2057_IDCODE		0x02057000
+#define BCM2057A0_IDCODE	0x1205717f
+
+#define BCM2064_ID		0x2064
+#define BCM2064_IDCODE		0x02064000
+#define BCM2064A0_IDCODE	0x0206417f
+
+#define PHY_TPC_HW_OFF		false
+#define PHY_TPC_HW_ON		true
+
+#define PHY_PERICAL_DRIVERUP	1
+#define PHY_PERICAL_WATCHDOG	2
+#define PHY_PERICAL_PHYINIT	3
+#define PHY_PERICAL_JOIN_BSS	4
+#define PHY_PERICAL_START_IBSS	5
+#define PHY_PERICAL_UP_BSS	6
+#define PHY_PERICAL_CHAN	7
+#define PHY_FULLCAL	8
+
+#define PHY_PERICAL_DISABLE	0
+#define PHY_PERICAL_SPHASE	1
+#define PHY_PERICAL_MPHASE	2
+#define PHY_PERICAL_MANUAL	3
+
+#define PHY_HOLD_FOR_ASSOC	1
+#define PHY_HOLD_FOR_SCAN	2
+#define PHY_HOLD_FOR_RM		4
+#define PHY_HOLD_FOR_PLT	8
+#define PHY_HOLD_FOR_MUTE	16
+#define PHY_HOLD_FOR_NOT_ASSOC 0x20
+
+#define PHY_MUTE_FOR_PREISM	1
+#define PHY_MUTE_ALL		0xffffffff
+
+#define PHY_NOISE_FIXED_VAL		(-95)
+#define PHY_NOISE_FIXED_VAL_NPHY	(-92)
+#define PHY_NOISE_FIXED_VAL_LCNPHY	(-92)
+
+#define PHY_MODE_CAL		0x0002
+#define PHY_MODE_NOISEM		0x0004
+
+#define BRCMS_TXPWR_DB_FACTOR	4
+
+/* a large TX Power as an init value to factor out of min() calculations,
+ * keep low enough to fit in an s8, units are .25 dBm
+ */
+#define BRCMS_TXPWR_MAX		(127)	/* ~32 dBm = 1,500 mW */
+
+#define BRCMS_NUM_RATES_CCK           4
+#define BRCMS_NUM_RATES_OFDM          8
+#define BRCMS_NUM_RATES_MCS_1_STREAM  8
+#define BRCMS_NUM_RATES_MCS_2_STREAM  8
+#define BRCMS_NUM_RATES_MCS_3_STREAM  8
+#define BRCMS_NUM_RATES_MCS_4_STREAM  8
+
+#define	BRCMS_RSSI_INVALID	 0	/* invalid RSSI value */
+
+struct d11regs;
+struct phy_shim_info;
+
+struct txpwr_limits {
+	u8 cck[BRCMS_NUM_RATES_CCK];
+	u8 ofdm[BRCMS_NUM_RATES_OFDM];
+
+	u8 ofdm_cdd[BRCMS_NUM_RATES_OFDM];
+
+	u8 ofdm_40_siso[BRCMS_NUM_RATES_OFDM];
+	u8 ofdm_40_cdd[BRCMS_NUM_RATES_OFDM];
+
+	u8 mcs_20_siso[BRCMS_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_20_cdd[BRCMS_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_20_stbc[BRCMS_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_20_mimo[BRCMS_NUM_RATES_MCS_2_STREAM];
+
+	u8 mcs_40_siso[BRCMS_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_40_cdd[BRCMS_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_40_stbc[BRCMS_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_40_mimo[BRCMS_NUM_RATES_MCS_2_STREAM];
+	u8 mcs32;
+};
+
+struct tx_power {
+	u32 flags;
+	u16 chanspec;   /* txpwr report for this channel */
+	u16 local_chanspec;     /* channel on which we are associated */
+	u8 local_max;   /* local max according to the AP */
+	u8 local_constraint;    /* local constraint according to the AP */
+	s8 antgain[2];  /* Ant gain for each band - from SROM */
+	u8 rf_cores;            /* count of RF Cores being reported */
+	u8 est_Pout[4]; /* Latest tx power out estimate per RF chain */
+	u8 est_Pout_act[4];     /* Latest tx power out estimate per RF chain
+				 * without adjustment */
+	u8 est_Pout_cck;        /* Latest CCK tx power out estimate */
+	u8 tx_power_max[4];     /* Maximum target power among all rates */
+	/* Index of the rate with the max target power */
+	u8 tx_power_max_rate_ind[4];
+	/* User limit */
+	u8 user_limit[WL_TX_POWER_RATES];
+	/* Regulatory power limit */
+	u8 reg_limit[WL_TX_POWER_RATES];
+	/* Max power board can support (SROM) */
+	u8 board_limit[WL_TX_POWER_RATES];
+	/* Latest target power */
+	u8 target[WL_TX_POWER_RATES];
+};
+
+struct tx_inst_power {
+	u8 txpwr_est_Pout[2];   /* Latest estimate for 2.4 and 5 Ghz */
+	u8 txpwr_est_Pout_gofdm;        /* Pwr estimate for 2.4 OFDM */
+};
+
+struct brcms_chanvec {
+	u8 vec[MAXCHANNEL / NBBY];
+};
+
+struct shared_phy_params {
+	struct si_pub *sih;
+	struct phy_shim_info *physhim;
+	uint unit;
+	uint corerev;
+	u16 vid;
+	u16 did;
+	uint chip;
+	uint chiprev;
+	uint chippkg;
+	uint sromrev;
+	uint boardtype;
+	uint boardrev;
+	u32 boardflags;
+	u32 boardflags2;
+};
+
+
+struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp);
+struct brcms_phy_pub *wlc_phy_attach(struct shared_phy *sh,
+				     struct bcma_device *d11core, int bandtype,
+				     struct wiphy *wiphy);
+void wlc_phy_detach(struct brcms_phy_pub *ppi);
+
+bool wlc_phy_get_phyversion(struct brcms_phy_pub *pih, u16 *phytype,
+			    u16 *phyrev, u16 *radioid, u16 *radiover);
+bool wlc_phy_get_encore(struct brcms_phy_pub *pih);
+u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih);
+
+void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub *ppi, bool newstate);
+void wlc_phy_hw_state_upd(struct brcms_phy_pub *ppi, bool newstate);
+void wlc_phy_init(struct brcms_phy_pub *ppi, u16 chanspec);
+void wlc_phy_watchdog(struct brcms_phy_pub *ppi);
+int wlc_phy_down(struct brcms_phy_pub *ppi);
+u32 wlc_phy_clk_bwbits(struct brcms_phy_pub *pih);
+void wlc_phy_cal_init(struct brcms_phy_pub *ppi);
+void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init);
+
+void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, u16 chanspec);
+u16 wlc_phy_chanspec_get(struct brcms_phy_pub *ppi);
+void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, u16 newch);
+u16 wlc_phy_bw_state_get(struct brcms_phy_pub *ppi);
+void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw);
+
+int wlc_phy_rssi_compute(struct brcms_phy_pub *pih, struct d11rxhdr *rxh);
+void wlc_phy_por_inform(struct brcms_phy_pub *ppi);
+void wlc_phy_noise_sample_intr(struct brcms_phy_pub *ppi);
+bool wlc_phy_bist_check_phy(struct brcms_phy_pub *ppi);
+
+void wlc_phy_set_deaf(struct brcms_phy_pub *ppi, bool user_flag);
+
+void wlc_phy_switch_radio(struct brcms_phy_pub *ppi, bool on);
+void wlc_phy_anacore(struct brcms_phy_pub *ppi, bool on);
+
+
+void wlc_phy_BSSinit(struct brcms_phy_pub *ppi, bool bonlyap, int rssi);
+
+void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub *ppi,
+					  bool wide_filter);
+void wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band,
+				   struct brcms_chanvec *channels);
+u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band);
+
+void wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint chan, u8 *_min_,
+			       u8 *_max_, int rate);
+void wlc_phy_txpower_sromlimit_max_get(struct brcms_phy_pub *ppi, uint chan,
+				       u8 *_max_, u8 *_min_);
+void wlc_phy_txpower_boardlimit_band(struct brcms_phy_pub *ppi, uint band,
+				     s32 *, s32 *, u32 *);
+void wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi, struct txpwr_limits *,
+			       u16 chanspec);
+int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm, bool *override);
+int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, bool override);
+void wlc_phy_txpower_target_set(struct brcms_phy_pub *ppi,
+				struct txpwr_limits *);
+bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi);
+void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi, bool hwpwrctrl);
+u8 wlc_phy_txpower_get_target_min(struct brcms_phy_pub *ppi);
+u8 wlc_phy_txpower_get_target_max(struct brcms_phy_pub *ppi);
+bool wlc_phy_txpower_ipa_ison(struct brcms_phy_pub *pih);
+
+void wlc_phy_stf_chain_init(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain);
+void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain);
+void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain, u8 *rxchain);
+u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih);
+s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, u16 chanspec);
+void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool val);
+
+void wlc_phy_cal_perical(struct brcms_phy_pub *ppi, u8 reason);
+void wlc_phy_noise_sample_request_external(struct brcms_phy_pub *ppi);
+void wlc_phy_edcrs_lock(struct brcms_phy_pub *pih, bool lock);
+void wlc_phy_cal_papd_recal(struct brcms_phy_pub *ppi);
+
+void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val);
+void wlc_phy_clear_tssi(struct brcms_phy_pub *ppi);
+void wlc_phy_hold_upd(struct brcms_phy_pub *ppi, u32 id, bool val);
+void wlc_phy_mute_upd(struct brcms_phy_pub *ppi, bool val, u32 flags);
+
+void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type);
+
+void wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi,
+				 struct tx_power *power, uint channel);
+
+void wlc_phy_initcal_enable(struct brcms_phy_pub *pih, bool initcal);
+bool wlc_phy_test_ison(struct brcms_phy_pub *ppi);
+void wlc_phy_txpwr_percent_set(struct brcms_phy_pub *ppi, u8 txpwr_percent);
+void wlc_phy_ofdm_rateset_war(struct brcms_phy_pub *pih, bool war);
+void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih, bool bf_preempt);
+void wlc_phy_machwcap_set(struct brcms_phy_pub *ppi, u32 machwcap);
+
+void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end);
+
+void wlc_phy_freqtrack_start(struct brcms_phy_pub *ppi);
+void wlc_phy_freqtrack_end(struct brcms_phy_pub *ppi);
+
+const u8 *wlc_phy_get_ofdm_rate_lookup(void);
+
+s8 wlc_phy_get_tx_power_offset_by_mcs(struct brcms_phy_pub *ppi,
+				      u8 mcs_offset);
+s8 wlc_phy_get_tx_power_offset(struct brcms_phy_pub *ppi, u8 tbl_offset);
+#endif                          /* _BRCM_PHY_HAL_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_int.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_int.h
new file mode 100644
index 0000000..4960f7d
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_int.h
@@ -0,0 +1,1142 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_PHY_INT_H_
+#define _BRCM_PHY_INT_H_
+
+#include <types.h>
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+
+#define	PHY_VERSION			{ 1, 82, 8, 0 }
+
+#define LCNXN_BASEREV		16
+
+struct phy_shim_info;
+
+struct brcms_phy_srom_fem {
+	/* TSSI positive slope, 1: positive, 0: negative */
+	u8 tssipos;
+	/* Ext PA gain-type: full-gain: 0, pa-lite: 1, no_pa: 2 */
+	u8 extpagain;
+	/* support 32 combinations of different Pdet dynamic ranges */
+	u8 pdetrange;
+	/* TR switch isolation */
+	u8 triso;
+	/* antswctrl lookup table configuration: 32 possible choices */
+	u8 antswctrllut;
+};
+
+#define ISNPHY(pi)	PHYTYPE_IS((pi)->pubpi.phy_type, PHY_TYPE_N)
+#define ISLCNPHY(pi)	PHYTYPE_IS((pi)->pubpi.phy_type, PHY_TYPE_LCN)
+
+#define PHY_GET_RFATTN(rfgain)	((rfgain) & 0x0f)
+#define PHY_GET_PADMIX(rfgain)	(((rfgain) & 0x10) >> 4)
+#define PHY_GET_RFGAINID(rfattn, padmix, width)	((rfattn) + ((padmix)*(width)))
+#define PHY_SAT(x, n)		((x) > ((1<<((n)-1))-1) ? ((1<<((n)-1))-1) : \
+				((x) < -(1<<((n)-1)) ? -(1<<((n)-1)) : (x)))
+#define PHY_SHIFT_ROUND(x, n)	((x) >= 0 ? ((x)+(1<<((n)-1)))>>(n) : (x)>>(n))
+#define PHY_HW_ROUND(x, s)		((x >> s) + ((x >> (s-1)) & (s != 0)))
+
+#define CH_5G_GROUP	3
+#define A_LOW_CHANS	0
+#define A_MID_CHANS	1
+#define A_HIGH_CHANS	2
+#define CH_2G_GROUP	1
+#define G_ALL_CHANS	0
+
+#define FIRST_REF5_CHANNUM	149
+#define LAST_REF5_CHANNUM	165
+#define	FIRST_5G_CHAN		14
+#define	LAST_5G_CHAN		50
+#define	FIRST_MID_5G_CHAN	14
+#define	LAST_MID_5G_CHAN	35
+#define	FIRST_HIGH_5G_CHAN	36
+#define	LAST_HIGH_5G_CHAN	41
+#define	FIRST_LOW_5G_CHAN	42
+#define	LAST_LOW_5G_CHAN	50
+
+#define BASE_LOW_5G_CHAN	4900
+#define BASE_MID_5G_CHAN	5100
+#define BASE_HIGH_5G_CHAN	5500
+
+#define CHAN5G_FREQ(chan)  (5000 + chan*5)
+#define CHAN2G_FREQ(chan)  (2407 + chan*5)
+
+#define TXP_FIRST_CCK		0
+#define TXP_LAST_CCK		3
+#define TXP_FIRST_OFDM		4
+#define TXP_LAST_OFDM		11
+#define TXP_FIRST_OFDM_20_CDD	12
+#define TXP_LAST_OFDM_20_CDD	19
+#define TXP_FIRST_MCS_20_SISO	20
+#define TXP_LAST_MCS_20_SISO	27
+#define TXP_FIRST_MCS_20_CDD	28
+#define TXP_LAST_MCS_20_CDD	35
+#define TXP_FIRST_MCS_20_STBC	36
+#define TXP_LAST_MCS_20_STBC	43
+#define TXP_FIRST_MCS_20_SDM	44
+#define TXP_LAST_MCS_20_SDM	51
+#define TXP_FIRST_OFDM_40_SISO	52
+#define TXP_LAST_OFDM_40_SISO	59
+#define TXP_FIRST_OFDM_40_CDD	60
+#define TXP_LAST_OFDM_40_CDD	67
+#define TXP_FIRST_MCS_40_SISO	68
+#define TXP_LAST_MCS_40_SISO	75
+#define TXP_FIRST_MCS_40_CDD	76
+#define TXP_LAST_MCS_40_CDD	83
+#define TXP_FIRST_MCS_40_STBC	84
+#define TXP_LAST_MCS_40_STBC	91
+#define TXP_FIRST_MCS_40_SDM	92
+#define TXP_LAST_MCS_40_SDM	99
+#define TXP_MCS_32	        100
+#define TXP_NUM_RATES		101
+#define ADJ_PWR_TBL_LEN		84
+
+#define TXP_FIRST_SISO_MCS_20	20
+#define TXP_LAST_SISO_MCS_20	27
+
+#define PHY_CORE_NUM_1	1
+#define PHY_CORE_NUM_2	2
+#define PHY_CORE_NUM_3	3
+#define PHY_CORE_NUM_4	4
+#define PHY_CORE_MAX	PHY_CORE_NUM_4
+#define PHY_CORE_0	0
+#define PHY_CORE_1	1
+#define PHY_CORE_2	2
+#define PHY_CORE_3	3
+
+#define MA_WINDOW_SZ		8
+
+#define PHY_NOISE_SAMPLE_MON		1
+#define PHY_NOISE_SAMPLE_EXTERNAL	2
+#define PHY_NOISE_WINDOW_SZ	16
+#define PHY_NOISE_GLITCH_INIT_MA 10
+#define PHY_NOISE_GLITCH_INIT_MA_BADPlCP 10
+#define PHY_NOISE_STATE_MON		0x1
+#define PHY_NOISE_STATE_EXTERNAL	0x2
+#define PHY_NOISE_SAMPLE_LOG_NUM_NPHY	10
+#define PHY_NOISE_SAMPLE_LOG_NUM_UCODE	9
+
+#define PHY_NOISE_OFFSETFACT_4322  (-103)
+#define PHY_NOISE_MA_WINDOW_SZ	2
+
+#define	PHY_RSSI_TABLE_SIZE	64
+#define RSSI_ANT_MERGE_MAX	0
+#define RSSI_ANT_MERGE_MIN	1
+#define RSSI_ANT_MERGE_AVG	2
+
+#define	PHY_TSSI_TABLE_SIZE	64
+#define	APHY_TSSI_TABLE_SIZE	256
+#define	TX_GAIN_TABLE_LENGTH	64
+#define	DEFAULT_11A_TXP_IDX	24
+#define NUM_TSSI_FRAMES        4
+#define	NULL_TSSI		0x7f
+#define	NULL_TSSI_W		0x7f7f
+
+#define PHY_PAPD_EPS_TBL_SIZE_LCNPHY 64
+
+#define LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL 9
+
+#define PHY_TXPWR_MIN		10
+#define PHY_TXPWR_MIN_NPHY	8
+#define RADIOPWR_OVERRIDE_DEF	(-1)
+
+#define PWRTBL_NUM_COEFF	3
+
+#define SPURAVOID_DISABLE	0
+#define SPURAVOID_AUTO		1
+#define SPURAVOID_FORCEON	2
+#define SPURAVOID_FORCEON2	3
+
+#define PHY_SW_TIMER_FAST		15
+#define PHY_SW_TIMER_SLOW		60
+#define PHY_SW_TIMER_GLACIAL	120
+
+#define PHY_PERICAL_AUTO	0
+#define PHY_PERICAL_FULL	1
+#define PHY_PERICAL_PARTIAL	2
+
+#define PHY_PERICAL_NODELAY	0
+#define PHY_PERICAL_INIT_DELAY	5
+#define PHY_PERICAL_ASSOC_DELAY	5
+#define PHY_PERICAL_WDOG_DELAY	5
+
+#define MPHASE_TXCAL_NUMCMDS	2
+
+#define PHY_PERICAL_MPHASE_PENDING(pi) \
+	(pi->mphase_cal_phase_id > MPHASE_CAL_STATE_IDLE)
+
+enum {
+	MPHASE_CAL_STATE_IDLE = 0,
+	MPHASE_CAL_STATE_INIT = 1,
+	MPHASE_CAL_STATE_TXPHASE0,
+	MPHASE_CAL_STATE_TXPHASE1,
+	MPHASE_CAL_STATE_TXPHASE2,
+	MPHASE_CAL_STATE_TXPHASE3,
+	MPHASE_CAL_STATE_TXPHASE4,
+	MPHASE_CAL_STATE_TXPHASE5,
+	MPHASE_CAL_STATE_PAPDCAL,
+	MPHASE_CAL_STATE_RXCAL,
+	MPHASE_CAL_STATE_RSSICAL,
+	MPHASE_CAL_STATE_IDLETSSI
+};
+
+enum phy_cal_mode {
+	CAL_FULL,
+	CAL_RECAL,
+	CAL_CURRECAL,
+	CAL_DIGCAL,
+	CAL_GCTRL,
+	CAL_SOFT,
+	CAL_DIGLO
+};
+
+#define RDR_NTIERS  1
+#define RDR_TIER_SIZE 64
+#define RDR_LIST_SIZE (512/3)
+#define RDR_EPOCH_SIZE 40
+#define RDR_NANTENNAS 2
+#define RDR_NTIER_SIZE  RDR_LIST_SIZE
+#define RDR_LP_BUFFER_SIZE 64
+#define LP_LEN_HIS_SIZE 10
+
+#define STATIC_NUM_RF 32
+#define STATIC_NUM_BB 9
+
+#define BB_MULT_MASK		0x0000ffff
+#define BB_MULT_VALID_MASK	0x80000000
+
+#define CORDIC_AG	39797
+#define	CORDIC_NI	18
+#define	FIXED(X)	((s32)((X) << 16))
+
+#define	FLOAT(X) \
+	(((X) >= 0) ? ((((X) >> 15) + 1) >> 1) : -((((-(X)) >> 15) + 1) >> 1))
+
+#define PHY_CHAIN_TX_DISABLE_TEMP	115
+#define PHY_HYSTERESIS_DELTATEMP	5
+
+#define SCAN_INPROG_PHY(pi) \
+	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN))
+
+#define PLT_INPROG_PHY(pi)      (mboolisset(pi->measure_hold, PHY_HOLD_FOR_PLT))
+
+#define ASSOC_INPROG_PHY(pi) \
+	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_ASSOC))
+
+#define SCAN_RM_IN_PROGRESS(pi) \
+	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN | PHY_HOLD_FOR_RM))
+
+#define PHY_MUTED(pi) \
+	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_MUTE))
+
+#define PUB_NOT_ASSOC(pi) \
+	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_NOT_ASSOC))
+
+struct phy_table_info {
+	uint table;
+	int q;
+	uint max;
+};
+
+struct phytbl_info {
+	const void *tbl_ptr;
+	u32 tbl_len;
+	u32 tbl_id;
+	u32 tbl_offset;
+	u32 tbl_width;
+};
+
+struct interference_info {
+	u8 curr_home_channel;
+	u16 crsminpwrthld_40_stored;
+	u16 crsminpwrthld_20L_stored;
+	u16 crsminpwrthld_20U_stored;
+	u16 init_gain_code_core1_stored;
+	u16 init_gain_code_core2_stored;
+	u16 init_gain_codeb_core1_stored;
+	u16 init_gain_codeb_core2_stored;
+	u16 init_gain_table_stored[4];
+
+	u16 clip1_hi_gain_code_core1_stored;
+	u16 clip1_hi_gain_code_core2_stored;
+	u16 clip1_hi_gain_codeb_core1_stored;
+	u16 clip1_hi_gain_codeb_core2_stored;
+	u16 nb_clip_thresh_core1_stored;
+	u16 nb_clip_thresh_core2_stored;
+	u16 init_ofdmlna2gainchange_stored[4];
+	u16 init_ccklna2gainchange_stored[4];
+	u16 clip1_lo_gain_code_core1_stored;
+	u16 clip1_lo_gain_code_core2_stored;
+	u16 clip1_lo_gain_codeb_core1_stored;
+	u16 clip1_lo_gain_codeb_core2_stored;
+	u16 w1_clip_thresh_core1_stored;
+	u16 w1_clip_thresh_core2_stored;
+	u16 radio_2056_core1_rssi_gain_stored;
+	u16 radio_2056_core2_rssi_gain_stored;
+	u16 energy_drop_timeout_len_stored;
+
+	u16 ed_crs40_assertthld0_stored;
+	u16 ed_crs40_assertthld1_stored;
+	u16 ed_crs40_deassertthld0_stored;
+	u16 ed_crs40_deassertthld1_stored;
+	u16 ed_crs20L_assertthld0_stored;
+	u16 ed_crs20L_assertthld1_stored;
+	u16 ed_crs20L_deassertthld0_stored;
+	u16 ed_crs20L_deassertthld1_stored;
+	u16 ed_crs20U_assertthld0_stored;
+	u16 ed_crs20U_assertthld1_stored;
+	u16 ed_crs20U_deassertthld0_stored;
+	u16 ed_crs20U_deassertthld1_stored;
+
+	u16 badplcp_ma;
+	u16 badplcp_ma_previous;
+	u16 badplcp_ma_total;
+	u16 badplcp_ma_list[MA_WINDOW_SZ];
+	int badplcp_ma_index;
+	s16 pre_badplcp_cnt;
+	s16 bphy_pre_badplcp_cnt;
+
+	u16 init_gain_core1;
+	u16 init_gain_core2;
+	u16 init_gainb_core1;
+	u16 init_gainb_core2;
+	u16 init_gain_rfseq[4];
+
+	u16 crsminpwr0;
+	u16 crsminpwrl0;
+	u16 crsminpwru0;
+
+	s16 crsminpwr_index;
+
+	u16 radio_2057_core1_rssi_wb1a_gc_stored;
+	u16 radio_2057_core2_rssi_wb1a_gc_stored;
+	u16 radio_2057_core1_rssi_wb1g_gc_stored;
+	u16 radio_2057_core2_rssi_wb1g_gc_stored;
+	u16 radio_2057_core1_rssi_wb2_gc_stored;
+	u16 radio_2057_core2_rssi_wb2_gc_stored;
+	u16 radio_2057_core1_rssi_nb_gc_stored;
+	u16 radio_2057_core2_rssi_nb_gc_stored;
+};
+
+struct aci_save_gphy {
+	u16 rc_cal_ovr;
+	u16 phycrsth1;
+	u16 phycrsth2;
+	u16 init_n1p1_gain;
+	u16 p1_p2_gain;
+	u16 n1_n2_gain;
+	u16 n1_p1_gain;
+	u16 div_search_gain;
+	u16 div_p1_p2_gain;
+	u16 div_search_gn_change;
+	u16 table_7_2;
+	u16 table_7_3;
+	u16 cckshbits_gnref;
+	u16 clip_thresh;
+	u16 clip2_thresh;
+	u16 clip3_thresh;
+	u16 clip_p2_thresh;
+	u16 clip_pwdn_thresh;
+	u16 clip_n1p1_thresh;
+	u16 clip_n1_pwdn_thresh;
+	u16 bbconfig;
+	u16 cthr_sthr_shdin;
+	u16 energy;
+	u16 clip_p1_p2_thresh;
+	u16 threshold;
+	u16 reg15;
+	u16 reg16;
+	u16 reg17;
+	u16 div_srch_idx;
+	u16 div_srch_p1_p2;
+	u16 div_srch_gn_back;
+	u16 ant_dwell;
+	u16 ant_wr_settle;
+};
+
+struct lo_complex_abgphy_info {
+	s8 i;
+	s8 q;
+};
+
+struct nphy_iq_comp {
+	s16 a0;
+	s16 b0;
+	s16 a1;
+	s16 b1;
+};
+
+struct nphy_txpwrindex {
+	s8 index;
+	s8 index_internal;
+	s8 index_internal_save;
+	u16 AfectrlOverride;
+	u16 AfeCtrlDacGain;
+	u16 rad_gain;
+	u8 bbmult;
+	u16 iqcomp_a;
+	u16 iqcomp_b;
+	u16 locomp;
+};
+
+struct txiqcal_cache {
+
+	u16 txcal_coeffs_2G[8];
+	u16 txcal_radio_regs_2G[8];
+	struct nphy_iq_comp rxcal_coeffs_2G;
+
+	u16 txcal_coeffs_5G[8];
+	u16 txcal_radio_regs_5G[8];
+	struct nphy_iq_comp rxcal_coeffs_5G;
+};
+
+struct nphy_pwrctrl {
+	s8 max_pwr_2g;
+	s8 idle_targ_2g;
+	s16 pwrdet_2g_a1;
+	s16 pwrdet_2g_b0;
+	s16 pwrdet_2g_b1;
+	s8 max_pwr_5gm;
+	s8 idle_targ_5gm;
+	s8 max_pwr_5gh;
+	s8 max_pwr_5gl;
+	s16 pwrdet_5gm_a1;
+	s16 pwrdet_5gm_b0;
+	s16 pwrdet_5gm_b1;
+	s16 pwrdet_5gl_a1;
+	s16 pwrdet_5gl_b0;
+	s16 pwrdet_5gl_b1;
+	s16 pwrdet_5gh_a1;
+	s16 pwrdet_5gh_b0;
+	s16 pwrdet_5gh_b1;
+	s8 idle_targ_5gl;
+	s8 idle_targ_5gh;
+	s8 idle_tssi_2g;
+	s8 idle_tssi_5g;
+	s8 idle_tssi;
+	s16 a1;
+	s16 b0;
+	s16 b1;
+};
+
+struct nphy_txgains {
+	u16 txlpf[2];
+	u16 txgm[2];
+	u16 pga[2];
+	u16 pad[2];
+	u16 ipa[2];
+};
+
+#define PHY_NOISEVAR_BUFSIZE 10
+
+struct nphy_noisevar_buf {
+	int bufcount;
+	int tone_id[PHY_NOISEVAR_BUFSIZE];
+	u32 noise_vars[PHY_NOISEVAR_BUFSIZE];
+	u32 min_noise_vars[PHY_NOISEVAR_BUFSIZE];
+};
+
+struct rssical_cache {
+	u16 rssical_radio_regs_2G[2];
+	u16 rssical_phyregs_2G[12];
+
+	u16 rssical_radio_regs_5G[2];
+	u16 rssical_phyregs_5G[12];
+};
+
+struct lcnphy_cal_results {
+
+	u16 txiqlocal_a;
+	u16 txiqlocal_b;
+	u16 txiqlocal_didq;
+	u8 txiqlocal_ei0;
+	u8 txiqlocal_eq0;
+	u8 txiqlocal_fi0;
+	u8 txiqlocal_fq0;
+
+	u16 txiqlocal_bestcoeffs[11];
+	u16 txiqlocal_bestcoeffs_valid;
+
+	u32 papd_eps_tbl[PHY_PAPD_EPS_TBL_SIZE_LCNPHY];
+	u16 analog_gain_ref;
+	u16 lut_begin;
+	u16 lut_end;
+	u16 lut_step;
+	u16 rxcompdbm;
+	u16 papdctrl;
+	u16 sslpnCalibClkEnCtrl;
+
+	u16 rxiqcal_coeff_a0;
+	u16 rxiqcal_coeff_b0;
+};
+
+struct shared_phy {
+	struct brcms_phy *phy_head;
+	uint unit;
+	struct phy_shim_info *physhim;
+	uint corerev;
+	u32 machwcap;
+	bool up;
+	bool clk;
+	uint now;
+	u16 vid;
+	u16 did;
+	uint chip;
+	uint chiprev;
+	uint chippkg;
+	uint sromrev;
+	uint boardtype;
+	uint boardrev;
+	u32 boardflags;
+	u32 boardflags2;
+	uint fast_timer;
+	uint slow_timer;
+	uint glacial_timer;
+	u8 rx_antdiv;
+	s8 phy_noise_window[MA_WINDOW_SZ];
+	uint phy_noise_index;
+	u8 hw_phytxchain;
+	u8 hw_phyrxchain;
+	u8 phytxchain;
+	u8 phyrxchain;
+	u8 rssi_mode;
+	bool _rifs_phy;
+};
+
+struct brcms_phy_pub {
+	uint phy_type;
+	uint phy_rev;
+	u8 phy_corenum;
+	u16 radioid;
+	u8 radiorev;
+	u8 radiover;
+
+	uint coreflags;
+	uint ana_rev;
+	bool abgphy_encore;
+};
+
+struct phy_func_ptr {
+	void (*init)(struct brcms_phy *);
+	void (*calinit)(struct brcms_phy *);
+	void (*chanset)(struct brcms_phy *, u16 chanspec);
+	void (*txpwrrecalc)(struct brcms_phy *);
+	int (*longtrn)(struct brcms_phy *, int);
+	void (*txiqccget)(struct brcms_phy *, u16 *, u16 *);
+	void (*txiqccset)(struct brcms_phy *, u16, u16);
+	u16 (*txloccget)(struct brcms_phy *);
+	void (*radioloftget)(struct brcms_phy *, u8 *, u8 *, u8 *, u8 *);
+	void (*carrsuppr)(struct brcms_phy *);
+	s32 (*rxsigpwr)(struct brcms_phy *, s32);
+	void (*detach)(struct brcms_phy *);
+};
+
+struct brcms_phy {
+	struct brcms_phy_pub pubpi_ro;
+	struct shared_phy *sh;
+	struct phy_func_ptr pi_fptr;
+
+	union {
+		struct brcms_phy_lcnphy *pi_lcnphy;
+	} u;
+	bool user_txpwr_at_rfport;
+
+	struct bcma_device *d11core;
+	struct brcms_phy *next;
+	struct brcms_phy_pub pubpi;
+
+	bool do_initcal;
+	bool phytest_on;
+	bool ofdm_rateset_war;
+	bool bf_preempt_4306;
+	u16 radio_chanspec;
+	u8 antsel_type;
+	u16 bw;
+	u8 txpwr_percent;
+	bool phy_init_por;
+
+	bool init_in_progress;
+	bool initialized;
+	bool sbtml_gm;
+	uint refcnt;
+	bool watchdog_override;
+	u8 phynoise_state;
+	uint phynoise_now;
+	int phynoise_chan_watchdog;
+	bool phynoise_polling;
+	bool disable_percal;
+	u32 measure_hold;
+
+	s16 txpa_2g[PWRTBL_NUM_COEFF];
+	s16 txpa_2g_low_temp[PWRTBL_NUM_COEFF];
+	s16 txpa_2g_high_temp[PWRTBL_NUM_COEFF];
+	s16 txpa_5g_low[PWRTBL_NUM_COEFF];
+	s16 txpa_5g_mid[PWRTBL_NUM_COEFF];
+	s16 txpa_5g_hi[PWRTBL_NUM_COEFF];
+
+	u8 tx_srom_max_2g;
+	u8 tx_srom_max_5g_low;
+	u8 tx_srom_max_5g_mid;
+	u8 tx_srom_max_5g_hi;
+	u8 tx_srom_max_rate_2g[TXP_NUM_RATES];
+	u8 tx_srom_max_rate_5g_low[TXP_NUM_RATES];
+	u8 tx_srom_max_rate_5g_mid[TXP_NUM_RATES];
+	u8 tx_srom_max_rate_5g_hi[TXP_NUM_RATES];
+	u8 tx_user_target[TXP_NUM_RATES];
+	s8 tx_power_offset[TXP_NUM_RATES];
+	u8 tx_power_target[TXP_NUM_RATES];
+
+	struct brcms_phy_srom_fem srom_fem2g;
+	struct brcms_phy_srom_fem srom_fem5g;
+
+	u8 tx_power_max;
+	u8 tx_power_max_rate_ind;
+	bool hwpwrctrl;
+	u8 nphy_txpwrctrl;
+	s8 nphy_txrx_chain;
+	bool phy_5g_pwrgain;
+
+	u16 phy_wreg;
+	u16 phy_wreg_limit;
+
+	s8 n_preamble_override;
+	u8 antswitch;
+	u8 aa2g, aa5g;
+
+	s8 idle_tssi[CH_5G_GROUP];
+	s8 target_idle_tssi;
+	s8 txpwr_est_Pout;
+	u8 tx_power_min;
+	u8 txpwr_limit[TXP_NUM_RATES];
+	u8 txpwr_env_limit[TXP_NUM_RATES];
+	u8 adj_pwr_tbl_nphy[ADJ_PWR_TBL_LEN];
+
+	bool channel_14_wide_filter;
+
+	bool txpwroverride;
+	bool txpwridx_override_aphy;
+	s16 radiopwr_override;
+	u16 hwpwr_txcur;
+	u8 saved_txpwr_idx;
+
+	bool edcrs_threshold_lock;
+
+	u32 tr_R_gain_val;
+	u32 tr_T_gain_val;
+
+	s16 ofdm_analog_filt_bw_override;
+	s16 cck_analog_filt_bw_override;
+	s16 ofdm_rccal_override;
+	s16 cck_rccal_override;
+	u16 extlna_type;
+
+	uint interference_mode_crs_time;
+	u16 crsglitch_prev;
+	bool interference_mode_crs;
+
+	u32 phy_tx_tone_freq;
+	uint phy_lastcal;
+	bool phy_forcecal;
+	bool phy_fixed_noise;
+	u32 xtalfreq;
+	u8 pdiv;
+	s8 carrier_suppr_disable;
+
+	bool phy_bphy_evm;
+	bool phy_bphy_rfcs;
+	s8 phy_scraminit;
+	u8 phy_gpiosel;
+
+	s16 phy_txcore_disable_temp;
+	s16 phy_txcore_enable_temp;
+	s8 phy_tempsense_offset;
+	bool phy_txcore_heatedup;
+
+	u16 radiopwr;
+	u16 bb_atten;
+	u16 txctl1;
+
+	u16 mintxbias;
+	u16 mintxmag;
+	struct lo_complex_abgphy_info gphy_locomp_iq
+			[STATIC_NUM_RF][STATIC_NUM_BB];
+	s8 stats_11b_txpower[STATIC_NUM_RF][STATIC_NUM_BB];
+	u16 gain_table[TX_GAIN_TABLE_LENGTH];
+	bool loopback_gain;
+	s16 max_lpback_gain_hdB;
+	s16 trsw_rx_gain_hdB;
+	u8 power_vec[8];
+
+	u16 rc_cal;
+	int nrssi_table_delta;
+	int nrssi_slope_scale;
+	int nrssi_slope_offset;
+	int min_rssi;
+	int max_rssi;
+
+	s8 txpwridx;
+	u8 min_txpower;
+
+	u8 a_band_high_disable;
+
+	u16 tx_vos;
+	u16 global_tx_bb_dc_bias_loft;
+
+	int rf_max;
+	int bb_max;
+	int rf_list_size;
+	int bb_list_size;
+	u16 *rf_attn_list;
+	u16 *bb_attn_list;
+	u16 padmix_mask;
+	u16 padmix_reg;
+	u16 *txmag_list;
+	uint txmag_len;
+	bool txmag_enable;
+
+	s8 *a_tssi_to_dbm;
+	s8 *m_tssi_to_dbm;
+	s8 *l_tssi_to_dbm;
+	s8 *h_tssi_to_dbm;
+	u8 *hwtxpwr;
+
+	u16 freqtrack_saved_regs[2];
+	int cur_interference_mode;
+	bool hwpwrctrl_capable;
+	bool temppwrctrl_capable;
+
+	uint phycal_nslope;
+	uint phycal_noffset;
+	uint phycal_mlo;
+	uint phycal_txpower;
+
+	u8 phy_aa2g;
+
+	bool nphy_tableloaded;
+	s8 nphy_rssisel;
+	u32 nphy_bb_mult_save;
+	u16 nphy_txiqlocal_bestc[11];
+	bool nphy_txiqlocal_coeffsvalid;
+	struct nphy_txpwrindex nphy_txpwrindex[PHY_CORE_NUM_2];
+	struct nphy_pwrctrl nphy_pwrctrl_info[PHY_CORE_NUM_2];
+	u16 cck2gpo;
+	u32 ofdm2gpo;
+	u32 ofdm5gpo;
+	u32 ofdm5glpo;
+	u32 ofdm5ghpo;
+	u8 bw402gpo;
+	u8 bw405gpo;
+	u8 bw405glpo;
+	u8 bw405ghpo;
+	u8 cdd2gpo;
+	u8 cdd5gpo;
+	u8 cdd5glpo;
+	u8 cdd5ghpo;
+	u8 stbc2gpo;
+	u8 stbc5gpo;
+	u8 stbc5glpo;
+	u8 stbc5ghpo;
+	u8 bwdup2gpo;
+	u8 bwdup5gpo;
+	u8 bwdup5glpo;
+	u8 bwdup5ghpo;
+	u16 mcs2gpo[8];
+	u16 mcs5gpo[8];
+	u16 mcs5glpo[8];
+	u16 mcs5ghpo[8];
+	u32 nphy_rxcalparams;
+
+	u8 phy_spuravoid;
+	bool phy_isspuravoid;
+
+	u8 phy_pabias;
+	u8 nphy_papd_skip;
+	u8 nphy_tssi_slope;
+
+	s16 nphy_noise_win[PHY_CORE_MAX][PHY_NOISE_WINDOW_SZ];
+	u8 nphy_noise_index;
+
+	bool nphy_gain_boost;
+	bool nphy_elna_gain_config;
+	u16 old_bphy_test;
+	u16 old_bphy_testcontrol;
+
+	bool phyhang_avoid;
+
+	bool rssical_nphy;
+	u8 nphy_perical;
+	uint nphy_perical_last;
+	u8 cal_type_override;
+	u8 mphase_cal_phase_id;
+	u8 mphase_txcal_cmdidx;
+	u8 mphase_txcal_numcmds;
+	u16 mphase_txcal_bestcoeffs[11];
+	u16 nphy_txiqlocal_chanspec;
+	u16 nphy_iqcal_chanspec_2G;
+	u16 nphy_iqcal_chanspec_5G;
+	u16 nphy_rssical_chanspec_2G;
+	u16 nphy_rssical_chanspec_5G;
+	struct wlapi_timer *phycal_timer;
+	bool use_int_tx_iqlo_cal_nphy;
+	bool internal_tx_iqlo_cal_tapoff_intpa_nphy;
+	s16 nphy_lastcal_temp;
+
+	struct txiqcal_cache calibration_cache;
+	struct rssical_cache rssical_cache;
+
+	u8 nphy_txpwr_idx[2];
+	u8 nphy_papd_cal_type;
+	uint nphy_papd_last_cal;
+	u16 nphy_papd_tx_gain_at_last_cal[2];
+	u8 nphy_papd_cal_gain_index[2];
+	s16 nphy_papd_epsilon_offset[2];
+	bool nphy_papd_recal_enable;
+	u32 nphy_papd_recal_counter;
+	bool nphy_force_papd_cal;
+	bool nphy_papdcomp;
+	bool ipa2g_on;
+	bool ipa5g_on;
+
+	u16 classifier_state;
+	u16 clip_state[2];
+	uint nphy_deaf_count;
+	u8 rxiq_samps;
+	u8 rxiq_antsel;
+
+	u16 rfctrlIntc1_save;
+	u16 rfctrlIntc2_save;
+	bool first_cal_after_assoc;
+	u16 tx_rx_cal_radio_saveregs[22];
+	u16 tx_rx_cal_phy_saveregs[15];
+
+	u8 nphy_cal_orig_pwr_idx[2];
+	u8 nphy_txcal_pwr_idx[2];
+	u8 nphy_rxcal_pwr_idx[2];
+	u16 nphy_cal_orig_tx_gain[2];
+	struct nphy_txgains nphy_cal_target_gain;
+	u16 nphy_txcal_bbmult;
+	u16 nphy_gmval;
+
+	u16 nphy_saved_bbconf;
+
+	bool nphy_gband_spurwar_en;
+	bool nphy_gband_spurwar2_en;
+	bool nphy_aband_spurwar_en;
+	u16 nphy_rccal_value;
+	u16 nphy_crsminpwr[3];
+	struct nphy_noisevar_buf nphy_saved_noisevars;
+	bool nphy_anarxlpf_adjusted;
+	bool nphy_crsminpwr_adjusted;
+	bool nphy_noisevars_adjusted;
+
+	bool nphy_rxcal_active;
+	u16 radar_percal_mask;
+	bool dfs_lp_buffer_nphy;
+
+	u16 nphy_fineclockgatecontrol;
+
+	s8 rx2tx_biasentry;
+
+	u16 crsminpwr0;
+	u16 crsminpwrl0;
+	u16 crsminpwru0;
+	s16 noise_crsminpwr_index;
+	u16 init_gain_core1;
+	u16 init_gain_core2;
+	u16 init_gainb_core1;
+	u16 init_gainb_core2;
+	u8 aci_noise_curr_channel;
+	u16 init_gain_rfseq[4];
+
+	bool radio_is_on;
+
+	bool nphy_sample_play_lpf_bw_ctl_ovr;
+
+	u16 tbl_data_hi;
+	u16 tbl_data_lo;
+	u16 tbl_addr;
+
+	uint tbl_save_id;
+	uint tbl_save_offset;
+
+	u8 txpwrctrl;
+	s8 txpwrindex[PHY_CORE_MAX];
+
+	u8 phycal_tempdelta;
+	u32 mcs20_po;
+	u32 mcs40_po;
+	struct wiphy *wiphy;
+};
+
+struct cs32 {
+	s32 q;
+	s32 i;
+};
+
+struct radio_regs {
+	u16 address;
+	u32 init_a;
+	u32 init_g;
+	u8 do_init_a;
+	u8 do_init_g;
+};
+
+struct radio_20xx_regs {
+	u16 address;
+	u8 init;
+	u8 do_init;
+};
+
+struct lcnphy_radio_regs {
+	u16 address;
+	u8 init_a;
+	u8 init_g;
+	u8 do_init_a;
+	u8 do_init_g;
+};
+
+u16 read_phy_reg(struct brcms_phy *pi, u16 addr);
+void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val);
+void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val);
+void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val);
+void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val);
+
+u16 read_radio_reg(struct brcms_phy *pi, u16 addr);
+void or_radio_reg(struct brcms_phy *pi, u16 addr, u16 val);
+void and_radio_reg(struct brcms_phy *pi, u16 addr, u16 val);
+void mod_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val);
+void xor_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask);
+
+void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val);
+
+void wlc_phyreg_enter(struct brcms_phy_pub *pih);
+void wlc_phyreg_exit(struct brcms_phy_pub *pih);
+void wlc_radioreg_enter(struct brcms_phy_pub *pih);
+void wlc_radioreg_exit(struct brcms_phy_pub *pih);
+
+void wlc_phy_read_table(struct brcms_phy *pi,
+			const struct phytbl_info *ptbl_info,
+			u16 tblAddr, u16 tblDataHi, u16 tblDatalo);
+void wlc_phy_write_table(struct brcms_phy *pi,
+			 const struct phytbl_info *ptbl_info,
+			 u16 tblAddr, u16 tblDataHi, u16 tblDatalo);
+void wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, uint tbl_offset,
+			u16 tblAddr, u16 tblDataHi, u16 tblDataLo);
+void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val);
+
+void write_phy_channel_reg(struct brcms_phy *pi, uint val);
+void wlc_phy_txpower_update_shm(struct brcms_phy *pi);
+
+u8 wlc_phy_nbits(s32 value);
+void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_dB, u8 core);
+
+uint wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi,
+				      struct radio_20xx_regs *radioregs);
+uint wlc_phy_init_radio_regs(struct brcms_phy *pi,
+			     const struct radio_regs *radioregs,
+			     u16 core_offset);
+
+void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi);
+
+void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on);
+void wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, s32 *eps_imag);
+
+void wlc_phy_cal_perical_mphase_reset(struct brcms_phy *pi);
+void wlc_phy_cal_perical_mphase_restart(struct brcms_phy *pi);
+
+bool wlc_phy_attach_nphy(struct brcms_phy *pi);
+bool wlc_phy_attach_lcnphy(struct brcms_phy *pi);
+
+void wlc_phy_detach_lcnphy(struct brcms_phy *pi);
+
+void wlc_phy_init_nphy(struct brcms_phy *pi);
+void wlc_phy_init_lcnphy(struct brcms_phy *pi);
+
+void wlc_phy_cal_init_nphy(struct brcms_phy *pi);
+void wlc_phy_cal_init_lcnphy(struct brcms_phy *pi);
+
+void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, u16 chanspec);
+void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec);
+void wlc_phy_chanspec_set_fixup_lcnphy(struct brcms_phy *pi, u16 chanspec);
+int wlc_phy_channel2freq(uint channel);
+int wlc_phy_chanspec_freq2bandrange_lpssn(uint);
+int wlc_phy_chanspec_bandrange_get(struct brcms_phy *, u16 chanspec);
+
+void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode);
+s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi);
+
+void wlc_phy_txpower_recalc_target_nphy(struct brcms_phy *pi);
+void wlc_lcnphy_txpower_recalc_target(struct brcms_phy *pi);
+void wlc_phy_txpower_recalc_target_lcnphy(struct brcms_phy *pi);
+
+void wlc_lcnphy_set_tx_pwr_by_index(struct brcms_phy *pi, int index);
+void wlc_lcnphy_tx_pu(struct brcms_phy *pi, bool bEnable);
+void wlc_lcnphy_stop_tx_tone(struct brcms_phy *pi);
+void wlc_lcnphy_start_tx_tone(struct brcms_phy *pi, s32 f_kHz, u16 max_val,
+			      bool iqcalmode);
+
+void wlc_phy_txpower_sromlimit_get_nphy(struct brcms_phy *pi, uint chan,
+					u8 *max_pwr, u8 rate_id);
+void wlc_phy_ofdm_to_mcs_powers_nphy(u8 *power, u8 rate_mcs_start,
+				     u8 rate_mcs_end, u8 rate_ofdm_start);
+void wlc_phy_mcs_to_ofdm_powers_nphy(u8 *power, u8 rate_ofdm_start,
+				     u8 rate_ofdm_end, u8 rate_mcs_start);
+
+u16 wlc_lcnphy_tempsense(struct brcms_phy *pi, bool mode);
+s16 wlc_lcnphy_tempsense_new(struct brcms_phy *pi, bool mode);
+s8 wlc_lcnphy_tempsense_degree(struct brcms_phy *pi, bool mode);
+s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode);
+void wlc_phy_carrier_suppress_lcnphy(struct brcms_phy *pi);
+void wlc_lcnphy_crsuprs(struct brcms_phy *pi, int channel);
+void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode);
+void wlc_2064_vco_cal(struct brcms_phy *pi);
+
+void wlc_phy_txpower_recalc_target(struct brcms_phy *pi);
+
+#define LCNPHY_TBL_ID_PAPDCOMPDELTATBL	0x18
+#define LCNPHY_TX_POWER_TABLE_SIZE	128
+#define LCNPHY_MAX_TX_POWER_INDEX	(LCNPHY_TX_POWER_TABLE_SIZE - 1)
+#define LCNPHY_TBL_ID_TXPWRCTL	0x07
+#define LCNPHY_TX_PWR_CTRL_OFF	0
+#define LCNPHY_TX_PWR_CTRL_SW		(0x1 << 15)
+#define LCNPHY_TX_PWR_CTRL_HW         ((0x1 << 15) | \
+					(0x1 << 14) | \
+					(0x1 << 13))
+
+#define LCNPHY_TX_PWR_CTRL_TEMPBASED	0xE001
+
+void wlc_lcnphy_write_table(struct brcms_phy *pi,
+			    const struct phytbl_info *pti);
+void wlc_lcnphy_read_table(struct brcms_phy *pi, struct phytbl_info *pti);
+void wlc_lcnphy_set_tx_iqcc(struct brcms_phy *pi, u16 a, u16 b);
+void wlc_lcnphy_set_tx_locc(struct brcms_phy *pi, u16 didq);
+void wlc_lcnphy_get_tx_iqcc(struct brcms_phy *pi, u16 *a, u16 *b);
+u16 wlc_lcnphy_get_tx_locc(struct brcms_phy *pi);
+void wlc_lcnphy_get_radio_loft(struct brcms_phy *pi, u8 *ei0, u8 *eq0, u8 *fi0,
+			       u8 *fq0);
+void wlc_lcnphy_calib_modes(struct brcms_phy *pi, uint mode);
+void wlc_lcnphy_deaf_mode(struct brcms_phy *pi, bool mode);
+bool wlc_phy_tpc_isenabled_lcnphy(struct brcms_phy *pi);
+void wlc_lcnphy_tx_pwr_update_npt(struct brcms_phy *pi);
+s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1);
+void wlc_lcnphy_get_tssi(struct brcms_phy *pi, s8 *ofdm_pwr, s8 *cck_pwr);
+void wlc_lcnphy_tx_power_adjustment(struct brcms_phy_pub *ppi);
+
+s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index);
+
+#define NPHY_MAX_HPVGA1_INDEX		10
+#define NPHY_DEF_HPVGA1_INDEXLIMIT	7
+
+struct phy_iq_est {
+	s32 iq_prod;
+	u32 i_pwr;
+	u32 q_pwr;
+};
+
+void wlc_phy_stay_in_carriersearch_nphy(struct brcms_phy *pi, bool enable);
+void wlc_nphy_deaf_mode(struct brcms_phy *pi, bool mode);
+
+#define wlc_phy_write_table_nphy(pi, pti) \
+	wlc_phy_write_table(pi, pti, 0x72, 0x74, 0x73)
+
+#define wlc_phy_read_table_nphy(pi, pti) \
+	wlc_phy_read_table(pi, pti, 0x72, 0x74, 0x73)
+
+#define wlc_nphy_table_addr(pi, id, off) \
+	wlc_phy_table_addr((pi), (id), (off), 0x72, 0x74, 0x73)
+
+#define wlc_nphy_table_data_write(pi, w, v) \
+	wlc_phy_table_data_write((pi), (w), (v))
+
+void wlc_phy_table_read_nphy(struct brcms_phy *pi, u32, u32 l, u32 o, u32 w,
+			     void *d);
+void wlc_phy_table_write_nphy(struct brcms_phy *pi, u32, u32, u32, u32,
+			      const void *);
+
+#define	PHY_IPA(pi) \
+	((pi->ipa2g_on && CHSPEC_IS2G(pi->radio_chanspec)) || \
+	 (pi->ipa5g_on && CHSPEC_IS5G(pi->radio_chanspec)))
+
+#define BRCMS_PHY_WAR_PR51571(pi) \
+	if (NREV_LT((pi)->pubpi.phy_rev, 3)) \
+		(void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol))
+
+void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype);
+void wlc_phy_aci_reset_nphy(struct brcms_phy *pi);
+void wlc_phy_pa_override_nphy(struct brcms_phy *pi, bool en);
+
+u8 wlc_phy_get_chan_freq_range_nphy(struct brcms_phy *pi, uint chan);
+void wlc_phy_switch_radio_nphy(struct brcms_phy *pi, bool on);
+
+void wlc_phy_stf_chain_upd_nphy(struct brcms_phy *pi);
+
+void wlc_phy_force_rfseq_nphy(struct brcms_phy *pi, u8 cmd);
+s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi);
+
+u16 wlc_phy_classifier_nphy(struct brcms_phy *pi, u16 mask, u16 val);
+
+void wlc_phy_rx_iq_est_nphy(struct brcms_phy *pi, struct phy_iq_est *est,
+			    u16 num_samps, u8 wait_time, u8 wait_for_crs);
+
+void wlc_phy_rx_iq_coeffs_nphy(struct brcms_phy *pi, u8 write,
+			       struct nphy_iq_comp *comp);
+void wlc_phy_aci_and_noise_reduction_nphy(struct brcms_phy *pi);
+
+void wlc_phy_rxcore_setstate_nphy(struct brcms_phy_pub *pih, u8 rxcore_bitmask);
+u8 wlc_phy_rxcore_getstate_nphy(struct brcms_phy_pub *pih);
+
+void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type);
+void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi);
+void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi);
+void wlc_phy_txpwr_papd_cal_nphy(struct brcms_phy *pi);
+u16 wlc_phy_txpwr_idx_get_nphy(struct brcms_phy *pi);
+
+struct nphy_txgains wlc_phy_get_tx_gain_nphy(struct brcms_phy *pi);
+int wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi,
+			    struct nphy_txgains target_gain, bool full, bool m);
+int wlc_phy_cal_rxiq_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
+			  u8 type, bool d);
+void wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask,
+			      s8 txpwrindex, bool res);
+void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core, u8 rssi_type);
+int wlc_phy_poll_rssi_nphy(struct brcms_phy *pi, u8 rssi_type,
+			   s32 *rssi_buf, u8 nsamps);
+void wlc_phy_rssi_cal_nphy(struct brcms_phy *pi);
+int wlc_phy_aci_scan_nphy(struct brcms_phy *pi);
+void wlc_phy_cal_txgainctrl_nphy(struct brcms_phy *pi, s32 dBm_targetpower,
+				 bool debug);
+int wlc_phy_tx_tone_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val, u8 mode,
+			 u8, bool);
+void wlc_phy_stopplayback_nphy(struct brcms_phy *pi);
+void wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf,
+			      u8 num_samps);
+void wlc_phy_radio205x_vcocal_nphy(struct brcms_phy *pi);
+
+int wlc_phy_rssi_compute_nphy(struct brcms_phy *pi, struct d11rxhdr *rxh);
+
+#define NPHY_TESTPATTERN_BPHY_EVM   0
+#define NPHY_TESTPATTERN_BPHY_RFCS  1
+
+void wlc_phy_nphy_tkip_rifs_war(struct brcms_phy *pi, u8 rifs);
+
+void wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset,
+				s8 *ofdmoffset);
+s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, u16 chanspec);
+
+bool wlc_phy_n_txpower_ipa_ison(struct brcms_phy *pih);
+#endif				/* _BRCM_PHY_INT_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c
new file mode 100644
index 0000000..9fb0d9f
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c
@@ -0,0 +1,5242 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/cordic.h>
+
+#include <pmu.h>
+#include <d11.h>
+#include <phy_shim.h>
+#include "phy_qmath.h"
+#include "phy_hal.h"
+#include "phy_radio.h"
+#include "phytbl_lcn.h"
+#include "phy_lcn.h"
+
+#define PLL_2064_NDIV		90
+#define PLL_2064_LOW_END_VCO	3000
+#define PLL_2064_LOW_END_KVCO	27
+#define PLL_2064_HIGH_END_VCO	4200
+#define PLL_2064_HIGH_END_KVCO	68
+#define PLL_2064_LOOP_BW_DOUBLER	200
+#define PLL_2064_D30_DOUBLER		10500
+#define PLL_2064_LOOP_BW	260
+#define PLL_2064_D30		8000
+#define PLL_2064_CAL_REF_TO	8
+#define PLL_2064_MHZ		1000000
+#define PLL_2064_OPEN_LOOP_DELAY	5
+
+#define TEMPSENSE			1
+#define VBATSENSE           2
+
+#define NOISE_IF_UPD_CHK_INTERVAL	1
+#define NOISE_IF_UPD_RST_INTERVAL	60
+#define NOISE_IF_UPD_THRESHOLD_CNT	1
+#define NOISE_IF_UPD_TRHRESHOLD	50
+#define NOISE_IF_UPD_TIMEOUT		1000
+#define NOISE_IF_OFF			0
+#define NOISE_IF_CHK			1
+#define NOISE_IF_ON			2
+
+#define PAPD_BLANKING_PROFILE		3
+#define PAPD2LUT			0
+#define PAPD_CORR_NORM			0
+#define PAPD_BLANKING_THRESHOLD		0
+#define PAPD_STOP_AFTER_LAST_UPDATE	0
+
+#define LCN_TARGET_PWR  60
+
+#define LCN_VBAT_OFFSET_433X 34649679
+#define LCN_VBAT_SLOPE_433X  8258032
+
+#define LCN_VBAT_SCALE_NOM  53
+#define LCN_VBAT_SCALE_DEN  432
+
+#define LCN_TEMPSENSE_OFFSET  80812
+#define LCN_TEMPSENSE_DEN  2647
+
+#define LCN_BW_LMT	200
+#define LCN_CUR_LMT	1250
+#define LCN_MULT	1
+#define LCN_VCO_DIV	30
+#define LCN_OFFSET	680
+#define LCN_FACT	490
+#define LCN_CUR_DIV	2640
+
+#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT \
+	(0 + 8)
+#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK \
+	(0x7f << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT)
+
+#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT \
+	(0 + 8)
+#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK \
+	(0x7f << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT)
+
+#define wlc_lcnphy_enable_tx_gain_override(pi) \
+	wlc_lcnphy_set_tx_gain_override(pi, true)
+#define wlc_lcnphy_disable_tx_gain_override(pi)	\
+	wlc_lcnphy_set_tx_gain_override(pi, false)
+
+#define wlc_lcnphy_iqcal_active(pi)	\
+	(read_phy_reg((pi), 0x451) & \
+	 ((0x1 << 15) | (0x1 << 14)))
+
+#define txpwrctrl_off(pi) (0x7 != ((read_phy_reg(pi, 0x4a4) & 0xE000) >> 13))
+#define wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)	\
+	(pi->temppwrctrl_capable)
+#define wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) \
+	(pi->hwpwrctrl_capable)
+
+#define SWCTRL_BT_TX		0x18
+#define SWCTRL_OVR_DISABLE	0x40
+
+#define	AFE_CLK_INIT_MODE_TXRX2X	1
+#define	AFE_CLK_INIT_MODE_PAPD		0
+
+#define LCNPHY_TBL_ID_IQLOCAL			0x00
+
+#define LCNPHY_TBL_ID_RFSEQ         0x08
+#define LCNPHY_TBL_ID_GAIN_IDX		0x0d
+#define LCNPHY_TBL_ID_SW_CTRL			0x0f
+#define LCNPHY_TBL_ID_GAIN_TBL		0x12
+#define LCNPHY_TBL_ID_SPUR			0x14
+#define LCNPHY_TBL_ID_SAMPLEPLAY		0x15
+#define LCNPHY_TBL_ID_SAMPLEPLAY1		0x16
+
+#define LCNPHY_TX_PWR_CTRL_RATE_OFFSET	832
+#define LCNPHY_TX_PWR_CTRL_MAC_OFFSET	128
+#define LCNPHY_TX_PWR_CTRL_GAIN_OFFSET	192
+#define LCNPHY_TX_PWR_CTRL_IQ_OFFSET		320
+#define LCNPHY_TX_PWR_CTRL_LO_OFFSET		448
+#define LCNPHY_TX_PWR_CTRL_PWR_OFFSET		576
+
+#define LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313	140
+
+#define LCNPHY_TX_PWR_CTRL_START_NPT		1
+#define LCNPHY_TX_PWR_CTRL_MAX_NPT			7
+
+#define LCNPHY_NOISE_SAMPLES_DEFAULT 5000
+
+#define LCNPHY_ACI_DETECT_START      1
+#define LCNPHY_ACI_DETECT_PROGRESS   2
+#define LCNPHY_ACI_DETECT_STOP       3
+
+#define LCNPHY_ACI_CRSHIFRMLO_TRSH 100
+#define LCNPHY_ACI_GLITCH_TRSH 2000
+#define	LCNPHY_ACI_TMOUT 250
+#define LCNPHY_ACI_DETECT_TIMEOUT  2
+#define LCNPHY_ACI_START_DELAY 0
+
+#define wlc_lcnphy_tx_gain_override_enabled(pi)	\
+	(0 != (read_phy_reg((pi), 0x43b) & (0x1 << 6)))
+
+#define wlc_lcnphy_total_tx_frames(pi) \
+	wlapi_bmac_read_shm((pi)->sh->physhim, M_UCODE_MACSTAT + \
+			    offsetof(struct macstat, txallfrm))
+
+struct lcnphy_txgains {
+	u16 gm_gain;
+	u16 pga_gain;
+	u16 pad_gain;
+	u16 dac_gain;
+};
+
+enum lcnphy_cal_mode {
+	LCNPHY_CAL_FULL,
+	LCNPHY_CAL_RECAL,
+	LCNPHY_CAL_CURRECAL,
+	LCNPHY_CAL_DIGCAL,
+	LCNPHY_CAL_GCTRL
+};
+
+struct lcnphy_rx_iqcomp {
+	u8 chan;
+	s16 a;
+	s16 b;
+};
+
+struct lcnphy_spb_tone {
+	s16 re;
+	s16 im;
+};
+
+struct lcnphy_unsign16_struct {
+	u16 re;
+	u16 im;
+};
+
+struct lcnphy_iq_est {
+	u32 iq_prod;
+	u32 i_pwr;
+	u32 q_pwr;
+};
+
+struct lcnphy_sfo_cfg {
+	u16 ptcentreTs20;
+	u16 ptcentreFactor;
+};
+
+enum lcnphy_papd_cal_type {
+	LCNPHY_PAPD_CAL_CW,
+	LCNPHY_PAPD_CAL_OFDM
+};
+
+typedef u16 iqcal_gain_params_lcnphy[9];
+
+static const iqcal_gain_params_lcnphy tbl_iqcal_gainparams_lcnphy_2G[] = {
+	{0, 0, 0, 0, 0, 0, 0, 0, 0},
+};
+
+static const iqcal_gain_params_lcnphy *tbl_iqcal_gainparams_lcnphy[1] = {
+	tbl_iqcal_gainparams_lcnphy_2G,
+};
+
+static const u16 iqcal_gainparams_numgains_lcnphy[1] = {
+	ARRAY_SIZE(tbl_iqcal_gainparams_lcnphy_2G),
+};
+
+static const struct lcnphy_sfo_cfg lcnphy_sfo_cfg[] = {
+	{965, 1087},
+	{967, 1085},
+	{969, 1082},
+	{971, 1080},
+	{973, 1078},
+	{975, 1076},
+	{977, 1073},
+	{979, 1071},
+	{981, 1069},
+	{983, 1067},
+	{985, 1065},
+	{987, 1063},
+	{989, 1060},
+	{994, 1055}
+};
+
+static const
+u16 lcnphy_iqcal_loft_gainladder[] = {
+	((2 << 8) | 0),
+	((3 << 8) | 0),
+	((4 << 8) | 0),
+	((6 << 8) | 0),
+	((8 << 8) | 0),
+	((11 << 8) | 0),
+	((16 << 8) | 0),
+	((16 << 8) | 1),
+	((16 << 8) | 2),
+	((16 << 8) | 3),
+	((16 << 8) | 4),
+	((16 << 8) | 5),
+	((16 << 8) | 6),
+	((16 << 8) | 7),
+	((23 << 8) | 7),
+	((32 << 8) | 7),
+	((45 << 8) | 7),
+	((64 << 8) | 7),
+	((91 << 8) | 7),
+	((128 << 8) | 7)
+};
+
+static const
+u16 lcnphy_iqcal_ir_gainladder[] = {
+	((1 << 8) | 0),
+	((2 << 8) | 0),
+	((4 << 8) | 0),
+	((6 << 8) | 0),
+	((8 << 8) | 0),
+	((11 << 8) | 0),
+	((16 << 8) | 0),
+	((23 << 8) | 0),
+	((32 << 8) | 0),
+	((45 << 8) | 0),
+	((64 << 8) | 0),
+	((64 << 8) | 1),
+	((64 << 8) | 2),
+	((64 << 8) | 3),
+	((64 << 8) | 4),
+	((64 << 8) | 5),
+	((64 << 8) | 6),
+	((64 << 8) | 7),
+	((91 << 8) | 7),
+	((128 << 8) | 7)
+};
+
+static const
+struct lcnphy_spb_tone lcnphy_spb_tone_3750[] = {
+	{88, 0},
+	{73, 49},
+	{34, 81},
+	{-17, 86},
+	{-62, 62},
+	{-86, 17},
+	{-81, -34},
+	{-49, -73},
+	{0, -88},
+	{49, -73},
+	{81, -34},
+	{86, 17},
+	{62, 62},
+	{17, 86},
+	{-34, 81},
+	{-73, 49},
+	{-88, 0},
+	{-73, -49},
+	{-34, -81},
+	{17, -86},
+	{62, -62},
+	{86, -17},
+	{81, 34},
+	{49, 73},
+	{0, 88},
+	{-49, 73},
+	{-81, 34},
+	{-86, -17},
+	{-62, -62},
+	{-17, -86},
+	{34, -81},
+	{73, -49},
+};
+
+static const
+u16 iqlo_loopback_rf_regs[20] = {
+	RADIO_2064_REG036,
+	RADIO_2064_REG11A,
+	RADIO_2064_REG03A,
+	RADIO_2064_REG025,
+	RADIO_2064_REG028,
+	RADIO_2064_REG005,
+	RADIO_2064_REG112,
+	RADIO_2064_REG0FF,
+	RADIO_2064_REG11F,
+	RADIO_2064_REG00B,
+	RADIO_2064_REG113,
+	RADIO_2064_REG007,
+	RADIO_2064_REG0FC,
+	RADIO_2064_REG0FD,
+	RADIO_2064_REG012,
+	RADIO_2064_REG057,
+	RADIO_2064_REG059,
+	RADIO_2064_REG05C,
+	RADIO_2064_REG078,
+	RADIO_2064_REG092,
+};
+
+static const
+u16 tempsense_phy_regs[14] = {
+	0x503,
+	0x4a4,
+	0x4d0,
+	0x4d9,
+	0x4da,
+	0x4a6,
+	0x938,
+	0x939,
+	0x4d8,
+	0x4d0,
+	0x4d7,
+	0x4a5,
+	0x40d,
+	0x4a2,
+};
+
+static const
+u16 rxiq_cal_rf_reg[11] = {
+	RADIO_2064_REG098,
+	RADIO_2064_REG116,
+	RADIO_2064_REG12C,
+	RADIO_2064_REG06A,
+	RADIO_2064_REG00B,
+	RADIO_2064_REG01B,
+	RADIO_2064_REG113,
+	RADIO_2064_REG01D,
+	RADIO_2064_REG114,
+	RADIO_2064_REG02E,
+	RADIO_2064_REG12A,
+};
+
+static const
+struct lcnphy_rx_iqcomp lcnphy_rx_iqcomp_table_rev0[] = {
+	{1, 0, 0},
+	{2, 0, 0},
+	{3, 0, 0},
+	{4, 0, 0},
+	{5, 0, 0},
+	{6, 0, 0},
+	{7, 0, 0},
+	{8, 0, 0},
+	{9, 0, 0},
+	{10, 0, 0},
+	{11, 0, 0},
+	{12, 0, 0},
+	{13, 0, 0},
+	{14, 0, 0},
+	{34, 0, 0},
+	{38, 0, 0},
+	{42, 0, 0},
+	{46, 0, 0},
+	{36, 0, 0},
+	{40, 0, 0},
+	{44, 0, 0},
+	{48, 0, 0},
+	{52, 0, 0},
+	{56, 0, 0},
+	{60, 0, 0},
+	{64, 0, 0},
+	{100, 0, 0},
+	{104, 0, 0},
+	{108, 0, 0},
+	{112, 0, 0},
+	{116, 0, 0},
+	{120, 0, 0},
+	{124, 0, 0},
+	{128, 0, 0},
+	{132, 0, 0},
+	{136, 0, 0},
+	{140, 0, 0},
+	{149, 0, 0},
+	{153, 0, 0},
+	{157, 0, 0},
+	{161, 0, 0},
+	{165, 0, 0},
+	{184, 0, 0},
+	{188, 0, 0},
+	{192, 0, 0},
+	{196, 0, 0},
+	{200, 0, 0},
+	{204, 0, 0},
+	{208, 0, 0},
+	{212, 0, 0},
+	{216, 0, 0},
+};
+
+static const u32 lcnphy_23bitgaincode_table[] = {
+	0x200100,
+	0x200200,
+	0x200004,
+	0x200014,
+	0x200024,
+	0x200034,
+	0x200134,
+	0x200234,
+	0x200334,
+	0x200434,
+	0x200037,
+	0x200137,
+	0x200237,
+	0x200337,
+	0x200437,
+	0x000035,
+	0x000135,
+	0x000235,
+	0x000037,
+	0x000137,
+	0x000237,
+	0x000337,
+	0x00013f,
+	0x00023f,
+	0x00033f,
+	0x00034f,
+	0x00044f,
+	0x00144f,
+	0x00244f,
+	0x00254f,
+	0x00354f,
+	0x00454f,
+	0x00464f,
+	0x01464f,
+	0x02464f,
+	0x03464f,
+	0x04464f,
+};
+
+static const s8 lcnphy_gain_table[] = {
+	-16,
+	-13,
+	10,
+	7,
+	4,
+	0,
+	3,
+	6,
+	9,
+	12,
+	15,
+	18,
+	21,
+	24,
+	27,
+	30,
+	33,
+	36,
+	39,
+	42,
+	45,
+	48,
+	50,
+	53,
+	56,
+	59,
+	62,
+	65,
+	68,
+	71,
+	74,
+	77,
+	80,
+	83,
+	86,
+	89,
+	92,
+};
+
+static const s8 lcnphy_gain_index_offset_for_rssi[] = {
+	7,
+	7,
+	7,
+	7,
+	7,
+	7,
+	7,
+	8,
+	7,
+	7,
+	6,
+	7,
+	7,
+	4,
+	4,
+	4,
+	4,
+	4,
+	4,
+	4,
+	4,
+	3,
+	3,
+	3,
+	3,
+	3,
+	3,
+	4,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	-1,
+	-2,
+	-2,
+	-2
+};
+
+struct chan_info_2064_lcnphy {
+	uint chan;
+	uint freq;
+	u8 logen_buftune;
+	u8 logen_rccr_tx;
+	u8 txrf_mix_tune_ctrl;
+	u8 pa_input_tune_g;
+	u8 logen_rccr_rx;
+	u8 pa_rxrf_lna1_freq_tune;
+	u8 pa_rxrf_lna2_freq_tune;
+	u8 rxrf_rxrf_spare1;
+};
+
+static const struct chan_info_2064_lcnphy chan_info_2064_lcnphy[] = {
+	{1, 2412, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{2, 2417, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{3, 2422, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{4, 2427, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{5, 2432, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{6, 2437, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{7, 2442, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{8, 2447, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{9, 2452, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{10, 2457, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{11, 2462, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{12, 2467, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{13, 2472, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{14, 2484, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+};
+
+static const struct lcnphy_radio_regs lcnphy_radio_regs_2064[] = {
+	{0x00, 0, 0, 0, 0},
+	{0x01, 0x64, 0x64, 0, 0},
+	{0x02, 0x20, 0x20, 0, 0},
+	{0x03, 0x66, 0x66, 0, 0},
+	{0x04, 0xf8, 0xf8, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0x10, 0x10, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0x37, 0x37, 0, 0},
+	{0x0B, 0x6, 0x6, 0, 0},
+	{0x0C, 0x55, 0x55, 0, 0},
+	{0x0D, 0x8b, 0x8b, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0x5, 0x5, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0xe, 0xe, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0xb, 0xb, 0, 0},
+	{0x14, 0x2, 0x2, 0, 0},
+	{0x15, 0x12, 0x12, 0, 0},
+	{0x16, 0x12, 0x12, 0, 0},
+	{0x17, 0xc, 0xc, 0, 0},
+	{0x18, 0xc, 0xc, 0, 0},
+	{0x19, 0xc, 0xc, 0, 0},
+	{0x1A, 0x8, 0x8, 0, 0},
+	{0x1B, 0x2, 0x2, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0x1, 0x1, 0, 0},
+	{0x1E, 0x12, 0x12, 0, 0},
+	{0x1F, 0x6e, 0x6e, 0, 0},
+	{0x20, 0x2, 0x2, 0, 0},
+	{0x21, 0x23, 0x23, 0, 0},
+	{0x22, 0x8, 0x8, 0, 0},
+	{0x23, 0, 0, 0, 0},
+	{0x24, 0, 0, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0x33, 0x33, 0, 0},
+	{0x27, 0x55, 0x55, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x30, 0x30, 0, 0},
+	{0x2A, 0xb, 0xb, 0, 0},
+	{0x2B, 0x1b, 0x1b, 0, 0},
+	{0x2C, 0x3, 0x3, 0, 0},
+	{0x2D, 0x1b, 0x1b, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x20, 0x20, 0, 0},
+	{0x30, 0xa, 0xa, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0x62, 0x62, 0, 0},
+	{0x33, 0x19, 0x19, 0, 0},
+	{0x34, 0x33, 0x33, 0, 0},
+	{0x35, 0x77, 0x77, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x70, 0x70, 0, 0},
+	{0x38, 0x3, 0x3, 0, 0},
+	{0x39, 0xf, 0xf, 0, 0},
+	{0x3A, 0x6, 0x6, 0, 0},
+	{0x3B, 0xcf, 0xcf, 0, 0},
+	{0x3C, 0x1a, 0x1a, 0, 0},
+	{0x3D, 0x6, 0x6, 0, 0},
+	{0x3E, 0x42, 0x42, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0xfb, 0xfb, 0, 0},
+	{0x41, 0x9a, 0x9a, 0, 0},
+	{0x42, 0x7a, 0x7a, 0, 0},
+	{0x43, 0x29, 0x29, 0, 0},
+	{0x44, 0, 0, 0, 0},
+	{0x45, 0x8, 0x8, 0, 0},
+	{0x46, 0xce, 0xce, 0, 0},
+	{0x47, 0x27, 0x27, 0, 0},
+	{0x48, 0x62, 0x62, 0, 0},
+	{0x49, 0x6, 0x6, 0, 0},
+	{0x4A, 0x58, 0x58, 0, 0},
+	{0x4B, 0xf7, 0xf7, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0xb3, 0xb3, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0, 0, 0, 0},
+	{0x51, 0x9, 0x9, 0, 0},
+	{0x52, 0x5, 0x5, 0, 0},
+	{0x53, 0x17, 0x17, 0, 0},
+	{0x54, 0x38, 0x38, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0xb, 0xb, 0, 0},
+	{0x58, 0, 0, 0, 0},
+	{0x59, 0, 0, 0, 0},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0, 0, 0, 0},
+	{0x5C, 0, 0, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x88, 0x88, 0, 0},
+	{0x5F, 0xcc, 0xcc, 0, 0},
+	{0x60, 0x74, 0x74, 0, 0},
+	{0x61, 0x74, 0x74, 0, 0},
+	{0x62, 0x74, 0x74, 0, 0},
+	{0x63, 0x44, 0x44, 0, 0},
+	{0x64, 0x77, 0x77, 0, 0},
+	{0x65, 0x44, 0x44, 0, 0},
+	{0x66, 0x77, 0x77, 0, 0},
+	{0x67, 0x55, 0x55, 0, 0},
+	{0x68, 0x77, 0x77, 0, 0},
+	{0x69, 0x77, 0x77, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0x7f, 0x7f, 0, 0},
+	{0x6C, 0x8, 0x8, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0x88, 0x88, 0, 0},
+	{0x6F, 0x66, 0x66, 0, 0},
+	{0x70, 0x66, 0x66, 0, 0},
+	{0x71, 0x28, 0x28, 0, 0},
+	{0x72, 0x55, 0x55, 0, 0},
+	{0x73, 0x4, 0x4, 0, 0},
+	{0x74, 0, 0, 0, 0},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0, 0, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0xd6, 0xd6, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0xb4, 0xb4, 0, 0},
+	{0x84, 0x1, 0x1, 0, 0},
+	{0x85, 0x20, 0x20, 0, 0},
+	{0x86, 0x5, 0x5, 0, 0},
+	{0x87, 0xff, 0xff, 0, 0},
+	{0x88, 0x7, 0x7, 0, 0},
+	{0x89, 0x77, 0x77, 0, 0},
+	{0x8A, 0x77, 0x77, 0, 0},
+	{0x8B, 0x77, 0x77, 0, 0},
+	{0x8C, 0x77, 0x77, 0, 0},
+	{0x8D, 0x8, 0x8, 0, 0},
+	{0x8E, 0xa, 0xa, 0, 0},
+	{0x8F, 0x8, 0x8, 0, 0},
+	{0x90, 0x18, 0x18, 0, 0},
+	{0x91, 0x5, 0x5, 0, 0},
+	{0x92, 0x1f, 0x1f, 0, 0},
+	{0x93, 0x10, 0x10, 0, 0},
+	{0x94, 0x3, 0x3, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0xaa, 0xaa, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0x23, 0x23, 0, 0},
+	{0x9A, 0x7, 0x7, 0, 0},
+	{0x9B, 0xf, 0xf, 0, 0},
+	{0x9C, 0x10, 0x10, 0, 0},
+	{0x9D, 0x3, 0x3, 0, 0},
+	{0x9E, 0x4, 0x4, 0, 0},
+	{0x9F, 0x20, 0x20, 0, 0},
+	{0xA0, 0, 0, 0, 0},
+	{0xA1, 0, 0, 0, 0},
+	{0xA2, 0, 0, 0, 0},
+	{0xA3, 0, 0, 0, 0},
+	{0xA4, 0x1, 0x1, 0, 0},
+	{0xA5, 0x77, 0x77, 0, 0},
+	{0xA6, 0x77, 0x77, 0, 0},
+	{0xA7, 0x77, 0x77, 0, 0},
+	{0xA8, 0x77, 0x77, 0, 0},
+	{0xA9, 0x8c, 0x8c, 0, 0},
+	{0xAA, 0x88, 0x88, 0, 0},
+	{0xAB, 0x78, 0x78, 0, 0},
+	{0xAC, 0x57, 0x57, 0, 0},
+	{0xAD, 0x88, 0x88, 0, 0},
+	{0xAE, 0, 0, 0, 0},
+	{0xAF, 0x8, 0x8, 0, 0},
+	{0xB0, 0x88, 0x88, 0, 0},
+	{0xB1, 0, 0, 0, 0},
+	{0xB2, 0x1b, 0x1b, 0, 0},
+	{0xB3, 0x3, 0x3, 0, 0},
+	{0xB4, 0x24, 0x24, 0, 0},
+	{0xB5, 0x3, 0x3, 0, 0},
+	{0xB6, 0x1b, 0x1b, 0, 0},
+	{0xB7, 0x24, 0x24, 0, 0},
+	{0xB8, 0x3, 0x3, 0, 0},
+	{0xB9, 0, 0, 0, 0},
+	{0xBA, 0xaa, 0xaa, 0, 0},
+	{0xBB, 0, 0, 0, 0},
+	{0xBC, 0x4, 0x4, 0, 0},
+	{0xBD, 0, 0, 0, 0},
+	{0xBE, 0x8, 0x8, 0, 0},
+	{0xBF, 0x11, 0x11, 0, 0},
+	{0xC0, 0, 0, 0, 0},
+	{0xC1, 0, 0, 0, 0},
+	{0xC2, 0x62, 0x62, 0, 0},
+	{0xC3, 0x1e, 0x1e, 0, 0},
+	{0xC4, 0x33, 0x33, 0, 0},
+	{0xC5, 0x37, 0x37, 0, 0},
+	{0xC6, 0, 0, 0, 0},
+	{0xC7, 0x70, 0x70, 0, 0},
+	{0xC8, 0x1e, 0x1e, 0, 0},
+	{0xC9, 0x6, 0x6, 0, 0},
+	{0xCA, 0x4, 0x4, 0, 0},
+	{0xCB, 0x2f, 0x2f, 0, 0},
+	{0xCC, 0xf, 0xf, 0, 0},
+	{0xCD, 0, 0, 0, 0},
+	{0xCE, 0xff, 0xff, 0, 0},
+	{0xCF, 0x8, 0x8, 0, 0},
+	{0xD0, 0x3f, 0x3f, 0, 0},
+	{0xD1, 0x3f, 0x3f, 0, 0},
+	{0xD2, 0x3f, 0x3f, 0, 0},
+	{0xD3, 0, 0, 0, 0},
+	{0xD4, 0, 0, 0, 0},
+	{0xD5, 0, 0, 0, 0},
+	{0xD6, 0xcc, 0xcc, 0, 0},
+	{0xD7, 0, 0, 0, 0},
+	{0xD8, 0x8, 0x8, 0, 0},
+	{0xD9, 0x8, 0x8, 0, 0},
+	{0xDA, 0x8, 0x8, 0, 0},
+	{0xDB, 0x11, 0x11, 0, 0},
+	{0xDC, 0, 0, 0, 0},
+	{0xDD, 0x87, 0x87, 0, 0},
+	{0xDE, 0x88, 0x88, 0, 0},
+	{0xDF, 0x8, 0x8, 0, 0},
+	{0xE0, 0x8, 0x8, 0, 0},
+	{0xE1, 0x8, 0x8, 0, 0},
+	{0xE2, 0, 0, 0, 0},
+	{0xE3, 0, 0, 0, 0},
+	{0xE4, 0, 0, 0, 0},
+	{0xE5, 0xf5, 0xf5, 0, 0},
+	{0xE6, 0x30, 0x30, 0, 0},
+	{0xE7, 0x1, 0x1, 0, 0},
+	{0xE8, 0, 0, 0, 0},
+	{0xE9, 0xff, 0xff, 0, 0},
+	{0xEA, 0, 0, 0, 0},
+	{0xEB, 0, 0, 0, 0},
+	{0xEC, 0x22, 0x22, 0, 0},
+	{0xED, 0, 0, 0, 0},
+	{0xEE, 0, 0, 0, 0},
+	{0xEF, 0, 0, 0, 0},
+	{0xF0, 0x3, 0x3, 0, 0},
+	{0xF1, 0x1, 0x1, 0, 0},
+	{0xF2, 0, 0, 0, 0},
+	{0xF3, 0, 0, 0, 0},
+	{0xF4, 0, 0, 0, 0},
+	{0xF5, 0, 0, 0, 0},
+	{0xF6, 0, 0, 0, 0},
+	{0xF7, 0x6, 0x6, 0, 0},
+	{0xF8, 0, 0, 0, 0},
+	{0xF9, 0, 0, 0, 0},
+	{0xFA, 0x40, 0x40, 0, 0},
+	{0xFB, 0, 0, 0, 0},
+	{0xFC, 0x1, 0x1, 0, 0},
+	{0xFD, 0x80, 0x80, 0, 0},
+	{0xFE, 0x2, 0x2, 0, 0},
+	{0xFF, 0x10, 0x10, 0, 0},
+	{0x100, 0x2, 0x2, 0, 0},
+	{0x101, 0x1e, 0x1e, 0, 0},
+	{0x102, 0x1e, 0x1e, 0, 0},
+	{0x103, 0, 0, 0, 0},
+	{0x104, 0x1f, 0x1f, 0, 0},
+	{0x105, 0, 0x8, 0, 1},
+	{0x106, 0x2a, 0x2a, 0, 0},
+	{0x107, 0xf, 0xf, 0, 0},
+	{0x108, 0, 0, 0, 0},
+	{0x109, 0, 0, 0, 0},
+	{0x10A, 0, 0, 0, 0},
+	{0x10B, 0, 0, 0, 0},
+	{0x10C, 0, 0, 0, 0},
+	{0x10D, 0, 0, 0, 0},
+	{0x10E, 0, 0, 0, 0},
+	{0x10F, 0, 0, 0, 0},
+	{0x110, 0, 0, 0, 0},
+	{0x111, 0, 0, 0, 0},
+	{0x112, 0, 0, 0, 0},
+	{0x113, 0, 0, 0, 0},
+	{0x114, 0, 0, 0, 0},
+	{0x115, 0, 0, 0, 0},
+	{0x116, 0, 0, 0, 0},
+	{0x117, 0, 0, 0, 0},
+	{0x118, 0, 0, 0, 0},
+	{0x119, 0, 0, 0, 0},
+	{0x11A, 0, 0, 0, 0},
+	{0x11B, 0, 0, 0, 0},
+	{0x11C, 0x1, 0x1, 0, 0},
+	{0x11D, 0, 0, 0, 0},
+	{0x11E, 0, 0, 0, 0},
+	{0x11F, 0, 0, 0, 0},
+	{0x120, 0, 0, 0, 0},
+	{0x121, 0, 0, 0, 0},
+	{0x122, 0x80, 0x80, 0, 0},
+	{0x123, 0, 0, 0, 0},
+	{0x124, 0xf8, 0xf8, 0, 0},
+	{0x125, 0, 0, 0, 0},
+	{0x126, 0, 0, 0, 0},
+	{0x127, 0, 0, 0, 0},
+	{0x128, 0, 0, 0, 0},
+	{0x129, 0, 0, 0, 0},
+	{0x12A, 0, 0, 0, 0},
+	{0x12B, 0, 0, 0, 0},
+	{0x12C, 0, 0, 0, 0},
+	{0x12D, 0, 0, 0, 0},
+	{0x12E, 0, 0, 0, 0},
+	{0x12F, 0, 0, 0, 0},
+	{0x130, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+#define LCNPHY_NUM_DIG_FILT_COEFFS 16
+#define LCNPHY_NUM_TX_DIG_FILTERS_CCK 13
+
+static const u16 LCNPHY_txdigfiltcoeffs_cck[LCNPHY_NUM_TX_DIG_FILTERS_CCK]
+	[LCNPHY_NUM_DIG_FILT_COEFFS + 1] = {
+	{0, 1, 415, 1874, 64, 128, 64, 792, 1656, 64, 128, 64, 778, 1582, 64,
+	 128, 64,},
+	{1, 1, 402, 1847, 259, 59, 259, 671, 1794, 68, 54, 68, 608, 1863, 93,
+	 167, 93,},
+	{2, 1, 415, 1874, 64, 128, 64, 792, 1656, 192, 384, 192, 778, 1582, 64,
+	 128, 64,},
+	{3, 1, 302, 1841, 129, 258, 129, 658, 1720, 205, 410, 205, 754, 1760,
+	 170, 340, 170,},
+	{20, 1, 360, 1884, 242, 1734, 242, 752, 1720, 205, 1845, 205, 767, 1760,
+	 256, 185, 256,},
+	{21, 1, 360, 1884, 149, 1874, 149, 752, 1720, 205, 1883, 205, 767, 1760,
+	 256, 273, 256,},
+	{22, 1, 360, 1884, 98, 1948, 98, 752, 1720, 205, 1924, 205, 767, 1760,
+	 256, 352, 256,},
+	{23, 1, 350, 1884, 116, 1966, 116, 752, 1720, 205, 2008, 205, 767, 1760,
+	 128, 233, 128,},
+	{24, 1, 325, 1884, 32, 40, 32, 756, 1720, 256, 471, 256, 766, 1760, 256,
+	 1881, 256,},
+	{25, 1, 299, 1884, 51, 64, 51, 736, 1720, 256, 471, 256, 765, 1760, 256,
+	 1881, 256,},
+	{26, 1, 277, 1943, 39, 117, 88, 637, 1838, 64, 192, 144, 614, 1864, 128,
+	 384, 288,},
+	{27, 1, 245, 1943, 49, 147, 110, 626, 1838, 256, 768, 576, 613, 1864,
+	 128, 384, 288,},
+	{30, 1, 302, 1841, 61, 122, 61, 658, 1720, 205, 410, 205, 754, 1760,
+	 170, 340, 170,},
+};
+
+#define LCNPHY_NUM_TX_DIG_FILTERS_OFDM 3
+static const u16 LCNPHY_txdigfiltcoeffs_ofdm[LCNPHY_NUM_TX_DIG_FILTERS_OFDM]
+	[LCNPHY_NUM_DIG_FILT_COEFFS + 1] = {
+	{0, 0, 0xa2, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x100, 0x0, 0x0,
+	 0x278, 0xfea0, 0x80, 0x100, 0x80,},
+	{1, 0, 374, 0xFF79, 16, 32, 16, 799, 0xFE74, 50, 32, 50,
+	 750, 0xFE2B, 212, 0xFFCE, 212,},
+	{2, 0, 375, 0xFF16, 37, 76, 37, 799, 0xFE74, 32, 20, 32, 748,
+	 0xFEF2, 128, 0xFFE2, 128}
+};
+
+#define wlc_lcnphy_set_start_tx_pwr_idx(pi, idx) \
+	mod_phy_reg(pi, 0x4a4, \
+		    (0x1ff << 0), \
+		    (u16)(idx) << 0)
+
+#define wlc_lcnphy_set_tx_pwr_npt(pi, npt) \
+	mod_phy_reg(pi, 0x4a5, \
+		    (0x7 << 8),	\
+		    (u16)(npt) << 8)
+
+#define wlc_lcnphy_get_tx_pwr_ctrl(pi) \
+	(read_phy_reg((pi), 0x4a4) & \
+	 ((0x1 << 15) |	\
+	  (0x1 << 14) |	\
+	  (0x1 << 13)))
+
+#define wlc_lcnphy_get_tx_pwr_npt(pi) \
+	((read_phy_reg(pi, 0x4a5) & \
+	  (0x7 << 8)) >> \
+	 8)
+
+#define wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi) \
+	(read_phy_reg(pi, 0x473) & 0x1ff)
+
+#define wlc_lcnphy_get_target_tx_pwr(pi) \
+	((read_phy_reg(pi, 0x4a7) & \
+	  (0xff << 0)) >> \
+	 0)
+
+#define wlc_lcnphy_set_target_tx_pwr(pi, target) \
+	mod_phy_reg(pi, 0x4a7, \
+		    (0xff << 0), \
+		    (u16)(target) << 0)
+
+#define wlc_radio_2064_rcal_done(pi) \
+	(0 != (read_radio_reg(pi, RADIO_2064_REG05C) & 0x20))
+
+#define tempsense_done(pi) \
+	(0x8000 == (read_phy_reg(pi, 0x476) & 0x8000))
+
+#define LCNPHY_IQLOCC_READ(val) \
+	((u8)(-(s8)(((val) & 0xf0) >> 4) + (s8)((val) & 0x0f)))
+
+#define FIXED_TXPWR 78
+#define LCNPHY_TEMPSENSE(val) ((s16)((val > 255) ? (val - 512) : val))
+
+void wlc_lcnphy_write_table(struct brcms_phy *pi, const struct phytbl_info *pti)
+{
+	wlc_phy_write_table(pi, pti, 0x455, 0x457, 0x456);
+}
+
+void wlc_lcnphy_read_table(struct brcms_phy *pi, struct phytbl_info *pti)
+{
+	wlc_phy_read_table(pi, pti, 0x455, 0x457, 0x456);
+}
+
+static void
+wlc_lcnphy_common_read_table(struct brcms_phy *pi, u32 tbl_id,
+			     const u16 *tbl_ptr, u32 tbl_len,
+			     u32 tbl_width, u32 tbl_offset)
+{
+	struct phytbl_info tab;
+	tab.tbl_id = tbl_id;
+	tab.tbl_ptr = tbl_ptr;
+	tab.tbl_len = tbl_len;
+	tab.tbl_width = tbl_width;
+	tab.tbl_offset = tbl_offset;
+	wlc_lcnphy_read_table(pi, &tab);
+}
+
+static void
+wlc_lcnphy_common_write_table(struct brcms_phy *pi, u32 tbl_id,
+			      const u16 *tbl_ptr, u32 tbl_len,
+			      u32 tbl_width, u32 tbl_offset)
+{
+
+	struct phytbl_info tab;
+	tab.tbl_id = tbl_id;
+	tab.tbl_ptr = tbl_ptr;
+	tab.tbl_len = tbl_len;
+	tab.tbl_width = tbl_width;
+	tab.tbl_offset = tbl_offset;
+	wlc_lcnphy_write_table(pi, &tab);
+}
+
+static u32
+wlc_lcnphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
+{
+	u32 quotient, remainder, roundup, rbit;
+
+	quotient = dividend / divisor;
+	remainder = dividend % divisor;
+	rbit = divisor & 1;
+	roundup = (divisor >> 1) + rbit;
+
+	while (precision--) {
+		quotient <<= 1;
+		if (remainder >= roundup) {
+			quotient++;
+			remainder = ((remainder - roundup) << 1) + rbit;
+		} else {
+			remainder <<= 1;
+		}
+	}
+
+	if (remainder >= roundup)
+		quotient++;
+
+	return quotient;
+}
+
+static int wlc_lcnphy_calc_floor(s16 coeff_x, int type)
+{
+	int k;
+	k = 0;
+	if (type == 0) {
+		if (coeff_x < 0)
+			k = (coeff_x - 1) / 2;
+		else
+			k = coeff_x / 2;
+	}
+
+	if (type == 1) {
+		if ((coeff_x + 1) < 0)
+			k = (coeff_x) / 2;
+		else
+			k = (coeff_x + 1) / 2;
+	}
+	return k;
+}
+
+static void
+wlc_lcnphy_get_tx_gain(struct brcms_phy *pi, struct lcnphy_txgains *gains)
+{
+	u16 dac_gain, rfgain0, rfgain1;
+
+	dac_gain = read_phy_reg(pi, 0x439) >> 0;
+	gains->dac_gain = (dac_gain & 0x380) >> 7;
+
+	rfgain0 = (read_phy_reg(pi, 0x4b5) & (0xffff << 0)) >> 0;
+	rfgain1 = (read_phy_reg(pi, 0x4fb) & (0x7fff << 0)) >> 0;
+
+	gains->gm_gain = rfgain0 & 0xff;
+	gains->pga_gain = (rfgain0 >> 8) & 0xff;
+	gains->pad_gain = rfgain1 & 0xff;
+}
+
+
+static void wlc_lcnphy_set_dac_gain(struct brcms_phy *pi, u16 dac_gain)
+{
+	u16 dac_ctrl;
+
+	dac_ctrl = (read_phy_reg(pi, 0x439) >> 0);
+	dac_ctrl = dac_ctrl & 0xc7f;
+	dac_ctrl = dac_ctrl | (dac_gain << 7);
+	mod_phy_reg(pi, 0x439, (0xfff << 0), (dac_ctrl) << 0);
+
+}
+
+static void wlc_lcnphy_set_tx_gain_override(struct brcms_phy *pi, bool bEnable)
+{
+	u16 bit = bEnable ? 1 : 0;
+
+	mod_phy_reg(pi, 0x4b0, (0x1 << 7), bit << 7);
+
+	mod_phy_reg(pi, 0x4b0, (0x1 << 14), bit << 14);
+
+	mod_phy_reg(pi, 0x43b, (0x1 << 6), bit << 6);
+}
+
+static void
+wlc_lcnphy_rx_gain_override_enable(struct brcms_phy *pi, bool enable)
+{
+	u16 ebit = enable ? 1 : 0;
+
+	mod_phy_reg(pi, 0x4b0, (0x1 << 8), ebit << 8);
+
+	mod_phy_reg(pi, 0x44c, (0x1 << 0), ebit << 0);
+
+	if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
+		mod_phy_reg(pi, 0x44c, (0x1 << 4), ebit << 4);
+		mod_phy_reg(pi, 0x44c, (0x1 << 6), ebit << 6);
+		mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
+		mod_phy_reg(pi, 0x4b0, (0x1 << 6), ebit << 6);
+	} else {
+		mod_phy_reg(pi, 0x4b0, (0x1 << 12), ebit << 12);
+		mod_phy_reg(pi, 0x4b0, (0x1 << 13), ebit << 13);
+		mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
+	}
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		mod_phy_reg(pi, 0x4b0, (0x1 << 10), ebit << 10);
+		mod_phy_reg(pi, 0x4e5, (0x1 << 3), ebit << 3);
+	}
+}
+
+static void
+wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
+				       u16 trsw,
+				       u16 ext_lna,
+				       u16 biq2,
+				       u16 biq1,
+				       u16 tia, u16 lna2, u16 lna1)
+{
+	u16 gain0_15, gain16_19;
+
+	gain16_19 = biq2 & 0xf;
+	gain0_15 = ((biq1 & 0xf) << 12) |
+		   ((tia & 0xf) << 8) |
+		   ((lna2 & 0x3) << 6) |
+		   ((lna2 & 0x3) << 4) |
+		   ((lna1 & 0x3) << 2) |
+		   ((lna1 & 0x3) << 0);
+
+	mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
+	mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
+	mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
+
+	if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
+		mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
+		mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10);
+	} else {
+		mod_phy_reg(pi, 0x4b1, (0x1 << 10), 0 << 10);
+
+		mod_phy_reg(pi, 0x4b1, (0x1 << 15), 0 << 15);
+
+		mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
+	}
+
+	mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0);
+
+}
+
+static void wlc_lcnphy_set_trsw_override(struct brcms_phy *pi, bool tx, bool rx)
+{
+
+	mod_phy_reg(pi, 0x44d,
+		    (0x1 << 1) |
+		    (0x1 << 0), (tx ? (0x1 << 1) : 0) | (rx ? (0x1 << 0) : 0));
+
+	or_phy_reg(pi, 0x44c, (0x1 << 1) | (0x1 << 0));
+}
+
+static void wlc_lcnphy_clear_trsw_override(struct brcms_phy *pi)
+{
+
+	and_phy_reg(pi, 0x44c, (u16) ~((0x1 << 1) | (0x1 << 0)));
+}
+
+static void wlc_lcnphy_set_rx_iq_comp(struct brcms_phy *pi, u16 a, u16 b)
+{
+	mod_phy_reg(pi, 0x645, (0x3ff << 0), (a) << 0);
+
+	mod_phy_reg(pi, 0x646, (0x3ff << 0), (b) << 0);
+
+	mod_phy_reg(pi, 0x647, (0x3ff << 0), (a) << 0);
+
+	mod_phy_reg(pi, 0x648, (0x3ff << 0), (b) << 0);
+
+	mod_phy_reg(pi, 0x649, (0x3ff << 0), (a) << 0);
+
+	mod_phy_reg(pi, 0x64a, (0x3ff << 0), (b) << 0);
+
+}
+
+static bool
+wlc_lcnphy_rx_iq_est(struct brcms_phy *pi,
+		     u16 num_samps,
+		     u8 wait_time, struct lcnphy_iq_est *iq_est)
+{
+	int wait_count = 0;
+	bool result = true;
+	u8 phybw40;
+	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 5), (1) << 5);
+
+	mod_phy_reg(pi, 0x410, (0x1 << 3), (0) << 3);
+
+	mod_phy_reg(pi, 0x482, (0xffff << 0), (num_samps) << 0);
+
+	mod_phy_reg(pi, 0x481, (0xff << 0), ((u16) wait_time) << 0);
+
+	mod_phy_reg(pi, 0x481, (0x1 << 8), (0) << 8);
+
+	mod_phy_reg(pi, 0x481, (0x1 << 9), (1) << 9);
+
+	while (read_phy_reg(pi, 0x481) & (0x1 << 9)) {
+
+		if (wait_count > (10 * 500)) {
+			result = false;
+			goto cleanup;
+		}
+		udelay(100);
+		wait_count++;
+	}
+
+	iq_est->iq_prod = ((u32) read_phy_reg(pi, 0x483) << 16) |
+			  (u32) read_phy_reg(pi, 0x484);
+	iq_est->i_pwr = ((u32) read_phy_reg(pi, 0x485) << 16) |
+			(u32) read_phy_reg(pi, 0x486);
+	iq_est->q_pwr = ((u32) read_phy_reg(pi, 0x487) << 16) |
+			(u32) read_phy_reg(pi, 0x488);
+
+cleanup:
+	mod_phy_reg(pi, 0x410, (0x1 << 3), (1) << 3);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 5), (0) << 5);
+
+	return result;
+}
+
+static bool wlc_lcnphy_calc_rx_iq_comp(struct brcms_phy *pi, u16 num_samps)
+{
+#define LCNPHY_MIN_RXIQ_PWR 2
+	bool result;
+	u16 a0_new, b0_new;
+	struct lcnphy_iq_est iq_est = { 0, 0, 0 };
+	s32 a, b, temp;
+	s16 iq_nbits, qq_nbits, arsh, brsh;
+	s32 iq;
+	u32 ii, qq;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	a0_new = ((read_phy_reg(pi, 0x645) & (0x3ff << 0)) >> 0);
+	b0_new = ((read_phy_reg(pi, 0x646) & (0x3ff << 0)) >> 0);
+	mod_phy_reg(pi, 0x6d1, (0x1 << 2), (0) << 2);
+
+	mod_phy_reg(pi, 0x64b, (0x1 << 6), (1) << 6);
+
+	wlc_lcnphy_set_rx_iq_comp(pi, 0, 0);
+
+	result = wlc_lcnphy_rx_iq_est(pi, num_samps, 32, &iq_est);
+	if (!result)
+		goto cleanup;
+
+	iq = (s32) iq_est.iq_prod;
+	ii = iq_est.i_pwr;
+	qq = iq_est.q_pwr;
+
+	if ((ii + qq) < LCNPHY_MIN_RXIQ_PWR) {
+		result = false;
+		goto cleanup;
+	}
+
+	iq_nbits = wlc_phy_nbits(iq);
+	qq_nbits = wlc_phy_nbits(qq);
+
+	arsh = 10 - (30 - iq_nbits);
+	if (arsh >= 0) {
+		a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
+		temp = (s32) (ii >> arsh);
+		if (temp == 0)
+			return false;
+	} else {
+		a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
+		temp = (s32) (ii << -arsh);
+		if (temp == 0)
+			return false;
+	}
+	a /= temp;
+	brsh = qq_nbits - 31 + 20;
+	if (brsh >= 0) {
+		b = (qq << (31 - qq_nbits));
+		temp = (s32) (ii >> brsh);
+		if (temp == 0)
+			return false;
+	} else {
+		b = (qq << (31 - qq_nbits));
+		temp = (s32) (ii << -brsh);
+		if (temp == 0)
+			return false;
+	}
+	b /= temp;
+	b -= a * a;
+	b = (s32) int_sqrt((unsigned long) b);
+	b -= (1 << 10);
+	a0_new = (u16) (a & 0x3ff);
+	b0_new = (u16) (b & 0x3ff);
+cleanup:
+
+	wlc_lcnphy_set_rx_iq_comp(pi, a0_new, b0_new);
+
+	mod_phy_reg(pi, 0x64b, (0x1 << 0), (1) << 0);
+
+	mod_phy_reg(pi, 0x64b, (0x1 << 3), (1) << 3);
+
+	pi_lcn->lcnphy_cal_results.rxiqcal_coeff_a0 = a0_new;
+	pi_lcn->lcnphy_cal_results.rxiqcal_coeff_b0 = b0_new;
+
+	return result;
+}
+
+static u32 wlc_lcnphy_measure_digital_power(struct brcms_phy *pi, u16 nsamples)
+{
+	struct lcnphy_iq_est iq_est = { 0, 0, 0 };
+
+	if (!wlc_lcnphy_rx_iq_est(pi, nsamples, 32, &iq_est))
+		return 0;
+	return (iq_est.i_pwr + iq_est.q_pwr) / nsamples;
+}
+
+static bool wlc_lcnphy_rx_iq_cal_gain(struct brcms_phy *pi, u16 biq1_gain,
+				      u16 tia_gain, u16 lna2_gain)
+{
+	u32 i_thresh_l, q_thresh_l;
+	u32 i_thresh_h, q_thresh_h;
+	struct lcnphy_iq_est iq_est_h, iq_est_l;
+
+	wlc_lcnphy_set_rx_gain_by_distribution(pi, 0, 0, 0, biq1_gain, tia_gain,
+					       lna2_gain, 0);
+
+	wlc_lcnphy_rx_gain_override_enable(pi, true);
+	wlc_lcnphy_start_tx_tone(pi, 2000, (40 >> 1), 0);
+	udelay(500);
+	write_radio_reg(pi, RADIO_2064_REG112, 0);
+	if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_l))
+		return false;
+
+	wlc_lcnphy_start_tx_tone(pi, 2000, 40, 0);
+	udelay(500);
+	write_radio_reg(pi, RADIO_2064_REG112, 0);
+	if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_h))
+		return false;
+
+	i_thresh_l = (iq_est_l.i_pwr << 1);
+	i_thresh_h = (iq_est_l.i_pwr << 2) + iq_est_l.i_pwr;
+
+	q_thresh_l = (iq_est_l.q_pwr << 1);
+	q_thresh_h = (iq_est_l.q_pwr << 2) + iq_est_l.q_pwr;
+	if ((iq_est_h.i_pwr > i_thresh_l) &&
+	    (iq_est_h.i_pwr < i_thresh_h) &&
+	    (iq_est_h.q_pwr > q_thresh_l) &&
+	    (iq_est_h.q_pwr < q_thresh_h))
+		return true;
+
+	return false;
+}
+
+static bool
+wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
+		     const struct lcnphy_rx_iqcomp *iqcomp,
+		     int iqcomp_sz, bool tx_switch, bool rx_switch, int module,
+		     int tx_gain_idx)
+{
+	struct lcnphy_txgains old_gains;
+	u16 tx_pwr_ctrl;
+	u8 tx_gain_index_old = 0;
+	bool result = false, tx_gain_override_old = false;
+	u16 i, Core1TxControl_old, RFOverride0_old,
+	    RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old,
+	    rfoverride3_old, rfoverride3val_old, rfoverride4_old,
+	    rfoverride4val_old, afectrlovr_old, afectrlovrval_old;
+	int tia_gain, lna2_gain, biq1_gain;
+	bool set_gain;
+	u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
+	u16 values_to_save[11];
+	s16 *ptr;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	ptr = kmalloc_array(131, sizeof(s16), GFP_ATOMIC);
+	if (NULL == ptr)
+		return false;
+	if (module == 2) {
+		while (iqcomp_sz--) {
+			if (iqcomp[iqcomp_sz].chan ==
+			    CHSPEC_CHANNEL(pi->radio_chanspec)) {
+				wlc_lcnphy_set_rx_iq_comp(pi,
+							  (u16)
+							  iqcomp[iqcomp_sz].a,
+							  (u16)
+							  iqcomp[iqcomp_sz].b);
+				result = true;
+				break;
+			}
+		}
+		goto cal_done;
+	}
+
+	WARN_ON(module != 1);
+	tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+
+	for (i = 0; i < 11; i++)
+		values_to_save[i] =
+			read_radio_reg(pi, rxiq_cal_rf_reg[i]);
+	Core1TxControl_old = read_phy_reg(pi, 0x631);
+
+	or_phy_reg(pi, 0x631, 0x0015);
+
+	RFOverride0_old = read_phy_reg(pi, 0x44c);
+	RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
+	rfoverride2_old = read_phy_reg(pi, 0x4b0);
+	rfoverride2val_old = read_phy_reg(pi, 0x4b1);
+	rfoverride3_old = read_phy_reg(pi, 0x4f9);
+	rfoverride3val_old = read_phy_reg(pi, 0x4fa);
+	rfoverride4_old = read_phy_reg(pi, 0x938);
+	rfoverride4val_old = read_phy_reg(pi, 0x939);
+	afectrlovr_old = read_phy_reg(pi, 0x43b);
+	afectrlovrval_old = read_phy_reg(pi, 0x43c);
+	old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+	old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
+
+	tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
+	if (tx_gain_override_old) {
+		wlc_lcnphy_get_tx_gain(pi, &old_gains);
+		tx_gain_index_old = pi_lcn->lcnphy_current_index;
+	}
+
+	wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
+
+	mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
+	mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
+
+	mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
+	mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
+
+	write_radio_reg(pi, RADIO_2064_REG116, 0x06);
+	write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
+	write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
+	write_radio_reg(pi, RADIO_2064_REG098, 0x03);
+	write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
+	mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
+	write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
+	write_radio_reg(pi, RADIO_2064_REG114, 0x01);
+	write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
+	write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
+
+	mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
+	mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
+	mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
+	mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
+	mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
+	mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
+	mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
+	mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
+	mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
+	mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
+
+	mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
+	mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
+
+	write_phy_reg(pi, 0x6da, 0xffff);
+	or_phy_reg(pi, 0x6db, 0x3);
+
+	wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
+	for (lna2_gain = 3; lna2_gain >= 0; lna2_gain--) {
+		for (tia_gain = 4; tia_gain >= 0; tia_gain--) {
+			for (biq1_gain = 6; biq1_gain >= 0; biq1_gain--) {
+				set_gain = wlc_lcnphy_rx_iq_cal_gain(pi,
+								     (u16)
+								     biq1_gain,
+								     (u16)
+								     tia_gain,
+								     (u16)
+								     lna2_gain);
+				if (!set_gain)
+					continue;
+
+				result = wlc_lcnphy_calc_rx_iq_comp(pi, 1024);
+				goto stop_tone;
+			}
+		}
+	}
+
+stop_tone:
+	wlc_lcnphy_stop_tx_tone(pi);
+
+	write_phy_reg(pi, 0x631, Core1TxControl_old);
+
+	write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
+	write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
+	write_phy_reg(pi, 0x4b0, rfoverride2_old);
+	write_phy_reg(pi, 0x4b1, rfoverride2val_old);
+	write_phy_reg(pi, 0x4f9, rfoverride3_old);
+	write_phy_reg(pi, 0x4fa, rfoverride3val_old);
+	write_phy_reg(pi, 0x938, rfoverride4_old);
+	write_phy_reg(pi, 0x939, rfoverride4val_old);
+	write_phy_reg(pi, 0x43b, afectrlovr_old);
+	write_phy_reg(pi, 0x43c, afectrlovrval_old);
+	write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
+	write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
+
+	wlc_lcnphy_clear_trsw_override(pi);
+
+	mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
+
+	for (i = 0; i < 11; i++)
+		write_radio_reg(pi, rxiq_cal_rf_reg[i],
+				values_to_save[i]);
+
+	if (tx_gain_override_old)
+		wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
+	else
+		wlc_lcnphy_disable_tx_gain_override(pi);
+
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
+	wlc_lcnphy_rx_gain_override_enable(pi, false);
+
+cal_done:
+	kfree(ptr);
+	return result;
+}
+
+s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi)
+{
+	s8 index;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	if (txpwrctrl_off(pi))
+		index = pi_lcn->lcnphy_current_index;
+	else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
+		index =	(s8) (wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(
+			      pi) / 2);
+	else
+		index = pi_lcn->lcnphy_current_index;
+	return index;
+}
+
+void wlc_lcnphy_crsuprs(struct brcms_phy *pi, int channel)
+{
+	u16 afectrlovr, afectrlovrval;
+	afectrlovr = read_phy_reg(pi, 0x43b);
+	afectrlovrval = read_phy_reg(pi, 0x43c);
+	if (channel != 0) {
+		mod_phy_reg(pi, 0x43b, (0x1 << 1), (1) << 1);
+
+		mod_phy_reg(pi, 0x43c, (0x1 << 1), (0) << 1);
+
+		mod_phy_reg(pi, 0x43b, (0x1 << 4), (1) << 4);
+
+		mod_phy_reg(pi, 0x43c, (0x1 << 6), (0) << 6);
+
+		write_phy_reg(pi, 0x44b, 0xffff);
+		wlc_lcnphy_tx_pu(pi, 1);
+
+		mod_phy_reg(pi, 0x634, (0xff << 8), (0) << 8);
+
+		or_phy_reg(pi, 0x6da, 0x0080);
+
+		or_phy_reg(pi, 0x00a, 0x228);
+	} else {
+		and_phy_reg(pi, 0x00a, ~(0x228));
+
+		and_phy_reg(pi, 0x6da, 0xFF7F);
+		write_phy_reg(pi, 0x43b, afectrlovr);
+		write_phy_reg(pi, 0x43c, afectrlovrval);
+	}
+}
+
+static void wlc_lcnphy_toggle_afe_pwdn(struct brcms_phy *pi)
+{
+	u16 save_AfeCtrlOvrVal, save_AfeCtrlOvr;
+
+	save_AfeCtrlOvrVal = read_phy_reg(pi, 0x43c);
+	save_AfeCtrlOvr = read_phy_reg(pi, 0x43b);
+
+	write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal | 0x1);
+	write_phy_reg(pi, 0x43b, save_AfeCtrlOvr | 0x1);
+
+	write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal & 0xfffe);
+	write_phy_reg(pi, 0x43b, save_AfeCtrlOvr & 0xfffe);
+
+	write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal);
+	write_phy_reg(pi, 0x43b, save_AfeCtrlOvr);
+}
+
+static void
+wlc_lcnphy_txrx_spur_avoidance_mode(struct brcms_phy *pi, bool enable)
+{
+	if (enable) {
+		write_phy_reg(pi, 0x942, 0x7);
+		write_phy_reg(pi, 0x93b, ((1 << 13) + 23));
+		write_phy_reg(pi, 0x93c, ((1 << 13) + 1989));
+
+		write_phy_reg(pi, 0x44a, 0x084);
+		write_phy_reg(pi, 0x44a, 0x080);
+		write_phy_reg(pi, 0x6d3, 0x2222);
+		write_phy_reg(pi, 0x6d3, 0x2220);
+	} else {
+		write_phy_reg(pi, 0x942, 0x0);
+		write_phy_reg(pi, 0x93b, ((0 << 13) + 23));
+		write_phy_reg(pi, 0x93c, ((0 << 13) + 1989));
+	}
+	wlapi_switch_macfreq(pi->sh->physhim, enable);
+}
+
+static void
+wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, u16 chanspec)
+{
+	u8 channel = CHSPEC_CHANNEL(chanspec);
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	if (channel == 14)
+		mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
+	else
+		mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
+
+	pi_lcn->lcnphy_bandedge_corr = 2;
+	if (channel == 1)
+		pi_lcn->lcnphy_bandedge_corr = 4;
+
+	if (channel == 1 || channel == 2 || channel == 3 ||
+	    channel == 4 || channel == 9 ||
+	    channel == 10 || channel == 11 || channel == 12) {
+		bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x2,
+				      0x03000c04);
+		bcma_chipco_pll_maskset(&pi->d11core->bus->drv_cc, 0x3,
+					~0x00ffffff, 0x0);
+		bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x4,
+				      0x200005c0);
+
+		bcma_cc_set32(&pi->d11core->bus->drv_cc, BCMA_CC_PMU_CTL,
+			      BCMA_CC_PMU_CTL_PLL_UPD);
+		write_phy_reg(pi, 0x942, 0);
+		wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
+		pi_lcn->lcnphy_spurmod = false;
+		mod_phy_reg(pi, 0x424, (0xff << 8), (0x1b) << 8);
+
+		write_phy_reg(pi, 0x425, 0x5907);
+	} else {
+		bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x2,
+				      0x03140c04);
+		bcma_chipco_pll_maskset(&pi->d11core->bus->drv_cc, 0x3,
+					~0x00ffffff, 0x333333);
+		bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x4,
+				      0x202c2820);
+
+		bcma_cc_set32(&pi->d11core->bus->drv_cc, BCMA_CC_PMU_CTL,
+			      BCMA_CC_PMU_CTL_PLL_UPD);
+		write_phy_reg(pi, 0x942, 0);
+		wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
+
+		pi_lcn->lcnphy_spurmod = false;
+		mod_phy_reg(pi, 0x424, (0xff << 8), (0x1f) << 8);
+
+		write_phy_reg(pi, 0x425, 0x590a);
+	}
+
+	or_phy_reg(pi, 0x44a, 0x44);
+	write_phy_reg(pi, 0x44a, 0x80);
+}
+
+static void
+wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
+{
+	uint i;
+	const struct chan_info_2064_lcnphy *ci;
+	u8 rfpll_doubler = 0;
+	u8 pll_pwrup, pll_pwrup_ovr;
+	s32 qFxtal, qFref, qFvco, qFcal;
+	u8 d15, d16, f16, e44, e45;
+	u32 div_int, div_frac, fvco3, fpfd, fref3, fcal_div;
+	u16 loop_bw, d30, setCount;
+
+	u8 h29, h28_ten, e30, h30_ten, cp_current;
+	u16 g30, d28;
+
+	ci = &chan_info_2064_lcnphy[0];
+	rfpll_doubler = 1;
+
+	mod_radio_reg(pi, RADIO_2064_REG09D, 0x4, 0x1 << 2);
+
+	write_radio_reg(pi, RADIO_2064_REG09E, 0xf);
+	if (!rfpll_doubler) {
+		loop_bw = PLL_2064_LOOP_BW;
+		d30 = PLL_2064_D30;
+	} else {
+		loop_bw = PLL_2064_LOOP_BW_DOUBLER;
+		d30 = PLL_2064_D30_DOUBLER;
+	}
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		for (i = 0; i < ARRAY_SIZE(chan_info_2064_lcnphy); i++)
+			if (chan_info_2064_lcnphy[i].chan == channel)
+				break;
+
+		if (i >= ARRAY_SIZE(chan_info_2064_lcnphy))
+			return;
+
+		ci = &chan_info_2064_lcnphy[i];
+	}
+
+	write_radio_reg(pi, RADIO_2064_REG02A, ci->logen_buftune);
+
+	mod_radio_reg(pi, RADIO_2064_REG030, 0x3, ci->logen_rccr_tx);
+
+	mod_radio_reg(pi, RADIO_2064_REG091, 0x3, ci->txrf_mix_tune_ctrl);
+
+	mod_radio_reg(pi, RADIO_2064_REG038, 0xf, ci->pa_input_tune_g);
+
+	mod_radio_reg(pi, RADIO_2064_REG030, 0x3 << 2,
+		      (ci->logen_rccr_rx) << 2);
+
+	mod_radio_reg(pi, RADIO_2064_REG05E, 0xf, ci->pa_rxrf_lna1_freq_tune);
+
+	mod_radio_reg(pi, RADIO_2064_REG05E, (0xf) << 4,
+		      (ci->pa_rxrf_lna2_freq_tune) << 4);
+
+	write_radio_reg(pi, RADIO_2064_REG06C, ci->rxrf_rxrf_spare1);
+
+	pll_pwrup = (u8) read_radio_reg(pi, RADIO_2064_REG044);
+	pll_pwrup_ovr = (u8) read_radio_reg(pi, RADIO_2064_REG12B);
+
+	or_radio_reg(pi, RADIO_2064_REG044, 0x07);
+
+	or_radio_reg(pi, RADIO_2064_REG12B, (0x07) << 1);
+	e44 = 0;
+	e45 = 0;
+
+	fpfd = rfpll_doubler ? (pi->xtalfreq << 1) : (pi->xtalfreq);
+	if (pi->xtalfreq > 26000000)
+		e44 = 1;
+	if (pi->xtalfreq > 52000000)
+		e45 = 1;
+	if (e44 == 0)
+		fcal_div = 1;
+	else if (e45 == 0)
+		fcal_div = 2;
+	else
+		fcal_div = 4;
+	fvco3 = (ci->freq * 3);
+	fref3 = 2 * fpfd;
+
+	qFxtal = wlc_lcnphy_qdiv_roundup(pi->xtalfreq, PLL_2064_MHZ, 16);
+	qFref = wlc_lcnphy_qdiv_roundup(fpfd, PLL_2064_MHZ, 16);
+	qFcal = pi->xtalfreq * fcal_div / PLL_2064_MHZ;
+	qFvco = wlc_lcnphy_qdiv_roundup(fvco3, 2, 16);
+
+	write_radio_reg(pi, RADIO_2064_REG04F, 0x02);
+
+	d15 = (pi->xtalfreq * fcal_div * 4 / 5) / PLL_2064_MHZ - 1;
+	write_radio_reg(pi, RADIO_2064_REG052, (0x07 & (d15 >> 2)));
+	write_radio_reg(pi, RADIO_2064_REG053, (d15 & 0x3) << 5);
+
+	d16 = (qFcal * 8 / (d15 + 1)) - 1;
+	write_radio_reg(pi, RADIO_2064_REG051, d16);
+
+	f16 = ((d16 + 1) * (d15 + 1)) / qFcal;
+	setCount = f16 * 3 * (ci->freq) / 32 - 1;
+	mod_radio_reg(pi, RADIO_2064_REG053, (0x0f << 0),
+		      (u8) (setCount >> 8));
+
+	or_radio_reg(pi, RADIO_2064_REG053, 0x10);
+	write_radio_reg(pi, RADIO_2064_REG054, (u8) (setCount & 0xff));
+
+	div_int = ((fvco3 * (PLL_2064_MHZ >> 4)) / fref3) << 4;
+
+	div_frac = ((fvco3 * (PLL_2064_MHZ >> 4)) % fref3) << 4;
+	while (div_frac >= fref3) {
+		div_int++;
+		div_frac -= fref3;
+	}
+	div_frac = wlc_lcnphy_qdiv_roundup(div_frac, fref3, 20);
+
+	mod_radio_reg(pi, RADIO_2064_REG045, (0x1f << 0),
+		      (u8) (div_int >> 4));
+	mod_radio_reg(pi, RADIO_2064_REG046, (0x1f << 4),
+		      (u8) (div_int << 4));
+	mod_radio_reg(pi, RADIO_2064_REG046, (0x0f << 0),
+		      (u8) (div_frac >> 16));
+	write_radio_reg(pi, RADIO_2064_REG047, (u8) (div_frac >> 8) & 0xff);
+	write_radio_reg(pi, RADIO_2064_REG048, (u8) div_frac & 0xff);
+
+	write_radio_reg(pi, RADIO_2064_REG040, 0xfb);
+
+	write_radio_reg(pi, RADIO_2064_REG041, 0x9A);
+	write_radio_reg(pi, RADIO_2064_REG042, 0xA3);
+	write_radio_reg(pi, RADIO_2064_REG043, 0x0C);
+
+	h29 = LCN_BW_LMT / loop_bw;
+	d28 = (((PLL_2064_HIGH_END_KVCO - PLL_2064_LOW_END_KVCO) *
+		(fvco3 / 2 - PLL_2064_LOW_END_VCO)) /
+	       (PLL_2064_HIGH_END_VCO - PLL_2064_LOW_END_VCO))
+	      + PLL_2064_LOW_END_KVCO;
+	h28_ten = (d28 * 10) / LCN_VCO_DIV;
+	e30 = (d30 - LCN_OFFSET) / LCN_FACT;
+	g30 = LCN_OFFSET + (e30 * LCN_FACT);
+	h30_ten = (g30 * 10) / LCN_CUR_DIV;
+	cp_current = ((LCN_CUR_LMT * h29 * LCN_MULT * 100) / h28_ten) / h30_ten;
+	mod_radio_reg(pi, RADIO_2064_REG03C, 0x3f, cp_current);
+
+	if (channel >= 1 && channel <= 5)
+		write_radio_reg(pi, RADIO_2064_REG03C, 0x8);
+	else
+		write_radio_reg(pi, RADIO_2064_REG03C, 0x7);
+	write_radio_reg(pi, RADIO_2064_REG03D, 0x3);
+
+	mod_radio_reg(pi, RADIO_2064_REG044, 0x0c, 0x0c);
+	udelay(1);
+
+	wlc_2064_vco_cal(pi);
+
+	write_radio_reg(pi, RADIO_2064_REG044, pll_pwrup);
+	write_radio_reg(pi, RADIO_2064_REG12B, pll_pwrup_ovr);
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+		write_radio_reg(pi, RADIO_2064_REG038, 3);
+		write_radio_reg(pi, RADIO_2064_REG091, 7);
+	}
+
+	if (!(pi->sh->boardflags & BFL_FEM)) {
+		static const u8 reg038[14] = {
+			0xd, 0xe, 0xd, 0xd, 0xd, 0xc, 0xa,
+			0xb, 0xb, 0x3, 0x3, 0x2, 0x0, 0x0
+		};
+
+		write_radio_reg(pi, RADIO_2064_REG02A, 0xf);
+		write_radio_reg(pi, RADIO_2064_REG091, 0x3);
+		write_radio_reg(pi, RADIO_2064_REG038, 0x3);
+
+		write_radio_reg(pi, RADIO_2064_REG038, reg038[channel - 1]);
+	}
+}
+
+static int
+wlc_lcnphy_load_tx_iir_filter(struct brcms_phy *pi, bool is_ofdm, s16 filt_type)
+{
+	s16 filt_index = -1;
+	int j;
+
+	u16 addr[] = {
+		0x910,
+		0x91e,
+		0x91f,
+		0x924,
+		0x925,
+		0x926,
+		0x920,
+		0x921,
+		0x927,
+		0x928,
+		0x929,
+		0x922,
+		0x923,
+		0x930,
+		0x931,
+		0x932
+	};
+
+	u16 addr_ofdm[] = {
+		0x90f,
+		0x900,
+		0x901,
+		0x906,
+		0x907,
+		0x908,
+		0x902,
+		0x903,
+		0x909,
+		0x90a,
+		0x90b,
+		0x904,
+		0x905,
+		0x90c,
+		0x90d,
+		0x90e
+	};
+
+	if (!is_ofdm) {
+		for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_CCK; j++) {
+			if (filt_type == LCNPHY_txdigfiltcoeffs_cck[j][0]) {
+				filt_index = (s16) j;
+				break;
+			}
+		}
+
+		if (filt_index != -1) {
+			for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++)
+				write_phy_reg(pi, addr[j],
+					      LCNPHY_txdigfiltcoeffs_cck
+					      [filt_index][j + 1]);
+		}
+	} else {
+		for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_OFDM; j++) {
+			if (filt_type == LCNPHY_txdigfiltcoeffs_ofdm[j][0]) {
+				filt_index = (s16) j;
+				break;
+			}
+		}
+
+		if (filt_index != -1) {
+			for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++)
+				write_phy_reg(pi, addr_ofdm[j],
+					      LCNPHY_txdigfiltcoeffs_ofdm
+					      [filt_index][j + 1]);
+		}
+	}
+
+	return (filt_index != -1) ? 0 : -1;
+}
+
+static u16 wlc_lcnphy_get_pa_gain(struct brcms_phy *pi)
+{
+	u16 pa_gain;
+
+	pa_gain = (read_phy_reg(pi, 0x4fb) &
+		   LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK) >>
+		  LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT;
+
+	return pa_gain;
+}
+
+static void wlc_lcnphy_set_tx_gain(struct brcms_phy *pi,
+				   struct lcnphy_txgains *target_gains)
+{
+	u16 pa_gain = wlc_lcnphy_get_pa_gain(pi);
+
+	mod_phy_reg(
+		pi, 0x4b5,
+		(0xffff << 0),
+		((target_gains->gm_gain) |
+		 (target_gains->pga_gain << 8)) <<
+		0);
+	mod_phy_reg(pi, 0x4fb,
+		    (0x7fff << 0),
+		    ((target_gains->pad_gain) | (pa_gain << 8)) << 0);
+
+	mod_phy_reg(
+		pi, 0x4fc,
+		(0xffff << 0),
+		((target_gains->gm_gain) |
+		 (target_gains->pga_gain << 8)) <<
+		0);
+	mod_phy_reg(pi, 0x4fd,
+		    (0x7fff << 0),
+		    ((target_gains->pad_gain) | (pa_gain << 8)) << 0);
+
+	wlc_lcnphy_set_dac_gain(pi, target_gains->dac_gain);
+
+	wlc_lcnphy_enable_tx_gain_override(pi);
+}
+
+static u8 wlc_lcnphy_get_bbmult(struct brcms_phy *pi)
+{
+	u16 m0m1;
+	struct phytbl_info tab;
+
+	tab.tbl_ptr = &m0m1;
+	tab.tbl_len = 1;
+	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
+	tab.tbl_offset = 87;
+	tab.tbl_width = 16;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	return (u8) ((m0m1 & 0xff00) >> 8);
+}
+
+static void wlc_lcnphy_set_bbmult(struct brcms_phy *pi, u8 m0)
+{
+	u16 m0m1 = (u16) m0 << 8;
+	struct phytbl_info tab;
+
+	tab.tbl_ptr = &m0m1;
+	tab.tbl_len = 1;
+	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
+	tab.tbl_offset = 87;
+	tab.tbl_width = 16;
+	wlc_lcnphy_write_table(pi, &tab);
+}
+
+static void wlc_lcnphy_clear_tx_power_offsets(struct brcms_phy *pi)
+{
+	u32 data_buf[64];
+	struct phytbl_info tab;
+
+	memset(data_buf, 0, sizeof(data_buf));
+
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_ptr = data_buf;
+
+	if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
+
+		tab.tbl_len = 30;
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+
+	tab.tbl_len = 64;
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_MAC_OFFSET;
+	wlc_lcnphy_write_table(pi, &tab);
+}
+
+enum lcnphy_tssi_mode {
+	LCNPHY_TSSI_PRE_PA,
+	LCNPHY_TSSI_POST_PA,
+	LCNPHY_TSSI_EXT
+};
+
+static void
+wlc_lcnphy_set_tssi_mux(struct brcms_phy *pi, enum lcnphy_tssi_mode pos)
+{
+	mod_phy_reg(pi, 0x4d7, (0x1 << 0), (0x1) << 0);
+
+	mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1) << 6);
+
+	if (LCNPHY_TSSI_POST_PA == pos) {
+		mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0) << 2);
+
+		mod_phy_reg(pi, 0x4d9, (0x1 << 3), (1) << 3);
+
+		if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+			mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
+		} else {
+			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1);
+			mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
+			mod_radio_reg(pi, RADIO_2064_REG028, 0x1, 0x0);
+			mod_radio_reg(pi, RADIO_2064_REG11A, 0x4, 1<<2);
+			mod_radio_reg(pi, RADIO_2064_REG036, 0x10, 0x0);
+			mod_radio_reg(pi, RADIO_2064_REG11A, 0x10, 1<<4);
+			mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0);
+			mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x77);
+			mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0xe<<1);
+			mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1<<7);
+			mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 1<<1);
+			mod_radio_reg(pi, RADIO_2064_REG029, 0xf0, 0<<4);
+		}
+	} else {
+		mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2);
+
+		mod_phy_reg(pi, 0x4d9, (0x1 << 3), (0) << 3);
+
+		if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+			mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
+		} else {
+			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0);
+			mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
+		}
+	}
+	mod_phy_reg(pi, 0x637, (0x3 << 14), (0) << 14);
+
+	if (LCNPHY_TSSI_EXT == pos) {
+		write_radio_reg(pi, RADIO_2064_REG07F, 1);
+		mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 0x2);
+		mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 0x1 << 7);
+		mod_radio_reg(pi, RADIO_2064_REG028, 0x1f, 0x3);
+	}
+}
+
+static u16 wlc_lcnphy_rfseq_tbl_adc_pwrup(struct brcms_phy *pi)
+{
+	u16 N1, N2, N3, N4, N5, N6, N;
+	N1 = ((read_phy_reg(pi, 0x4a5) & (0xff << 0))
+	      >> 0);
+	N2 = 1 << ((read_phy_reg(pi, 0x4a5) & (0x7 << 12))
+		   >> 12);
+	N3 = ((read_phy_reg(pi, 0x40d) & (0xff << 0))
+	      >> 0);
+	N4 = 1 << ((read_phy_reg(pi, 0x40d) & (0x7 << 8))
+		   >> 8);
+	N5 = ((read_phy_reg(pi, 0x4a2) & (0xff << 0))
+	      >> 0);
+	N6 = 1 << ((read_phy_reg(pi, 0x4a2) & (0x7 << 8))
+		   >> 8);
+	N = 2 * (N1 + N2 + N3 + N4 + 2 * (N5 + N6)) + 80;
+	if (N < 1600)
+		N = 1600;
+	return N;
+}
+
+static void wlc_lcnphy_pwrctrl_rssiparams(struct brcms_phy *pi)
+{
+	u16 auxpga_vmid, auxpga_vmid_temp, auxpga_gain_temp;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	auxpga_vmid = (2 << 8) |
+		      (pi_lcn->lcnphy_rssi_vc << 4) | pi_lcn->lcnphy_rssi_vf;
+	auxpga_vmid_temp = (2 << 8) | (8 << 4) | 4;
+	auxpga_gain_temp = 2;
+
+	mod_phy_reg(pi, 0x4d8, (0x1 << 0), (0) << 0);
+
+	mod_phy_reg(pi, 0x4d8, (0x1 << 1), (0) << 1);
+
+	mod_phy_reg(pi, 0x4d7, (0x1 << 3), (0) << 3);
+
+	mod_phy_reg(pi, 0x4db,
+		    (0x3ff << 0) |
+		    (0x7 << 12),
+		    (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
+
+	mod_phy_reg(pi, 0x4dc,
+		    (0x3ff << 0) |
+		    (0x7 << 12),
+		    (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
+
+	mod_phy_reg(pi, 0x40a,
+		    (0x3ff << 0) |
+		    (0x7 << 12),
+		    (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
+
+	mod_phy_reg(pi, 0x40b,
+		    (0x3ff << 0) |
+		    (0x7 << 12),
+		    (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
+
+	mod_phy_reg(pi, 0x40c,
+		    (0x3ff << 0) |
+		    (0x7 << 12),
+		    (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
+
+	mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5));
+	mod_radio_reg(pi, RADIO_2064_REG07C, (1 << 0), (1 << 0));
+}
+
+static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
+{
+	struct phytbl_info tab;
+	u32 rfseq, ind;
+	enum lcnphy_tssi_mode mode;
+	u8 tssi_sel;
+
+	if (pi->sh->boardflags & BFL_FEM) {
+		tssi_sel = 0x1;
+		mode = LCNPHY_TSSI_EXT;
+	} else {
+		tssi_sel = 0xe;
+		mode = LCNPHY_TSSI_POST_PA;
+	}
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_ptr = &ind;
+	tab.tbl_len = 1;
+	tab.tbl_offset = 0;
+	for (ind = 0; ind < 128; ind++) {
+		wlc_lcnphy_write_table(pi, &tab);
+		tab.tbl_offset++;
+	}
+	tab.tbl_offset = 704;
+	for (ind = 0; ind < 128; ind++) {
+		wlc_lcnphy_write_table(pi, &tab);
+		tab.tbl_offset++;
+	}
+	mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0);
+
+	mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2);
+
+	mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4);
+
+	wlc_lcnphy_set_tssi_mux(pi, mode);
+	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15);
+
+	mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5);
+
+	mod_phy_reg(pi, 0x4a4, (0x1ff << 0), (0) << 0);
+
+	mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0);
+
+	mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12);
+
+	mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8);
+
+	mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0);
+
+	mod_phy_reg(pi, 0x40d, (0x7 << 8), (4) << 8);
+
+	mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0);
+
+	mod_phy_reg(pi, 0x4a2, (0x7 << 8), (4) << 8);
+
+	mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (0) << 6);
+
+	mod_phy_reg(pi, 0x4a8, (0xff << 0), (0x1) << 0);
+
+	wlc_lcnphy_clear_tx_power_offsets(pi);
+
+	mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15);
+
+	mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (0xff) << 0);
+
+	mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+		mod_radio_reg(pi, RADIO_2064_REG028, 0xf, tssi_sel);
+		mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
+	} else {
+		mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, tssi_sel << 1);
+		mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
+		mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3);
+	}
+
+	write_radio_reg(pi, RADIO_2064_REG025, 0xc);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+		mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
+	} else {
+		if (CHSPEC_IS2G(pi->radio_chanspec))
+			mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1);
+		else
+			mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 0 << 1);
+	}
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2))
+		mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1);
+	else
+		mod_radio_reg(pi, RADIO_2064_REG03A, 0x4, 1 << 2);
+
+	mod_radio_reg(pi, RADIO_2064_REG11A, 0x1, 1 << 0);
+
+	mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 1 << 3);
+
+	if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
+		mod_phy_reg(pi, 0x4d7,
+			    (0x1 << 3) | (0x7 << 12), 0 << 3 | 2 << 12);
+
+	rfseq = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi);
+	tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
+	tab.tbl_width = 16;
+	tab.tbl_ptr = &rfseq;
+	tab.tbl_len = 1;
+	tab.tbl_offset = 6;
+	wlc_lcnphy_write_table(pi, &tab);
+
+	mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2);
+
+	mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
+
+	mod_phy_reg(pi, 0x4d7, (0x1 << 2), (1) << 2);
+
+	mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8);
+
+	mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x0);
+	mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0);
+	mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
+
+	wlc_lcnphy_pwrctrl_rssiparams(pi);
+}
+
+void wlc_lcnphy_tx_pwr_update_npt(struct brcms_phy *pi)
+{
+	u16 tx_cnt, tx_total, npt;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	tx_total = wlc_lcnphy_total_tx_frames(pi);
+	tx_cnt = tx_total - pi_lcn->lcnphy_tssi_tx_cnt;
+	npt = wlc_lcnphy_get_tx_pwr_npt(pi);
+
+	if (tx_cnt > (1 << npt)) {
+
+		pi_lcn->lcnphy_tssi_tx_cnt = tx_total;
+
+		pi_lcn->lcnphy_tssi_idx = wlc_lcnphy_get_current_tx_pwr_idx(pi);
+		pi_lcn->lcnphy_tssi_npt = npt;
+
+	}
+}
+
+s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1)
+{
+	s32 a, b, p;
+
+	a = 32768 + (a1 * tssi);
+	b = (1024 * b0) + (64 * b1 * tssi);
+	p = ((2 * b) + a) / (2 * a);
+
+	return p;
+}
+
+static void wlc_lcnphy_txpower_reset_npt(struct brcms_phy *pi)
+{
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
+		return;
+
+	pi_lcn->lcnphy_tssi_idx = LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313;
+	pi_lcn->lcnphy_tssi_npt = LCNPHY_TX_PWR_CTRL_START_NPT;
+}
+
+void wlc_lcnphy_txpower_recalc_target(struct brcms_phy *pi)
+{
+	struct phytbl_info tab;
+	u32 rate_table[BRCMS_NUM_RATES_CCK + BRCMS_NUM_RATES_OFDM +
+		       BRCMS_NUM_RATES_MCS_1_STREAM];
+	uint i, j;
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
+		return;
+
+	for (i = 0, j = 0; i < ARRAY_SIZE(rate_table); i++, j++) {
+
+		if (i == BRCMS_NUM_RATES_CCK + BRCMS_NUM_RATES_OFDM)
+			j = TXP_FIRST_MCS_20_SISO;
+
+		rate_table[i] = (u32) ((s32) (-pi->tx_power_offset[j]));
+	}
+
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_len = ARRAY_SIZE(rate_table);
+	tab.tbl_ptr = rate_table;
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
+	wlc_lcnphy_write_table(pi, &tab);
+
+	if (wlc_lcnphy_get_target_tx_pwr(pi) != pi->tx_power_min) {
+		wlc_lcnphy_set_target_tx_pwr(pi, pi->tx_power_min);
+
+		wlc_lcnphy_txpower_reset_npt(pi);
+	}
+}
+
+static void wlc_lcnphy_set_tx_pwr_soft_ctrl(struct brcms_phy *pi, s8 index)
+{
+	u32 cck_offset[4] = { 22, 22, 22, 22 };
+	u32 ofdm_offset, reg_offset_cck;
+	int i;
+	u16 index2;
+	struct phytbl_info tab;
+
+	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
+		return;
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x0) << 14);
+
+	or_phy_reg(pi, 0x6da, 0x0040);
+
+	reg_offset_cck = 0;
+	for (i = 0; i < 4; i++)
+		cck_offset[i] -= reg_offset_cck;
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_len = 4;
+	tab.tbl_ptr = cck_offset;
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
+	wlc_lcnphy_write_table(pi, &tab);
+	ofdm_offset = 0;
+	tab.tbl_len = 1;
+	tab.tbl_ptr = &ofdm_offset;
+	for (i = 836; i < 862; i++) {
+		tab.tbl_offset = i;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0x1) << 15);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 13), (0x1) << 13);
+
+	mod_phy_reg(pi, 0x4b0, (0x1 << 7), (0) << 7);
+
+	mod_phy_reg(pi, 0x43b, (0x1 << 6), (0) << 6);
+
+	mod_phy_reg(pi, 0x4a9, (0x1 << 15), (1) << 15);
+
+	index2 = (u16) (index * 2);
+	mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0);
+
+	mod_phy_reg(pi, 0x6a3, (0x1 << 4), (0) << 4);
+
+}
+
+static s8 wlc_lcnphy_tempcompensated_txpwrctrl(struct brcms_phy *pi)
+{
+	s8 index, delta_brd, delta_temp, new_index, tempcorrx;
+	s16 manp, meas_temp, temp_diff;
+	bool neg = false;
+	u16 temp;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
+		return pi_lcn->lcnphy_current_index;
+
+	index = FIXED_TXPWR;
+
+	if (pi_lcn->lcnphy_tempsense_slope == 0)
+		return index;
+
+	temp = (u16) wlc_lcnphy_tempsense(pi, 0);
+	meas_temp = LCNPHY_TEMPSENSE(temp);
+
+	if (pi->tx_power_min != 0)
+		delta_brd = (pi_lcn->lcnphy_measPower - pi->tx_power_min);
+	else
+		delta_brd = 0;
+
+	manp = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_rawtempsense);
+	temp_diff = manp - meas_temp;
+	if (temp_diff < 0) {
+		neg = true;
+		temp_diff = -temp_diff;
+	}
+
+	delta_temp = (s8) wlc_lcnphy_qdiv_roundup((u32) (temp_diff * 192),
+						  (u32) (pi_lcn->
+							 lcnphy_tempsense_slope
+							 * 10), 0);
+	if (neg)
+		delta_temp = -delta_temp;
+
+	if (pi_lcn->lcnphy_tempsense_option == 3
+	    && LCNREV_IS(pi->pubpi.phy_rev, 0))
+		delta_temp = 0;
+	if (pi_lcn->lcnphy_tempcorrx > 31)
+		tempcorrx = (s8) (pi_lcn->lcnphy_tempcorrx - 64);
+	else
+		tempcorrx = (s8) pi_lcn->lcnphy_tempcorrx;
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
+		tempcorrx = 4;
+	new_index =
+		index + delta_brd + delta_temp - pi_lcn->lcnphy_bandedge_corr;
+	new_index += tempcorrx;
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
+		index = 127;
+
+	if (new_index < 0 || new_index > 126)
+		return index;
+
+	return new_index;
+}
+
+static u16 wlc_lcnphy_set_tx_pwr_ctrl_mode(struct brcms_phy *pi, u16 mode)
+{
+
+	u16 current_mode = mode;
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) &&
+	    mode == LCNPHY_TX_PWR_CTRL_HW)
+		current_mode = LCNPHY_TX_PWR_CTRL_TEMPBASED;
+	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) &&
+	    mode == LCNPHY_TX_PWR_CTRL_TEMPBASED)
+		current_mode = LCNPHY_TX_PWR_CTRL_HW;
+	return current_mode;
+}
+
+void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode)
+{
+	u16 old_mode = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	s8 index;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, mode);
+	old_mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, old_mode);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 6),
+		    ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 1 : 0) << 6);
+
+	mod_phy_reg(pi, 0x6a3, (0x1 << 4),
+		    ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 0 : 1) << 4);
+
+	if (old_mode != mode) {
+		if (LCNPHY_TX_PWR_CTRL_HW == old_mode) {
+
+			wlc_lcnphy_tx_pwr_update_npt(pi);
+
+			wlc_lcnphy_clear_tx_power_offsets(pi);
+		}
+		if (LCNPHY_TX_PWR_CTRL_HW == mode) {
+
+			wlc_lcnphy_txpower_recalc_target(pi);
+
+			wlc_lcnphy_set_start_tx_pwr_idx(pi,
+							pi_lcn->
+							lcnphy_tssi_idx);
+			wlc_lcnphy_set_tx_pwr_npt(pi, pi_lcn->lcnphy_tssi_npt);
+			mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0);
+
+			pi_lcn->lcnphy_tssi_tx_cnt =
+				wlc_lcnphy_total_tx_frames(pi);
+
+			wlc_lcnphy_disable_tx_gain_override(pi);
+			pi_lcn->lcnphy_tx_power_idx_override = -1;
+		} else
+			wlc_lcnphy_enable_tx_gain_override(pi);
+
+		mod_phy_reg(pi, 0x4a4,
+			    ((0x1 << 15) | (0x1 << 14) | (0x1 << 13)), mode);
+		if (mode == LCNPHY_TX_PWR_CTRL_TEMPBASED) {
+			index = wlc_lcnphy_tempcompensated_txpwrctrl(pi);
+			wlc_lcnphy_set_tx_pwr_soft_ctrl(pi, index);
+			pi_lcn->lcnphy_current_index = (s8)
+						       ((read_phy_reg(pi,
+								      0x4a9) &
+							 0xFF) / 2);
+		}
+	}
+}
+
+static void
+wlc_lcnphy_tx_iqlo_loopback(struct brcms_phy *pi, u16 *values_to_save)
+{
+	u16 vmid;
+	int i;
+	for (i = 0; i < 20; i++)
+		values_to_save[i] =
+			read_radio_reg(pi, iqlo_loopback_rf_regs[i]);
+
+	mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12);
+	mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14);
+
+	mod_phy_reg(pi, 0x44c, (0x1 << 11), 1 << 11);
+	mod_phy_reg(pi, 0x44d, (0x1 << 13), 0 << 13);
+
+	mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
+	mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
+
+	mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
+	mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2))
+		and_radio_reg(pi, RADIO_2064_REG03A, 0xFD);
+	else
+		and_radio_reg(pi, RADIO_2064_REG03A, 0xF9);
+	or_radio_reg(pi, RADIO_2064_REG11A, 0x1);
+
+	or_radio_reg(pi, RADIO_2064_REG036, 0x01);
+	or_radio_reg(pi, RADIO_2064_REG11A, 0x18);
+	udelay(20);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+		if (CHSPEC_IS5G(pi->radio_chanspec))
+			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0);
+		else
+			or_radio_reg(pi, RADIO_2064_REG03A, 1);
+	} else {
+		if (CHSPEC_IS5G(pi->radio_chanspec))
+			mod_radio_reg(pi, RADIO_2064_REG03A, 3, 1);
+		else
+			or_radio_reg(pi, RADIO_2064_REG03A, 0x3);
+	}
+
+	udelay(20);
+
+	write_radio_reg(pi, RADIO_2064_REG025, 0xF);
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+		if (CHSPEC_IS5G(pi->radio_chanspec))
+			mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x4);
+		else
+			mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x6);
+	} else {
+		if (CHSPEC_IS5G(pi->radio_chanspec))
+			mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x4 << 1);
+		else
+			mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x6 << 1);
+	}
+
+	udelay(20);
+
+	write_radio_reg(pi, RADIO_2064_REG005, 0x8);
+	or_radio_reg(pi, RADIO_2064_REG112, 0x80);
+	udelay(20);
+
+	or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
+	or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
+	udelay(20);
+
+	or_radio_reg(pi, RADIO_2064_REG00B, 0x7);
+	or_radio_reg(pi, RADIO_2064_REG113, 0x10);
+	udelay(20);
+
+	write_radio_reg(pi, RADIO_2064_REG007, 0x1);
+	udelay(20);
+
+	vmid = 0x2A6;
+	mod_radio_reg(pi, RADIO_2064_REG0FC, 0x3 << 0, (vmid >> 8) & 0x3);
+	write_radio_reg(pi, RADIO_2064_REG0FD, (vmid & 0xff));
+	or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
+	udelay(20);
+
+	or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
+	udelay(20);
+	write_radio_reg(pi, RADIO_2064_REG012, 0x02);
+	or_radio_reg(pi, RADIO_2064_REG112, 0x06);
+	write_radio_reg(pi, RADIO_2064_REG036, 0x11);
+	write_radio_reg(pi, RADIO_2064_REG059, 0xcc);
+	write_radio_reg(pi, RADIO_2064_REG05C, 0x2e);
+	write_radio_reg(pi, RADIO_2064_REG078, 0xd7);
+	write_radio_reg(pi, RADIO_2064_REG092, 0x15);
+}
+
+static bool wlc_lcnphy_iqcal_wait(struct brcms_phy *pi)
+{
+	uint delay_count = 0;
+
+	while (wlc_lcnphy_iqcal_active(pi)) {
+		udelay(100);
+		delay_count++;
+
+		if (delay_count > (10 * 500))
+			break;
+	}
+
+	return (0 == wlc_lcnphy_iqcal_active(pi));
+}
+
+static void
+wlc_lcnphy_tx_iqlo_loopback_cleanup(struct brcms_phy *pi, u16 *values_to_save)
+{
+	int i;
+
+	and_phy_reg(pi, 0x44c, 0x0 >> 11);
+
+	and_phy_reg(pi, 0x43b, 0xC);
+
+	for (i = 0; i < 20; i++)
+		write_radio_reg(pi, iqlo_loopback_rf_regs[i],
+				values_to_save[i]);
+}
+
+static void
+wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
+		       struct lcnphy_txgains *target_gains,
+		       enum lcnphy_cal_mode cal_mode, bool keep_tone)
+{
+
+	struct lcnphy_txgains cal_gains, temp_gains;
+	u16 hash;
+	u8 band_idx;
+	int j;
+	u16 ncorr_override[5];
+	u16 syst_coeffs[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+			      0x0000, 0x0000, 0x0000, 0x0000, 0x0000};
+
+	u16 commands_fullcal[] = {
+		0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234
+	};
+
+	u16 commands_recal[] = {
+		0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234
+	};
+
+	u16 command_nums_fullcal[] = {
+		0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97
+	};
+
+	u16 command_nums_recal[] = {
+		0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97
+	};
+	u16 *command_nums = command_nums_fullcal;
+
+	u16 *start_coeffs = NULL, *cal_cmds = NULL, cal_type, diq_start;
+	u16 tx_pwr_ctrl_old, save_txpwrctrlrfctrl2;
+	u16 save_sslpnCalibClkEnCtrl, save_sslpnRxFeClkEnCtrl;
+	bool tx_gain_override_old;
+	struct lcnphy_txgains old_gains;
+	uint i, n_cal_cmds = 0, n_cal_start = 0;
+	u16 *values_to_save;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	values_to_save = kmalloc_array(20, sizeof(u16), GFP_ATOMIC);
+	if (NULL == values_to_save)
+		return;
+
+	save_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
+	save_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+
+	or_phy_reg(pi, 0x6da, 0x40);
+	or_phy_reg(pi, 0x6db, 0x3);
+
+	switch (cal_mode) {
+	case LCNPHY_CAL_FULL:
+		start_coeffs = syst_coeffs;
+		cal_cmds = commands_fullcal;
+		n_cal_cmds = ARRAY_SIZE(commands_fullcal);
+		break;
+
+	case LCNPHY_CAL_RECAL:
+		start_coeffs = syst_coeffs;
+		cal_cmds = commands_recal;
+		n_cal_cmds = ARRAY_SIZE(commands_recal);
+		command_nums = command_nums_recal;
+		break;
+
+	default:
+		break;
+	}
+
+	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				      start_coeffs, 11, 16, 64);
+
+	write_phy_reg(pi, 0x6da, 0xffff);
+	mod_phy_reg(pi, 0x503, (0x1 << 3), (1) << 3);
+
+	tx_pwr_ctrl_old = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
+
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+
+	save_txpwrctrlrfctrl2 = read_phy_reg(pi, 0x4db);
+
+	mod_phy_reg(pi, 0x4db, (0x3ff << 0), (0x2a6) << 0);
+
+	mod_phy_reg(pi, 0x4db, (0x7 << 12), (2) << 12);
+
+	wlc_lcnphy_tx_iqlo_loopback(pi, values_to_save);
+
+	tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
+	if (tx_gain_override_old)
+		wlc_lcnphy_get_tx_gain(pi, &old_gains);
+
+	if (!target_gains) {
+		if (!tx_gain_override_old)
+			wlc_lcnphy_set_tx_pwr_by_index(pi,
+						       pi_lcn->lcnphy_tssi_idx);
+		wlc_lcnphy_get_tx_gain(pi, &temp_gains);
+		target_gains = &temp_gains;
+	}
+
+	hash = (target_gains->gm_gain << 8) |
+	       (target_gains->pga_gain << 4) | (target_gains->pad_gain);
+
+	band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0);
+
+	cal_gains = *target_gains;
+	memset(ncorr_override, 0, sizeof(ncorr_override));
+	for (j = 0; j < iqcal_gainparams_numgains_lcnphy[band_idx]; j++) {
+		if (hash == tbl_iqcal_gainparams_lcnphy[band_idx][j][0]) {
+			cal_gains.gm_gain =
+				tbl_iqcal_gainparams_lcnphy[band_idx][j][1];
+			cal_gains.pga_gain =
+				tbl_iqcal_gainparams_lcnphy[band_idx][j][2];
+			cal_gains.pad_gain =
+				tbl_iqcal_gainparams_lcnphy[band_idx][j][3];
+			memcpy(ncorr_override,
+			       &tbl_iqcal_gainparams_lcnphy[band_idx][j][3],
+			       sizeof(ncorr_override));
+			break;
+		}
+	}
+
+	wlc_lcnphy_set_tx_gain(pi, &cal_gains);
+
+	write_phy_reg(pi, 0x453, 0xaa9);
+	write_phy_reg(pi, 0x93d, 0xc0);
+
+	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				      lcnphy_iqcal_loft_gainladder,
+				      ARRAY_SIZE(lcnphy_iqcal_loft_gainladder),
+				      16, 0);
+
+	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				      lcnphy_iqcal_ir_gainladder,
+				      ARRAY_SIZE(
+					      lcnphy_iqcal_ir_gainladder), 16,
+				      32);
+
+	if (pi->phy_tx_tone_freq) {
+
+		wlc_lcnphy_stop_tx_tone(pi);
+		udelay(5);
+		wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1);
+	} else {
+		wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1);
+	}
+
+	write_phy_reg(pi, 0x6da, 0xffff);
+
+	for (i = n_cal_start; i < n_cal_cmds; i++) {
+		u16 zero_diq = 0;
+		u16 best_coeffs[11];
+		u16 command_num;
+
+		cal_type = (cal_cmds[i] & 0x0f00) >> 8;
+
+		command_num = command_nums[i];
+		if (ncorr_override[cal_type])
+			command_num =
+				ncorr_override[cal_type] << 8 | (command_num &
+								 0xff);
+
+		write_phy_reg(pi, 0x452, command_num);
+
+		if ((cal_type == 3) || (cal_type == 4)) {
+			wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+						     &diq_start, 1, 16, 69);
+
+			wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+						      &zero_diq, 1, 16, 69);
+		}
+
+		write_phy_reg(pi, 0x451, cal_cmds[i]);
+
+		if (!wlc_lcnphy_iqcal_wait(pi))
+			goto cleanup;
+
+		wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+					     best_coeffs,
+					     ARRAY_SIZE(best_coeffs), 16, 96);
+		wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+					      best_coeffs,
+					      ARRAY_SIZE(best_coeffs), 16, 64);
+
+		if ((cal_type == 3) || (cal_type == 4))
+			wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+						      &diq_start, 1, 16, 69);
+		wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+					     pi_lcn->lcnphy_cal_results.
+					     txiqlocal_bestcoeffs,
+					     ARRAY_SIZE(pi_lcn->
+							lcnphy_cal_results.
+							txiqlocal_bestcoeffs),
+					     16, 96);
+	}
+
+	wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				     pi_lcn->lcnphy_cal_results.
+				     txiqlocal_bestcoeffs,
+				     ARRAY_SIZE(pi_lcn->lcnphy_cal_results.
+						txiqlocal_bestcoeffs), 16, 96);
+	pi_lcn->lcnphy_cal_results.txiqlocal_bestcoeffs_valid = true;
+
+	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				      &pi_lcn->lcnphy_cal_results.
+				      txiqlocal_bestcoeffs[0], 4, 16, 80);
+
+	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				      &pi_lcn->lcnphy_cal_results.
+				      txiqlocal_bestcoeffs[5], 2, 16, 85);
+
+cleanup:
+	wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, values_to_save);
+	kfree(values_to_save);
+
+	if (!keep_tone)
+		wlc_lcnphy_stop_tx_tone(pi);
+
+	write_phy_reg(pi, 0x4db, save_txpwrctrlrfctrl2);
+
+	write_phy_reg(pi, 0x453, 0);
+
+	if (tx_gain_override_old)
+		wlc_lcnphy_set_tx_gain(pi, &old_gains);
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl_old);
+
+	write_phy_reg(pi, 0x6da, save_sslpnCalibClkEnCtrl);
+	write_phy_reg(pi, 0x6db, save_sslpnRxFeClkEnCtrl);
+
+}
+
+static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
+{
+	bool suspend, tx_gain_override_old;
+	struct lcnphy_txgains old_gains;
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+	u16 idleTssi, idleTssi0_2C, idleTssi0_OB, idleTssi0_regvalue_OB,
+	    idleTssi0_regvalue_2C;
+	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	u16 SAVE_lpfgain = read_radio_reg(pi, RADIO_2064_REG112);
+	u16 SAVE_jtag_bb_afe_switch =
+		read_radio_reg(pi, RADIO_2064_REG007) & 1;
+	u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10;
+	u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4;
+	u8 SAVE_bbmult = wlc_lcnphy_get_bbmult(pi);
+
+	idleTssi = read_phy_reg(pi, 0x4ab);
+	suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
+			 MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+
+	tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
+	wlc_lcnphy_get_tx_gain(pi, &old_gains);
+
+	wlc_lcnphy_enable_tx_gain_override(pi);
+	wlc_lcnphy_set_tx_pwr_by_index(pi, 127);
+	write_radio_reg(pi, RADIO_2064_REG112, 0x6);
+	mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 1);
+	mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4);
+	mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2);
+	wlc_lcnphy_tssi_setup(pi);
+
+	mod_phy_reg(pi, 0x4d7, (0x1 << 0), (1 << 0));
+	mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1 << 6));
+
+	wlc_lcnphy_set_bbmult(pi, 0x0);
+
+	wlc_phy_do_dummy_tx(pi, true, OFF);
+	idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
+		    >> 0);
+
+	idleTssi0_2C = ((read_phy_reg(pi, 0x63e) & (0x1ff << 0))
+			>> 0);
+
+	if (idleTssi0_2C >= 256)
+		idleTssi0_OB = idleTssi0_2C - 256;
+	else
+		idleTssi0_OB = idleTssi0_2C + 256;
+
+	idleTssi0_regvalue_OB = idleTssi0_OB;
+	if (idleTssi0_regvalue_OB >= 256)
+		idleTssi0_regvalue_2C = idleTssi0_regvalue_OB - 256;
+	else
+		idleTssi0_regvalue_2C = idleTssi0_regvalue_OB + 256;
+	mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (idleTssi0_regvalue_2C) << 0);
+
+	mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12);
+
+	wlc_lcnphy_set_bbmult(pi, SAVE_bbmult);
+	wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old);
+	wlc_lcnphy_set_tx_gain(pi, &old_gains);
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
+
+	write_radio_reg(pi, RADIO_2064_REG112, SAVE_lpfgain);
+	mod_radio_reg(pi, RADIO_2064_REG007, 0x1, SAVE_jtag_bb_afe_switch);
+	mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, SAVE_jtag_auxpga);
+	mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, SAVE_iqadc_aux_en);
+	mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1 << 7);
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+}
+
+static void wlc_lcnphy_vbat_temp_sense_setup(struct brcms_phy *pi, u8 mode)
+{
+	bool suspend;
+	u16 save_txpwrCtrlEn;
+	u8 auxpga_vmidcourse, auxpga_vmidfine, auxpga_gain;
+	u16 auxpga_vmid;
+	struct phytbl_info tab;
+	u32 val;
+	u8 save_reg007, save_reg0FF, save_reg11F, save_reg005, save_reg025,
+	   save_reg112;
+	u16 values_to_save[14];
+	s8 index;
+	int i;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+	udelay(999);
+
+	save_reg007 = (u8) read_radio_reg(pi, RADIO_2064_REG007);
+	save_reg0FF = (u8) read_radio_reg(pi, RADIO_2064_REG0FF);
+	save_reg11F = (u8) read_radio_reg(pi, RADIO_2064_REG11F);
+	save_reg005 = (u8) read_radio_reg(pi, RADIO_2064_REG005);
+	save_reg025 = (u8) read_radio_reg(pi, RADIO_2064_REG025);
+	save_reg112 = (u8) read_radio_reg(pi, RADIO_2064_REG112);
+
+	for (i = 0; i < 14; i++)
+		values_to_save[i] = read_phy_reg(pi, tempsense_phy_regs[i]);
+	suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
+			 MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+	save_txpwrCtrlEn = read_radio_reg(pi, 0x4a4);
+
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+	index = pi_lcn->lcnphy_current_index;
+	wlc_lcnphy_set_tx_pwr_by_index(pi, 127);
+	mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 0x1);
+	mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 0x1 << 4);
+	mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0x1 << 2);
+	mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0);
+
+	mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0) << 15);
+
+	mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5);
+
+	mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0);
+
+	mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12);
+
+	mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8);
+
+	mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0);
+
+	mod_phy_reg(pi, 0x40d, (0x7 << 8), (6) << 8);
+
+	mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0);
+
+	mod_phy_reg(pi, 0x4a2, (0x7 << 8), (6) << 8);
+
+	mod_phy_reg(pi, 0x4d9, (0x7 << 4), (2) << 4);
+
+	mod_phy_reg(pi, 0x4d9, (0x7 << 8), (3) << 8);
+
+	mod_phy_reg(pi, 0x4d9, (0x7 << 12), (1) << 12);
+
+	mod_phy_reg(pi, 0x4da, (0x1 << 12), (0) << 12);
+
+	mod_phy_reg(pi, 0x4da, (0x1 << 13), (1) << 13);
+
+	mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15);
+
+	write_radio_reg(pi, RADIO_2064_REG025, 0xC);
+
+	mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 0x1 << 3);
+
+	mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2);
+
+	mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
+
+	val = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi);
+	tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
+	tab.tbl_width = 16;
+	tab.tbl_len = 1;
+	tab.tbl_ptr = &val;
+	tab.tbl_offset = 6;
+	wlc_lcnphy_write_table(pi, &tab);
+	if (mode == TEMPSENSE) {
+		mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3);
+
+		mod_phy_reg(pi, 0x4d7, (0x7 << 12), (1) << 12);
+
+		auxpga_vmidcourse = 8;
+		auxpga_vmidfine = 0x4;
+		auxpga_gain = 2;
+		mod_radio_reg(pi, RADIO_2064_REG082, 0x20, 1 << 5);
+	} else {
+		mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3);
+
+		mod_phy_reg(pi, 0x4d7, (0x7 << 12), (3) << 12);
+
+		auxpga_vmidcourse = 7;
+		auxpga_vmidfine = 0xa;
+		auxpga_gain = 2;
+	}
+	auxpga_vmid =
+		(u16) ((2 << 8) | (auxpga_vmidcourse << 4) | auxpga_vmidfine);
+	mod_phy_reg(pi, 0x4d8, (0x1 << 0), (1) << 0);
+
+	mod_phy_reg(pi, 0x4d8, (0x3ff << 2), (auxpga_vmid) << 2);
+
+	mod_phy_reg(pi, 0x4d8, (0x1 << 1), (1) << 1);
+
+	mod_phy_reg(pi, 0x4d8, (0x7 << 12), (auxpga_gain) << 12);
+
+	mod_phy_reg(pi, 0x4d0, (0x1 << 5), (1) << 5);
+
+	write_radio_reg(pi, RADIO_2064_REG112, 0x6);
+
+	wlc_phy_do_dummy_tx(pi, true, OFF);
+	if (!tempsense_done(pi))
+		udelay(10);
+
+	write_radio_reg(pi, RADIO_2064_REG007, (u16) save_reg007);
+	write_radio_reg(pi, RADIO_2064_REG0FF, (u16) save_reg0FF);
+	write_radio_reg(pi, RADIO_2064_REG11F, (u16) save_reg11F);
+	write_radio_reg(pi, RADIO_2064_REG005, (u16) save_reg005);
+	write_radio_reg(pi, RADIO_2064_REG025, (u16) save_reg025);
+	write_radio_reg(pi, RADIO_2064_REG112, (u16) save_reg112);
+	for (i = 0; i < 14; i++)
+		write_phy_reg(pi, tempsense_phy_regs[i], values_to_save[i]);
+	wlc_lcnphy_set_tx_pwr_by_index(pi, (int)index);
+
+	write_radio_reg(pi, 0x4a4, save_txpwrCtrlEn);
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+	udelay(999);
+}
+
+static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi)
+{
+	struct lcnphy_txgains tx_gains;
+	u8 bbmult;
+	struct phytbl_info tab;
+	s32 a1, b0, b1;
+	s32 tssi, pwr, maxtargetpwr, mintargetpwr;
+	bool suspend;
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+
+	suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
+			 MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	if (!pi->hwpwrctrl_capable) {
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			tx_gains.gm_gain = 4;
+			tx_gains.pga_gain = 12;
+			tx_gains.pad_gain = 12;
+			tx_gains.dac_gain = 0;
+
+			bbmult = 150;
+		} else {
+			tx_gains.gm_gain = 7;
+			tx_gains.pga_gain = 15;
+			tx_gains.pad_gain = 14;
+			tx_gains.dac_gain = 0;
+
+			bbmult = 150;
+		}
+		wlc_lcnphy_set_tx_gain(pi, &tx_gains);
+		wlc_lcnphy_set_bbmult(pi, bbmult);
+		wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
+	} else {
+
+		wlc_lcnphy_idle_tssi_est(ppi);
+
+		wlc_lcnphy_clear_tx_power_offsets(pi);
+
+		b0 = pi->txpa_2g[0];
+		b1 = pi->txpa_2g[1];
+		a1 = pi->txpa_2g[2];
+		maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1);
+		mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1);
+
+		tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+		tab.tbl_width = 32;
+		tab.tbl_ptr = &pwr;
+		tab.tbl_len = 1;
+		tab.tbl_offset = 0;
+		for (tssi = 0; tssi < 128; tssi++) {
+			pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1);
+
+			pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr;
+			wlc_lcnphy_write_table(pi, &tab);
+			tab.tbl_offset++;
+		}
+		mod_phy_reg(pi, 0x4d0, (0x1 << 0), (0) << 0);
+		mod_phy_reg(pi, 0x4d3, (0xff << 0), (0) << 0);
+		mod_phy_reg(pi, 0x4d3, (0xff << 8), (0) << 8);
+		mod_phy_reg(pi, 0x4d0, (0x1 << 4), (0) << 4);
+		mod_phy_reg(pi, 0x4d0, (0x1 << 2), (0) << 2);
+
+		mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7);
+
+		write_phy_reg(pi, 0x4a8, 10);
+
+		wlc_lcnphy_set_target_tx_pwr(pi, LCN_TARGET_PWR);
+
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
+	}
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+}
+
+static void wlc_lcnphy_set_pa_gain(struct brcms_phy *pi, u16 gain)
+{
+	mod_phy_reg(pi, 0x4fb,
+		    LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK,
+		    gain << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT);
+	mod_phy_reg(pi, 0x4fd,
+		    LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK,
+		    gain << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT);
+}
+
+void
+wlc_lcnphy_get_radio_loft(struct brcms_phy *pi,
+			  u8 *ei0, u8 *eq0, u8 *fi0, u8 *fq0)
+{
+	*ei0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG089));
+	*eq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08A));
+	*fi0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08B));
+	*fq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08C));
+}
+
+void wlc_lcnphy_set_tx_iqcc(struct brcms_phy *pi, u16 a, u16 b)
+{
+	struct phytbl_info tab;
+	u16 iqcc[2];
+
+	iqcc[0] = a;
+	iqcc[1] = b;
+
+	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
+	tab.tbl_width = 16;
+	tab.tbl_ptr = iqcc;
+	tab.tbl_len = 2;
+	tab.tbl_offset = 80;
+	wlc_lcnphy_write_table(pi, &tab);
+}
+
+void wlc_lcnphy_set_tx_locc(struct brcms_phy *pi, u16 didq)
+{
+	struct phytbl_info tab;
+
+	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
+	tab.tbl_width = 16;
+	tab.tbl_ptr = &didq;
+	tab.tbl_len = 1;
+	tab.tbl_offset = 85;
+	wlc_lcnphy_write_table(pi, &tab);
+}
+
+void wlc_lcnphy_set_tx_pwr_by_index(struct brcms_phy *pi, int index)
+{
+	struct phytbl_info tab;
+	u16 a, b;
+	u8 bb_mult;
+	u32 bbmultiqcomp, txgain, locoeffs, rfpower;
+	struct lcnphy_txgains gains;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	pi_lcn->lcnphy_tx_power_idx_override = (s8) index;
+	pi_lcn->lcnphy_current_index = (u8) index;
+
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_len = 1;
+
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index;
+	tab.tbl_ptr = &bbmultiqcomp;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index;
+	tab.tbl_width = 32;
+	tab.tbl_ptr = &txgain;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	gains.gm_gain = (u16) (txgain & 0xff);
+	gains.pga_gain = (u16) (txgain >> 8) & 0xff;
+	gains.pad_gain = (u16) (txgain >> 16) & 0xff;
+	gains.dac_gain = (u16) (bbmultiqcomp >> 28) & 0x07;
+	wlc_lcnphy_set_tx_gain(pi, &gains);
+	wlc_lcnphy_set_pa_gain(pi, (u16) (txgain >> 24) & 0x7f);
+
+	bb_mult = (u8) ((bbmultiqcomp >> 20) & 0xff);
+	wlc_lcnphy_set_bbmult(pi, bb_mult);
+
+	wlc_lcnphy_enable_tx_gain_override(pi);
+
+	if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
+
+		a = (u16) ((bbmultiqcomp >> 10) & 0x3ff);
+		b = (u16) (bbmultiqcomp & 0x3ff);
+		wlc_lcnphy_set_tx_iqcc(pi, a, b);
+
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + index;
+		tab.tbl_ptr = &locoeffs;
+		wlc_lcnphy_read_table(pi, &tab);
+
+		wlc_lcnphy_set_tx_locc(pi, (u16) locoeffs);
+
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index;
+		tab.tbl_ptr = &rfpower;
+		wlc_lcnphy_read_table(pi, &tab);
+		mod_phy_reg(pi, 0x6a6, (0x1fff << 0), (rfpower * 8) << 0);
+
+	}
+}
+
+static void wlc_lcnphy_clear_papd_comptable(struct brcms_phy *pi)
+{
+	u32 j;
+	struct phytbl_info tab;
+	u32 temp_offset[128];
+	tab.tbl_ptr = temp_offset;
+	tab.tbl_len = 128;
+	tab.tbl_id = LCNPHY_TBL_ID_PAPDCOMPDELTATBL;
+	tab.tbl_width = 32;
+	tab.tbl_offset = 0;
+
+	memset(temp_offset, 0, sizeof(temp_offset));
+	for (j = 1; j < 128; j += 2)
+		temp_offset[j] = 0x80000;
+
+	wlc_lcnphy_write_table(pi, &tab);
+	return;
+}
+
+void wlc_lcnphy_tx_pu(struct brcms_phy *pi, bool bEnable)
+{
+	if (!bEnable) {
+
+		and_phy_reg(pi, 0x43b, ~(u16) ((0x1 << 1) | (0x1 << 4)));
+
+		mod_phy_reg(pi, 0x43c, (0x1 << 1), 1 << 1);
+
+		and_phy_reg(pi, 0x44c,
+			    ~(u16) ((0x1 << 3) |
+				    (0x1 << 5) |
+				    (0x1 << 12) |
+				    (0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
+
+		and_phy_reg(pi, 0x44d,
+			    ~(u16) ((0x1 << 3) | (0x1 << 5) | (0x1 << 14)));
+		mod_phy_reg(pi, 0x44d, (0x1 << 2), 1 << 2);
+
+		mod_phy_reg(pi, 0x44d, (0x1 << 1) | (0x1 << 0), (0x1 << 0));
+
+		and_phy_reg(pi, 0x4f9,
+			    ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
+
+		and_phy_reg(pi, 0x4fa,
+			    ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
+	} else {
+
+		mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
+		mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
+
+		mod_phy_reg(pi, 0x43b, (0x1 << 4), 1 << 4);
+		mod_phy_reg(pi, 0x43c, (0x1 << 6), 0 << 6);
+
+		mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12);
+		mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14);
+
+		wlc_lcnphy_set_trsw_override(pi, true, false);
+
+		mod_phy_reg(pi, 0x44d, (0x1 << 2), 0 << 2);
+		mod_phy_reg(pi, 0x44c, (0x1 << 2), 1 << 2);
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+
+			mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3);
+			mod_phy_reg(pi, 0x44d, (0x1 << 3), 1 << 3);
+
+			mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5);
+			mod_phy_reg(pi, 0x44d, (0x1 << 5), 0 << 5);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 1), 1 << 1);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 2), 1 << 2);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 0), 1 << 0);
+		} else {
+
+			mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3);
+			mod_phy_reg(pi, 0x44d, (0x1 << 3), 0 << 3);
+
+			mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5);
+			mod_phy_reg(pi, 0x44d, (0x1 << 5), 1 << 5);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 1), 0 << 1);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 2), 0 << 2);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
+		}
+	}
+}
+
+static void
+wlc_lcnphy_run_samples(struct brcms_phy *pi,
+		       u16 num_samps,
+		       u16 num_loops, u16 wait, bool iqcalmode)
+{
+
+	or_phy_reg(pi, 0x6da, 0x8080);
+
+	mod_phy_reg(pi, 0x642, (0x7f << 0), (num_samps - 1) << 0);
+	if (num_loops != 0xffff)
+		num_loops--;
+	mod_phy_reg(pi, 0x640, (0xffff << 0), num_loops << 0);
+
+	mod_phy_reg(pi, 0x641, (0xffff << 0), wait << 0);
+
+	if (iqcalmode) {
+
+		and_phy_reg(pi, 0x453, (u16) ~(0x1 << 15));
+		or_phy_reg(pi, 0x453, (0x1 << 15));
+	} else {
+		write_phy_reg(pi, 0x63f, 1);
+		wlc_lcnphy_tx_pu(pi, 1);
+	}
+
+	or_radio_reg(pi, RADIO_2064_REG112, 0x6);
+}
+
+void wlc_lcnphy_deaf_mode(struct brcms_phy *pi, bool mode)
+{
+
+	u8 phybw40;
+	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+
+	mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5);
+	mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9);
+
+	if (phybw40 == 0) {
+		mod_phy_reg((pi), 0x410,
+			    (0x1 << 6) |
+			    (0x1 << 5),
+			    ((CHSPEC_IS2G(
+				      pi->radio_chanspec)) ? (!mode) : 0) <<
+			    6 | (!mode) << 5);
+		mod_phy_reg(pi, 0x410, (0x1 << 7), (mode) << 7);
+	}
+}
+
+void
+wlc_lcnphy_start_tx_tone(struct brcms_phy *pi, s32 f_kHz, u16 max_val,
+			 bool iqcalmode)
+{
+	u8 phy_bw;
+	u16 num_samps, t, k;
+	u32 bw;
+	s32 theta = 0, rot = 0;
+	struct cordic_iq tone_samp;
+	u32 data_buf[64];
+	u16 i_samp, q_samp;
+	struct phytbl_info tab;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	pi->phy_tx_tone_freq = f_kHz;
+
+	wlc_lcnphy_deaf_mode(pi, true);
+
+	phy_bw = 40;
+	if (pi_lcn->lcnphy_spurmod) {
+		write_phy_reg(pi, 0x942, 0x2);
+		write_phy_reg(pi, 0x93b, 0x0);
+		write_phy_reg(pi, 0x93c, 0x0);
+		wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
+	}
+
+	if (f_kHz) {
+		k = 1;
+		do {
+			bw = phy_bw * 1000 * k;
+			num_samps = bw / abs(f_kHz);
+			k++;
+		} while ((num_samps * (u32) (abs(f_kHz))) != bw);
+	} else
+		num_samps = 2;
+
+	rot = ((f_kHz * 36) / phy_bw) / 100;
+	theta = 0;
+
+	for (t = 0; t < num_samps; t++) {
+
+		tone_samp = cordic_calc_iq(theta);
+
+		theta += rot;
+
+		i_samp = (u16) (FLOAT(tone_samp.i * max_val) & 0x3ff);
+		q_samp = (u16) (FLOAT(tone_samp.q * max_val) & 0x3ff);
+		data_buf[t] = (i_samp << 10) | q_samp;
+	}
+
+	mod_phy_reg(pi, 0x6d6, (0x3 << 0), 0 << 0);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 3), 1 << 3);
+
+	tab.tbl_ptr = data_buf;
+	tab.tbl_len = num_samps;
+	tab.tbl_id = LCNPHY_TBL_ID_SAMPLEPLAY;
+	tab.tbl_offset = 0;
+	tab.tbl_width = 32;
+	wlc_lcnphy_write_table(pi, &tab);
+
+	wlc_lcnphy_run_samples(pi, num_samps, 0xffff, 0, iqcalmode);
+}
+
+void wlc_lcnphy_stop_tx_tone(struct brcms_phy *pi)
+{
+	s16 playback_status;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	pi->phy_tx_tone_freq = 0;
+	if (pi_lcn->lcnphy_spurmod) {
+		write_phy_reg(pi, 0x942, 0x7);
+		write_phy_reg(pi, 0x93b, 0x2017);
+		write_phy_reg(pi, 0x93c, 0x27c5);
+		wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
+	}
+
+	playback_status = read_phy_reg(pi, 0x644);
+	if (playback_status & (0x1 << 0)) {
+		wlc_lcnphy_tx_pu(pi, 0);
+		mod_phy_reg(pi, 0x63f, (0x1 << 1), 1 << 1);
+	} else if (playback_status & (0x1 << 1))
+		mod_phy_reg(pi, 0x453, (0x1 << 15), 0 << 15);
+
+	mod_phy_reg(pi, 0x6d6, (0x3 << 0), 1 << 0);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 3), 0 << 3);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 7), 0 << 7);
+
+	and_radio_reg(pi, RADIO_2064_REG112, 0xFFF9);
+
+	wlc_lcnphy_deaf_mode(pi, false);
+}
+
+static void
+wlc_lcnphy_set_cc(struct brcms_phy *pi, int cal_type, s16 coeff_x, s16 coeff_y)
+{
+	u16 di0dq0;
+	u16 x, y, data_rf;
+	int k;
+	switch (cal_type) {
+	case 0:
+		wlc_lcnphy_set_tx_iqcc(pi, coeff_x, coeff_y);
+		break;
+	case 2:
+		di0dq0 = (coeff_x & 0xff) << 8 | (coeff_y & 0xff);
+		wlc_lcnphy_set_tx_locc(pi, di0dq0);
+		break;
+	case 3:
+		k = wlc_lcnphy_calc_floor(coeff_x, 0);
+		y = 8 + k;
+		k = wlc_lcnphy_calc_floor(coeff_x, 1);
+		x = 8 - k;
+		data_rf = (x * 16 + y);
+		write_radio_reg(pi, RADIO_2064_REG089, data_rf);
+		k = wlc_lcnphy_calc_floor(coeff_y, 0);
+		y = 8 + k;
+		k = wlc_lcnphy_calc_floor(coeff_y, 1);
+		x = 8 - k;
+		data_rf = (x * 16 + y);
+		write_radio_reg(pi, RADIO_2064_REG08A, data_rf);
+		break;
+	case 4:
+		k = wlc_lcnphy_calc_floor(coeff_x, 0);
+		y = 8 + k;
+		k = wlc_lcnphy_calc_floor(coeff_x, 1);
+		x = 8 - k;
+		data_rf = (x * 16 + y);
+		write_radio_reg(pi, RADIO_2064_REG08B, data_rf);
+		k = wlc_lcnphy_calc_floor(coeff_y, 0);
+		y = 8 + k;
+		k = wlc_lcnphy_calc_floor(coeff_y, 1);
+		x = 8 - k;
+		data_rf = (x * 16 + y);
+		write_radio_reg(pi, RADIO_2064_REG08C, data_rf);
+		break;
+	}
+}
+
+static struct lcnphy_unsign16_struct
+wlc_lcnphy_get_cc(struct brcms_phy *pi, int cal_type)
+{
+	u16 a, b, didq;
+	u8 di0, dq0, ei, eq, fi, fq;
+	struct lcnphy_unsign16_struct cc;
+	cc.re = 0;
+	cc.im = 0;
+	switch (cal_type) {
+	case 0:
+		wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
+		cc.re = a;
+		cc.im = b;
+		break;
+	case 2:
+		didq = wlc_lcnphy_get_tx_locc(pi);
+		di0 = (((didq & 0xff00) << 16) >> 24);
+		dq0 = (((didq & 0x00ff) << 24) >> 24);
+		cc.re = (u16) di0;
+		cc.im = (u16) dq0;
+		break;
+	case 3:
+		wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
+		cc.re = (u16) ei;
+		cc.im = (u16) eq;
+		break;
+	case 4:
+		wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
+		cc.re = (u16) fi;
+		cc.im = (u16) fq;
+		break;
+	}
+	return cc;
+}
+
+static void
+wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo, u16 thresh,
+		    s16 *ptr, int mode)
+{
+	u32 curval1, curval2, stpptr, curptr, strptr, val;
+	u16 sslpnCalibClkEnCtrl, timer;
+	u16 old_sslpnCalibClkEnCtrl;
+	s16 imag, real;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	timer = 0;
+	old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+
+	curval1 = bcma_read16(pi->d11core, D11REGOFFS(psm_corectlsts));
+	ptr[130] = 0;
+	bcma_write16(pi->d11core, D11REGOFFS(psm_corectlsts),
+		     ((1 << 6) | curval1));
+
+	bcma_write16(pi->d11core, D11REGOFFS(smpl_clct_strptr), 0x7E00);
+	bcma_write16(pi->d11core, D11REGOFFS(smpl_clct_stpptr), 0x8000);
+	udelay(20);
+	curval2 = bcma_read16(pi->d11core, D11REGOFFS(psm_phy_hdr_param));
+	bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param),
+		     curval2 | 0x30);
+
+	write_phy_reg(pi, 0x555, 0x0);
+	write_phy_reg(pi, 0x5a6, 0x5);
+
+	write_phy_reg(pi, 0x5a2, (u16) (mode | mode << 6));
+	write_phy_reg(pi, 0x5cf, 3);
+	write_phy_reg(pi, 0x5a5, 0x3);
+	write_phy_reg(pi, 0x583, 0x0);
+	write_phy_reg(pi, 0x584, 0x0);
+	write_phy_reg(pi, 0x585, 0x0fff);
+	write_phy_reg(pi, 0x586, 0x0000);
+
+	write_phy_reg(pi, 0x580, 0x4501);
+
+	sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+	write_phy_reg(pi, 0x6da, (u32) (sslpnCalibClkEnCtrl | 0x2008));
+	stpptr = bcma_read16(pi->d11core, D11REGOFFS(smpl_clct_stpptr));
+	curptr = bcma_read16(pi->d11core, D11REGOFFS(smpl_clct_curptr));
+	do {
+		udelay(10);
+		curptr = bcma_read16(pi->d11core, D11REGOFFS(smpl_clct_curptr));
+		timer++;
+	} while ((curptr != stpptr) && (timer < 500));
+
+	bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), 0x2);
+	strptr = 0x7E00;
+	bcma_write32(pi->d11core, D11REGOFFS(tplatewrptr), strptr);
+	while (strptr < 0x8000) {
+		val = bcma_read32(pi->d11core, D11REGOFFS(tplatewrdata));
+		imag = ((val >> 16) & 0x3ff);
+		real = ((val) & 0x3ff);
+		if (imag > 511)
+			imag -= 1024;
+
+		if (real > 511)
+			real -= 1024;
+
+		if (pi_lcn->lcnphy_iqcal_swp_dis)
+			ptr[(strptr - 0x7E00) / 4] = real;
+		else
+			ptr[(strptr - 0x7E00) / 4] = imag;
+
+		if (clip_detect_algo) {
+			if (imag > thresh || imag < -thresh) {
+				strptr = 0x8000;
+				ptr[130] = 1;
+			}
+		}
+
+		strptr += 4;
+	}
+
+	write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
+	bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), curval2);
+	bcma_write16(pi->d11core, D11REGOFFS(psm_corectlsts), curval1);
+}
+
+static void
+wlc_lcnphy_a1(struct brcms_phy *pi, int cal_type, int num_levels,
+	      int step_size_lg2)
+{
+	const struct lcnphy_spb_tone *phy_c1;
+	struct lcnphy_spb_tone phy_c2;
+	struct lcnphy_unsign16_struct phy_c3;
+	int phy_c4, phy_c5, k, l, j, phy_c6;
+	u16 phy_c7, phy_c8, phy_c9;
+	s16 phy_c10, phy_c11, phy_c12, phy_c13, phy_c14, phy_c15, phy_c16;
+	s16 *ptr, phy_c17;
+	s32 phy_c18, phy_c19;
+	u32 phy_c20, phy_c21;
+	bool phy_c22, phy_c23, phy_c24, phy_c25;
+	u16 phy_c26, phy_c27;
+	u16 phy_c28, phy_c29, phy_c30;
+	u16 phy_c31;
+	u16 *phy_c32;
+	phy_c21 = 0;
+	phy_c10 = phy_c13 = phy_c14 = phy_c8 = 0;
+	ptr = kmalloc_array(131, sizeof(s16), GFP_ATOMIC);
+	if (NULL == ptr)
+		return;
+
+	phy_c32 = kmalloc_array(20, sizeof(u16), GFP_ATOMIC);
+	if (NULL == phy_c32) {
+		kfree(ptr);
+		return;
+	}
+	phy_c26 = read_phy_reg(pi, 0x6da);
+	phy_c27 = read_phy_reg(pi, 0x6db);
+	phy_c31 = read_radio_reg(pi, RADIO_2064_REG026);
+	write_phy_reg(pi, 0x93d, 0xC0);
+
+	wlc_lcnphy_start_tx_tone(pi, 3750, 88, 0);
+	write_phy_reg(pi, 0x6da, 0xffff);
+	or_phy_reg(pi, 0x6db, 0x3);
+
+	wlc_lcnphy_tx_iqlo_loopback(pi, phy_c32);
+	udelay(500);
+	phy_c28 = read_phy_reg(pi, 0x938);
+	phy_c29 = read_phy_reg(pi, 0x4d7);
+	phy_c30 = read_phy_reg(pi, 0x4d8);
+	or_phy_reg(pi, 0x938, 0x1 << 2);
+	or_phy_reg(pi, 0x4d7, 0x1 << 2);
+	or_phy_reg(pi, 0x4d7, 0x1 << 3);
+	mod_phy_reg(pi, 0x4d7, (0x7 << 12), 0x2 << 12);
+	or_phy_reg(pi, 0x4d8, 1 << 0);
+	or_phy_reg(pi, 0x4d8, 1 << 1);
+	mod_phy_reg(pi, 0x4d8, (0x3ff << 2), 0x23A << 2);
+	mod_phy_reg(pi, 0x4d8, (0x7 << 12), 0x7 << 12);
+	phy_c1 = &lcnphy_spb_tone_3750[0];
+	phy_c4 = 32;
+
+	if (num_levels == 0) {
+		if (cal_type != 0)
+			num_levels = 4;
+		else
+			num_levels = 9;
+	}
+	if (step_size_lg2 == 0) {
+		if (cal_type != 0)
+			step_size_lg2 = 3;
+		else
+			step_size_lg2 = 8;
+	}
+
+	phy_c7 = (1 << step_size_lg2);
+	phy_c3 = wlc_lcnphy_get_cc(pi, cal_type);
+	phy_c15 = (s16) phy_c3.re;
+	phy_c16 = (s16) phy_c3.im;
+	if (cal_type == 2) {
+		if (phy_c3.re > 127)
+			phy_c15 = phy_c3.re - 256;
+		if (phy_c3.im > 127)
+			phy_c16 = phy_c3.im - 256;
+	}
+	wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
+	udelay(20);
+	for (phy_c8 = 0; phy_c7 != 0 && phy_c8 < num_levels; phy_c8++) {
+		phy_c23 = true;
+		phy_c22 = false;
+		switch (cal_type) {
+		case 0:
+			phy_c10 = 511;
+			break;
+		case 2:
+			phy_c10 = 127;
+			break;
+		case 3:
+			phy_c10 = 15;
+			break;
+		case 4:
+			phy_c10 = 15;
+			break;
+		}
+
+		phy_c9 = read_phy_reg(pi, 0x93d);
+		phy_c9 = 2 * phy_c9;
+		phy_c24 = false;
+		phy_c5 = 7;
+		phy_c25 = true;
+		while (1) {
+			write_radio_reg(pi, RADIO_2064_REG026,
+					(phy_c5 & 0x7) | ((phy_c5 & 0x7) << 4));
+			udelay(50);
+			phy_c22 = false;
+			ptr[130] = 0;
+			wlc_lcnphy_samp_cap(pi, 1, phy_c9, &ptr[0], 2);
+			if (ptr[130] == 1)
+				phy_c22 = true;
+			if (phy_c22)
+				phy_c5 -= 1;
+			if ((phy_c22 != phy_c24) && (!phy_c25))
+				break;
+			if (!phy_c22)
+				phy_c5 += 1;
+			if (phy_c5 <= 0 || phy_c5 >= 7)
+				break;
+			phy_c24 = phy_c22;
+			phy_c25 = false;
+		}
+
+		if (phy_c5 < 0)
+			phy_c5 = 0;
+		else if (phy_c5 > 7)
+			phy_c5 = 7;
+
+		for (k = -phy_c7; k <= phy_c7; k += phy_c7) {
+			for (l = -phy_c7; l <= phy_c7; l += phy_c7) {
+				phy_c11 = phy_c15 + k;
+				phy_c12 = phy_c16 + l;
+
+				if (phy_c11 < -phy_c10)
+					phy_c11 = -phy_c10;
+				else if (phy_c11 > phy_c10)
+					phy_c11 = phy_c10;
+				if (phy_c12 < -phy_c10)
+					phy_c12 = -phy_c10;
+				else if (phy_c12 > phy_c10)
+					phy_c12 = phy_c10;
+				wlc_lcnphy_set_cc(pi, cal_type, phy_c11,
+						  phy_c12);
+				udelay(20);
+				wlc_lcnphy_samp_cap(pi, 0, 0, ptr, 2);
+
+				phy_c18 = 0;
+				phy_c19 = 0;
+				for (j = 0; j < 128; j++) {
+					if (cal_type != 0)
+						phy_c6 = j % phy_c4;
+					else
+						phy_c6 = (2 * j) % phy_c4;
+
+					phy_c2.re = phy_c1[phy_c6].re;
+					phy_c2.im = phy_c1[phy_c6].im;
+					phy_c17 = ptr[j];
+					phy_c18 = phy_c18 + phy_c17 * phy_c2.re;
+					phy_c19 = phy_c19 + phy_c17 * phy_c2.im;
+				}
+
+				phy_c18 = phy_c18 >> 10;
+				phy_c19 = phy_c19 >> 10;
+				phy_c20 = ((phy_c18 * phy_c18) +
+					   (phy_c19 * phy_c19));
+
+				if (phy_c23 || phy_c20 < phy_c21) {
+					phy_c21 = phy_c20;
+					phy_c13 = phy_c11;
+					phy_c14 = phy_c12;
+				}
+				phy_c23 = false;
+			}
+		}
+		phy_c23 = true;
+		phy_c15 = phy_c13;
+		phy_c16 = phy_c14;
+		phy_c7 = phy_c7 >> 1;
+		wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
+		udelay(20);
+	}
+	goto cleanup;
+cleanup:
+	wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, phy_c32);
+	wlc_lcnphy_stop_tx_tone(pi);
+	write_phy_reg(pi, 0x6da, phy_c26);
+	write_phy_reg(pi, 0x6db, phy_c27);
+	write_phy_reg(pi, 0x938, phy_c28);
+	write_phy_reg(pi, 0x4d7, phy_c29);
+	write_phy_reg(pi, 0x4d8, phy_c30);
+	write_radio_reg(pi, RADIO_2064_REG026, phy_c31);
+
+	kfree(phy_c32);
+	kfree(ptr);
+}
+
+void wlc_lcnphy_get_tx_iqcc(struct brcms_phy *pi, u16 *a, u16 *b)
+{
+	u16 iqcc[2];
+	struct phytbl_info tab;
+
+	tab.tbl_ptr = iqcc;
+	tab.tbl_len = 2;
+	tab.tbl_id = 0;
+	tab.tbl_offset = 80;
+	tab.tbl_width = 16;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	*a = iqcc[0];
+	*b = iqcc[1];
+}
+
+static void wlc_lcnphy_tx_iqlo_soft_cal_full(struct brcms_phy *pi)
+{
+	struct lcnphy_unsign16_struct iqcc0, locc2, locc3, locc4;
+
+	wlc_lcnphy_set_cc(pi, 0, 0, 0);
+	wlc_lcnphy_set_cc(pi, 2, 0, 0);
+	wlc_lcnphy_set_cc(pi, 3, 0, 0);
+	wlc_lcnphy_set_cc(pi, 4, 0, 0);
+
+	wlc_lcnphy_a1(pi, 4, 0, 0);
+	wlc_lcnphy_a1(pi, 3, 0, 0);
+	wlc_lcnphy_a1(pi, 2, 3, 2);
+	wlc_lcnphy_a1(pi, 0, 5, 8);
+	wlc_lcnphy_a1(pi, 2, 2, 1);
+	wlc_lcnphy_a1(pi, 0, 4, 3);
+
+	iqcc0 = wlc_lcnphy_get_cc(pi, 0);
+	locc2 = wlc_lcnphy_get_cc(pi, 2);
+	locc3 = wlc_lcnphy_get_cc(pi, 3);
+	locc4 = wlc_lcnphy_get_cc(pi, 4);
+}
+
+u16 wlc_lcnphy_get_tx_locc(struct brcms_phy *pi)
+{
+	struct phytbl_info tab;
+	u16 didq;
+
+	tab.tbl_id = 0;
+	tab.tbl_width = 16;
+	tab.tbl_ptr = &didq;
+	tab.tbl_len = 1;
+	tab.tbl_offset = 85;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	return didq;
+}
+
+static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
+{
+
+	struct lcnphy_txgains target_gains, old_gains;
+	u8 save_bb_mult;
+	u16 a, b, didq, save_pa_gain = 0;
+	uint idx, SAVE_txpwrindex = 0xFF;
+	u32 val;
+	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	struct phytbl_info tab;
+	u8 ei0, eq0, fi0, fq0;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	wlc_lcnphy_get_tx_gain(pi, &old_gains);
+	save_pa_gain = wlc_lcnphy_get_pa_gain(pi);
+
+	save_bb_mult = wlc_lcnphy_get_bbmult(pi);
+
+	if (SAVE_txpwrctrl == LCNPHY_TX_PWR_CTRL_OFF)
+		SAVE_txpwrindex = wlc_lcnphy_get_current_tx_pwr_idx(pi);
+
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+
+	target_gains.gm_gain = 7;
+	target_gains.pga_gain = 0;
+	target_gains.pad_gain = 21;
+	target_gains.dac_gain = 0;
+	wlc_lcnphy_set_tx_gain(pi, &target_gains);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) {
+
+		wlc_lcnphy_set_tx_pwr_by_index(pi, 30);
+
+		wlc_lcnphy_tx_iqlo_cal(pi, &target_gains,
+				       (pi_lcn->
+					lcnphy_recal ? LCNPHY_CAL_RECAL :
+					LCNPHY_CAL_FULL), false);
+	} else {
+		wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
+		wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
+	}
+
+	wlc_lcnphy_get_radio_loft(pi, &ei0, &eq0, &fi0, &fq0);
+	if ((abs((s8) fi0) == 15) && (abs((s8) fq0) == 15)) {
+		if (CHSPEC_IS5G(pi->radio_chanspec)) {
+			target_gains.gm_gain = 255;
+			target_gains.pga_gain = 255;
+			target_gains.pad_gain = 0xf0;
+			target_gains.dac_gain = 0;
+		} else {
+			target_gains.gm_gain = 7;
+			target_gains.pga_gain = 45;
+			target_gains.pad_gain = 186;
+			target_gains.dac_gain = 0;
+		}
+
+		if (LCNREV_IS(pi->pubpi.phy_rev, 1)
+		    || pi_lcn->lcnphy_hw_iqcal_en) {
+
+			target_gains.pga_gain = 0;
+			target_gains.pad_gain = 30;
+			wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
+			wlc_lcnphy_tx_iqlo_cal(pi, &target_gains,
+					       LCNPHY_CAL_FULL, false);
+		} else {
+			wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
+		}
+	}
+
+	wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
+
+	didq = wlc_lcnphy_get_tx_locc(pi);
+
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_ptr = &val;
+
+	tab.tbl_len = 1;
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
+
+	for (idx = 0; idx < 128; idx++) {
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + idx;
+
+		wlc_lcnphy_read_table(pi, &tab);
+		val = (val & 0xfff00000) |
+		      ((u32) (a & 0x3FF) << 10) | (b & 0x3ff);
+		wlc_lcnphy_write_table(pi, &tab);
+
+		val = didq;
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + idx;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+
+	pi_lcn->lcnphy_cal_results.txiqlocal_a = a;
+	pi_lcn->lcnphy_cal_results.txiqlocal_b = b;
+	pi_lcn->lcnphy_cal_results.txiqlocal_didq = didq;
+	pi_lcn->lcnphy_cal_results.txiqlocal_ei0 = ei0;
+	pi_lcn->lcnphy_cal_results.txiqlocal_eq0 = eq0;
+	pi_lcn->lcnphy_cal_results.txiqlocal_fi0 = fi0;
+	pi_lcn->lcnphy_cal_results.txiqlocal_fq0 = fq0;
+
+	wlc_lcnphy_set_bbmult(pi, save_bb_mult);
+	wlc_lcnphy_set_pa_gain(pi, save_pa_gain);
+	wlc_lcnphy_set_tx_gain(pi, &old_gains);
+
+	if (SAVE_txpwrctrl != LCNPHY_TX_PWR_CTRL_OFF)
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
+	else
+		wlc_lcnphy_set_tx_pwr_by_index(pi, SAVE_txpwrindex);
+}
+
+s16 wlc_lcnphy_tempsense_new(struct brcms_phy *pi, bool mode)
+{
+	u16 tempsenseval1, tempsenseval2;
+	s16 avg = 0;
+	bool suspend = false;
+
+	if (mode == 1) {
+		suspend = (0 == (bcma_read32(pi->d11core,
+					     D11REGOFFS(maccontrol)) &
+				 MCTL_EN_MAC));
+		if (!suspend)
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+		wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
+	}
+	tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF;
+	tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF;
+
+	if (tempsenseval1 > 255)
+		avg = (s16) (tempsenseval1 - 512);
+	else
+		avg = (s16) tempsenseval1;
+
+	if (tempsenseval2 > 255)
+		avg += (s16) (tempsenseval2 - 512);
+	else
+		avg += (s16) tempsenseval2;
+
+	avg /= 2;
+
+	if (mode == 1) {
+
+		mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
+
+		udelay(100);
+		mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
+
+		if (!suspend)
+			wlapi_enable_mac(pi->sh->physhim);
+	}
+	return avg;
+}
+
+u16 wlc_lcnphy_tempsense(struct brcms_phy *pi, bool mode)
+{
+	u16 tempsenseval1, tempsenseval2;
+	s32 avg = 0;
+	bool suspend = false;
+	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	if (mode == 1) {
+		suspend = (0 == (bcma_read32(pi->d11core,
+					     D11REGOFFS(maccontrol)) &
+				 MCTL_EN_MAC));
+		if (!suspend)
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+		wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
+	}
+	tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF;
+	tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF;
+
+	if (tempsenseval1 > 255)
+		avg = (int)(tempsenseval1 - 512);
+	else
+		avg = (int)tempsenseval1;
+
+	if (pi_lcn->lcnphy_tempsense_option == 1 || pi->hwpwrctrl_capable) {
+		if (tempsenseval2 > 255)
+			avg = (int)(avg - tempsenseval2 + 512);
+		else
+			avg = (int)(avg - tempsenseval2);
+	} else {
+		if (tempsenseval2 > 255)
+			avg = (int)(avg + tempsenseval2 - 512);
+		else
+			avg = (int)(avg + tempsenseval2);
+		avg = avg / 2;
+	}
+	if (avg < 0)
+		avg = avg + 512;
+
+	if (pi_lcn->lcnphy_tempsense_option == 2)
+		avg = tempsenseval1;
+
+	if (mode)
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
+
+	if (mode == 1) {
+
+		mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
+
+		udelay(100);
+		mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
+
+		if (!suspend)
+			wlapi_enable_mac(pi->sh->physhim);
+	}
+	return (u16) avg;
+}
+
+s8 wlc_lcnphy_tempsense_degree(struct brcms_phy *pi, bool mode)
+{
+	s32 degree = wlc_lcnphy_tempsense_new(pi, mode);
+	degree =
+		((degree <<
+		  10) + LCN_TEMPSENSE_OFFSET + (LCN_TEMPSENSE_DEN >> 1))
+		/ LCN_TEMPSENSE_DEN;
+	return (s8) degree;
+}
+
+s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode)
+{
+	u16 vbatsenseval;
+	s32 avg = 0;
+	bool suspend = false;
+
+	if (mode == 1) {
+		suspend = (0 == (bcma_read32(pi->d11core,
+					     D11REGOFFS(maccontrol)) &
+				 MCTL_EN_MAC));
+		if (!suspend)
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+		wlc_lcnphy_vbat_temp_sense_setup(pi, VBATSENSE);
+	}
+
+	vbatsenseval = read_phy_reg(pi, 0x475) & 0x1FF;
+
+	if (vbatsenseval > 255)
+		avg = (s32) (vbatsenseval - 512);
+	else
+		avg = (s32) vbatsenseval;
+
+	avg =	(avg * LCN_VBAT_SCALE_NOM +
+		 (LCN_VBAT_SCALE_DEN >> 1)) / LCN_VBAT_SCALE_DEN;
+
+	if (mode == 1) {
+		if (!suspend)
+			wlapi_enable_mac(pi->sh->physhim);
+	}
+	return (s8) avg;
+}
+
+static void wlc_lcnphy_afe_clk_init(struct brcms_phy *pi, u8 mode)
+{
+	u8 phybw40;
+	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+
+	mod_phy_reg(pi, 0x6d1, (0x1 << 7), (1) << 7);
+
+	if (((mode == AFE_CLK_INIT_MODE_PAPD) && (phybw40 == 0)) ||
+	    (mode == AFE_CLK_INIT_MODE_TXRX2X))
+		write_phy_reg(pi, 0x6d0, 0x7);
+
+	wlc_lcnphy_toggle_afe_pwdn(pi);
+}
+
+static void wlc_lcnphy_temp_adj(struct brcms_phy *pi)
+{
+}
+
+static void wlc_lcnphy_glacial_timer_based_cal(struct brcms_phy *pi)
+{
+	bool suspend;
+	s8 index;
+	u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+	suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
+			 MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+	wlc_lcnphy_deaf_mode(pi, true);
+	pi->phy_lastcal = pi->sh->now;
+	pi->phy_forcecal = false;
+	index = pi_lcn->lcnphy_current_index;
+
+	wlc_lcnphy_txpwrtbl_iqlo_cal(pi);
+
+	wlc_lcnphy_set_tx_pwr_by_index(pi, index);
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl);
+	wlc_lcnphy_deaf_mode(pi, false);
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+
+}
+
+static void wlc_lcnphy_periodic_cal(struct brcms_phy *pi)
+{
+	bool suspend, full_cal;
+	const struct lcnphy_rx_iqcomp *rx_iqcomp;
+	int rx_iqcomp_sz;
+	u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	s8 index;
+	struct phytbl_info tab;
+	s32 a1, b0, b1;
+	s32 tssi, pwr, maxtargetpwr, mintargetpwr;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	pi->phy_lastcal = pi->sh->now;
+	pi->phy_forcecal = false;
+	full_cal =
+		(pi_lcn->lcnphy_full_cal_channel !=
+		 CHSPEC_CHANNEL(pi->radio_chanspec));
+	pi_lcn->lcnphy_full_cal_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
+	index = pi_lcn->lcnphy_current_index;
+
+	suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
+			 MCTL_EN_MAC));
+	if (!suspend) {
+		wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000);
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+	}
+
+	wlc_lcnphy_deaf_mode(pi, true);
+
+	wlc_lcnphy_txpwrtbl_iqlo_cal(pi);
+
+	rx_iqcomp = lcnphy_rx_iqcomp_table_rev0;
+	rx_iqcomp_sz = ARRAY_SIZE(lcnphy_rx_iqcomp_table_rev0);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
+		wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 40);
+	else
+		wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 127);
+
+	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) {
+
+		wlc_lcnphy_idle_tssi_est((struct brcms_phy_pub *) pi);
+
+		b0 = pi->txpa_2g[0];
+		b1 = pi->txpa_2g[1];
+		a1 = pi->txpa_2g[2];
+		maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1);
+		mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1);
+
+		tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+		tab.tbl_width = 32;
+		tab.tbl_ptr = &pwr;
+		tab.tbl_len = 1;
+		tab.tbl_offset = 0;
+		for (tssi = 0; tssi < 128; tssi++) {
+			pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1);
+			pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr;
+			wlc_lcnphy_write_table(pi, &tab);
+			tab.tbl_offset++;
+		}
+	}
+
+	wlc_lcnphy_set_tx_pwr_by_index(pi, index);
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl);
+	wlc_lcnphy_deaf_mode(pi, false);
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+}
+
+void wlc_lcnphy_calib_modes(struct brcms_phy *pi, uint mode)
+{
+	u16 temp_new;
+	int temp1, temp2, temp_diff;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	switch (mode) {
+	case PHY_PERICAL_CHAN:
+		break;
+	case PHY_FULLCAL:
+		wlc_lcnphy_periodic_cal(pi);
+		break;
+	case PHY_PERICAL_PHYINIT:
+		wlc_lcnphy_periodic_cal(pi);
+		break;
+	case PHY_PERICAL_WATCHDOG:
+		if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
+			temp_new = wlc_lcnphy_tempsense(pi, 0);
+			temp1 = LCNPHY_TEMPSENSE(temp_new);
+			temp2 = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_cal_temper);
+			temp_diff = temp1 - temp2;
+			if ((pi_lcn->lcnphy_cal_counter > 90) ||
+			    (temp_diff > 60) || (temp_diff < -60)) {
+				wlc_lcnphy_glacial_timer_based_cal(pi);
+				wlc_2064_vco_cal(pi);
+				pi_lcn->lcnphy_cal_temper = temp_new;
+				pi_lcn->lcnphy_cal_counter = 0;
+			} else
+				pi_lcn->lcnphy_cal_counter++;
+		}
+		break;
+	case LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL:
+		if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
+			wlc_lcnphy_tx_power_adjustment(
+				(struct brcms_phy_pub *) pi);
+		break;
+	}
+}
+
+void wlc_lcnphy_get_tssi(struct brcms_phy *pi, s8 *ofdm_pwr, s8 *cck_pwr)
+{
+	s8 cck_offset;
+	u16 status;
+	status = (read_phy_reg(pi, 0x4ab));
+	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) &&
+	    (status  & (0x1 << 15))) {
+		*ofdm_pwr = (s8) (((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
+				   >> 0) >> 1);
+
+		if (wlc_phy_tpc_isenabled_lcnphy(pi))
+			cck_offset = pi->tx_power_offset[TXP_FIRST_CCK];
+		else
+			cck_offset = 0;
+
+		*cck_pwr = *ofdm_pwr + cck_offset;
+	} else {
+		*cck_pwr = 0;
+		*ofdm_pwr = 0;
+	}
+}
+
+void wlc_phy_cal_init_lcnphy(struct brcms_phy *pi)
+{
+	return;
+
+}
+
+void wlc_lcnphy_tx_power_adjustment(struct brcms_phy_pub *ppi)
+{
+	s8 index;
+	u16 index2;
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) &&
+	    SAVE_txpwrctrl) {
+		index = wlc_lcnphy_tempcompensated_txpwrctrl(pi);
+		index2 = (u16) (index * 2);
+		mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0);
+
+		pi_lcn->lcnphy_current_index =
+			(s8)((read_phy_reg(pi, 0x4a9) & 0xFF) / 2);
+	}
+}
+
+static void
+wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi,
+			      const struct lcnphy_tx_gain_tbl_entry *gain_table)
+{
+	u32 j;
+	struct phytbl_info tab;
+	u32 val;
+	u16 pa_gain;
+	u16 gm_gain;
+
+	if (pi->sh->boardflags & BFL_FEM)
+		pa_gain = 0x10;
+	else
+		pa_gain = 0x60;
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_len = 1;
+	tab.tbl_ptr = &val;
+
+	/* fixed gm_gain value for iPA */
+	gm_gain = 15;
+	for (j = 0; j < 128; j++) {
+		if (pi->sh->boardflags & BFL_FEM)
+			gm_gain = gain_table[j].gm;
+		val = (((u32) pa_gain << 24) |
+		       (gain_table[j].pad << 16) |
+		       (gain_table[j].pga << 8) | gm_gain);
+
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + j;
+		wlc_lcnphy_write_table(pi, &tab);
+
+		val = (gain_table[j].dac << 28) | (gain_table[j].bb_mult << 20);
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + j;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+}
+
+static void wlc_lcnphy_load_rfpower(struct brcms_phy *pi)
+{
+	struct phytbl_info tab;
+	u32 val, bbmult, rfgain;
+	u8 index;
+	u8 scale_factor = 1;
+	s16 temp, temp1, temp2, qQ, qQ1, qQ2, shift;
+
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_len = 1;
+
+	for (index = 0; index < 128; index++) {
+		tab.tbl_ptr = &bbmult;
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index;
+		wlc_lcnphy_read_table(pi, &tab);
+		bbmult = bbmult >> 20;
+
+		tab.tbl_ptr = &rfgain;
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index;
+		wlc_lcnphy_read_table(pi, &tab);
+
+		qm_log10((s32) (bbmult), 0, &temp1, &qQ1);
+		qm_log10((s32) (1 << 6), 0, &temp2, &qQ2);
+
+		if (qQ1 < qQ2) {
+			temp2 = qm_shr16(temp2, qQ2 - qQ1);
+			qQ = qQ1;
+		} else {
+			temp1 = qm_shr16(temp1, qQ1 - qQ2);
+			qQ = qQ2;
+		}
+		temp = qm_sub16(temp1, temp2);
+
+		if (qQ >= 4)
+			shift = qQ - 4;
+		else
+			shift = 4 - qQ;
+
+		val = (((index << shift) + (5 * temp) +
+			(1 << (scale_factor + shift - 3))) >> (scale_factor +
+							       shift - 2));
+
+		tab.tbl_ptr = &val;
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+}
+
+static void wlc_lcnphy_bu_tweaks(struct brcms_phy *pi)
+{
+	or_phy_reg(pi, 0x805, 0x1);
+
+	mod_phy_reg(pi, 0x42f, (0x7 << 0), (0x3) << 0);
+
+	mod_phy_reg(pi, 0x030, (0x7 << 0), (0x3) << 0);
+
+	write_phy_reg(pi, 0x414, 0x1e10);
+	write_phy_reg(pi, 0x415, 0x0640);
+
+	mod_phy_reg(pi, 0x4df, (0xff << 8), -9 << 8);
+
+	or_phy_reg(pi, 0x44a, 0x44);
+	write_phy_reg(pi, 0x44a, 0x80);
+	mod_phy_reg(pi, 0x434, (0xff << 0), (0xFD) << 0);
+
+	mod_phy_reg(pi, 0x420, (0xff << 0), (16) << 0);
+
+	if (!(pi->sh->boardrev < 0x1204))
+		mod_radio_reg(pi, RADIO_2064_REG09B, 0xF0, 0xF0);
+
+	write_phy_reg(pi, 0x7d6, 0x0902);
+	mod_phy_reg(pi, 0x429, (0xf << 0), (0x9) << 0);
+
+	mod_phy_reg(pi, 0x429, (0x3f << 4), (0xe) << 4);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+		mod_phy_reg(pi, 0x423, (0xff << 0), (0x46) << 0);
+
+		mod_phy_reg(pi, 0x411, (0xff << 0), (1) << 0);
+
+		mod_phy_reg(pi, 0x434, (0xff << 0), (0xFF) << 0);
+
+		mod_phy_reg(pi, 0x656, (0xf << 0), (2) << 0);
+
+		mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2);
+
+		mod_radio_reg(pi, RADIO_2064_REG0F7, 0x4, 0x4);
+		mod_radio_reg(pi, RADIO_2064_REG0F1, 0x3, 0);
+		mod_radio_reg(pi, RADIO_2064_REG0F2, 0xF8, 0x90);
+		mod_radio_reg(pi, RADIO_2064_REG0F3, 0x3, 0x2);
+		mod_radio_reg(pi, RADIO_2064_REG0F3, 0xf0, 0xa0);
+
+		mod_radio_reg(pi, RADIO_2064_REG11F, 0x2, 0x2);
+
+		wlc_lcnphy_clear_tx_power_offsets(pi);
+		mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (10) << 6);
+
+	}
+}
+
+static void wlc_lcnphy_rcal(struct brcms_phy *pi)
+{
+	u8 rcal_value;
+
+	and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
+
+	or_radio_reg(pi, RADIO_2064_REG004, 0x40);
+	or_radio_reg(pi, RADIO_2064_REG120, 0x10);
+
+	or_radio_reg(pi, RADIO_2064_REG078, 0x80);
+	or_radio_reg(pi, RADIO_2064_REG129, 0x02);
+
+	or_radio_reg(pi, RADIO_2064_REG057, 0x01);
+
+	or_radio_reg(pi, RADIO_2064_REG05B, 0x02);
+	mdelay(5);
+	SPINWAIT(!wlc_radio_2064_rcal_done(pi), 10 * 1000 * 1000);
+
+	if (wlc_radio_2064_rcal_done(pi)) {
+		rcal_value = (u8) read_radio_reg(pi, RADIO_2064_REG05C);
+		rcal_value = rcal_value & 0x1f;
+	}
+
+	and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
+
+	and_radio_reg(pi, RADIO_2064_REG057, 0xFE);
+}
+
+static void wlc_lcnphy_rc_cal(struct brcms_phy *pi)
+{
+	u8 dflt_rc_cal_val;
+	u16 flt_val;
+
+	dflt_rc_cal_val = 7;
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
+		dflt_rc_cal_val = 11;
+	flt_val =
+		(dflt_rc_cal_val << 10) | (dflt_rc_cal_val << 5) |
+		(dflt_rc_cal_val);
+	write_phy_reg(pi, 0x933, flt_val);
+	write_phy_reg(pi, 0x934, flt_val);
+	write_phy_reg(pi, 0x935, flt_val);
+	write_phy_reg(pi, 0x936, flt_val);
+	write_phy_reg(pi, 0x937, (flt_val & 0x1FF));
+
+	return;
+}
+
+static void wlc_radio_2064_init(struct brcms_phy *pi)
+{
+	u32 i;
+	const struct lcnphy_radio_regs *lcnphyregs = NULL;
+
+	lcnphyregs = lcnphy_radio_regs_2064;
+
+	for (i = 0; lcnphyregs[i].address != 0xffff; i++)
+		if (CHSPEC_IS5G(pi->radio_chanspec) && lcnphyregs[i].do_init_a)
+			write_radio_reg(pi,
+					((lcnphyregs[i].address & 0x3fff) |
+					 RADIO_DEFAULT_CORE),
+					(u16) lcnphyregs[i].init_a);
+		else if (lcnphyregs[i].do_init_g)
+			write_radio_reg(pi,
+					((lcnphyregs[i].address & 0x3fff) |
+					 RADIO_DEFAULT_CORE),
+					(u16) lcnphyregs[i].init_g);
+
+	write_radio_reg(pi, RADIO_2064_REG032, 0x62);
+	write_radio_reg(pi, RADIO_2064_REG033, 0x19);
+
+	write_radio_reg(pi, RADIO_2064_REG090, 0x10);
+
+	write_radio_reg(pi, RADIO_2064_REG010, 0x00);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+
+		write_radio_reg(pi, RADIO_2064_REG060, 0x7f);
+		write_radio_reg(pi, RADIO_2064_REG061, 0x72);
+		write_radio_reg(pi, RADIO_2064_REG062, 0x7f);
+	}
+
+	write_radio_reg(pi, RADIO_2064_REG01D, 0x02);
+	write_radio_reg(pi, RADIO_2064_REG01E, 0x06);
+
+	mod_phy_reg(pi, 0x4ea, (0x7 << 0), 0 << 0);
+
+	mod_phy_reg(pi, 0x4ea, (0x7 << 3), 1 << 3);
+
+	mod_phy_reg(pi, 0x4ea, (0x7 << 6), 2 << 6);
+
+	mod_phy_reg(pi, 0x4ea, (0x7 << 9), 3 << 9);
+
+	mod_phy_reg(pi, 0x4ea, (0x7 << 12), 4 << 12);
+
+	write_phy_reg(pi, 0x4ea, 0x4688);
+
+	if (pi->sh->boardflags & BFL_FEM)
+		mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
+	else
+		mod_phy_reg(pi, 0x4eb, (0x7 << 0), 3 << 0);
+
+	mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
+
+	mod_phy_reg(pi, 0x46a, (0xffff << 0), 25 << 0);
+
+	wlc_lcnphy_set_tx_locc(pi, 0);
+
+	wlc_lcnphy_rcal(pi);
+
+	wlc_lcnphy_rc_cal(pi);
+
+	if (!(pi->sh->boardflags & BFL_FEM)) {
+		write_radio_reg(pi, RADIO_2064_REG032, 0x6f);
+		write_radio_reg(pi, RADIO_2064_REG033, 0x19);
+		write_radio_reg(pi, RADIO_2064_REG039, 0xe);
+	}
+
+}
+
+static void wlc_lcnphy_radio_init(struct brcms_phy *pi)
+{
+	wlc_radio_2064_init(pi);
+}
+
+static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
+{
+	uint idx;
+	u8 phybw40;
+	struct phytbl_info tab;
+	const struct phytbl_info *tb;
+	u32 val;
+
+	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+
+	for (idx = 0; idx < dot11lcnphytbl_info_sz_rev0; idx++)
+		wlc_lcnphy_write_table(pi, &dot11lcnphytbl_info_rev0[idx]);
+
+	if (pi->sh->boardflags & BFL_FEM_BT) {
+		tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
+		tab.tbl_width = 16;
+		tab.tbl_ptr = &val;
+		tab.tbl_len = 1;
+		val = 100;
+		tab.tbl_offset = 4;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+
+	if (!(pi->sh->boardflags & BFL_FEM)) {
+		tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
+		tab.tbl_width = 16;
+		tab.tbl_ptr = &val;
+		tab.tbl_len = 1;
+
+		val = 150;
+		tab.tbl_offset = 0;
+		wlc_lcnphy_write_table(pi, &tab);
+
+		val = 220;
+		tab.tbl_offset = 1;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (pi->sh->boardflags & BFL_FEM)
+			wlc_lcnphy_load_tx_gain_table(
+				pi,
+				dot11lcnphy_2GHz_extPA_gaintable_rev0);
+		else
+			wlc_lcnphy_load_tx_gain_table(
+				pi,
+				dot11lcnphy_2GHz_gaintable_rev0);
+	}
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+		int l;
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			l = dot11lcnphytbl_rx_gain_info_2G_rev2_sz;
+			if (pi->sh->boardflags & BFL_EXTLNA)
+				tb = dot11lcnphytbl_rx_gain_info_extlna_2G_rev2;
+			else
+				tb = dot11lcnphytbl_rx_gain_info_2G_rev2;
+		} else {
+			l = dot11lcnphytbl_rx_gain_info_5G_rev2_sz;
+			if (pi->sh->boardflags & BFL_EXTLNA_5GHz)
+				tb = dot11lcnphytbl_rx_gain_info_extlna_5G_rev2;
+			else
+				tb = dot11lcnphytbl_rx_gain_info_5G_rev2;
+		}
+
+		for (idx = 0; idx < l; idx++)
+			wlc_lcnphy_write_table(pi, &tb[idx]);
+	}
+
+	if (pi->sh->boardflags & BFL_FEM) {
+		if (pi->sh->boardflags & BFL_FEM_BT) {
+			if (pi->sh->boardrev < 0x1250)
+				tb = &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa;
+			else
+				tb = &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250;
+		} else {
+			tb = &dot11lcn_sw_ctrl_tbl_info_4313_epa;
+		}
+	} else {
+		if (pi->sh->boardflags & BFL_FEM_BT)
+			tb = &dot11lcn_sw_ctrl_tbl_info_4313_bt_ipa;
+		else
+			tb = &dot11lcn_sw_ctrl_tbl_info_4313;
+	}
+	wlc_lcnphy_write_table(pi, tb);
+	wlc_lcnphy_load_rfpower(pi);
+
+	wlc_lcnphy_clear_papd_comptable(pi);
+}
+
+static void wlc_lcnphy_rev0_baseband_init(struct brcms_phy *pi)
+{
+	u16 afectrl1;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	write_radio_reg(pi, RADIO_2064_REG11C, 0x0);
+
+	write_phy_reg(pi, 0x43b, 0x0);
+	write_phy_reg(pi, 0x43c, 0x0);
+	write_phy_reg(pi, 0x44c, 0x0);
+	write_phy_reg(pi, 0x4e6, 0x0);
+	write_phy_reg(pi, 0x4f9, 0x0);
+	write_phy_reg(pi, 0x4b0, 0x0);
+	write_phy_reg(pi, 0x938, 0x0);
+	write_phy_reg(pi, 0x4b0, 0x0);
+	write_phy_reg(pi, 0x44e, 0);
+
+	or_phy_reg(pi, 0x567, 0x03);
+
+	or_phy_reg(pi, 0x44a, 0x44);
+	write_phy_reg(pi, 0x44a, 0x80);
+
+	if (!(pi->sh->boardflags & BFL_FEM))
+		wlc_lcnphy_set_tx_pwr_by_index(pi, 52);
+
+	if (0) {
+		afectrl1 = 0;
+		afectrl1 = (u16) ((pi_lcn->lcnphy_rssi_vf) |
+				  (pi_lcn->lcnphy_rssi_vc << 4) |
+				  (pi_lcn->lcnphy_rssi_gs << 10));
+		write_phy_reg(pi, 0x43e, afectrl1);
+	}
+
+	mod_phy_reg(pi, 0x634, (0xff << 0), 0xC << 0);
+	if (pi->sh->boardflags & BFL_FEM) {
+		mod_phy_reg(pi, 0x634, (0xff << 0), 0xA << 0);
+
+		write_phy_reg(pi, 0x910, 0x1);
+	}
+
+	mod_phy_reg(pi, 0x448, (0x3 << 8), 1 << 8);
+	mod_phy_reg(pi, 0x608, (0xff << 0), 0x17 << 0);
+	mod_phy_reg(pi, 0x604, (0x7ff << 0), 0x3EA << 0);
+
+}
+
+static void wlc_lcnphy_rev2_baseband_init(struct brcms_phy *pi)
+{
+	if (CHSPEC_IS5G(pi->radio_chanspec)) {
+		mod_phy_reg(pi, 0x416, (0xff << 0), 80 << 0);
+		mod_phy_reg(pi, 0x416, (0xff << 8), 80 << 8);
+	}
+}
+
+static void wlc_lcnphy_agc_temp_init(struct brcms_phy *pi)
+{
+	s16 temp;
+	struct phytbl_info tab;
+	u32 tableBuffer[2];
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	temp = (s16) read_phy_reg(pi, 0x4df);
+	pi_lcn->lcnphy_ofdmgainidxtableoffset = (temp & (0xff << 0)) >> 0;
+
+	if (pi_lcn->lcnphy_ofdmgainidxtableoffset > 127)
+		pi_lcn->lcnphy_ofdmgainidxtableoffset -= 256;
+
+	pi_lcn->lcnphy_dsssgainidxtableoffset = (temp & (0xff << 8)) >> 8;
+
+	if (pi_lcn->lcnphy_dsssgainidxtableoffset > 127)
+		pi_lcn->lcnphy_dsssgainidxtableoffset -= 256;
+
+	tab.tbl_ptr = tableBuffer;
+	tab.tbl_len = 2;
+	tab.tbl_id = 17;
+	tab.tbl_offset = 59;
+	tab.tbl_width = 32;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	if (tableBuffer[0] > 63)
+		tableBuffer[0] -= 128;
+	pi_lcn->lcnphy_tr_R_gain_val = tableBuffer[0];
+
+	if (tableBuffer[1] > 63)
+		tableBuffer[1] -= 128;
+	pi_lcn->lcnphy_tr_T_gain_val = tableBuffer[1];
+
+	temp = (s16) (read_phy_reg(pi, 0x434) & (0xff << 0));
+	if (temp > 127)
+		temp -= 256;
+	pi_lcn->lcnphy_input_pwr_offset_db = (s8) temp;
+
+	pi_lcn->lcnphy_Med_Low_Gain_db =
+		(read_phy_reg(pi, 0x424) & (0xff << 8)) >> 8;
+	pi_lcn->lcnphy_Very_Low_Gain_db =
+		(read_phy_reg(pi, 0x425) & (0xff << 0)) >> 0;
+
+	tab.tbl_ptr = tableBuffer;
+	tab.tbl_len = 2;
+	tab.tbl_id = LCNPHY_TBL_ID_GAIN_IDX;
+	tab.tbl_offset = 28;
+	tab.tbl_width = 32;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	pi_lcn->lcnphy_gain_idx_14_lowword = tableBuffer[0];
+	pi_lcn->lcnphy_gain_idx_14_hiword = tableBuffer[1];
+
+}
+
+static void wlc_lcnphy_baseband_init(struct brcms_phy *pi)
+{
+
+	wlc_lcnphy_tbl_init(pi);
+	wlc_lcnphy_rev0_baseband_init(pi);
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2))
+		wlc_lcnphy_rev2_baseband_init(pi);
+	wlc_lcnphy_bu_tweaks(pi);
+}
+
+void wlc_phy_init_lcnphy(struct brcms_phy *pi)
+{
+	u8 phybw40;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+
+	pi_lcn->lcnphy_cal_counter = 0;
+	pi_lcn->lcnphy_cal_temper = pi_lcn->lcnphy_rawtempsense;
+
+	or_phy_reg(pi, 0x44a, 0x80);
+	and_phy_reg(pi, 0x44a, 0x7f);
+
+	wlc_lcnphy_afe_clk_init(pi, AFE_CLK_INIT_MODE_TXRX2X);
+
+	write_phy_reg(pi, 0x60a, 160);
+
+	write_phy_reg(pi, 0x46a, 25);
+
+	wlc_lcnphy_baseband_init(pi);
+
+	wlc_lcnphy_radio_init(pi);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec))
+		wlc_lcnphy_tx_pwr_ctrl_init((struct brcms_phy_pub *) pi);
+
+	wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec);
+
+	bcma_chipco_regctl_maskset(&pi->d11core->bus->drv_cc, 0, ~0xf, 0x9);
+
+	bcma_chipco_chipctl_maskset(&pi->d11core->bus->drv_cc, 0, 0x0,
+				    0x03CDDDDD);
+
+	if ((pi->sh->boardflags & BFL_FEM)
+	    && wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
+		wlc_lcnphy_set_tx_pwr_by_index(pi, FIXED_TXPWR);
+
+	wlc_lcnphy_agc_temp_init(pi);
+
+	wlc_lcnphy_temp_adj(pi);
+
+	mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
+
+	udelay(100);
+	mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
+
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
+	pi_lcn->lcnphy_noise_samples = LCNPHY_NOISE_SAMPLES_DEFAULT;
+	wlc_lcnphy_calib_modes(pi, PHY_PERICAL_PHYINIT);
+}
+
+static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi)
+{
+	s8 txpwr = 0;
+	int i;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+	struct ssb_sprom *sprom = &pi->d11core->bus->sprom;
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		u16 cckpo = 0;
+		u32 offset_ofdm, offset_mcs;
+
+		pi_lcn->lcnphy_tr_isolation_mid = sprom->fem.ghz2.tr_iso;
+
+		pi_lcn->lcnphy_rx_power_offset = sprom->rxpo2g;
+
+		pi->txpa_2g[0] = sprom->pa0b0;
+		pi->txpa_2g[1] = sprom->pa0b1;
+		pi->txpa_2g[2] = sprom->pa0b2;
+
+		pi_lcn->lcnphy_rssi_vf = sprom->rssismf2g;
+		pi_lcn->lcnphy_rssi_vc = sprom->rssismc2g;
+		pi_lcn->lcnphy_rssi_gs = sprom->rssisav2g;
+
+		pi_lcn->lcnphy_rssi_vf_lowtemp = pi_lcn->lcnphy_rssi_vf;
+		pi_lcn->lcnphy_rssi_vc_lowtemp = pi_lcn->lcnphy_rssi_vc;
+		pi_lcn->lcnphy_rssi_gs_lowtemp = pi_lcn->lcnphy_rssi_gs;
+
+		pi_lcn->lcnphy_rssi_vf_hightemp = pi_lcn->lcnphy_rssi_vf;
+		pi_lcn->lcnphy_rssi_vc_hightemp = pi_lcn->lcnphy_rssi_vc;
+		pi_lcn->lcnphy_rssi_gs_hightemp = pi_lcn->lcnphy_rssi_gs;
+
+		txpwr = sprom->core_pwr_info[0].maxpwr_2g;
+		pi->tx_srom_max_2g = txpwr;
+
+		for (i = 0; i < PWRTBL_NUM_COEFF; i++) {
+			pi->txpa_2g_low_temp[i] = pi->txpa_2g[i];
+			pi->txpa_2g_high_temp[i] = pi->txpa_2g[i];
+		}
+
+		cckpo = sprom->cck2gpo;
+		offset_ofdm = sprom->ofdm2gpo;
+		if (cckpo) {
+			uint max_pwr_chan = txpwr;
+
+			for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) {
+				pi->tx_srom_max_rate_2g[i] =
+					max_pwr_chan - ((cckpo & 0xf) * 2);
+				cckpo >>= 4;
+			}
+
+			for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
+				pi->tx_srom_max_rate_2g[i] =
+					max_pwr_chan -
+					((offset_ofdm & 0xf) * 2);
+				offset_ofdm >>= 4;
+			}
+		} else {
+			u8 opo = 0;
+
+			opo = sprom->opo;
+
+			for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++)
+				pi->tx_srom_max_rate_2g[i] = txpwr;
+
+			for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
+				pi->tx_srom_max_rate_2g[i] = txpwr -
+						((offset_ofdm & 0xf) * 2);
+				offset_ofdm >>= 4;
+			}
+			offset_mcs = sprom->mcs2gpo[1] << 16;
+			offset_mcs |= sprom->mcs2gpo[0];
+			pi_lcn->lcnphy_mcs20_po = offset_mcs;
+			for (i = TXP_FIRST_SISO_MCS_20;
+			     i <= TXP_LAST_SISO_MCS_20; i++) {
+				pi->tx_srom_max_rate_2g[i] =
+					txpwr - ((offset_mcs & 0xf) * 2);
+				offset_mcs >>= 4;
+			}
+		}
+
+		pi_lcn->lcnphy_rawtempsense = sprom->rawtempsense;
+		pi_lcn->lcnphy_measPower = sprom->measpower;
+		pi_lcn->lcnphy_tempsense_slope = sprom->tempsense_slope;
+		pi_lcn->lcnphy_hw_iqcal_en = sprom->hw_iqcal_en;
+		pi_lcn->lcnphy_iqcal_swp_dis = sprom->iqcal_swp_dis;
+		pi_lcn->lcnphy_tempcorrx = sprom->tempcorrx;
+		pi_lcn->lcnphy_tempsense_option = sprom->tempsense_option;
+		pi_lcn->lcnphy_freqoffset_corr = sprom->freqoffset_corr;
+		if (sprom->ant_available_bg > 1)
+			wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi,
+				sprom->ant_available_bg);
+	}
+	pi_lcn->lcnphy_cck_dig_filt_type = -1;
+
+	return true;
+}
+
+void wlc_2064_vco_cal(struct brcms_phy *pi)
+{
+	u8 calnrst;
+
+	mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 1 << 3);
+	calnrst = (u8) read_radio_reg(pi, RADIO_2064_REG056) & 0xf8;
+	write_radio_reg(pi, RADIO_2064_REG056, calnrst);
+	udelay(1);
+	write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x03);
+	udelay(1);
+	write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x07);
+	udelay(300);
+	mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 0);
+}
+
+bool wlc_phy_tpc_isenabled_lcnphy(struct brcms_phy *pi)
+{
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
+		return false;
+	else
+		return (LCNPHY_TX_PWR_CTRL_HW ==
+			wlc_lcnphy_get_tx_pwr_ctrl((pi)));
+}
+
+void wlc_phy_txpower_recalc_target_lcnphy(struct brcms_phy *pi)
+{
+	u16 pwr_ctrl;
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
+		wlc_lcnphy_calib_modes(pi, LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
+	} else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) {
+		pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+		wlc_lcnphy_txpower_recalc_target(pi);
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, pwr_ctrl);
+	}
+}
+
+void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec)
+{
+	u8 channel = CHSPEC_CHANNEL(chanspec);
+
+	wlc_phy_chanspec_radio_set((struct brcms_phy_pub *)pi, chanspec);
+
+	wlc_lcnphy_set_chanspec_tweaks(pi, pi->radio_chanspec);
+
+	or_phy_reg(pi, 0x44a, 0x44);
+	write_phy_reg(pi, 0x44a, 0x80);
+
+	wlc_lcnphy_radio_2064_channel_tune_4313(pi, channel);
+	udelay(1000);
+
+	wlc_lcnphy_toggle_afe_pwdn(pi);
+
+	write_phy_reg(pi, 0x657, lcnphy_sfo_cfg[channel - 1].ptcentreTs20);
+	write_phy_reg(pi, 0x658, lcnphy_sfo_cfg[channel - 1].ptcentreFactor);
+
+	if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
+		mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
+
+		wlc_lcnphy_load_tx_iir_filter(pi, false, 3);
+	} else {
+		mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
+
+		wlc_lcnphy_load_tx_iir_filter(pi, false, 2);
+	}
+
+	if (pi->sh->boardflags & BFL_FEM)
+		wlc_lcnphy_load_tx_iir_filter(pi, true, 0);
+	else
+		wlc_lcnphy_load_tx_iir_filter(pi, true, 3);
+
+	mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3);
+	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
+		wlc_lcnphy_tssi_setup(pi);
+}
+
+void wlc_phy_detach_lcnphy(struct brcms_phy *pi)
+{
+	kfree(pi->u.pi_lcnphy);
+}
+
+bool wlc_phy_attach_lcnphy(struct brcms_phy *pi)
+{
+	struct brcms_phy_lcnphy *pi_lcn;
+
+	pi->u.pi_lcnphy = kzalloc(sizeof(struct brcms_phy_lcnphy), GFP_ATOMIC);
+	if (pi->u.pi_lcnphy == NULL)
+		return false;
+
+	pi_lcn = pi->u.pi_lcnphy;
+
+	if (0 == (pi->sh->boardflags & BFL_NOPA)) {
+		pi->hwpwrctrl = true;
+		pi->hwpwrctrl_capable = true;
+	}
+
+	pi->xtalfreq = bcma_chipco_get_alp_clock(&pi->d11core->bus->drv_cc);
+	pi_lcn->lcnphy_papd_rxGnCtrl_init = 0;
+
+	pi->pi_fptr.init = wlc_phy_init_lcnphy;
+	pi->pi_fptr.calinit = wlc_phy_cal_init_lcnphy;
+	pi->pi_fptr.chanset = wlc_phy_chanspec_set_lcnphy;
+	pi->pi_fptr.txpwrrecalc = wlc_phy_txpower_recalc_target_lcnphy;
+	pi->pi_fptr.txiqccget = wlc_lcnphy_get_tx_iqcc;
+	pi->pi_fptr.txiqccset = wlc_lcnphy_set_tx_iqcc;
+	pi->pi_fptr.txloccget = wlc_lcnphy_get_tx_locc;
+	pi->pi_fptr.radioloftget = wlc_lcnphy_get_radio_loft;
+	pi->pi_fptr.detach = wlc_phy_detach_lcnphy;
+
+	if (!wlc_phy_txpwr_srom_read_lcnphy(pi))
+		return false;
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+		if (pi_lcn->lcnphy_tempsense_option == 3) {
+			pi->hwpwrctrl = true;
+			pi->hwpwrctrl_capable = true;
+			pi->temppwrctrl_capable = false;
+		} else {
+			pi->hwpwrctrl = false;
+			pi->hwpwrctrl_capable = false;
+			pi->temppwrctrl_capable = true;
+		}
+	}
+
+	return true;
+}
+
+static void wlc_lcnphy_set_rx_gain(struct brcms_phy *pi, u32 gain)
+{
+	u16 trsw, ext_lna, lna1, lna2, tia, biq0, biq1, gain0_15, gain16_19;
+
+	trsw = (gain & ((u32) 1 << 28)) ? 0 : 1;
+	ext_lna = (u16) (gain >> 29) & 0x01;
+	lna1 = (u16) (gain >> 0) & 0x0f;
+	lna2 = (u16) (gain >> 4) & 0x0f;
+	tia = (u16) (gain >> 8) & 0xf;
+	biq0 = (u16) (gain >> 12) & 0xf;
+	biq1 = (u16) (gain >> 16) & 0xf;
+
+	gain0_15 = (u16) ((lna1 & 0x3) | ((lna1 & 0x3) << 2) |
+			  ((lna2 & 0x3) << 4) | ((lna2 & 0x3) << 6) |
+			  ((tia & 0xf) << 8) | ((biq0 & 0xf) << 12));
+	gain16_19 = biq1;
+
+	mod_phy_reg(pi, 0x44d, (0x1 << 0), trsw << 0);
+	mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
+	mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10);
+	mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
+	mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
+		mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3);
+	}
+	wlc_lcnphy_rx_gain_override_enable(pi, true);
+}
+
+static u32 wlc_lcnphy_get_receive_power(struct brcms_phy *pi, s32 *gain_index)
+{
+	u32 received_power = 0;
+	s32 max_index = 0;
+	u32 gain_code = 0;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	max_index = 36;
+	if (*gain_index >= 0)
+		gain_code = lcnphy_23bitgaincode_table[*gain_index];
+
+	if (-1 == *gain_index) {
+		*gain_index = 0;
+		while ((*gain_index <= (s32) max_index)
+		       && (received_power < 700)) {
+			wlc_lcnphy_set_rx_gain(pi,
+					       lcnphy_23bitgaincode_table
+					       [*gain_index]);
+			received_power =
+				wlc_lcnphy_measure_digital_power(
+					pi,
+					pi_lcn->
+					lcnphy_noise_samples);
+			(*gain_index)++;
+		}
+		(*gain_index)--;
+	} else {
+		wlc_lcnphy_set_rx_gain(pi, gain_code);
+		received_power =
+			wlc_lcnphy_measure_digital_power(pi,
+							 pi_lcn->
+							 lcnphy_noise_samples);
+	}
+
+	return received_power;
+}
+
+s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index)
+{
+	s32 gain = 0;
+	s32 nominal_power_db;
+	s32 log_val, gain_mismatch, desired_gain, input_power_offset_db,
+	    input_power_db;
+	s32 received_power, temperature;
+	u32 power;
+	u32 msb1, msb2, val1, val2, diff1, diff2;
+	uint freq;
+	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
+
+	received_power = wlc_lcnphy_get_receive_power(pi, &gain_index);
+
+	gain = lcnphy_gain_table[gain_index];
+
+	nominal_power_db = read_phy_reg(pi, 0x425) >> 8;
+
+	power = (received_power * 16);
+	msb1 = ffs(power) - 1;
+	msb2 = msb1 + 1;
+	val1 = 1 << msb1;
+	val2 = 1 << msb2;
+	diff1 = (power - val1);
+	diff2 = (val2 - power);
+	if (diff1 < diff2)
+		log_val = msb1;
+	else
+		log_val = msb2;
+
+	log_val = log_val * 3;
+
+	gain_mismatch = (nominal_power_db / 2) - (log_val);
+
+	desired_gain = gain + gain_mismatch;
+
+	input_power_offset_db = read_phy_reg(pi, 0x434) & 0xFF;
+
+	if (input_power_offset_db > 127)
+		input_power_offset_db -= 256;
+
+	input_power_db = input_power_offset_db - desired_gain;
+
+	input_power_db =
+		input_power_db + lcnphy_gain_index_offset_for_rssi[gain_index];
+
+	freq = wlc_phy_channel2freq(CHSPEC_CHANNEL(pi->radio_chanspec));
+	if ((freq > 2427) && (freq <= 2467))
+		input_power_db = input_power_db - 1;
+
+	temperature = pi_lcn->lcnphy_lastsensed_temperature;
+
+	if ((temperature - 15) < -30)
+		input_power_db =
+			input_power_db +
+			(((temperature - 10 - 25) * 286) >> 12) -
+			7;
+	else if ((temperature - 15) < 4)
+		input_power_db =
+			input_power_db +
+			(((temperature - 10 - 25) * 286) >> 12) -
+			3;
+	else
+		input_power_db = input_power_db +
+					(((temperature - 10 - 25) * 286) >> 12);
+
+	wlc_lcnphy_rx_gain_override_enable(pi, 0);
+
+	return input_power_db;
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.h
new file mode 100644
index 0000000..f4a8ab0
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_PHY_LCN_H_
+#define _BRCM_PHY_LCN_H_
+
+#include <types.h>
+
+struct brcms_phy_lcnphy {
+	int lcnphy_txrf_sp_9_override;
+	u8 lcnphy_full_cal_channel;
+	u8 lcnphy_cal_counter;
+	u16 lcnphy_cal_temper;
+	bool lcnphy_recal;
+
+	u8 lcnphy_rc_cap;
+	u32 lcnphy_mcs20_po;
+
+	u8 lcnphy_tr_isolation_mid;
+	u8 lcnphy_tr_isolation_low;
+	u8 lcnphy_tr_isolation_hi;
+
+	u8 lcnphy_bx_arch;
+	u8 lcnphy_rx_power_offset;
+	u8 lcnphy_rssi_vf;
+	u8 lcnphy_rssi_vc;
+	u8 lcnphy_rssi_gs;
+	u8 lcnphy_tssi_val;
+	u8 lcnphy_rssi_vf_lowtemp;
+	u8 lcnphy_rssi_vc_lowtemp;
+	u8 lcnphy_rssi_gs_lowtemp;
+
+	u8 lcnphy_rssi_vf_hightemp;
+	u8 lcnphy_rssi_vc_hightemp;
+	u8 lcnphy_rssi_gs_hightemp;
+
+	s16 lcnphy_pa0b0;
+	s16 lcnphy_pa0b1;
+	s16 lcnphy_pa0b2;
+
+	u16 lcnphy_rawtempsense;
+	u8 lcnphy_measPower;
+	u8 lcnphy_tempsense_slope;
+	u8 lcnphy_freqoffset_corr;
+	u8 lcnphy_tempsense_option;
+	u8 lcnphy_tempcorrx;
+	bool lcnphy_iqcal_swp_dis;
+	bool lcnphy_hw_iqcal_en;
+	uint lcnphy_bandedge_corr;
+	bool lcnphy_spurmod;
+	u16 lcnphy_tssi_tx_cnt;
+	u16 lcnphy_tssi_idx;
+	u16 lcnphy_tssi_npt;
+
+	u16 lcnphy_target_tx_freq;
+	s8 lcnphy_tx_power_idx_override;
+	u16 lcnphy_noise_samples;
+
+	u32 lcnphy_papdRxGnIdx;
+	u32 lcnphy_papd_rxGnCtrl_init;
+
+	u32 lcnphy_gain_idx_14_lowword;
+	u32 lcnphy_gain_idx_14_hiword;
+	u32 lcnphy_gain_idx_27_lowword;
+	u32 lcnphy_gain_idx_27_hiword;
+	s16 lcnphy_ofdmgainidxtableoffset;
+	s16 lcnphy_dsssgainidxtableoffset;
+	u32 lcnphy_tr_R_gain_val;
+	u32 lcnphy_tr_T_gain_val;
+	s8 lcnphy_input_pwr_offset_db;
+	u16 lcnphy_Med_Low_Gain_db;
+	u16 lcnphy_Very_Low_Gain_db;
+	s8 lcnphy_lastsensed_temperature;
+	s8 lcnphy_pkteng_rssi_slope;
+	u8 lcnphy_saved_tx_user_target[TXP_NUM_RATES];
+	u8 lcnphy_volt_winner;
+	u8 lcnphy_volt_low;
+	u8 lcnphy_54_48_36_24mbps_backoff;
+	u8 lcnphy_11n_backoff;
+	u8 lcnphy_lowerofdm;
+	u8 lcnphy_cck;
+	u8 lcnphy_psat_2pt3_detected;
+	s32 lcnphy_lowest_Re_div_Im;
+	s8 lcnphy_final_papd_cal_idx;
+	u16 lcnphy_extstxctrl4;
+	u16 lcnphy_extstxctrl0;
+	u16 lcnphy_extstxctrl1;
+	s16 lcnphy_cck_dig_filt_type;
+	s16 lcnphy_ofdm_dig_filt_type;
+	struct lcnphy_cal_results lcnphy_cal_results;
+
+	u8 lcnphy_psat_pwr;
+	u8 lcnphy_psat_indx;
+	s32 lcnphy_min_phase;
+	u8 lcnphy_final_idx;
+	u8 lcnphy_start_idx;
+	u8 lcnphy_current_index;
+	u16 lcnphy_logen_buf_1;
+	u16 lcnphy_local_ovr_2;
+	u16 lcnphy_local_oval_6;
+	u16 lcnphy_local_oval_5;
+	u16 lcnphy_logen_mixer_1;
+
+	u8 lcnphy_aci_stat;
+	uint lcnphy_aci_start_time;
+	s8 lcnphy_tx_power_offset[TXP_NUM_RATES];
+};
+#endif				/* _BRCM_PHY_LCN_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c
new file mode 100644
index 0000000..bedec16
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c
@@ -0,0 +1,28635 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/cordic.h>
+
+#include <brcm_hw_ids.h>
+#include <aiutils.h>
+#include <chipcommon.h>
+#include <pmu.h>
+#include <d11.h>
+#include <phy_shim.h>
+#include "phy_int.h"
+#include "phy_hal.h"
+#include "phy_radio.h"
+#include "phyreg_n.h"
+#include "phytbl_n.h"
+#include "soc.h"
+
+#define READ_RADIO_REG2(pi, radio_type, jspace, core, reg_name)	\
+	read_radio_reg(pi, radio_type##_##jspace##_##reg_name |	\
+		       ((core == PHY_CORE_0) ? \
+			radio_type##_##jspace##0 : \
+			radio_type##_##jspace##1))
+
+#define WRITE_RADIO_REG2(pi, radio_type, jspace, core, reg_name, value)	\
+	write_radio_reg(pi, radio_type##_##jspace##_##reg_name | \
+			((core ==  PHY_CORE_0) ? \
+			 radio_type##_##jspace##0 : \
+			 radio_type##_##jspace##1), value)
+
+#define WRITE_RADIO_SYN(pi, radio_type, reg_name, value) \
+	write_radio_reg(pi, radio_type##_##SYN##_##reg_name, value)
+
+#define READ_RADIO_REG3(pi, radio_type, jspace, core, reg_name)	\
+	read_radio_reg(pi, ((core == PHY_CORE_0) ? \
+			    radio_type##_##jspace##0##_##reg_name : \
+			    radio_type##_##jspace##1##_##reg_name))
+
+#define WRITE_RADIO_REG3(pi, radio_type, jspace, core, reg_name, value)	\
+	write_radio_reg(pi, ((core ==  PHY_CORE_0) ? \
+			     radio_type##_##jspace##0##_##reg_name : \
+			     radio_type##_##jspace##1##_##reg_name), \
+			value)
+
+#define READ_RADIO_REG4(pi, radio_type, jspace, core, reg_name)	\
+	read_radio_reg(pi, ((core == PHY_CORE_0) ? \
+			     radio_type##_##reg_name##_##jspace##0 : \
+			     radio_type##_##reg_name##_##jspace##1))
+
+#define WRITE_RADIO_REG4(pi, radio_type, jspace, core, reg_name, value)	\
+	write_radio_reg(pi, ((core == PHY_CORE_0) ? \
+			radio_type##_##reg_name##_##jspace##0 : \
+			radio_type##_##reg_name##_##jspace##1), \
+			value)
+
+#define NPHY_ACI_MAX_UNDETECT_WINDOW_SZ 40
+#define NPHY_ACI_CHANNEL_DELTA 5
+#define NPHY_ACI_CHANNEL_SKIP 4
+#define NPHY_ACI_40MHZ_CHANNEL_DELTA 6
+#define NPHY_ACI_40MHZ_CHANNEL_SKIP 5
+#define NPHY_ACI_40MHZ_CHANNEL_DELTA_GE_REV3 6
+#define NPHY_ACI_40MHZ_CHANNEL_SKIP_GE_REV3 5
+#define NPHY_ACI_CHANNEL_DELTA_GE_REV3 4
+#define NPHY_ACI_CHANNEL_SKIP_GE_REV3 3
+
+#define NPHY_NOISE_NOASSOC_GLITCH_TH_UP 2
+
+#define NPHY_NOISE_NOASSOC_GLITCH_TH_DN 8
+
+#define NPHY_NOISE_ASSOC_GLITCH_TH_UP 2
+
+#define NPHY_NOISE_ASSOC_GLITCH_TH_DN 8
+
+#define NPHY_NOISE_ASSOC_ACI_GLITCH_TH_UP 2
+
+#define NPHY_NOISE_ASSOC_ACI_GLITCH_TH_DN 8
+
+#define NPHY_NOISE_NOASSOC_ENTER_TH  400
+
+#define NPHY_NOISE_ASSOC_ENTER_TH  400
+
+#define NPHY_NOISE_ASSOC_RX_GLITCH_BADPLCP_ENTER_TH  400
+
+#define NPHY_NOISE_CRSMINPWR_ARRAY_MAX_INDEX 44
+#define NPHY_NOISE_CRSMINPWR_ARRAY_MAX_INDEX_REV_7 56
+
+#define NPHY_NOISE_NOASSOC_CRSIDX_INCR 16
+
+#define NPHY_NOISE_ASSOC_CRSIDX_INCR 8
+
+#define NPHY_IS_SROM_REINTERPRET NREV_GE(pi->pubpi.phy_rev, 5)
+
+#define NPHY_RSSICAL_MAXREAD 31
+
+#define NPHY_RSSICAL_NPOLL 8
+#define NPHY_RSSICAL_MAXD  (1<<20)
+#define NPHY_MIN_RXIQ_PWR 2
+
+#define NPHY_RSSICAL_W1_TARGET 25
+#define NPHY_RSSICAL_W2_TARGET NPHY_RSSICAL_W1_TARGET
+#define NPHY_RSSICAL_NB_TARGET 0
+
+#define NPHY_RSSICAL_W1_TARGET_REV3 29
+#define NPHY_RSSICAL_W2_TARGET_REV3 NPHY_RSSICAL_W1_TARGET_REV3
+
+#define NPHY_CALSANITY_RSSI_NB_MAX_POS  9
+#define NPHY_CALSANITY_RSSI_NB_MAX_NEG -9
+#define NPHY_CALSANITY_RSSI_W1_MAX_POS  12
+#define NPHY_CALSANITY_RSSI_W1_MAX_NEG (NPHY_RSSICAL_W1_TARGET - \
+					NPHY_RSSICAL_MAXREAD)
+#define NPHY_CALSANITY_RSSI_W2_MAX_POS  NPHY_CALSANITY_RSSI_W1_MAX_POS
+#define NPHY_CALSANITY_RSSI_W2_MAX_NEG (NPHY_RSSICAL_W2_TARGET - \
+					NPHY_RSSICAL_MAXREAD)
+#define NPHY_RSSI_SXT(x) ((s8) (-((x) & 0x20) + ((x) & 0x1f)))
+#define NPHY_RSSI_NB_VIOL(x)  (((x) > NPHY_CALSANITY_RSSI_NB_MAX_POS) || \
+			       ((x) < NPHY_CALSANITY_RSSI_NB_MAX_NEG))
+#define NPHY_RSSI_W1_VIOL(x)  (((x) > NPHY_CALSANITY_RSSI_W1_MAX_POS) || \
+			       ((x) < NPHY_CALSANITY_RSSI_W1_MAX_NEG))
+#define NPHY_RSSI_W2_VIOL(x)  (((x) > NPHY_CALSANITY_RSSI_W2_MAX_POS) || \
+			       ((x) < NPHY_CALSANITY_RSSI_W2_MAX_NEG))
+
+#define NPHY_IQCAL_NUMGAINS 9
+#define NPHY_N_GCTL 0x66
+
+#define NPHY_PAPD_EPS_TBL_SIZE 64
+#define NPHY_PAPD_SCL_TBL_SIZE 64
+#define NPHY_NUM_DIG_FILT_COEFFS 15
+
+#define NPHY_PAPD_COMP_OFF 0
+#define NPHY_PAPD_COMP_ON  1
+
+#define NPHY_SROM_TEMPSHIFT             32
+#define NPHY_SROM_MAXTEMPOFFSET         16
+#define NPHY_SROM_MINTEMPOFFSET         -16
+
+#define NPHY_CAL_MAXTEMPDELTA           64
+
+#define NPHY_NOISEVAR_TBLLEN40 256
+#define NPHY_NOISEVAR_TBLLEN20 128
+
+#define NPHY_ANARXLPFBW_REDUCTIONFACT 7
+
+#define NPHY_ADJUSTED_MINCRSPOWER 0x1e
+
+/* 5357 Chip specific ChipControl register bits */
+#define CCTRL5357_EXTPA            (1<<14) /* extPA in ChipControl 1, bit 14 */
+#define CCTRL5357_ANT_MUX_2o3      (1<<15) /* 2o3 in ChipControl 1, bit 15 */
+
+#define NPHY_CAL_TSSISAMPS      64
+#define NPHY_TEST_TONE_FREQ_40MHz 4000
+#define NPHY_TEST_TONE_FREQ_20MHz 2500
+
+#define MAX_205x_RCAL_WAITLOOPS 10000
+
+#define NPHY_RXCAL_TONEAMP 181
+#define NPHY_RXCAL_TONEFREQ_40MHz 4000
+#define NPHY_RXCAL_TONEFREQ_20MHz 2000
+
+#define TXFILT_SHAPING_OFDM20   0
+#define TXFILT_SHAPING_OFDM40   1
+#define TXFILT_SHAPING_CCK      2
+#define TXFILT_DEFAULT_OFDM20   3
+#define TXFILT_DEFAULT_OFDM40   4
+
+struct nphy_iqcal_params {
+	u16 txlpf;
+	u16 txgm;
+	u16 pga;
+	u16 pad;
+	u16 ipa;
+	u16 cal_gain;
+	u16 ncorr[5];
+};
+
+struct nphy_txiqcal_ladder {
+	u8 percent;
+	u8 g_env;
+};
+
+struct nphy_ipa_txcalgains {
+	struct nphy_txgains gains;
+	bool useindex;
+	u8 index;
+};
+
+struct nphy_papd_restore_state {
+	u16 fbmix[2];
+	u16 vga_master[2];
+	u16 intpa_master[2];
+	u16 afectrl[2];
+	u16 afeoverride[2];
+	u16 pwrup[2];
+	u16 atten[2];
+	u16 mm;
+};
+
+struct nphy_ipa_txrxgain {
+	u16 hpvga;
+	u16 lpf_biq1;
+	u16 lpf_biq0;
+	u16 lna2;
+	u16 lna1;
+	s8 txpwrindex;
+};
+
+#define NPHY_IPA_RXCAL_MAXGAININDEX (6 - 1)
+
+static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_5GHz[] = {
+	{0, 0, 0, 0, 0, 100},
+	{0, 0, 0, 0, 0, 50},
+	{0, 0, 0, 0, 0, -1},
+	{0, 0, 0, 3, 0, -1},
+	{0, 0, 3, 3, 0, -1},
+	{0, 2, 3, 3, 0, -1}
+};
+
+static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_2GHz[] = {
+	{0, 0, 0, 0, 0, 128},
+	{0, 0, 0, 0, 0, 70},
+	{0, 0, 0, 0, 0, 20},
+	{0, 0, 0, 3, 0, 20},
+	{0, 0, 3, 3, 0, 20},
+	{0, 2, 3, 3, 0, 20}
+};
+
+static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_5GHz_rev7[] = {
+	{0, 0, 0, 0, 0, 100},
+	{0, 0, 0, 0, 0, 50},
+	{0, 0, 0, 0, 0, -1},
+	{0, 0, 0, 3, 0, -1},
+	{0, 0, 3, 3, 0, -1},
+	{0, 0, 5, 3, 0, -1}
+};
+
+static const struct nphy_ipa_txrxgain nphy_ipa_rxcal_gaintbl_2GHz_rev7[] = {
+	{0, 0, 0, 0, 0, 10},
+	{0, 0, 0, 1, 0, 10},
+	{0, 0, 1, 2, 0, 10},
+	{0, 0, 1, 3, 0, 10},
+	{0, 0, 4, 3, 0, 10},
+	{0, 0, 6, 3, 0, 10}
+};
+
+enum {
+	NPHY_RXCAL_GAIN_INIT = 0,
+	NPHY_RXCAL_GAIN_UP,
+	NPHY_RXCAL_GAIN_DOWN
+};
+
+#define wlc_phy_get_papd_nphy(pi) \
+	(read_phy_reg((pi), 0x1e7) & \
+	 ((0x1 << 15) |	\
+	  (0x1 << 14) |	\
+	  (0x1 << 13)))
+
+static const u16 NPHY_IPA_REV4_txdigi_filtcoeffs[][NPHY_NUM_DIG_FILT_COEFFS] = {
+	{-377, 137, -407, 208, -1527, 956, 93, 186, 93,
+	 230, -44, 230, 201, -191, 201},
+	{-77, 20, -98, 49, -93, 60, 56, 111, 56, 26, -5,
+	 26, 34, -32, 34},
+	{-360, 164, -376, 164, -1533, 576, 308, -314, 308,
+	 121, -73, 121, 91, 124, 91},
+	{-295, 200, -363, 142, -1391, 826, 151, 301, 151,
+	 151, 301, 151, 602, -752, 602},
+	{-92, 58, -96, 49, -104, 44, 17, 35, 17,
+	 12, 25, 12, 13, 27, 13},
+	{-375, 136, -399, 209, -1479, 949, 130, 260, 130,
+	 230, -44, 230, 201, -191, 201},
+	{0xed9, 0xc8, 0xe95, 0x8e, 0xa91, 0x33a, 0x97, 0x12d, 0x97,
+	 0x97, 0x12d, 0x97, 0x25a, 0xd10, 0x25a}
+};
+
+struct chan_info_nphy_2055 {
+	u16 chan;
+	u16 freq;
+	uint unknown;
+	u8 RF_pll_ref;
+	u8 RF_rf_pll_mod1;
+	u8 RF_rf_pll_mod0;
+	u8 RF_vco_cap_tail;
+	u8 RF_vco_cal1;
+	u8 RF_vco_cal2;
+	u8 RF_pll_lf_c1;
+	u8 RF_pll_lf_r1;
+	u8 RF_pll_lf_c2;
+	u8 RF_lgbuf_cen_buf;
+	u8 RF_lgen_tune1;
+	u8 RF_lgen_tune2;
+	u8 RF_core1_lgbuf_a_tune;
+	u8 RF_core1_lgbuf_g_tune;
+	u8 RF_core1_rxrf_reg1;
+	u8 RF_core1_tx_pga_pad_tn;
+	u8 RF_core1_tx_mx_bgtrim;
+	u8 RF_core2_lgbuf_a_tune;
+	u8 RF_core2_lgbuf_g_tune;
+	u8 RF_core2_rxrf_reg1;
+	u8 RF_core2_tx_pga_pad_tn;
+	u8 RF_core2_tx_mx_bgtrim;
+	u16 PHY_BW1a;
+	u16 PHY_BW2;
+	u16 PHY_BW3;
+	u16 PHY_BW4;
+	u16 PHY_BW5;
+	u16 PHY_BW6;
+};
+
+struct chan_info_nphy_radio205x {
+	u16 chan;
+	u16 freq;
+	u8 RF_SYN_pll_vcocal1;
+	u8 RF_SYN_pll_vcocal2;
+	u8 RF_SYN_pll_refdiv;
+	u8 RF_SYN_pll_mmd2;
+	u8 RF_SYN_pll_mmd1;
+	u8 RF_SYN_pll_loopfilter1;
+	u8 RF_SYN_pll_loopfilter2;
+	u8 RF_SYN_pll_loopfilter3;
+	u8 RF_SYN_pll_loopfilter4;
+	u8 RF_SYN_pll_loopfilter5;
+	u8 RF_SYN_reserved_addr27;
+	u8 RF_SYN_reserved_addr28;
+	u8 RF_SYN_reserved_addr29;
+	u8 RF_SYN_logen_VCOBUF1;
+	u8 RF_SYN_logen_MIXER2;
+	u8 RF_SYN_logen_BUF3;
+	u8 RF_SYN_logen_BUF4;
+	u8 RF_RX0_lnaa_tune;
+	u8 RF_RX0_lnag_tune;
+	u8 RF_TX0_intpaa_boost_tune;
+	u8 RF_TX0_intpag_boost_tune;
+	u8 RF_TX0_pada_boost_tune;
+	u8 RF_TX0_padg_boost_tune;
+	u8 RF_TX0_pgaa_boost_tune;
+	u8 RF_TX0_pgag_boost_tune;
+	u8 RF_TX0_mixa_boost_tune;
+	u8 RF_TX0_mixg_boost_tune;
+	u8 RF_RX1_lnaa_tune;
+	u8 RF_RX1_lnag_tune;
+	u8 RF_TX1_intpaa_boost_tune;
+	u8 RF_TX1_intpag_boost_tune;
+	u8 RF_TX1_pada_boost_tune;
+	u8 RF_TX1_padg_boost_tune;
+	u8 RF_TX1_pgaa_boost_tune;
+	u8 RF_TX1_pgag_boost_tune;
+	u8 RF_TX1_mixa_boost_tune;
+	u8 RF_TX1_mixg_boost_tune;
+	u16 PHY_BW1a;
+	u16 PHY_BW2;
+	u16 PHY_BW3;
+	u16 PHY_BW4;
+	u16 PHY_BW5;
+	u16 PHY_BW6;
+};
+
+struct chan_info_nphy_radio2057 {
+	u16 chan;
+	u16 freq;
+	u8 RF_vcocal_countval0;
+	u8 RF_vcocal_countval1;
+	u8 RF_rfpll_refmaster_sparextalsize;
+	u8 RF_rfpll_loopfilter_r1;
+	u8 RF_rfpll_loopfilter_c2;
+	u8 RF_rfpll_loopfilter_c1;
+	u8 RF_cp_kpd_idac;
+	u8 RF_rfpll_mmd0;
+	u8 RF_rfpll_mmd1;
+	u8 RF_vcobuf_tune;
+	u8 RF_logen_mx2g_tune;
+	u8 RF_logen_mx5g_tune;
+	u8 RF_logen_indbuf2g_tune;
+	u8 RF_logen_indbuf5g_tune;
+	u8 RF_txmix2g_tune_boost_pu_core0;
+	u8 RF_pad2g_tune_pus_core0;
+	u8 RF_pga_boost_tune_core0;
+	u8 RF_txmix5g_boost_tune_core0;
+	u8 RF_pad5g_tune_misc_pus_core0;
+	u8 RF_lna2g_tune_core0;
+	u8 RF_lna5g_tune_core0;
+	u8 RF_txmix2g_tune_boost_pu_core1;
+	u8 RF_pad2g_tune_pus_core1;
+	u8 RF_pga_boost_tune_core1;
+	u8 RF_txmix5g_boost_tune_core1;
+	u8 RF_pad5g_tune_misc_pus_core1;
+	u8 RF_lna2g_tune_core1;
+	u8 RF_lna5g_tune_core1;
+	u16 PHY_BW1a;
+	u16 PHY_BW2;
+	u16 PHY_BW3;
+	u16 PHY_BW4;
+	u16 PHY_BW5;
+	u16 PHY_BW6;
+};
+
+struct chan_info_nphy_radio2057_rev5 {
+	u16 chan;
+	u16 freq;
+	u8 RF_vcocal_countval0;
+	u8 RF_vcocal_countval1;
+	u8 RF_rfpll_refmaster_sparextalsize;
+	u8 RF_rfpll_loopfilter_r1;
+	u8 RF_rfpll_loopfilter_c2;
+	u8 RF_rfpll_loopfilter_c1;
+	u8 RF_cp_kpd_idac;
+	u8 RF_rfpll_mmd0;
+	u8 RF_rfpll_mmd1;
+	u8 RF_vcobuf_tune;
+	u8 RF_logen_mx2g_tune;
+	u8 RF_logen_indbuf2g_tune;
+	u8 RF_txmix2g_tune_boost_pu_core0;
+	u8 RF_pad2g_tune_pus_core0;
+	u8 RF_lna2g_tune_core0;
+	u8 RF_txmix2g_tune_boost_pu_core1;
+	u8 RF_pad2g_tune_pus_core1;
+	u8 RF_lna2g_tune_core1;
+	u16 PHY_BW1a;
+	u16 PHY_BW2;
+	u16 PHY_BW3;
+	u16 PHY_BW4;
+	u16 PHY_BW5;
+	u16 PHY_BW6;
+};
+
+struct nphy_sfo_cfg {
+	u16 PHY_BW1a;
+	u16 PHY_BW2;
+	u16 PHY_BW3;
+	u16 PHY_BW4;
+	u16 PHY_BW5;
+	u16 PHY_BW6;
+};
+
+static const struct chan_info_nphy_2055 chan_info_nphy_2055[] = {
+	{
+	 184, 4920, 3280, 0x71, 0x01, 0xEC, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7B4, 0x7B0, 0x7AC, 0x214, 0x215, 0x216},
+	{
+	 186, 4930, 3287, 0x71, 0x01, 0xED, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7B8, 0x7B4, 0x7B0, 0x213, 0x214, 0x215},
+	{
+	 188, 4940, 3293, 0x71, 0x01, 0xEE, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7BC, 0x7B8, 0x7B4, 0x212, 0x213, 0x214},
+	{
+	 190, 4950, 3300, 0x71, 0x01, 0xEF, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7C0, 0x7BC, 0x7B8, 0x211, 0x212, 0x213},
+	{
+	 192, 4960, 3307, 0x71, 0x01, 0xF0, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7C4, 0x7C0, 0x7BC, 0x20F, 0x211, 0x212},
+	{
+	 194, 4970, 3313, 0x71, 0x01, 0xF1, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7C8, 0x7C4, 0x7C0, 0x20E, 0x20F, 0x211},
+	{
+	 196, 4980, 3320, 0x71, 0x01, 0xF2, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7CC, 0x7C8, 0x7C4, 0x20D, 0x20E, 0x20F},
+	{
+	 198, 4990, 3327, 0x71, 0x01, 0xF3, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7D0, 0x7CC, 0x7C8, 0x20C, 0x20D, 0x20E},
+	{
+	 200, 5000, 3333, 0x71, 0x01, 0xF4, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7D4, 0x7D0, 0x7CC, 0x20B, 0x20C, 0x20D},
+	{
+	 202, 5010, 3340, 0x71, 0x01, 0xF5, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7D8, 0x7D4, 0x7D0, 0x20A, 0x20B, 0x20C},
+	{
+	 204, 5020, 3347, 0x71, 0x01, 0xF6, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7DC, 0x7D8, 0x7D4, 0x209, 0x20A, 0x20B},
+	{
+	 206, 5030, 3353, 0x71, 0x01, 0xF7, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7E0, 0x7DC, 0x7D8, 0x208, 0x209, 0x20A},
+	{
+	 208, 5040, 3360, 0x71, 0x01, 0xF8, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7E4, 0x7E0, 0x7DC, 0x207, 0x208, 0x209},
+	{
+	 210, 5050, 3367, 0x71, 0x01, 0xF9, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7E8, 0x7E4, 0x7E0, 0x206, 0x207, 0x208},
+	{
+	 212, 5060, 3373, 0x71, 0x01, 0xFA, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, 0x8E, 0xFF, 0x00, 0x0E,
+	 0x0F, 0x8E, 0x7EC, 0x7E8, 0x7E4, 0x205, 0x206, 0x207},
+	{
+	 214, 5070, 3380, 0x71, 0x01, 0xFB, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, 0x8E, 0xFF, 0x00, 0x0E,
+	 0x0F, 0x8E, 0x7F0, 0x7EC, 0x7E8, 0x204, 0x205, 0x206},
+	{
+	 216, 5080, 3387, 0x71, 0x01, 0xFC, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, 0x8D, 0xEE, 0x00, 0x0E,
+	 0x0F, 0x8D, 0x7F4, 0x7F0, 0x7EC, 0x203, 0x204, 0x205},
+	{
+	 218, 5090, 3393, 0x71, 0x01, 0xFD, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, 0x8D, 0xEE, 0x00, 0x0E,
+	 0x0F, 0x8D, 0x7F8, 0x7F4, 0x7F0, 0x202, 0x203, 0x204},
+	{
+	 220, 5100, 3400, 0x71, 0x01, 0xFE, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, 0x8D, 0xEE, 0x00, 0x0D,
+	 0x0F, 0x8D, 0x7FC, 0x7F8, 0x7F4, 0x201, 0x202, 0x203},
+	{
+	 222, 5110, 3407, 0x71, 0x01, 0xFF, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, 0x8D, 0xEE, 0x00, 0x0D,
+	 0x0F, 0x8D, 0x800, 0x7FC, 0x7F8, 0x200, 0x201, 0x202},
+	{
+	 224, 5120, 3413, 0x71, 0x02, 0x00, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, 0x8C, 0xDD, 0x00, 0x0D,
+	 0x0F, 0x8C, 0x804, 0x800, 0x7FC, 0x1FF, 0x200, 0x201},
+	{
+	 226, 5130, 3420, 0x71, 0x02, 0x01, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, 0x8C, 0xDD, 0x00, 0x0D,
+	 0x0F, 0x8C, 0x808, 0x804, 0x800, 0x1FE, 0x1FF, 0x200},
+	{
+	 228, 5140, 3427, 0x71, 0x02, 0x02, 0x0C, 0xC6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8D, 0x99, 0x99, 0xDD, 0x00, 0x0C, 0x0E, 0x8B, 0xDD, 0x00, 0x0C,
+	 0x0E, 0x8B, 0x80C, 0x808, 0x804, 0x1FD, 0x1FE, 0x1FF},
+	{
+	 32, 5160, 3440, 0x71, 0x02, 0x04, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, 0x8A, 0xCC, 0x00, 0x0B,
+	 0x0D, 0x8A, 0x814, 0x810, 0x80C, 0x1FB, 0x1FC, 0x1FD},
+	{
+	 34, 5170, 3447, 0x71, 0x02, 0x05, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, 0x8A, 0xCC, 0x00, 0x0B,
+	 0x0D, 0x8A, 0x818, 0x814, 0x810, 0x1FA, 0x1FB, 0x1FC},
+	{
+	 36, 5180, 3453, 0x71, 0x02, 0x06, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, 0x89, 0xCC, 0x00, 0x0B,
+	 0x0C, 0x89, 0x81C, 0x818, 0x814, 0x1F9, 0x1FA, 0x1FB},
+	{
+	 38, 5190, 3460, 0x71, 0x02, 0x07, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, 0x89, 0xCC, 0x00, 0x0B,
+	 0x0C, 0x89, 0x820, 0x81C, 0x818, 0x1F8, 0x1F9, 0x1FA},
+	{
+	 40, 5200, 3467, 0x71, 0x02, 0x08, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, 0x89, 0xBB, 0x00, 0x0A,
+	 0x0B, 0x89, 0x824, 0x820, 0x81C, 0x1F7, 0x1F8, 0x1F9},
+	{
+	 42, 5210, 3473, 0x71, 0x02, 0x09, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, 0x89, 0xBB, 0x00, 0x0A,
+	 0x0B, 0x89, 0x828, 0x824, 0x820, 0x1F6, 0x1F7, 0x1F8},
+	{
+	 44, 5220, 3480, 0x71, 0x02, 0x0A, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
+	 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, 0x88, 0xBB, 0x00, 0x09,
+	 0x0A, 0x88, 0x82C, 0x828, 0x824, 0x1F5, 0x1F6, 0x1F7},
+	{
+	 46, 5230, 3487, 0x71, 0x02, 0x0B, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
+	 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, 0x88, 0xBB, 0x00, 0x09,
+	 0x0A, 0x88, 0x830, 0x82C, 0x828, 0x1F4, 0x1F5, 0x1F6},
+	{
+	 48, 5240, 3493, 0x71, 0x02, 0x0C, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
+	 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, 0x87, 0xAA, 0x00, 0x09,
+	 0x0A, 0x87, 0x834, 0x830, 0x82C, 0x1F3, 0x1F4, 0x1F5},
+	{
+	 50, 5250, 3500, 0x71, 0x02, 0x0D, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
+	 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, 0x87, 0xAA, 0x00, 0x09,
+	 0x0A, 0x87, 0x838, 0x834, 0x830, 0x1F2, 0x1F3, 0x1F4},
+	{
+	 52, 5260, 3507, 0x71, 0x02, 0x0E, 0x0A, 0x98, 0x01, 0x04, 0x0A,
+	 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, 0x87, 0xAA, 0x00, 0x08,
+	 0x09, 0x87, 0x83C, 0x838, 0x834, 0x1F1, 0x1F2, 0x1F3},
+	{
+	 54, 5270, 3513, 0x71, 0x02, 0x0F, 0x0A, 0x98, 0x01, 0x04, 0x0A,
+	 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, 0x87, 0xAA, 0x00, 0x08,
+	 0x09, 0x87, 0x840, 0x83C, 0x838, 0x1F0, 0x1F1, 0x1F2},
+	{
+	 56, 5280, 3520, 0x71, 0x02, 0x10, 0x09, 0x91, 0x01, 0x04, 0x0A,
+	 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, 0x86, 0x99, 0x00, 0x08,
+	 0x08, 0x86, 0x844, 0x840, 0x83C, 0x1F0, 0x1F0, 0x1F1},
+	{
+	 58, 5290, 3527, 0x71, 0x02, 0x11, 0x09, 0x91, 0x01, 0x04, 0x0A,
+	 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, 0x86, 0x99, 0x00, 0x08,
+	 0x08, 0x86, 0x848, 0x844, 0x840, 0x1EF, 0x1F0, 0x1F0},
+	{
+	 60, 5300, 3533, 0x71, 0x02, 0x12, 0x09, 0x8A, 0x01, 0x04, 0x0A,
+	 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, 0x85, 0x99, 0x00, 0x08,
+	 0x07, 0x85, 0x84C, 0x848, 0x844, 0x1EE, 0x1EF, 0x1F0},
+	{
+	 62, 5310, 3540, 0x71, 0x02, 0x13, 0x09, 0x8A, 0x01, 0x04, 0x0A,
+	 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, 0x85, 0x99, 0x00, 0x08,
+	 0x07, 0x85, 0x850, 0x84C, 0x848, 0x1ED, 0x1EE, 0x1EF},
+	{
+	 64, 5320, 3547, 0x71, 0x02, 0x14, 0x09, 0x83, 0x01, 0x04, 0x0A,
+	 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, 0x84, 0x88, 0x00, 0x07,
+	 0x07, 0x84, 0x854, 0x850, 0x84C, 0x1EC, 0x1ED, 0x1EE},
+	{
+	 66, 5330, 3553, 0x71, 0x02, 0x15, 0x09, 0x83, 0x01, 0x04, 0x0A,
+	 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, 0x84, 0x88, 0x00, 0x07,
+	 0x07, 0x84, 0x858, 0x854, 0x850, 0x1EB, 0x1EC, 0x1ED},
+	{
+	 68, 5340, 3560, 0x71, 0x02, 0x16, 0x08, 0x7C, 0x01, 0x04, 0x0A,
+	 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, 0x84, 0x88, 0x00, 0x07,
+	 0x06, 0x84, 0x85C, 0x858, 0x854, 0x1EA, 0x1EB, 0x1EC},
+	{
+	 70, 5350, 3567, 0x71, 0x02, 0x17, 0x08, 0x7C, 0x01, 0x04, 0x0A,
+	 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, 0x84, 0x88, 0x00, 0x07,
+	 0x06, 0x84, 0x860, 0x85C, 0x858, 0x1E9, 0x1EA, 0x1EB},
+	{
+	 72, 5360, 3573, 0x71, 0x02, 0x18, 0x08, 0x75, 0x01, 0x04, 0x0A,
+	 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, 0x83, 0x77, 0x00, 0x06,
+	 0x05, 0x83, 0x864, 0x860, 0x85C, 0x1E8, 0x1E9, 0x1EA},
+	{
+	 74, 5370, 3580, 0x71, 0x02, 0x19, 0x08, 0x75, 0x01, 0x04, 0x0A,
+	 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, 0x83, 0x77, 0x00, 0x06,
+	 0x05, 0x83, 0x868, 0x864, 0x860, 0x1E7, 0x1E8, 0x1E9},
+	{
+	 76, 5380, 3587, 0x71, 0x02, 0x1A, 0x08, 0x6E, 0x01, 0x04, 0x0A,
+	 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, 0x82, 0x77, 0x00, 0x06,
+	 0x04, 0x82, 0x86C, 0x868, 0x864, 0x1E6, 0x1E7, 0x1E8},
+	{
+	 78, 5390, 3593, 0x71, 0x02, 0x1B, 0x08, 0x6E, 0x01, 0x04, 0x0A,
+	 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, 0x82, 0x77, 0x00, 0x06,
+	 0x04, 0x82, 0x870, 0x86C, 0x868, 0x1E5, 0x1E6, 0x1E7},
+	{
+	 80, 5400, 3600, 0x71, 0x02, 0x1C, 0x07, 0x67, 0x01, 0x04, 0x0A,
+	 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, 0x81, 0x66, 0x00, 0x05,
+	 0x04, 0x81, 0x874, 0x870, 0x86C, 0x1E5, 0x1E5, 0x1E6},
+	{
+	 82, 5410, 3607, 0x71, 0x02, 0x1D, 0x07, 0x67, 0x01, 0x04, 0x0A,
+	 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, 0x81, 0x66, 0x00, 0x05,
+	 0x04, 0x81, 0x878, 0x874, 0x870, 0x1E4, 0x1E5, 0x1E5},
+	{
+	 84, 5420, 3613, 0x71, 0x02, 0x1E, 0x07, 0x61, 0x01, 0x04, 0x0A,
+	 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, 0x80, 0x66, 0x00, 0x05,
+	 0x03, 0x80, 0x87C, 0x878, 0x874, 0x1E3, 0x1E4, 0x1E5},
+	{
+	 86, 5430, 3620, 0x71, 0x02, 0x1F, 0x07, 0x61, 0x01, 0x04, 0x0A,
+	 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, 0x80, 0x66, 0x00, 0x05,
+	 0x03, 0x80, 0x880, 0x87C, 0x878, 0x1E2, 0x1E3, 0x1E4},
+	{
+	 88, 5440, 3627, 0x71, 0x02, 0x20, 0x07, 0x5A, 0x01, 0x04, 0x0A,
+	 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, 0x80, 0x55, 0x00, 0x04,
+	 0x02, 0x80, 0x884, 0x880, 0x87C, 0x1E1, 0x1E2, 0x1E3},
+	{
+	 90, 5450, 3633, 0x71, 0x02, 0x21, 0x07, 0x5A, 0x01, 0x04, 0x0A,
+	 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, 0x80, 0x55, 0x00, 0x04,
+	 0x02, 0x80, 0x888, 0x884, 0x880, 0x1E0, 0x1E1, 0x1E2},
+	{
+	 92, 5460, 3640, 0x71, 0x02, 0x22, 0x06, 0x53, 0x01, 0x04, 0x0A,
+	 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, 0x80, 0x55, 0x00, 0x04,
+	 0x01, 0x80, 0x88C, 0x888, 0x884, 0x1DF, 0x1E0, 0x1E1},
+	{
+	 94, 5470, 3647, 0x71, 0x02, 0x23, 0x06, 0x53, 0x01, 0x04, 0x0A,
+	 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, 0x80, 0x55, 0x00, 0x04,
+	 0x01, 0x80, 0x890, 0x88C, 0x888, 0x1DE, 0x1DF, 0x1E0},
+	{
+	 96, 5480, 3653, 0x71, 0x02, 0x24, 0x06, 0x4D, 0x01, 0x04, 0x0A,
+	 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
+	 0x00, 0x80, 0x894, 0x890, 0x88C, 0x1DD, 0x1DE, 0x1DF},
+	{
+	 98, 5490, 3660, 0x71, 0x02, 0x25, 0x06, 0x4D, 0x01, 0x04, 0x0A,
+	 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
+	 0x00, 0x80, 0x898, 0x894, 0x890, 0x1DD, 0x1DD, 0x1DE},
+	{
+	 100, 5500, 3667, 0x71, 0x02, 0x26, 0x06, 0x47, 0x01, 0x04, 0x0A,
+	 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
+	 0x00, 0x80, 0x89C, 0x898, 0x894, 0x1DC, 0x1DD, 0x1DD},
+	{
+	 102, 5510, 3673, 0x71, 0x02, 0x27, 0x06, 0x47, 0x01, 0x04, 0x0A,
+	 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
+	 0x00, 0x80, 0x8A0, 0x89C, 0x898, 0x1DB, 0x1DC, 0x1DD},
+	{
+	 104, 5520, 3680, 0x71, 0x02, 0x28, 0x05, 0x40, 0x01, 0x04, 0x0A,
+	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
+	 0x00, 0x80, 0x8A4, 0x8A0, 0x89C, 0x1DA, 0x1DB, 0x1DC},
+	{
+	 106, 5530, 3687, 0x71, 0x02, 0x29, 0x05, 0x40, 0x01, 0x04, 0x0A,
+	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
+	 0x00, 0x80, 0x8A8, 0x8A4, 0x8A0, 0x1D9, 0x1DA, 0x1DB},
+	{
+	 108, 5540, 3693, 0x71, 0x02, 0x2A, 0x05, 0x3A, 0x01, 0x04, 0x0A,
+	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
+	 0x00, 0x80, 0x8AC, 0x8A8, 0x8A4, 0x1D8, 0x1D9, 0x1DA},
+	{
+	 110, 5550, 3700, 0x71, 0x02, 0x2B, 0x05, 0x3A, 0x01, 0x04, 0x0A,
+	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
+	 0x00, 0x80, 0x8B0, 0x8AC, 0x8A8, 0x1D7, 0x1D8, 0x1D9},
+	{
+	 112, 5560, 3707, 0x71, 0x02, 0x2C, 0x05, 0x34, 0x01, 0x04, 0x0A,
+	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
+	 0x00, 0x80, 0x8B4, 0x8B0, 0x8AC, 0x1D7, 0x1D7, 0x1D8},
+	{
+	 114, 5570, 3713, 0x71, 0x02, 0x2D, 0x05, 0x34, 0x01, 0x04, 0x0A,
+	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
+	 0x00, 0x80, 0x8B8, 0x8B4, 0x8B0, 0x1D6, 0x1D7, 0x1D7},
+	{
+	 116, 5580, 3720, 0x71, 0x02, 0x2E, 0x04, 0x2E, 0x01, 0x04, 0x0A,
+	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
+	 0x00, 0x80, 0x8BC, 0x8B8, 0x8B4, 0x1D5, 0x1D6, 0x1D7},
+	{
+	 118, 5590, 3727, 0x71, 0x02, 0x2F, 0x04, 0x2E, 0x01, 0x04, 0x0A,
+	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
+	 0x00, 0x80, 0x8C0, 0x8BC, 0x8B8, 0x1D4, 0x1D5, 0x1D6},
+	{
+	 120, 5600, 3733, 0x71, 0x02, 0x30, 0x04, 0x28, 0x01, 0x04, 0x0A,
+	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x80, 0x11, 0x00, 0x01,
+	 0x00, 0x80, 0x8C4, 0x8C0, 0x8BC, 0x1D3, 0x1D4, 0x1D5},
+	{
+	 122, 5610, 3740, 0x71, 0x02, 0x31, 0x04, 0x28, 0x01, 0x04, 0x0A,
+	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x80, 0x11, 0x00, 0x01,
+	 0x00, 0x80, 0x8C8, 0x8C4, 0x8C0, 0x1D2, 0x1D3, 0x1D4},
+	{
+	 124, 5620, 3747, 0x71, 0x02, 0x32, 0x04, 0x21, 0x01, 0x04, 0x0A,
+	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00,
+	 0x00, 0x80, 0x8CC, 0x8C8, 0x8C4, 0x1D2, 0x1D2, 0x1D3},
+	{
+	 126, 5630, 3753, 0x71, 0x02, 0x33, 0x04, 0x21, 0x01, 0x04, 0x0A,
+	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00,
+	 0x00, 0x80, 0x8D0, 0x8CC, 0x8C8, 0x1D1, 0x1D2, 0x1D2},
+	{
+	 128, 5640, 3760, 0x71, 0x02, 0x34, 0x03, 0x1C, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8D4, 0x8D0, 0x8CC, 0x1D0, 0x1D1, 0x1D2},
+	{
+	 130, 5650, 3767, 0x71, 0x02, 0x35, 0x03, 0x1C, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8D8, 0x8D4, 0x8D0, 0x1CF, 0x1D0, 0x1D1},
+	{
+	 132, 5660, 3773, 0x71, 0x02, 0x36, 0x03, 0x16, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8DC, 0x8D8, 0x8D4, 0x1CE, 0x1CF, 0x1D0},
+	{
+	 134, 5670, 3780, 0x71, 0x02, 0x37, 0x03, 0x16, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8E0, 0x8DC, 0x8D8, 0x1CE, 0x1CE, 0x1CF},
+	{
+	 136, 5680, 3787, 0x71, 0x02, 0x38, 0x03, 0x10, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8E4, 0x8E0, 0x8DC, 0x1CD, 0x1CE, 0x1CE},
+	{
+	 138, 5690, 3793, 0x71, 0x02, 0x39, 0x03, 0x10, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8E8, 0x8E4, 0x8E0, 0x1CC, 0x1CD, 0x1CE},
+	{
+	 140, 5700, 3800, 0x71, 0x02, 0x3A, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8EC, 0x8E8, 0x8E4, 0x1CB, 0x1CC, 0x1CD},
+	{
+	 142, 5710, 3807, 0x71, 0x02, 0x3B, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8F0, 0x8EC, 0x8E8, 0x1CA, 0x1CB, 0x1CC},
+	{
+	 144, 5720, 3813, 0x71, 0x02, 0x3C, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8F4, 0x8F0, 0x8EC, 0x1C9, 0x1CA, 0x1CB},
+	{
+	 145, 5725, 3817, 0x72, 0x04, 0x79, 0x02, 0x03, 0x01, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8F6, 0x8F2, 0x8EE, 0x1C9, 0x1CA, 0x1CB},
+	{
+	 146, 5730, 3820, 0x71, 0x02, 0x3D, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8F8, 0x8F4, 0x8F0, 0x1C9, 0x1C9, 0x1CA},
+	{
+	 147, 5735, 3823, 0x72, 0x04, 0x7B, 0x02, 0x03, 0x01, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8FA, 0x8F6, 0x8F2, 0x1C8, 0x1C9, 0x1CA},
+	{
+	 148, 5740, 3827, 0x71, 0x02, 0x3E, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8FC, 0x8F8, 0x8F4, 0x1C8, 0x1C9, 0x1C9},
+	{
+	 149, 5745, 3830, 0x72, 0x04, 0x7D, 0x02, 0xFE, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8FE, 0x8FA, 0x8F6, 0x1C8, 0x1C8, 0x1C9},
+	{
+	 150, 5750, 3833, 0x71, 0x02, 0x3F, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x900, 0x8FC, 0x8F8, 0x1C7, 0x1C8, 0x1C9},
+	{
+	 151, 5755, 3837, 0x72, 0x04, 0x7F, 0x02, 0xFE, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x902, 0x8FE, 0x8FA, 0x1C7, 0x1C8, 0x1C8},
+	{
+	 152, 5760, 3840, 0x71, 0x02, 0x40, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x904, 0x900, 0x8FC, 0x1C6, 0x1C7, 0x1C8},
+	{
+	 153, 5765, 3843, 0x72, 0x04, 0x81, 0x02, 0xF8, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x906, 0x902, 0x8FE, 0x1C6, 0x1C7, 0x1C8},
+	{
+	 154, 5770, 3847, 0x71, 0x02, 0x41, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x908, 0x904, 0x900, 0x1C6, 0x1C6, 0x1C7},
+	{
+	 155, 5775, 3850, 0x72, 0x04, 0x83, 0x02, 0xF8, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x90A, 0x906, 0x902, 0x1C5, 0x1C6, 0x1C7},
+	{
+	 156, 5780, 3853, 0x71, 0x02, 0x42, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x90C, 0x908, 0x904, 0x1C5, 0x1C6, 0x1C6},
+	{
+	 157, 5785, 3857, 0x72, 0x04, 0x85, 0x02, 0xF2, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x90E, 0x90A, 0x906, 0x1C4, 0x1C5, 0x1C6},
+	{
+	 158, 5790, 3860, 0x71, 0x02, 0x43, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x910, 0x90C, 0x908, 0x1C4, 0x1C5, 0x1C6},
+	{
+	 159, 5795, 3863, 0x72, 0x04, 0x87, 0x02, 0xF2, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x912, 0x90E, 0x90A, 0x1C4, 0x1C4, 0x1C5},
+	{
+	 160, 5800, 3867, 0x71, 0x02, 0x44, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x914, 0x910, 0x90C, 0x1C3, 0x1C4, 0x1C5},
+	{
+	 161, 5805, 3870, 0x72, 0x04, 0x89, 0x01, 0xED, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x916, 0x912, 0x90E, 0x1C3, 0x1C4, 0x1C4},
+	{
+	 162, 5810, 3873, 0x71, 0x02, 0x45, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x918, 0x914, 0x910, 0x1C2, 0x1C3, 0x1C4},
+	{
+	 163, 5815, 3877, 0x72, 0x04, 0x8B, 0x01, 0xED, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x91A, 0x916, 0x912, 0x1C2, 0x1C3, 0x1C4},
+	{
+	 164, 5820, 3880, 0x71, 0x02, 0x46, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x91C, 0x918, 0x914, 0x1C2, 0x1C2, 0x1C3},
+	{
+	 165, 5825, 3883, 0x72, 0x04, 0x8D, 0x01, 0xED, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x91E, 0x91A, 0x916, 0x1C1, 0x1C2, 0x1C3},
+	{
+	 166, 5830, 3887, 0x71, 0x02, 0x47, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x920, 0x91C, 0x918, 0x1C1, 0x1C2, 0x1C2},
+	{
+	 168, 5840, 3893, 0x71, 0x02, 0x48, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x924, 0x920, 0x91C, 0x1C0, 0x1C1, 0x1C2},
+	{
+	 170, 5850, 3900, 0x71, 0x02, 0x49, 0x01, 0xE0, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x928, 0x924, 0x920, 0x1BF, 0x1C0, 0x1C1},
+	{
+	 172, 5860, 3907, 0x71, 0x02, 0x4A, 0x01, 0xDE, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x92C, 0x928, 0x924, 0x1BF, 0x1BF, 0x1C0},
+	{
+	 174, 5870, 3913, 0x71, 0x02, 0x4B, 0x00, 0xDB, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x930, 0x92C, 0x928, 0x1BE, 0x1BF, 0x1BF},
+	{
+	 176, 5880, 3920, 0x71, 0x02, 0x4C, 0x00, 0xD8, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x934, 0x930, 0x92C, 0x1BD, 0x1BE, 0x1BF},
+	{
+	 178, 5890, 3927, 0x71, 0x02, 0x4D, 0x00, 0xD6, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x938, 0x934, 0x930, 0x1BC, 0x1BD, 0x1BE},
+	{
+	 180, 5900, 3933, 0x71, 0x02, 0x4E, 0x00, 0xD3, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x93C, 0x938, 0x934, 0x1BC, 0x1BC, 0x1BD},
+	{
+	 182, 5910, 3940, 0x71, 0x02, 0x4F, 0x00, 0xD6, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x940, 0x93C, 0x938, 0x1BB, 0x1BC, 0x1BC},
+	{
+	 1, 2412, 3216, 0x73, 0x09, 0x6C, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0D, 0x0C, 0x80, 0xFF, 0x88, 0x0D,
+	 0x0C, 0x80, 0x3C9, 0x3C5, 0x3C1, 0x43A, 0x43F, 0x443},
+	{
+	 2, 2417, 3223, 0x73, 0x09, 0x71, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0B, 0x80, 0xFF, 0x88, 0x0C,
+	 0x0B, 0x80, 0x3CB, 0x3C7, 0x3C3, 0x438, 0x43D, 0x441},
+	{
+	 3, 2422, 3229, 0x73, 0x09, 0x76, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, 0x80, 0xFF, 0x88, 0x0C,
+	 0x0A, 0x80, 0x3CD, 0x3C9, 0x3C5, 0x436, 0x43A, 0x43F},
+	{
+	 4, 2427, 3236, 0x73, 0x09, 0x7B, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, 0x80, 0xFF, 0x88, 0x0C,
+	 0x0A, 0x80, 0x3CF, 0x3CB, 0x3C7, 0x434, 0x438, 0x43D},
+	{
+	 5, 2432, 3243, 0x73, 0x09, 0x80, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x09, 0x80, 0xFF, 0x88, 0x0C,
+	 0x09, 0x80, 0x3D1, 0x3CD, 0x3C9, 0x431, 0x436, 0x43A},
+	{
+	 6, 2437, 3249, 0x73, 0x09, 0x85, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0B, 0x08, 0x80, 0xFF, 0x88, 0x0B,
+	 0x08, 0x80, 0x3D3, 0x3CF, 0x3CB, 0x42F, 0x434, 0x438},
+	{
+	 7, 2442, 3256, 0x73, 0x09, 0x8A, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x07, 0x80, 0xFF, 0x88, 0x0A,
+	 0x07, 0x80, 0x3D5, 0x3D1, 0x3CD, 0x42D, 0x431, 0x436},
+	{
+	 8, 2447, 3263, 0x73, 0x09, 0x8F, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x06, 0x80, 0xFF, 0x88, 0x0A,
+	 0x06, 0x80, 0x3D7, 0x3D3, 0x3CF, 0x42B, 0x42F, 0x434},
+	{
+	 9, 2452, 3269, 0x73, 0x09, 0x94, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x09, 0x06, 0x80, 0xFF, 0x88, 0x09,
+	 0x06, 0x80, 0x3D9, 0x3D5, 0x3D1, 0x429, 0x42D, 0x431},
+	{
+	 10, 2457, 3276, 0x73, 0x09, 0x99, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x05, 0x80, 0xFF, 0x88, 0x08,
+	 0x05, 0x80, 0x3DB, 0x3D7, 0x3D3, 0x427, 0x42B, 0x42F},
+	{
+	 11, 2462, 3283, 0x73, 0x09, 0x9E, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x04, 0x80, 0xFF, 0x88, 0x08,
+	 0x04, 0x80, 0x3DD, 0x3D9, 0x3D5, 0x424, 0x429, 0x42D},
+	{
+	 12, 2467, 3289, 0x73, 0x09, 0xA3, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x03, 0x80, 0xFF, 0x88, 0x08,
+	 0x03, 0x80, 0x3DF, 0x3DB, 0x3D7, 0x422, 0x427, 0x42B},
+	{
+	 13, 2472, 3296, 0x73, 0x09, 0xA8, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x03, 0x80, 0xFF, 0x88, 0x07,
+	 0x03, 0x80, 0x3E1, 0x3DD, 0x3D9, 0x420, 0x424, 0x429},
+	{
+	 14, 2484, 3312, 0x73, 0x09, 0xB4, 0x0F, 0xFF, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x01, 0x80, 0xFF, 0x88, 0x07,
+	 0x01, 0x80, 0x3E6, 0x3E2, 0x3DE, 0x41B, 0x41F, 0x424}
+};
+
+static const struct chan_info_nphy_radio205x chan_info_nphyrev3_2056[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfc, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x8f, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7e, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x7e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7d, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x7d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xf8, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xf8, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5d, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x5d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xf8, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5c, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xf8, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x5c, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2b, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x2b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2a, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x2a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x1a, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf6, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf6, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf6, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x07, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf6, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf6, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf6, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf2, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf2, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf2, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf2, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x05, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05,
+	 0x00, 0xf2, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x05, 0x00, 0xf2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05,
+	 0x00, 0xf2, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfd, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfb, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf7, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf6, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf5, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0d, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0d, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf3, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0d, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf2, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0d, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf0, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0d, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static const struct chan_info_nphy_radio205x chan_info_nphyrev4_2056_A1[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x8f, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7e, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x7e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7d, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x7d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5d, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x5d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5c, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x5c, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x5c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2b, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x2b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2a, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x2a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x1a, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x07, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf0, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf0, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfd, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfb, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf8, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf7, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf6, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf5, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf3, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf2, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static const struct chan_info_nphy_radio205x chan_info_nphyrev5_2056v5[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0f, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
+	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xea, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6e, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xe9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xe9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xd9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xd8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb7, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6b, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb7, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6b, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa7, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x6b, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x6b, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x5b, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x96, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x5a, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x5a, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x5a, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x5a, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x5a, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x85, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x59, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x59, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x59, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x74, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x63, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x78, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x52, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x52, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x75, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x50, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x75, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x50, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x75, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x84, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x72, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x72, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x72, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x72, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x71, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x71, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x71, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x71, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x71, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0b, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x08, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x07, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x06, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x05, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x03, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static const struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v6[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x67, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x57, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x56, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x46, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x23, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x12, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x02, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static const struct chan_info_nphy_radio205x chan_info_nphyrev5n6_2056v7[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0f, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
+	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xea, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6e, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xe9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xe9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xd9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xd8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xb7, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6b, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xb7, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6b, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa7, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x6b, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x6b, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x7b, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x96, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x7a, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x7a, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x7a, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x7a, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x7a, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x85, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x79, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x79, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x79, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x79, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x74, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x79, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x63, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x78, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x52, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x52, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x85, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x85, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x85, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x84, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x84, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x91, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x91, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x91, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x91, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x91, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0b, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x76, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x66, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x55, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x22, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static const struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v8[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static const struct chan_info_nphy_radio205x chan_info_nphyrev6_2056v11[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static const struct chan_info_nphy_radio2057 chan_info_nphyrev7_2057_rev4[] = {
+	{
+	 184, 4920, 0x68, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xec, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07b4, 0x07b0, 0x07ac, 0x0214,
+	 0x0215,
+	 0x0216,
+	 },
+	{
+	 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07b8, 0x07b4, 0x07b0, 0x0213,
+	 0x0214,
+	 0x0215,
+	 },
+	{
+	 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07bc, 0x07b8, 0x07b4, 0x0212,
+	 0x0213,
+	 0x0214,
+	 },
+	{
+	 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c0, 0x07bc, 0x07b8, 0x0211,
+	 0x0212,
+	 0x0213,
+	 },
+	{
+	 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c4, 0x07c0, 0x07bc, 0x020f,
+	 0x0211,
+	 0x0212,
+	 },
+	{
+	 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c8, 0x07c4, 0x07c0, 0x020e,
+	 0x020f,
+	 0x0211,
+	 },
+	{
+	 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07cc, 0x07c8, 0x07c4, 0x020d,
+	 0x020e,
+	 0x020f,
+	 },
+	{
+	 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d0, 0x07cc, 0x07c8, 0x020c,
+	 0x020d,
+	 0x020e,
+	 },
+	{
+	 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d4, 0x07d0, 0x07cc, 0x020b,
+	 0x020c,
+	 0x020d,
+	 },
+	{
+	 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d8, 0x07d4, 0x07d0, 0x020a,
+	 0x020b,
+	 0x020c,
+	 },
+	{
+	 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07dc, 0x07d8, 0x07d4, 0x0209,
+	 0x020a,
+	 0x020b,
+	 },
+	{
+	 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e0, 0x07dc, 0x07d8, 0x0208,
+	 0x0209,
+	 0x020a,
+	 },
+	{
+	 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e4, 0x07e0, 0x07dc, 0x0207,
+	 0x0208,
+	 0x0209,
+	 },
+	{
+	 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e8, 0x07e4, 0x07e0, 0x0206,
+	 0x0207,
+	 0x0208,
+	 },
+	{
+	 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xe3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xe3, 0x00, 0xef, 0x07ec, 0x07e8, 0x07e4, 0x0205,
+	 0x0206,
+	 0x0207,
+	 },
+	{
+	 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x07f0, 0x07ec, 0x07e8, 0x0204,
+	 0x0205,
+	 0x0206,
+	 },
+	{
+	 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x07f4, 0x07f0, 0x07ec, 0x0203,
+	 0x0204,
+	 0x0205,
+	 },
+	{
+	 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x07f8, 0x07f4, 0x07f0, 0x0202,
+	 0x0203,
+	 0x0204,
+	 },
+	{
+	 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x07fc, 0x07f8, 0x07f4, 0x0201,
+	 0x0202,
+	 0x0203,
+	 },
+	{
+	 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0800, 0x07fc, 0x07f8, 0x0200,
+	 0x0201,
+	 0x0202,
+	 },
+	{
+	 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0804, 0x0800, 0x07fc, 0x01ff,
+	 0x0200,
+	 0x0201,
+	 },
+	{
+	 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0808, 0x0804, 0x0800, 0x01fe,
+	 0x01ff,
+	 0x0200,
+	 },
+	{
+	 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0e, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0e, 0xe3, 0x00, 0xd6, 0x080c, 0x0808, 0x0804, 0x01fd,
+	 0x01fe,
+	 0x01ff,
+	 },
+	{
+	 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x0814, 0x0810, 0x080c, 0x01fb,
+	 0x01fc,
+	 0x01fd,
+	 },
+	{
+	 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x0818, 0x0814, 0x0810, 0x01fa,
+	 0x01fb,
+	 0x01fc,
+	 },
+	{
+	 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x081c, 0x0818, 0x0814, 0x01f9,
+	 0x01fa,
+	 0x01fb,
+	 },
+	{
+	 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0820, 0x081c, 0x0818, 0x01f8,
+	 0x01f9,
+	 0x01fa,
+	 },
+	{
+	 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0824, 0x0820, 0x081c, 0x01f7,
+	 0x01f8,
+	 0x01f9,
+	 },
+	{
+	 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0828, 0x0824, 0x0820, 0x01f6,
+	 0x01f7,
+	 0x01f8,
+	 },
+	{
+	 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x082c, 0x0828, 0x0824, 0x01f5,
+	 0x01f6,
+	 0x01f7,
+	 },
+	{
+	 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0830, 0x082c, 0x0828, 0x01f4,
+	 0x01f5,
+	 0x01f6,
+	 },
+	{
+	 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0834, 0x0830, 0x082c, 0x01f3,
+	 0x01f4,
+	 0x01f5,
+	 },
+	{
+	 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0838, 0x0834, 0x0830, 0x01f2,
+	 0x01f3,
+	 0x01f4,
+	 },
+	{
+	 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x083c, 0x0838, 0x0834, 0x01f1,
+	 0x01f2,
+	 0x01f3,
+	 },
+	{
+	 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x0840, 0x083c, 0x0838, 0x01f0,
+	 0x01f1,
+	 0x01f2,
+	 },
+	{
+	 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x0844, 0x0840, 0x083c, 0x01f0,
+	 0x01f0,
+	 0x01f1,
+	 },
+	{
+	 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x0848, 0x0844, 0x0840, 0x01ef,
+	 0x01f0,
+	 0x01f0,
+	 },
+	{
+	 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x084c, 0x0848, 0x0844, 0x01ee,
+	 0x01ef,
+	 0x01f0,
+	 },
+	{
+	 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0850, 0x084c, 0x0848, 0x01ed,
+	 0x01ee,
+	 0x01ef,
+	 },
+	{
+	 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0854, 0x0850, 0x084c, 0x01ec,
+	 0x01ed,
+	 0x01ee,
+	 },
+	{
+	 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0858, 0x0854, 0x0850, 0x01eb,
+	 0x01ec,
+	 0x01ed,
+	 },
+	{
+	 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0c, 0xc3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0c, 0xc3, 0x00, 0xa1, 0x085c, 0x0858, 0x0854, 0x01ea,
+	 0x01eb,
+	 0x01ec,
+	 },
+	{
+	 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0860, 0x085c, 0x0858, 0x01e9,
+	 0x01ea,
+	 0x01eb,
+	 },
+	{
+	 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0864, 0x0860, 0x085c, 0x01e8,
+	 0x01e9,
+	 0x01ea,
+	 },
+	{
+	 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0868, 0x0864, 0x0860, 0x01e7,
+	 0x01e8,
+	 0x01e9,
+	 },
+	{
+	 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x086c, 0x0868, 0x0864, 0x01e6,
+	 0x01e7,
+	 0x01e8,
+	 },
+	{
+	 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0a, 0xa3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0a, 0xa3, 0x00, 0xa1, 0x0870, 0x086c, 0x0868, 0x01e5,
+	 0x01e6,
+	 0x01e7,
+	 },
+	{
+	 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x0874, 0x0870, 0x086c, 0x01e5,
+	 0x01e5,
+	 0x01e6,
+	 },
+	{
+	 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x0878, 0x0874, 0x0870, 0x01e4,
+	 0x01e5,
+	 0x01e5,
+	 },
+	{
+	 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0xa3, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x09, 0xa3, 0x00, 0x90, 0x087c, 0x0878, 0x0874, 0x01e3,
+	 0x01e4,
+	 0x01e5,
+	 },
+	{
+	 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0880, 0x087c, 0x0878, 0x01e2,
+	 0x01e3,
+	 0x01e4,
+	 },
+	{
+	 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0884, 0x0880, 0x087c, 0x01e1,
+	 0x01e2,
+	 0x01e3,
+	 },
+	{
+	 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0888, 0x0884, 0x0880, 0x01e0,
+	 0x01e1,
+	 0x01e2,
+	 },
+	{
+	 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x08, 0x93, 0x00, 0x90, 0x00,
+	 0x00, 0x08, 0x08, 0x93, 0x00, 0x90, 0x088c, 0x0888, 0x0884, 0x01df,
+	 0x01e0,
+	 0x01e1,
+	 },
+	{
+	 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x08, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x08, 0x93, 0x00, 0x60, 0x0890, 0x088c, 0x0888, 0x01de,
+	 0x01df,
+	 0x01e0,
+	 },
+	{
+	 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x0894, 0x0890, 0x088c, 0x01dd,
+	 0x01de,
+	 0x01df,
+	 },
+	{
+	 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x0898, 0x0894, 0x0890, 0x01dd,
+	 0x01dd,
+	 0x01de,
+	 },
+	{
+	 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x089c, 0x0898, 0x0894, 0x01dc,
+	 0x01dd,
+	 0x01dd,
+	 },
+	{
+	 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x08a0, 0x089c, 0x0898, 0x01db,
+	 0x01dc,
+	 0x01dd,
+	 },
+	{
+	 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08a4, 0x08a0, 0x089c, 0x01da,
+	 0x01db,
+	 0x01dc,
+	 },
+	{
+	 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08a8, 0x08a4, 0x08a0, 0x01d9,
+	 0x01da,
+	 0x01db,
+	 },
+	{
+	 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08ac, 0x08a8, 0x08a4, 0x01d8,
+	 0x01d9,
+	 0x01da,
+	 },
+	{
+	 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b0, 0x08ac, 0x08a8, 0x01d7,
+	 0x01d8,
+	 0x01d9,
+	 },
+	{
+	 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b4, 0x08b0, 0x08ac, 0x01d7,
+	 0x01d7,
+	 0x01d8,
+	 },
+	{
+	 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b8, 0x08b4, 0x08b0, 0x01d6,
+	 0x01d7,
+	 0x01d7,
+	 },
+	{
+	 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x05, 0x83, 0x00, 0x60, 0x00,
+	 0x00, 0x07, 0x05, 0x83, 0x00, 0x60, 0x08bc, 0x08b8, 0x08b4, 0x01d5,
+	 0x01d6,
+	 0x01d7,
+	 },
+	{
+	 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x04, 0x83, 0x00, 0x60, 0x00,
+	 0x00, 0x07, 0x04, 0x83, 0x00, 0x60, 0x08c0, 0x08bc, 0x08b8, 0x01d4,
+	 0x01d5,
+	 0x01d6,
+	 },
+	{
+	 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x04, 0x73, 0x00, 0x30, 0x00,
+	 0x00, 0x07, 0x04, 0x73, 0x00, 0x30, 0x08c4, 0x08c0, 0x08bc, 0x01d3,
+	 0x01d4,
+	 0x01d5,
+	 },
+	{
+	 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08c8, 0x08c4, 0x08c0, 0x01d2,
+	 0x01d3,
+	 0x01d4,
+	 },
+	{
+	 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08cc, 0x08c8, 0x08c4, 0x01d2,
+	 0x01d2,
+	 0x01d3,
+	 },
+	{
+	 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08d0, 0x08cc, 0x08c8, 0x01d1,
+	 0x01d2,
+	 0x01d2,
+	 },
+	{
+	 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08d4, 0x08d0, 0x08cc, 0x01d0,
+	 0x01d1,
+	 0x01d2,
+	 },
+	{
+	 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x08d8, 0x08d4, 0x08d0, 0x01cf,
+	 0x01d0,
+	 0x01d1,
+	 },
+	{
+	 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x08dc, 0x08d8, 0x08d4, 0x01ce,
+	 0x01cf,
+	 0x01d0,
+	 },
+	{
+	 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x03, 0x63, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x03, 0x63, 0x00, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce,
+	 0x01ce,
+	 0x01cf,
+	 },
+	{
+	 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd,
+	 0x01ce,
+	 0x01ce,
+	 },
+	{
+	 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc,
+	 0x01cd,
+	 0x01ce,
+	 },
+	{
+	 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb,
+	 0x01cc,
+	 0x01cd,
+	 },
+	{
+	 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca,
+	 0x01cb,
+	 0x01cc,
+	 },
+	{
+	 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9,
+	 0x01ca,
+	 0x01cb,
+	 },
+	{
+	 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x05, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x01, 0x53, 0x00, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9,
+	 0x01ca,
+	 0x01cb,
+	 },
+	{
+	 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9,
+	 0x01c9,
+	 0x01ca,
+	 },
+	{
+	 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8,
+	 0x01c9,
+	 0x01ca,
+	 },
+	{
+	 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8,
+	 0x01c9,
+	 0x01c9,
+	 },
+	{
+	 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8,
+	 0x01c8,
+	 0x01c9,
+	 },
+	{
+	 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7,
+	 0x01c8,
+	 0x01c9,
+	 },
+	{
+	 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7,
+	 0x01c8,
+	 0x01c8,
+	 },
+	{
+	 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6,
+	 0x01c7,
+	 0x01c8,
+	 },
+	{
+	 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6,
+	 0x01c7,
+	 0x01c8,
+	 },
+	{
+	 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6,
+	 0x01c6,
+	 0x01c7,
+	 },
+	{
+	 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5,
+	 0x01c6,
+	 0x01c7,
+	 },
+	{
+	 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x03, 0x01, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x01, 0x43, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5,
+	 0x01c6,
+	 0x01c6,
+	 },
+	{
+	 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4,
+	 0x01c5,
+	 0x01c6,
+	 },
+	{
+	 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4,
+	 0x01c5,
+	 0x01c6,
+	 },
+	{
+	 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4,
+	 0x01c4,
+	 0x01c5,
+	 },
+	{
+	 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3,
+	 0x01c4,
+	 0x01c5,
+	 },
+	{
+	 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3,
+	 0x01c4,
+	 0x01c4,
+	 },
+	{
+	 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2,
+	 0x01c3,
+	 0x01c4,
+	 },
+	{
+	 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2,
+	 0x01c3,
+	 0x01c4,
+	 },
+	{
+	 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2,
+	 0x01c2,
+	 0x01c3,
+	 },
+	{
+	 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1,
+	 0x01c2,
+	 0x01c3,
+	 },
+	{
+	 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1,
+	 0x01c2,
+	 0x01c2,
+	 },
+	{
+	 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0,
+	 0x01c1,
+	 0x01c2,
+	 },
+	{
+	 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf,
+	 0x01c0,
+	 0x01c1,
+	 },
+	{
+	 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf,
+	 0x01bf,
+	 0x01c0,
+	 },
+	{
+	 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be,
+	 0x01bf,
+	 0x01bf,
+	 },
+	{
+	 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd,
+	 0x01be,
+	 0x01bf,
+	 },
+	{
+	 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc,
+	 0x01bd,
+	 0x01be,
+	 },
+	{
+	 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc,
+	 0x01bc,
+	 0x01bd,
+	 },
+	{
+	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x71, 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
+	 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a,
+	 0x043f,
+	 0x0443,
+	 },
+	{
+	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x71, 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
+	 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438,
+	 0x043d,
+	 0x0441,
+	 },
+	{
+	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x71, 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
+	 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436,
+	 0x043a,
+	 0x043f,
+	 },
+	{
+	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x71, 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
+	 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434,
+	 0x0438,
+	 0x043d,
+	 },
+	{
+	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x51, 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51,
+	 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431,
+	 0x0436,
+	 0x043a,
+	 },
+	{
+	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x51, 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51,
+	 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f,
+	 0x0434,
+	 0x0438,
+	 },
+	{
+	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x51, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d,
+	 0x0431,
+	 0x0436,
+	 },
+	{
+	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x31, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b,
+	 0x042f,
+	 0x0434,
+	 },
+	{
+	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x31, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429,
+	 0x042d,
+	 0x0431,
+	 },
+	{
+	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x31, 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
+	 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427,
+	 0x042b,
+	 0x042f,
+	 },
+	{
+	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x31, 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
+	 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424,
+	 0x0429,
+	 0x042d,
+	 },
+	{
+	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x11, 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x11,
+	 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422,
+	 0x0427,
+	 0x042b,
+	 },
+	{
+	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x11, 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x11,
+	 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420,
+	 0x0424,
+	 0x0429,
+	 },
+	{
+	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f,
+	 0x04, 0x00, 0x04, 0x00, 0x11, 0x43, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x11,
+	 0x43, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b,
+	 0x041f,
+	 0x0424}
+};
+
+static const struct chan_info_nphy_radio2057_rev5
+chan_info_nphyrev8_2057_rev5[] = {
+	{
+	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03c9, 0x03c5, 0x03c1,
+	 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03cb, 0x03c7, 0x03c3,
+	 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61, 0x03, 0xef, 0x03cd, 0x03c9, 0x03c5,
+	 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0c,
+	 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61, 0x03, 0xdf, 0x03cf, 0x03cb, 0x03c7,
+	 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0c,
+	 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61, 0x03, 0xcf, 0x03d1, 0x03cd, 0x03c9,
+	 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0c,
+	 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61, 0x03, 0xbf, 0x03d3, 0x03cf, 0x03cb,
+	 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61, 0x03, 0xaf, 0x03d5, 0x03d1, 0x03cd,
+	 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61, 0x03, 0x9f, 0x03d7, 0x03d3, 0x03cf,
+	 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61, 0x03, 0x8f, 0x03d9, 0x03d5, 0x03d1,
+	 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0b,
+	 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61, 0x03, 0x7f, 0x03db, 0x03d7, 0x03d3,
+	 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0b,
+	 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61, 0x03, 0x6f, 0x03dd, 0x03d9, 0x03d5,
+	 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0b,
+	 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61, 0x03, 0x5f, 0x03df, 0x03db, 0x03d7,
+	 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0a,
+	 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61, 0x03, 0x4f, 0x03e1, 0x03dd, 0x03d9,
+	 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0a,
+	 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61, 0x03, 0x3f, 0x03e6, 0x03e2, 0x03de,
+	 0x041b, 0x041f, 0x0424}
+};
+
+static const struct chan_info_nphy_radio2057_rev5
+chan_info_nphyrev9_2057_rev5v1[] = {
+	{
+	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03c9, 0x03c5, 0x03c1,
+	 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03cb, 0x03c7, 0x03c3,
+	 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61, 0x03, 0xef, 0x03cd, 0x03c9, 0x03c5,
+	 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0c,
+	 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61, 0x03, 0xdf, 0x03cf, 0x03cb, 0x03c7,
+	 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0c,
+	 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61, 0x03, 0xcf, 0x03d1, 0x03cd, 0x03c9,
+	 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0c,
+	 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61, 0x03, 0xbf, 0x03d3, 0x03cf, 0x03cb,
+	 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61, 0x03, 0xaf, 0x03d5, 0x03d1, 0x03cd,
+	 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61, 0x03, 0x9f, 0x03d7, 0x03d3, 0x03cf,
+	 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61, 0x03, 0x8f, 0x03d9, 0x03d5, 0x03d1,
+	 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0b,
+	 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61, 0x03, 0x7f, 0x03db, 0x03d7, 0x03d3,
+	 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0b,
+	 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61, 0x03, 0x6f, 0x03dd, 0x03d9, 0x03d5,
+	 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0b,
+	 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61, 0x03, 0x5f, 0x03df, 0x03db, 0x03d7,
+	 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0a,
+	 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61, 0x03, 0x4f, 0x03e1, 0x03dd, 0x03d9,
+	 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0a,
+	 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61, 0x03, 0x3f, 0x03e6, 0x03e2, 0x03de,
+	 0x041b, 0x041f, 0x0424}
+};
+
+static const struct chan_info_nphy_radio2057 chan_info_nphyrev8_2057_rev7[] = {
+	{
+	 184, 4920, 0x68, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xec, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b4, 0x07b0, 0x07ac, 0x0214,
+	 0x0215,
+	 0x0216},
+	{
+	 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b8, 0x07b4, 0x07b0, 0x0213,
+	 0x0214,
+	 0x0215},
+	{
+	 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07bc, 0x07b8, 0x07b4, 0x0212,
+	 0x0213,
+	 0x0214},
+	{
+	 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c0, 0x07bc, 0x07b8, 0x0211,
+	 0x0212,
+	 0x0213},
+	{
+	 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c4, 0x07c0, 0x07bc, 0x020f,
+	 0x0211,
+	 0x0212},
+	{
+	 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c8, 0x07c4, 0x07c0, 0x020e,
+	 0x020f,
+	 0x0211},
+	{
+	 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07cc, 0x07c8, 0x07c4, 0x020d,
+	 0x020e,
+	 0x020f},
+	{
+	 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07d0, 0x07cc, 0x07c8, 0x020c,
+	 0x020d,
+	 0x020e},
+	{
+	 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d4, 0x07d0, 0x07cc, 0x020b,
+	 0x020c,
+	 0x020d},
+	{
+	 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d8, 0x07d4, 0x07d0, 0x020a,
+	 0x020b,
+	 0x020c},
+	{
+	 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07dc, 0x07d8, 0x07d4, 0x0209,
+	 0x020a,
+	 0x020b},
+	{
+	 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e0, 0x07dc, 0x07d8, 0x0208,
+	 0x0209,
+	 0x020a},
+	{
+	 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e4, 0x07e0, 0x07dc, 0x0207,
+	 0x0208,
+	 0x0209},
+	{
+	 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e8, 0x07e4, 0x07e0, 0x0206,
+	 0x0207,
+	 0x0208},
+	{
+	 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07ec, 0x07e8, 0x07e4, 0x0205,
+	 0x0206,
+	 0x0207},
+	{
+	 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f0, 0x07ec, 0x07e8, 0x0204,
+	 0x0205,
+	 0x0206},
+	{
+	 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f4, 0x07f0, 0x07ec, 0x0203,
+	 0x0204,
+	 0x0205},
+	{
+	 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f8, 0x07f4, 0x07f0, 0x0202,
+	 0x0203,
+	 0x0204},
+	{
+	 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x07fc, 0x07f8, 0x07f4, 0x0201,
+	 0x0202,
+	 0x0203},
+	{
+	 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0800, 0x07fc, 0x07f8, 0x0200,
+	 0x0201,
+	 0x0202},
+	{
+	 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0804, 0x0800, 0x07fc, 0x01ff,
+	 0x0200,
+	 0x0201},
+	{
+	 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0808, 0x0804, 0x0800, 0x01fe,
+	 0x01ff,
+	 0x0200},
+	{
+	 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x080c, 0x0808, 0x0804, 0x01fd,
+	 0x01fe,
+	 0x01ff},
+	{
+	 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0814, 0x0810, 0x080c, 0x01fb,
+	 0x01fc,
+	 0x01fd},
+	{
+	 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0818, 0x0814, 0x0810, 0x01fa,
+	 0x01fb,
+	 0x01fc},
+	{
+	 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x081c, 0x0818, 0x0814, 0x01f9,
+	 0x01fa,
+	 0x01fb},
+	{
+	 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0820, 0x081c, 0x0818, 0x01f8,
+	 0x01f9,
+	 0x01fa},
+	{
+	 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0824, 0x0820, 0x081c, 0x01f7,
+	 0x01f8,
+	 0x01f9},
+	{
+	 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0828, 0x0824, 0x0820, 0x01f6,
+	 0x01f7,
+	 0x01f8},
+	{
+	 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x082c, 0x0828, 0x0824, 0x01f5,
+	 0x01f6,
+	 0x01f7},
+	{
+	 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0830, 0x082c, 0x0828, 0x01f4,
+	 0x01f5,
+	 0x01f6},
+	{
+	 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0834, 0x0830, 0x082c, 0x01f3,
+	 0x01f4,
+	 0x01f5},
+	{
+	 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0838, 0x0834, 0x0830, 0x01f2,
+	 0x01f3,
+	 0x01f4},
+	{
+	 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x083c, 0x0838, 0x0834, 0x01f1,
+	 0x01f2,
+	 0x01f3},
+	{
+	 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0840, 0x083c, 0x0838, 0x01f0,
+	 0x01f1,
+	 0x01f2},
+	{
+	 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0844, 0x0840, 0x083c, 0x01f0,
+	 0x01f0,
+	 0x01f1},
+	{
+	 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0848, 0x0844, 0x0840, 0x01ef,
+	 0x01f0,
+	 0x01f0},
+	{
+	 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x084c, 0x0848, 0x0844, 0x01ee,
+	 0x01ef,
+	 0x01f0},
+	{
+	 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0850, 0x084c, 0x0848, 0x01ed,
+	 0x01ee,
+	 0x01ef},
+	{
+	 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0854, 0x0850, 0x084c, 0x01ec,
+	 0x01ed,
+	 0x01ee},
+	{
+	 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0858, 0x0854, 0x0850, 0x01eb,
+	 0x01ec,
+	 0x01ed},
+	{
+	 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x085c, 0x0858, 0x0854, 0x01ea,
+	 0x01eb,
+	 0x01ec},
+	{
+	 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0860, 0x085c, 0x0858, 0x01e9,
+	 0x01ea,
+	 0x01eb},
+	{
+	 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0864, 0x0860, 0x085c, 0x01e8,
+	 0x01e9,
+	 0x01ea},
+	{
+	 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0868, 0x0864, 0x0860, 0x01e7,
+	 0x01e8,
+	 0x01e9},
+	{
+	 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x086c, 0x0868, 0x0864, 0x01e6,
+	 0x01e7,
+	 0x01e8},
+	{
+	 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0870, 0x086c, 0x0868, 0x01e5,
+	 0x01e6,
+	 0x01e7},
+	{
+	 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0874, 0x0870, 0x086c, 0x01e5,
+	 0x01e5,
+	 0x01e6},
+	{
+	 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0878, 0x0874, 0x0870, 0x01e4,
+	 0x01e5,
+	 0x01e5},
+	{
+	 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x087c, 0x0878, 0x0874, 0x01e3,
+	 0x01e4,
+	 0x01e5},
+	{
+	 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0880, 0x087c, 0x0878, 0x01e2,
+	 0x01e3,
+	 0x01e4},
+	{
+	 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0884, 0x0880, 0x087c, 0x01e1,
+	 0x01e2,
+	 0x01e3},
+	{
+	 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0888, 0x0884, 0x0880, 0x01e0,
+	 0x01e1,
+	 0x01e2},
+	{
+	 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x088c, 0x0888, 0x0884, 0x01df,
+	 0x01e0,
+	 0x01e1},
+	{
+	 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0890, 0x088c, 0x0888, 0x01de,
+	 0x01df,
+	 0x01e0},
+	{
+	 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0894, 0x0890, 0x088c, 0x01dd,
+	 0x01de,
+	 0x01df},
+	{
+	 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0898, 0x0894, 0x0890, 0x01dd,
+	 0x01dd,
+	 0x01de},
+	{
+	 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x089c, 0x0898, 0x0894, 0x01dc,
+	 0x01dd,
+	 0x01dd},
+	{
+	 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a0, 0x089c, 0x0898, 0x01db,
+	 0x01dc,
+	 0x01dd},
+	{
+	 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a4, 0x08a0, 0x089c, 0x01da,
+	 0x01db,
+	 0x01dc},
+	{
+	 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a8, 0x08a4, 0x08a0, 0x01d9,
+	 0x01da,
+	 0x01db},
+	{
+	 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08ac, 0x08a8, 0x08a4, 0x01d8,
+	 0x01d9,
+	 0x01da},
+	{
+	 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b0, 0x08ac, 0x08a8, 0x01d7,
+	 0x01d8,
+	 0x01d9},
+	{
+	 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b4, 0x08b0, 0x08ac, 0x01d7,
+	 0x01d7,
+	 0x01d8},
+	{
+	 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b8, 0x08b4, 0x08b0, 0x01d6,
+	 0x01d7,
+	 0x01d7},
+	{
+	 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08bc, 0x08b8, 0x08b4, 0x01d5,
+	 0x01d6,
+	 0x01d7},
+	{
+	 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08c0, 0x08bc, 0x08b8, 0x01d4,
+	 0x01d5,
+	 0x01d6},
+	{
+	 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c4, 0x08c0, 0x08bc, 0x01d3,
+	 0x01d4,
+	 0x01d5},
+	{
+	 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c8, 0x08c4, 0x08c0, 0x01d2,
+	 0x01d3,
+	 0x01d4},
+	{
+	 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08cc, 0x08c8, 0x08c4, 0x01d2,
+	 0x01d2,
+	 0x01d3},
+	{
+	 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d0, 0x08cc, 0x08c8, 0x01d1,
+	 0x01d2,
+	 0x01d2},
+	{
+	 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d4, 0x08d0, 0x08cc, 0x01d0,
+	 0x01d1,
+	 0x01d2},
+	{
+	 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08d8, 0x08d4, 0x08d0, 0x01cf,
+	 0x01d0,
+	 0x01d1},
+	{
+	 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08dc, 0x08d8, 0x08d4, 0x01ce,
+	 0x01cf,
+	 0x01d0},
+	{
+	 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08e0, 0x08dc, 0x08d8, 0x01ce,
+	 0x01ce,
+	 0x01cf},
+	{
+	 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e4, 0x08e0, 0x08dc, 0x01cd,
+	 0x01ce,
+	 0x01ce},
+	{
+	 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e8, 0x08e4, 0x08e0, 0x01cc,
+	 0x01cd,
+	 0x01ce},
+	{
+	 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08ec, 0x08e8, 0x08e4, 0x01cb,
+	 0x01cc,
+	 0x01cd},
+	{
+	 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f0, 0x08ec, 0x08e8, 0x01ca,
+	 0x01cb,
+	 0x01cc},
+	{
+	 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f4, 0x08f0, 0x08ec, 0x01c9,
+	 0x01ca,
+	 0x01cb},
+	{
+	 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f6, 0x08f2, 0x08ee, 0x01c9,
+	 0x01ca,
+	 0x01cb},
+	{
+	 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f8, 0x08f4, 0x08f0, 0x01c9,
+	 0x01c9,
+	 0x01ca},
+	{
+	 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fa, 0x08f6, 0x08f2, 0x01c8,
+	 0x01c9,
+	 0x01ca},
+	{
+	 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fc, 0x08f8, 0x08f4, 0x01c8,
+	 0x01c9,
+	 0x01c9},
+	{
+	 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fe, 0x08fa, 0x08f6, 0x01c8,
+	 0x01c8,
+	 0x01c9},
+	{
+	 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7,
+	 0x01c8,
+	 0x01c9},
+	{
+	 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7,
+	 0x01c8,
+	 0x01c8},
+	{
+	 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6,
+	 0x01c7,
+	 0x01c8},
+	{
+	 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6,
+	 0x01c7,
+	 0x01c8},
+	{
+	 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6,
+	 0x01c6,
+	 0x01c7},
+	{
+	 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5,
+	 0x01c6,
+	 0x01c7},
+	{
+	 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5,
+	 0x01c6,
+	 0x01c6},
+	{
+	 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4,
+	 0x01c5,
+	 0x01c6},
+	{
+	 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4,
+	 0x01c5,
+	 0x01c6},
+	{
+	 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4,
+	 0x01c4,
+	 0x01c5},
+	{
+	 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3,
+	 0x01c4,
+	 0x01c5},
+	{
+	 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3,
+	 0x01c4,
+	 0x01c4},
+	{
+	 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2,
+	 0x01c3,
+	 0x01c4},
+	{
+	 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2,
+	 0x01c3,
+	 0x01c4},
+	{
+	 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2,
+	 0x01c2,
+	 0x01c3},
+	{
+	 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1,
+	 0x01c2,
+	 0x01c3},
+	{
+	 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1,
+	 0x01c2,
+	 0x01c2},
+	{
+	 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0,
+	 0x01c1,
+	 0x01c2},
+	{
+	 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf,
+	 0x01c0,
+	 0x01c1},
+	{
+	 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf,
+	 0x01bf,
+	 0x01c0},
+	{
+	 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be,
+	 0x01bf,
+	 0x01bf},
+	{
+	 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd,
+	 0x01be,
+	 0x01bf},
+	{
+	 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc,
+	 0x01bd,
+	 0x01be},
+	{
+	 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc,
+	 0x01bc,
+	 0x01bd},
+	{
+	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a,
+	 0x043f,
+	 0x0443},
+	{
+	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438,
+	 0x043d,
+	 0x0441},
+	{
+	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436,
+	 0x043a,
+	 0x043f},
+	{
+	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434,
+	 0x0438,
+	 0x043d},
+	{
+	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431,
+	 0x0436,
+	 0x043a},
+	{
+	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f,
+	 0x0434,
+	 0x0438},
+	{
+	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d,
+	 0x0431,
+	 0x0436},
+	{
+	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b,
+	 0x042f,
+	 0x0434},
+	{
+	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429,
+	 0x042d,
+	 0x0431},
+	{
+	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427,
+	 0x042b,
+	 0x042f},
+	{
+	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424,
+	 0x0429,
+	 0x042d},
+	{
+	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422,
+	 0x0427,
+	 0x042b},
+	{
+	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420,
+	 0x0424,
+	 0x0429},
+	{
+	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f,
+	 0x04, 0x00, 0x04, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b,
+	 0x041f,
+	 0x0424}
+};
+
+static const struct chan_info_nphy_radio2057 chan_info_nphyrev8_2057_rev8[] = {
+	{
+	 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b8, 0x07b4, 0x07b0, 0x0213,
+	 0x0214,
+	 0x0215},
+	{
+	 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07bc, 0x07b8, 0x07b4, 0x0212,
+	 0x0213,
+	 0x0214},
+	{
+	 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c0, 0x07bc, 0x07b8, 0x0211,
+	 0x0212,
+	 0x0213},
+	{
+	 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c4, 0x07c0, 0x07bc, 0x020f,
+	 0x0211,
+	 0x0212},
+	{
+	 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c8, 0x07c4, 0x07c0, 0x020e,
+	 0x020f,
+	 0x0211},
+	{
+	 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07cc, 0x07c8, 0x07c4, 0x020d,
+	 0x020e,
+	 0x020f},
+	{
+	 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07d0, 0x07cc, 0x07c8, 0x020c,
+	 0x020d,
+	 0x020e},
+	{
+	 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d4, 0x07d0, 0x07cc, 0x020b,
+	 0x020c,
+	 0x020d},
+	{
+	 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d8, 0x07d4, 0x07d0, 0x020a,
+	 0x020b,
+	 0x020c},
+	{
+	 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07dc, 0x07d8, 0x07d4, 0x0209,
+	 0x020a,
+	 0x020b},
+	{
+	 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e0, 0x07dc, 0x07d8, 0x0208,
+	 0x0209,
+	 0x020a},
+	{
+	 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e4, 0x07e0, 0x07dc, 0x0207,
+	 0x0208,
+	 0x0209},
+	{
+	 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e8, 0x07e4, 0x07e0, 0x0206,
+	 0x0207,
+	 0x0208},
+	{
+	 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07ec, 0x07e8, 0x07e4, 0x0205,
+	 0x0206,
+	 0x0207},
+	{
+	 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f0, 0x07ec, 0x07e8, 0x0204,
+	 0x0205,
+	 0x0206},
+	{
+	 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f4, 0x07f0, 0x07ec, 0x0203,
+	 0x0204,
+	 0x0205},
+	{
+	 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f8, 0x07f4, 0x07f0, 0x0202,
+	 0x0203,
+	 0x0204},
+	{
+	 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x07fc, 0x07f8, 0x07f4, 0x0201,
+	 0x0202,
+	 0x0203},
+	{
+	 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0800, 0x07fc, 0x07f8, 0x0200,
+	 0x0201,
+	 0x0202},
+	{
+	 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0804, 0x0800, 0x07fc, 0x01ff,
+	 0x0200,
+	 0x0201},
+	{
+	 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0808, 0x0804, 0x0800, 0x01fe,
+	 0x01ff,
+	 0x0200},
+	{
+	 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x080c, 0x0808, 0x0804, 0x01fd,
+	 0x01fe,
+	 0x01ff},
+	{
+	 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0814, 0x0810, 0x080c, 0x01fb,
+	 0x01fc,
+	 0x01fd},
+	{
+	 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0818, 0x0814, 0x0810, 0x01fa,
+	 0x01fb,
+	 0x01fc},
+	{
+	 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x081c, 0x0818, 0x0814, 0x01f9,
+	 0x01fa,
+	 0x01fb},
+	{
+	 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0820, 0x081c, 0x0818, 0x01f8,
+	 0x01f9,
+	 0x01fa},
+	{
+	 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0824, 0x0820, 0x081c, 0x01f7,
+	 0x01f8,
+	 0x01f9},
+	{
+	 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0828, 0x0824, 0x0820, 0x01f6,
+	 0x01f7,
+	 0x01f8},
+	{
+	 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x082c, 0x0828, 0x0824, 0x01f5,
+	 0x01f6,
+	 0x01f7},
+	{
+	 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0830, 0x082c, 0x0828, 0x01f4,
+	 0x01f5,
+	 0x01f6},
+	{
+	 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0834, 0x0830, 0x082c, 0x01f3,
+	 0x01f4,
+	 0x01f5},
+	{
+	 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0838, 0x0834, 0x0830, 0x01f2,
+	 0x01f3,
+	 0x01f4},
+	{
+	 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x083c, 0x0838, 0x0834, 0x01f1,
+	 0x01f2,
+	 0x01f3},
+	{
+	 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0840, 0x083c, 0x0838, 0x01f0,
+	 0x01f1,
+	 0x01f2},
+	{
+	 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0844, 0x0840, 0x083c, 0x01f0,
+	 0x01f0,
+	 0x01f1},
+	{
+	 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0848, 0x0844, 0x0840, 0x01ef,
+	 0x01f0,
+	 0x01f0},
+	{
+	 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x084c, 0x0848, 0x0844, 0x01ee,
+	 0x01ef,
+	 0x01f0},
+	{
+	 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0850, 0x084c, 0x0848, 0x01ed,
+	 0x01ee,
+	 0x01ef},
+	{
+	 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0854, 0x0850, 0x084c, 0x01ec,
+	 0x01ed,
+	 0x01ee},
+	{
+	 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0858, 0x0854, 0x0850, 0x01eb,
+	 0x01ec,
+	 0x01ed},
+	{
+	 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x085c, 0x0858, 0x0854, 0x01ea,
+	 0x01eb,
+	 0x01ec},
+	{
+	 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0860, 0x085c, 0x0858, 0x01e9,
+	 0x01ea,
+	 0x01eb},
+	{
+	 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0864, 0x0860, 0x085c, 0x01e8,
+	 0x01e9,
+	 0x01ea},
+	{
+	 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0868, 0x0864, 0x0860, 0x01e7,
+	 0x01e8,
+	 0x01e9},
+	{
+	 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x086c, 0x0868, 0x0864, 0x01e6,
+	 0x01e7,
+	 0x01e8},
+	{
+	 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0870, 0x086c, 0x0868, 0x01e5,
+	 0x01e6,
+	 0x01e7},
+	{
+	 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0874, 0x0870, 0x086c, 0x01e5,
+	 0x01e5,
+	 0x01e6},
+	{
+	 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0878, 0x0874, 0x0870, 0x01e4,
+	 0x01e5,
+	 0x01e5},
+	{
+	 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x087c, 0x0878, 0x0874, 0x01e3,
+	 0x01e4,
+	 0x01e5},
+	{
+	 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0880, 0x087c, 0x0878, 0x01e2,
+	 0x01e3,
+	 0x01e4},
+	{
+	 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0884, 0x0880, 0x087c, 0x01e1,
+	 0x01e2,
+	 0x01e3},
+	{
+	 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0888, 0x0884, 0x0880, 0x01e0,
+	 0x01e1,
+	 0x01e2},
+	{
+	 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x088c, 0x0888, 0x0884, 0x01df,
+	 0x01e0,
+	 0x01e1},
+	{
+	 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0890, 0x088c, 0x0888, 0x01de,
+	 0x01df,
+	 0x01e0},
+	{
+	 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0894, 0x0890, 0x088c, 0x01dd,
+	 0x01de,
+	 0x01df},
+	{
+	 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0898, 0x0894, 0x0890, 0x01dd,
+	 0x01dd,
+	 0x01de},
+	{
+	 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x089c, 0x0898, 0x0894, 0x01dc,
+	 0x01dd,
+	 0x01dd},
+	{
+	 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a0, 0x089c, 0x0898, 0x01db,
+	 0x01dc,
+	 0x01dd},
+	{
+	 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a4, 0x08a0, 0x089c, 0x01da,
+	 0x01db,
+	 0x01dc},
+	{
+	 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a8, 0x08a4, 0x08a0, 0x01d9,
+	 0x01da,
+	 0x01db},
+	{
+	 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08ac, 0x08a8, 0x08a4, 0x01d8,
+	 0x01d9,
+	 0x01da},
+	{
+	 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b0, 0x08ac, 0x08a8, 0x01d7,
+	 0x01d8,
+	 0x01d9},
+	{
+	 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b4, 0x08b0, 0x08ac, 0x01d7,
+	 0x01d7,
+	 0x01d8},
+	{
+	 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b8, 0x08b4, 0x08b0, 0x01d6,
+	 0x01d7,
+	 0x01d7},
+	{
+	 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08bc, 0x08b8, 0x08b4, 0x01d5,
+	 0x01d6,
+	 0x01d7},
+	{
+	 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08c0, 0x08bc, 0x08b8, 0x01d4,
+	 0x01d5,
+	 0x01d6},
+	{
+	 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c4, 0x08c0, 0x08bc, 0x01d3,
+	 0x01d4,
+	 0x01d5},
+	{
+	 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c8, 0x08c4, 0x08c0, 0x01d2,
+	 0x01d3,
+	 0x01d4},
+	{
+	 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08cc, 0x08c8, 0x08c4, 0x01d2,
+	 0x01d2,
+	 0x01d3},
+	{
+	 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d0, 0x08cc, 0x08c8, 0x01d1,
+	 0x01d2,
+	 0x01d2},
+	{
+	 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d4, 0x08d0, 0x08cc, 0x01d0,
+	 0x01d1,
+	 0x01d2},
+	{
+	 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08d8, 0x08d4, 0x08d0, 0x01cf,
+	 0x01d0,
+	 0x01d1},
+	{
+	 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08dc, 0x08d8, 0x08d4, 0x01ce,
+	 0x01cf,
+	 0x01d0},
+	{
+	 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08e0, 0x08dc, 0x08d8, 0x01ce,
+	 0x01ce,
+	 0x01cf},
+	{
+	 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e4, 0x08e0, 0x08dc, 0x01cd,
+	 0x01ce,
+	 0x01ce},
+	{
+	 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e8, 0x08e4, 0x08e0, 0x01cc,
+	 0x01cd,
+	 0x01ce},
+	{
+	 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08ec, 0x08e8, 0x08e4, 0x01cb,
+	 0x01cc,
+	 0x01cd},
+	{
+	 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f0, 0x08ec, 0x08e8, 0x01ca,
+	 0x01cb,
+	 0x01cc},
+	{
+	 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f4, 0x08f0, 0x08ec, 0x01c9,
+	 0x01ca,
+	 0x01cb},
+	{
+	 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f6, 0x08f2, 0x08ee, 0x01c9,
+	 0x01ca,
+	 0x01cb},
+	{
+	 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f8, 0x08f4, 0x08f0, 0x01c9,
+	 0x01c9,
+	 0x01ca},
+	{
+	 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fa, 0x08f6, 0x08f2, 0x01c8,
+	 0x01c9,
+	 0x01ca},
+	{
+	 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fc, 0x08f8, 0x08f4, 0x01c8,
+	 0x01c9,
+	 0x01c9},
+	{
+	 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fe, 0x08fa, 0x08f6, 0x01c8,
+	 0x01c8,
+	 0x01c9},
+	{
+	 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7,
+	 0x01c8,
+	 0x01c9},
+	{
+	 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7,
+	 0x01c8,
+	 0x01c8},
+	{
+	 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6,
+	 0x01c7,
+	 0x01c8},
+	{
+	 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6,
+	 0x01c7,
+	 0x01c8},
+	{
+	 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6,
+	 0x01c6,
+	 0x01c7},
+	{
+	 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5,
+	 0x01c6,
+	 0x01c7},
+	{
+	 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5,
+	 0x01c6,
+	 0x01c6},
+	{
+	 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4,
+	 0x01c5,
+	 0x01c6},
+	{
+	 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4,
+	 0x01c5,
+	 0x01c6},
+	{
+	 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4,
+	 0x01c4,
+	 0x01c5},
+	{
+	 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3,
+	 0x01c4,
+	 0x01c5},
+	{
+	 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3,
+	 0x01c4,
+	 0x01c4},
+	{
+	 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2,
+	 0x01c3,
+	 0x01c4},
+	{
+	 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2,
+	 0x01c3,
+	 0x01c4},
+	{
+	 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2,
+	 0x01c2,
+	 0x01c3},
+	{
+	 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1,
+	 0x01c2,
+	 0x01c3},
+	{
+	 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1,
+	 0x01c2,
+	 0x01c2},
+	{
+	 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0,
+	 0x01c1,
+	 0x01c2},
+	{
+	 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf,
+	 0x01c0,
+	 0x01c1},
+	{
+	 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf,
+	 0x01bf,
+	 0x01c0},
+	{
+	 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be,
+	 0x01bf,
+	 0x01bf},
+	{
+	 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd,
+	 0x01be,
+	 0x01bf},
+	{
+	 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc,
+	 0x01bd,
+	 0x01be},
+	{
+	 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc,
+	 0x01bc,
+	 0x01bd},
+	{
+	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a,
+	 0x043f,
+	 0x0443},
+	{
+	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438,
+	 0x043d,
+	 0x0441},
+	{
+	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436,
+	 0x043a,
+	 0x043f},
+	{
+	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434,
+	 0x0438,
+	 0x043d},
+	{
+	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431,
+	 0x0436,
+	 0x043a},
+	{
+	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f,
+	 0x0434,
+	 0x0438},
+	{
+	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d,
+	 0x0431,
+	 0x0436},
+	{
+	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b,
+	 0x042f,
+	 0x0434},
+	{
+	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429,
+	 0x042d,
+	 0x0431},
+	{
+	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427,
+	 0x042b,
+	 0x042f},
+	{
+	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424,
+	 0x0429,
+	 0x042d},
+	{
+	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422,
+	 0x0427,
+	 0x042b},
+	{
+	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420,
+	 0x0424,
+	 0x0429},
+	{
+	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f,
+	 0x04, 0x00, 0x04, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b,
+	 0x041f,
+	 0x0424}
+};
+
+static struct radio_regs regs_2055[] = {
+	{0x02, 0x80, 0x80, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0x27, 0x27, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0x27, 0x27, 0, 0},
+	{0x07, 0x7f, 0x7f, 1, 1},
+	{0x08, 0x7, 0x7, 1, 1},
+	{0x09, 0x7f, 0x7f, 1, 1},
+	{0x0A, 0x7, 0x7, 1, 1},
+	{0x0B, 0x15, 0x15, 0, 0},
+	{0x0C, 0x15, 0x15, 0, 0},
+	{0x0D, 0x4f, 0x4f, 1, 1},
+	{0x0E, 0x5, 0x5, 1, 1},
+	{0x0F, 0x4f, 0x4f, 1, 1},
+	{0x10, 0x5, 0x5, 1, 1},
+	{0x11, 0xd0, 0xd0, 0, 0},
+	{0x12, 0x2, 0x2, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0x40, 0x40, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0xc0, 0xc0, 0, 0},
+	{0x1E, 0xff, 0xff, 0, 0},
+	{0x1F, 0xc0, 0xc0, 0, 0},
+	{0x20, 0xff, 0xff, 0, 0},
+	{0x21, 0xc0, 0xc0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x2c, 0x2c, 0, 0},
+	{0x24, 0, 0, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0xa4, 0xa4, 0, 0},
+	{0x2E, 0x38, 0x38, 0, 0},
+	{0x2F, 0, 0, 0, 0},
+	{0x30, 0x4, 0x4, 1, 1},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0xa, 0xa, 0, 0},
+	{0x33, 0x87, 0x87, 0, 0},
+	{0x34, 0x9, 0x9, 0, 0},
+	{0x35, 0x70, 0x70, 0, 0},
+	{0x36, 0x11, 0x11, 0, 0},
+	{0x37, 0x18, 0x18, 1, 1},
+	{0x38, 0x6, 0x6, 0, 0},
+	{0x39, 0x4, 0x4, 1, 1},
+	{0x3A, 0x6, 0x6, 0, 0},
+	{0x3B, 0x9e, 0x9e, 0, 0},
+	{0x3C, 0x9, 0x9, 0, 0},
+	{0x3D, 0xc8, 0xc8, 1, 1},
+	{0x3E, 0x88, 0x88, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0, 0, 0, 0},
+	{0x42, 0x1, 0x1, 0, 0},
+	{0x43, 0x2, 0x2, 0, 0},
+	{0x44, 0x96, 0x96, 0, 0},
+	{0x45, 0x3e, 0x3e, 0, 0},
+	{0x46, 0x3e, 0x3e, 0, 0},
+	{0x47, 0x13, 0x13, 0, 0},
+	{0x48, 0x2, 0x2, 0, 0},
+	{0x49, 0x15, 0x15, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0, 0, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0, 0, 0, 0},
+	{0x50, 0x8, 0x8, 0, 0},
+	{0x51, 0x8, 0x8, 0, 0},
+	{0x52, 0x6, 0x6, 0, 0},
+	{0x53, 0x84, 0x84, 1, 1},
+	{0x54, 0xc3, 0xc3, 0, 0},
+	{0x55, 0x8f, 0x8f, 0, 0},
+	{0x56, 0xff, 0xff, 0, 0},
+	{0x57, 0xff, 0xff, 0, 0},
+	{0x58, 0x88, 0x88, 0, 0},
+	{0x59, 0x88, 0x88, 0, 0},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0xcc, 0xcc, 0, 0},
+	{0x5C, 0x6, 0x6, 0, 0},
+	{0x5D, 0x80, 0x80, 0, 0},
+	{0x5E, 0x80, 0x80, 0, 0},
+	{0x5F, 0xf8, 0xf8, 0, 0},
+	{0x60, 0x88, 0x88, 0, 0},
+	{0x61, 0x88, 0x88, 0, 0},
+	{0x62, 0x88, 0x8, 1, 1},
+	{0x63, 0x88, 0x88, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0x1, 0x1, 1, 1},
+	{0x66, 0x8a, 0x8a, 0, 0},
+	{0x67, 0x8, 0x8, 0, 0},
+	{0x68, 0x83, 0x83, 0, 0},
+	{0x69, 0x6, 0x6, 0, 0},
+	{0x6A, 0xa0, 0xa0, 0, 0},
+	{0x6B, 0xa, 0xa, 0, 0},
+	{0x6C, 0x87, 0x87, 1, 1},
+	{0x6D, 0x2a, 0x2a, 0, 0},
+	{0x6E, 0x2a, 0x2a, 0, 0},
+	{0x6F, 0x2a, 0x2a, 0, 0},
+	{0x70, 0x2a, 0x2a, 0, 0},
+	{0x71, 0x18, 0x18, 0, 0},
+	{0x72, 0x6a, 0x6a, 1, 1},
+	{0x73, 0xab, 0xab, 1, 1},
+	{0x74, 0x13, 0x13, 1, 1},
+	{0x75, 0xc1, 0xc1, 1, 1},
+	{0x76, 0xaa, 0xaa, 1, 1},
+	{0x77, 0x87, 0x87, 1, 1},
+	{0x78, 0, 0, 0, 0},
+	{0x79, 0x6, 0x6, 0, 0},
+	{0x7A, 0x7, 0x7, 0, 0},
+	{0x7B, 0x7, 0x7, 0, 0},
+	{0x7C, 0x15, 0x15, 0, 0},
+	{0x7D, 0x55, 0x55, 0, 0},
+	{0x7E, 0x97, 0x97, 1, 1},
+	{0x7F, 0x8, 0x8, 0, 0},
+	{0x80, 0x14, 0x14, 1, 1},
+	{0x81, 0x33, 0x33, 0, 0},
+	{0x82, 0x88, 0x88, 0, 0},
+	{0x83, 0x6, 0x6, 0, 0},
+	{0x84, 0x3, 0x3, 1, 1},
+	{0x85, 0xa, 0xa, 0, 0},
+	{0x86, 0x3, 0x3, 1, 1},
+	{0x87, 0x2a, 0x2a, 0, 0},
+	{0x88, 0xa4, 0xa4, 0, 0},
+	{0x89, 0x18, 0x18, 0, 0},
+	{0x8A, 0x28, 0x28, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0x4a, 0x4a, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0xf8, 0xf8, 0, 0},
+	{0x8F, 0x88, 0x88, 0, 0},
+	{0x90, 0x88, 0x88, 0, 0},
+	{0x91, 0x88, 0x8, 1, 1},
+	{0x92, 0x88, 0x88, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0x1, 0x1, 1, 1},
+	{0x95, 0x8a, 0x8a, 0, 0},
+	{0x96, 0x8, 0x8, 0, 0},
+	{0x97, 0x83, 0x83, 0, 0},
+	{0x98, 0x6, 0x6, 0, 0},
+	{0x99, 0xa0, 0xa0, 0, 0},
+	{0x9A, 0xa, 0xa, 0, 0},
+	{0x9B, 0x87, 0x87, 1, 1},
+	{0x9C, 0x2a, 0x2a, 0, 0},
+	{0x9D, 0x2a, 0x2a, 0, 0},
+	{0x9E, 0x2a, 0x2a, 0, 0},
+	{0x9F, 0x2a, 0x2a, 0, 0},
+	{0xA0, 0x18, 0x18, 0, 0},
+	{0xA1, 0x6a, 0x6a, 1, 1},
+	{0xA2, 0xab, 0xab, 1, 1},
+	{0xA3, 0x13, 0x13, 1, 1},
+	{0xA4, 0xc1, 0xc1, 1, 1},
+	{0xA5, 0xaa, 0xaa, 1, 1},
+	{0xA6, 0x87, 0x87, 1, 1},
+	{0xA7, 0, 0, 0, 0},
+	{0xA8, 0x6, 0x6, 0, 0},
+	{0xA9, 0x7, 0x7, 0, 0},
+	{0xAA, 0x7, 0x7, 0, 0},
+	{0xAB, 0x15, 0x15, 0, 0},
+	{0xAC, 0x55, 0x55, 0, 0},
+	{0xAD, 0x97, 0x97, 1, 1},
+	{0xAE, 0x8, 0x8, 0, 0},
+	{0xAF, 0x14, 0x14, 1, 1},
+	{0xB0, 0x33, 0x33, 0, 0},
+	{0xB1, 0x88, 0x88, 0, 0},
+	{0xB2, 0x6, 0x6, 0, 0},
+	{0xB3, 0x3, 0x3, 1, 1},
+	{0xB4, 0xa, 0xa, 0, 0},
+	{0xB5, 0x3, 0x3, 1, 1},
+	{0xB6, 0x2a, 0x2a, 0, 0},
+	{0xB7, 0xa4, 0xa4, 0, 0},
+	{0xB8, 0x18, 0x18, 0, 0},
+	{0xB9, 0x28, 0x28, 0, 0},
+	{0xBA, 0, 0, 0, 0},
+	{0xBB, 0x4a, 0x4a, 0, 0},
+	{0xBC, 0, 0, 0, 0},
+	{0xBD, 0x71, 0x71, 0, 0},
+	{0xBE, 0x72, 0x72, 0, 0},
+	{0xBF, 0x73, 0x73, 0, 0},
+	{0xC0, 0x74, 0x74, 0, 0},
+	{0xC1, 0x75, 0x75, 0, 0},
+	{0xC2, 0x76, 0x76, 0, 0},
+	{0xC3, 0x77, 0x77, 0, 0},
+	{0xC4, 0x78, 0x78, 0, 0},
+	{0xC5, 0x79, 0x79, 0, 0},
+	{0xC6, 0x7a, 0x7a, 0, 0},
+	{0xC7, 0, 0, 0, 0},
+	{0xC8, 0, 0, 0, 0},
+	{0xC9, 0, 0, 0, 0},
+	{0xCA, 0, 0, 0, 0},
+	{0xCB, 0, 0, 0, 0},
+	{0xCC, 0, 0, 0, 0},
+	{0xCD, 0, 0, 0, 0},
+	{0xCE, 0x6, 0x6, 0, 0},
+	{0xCF, 0, 0, 0, 0},
+	{0xD0, 0, 0, 0, 0},
+	{0xD1, 0x18, 0x18, 0, 0},
+	{0xD2, 0x88, 0x88, 0, 0},
+	{0xD3, 0, 0, 0, 0},
+	{0xD4, 0, 0, 0, 0},
+	{0xD5, 0, 0, 0, 0},
+	{0xD6, 0, 0, 0, 0},
+	{0xD7, 0, 0, 0, 0},
+	{0xD8, 0, 0, 0, 0},
+	{0xD9, 0, 0, 0, 0},
+	{0xDA, 0x6, 0x6, 0, 0},
+	{0xDB, 0, 0, 0, 0},
+	{0xDC, 0, 0, 0, 0},
+	{0xDD, 0x18, 0x18, 0, 0},
+	{0xDE, 0x88, 0x88, 0, 0},
+	{0xDF, 0, 0, 0, 0},
+	{0xE0, 0, 0, 0, 0},
+	{0xE1, 0, 0, 0, 0},
+	{0xE2, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+static struct radio_regs regs_SYN_2056[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0xd, 0xd, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+static struct radio_regs regs_TX_2056[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0x11, 0x11, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0xf, 0xf, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x2d, 0x2d, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0x74, 0x74, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+static struct radio_regs regs_RX_2056[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x99, 0x99, 0, 0},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x44, 0x44, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0x44, 0x44, 0, 0},
+	{0x40, 0xf, 0xf, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0x50, 0x50, 1, 1},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x99, 0x99, 0, 0},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x44, 0x44, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x66, 0x66, 0, 0},
+	{0x50, 0x66, 0x66, 0, 0},
+	{0x51, 0x57, 0x57, 0, 0},
+	{0x52, 0x57, 0x57, 0, 0},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x23, 0x23, 0, 0},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0x2, 0x2, 0, 0},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+static struct radio_regs regs_SYN_2056_A1[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0xd, 0xd, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+static struct radio_regs regs_TX_2056_A1[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0x11, 0x11, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0xf, 0xf, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x2d, 0x2d, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0x72, 0x72, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+static struct radio_regs regs_RX_2056_A1[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x44, 0x44, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0x44, 0x44, 0, 0},
+	{0x40, 0xf, 0xf, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0x50, 0x50, 1, 1},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x44, 0x44, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x2f, 0x2f, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+static struct radio_regs regs_SYN_2056_rev5[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+static struct radio_regs regs_TX_2056_rev5[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0x11, 0x11, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0xf, 0xf, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x2d, 0x2d, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0x70, 0x70, 0, 0},
+	{0x94, 0x70, 0x70, 0, 0},
+	{0x95, 0x71, 0x71, 1, 1},
+	{0x96, 0x71, 0x71, 1, 1},
+	{0x97, 0x72, 0x72, 1, 1},
+	{0x98, 0x73, 0x73, 1, 1},
+	{0x99, 0x74, 0x74, 1, 1},
+	{0x9A, 0x75, 0x75, 1, 1},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+static struct radio_regs regs_RX_2056_rev5[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x88, 0x88, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 1, 1},
+	{0x40, 0x7, 0x7, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0, 0, 1, 1},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x4, 0x4, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+static struct radio_regs regs_SYN_2056_rev6[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+static struct radio_regs regs_TX_2056_rev6[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0xee, 0xee, 1, 1},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0x50, 0x50, 1, 1},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x50, 0x50, 1, 1},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0x30, 0x30, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0x70, 0x70, 0, 0},
+	{0x94, 0x70, 0x70, 0, 0},
+	{0x95, 0x70, 0x70, 0, 0},
+	{0x96, 0x70, 0x70, 0, 0},
+	{0x97, 0x70, 0x70, 0, 0},
+	{0x98, 0x70, 0x70, 0, 0},
+	{0x99, 0x70, 0x70, 0, 0},
+	{0x9A, 0x70, 0x70, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+static struct radio_regs regs_RX_2056_rev6[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x88, 0x88, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0x44, 0x44, 0, 0},
+	{0x40, 0x7, 0x7, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x44, 0x44, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x4, 0x4, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0x5, 0x5, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+static struct radio_regs regs_SYN_2056_rev7[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+static struct radio_regs regs_TX_2056_rev7[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0xee, 0xee, 1, 1},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0x50, 0x50, 1, 1},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x50, 0x50, 1, 1},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0x30, 0x30, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0x70, 0x70, 0, 0},
+	{0x94, 0x70, 0x70, 0, 0},
+	{0x95, 0x71, 0x71, 1, 1},
+	{0x96, 0x71, 0x71, 1, 1},
+	{0x97, 0x72, 0x72, 1, 1},
+	{0x98, 0x73, 0x73, 1, 1},
+	{0x99, 0x74, 0x74, 1, 1},
+	{0x9A, 0x75, 0x75, 1, 1},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+static struct radio_regs regs_RX_2056_rev7[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x88, 0x88, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 1, 1},
+	{0x40, 0x7, 0x7, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0, 0, 1, 1},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x4, 0x4, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+static struct radio_regs regs_SYN_2056_rev8[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+static struct radio_regs regs_TX_2056_rev8[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0xee, 0xee, 1, 1},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0x50, 0x50, 1, 1},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x50, 0x50, 1, 1},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0x30, 0x30, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0x70, 0x70, 0, 0},
+	{0x94, 0x70, 0x70, 0, 0},
+	{0x95, 0x70, 0x70, 0, 0},
+	{0x96, 0x70, 0x70, 0, 0},
+	{0x97, 0x70, 0x70, 0, 0},
+	{0x98, 0x70, 0x70, 0, 0},
+	{0x99, 0x70, 0x70, 0, 0},
+	{0x9A, 0x70, 0x70, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+static struct radio_regs regs_RX_2056_rev8[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x88, 0x88, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0x44, 0x44, 0, 0},
+	{0x40, 0x7, 0x7, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x44, 0x44, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x4, 0x4, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0x5, 0x5, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+static const struct radio_regs regs_SYN_2056_rev11[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x6, 0x6, 1, 1},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x3f, 0x3f, 1, 1},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0x6, 0x6, 1, 1},
+	{0x4C, 0x6, 0x6, 1, 1},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x2b, 0x2b, 1, 1},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+static const struct radio_regs regs_TX_2056_rev11[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0xee, 0xee, 1, 1},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0x50, 0x50, 1, 1},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x50, 0x50, 1, 1},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0x30, 0x30, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0x70, 0x70, 0, 0},
+	{0x94, 0x70, 0x70, 0, 0},
+	{0x95, 0x70, 0x70, 0, 0},
+	{0x96, 0x70, 0x70, 0, 0},
+	{0x97, 0x70, 0x70, 0, 0},
+	{0x98, 0x70, 0x70, 0, 0},
+	{0x99, 0x70, 0x70, 0, 0},
+	{0x9A, 0x70, 0x70, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+static const struct radio_regs regs_RX_2056_rev11[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x88, 0x88, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0x44, 0x44, 0, 0},
+	{0x40, 0x7, 0x7, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x44, 0x44, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x4, 0x4, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0x5, 0x5, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+static struct radio_20xx_regs regs_2057_rev4[] = {
+	{0x00, 0x84, 0},
+	{0x01, 0, 0},
+	{0x02, 0x60, 0},
+	{0x03, 0x1f, 0},
+	{0x04, 0x4, 0},
+	{0x05, 0x2, 0},
+	{0x06, 0x1, 0},
+	{0x07, 0x1, 0},
+	{0x08, 0x1, 0},
+	{0x09, 0x69, 0},
+	{0x0A, 0x66, 0},
+	{0x0B, 0x6, 0},
+	{0x0C, 0x18, 0},
+	{0x0D, 0x3, 0},
+	{0x0E, 0x20, 1},
+	{0x0F, 0x20, 0},
+	{0x10, 0, 0},
+	{0x11, 0x7c, 0},
+	{0x12, 0x42, 0},
+	{0x13, 0xbd, 0},
+	{0x14, 0x7, 0},
+	{0x15, 0xf7, 0},
+	{0x16, 0x8, 0},
+	{0x17, 0x17, 0},
+	{0x18, 0x7, 0},
+	{0x19, 0, 0},
+	{0x1A, 0x2, 0},
+	{0x1B, 0x13, 0},
+	{0x1C, 0x3e, 0},
+	{0x1D, 0x3e, 0},
+	{0x1E, 0x96, 0},
+	{0x1F, 0x4, 0},
+	{0x20, 0, 0},
+	{0x21, 0, 0},
+	{0x22, 0x17, 0},
+	{0x23, 0x4, 0},
+	{0x24, 0x1, 0},
+	{0x25, 0x6, 0},
+	{0x26, 0x4, 0},
+	{0x27, 0xd, 0},
+	{0x28, 0xd, 0},
+	{0x29, 0x30, 0},
+	{0x2A, 0x32, 0},
+	{0x2B, 0x8, 0},
+	{0x2C, 0x1c, 0},
+	{0x2D, 0x2, 0},
+	{0x2E, 0x4, 0},
+	{0x2F, 0x7f, 0},
+	{0x30, 0x27, 0},
+	{0x31, 0, 1},
+	{0x32, 0, 1},
+	{0x33, 0, 1},
+	{0x34, 0, 0},
+	{0x35, 0x26, 1},
+	{0x36, 0x18, 0},
+	{0x37, 0x7, 0},
+	{0x38, 0x66, 0},
+	{0x39, 0x66, 0},
+	{0x3A, 0x66, 0},
+	{0x3B, 0x66, 0},
+	{0x3C, 0xff, 1},
+	{0x3D, 0xff, 1},
+	{0x3E, 0xff, 1},
+	{0x3F, 0xff, 1},
+	{0x40, 0x16, 0},
+	{0x41, 0x7, 0},
+	{0x42, 0x19, 0},
+	{0x43, 0x7, 0},
+	{0x44, 0x6, 0},
+	{0x45, 0x3, 0},
+	{0x46, 0x1, 0},
+	{0x47, 0x7, 0},
+	{0x48, 0x33, 0},
+	{0x49, 0x5, 0},
+	{0x4A, 0x77, 0},
+	{0x4B, 0x66, 0},
+	{0x4C, 0x66, 0},
+	{0x4D, 0, 0},
+	{0x4E, 0x4, 0},
+	{0x4F, 0xc, 0},
+	{0x50, 0, 0},
+	{0x51, 0x75, 0},
+	{0x56, 0x7, 0},
+	{0x57, 0, 0},
+	{0x58, 0, 0},
+	{0x59, 0xa8, 0},
+	{0x5A, 0, 0},
+	{0x5B, 0x1f, 0},
+	{0x5C, 0x30, 0},
+	{0x5D, 0x1, 0},
+	{0x5E, 0x30, 0},
+	{0x5F, 0x70, 0},
+	{0x60, 0, 0},
+	{0x61, 0, 0},
+	{0x62, 0x33, 1},
+	{0x63, 0x19, 0},
+	{0x64, 0x62, 0},
+	{0x65, 0, 0},
+	{0x66, 0x11, 0},
+	{0x69, 0, 0},
+	{0x6A, 0x7e, 0},
+	{0x6B, 0x3f, 0},
+	{0x6C, 0x7f, 0},
+	{0x6D, 0x78, 0},
+	{0x6E, 0xc8, 0},
+	{0x6F, 0x88, 0},
+	{0x70, 0x8, 0},
+	{0x71, 0xf, 0},
+	{0x72, 0xbc, 0},
+	{0x73, 0x8, 0},
+	{0x74, 0x60, 0},
+	{0x75, 0x1e, 0},
+	{0x76, 0x70, 0},
+	{0x77, 0, 0},
+	{0x78, 0, 0},
+	{0x79, 0, 0},
+	{0x7A, 0x33, 0},
+	{0x7B, 0x1e, 0},
+	{0x7C, 0x62, 0},
+	{0x7D, 0x11, 0},
+	{0x80, 0x3c, 0},
+	{0x81, 0x9c, 0},
+	{0x82, 0xa, 0},
+	{0x83, 0x9d, 0},
+	{0x84, 0xa, 0},
+	{0x85, 0, 0},
+	{0x86, 0x40, 0},
+	{0x87, 0x40, 0},
+	{0x88, 0x88, 0},
+	{0x89, 0x10, 0},
+	{0x8A, 0xf0, 1},
+	{0x8B, 0x10, 1},
+	{0x8C, 0xf0, 1},
+	{0x8D, 0, 0},
+	{0x8E, 0, 0},
+	{0x8F, 0x10, 0},
+	{0x90, 0x55, 0},
+	{0x91, 0x3f, 1},
+	{0x92, 0x36, 1},
+	{0x93, 0, 0},
+	{0x94, 0, 0},
+	{0x95, 0, 0},
+	{0x96, 0x87, 0},
+	{0x97, 0x11, 0},
+	{0x98, 0, 0},
+	{0x99, 0x33, 0},
+	{0x9A, 0x88, 0},
+	{0x9B, 0, 0},
+	{0x9C, 0x87, 0},
+	{0x9D, 0x11, 0},
+	{0x9E, 0, 0},
+	{0x9F, 0x33, 0},
+	{0xA0, 0x88, 0},
+	{0xA1, 0xe1, 0},
+	{0xA2, 0x3f, 0},
+	{0xA3, 0x44, 0},
+	{0xA4, 0x8c, 1},
+	{0xA5, 0x6d, 0},
+	{0xA6, 0x22, 0},
+	{0xA7, 0xbe, 0},
+	{0xA8, 0x55, 1},
+	{0xA9, 0xc, 0},
+	{0xAA, 0xc, 0},
+	{0xAB, 0xaa, 0},
+	{0xAC, 0x2, 0},
+	{0xAD, 0, 0},
+	{0xAE, 0x10, 0},
+	{0xAF, 0x1, 1},
+	{0xB0, 0, 0},
+	{0xB1, 0, 0},
+	{0xB2, 0x80, 0},
+	{0xB3, 0x60, 0},
+	{0xB4, 0x44, 0},
+	{0xB5, 0x55, 0},
+	{0xB6, 0x1, 0},
+	{0xB7, 0x55, 0},
+	{0xB8, 0x1, 0},
+	{0xB9, 0x5, 0},
+	{0xBA, 0x55, 0},
+	{0xBB, 0x55, 0},
+	{0xC1, 0, 0},
+	{0xC2, 0, 0},
+	{0xC3, 0, 0},
+	{0xC4, 0, 0},
+	{0xC5, 0, 0},
+	{0xC6, 0, 0},
+	{0xC7, 0, 0},
+	{0xC8, 0, 0},
+	{0xC9, 0, 0},
+	{0xCA, 0, 0},
+	{0xCB, 0, 0},
+	{0xCC, 0, 0},
+	{0xCD, 0, 0},
+	{0xCE, 0x5e, 0},
+	{0xCF, 0xc, 0},
+	{0xD0, 0xc, 0},
+	{0xD1, 0xc, 0},
+	{0xD2, 0, 0},
+	{0xD3, 0x2b, 0},
+	{0xD4, 0xc, 0},
+	{0xD5, 0, 0},
+	{0xD6, 0x75, 0},
+	{0xDB, 0x7, 0},
+	{0xDC, 0, 0},
+	{0xDD, 0, 0},
+	{0xDE, 0xa8, 0},
+	{0xDF, 0, 0},
+	{0xE0, 0x1f, 0},
+	{0xE1, 0x30, 0},
+	{0xE2, 0x1, 0},
+	{0xE3, 0x30, 0},
+	{0xE4, 0x70, 0},
+	{0xE5, 0, 0},
+	{0xE6, 0, 0},
+	{0xE7, 0x33, 0},
+	{0xE8, 0x19, 0},
+	{0xE9, 0x62, 0},
+	{0xEA, 0, 0},
+	{0xEB, 0x11, 0},
+	{0xEE, 0, 0},
+	{0xEF, 0x7e, 0},
+	{0xF0, 0x3f, 0},
+	{0xF1, 0x7f, 0},
+	{0xF2, 0x78, 0},
+	{0xF3, 0xc8, 0},
+	{0xF4, 0x88, 0},
+	{0xF5, 0x8, 0},
+	{0xF6, 0xf, 0},
+	{0xF7, 0xbc, 0},
+	{0xF8, 0x8, 0},
+	{0xF9, 0x60, 0},
+	{0xFA, 0x1e, 0},
+	{0xFB, 0x70, 0},
+	{0xFC, 0, 0},
+	{0xFD, 0, 0},
+	{0xFE, 0, 0},
+	{0xFF, 0x33, 0},
+	{0x100, 0x1e, 0},
+	{0x101, 0x62, 0},
+	{0x102, 0x11, 0},
+	{0x105, 0x3c, 0},
+	{0x106, 0x9c, 0},
+	{0x107, 0xa, 0},
+	{0x108, 0x9d, 0},
+	{0x109, 0xa, 0},
+	{0x10A, 0, 0},
+	{0x10B, 0x40, 0},
+	{0x10C, 0x40, 0},
+	{0x10D, 0x88, 0},
+	{0x10E, 0x10, 0},
+	{0x10F, 0xf0, 1},
+	{0x110, 0x10, 1},
+	{0x111, 0xf0, 1},
+	{0x112, 0, 0},
+	{0x113, 0, 0},
+	{0x114, 0x10, 0},
+	{0x115, 0x55, 0},
+	{0x116, 0x3f, 1},
+	{0x117, 0x36, 1},
+	{0x118, 0, 0},
+	{0x119, 0, 0},
+	{0x11A, 0, 0},
+	{0x11B, 0x87, 0},
+	{0x11C, 0x11, 0},
+	{0x11D, 0, 0},
+	{0x11E, 0x33, 0},
+	{0x11F, 0x88, 0},
+	{0x120, 0, 0},
+	{0x121, 0x87, 0},
+	{0x122, 0x11, 0},
+	{0x123, 0, 0},
+	{0x124, 0x33, 0},
+	{0x125, 0x88, 0},
+	{0x126, 0xe1, 0},
+	{0x127, 0x3f, 0},
+	{0x128, 0x44, 0},
+	{0x129, 0x8c, 1},
+	{0x12A, 0x6d, 0},
+	{0x12B, 0x22, 0},
+	{0x12C, 0xbe, 0},
+	{0x12D, 0x55, 1},
+	{0x12E, 0xc, 0},
+	{0x12F, 0xc, 0},
+	{0x130, 0xaa, 0},
+	{0x131, 0x2, 0},
+	{0x132, 0, 0},
+	{0x133, 0x10, 0},
+	{0x134, 0x1, 1},
+	{0x135, 0, 0},
+	{0x136, 0, 0},
+	{0x137, 0x80, 0},
+	{0x138, 0x60, 0},
+	{0x139, 0x44, 0},
+	{0x13A, 0x55, 0},
+	{0x13B, 0x1, 0},
+	{0x13C, 0x55, 0},
+	{0x13D, 0x1, 0},
+	{0x13E, 0x5, 0},
+	{0x13F, 0x55, 0},
+	{0x140, 0x55, 0},
+	{0x146, 0, 0},
+	{0x147, 0, 0},
+	{0x148, 0, 0},
+	{0x149, 0, 0},
+	{0x14A, 0, 0},
+	{0x14B, 0, 0},
+	{0x14C, 0, 0},
+	{0x14D, 0, 0},
+	{0x14E, 0, 0},
+	{0x14F, 0, 0},
+	{0x150, 0, 0},
+	{0x151, 0, 0},
+	{0x152, 0, 0},
+	{0x153, 0, 0},
+	{0x154, 0xc, 0},
+	{0x155, 0xc, 0},
+	{0x156, 0xc, 0},
+	{0x157, 0, 0},
+	{0x158, 0x2b, 0},
+	{0x159, 0x84, 0},
+	{0x15A, 0x15, 0},
+	{0x15B, 0xf, 0},
+	{0x15C, 0, 0},
+	{0x15D, 0, 0},
+	{0x15E, 0, 1},
+	{0x15F, 0, 1},
+	{0x160, 0, 1},
+	{0x161, 0, 1},
+	{0x162, 0, 1},
+	{0x163, 0, 1},
+	{0x164, 0, 0},
+	{0x165, 0, 0},
+	{0x166, 0, 0},
+	{0x167, 0, 0},
+	{0x168, 0, 0},
+	{0x169, 0x2, 1},
+	{0x16A, 0, 1},
+	{0x16B, 0, 1},
+	{0x16C, 0, 1},
+	{0x16D, 0, 0},
+	{0x170, 0, 0},
+	{0x171, 0x77, 0},
+	{0x172, 0x77, 0},
+	{0x173, 0x77, 0},
+	{0x174, 0x77, 0},
+	{0x175, 0, 0},
+	{0x176, 0x3, 0},
+	{0x177, 0x37, 0},
+	{0x178, 0x3, 0},
+	{0x179, 0, 0},
+	{0x17A, 0x21, 0},
+	{0x17B, 0x21, 0},
+	{0x17C, 0, 0},
+	{0x17D, 0xaa, 0},
+	{0x17E, 0, 0},
+	{0x17F, 0xaa, 0},
+	{0x180, 0, 0},
+	{0x190, 0, 0},
+	{0x191, 0x77, 0},
+	{0x192, 0x77, 0},
+	{0x193, 0x77, 0},
+	{0x194, 0x77, 0},
+	{0x195, 0, 0},
+	{0x196, 0x3, 0},
+	{0x197, 0x37, 0},
+	{0x198, 0x3, 0},
+	{0x199, 0, 0},
+	{0x19A, 0x21, 0},
+	{0x19B, 0x21, 0},
+	{0x19C, 0, 0},
+	{0x19D, 0xaa, 0},
+	{0x19E, 0, 0},
+	{0x19F, 0xaa, 0},
+	{0x1A0, 0, 0},
+	{0x1A1, 0x2, 0},
+	{0x1A2, 0xf, 0},
+	{0x1A3, 0xf, 0},
+	{0x1A4, 0, 1},
+	{0x1A5, 0, 1},
+	{0x1A6, 0, 1},
+	{0x1A7, 0x2, 0},
+	{0x1A8, 0xf, 0},
+	{0x1A9, 0xf, 0},
+	{0x1AA, 0, 1},
+	{0x1AB, 0, 1},
+	{0x1AC, 0, 1},
+	{0xFFFF, 0, 0},
+};
+
+static struct radio_20xx_regs regs_2057_rev5[] = {
+	{0x00, 0, 1},
+	{0x01, 0x57, 1},
+	{0x02, 0x20, 1},
+	{0x03, 0x1f, 0},
+	{0x04, 0x4, 0},
+	{0x05, 0x2, 0},
+	{0x06, 0x1, 0},
+	{0x07, 0x1, 0},
+	{0x08, 0x1, 0},
+	{0x09, 0x69, 0},
+	{0x0A, 0x66, 0},
+	{0x0B, 0x6, 0},
+	{0x0C, 0x18, 0},
+	{0x0D, 0x3, 0},
+	{0x0E, 0x20, 0},
+	{0x0F, 0x20, 0},
+	{0x10, 0, 0},
+	{0x11, 0x7c, 0},
+	{0x12, 0x42, 0},
+	{0x13, 0xbd, 0},
+	{0x14, 0x7, 0},
+	{0x15, 0x87, 0},
+	{0x16, 0x8, 0},
+	{0x17, 0x17, 0},
+	{0x18, 0x7, 0},
+	{0x19, 0, 0},
+	{0x1A, 0x2, 0},
+	{0x1B, 0x13, 0},
+	{0x1C, 0x3e, 0},
+	{0x1D, 0x3e, 0},
+	{0x1E, 0x96, 0},
+	{0x1F, 0x4, 0},
+	{0x20, 0, 0},
+	{0x21, 0, 0},
+	{0x22, 0x17, 0},
+	{0x23, 0x6, 1},
+	{0x24, 0x1, 0},
+	{0x25, 0x6, 0},
+	{0x26, 0x4, 0},
+	{0x27, 0xd, 0},
+	{0x28, 0xd, 0},
+	{0x29, 0x30, 0},
+	{0x2A, 0x32, 0},
+	{0x2B, 0x8, 0},
+	{0x2C, 0x1c, 0},
+	{0x2D, 0x2, 0},
+	{0x2E, 0x4, 0},
+	{0x2F, 0x7f, 0},
+	{0x30, 0x27, 0},
+	{0x31, 0, 1},
+	{0x32, 0, 1},
+	{0x33, 0, 1},
+	{0x34, 0, 0},
+	{0x35, 0x20, 0},
+	{0x36, 0x18, 0},
+	{0x37, 0x7, 0},
+	{0x38, 0x66, 0},
+	{0x39, 0x66, 0},
+	{0x3C, 0xff, 0},
+	{0x3D, 0xff, 0},
+	{0x40, 0x16, 0},
+	{0x41, 0x7, 0},
+	{0x45, 0x3, 0},
+	{0x46, 0x1, 0},
+	{0x47, 0x7, 0},
+	{0x4B, 0x66, 0},
+	{0x4C, 0x66, 0},
+	{0x4D, 0, 0},
+	{0x4E, 0x4, 0},
+	{0x4F, 0xc, 0},
+	{0x50, 0, 0},
+	{0x51, 0x70, 1},
+	{0x56, 0x7, 0},
+	{0x57, 0, 0},
+	{0x58, 0, 0},
+	{0x59, 0x88, 1},
+	{0x5A, 0, 0},
+	{0x5B, 0x1f, 0},
+	{0x5C, 0x20, 1},
+	{0x5D, 0x1, 0},
+	{0x5E, 0x30, 0},
+	{0x5F, 0x70, 0},
+	{0x60, 0, 0},
+	{0x61, 0, 0},
+	{0x62, 0x33, 1},
+	{0x63, 0xf, 1},
+	{0x64, 0xf, 1},
+	{0x65, 0, 0},
+	{0x66, 0x11, 0},
+	{0x80, 0x3c, 0},
+	{0x81, 0x1, 1},
+	{0x82, 0xa, 0},
+	{0x85, 0, 0},
+	{0x86, 0x40, 0},
+	{0x87, 0x40, 0},
+	{0x88, 0x88, 0},
+	{0x89, 0x10, 0},
+	{0x8A, 0xf0, 0},
+	{0x8B, 0x10, 0},
+	{0x8C, 0xf0, 0},
+	{0x8F, 0x10, 0},
+	{0x90, 0x55, 0},
+	{0x91, 0x3f, 1},
+	{0x92, 0x36, 1},
+	{0x93, 0, 0},
+	{0x94, 0, 0},
+	{0x95, 0, 0},
+	{0x96, 0x87, 0},
+	{0x97, 0x11, 0},
+	{0x98, 0, 0},
+	{0x99, 0x33, 0},
+	{0x9A, 0x88, 0},
+	{0xA1, 0x20, 1},
+	{0xA2, 0x3f, 0},
+	{0xA3, 0x44, 0},
+	{0xA4, 0x8c, 0},
+	{0xA5, 0x6c, 0},
+	{0xA6, 0x22, 0},
+	{0xA7, 0xbe, 0},
+	{0xA8, 0x55, 0},
+	{0xAA, 0xc, 0},
+	{0xAB, 0xaa, 0},
+	{0xAC, 0x2, 0},
+	{0xAD, 0, 0},
+	{0xAE, 0x10, 0},
+	{0xAF, 0x1, 0},
+	{0xB0, 0, 0},
+	{0xB1, 0, 0},
+	{0xB2, 0x80, 0},
+	{0xB3, 0x60, 0},
+	{0xB4, 0x44, 0},
+	{0xB5, 0x55, 0},
+	{0xB6, 0x1, 0},
+	{0xB7, 0x55, 0},
+	{0xB8, 0x1, 0},
+	{0xB9, 0x5, 0},
+	{0xBA, 0x55, 0},
+	{0xBB, 0x55, 0},
+	{0xC3, 0, 0},
+	{0xC4, 0, 0},
+	{0xC5, 0, 0},
+	{0xC6, 0, 0},
+	{0xC7, 0, 0},
+	{0xC8, 0, 0},
+	{0xC9, 0, 0},
+	{0xCA, 0, 0},
+	{0xCB, 0, 0},
+	{0xCD, 0, 0},
+	{0xCE, 0x5e, 0},
+	{0xCF, 0xc, 0},
+	{0xD0, 0xc, 0},
+	{0xD1, 0xc, 0},
+	{0xD2, 0, 0},
+	{0xD3, 0x2b, 0},
+	{0xD4, 0xc, 0},
+	{0xD5, 0, 0},
+	{0xD6, 0x70, 1},
+	{0xDB, 0x7, 0},
+	{0xDC, 0, 0},
+	{0xDD, 0, 0},
+	{0xDE, 0x88, 1},
+	{0xDF, 0, 0},
+	{0xE0, 0x1f, 0},
+	{0xE1, 0x20, 1},
+	{0xE2, 0x1, 0},
+	{0xE3, 0x30, 0},
+	{0xE4, 0x70, 0},
+	{0xE5, 0, 0},
+	{0xE6, 0, 0},
+	{0xE7, 0x33, 0},
+	{0xE8, 0xf, 1},
+	{0xE9, 0xf, 1},
+	{0xEA, 0, 0},
+	{0xEB, 0x11, 0},
+	{0x105, 0x3c, 0},
+	{0x106, 0x1, 1},
+	{0x107, 0xa, 0},
+	{0x10A, 0, 0},
+	{0x10B, 0x40, 0},
+	{0x10C, 0x40, 0},
+	{0x10D, 0x88, 0},
+	{0x10E, 0x10, 0},
+	{0x10F, 0xf0, 0},
+	{0x110, 0x10, 0},
+	{0x111, 0xf0, 0},
+	{0x114, 0x10, 0},
+	{0x115, 0x55, 0},
+	{0x116, 0x3f, 1},
+	{0x117, 0x36, 1},
+	{0x118, 0, 0},
+	{0x119, 0, 0},
+	{0x11A, 0, 0},
+	{0x11B, 0x87, 0},
+	{0x11C, 0x11, 0},
+	{0x11D, 0, 0},
+	{0x11E, 0x33, 0},
+	{0x11F, 0x88, 0},
+	{0x126, 0x20, 1},
+	{0x127, 0x3f, 0},
+	{0x128, 0x44, 0},
+	{0x129, 0x8c, 0},
+	{0x12A, 0x6c, 0},
+	{0x12B, 0x22, 0},
+	{0x12C, 0xbe, 0},
+	{0x12D, 0x55, 0},
+	{0x12F, 0xc, 0},
+	{0x130, 0xaa, 0},
+	{0x131, 0x2, 0},
+	{0x132, 0, 0},
+	{0x133, 0x10, 0},
+	{0x134, 0x1, 0},
+	{0x135, 0, 0},
+	{0x136, 0, 0},
+	{0x137, 0x80, 0},
+	{0x138, 0x60, 0},
+	{0x139, 0x44, 0},
+	{0x13A, 0x55, 0},
+	{0x13B, 0x1, 0},
+	{0x13C, 0x55, 0},
+	{0x13D, 0x1, 0},
+	{0x13E, 0x5, 0},
+	{0x13F, 0x55, 0},
+	{0x140, 0x55, 0},
+	{0x148, 0, 0},
+	{0x149, 0, 0},
+	{0x14A, 0, 0},
+	{0x14B, 0, 0},
+	{0x14C, 0, 0},
+	{0x14D, 0, 0},
+	{0x14E, 0, 0},
+	{0x14F, 0, 0},
+	{0x150, 0, 0},
+	{0x154, 0xc, 0},
+	{0x155, 0xc, 0},
+	{0x156, 0xc, 0},
+	{0x157, 0, 0},
+	{0x158, 0x2b, 0},
+	{0x159, 0x84, 0},
+	{0x15A, 0x15, 0},
+	{0x15B, 0xf, 0},
+	{0x15C, 0, 0},
+	{0x15D, 0, 0},
+	{0x15E, 0, 1},
+	{0x15F, 0, 1},
+	{0x160, 0, 1},
+	{0x161, 0, 1},
+	{0x162, 0, 1},
+	{0x163, 0, 1},
+	{0x164, 0, 0},
+	{0x165, 0, 0},
+	{0x166, 0, 0},
+	{0x167, 0, 0},
+	{0x168, 0, 0},
+	{0x169, 0, 0},
+	{0x16A, 0, 1},
+	{0x16B, 0, 1},
+	{0x16C, 0, 1},
+	{0x16D, 0, 0},
+	{0x170, 0, 0},
+	{0x171, 0x77, 0},
+	{0x172, 0x77, 0},
+	{0x173, 0x77, 0},
+	{0x174, 0x77, 0},
+	{0x175, 0, 0},
+	{0x176, 0x3, 0},
+	{0x177, 0x37, 0},
+	{0x178, 0x3, 0},
+	{0x179, 0, 0},
+	{0x17B, 0x21, 0},
+	{0x17C, 0, 0},
+	{0x17D, 0xaa, 0},
+	{0x17E, 0, 0},
+	{0x190, 0, 0},
+	{0x191, 0x77, 0},
+	{0x192, 0x77, 0},
+	{0x193, 0x77, 0},
+	{0x194, 0x77, 0},
+	{0x195, 0, 0},
+	{0x196, 0x3, 0},
+	{0x197, 0x37, 0},
+	{0x198, 0x3, 0},
+	{0x199, 0, 0},
+	{0x19B, 0x21, 0},
+	{0x19C, 0, 0},
+	{0x19D, 0xaa, 0},
+	{0x19E, 0, 0},
+	{0x1A1, 0x2, 0},
+	{0x1A2, 0xf, 0},
+	{0x1A3, 0xf, 0},
+	{0x1A4, 0, 1},
+	{0x1A5, 0, 1},
+	{0x1A6, 0, 1},
+	{0x1A7, 0x2, 0},
+	{0x1A8, 0xf, 0},
+	{0x1A9, 0xf, 0},
+	{0x1AA, 0, 1},
+	{0x1AB, 0, 1},
+	{0x1AC, 0, 1},
+	{0x1AD, 0x84, 0},
+	{0x1AE, 0x60, 0},
+	{0x1AF, 0x47, 0},
+	{0x1B0, 0x47, 0},
+	{0x1B1, 0, 0},
+	{0x1B2, 0, 0},
+	{0x1B3, 0, 0},
+	{0x1B4, 0, 0},
+	{0x1B5, 0, 0},
+	{0x1B6, 0, 0},
+	{0x1B7, 0xc, 1},
+	{0x1B8, 0, 0},
+	{0x1B9, 0, 0},
+	{0x1BA, 0, 0},
+	{0x1BB, 0, 0},
+	{0x1BC, 0, 0},
+	{0x1BD, 0, 0},
+	{0x1BE, 0, 0},
+	{0x1BF, 0, 0},
+	{0x1C0, 0, 0},
+	{0x1C1, 0x1, 1},
+	{0x1C2, 0x80, 1},
+	{0x1C3, 0, 0},
+	{0x1C4, 0, 0},
+	{0x1C5, 0, 0},
+	{0x1C6, 0, 0},
+	{0x1C7, 0, 0},
+	{0x1C8, 0, 0},
+	{0x1C9, 0, 0},
+	{0x1CA, 0, 0},
+	{0xFFFF, 0, 0}
+};
+
+static struct radio_20xx_regs regs_2057_rev5v1[] = {
+	{0x00, 0x15, 1},
+	{0x01, 0x57, 1},
+	{0x02, 0x20, 1},
+	{0x03, 0x1f, 0},
+	{0x04, 0x4, 0},
+	{0x05, 0x2, 0},
+	{0x06, 0x1, 0},
+	{0x07, 0x1, 0},
+	{0x08, 0x1, 0},
+	{0x09, 0x69, 0},
+	{0x0A, 0x66, 0},
+	{0x0B, 0x6, 0},
+	{0x0C, 0x18, 0},
+	{0x0D, 0x3, 0},
+	{0x0E, 0x20, 0},
+	{0x0F, 0x20, 0},
+	{0x10, 0, 0},
+	{0x11, 0x7c, 0},
+	{0x12, 0x42, 0},
+	{0x13, 0xbd, 0},
+	{0x14, 0x7, 0},
+	{0x15, 0x87, 0},
+	{0x16, 0x8, 0},
+	{0x17, 0x17, 0},
+	{0x18, 0x7, 0},
+	{0x19, 0, 0},
+	{0x1A, 0x2, 0},
+	{0x1B, 0x13, 0},
+	{0x1C, 0x3e, 0},
+	{0x1D, 0x3e, 0},
+	{0x1E, 0x96, 0},
+	{0x1F, 0x4, 0},
+	{0x20, 0, 0},
+	{0x21, 0, 0},
+	{0x22, 0x17, 0},
+	{0x23, 0x6, 1},
+	{0x24, 0x1, 0},
+	{0x25, 0x6, 0},
+	{0x26, 0x4, 0},
+	{0x27, 0xd, 0},
+	{0x28, 0xd, 0},
+	{0x29, 0x30, 0},
+	{0x2A, 0x32, 0},
+	{0x2B, 0x8, 0},
+	{0x2C, 0x1c, 0},
+	{0x2D, 0x2, 0},
+	{0x2E, 0x4, 0},
+	{0x2F, 0x7f, 0},
+	{0x30, 0x27, 0},
+	{0x31, 0, 1},
+	{0x32, 0, 1},
+	{0x33, 0, 1},
+	{0x34, 0, 0},
+	{0x35, 0x20, 0},
+	{0x36, 0x18, 0},
+	{0x37, 0x7, 0},
+	{0x38, 0x66, 0},
+	{0x39, 0x66, 0},
+	{0x3C, 0xff, 0},
+	{0x3D, 0xff, 0},
+	{0x40, 0x16, 0},
+	{0x41, 0x7, 0},
+	{0x45, 0x3, 0},
+	{0x46, 0x1, 0},
+	{0x47, 0x7, 0},
+	{0x4B, 0x66, 0},
+	{0x4C, 0x66, 0},
+	{0x4D, 0, 0},
+	{0x4E, 0x4, 0},
+	{0x4F, 0xc, 0},
+	{0x50, 0, 0},
+	{0x51, 0x70, 1},
+	{0x56, 0x7, 0},
+	{0x57, 0, 0},
+	{0x58, 0, 0},
+	{0x59, 0x88, 1},
+	{0x5A, 0, 0},
+	{0x5B, 0x1f, 0},
+	{0x5C, 0x20, 1},
+	{0x5D, 0x1, 0},
+	{0x5E, 0x30, 0},
+	{0x5F, 0x70, 0},
+	{0x60, 0, 0},
+	{0x61, 0, 0},
+	{0x62, 0x33, 1},
+	{0x63, 0xf, 1},
+	{0x64, 0xf, 1},
+	{0x65, 0, 0},
+	{0x66, 0x11, 0},
+	{0x80, 0x3c, 0},
+	{0x81, 0x1, 1},
+	{0x82, 0xa, 0},
+	{0x85, 0, 0},
+	{0x86, 0x40, 0},
+	{0x87, 0x40, 0},
+	{0x88, 0x88, 0},
+	{0x89, 0x10, 0},
+	{0x8A, 0xf0, 0},
+	{0x8B, 0x10, 0},
+	{0x8C, 0xf0, 0},
+	{0x8F, 0x10, 0},
+	{0x90, 0x55, 0},
+	{0x91, 0x3f, 1},
+	{0x92, 0x36, 1},
+	{0x93, 0, 0},
+	{0x94, 0, 0},
+	{0x95, 0, 0},
+	{0x96, 0x87, 0},
+	{0x97, 0x11, 0},
+	{0x98, 0, 0},
+	{0x99, 0x33, 0},
+	{0x9A, 0x88, 0},
+	{0xA1, 0x20, 1},
+	{0xA2, 0x3f, 0},
+	{0xA3, 0x44, 0},
+	{0xA4, 0x8c, 0},
+	{0xA5, 0x6c, 0},
+	{0xA6, 0x22, 0},
+	{0xA7, 0xbe, 0},
+	{0xA8, 0x55, 0},
+	{0xAA, 0xc, 0},
+	{0xAB, 0xaa, 0},
+	{0xAC, 0x2, 0},
+	{0xAD, 0, 0},
+	{0xAE, 0x10, 0},
+	{0xAF, 0x1, 0},
+	{0xB0, 0, 0},
+	{0xB1, 0, 0},
+	{0xB2, 0x80, 0},
+	{0xB3, 0x60, 0},
+	{0xB4, 0x44, 0},
+	{0xB5, 0x55, 0},
+	{0xB6, 0x1, 0},
+	{0xB7, 0x55, 0},
+	{0xB8, 0x1, 0},
+	{0xB9, 0x5, 0},
+	{0xBA, 0x55, 0},
+	{0xBB, 0x55, 0},
+	{0xC3, 0, 0},
+	{0xC4, 0, 0},
+	{0xC5, 0, 0},
+	{0xC6, 0, 0},
+	{0xC7, 0, 0},
+	{0xC8, 0, 0},
+	{0xC9, 0x1, 1},
+	{0xCA, 0, 0},
+	{0xCB, 0, 0},
+	{0xCD, 0, 0},
+	{0xCE, 0x5e, 0},
+	{0xCF, 0xc, 0},
+	{0xD0, 0xc, 0},
+	{0xD1, 0xc, 0},
+	{0xD2, 0, 0},
+	{0xD3, 0x2b, 0},
+	{0xD4, 0xc, 0},
+	{0xD5, 0, 0},
+	{0xD6, 0x70, 1},
+	{0xDB, 0x7, 0},
+	{0xDC, 0, 0},
+	{0xDD, 0, 0},
+	{0xDE, 0x88, 1},
+	{0xDF, 0, 0},
+	{0xE0, 0x1f, 0},
+	{0xE1, 0x20, 1},
+	{0xE2, 0x1, 0},
+	{0xE3, 0x30, 0},
+	{0xE4, 0x70, 0},
+	{0xE5, 0, 0},
+	{0xE6, 0, 0},
+	{0xE7, 0x33, 0},
+	{0xE8, 0xf, 1},
+	{0xE9, 0xf, 1},
+	{0xEA, 0, 0},
+	{0xEB, 0x11, 0},
+	{0x105, 0x3c, 0},
+	{0x106, 0x1, 1},
+	{0x107, 0xa, 0},
+	{0x10A, 0, 0},
+	{0x10B, 0x40, 0},
+	{0x10C, 0x40, 0},
+	{0x10D, 0x88, 0},
+	{0x10E, 0x10, 0},
+	{0x10F, 0xf0, 0},
+	{0x110, 0x10, 0},
+	{0x111, 0xf0, 0},
+	{0x114, 0x10, 0},
+	{0x115, 0x55, 0},
+	{0x116, 0x3f, 1},
+	{0x117, 0x36, 1},
+	{0x118, 0, 0},
+	{0x119, 0, 0},
+	{0x11A, 0, 0},
+	{0x11B, 0x87, 0},
+	{0x11C, 0x11, 0},
+	{0x11D, 0, 0},
+	{0x11E, 0x33, 0},
+	{0x11F, 0x88, 0},
+	{0x126, 0x20, 1},
+	{0x127, 0x3f, 0},
+	{0x128, 0x44, 0},
+	{0x129, 0x8c, 0},
+	{0x12A, 0x6c, 0},
+	{0x12B, 0x22, 0},
+	{0x12C, 0xbe, 0},
+	{0x12D, 0x55, 0},
+	{0x12F, 0xc, 0},
+	{0x130, 0xaa, 0},
+	{0x131, 0x2, 0},
+	{0x132, 0, 0},
+	{0x133, 0x10, 0},
+	{0x134, 0x1, 0},
+	{0x135, 0, 0},
+	{0x136, 0, 0},
+	{0x137, 0x80, 0},
+	{0x138, 0x60, 0},
+	{0x139, 0x44, 0},
+	{0x13A, 0x55, 0},
+	{0x13B, 0x1, 0},
+	{0x13C, 0x55, 0},
+	{0x13D, 0x1, 0},
+	{0x13E, 0x5, 0},
+	{0x13F, 0x55, 0},
+	{0x140, 0x55, 0},
+	{0x148, 0, 0},
+	{0x149, 0, 0},
+	{0x14A, 0, 0},
+	{0x14B, 0, 0},
+	{0x14C, 0, 0},
+	{0x14D, 0, 0},
+	{0x14E, 0x1, 1},
+	{0x14F, 0, 0},
+	{0x150, 0, 0},
+	{0x154, 0xc, 0},
+	{0x155, 0xc, 0},
+	{0x156, 0xc, 0},
+	{0x157, 0, 0},
+	{0x158, 0x2b, 0},
+	{0x159, 0x84, 0},
+	{0x15A, 0x15, 0},
+	{0x15B, 0xf, 0},
+	{0x15C, 0, 0},
+	{0x15D, 0, 0},
+	{0x15E, 0, 1},
+	{0x15F, 0, 1},
+	{0x160, 0, 1},
+	{0x161, 0, 1},
+	{0x162, 0, 1},
+	{0x163, 0, 1},
+	{0x164, 0, 0},
+	{0x165, 0, 0},
+	{0x166, 0, 0},
+	{0x167, 0, 0},
+	{0x168, 0, 0},
+	{0x169, 0, 0},
+	{0x16A, 0, 1},
+	{0x16B, 0, 1},
+	{0x16C, 0, 1},
+	{0x16D, 0, 0},
+	{0x170, 0, 0},
+	{0x171, 0x77, 0},
+	{0x172, 0x77, 0},
+	{0x173, 0x77, 0},
+	{0x174, 0x77, 0},
+	{0x175, 0, 0},
+	{0x176, 0x3, 0},
+	{0x177, 0x37, 0},
+	{0x178, 0x3, 0},
+	{0x179, 0, 0},
+	{0x17B, 0x21, 0},
+	{0x17C, 0, 0},
+	{0x17D, 0xaa, 0},
+	{0x17E, 0, 0},
+	{0x190, 0, 0},
+	{0x191, 0x77, 0},
+	{0x192, 0x77, 0},
+	{0x193, 0x77, 0},
+	{0x194, 0x77, 0},
+	{0x195, 0, 0},
+	{0x196, 0x3, 0},
+	{0x197, 0x37, 0},
+	{0x198, 0x3, 0},
+	{0x199, 0, 0},
+	{0x19B, 0x21, 0},
+	{0x19C, 0, 0},
+	{0x19D, 0xaa, 0},
+	{0x19E, 0, 0},
+	{0x1A1, 0x2, 0},
+	{0x1A2, 0xf, 0},
+	{0x1A3, 0xf, 0},
+	{0x1A4, 0, 1},
+	{0x1A5, 0, 1},
+	{0x1A6, 0, 1},
+	{0x1A7, 0x2, 0},
+	{0x1A8, 0xf, 0},
+	{0x1A9, 0xf, 0},
+	{0x1AA, 0, 1},
+	{0x1AB, 0, 1},
+	{0x1AC, 0, 1},
+	{0x1AD, 0x84, 0},
+	{0x1AE, 0x60, 0},
+	{0x1AF, 0x47, 0},
+	{0x1B0, 0x47, 0},
+	{0x1B1, 0, 0},
+	{0x1B2, 0, 0},
+	{0x1B3, 0, 0},
+	{0x1B4, 0, 0},
+	{0x1B5, 0, 0},
+	{0x1B6, 0, 0},
+	{0x1B7, 0xc, 1},
+	{0x1B8, 0, 0},
+	{0x1B9, 0, 0},
+	{0x1BA, 0, 0},
+	{0x1BB, 0, 0},
+	{0x1BC, 0, 0},
+	{0x1BD, 0, 0},
+	{0x1BE, 0, 0},
+	{0x1BF, 0, 0},
+	{0x1C0, 0, 0},
+	{0x1C1, 0x1, 1},
+	{0x1C2, 0x80, 1},
+	{0x1C3, 0, 0},
+	{0x1C4, 0, 0},
+	{0x1C5, 0, 0},
+	{0x1C6, 0, 0},
+	{0x1C7, 0, 0},
+	{0x1C8, 0, 0},
+	{0x1C9, 0, 0},
+	{0x1CA, 0, 0},
+	{0xFFFF, 0, 0}
+};
+
+static struct radio_20xx_regs regs_2057_rev7[] = {
+	{0x00, 0, 1},
+	{0x01, 0x57, 1},
+	{0x02, 0x20, 1},
+	{0x03, 0x1f, 0},
+	{0x04, 0x4, 0},
+	{0x05, 0x2, 0},
+	{0x06, 0x1, 0},
+	{0x07, 0x1, 0},
+	{0x08, 0x1, 0},
+	{0x09, 0x69, 0},
+	{0x0A, 0x66, 0},
+	{0x0B, 0x6, 0},
+	{0x0C, 0x18, 0},
+	{0x0D, 0x3, 0},
+	{0x0E, 0x20, 0},
+	{0x0F, 0x20, 0},
+	{0x10, 0, 0},
+	{0x11, 0x7c, 0},
+	{0x12, 0x42, 0},
+	{0x13, 0xbd, 0},
+	{0x14, 0x7, 0},
+	{0x15, 0x87, 0},
+	{0x16, 0x8, 0},
+	{0x17, 0x17, 0},
+	{0x18, 0x7, 0},
+	{0x19, 0, 0},
+	{0x1A, 0x2, 0},
+	{0x1B, 0x13, 0},
+	{0x1C, 0x3e, 0},
+	{0x1D, 0x3e, 0},
+	{0x1E, 0x96, 0},
+	{0x1F, 0x4, 0},
+	{0x20, 0, 0},
+	{0x21, 0, 0},
+	{0x22, 0x17, 0},
+	{0x23, 0x6, 0},
+	{0x24, 0x1, 0},
+	{0x25, 0x6, 0},
+	{0x26, 0x4, 0},
+	{0x27, 0xd, 0},
+	{0x28, 0xd, 0},
+	{0x29, 0x30, 0},
+	{0x2A, 0x32, 0},
+	{0x2B, 0x8, 0},
+	{0x2C, 0x1c, 0},
+	{0x2D, 0x2, 0},
+	{0x2E, 0x4, 0},
+	{0x2F, 0x7f, 0},
+	{0x30, 0x27, 0},
+	{0x31, 0, 1},
+	{0x32, 0, 1},
+	{0x33, 0, 1},
+	{0x34, 0, 0},
+	{0x35, 0x20, 0},
+	{0x36, 0x18, 0},
+	{0x37, 0x7, 0},
+	{0x38, 0x66, 0},
+	{0x39, 0x66, 0},
+	{0x3A, 0x66, 0},
+	{0x3B, 0x66, 0},
+	{0x3C, 0xff, 0},
+	{0x3D, 0xff, 0},
+	{0x3E, 0xff, 0},
+	{0x3F, 0xff, 0},
+	{0x40, 0x16, 0},
+	{0x41, 0x7, 0},
+	{0x42, 0x19, 0},
+	{0x43, 0x7, 0},
+	{0x44, 0x6, 0},
+	{0x45, 0x3, 0},
+	{0x46, 0x1, 0},
+	{0x47, 0x7, 0},
+	{0x48, 0x33, 0},
+	{0x49, 0x5, 0},
+	{0x4A, 0x77, 0},
+	{0x4B, 0x66, 0},
+	{0x4C, 0x66, 0},
+	{0x4D, 0, 0},
+	{0x4E, 0x4, 0},
+	{0x4F, 0xc, 0},
+	{0x50, 0, 0},
+	{0x51, 0x70, 1},
+	{0x56, 0x7, 0},
+	{0x57, 0, 0},
+	{0x58, 0, 0},
+	{0x59, 0x88, 1},
+	{0x5A, 0, 0},
+	{0x5B, 0x1f, 0},
+	{0x5C, 0x20, 1},
+	{0x5D, 0x1, 0},
+	{0x5E, 0x30, 0},
+	{0x5F, 0x70, 0},
+	{0x60, 0, 0},
+	{0x61, 0, 0},
+	{0x62, 0x33, 1},
+	{0x63, 0xf, 1},
+	{0x64, 0x13, 1},
+	{0x65, 0, 0},
+	{0x66, 0xee, 1},
+	{0x69, 0, 0},
+	{0x6A, 0x7e, 0},
+	{0x6B, 0x3f, 0},
+	{0x6C, 0x7f, 0},
+	{0x6D, 0x78, 0},
+	{0x6E, 0x58, 1},
+	{0x6F, 0x88, 0},
+	{0x70, 0x8, 0},
+	{0x71, 0xf, 0},
+	{0x72, 0xbc, 0},
+	{0x73, 0x8, 0},
+	{0x74, 0x60, 0},
+	{0x75, 0x13, 1},
+	{0x76, 0x70, 0},
+	{0x77, 0, 0},
+	{0x78, 0, 0},
+	{0x79, 0, 0},
+	{0x7A, 0x33, 0},
+	{0x7B, 0x13, 1},
+	{0x7C, 0x14, 1},
+	{0x7D, 0xee, 1},
+	{0x80, 0x3c, 0},
+	{0x81, 0x1, 1},
+	{0x82, 0xa, 0},
+	{0x83, 0x9d, 0},
+	{0x84, 0xa, 0},
+	{0x85, 0, 0},
+	{0x86, 0x40, 0},
+	{0x87, 0x40, 0},
+	{0x88, 0x88, 0},
+	{0x89, 0x10, 0},
+	{0x8A, 0xf0, 0},
+	{0x8B, 0x10, 0},
+	{0x8C, 0xf0, 0},
+	{0x8D, 0, 0},
+	{0x8E, 0, 0},
+	{0x8F, 0x10, 0},
+	{0x90, 0x55, 0},
+	{0x91, 0x3f, 1},
+	{0x92, 0x36, 1},
+	{0x93, 0, 0},
+	{0x94, 0, 0},
+	{0x95, 0, 0},
+	{0x96, 0x87, 0},
+	{0x97, 0x11, 0},
+	{0x98, 0, 0},
+	{0x99, 0x33, 0},
+	{0x9A, 0x88, 0},
+	{0x9B, 0, 0},
+	{0x9C, 0x87, 0},
+	{0x9D, 0x11, 0},
+	{0x9E, 0, 0},
+	{0x9F, 0x33, 0},
+	{0xA0, 0x88, 0},
+	{0xA1, 0x20, 1},
+	{0xA2, 0x3f, 0},
+	{0xA3, 0x44, 0},
+	{0xA4, 0x8c, 0},
+	{0xA5, 0x6c, 0},
+	{0xA6, 0x22, 0},
+	{0xA7, 0xbe, 0},
+	{0xA8, 0x55, 0},
+	{0xAA, 0xc, 0},
+	{0xAB, 0xaa, 0},
+	{0xAC, 0x2, 0},
+	{0xAD, 0, 0},
+	{0xAE, 0x10, 0},
+	{0xAF, 0x1, 0},
+	{0xB0, 0, 0},
+	{0xB1, 0, 0},
+	{0xB2, 0x80, 0},
+	{0xB3, 0x60, 0},
+	{0xB4, 0x44, 0},
+	{0xB5, 0x55, 0},
+	{0xB6, 0x1, 0},
+	{0xB7, 0x55, 0},
+	{0xB8, 0x1, 0},
+	{0xB9, 0x5, 0},
+	{0xBA, 0x55, 0},
+	{0xBB, 0x55, 0},
+	{0xC1, 0, 0},
+	{0xC2, 0, 0},
+	{0xC3, 0, 0},
+	{0xC4, 0, 0},
+	{0xC5, 0, 0},
+	{0xC6, 0, 0},
+	{0xC7, 0, 0},
+	{0xC8, 0, 0},
+	{0xC9, 0, 0},
+	{0xCA, 0, 0},
+	{0xCB, 0, 0},
+	{0xCC, 0, 0},
+	{0xCD, 0, 0},
+	{0xCE, 0x5e, 0},
+	{0xCF, 0xc, 0},
+	{0xD0, 0xc, 0},
+	{0xD1, 0xc, 0},
+	{0xD2, 0, 0},
+	{0xD3, 0x2b, 0},
+	{0xD4, 0xc, 0},
+	{0xD5, 0, 0},
+	{0xD6, 0x70, 1},
+	{0xDB, 0x7, 0},
+	{0xDC, 0, 0},
+	{0xDD, 0, 0},
+	{0xDE, 0x88, 1},
+	{0xDF, 0, 0},
+	{0xE0, 0x1f, 0},
+	{0xE1, 0x20, 1},
+	{0xE2, 0x1, 0},
+	{0xE3, 0x30, 0},
+	{0xE4, 0x70, 0},
+	{0xE5, 0, 0},
+	{0xE6, 0, 0},
+	{0xE7, 0x33, 0},
+	{0xE8, 0xf, 1},
+	{0xE9, 0x13, 1},
+	{0xEA, 0, 0},
+	{0xEB, 0xee, 1},
+	{0xEE, 0, 0},
+	{0xEF, 0x7e, 0},
+	{0xF0, 0x3f, 0},
+	{0xF1, 0x7f, 0},
+	{0xF2, 0x78, 0},
+	{0xF3, 0x58, 1},
+	{0xF4, 0x88, 0},
+	{0xF5, 0x8, 0},
+	{0xF6, 0xf, 0},
+	{0xF7, 0xbc, 0},
+	{0xF8, 0x8, 0},
+	{0xF9, 0x60, 0},
+	{0xFA, 0x13, 1},
+	{0xFB, 0x70, 0},
+	{0xFC, 0, 0},
+	{0xFD, 0, 0},
+	{0xFE, 0, 0},
+	{0xFF, 0x33, 0},
+	{0x100, 0x13, 1},
+	{0x101, 0x14, 1},
+	{0x102, 0xee, 1},
+	{0x105, 0x3c, 0},
+	{0x106, 0x1, 1},
+	{0x107, 0xa, 0},
+	{0x108, 0x9d, 0},
+	{0x109, 0xa, 0},
+	{0x10A, 0, 0},
+	{0x10B, 0x40, 0},
+	{0x10C, 0x40, 0},
+	{0x10D, 0x88, 0},
+	{0x10E, 0x10, 0},
+	{0x10F, 0xf0, 0},
+	{0x110, 0x10, 0},
+	{0x111, 0xf0, 0},
+	{0x112, 0, 0},
+	{0x113, 0, 0},
+	{0x114, 0x10, 0},
+	{0x115, 0x55, 0},
+	{0x116, 0x3f, 1},
+	{0x117, 0x36, 1},
+	{0x118, 0, 0},
+	{0x119, 0, 0},
+	{0x11A, 0, 0},
+	{0x11B, 0x87, 0},
+	{0x11C, 0x11, 0},
+	{0x11D, 0, 0},
+	{0x11E, 0x33, 0},
+	{0x11F, 0x88, 0},
+	{0x120, 0, 0},
+	{0x121, 0x87, 0},
+	{0x122, 0x11, 0},
+	{0x123, 0, 0},
+	{0x124, 0x33, 0},
+	{0x125, 0x88, 0},
+	{0x126, 0x20, 1},
+	{0x127, 0x3f, 0},
+	{0x128, 0x44, 0},
+	{0x129, 0x8c, 0},
+	{0x12A, 0x6c, 0},
+	{0x12B, 0x22, 0},
+	{0x12C, 0xbe, 0},
+	{0x12D, 0x55, 0},
+	{0x12F, 0xc, 0},
+	{0x130, 0xaa, 0},
+	{0x131, 0x2, 0},
+	{0x132, 0, 0},
+	{0x133, 0x10, 0},
+	{0x134, 0x1, 0},
+	{0x135, 0, 0},
+	{0x136, 0, 0},
+	{0x137, 0x80, 0},
+	{0x138, 0x60, 0},
+	{0x139, 0x44, 0},
+	{0x13A, 0x55, 0},
+	{0x13B, 0x1, 0},
+	{0x13C, 0x55, 0},
+	{0x13D, 0x1, 0},
+	{0x13E, 0x5, 0},
+	{0x13F, 0x55, 0},
+	{0x140, 0x55, 0},
+	{0x146, 0, 0},
+	{0x147, 0, 0},
+	{0x148, 0, 0},
+	{0x149, 0, 0},
+	{0x14A, 0, 0},
+	{0x14B, 0, 0},
+	{0x14C, 0, 0},
+	{0x14D, 0, 0},
+	{0x14E, 0, 0},
+	{0x14F, 0, 0},
+	{0x150, 0, 0},
+	{0x151, 0, 0},
+	{0x154, 0xc, 0},
+	{0x155, 0xc, 0},
+	{0x156, 0xc, 0},
+	{0x157, 0, 0},
+	{0x158, 0x2b, 0},
+	{0x159, 0x84, 0},
+	{0x15A, 0x15, 0},
+	{0x15B, 0xf, 0},
+	{0x15C, 0, 0},
+	{0x15D, 0, 0},
+	{0x15E, 0, 1},
+	{0x15F, 0, 1},
+	{0x160, 0, 1},
+	{0x161, 0, 1},
+	{0x162, 0, 1},
+	{0x163, 0, 1},
+	{0x164, 0, 0},
+	{0x165, 0, 0},
+	{0x166, 0, 0},
+	{0x167, 0, 0},
+	{0x168, 0, 0},
+	{0x169, 0, 0},
+	{0x16A, 0, 1},
+	{0x16B, 0, 1},
+	{0x16C, 0, 1},
+	{0x16D, 0, 0},
+	{0x170, 0, 0},
+	{0x171, 0x77, 0},
+	{0x172, 0x77, 0},
+	{0x173, 0x77, 0},
+	{0x174, 0x77, 0},
+	{0x175, 0, 0},
+	{0x176, 0x3, 0},
+	{0x177, 0x37, 0},
+	{0x178, 0x3, 0},
+	{0x179, 0, 0},
+	{0x17A, 0x21, 0},
+	{0x17B, 0x21, 0},
+	{0x17C, 0, 0},
+	{0x17D, 0xaa, 0},
+	{0x17E, 0, 0},
+	{0x17F, 0xaa, 0},
+	{0x180, 0, 0},
+	{0x190, 0, 0},
+	{0x191, 0x77, 0},
+	{0x192, 0x77, 0},
+	{0x193, 0x77, 0},
+	{0x194, 0x77, 0},
+	{0x195, 0, 0},
+	{0x196, 0x3, 0},
+	{0x197, 0x37, 0},
+	{0x198, 0x3, 0},
+	{0x199, 0, 0},
+	{0x19A, 0x21, 0},
+	{0x19B, 0x21, 0},
+	{0x19C, 0, 0},
+	{0x19D, 0xaa, 0},
+	{0x19E, 0, 0},
+	{0x19F, 0xaa, 0},
+	{0x1A0, 0, 0},
+	{0x1A1, 0x2, 0},
+	{0x1A2, 0xf, 0},
+	{0x1A3, 0xf, 0},
+	{0x1A4, 0, 1},
+	{0x1A5, 0, 1},
+	{0x1A6, 0, 1},
+	{0x1A7, 0x2, 0},
+	{0x1A8, 0xf, 0},
+	{0x1A9, 0xf, 0},
+	{0x1AA, 0, 1},
+	{0x1AB, 0, 1},
+	{0x1AC, 0, 1},
+	{0x1AD, 0x84, 0},
+	{0x1AE, 0x60, 0},
+	{0x1AF, 0x47, 0},
+	{0x1B0, 0x47, 0},
+	{0x1B1, 0, 0},
+	{0x1B2, 0, 0},
+	{0x1B3, 0, 0},
+	{0x1B4, 0, 0},
+	{0x1B5, 0, 0},
+	{0x1B6, 0, 0},
+	{0x1B7, 0x5, 1},
+	{0x1B8, 0, 0},
+	{0x1B9, 0, 0},
+	{0x1BA, 0, 0},
+	{0x1BB, 0, 0},
+	{0x1BC, 0, 0},
+	{0x1BD, 0, 0},
+	{0x1BE, 0, 0},
+	{0x1BF, 0, 0},
+	{0x1C0, 0, 0},
+	{0x1C1, 0, 0},
+	{0x1C2, 0xa0, 1},
+	{0x1C3, 0, 0},
+	{0x1C4, 0, 0},
+	{0x1C5, 0, 0},
+	{0x1C6, 0, 0},
+	{0x1C7, 0, 0},
+	{0x1C8, 0, 0},
+	{0x1C9, 0, 0},
+	{0x1CA, 0, 0},
+	{0xFFFF, 0, 0}
+};
+
+static struct radio_20xx_regs regs_2057_rev8[] = {
+	{0x00, 0x8, 1},
+	{0x01, 0x57, 1},
+	{0x02, 0x20, 1},
+	{0x03, 0x1f, 0},
+	{0x04, 0x4, 0},
+	{0x05, 0x2, 0},
+	{0x06, 0x1, 0},
+	{0x07, 0x1, 0},
+	{0x08, 0x1, 0},
+	{0x09, 0x69, 0},
+	{0x0A, 0x66, 0},
+	{0x0B, 0x6, 0},
+	{0x0C, 0x18, 0},
+	{0x0D, 0x3, 0},
+	{0x0E, 0x20, 0},
+	{0x0F, 0x20, 0},
+	{0x10, 0, 0},
+	{0x11, 0x7c, 0},
+	{0x12, 0x42, 0},
+	{0x13, 0xbd, 0},
+	{0x14, 0x7, 0},
+	{0x15, 0x87, 0},
+	{0x16, 0x8, 0},
+	{0x17, 0x17, 0},
+	{0x18, 0x7, 0},
+	{0x19, 0, 0},
+	{0x1A, 0x2, 0},
+	{0x1B, 0x13, 0},
+	{0x1C, 0x3e, 0},
+	{0x1D, 0x3e, 0},
+	{0x1E, 0x96, 0},
+	{0x1F, 0x4, 0},
+	{0x20, 0, 0},
+	{0x21, 0, 0},
+	{0x22, 0x17, 0},
+	{0x23, 0x6, 0},
+	{0x24, 0x1, 0},
+	{0x25, 0x6, 0},
+	{0x26, 0x4, 0},
+	{0x27, 0xd, 0},
+	{0x28, 0xd, 0},
+	{0x29, 0x30, 0},
+	{0x2A, 0x32, 0},
+	{0x2B, 0x8, 0},
+	{0x2C, 0x1c, 0},
+	{0x2D, 0x2, 0},
+	{0x2E, 0x4, 0},
+	{0x2F, 0x7f, 0},
+	{0x30, 0x27, 0},
+	{0x31, 0, 1},
+	{0x32, 0, 1},
+	{0x33, 0, 1},
+	{0x34, 0, 0},
+	{0x35, 0x20, 0},
+	{0x36, 0x18, 0},
+	{0x37, 0x7, 0},
+	{0x38, 0x66, 0},
+	{0x39, 0x66, 0},
+	{0x3A, 0x66, 0},
+	{0x3B, 0x66, 0},
+	{0x3C, 0xff, 0},
+	{0x3D, 0xff, 0},
+	{0x3E, 0xff, 0},
+	{0x3F, 0xff, 0},
+	{0x40, 0x16, 0},
+	{0x41, 0x7, 0},
+	{0x42, 0x19, 0},
+	{0x43, 0x7, 0},
+	{0x44, 0x6, 0},
+	{0x45, 0x3, 0},
+	{0x46, 0x1, 0},
+	{0x47, 0x7, 0},
+	{0x48, 0x33, 0},
+	{0x49, 0x5, 0},
+	{0x4A, 0x77, 0},
+	{0x4B, 0x66, 0},
+	{0x4C, 0x66, 0},
+	{0x4D, 0, 0},
+	{0x4E, 0x4, 0},
+	{0x4F, 0xc, 0},
+	{0x50, 0, 0},
+	{0x51, 0x70, 1},
+	{0x56, 0x7, 0},
+	{0x57, 0, 0},
+	{0x58, 0, 0},
+	{0x59, 0x88, 1},
+	{0x5A, 0, 0},
+	{0x5B, 0x1f, 0},
+	{0x5C, 0x20, 1},
+	{0x5D, 0x1, 0},
+	{0x5E, 0x30, 0},
+	{0x5F, 0x70, 0},
+	{0x60, 0, 0},
+	{0x61, 0, 0},
+	{0x62, 0x33, 1},
+	{0x63, 0xf, 1},
+	{0x64, 0xf, 1},
+	{0x65, 0, 0},
+	{0x66, 0x11, 0},
+	{0x69, 0, 0},
+	{0x6A, 0x7e, 0},
+	{0x6B, 0x3f, 0},
+	{0x6C, 0x7f, 0},
+	{0x6D, 0x78, 0},
+	{0x6E, 0x58, 1},
+	{0x6F, 0x88, 0},
+	{0x70, 0x8, 0},
+	{0x71, 0xf, 0},
+	{0x72, 0xbc, 0},
+	{0x73, 0x8, 0},
+	{0x74, 0x60, 0},
+	{0x75, 0x13, 1},
+	{0x76, 0x70, 0},
+	{0x77, 0, 0},
+	{0x78, 0, 0},
+	{0x79, 0, 0},
+	{0x7A, 0x33, 0},
+	{0x7B, 0x13, 1},
+	{0x7C, 0xf, 1},
+	{0x7D, 0xee, 1},
+	{0x80, 0x3c, 0},
+	{0x81, 0x1, 1},
+	{0x82, 0xa, 0},
+	{0x83, 0x9d, 0},
+	{0x84, 0xa, 0},
+	{0x85, 0, 0},
+	{0x86, 0x40, 0},
+	{0x87, 0x40, 0},
+	{0x88, 0x88, 0},
+	{0x89, 0x10, 0},
+	{0x8A, 0xf0, 0},
+	{0x8B, 0x10, 0},
+	{0x8C, 0xf0, 0},
+	{0x8D, 0, 0},
+	{0x8E, 0, 0},
+	{0x8F, 0x10, 0},
+	{0x90, 0x55, 0},
+	{0x91, 0x3f, 1},
+	{0x92, 0x36, 1},
+	{0x93, 0, 0},
+	{0x94, 0, 0},
+	{0x95, 0, 0},
+	{0x96, 0x87, 0},
+	{0x97, 0x11, 0},
+	{0x98, 0, 0},
+	{0x99, 0x33, 0},
+	{0x9A, 0x88, 0},
+	{0x9B, 0, 0},
+	{0x9C, 0x87, 0},
+	{0x9D, 0x11, 0},
+	{0x9E, 0, 0},
+	{0x9F, 0x33, 0},
+	{0xA0, 0x88, 0},
+	{0xA1, 0x20, 1},
+	{0xA2, 0x3f, 0},
+	{0xA3, 0x44, 0},
+	{0xA4, 0x8c, 0},
+	{0xA5, 0x6c, 0},
+	{0xA6, 0x22, 0},
+	{0xA7, 0xbe, 0},
+	{0xA8, 0x55, 0},
+	{0xAA, 0xc, 0},
+	{0xAB, 0xaa, 0},
+	{0xAC, 0x2, 0},
+	{0xAD, 0, 0},
+	{0xAE, 0x10, 0},
+	{0xAF, 0x1, 0},
+	{0xB0, 0, 0},
+	{0xB1, 0, 0},
+	{0xB2, 0x80, 0},
+	{0xB3, 0x60, 0},
+	{0xB4, 0x44, 0},
+	{0xB5, 0x55, 0},
+	{0xB6, 0x1, 0},
+	{0xB7, 0x55, 0},
+	{0xB8, 0x1, 0},
+	{0xB9, 0x5, 0},
+	{0xBA, 0x55, 0},
+	{0xBB, 0x55, 0},
+	{0xC1, 0, 0},
+	{0xC2, 0, 0},
+	{0xC3, 0, 0},
+	{0xC4, 0, 0},
+	{0xC5, 0, 0},
+	{0xC6, 0, 0},
+	{0xC7, 0, 0},
+	{0xC8, 0, 0},
+	{0xC9, 0x1, 1},
+	{0xCA, 0, 0},
+	{0xCB, 0, 0},
+	{0xCC, 0, 0},
+	{0xCD, 0, 0},
+	{0xCE, 0x5e, 0},
+	{0xCF, 0xc, 0},
+	{0xD0, 0xc, 0},
+	{0xD1, 0xc, 0},
+	{0xD2, 0, 0},
+	{0xD3, 0x2b, 0},
+	{0xD4, 0xc, 0},
+	{0xD5, 0, 0},
+	{0xD6, 0x70, 1},
+	{0xDB, 0x7, 0},
+	{0xDC, 0, 0},
+	{0xDD, 0, 0},
+	{0xDE, 0x88, 1},
+	{0xDF, 0, 0},
+	{0xE0, 0x1f, 0},
+	{0xE1, 0x20, 1},
+	{0xE2, 0x1, 0},
+	{0xE3, 0x30, 0},
+	{0xE4, 0x70, 0},
+	{0xE5, 0, 0},
+	{0xE6, 0, 0},
+	{0xE7, 0x33, 0},
+	{0xE8, 0xf, 1},
+	{0xE9, 0xf, 1},
+	{0xEA, 0, 0},
+	{0xEB, 0x11, 0},
+	{0xEE, 0, 0},
+	{0xEF, 0x7e, 0},
+	{0xF0, 0x3f, 0},
+	{0xF1, 0x7f, 0},
+	{0xF2, 0x78, 0},
+	{0xF3, 0x58, 1},
+	{0xF4, 0x88, 0},
+	{0xF5, 0x8, 0},
+	{0xF6, 0xf, 0},
+	{0xF7, 0xbc, 0},
+	{0xF8, 0x8, 0},
+	{0xF9, 0x60, 0},
+	{0xFA, 0x13, 1},
+	{0xFB, 0x70, 0},
+	{0xFC, 0, 0},
+	{0xFD, 0, 0},
+	{0xFE, 0, 0},
+	{0xFF, 0x33, 0},
+	{0x100, 0x13, 1},
+	{0x101, 0xf, 1},
+	{0x102, 0xee, 1},
+	{0x105, 0x3c, 0},
+	{0x106, 0x1, 1},
+	{0x107, 0xa, 0},
+	{0x108, 0x9d, 0},
+	{0x109, 0xa, 0},
+	{0x10A, 0, 0},
+	{0x10B, 0x40, 0},
+	{0x10C, 0x40, 0},
+	{0x10D, 0x88, 0},
+	{0x10E, 0x10, 0},
+	{0x10F, 0xf0, 0},
+	{0x110, 0x10, 0},
+	{0x111, 0xf0, 0},
+	{0x112, 0, 0},
+	{0x113, 0, 0},
+	{0x114, 0x10, 0},
+	{0x115, 0x55, 0},
+	{0x116, 0x3f, 1},
+	{0x117, 0x36, 1},
+	{0x118, 0, 0},
+	{0x119, 0, 0},
+	{0x11A, 0, 0},
+	{0x11B, 0x87, 0},
+	{0x11C, 0x11, 0},
+	{0x11D, 0, 0},
+	{0x11E, 0x33, 0},
+	{0x11F, 0x88, 0},
+	{0x120, 0, 0},
+	{0x121, 0x87, 0},
+	{0x122, 0x11, 0},
+	{0x123, 0, 0},
+	{0x124, 0x33, 0},
+	{0x125, 0x88, 0},
+	{0x126, 0x20, 1},
+	{0x127, 0x3f, 0},
+	{0x128, 0x44, 0},
+	{0x129, 0x8c, 0},
+	{0x12A, 0x6c, 0},
+	{0x12B, 0x22, 0},
+	{0x12C, 0xbe, 0},
+	{0x12D, 0x55, 0},
+	{0x12F, 0xc, 0},
+	{0x130, 0xaa, 0},
+	{0x131, 0x2, 0},
+	{0x132, 0, 0},
+	{0x133, 0x10, 0},
+	{0x134, 0x1, 0},
+	{0x135, 0, 0},
+	{0x136, 0, 0},
+	{0x137, 0x80, 0},
+	{0x138, 0x60, 0},
+	{0x139, 0x44, 0},
+	{0x13A, 0x55, 0},
+	{0x13B, 0x1, 0},
+	{0x13C, 0x55, 0},
+	{0x13D, 0x1, 0},
+	{0x13E, 0x5, 0},
+	{0x13F, 0x55, 0},
+	{0x140, 0x55, 0},
+	{0x146, 0, 0},
+	{0x147, 0, 0},
+	{0x148, 0, 0},
+	{0x149, 0, 0},
+	{0x14A, 0, 0},
+	{0x14B, 0, 0},
+	{0x14C, 0, 0},
+	{0x14D, 0, 0},
+	{0x14E, 0x1, 1},
+	{0x14F, 0, 0},
+	{0x150, 0, 0},
+	{0x151, 0, 0},
+	{0x154, 0xc, 0},
+	{0x155, 0xc, 0},
+	{0x156, 0xc, 0},
+	{0x157, 0, 0},
+	{0x158, 0x2b, 0},
+	{0x159, 0x84, 0},
+	{0x15A, 0x15, 0},
+	{0x15B, 0xf, 0},
+	{0x15C, 0, 0},
+	{0x15D, 0, 0},
+	{0x15E, 0, 1},
+	{0x15F, 0, 1},
+	{0x160, 0, 1},
+	{0x161, 0, 1},
+	{0x162, 0, 1},
+	{0x163, 0, 1},
+	{0x164, 0, 0},
+	{0x165, 0, 0},
+	{0x166, 0, 0},
+	{0x167, 0, 0},
+	{0x168, 0, 0},
+	{0x169, 0, 0},
+	{0x16A, 0, 1},
+	{0x16B, 0, 1},
+	{0x16C, 0, 1},
+	{0x16D, 0, 0},
+	{0x170, 0, 0},
+	{0x171, 0x77, 0},
+	{0x172, 0x77, 0},
+	{0x173, 0x77, 0},
+	{0x174, 0x77, 0},
+	{0x175, 0, 0},
+	{0x176, 0x3, 0},
+	{0x177, 0x37, 0},
+	{0x178, 0x3, 0},
+	{0x179, 0, 0},
+	{0x17A, 0x21, 0},
+	{0x17B, 0x21, 0},
+	{0x17C, 0, 0},
+	{0x17D, 0xaa, 0},
+	{0x17E, 0, 0},
+	{0x17F, 0xaa, 0},
+	{0x180, 0, 0},
+	{0x190, 0, 0},
+	{0x191, 0x77, 0},
+	{0x192, 0x77, 0},
+	{0x193, 0x77, 0},
+	{0x194, 0x77, 0},
+	{0x195, 0, 0},
+	{0x196, 0x3, 0},
+	{0x197, 0x37, 0},
+	{0x198, 0x3, 0},
+	{0x199, 0, 0},
+	{0x19A, 0x21, 0},
+	{0x19B, 0x21, 0},
+	{0x19C, 0, 0},
+	{0x19D, 0xaa, 0},
+	{0x19E, 0, 0},
+	{0x19F, 0xaa, 0},
+	{0x1A0, 0, 0},
+	{0x1A1, 0x2, 0},
+	{0x1A2, 0xf, 0},
+	{0x1A3, 0xf, 0},
+	{0x1A4, 0, 1},
+	{0x1A5, 0, 1},
+	{0x1A6, 0, 1},
+	{0x1A7, 0x2, 0},
+	{0x1A8, 0xf, 0},
+	{0x1A9, 0xf, 0},
+	{0x1AA, 0, 1},
+	{0x1AB, 0, 1},
+	{0x1AC, 0, 1},
+	{0x1AD, 0x84, 0},
+	{0x1AE, 0x60, 0},
+	{0x1AF, 0x47, 0},
+	{0x1B0, 0x47, 0},
+	{0x1B1, 0, 0},
+	{0x1B2, 0, 0},
+	{0x1B3, 0, 0},
+	{0x1B4, 0, 0},
+	{0x1B5, 0, 0},
+	{0x1B6, 0, 0},
+	{0x1B7, 0x5, 1},
+	{0x1B8, 0, 0},
+	{0x1B9, 0, 0},
+	{0x1BA, 0, 0},
+	{0x1BB, 0, 0},
+	{0x1BC, 0, 0},
+	{0x1BD, 0, 0},
+	{0x1BE, 0, 0},
+	{0x1BF, 0, 0},
+	{0x1C0, 0, 0},
+	{0x1C1, 0, 0},
+	{0x1C2, 0xa0, 1},
+	{0x1C3, 0, 0},
+	{0x1C4, 0, 0},
+	{0x1C5, 0, 0},
+	{0x1C6, 0, 0},
+	{0x1C7, 0, 0},
+	{0x1C8, 0, 0},
+	{0x1C9, 0, 0},
+	{0x1CA, 0, 0},
+	{0xFFFF, 0, 0}
+};
+
+static s16 nphy_def_lnagains[] = { -2, 10, 19, 25 };
+
+static s32 nphy_lnagain_est0[] = { -315, 40370 };
+static s32 nphy_lnagain_est1[] = { -224, 23242 };
+
+static const u16 tbl_iqcal_gainparams_nphy[2][NPHY_IQCAL_NUMGAINS][8] = {
+	{
+		{0x000, 0, 0, 2, 0x69, 0x69, 0x69, 0x69},
+		{0x700, 7, 0, 0, 0x69, 0x69, 0x69, 0x69},
+		{0x710, 7, 1, 0, 0x68, 0x68, 0x68, 0x68},
+		{0x720, 7, 2, 0, 0x67, 0x67, 0x67, 0x67},
+		{0x730, 7, 3, 0, 0x66, 0x66, 0x66, 0x66},
+		{0x740, 7, 4, 0, 0x65, 0x65, 0x65, 0x65},
+		{0x741, 7, 4, 1, 0x65, 0x65, 0x65, 0x65},
+		{0x742, 7, 4, 2, 0x65, 0x65, 0x65, 0x65},
+		{0x743, 7, 4, 3, 0x65, 0x65, 0x65, 0x65}
+	},
+	{
+		{0x000, 7, 0, 0, 0x79, 0x79, 0x79, 0x79},
+		{0x700, 7, 0, 0, 0x79, 0x79, 0x79, 0x79},
+		{0x710, 7, 1, 0, 0x79, 0x79, 0x79, 0x79},
+		{0x720, 7, 2, 0, 0x78, 0x78, 0x78, 0x78},
+		{0x730, 7, 3, 0, 0x78, 0x78, 0x78, 0x78},
+		{0x740, 7, 4, 0, 0x78, 0x78, 0x78, 0x78},
+		{0x741, 7, 4, 1, 0x78, 0x78, 0x78, 0x78},
+		{0x742, 7, 4, 2, 0x78, 0x78, 0x78, 0x78},
+		{0x743, 7, 4, 3, 0x78, 0x78, 0x78, 0x78}
+	}
+};
+
+static const u32 nphy_tpc_txgain[] = {
+	0x03cc2b44, 0x03cc2b42, 0x03cc2a44, 0x03cc2a42,
+	0x03cc2944, 0x03c82b44, 0x03c82b42, 0x03c82a44,
+	0x03c82a42, 0x03c82944, 0x03c82942, 0x03c82844,
+	0x03c82842, 0x03c42b44, 0x03c42b42, 0x03c42a44,
+	0x03c42a42, 0x03c42944, 0x03c42942, 0x03c42844,
+	0x03c42842, 0x03c42744, 0x03c42742, 0x03c42644,
+	0x03c42642, 0x03c42544, 0x03c42542, 0x03c42444,
+	0x03c42442, 0x03c02b44, 0x03c02b42, 0x03c02a44,
+	0x03c02a42, 0x03c02944, 0x03c02942, 0x03c02844,
+	0x03c02842, 0x03c02744, 0x03c02742, 0x03b02b44,
+	0x03b02b42, 0x03b02a44, 0x03b02a42, 0x03b02944,
+	0x03b02942, 0x03b02844, 0x03b02842, 0x03b02744,
+	0x03b02742, 0x03b02644, 0x03b02642, 0x03b02544,
+	0x03b02542, 0x03a02b44, 0x03a02b42, 0x03a02a44,
+	0x03a02a42, 0x03a02944, 0x03a02942, 0x03a02844,
+	0x03a02842, 0x03a02744, 0x03a02742, 0x03902b44,
+	0x03902b42, 0x03902a44, 0x03902a42, 0x03902944,
+	0x03902942, 0x03902844, 0x03902842, 0x03902744,
+	0x03902742, 0x03902644, 0x03902642, 0x03902544,
+	0x03902542, 0x03802b44, 0x03802b42, 0x03802a44,
+	0x03802a42, 0x03802944, 0x03802942, 0x03802844,
+	0x03802842, 0x03802744, 0x03802742, 0x03802644,
+	0x03802642, 0x03802544, 0x03802542, 0x03802444,
+	0x03802442, 0x03802344, 0x03802342, 0x03802244,
+	0x03802242, 0x03802144, 0x03802142, 0x03802044,
+	0x03802042, 0x03801f44, 0x03801f42, 0x03801e44,
+	0x03801e42, 0x03801d44, 0x03801d42, 0x03801c44,
+	0x03801c42, 0x03801b44, 0x03801b42, 0x03801a44,
+	0x03801a42, 0x03801944, 0x03801942, 0x03801844,
+	0x03801842, 0x03801744, 0x03801742, 0x03801644,
+	0x03801642, 0x03801544, 0x03801542, 0x03801444,
+	0x03801442, 0x03801344, 0x03801342, 0x00002b00
+};
+
+static const u16 nphy_tpc_loscale[] = {
+	256, 256, 271, 271, 287, 256, 256, 271,
+	271, 287, 287, 304, 304, 256, 256, 271,
+	271, 287, 287, 304, 304, 322, 322, 341,
+	341, 362, 362, 383, 383, 256, 256, 271,
+	271, 287, 287, 304, 304, 322, 322, 256,
+	256, 271, 271, 287, 287, 304, 304, 322,
+	322, 341, 341, 362, 362, 256, 256, 271,
+	271, 287, 287, 304, 304, 322, 322, 256,
+	256, 271, 271, 287, 287, 304, 304, 322,
+	322, 341, 341, 362, 362, 256, 256, 271,
+	271, 287, 287, 304, 304, 322, 322, 341,
+	341, 362, 362, 383, 383, 406, 406, 430,
+	430, 455, 455, 482, 482, 511, 511, 541,
+	541, 573, 573, 607, 607, 643, 643, 681,
+	681, 722, 722, 764, 764, 810, 810, 858,
+	858, 908, 908, 962, 962, 1019, 1019, 256
+};
+
+static u32 nphy_tpc_txgain_ipa[] = {
+	0x5ff7002d, 0x5ff7002b, 0x5ff7002a, 0x5ff70029,
+	0x5ff70028, 0x5ff70027, 0x5ff70026, 0x5ff70025,
+	0x5ef7002d, 0x5ef7002b, 0x5ef7002a, 0x5ef70029,
+	0x5ef70028, 0x5ef70027, 0x5ef70026, 0x5ef70025,
+	0x5df7002d, 0x5df7002b, 0x5df7002a, 0x5df70029,
+	0x5df70028, 0x5df70027, 0x5df70026, 0x5df70025,
+	0x5cf7002d, 0x5cf7002b, 0x5cf7002a, 0x5cf70029,
+	0x5cf70028, 0x5cf70027, 0x5cf70026, 0x5cf70025,
+	0x5bf7002d, 0x5bf7002b, 0x5bf7002a, 0x5bf70029,
+	0x5bf70028, 0x5bf70027, 0x5bf70026, 0x5bf70025,
+	0x5af7002d, 0x5af7002b, 0x5af7002a, 0x5af70029,
+	0x5af70028, 0x5af70027, 0x5af70026, 0x5af70025,
+	0x59f7002d, 0x59f7002b, 0x59f7002a, 0x59f70029,
+	0x59f70028, 0x59f70027, 0x59f70026, 0x59f70025,
+	0x58f7002d, 0x58f7002b, 0x58f7002a, 0x58f70029,
+	0x58f70028, 0x58f70027, 0x58f70026, 0x58f70025,
+	0x57f7002d, 0x57f7002b, 0x57f7002a, 0x57f70029,
+	0x57f70028, 0x57f70027, 0x57f70026, 0x57f70025,
+	0x56f7002d, 0x56f7002b, 0x56f7002a, 0x56f70029,
+	0x56f70028, 0x56f70027, 0x56f70026, 0x56f70025,
+	0x55f7002d, 0x55f7002b, 0x55f7002a, 0x55f70029,
+	0x55f70028, 0x55f70027, 0x55f70026, 0x55f70025,
+	0x54f7002d, 0x54f7002b, 0x54f7002a, 0x54f70029,
+	0x54f70028, 0x54f70027, 0x54f70026, 0x54f70025,
+	0x53f7002d, 0x53f7002b, 0x53f7002a, 0x53f70029,
+	0x53f70028, 0x53f70027, 0x53f70026, 0x53f70025,
+	0x52f7002d, 0x52f7002b, 0x52f7002a, 0x52f70029,
+	0x52f70028, 0x52f70027, 0x52f70026, 0x52f70025,
+	0x51f7002d, 0x51f7002b, 0x51f7002a, 0x51f70029,
+	0x51f70028, 0x51f70027, 0x51f70026, 0x51f70025,
+	0x50f7002d, 0x50f7002b, 0x50f7002a, 0x50f70029,
+	0x50f70028, 0x50f70027, 0x50f70026, 0x50f70025
+};
+
+static u32 nphy_tpc_txgain_ipa_rev5[] = {
+	0x1ff7002d, 0x1ff7002b, 0x1ff7002a, 0x1ff70029,
+	0x1ff70028, 0x1ff70027, 0x1ff70026, 0x1ff70025,
+	0x1ef7002d, 0x1ef7002b, 0x1ef7002a, 0x1ef70029,
+	0x1ef70028, 0x1ef70027, 0x1ef70026, 0x1ef70025,
+	0x1df7002d, 0x1df7002b, 0x1df7002a, 0x1df70029,
+	0x1df70028, 0x1df70027, 0x1df70026, 0x1df70025,
+	0x1cf7002d, 0x1cf7002b, 0x1cf7002a, 0x1cf70029,
+	0x1cf70028, 0x1cf70027, 0x1cf70026, 0x1cf70025,
+	0x1bf7002d, 0x1bf7002b, 0x1bf7002a, 0x1bf70029,
+	0x1bf70028, 0x1bf70027, 0x1bf70026, 0x1bf70025,
+	0x1af7002d, 0x1af7002b, 0x1af7002a, 0x1af70029,
+	0x1af70028, 0x1af70027, 0x1af70026, 0x1af70025,
+	0x19f7002d, 0x19f7002b, 0x19f7002a, 0x19f70029,
+	0x19f70028, 0x19f70027, 0x19f70026, 0x19f70025,
+	0x18f7002d, 0x18f7002b, 0x18f7002a, 0x18f70029,
+	0x18f70028, 0x18f70027, 0x18f70026, 0x18f70025,
+	0x17f7002d, 0x17f7002b, 0x17f7002a, 0x17f70029,
+	0x17f70028, 0x17f70027, 0x17f70026, 0x17f70025,
+	0x16f7002d, 0x16f7002b, 0x16f7002a, 0x16f70029,
+	0x16f70028, 0x16f70027, 0x16f70026, 0x16f70025,
+	0x15f7002d, 0x15f7002b, 0x15f7002a, 0x15f70029,
+	0x15f70028, 0x15f70027, 0x15f70026, 0x15f70025,
+	0x14f7002d, 0x14f7002b, 0x14f7002a, 0x14f70029,
+	0x14f70028, 0x14f70027, 0x14f70026, 0x14f70025,
+	0x13f7002d, 0x13f7002b, 0x13f7002a, 0x13f70029,
+	0x13f70028, 0x13f70027, 0x13f70026, 0x13f70025,
+	0x12f7002d, 0x12f7002b, 0x12f7002a, 0x12f70029,
+	0x12f70028, 0x12f70027, 0x12f70026, 0x12f70025,
+	0x11f7002d, 0x11f7002b, 0x11f7002a, 0x11f70029,
+	0x11f70028, 0x11f70027, 0x11f70026, 0x11f70025,
+	0x10f7002d, 0x10f7002b, 0x10f7002a, 0x10f70029,
+	0x10f70028, 0x10f70027, 0x10f70026, 0x10f70025
+};
+
+static u32 nphy_tpc_txgain_ipa_rev6[] = {
+	0x0ff7002d, 0x0ff7002b, 0x0ff7002a, 0x0ff70029,
+	0x0ff70028, 0x0ff70027, 0x0ff70026, 0x0ff70025,
+	0x0ef7002d, 0x0ef7002b, 0x0ef7002a, 0x0ef70029,
+	0x0ef70028, 0x0ef70027, 0x0ef70026, 0x0ef70025,
+	0x0df7002d, 0x0df7002b, 0x0df7002a, 0x0df70029,
+	0x0df70028, 0x0df70027, 0x0df70026, 0x0df70025,
+	0x0cf7002d, 0x0cf7002b, 0x0cf7002a, 0x0cf70029,
+	0x0cf70028, 0x0cf70027, 0x0cf70026, 0x0cf70025,
+	0x0bf7002d, 0x0bf7002b, 0x0bf7002a, 0x0bf70029,
+	0x0bf70028, 0x0bf70027, 0x0bf70026, 0x0bf70025,
+	0x0af7002d, 0x0af7002b, 0x0af7002a, 0x0af70029,
+	0x0af70028, 0x0af70027, 0x0af70026, 0x0af70025,
+	0x09f7002d, 0x09f7002b, 0x09f7002a, 0x09f70029,
+	0x09f70028, 0x09f70027, 0x09f70026, 0x09f70025,
+	0x08f7002d, 0x08f7002b, 0x08f7002a, 0x08f70029,
+	0x08f70028, 0x08f70027, 0x08f70026, 0x08f70025,
+	0x07f7002d, 0x07f7002b, 0x07f7002a, 0x07f70029,
+	0x07f70028, 0x07f70027, 0x07f70026, 0x07f70025,
+	0x06f7002d, 0x06f7002b, 0x06f7002a, 0x06f70029,
+	0x06f70028, 0x06f70027, 0x06f70026, 0x06f70025,
+	0x05f7002d, 0x05f7002b, 0x05f7002a, 0x05f70029,
+	0x05f70028, 0x05f70027, 0x05f70026, 0x05f70025,
+	0x04f7002d, 0x04f7002b, 0x04f7002a, 0x04f70029,
+	0x04f70028, 0x04f70027, 0x04f70026, 0x04f70025,
+	0x03f7002d, 0x03f7002b, 0x03f7002a, 0x03f70029,
+	0x03f70028, 0x03f70027, 0x03f70026, 0x03f70025,
+	0x02f7002d, 0x02f7002b, 0x02f7002a, 0x02f70029,
+	0x02f70028, 0x02f70027, 0x02f70026, 0x02f70025,
+	0x01f7002d, 0x01f7002b, 0x01f7002a, 0x01f70029,
+	0x01f70028, 0x01f70027, 0x01f70026, 0x01f70025,
+	0x00f7002d, 0x00f7002b, 0x00f7002a, 0x00f70029,
+	0x00f70028, 0x00f70027, 0x00f70026, 0x00f70025
+};
+
+static u32 nphy_tpc_txgain_ipa_2g_2057rev3[] = {
+	0x70ff0040, 0x70f7003e, 0x70ef003b, 0x70e70039,
+	0x70df0037, 0x70d70036, 0x70cf0033, 0x70c70032,
+	0x70bf0031, 0x70b7002f, 0x70af002e, 0x70a7002d,
+	0x709f002d, 0x7097002c, 0x708f002c, 0x7087002c,
+	0x707f002b, 0x7077002c, 0x706f002c, 0x7067002d,
+	0x705f002e, 0x705f002b, 0x705f0029, 0x7057002a,
+	0x70570028, 0x704f002a, 0x7047002c, 0x7047002a,
+	0x70470028, 0x70470026, 0x70470024, 0x70470022,
+	0x7047001f, 0x70370027, 0x70370024, 0x70370022,
+	0x70370020, 0x7037001f, 0x7037001d, 0x7037001b,
+	0x7037001a, 0x70370018, 0x70370017, 0x7027001e,
+	0x7027001d, 0x7027001a, 0x701f0024, 0x701f0022,
+	0x701f0020, 0x701f001f, 0x701f001d, 0x701f001b,
+	0x701f001a, 0x701f0018, 0x701f0017, 0x701f0015,
+	0x701f0014, 0x701f0013, 0x701f0012, 0x701f0011,
+	0x70170019, 0x70170018, 0x70170016, 0x70170015,
+	0x70170014, 0x70170013, 0x70170012, 0x70170010,
+	0x70170010, 0x7017000f, 0x700f001d, 0x700f001b,
+	0x700f001a, 0x700f0018, 0x700f0017, 0x700f0015,
+	0x700f0015, 0x700f0013, 0x700f0013, 0x700f0011,
+	0x700f0010, 0x700f0010, 0x700f000f, 0x700f000e,
+	0x700f000d, 0x700f000c, 0x700f000b, 0x700f000b,
+	0x700f000b, 0x700f000a, 0x700f0009, 0x700f0009,
+	0x700f0009, 0x700f0008, 0x700f0007, 0x700f0007,
+	0x700f0006, 0x700f0006, 0x700f0006, 0x700f0006,
+	0x700f0005, 0x700f0005, 0x700f0005, 0x700f0004,
+	0x700f0004, 0x700f0004, 0x700f0004, 0x700f0004,
+	0x700f0004, 0x700f0003, 0x700f0003, 0x700f0003,
+	0x700f0003, 0x700f0002, 0x700f0002, 0x700f0002,
+	0x700f0002, 0x700f0002, 0x700f0002, 0x700f0001,
+	0x700f0001, 0x700f0001, 0x700f0001, 0x700f0001,
+	0x700f0001, 0x700f0001, 0x700f0001, 0x700f0001
+};
+
+static u32 nphy_tpc_txgain_ipa_2g_2057rev4n6[] = {
+	0xf0ff0040, 0xf0f7003e, 0xf0ef003b, 0xf0e70039,
+	0xf0df0037, 0xf0d70036, 0xf0cf0033, 0xf0c70032,
+	0xf0bf0031, 0xf0b7002f, 0xf0af002e, 0xf0a7002d,
+	0xf09f002d, 0xf097002c, 0xf08f002c, 0xf087002c,
+	0xf07f002b, 0xf077002c, 0xf06f002c, 0xf067002d,
+	0xf05f002e, 0xf05f002b, 0xf05f0029, 0xf057002a,
+	0xf0570028, 0xf04f002a, 0xf047002c, 0xf047002a,
+	0xf0470028, 0xf0470026, 0xf0470024, 0xf0470022,
+	0xf047001f, 0xf0370027, 0xf0370024, 0xf0370022,
+	0xf0370020, 0xf037001f, 0xf037001d, 0xf037001b,
+	0xf037001a, 0xf0370018, 0xf0370017, 0xf027001e,
+	0xf027001d, 0xf027001a, 0xf01f0024, 0xf01f0022,
+	0xf01f0020, 0xf01f001f, 0xf01f001d, 0xf01f001b,
+	0xf01f001a, 0xf01f0018, 0xf01f0017, 0xf01f0015,
+	0xf01f0014, 0xf01f0013, 0xf01f0012, 0xf01f0011,
+	0xf0170019, 0xf0170018, 0xf0170016, 0xf0170015,
+	0xf0170014, 0xf0170013, 0xf0170012, 0xf0170010,
+	0xf0170010, 0xf017000f, 0xf00f001d, 0xf00f001b,
+	0xf00f001a, 0xf00f0018, 0xf00f0017, 0xf00f0015,
+	0xf00f0015, 0xf00f0013, 0xf00f0013, 0xf00f0011,
+	0xf00f0010, 0xf00f0010, 0xf00f000f, 0xf00f000e,
+	0xf00f000d, 0xf00f000c, 0xf00f000b, 0xf00f000b,
+	0xf00f000b, 0xf00f000a, 0xf00f0009, 0xf00f0009,
+	0xf00f0009, 0xf00f0008, 0xf00f0007, 0xf00f0007,
+	0xf00f0006, 0xf00f0006, 0xf00f0006, 0xf00f0006,
+	0xf00f0005, 0xf00f0005, 0xf00f0005, 0xf00f0004,
+	0xf00f0004, 0xf00f0004, 0xf00f0004, 0xf00f0004,
+	0xf00f0004, 0xf00f0003, 0xf00f0003, 0xf00f0003,
+	0xf00f0003, 0xf00f0002, 0xf00f0002, 0xf00f0002,
+	0xf00f0002, 0xf00f0002, 0xf00f0002, 0xf00f0001,
+	0xf00f0001, 0xf00f0001, 0xf00f0001, 0xf00f0001,
+	0xf00f0001, 0xf00f0001, 0xf00f0001, 0xf00f0001
+};
+
+static u32 nphy_tpc_txgain_ipa_2g_2057rev5[] = {
+	0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e,
+	0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033,
+	0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e,
+	0x3067002e, 0x305f002f, 0x30570030, 0x3057002d,
+	0x304f002e, 0x30470031, 0x3047002e, 0x3047002c,
+	0x30470029, 0x303f002c, 0x303f0029, 0x3037002d,
+	0x3037002a, 0x30370028, 0x302f002c, 0x302f002a,
+	0x302f0028, 0x302f0026, 0x3027002c, 0x30270029,
+	0x30270027, 0x30270025, 0x30270023, 0x301f002c,
+	0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024,
+	0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b,
+	0x30170028, 0x30170026, 0x30170024, 0x30170022,
+	0x30170020, 0x3017001e, 0x3017001d, 0x3017001b,
+	0x3017001a, 0x30170018, 0x30170017, 0x30170015,
+	0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024,
+	0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d,
+	0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017,
+	0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215,
+	0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715
+};
+
+static u32 nphy_tpc_txgain_ipa_2g_2057rev7[] = {
+	0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e,
+	0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033,
+	0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e,
+	0x3067002e, 0x305f002f, 0x30570030, 0x3057002d,
+	0x304f002e, 0x30470031, 0x3047002e, 0x3047002c,
+	0x30470029, 0x303f002c, 0x303f0029, 0x3037002d,
+	0x3037002a, 0x30370028, 0x302f002c, 0x302f002a,
+	0x302f0028, 0x302f0026, 0x3027002c, 0x30270029,
+	0x30270027, 0x30270025, 0x30270023, 0x301f002c,
+	0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024,
+	0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b,
+	0x30170028, 0x30170026, 0x30170024, 0x30170022,
+	0x30170020, 0x3017001e, 0x3017001d, 0x3017001b,
+	0x3017001a, 0x30170018, 0x30170017, 0x30170015,
+	0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024,
+	0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d,
+	0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017,
+	0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215,
+	0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715
+};
+
+static u32 nphy_tpc_txgain_ipa_5g[] = {
+	0x7ff70035, 0x7ff70033, 0x7ff70032, 0x7ff70031,
+	0x7ff7002f, 0x7ff7002e, 0x7ff7002d, 0x7ff7002b,
+	0x7ff7002a, 0x7ff70029, 0x7ff70028, 0x7ff70027,
+	0x7ff70026, 0x7ff70024, 0x7ff70023, 0x7ff70022,
+	0x7ef70028, 0x7ef70027, 0x7ef70026, 0x7ef70025,
+	0x7ef70024, 0x7ef70023, 0x7df70028, 0x7df70027,
+	0x7df70026, 0x7df70025, 0x7df70024, 0x7df70023,
+	0x7df70022, 0x7cf70029, 0x7cf70028, 0x7cf70027,
+	0x7cf70026, 0x7cf70025, 0x7cf70023, 0x7cf70022,
+	0x7bf70029, 0x7bf70028, 0x7bf70026, 0x7bf70025,
+	0x7bf70024, 0x7bf70023, 0x7bf70022, 0x7bf70021,
+	0x7af70029, 0x7af70028, 0x7af70027, 0x7af70026,
+	0x7af70025, 0x7af70024, 0x7af70023, 0x7af70022,
+	0x79f70029, 0x79f70028, 0x79f70027, 0x79f70026,
+	0x79f70025, 0x79f70024, 0x79f70023, 0x79f70022,
+	0x78f70029, 0x78f70028, 0x78f70027, 0x78f70026,
+	0x78f70025, 0x78f70024, 0x78f70023, 0x78f70022,
+	0x77f70029, 0x77f70028, 0x77f70027, 0x77f70026,
+	0x77f70025, 0x77f70024, 0x77f70023, 0x77f70022,
+	0x76f70029, 0x76f70028, 0x76f70027, 0x76f70026,
+	0x76f70024, 0x76f70023, 0x76f70022, 0x76f70021,
+	0x75f70029, 0x75f70028, 0x75f70027, 0x75f70026,
+	0x75f70025, 0x75f70024, 0x75f70023, 0x74f70029,
+	0x74f70028, 0x74f70026, 0x74f70025, 0x74f70024,
+	0x74f70023, 0x74f70022, 0x73f70029, 0x73f70027,
+	0x73f70026, 0x73f70025, 0x73f70024, 0x73f70023,
+	0x73f70022, 0x72f70028, 0x72f70027, 0x72f70026,
+	0x72f70025, 0x72f70024, 0x72f70023, 0x72f70022,
+	0x71f70028, 0x71f70027, 0x71f70026, 0x71f70025,
+	0x71f70024, 0x71f70023, 0x70f70028, 0x70f70027,
+	0x70f70026, 0x70f70024, 0x70f70023, 0x70f70022,
+	0x70f70021, 0x70f70020, 0x70f70020, 0x70f7001f
+};
+
+static u32 nphy_tpc_txgain_ipa_5g_2057[] = {
+	0x7f7f0044, 0x7f7f0040, 0x7f7f003c, 0x7f7f0039,
+	0x7f7f0036, 0x7e7f003c, 0x7e7f0038, 0x7e7f0035,
+	0x7d7f003c, 0x7d7f0039, 0x7d7f0036, 0x7d7f0033,
+	0x7c7f003b, 0x7c7f0037, 0x7c7f0034, 0x7b7f003a,
+	0x7b7f0036, 0x7b7f0033, 0x7a7f003c, 0x7a7f0039,
+	0x7a7f0036, 0x7a7f0033, 0x797f003b, 0x797f0038,
+	0x797f0035, 0x797f0032, 0x787f003b, 0x787f0038,
+	0x787f0035, 0x787f0032, 0x777f003a, 0x777f0037,
+	0x777f0034, 0x777f0031, 0x767f003a, 0x767f0036,
+	0x767f0033, 0x767f0031, 0x757f003a, 0x757f0037,
+	0x757f0034, 0x747f003c, 0x747f0039, 0x747f0036,
+	0x747f0033, 0x737f003b, 0x737f0038, 0x737f0035,
+	0x737f0032, 0x727f0039, 0x727f0036, 0x727f0033,
+	0x727f0030, 0x717f003a, 0x717f0037, 0x717f0034,
+	0x707f003b, 0x707f0038, 0x707f0035, 0x707f0032,
+	0x707f002f, 0x707f002d, 0x707f002a, 0x707f0028,
+	0x707f0025, 0x707f0023, 0x707f0021, 0x707f0020,
+	0x707f001e, 0x707f001c, 0x707f001b, 0x707f0019,
+	0x707f0018, 0x707f0016, 0x707f0015, 0x707f0014,
+	0x707f0013, 0x707f0012, 0x707f0011, 0x707f0010,
+	0x707f000f, 0x707f000e, 0x707f000d, 0x707f000d,
+	0x707f000c, 0x707f000b, 0x707f000b, 0x707f000a,
+	0x707f0009, 0x707f0009, 0x707f0008, 0x707f0008,
+	0x707f0007, 0x707f0007, 0x707f0007, 0x707f0006,
+	0x707f0006, 0x707f0006, 0x707f0005, 0x707f0005,
+	0x707f0005, 0x707f0004, 0x707f0004, 0x707f0004,
+	0x707f0004, 0x707f0004, 0x707f0003, 0x707f0003,
+	0x707f0003, 0x707f0003, 0x707f0003, 0x707f0003,
+	0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002,
+	0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002,
+	0x707f0001, 0x707f0001, 0x707f0001, 0x707f0001,
+	0x707f0001, 0x707f0001, 0x707f0001, 0x707f0001
+};
+
+static u32 nphy_tpc_txgain_ipa_5g_2057rev7[] = {
+	0x6f7f0031, 0x6f7f002e, 0x6f7f002c, 0x6f7f002a,
+	0x6f7f0027, 0x6e7f002e, 0x6e7f002c, 0x6e7f002a,
+	0x6d7f0030, 0x6d7f002d, 0x6d7f002a, 0x6d7f0028,
+	0x6c7f0030, 0x6c7f002d, 0x6c7f002b, 0x6b7f002e,
+	0x6b7f002c, 0x6b7f002a, 0x6b7f0027, 0x6a7f002e,
+	0x6a7f002c, 0x6a7f002a, 0x697f0030, 0x697f002e,
+	0x697f002b, 0x697f0029, 0x687f002f, 0x687f002d,
+	0x687f002a, 0x687f0027, 0x677f002f, 0x677f002d,
+	0x677f002a, 0x667f0031, 0x667f002e, 0x667f002c,
+	0x667f002a, 0x657f0030, 0x657f002e, 0x657f002b,
+	0x657f0029, 0x647f0030, 0x647f002d, 0x647f002b,
+	0x647f0029, 0x637f002f, 0x637f002d, 0x637f002a,
+	0x627f0030, 0x627f002d, 0x627f002b, 0x627f0029,
+	0x617f0030, 0x617f002e, 0x617f002b, 0x617f0029,
+	0x607f002f, 0x607f002d, 0x607f002a, 0x607f0027,
+	0x607f0026, 0x607f0023, 0x607f0021, 0x607f0020,
+	0x607f001e, 0x607f001c, 0x607f001a, 0x607f0019,
+	0x607f0018, 0x607f0016, 0x607f0015, 0x607f0014,
+	0x607f0012, 0x607f0012, 0x607f0011, 0x607f000f,
+	0x607f000f, 0x607f000e, 0x607f000d, 0x607f000c,
+	0x607f000c, 0x607f000b, 0x607f000b, 0x607f000a,
+	0x607f0009, 0x607f0009, 0x607f0008, 0x607f0008,
+	0x607f0008, 0x607f0007, 0x607f0007, 0x607f0006,
+	0x607f0006, 0x607f0005, 0x607f0005, 0x607f0005,
+	0x607f0005, 0x607f0005, 0x607f0004, 0x607f0004,
+	0x607f0004, 0x607f0004, 0x607f0003, 0x607f0003,
+	0x607f0003, 0x607f0003, 0x607f0002, 0x607f0002,
+	0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002,
+	0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002,
+	0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002,
+	0x607f0002, 0x607f0001, 0x607f0001, 0x607f0001,
+	0x607f0001, 0x607f0001, 0x607f0001, 0x607f0001
+};
+
+static s8 nphy_papd_pga_gain_delta_ipa_2g[] = {
+	-114, -108, -98, -91, -84, -78, -70, -62,
+	-54, -46, -39, -31, -23, -15, -8, 0
+};
+
+static s8 nphy_papd_pga_gain_delta_ipa_5g[] = {
+	-100, -95, -89, -83, -77, -70, -63, -56,
+	-48, -41, -33, -25, -19, -12, -6, 0
+};
+
+static s16 nphy_papd_padgain_dlt_2g_2057rev3n4[] = {
+	-159, -113, -86, -72, -62, -54, -48, -43,
+	-39, -35, -31, -28, -25, -23, -20, -18,
+	-17, -15, -13, -11, -10, -8, -7, -6,
+	-5, -4, -3, -3, -2, -1, -1, 0
+};
+
+static s16 nphy_papd_padgain_dlt_2g_2057rev5[] = {
+	-109, -109, -82, -68, -58, -50, -44, -39,
+	-35, -31, -28, -26, -23, -21, -19, -17,
+	-16, -14, -13, -11, -10, -9, -8, -7,
+	-5, -5, -4, -3, -2, -1, -1, 0
+};
+
+static s16 nphy_papd_padgain_dlt_2g_2057rev7[] = {
+	-122, -122, -95, -80, -69, -61, -54, -49,
+	-43, -39, -35, -32, -28, -26, -23, -21,
+	-18, -16, -15, -13, -11, -10, -8, -7,
+	-6, -5, -4, -3, -2, -1, -1, 0
+};
+
+static s8 nphy_papd_pgagain_dlt_5g_2057[] = {
+	-107, -101, -92, -85, -78, -71, -62, -55,
+	-47, -39, -32, -24, -19, -12, -6, 0
+};
+
+static s8 nphy_papd_pgagain_dlt_5g_2057rev7[] = {
+	-110, -104, -95, -88, -81, -74, -66, -58,
+	-50, -44, -36, -28, -23, -15, -8, 0
+};
+
+static u8 pad_gain_codes_used_2057rev5[] = {
+	20, 19, 18, 17, 16, 15, 14, 13, 12, 11,
+	10, 9, 8, 7, 6, 5, 4, 3, 2, 1
+};
+
+static u8 pad_gain_codes_used_2057rev7[] = {
+	15, 14, 13, 12, 11, 10, 9, 8, 7, 6,
+	5, 4, 3, 2, 1
+};
+
+static u8 pad_all_gain_codes_2057[] = {
+	31, 30, 29, 28, 27, 26, 25, 24, 23, 22,
+	21, 20, 19, 18, 17, 16, 15, 14, 13, 12,
+	11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
+	1, 0
+};
+
+static u8 pga_all_gain_codes_2057[] = {
+	15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+};
+
+static u32 nphy_papd_scaltbl[] = {
+	0x0ae2002f, 0x0a3b0032, 0x09a70035, 0x09220038,
+	0x0887003c, 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, 0x01d0011a,
+	0x01b7012a, 0x019e013c, 0x0187014f, 0x01720162,
+	0x015d0177, 0x0149018e, 0x013701a5, 0x012601be,
+	0x011501d9, 0x010501f5, 0x00f70212, 0x00e90232,
+	0x00dc0253, 0x00d00276, 0x00c4029c, 0x00b902c3,
+	0x00af02ed, 0x00a5031a, 0x009c0349, 0x0093037a,
+	0x008b03af, 0x008303e7, 0x007c0422, 0x00750461,
+	0x006e04a3, 0x006804ea, 0x00620534, 0x005d0583,
+	0x005805d7, 0x0053062f, 0x004e068d, 0x004a06f1
+};
+
+static u32 nphy_tpc_txgain_rev3[] = {
+	0x1f410044, 0x1f410042, 0x1f410040, 0x1f41003e,
+	0x1f41003c, 0x1f41003b, 0x1f410039, 0x1f410037,
+	0x1e410044, 0x1e410042, 0x1e410040, 0x1e41003e,
+	0x1e41003c, 0x1e41003b, 0x1e410039, 0x1e410037,
+	0x1d410044, 0x1d410042, 0x1d410040, 0x1d41003e,
+	0x1d41003c, 0x1d41003b, 0x1d410039, 0x1d410037,
+	0x1c410044, 0x1c410042, 0x1c410040, 0x1c41003e,
+	0x1c41003c, 0x1c41003b, 0x1c410039, 0x1c410037,
+	0x1b410044, 0x1b410042, 0x1b410040, 0x1b41003e,
+	0x1b41003c, 0x1b41003b, 0x1b410039, 0x1b410037,
+	0x1a410044, 0x1a410042, 0x1a410040, 0x1a41003e,
+	0x1a41003c, 0x1a41003b, 0x1a410039, 0x1a410037,
+	0x19410044, 0x19410042, 0x19410040, 0x1941003e,
+	0x1941003c, 0x1941003b, 0x19410039, 0x19410037,
+	0x18410044, 0x18410042, 0x18410040, 0x1841003e,
+	0x1841003c, 0x1841003b, 0x18410039, 0x18410037,
+	0x17410044, 0x17410042, 0x17410040, 0x1741003e,
+	0x1741003c, 0x1741003b, 0x17410039, 0x17410037,
+	0x16410044, 0x16410042, 0x16410040, 0x1641003e,
+	0x1641003c, 0x1641003b, 0x16410039, 0x16410037,
+	0x15410044, 0x15410042, 0x15410040, 0x1541003e,
+	0x1541003c, 0x1541003b, 0x15410039, 0x15410037,
+	0x14410044, 0x14410042, 0x14410040, 0x1441003e,
+	0x1441003c, 0x1441003b, 0x14410039, 0x14410037,
+	0x13410044, 0x13410042, 0x13410040, 0x1341003e,
+	0x1341003c, 0x1341003b, 0x13410039, 0x13410037,
+	0x12410044, 0x12410042, 0x12410040, 0x1241003e,
+	0x1241003c, 0x1241003b, 0x12410039, 0x12410037,
+	0x11410044, 0x11410042, 0x11410040, 0x1141003e,
+	0x1141003c, 0x1141003b, 0x11410039, 0x11410037,
+	0x10410044, 0x10410042, 0x10410040, 0x1041003e,
+	0x1041003c, 0x1041003b, 0x10410039, 0x10410037
+};
+
+static u32 nphy_tpc_txgain_HiPwrEPA[] = {
+	0x0f410044, 0x0f410042, 0x0f410040, 0x0f41003e,
+	0x0f41003c, 0x0f41003b, 0x0f410039, 0x0f410037,
+	0x0e410044, 0x0e410042, 0x0e410040, 0x0e41003e,
+	0x0e41003c, 0x0e41003b, 0x0e410039, 0x0e410037,
+	0x0d410044, 0x0d410042, 0x0d410040, 0x0d41003e,
+	0x0d41003c, 0x0d41003b, 0x0d410039, 0x0d410037,
+	0x0c410044, 0x0c410042, 0x0c410040, 0x0c41003e,
+	0x0c41003c, 0x0c41003b, 0x0c410039, 0x0c410037,
+	0x0b410044, 0x0b410042, 0x0b410040, 0x0b41003e,
+	0x0b41003c, 0x0b41003b, 0x0b410039, 0x0b410037,
+	0x0a410044, 0x0a410042, 0x0a410040, 0x0a41003e,
+	0x0a41003c, 0x0a41003b, 0x0a410039, 0x0a410037,
+	0x09410044, 0x09410042, 0x09410040, 0x0941003e,
+	0x0941003c, 0x0941003b, 0x09410039, 0x09410037,
+	0x08410044, 0x08410042, 0x08410040, 0x0841003e,
+	0x0841003c, 0x0841003b, 0x08410039, 0x08410037,
+	0x07410044, 0x07410042, 0x07410040, 0x0741003e,
+	0x0741003c, 0x0741003b, 0x07410039, 0x07410037,
+	0x06410044, 0x06410042, 0x06410040, 0x0641003e,
+	0x0641003c, 0x0641003b, 0x06410039, 0x06410037,
+	0x05410044, 0x05410042, 0x05410040, 0x0541003e,
+	0x0541003c, 0x0541003b, 0x05410039, 0x05410037,
+	0x04410044, 0x04410042, 0x04410040, 0x0441003e,
+	0x0441003c, 0x0441003b, 0x04410039, 0x04410037,
+	0x03410044, 0x03410042, 0x03410040, 0x0341003e,
+	0x0341003c, 0x0341003b, 0x03410039, 0x03410037,
+	0x02410044, 0x02410042, 0x02410040, 0x0241003e,
+	0x0241003c, 0x0241003b, 0x02410039, 0x02410037,
+	0x01410044, 0x01410042, 0x01410040, 0x0141003e,
+	0x0141003c, 0x0141003b, 0x01410039, 0x01410037,
+	0x00410044, 0x00410042, 0x00410040, 0x0041003e,
+	0x0041003c, 0x0041003b, 0x00410039, 0x00410037
+};
+
+static u32 nphy_tpc_txgain_epa_2057rev3[] = {
+	0x80f90040, 0x80e10040, 0x80e1003c, 0x80c9003d,
+	0x80b9003c, 0x80a9003d, 0x80a1003c, 0x8099003b,
+	0x8091003b, 0x8089003a, 0x8081003a, 0x80790039,
+	0x80710039, 0x8069003a, 0x8061003b, 0x8059003d,
+	0x8051003f, 0x80490042, 0x8049003e, 0x8049003b,
+	0x8041003e, 0x8041003b, 0x8039003e, 0x8039003b,
+	0x80390038, 0x80390035, 0x8031003a, 0x80310036,
+	0x80310033, 0x8029003a, 0x80290037, 0x80290034,
+	0x80290031, 0x80210039, 0x80210036, 0x80210033,
+	0x80210030, 0x8019003c, 0x80190039, 0x80190036,
+	0x80190033, 0x80190030, 0x8019002d, 0x8019002b,
+	0x80190028, 0x8011003a, 0x80110036, 0x80110033,
+	0x80110030, 0x8011002e, 0x8011002b, 0x80110029,
+	0x80110027, 0x80110024, 0x80110022, 0x80110020,
+	0x8011001f, 0x8011001d, 0x8009003a, 0x80090037,
+	0x80090034, 0x80090031, 0x8009002e, 0x8009002c,
+	0x80090029, 0x80090027, 0x80090025, 0x80090023,
+	0x80090021, 0x8009001f, 0x8009001d, 0x8009011d,
+	0x8009021d, 0x8009031d, 0x8009041d, 0x8009051d,
+	0x8009061d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d
+};
+
+static u32 nphy_tpc_txgain_epa_2057rev5[] = {
+	0x10f90040, 0x10e10040, 0x10e1003c, 0x10c9003d,
+	0x10b9003c, 0x10a9003d, 0x10a1003c, 0x1099003b,
+	0x1091003b, 0x1089003a, 0x1081003a, 0x10790039,
+	0x10710039, 0x1069003a, 0x1061003b, 0x1059003d,
+	0x1051003f, 0x10490042, 0x1049003e, 0x1049003b,
+	0x1041003e, 0x1041003b, 0x1039003e, 0x1039003b,
+	0x10390038, 0x10390035, 0x1031003a, 0x10310036,
+	0x10310033, 0x1029003a, 0x10290037, 0x10290034,
+	0x10290031, 0x10210039, 0x10210036, 0x10210033,
+	0x10210030, 0x1019003c, 0x10190039, 0x10190036,
+	0x10190033, 0x10190030, 0x1019002d, 0x1019002b,
+	0x10190028, 0x1011003a, 0x10110036, 0x10110033,
+	0x10110030, 0x1011002e, 0x1011002b, 0x10110029,
+	0x10110027, 0x10110024, 0x10110022, 0x10110020,
+	0x1011001f, 0x1011001d, 0x1009003a, 0x10090037,
+	0x10090034, 0x10090031, 0x1009002e, 0x1009002c,
+	0x10090029, 0x10090027, 0x10090025, 0x10090023,
+	0x10090021, 0x1009001f, 0x1009001d, 0x1009001b,
+	0x1009001a, 0x10090018, 0x10090017, 0x10090016,
+	0x10090015, 0x10090013, 0x10090012, 0x10090011,
+	0x10090010, 0x1009000f, 0x1009000f, 0x1009000e,
+	0x1009000d, 0x1009000c, 0x1009000c, 0x1009000b,
+	0x1009000a, 0x1009000a, 0x10090009, 0x10090009,
+	0x10090008, 0x10090008, 0x10090007, 0x10090007,
+	0x10090007, 0x10090006, 0x10090006, 0x10090005,
+	0x10090005, 0x10090005, 0x10090005, 0x10090004,
+	0x10090004, 0x10090004, 0x10090004, 0x10090003,
+	0x10090003, 0x10090003, 0x10090003, 0x10090003,
+	0x10090003, 0x10090002, 0x10090002, 0x10090002,
+	0x10090002, 0x10090002, 0x10090002, 0x10090002,
+	0x10090002, 0x10090002, 0x10090001, 0x10090001,
+	0x10090001, 0x10090001, 0x10090001, 0x10090001
+};
+
+static u32 nphy_tpc_5GHz_txgain_rev3[] = {
+	0xcff70044, 0xcff70042, 0xcff70040, 0xcff7003e,
+	0xcff7003c, 0xcff7003b, 0xcff70039, 0xcff70037,
+	0xcef70044, 0xcef70042, 0xcef70040, 0xcef7003e,
+	0xcef7003c, 0xcef7003b, 0xcef70039, 0xcef70037,
+	0xcdf70044, 0xcdf70042, 0xcdf70040, 0xcdf7003e,
+	0xcdf7003c, 0xcdf7003b, 0xcdf70039, 0xcdf70037,
+	0xccf70044, 0xccf70042, 0xccf70040, 0xccf7003e,
+	0xccf7003c, 0xccf7003b, 0xccf70039, 0xccf70037,
+	0xcbf70044, 0xcbf70042, 0xcbf70040, 0xcbf7003e,
+	0xcbf7003c, 0xcbf7003b, 0xcbf70039, 0xcbf70037,
+	0xcaf70044, 0xcaf70042, 0xcaf70040, 0xcaf7003e,
+	0xcaf7003c, 0xcaf7003b, 0xcaf70039, 0xcaf70037,
+	0xc9f70044, 0xc9f70042, 0xc9f70040, 0xc9f7003e,
+	0xc9f7003c, 0xc9f7003b, 0xc9f70039, 0xc9f70037,
+	0xc8f70044, 0xc8f70042, 0xc8f70040, 0xc8f7003e,
+	0xc8f7003c, 0xc8f7003b, 0xc8f70039, 0xc8f70037,
+	0xc7f70044, 0xc7f70042, 0xc7f70040, 0xc7f7003e,
+	0xc7f7003c, 0xc7f7003b, 0xc7f70039, 0xc7f70037,
+	0xc6f70044, 0xc6f70042, 0xc6f70040, 0xc6f7003e,
+	0xc6f7003c, 0xc6f7003b, 0xc6f70039, 0xc6f70037,
+	0xc5f70044, 0xc5f70042, 0xc5f70040, 0xc5f7003e,
+	0xc5f7003c, 0xc5f7003b, 0xc5f70039, 0xc5f70037,
+	0xc4f70044, 0xc4f70042, 0xc4f70040, 0xc4f7003e,
+	0xc4f7003c, 0xc4f7003b, 0xc4f70039, 0xc4f70037,
+	0xc3f70044, 0xc3f70042, 0xc3f70040, 0xc3f7003e,
+	0xc3f7003c, 0xc3f7003b, 0xc3f70039, 0xc3f70037,
+	0xc2f70044, 0xc2f70042, 0xc2f70040, 0xc2f7003e,
+	0xc2f7003c, 0xc2f7003b, 0xc2f70039, 0xc2f70037,
+	0xc1f70044, 0xc1f70042, 0xc1f70040, 0xc1f7003e,
+	0xc1f7003c, 0xc1f7003b, 0xc1f70039, 0xc1f70037,
+	0xc0f70044, 0xc0f70042, 0xc0f70040, 0xc0f7003e,
+	0xc0f7003c, 0xc0f7003b, 0xc0f70039, 0xc0f70037
+};
+
+static u32 nphy_tpc_5GHz_txgain_rev4[] = {
+	0x2ff20044, 0x2ff20042, 0x2ff20040, 0x2ff2003e,
+	0x2ff2003c, 0x2ff2003b, 0x2ff20039, 0x2ff20037,
+	0x2ef20044, 0x2ef20042, 0x2ef20040, 0x2ef2003e,
+	0x2ef2003c, 0x2ef2003b, 0x2ef20039, 0x2ef20037,
+	0x2df20044, 0x2df20042, 0x2df20040, 0x2df2003e,
+	0x2df2003c, 0x2df2003b, 0x2df20039, 0x2df20037,
+	0x2cf20044, 0x2cf20042, 0x2cf20040, 0x2cf2003e,
+	0x2cf2003c, 0x2cf2003b, 0x2cf20039, 0x2cf20037,
+	0x2bf20044, 0x2bf20042, 0x2bf20040, 0x2bf2003e,
+	0x2bf2003c, 0x2bf2003b, 0x2bf20039, 0x2bf20037,
+	0x2af20044, 0x2af20042, 0x2af20040, 0x2af2003e,
+	0x2af2003c, 0x2af2003b, 0x2af20039, 0x2af20037,
+	0x29f20044, 0x29f20042, 0x29f20040, 0x29f2003e,
+	0x29f2003c, 0x29f2003b, 0x29f20039, 0x29f20037,
+	0x28f20044, 0x28f20042, 0x28f20040, 0x28f2003e,
+	0x28f2003c, 0x28f2003b, 0x28f20039, 0x28f20037,
+	0x27f20044, 0x27f20042, 0x27f20040, 0x27f2003e,
+	0x27f2003c, 0x27f2003b, 0x27f20039, 0x27f20037,
+	0x26f20044, 0x26f20042, 0x26f20040, 0x26f2003e,
+	0x26f2003c, 0x26f2003b, 0x26f20039, 0x26f20037,
+	0x25f20044, 0x25f20042, 0x25f20040, 0x25f2003e,
+	0x25f2003c, 0x25f2003b, 0x25f20039, 0x25f20037,
+	0x24f20044, 0x24f20042, 0x24f20040, 0x24f2003e,
+	0x24f2003c, 0x24f2003b, 0x24f20039, 0x24f20038,
+	0x23f20041, 0x23f20040, 0x23f2003f, 0x23f2003e,
+	0x23f2003c, 0x23f2003b, 0x23f20039, 0x23f20037,
+	0x22f20044, 0x22f20042, 0x22f20040, 0x22f2003e,
+	0x22f2003c, 0x22f2003b, 0x22f20039, 0x22f20037,
+	0x21f20044, 0x21f20042, 0x21f20040, 0x21f2003e,
+	0x21f2003c, 0x21f2003b, 0x21f20039, 0x21f20037,
+	0x20d20043, 0x20d20041, 0x20d2003e, 0x20d2003c,
+	0x20d2003a, 0x20d20038, 0x20d20036, 0x20d20034
+};
+
+static u32 nphy_tpc_5GHz_txgain_rev5[] = {
+	0x0f62004a, 0x0f620048, 0x0f620046, 0x0f620044,
+	0x0f620042, 0x0f620040, 0x0f62003e, 0x0f62003c,
+	0x0e620044, 0x0e620042, 0x0e620040, 0x0e62003e,
+	0x0e62003c, 0x0e62003d, 0x0e62003b, 0x0e62003a,
+	0x0d620043, 0x0d620041, 0x0d620040, 0x0d62003e,
+	0x0d62003d, 0x0d62003c, 0x0d62003b, 0x0d62003a,
+	0x0c620041, 0x0c620040, 0x0c62003f, 0x0c62003e,
+	0x0c62003c, 0x0c62003b, 0x0c620039, 0x0c620037,
+	0x0b620046, 0x0b620044, 0x0b620042, 0x0b620040,
+	0x0b62003e, 0x0b62003c, 0x0b62003b, 0x0b62003a,
+	0x0a620041, 0x0a620040, 0x0a62003e, 0x0a62003c,
+	0x0a62003b, 0x0a62003a, 0x0a620039, 0x0a620038,
+	0x0962003e, 0x0962003d, 0x0962003c, 0x0962003b,
+	0x09620039, 0x09620037, 0x09620035, 0x09620033,
+	0x08620044, 0x08620042, 0x08620040, 0x0862003e,
+	0x0862003c, 0x0862003b, 0x0862003a, 0x08620039,
+	0x07620043, 0x07620042, 0x07620040, 0x0762003f,
+	0x0762003d, 0x0762003b, 0x0762003a, 0x07620039,
+	0x0662003e, 0x0662003d, 0x0662003c, 0x0662003b,
+	0x06620039, 0x06620037, 0x06620035, 0x06620033,
+	0x05620046, 0x05620044, 0x05620042, 0x05620040,
+	0x0562003e, 0x0562003c, 0x0562003b, 0x05620039,
+	0x04620044, 0x04620042, 0x04620040, 0x0462003e,
+	0x0462003c, 0x0462003b, 0x04620039, 0x04620038,
+	0x0362003c, 0x0362003b, 0x0362003a, 0x03620039,
+	0x03620038, 0x03620037, 0x03620035, 0x03620033,
+	0x0262004c, 0x0262004a, 0x02620048, 0x02620047,
+	0x02620046, 0x02620044, 0x02620043, 0x02620042,
+	0x0162004a, 0x01620048, 0x01620046, 0x01620044,
+	0x01620043, 0x01620042, 0x01620041, 0x01620040,
+	0x00620042, 0x00620040, 0x0062003e, 0x0062003c,
+	0x0062003b, 0x00620039, 0x00620037, 0x00620035
+};
+
+static u32 nphy_tpc_5GHz_txgain_HiPwrEPA[] = {
+	0x2ff10044, 0x2ff10042, 0x2ff10040, 0x2ff1003e,
+	0x2ff1003c, 0x2ff1003b, 0x2ff10039, 0x2ff10037,
+	0x2ef10044, 0x2ef10042, 0x2ef10040, 0x2ef1003e,
+	0x2ef1003c, 0x2ef1003b, 0x2ef10039, 0x2ef10037,
+	0x2df10044, 0x2df10042, 0x2df10040, 0x2df1003e,
+	0x2df1003c, 0x2df1003b, 0x2df10039, 0x2df10037,
+	0x2cf10044, 0x2cf10042, 0x2cf10040, 0x2cf1003e,
+	0x2cf1003c, 0x2cf1003b, 0x2cf10039, 0x2cf10037,
+	0x2bf10044, 0x2bf10042, 0x2bf10040, 0x2bf1003e,
+	0x2bf1003c, 0x2bf1003b, 0x2bf10039, 0x2bf10037,
+	0x2af10044, 0x2af10042, 0x2af10040, 0x2af1003e,
+	0x2af1003c, 0x2af1003b, 0x2af10039, 0x2af10037,
+	0x29f10044, 0x29f10042, 0x29f10040, 0x29f1003e,
+	0x29f1003c, 0x29f1003b, 0x29f10039, 0x29f10037,
+	0x28f10044, 0x28f10042, 0x28f10040, 0x28f1003e,
+	0x28f1003c, 0x28f1003b, 0x28f10039, 0x28f10037,
+	0x27f10044, 0x27f10042, 0x27f10040, 0x27f1003e,
+	0x27f1003c, 0x27f1003b, 0x27f10039, 0x27f10037,
+	0x26f10044, 0x26f10042, 0x26f10040, 0x26f1003e,
+	0x26f1003c, 0x26f1003b, 0x26f10039, 0x26f10037,
+	0x25f10044, 0x25f10042, 0x25f10040, 0x25f1003e,
+	0x25f1003c, 0x25f1003b, 0x25f10039, 0x25f10037,
+	0x24f10044, 0x24f10042, 0x24f10040, 0x24f1003e,
+	0x24f1003c, 0x24f1003b, 0x24f10039, 0x24f10038,
+	0x23f10041, 0x23f10040, 0x23f1003f, 0x23f1003e,
+	0x23f1003c, 0x23f1003b, 0x23f10039, 0x23f10037,
+	0x22f10044, 0x22f10042, 0x22f10040, 0x22f1003e,
+	0x22f1003c, 0x22f1003b, 0x22f10039, 0x22f10037,
+	0x21f10044, 0x21f10042, 0x21f10040, 0x21f1003e,
+	0x21f1003c, 0x21f1003b, 0x21f10039, 0x21f10037,
+	0x20d10043, 0x20d10041, 0x20d1003e, 0x20d1003c,
+	0x20d1003a, 0x20d10038, 0x20d10036, 0x20d10034
+};
+
+static u8 ant_sw_ctrl_tbl_rev8_2o3[] = { 0x14, 0x18 };
+static u8 ant_sw_ctrl_tbl_rev8[] = { 0x4, 0x8, 0x4, 0x8, 0x11, 0x12 };
+static u8 ant_sw_ctrl_tbl_rev8_2057v7_core0[] = {
+	0x09, 0x0a, 0x15, 0x16, 0x09, 0x0a
+};
+static u8 ant_sw_ctrl_tbl_rev8_2057v7_core1[] = {
+	0x09, 0x0a, 0x09, 0x0a, 0x15, 0x16
+};
+
+bool wlc_phy_bist_check_phy(struct brcms_phy_pub *pih)
+{
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+	u32 phybist0, phybist1, phybist2, phybist3, phybist4;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 16))
+		return true;
+
+	phybist0 = read_phy_reg(pi, 0x0e);
+	phybist1 = read_phy_reg(pi, 0x0f);
+	phybist2 = read_phy_reg(pi, 0xea);
+	phybist3 = read_phy_reg(pi, 0xeb);
+	phybist4 = read_phy_reg(pi, 0x156);
+
+	if ((phybist0 == 0) && (phybist1 == 0x4000) && (phybist2 == 0x1fe0) &&
+	    (phybist3 == 0) && (phybist4 == 0))
+		return true;
+
+	return false;
+}
+
+static void wlc_phy_bphy_init_nphy(struct brcms_phy *pi)
+{
+	u16 addr, val;
+
+	val = 0x1e1f;
+	for (addr = (NPHY_TO_BPHY_OFF + BPHY_RSSI_LUT);
+	     addr <= (NPHY_TO_BPHY_OFF + BPHY_RSSI_LUT_END); addr++) {
+		write_phy_reg(pi, addr, val);
+		if (addr == (NPHY_TO_BPHY_OFF + 0x97))
+			val = 0x3e3f;
+		else
+			val -= 0x0202;
+	}
+
+	write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_STEP, 0x668);
+}
+
+void
+wlc_phy_table_write_nphy(struct brcms_phy *pi, u32 id, u32 len, u32 offset,
+			 u32 width, const void *data)
+{
+	struct phytbl_info tbl;
+
+	tbl.tbl_id = id;
+	tbl.tbl_len = len;
+	tbl.tbl_offset = offset;
+	tbl.tbl_width = width;
+	tbl.tbl_ptr = data;
+	wlc_phy_write_table_nphy(pi, &tbl);
+}
+
+void
+wlc_phy_table_read_nphy(struct brcms_phy *pi, u32 id, u32 len, u32 offset,
+			u32 width, void *data)
+{
+	struct phytbl_info tbl;
+
+	tbl.tbl_id = id;
+	tbl.tbl_len = len;
+	tbl.tbl_offset = offset;
+	tbl.tbl_width = width;
+	tbl.tbl_ptr = data;
+	wlc_phy_read_table_nphy(pi, &tbl);
+}
+
+static void
+wlc_phy_static_table_download_nphy(struct brcms_phy *pi)
+{
+	uint idx;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 16)) {
+		for (idx = 0; idx < mimophytbl_info_sz_rev16; idx++)
+			wlc_phy_write_table_nphy(pi,
+						 &mimophytbl_info_rev16[idx]);
+	} else if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		for (idx = 0; idx < mimophytbl_info_sz_rev7; idx++)
+			wlc_phy_write_table_nphy(pi,
+						 &mimophytbl_info_rev7[idx]);
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		for (idx = 0; idx < mimophytbl_info_sz_rev3; idx++)
+			wlc_phy_write_table_nphy(pi,
+						 &mimophytbl_info_rev3[idx]);
+	} else {
+		for (idx = 0; idx < mimophytbl_info_sz_rev0; idx++)
+			wlc_phy_write_table_nphy(pi,
+						 &mimophytbl_info_rev0[idx]);
+	}
+}
+
+static void wlc_phy_tbl_init_nphy(struct brcms_phy *pi)
+{
+	uint idx = 0;
+	u8 antswctrllut;
+
+	if (pi->phy_init_por)
+		wlc_phy_static_table_download_nphy(pi);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		antswctrllut = CHSPEC_IS2G(pi->radio_chanspec) ?
+			       pi->srom_fem2g.antswctrllut : pi->srom_fem5g.
+			       antswctrllut;
+
+		switch (antswctrllut) {
+		case 0:
+
+			break;
+
+		case 1:
+
+			if (pi->aa2g == 7)
+				wlc_phy_table_write_nphy(
+					pi,
+					NPHY_TBL_ID_ANTSWCTRLLUT,
+					2, 0x21, 8,
+					&ant_sw_ctrl_tbl_rev8_2o3[0]);
+			else
+				wlc_phy_table_write_nphy(
+					pi,
+					NPHY_TBL_ID_ANTSWCTRLLUT,
+					2, 0x21, 8,
+					&ant_sw_ctrl_tbl_rev8
+					[0]);
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x25, 8,
+						 &ant_sw_ctrl_tbl_rev8[2]);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x29, 8,
+						 &ant_sw_ctrl_tbl_rev8[4]);
+			break;
+
+		case 2:
+
+			wlc_phy_table_write_nphy(
+				pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+				2, 0x1, 8,
+				&ant_sw_ctrl_tbl_rev8_2057v7_core0[0]);
+			wlc_phy_table_write_nphy(
+				pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+				2, 0x5, 8,
+				&ant_sw_ctrl_tbl_rev8_2057v7_core0[2]);
+			wlc_phy_table_write_nphy(
+				pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+				2, 0x9, 8,
+				&ant_sw_ctrl_tbl_rev8_2057v7_core0[4]);
+
+			wlc_phy_table_write_nphy(
+				pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+				2, 0x21, 8,
+				&ant_sw_ctrl_tbl_rev8_2057v7_core1[0]);
+			wlc_phy_table_write_nphy(
+				pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+				2, 0x25, 8,
+				&ant_sw_ctrl_tbl_rev8_2057v7_core1[2]);
+			wlc_phy_table_write_nphy(
+				pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+				2, 0x29, 8,
+				&ant_sw_ctrl_tbl_rev8_2057v7_core1[4]);
+			break;
+
+		default:
+			break;
+		}
+
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		for (idx = 0; idx < mimophytbl_info_sz_rev3_volatile; idx++) {
+
+			if (idx == ANT_SWCTRL_TBL_REV3_IDX) {
+				antswctrllut =
+					CHSPEC_IS2G(pi->radio_chanspec) ?
+					pi->srom_fem2g.antswctrllut :
+					pi->srom_fem5g.antswctrllut;
+				switch (antswctrllut) {
+				case 0:
+					wlc_phy_write_table_nphy(
+						pi,
+						&mimophytbl_info_rev3_volatile
+						[idx]);
+					break;
+				case 1:
+					wlc_phy_write_table_nphy(
+						pi,
+						&mimophytbl_info_rev3_volatile1
+						[idx]);
+					break;
+				case 2:
+					wlc_phy_write_table_nphy(
+						pi,
+						&mimophytbl_info_rev3_volatile2
+						[idx]);
+					break;
+				case 3:
+					wlc_phy_write_table_nphy(
+						pi,
+						&mimophytbl_info_rev3_volatile3
+						[idx]);
+					break;
+				default:
+					break;
+				}
+			} else {
+				wlc_phy_write_table_nphy(
+					pi,
+					&mimophytbl_info_rev3_volatile[idx]);
+			}
+		}
+	} else {
+		for (idx = 0; idx < mimophytbl_info_sz_rev0_volatile; idx++)
+			wlc_phy_write_table_nphy(pi,
+						 &mimophytbl_info_rev0_volatile
+						 [idx]);
+	}
+}
+
+static void
+wlc_phy_write_txmacreg_nphy(struct brcms_phy *pi, u16 holdoff, u16 delay)
+{
+	write_phy_reg(pi, 0x77, holdoff);
+	write_phy_reg(pi, 0xb4, delay);
+}
+
+void wlc_phy_nphy_tkip_rifs_war(struct brcms_phy *pi, u8 rifs)
+{
+	u16 holdoff, delay;
+
+	if (rifs) {
+
+		holdoff = 0x10;
+		delay = 0x258;
+	} else {
+
+		holdoff = 0x15;
+		delay = 0x320;
+	}
+
+	wlc_phy_write_txmacreg_nphy(pi, holdoff, delay);
+
+	if (pi->sh && (pi->sh->_rifs_phy != rifs))
+		pi->sh->_rifs_phy = rifs;
+}
+
+static void wlc_phy_txpwrctrl_config_nphy(struct brcms_phy *pi)
+{
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		pi->nphy_txpwrctrl = PHY_TPC_HW_ON;
+		pi->phy_5g_pwrgain = true;
+		return;
+	}
+
+	pi->nphy_txpwrctrl = PHY_TPC_HW_OFF;
+	pi->phy_5g_pwrgain = false;
+
+	if ((pi->sh->boardflags2 & BFL2_TXPWRCTRL_EN) &&
+	    NREV_GE(pi->pubpi.phy_rev, 2) && (pi->sh->sromrev >= 4))
+		pi->nphy_txpwrctrl = PHY_TPC_HW_ON;
+	else if ((pi->sh->sromrev >= 4)
+		 && (pi->sh->boardflags2 & BFL2_5G_PWRGAIN))
+		pi->phy_5g_pwrgain = true;
+}
+
+static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi)
+{
+	u16 bw40po, cddpo, stbcpo, bwduppo;
+	uint band_num;
+	struct ssb_sprom *sprom = &pi->d11core->bus->sprom;
+
+	if (pi->sh->sromrev >= 9)
+		return;
+
+	bw40po = sprom->bw40po;
+	pi->bw402gpo = bw40po & 0xf;
+	pi->bw405gpo = (bw40po & 0xf0) >> 4;
+	pi->bw405glpo = (bw40po & 0xf00) >> 8;
+	pi->bw405ghpo = (bw40po & 0xf000) >> 12;
+
+	cddpo = sprom->cddpo;
+	pi->cdd2gpo = cddpo & 0xf;
+	pi->cdd5gpo = (cddpo & 0xf0) >> 4;
+	pi->cdd5glpo = (cddpo & 0xf00) >> 8;
+	pi->cdd5ghpo = (cddpo & 0xf000) >> 12;
+
+	stbcpo = sprom->stbcpo;
+	pi->stbc2gpo = stbcpo & 0xf;
+	pi->stbc5gpo = (stbcpo & 0xf0) >> 4;
+	pi->stbc5glpo = (stbcpo & 0xf00) >> 8;
+	pi->stbc5ghpo = (stbcpo & 0xf000) >> 12;
+
+	bwduppo = sprom->bwduppo;
+	pi->bwdup2gpo = bwduppo & 0xf;
+	pi->bwdup5gpo = (bwduppo & 0xf0) >> 4;
+	pi->bwdup5glpo = (bwduppo & 0xf00) >> 8;
+	pi->bwdup5ghpo = (bwduppo & 0xf000) >> 12;
+
+	for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP);
+	     band_num++) {
+		switch (band_num) {
+		case 0:
+			pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_2g =
+				sprom->core_pwr_info[0].maxpwr_2g;
+			pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_2g =
+				sprom->core_pwr_info[1].maxpwr_2g;
+			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_a1 =
+				sprom->core_pwr_info[0].pa_2g[0];
+			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_a1 =
+				sprom->core_pwr_info[1].pa_2g[0];
+			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b0 =
+				sprom->core_pwr_info[0].pa_2g[1];
+			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b0 =
+				sprom->core_pwr_info[1].pa_2g[1];
+			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b1 =
+				sprom->core_pwr_info[0].pa_2g[2];
+			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b1 =
+				sprom->core_pwr_info[1].pa_2g[2];
+			pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_2g =
+				sprom->core_pwr_info[0].itssi_2g;
+			pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_2g =
+				sprom->core_pwr_info[1].itssi_2g;
+
+			pi->cck2gpo = sprom->cck2gpo;
+
+			pi->ofdm2gpo = sprom->ofdm2gpo;
+
+			pi->mcs2gpo[0] = sprom->mcs2gpo[0];
+			pi->mcs2gpo[1] = sprom->mcs2gpo[1];
+			pi->mcs2gpo[2] = sprom->mcs2gpo[2];
+			pi->mcs2gpo[3] = sprom->mcs2gpo[3];
+			pi->mcs2gpo[4] = sprom->mcs2gpo[4];
+			pi->mcs2gpo[5] = sprom->mcs2gpo[5];
+			pi->mcs2gpo[6] = sprom->mcs2gpo[6];
+			pi->mcs2gpo[7] = sprom->mcs2gpo[7];
+			break;
+		case 1:
+
+			pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_5gm =
+				sprom->core_pwr_info[0].maxpwr_5g;
+			pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_5gm =
+				sprom->core_pwr_info[1].maxpwr_5g;
+			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_a1 =
+				sprom->core_pwr_info[0].pa_5g[0];
+			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_a1 =
+				sprom->core_pwr_info[1].pa_5g[0];
+			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b0 =
+				sprom->core_pwr_info[0].pa_5g[1];
+			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b0 =
+				sprom->core_pwr_info[1].pa_5g[1];
+			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b1 =
+				sprom->core_pwr_info[0].pa_5g[2];
+			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b1 =
+				sprom->core_pwr_info[1].pa_5g[2];
+			pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_5gm =
+				sprom->core_pwr_info[0].itssi_5g;
+			pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_5gm =
+				sprom->core_pwr_info[1].itssi_5g;
+
+			pi->ofdm5gpo = sprom->ofdm5gpo;
+
+			pi->mcs5gpo[0] = sprom->mcs5gpo[0];
+			pi->mcs5gpo[1] = sprom->mcs5gpo[1];
+			pi->mcs5gpo[2] = sprom->mcs5gpo[2];
+			pi->mcs5gpo[3] = sprom->mcs5gpo[3];
+			pi->mcs5gpo[4] = sprom->mcs5gpo[4];
+			pi->mcs5gpo[5] = sprom->mcs5gpo[5];
+			pi->mcs5gpo[6] = sprom->mcs5gpo[6];
+			pi->mcs5gpo[7] = sprom->mcs5gpo[7];
+			break;
+		case 2:
+
+			pi->nphy_pwrctrl_info[0].max_pwr_5gl =
+				sprom->core_pwr_info[0].maxpwr_5gl;
+			pi->nphy_pwrctrl_info[1].max_pwr_5gl =
+				sprom->core_pwr_info[1].maxpwr_5gl;
+			pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1 =
+				sprom->core_pwr_info[0].pa_5gl[0];
+			pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1 =
+				sprom->core_pwr_info[1].pa_5gl[0];
+			pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0 =
+				sprom->core_pwr_info[0].pa_5gl[1];
+			pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0 =
+				sprom->core_pwr_info[1].pa_5gl[1];
+			pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1 =
+				sprom->core_pwr_info[0].pa_5gl[2];
+			pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1 =
+				sprom->core_pwr_info[1].pa_5gl[2];
+			pi->nphy_pwrctrl_info[0].idle_targ_5gl = 0;
+			pi->nphy_pwrctrl_info[1].idle_targ_5gl = 0;
+
+			pi->ofdm5glpo = sprom->ofdm5glpo;
+
+			pi->mcs5glpo[0] = sprom->mcs5glpo[0];
+			pi->mcs5glpo[1] = sprom->mcs5glpo[1];
+			pi->mcs5glpo[2] = sprom->mcs5glpo[2];
+			pi->mcs5glpo[3] = sprom->mcs5glpo[3];
+			pi->mcs5glpo[4] = sprom->mcs5glpo[4];
+			pi->mcs5glpo[5] = sprom->mcs5glpo[5];
+			pi->mcs5glpo[6] = sprom->mcs5glpo[6];
+			pi->mcs5glpo[7] = sprom->mcs5glpo[7];
+			break;
+		case 3:
+
+			pi->nphy_pwrctrl_info[0].max_pwr_5gh =
+				sprom->core_pwr_info[0].maxpwr_5gh;
+			pi->nphy_pwrctrl_info[1].max_pwr_5gh =
+				sprom->core_pwr_info[1].maxpwr_5gh;
+			pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1 =
+				sprom->core_pwr_info[0].pa_5gh[0];
+			pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1 =
+				sprom->core_pwr_info[1].pa_5gh[0];
+			pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0 =
+				sprom->core_pwr_info[0].pa_5gh[1];
+			pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0 =
+				sprom->core_pwr_info[1].pa_5gh[1];
+			pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1 =
+				sprom->core_pwr_info[0].pa_5gh[2];
+			pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1 =
+				sprom->core_pwr_info[1].pa_5gh[2];
+			pi->nphy_pwrctrl_info[0].idle_targ_5gh = 0;
+			pi->nphy_pwrctrl_info[1].idle_targ_5gh = 0;
+
+			pi->ofdm5ghpo = sprom->ofdm5ghpo;
+
+			pi->mcs5ghpo[0] = sprom->mcs5ghpo[0];
+			pi->mcs5ghpo[1] = sprom->mcs5ghpo[1];
+			pi->mcs5ghpo[2] = sprom->mcs5ghpo[2];
+			pi->mcs5ghpo[3] = sprom->mcs5ghpo[3];
+			pi->mcs5ghpo[4] = sprom->mcs5ghpo[4];
+			pi->mcs5ghpo[5] = sprom->mcs5ghpo[5];
+			pi->mcs5ghpo[6] = sprom->mcs5ghpo[6];
+			pi->mcs5ghpo[7] = sprom->mcs5ghpo[7];
+			break;
+		}
+	}
+
+	wlc_phy_txpwr_apply_nphy(pi);
+}
+
+static bool wlc_phy_txpwr_srom_read_nphy(struct brcms_phy *pi)
+{
+	struct ssb_sprom *sprom = &pi->d11core->bus->sprom;
+
+	pi->antswitch = sprom->antswitch;
+	pi->aa2g = sprom->ant_available_bg;
+	pi->aa5g = sprom->ant_available_a;
+
+	pi->srom_fem2g.tssipos = sprom->fem.ghz2.tssipos;
+	pi->srom_fem2g.extpagain = sprom->fem.ghz2.extpa_gain;
+	pi->srom_fem2g.pdetrange = sprom->fem.ghz2.pdet_range;
+	pi->srom_fem2g.triso = sprom->fem.ghz2.tr_iso;
+	pi->srom_fem2g.antswctrllut = sprom->fem.ghz2.antswlut;
+
+	pi->srom_fem5g.tssipos = sprom->fem.ghz5.tssipos;
+	pi->srom_fem5g.extpagain = sprom->fem.ghz5.extpa_gain;
+	pi->srom_fem5g.pdetrange = sprom->fem.ghz5.pdet_range;
+	pi->srom_fem5g.triso = sprom->fem.ghz5.tr_iso;
+	if (sprom->fem.ghz5.antswlut)
+		pi->srom_fem5g.antswctrllut = sprom->fem.ghz5.antswlut;
+	else
+		pi->srom_fem5g.antswctrllut = sprom->fem.ghz2.antswlut;
+
+	wlc_phy_txpower_ipa_upd(pi);
+
+	pi->phy_txcore_disable_temp = sprom->tempthresh;
+	if (pi->phy_txcore_disable_temp == 0)
+		pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP;
+
+	pi->phy_tempsense_offset = sprom->tempoffset;
+	if (pi->phy_tempsense_offset != 0) {
+		if (pi->phy_tempsense_offset >
+		    (NPHY_SROM_TEMPSHIFT + NPHY_SROM_MAXTEMPOFFSET))
+			pi->phy_tempsense_offset = NPHY_SROM_MAXTEMPOFFSET;
+		else if (pi->phy_tempsense_offset < (NPHY_SROM_TEMPSHIFT +
+						     NPHY_SROM_MINTEMPOFFSET))
+			pi->phy_tempsense_offset = NPHY_SROM_MINTEMPOFFSET;
+		else
+			pi->phy_tempsense_offset -= NPHY_SROM_TEMPSHIFT;
+	}
+
+	pi->phy_txcore_enable_temp =
+		pi->phy_txcore_disable_temp - PHY_HYSTERESIS_DELTATEMP;
+
+	pi->phycal_tempdelta = sprom->phycal_tempdelta;
+	if (pi->phycal_tempdelta > NPHY_CAL_MAXTEMPDELTA)
+		pi->phycal_tempdelta = 0;
+
+	wlc_phy_txpwr_srom_read_ppr_nphy(pi);
+
+	return true;
+}
+
+bool wlc_phy_attach_nphy(struct brcms_phy *pi)
+{
+	uint i;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 6))
+		pi->phyhang_avoid = true;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+		pi->nphy_gband_spurwar_en = true;
+		if (pi->sh->boardflags2 & BFL2_SPUR_WAR)
+			pi->nphy_aband_spurwar_en = true;
+	}
+	if (NREV_GE(pi->pubpi.phy_rev, 6) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+		if (pi->sh->boardflags2 & BFL2_2G_SPUR_WAR)
+			pi->nphy_gband_spurwar2_en = true;
+	}
+
+	pi->n_preamble_override = AUTO;
+	if (NREV_IS(pi->pubpi.phy_rev, 3) || NREV_IS(pi->pubpi.phy_rev, 4))
+		pi->n_preamble_override = BRCMS_N_PREAMBLE_MIXEDMODE;
+
+	pi->nphy_txrx_chain = AUTO;
+	pi->phy_scraminit = AUTO;
+
+	pi->nphy_rxcalparams = 0x010100B5;
+
+	pi->nphy_perical = PHY_PERICAL_MPHASE;
+	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE;
+	pi->mphase_txcal_numcmds = MPHASE_TXCAL_NUMCMDS;
+
+	pi->nphy_gain_boost = true;
+	pi->nphy_elna_gain_config = false;
+	pi->radio_is_on = false;
+
+	for (i = 0; i < pi->pubpi.phy_corenum; i++)
+		pi->nphy_txpwrindex[i].index = AUTO;
+
+	wlc_phy_txpwrctrl_config_nphy(pi);
+	if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON)
+		pi->hwpwrctrl_capable = true;
+
+	pi->pi_fptr.init = wlc_phy_init_nphy;
+	pi->pi_fptr.calinit = wlc_phy_cal_init_nphy;
+	pi->pi_fptr.chanset = wlc_phy_chanspec_set_nphy;
+	pi->pi_fptr.txpwrrecalc = wlc_phy_txpower_recalc_target_nphy;
+
+	if (!wlc_phy_txpwr_srom_read_nphy(pi))
+		return false;
+
+	return true;
+}
+
+static s32 get_rf_pwr_offset(struct brcms_phy *pi, s16 pga_gn, s16 pad_gn)
+{
+	s32 rfpwr_offset = 0;
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if ((pi->pubpi.radiorev == 3) ||
+		    (pi->pubpi.radiorev == 4) ||
+		    (pi->pubpi.radiorev == 6))
+			rfpwr_offset = (s16)
+				       nphy_papd_padgain_dlt_2g_2057rev3n4
+				       [pad_gn];
+		else if (pi->pubpi.radiorev == 5)
+			rfpwr_offset = (s16)
+				       nphy_papd_padgain_dlt_2g_2057rev5
+				       [pad_gn];
+		else if ((pi->pubpi.radiorev == 7)
+			 || (pi->pubpi.radiorev ==
+			     8))
+			rfpwr_offset = (s16)
+				       nphy_papd_padgain_dlt_2g_2057rev7
+				       [pad_gn];
+	} else {
+		if ((pi->pubpi.radiorev == 3) ||
+		    (pi->pubpi.radiorev == 4) ||
+		    (pi->pubpi.radiorev == 6))
+			rfpwr_offset = (s16)
+				       nphy_papd_pgagain_dlt_5g_2057
+				       [pga_gn];
+		else if ((pi->pubpi.radiorev == 7)
+			 || (pi->pubpi.radiorev ==
+			     8))
+			rfpwr_offset = (s16)
+				       nphy_papd_pgagain_dlt_5g_2057rev7
+				       [pga_gn];
+	}
+	return rfpwr_offset;
+}
+
+static void wlc_phy_update_mimoconfig_nphy(struct brcms_phy *pi, s32 preamble)
+{
+	bool gf_preamble = false;
+	u16 val;
+
+	if (preamble == BRCMS_N_PREAMBLE_GF)
+		gf_preamble = true;
+
+	val = read_phy_reg(pi, 0xed);
+
+	val |= RX_GF_MM_AUTO;
+	val &= ~RX_GF_OR_MM;
+	if (gf_preamble)
+		val |= RX_GF_OR_MM;
+
+	write_phy_reg(pi, 0xed, val);
+}
+
+static void wlc_phy_ipa_set_tx_digi_filts_nphy(struct brcms_phy *pi)
+{
+	int j, type;
+	u16 addr_offset[] = { 0x186, 0x195, 0x2c5};
+
+	for (type = 0; type < 3; type++) {
+		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++)
+			write_phy_reg(pi, addr_offset[type] + j,
+				      NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]);
+	}
+
+	if (pi->bw == WL_CHANSPEC_BW_40) {
+		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++)
+			write_phy_reg(pi, 0x186 + j,
+				      NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]);
+	} else {
+		if (CHSPEC_IS5G(pi->radio_chanspec)) {
+			for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++)
+				write_phy_reg(pi, 0x186 + j,
+					NPHY_IPA_REV4_txdigi_filtcoeffs[5][j]);
+		}
+
+		if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
+			for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++)
+				write_phy_reg(pi, 0x2c5 + j,
+					NPHY_IPA_REV4_txdigi_filtcoeffs[6][j]);
+		}
+	}
+}
+
+static void wlc_phy_ipa_restore_tx_digi_filts_nphy(struct brcms_phy *pi)
+{
+	int j;
+
+	if (pi->bw == WL_CHANSPEC_BW_40) {
+		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++)
+			write_phy_reg(pi, 0x195 + j,
+				      NPHY_IPA_REV4_txdigi_filtcoeffs[4][j]);
+	} else {
+		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++)
+			write_phy_reg(pi, 0x186 + j,
+				      NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]);
+	}
+}
+
+static void
+wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, const u8 *events,
+		       const u8 *dlys, u8 len)
+{
+	u32 t1_offset, t2_offset;
+	u8 ctr;
+	u8 end_event =
+		NREV_GE(pi->pubpi.phy_rev,
+			3) ? NPHY_REV3_RFSEQ_CMD_END : NPHY_RFSEQ_CMD_END;
+	u8 end_dly = 1;
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	t1_offset = cmd << 4;
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t1_offset, 8,
+				 events);
+	t2_offset = t1_offset + 0x080;
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t2_offset, 8,
+				 dlys);
+
+	for (ctr = len; ctr < 16; ctr++) {
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+					 t1_offset + ctr, 8, &end_event);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+					 t2_offset + ctr, 8, &end_dly);
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static u16 wlc_phy_read_lpf_bw_ctl_nphy(struct brcms_phy *pi, u16 offset)
+{
+	u16 lpf_bw_ctl_val = 0;
+	u16 rx2tx_lpf_rc_lut_offset = 0;
+
+	if (offset == 0) {
+		if (CHSPEC_IS40(pi->radio_chanspec))
+			rx2tx_lpf_rc_lut_offset = 0x159;
+		else
+			rx2tx_lpf_rc_lut_offset = 0x154;
+	} else {
+		rx2tx_lpf_rc_lut_offset = offset;
+	}
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+				(u32) rx2tx_lpf_rc_lut_offset, 16,
+				&lpf_bw_ctl_val);
+
+	lpf_bw_ctl_val = lpf_bw_ctl_val & 0x7;
+
+	return lpf_bw_ctl_val;
+}
+
+static void
+wlc_phy_rfctrl_override_nphy_rev7(struct brcms_phy *pi, u16 field, u16 value,
+				  u8 core_mask, u8 off, u8 override_id)
+{
+	u8 core_num;
+	u16 addr = 0, en_addr = 0, val_addr = 0, en_mask = 0, val_mask = 0;
+	u8 val_shift = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		en_mask = field;
+		for (core_num = 0; core_num < 2; core_num++) {
+			if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID0) {
+
+				switch (field) {
+				case (0x1 << 2):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+						   0x7d;
+					val_mask = (0x1 << 1);
+					val_shift = 1;
+					break;
+				case (0x1 << 3):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+						   0x7d;
+					val_mask = (0x1 << 2);
+					val_shift = 2;
+					break;
+				case (0x1 << 4):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+						   0x7d;
+					val_mask = (0x1 << 4);
+					val_shift = 4;
+					break;
+				case (0x1 << 5):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+						   0x7d;
+					val_mask = (0x1 << 5);
+					val_shift = 5;
+					break;
+				case (0x1 << 6):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+						   0x7d;
+					val_mask = (0x1 << 6);
+					val_shift = 6;
+					break;
+				case (0x1 << 7):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+						   0x7d;
+					val_mask = (0x1 << 7);
+					val_shift = 7;
+					break;
+				case (0x1 << 10):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0xf8 :
+						   0xfa;
+					val_mask = (0x7 << 4);
+					val_shift = 4;
+					break;
+				case (0x1 << 11):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7b :
+						   0x7e;
+					val_mask = (0xffff << 0);
+					val_shift = 0;
+					break;
+				case (0x1 << 12):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7c :
+						   0x7f;
+					val_mask = (0xffff << 0);
+					val_shift = 0;
+					break;
+				case (0x3 << 13):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x348 :
+						   0x349;
+					val_mask = (0xff << 0);
+					val_shift = 0;
+					break;
+				case (0x1 << 13):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x348 :
+						   0x349;
+					val_mask = (0xf << 0);
+					val_shift = 0;
+					break;
+				default:
+					addr = 0xffff;
+					break;
+				}
+			} else if (override_id ==
+				   NPHY_REV7_RFCTRLOVERRIDE_ID1) {
+
+				switch (field) {
+				case (0x1 << 1):
+					en_addr = (core_num == 0) ? 0x342 :
+						  0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+						   0x341;
+					val_mask = (0x1 << 1);
+					val_shift = 1;
+					break;
+				case (0x1 << 3):
+					en_addr = (core_num == 0) ? 0x342 :
+						  0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+						   0x341;
+					val_mask = (0x1 << 3);
+					val_shift = 3;
+					break;
+				case (0x1 << 5):
+					en_addr = (core_num == 0) ? 0x342 :
+						  0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+						   0x341;
+					val_mask = (0x1 << 5);
+					val_shift = 5;
+					break;
+				case (0x1 << 4):
+					en_addr = (core_num == 0) ? 0x342 :
+						  0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+						   0x341;
+					val_mask = (0x1 << 4);
+					val_shift = 4;
+					break;
+				case (0x1 << 2):
+
+					en_addr = (core_num == 0) ? 0x342 :
+						  0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+						   0x341;
+					val_mask = (0x1 << 2);
+					val_shift = 2;
+					break;
+				case (0x1 << 7):
+
+					en_addr = (core_num == 0) ? 0x342 :
+						  0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+						   0x341;
+					val_mask = (0x7 << 8);
+					val_shift = 8;
+					break;
+				case (0x1 << 11):
+					en_addr = (core_num == 0) ? 0x342 :
+						  0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+						   0x341;
+					val_mask = (0x1 << 14);
+					val_shift = 14;
+					break;
+				case (0x1 << 10):
+					en_addr = (core_num == 0) ? 0x342 :
+						  0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+						   0x341;
+					val_mask = (0x1 << 13);
+					val_shift = 13;
+					break;
+				case (0x1 << 9):
+					en_addr = (core_num == 0) ? 0x342 :
+						  0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+						   0x341;
+					val_mask = (0x1 << 12);
+					val_shift = 12;
+					break;
+				case (0x1 << 8):
+					en_addr = (core_num == 0) ? 0x342 :
+						  0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+						   0x341;
+					val_mask = (0x1 << 11);
+					val_shift = 11;
+					break;
+				case (0x1 << 6):
+					en_addr = (core_num == 0) ? 0x342 :
+						  0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+						   0x341;
+					val_mask = (0x1 << 6);
+					val_shift = 6;
+					break;
+				case (0x1 << 0):
+					en_addr = (core_num == 0) ? 0x342 :
+						  0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+						   0x341;
+					val_mask = (0x1 << 0);
+					val_shift = 0;
+					break;
+				default:
+					addr = 0xffff;
+					break;
+				}
+			} else if (override_id ==
+				   NPHY_REV7_RFCTRLOVERRIDE_ID2) {
+
+				switch (field) {
+				case (0x1 << 3):
+					en_addr = (core_num == 0) ? 0x346 :
+						  0x347;
+					val_addr = (core_num == 0) ? 0x344 :
+						   0x345;
+					val_mask = (0x1 << 3);
+					val_shift = 3;
+					break;
+				case (0x1 << 1):
+					en_addr = (core_num == 0) ? 0x346 :
+						  0x347;
+					val_addr = (core_num == 0) ? 0x344 :
+						   0x345;
+					val_mask = (0x1 << 1);
+					val_shift = 1;
+					break;
+				case (0x1 << 0):
+					en_addr = (core_num == 0) ? 0x346 :
+						  0x347;
+					val_addr = (core_num == 0) ? 0x344 :
+						   0x345;
+					val_mask = (0x1 << 0);
+					val_shift = 0;
+					break;
+				case (0x1 << 2):
+					en_addr = (core_num == 0) ? 0x346 :
+						  0x347;
+					val_addr = (core_num == 0) ? 0x344 :
+						   0x345;
+					val_mask = (0x1 << 2);
+					val_shift = 2;
+					break;
+				case (0x1 << 4):
+					en_addr = (core_num == 0) ? 0x346 :
+						  0x347;
+					val_addr = (core_num == 0) ? 0x344 :
+						   0x345;
+					val_mask = (0x1 << 4);
+					val_shift = 4;
+					break;
+				default:
+					addr = 0xffff;
+					break;
+				}
+			}
+
+			if (off) {
+				and_phy_reg(pi, en_addr, ~en_mask);
+				and_phy_reg(pi, val_addr, ~val_mask);
+			} else {
+
+				if ((core_mask == 0)
+				    || (core_mask & (1 << core_num))) {
+					or_phy_reg(pi, en_addr, en_mask);
+
+					if (addr != 0xffff)
+						mod_phy_reg(pi, val_addr,
+							    val_mask,
+							    (value <<
+							     val_shift));
+				}
+			}
+		}
+	}
+}
+
+static void wlc_phy_adjust_lnagaintbl_nphy(struct brcms_phy *pi)
+{
+	uint core;
+	int ctr;
+	s16 gain_delta[2];
+	u8 curr_channel;
+	u16 minmax_gain[2];
+	u16 regval[4];
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (pi->nphy_gain_boost) {
+		if ((CHSPEC_IS2G(pi->radio_chanspec))) {
+
+			gain_delta[0] = 6;
+			gain_delta[1] = 6;
+		} else {
+
+			curr_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
+			gain_delta[0] =
+				(s16)
+				PHY_HW_ROUND(((nphy_lnagain_est0[0] *
+					       curr_channel) +
+					      nphy_lnagain_est0[1]), 13);
+			gain_delta[1] =
+				(s16)
+				PHY_HW_ROUND(((nphy_lnagain_est1[0] *
+					       curr_channel) +
+					      nphy_lnagain_est1[1]), 13);
+		}
+	} else {
+
+		gain_delta[0] = 0;
+		gain_delta[1] = 0;
+	}
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+		if (pi->nphy_elna_gain_config) {
+
+			regval[0] = nphy_def_lnagains[2] + gain_delta[core];
+			regval[1] = nphy_def_lnagains[3] + gain_delta[core];
+			regval[2] = nphy_def_lnagains[3] + gain_delta[core];
+			regval[3] = nphy_def_lnagains[3] + gain_delta[core];
+		} else {
+			for (ctr = 0; ctr < 4; ctr++)
+				regval[ctr] =
+					nphy_def_lnagains[ctr] +
+					gain_delta[core];
+		}
+		wlc_phy_table_write_nphy(pi, core, 4, 8, 16, regval);
+
+		minmax_gain[core] =
+			(u16) (nphy_def_lnagains[2] + gain_delta[core] + 4);
+	}
+
+	mod_phy_reg(pi, 0x1e, (0xff << 0), (minmax_gain[0] << 0));
+	mod_phy_reg(pi, 0x34, (0xff << 0), (minmax_gain[1] << 0));
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void
+wlc_phy_war_force_trsw_to_R_cliplo_nphy(struct brcms_phy *pi, u8 core)
+{
+	if (core == PHY_CORE_0) {
+		write_phy_reg(pi, 0x38, 0x4);
+		if (CHSPEC_IS2G(pi->radio_chanspec))
+			write_phy_reg(pi, 0x37, 0x0060);
+		else
+			write_phy_reg(pi, 0x37, 0x1080);
+	} else if (core == PHY_CORE_1) {
+		write_phy_reg(pi, 0x2ae, 0x4);
+		if (CHSPEC_IS2G(pi->radio_chanspec))
+			write_phy_reg(pi, 0x2ad, 0x0060);
+		else
+			write_phy_reg(pi, 0x2ad, 0x1080);
+	}
+}
+
+static void wlc_phy_war_txchain_upd_nphy(struct brcms_phy *pi, u8 txchain)
+{
+	u8 txchain0, txchain1;
+
+	txchain0 = txchain & 0x1;
+	txchain1 = (txchain & 0x2) >> 1;
+	if (!txchain0)
+		wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0);
+
+	if (!txchain1)
+		wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1);
+}
+
+static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(struct brcms_phy *pi)
+{
+	s8 lna1_gain_db[] = { 8, 13, 17, 22 };
+	s8 lna2_gain_db[] = { -2, 7, 11, 15 };
+	s8 tia_gain_db[] = { -4, -1, 2, 5, 5, 5, 5, 5, 5, 5 };
+	s8 tia_gainbits[] = {
+		0x0, 0x01, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
+
+	mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+	mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+
+	mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0));
+
+	mod_phy_reg(pi, 0x283, (0xff << 0), (0x3c << 0));
+	mod_phy_reg(pi, 0x280, (0xff << 0), (0x3c << 0));
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x8, 8,
+				 lna1_gain_db);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x8, 8,
+				 lna1_gain_db);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10, 8,
+				 lna2_gain_db);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10, 8,
+				 lna2_gain_db);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8,
+				 tia_gain_db);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8,
+				 tia_gain_db);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8,
+				 tia_gainbits);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8,
+				 tia_gainbits);
+
+	write_phy_reg(pi, 0x37, 0x74);
+	write_phy_reg(pi, 0x2ad, 0x74);
+	write_phy_reg(pi, 0x38, 0x18);
+	write_phy_reg(pi, 0x2ae, 0x18);
+
+	write_phy_reg(pi, 0x2b, 0xe8);
+	write_phy_reg(pi, 0x41, 0xe8);
+
+	if (CHSPEC_IS20(pi->radio_chanspec)) {
+
+		mod_phy_reg(pi, 0x300, (0x3f << 0), (0x12 << 0));
+		mod_phy_reg(pi, 0x301, (0x3f << 0), (0x12 << 0));
+	} else {
+
+		mod_phy_reg(pi, 0x300, (0x3f << 0), (0x10 << 0));
+		mod_phy_reg(pi, 0x301, (0x3f << 0), (0x10 << 0));
+	}
+}
+
+static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi)
+{
+	u16 currband;
+	static const s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 };
+	const s8 *lna1_gain_db = NULL;
+	const s8 *lna1_gain_db_2 = NULL;
+	const s8 *lna2_gain_db = NULL;
+	static const s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 };
+	const s8 *tia_gain_db;
+	static const s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 };
+	const s8 *tia_gainbits;
+	static const u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f };
+	const u16 *rfseq_init_gain;
+	u16 init_gaincode;
+	u16 clip1hi_gaincode;
+	u16 clip1md_gaincode = 0;
+	u16 clip1md_gaincode_B;
+	u16 clip1lo_gaincode;
+	u16 clip1lo_gaincode_B;
+	u8 crsminl_th = 0;
+	u8 crsminu_th;
+	u16 nbclip_th = 0;
+	u8 w1clip_th;
+	u16 freq;
+	s8 nvar_baseline_offset0 = 0, nvar_baseline_offset1 = 0;
+	u8 chg_nbclip_th = 0;
+
+	mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+	mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+
+	currband = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
+	if (currband == 0) {
+
+		lna1_gain_db = lna1G_gain_db_rev7;
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8,
+					 lna1_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8,
+					 lna1_gain_db);
+
+		mod_phy_reg(pi, 0x283, (0xff << 0), (0x40 << 0));
+
+		if (CHSPEC_IS40(pi->radio_chanspec)) {
+			mod_phy_reg(pi, 0x280, (0xff << 0), (0x3e << 0));
+			mod_phy_reg(pi, 0x283, (0xff << 0), (0x3e << 0));
+		}
+
+		mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0));
+
+		if (CHSPEC_IS20(pi->radio_chanspec)) {
+			mod_phy_reg(pi, 0x300, (0x3f << 0), (13 << 0));
+			mod_phy_reg(pi, 0x301, (0x3f << 0), (13 << 0));
+		}
+	} else {
+
+		init_gaincode = 0x9e;
+		clip1hi_gaincode = 0x9e;
+		clip1md_gaincode_B = 0x24;
+		clip1lo_gaincode = 0x8a;
+		clip1lo_gaincode_B = 8;
+		rfseq_init_gain = rfseqA_init_gain_rev7;
+
+		tia_gain_db = tiaA_gain_db_rev7;
+		tia_gainbits = tiaA_gainbits_rev7;
+
+		freq = CHAN5G_FREQ(CHSPEC_CHANNEL(pi->radio_chanspec));
+		if (CHSPEC_IS20(pi->radio_chanspec)) {
+
+			w1clip_th = 25;
+			clip1md_gaincode = 0x82;
+
+			if ((freq <= 5080) || (freq == 5825)) {
+
+				static const s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 };
+				static const s8 lna1A_gain_db_2_rev7[] = { 11, 17, 22, 25};
+				static const s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
+
+				crsminu_th = 0x3e;
+				lna1_gain_db = lna1A_gain_db_rev7;
+				lna1_gain_db_2 = lna1A_gain_db_2_rev7;
+				lna2_gain_db = lna2A_gain_db_rev7;
+			} else if ((freq >= 5500) && (freq <= 5700)) {
+
+				static const s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 };
+				static const s8 lna1A_gain_db_2_rev7[] = { 12, 18, 22, 26};
+				static const s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 };
+
+				crsminu_th = 0x45;
+				clip1md_gaincode_B = 0x14;
+				nbclip_th = 0xff;
+				chg_nbclip_th = 1;
+				lna1_gain_db = lna1A_gain_db_rev7;
+				lna1_gain_db_2 = lna1A_gain_db_2_rev7;
+				lna2_gain_db = lna2A_gain_db_rev7;
+			} else {
+
+				static const s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 };
+				static const s8 lna1A_gain_db_2_rev7[] = { 12, 18, 22, 26};
+				static const s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
+
+				crsminu_th = 0x41;
+				lna1_gain_db = lna1A_gain_db_rev7;
+				lna1_gain_db_2 = lna1A_gain_db_2_rev7;
+				lna2_gain_db = lna2A_gain_db_rev7;
+			}
+
+			if (freq <= 4920) {
+				nvar_baseline_offset0 = 5;
+				nvar_baseline_offset1 = 5;
+			} else if ((freq > 4920) && (freq <= 5320)) {
+				nvar_baseline_offset0 = 3;
+				nvar_baseline_offset1 = 5;
+			} else if ((freq > 5320) && (freq <= 5700)) {
+				nvar_baseline_offset0 = 3;
+				nvar_baseline_offset1 = 2;
+			} else {
+				nvar_baseline_offset0 = 4;
+				nvar_baseline_offset1 = 0;
+			}
+		} else {
+
+			crsminu_th = 0x3a;
+			crsminl_th = 0x3a;
+			w1clip_th = 20;
+
+			if ((freq >= 4920) && (freq <= 5320)) {
+				nvar_baseline_offset0 = 4;
+				nvar_baseline_offset1 = 5;
+			} else if ((freq > 5320) && (freq <= 5550)) {
+				nvar_baseline_offset0 = 4;
+				nvar_baseline_offset1 = 2;
+			} else {
+				nvar_baseline_offset0 = 5;
+				nvar_baseline_offset1 = 3;
+			}
+		}
+
+		write_phy_reg(pi, 0x20, init_gaincode);
+		write_phy_reg(pi, 0x2a7, init_gaincode);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+					 pi->pubpi.phy_corenum, 0x106, 16,
+					 rfseq_init_gain);
+
+		write_phy_reg(pi, 0x22, clip1hi_gaincode);
+		write_phy_reg(pi, 0x2a9, clip1hi_gaincode);
+
+		write_phy_reg(pi, 0x36, clip1md_gaincode_B);
+		write_phy_reg(pi, 0x2ac, clip1md_gaincode_B);
+
+		write_phy_reg(pi, 0x37, clip1lo_gaincode);
+		write_phy_reg(pi, 0x2ad, clip1lo_gaincode);
+		write_phy_reg(pi, 0x38, clip1lo_gaincode_B);
+		write_phy_reg(pi, 0x2ae, clip1lo_gaincode_B);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8,
+					 tia_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8,
+					 tia_gain_db);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8,
+					 tia_gainbits);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8,
+					 tia_gainbits);
+
+		mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0));
+
+		if (chg_nbclip_th == 1) {
+			write_phy_reg(pi, 0x2b, nbclip_th);
+			write_phy_reg(pi, 0x41, nbclip_th);
+		}
+
+		mod_phy_reg(pi, 0x300, (0x3f << 0), (w1clip_th << 0));
+		mod_phy_reg(pi, 0x301, (0x3f << 0), (w1clip_th << 0));
+
+		mod_phy_reg(pi, 0x2e4,
+			    (0x3f << 0), (nvar_baseline_offset0 << 0));
+
+		mod_phy_reg(pi, 0x2e4,
+			    (0x3f << 6), (nvar_baseline_offset1 << 6));
+
+		if (CHSPEC_IS20(pi->radio_chanspec)) {
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8,
+						 lna1_gain_db);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8,
+						 lna1_gain_db_2);
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10,
+						 8, lna2_gain_db);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10,
+						 8, lna2_gain_db);
+
+			write_phy_reg(pi, 0x24, clip1md_gaincode);
+			write_phy_reg(pi, 0x2ab, clip1md_gaincode);
+		} else {
+			mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0));
+		}
+	}
+}
+
+static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi)
+{
+	u16 w1th, hpf_code, currband;
+	int ctr;
+	u8 rfseq_updategainu_events[] = {
+		NPHY_RFSEQ_CMD_RX_GAIN,
+		NPHY_RFSEQ_CMD_CLR_HIQ_DIS,
+		NPHY_RFSEQ_CMD_SET_HPF_BW
+	};
+	static const u8 rfseq_updategainu_dlys[] = { 10, 30, 1 };
+	static const s8 lna1G_gain_db[] = { 7, 11, 16, 23 };
+	static const s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 };
+	static const s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 };
+	static const s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 };
+	static const s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 };
+	static const s8 lna1A_gain_db[] = { 7, 11, 17, 23 };
+	static const s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 };
+	static const s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 };
+	static const s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 };
+	const s8 *lna1_gain_db = NULL;
+	static const s8 lna2G_gain_db[] = { -5, 6, 10, 14 };
+	static const s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 };
+	static const s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 };
+	static const s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 };
+	static const s8 lna2A_gain_db[] = { -6, 2, 6, 10 };
+	static const s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 };
+	static const s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 };
+	static const s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 };
+	const s8 *lna2_gain_db = NULL;
+	static const s8 tiaG_gain_db[] = {
+		0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A };
+	static const s8 tiaA_gain_db[] = {
+		0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 };
+	static const s8 tiaA_gain_db_rev4[] = {
+		0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
+	static const s8 tiaA_gain_db_rev5[] = {
+		0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
+	static const s8 tiaA_gain_db_rev6[] = {
+		0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
+	const s8 *tia_gain_db;
+	static const s8 tiaG_gainbits[] = {
+		0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
+	static const s8 tiaA_gainbits[] = {
+		0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06 };
+	static const s8 tiaA_gainbits_rev4[] = {
+		0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
+	static const s8 tiaA_gainbits_rev5[] = {
+		0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
+	static const s8 tiaA_gainbits_rev6[] = {
+		0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
+	const s8 *tia_gainbits;
+	static const s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 };
+	static const s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 };
+	static const u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f };
+	static const u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f };
+	static const u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f };
+	static const u16 rfseqG_init_gain_rev5_elna[] = {
+		0x013f, 0x013f, 0x013f, 0x013f };
+	static const u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f };
+	static const u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f };
+	static const u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f };
+	static const u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f };
+	static const u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f };
+	static const u16 rfseqA_init_gain_rev4_elna[] = {
+		0x314f, 0x314f, 0x314f, 0x314f };
+	static const u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f };
+	static const u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f };
+	const u16 *rfseq_init_gain;
+	u16 initG_gaincode = 0x627e;
+	u16 initG_gaincode_rev4 = 0x527e;
+	u16 initG_gaincode_rev5 = 0x427e;
+	u16 initG_gaincode_rev5_elna = 0x027e;
+	u16 initG_gaincode_rev6 = 0x527e;
+	u16 initG_gaincode_rev6_224B0 = 0x427e;
+	u16 initG_gaincode_rev6_elna = 0x127e;
+	u16 initA_gaincode = 0x52de;
+	u16 initA_gaincode_rev4 = 0x629e;
+	u16 initA_gaincode_rev4_elna = 0x329e;
+	u16 initA_gaincode_rev5 = 0x729e;
+	u16 initA_gaincode_rev6 = 0x729e;
+	u16 init_gaincode;
+	u16 clip1hiG_gaincode = 0x107e;
+	u16 clip1hiG_gaincode_rev4 = 0x007e;
+	u16 clip1hiG_gaincode_rev5 = 0x1076;
+	u16 clip1hiG_gaincode_rev6 = 0x007e;
+	u16 clip1hiA_gaincode = 0x00de;
+	u16 clip1hiA_gaincode_rev4 = 0x029e;
+	u16 clip1hiA_gaincode_rev5 = 0x029e;
+	u16 clip1hiA_gaincode_rev6 = 0x029e;
+	u16 clip1hi_gaincode;
+	u16 clip1mdG_gaincode = 0x0066;
+	u16 clip1mdA_gaincode = 0x00ca;
+	u16 clip1mdA_gaincode_rev4 = 0x1084;
+	u16 clip1mdA_gaincode_rev5 = 0x2084;
+	u16 clip1mdA_gaincode_rev6 = 0x2084;
+	u16 clip1md_gaincode = 0;
+	u16 clip1loG_gaincode = 0x0074;
+	static const u16 clip1loG_gaincode_rev5[] = {
+		0x0062, 0x0064, 0x006a, 0x106a, 0x106c, 0x1074, 0x107c, 0x207c
+	};
+	static const u16 clip1loG_gaincode_rev6[] = {
+		0x106a, 0x106c, 0x1074, 0x107c, 0x007e, 0x107e, 0x207e, 0x307e
+	};
+	u16 clip1loG_gaincode_rev6_224B0 = 0x1074;
+	u16 clip1loA_gaincode = 0x00cc;
+	u16 clip1loA_gaincode_rev4 = 0x0086;
+	u16 clip1loA_gaincode_rev5 = 0x2086;
+	u16 clip1loA_gaincode_rev6 = 0x2086;
+	u16 clip1lo_gaincode;
+	u8 crsminG_th = 0x18;
+	u8 crsminG_th_rev5 = 0x18;
+	u8 crsminG_th_rev6 = 0x18;
+	u8 crsminA_th = 0x1e;
+	u8 crsminA_th_rev4 = 0x24;
+	u8 crsminA_th_rev5 = 0x24;
+	u8 crsminA_th_rev6 = 0x24;
+	u8 crsmin_th;
+	u8 crsminlG_th = 0x18;
+	u8 crsminlG_th_rev5 = 0x18;
+	u8 crsminlG_th_rev6 = 0x18;
+	u8 crsminlA_th = 0x1e;
+	u8 crsminlA_th_rev4 = 0x24;
+	u8 crsminlA_th_rev5 = 0x24;
+	u8 crsminlA_th_rev6 = 0x24;
+	u8 crsminl_th = 0;
+	u8 crsminuG_th = 0x18;
+	u8 crsminuG_th_rev5 = 0x18;
+	u8 crsminuG_th_rev6 = 0x18;
+	u8 crsminuA_th = 0x1e;
+	u8 crsminuA_th_rev4 = 0x24;
+	u8 crsminuA_th_rev5 = 0x24;
+	u8 crsminuA_th_rev6 = 0x24;
+	u8 crsminuA_th_rev6_224B0 = 0x2d;
+	u8 crsminu_th;
+	u16 nbclipG_th = 0x20d;
+	u16 nbclipG_th_rev4 = 0x1a1;
+	u16 nbclipG_th_rev5 = 0x1d0;
+	u16 nbclipG_th_rev6 = 0x1d0;
+	u16 nbclipA_th = 0x1a1;
+	u16 nbclipA_th_rev4 = 0x107;
+	u16 nbclipA_th_rev5 = 0x0a9;
+	u16 nbclipA_th_rev6 = 0x0f0;
+	u16 nbclip_th = 0;
+	u8 w1clipG_th = 5;
+	u8 w1clipG_th_rev5 = 9;
+	u8 w1clipG_th_rev6 = 5;
+	u8 w1clipA_th = 25, w1clip_th;
+	u8 rssi_gain_default = 0x50;
+	u8 rssiG_gain_rev6_224B0 = 0x50;
+	u8 rssiA_gain_rev5 = 0x90;
+	u8 rssiA_gain_rev6 = 0x90;
+	u8 rssi_gain;
+	u16 regval[21];
+	u8 triso;
+
+	triso = (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.triso :
+		pi->srom_fem2g.triso;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		if (pi->pubpi.radiorev == 5) {
+			wlc_phy_workarounds_nphy_gainctrl_2057_rev5(pi);
+		} else if (pi->pubpi.radiorev == 7) {
+			wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
+
+			mod_phy_reg(pi, 0x283, (0xff << 0), (0x44 << 0));
+			mod_phy_reg(pi, 0x280, (0xff << 0), (0x44 << 0));
+
+		} else if ((pi->pubpi.radiorev == 3)
+			   || (pi->pubpi.radiorev == 8)) {
+			wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
+
+			if (pi->pubpi.radiorev == 8) {
+				mod_phy_reg(pi, 0x283,
+					    (0xff << 0), (0x44 << 0));
+				mod_phy_reg(pi, 0x280,
+					    (0xff << 0), (0x44 << 0));
+			}
+		} else {
+			wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
+		}
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+		mod_phy_reg(pi, 0xa0, (0x1 << 6), (1 << 6));
+
+		mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+		mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+
+		currband =
+			read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
+		if (currband == 0) {
+			if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+				if (pi->pubpi.radiorev == 11) {
+					lna1_gain_db = lna1G_gain_db_rev6_224B0;
+					lna2_gain_db = lna2G_gain_db_rev6_224B0;
+					rfseq_init_gain =
+						rfseqG_init_gain_rev6_224B0;
+					init_gaincode =
+						initG_gaincode_rev6_224B0;
+					clip1hi_gaincode =
+						clip1hiG_gaincode_rev6;
+					clip1lo_gaincode =
+						clip1loG_gaincode_rev6_224B0;
+					nbclip_th = nbclipG_th_rev6;
+					w1clip_th = w1clipG_th_rev6;
+					crsmin_th = crsminG_th_rev6;
+					crsminl_th = crsminlG_th_rev6;
+					crsminu_th = crsminuG_th_rev6;
+					rssi_gain = rssiG_gain_rev6_224B0;
+				} else {
+					lna1_gain_db = lna1G_gain_db_rev6;
+					lna2_gain_db = lna2G_gain_db_rev6;
+					if (pi->sh->boardflags & BFL_EXTLNA) {
+
+						rfseq_init_gain =
+						     rfseqG_init_gain_rev6_elna;
+						init_gaincode =
+						       initG_gaincode_rev6_elna;
+					} else {
+						rfseq_init_gain =
+							rfseqG_init_gain_rev6;
+						init_gaincode =
+							initG_gaincode_rev6;
+					}
+					clip1hi_gaincode =
+						clip1hiG_gaincode_rev6;
+					switch (triso) {
+					case 0:
+						clip1lo_gaincode =
+							clip1loG_gaincode_rev6
+							[0];
+						break;
+					case 1:
+						clip1lo_gaincode =
+							clip1loG_gaincode_rev6
+							[1];
+						break;
+					case 2:
+						clip1lo_gaincode =
+							clip1loG_gaincode_rev6
+							[2];
+						break;
+					case 3:
+					default:
+
+						clip1lo_gaincode =
+							clip1loG_gaincode_rev6
+							[3];
+						break;
+					case 4:
+						clip1lo_gaincode =
+							clip1loG_gaincode_rev6
+							[4];
+						break;
+					case 5:
+						clip1lo_gaincode =
+							clip1loG_gaincode_rev6
+							[5];
+						break;
+					case 6:
+						clip1lo_gaincode =
+							clip1loG_gaincode_rev6
+							[6];
+						break;
+					case 7:
+						clip1lo_gaincode =
+							clip1loG_gaincode_rev6
+							[7];
+						break;
+					}
+					nbclip_th = nbclipG_th_rev6;
+					w1clip_th = w1clipG_th_rev6;
+					crsmin_th = crsminG_th_rev6;
+					crsminl_th = crsminlG_th_rev6;
+					crsminu_th = crsminuG_th_rev6;
+					rssi_gain = rssi_gain_default;
+				}
+			} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+				lna1_gain_db = lna1G_gain_db_rev5;
+				lna2_gain_db = lna2G_gain_db_rev5;
+				if (pi->sh->boardflags & BFL_EXTLNA) {
+
+					rfseq_init_gain =
+						rfseqG_init_gain_rev5_elna;
+					init_gaincode =
+						initG_gaincode_rev5_elna;
+				} else {
+					rfseq_init_gain = rfseqG_init_gain_rev5;
+					init_gaincode = initG_gaincode_rev5;
+				}
+				clip1hi_gaincode = clip1hiG_gaincode_rev5;
+				switch (triso) {
+				case 0:
+					clip1lo_gaincode =
+						clip1loG_gaincode_rev5[0];
+					break;
+				case 1:
+					clip1lo_gaincode =
+						clip1loG_gaincode_rev5[1];
+					break;
+				case 2:
+					clip1lo_gaincode =
+						clip1loG_gaincode_rev5[2];
+					break;
+				case 3:
+
+					clip1lo_gaincode =
+						clip1loG_gaincode_rev5[3];
+					break;
+				case 4:
+					clip1lo_gaincode =
+						clip1loG_gaincode_rev5[4];
+					break;
+				case 5:
+					clip1lo_gaincode =
+						clip1loG_gaincode_rev5[5];
+					break;
+				case 6:
+					clip1lo_gaincode =
+						clip1loG_gaincode_rev5[6];
+					break;
+				case 7:
+					clip1lo_gaincode =
+						clip1loG_gaincode_rev5[7];
+					break;
+				default:
+					clip1lo_gaincode =
+						clip1loG_gaincode_rev5[3];
+					break;
+				}
+				nbclip_th = nbclipG_th_rev5;
+				w1clip_th = w1clipG_th_rev5;
+				crsmin_th = crsminG_th_rev5;
+				crsminl_th = crsminlG_th_rev5;
+				crsminu_th = crsminuG_th_rev5;
+				rssi_gain = rssi_gain_default;
+			} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+				lna1_gain_db = lna1G_gain_db_rev4;
+				lna2_gain_db = lna2G_gain_db;
+				rfseq_init_gain = rfseqG_init_gain_rev4;
+				init_gaincode = initG_gaincode_rev4;
+				clip1hi_gaincode = clip1hiG_gaincode_rev4;
+				clip1lo_gaincode = clip1loG_gaincode;
+				nbclip_th = nbclipG_th_rev4;
+				w1clip_th = w1clipG_th;
+				crsmin_th = crsminG_th;
+				crsminl_th = crsminlG_th;
+				crsminu_th = crsminuG_th;
+				rssi_gain = rssi_gain_default;
+			} else {
+				lna1_gain_db = lna1G_gain_db;
+				lna2_gain_db = lna2G_gain_db;
+				rfseq_init_gain = rfseqG_init_gain;
+				init_gaincode = initG_gaincode;
+				clip1hi_gaincode = clip1hiG_gaincode;
+				clip1lo_gaincode = clip1loG_gaincode;
+				nbclip_th = nbclipG_th;
+				w1clip_th = w1clipG_th;
+				crsmin_th = crsminG_th;
+				crsminl_th = crsminlG_th;
+				crsminu_th = crsminuG_th;
+				rssi_gain = rssi_gain_default;
+			}
+			tia_gain_db = tiaG_gain_db;
+			tia_gainbits = tiaG_gainbits;
+			clip1md_gaincode = clip1mdG_gaincode;
+		} else {
+			if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+				lna1_gain_db = lna1A_gain_db_rev6;
+				lna2_gain_db = lna2A_gain_db_rev6;
+				tia_gain_db = tiaA_gain_db_rev6;
+				tia_gainbits = tiaA_gainbits_rev6;
+				rfseq_init_gain = rfseqA_init_gain_rev6;
+				init_gaincode = initA_gaincode_rev6;
+				clip1hi_gaincode = clip1hiA_gaincode_rev6;
+				clip1md_gaincode = clip1mdA_gaincode_rev6;
+				clip1lo_gaincode = clip1loA_gaincode_rev6;
+				crsmin_th = crsminA_th_rev6;
+				crsminl_th = crsminlA_th_rev6;
+				if ((pi->pubpi.radiorev == 11) &&
+				    (CHSPEC_IS40(pi->radio_chanspec) == 0))
+					crsminu_th = crsminuA_th_rev6_224B0;
+				else
+					crsminu_th = crsminuA_th_rev6;
+
+				nbclip_th = nbclipA_th_rev6;
+				rssi_gain = rssiA_gain_rev6;
+			} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+				lna1_gain_db = lna1A_gain_db_rev5;
+				lna2_gain_db = lna2A_gain_db_rev5;
+				tia_gain_db = tiaA_gain_db_rev5;
+				tia_gainbits = tiaA_gainbits_rev5;
+				rfseq_init_gain = rfseqA_init_gain_rev5;
+				init_gaincode = initA_gaincode_rev5;
+				clip1hi_gaincode = clip1hiA_gaincode_rev5;
+				clip1md_gaincode = clip1mdA_gaincode_rev5;
+				clip1lo_gaincode = clip1loA_gaincode_rev5;
+				crsmin_th = crsminA_th_rev5;
+				crsminl_th = crsminlA_th_rev5;
+				crsminu_th = crsminuA_th_rev5;
+				nbclip_th = nbclipA_th_rev5;
+				rssi_gain = rssiA_gain_rev5;
+			} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+				lna1_gain_db = lna1A_gain_db_rev4;
+				lna2_gain_db = lna2A_gain_db_rev4;
+				tia_gain_db = tiaA_gain_db_rev4;
+				tia_gainbits = tiaA_gainbits_rev4;
+				if (pi->sh->boardflags & BFL_EXTLNA_5GHz) {
+
+					rfseq_init_gain =
+						rfseqA_init_gain_rev4_elna;
+					init_gaincode =
+						initA_gaincode_rev4_elna;
+				} else {
+					rfseq_init_gain = rfseqA_init_gain_rev4;
+					init_gaincode = initA_gaincode_rev4;
+				}
+				clip1hi_gaincode = clip1hiA_gaincode_rev4;
+				clip1md_gaincode = clip1mdA_gaincode_rev4;
+				clip1lo_gaincode = clip1loA_gaincode_rev4;
+				crsmin_th = crsminA_th_rev4;
+				crsminl_th = crsminlA_th_rev4;
+				crsminu_th = crsminuA_th_rev4;
+				nbclip_th = nbclipA_th_rev4;
+				rssi_gain = rssi_gain_default;
+			} else {
+				lna1_gain_db = lna1A_gain_db;
+				lna2_gain_db = lna2A_gain_db;
+				tia_gain_db = tiaA_gain_db;
+				tia_gainbits = tiaA_gainbits;
+				rfseq_init_gain = rfseqA_init_gain;
+				init_gaincode = initA_gaincode;
+				clip1hi_gaincode = clip1hiA_gaincode;
+				clip1md_gaincode = clip1mdA_gaincode;
+				clip1lo_gaincode = clip1loA_gaincode;
+				crsmin_th = crsminA_th;
+				crsminl_th = crsminlA_th;
+				crsminu_th = crsminuA_th;
+				nbclip_th = nbclipA_th;
+				rssi_gain = rssi_gain_default;
+			}
+			w1clip_th = w1clipA_th;
+		}
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_BIASPOLE_LNAG1_IDAC |
+				 RADIO_2056_RX0), 0x17);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_BIASPOLE_LNAG1_IDAC |
+				 RADIO_2056_RX1), 0x17);
+
+		write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX0),
+				0xf0);
+		write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX1),
+				0xf0);
+
+		write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX0),
+				0x0);
+		write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX1),
+				0x0);
+
+		write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX0),
+				rssi_gain);
+		write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX1),
+				rssi_gain);
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_BIASPOLE_LNAA1_IDAC |
+				 RADIO_2056_RX0), 0x17);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_BIASPOLE_LNAA1_IDAC |
+				 RADIO_2056_RX1), 0x17);
+
+		write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX0),
+				0xFF);
+		write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX1),
+				0xFF);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8,
+					 8, lna1_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8,
+					 8, lna1_gain_db);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10,
+					 8, lna2_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10,
+					 8, lna2_gain_db);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20,
+					 8, tia_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20,
+					 8, tia_gain_db);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20,
+					 8, tia_gainbits);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20,
+					 8, tia_gainbits);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 6, 0x40,
+					 8, &lpf_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 6, 0x40,
+					 8, &lpf_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 6, 0x40,
+					 8, &lpf_gainbits);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 6, 0x40,
+					 8, &lpf_gainbits);
+
+		write_phy_reg(pi, 0x20, init_gaincode);
+		write_phy_reg(pi, 0x2a7, init_gaincode);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+					 pi->pubpi.phy_corenum, 0x106, 16,
+					 rfseq_init_gain);
+
+		write_phy_reg(pi, 0x22, clip1hi_gaincode);
+		write_phy_reg(pi, 0x2a9, clip1hi_gaincode);
+
+		write_phy_reg(pi, 0x24, clip1md_gaincode);
+		write_phy_reg(pi, 0x2ab, clip1md_gaincode);
+
+		write_phy_reg(pi, 0x37, clip1lo_gaincode);
+		write_phy_reg(pi, 0x2ad, clip1lo_gaincode);
+
+		mod_phy_reg(pi, 0x27d, (0xff << 0), (crsmin_th << 0));
+		mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0));
+		mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0));
+
+		write_phy_reg(pi, 0x2b, nbclip_th);
+		write_phy_reg(pi, 0x41, nbclip_th);
+
+		mod_phy_reg(pi, 0x27, (0x3f << 0), (w1clip_th << 0));
+		mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1clip_th << 0));
+
+		write_phy_reg(pi, 0x150, 0x809c);
+
+	} else {
+
+		mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+		mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+
+		write_phy_reg(pi, 0x2b, 0x84);
+		write_phy_reg(pi, 0x41, 0x84);
+
+		if (CHSPEC_IS20(pi->radio_chanspec)) {
+			write_phy_reg(pi, 0x6b, 0x2b);
+			write_phy_reg(pi, 0x6c, 0x2b);
+			write_phy_reg(pi, 0x6d, 0x9);
+			write_phy_reg(pi, 0x6e, 0x9);
+		}
+
+		w1th = NPHY_RSSICAL_W1_TARGET - 4;
+		mod_phy_reg(pi, 0x27, (0x3f << 0), (w1th << 0));
+		mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1th << 0));
+
+		if (CHSPEC_IS20(pi->radio_chanspec)) {
+			mod_phy_reg(pi, 0x1c, (0x1f << 0), (0x1 << 0));
+			mod_phy_reg(pi, 0x32, (0x1f << 0), (0x1 << 0));
+
+			mod_phy_reg(pi, 0x1d, (0x1f << 0), (0x1 << 0));
+			mod_phy_reg(pi, 0x33, (0x1f << 0), (0x1 << 0));
+		}
+
+		write_phy_reg(pi, 0x150, 0x809c);
+
+		if (pi->nphy_gain_boost)
+			if ((CHSPEC_IS2G(pi->radio_chanspec)) &&
+			    (CHSPEC_IS40(pi->radio_chanspec)))
+				hpf_code = 4;
+			else
+				hpf_code = 5;
+		else if (CHSPEC_IS40(pi->radio_chanspec))
+			hpf_code = 6;
+		else
+			hpf_code = 7;
+
+		mod_phy_reg(pi, 0x20, (0x1f << 7), (hpf_code << 7));
+		mod_phy_reg(pi, 0x36, (0x1f << 7), (hpf_code << 7));
+
+		for (ctr = 0; ctr < 4; ctr++)
+			regval[ctr] = (hpf_code << 8) | 0x7c;
+		wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval);
+
+		wlc_phy_adjust_lnagaintbl_nphy(pi);
+
+		if (pi->nphy_elna_gain_config) {
+			regval[0] = 0;
+			regval[1] = 1;
+			regval[2] = 1;
+			regval[3] = 1;
+			wlc_phy_table_write_nphy(pi, 2, 4, 8, 16, regval);
+			wlc_phy_table_write_nphy(pi, 3, 4, 8, 16, regval);
+
+			for (ctr = 0; ctr < 4; ctr++)
+				regval[ctr] = (hpf_code << 8) | 0x74;
+			wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval);
+		}
+
+		if (NREV_IS(pi->pubpi.phy_rev, 2)) {
+			for (ctr = 0; ctr < 21; ctr++)
+				regval[ctr] = 3 * ctr;
+			wlc_phy_table_write_nphy(pi, 0, 21, 32, 16, regval);
+			wlc_phy_table_write_nphy(pi, 1, 21, 32, 16, regval);
+
+			for (ctr = 0; ctr < 21; ctr++)
+				regval[ctr] = (u16) ctr;
+			wlc_phy_table_write_nphy(pi, 2, 21, 32, 16, regval);
+			wlc_phy_table_write_nphy(pi, 3, 21, 32, 16, regval);
+		}
+
+		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_UPDATEGAINU,
+				       rfseq_updategainu_events,
+				       rfseq_updategainu_dlys,
+				       ARRAY_SIZE(rfseq_updategainu_events));
+
+		mod_phy_reg(pi, 0x153, (0xff << 8), (90 << 8));
+
+		if (CHSPEC_IS2G(pi->radio_chanspec))
+			mod_phy_reg(pi,
+				    (NPHY_TO_BPHY_OFF + BPHY_OPTIONAL_MODES),
+				    0x7f, 0x4);
+	}
+}
+
+static void wlc_phy_workarounds_nphy_rev7(struct brcms_phy *pi)
+{
+	static const u8 rfseq_rx2tx_events_rev3_ipa[] = {
+		NPHY_REV3_RFSEQ_CMD_NOP,
+		NPHY_REV3_RFSEQ_CMD_RXG_FBW,
+		NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
+		NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
+		NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
+		NPHY_REV3_RFSEQ_CMD_TX_GAIN,
+		NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS,
+		NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
+		NPHY_REV3_RFSEQ_CMD_END
+	};
+	static const u8 rfseq_rx2tx_dlys_rev3_ipa[] =
+		{ 8, 6, 6, 4, 4, 16, 43, 1, 1 };
+	static const u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f };
+	u32 leg_data_weights;
+	u8 chan_freq_range = 0;
+	static const u16 dac_control = 0x0002;
+	u16 aux_adc_vmid_rev7_core0[] = { 0x8e, 0x96, 0x96, 0x96 };
+	u16 aux_adc_vmid_rev7_core1[] = { 0x8f, 0x9f, 0x9f, 0x96 };
+	u16 aux_adc_gain_rev7[] = { 0x02, 0x02, 0x02, 0x02 };
+	s32 min_nvar_val = 0x18d;
+	s32 min_nvar_offset_6mbps = 20;
+	u8 pdetrange;
+	u16 afectrl_adc_ctrl1_rev7 = 0x20;
+	u16 afectrl_adc_ctrl2_rev7 = 0x0;
+	u16 rfseq_rx2tx_lpf_h_hpc_rev7 = 0x77;
+	u16 rfseq_tx2rx_lpf_h_hpc_rev7 = 0x77;
+	u16 rfseq_pktgn_lpf_h_hpc_rev7 = 0x77;
+	static const u16 rfseq_htpktgn_lpf_hpc_rev7[] = { 0x77, 0x11, 0x11 };
+	static const u16 rfseq_pktgn_lpf_hpc_rev7[] = { 0x11, 0x11 };
+	static const u16 rfseq_cckpktgn_lpf_hpc_rev7[] = { 0x11, 0x11 };
+	u16 ipalvlshift_3p3_war_en = 0;
+	u16 rccal_bcap_val, rccal_scap_val;
+	u16 rccal_tx20_11b_bcap = 0;
+	u16 rccal_tx20_11b_scap = 0;
+	u16 rccal_tx20_11n_bcap = 0;
+	u16 rccal_tx20_11n_scap = 0;
+	u16 rccal_tx40_11n_bcap = 0;
+	u16 rccal_tx40_11n_scap = 0;
+	u16 rx2tx_lpf_rc_lut_tx20_11b = 0;
+	u16 rx2tx_lpf_rc_lut_tx20_11n = 0;
+	u16 rx2tx_lpf_rc_lut_tx40_11n = 0;
+	u16 tx_lpf_bw_ofdm_20mhz = 0;
+	u16 tx_lpf_bw_ofdm_40mhz = 0;
+	u16 tx_lpf_bw_11b = 0;
+	u16 ipa2g_mainbias, ipa2g_casconv, ipa2g_biasfilt;
+	u16 txgm_idac_bleed = 0;
+	bool rccal_ovrd = false;
+	u16 freq;
+	int coreNum;
+
+
+	if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+		mod_phy_reg(pi, 0x221, (0x1 << 4), (1 << 4));
+
+		mod_phy_reg(pi, 0x160, (0x7f << 0), (32 << 0));
+		mod_phy_reg(pi, 0x160, (0x7f << 8), (39 << 8));
+		mod_phy_reg(pi, 0x161, (0x7f << 0), (46 << 0));
+		mod_phy_reg(pi, 0x161, (0x7f << 8), (51 << 8));
+		mod_phy_reg(pi, 0x162, (0x7f << 0), (55 << 0));
+		mod_phy_reg(pi, 0x162, (0x7f << 8), (58 << 8));
+		mod_phy_reg(pi, 0x163, (0x7f << 0), (60 << 0));
+		mod_phy_reg(pi, 0x163, (0x7f << 8), (62 << 8));
+		mod_phy_reg(pi, 0x164, (0x7f << 0), (62 << 0));
+		mod_phy_reg(pi, 0x164, (0x7f << 8), (63 << 8));
+		mod_phy_reg(pi, 0x165, (0x7f << 0), (63 << 0));
+		mod_phy_reg(pi, 0x165, (0x7f << 8), (64 << 8));
+		mod_phy_reg(pi, 0x166, (0x7f << 0), (64 << 0));
+		mod_phy_reg(pi, 0x166, (0x7f << 8), (64 << 8));
+		mod_phy_reg(pi, 0x167, (0x7f << 0), (64 << 0));
+		mod_phy_reg(pi, 0x167, (0x7f << 8), (64 << 8));
+	}
+
+	if (NREV_LE(pi->pubpi.phy_rev, 8)) {
+		write_phy_reg(pi, 0x23f, 0x1b0);
+		write_phy_reg(pi, 0x240, 0x1b0);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 8))
+		mod_phy_reg(pi, 0xbd, (0xff << 0), (114 << 0));
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16,
+				 &dac_control);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16,
+				 &dac_control);
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+				1, 0, 32, &leg_data_weights);
+	leg_data_weights = leg_data_weights & 0xffffff;
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+				 1, 0, 32, &leg_data_weights);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+				 2, 0x15e, 16, rfseq_rx2tx_dacbufpu_rev7);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x16e, 16,
+				 rfseq_rx2tx_dacbufpu_rev7);
+
+	if (PHY_IPA(pi))
+		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
+				       rfseq_rx2tx_events_rev3_ipa,
+				       rfseq_rx2tx_dlys_rev3_ipa,
+				       ARRAY_SIZE
+				       (rfseq_rx2tx_events_rev3_ipa));
+
+	mod_phy_reg(pi, 0x299, (0x3 << 14), (0x1 << 14));
+	mod_phy_reg(pi, 0x29d, (0x3 << 14), (0x1 << 14));
+
+	tx_lpf_bw_ofdm_20mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x154);
+	tx_lpf_bw_ofdm_40mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x159);
+	tx_lpf_bw_11b = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x152);
+
+	if (PHY_IPA(pi)) {
+
+		if (((pi->pubpi.radiorev == 5)
+		     && (CHSPEC_IS40(pi->radio_chanspec) == 1))
+		    || (pi->pubpi.radiorev == 7)
+		    || (pi->pubpi.radiorev == 8)) {
+
+			rccal_bcap_val =
+			    read_radio_reg(pi, RADIO_2057_RCCAL_BCAP_VAL);
+			rccal_scap_val =
+			    read_radio_reg(pi, RADIO_2057_RCCAL_SCAP_VAL);
+
+			rccal_tx20_11b_bcap = rccal_bcap_val;
+			rccal_tx20_11b_scap = rccal_scap_val;
+
+			if ((pi->pubpi.radiorev == 5) &&
+			    (CHSPEC_IS40(pi->radio_chanspec) == 1)) {
+
+				rccal_tx20_11n_bcap = rccal_bcap_val;
+				rccal_tx20_11n_scap = rccal_scap_val;
+				rccal_tx40_11n_bcap = 0xc;
+				rccal_tx40_11n_scap = 0xc;
+
+				rccal_ovrd = true;
+
+			} else if ((pi->pubpi.radiorev == 7)
+				   || (pi->pubpi.radiorev == 8)) {
+
+				tx_lpf_bw_ofdm_20mhz = 4;
+				tx_lpf_bw_11b = 1;
+
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					rccal_tx20_11n_bcap = 0xc;
+					rccal_tx20_11n_scap = 0xc;
+					rccal_tx40_11n_bcap = 0xa;
+					rccal_tx40_11n_scap = 0xa;
+				} else {
+					rccal_tx20_11n_bcap = 0x14;
+					rccal_tx20_11n_scap = 0x14;
+					rccal_tx40_11n_bcap = 0xf;
+					rccal_tx40_11n_scap = 0xf;
+				}
+
+				rccal_ovrd = true;
+			}
+		}
+
+	} else {
+
+		if (pi->pubpi.radiorev == 5) {
+
+			tx_lpf_bw_ofdm_20mhz = 1;
+			tx_lpf_bw_ofdm_40mhz = 3;
+
+			rccal_bcap_val =
+			    read_radio_reg(pi, RADIO_2057_RCCAL_BCAP_VAL);
+			rccal_scap_val =
+			    read_radio_reg(pi, RADIO_2057_RCCAL_SCAP_VAL);
+
+			rccal_tx20_11b_bcap = rccal_bcap_val;
+			rccal_tx20_11b_scap = rccal_scap_val;
+
+			rccal_tx20_11n_bcap = 0x13;
+			rccal_tx20_11n_scap = 0x11;
+			rccal_tx40_11n_bcap = 0x13;
+			rccal_tx40_11n_scap = 0x11;
+
+			rccal_ovrd = true;
+		}
+	}
+
+	if (rccal_ovrd) {
+
+		rx2tx_lpf_rc_lut_tx20_11b =
+		    (rccal_tx20_11b_bcap << 8) |
+		    (rccal_tx20_11b_scap << 3) | tx_lpf_bw_11b;
+		rx2tx_lpf_rc_lut_tx20_11n =
+		    (rccal_tx20_11n_bcap << 8) |
+		    (rccal_tx20_11n_scap << 3) | tx_lpf_bw_ofdm_20mhz;
+		rx2tx_lpf_rc_lut_tx40_11n =
+		    (rccal_tx40_11n_bcap << 8) |
+		    (rccal_tx40_11n_scap << 3) | tx_lpf_bw_ofdm_40mhz;
+
+		for (coreNum = 0; coreNum <= 1; coreNum++) {
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+						 0x152 + coreNum * 0x10, 16,
+						 &rx2tx_lpf_rc_lut_tx20_11b);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+						 0x153 + coreNum * 0x10, 16,
+						 &rx2tx_lpf_rc_lut_tx20_11n);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+						 0x154 + coreNum * 0x10, 16,
+						 &rx2tx_lpf_rc_lut_tx20_11n);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+						 0x155 + coreNum * 0x10, 16,
+						 &rx2tx_lpf_rc_lut_tx40_11n);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+						 0x156 + coreNum * 0x10, 16,
+						 &rx2tx_lpf_rc_lut_tx40_11n);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+						 0x157 + coreNum * 0x10, 16,
+						 &rx2tx_lpf_rc_lut_tx40_11n);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+						 0x158 + coreNum * 0x10, 16,
+						 &rx2tx_lpf_rc_lut_tx40_11n);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+						 0x159 + coreNum * 0x10, 16,
+						 &rx2tx_lpf_rc_lut_tx40_11n);
+		}
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 1, 0x3, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+	}
+
+	write_phy_reg(pi, 0x32f, 0x3);
+
+	if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6))
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1, 0x3, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+
+	if ((pi->pubpi.radiorev == 3) || (pi->pubpi.radiorev == 4) ||
+	    (pi->pubpi.radiorev == 6)) {
+		if ((pi->sh->sromrev >= 8)
+		    && (pi->sh->boardflags2 & BFL2_IPALVLSHIFT_3P3))
+			ipalvlshift_3p3_war_en = 1;
+
+		if (ipalvlshift_3p3_war_en) {
+			write_radio_reg(pi, RADIO_2057_GPAIO_CONFIG, 0x5);
+			write_radio_reg(pi, RADIO_2057_GPAIO_SEL1, 0x30);
+			write_radio_reg(pi, RADIO_2057_GPAIO_SEL0, 0x0);
+			or_radio_reg(pi, RADIO_2057_RXTXBIAS_CONFIG_CORE0, 0x1);
+			or_radio_reg(pi, RADIO_2057_RXTXBIAS_CONFIG_CORE1, 0x1);
+
+			ipa2g_mainbias = 0x1f;
+
+			ipa2g_casconv = 0x6f;
+
+			ipa2g_biasfilt = 0xaa;
+		} else {
+
+			ipa2g_mainbias = 0x2b;
+
+			ipa2g_casconv = 0x7f;
+
+			ipa2g_biasfilt = 0xee;
+		}
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			for (coreNum = 0; coreNum <= 1; coreNum++) {
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+						 coreNum, IPA2G_IMAIN,
+						 ipa2g_mainbias);
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+						 coreNum, IPA2G_CASCONV,
+						 ipa2g_casconv);
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+						 coreNum,
+						 IPA2G_BIAS_FILTER,
+						 ipa2g_biasfilt);
+			}
+		}
+	}
+
+	if (PHY_IPA(pi)) {
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			if ((pi->pubpi.radiorev == 3)
+			    || (pi->pubpi.radiorev == 4)
+			    || (pi->pubpi.radiorev == 6))
+				txgm_idac_bleed = 0x7f;
+
+			for (coreNum = 0; coreNum <= 1; coreNum++) {
+				if (txgm_idac_bleed != 0)
+					WRITE_RADIO_REG4(pi, RADIO_2057,
+							 CORE, coreNum,
+							 TXGM_IDAC_BLEED,
+							 txgm_idac_bleed);
+			}
+
+			if (pi->pubpi.radiorev == 5) {
+				for (coreNum = 0; coreNum <= 1; coreNum++) {
+					WRITE_RADIO_REG4(pi, RADIO_2057,
+							 CORE, coreNum,
+							 IPA2G_CASCONV,
+							 0x13);
+					WRITE_RADIO_REG4(pi, RADIO_2057,
+							 CORE, coreNum,
+							 IPA2G_IMAIN,
+							 0x1f);
+					WRITE_RADIO_REG4(pi, RADIO_2057,
+							 CORE, coreNum,
+							 IPA2G_BIAS_FILTER,
+							 0xee);
+					WRITE_RADIO_REG4(pi, RADIO_2057,
+							 CORE, coreNum,
+							 PAD2G_IDACS,
+							 0x8a);
+					WRITE_RADIO_REG4(pi, RADIO_2057,
+							 CORE, coreNum,
+							 PAD_BIAS_FILTER_BWS,
+							 0x3e);
+				}
+			} else if ((pi->pubpi.radiorev == 7) ||
+				   (pi->pubpi.radiorev == 8)) {
+
+				if (CHSPEC_IS40(pi->radio_chanspec) == 0) {
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 0, IPA2G_IMAIN, 0x14);
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 1, IPA2G_IMAIN, 0x12);
+				} else {
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 0, IPA2G_IMAIN, 0x16);
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 1, IPA2G_IMAIN, 0x16);
+				}
+			}
+
+		} else {
+			freq =
+			    CHAN5G_FREQ(CHSPEC_CHANNEL
+					(pi->radio_chanspec));
+			if (((freq >= 5180) && (freq <= 5230))
+			    || ((freq >= 5745) && (freq <= 5805))) {
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+						 0, IPA5G_BIAS_FILTER, 0xff);
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+						 1, IPA5G_BIAS_FILTER, 0xff);
+			}
+		}
+	} else {
+
+		if (pi->pubpi.radiorev != 5) {
+			for (coreNum = 0; coreNum <= 1; coreNum++) {
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
+						 TXMIX2G_TUNE_BOOST_PU, 0x61);
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
+						 TXGM_IDAC_BLEED, 0x70);
+			}
+		}
+	}
+
+	if (pi->pubpi.radiorev == 4) {
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x05, 16,
+					 &afectrl_adc_ctrl1_rev7);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x15, 16,
+					 &afectrl_adc_ctrl1_rev7);
+
+		for (coreNum = 0; coreNum <= 1; coreNum++) {
+			WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
+					 AFE_VCM_CAL_MASTER, 0x0);
+			WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
+					 AFE_SET_VCM_I, 0x3f);
+			WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
+					 AFE_SET_VCM_Q, 0x3f);
+		}
+	} else {
+		mod_phy_reg(pi, 0xa6, (0x1 << 2), (0x1 << 2));
+		mod_phy_reg(pi, 0x8f, (0x1 << 2), (0x1 << 2));
+		mod_phy_reg(pi, 0xa7, (0x1 << 2), (0x1 << 2));
+		mod_phy_reg(pi, 0xa5, (0x1 << 2), (0x1 << 2));
+
+		mod_phy_reg(pi, 0xa6, (0x1 << 0), 0);
+		mod_phy_reg(pi, 0x8f, (0x1 << 0), (0x1 << 0));
+		mod_phy_reg(pi, 0xa7, (0x1 << 0), 0);
+		mod_phy_reg(pi, 0xa5, (0x1 << 0), (0x1 << 0));
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x05, 16,
+					 &afectrl_adc_ctrl2_rev7);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x15, 16,
+					 &afectrl_adc_ctrl2_rev7);
+
+		mod_phy_reg(pi, 0xa6, (0x1 << 2), 0);
+		mod_phy_reg(pi, 0x8f, (0x1 << 2), 0);
+		mod_phy_reg(pi, 0xa7, (0x1 << 2), 0);
+		mod_phy_reg(pi, 0xa5, (0x1 << 2), 0);
+	}
+
+	write_phy_reg(pi, 0x6a, 0x2);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 256, 32,
+				 &min_nvar_offset_6mbps);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x138, 16,
+				 &rfseq_pktgn_lpf_hpc_rev7);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x141, 16,
+				 &rfseq_pktgn_lpf_h_hpc_rev7);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 3, 0x133, 16,
+				 &rfseq_htpktgn_lpf_hpc_rev7);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x146, 16,
+				 &rfseq_cckpktgn_lpf_hpc_rev7);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x123, 16,
+				 &rfseq_tx2rx_lpf_h_hpc_rev7);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x12A, 16,
+				 &rfseq_rx2tx_lpf_h_hpc_rev7);
+
+	if (CHSPEC_IS40(pi->radio_chanspec) == 0) {
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
+					 32, &min_nvar_val);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+					 127, 32, &min_nvar_val);
+	} else {
+		min_nvar_val = noise_var_tbl_rev7[3];
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
+					 32, &min_nvar_val);
+
+		min_nvar_val = noise_var_tbl_rev7[127];
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+					 127, 32, &min_nvar_val);
+	}
+
+	wlc_phy_workarounds_nphy_gainctrl(pi);
+
+	pdetrange = (CHSPEC_IS5G(pi->radio_chanspec)) ?
+		    pi->srom_fem5g.pdetrange : pi->srom_fem2g.pdetrange;
+
+	if (pdetrange == 0) {
+		chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
+		if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+			aux_adc_vmid_rev7_core0[3] = 0x70;
+			aux_adc_vmid_rev7_core1[3] = 0x70;
+			aux_adc_gain_rev7[3] = 2;
+		} else {
+			aux_adc_vmid_rev7_core0[3] = 0x80;
+			aux_adc_vmid_rev7_core1[3] = 0x80;
+			aux_adc_gain_rev7[3] = 3;
+		}
+	} else if (pdetrange == 1) {
+		if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+			aux_adc_vmid_rev7_core0[3] = 0x7c;
+			aux_adc_vmid_rev7_core1[3] = 0x7c;
+			aux_adc_gain_rev7[3] = 2;
+		} else {
+			aux_adc_vmid_rev7_core0[3] = 0x8c;
+			aux_adc_vmid_rev7_core1[3] = 0x8c;
+			aux_adc_gain_rev7[3] = 1;
+		}
+	} else if (pdetrange == 2) {
+		if (pi->pubpi.radioid == BCM2057_ID) {
+			if ((pi->pubpi.radiorev == 5)
+			    || (pi->pubpi.radiorev == 7)
+			    || (pi->pubpi.radiorev == 8)) {
+				if (chan_freq_range ==
+				    WL_CHAN_FREQ_RANGE_2G) {
+					aux_adc_vmid_rev7_core0[3] = 0x8c;
+					aux_adc_vmid_rev7_core1[3] = 0x8c;
+					aux_adc_gain_rev7[3] = 0;
+				} else {
+					aux_adc_vmid_rev7_core0[3] = 0x96;
+					aux_adc_vmid_rev7_core1[3] = 0x96;
+					aux_adc_gain_rev7[3] = 0;
+				}
+			}
+		}
+
+	} else if (pdetrange == 3) {
+		if (chan_freq_range == WL_CHAN_FREQ_RANGE_2G) {
+			aux_adc_vmid_rev7_core0[3] = 0x89;
+			aux_adc_vmid_rev7_core1[3] = 0x89;
+			aux_adc_gain_rev7[3] = 0;
+		}
+
+	} else if (pdetrange == 5) {
+
+		if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+			aux_adc_vmid_rev7_core0[3] = 0x80;
+			aux_adc_vmid_rev7_core1[3] = 0x80;
+			aux_adc_gain_rev7[3] = 3;
+		} else {
+			aux_adc_vmid_rev7_core0[3] = 0x70;
+			aux_adc_vmid_rev7_core1[3] = 0x70;
+			aux_adc_gain_rev7[3] = 2;
+		}
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x08, 16,
+				 &aux_adc_vmid_rev7_core0);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x18, 16,
+				 &aux_adc_vmid_rev7_core1);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x0c, 16,
+				 &aux_adc_gain_rev7);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x1c, 16,
+				 &aux_adc_gain_rev7);
+}
+
+static void wlc_phy_workarounds_nphy_rev3(struct brcms_phy *pi)
+{
+	static const u8 rfseq_tx2rx_events_rev3[] = {
+		NPHY_REV3_RFSEQ_CMD_EXT_PA,
+		NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
+		NPHY_REV3_RFSEQ_CMD_TX_GAIN,
+		NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
+		NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
+		NPHY_REV3_RFSEQ_CMD_RXG_FBW,
+		NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
+		NPHY_REV3_RFSEQ_CMD_END
+	};
+	static const u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 };
+	u8 rfseq_rx2tx_events_rev3[] = {
+		NPHY_REV3_RFSEQ_CMD_NOP,
+		NPHY_REV3_RFSEQ_CMD_RXG_FBW,
+		NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
+		NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
+		NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
+		NPHY_REV3_RFSEQ_CMD_TX_GAIN,
+		NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
+		NPHY_REV3_RFSEQ_CMD_EXT_PA,
+		NPHY_REV3_RFSEQ_CMD_END
+	};
+	u8 rfseq_rx2tx_dlys_rev3[] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 };
+	static const u8 rfseq_rx2tx_events_rev3_ipa[] = {
+		NPHY_REV3_RFSEQ_CMD_NOP,
+		NPHY_REV3_RFSEQ_CMD_RXG_FBW,
+		NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
+		NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
+		NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
+		NPHY_REV3_RFSEQ_CMD_TX_GAIN,
+		NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS,
+		NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
+		NPHY_REV3_RFSEQ_CMD_END
+	};
+	static const u8 rfseq_rx2tx_dlys_rev3_ipa[] =
+	    { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
+	s16 alpha0, alpha1, alpha2;
+	s16 beta0, beta1, beta2;
+	u32 leg_data_weights, ht_data_weights, nss1_data_weights,
+	    stbc_data_weights;
+	u8 chan_freq_range = 0;
+	static const u16 dac_control = 0x0002;
+	u16 aux_adc_vmid_rev4[] = { 0xa2, 0xb4, 0xb4, 0x89 };
+	u16 aux_adc_vmid_rev3[] = { 0xa2, 0xb4, 0xb4, 0x89 };
+	u16 *aux_adc_vmid;
+	u16 aux_adc_gain_rev4[] = { 0x02, 0x02, 0x02, 0x00 };
+	u16 aux_adc_gain_rev3[] = { 0x02, 0x02, 0x02, 0x00 };
+	u16 *aux_adc_gain;
+	static const u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 };
+	static const u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 };
+	s32 min_nvar_val = 0x18d;
+	u8 pdetrange;
+	u8 triso;
+
+	write_phy_reg(pi, 0x23f, 0x1f8);
+	write_phy_reg(pi, 0x240, 0x1f8);
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+				1, 0, 32, &leg_data_weights);
+	leg_data_weights = leg_data_weights & 0xffffff;
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+				 1, 0, 32, &leg_data_weights);
+
+	alpha0 = 293;
+	alpha1 = 435;
+	alpha2 = 261;
+	beta0 = 366;
+	beta1 = 205;
+	beta2 = 32;
+	write_phy_reg(pi, 0x145, alpha0);
+	write_phy_reg(pi, 0x146, alpha1);
+	write_phy_reg(pi, 0x147, alpha2);
+	write_phy_reg(pi, 0x148, beta0);
+	write_phy_reg(pi, 0x149, beta1);
+	write_phy_reg(pi, 0x14a, beta2);
+
+	write_phy_reg(pi, 0x38, 0xC);
+	write_phy_reg(pi, 0x2ae, 0xC);
+
+	wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX,
+			       rfseq_tx2rx_events_rev3,
+			       rfseq_tx2rx_dlys_rev3,
+			       ARRAY_SIZE(rfseq_tx2rx_events_rev3));
+
+	if (PHY_IPA(pi))
+		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
+				       rfseq_rx2tx_events_rev3_ipa,
+				       rfseq_rx2tx_dlys_rev3_ipa,
+				       ARRAY_SIZE (rfseq_rx2tx_events_rev3_ipa));
+
+	if ((pi->sh->hw_phyrxchain != 0x3) &&
+	    (pi->sh->hw_phyrxchain != pi->sh->hw_phytxchain)) {
+
+		if (PHY_IPA(pi)) {
+			rfseq_rx2tx_dlys_rev3[5] = 59;
+			rfseq_rx2tx_dlys_rev3[6] = 1;
+			rfseq_rx2tx_events_rev3[7] = NPHY_REV3_RFSEQ_CMD_END;
+		}
+
+		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
+				       rfseq_rx2tx_events_rev3,
+				       rfseq_rx2tx_dlys_rev3,
+				       ARRAY_SIZE (rfseq_rx2tx_events_rev3));
+	}
+
+	if (CHSPEC_IS2G(pi->radio_chanspec))
+		write_phy_reg(pi, 0x6a, 0x2);
+	else
+		write_phy_reg(pi, 0x6a, 0x9c40);
+
+	mod_phy_reg(pi, 0x294, (0xf << 8), (7 << 8));
+
+	if (CHSPEC_IS40(pi->radio_chanspec) == 0) {
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
+					 32, &min_nvar_val);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+					 127, 32, &min_nvar_val);
+	} else {
+		min_nvar_val = noise_var_tbl_rev3[3];
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
+					 32, &min_nvar_val);
+
+		min_nvar_val = noise_var_tbl_rev3[127];
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+					 127, 32, &min_nvar_val);
+	}
+
+	wlc_phy_workarounds_nphy_gainctrl(pi);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16,
+				 &dac_control);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16,
+				 &dac_control);
+
+	pdetrange = (CHSPEC_IS5G(pi->radio_chanspec)) ?
+			pi->srom_fem5g.pdetrange : pi->srom_fem2g.pdetrange;
+
+	if (pdetrange == 0) {
+		if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+			aux_adc_vmid = aux_adc_vmid_rev4;
+			aux_adc_gain = aux_adc_gain_rev4;
+		} else {
+			aux_adc_vmid = aux_adc_vmid_rev3;
+			aux_adc_gain = aux_adc_gain_rev3;
+		}
+		chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
+		if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+			switch (chan_freq_range) {
+			case WL_CHAN_FREQ_RANGE_5GL:
+				aux_adc_vmid[3] = 0x89;
+				aux_adc_gain[3] = 0;
+				break;
+			case WL_CHAN_FREQ_RANGE_5GM:
+				aux_adc_vmid[3] = 0x89;
+				aux_adc_gain[3] = 0;
+				break;
+			case WL_CHAN_FREQ_RANGE_5GH:
+				aux_adc_vmid[3] = 0x89;
+				aux_adc_gain[3] = 0;
+				break;
+			default:
+				break;
+			}
+		}
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+					 0x08, 16, aux_adc_vmid);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+					 0x18, 16, aux_adc_vmid);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+					 0x0c, 16, aux_adc_gain);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+					 0x1c, 16, aux_adc_gain);
+	} else if (pdetrange == 1) {
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+					 0x08, 16, sk_adc_vmid);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+					 0x18, 16, sk_adc_vmid);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+					 0x0c, 16, sk_adc_gain);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+					 0x1c, 16, sk_adc_gain);
+	} else if (pdetrange == 2) {
+
+		u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x74 };
+		u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x04 };
+
+		if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+			chan_freq_range =
+			    wlc_phy_get_chan_freq_range_nphy(pi, 0);
+			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+				bcm_adc_vmid[3] = 0x8e;
+				bcm_adc_gain[3] = 0x03;
+			} else {
+				bcm_adc_vmid[3] = 0x94;
+				bcm_adc_gain[3] = 0x03;
+			}
+		} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+			bcm_adc_vmid[3] = 0x84;
+			bcm_adc_gain[3] = 0x02;
+		}
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+					 0x08, 16, bcm_adc_vmid);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+					 0x18, 16, bcm_adc_vmid);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+					 0x0c, 16, bcm_adc_gain);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+					 0x1c, 16, bcm_adc_gain);
+	} else if (pdetrange == 3) {
+		chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
+		if ((NREV_GE(pi->pubpi.phy_rev, 4)) &&
+		    (chan_freq_range == WL_CHAN_FREQ_RANGE_2G)) {
+			u16 auxadc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x270 };
+			u16 auxadc_gain[] = { 0x02, 0x02, 0x02, 0x00 };
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x08, 16, auxadc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x18, 16, auxadc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x0c, 16, auxadc_gain);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x1c, 16, auxadc_gain);
+		}
+	} else if ((pdetrange == 4) || (pdetrange == 5)) {
+		u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x0 };
+		u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x0 };
+		u16 Vmid[2], Av[2];
+
+		chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
+		if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+			Vmid[0] = (pdetrange == 4) ? 0x8e : 0x89;
+			Vmid[1] = (pdetrange == 4) ? 0x96 : 0x89;
+			Av[0] = (pdetrange == 4) ? 2 : 0;
+			Av[1] = (pdetrange == 4) ? 2 : 0;
+		} else {
+			Vmid[0] = (pdetrange == 4) ? 0x89 : 0x74;
+			Vmid[1] = (pdetrange == 4) ? 0x8b : 0x70;
+			Av[0] = (pdetrange == 4) ? 2 : 0;
+			Av[1] = (pdetrange == 4) ? 2 : 0;
+		}
+
+		bcm_adc_vmid[3] = Vmid[0];
+		bcm_adc_gain[3] = Av[0];
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+					 0x08, 16, bcm_adc_vmid);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+					 0x0c, 16, bcm_adc_gain);
+
+		bcm_adc_vmid[3] = Vmid[1];
+		bcm_adc_gain[3] = Av[1];
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+					 0x18, 16, bcm_adc_vmid);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+					 0x1c, 16, bcm_adc_gain);
+	}
+
+	write_radio_reg(pi, (RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX0), 0x0);
+	write_radio_reg(pi, (RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX1), 0x0);
+
+	write_radio_reg(pi, (RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX0), 0x6);
+	write_radio_reg(pi, (RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX1), 0x6);
+
+	write_radio_reg(pi, (RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX0), 0x7);
+	write_radio_reg(pi, (RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX1), 0x7);
+
+	write_radio_reg(pi, (RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX0), 0x88);
+	write_radio_reg(pi, (RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX1), 0x88);
+
+	write_radio_reg(pi, (RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX0), 0x0);
+	write_radio_reg(pi, (RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX1), 0x0);
+
+	write_radio_reg(pi, (RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX0), 0x0);
+	write_radio_reg(pi, (RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX1), 0x0);
+
+	triso = (CHSPEC_IS5G(pi->radio_chanspec)) ?
+		 pi->srom_fem5g.triso : pi->srom_fem2g.triso;
+	if (triso == 7) {
+		wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0);
+		wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1);
+	}
+
+	wlc_phy_war_txchain_upd_nphy(pi, pi->sh->hw_phytxchain);
+
+	if (((pi->sh->boardflags2 & BFL2_APLL_WAR) &&
+	     (CHSPEC_IS5G(pi->radio_chanspec))) ||
+	    (((pi->sh->boardflags2 & BFL2_GPLL_WAR) ||
+	      (pi->sh->boardflags2 & BFL2_GPLL_WAR2)) &&
+	     (CHSPEC_IS2G(pi->radio_chanspec)))) {
+		nss1_data_weights = 0x00088888;
+		ht_data_weights = 0x00088888;
+		stbc_data_weights = 0x00088888;
+	} else {
+		nss1_data_weights = 0x88888888;
+		ht_data_weights = 0x88888888;
+		stbc_data_weights = 0x88888888;
+	}
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+				 1, 1, 32, &nss1_data_weights);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+				 1, 2, 32, &ht_data_weights);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+				 1, 3, 32, &stbc_data_weights);
+
+	if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+		if (CHSPEC_IS5G(pi->radio_chanspec)) {
+			write_radio_reg(pi,
+					RADIO_2056_TX_GMBB_IDAC |
+					RADIO_2056_TX0, 0x70);
+			write_radio_reg(pi,
+					RADIO_2056_TX_GMBB_IDAC |
+					RADIO_2056_TX1, 0x70);
+		}
+	}
+
+	if (!pi->edcrs_threshold_lock) {
+		write_phy_reg(pi, 0x224, 0x3eb);
+		write_phy_reg(pi, 0x225, 0x3eb);
+		write_phy_reg(pi, 0x226, 0x341);
+		write_phy_reg(pi, 0x227, 0x341);
+		write_phy_reg(pi, 0x228, 0x42b);
+		write_phy_reg(pi, 0x229, 0x42b);
+		write_phy_reg(pi, 0x22a, 0x381);
+		write_phy_reg(pi, 0x22b, 0x381);
+		write_phy_reg(pi, 0x22c, 0x42b);
+		write_phy_reg(pi, 0x22d, 0x42b);
+		write_phy_reg(pi, 0x22e, 0x381);
+		write_phy_reg(pi, 0x22f, 0x381);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+
+		if (pi->sh->boardflags2 & BFL2_SINGLEANT_CCK)
+			wlapi_bmac_mhf(pi->sh->physhim, MHF4,
+				       MHF4_BPHY_TXCORE0,
+				       MHF4_BPHY_TXCORE0, BRCM_BAND_ALL);
+	}
+}
+
+static void wlc_phy_workarounds_nphy_rev1(struct brcms_phy *pi)
+{
+	static const u8 rfseq_rx2tx_events[] = {
+		NPHY_RFSEQ_CMD_NOP,
+		NPHY_RFSEQ_CMD_RXG_FBW,
+		NPHY_RFSEQ_CMD_TR_SWITCH,
+		NPHY_RFSEQ_CMD_CLR_HIQ_DIS,
+		NPHY_RFSEQ_CMD_RXPD_TXPD,
+		NPHY_RFSEQ_CMD_TX_GAIN,
+		NPHY_RFSEQ_CMD_EXT_PA
+	};
+	u8 rfseq_rx2tx_dlys[] = { 8, 6, 6, 2, 4, 60, 1 };
+	static const u8 rfseq_tx2rx_events[] = {
+		NPHY_RFSEQ_CMD_NOP,
+		NPHY_RFSEQ_CMD_EXT_PA,
+		NPHY_RFSEQ_CMD_TX_GAIN,
+		NPHY_RFSEQ_CMD_RXPD_TXPD,
+		NPHY_RFSEQ_CMD_TR_SWITCH,
+		NPHY_RFSEQ_CMD_RXG_FBW,
+		NPHY_RFSEQ_CMD_CLR_HIQ_DIS
+	};
+	static const u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 };
+	s16 alpha0, alpha1, alpha2;
+	s16 beta0, beta1, beta2;
+	u16 regval;
+
+	if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD ||
+	    (pi->sh->boardtype == 0x8b)) {
+		uint i;
+		u8 war_dlys[] = { 1, 6, 6, 2, 4, 20, 1 };
+		for (i = 0; i < ARRAY_SIZE(rfseq_rx2tx_dlys); i++)
+			rfseq_rx2tx_dlys[i] = war_dlys[i];
+	}
+
+	if (CHSPEC_IS5G(pi->radio_chanspec) && pi->phy_5g_pwrgain) {
+		and_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0xf7);
+		and_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0xf7);
+	} else {
+		or_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0x8);
+		or_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0x8);
+	}
+
+	regval = 0x000a;
+	wlc_phy_table_write_nphy(pi, 8, 1, 0, 16, &regval);
+	wlc_phy_table_write_nphy(pi, 8, 1, 0x10, 16, &regval);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+		regval = 0xcdaa;
+		wlc_phy_table_write_nphy(pi, 8, 1, 0x02, 16, &regval);
+		wlc_phy_table_write_nphy(pi, 8, 1, 0x12, 16, &regval);
+	}
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+		regval = 0x0000;
+		wlc_phy_table_write_nphy(pi, 8, 1, 0x08, 16, &regval);
+		wlc_phy_table_write_nphy(pi, 8, 1, 0x18, 16, &regval);
+
+		regval = 0x7aab;
+		wlc_phy_table_write_nphy(pi, 8, 1, 0x07, 16, &regval);
+		wlc_phy_table_write_nphy(pi, 8, 1, 0x17, 16, &regval);
+
+		regval = 0x0800;
+		wlc_phy_table_write_nphy(pi, 8, 1, 0x06, 16, &regval);
+		wlc_phy_table_write_nphy(pi, 8, 1, 0x16, 16, &regval);
+	}
+
+	write_phy_reg(pi, 0xf8, 0x02d8);
+	write_phy_reg(pi, 0xf9, 0x0301);
+	write_phy_reg(pi, 0xfa, 0x02d8);
+	write_phy_reg(pi, 0xfb, 0x0301);
+
+	wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, rfseq_rx2tx_events,
+			       rfseq_rx2tx_dlys,
+			       ARRAY_SIZE(rfseq_rx2tx_events));
+
+	wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX, rfseq_tx2rx_events,
+			       rfseq_tx2rx_dlys,
+			       ARRAY_SIZE(rfseq_tx2rx_events));
+
+	wlc_phy_workarounds_nphy_gainctrl(pi);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+
+		if (read_phy_reg(pi, 0xa0) & NPHY_MLenable)
+			wlapi_bmac_mhf(pi->sh->physhim, MHF3,
+				       MHF3_NPHY_MLADV_WAR,
+				       MHF3_NPHY_MLADV_WAR, BRCM_BAND_ALL);
+
+	} else if (NREV_IS(pi->pubpi.phy_rev, 2)) {
+		write_phy_reg(pi, 0x1e3, 0x0);
+		write_phy_reg(pi, 0x1e4, 0x0);
+	}
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2))
+		mod_phy_reg(pi, 0x90, (0x1 << 7), 0);
+
+	alpha0 = 293;
+	alpha1 = 435;
+	alpha2 = 261;
+	beta0 = 366;
+	beta1 = 205;
+	beta2 = 32;
+	write_phy_reg(pi, 0x145, alpha0);
+	write_phy_reg(pi, 0x146, alpha1);
+	write_phy_reg(pi, 0x147, alpha2);
+	write_phy_reg(pi, 0x148, beta0);
+	write_phy_reg(pi, 0x149, beta1);
+	write_phy_reg(pi, 0x14a, beta2);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+		mod_phy_reg(pi, 0x142, (0xf << 12), 0);
+
+		write_phy_reg(pi, 0x192, 0xb5);
+		write_phy_reg(pi, 0x193, 0xa4);
+		write_phy_reg(pi, 0x194, 0x0);
+	}
+
+	if (NREV_IS(pi->pubpi.phy_rev, 2))
+		mod_phy_reg(pi, 0x221,
+			    NPHY_FORCESIG_DECODEGATEDCLKS,
+			    NPHY_FORCESIG_DECODEGATEDCLKS);
+}
+
+static void wlc_phy_workarounds_nphy(struct brcms_phy *pi)
+{
+	if (CHSPEC_IS5G(pi->radio_chanspec))
+		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 0);
+	else
+		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 1);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	or_phy_reg(pi, 0xb1, NPHY_IQFlip_ADC1 | NPHY_IQFlip_ADC2);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7))
+		wlc_phy_workarounds_nphy_rev7(pi);
+	else if (NREV_GE(pi->pubpi.phy_rev, 3))
+		wlc_phy_workarounds_nphy_rev3(pi);
+	else
+		wlc_phy_workarounds_nphy_rev1(pi);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void wlc_phy_extpa_set_tx_digi_filts_nphy(struct brcms_phy *pi)
+{
+	int j, type = 2;
+	u16 addr_offset = 0x2c5;
+
+	for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++)
+		write_phy_reg(pi, addr_offset + j,
+			      NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]);
+}
+
+static void wlc_phy_clip_det_nphy(struct brcms_phy *pi, u8 write, u16 *vals)
+{
+
+	if (write == 0) {
+		vals[0] = read_phy_reg(pi, 0x2c);
+		vals[1] = read_phy_reg(pi, 0x42);
+	} else {
+		write_phy_reg(pi, 0x2c, vals[0]);
+		write_phy_reg(pi, 0x42, vals[1]);
+	}
+}
+
+static void wlc_phy_ipa_internal_tssi_setup_nphy(struct brcms_phy *pi)
+{
+	u8 core;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TX_SSI_MASTER, 0x5);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TX_SSI_MUX, 0xe);
+
+				if (pi->pubpi.radiorev != 5)
+					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+							 core, TSSIA, 0);
+
+				if (!NREV_IS(pi->pubpi.phy_rev, 7))
+					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+							 core, TSSIG, 0x1);
+				else
+					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+							 core, TSSIG, 0x31);
+			} else {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TX_SSI_MASTER, 0x9);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TX_SSI_MUX, 0xc);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSIG, 0);
+
+				if (pi->pubpi.radiorev != 5) {
+					if (!NREV_IS(pi->pubpi.phy_rev, 7))
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TSSIA, 0x1);
+					else
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TSSIA, 0x31);
+				}
+			}
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_VCM_HG,
+					 0);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_IDAC,
+					 0);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM,
+					 0x3);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_MISC1,
+					 0x0);
+		}
+	} else {
+		WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR31,
+				(CHSPEC_IS2G(pi->radio_chanspec)) ? 0x128 :
+				0x80);
+		WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR30, 0x0);
+		WRITE_RADIO_SYN(pi, RADIO_2056, GPIO_MASTER1, 0x29);
+
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_VCM_HG,
+					 0x0);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_IDAC,
+					 0x0);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_VCM,
+					 0x3);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TX_AMP_DET,
+					 0x0);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC1,
+					 0x8);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC2,
+					 0x0);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC3,
+					 0x0);
+
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 TX_SSI_MASTER, 0x5);
+
+				if (pi->pubpi.radiorev != 5)
+					WRITE_RADIO_REG2(pi, RADIO_2056, TX,
+							 core, TSSIA, 0x0);
+				if (NREV_GE(pi->pubpi.phy_rev, 5))
+					WRITE_RADIO_REG2(pi, RADIO_2056, TX,
+							 core, TSSIG, 0x31);
+				else
+					WRITE_RADIO_REG2(pi, RADIO_2056, TX,
+							 core, TSSIG, 0x11);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 TX_SSI_MUX, 0xe);
+			} else {
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 TX_SSI_MASTER, 0x9);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 TSSIA, 0x31);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 TSSIG, 0x0);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 TX_SSI_MUX, 0xc);
+			}
+		}
+	}
+}
+
+static void
+wlc_phy_rfctrl_override_nphy(struct brcms_phy *pi, u16 field, u16 value,
+			     u8 core_mask, u8 off)
+{
+	u8 core_num;
+	u16 addr = 0, mask = 0, en_addr = 0, val_addr = 0, en_mask =
+		0, val_mask = 0;
+	u8 shift = 0, val_shift = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+
+		en_mask = field;
+		for (core_num = 0; core_num < 2; core_num++) {
+
+			switch (field) {
+			case (0x1 << 1):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 0);
+				val_shift = 0;
+				break;
+			case (0x1 << 2):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 1);
+				val_shift = 1;
+				break;
+			case (0x1 << 3):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 2);
+				val_shift = 2;
+				break;
+			case (0x1 << 4):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 4);
+				val_shift = 4;
+				break;
+			case (0x1 << 5):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 5);
+				val_shift = 5;
+				break;
+			case (0x1 << 6):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 6);
+				val_shift = 6;
+				break;
+			case (0x1 << 7):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 7);
+				val_shift = 7;
+				break;
+			case (0x1 << 8):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x7 << 8);
+				val_shift = 8;
+				break;
+			case (0x1 << 11):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x7 << 13);
+				val_shift = 13;
+				break;
+
+			case (0x1 << 9):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0xf8 : 0xfa;
+				val_mask = (0x7 << 0);
+				val_shift = 0;
+				break;
+
+			case (0x1 << 10):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0xf8 : 0xfa;
+				val_mask = (0x7 << 4);
+				val_shift = 4;
+				break;
+
+			case (0x1 << 12):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7b : 0x7e;
+				val_mask = (0xffff << 0);
+				val_shift = 0;
+				break;
+			case (0x1 << 13):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7c : 0x7f;
+				val_mask = (0xffff << 0);
+				val_shift = 0;
+				break;
+			case (0x1 << 14):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0xf9 : 0xfb;
+				val_mask = (0x3 << 6);
+				val_shift = 6;
+				break;
+			case (0x1 << 0):
+				en_addr = (core_num == 0) ? 0xe5 : 0xe6;
+				val_addr = (core_num == 0) ? 0xf9 : 0xfb;
+				val_mask = (0x1 << 15);
+				val_shift = 15;
+				break;
+			default:
+				addr = 0xffff;
+				break;
+			}
+
+			if (off) {
+				and_phy_reg(pi, en_addr, ~en_mask);
+				and_phy_reg(pi, val_addr, ~val_mask);
+			} else {
+
+				if ((core_mask == 0)
+				    || (core_mask & (1 << core_num))) {
+					or_phy_reg(pi, en_addr, en_mask);
+
+					if (addr != 0xffff)
+						mod_phy_reg(pi, val_addr,
+							    val_mask,
+							    (value <<
+							     val_shift));
+				}
+			}
+		}
+	} else {
+
+		if (off) {
+			and_phy_reg(pi, 0xec, ~field);
+			value = 0x0;
+		} else {
+			or_phy_reg(pi, 0xec, field);
+		}
+
+		for (core_num = 0; core_num < 2; core_num++) {
+
+			switch (field) {
+			case (0x1 << 1):
+			case (0x1 << 9):
+			case (0x1 << 12):
+			case (0x1 << 13):
+			case (0x1 << 14):
+				addr = 0x78;
+
+				core_mask = 0x1;
+				break;
+			case (0x1 << 2):
+			case (0x1 << 3):
+			case (0x1 << 4):
+			case (0x1 << 5):
+			case (0x1 << 6):
+			case (0x1 << 7):
+			case (0x1 << 8):
+				addr = (core_num == 0) ? 0x7a : 0x7d;
+				break;
+			case (0x1 << 10):
+				addr = (core_num == 0) ? 0x7b : 0x7e;
+				break;
+			case (0x1 << 11):
+				addr = (core_num == 0) ? 0x7c : 0x7f;
+				break;
+			default:
+				addr = 0xffff;
+			}
+
+			switch (field) {
+			case (0x1 << 1):
+				mask = (0x7 << 3);
+				shift = 3;
+				break;
+			case (0x1 << 9):
+				mask = (0x1 << 2);
+				shift = 2;
+				break;
+			case (0x1 << 12):
+				mask = (0x1 << 8);
+				shift = 8;
+				break;
+			case (0x1 << 13):
+				mask = (0x1 << 9);
+				shift = 9;
+				break;
+			case (0x1 << 14):
+				mask = (0xf << 12);
+				shift = 12;
+				break;
+			case (0x1 << 2):
+				mask = (0x1 << 0);
+				shift = 0;
+				break;
+			case (0x1 << 3):
+				mask = (0x1 << 1);
+				shift = 1;
+				break;
+			case (0x1 << 4):
+				mask = (0x1 << 2);
+				shift = 2;
+				break;
+			case (0x1 << 5):
+				mask = (0x3 << 4);
+				shift = 4;
+				break;
+			case (0x1 << 6):
+				mask = (0x3 << 6);
+				shift = 6;
+				break;
+			case (0x1 << 7):
+				mask = (0x1 << 8);
+				shift = 8;
+				break;
+			case (0x1 << 8):
+				mask = (0x1 << 9);
+				shift = 9;
+				break;
+			case (0x1 << 10):
+				mask = 0x1fff;
+				shift = 0x0;
+				break;
+			case (0x1 << 11):
+				mask = 0x1fff;
+				shift = 0x0;
+				break;
+			default:
+				mask = 0x0;
+				shift = 0x0;
+				break;
+			}
+
+			if ((addr != 0xffff) && (core_mask & (1 << core_num)))
+				mod_phy_reg(pi, addr, mask, (value << shift));
+		}
+
+		or_phy_reg(pi, 0xec, (0x1 << 0));
+		or_phy_reg(pi, 0x78, (0x1 << 0));
+		udelay(1);
+		and_phy_reg(pi, 0xec, ~(0x1 << 0));
+	}
+}
+
+static void wlc_phy_txpwrctrl_idle_tssi_nphy(struct brcms_phy *pi)
+{
+	s32 rssi_buf[4];
+	s32 int_val;
+
+	if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi) || PHY_MUTED(pi))
+
+		return;
+
+	if (PHY_IPA(pi))
+		wlc_phy_ipa_internal_tssi_setup_nphy(pi);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7))
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
+						  0, 0x3, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+	else if (NREV_GE(pi->pubpi.phy_rev, 3))
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 0);
+
+	wlc_phy_stopplayback_nphy(pi);
+
+	wlc_phy_tx_tone_nphy(pi, 4000, 0, 0, 0, false);
+
+	udelay(20);
+	int_val =
+		wlc_phy_poll_rssi_nphy(pi, (u8) NPHY_RSSI_SEL_TSSI_2G, rssi_buf,
+				       1);
+	wlc_phy_stopplayback_nphy(pi);
+	wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, 0);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7))
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
+						  0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+	else if (NREV_GE(pi->pubpi.phy_rev, 3))
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 1);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+		pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g =
+			(u8) ((int_val >> 24) & 0xff);
+		pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g =
+			(u8) ((int_val >> 24) & 0xff);
+
+		pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g =
+			(u8) ((int_val >> 8) & 0xff);
+		pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g =
+			(u8) ((int_val >> 8) & 0xff);
+	} else {
+		pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g =
+			(u8) ((int_val >> 24) & 0xff);
+
+		pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g =
+			(u8) ((int_val >> 8) & 0xff);
+
+		pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g =
+			(u8) ((int_val >> 16) & 0xff);
+		pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g =
+			(u8) ((int_val) & 0xff);
+	}
+
+}
+
+static void wlc_phy_txpwr_limit_to_tbl_nphy(struct brcms_phy *pi)
+{
+	u8 idx, idx2, i, delta_ind;
+
+	for (idx = TXP_FIRST_CCK; idx <= TXP_LAST_CCK; idx++)
+		pi->adj_pwr_tbl_nphy[idx] = pi->tx_power_offset[idx];
+
+	for (i = 0; i < 4; i++) {
+		idx2 = 0;
+
+		delta_ind = 0;
+
+		switch (i) {
+		case 0:
+
+			if (CHSPEC_IS40(pi->radio_chanspec)
+			    && NPHY_IS_SROM_REINTERPRET) {
+				idx = TXP_FIRST_MCS_40_SISO;
+			} else {
+				idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+				      TXP_FIRST_OFDM_40_SISO : TXP_FIRST_OFDM;
+				delta_ind = 1;
+			}
+			break;
+
+		case 1:
+
+			idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+			      TXP_FIRST_MCS_40_CDD : TXP_FIRST_MCS_20_CDD;
+			break;
+
+		case 2:
+
+			idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+			      TXP_FIRST_MCS_40_STBC : TXP_FIRST_MCS_20_STBC;
+			break;
+
+		case 3:
+
+			idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+			      TXP_FIRST_MCS_40_SDM : TXP_FIRST_MCS_20_SDM;
+			break;
+		}
+
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+			pi->tx_power_offset[idx];
+		idx = idx + delta_ind;
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+			pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+			pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+			pi->tx_power_offset[idx++];
+
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+			pi->tx_power_offset[idx++];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+			pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+			pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+			pi->tx_power_offset[idx++];
+
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+			pi->tx_power_offset[idx++];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+			pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+			pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+			pi->tx_power_offset[idx++];
+
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+			pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+			pi->tx_power_offset[idx++];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+			pi->tx_power_offset[idx];
+		idx = idx + 1 - delta_ind;
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+			pi->tx_power_offset[idx];
+
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+			pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+			pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+			pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+			pi->tx_power_offset[idx];
+	}
+}
+
+static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi)
+{
+	u32 idx;
+	s16 a1[2], b0[2], b1[2];
+	s8 target_pwr_qtrdbm[2];
+	s32 num, den, pwr_est;
+	u8 chan_freq_range;
+	u8 idle_tssi[2];
+	u32 tbl_id, tbl_len, tbl_offset;
+	u32 regval[64];
+	u8 core;
+
+	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
+		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
+		(void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
+		udelay(1);
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	or_phy_reg(pi, 0x122, (0x1 << 0));
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3))
+		and_phy_reg(pi, 0x1e7, (u16) (~(0x1 << 15)));
+	else
+		or_phy_reg(pi, 0x1e7, (0x1 << 15));
+
+	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
+		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
+
+	if (pi->sh->sromrev < 4) {
+		idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
+		idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
+		a1[0] = -424;
+		a1[1] = -424;
+		b0[0] = 5612;
+		b0[1] = 5612;
+		b1[1] = -1393;
+		b1[0] = -1393;
+	} else {
+
+		chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
+		switch (chan_freq_range) {
+		case WL_CHAN_FREQ_RANGE_2G:
+			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
+			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
+			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_a1;
+			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_a1;
+			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b0;
+			b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b0;
+			b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b1;
+			b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b1;
+			break;
+		case WL_CHAN_FREQ_RANGE_5GL:
+			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
+			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
+			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1;
+			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1;
+			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0;
+			b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0;
+			b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1;
+			b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1;
+			break;
+		case WL_CHAN_FREQ_RANGE_5GM:
+			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
+			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
+			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_a1;
+			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_a1;
+			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b0;
+			b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b0;
+			b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b1;
+			b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b1;
+			break;
+		case WL_CHAN_FREQ_RANGE_5GH:
+			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
+			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
+			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1;
+			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1;
+			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0;
+			b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0;
+			b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1;
+			b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1;
+			break;
+		default:
+			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
+			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
+			a1[0] = -424;
+			a1[1] = -424;
+			b0[0] = 5612;
+			b0[1] = 5612;
+			b1[1] = -1393;
+			b1[0] = -1393;
+			break;
+		}
+	}
+
+	/* use the provided transmit power */
+	target_pwr_qtrdbm[0] = (s8) pi->tx_power_max;
+	target_pwr_qtrdbm[1] = (s8) pi->tx_power_max;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (pi->srom_fem2g.tssipos)
+			or_phy_reg(pi, 0x1e9, (0x1 << 14));
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			for (core = 0; core <= 1; core++) {
+				if (PHY_IPA(pi)) {
+					if (CHSPEC_IS2G(pi->radio_chanspec))
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TX_SSI_MUX,
+								 0xe);
+					else
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TX_SSI_MUX,
+								 0xc);
+				}
+			}
+		} else {
+			if (PHY_IPA(pi)) {
+
+				write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
+						RADIO_2056_TX0,
+						(CHSPEC_IS5G
+						 (pi->radio_chanspec)) ?
+						 0xc : 0xe);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TX_SSI_MUX |
+						RADIO_2056_TX1,
+						(CHSPEC_IS5G
+						 (pi->radio_chanspec)) ?
+						 0xc : 0xe);
+			} else {
+
+				write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
+						RADIO_2056_TX0, 0x11);
+				write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
+						RADIO_2056_TX1, 0x11);
+			}
+		}
+	}
+
+	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
+		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
+		(void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
+		udelay(1);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7))
+		mod_phy_reg(pi, 0x1e7, (0x7f << 0),
+			    (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0));
+	else
+		mod_phy_reg(pi, 0x1e7, (0x7f << 0),
+			    (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0));
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7))
+		mod_phy_reg(pi, 0x222, (0xff << 0),
+			    (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0));
+	else if (NREV_GT(pi->pubpi.phy_rev, 1))
+		mod_phy_reg(pi, 0x222, (0xff << 0),
+			    (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0));
+
+	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
+		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
+
+	write_phy_reg(pi, 0x1e8, (0x3 << 8) | (240 << 0));
+
+	write_phy_reg(pi, 0x1e9,
+		      (1 << 15) | (idle_tssi[0] << 0) | (idle_tssi[1] << 8));
+
+	write_phy_reg(pi, 0x1ea,
+		      (target_pwr_qtrdbm[0] << 0) |
+		      (target_pwr_qtrdbm[1] << 8));
+
+	tbl_len = 64;
+	tbl_offset = 0;
+	for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
+	     tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
+
+		for (idx = 0; idx < tbl_len; idx++) {
+			num = 8 *
+			      (16 * b0[tbl_id - 26] + b1[tbl_id - 26] * idx);
+			den = 32768 + a1[tbl_id - 26] * idx;
+			pwr_est = max(((4 * num + den / 2) / den), -8);
+			if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+				if (idx <=
+				    (uint) (31 - idle_tssi[tbl_id - 26] + 1))
+					pwr_est =
+						max(pwr_est,
+						    target_pwr_qtrdbm
+						    [tbl_id - 26] + 1);
+			}
+			regval[idx] = (u32) pwr_est;
+		}
+		wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
+					 regval);
+	}
+
+	wlc_phy_txpwr_limit_to_tbl_nphy(pi);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 84, 64, 8,
+				 pi->adj_pwr_tbl_nphy);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 84, 64, 8,
+				 pi->adj_pwr_tbl_nphy);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static u32 *wlc_phy_get_ipa_gaintbl_nphy(struct brcms_phy *pi)
+{
+	u32 *tx_pwrctrl_tbl = NULL;
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			if ((pi->pubpi.radiorev == 4)
+			    || (pi->pubpi.radiorev == 6))
+				tx_pwrctrl_tbl =
+					nphy_tpc_txgain_ipa_2g_2057rev4n6;
+			else if (pi->pubpi.radiorev == 3)
+				tx_pwrctrl_tbl =
+					nphy_tpc_txgain_ipa_2g_2057rev3;
+			else if (pi->pubpi.radiorev == 5)
+				tx_pwrctrl_tbl =
+					nphy_tpc_txgain_ipa_2g_2057rev5;
+			else if ((pi->pubpi.radiorev == 7)
+				 || (pi->pubpi.radiorev == 8))
+				tx_pwrctrl_tbl =
+					nphy_tpc_txgain_ipa_2g_2057rev7;
+		} else if (NREV_IS(pi->pubpi.phy_rev, 6)) {
+			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev6;
+			if (pi->sh->chip == BCMA_CHIP_ID_BCM47162)
+				tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5;
+		} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5;
+		} else {
+			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa;
+		}
+	} else {
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			if ((pi->pubpi.radiorev == 3) ||
+			    (pi->pubpi.radiorev == 4) ||
+			    (pi->pubpi.radiorev == 6))
+				tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g_2057;
+			else if ((pi->pubpi.radiorev == 7)
+				 || (pi->pubpi.radiorev == 8))
+				tx_pwrctrl_tbl =
+					nphy_tpc_txgain_ipa_5g_2057rev7;
+		} else {
+			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g;
+		}
+	}
+
+	return tx_pwrctrl_tbl;
+}
+
+static void wlc_phy_restore_rssical_nphy(struct brcms_phy *pi)
+{
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (pi->nphy_rssical_chanspec_2G == 0)
+			return;
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0,
+				      RADIO_2057_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_2G[0]);
+			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1,
+				      RADIO_2057_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_2G[1]);
+		} else {
+			mod_radio_reg(pi,
+				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0,
+				      RADIO_2056_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_2G[0]);
+			mod_radio_reg(pi,
+				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1,
+				      RADIO_2056_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_2G[1]);
+		}
+
+		write_phy_reg(pi, 0x1a6,
+			      pi->rssical_cache.rssical_phyregs_2G[0]);
+		write_phy_reg(pi, 0x1ac,
+			      pi->rssical_cache.rssical_phyregs_2G[1]);
+		write_phy_reg(pi, 0x1b2,
+			      pi->rssical_cache.rssical_phyregs_2G[2]);
+		write_phy_reg(pi, 0x1b8,
+			      pi->rssical_cache.rssical_phyregs_2G[3]);
+		write_phy_reg(pi, 0x1a4,
+			      pi->rssical_cache.rssical_phyregs_2G[4]);
+		write_phy_reg(pi, 0x1aa,
+			      pi->rssical_cache.rssical_phyregs_2G[5]);
+		write_phy_reg(pi, 0x1b0,
+			      pi->rssical_cache.rssical_phyregs_2G[6]);
+		write_phy_reg(pi, 0x1b6,
+			      pi->rssical_cache.rssical_phyregs_2G[7]);
+		write_phy_reg(pi, 0x1a5,
+			      pi->rssical_cache.rssical_phyregs_2G[8]);
+		write_phy_reg(pi, 0x1ab,
+			      pi->rssical_cache.rssical_phyregs_2G[9]);
+		write_phy_reg(pi, 0x1b1,
+			      pi->rssical_cache.rssical_phyregs_2G[10]);
+		write_phy_reg(pi, 0x1b7,
+			      pi->rssical_cache.rssical_phyregs_2G[11]);
+
+	} else {
+		if (pi->nphy_rssical_chanspec_5G == 0)
+			return;
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0,
+				      RADIO_2057_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_5G[0]);
+			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1,
+				      RADIO_2057_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_5G[1]);
+		} else {
+			mod_radio_reg(pi,
+				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0,
+				      RADIO_2056_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_5G[0]);
+			mod_radio_reg(pi,
+				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1,
+				      RADIO_2056_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_5G[1]);
+		}
+
+		write_phy_reg(pi, 0x1a6,
+			      pi->rssical_cache.rssical_phyregs_5G[0]);
+		write_phy_reg(pi, 0x1ac,
+			      pi->rssical_cache.rssical_phyregs_5G[1]);
+		write_phy_reg(pi, 0x1b2,
+			      pi->rssical_cache.rssical_phyregs_5G[2]);
+		write_phy_reg(pi, 0x1b8,
+			      pi->rssical_cache.rssical_phyregs_5G[3]);
+		write_phy_reg(pi, 0x1a4,
+			      pi->rssical_cache.rssical_phyregs_5G[4]);
+		write_phy_reg(pi, 0x1aa,
+			      pi->rssical_cache.rssical_phyregs_5G[5]);
+		write_phy_reg(pi, 0x1b0,
+			      pi->rssical_cache.rssical_phyregs_5G[6]);
+		write_phy_reg(pi, 0x1b6,
+			      pi->rssical_cache.rssical_phyregs_5G[7]);
+		write_phy_reg(pi, 0x1a5,
+			      pi->rssical_cache.rssical_phyregs_5G[8]);
+		write_phy_reg(pi, 0x1ab,
+			      pi->rssical_cache.rssical_phyregs_5G[9]);
+		write_phy_reg(pi, 0x1b1,
+			      pi->rssical_cache.rssical_phyregs_5G[10]);
+		write_phy_reg(pi, 0x1b7,
+			      pi->rssical_cache.rssical_phyregs_5G[11]);
+	}
+}
+
+static void wlc_phy_internal_cal_txgain_nphy(struct brcms_phy *pi)
+{
+	u16 txcal_gain[2];
+
+	pi->nphy_txcal_pwr_idx[0] = pi->nphy_cal_orig_pwr_idx[0];
+	pi->nphy_txcal_pwr_idx[1] = pi->nphy_cal_orig_pwr_idx[0];
+	wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true);
+	wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true);
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+				txcal_gain);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F40;
+		txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F40;
+	} else {
+		txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F60;
+		txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F60;
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+				 txcal_gain);
+}
+
+static void wlc_phy_precal_txgain_nphy(struct brcms_phy *pi)
+{
+	bool save_bbmult = false;
+	u8 txcal_index_2057_rev5n7 = 0;
+	u8 txcal_index_2057_rev3n4n6 = 10;
+
+	if (pi->use_int_tx_iqlo_cal_nphy) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			if ((pi->pubpi.radiorev == 3) ||
+			    (pi->pubpi.radiorev == 4) ||
+			    (pi->pubpi.radiorev == 6)) {
+
+				pi->nphy_txcal_pwr_idx[0] =
+					txcal_index_2057_rev3n4n6;
+				pi->nphy_txcal_pwr_idx[1] =
+					txcal_index_2057_rev3n4n6;
+				wlc_phy_txpwr_index_nphy(
+					pi, 3,
+					txcal_index_2057_rev3n4n6,
+					false);
+			} else {
+
+				pi->nphy_txcal_pwr_idx[0] =
+					txcal_index_2057_rev5n7;
+				pi->nphy_txcal_pwr_idx[1] =
+					txcal_index_2057_rev5n7;
+				wlc_phy_txpwr_index_nphy(
+					pi, 3,
+					txcal_index_2057_rev5n7,
+					false);
+			}
+			save_bbmult = true;
+
+		} else if (NREV_LT(pi->pubpi.phy_rev, 5)) {
+			wlc_phy_cal_txgainctrl_nphy(pi, 11, false);
+			if (pi->sh->hw_phytxchain != 3) {
+				pi->nphy_txcal_pwr_idx[1] =
+					pi->nphy_txcal_pwr_idx[0];
+				wlc_phy_txpwr_index_nphy(pi, 3,
+							 pi->
+							 nphy_txcal_pwr_idx[0],
+							 true);
+				save_bbmult = true;
+			}
+
+		} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+			if (PHY_IPA(pi)) {
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					wlc_phy_cal_txgainctrl_nphy(pi, 12,
+								    false);
+				} else {
+					pi->nphy_txcal_pwr_idx[0] = 80;
+					pi->nphy_txcal_pwr_idx[1] = 80;
+					wlc_phy_txpwr_index_nphy(pi, 3, 80,
+								 false);
+					save_bbmult = true;
+				}
+			} else {
+				wlc_phy_internal_cal_txgain_nphy(pi);
+				save_bbmult = true;
+			}
+
+		} else if (NREV_IS(pi->pubpi.phy_rev, 6)) {
+			if (PHY_IPA(pi)) {
+				if (CHSPEC_IS2G(pi->radio_chanspec))
+					wlc_phy_cal_txgainctrl_nphy(pi, 12,
+								    false);
+				else
+					wlc_phy_cal_txgainctrl_nphy(pi, 14,
+								    false);
+			} else {
+				wlc_phy_internal_cal_txgain_nphy(pi);
+				save_bbmult = true;
+			}
+		}
+
+	} else {
+		wlc_phy_cal_txgainctrl_nphy(pi, 10, false);
+	}
+
+	if (save_bbmult)
+		wlc_phy_table_read_nphy(pi, 15, 1, 87, 16,
+					&pi->nphy_txcal_bbmult);
+}
+
+static void
+wlc_phy_rfctrlintc_override_nphy(struct brcms_phy *pi, u8 field, u16 value,
+				 u8 core_code)
+{
+	u16 mask;
+	u16 val;
+	u8 core;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+			if (core_code == RADIO_MIMO_CORESEL_CORE1
+			    && core == PHY_CORE_1)
+				continue;
+			else if (core_code == RADIO_MIMO_CORESEL_CORE2
+				 && core == PHY_CORE_0)
+				continue;
+
+			if (NREV_LT(pi->pubpi.phy_rev, 7)) {
+
+				mask = (0x1 << 10);
+				val = 1 << 10;
+				mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 :
+					    0x92, mask, val);
+			}
+
+			if (field == NPHY_RfctrlIntc_override_OFF) {
+
+				write_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 :
+					      0x92, 0);
+
+				wlc_phy_force_rfseq_nphy(pi,
+							 NPHY_RFSEQ_RESET2RX);
+			} else if (field == NPHY_RfctrlIntc_override_TRSW) {
+
+				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+					mask = (0x1 << 6) | (0x1 << 7);
+
+					val = value << 6;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+
+					or_phy_reg(pi,
+						   (core ==
+						    PHY_CORE_0) ? 0x91 : 0x92,
+						   (0x1 << 10));
+
+					and_phy_reg(pi, 0x2ff, (u16)
+						    ~(0x3 << 14));
+					or_phy_reg(pi, 0x2ff, (0x1 << 13));
+					or_phy_reg(pi, 0x2ff, (0x1 << 0));
+				} else {
+
+					mask = (0x1 << 6) |
+					       (0x1 << 7) |
+					       (0x1 << 8) | (0x1 << 9);
+					val = value << 6;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+
+					mask = (0x1 << 0);
+					val = 1 << 0;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0xe7 : 0xec,
+						    mask, val);
+
+					mask = (core == PHY_CORE_0) ?
+					       (0x1 << 0) : (0x1 << 1);
+					val = 1 << ((core == PHY_CORE_0) ?
+						    0 : 1);
+					mod_phy_reg(pi, 0x78, mask, val);
+
+					SPINWAIT(((read_phy_reg(pi, 0x78) & val)
+						  != 0), 10000);
+					if (WARN(read_phy_reg(pi, 0x78) & val,
+						 "HW error: override failed"))
+						return;
+
+					mask = (0x1 << 0);
+					val = 0 << 0;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0xe7 : 0xec,
+						    mask, val);
+				}
+			} else if (field == NPHY_RfctrlIntc_override_PA) {
+				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+					mask = (0x1 << 4) | (0x1 << 5);
+
+					if (CHSPEC_IS5G(pi->radio_chanspec))
+						val = value << 5;
+					else
+						val = value << 4;
+
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+
+					or_phy_reg(pi,
+						   (core ==
+						    PHY_CORE_0) ? 0x91 : 0x92,
+						   (0x1 << 12));
+				} else {
+
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+						mask = (0x1 << 5);
+						val = value << 5;
+					} else {
+						mask = (0x1 << 4);
+						val = value << 4;
+					}
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+				}
+			} else if (field ==
+				   NPHY_RfctrlIntc_override_EXT_LNA_PU) {
+				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+
+						mask = (0x1 << 0);
+						val = value << 0;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, val);
+
+						mask = (0x1 << 2);
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, 0);
+					} else {
+
+						mask = (0x1 << 2);
+						val = value << 2;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, val);
+
+						mask = (0x1 << 0);
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, 0);
+					}
+
+					mask = (0x1 << 11);
+					val = 1 << 11;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+				} else {
+
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+						mask = (0x1 << 0);
+						val = value << 0;
+					} else {
+						mask = (0x1 << 2);
+						val = value << 2;
+					}
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+				}
+			} else if (field ==
+				   NPHY_RfctrlIntc_override_EXT_LNA_GAIN) {
+				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+
+						mask = (0x1 << 1);
+						val = value << 1;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, val);
+
+						mask = (0x1 << 3);
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, 0);
+					} else {
+
+						mask = (0x1 << 3);
+						val = value << 3;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, val);
+
+						mask = (0x1 << 1);
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, 0);
+					}
+
+					mask = (0x1 << 11);
+					val = 1 << 11;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+				} else {
+
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+						mask = (0x1 << 1);
+						val = value << 1;
+					} else {
+						mask = (0x1 << 3);
+						val = value << 3;
+					}
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+				}
+			}
+		}
+	}
+}
+
+void
+wlc_phy_cal_txgainctrl_nphy(struct brcms_phy *pi, s32 dBm_targetpower,
+			    bool debug)
+{
+	int gainctrl_loopidx;
+	uint core;
+	u16 m0m1, curr_m0m1;
+	s32 delta_power;
+	s32 txpwrindex;
+	s32 qdBm_power[2];
+	u16 orig_BBConfig;
+	u16 phy_saveregs[4];
+	u32 freq_test;
+	u16 ampl_test = 250;
+	uint stepsize;
+	bool phyhang_avoid_state = false;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7))
+		stepsize = 2;
+	else
+		stepsize = 1;
+
+	if (CHSPEC_IS40(pi->radio_chanspec))
+		freq_test = 5000;
+	else
+		freq_test = 2500;
+
+	wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true);
+	wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	phyhang_avoid_state = pi->phyhang_avoid;
+	pi->phyhang_avoid = false;
+
+	phy_saveregs[0] = read_phy_reg(pi, 0x91);
+	phy_saveregs[1] = read_phy_reg(pi, 0x92);
+	phy_saveregs[2] = read_phy_reg(pi, 0xe7);
+	phy_saveregs[3] = read_phy_reg(pi, 0xec);
+	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_PA, 1,
+					 RADIO_MIMO_CORESEL_CORE1 |
+					 RADIO_MIMO_CORESEL_CORE2);
+
+	if (!debug) {
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x2, RADIO_MIMO_CORESEL_CORE1);
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x8, RADIO_MIMO_CORESEL_CORE2);
+	} else {
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x1, RADIO_MIMO_CORESEL_CORE1);
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x7, RADIO_MIMO_CORESEL_CORE2);
+	}
+
+	orig_BBConfig = read_phy_reg(pi, 0x01);
+	mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
+
+	wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1);
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+		txpwrindex = (s32) pi->nphy_cal_orig_pwr_idx[core];
+
+		for (gainctrl_loopidx = 0; gainctrl_loopidx < 2;
+		     gainctrl_loopidx++) {
+			wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0,
+					     false);
+
+			if (core == PHY_CORE_0)
+				curr_m0m1 = m0m1 & 0xff00;
+			else
+				curr_m0m1 = m0m1 & 0x00ff;
+
+			wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &curr_m0m1);
+			wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &curr_m0m1);
+
+			udelay(50);
+
+			wlc_phy_est_tonepwr_nphy(pi, qdBm_power,
+						 NPHY_CAL_TSSISAMPS);
+
+			pi->nphy_bb_mult_save = 0;
+			wlc_phy_stopplayback_nphy(pi);
+
+			delta_power = (dBm_targetpower * 4) - qdBm_power[core];
+
+			txpwrindex -= stepsize * delta_power;
+			if (txpwrindex < 0)
+				txpwrindex = 0;
+			else if (txpwrindex > 127)
+				txpwrindex = 127;
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				if (NREV_IS(pi->pubpi.phy_rev, 4) &&
+				    (pi->srom_fem5g.extpagain == 3)) {
+					if (txpwrindex < 30)
+						txpwrindex = 30;
+				}
+			} else {
+				if (NREV_GE(pi->pubpi.phy_rev, 5) &&
+				    (pi->srom_fem2g.extpagain == 3)) {
+					if (txpwrindex < 50)
+						txpwrindex = 50;
+				}
+			}
+
+			wlc_phy_txpwr_index_nphy(pi, (1 << core),
+						 (u8) txpwrindex, true);
+		}
+
+		pi->nphy_txcal_pwr_idx[core] = (u8) txpwrindex;
+
+		if (debug) {
+			u16 radio_gain;
+			u16 dbg_m0m1;
+
+			wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &dbg_m0m1);
+
+			wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0,
+					     false);
+
+			wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &dbg_m0m1);
+			wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &dbg_m0m1);
+
+			udelay(100);
+
+			wlc_phy_est_tonepwr_nphy(pi, qdBm_power,
+						 NPHY_CAL_TSSISAMPS);
+
+			wlc_phy_table_read_nphy(pi, 7, 1, (0x110 + core), 16,
+						&radio_gain);
+
+			mdelay(4000);
+			pi->nphy_bb_mult_save = 0;
+			wlc_phy_stopplayback_nphy(pi);
+		}
+	}
+
+	wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_txcal_pwr_idx[0], true);
+	wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_txcal_pwr_idx[1], true);
+
+	wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &pi->nphy_txcal_bbmult);
+
+	write_phy_reg(pi, 0x01, orig_BBConfig);
+
+	write_phy_reg(pi, 0x91, phy_saveregs[0]);
+	write_phy_reg(pi, 0x92, phy_saveregs[1]);
+	write_phy_reg(pi, 0xe7, phy_saveregs[2]);
+	write_phy_reg(pi, 0xec, phy_saveregs[3]);
+
+	pi->phyhang_avoid = phyhang_avoid_state;
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void wlc_phy_savecal_nphy(struct brcms_phy *pi)
+{
+	void *tbl_ptr;
+	int coreNum;
+	u16 *txcal_radio_regs = NULL;
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+
+		wlc_phy_rx_iq_coeffs_nphy(pi, 0,
+					  &pi->calibration_cache.
+					  rxcal_coeffs_2G);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			txcal_radio_regs =
+				pi->calibration_cache.txcal_radio_regs_2G;
+		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			pi->calibration_cache.txcal_radio_regs_2G[0] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_LOFT_FINE_I |
+					       RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_2G[1] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_LOFT_FINE_Q |
+					       RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_2G[2] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_LOFT_FINE_I |
+					       RADIO_2056_TX1);
+			pi->calibration_cache.txcal_radio_regs_2G[3] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_LOFT_FINE_Q |
+					       RADIO_2056_TX1);
+
+			pi->calibration_cache.txcal_radio_regs_2G[4] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_LOFT_COARSE_I |
+					       RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_2G[5] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_LOFT_COARSE_Q |
+					       RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_2G[6] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_LOFT_COARSE_I |
+					       RADIO_2056_TX1);
+			pi->calibration_cache.txcal_radio_regs_2G[7] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_LOFT_COARSE_Q |
+					       RADIO_2056_TX1);
+		} else {
+			pi->calibration_cache.txcal_radio_regs_2G[0] =
+			       read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL);
+			pi->calibration_cache.txcal_radio_regs_2G[1] =
+			       read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL);
+			pi->calibration_cache.txcal_radio_regs_2G[2] =
+			       read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM);
+			pi->calibration_cache.txcal_radio_regs_2G[3] =
+			       read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM);
+		}
+
+		pi->nphy_iqcal_chanspec_2G = pi->radio_chanspec;
+		tbl_ptr = pi->calibration_cache.txcal_coeffs_2G;
+	} else {
+
+		wlc_phy_rx_iq_coeffs_nphy(pi, 0,
+					  &pi->calibration_cache.
+					  rxcal_coeffs_5G);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			txcal_radio_regs =
+				pi->calibration_cache.txcal_radio_regs_5G;
+		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			pi->calibration_cache.txcal_radio_regs_5G[0] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_LOFT_FINE_I |
+					       RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_5G[1] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_LOFT_FINE_Q |
+					       RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_5G[2] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_LOFT_FINE_I |
+					       RADIO_2056_TX1);
+			pi->calibration_cache.txcal_radio_regs_5G[3] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_LOFT_FINE_Q |
+					       RADIO_2056_TX1);
+
+			pi->calibration_cache.txcal_radio_regs_5G[4] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_LOFT_COARSE_I |
+					       RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_5G[5] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_LOFT_COARSE_Q |
+					       RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_5G[6] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_LOFT_COARSE_I |
+					       RADIO_2056_TX1);
+			pi->calibration_cache.txcal_radio_regs_5G[7] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_LOFT_COARSE_Q |
+					       RADIO_2056_TX1);
+		} else {
+			pi->calibration_cache.txcal_radio_regs_5G[0] =
+			       read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL);
+			pi->calibration_cache.txcal_radio_regs_5G[1] =
+			       read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL);
+			pi->calibration_cache.txcal_radio_regs_5G[2] =
+			       read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM);
+			pi->calibration_cache.txcal_radio_regs_5G[3] =
+			       read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM);
+		}
+
+		pi->nphy_iqcal_chanspec_5G = pi->radio_chanspec;
+		tbl_ptr = pi->calibration_cache.txcal_coeffs_5G;
+	}
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		for (coreNum = 0; coreNum <= 1; coreNum++) {
+
+			txcal_radio_regs[2 * coreNum] =
+				READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+						LOFT_FINE_I);
+			txcal_radio_regs[2 * coreNum + 1] =
+				READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+						LOFT_FINE_Q);
+
+			txcal_radio_regs[2 * coreNum + 4] =
+				READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+						LOFT_COARSE_I);
+			txcal_radio_regs[2 * coreNum + 5] =
+				READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+						LOFT_COARSE_Q);
+		}
+	}
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 8, 80, 16, tbl_ptr);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void wlc_phy_tx_iq_war_nphy(struct brcms_phy *pi)
+{
+	struct nphy_iq_comp tx_comp;
+
+	wlc_phy_table_read_nphy(pi, 15, 4, 0x50, 16, &tx_comp);
+
+	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ, tx_comp.a0);
+	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 2, tx_comp.b0);
+	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 4, tx_comp.a1);
+	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 6, tx_comp.b1);
+}
+
+static void wlc_phy_restorecal_nphy(struct brcms_phy *pi)
+{
+	u16 *loft_comp;
+	u16 txcal_coeffs_bphy[4];
+	u16 *tbl_ptr;
+	int coreNum;
+	u16 *txcal_radio_regs = NULL;
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (pi->nphy_iqcal_chanspec_2G == 0)
+			return;
+
+		tbl_ptr = pi->calibration_cache.txcal_coeffs_2G;
+		loft_comp = &pi->calibration_cache.txcal_coeffs_2G[5];
+	} else {
+		if (pi->nphy_iqcal_chanspec_5G == 0)
+			return;
+
+		tbl_ptr = pi->calibration_cache.txcal_coeffs_5G;
+		loft_comp = &pi->calibration_cache.txcal_coeffs_5G[5];
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80, 16, tbl_ptr);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		txcal_coeffs_bphy[0] = tbl_ptr[0];
+		txcal_coeffs_bphy[1] = tbl_ptr[1];
+		txcal_coeffs_bphy[2] = tbl_ptr[2];
+		txcal_coeffs_bphy[3] = tbl_ptr[3];
+	} else {
+		txcal_coeffs_bphy[0] = 0;
+		txcal_coeffs_bphy[1] = 0;
+		txcal_coeffs_bphy[2] = 0;
+		txcal_coeffs_bphy[3] = 0;
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88, 16,
+				 txcal_coeffs_bphy);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85, 16, loft_comp);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93, 16, loft_comp);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2))
+		wlc_phy_tx_iq_war_nphy(pi);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			txcal_radio_regs =
+				pi->calibration_cache.txcal_radio_regs_2G;
+		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_I |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[0]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_Q |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[1]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_I |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[2]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_Q |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[3]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_I |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[4]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_Q |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[5]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_I |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[6]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_Q |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[7]);
+		} else {
+			write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[0]);
+			write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[1]);
+			write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[2]);
+			write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[3]);
+		}
+
+		wlc_phy_rx_iq_coeffs_nphy(pi, 1,
+					  &pi->calibration_cache.
+					  rxcal_coeffs_2G);
+	} else {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			txcal_radio_regs =
+				pi->calibration_cache.txcal_radio_regs_5G;
+		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_I |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[0]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_Q |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[1]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_I |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[2]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_Q |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[3]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_I |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[4]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_Q |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[5]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_I |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[6]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_Q |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[7]);
+		} else {
+			write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[0]);
+			write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[1]);
+			write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[2]);
+			write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[3]);
+		}
+
+		wlc_phy_rx_iq_coeffs_nphy(pi, 1,
+					  &pi->calibration_cache.
+					  rxcal_coeffs_5G);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		for (coreNum = 0; coreNum <= 1; coreNum++) {
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					 LOFT_FINE_I,
+					 txcal_radio_regs[2 * coreNum]);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					 LOFT_FINE_Q,
+					 txcal_radio_regs[2 * coreNum + 1]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					 LOFT_COARSE_I,
+					 txcal_radio_regs[2 * coreNum + 4]);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					 LOFT_COARSE_Q,
+					 txcal_radio_regs[2 * coreNum + 5]);
+		}
+	}
+}
+
+static void wlc_phy_txpwrctrl_coeff_setup_nphy(struct brcms_phy *pi)
+{
+	u32 idx;
+	u16 iqloCalbuf[7];
+	u32 iqcomp, locomp, curr_locomp;
+	s8 locomp_i, locomp_q;
+	s8 curr_locomp_i, curr_locomp_q;
+	u32 tbl_id, tbl_len, tbl_offset;
+	u32 regval[128];
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	wlc_phy_table_read_nphy(pi, 15, 7, 80, 16, iqloCalbuf);
+
+	tbl_len = 128;
+	tbl_offset = 320;
+	for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
+	     tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
+		iqcomp =
+			(tbl_id ==
+			 26) ? (((u32) (iqloCalbuf[0] & 0x3ff)) << 10) |
+			(iqloCalbuf[1] & 0x3ff)
+			: (((u32) (iqloCalbuf[2] & 0x3ff)) << 10) |
+			(iqloCalbuf[3] & 0x3ff);
+
+		for (idx = 0; idx < tbl_len; idx++)
+			regval[idx] = iqcomp;
+		wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
+					 regval);
+	}
+
+	tbl_offset = 448;
+	for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
+	     tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
+
+		locomp =
+			(u32) ((tbl_id == 26) ? iqloCalbuf[5] : iqloCalbuf[6]);
+		locomp_i = (s8) ((locomp >> 8) & 0xff);
+		locomp_q = (s8) ((locomp) & 0xff);
+		for (idx = 0; idx < tbl_len; idx++) {
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				curr_locomp_i = locomp_i;
+				curr_locomp_q = locomp_q;
+			} else {
+				curr_locomp_i = (s8) ((locomp_i *
+						       nphy_tpc_loscale[idx] +
+						       128) >> 8);
+				curr_locomp_q =
+					(s8) ((locomp_q *
+					       nphy_tpc_loscale[idx] +
+					       128) >> 8);
+			}
+			curr_locomp = (u32) ((curr_locomp_i & 0xff) << 8);
+			curr_locomp |= (u32) (curr_locomp_q & 0xff);
+			regval[idx] = curr_locomp;
+		}
+		wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
+					 regval);
+	}
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+
+		wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX1, 0xFFFF);
+		wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX2, 0xFFFF);
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void wlc_phy_txlpfbw_nphy(struct brcms_phy *pi)
+{
+	u8 tx_lpf_bw = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+		if (CHSPEC_IS40(pi->radio_chanspec))
+			tx_lpf_bw = 3;
+		else
+			tx_lpf_bw = 1;
+
+		if (PHY_IPA(pi)) {
+			if (CHSPEC_IS40(pi->radio_chanspec))
+				tx_lpf_bw = 5;
+			else
+				tx_lpf_bw = 4;
+		}
+
+		write_phy_reg(pi, 0xe8,
+			      (tx_lpf_bw << 0) |
+			      (tx_lpf_bw << 3) |
+			      (tx_lpf_bw << 6) | (tx_lpf_bw << 9));
+
+		if (PHY_IPA(pi)) {
+
+			if (CHSPEC_IS40(pi->radio_chanspec))
+				tx_lpf_bw = 4;
+			else
+				tx_lpf_bw = 1;
+
+			write_phy_reg(pi, 0xe9,
+				      (tx_lpf_bw << 0) |
+				      (tx_lpf_bw << 3) |
+				      (tx_lpf_bw << 6) | (tx_lpf_bw << 9));
+		}
+	}
+}
+
+static void
+wlc_phy_adjust_rx_analpfbw_nphy(struct brcms_phy *pi, u16 reduction_factr)
+{
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+		if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) &&
+		    CHSPEC_IS40(pi->radio_chanspec)) {
+			if (!pi->nphy_anarxlpf_adjusted) {
+				write_radio_reg(pi,
+						(RADIO_2056_RX_RXLPF_RCCAL_LPC |
+						 RADIO_2056_RX0),
+						((pi->nphy_rccal_value +
+						  reduction_factr) | 0x80));
+
+				pi->nphy_anarxlpf_adjusted = true;
+			}
+		} else {
+			if (pi->nphy_anarxlpf_adjusted) {
+				write_radio_reg(pi,
+						(RADIO_2056_RX_RXLPF_RCCAL_LPC |
+						 RADIO_2056_RX0),
+						(pi->nphy_rccal_value | 0x80));
+
+				pi->nphy_anarxlpf_adjusted = false;
+			}
+		}
+	}
+}
+
+static void
+wlc_phy_adjust_min_noisevar_nphy(struct brcms_phy *pi, int ntones,
+				 int *tone_id_buf, u32 *noise_var_buf)
+{
+	int i;
+	u32 offset;
+	int tone_id;
+	int tbllen =
+		CHSPEC_IS40(pi->radio_chanspec) ?
+		NPHY_NOISEVAR_TBLLEN40 : NPHY_NOISEVAR_TBLLEN20;
+
+	if (pi->nphy_noisevars_adjusted) {
+		for (i = 0; i < pi->nphy_saved_noisevars.bufcount; i++) {
+			tone_id = pi->nphy_saved_noisevars.tone_id[i];
+			offset = (tone_id >= 0) ?
+				 ((tone_id *
+				   2) + 1) : (tbllen + (tone_id * 2) + 1);
+			wlc_phy_table_write_nphy(
+				pi, NPHY_TBL_ID_NOISEVAR, 1,
+				offset, 32,
+				&pi->nphy_saved_noisevars.min_noise_vars[i]);
+		}
+
+		pi->nphy_saved_noisevars.bufcount = 0;
+		pi->nphy_noisevars_adjusted = false;
+	}
+
+	if ((noise_var_buf != NULL) && (tone_id_buf != NULL)) {
+		pi->nphy_saved_noisevars.bufcount = 0;
+
+		for (i = 0; i < ntones; i++) {
+			tone_id = tone_id_buf[i];
+			offset = (tone_id >= 0) ?
+				 ((tone_id * 2) + 1) :
+				 (tbllen + (tone_id * 2) + 1);
+			pi->nphy_saved_noisevars.tone_id[i] = tone_id;
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+						offset, 32,
+						&pi->nphy_saved_noisevars.
+						min_noise_vars[i]);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+						 offset, 32, &noise_var_buf[i]);
+			pi->nphy_saved_noisevars.bufcount++;
+		}
+
+		pi->nphy_noisevars_adjusted = true;
+	}
+}
+
+static void wlc_phy_adjust_crsminpwr_nphy(struct brcms_phy *pi, u8 minpwr)
+{
+	u16 regval;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) &&
+		    CHSPEC_IS40(pi->radio_chanspec)) {
+			if (!pi->nphy_crsminpwr_adjusted) {
+				regval = read_phy_reg(pi, 0x27d);
+				pi->nphy_crsminpwr[0] = regval & 0xff;
+				regval &= 0xff00;
+				regval |= (u16) minpwr;
+				write_phy_reg(pi, 0x27d, regval);
+
+				regval = read_phy_reg(pi, 0x280);
+				pi->nphy_crsminpwr[1] = regval & 0xff;
+				regval &= 0xff00;
+				regval |= (u16) minpwr;
+				write_phy_reg(pi, 0x280, regval);
+
+				regval = read_phy_reg(pi, 0x283);
+				pi->nphy_crsminpwr[2] = regval & 0xff;
+				regval &= 0xff00;
+				regval |= (u16) minpwr;
+				write_phy_reg(pi, 0x283, regval);
+
+				pi->nphy_crsminpwr_adjusted = true;
+			}
+		} else {
+			if (pi->nphy_crsminpwr_adjusted) {
+				regval = read_phy_reg(pi, 0x27d);
+				regval &= 0xff00;
+				regval |= pi->nphy_crsminpwr[0];
+				write_phy_reg(pi, 0x27d, regval);
+
+				regval = read_phy_reg(pi, 0x280);
+				regval &= 0xff00;
+				regval |= pi->nphy_crsminpwr[1];
+				write_phy_reg(pi, 0x280, regval);
+
+				regval = read_phy_reg(pi, 0x283);
+				regval &= 0xff00;
+				regval |= pi->nphy_crsminpwr[2];
+				write_phy_reg(pi, 0x283, regval);
+
+				pi->nphy_crsminpwr_adjusted = false;
+			}
+		}
+	}
+}
+
+static void wlc_phy_spurwar_nphy(struct brcms_phy *pi)
+{
+	u16 cur_channel = 0;
+	int nphy_adj_tone_id_buf[] = { 57, 58 };
+	u32 nphy_adj_noise_var_buf[] = { 0x3ff, 0x3ff };
+	bool isAdjustNoiseVar = false;
+	uint numTonesAdjust = 0;
+	u32 tempval = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (pi->phyhang_avoid)
+			wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+		cur_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
+
+		if (pi->nphy_gband_spurwar_en) {
+
+			wlc_phy_adjust_rx_analpfbw_nphy(
+				pi,
+				NPHY_ANARXLPFBW_REDUCTIONFACT);
+
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				if ((cur_channel == 11)
+				    && CHSPEC_IS40(pi->radio_chanspec))
+					wlc_phy_adjust_min_noisevar_nphy(
+						pi, 2,
+						nphy_adj_tone_id_buf,
+						nphy_adj_noise_var_buf);
+				else
+					wlc_phy_adjust_min_noisevar_nphy(pi, 0,
+									 NULL,
+									 NULL);
+			}
+
+			wlc_phy_adjust_crsminpwr_nphy(pi,
+						     NPHY_ADJUSTED_MINCRSPOWER);
+		}
+
+		if ((pi->nphy_gband_spurwar2_en)
+		    && CHSPEC_IS2G(pi->radio_chanspec)) {
+
+			if (CHSPEC_IS40(pi->radio_chanspec)) {
+				switch (cur_channel) {
+				case 3:
+					nphy_adj_tone_id_buf[0] = 57;
+					nphy_adj_tone_id_buf[1] = 58;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x25f;
+					isAdjustNoiseVar = true;
+					break;
+				case 4:
+					nphy_adj_tone_id_buf[0] = 41;
+					nphy_adj_tone_id_buf[1] = 42;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x25f;
+					isAdjustNoiseVar = true;
+					break;
+				case 5:
+					nphy_adj_tone_id_buf[0] = 25;
+					nphy_adj_tone_id_buf[1] = 26;
+					nphy_adj_noise_var_buf[0] = 0x24f;
+					nphy_adj_noise_var_buf[1] = 0x25f;
+					isAdjustNoiseVar = true;
+					break;
+				case 6:
+					nphy_adj_tone_id_buf[0] = 9;
+					nphy_adj_tone_id_buf[1] = 10;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x24f;
+					isAdjustNoiseVar = true;
+					break;
+				case 7:
+					nphy_adj_tone_id_buf[0] = 121;
+					nphy_adj_tone_id_buf[1] = 122;
+					nphy_adj_noise_var_buf[0] = 0x18f;
+					nphy_adj_noise_var_buf[1] = 0x24f;
+					isAdjustNoiseVar = true;
+					break;
+				case 8:
+					nphy_adj_tone_id_buf[0] = 105;
+					nphy_adj_tone_id_buf[1] = 106;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x25f;
+					isAdjustNoiseVar = true;
+					break;
+				case 9:
+					nphy_adj_tone_id_buf[0] = 89;
+					nphy_adj_tone_id_buf[1] = 90;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x24f;
+					isAdjustNoiseVar = true;
+					break;
+				case 10:
+					nphy_adj_tone_id_buf[0] = 73;
+					nphy_adj_tone_id_buf[1] = 74;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x24f;
+					isAdjustNoiseVar = true;
+					break;
+				default:
+					isAdjustNoiseVar = false;
+					break;
+				}
+			}
+
+			if (isAdjustNoiseVar) {
+				numTonesAdjust = ARRAY_SIZE(nphy_adj_tone_id_buf);
+
+				wlc_phy_adjust_min_noisevar_nphy(
+					pi,
+					numTonesAdjust,
+					nphy_adj_tone_id_buf,
+					nphy_adj_noise_var_buf);
+
+				tempval = 0;
+
+			} else {
+				wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL,
+								 NULL);
+			}
+		}
+
+		if ((pi->nphy_aband_spurwar_en) &&
+		    (CHSPEC_IS5G(pi->radio_chanspec))) {
+			switch (cur_channel) {
+			case 54:
+				nphy_adj_tone_id_buf[0] = 32;
+				nphy_adj_noise_var_buf[0] = 0x25f;
+				break;
+			case 38:
+			case 102:
+			case 118:
+				if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) &&
+				    (pi->sh->chippkg == BCMA_PKG_ID_BCM4717)) {
+					nphy_adj_tone_id_buf[0] = 32;
+					nphy_adj_noise_var_buf[0] = 0x21f;
+				} else {
+					nphy_adj_tone_id_buf[0] = 0;
+					nphy_adj_noise_var_buf[0] = 0x0;
+				}
+				break;
+			case 134:
+				nphy_adj_tone_id_buf[0] = 32;
+				nphy_adj_noise_var_buf[0] = 0x21f;
+				break;
+			case 151:
+				nphy_adj_tone_id_buf[0] = 16;
+				nphy_adj_noise_var_buf[0] = 0x23f;
+				break;
+			case 153:
+			case 161:
+				nphy_adj_tone_id_buf[0] = 48;
+				nphy_adj_noise_var_buf[0] = 0x23f;
+				break;
+			default:
+				nphy_adj_tone_id_buf[0] = 0;
+				nphy_adj_noise_var_buf[0] = 0x0;
+				break;
+			}
+
+			if (nphy_adj_tone_id_buf[0]
+			    && nphy_adj_noise_var_buf[0])
+				wlc_phy_adjust_min_noisevar_nphy(
+					pi, 1,
+					nphy_adj_tone_id_buf,
+					nphy_adj_noise_var_buf);
+			else
+				wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL,
+								 NULL);
+		}
+
+		if (pi->phyhang_avoid)
+			wlc_phy_stay_in_carriersearch_nphy(pi, false);
+	}
+}
+
+void wlc_phy_init_nphy(struct brcms_phy *pi)
+{
+	u16 val;
+	u16 clip1_ths[2];
+	struct nphy_txgains target_gain;
+	u8 tx_pwr_ctrl_state;
+	bool do_nphy_cal = false;
+	uint core;
+	u32 d11_clk_ctl_st;
+	bool do_rssi_cal = false;
+
+	core = 0;
+
+	if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN))
+		pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
+
+	if ((ISNPHY(pi)) && (NREV_GE(pi->pubpi.phy_rev, 5)) &&
+	    ((pi->sh->chippkg == BCMA_PKG_ID_BCM4717) ||
+	     (pi->sh->chippkg == BCMA_PKG_ID_BCM4718))) {
+		if ((pi->sh->boardflags & BFL_EXTLNA) &&
+		    (CHSPEC_IS2G(pi->radio_chanspec)))
+			bcma_cc_set32(&pi->d11core->bus->drv_cc,
+				      BCMA_CC_CHIPCTL, 0x40);
+	}
+
+	if ((!PHY_IPA(pi)) && (pi->sh->chip == BCMA_CHIP_ID_BCM5357))
+		bcma_chipco_chipctl_maskset(&pi->d11core->bus->drv_cc, 1,
+					    ~CCTRL5357_EXTPA, CCTRL5357_EXTPA);
+
+	if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) &&
+	    CHSPEC_IS40(pi->radio_chanspec)) {
+
+		d11_clk_ctl_st = bcma_read32(pi->d11core,
+					     D11REGOFFS(clk_ctl_st));
+		bcma_mask32(pi->d11core, D11REGOFFS(clk_ctl_st),
+			    ~(CCS_FORCEHT | CCS_HTAREQ));
+
+		bcma_write32(pi->d11core, D11REGOFFS(clk_ctl_st),
+			     d11_clk_ctl_st);
+	}
+
+	pi->use_int_tx_iqlo_cal_nphy =
+		(PHY_IPA(pi) ||
+		 (NREV_GE(pi->pubpi.phy_rev, 7) ||
+		  (NREV_GE(pi->pubpi.phy_rev, 5)
+		   && pi->sh->boardflags2 & BFL2_INTERNDET_TXIQCAL)));
+
+	pi->internal_tx_iqlo_cal_tapoff_intpa_nphy = false;
+
+	pi->nphy_deaf_count = 0;
+
+	wlc_phy_tbl_init_nphy(pi);
+
+	pi->nphy_crsminpwr_adjusted = false;
+	pi->nphy_noisevars_adjusted = false;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		write_phy_reg(pi, 0xe7, 0);
+		write_phy_reg(pi, 0xec, 0);
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			write_phy_reg(pi, 0x342, 0);
+			write_phy_reg(pi, 0x343, 0);
+			write_phy_reg(pi, 0x346, 0);
+			write_phy_reg(pi, 0x347, 0);
+		}
+		write_phy_reg(pi, 0xe5, 0);
+		write_phy_reg(pi, 0xe6, 0);
+	} else {
+		write_phy_reg(pi, 0xec, 0);
+	}
+
+	write_phy_reg(pi, 0x91, 0);
+	write_phy_reg(pi, 0x92, 0);
+	if (NREV_LT(pi->pubpi.phy_rev, 6)) {
+		write_phy_reg(pi, 0x93, 0);
+		write_phy_reg(pi, 0x94, 0);
+	}
+
+	and_phy_reg(pi, 0xa1, ~3);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		write_phy_reg(pi, 0x8f, 0);
+		write_phy_reg(pi, 0xa5, 0);
+	} else {
+		write_phy_reg(pi, 0xa5, 0);
+	}
+
+	if (NREV_IS(pi->pubpi.phy_rev, 2))
+		mod_phy_reg(pi, 0xdc, 0x00ff, 0x3b);
+	else if (NREV_LT(pi->pubpi.phy_rev, 2))
+		mod_phy_reg(pi, 0xdc, 0x00ff, 0x40);
+
+	write_phy_reg(pi, 0x203, 32);
+	write_phy_reg(pi, 0x201, 32);
+
+	if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD)
+		write_phy_reg(pi, 0x20d, 160);
+	else
+		write_phy_reg(pi, 0x20d, 184);
+
+	write_phy_reg(pi, 0x13a, 200);
+
+	write_phy_reg(pi, 0x70, 80);
+
+	write_phy_reg(pi, 0x1ff, 48);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 8))
+		wlc_phy_update_mimoconfig_nphy(pi, pi->n_preamble_override);
+
+	wlc_phy_stf_chain_upd_nphy(pi);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+		write_phy_reg(pi, 0x180, 0xaa8);
+		write_phy_reg(pi, 0x181, 0x9a4);
+	}
+
+	if (PHY_IPA(pi)) {
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+				    0x29b, (0x1 << 0), (1) << 0);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x298 :
+				    0x29c, (0x1ff << 7),
+				    (pi->nphy_papd_epsilon_offset[core]) << 7);
+
+		}
+
+		wlc_phy_ipa_set_tx_digi_filts_nphy(pi);
+	} else if (NREV_GE(pi->pubpi.phy_rev, 5)) {
+		wlc_phy_extpa_set_tx_digi_filts_nphy(pi);
+	}
+
+	wlc_phy_workarounds_nphy(pi);
+
+	wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
+
+	val = read_phy_reg(pi, 0x01);
+	write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA);
+	write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA));
+	wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
+
+	wlapi_bmac_macphyclk_set(pi->sh->physhim, ON);
+
+	wlc_phy_pa_override_nphy(pi, OFF);
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX);
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+	wlc_phy_pa_override_nphy(pi, ON);
+
+	wlc_phy_classifier_nphy(pi, 0, 0);
+	wlc_phy_clip_det_nphy(pi, 0, clip1_ths);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec))
+		wlc_phy_bphy_init_nphy(pi);
+
+	tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
+	wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
+
+	wlc_phy_txpwr_fixpower_nphy(pi);
+
+	wlc_phy_txpwrctrl_idle_tssi_nphy(pi);
+
+	wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		u32 *tx_pwrctrl_tbl = NULL;
+		u16 idx;
+		s16 pga_gn = 0;
+		s16 pad_gn = 0;
+		s32 rfpwr_offset;
+
+		if (PHY_IPA(pi)) {
+			tx_pwrctrl_tbl = wlc_phy_get_ipa_gaintbl_nphy(pi);
+		} else {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				if (NREV_IS(pi->pubpi.phy_rev, 3))
+					tx_pwrctrl_tbl =
+						nphy_tpc_5GHz_txgain_rev3;
+				else if (NREV_IS(pi->pubpi.phy_rev, 4))
+					tx_pwrctrl_tbl =
+						(pi->srom_fem5g.extpagain ==
+						 3) ?
+						nphy_tpc_5GHz_txgain_HiPwrEPA :
+						nphy_tpc_5GHz_txgain_rev4;
+				else
+					tx_pwrctrl_tbl =
+						nphy_tpc_5GHz_txgain_rev5;
+			} else {
+				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+					if (pi->pubpi.radiorev == 5)
+						tx_pwrctrl_tbl =
+						   nphy_tpc_txgain_epa_2057rev5;
+					else if (pi->pubpi.radiorev == 3)
+						tx_pwrctrl_tbl =
+						   nphy_tpc_txgain_epa_2057rev3;
+				} else {
+					if (NREV_GE(pi->pubpi.phy_rev, 5) &&
+					    (pi->srom_fem2g.extpagain == 3))
+						tx_pwrctrl_tbl =
+						       nphy_tpc_txgain_HiPwrEPA;
+					else
+						tx_pwrctrl_tbl =
+							nphy_tpc_txgain_rev3;
+				}
+			}
+		}
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128,
+					 192, 32, tx_pwrctrl_tbl);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128,
+					 192, 32, tx_pwrctrl_tbl);
+
+		pi->nphy_gmval = (u16) ((*tx_pwrctrl_tbl >> 16) & 0x7000);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+			for (idx = 0; idx < 128; idx++) {
+				pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf;
+				pad_gn = (tx_pwrctrl_tbl[idx] >> 19) & 0x1f;
+				rfpwr_offset = get_rf_pwr_offset(pi, pga_gn,
+								 pad_gn);
+				wlc_phy_table_write_nphy(
+					pi,
+					NPHY_TBL_ID_CORE1TXPWRCTL,
+					1, 576 + idx, 32,
+					&rfpwr_offset);
+				wlc_phy_table_write_nphy(
+					pi,
+					NPHY_TBL_ID_CORE2TXPWRCTL,
+					1, 576 + idx, 32,
+					&rfpwr_offset);
+			}
+		} else {
+
+			for (idx = 0; idx < 128; idx++) {
+				pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf;
+				if (CHSPEC_IS2G(pi->radio_chanspec))
+					rfpwr_offset = (s16)
+						 nphy_papd_pga_gain_delta_ipa_2g
+								       [pga_gn];
+				else
+					rfpwr_offset = (s16)
+						 nphy_papd_pga_gain_delta_ipa_5g
+								       [pga_gn];
+
+				wlc_phy_table_write_nphy(
+					pi,
+					NPHY_TBL_ID_CORE1TXPWRCTL,
+					1, 576 + idx, 32,
+					&rfpwr_offset);
+				wlc_phy_table_write_nphy(
+					pi,
+					NPHY_TBL_ID_CORE2TXPWRCTL,
+					1, 576 + idx, 32,
+					&rfpwr_offset);
+			}
+
+		}
+	} else {
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128,
+					 192, 32, nphy_tpc_txgain);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128,
+					 192, 32, nphy_tpc_txgain);
+	}
+
+	if (pi->sh->phyrxchain != 0x3)
+		wlc_phy_rxcore_setstate_nphy((struct brcms_phy_pub *) pi,
+					     pi->sh->phyrxchain);
+
+	if (PHY_PERICAL_MPHASE_PENDING(pi))
+		wlc_phy_cal_perical_mphase_restart(pi);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		do_rssi_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ?
+			      (pi->nphy_rssical_chanspec_2G == 0) :
+			      (pi->nphy_rssical_chanspec_5G == 0);
+
+		if (do_rssi_cal)
+			wlc_phy_rssi_cal_nphy(pi);
+		else
+			wlc_phy_restore_rssical_nphy(pi);
+	} else {
+		wlc_phy_rssi_cal_nphy(pi);
+	}
+
+	if (!SCAN_RM_IN_PROGRESS(pi))
+		do_nphy_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ?
+			      (pi->nphy_iqcal_chanspec_2G == 0) :
+			      (pi->nphy_iqcal_chanspec_5G == 0);
+
+	if (!pi->do_initcal)
+		do_nphy_cal = false;
+
+	if (do_nphy_cal) {
+
+		target_gain = wlc_phy_get_tx_gain_nphy(pi);
+
+		if (pi->antsel_type == ANTSEL_2x3)
+			wlc_phy_antsel_init((struct brcms_phy_pub *) pi,
+					    true);
+
+		if (pi->nphy_perical != PHY_PERICAL_MPHASE) {
+			wlc_phy_rssi_cal_nphy(pi);
+
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				pi->nphy_cal_orig_pwr_idx[0] =
+					pi->nphy_txpwrindex[PHY_CORE_0]
+					.
+					index_internal;
+				pi->nphy_cal_orig_pwr_idx[1] =
+					pi->nphy_txpwrindex[PHY_CORE_1]
+					.
+					index_internal;
+
+				wlc_phy_precal_txgain_nphy(pi);
+				target_gain =
+					wlc_phy_get_tx_gain_nphy(pi);
+			}
+
+			if (wlc_phy_cal_txiqlo_nphy
+				    (pi, target_gain, true,
+				    false) == 0) {
+				if (wlc_phy_cal_rxiq_nphy
+					    (pi, target_gain, 2,
+					    false) == 0)
+					wlc_phy_savecal_nphy(pi);
+
+			}
+		} else if (pi->mphase_cal_phase_id ==
+			   MPHASE_CAL_STATE_IDLE) {
+			wlc_phy_cal_perical((struct brcms_phy_pub *) pi,
+					    PHY_PERICAL_PHYINIT);
+		}
+	} else {
+		wlc_phy_restorecal_nphy(pi);
+	}
+
+	wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
+
+	wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
+
+	wlc_phy_nphy_tkip_rifs_war(pi, pi->sh->_rifs_phy);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LE(pi->pubpi.phy_rev, 6))
+
+		write_phy_reg(pi, 0x70, 50);
+
+	wlc_phy_txlpfbw_nphy(pi);
+
+	wlc_phy_spurwar_nphy(pi);
+
+}
+
+static void wlc_phy_resetcca_nphy(struct brcms_phy *pi)
+{
+	u16 val;
+
+	wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
+
+	val = read_phy_reg(pi, 0x01);
+	write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA);
+	udelay(1);
+	write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA));
+
+	wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
+
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+}
+
+void wlc_phy_pa_override_nphy(struct brcms_phy *pi, bool en)
+{
+	u16 rfctrlintc_override_val;
+
+	if (!en) {
+
+		pi->rfctrlIntc1_save = read_phy_reg(pi, 0x91);
+		pi->rfctrlIntc2_save = read_phy_reg(pi, 0x92);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7))
+			rfctrlintc_override_val = 0x1480;
+		else if (NREV_GE(pi->pubpi.phy_rev, 3))
+			rfctrlintc_override_val =
+				CHSPEC_IS5G(pi->radio_chanspec) ? 0x600 : 0x480;
+		else
+			rfctrlintc_override_val =
+				CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120;
+
+		write_phy_reg(pi, 0x91, rfctrlintc_override_val);
+		write_phy_reg(pi, 0x92, rfctrlintc_override_val);
+	} else {
+		write_phy_reg(pi, 0x91, pi->rfctrlIntc1_save);
+		write_phy_reg(pi, 0x92, pi->rfctrlIntc2_save);
+	}
+
+}
+
+void wlc_phy_stf_chain_upd_nphy(struct brcms_phy *pi)
+{
+
+	u16 txrx_chain =
+		(NPHY_RfseqCoreActv_TxRxChain0 | NPHY_RfseqCoreActv_TxRxChain1);
+	bool CoreActv_override = false;
+
+	if (pi->nphy_txrx_chain == BRCMS_N_TXRX_CHAIN0) {
+		txrx_chain = NPHY_RfseqCoreActv_TxRxChain0;
+		CoreActv_override = true;
+
+		if (NREV_LE(pi->pubpi.phy_rev, 2))
+			and_phy_reg(pi, 0xa0, ~0x20);
+	} else if (pi->nphy_txrx_chain == BRCMS_N_TXRX_CHAIN1) {
+		txrx_chain = NPHY_RfseqCoreActv_TxRxChain1;
+		CoreActv_override = true;
+
+		if (NREV_LE(pi->pubpi.phy_rev, 2))
+			or_phy_reg(pi, 0xa0, 0x20);
+	}
+
+	mod_phy_reg(pi, 0xa2, ((0xf << 0) | (0xf << 4)), txrx_chain);
+
+	if (CoreActv_override) {
+		pi->nphy_perical = PHY_PERICAL_DISABLE;
+		or_phy_reg(pi, 0xa1, NPHY_RfseqMode_CoreActv_override);
+	} else {
+		pi->nphy_perical = PHY_PERICAL_MPHASE;
+		and_phy_reg(pi, 0xa1, ~NPHY_RfseqMode_CoreActv_override);
+	}
+}
+
+void wlc_phy_rxcore_setstate_nphy(struct brcms_phy_pub *pih, u8 rxcore_bitmask)
+{
+	u16 regval;
+	u16 tbl_buf[16];
+	uint i;
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+	u16 tbl_opcode;
+	bool suspend;
+
+	pi->sh->phyrxchain = rxcore_bitmask;
+
+	if (!pi->sh->clk)
+		return;
+
+	suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
+			 MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	regval = read_phy_reg(pi, 0xa2);
+	regval &= ~(0xf << 4);
+	regval |= ((u16) (rxcore_bitmask & 0x3)) << 4;
+	write_phy_reg(pi, 0xa2, regval);
+
+	if ((rxcore_bitmask & 0x3) != 0x3) {
+
+		write_phy_reg(pi, 0x20e, 1);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			if (pi->rx2tx_biasentry == -1) {
+				wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							ARRAY_SIZE(tbl_buf), 80,
+							16, tbl_buf);
+
+				for (i = 0; i < ARRAY_SIZE(tbl_buf); i++) {
+					if (tbl_buf[i] ==
+					    NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS) {
+						pi->rx2tx_biasentry = (u8) i;
+						tbl_opcode =
+							NPHY_REV3_RFSEQ_CMD_NOP;
+						wlc_phy_table_write_nphy(
+							pi,
+							NPHY_TBL_ID_RFSEQ,
+							1, i,
+							16,
+							&tbl_opcode);
+						break;
+					} else if (tbl_buf[i] ==
+						   NPHY_REV3_RFSEQ_CMD_END)
+						break;
+				}
+			}
+		}
+	} else {
+
+		write_phy_reg(pi, 0x20e, 30);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			if (pi->rx2tx_biasentry != -1) {
+				tbl_opcode = NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS;
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1, pi->rx2tx_biasentry,
+							 16, &tbl_opcode);
+				pi->rx2tx_biasentry = -1;
+			}
+		}
+	}
+
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+}
+
+u8 wlc_phy_rxcore_getstate_nphy(struct brcms_phy_pub *pih)
+{
+	u16 regval, rxen_bits;
+	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
+
+	regval = read_phy_reg(pi, 0xa2);
+	rxen_bits = (regval >> 4) & 0xf;
+
+	return (u8) rxen_bits;
+}
+
+bool wlc_phy_n_txpower_ipa_ison(struct brcms_phy *pi)
+{
+	return PHY_IPA(pi);
+}
+
+void wlc_phy_cal_init_nphy(struct brcms_phy *pi)
+{
+}
+
+static void wlc_phy_radio_preinit_205x(struct brcms_phy *pi)
+{
+
+	and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
+	and_phy_reg(pi, 0x78, RFCC_OE_POR_FORCE);
+
+	or_phy_reg(pi, 0x78, ~RFCC_OE_POR_FORCE);
+	or_phy_reg(pi, 0x78, RFCC_CHIP0_PU);
+
+}
+
+static void wlc_phy_radio_init_2057(struct brcms_phy *pi)
+{
+	struct radio_20xx_regs *regs_2057_ptr = NULL;
+
+	if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+		regs_2057_ptr = regs_2057_rev4;
+	} else if (NREV_IS(pi->pubpi.phy_rev, 8)
+		   || NREV_IS(pi->pubpi.phy_rev, 9)) {
+		switch (pi->pubpi.radiorev) {
+		case 5:
+
+			if (NREV_IS(pi->pubpi.phy_rev, 8))
+				regs_2057_ptr = regs_2057_rev5;
+			else if (NREV_IS(pi->pubpi.phy_rev, 9))
+				regs_2057_ptr = regs_2057_rev5v1;
+			break;
+
+		case 7:
+
+			regs_2057_ptr = regs_2057_rev7;
+			break;
+
+		case 8:
+
+			regs_2057_ptr = regs_2057_rev8;
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	wlc_phy_init_radio_regs_allbands(pi, regs_2057_ptr);
+}
+
+static u16 wlc_phy_radio205x_rcal(struct brcms_phy *pi)
+{
+	u16 rcal_reg = 0;
+	int i;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		if (pi->pubpi.radiorev == 5) {
+
+			and_phy_reg(pi, 0x342, ~(0x1 << 1));
+
+			udelay(10);
+
+			mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x1);
+			mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2,
+				      0x1);
+		}
+		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x1);
+
+		udelay(10);
+
+		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x3, 0x3);
+
+		for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+			rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS);
+			if (rcal_reg & 0x1)
+				break;
+
+			udelay(100);
+		}
+
+		if (WARN(i == MAX_205x_RCAL_WAITLOOPS,
+			 "HW error: radio calib2"))
+			return 0;
+
+		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x2, 0x0);
+
+		rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS) & 0x3e;
+
+		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x0);
+		if (pi->pubpi.radiorev == 5) {
+
+			mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x0);
+			mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2,
+				      0x0);
+		}
+
+		if ((pi->pubpi.radiorev <= 4) || (pi->pubpi.radiorev == 6)) {
+
+			mod_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x3c,
+				      rcal_reg);
+			mod_radio_reg(pi, RADIO_2057_BANDGAP_RCAL_TRIM, 0xf0,
+				      rcal_reg << 2);
+		}
+
+	} else if (NREV_IS(pi->pubpi.phy_rev, 3)) {
+		u16 savereg;
+
+		savereg =
+			read_radio_reg(
+				pi,
+				RADIO_2056_SYN_PLL_MAST2 |
+				RADIO_2056_SYN);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN,
+				savereg | 0x7);
+		udelay(10);
+
+		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+				0x1);
+		udelay(10);
+
+		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+				0x9);
+
+		for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+			rcal_reg = read_radio_reg(
+				pi,
+				RADIO_2056_SYN_RCAL_CODE_OUT |
+				RADIO_2056_SYN);
+			if (rcal_reg & 0x80)
+				break;
+
+			udelay(100);
+		}
+
+		if (WARN(i == MAX_205x_RCAL_WAITLOOPS,
+			 "HW error: radio calib3"))
+			return 0;
+
+		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+				0x1);
+
+		rcal_reg =
+			read_radio_reg(pi,
+				       RADIO_2056_SYN_RCAL_CODE_OUT |
+				       RADIO_2056_SYN);
+
+		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+				0x0);
+
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN,
+				savereg);
+
+		return rcal_reg & 0x1f;
+	}
+	return rcal_reg & 0x3e;
+}
+
+static u16 wlc_phy_radio2057_rccal(struct brcms_phy *pi)
+{
+	u16 rccal_valid;
+	int i;
+	bool chip43226_6362A0;
+
+	chip43226_6362A0 = ((pi->pubpi.radiorev == 3)
+			    || (pi->pubpi.radiorev == 4)
+			    || (pi->pubpi.radiorev == 6));
+
+	rccal_valid = 0;
+	if (chip43226_6362A0) {
+		write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x61);
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xc0);
+	} else {
+		write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x61);
+
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xe9);
+	}
+	write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
+
+	for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+		rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
+		if (rccal_valid & 0x2)
+			break;
+
+		udelay(500);
+	}
+
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
+
+	rccal_valid = 0;
+	if (chip43226_6362A0) {
+		write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x69);
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0);
+	} else {
+		write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x69);
+
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xd5);
+	}
+	write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
+
+	for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+		rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
+		if (rccal_valid & 0x2)
+			break;
+
+		udelay(500);
+	}
+
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
+
+	rccal_valid = 0;
+	if (chip43226_6362A0) {
+		write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x73);
+
+		write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x28);
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0);
+	} else {
+		write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x73);
+		write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0x99);
+	}
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
+
+	for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+		rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
+		if (rccal_valid & 0x2)
+			break;
+
+		udelay(500);
+	}
+
+	if (WARN(!(rccal_valid & 0x2), "HW error: radio calib4"))
+		return 0;
+
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
+
+	return rccal_valid;
+}
+
+static void wlc_phy_radio_postinit_2057(struct brcms_phy *pi)
+{
+
+	mod_radio_reg(pi, RADIO_2057_XTALPUOVR_PINCTRL, 0x1, 0x1);
+
+	mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x78);
+	mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x80);
+	mdelay(2);
+	mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x0);
+	mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x0);
+
+	if (pi->phy_init_por) {
+		wlc_phy_radio205x_rcal(pi);
+		wlc_phy_radio2057_rccal(pi);
+	}
+
+	mod_radio_reg(pi, RADIO_2057_RFPLL_MASTER, 0x8, 0x0);
+}
+
+static void wlc_phy_radio_init_2056(struct brcms_phy *pi)
+{
+	const struct radio_regs *regs_SYN_2056_ptr = NULL;
+	const struct radio_regs *regs_TX_2056_ptr = NULL;
+	const struct radio_regs *regs_RX_2056_ptr = NULL;
+
+	if (NREV_IS(pi->pubpi.phy_rev, 3)) {
+		regs_SYN_2056_ptr = regs_SYN_2056;
+		regs_TX_2056_ptr = regs_TX_2056;
+		regs_RX_2056_ptr = regs_RX_2056;
+	} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+		regs_SYN_2056_ptr = regs_SYN_2056_A1;
+		regs_TX_2056_ptr = regs_TX_2056_A1;
+		regs_RX_2056_ptr = regs_RX_2056_A1;
+	} else {
+		switch (pi->pubpi.radiorev) {
+		case 5:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev5;
+			regs_TX_2056_ptr = regs_TX_2056_rev5;
+			regs_RX_2056_ptr = regs_RX_2056_rev5;
+			break;
+
+		case 6:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev6;
+			regs_TX_2056_ptr = regs_TX_2056_rev6;
+			regs_RX_2056_ptr = regs_RX_2056_rev6;
+			break;
+
+		case 7:
+		case 9:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev7;
+			regs_TX_2056_ptr = regs_TX_2056_rev7;
+			regs_RX_2056_ptr = regs_RX_2056_rev7;
+			break;
+
+		case 8:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev8;
+			regs_TX_2056_ptr = regs_TX_2056_rev8;
+			regs_RX_2056_ptr = regs_RX_2056_rev8;
+			break;
+
+		case 11:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev11;
+			regs_TX_2056_ptr = regs_TX_2056_rev11;
+			regs_RX_2056_ptr = regs_RX_2056_rev11;
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	wlc_phy_init_radio_regs(pi, regs_SYN_2056_ptr, (u16) RADIO_2056_SYN);
+
+	wlc_phy_init_radio_regs(pi, regs_TX_2056_ptr, (u16) RADIO_2056_TX0);
+
+	wlc_phy_init_radio_regs(pi, regs_TX_2056_ptr, (u16) RADIO_2056_TX1);
+
+	wlc_phy_init_radio_regs(pi, regs_RX_2056_ptr, (u16) RADIO_2056_RX0);
+
+	wlc_phy_init_radio_regs(pi, regs_RX_2056_ptr, (u16) RADIO_2056_RX1);
+}
+
+static void wlc_phy_radio_postinit_2056(struct brcms_phy *pi)
+{
+	mod_radio_reg(pi, RADIO_2056_SYN_COM_CTRL, 0xb, 0xb);
+
+	mod_radio_reg(pi, RADIO_2056_SYN_COM_PU, 0x2, 0x2);
+	mod_radio_reg(pi, RADIO_2056_SYN_COM_RESET, 0x2, 0x2);
+	udelay(1000);
+	mod_radio_reg(pi, RADIO_2056_SYN_COM_RESET, 0x2, 0x0);
+
+	if ((pi->sh->boardflags2 & BFL2_LEGACY)
+	    || (pi->sh->boardflags2 & BFL2_XTALBUFOUTEN))
+		mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xf4, 0x0);
+	else
+		mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xfc, 0x0);
+
+	mod_radio_reg(pi, RADIO_2056_SYN_RCCAL_CTRL0, 0x1, 0x0);
+
+	if (pi->phy_init_por)
+		wlc_phy_radio205x_rcal(pi);
+}
+
+static void wlc_phy_radio_preinit_2055(struct brcms_phy *pi)
+{
+
+	and_phy_reg(pi, 0x78, ~RFCC_POR_FORCE);
+	or_phy_reg(pi, 0x78, RFCC_CHIP0_PU | RFCC_OE_POR_FORCE);
+
+	or_phy_reg(pi, 0x78, RFCC_POR_FORCE);
+}
+
+static void wlc_phy_radio_init_2055(struct brcms_phy *pi)
+{
+	wlc_phy_init_radio_regs(pi, regs_2055, RADIO_DEFAULT_CORE);
+}
+
+static void wlc_phy_radio_postinit_2055(struct brcms_phy *pi)
+{
+
+	and_radio_reg(pi, RADIO_2055_MASTER_CNTRL1,
+		      ~(RADIO_2055_JTAGCTRL_MASK | RADIO_2055_JTAGSYNC_MASK));
+
+	if (((pi->sh->sromrev >= 4)
+	     && !(pi->sh->boardflags2 & BFL2_RXBB_INT_REG_DIS))
+	    || ((pi->sh->sromrev < 4))) {
+		and_radio_reg(pi, RADIO_2055_CORE1_RXBB_REGULATOR, 0x7F);
+		and_radio_reg(pi, RADIO_2055_CORE2_RXBB_REGULATOR, 0x7F);
+	}
+
+	mod_radio_reg(pi, RADIO_2055_RRCCAL_N_OPT_SEL, 0x3F, 0x2C);
+	write_radio_reg(pi, RADIO_2055_CAL_MISC, 0x3C);
+
+	and_radio_reg(pi, RADIO_2055_CAL_MISC,
+		      ~(RADIO_2055_RRCAL_START | RADIO_2055_RRCAL_RST_N));
+
+	or_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL, RADIO_2055_CAL_LPO_ENABLE);
+
+	or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_RST_N);
+
+	udelay(1000);
+
+	or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_START);
+
+	SPINWAIT(((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) &
+		   RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE), 2000);
+
+	if (WARN((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) &
+		  RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE,
+		 "HW error: radio calibration1\n"))
+		return;
+
+	and_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL,
+		      ~(RADIO_2055_CAL_LPO_ENABLE));
+
+	wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec);
+
+	write_radio_reg(pi, RADIO_2055_CORE1_RXBB_LPF, 9);
+	write_radio_reg(pi, RADIO_2055_CORE2_RXBB_LPF, 9);
+
+	write_radio_reg(pi, RADIO_2055_CORE1_RXBB_MIDAC_HIPAS, 0x83);
+	write_radio_reg(pi, RADIO_2055_CORE2_RXBB_MIDAC_HIPAS, 0x83);
+
+	mod_radio_reg(pi, RADIO_2055_CORE1_LNA_GAINBST,
+		      RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE);
+	mod_radio_reg(pi, RADIO_2055_CORE2_LNA_GAINBST,
+		      RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE);
+	if (pi->nphy_gain_boost) {
+		and_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1,
+			      ~(RADIO_2055_GAINBST_DISABLE));
+		and_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1,
+			      ~(RADIO_2055_GAINBST_DISABLE));
+	} else {
+		or_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1,
+			     RADIO_2055_GAINBST_DISABLE);
+		or_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1,
+			     RADIO_2055_GAINBST_DISABLE);
+	}
+
+	udelay(2);
+}
+
+void wlc_phy_switch_radio_nphy(struct brcms_phy *pi, bool on)
+{
+	if (on) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			if (!pi->radio_is_on) {
+				wlc_phy_radio_preinit_205x(pi);
+				wlc_phy_radio_init_2057(pi);
+				wlc_phy_radio_postinit_2057(pi);
+			}
+
+			wlc_phy_chanspec_set((struct brcms_phy_pub *) pi,
+					     pi->radio_chanspec);
+		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			wlc_phy_radio_preinit_205x(pi);
+			wlc_phy_radio_init_2056(pi);
+			wlc_phy_radio_postinit_2056(pi);
+
+			wlc_phy_chanspec_set((struct brcms_phy_pub *) pi,
+					     pi->radio_chanspec);
+		} else {
+			wlc_phy_radio_preinit_2055(pi);
+			wlc_phy_radio_init_2055(pi);
+			wlc_phy_radio_postinit_2055(pi);
+		}
+
+		pi->radio_is_on = true;
+
+	} else {
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)
+		    && NREV_LT(pi->pubpi.phy_rev, 7)) {
+			and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
+			mod_radio_reg(pi, RADIO_2056_SYN_COM_PU, 0x2, 0x0);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_PADA_BOOST_TUNE |
+					RADIO_2056_TX0, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PADG_BOOST_TUNE |
+					RADIO_2056_TX0, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PGAA_BOOST_TUNE |
+					RADIO_2056_TX0, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PGAG_BOOST_TUNE |
+					RADIO_2056_TX0, 0);
+			mod_radio_reg(pi,
+				      RADIO_2056_TX_MIXA_BOOST_TUNE |
+				      RADIO_2056_TX0, 0xf0, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_MIXG_BOOST_TUNE |
+					RADIO_2056_TX0, 0);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_PADA_BOOST_TUNE |
+					RADIO_2056_TX1, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PADG_BOOST_TUNE |
+					RADIO_2056_TX1, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PGAA_BOOST_TUNE |
+					RADIO_2056_TX1, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PGAG_BOOST_TUNE |
+					RADIO_2056_TX1, 0);
+			mod_radio_reg(pi,
+				      RADIO_2056_TX_MIXA_BOOST_TUNE |
+				      RADIO_2056_TX1, 0xf0, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_MIXG_BOOST_TUNE |
+					RADIO_2056_TX1, 0);
+
+			pi->radio_is_on = false;
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 8)) {
+			and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
+			pi->radio_is_on = false;
+		}
+
+	}
+}
+
+static bool
+wlc_phy_chan2freq_nphy(struct brcms_phy *pi, uint channel, int *f,
+		       const struct chan_info_nphy_radio2057 **t0,
+		       const struct chan_info_nphy_radio205x **t1,
+		       const struct chan_info_nphy_radio2057_rev5 **t2,
+		       const struct chan_info_nphy_2055 **t3)
+{
+	uint i;
+	const struct chan_info_nphy_radio2057 *chan_info_tbl_p_0 = NULL;
+	const struct chan_info_nphy_radio205x *chan_info_tbl_p_1 = NULL;
+	const struct chan_info_nphy_radio2057_rev5 *chan_info_tbl_p_2 = NULL;
+	u32 tbl_len = 0;
+
+	int freq = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+
+			chan_info_tbl_p_0 = chan_info_nphyrev7_2057_rev4;
+			tbl_len = ARRAY_SIZE(chan_info_nphyrev7_2057_rev4);
+
+		} else if (NREV_IS(pi->pubpi.phy_rev, 8)
+			   || NREV_IS(pi->pubpi.phy_rev, 9)) {
+			switch (pi->pubpi.radiorev) {
+
+			case 5:
+
+				if (pi->pubpi.radiover == 0x0) {
+
+					chan_info_tbl_p_2 =
+						chan_info_nphyrev8_2057_rev5;
+					tbl_len = ARRAY_SIZE(
+						  chan_info_nphyrev8_2057_rev5);
+
+				} else if (pi->pubpi.radiover == 0x1) {
+
+					chan_info_tbl_p_2 =
+						chan_info_nphyrev9_2057_rev5v1;
+					tbl_len = ARRAY_SIZE(
+						chan_info_nphyrev9_2057_rev5v1);
+
+				}
+				break;
+
+			case 7:
+				chan_info_tbl_p_0 =
+					chan_info_nphyrev8_2057_rev7;
+				tbl_len = ARRAY_SIZE(
+						  chan_info_nphyrev8_2057_rev7);
+				break;
+
+			case 8:
+				chan_info_tbl_p_0 =
+					chan_info_nphyrev8_2057_rev8;
+				tbl_len = ARRAY_SIZE(
+						  chan_info_nphyrev8_2057_rev8);
+				break;
+
+			default:
+				break;
+			}
+		} else if (NREV_IS(pi->pubpi.phy_rev, 16)) {
+
+			chan_info_tbl_p_0 = chan_info_nphyrev8_2057_rev8;
+			tbl_len = ARRAY_SIZE(chan_info_nphyrev8_2057_rev8);
+		} else {
+			goto fail;
+		}
+
+		for (i = 0; i < tbl_len; i++) {
+			if (pi->pubpi.radiorev == 5) {
+
+				if (chan_info_tbl_p_2[i].chan == channel)
+					break;
+			} else {
+
+				if (chan_info_tbl_p_0[i].chan == channel)
+					break;
+			}
+		}
+
+		if (i >= tbl_len)
+			goto fail;
+
+		if (pi->pubpi.radiorev == 5) {
+			*t2 = &chan_info_tbl_p_2[i];
+			freq = chan_info_tbl_p_2[i].freq;
+		} else {
+			*t0 = &chan_info_tbl_p_0[i];
+			freq = chan_info_tbl_p_0[i].freq;
+		}
+
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (NREV_IS(pi->pubpi.phy_rev, 3)) {
+			chan_info_tbl_p_1 = chan_info_nphyrev3_2056;
+			tbl_len = ARRAY_SIZE(chan_info_nphyrev3_2056);
+		} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+			chan_info_tbl_p_1 = chan_info_nphyrev4_2056_A1;
+			tbl_len = ARRAY_SIZE(chan_info_nphyrev4_2056_A1);
+		} else if (NREV_IS(pi->pubpi.phy_rev, 5)
+			   || NREV_IS(pi->pubpi.phy_rev, 6)) {
+			switch (pi->pubpi.radiorev) {
+			case 5:
+				chan_info_tbl_p_1 = chan_info_nphyrev5_2056v5;
+				tbl_len = ARRAY_SIZE(chan_info_nphyrev5_2056v5);
+				break;
+			case 6:
+				chan_info_tbl_p_1 = chan_info_nphyrev6_2056v6;
+				tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v6);
+				break;
+			case 7:
+			case 9:
+				chan_info_tbl_p_1 = chan_info_nphyrev5n6_2056v7;
+				tbl_len =
+					ARRAY_SIZE(chan_info_nphyrev5n6_2056v7);
+				break;
+			case 8:
+				chan_info_tbl_p_1 = chan_info_nphyrev6_2056v8;
+				tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v8);
+				break;
+			case 11:
+				chan_info_tbl_p_1 = chan_info_nphyrev6_2056v11;
+				tbl_len = ARRAY_SIZE(
+						    chan_info_nphyrev6_2056v11);
+				break;
+			default:
+				break;
+			}
+		}
+
+		for (i = 0; i < tbl_len; i++) {
+			if (chan_info_tbl_p_1[i].chan == channel)
+				break;
+		}
+
+		if (i >= tbl_len)
+			goto fail;
+
+		*t1 = &chan_info_tbl_p_1[i];
+		freq = chan_info_tbl_p_1[i].freq;
+
+	} else {
+		for (i = 0; i < ARRAY_SIZE(chan_info_nphy_2055); i++)
+			if (chan_info_nphy_2055[i].chan == channel)
+				break;
+
+		if (i >= ARRAY_SIZE(chan_info_nphy_2055))
+			goto fail;
+
+		*t3 = &chan_info_nphy_2055[i];
+		freq = chan_info_nphy_2055[i].freq;
+	}
+
+	*f = freq;
+	return true;
+
+fail:
+	*f = WL_CHAN_FREQ_RANGE_2G;
+	return false;
+}
+
+u8 wlc_phy_get_chan_freq_range_nphy(struct brcms_phy *pi, uint channel)
+{
+	int freq;
+	const struct chan_info_nphy_radio2057 *t0 = NULL;
+	const struct chan_info_nphy_radio205x *t1 = NULL;
+	const struct chan_info_nphy_radio2057_rev5 *t2 = NULL;
+	const struct chan_info_nphy_2055 *t3 = NULL;
+
+	if (channel == 0)
+		channel = CHSPEC_CHANNEL(pi->radio_chanspec);
+
+	wlc_phy_chan2freq_nphy(pi, channel, &freq, &t0, &t1, &t2, &t3);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec))
+		return WL_CHAN_FREQ_RANGE_2G;
+
+	if ((freq >= BASE_LOW_5G_CHAN) && (freq < BASE_MID_5G_CHAN))
+		return WL_CHAN_FREQ_RANGE_5GL;
+	else if ((freq >= BASE_MID_5G_CHAN) && (freq < BASE_HIGH_5G_CHAN))
+		return WL_CHAN_FREQ_RANGE_5GM;
+	else
+		return WL_CHAN_FREQ_RANGE_5GH;
+}
+
+static void
+wlc_phy_chanspec_radio2055_setup(struct brcms_phy *pi,
+				 const struct chan_info_nphy_2055 *ci)
+{
+
+	write_radio_reg(pi, RADIO_2055_PLL_REF, ci->RF_pll_ref);
+	write_radio_reg(pi, RADIO_2055_RF_PLL_MOD0, ci->RF_rf_pll_mod0);
+	write_radio_reg(pi, RADIO_2055_RF_PLL_MOD1, ci->RF_rf_pll_mod1);
+	write_radio_reg(pi, RADIO_2055_VCO_CAP_TAIL, ci->RF_vco_cap_tail);
+
+	BRCMS_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_VCO_CAL1, ci->RF_vco_cal1);
+	write_radio_reg(pi, RADIO_2055_VCO_CAL2, ci->RF_vco_cal2);
+	write_radio_reg(pi, RADIO_2055_PLL_LF_C1, ci->RF_pll_lf_c1);
+	write_radio_reg(pi, RADIO_2055_PLL_LF_R1, ci->RF_pll_lf_r1);
+
+	BRCMS_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_PLL_LF_C2, ci->RF_pll_lf_c2);
+	write_radio_reg(pi, RADIO_2055_LGBUF_CEN_BUF, ci->RF_lgbuf_cen_buf);
+	write_radio_reg(pi, RADIO_2055_LGEN_TUNE1, ci->RF_lgen_tune1);
+	write_radio_reg(pi, RADIO_2055_LGEN_TUNE2, ci->RF_lgen_tune2);
+
+	BRCMS_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_CORE1_LGBUF_A_TUNE,
+			ci->RF_core1_lgbuf_a_tune);
+	write_radio_reg(pi, RADIO_2055_CORE1_LGBUF_G_TUNE,
+			ci->RF_core1_lgbuf_g_tune);
+	write_radio_reg(pi, RADIO_2055_CORE1_RXRF_REG1, ci->RF_core1_rxrf_reg1);
+	write_radio_reg(pi, RADIO_2055_CORE1_TX_PGA_PAD_TN,
+			ci->RF_core1_tx_pga_pad_tn);
+
+	BRCMS_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_CORE1_TX_MX_BGTRIM,
+			ci->RF_core1_tx_mx_bgtrim);
+	write_radio_reg(pi, RADIO_2055_CORE2_LGBUF_A_TUNE,
+			ci->RF_core2_lgbuf_a_tune);
+	write_radio_reg(pi, RADIO_2055_CORE2_LGBUF_G_TUNE,
+			ci->RF_core2_lgbuf_g_tune);
+	write_radio_reg(pi, RADIO_2055_CORE2_RXRF_REG1, ci->RF_core2_rxrf_reg1);
+
+	BRCMS_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_CORE2_TX_PGA_PAD_TN,
+			ci->RF_core2_tx_pga_pad_tn);
+	write_radio_reg(pi, RADIO_2055_CORE2_TX_MX_BGTRIM,
+			ci->RF_core2_tx_mx_bgtrim);
+
+	udelay(50);
+
+	write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x05);
+	write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x45);
+
+	BRCMS_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x65);
+
+	udelay(300);
+}
+
+static void
+wlc_phy_chanspec_radio2056_setup(struct brcms_phy *pi,
+				 const struct chan_info_nphy_radio205x *ci)
+{
+	const struct radio_regs *regs_SYN_2056_ptr = NULL;
+
+	write_radio_reg(pi,
+			RADIO_2056_SYN_PLL_VCOCAL1 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_vcocal1);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_VCOCAL2 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_vcocal2);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_REFDIV | RADIO_2056_SYN,
+			ci->RF_SYN_pll_refdiv);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_MMD2 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_mmd2);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_MMD1 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_mmd1);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_loopfilter1);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_loopfilter2);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER3 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_loopfilter3);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER4 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_loopfilter4);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER5 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_loopfilter5);
+	write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR27 | RADIO_2056_SYN,
+			ci->RF_SYN_reserved_addr27);
+	write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR28 | RADIO_2056_SYN,
+			ci->RF_SYN_reserved_addr28);
+	write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR29 | RADIO_2056_SYN,
+			ci->RF_SYN_reserved_addr29);
+	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_VCOBUF1 | RADIO_2056_SYN,
+			ci->RF_SYN_logen_VCOBUF1);
+	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_MIXER2 | RADIO_2056_SYN,
+			ci->RF_SYN_logen_MIXER2);
+	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_BUF3 | RADIO_2056_SYN,
+			ci->RF_SYN_logen_BUF3);
+	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_BUF4 | RADIO_2056_SYN,
+			ci->RF_SYN_logen_BUF4);
+
+	write_radio_reg(pi,
+			RADIO_2056_RX_LNAA_TUNE | RADIO_2056_RX0,
+			ci->RF_RX0_lnaa_tune);
+	write_radio_reg(pi, RADIO_2056_RX_LNAG_TUNE | RADIO_2056_RX0,
+			ci->RF_RX0_lnag_tune);
+	write_radio_reg(pi, RADIO_2056_TX_INTPAA_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_intpaa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_INTPAG_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_intpag_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PADA_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_pada_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PADG_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_padg_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PGAA_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_pgaa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PGAG_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_pgag_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_MIXA_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_mixa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_MIXG_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_mixg_boost_tune);
+
+	write_radio_reg(pi,
+			RADIO_2056_RX_LNAA_TUNE | RADIO_2056_RX1,
+			ci->RF_RX1_lnaa_tune);
+	write_radio_reg(pi, RADIO_2056_RX_LNAG_TUNE | RADIO_2056_RX1,
+			ci->RF_RX1_lnag_tune);
+	write_radio_reg(pi, RADIO_2056_TX_INTPAA_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_intpaa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_INTPAG_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_intpag_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PADA_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_pada_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PADG_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_padg_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PGAA_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_pgaa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PGAG_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_pgag_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_MIXA_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_mixa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_MIXG_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_mixg_boost_tune);
+
+	if (NREV_IS(pi->pubpi.phy_rev, 3))
+		regs_SYN_2056_ptr = regs_SYN_2056;
+	else if (NREV_IS(pi->pubpi.phy_rev, 4))
+		regs_SYN_2056_ptr = regs_SYN_2056_A1;
+	else {
+		switch (pi->pubpi.radiorev) {
+		case 5:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev5;
+			break;
+		case 6:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev6;
+			break;
+		case 7:
+		case 9:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev7;
+			break;
+		case 8:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev8;
+			break;
+		case 11:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev11;
+			break;
+		}
+	}
+	if (CHSPEC_IS2G(pi->radio_chanspec))
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 |
+				RADIO_2056_SYN,
+				(u16) regs_SYN_2056_ptr[0x49 - 2].init_g);
+	else
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 |
+				RADIO_2056_SYN,
+				(u16) regs_SYN_2056_ptr[0x49 - 2].init_a);
+
+	if (pi->sh->boardflags2 & BFL2_GPLL_WAR) {
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 |
+					RADIO_2056_SYN, 0x1f);
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 |
+					RADIO_2056_SYN, 0x1f);
+
+			if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) ||
+			    (pi->sh->chip == BCMA_CHIP_ID_BCM47162)) {
+				write_radio_reg(pi,
+						RADIO_2056_SYN_PLL_LOOPFILTER4 |
+						RADIO_2056_SYN, 0x14);
+				write_radio_reg(pi,
+						RADIO_2056_SYN_PLL_CP2 |
+						RADIO_2056_SYN, 0x00);
+			} else {
+				write_radio_reg(pi,
+						RADIO_2056_SYN_PLL_LOOPFILTER4 |
+						RADIO_2056_SYN, 0xb);
+				write_radio_reg(pi,
+						RADIO_2056_SYN_PLL_CP2 |
+						RADIO_2056_SYN, 0x14);
+			}
+		}
+	}
+
+	if ((pi->sh->boardflags2 & BFL2_GPLL_WAR2) &&
+	    (CHSPEC_IS2G(pi->radio_chanspec))) {
+		write_radio_reg(pi,
+				RADIO_2056_SYN_PLL_LOOPFILTER1 | RADIO_2056_SYN,
+				0x1f);
+		write_radio_reg(pi,
+				RADIO_2056_SYN_PLL_LOOPFILTER2 | RADIO_2056_SYN,
+				0x1f);
+		write_radio_reg(pi,
+				RADIO_2056_SYN_PLL_LOOPFILTER4 | RADIO_2056_SYN,
+				0xb);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 | RADIO_2056_SYN,
+				0x20);
+	}
+
+	if (pi->sh->boardflags2 & BFL2_APLL_WAR) {
+		if (CHSPEC_IS5G(pi->radio_chanspec)) {
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 |
+					RADIO_2056_SYN, 0x1f);
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 |
+					RADIO_2056_SYN, 0x1f);
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER4 |
+					RADIO_2056_SYN, 0x5);
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 |
+					RADIO_2056_SYN, 0xc);
+		}
+	}
+
+	if (PHY_IPA(pi) && CHSPEC_IS2G(pi->radio_chanspec)) {
+		u16 pag_boost_tune;
+		u16 padg_boost_tune;
+		u16 pgag_boost_tune;
+		u16 mixg_boost_tune;
+		u16 bias, cascbias;
+		uint core;
+
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+			if (NREV_GE(pi->pubpi.phy_rev, 5)) {
+
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 PADG_IDAC, 0xcc);
+
+				if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) ||
+				    (pi->sh->chip == BCMA_CHIP_ID_BCM47162)) {
+					bias = 0x40;
+					cascbias = 0x45;
+					pag_boost_tune = 0x5;
+					pgag_boost_tune = 0x33;
+					padg_boost_tune = 0x77;
+					mixg_boost_tune = 0x55;
+				} else {
+					bias = 0x25;
+					cascbias = 0x20;
+
+					if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224 ||
+					     pi->sh->chip == BCMA_CHIP_ID_BCM43225) &&
+					    pi->sh->chippkg == BCMA_PKG_ID_BCM43224_FAB_SMIC) {
+						bias = 0x2a;
+						cascbias = 0x38;
+					}
+
+					pag_boost_tune = 0x4;
+					pgag_boost_tune = 0x03;
+					padg_boost_tune = 0x77;
+					mixg_boost_tune = 0x65;
+				}
+
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_IMAIN_STAT, bias);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_IAUX_STAT, bias);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_CASCBIAS, cascbias);
+
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_BOOST_TUNE,
+						 pag_boost_tune);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 PGAG_BOOST_TUNE,
+						 pgag_boost_tune);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 PADG_BOOST_TUNE,
+						 padg_boost_tune);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 MIXG_BOOST_TUNE,
+						 mixg_boost_tune);
+			} else {
+
+				bias = (pi->bw == WL_CHANSPEC_BW_40) ?
+				       0x40 : 0x20;
+
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_IMAIN_STAT, bias);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_IAUX_STAT, bias);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_CASCBIAS, 0x30);
+			}
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, PA_SPARE1,
+					 0xee);
+		}
+	}
+
+	if (PHY_IPA(pi) && NREV_IS(pi->pubpi.phy_rev, 6)
+	    && CHSPEC_IS5G(pi->radio_chanspec)) {
+		u16 paa_boost_tune;
+		u16 pada_boost_tune;
+		u16 pgaa_boost_tune;
+		u16 mixa_boost_tune;
+		u16 freq, pabias, cascbias;
+		uint core;
+
+		freq = CHAN5G_FREQ(CHSPEC_CHANNEL(pi->radio_chanspec));
+
+		if (freq < 5150) {
+
+			paa_boost_tune = 0xa;
+			pada_boost_tune = 0x77;
+			pgaa_boost_tune = 0xf;
+			mixa_boost_tune = 0xf;
+		} else if (freq < 5340) {
+
+			paa_boost_tune = 0x8;
+			pada_boost_tune = 0x77;
+			pgaa_boost_tune = 0xfb;
+			mixa_boost_tune = 0xf;
+		} else if (freq < 5650) {
+
+			paa_boost_tune = 0x0;
+			pada_boost_tune = 0x77;
+			pgaa_boost_tune = 0xb;
+			mixa_boost_tune = 0xf;
+		} else {
+
+			paa_boost_tune = 0x0;
+			pada_boost_tune = 0x77;
+			if (freq != 5825)
+				pgaa_boost_tune = -(int)(freq - 18) / 36 + 168;
+			else
+				pgaa_boost_tune = 6;
+
+			mixa_boost_tune = 0xf;
+		}
+
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAA_BOOST_TUNE, paa_boost_tune);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 PADA_BOOST_TUNE, pada_boost_tune);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 PGAA_BOOST_TUNE, pgaa_boost_tune);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 MIXA_BOOST_TUNE, mixa_boost_tune);
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 TXSPARE1, 0x30);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 PA_SPARE2, 0xee);
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 PADA_CASCBIAS, 0x3);
+
+			cascbias = 0x30;
+
+			if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224 ||
+			     pi->sh->chip == BCMA_CHIP_ID_BCM43225) &&
+			    pi->sh->chippkg == BCMA_PKG_ID_BCM43224_FAB_SMIC)
+				cascbias = 0x35;
+
+			pabias = (pi->phy_pabias == 0) ? 0x30 : pi->phy_pabias;
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAA_IAUX_STAT, pabias);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAA_IMAIN_STAT, pabias);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAA_CASCBIAS, cascbias);
+		}
+	}
+
+	udelay(50);
+
+	wlc_phy_radio205x_vcocal_nphy(pi);
+}
+
+void wlc_phy_radio205x_vcocal_nphy(struct brcms_phy *pi)
+{
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_EN, 0x01, 0x0);
+		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x04, 0x0);
+		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x04,
+			      (1 << 2));
+		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_EN, 0x01, 0x01);
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_VCOCAL12, 0x0);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x38);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x18);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x38);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x39);
+	}
+
+	udelay(300);
+}
+
+static void
+wlc_phy_chanspec_radio2057_setup(
+	struct brcms_phy *pi,
+	const struct chan_info_nphy_radio2057 *ci,
+	const struct chan_info_nphy_radio2057_rev5 *
+	ci2)
+{
+	int coreNum;
+	u16 txmix2g_tune_boost_pu = 0;
+	u16 pad2g_tune_pus = 0;
+
+	if (pi->pubpi.radiorev == 5) {
+
+		write_radio_reg(pi,
+				RADIO_2057_VCOCAL_COUNTVAL0,
+				ci2->RF_vcocal_countval0);
+		write_radio_reg(pi, RADIO_2057_VCOCAL_COUNTVAL1,
+				ci2->RF_vcocal_countval1);
+		write_radio_reg(pi, RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE,
+				ci2->RF_rfpll_refmaster_sparextalsize);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+				ci2->RF_rfpll_loopfilter_r1);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+				ci2->RF_rfpll_loopfilter_c2);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+				ci2->RF_rfpll_loopfilter_c1);
+		write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC,
+				ci2->RF_cp_kpd_idac);
+		write_radio_reg(pi, RADIO_2057_RFPLL_MMD0, ci2->RF_rfpll_mmd0);
+		write_radio_reg(pi, RADIO_2057_RFPLL_MMD1, ci2->RF_rfpll_mmd1);
+		write_radio_reg(pi,
+				RADIO_2057_VCOBUF_TUNE, ci2->RF_vcobuf_tune);
+		write_radio_reg(pi,
+				RADIO_2057_LOGEN_MX2G_TUNE,
+				ci2->RF_logen_mx2g_tune);
+		write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF2G_TUNE,
+				ci2->RF_logen_indbuf2g_tune);
+
+		write_radio_reg(pi,
+				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0,
+				ci2->RF_txmix2g_tune_boost_pu_core0);
+		write_radio_reg(pi,
+				RADIO_2057_PAD2G_TUNE_PUS_CORE0,
+				ci2->RF_pad2g_tune_pus_core0);
+		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE0,
+				ci2->RF_lna2g_tune_core0);
+
+		write_radio_reg(pi,
+				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1,
+				ci2->RF_txmix2g_tune_boost_pu_core1);
+		write_radio_reg(pi,
+				RADIO_2057_PAD2G_TUNE_PUS_CORE1,
+				ci2->RF_pad2g_tune_pus_core1);
+		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE1,
+				ci2->RF_lna2g_tune_core1);
+
+	} else {
+
+		write_radio_reg(pi,
+				RADIO_2057_VCOCAL_COUNTVAL0,
+				ci->RF_vcocal_countval0);
+		write_radio_reg(pi, RADIO_2057_VCOCAL_COUNTVAL1,
+				ci->RF_vcocal_countval1);
+		write_radio_reg(pi, RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE,
+				ci->RF_rfpll_refmaster_sparextalsize);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+				ci->RF_rfpll_loopfilter_r1);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+				ci->RF_rfpll_loopfilter_c2);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+				ci->RF_rfpll_loopfilter_c1);
+		write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, ci->RF_cp_kpd_idac);
+		write_radio_reg(pi, RADIO_2057_RFPLL_MMD0, ci->RF_rfpll_mmd0);
+		write_radio_reg(pi, RADIO_2057_RFPLL_MMD1, ci->RF_rfpll_mmd1);
+		write_radio_reg(pi, RADIO_2057_VCOBUF_TUNE, ci->RF_vcobuf_tune);
+		write_radio_reg(pi,
+				RADIO_2057_LOGEN_MX2G_TUNE,
+				ci->RF_logen_mx2g_tune);
+		write_radio_reg(pi, RADIO_2057_LOGEN_MX5G_TUNE,
+				ci->RF_logen_mx5g_tune);
+		write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF2G_TUNE,
+				ci->RF_logen_indbuf2g_tune);
+		write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF5G_TUNE,
+				ci->RF_logen_indbuf5g_tune);
+
+		write_radio_reg(pi,
+				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0,
+				ci->RF_txmix2g_tune_boost_pu_core0);
+		write_radio_reg(pi,
+				RADIO_2057_PAD2G_TUNE_PUS_CORE0,
+				ci->RF_pad2g_tune_pus_core0);
+		write_radio_reg(pi, RADIO_2057_PGA_BOOST_TUNE_CORE0,
+				ci->RF_pga_boost_tune_core0);
+		write_radio_reg(pi, RADIO_2057_TXMIX5G_BOOST_TUNE_CORE0,
+				ci->RF_txmix5g_boost_tune_core0);
+		write_radio_reg(pi, RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE0,
+				ci->RF_pad5g_tune_misc_pus_core0);
+		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE0,
+				ci->RF_lna2g_tune_core0);
+		write_radio_reg(pi, RADIO_2057_LNA5G_TUNE_CORE0,
+				ci->RF_lna5g_tune_core0);
+
+		write_radio_reg(pi,
+				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1,
+				ci->RF_txmix2g_tune_boost_pu_core1);
+		write_radio_reg(pi,
+				RADIO_2057_PAD2G_TUNE_PUS_CORE1,
+				ci->RF_pad2g_tune_pus_core1);
+		write_radio_reg(pi, RADIO_2057_PGA_BOOST_TUNE_CORE1,
+				ci->RF_pga_boost_tune_core1);
+		write_radio_reg(pi, RADIO_2057_TXMIX5G_BOOST_TUNE_CORE1,
+				ci->RF_txmix5g_boost_tune_core1);
+		write_radio_reg(pi, RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE1,
+				ci->RF_pad5g_tune_misc_pus_core1);
+		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE1,
+				ci->RF_lna2g_tune_core1);
+		write_radio_reg(pi, RADIO_2057_LNA5G_TUNE_CORE1,
+				ci->RF_lna5g_tune_core1);
+	}
+
+	if ((pi->pubpi.radiorev <= 4) || (pi->pubpi.radiorev == 6)) {
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+					0x3f);
+			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+					0x8);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+					0x8);
+		} else {
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+					0x1f);
+			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+					0x8);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+					0x8);
+		}
+	} else if ((pi->pubpi.radiorev == 5) || (pi->pubpi.radiorev == 7) ||
+		   (pi->pubpi.radiorev == 8)) {
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+					0x1b);
+			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x30);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+					0xa);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+					0xa);
+		} else {
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+					0x1f);
+			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+					0x8);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+					0x8);
+		}
+
+	}
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (PHY_IPA(pi)) {
+			if (pi->pubpi.radiorev == 3)
+				txmix2g_tune_boost_pu = 0x6b;
+
+			if (pi->pubpi.radiorev == 5)
+				pad2g_tune_pus = 0x73;
+
+		} else {
+			if (pi->pubpi.radiorev != 5) {
+				pad2g_tune_pus = 0x3;
+
+				txmix2g_tune_boost_pu = 0x61;
+			}
+		}
+
+		for (coreNum = 0; coreNum <= 1; coreNum++) {
+
+			if (txmix2g_tune_boost_pu != 0)
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
+						 TXMIX2G_TUNE_BOOST_PU,
+						 txmix2g_tune_boost_pu);
+
+			if (pad2g_tune_pus != 0)
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
+						 PAD2G_TUNE_PUS,
+						 pad2g_tune_pus);
+		}
+	}
+
+	udelay(50);
+
+	wlc_phy_radio205x_vcocal_nphy(pi);
+}
+
+static void
+wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec,
+			    const struct nphy_sfo_cfg *ci)
+{
+	u16 val;
+
+	val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
+	if (CHSPEC_IS5G(chanspec) && !val) {
+
+		val = bcma_read16(pi->d11core, D11REGOFFS(psm_phy_hdr_param));
+		bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param),
+		      (val | MAC_PHY_FORCE_CLK));
+
+		or_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG),
+			   (BBCFG_RESETCCA | BBCFG_RESETRX));
+
+		bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), val);
+
+		or_phy_reg(pi, 0x09, NPHY_BandControl_currentBand);
+	} else if (!CHSPEC_IS5G(chanspec) && val) {
+
+		and_phy_reg(pi, 0x09, ~NPHY_BandControl_currentBand);
+
+		val = bcma_read16(pi->d11core, D11REGOFFS(psm_phy_hdr_param));
+		bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param),
+		      (val | MAC_PHY_FORCE_CLK));
+
+		and_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG),
+			    (u16) (~(BBCFG_RESETCCA | BBCFG_RESETRX)));
+
+		bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), val);
+	}
+
+	write_phy_reg(pi, 0x1ce, ci->PHY_BW1a);
+	write_phy_reg(pi, 0x1cf, ci->PHY_BW2);
+	write_phy_reg(pi, 0x1d0, ci->PHY_BW3);
+
+	write_phy_reg(pi, 0x1d1, ci->PHY_BW4);
+	write_phy_reg(pi, 0x1d2, ci->PHY_BW5);
+	write_phy_reg(pi, 0x1d3, ci->PHY_BW6);
+
+	if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
+		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_ofdm_en, 0);
+
+		or_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_TEST, 0x800);
+	} else {
+		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_ofdm_en,
+					NPHY_ClassifierCtrl_ofdm_en);
+
+		if (CHSPEC_IS2G(chanspec))
+			and_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_TEST, ~0x840);
+	}
+
+	if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF)
+		wlc_phy_txpwr_fixpower_nphy(pi);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 3))
+		wlc_phy_adjust_lnagaintbl_nphy(pi);
+
+	wlc_phy_txlpfbw_nphy(pi);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)
+	    && (pi->phy_spuravoid != SPURAVOID_DISABLE)) {
+		u8 spuravoid = 0;
+
+		val = CHSPEC_CHANNEL(chanspec);
+		if (!CHSPEC_IS40(pi->radio_chanspec)) {
+			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+				if ((val == 13) || (val == 14) || (val == 153))
+					spuravoid = 1;
+			} else if (((val >= 5) && (val <= 8)) || (val == 13)
+				   || (val == 14)) {
+				spuravoid = 1;
+			}
+		} else if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			if (val == 54)
+				spuravoid = 1;
+		} else if (pi->nphy_aband_spurwar_en &&
+		    ((val == 38) || (val == 102) || (val == 118))) {
+			if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716)
+			    && (pi->sh->chippkg == BCMA_PKG_ID_BCM4717)) {
+				spuravoid = 0;
+			} else {
+				spuravoid = 1;
+			}
+		}
+
+		if (pi->phy_spuravoid == SPURAVOID_FORCEON)
+			spuravoid = 1;
+
+		if ((pi->sh->chip == BCMA_CHIP_ID_BCM4716) ||
+		    (pi->sh->chip == BCMA_CHIP_ID_BCM43225)) {
+			bcma_pmu_spuravoid_pllupdate(&pi->d11core->bus->drv_cc,
+						     spuravoid);
+		} else {
+			wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false);
+			bcma_pmu_spuravoid_pllupdate(&pi->d11core->bus->drv_cc,
+						     spuravoid);
+			wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true);
+		}
+
+		if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) ||
+		    (pi->sh->chip == BCMA_CHIP_ID_BCM43225)) {
+			if (spuravoid == 1) {
+				bcma_write16(pi->d11core,
+					     D11REGOFFS(tsf_clk_frac_l),
+					     0x5341);
+				bcma_write16(pi->d11core,
+					     D11REGOFFS(tsf_clk_frac_h), 0x8);
+			} else {
+				bcma_write16(pi->d11core,
+					     D11REGOFFS(tsf_clk_frac_l),
+					     0x8889);
+				bcma_write16(pi->d11core,
+					     D11REGOFFS(tsf_clk_frac_h), 0x8);
+			}
+		}
+
+		if (!((pi->sh->chip == BCMA_CHIP_ID_BCM4716) ||
+		      (pi->sh->chip == BCMA_CHIP_ID_BCM47162)))
+			wlapi_bmac_core_phypll_reset(pi->sh->physhim);
+
+		mod_phy_reg(pi, 0x01, (0x1 << 15),
+			    ((spuravoid > 0) ? (0x1 << 15) : 0));
+
+		wlc_phy_resetcca_nphy(pi);
+
+		pi->phy_isspuravoid = (spuravoid > 0);
+	}
+
+	if (NREV_LT(pi->pubpi.phy_rev, 7))
+		write_phy_reg(pi, 0x17e, 0x3830);
+
+	wlc_phy_spurwar_nphy(pi);
+}
+
+void wlc_phy_chanspec_set_nphy(struct brcms_phy *pi, u16 chanspec)
+{
+	int freq;
+	const struct chan_info_nphy_radio2057 *t0 = NULL;
+	const struct chan_info_nphy_radio205x *t1 = NULL;
+	const struct chan_info_nphy_radio2057_rev5 *t2 = NULL;
+	const struct chan_info_nphy_2055 *t3 = NULL;
+
+	if (!wlc_phy_chan2freq_nphy
+		    (pi, CHSPEC_CHANNEL(chanspec), &freq, &t0, &t1, &t2, &t3))
+		return;
+
+	wlc_phy_chanspec_radio_set((struct brcms_phy_pub *) pi, chanspec);
+
+	if (CHSPEC_BW(chanspec) != pi->bw)
+		wlapi_bmac_bw_set(pi->sh->physhim, CHSPEC_BW(chanspec));
+
+	if (CHSPEC_IS40(chanspec)) {
+		if (CHSPEC_SB_UPPER(chanspec)) {
+			or_phy_reg(pi, 0xa0, BPHY_BAND_SEL_UP20);
+			if (NREV_GE(pi->pubpi.phy_rev, 7))
+				or_phy_reg(pi, 0x310, PRIM_SEL_UP20);
+		} else {
+			and_phy_reg(pi, 0xa0, ~BPHY_BAND_SEL_UP20);
+			if (NREV_GE(pi->pubpi.phy_rev, 7))
+				and_phy_reg(pi, 0x310,
+					    (~PRIM_SEL_UP20 & 0xffff));
+		}
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+			if ((pi->pubpi.radiorev <= 4)
+			    || (pi->pubpi.radiorev == 6)) {
+				mod_radio_reg(pi, RADIO_2057_TIA_CONFIG_CORE0,
+					      0x2,
+					      (CHSPEC_IS5G(chanspec) ? (1 << 1)
+					       : 0));
+				mod_radio_reg(pi, RADIO_2057_TIA_CONFIG_CORE1,
+					      0x2,
+					      (CHSPEC_IS5G(chanspec) ? (1 << 1)
+					       : 0));
+			}
+
+			wlc_phy_chanspec_radio2057_setup(pi, t0, t2);
+			wlc_phy_chanspec_nphy_setup(pi, chanspec,
+				(pi->pubpi.radiorev == 5) ?
+				(const struct nphy_sfo_cfg *)&(t2->PHY_BW1a) :
+				(const struct nphy_sfo_cfg *)&(t0->PHY_BW1a));
+
+		} else {
+
+			mod_radio_reg(pi,
+				      RADIO_2056_SYN_COM_CTRL | RADIO_2056_SYN,
+				      0x4,
+				      (CHSPEC_IS5G(chanspec) ? (0x1 << 2) : 0));
+			wlc_phy_chanspec_radio2056_setup(pi, t1);
+
+			wlc_phy_chanspec_nphy_setup(pi, chanspec,
+				(const struct nphy_sfo_cfg *) &(t1->PHY_BW1a));
+		}
+
+	} else {
+
+		mod_radio_reg(pi, RADIO_2055_MASTER_CNTRL1, 0x70,
+			      (CHSPEC_IS5G(chanspec) ? (0x02 << 4)
+			       : (0x05 << 4)));
+
+		wlc_phy_chanspec_radio2055_setup(pi, t3);
+		wlc_phy_chanspec_nphy_setup(pi, chanspec,
+					    (const struct nphy_sfo_cfg *)
+					     &(t3->PHY_BW1a));
+	}
+
+}
+
+void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init)
+{
+	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
+	u16 mask = 0xfc00;
+	u32 mc = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7))
+		return;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		u16 v0 = 0x211, v1 = 0x222, v2 = 0x144, v3 = 0x188;
+
+		if (!lut_init)
+			return;
+
+		if (pi->srom_fem2g.antswctrllut == 0) {
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x02, 16, &v0);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x03, 16, &v1);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x08, 16, &v2);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x0C, 16, &v3);
+		}
+
+		if (pi->srom_fem5g.antswctrllut == 0) {
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x12, 16, &v0);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x13, 16, &v1);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x18, 16, &v2);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x1C, 16, &v3);
+		}
+	} else {
+
+		write_phy_reg(pi, 0xc8, 0x0);
+		write_phy_reg(pi, 0xc9, 0x0);
+
+		bcma_chipco_gpio_control(&pi->d11core->bus->drv_cc, mask, mask);
+
+		mc = bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
+		mc &= ~MCTL_GPOUT_SEL_MASK;
+		bcma_write32(pi->d11core, D11REGOFFS(maccontrol), mc);
+
+		bcma_set16(pi->d11core, D11REGOFFS(psm_gpio_oe), mask);
+
+		bcma_mask16(pi->d11core, D11REGOFFS(psm_gpio_out), ~mask);
+
+		if (lut_init) {
+			write_phy_reg(pi, 0xf8, 0x02d8);
+			write_phy_reg(pi, 0xf9, 0x0301);
+			write_phy_reg(pi, 0xfa, 0x02d8);
+			write_phy_reg(pi, 0xfb, 0x0301);
+		}
+	}
+}
+
+u16 wlc_phy_classifier_nphy(struct brcms_phy *pi, u16 mask, u16 val)
+{
+	u16 curr_ctl, new_ctl;
+	bool suspended = false;
+
+	if (D11REV_IS(pi->sh->corerev, 16)) {
+		suspended = (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
+			     MCTL_EN_MAC) ? false : true;
+		if (!suspended)
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+	}
+
+	curr_ctl = read_phy_reg(pi, 0xb0) & (0x7 << 0);
+
+	new_ctl = (curr_ctl & (~mask)) | (val & mask);
+
+	mod_phy_reg(pi, 0xb0, (0x7 << 0), new_ctl);
+
+	if (D11REV_IS(pi->sh->corerev, 16) && !suspended)
+		wlapi_enable_mac(pi->sh->physhim);
+
+	return new_ctl;
+}
+
+void wlc_phy_force_rfseq_nphy(struct brcms_phy *pi, u8 cmd)
+{
+	u16 trigger_mask, status_mask;
+	u16 orig_RfseqCoreActv;
+
+	switch (cmd) {
+	case NPHY_RFSEQ_RX2TX:
+		trigger_mask = NPHY_RfseqTrigger_rx2tx;
+		status_mask = NPHY_RfseqStatus_rx2tx;
+		break;
+	case NPHY_RFSEQ_TX2RX:
+		trigger_mask = NPHY_RfseqTrigger_tx2rx;
+		status_mask = NPHY_RfseqStatus_tx2rx;
+		break;
+	case NPHY_RFSEQ_RESET2RX:
+		trigger_mask = NPHY_RfseqTrigger_reset2rx;
+		status_mask = NPHY_RfseqStatus_reset2rx;
+		break;
+	case NPHY_RFSEQ_UPDATEGAINH:
+		trigger_mask = NPHY_RfseqTrigger_updategainh;
+		status_mask = NPHY_RfseqStatus_updategainh;
+		break;
+	case NPHY_RFSEQ_UPDATEGAINL:
+		trigger_mask = NPHY_RfseqTrigger_updategainl;
+		status_mask = NPHY_RfseqStatus_updategainl;
+		break;
+	case NPHY_RFSEQ_UPDATEGAINU:
+		trigger_mask = NPHY_RfseqTrigger_updategainu;
+		status_mask = NPHY_RfseqStatus_updategainu;
+		break;
+	default:
+		return;
+	}
+
+	orig_RfseqCoreActv = read_phy_reg(pi, 0xa1);
+	or_phy_reg(pi, 0xa1,
+		   (NPHY_RfseqMode_CoreActv_override |
+		    NPHY_RfseqMode_Trigger_override));
+	or_phy_reg(pi, 0xa3, trigger_mask);
+	SPINWAIT((read_phy_reg(pi, 0xa4) & status_mask), 200000);
+	write_phy_reg(pi, 0xa1, orig_RfseqCoreActv);
+	WARN(read_phy_reg(pi, 0xa4) & status_mask, "HW error in rf");
+}
+
+static void
+wlc_phy_rfctrl_override_1tomany_nphy(struct brcms_phy *pi, u16 cmd, u16 value,
+				     u8 core_mask, u8 off)
+{
+	u16 rfmxgain = 0, lpfgain = 0;
+	u16 tgain = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		switch (cmd) {
+		case NPHY_REV7_RfctrlOverride_cmd_rxrf_pu:
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 5),
+				value, core_mask, off,
+				NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 4), value,
+				core_mask, off,
+				NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 3), value,
+				core_mask, off,
+				NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			break;
+		case NPHY_REV7_RfctrlOverride_cmd_rx_pu:
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 2),
+				value, core_mask, off,
+				NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 1), value,
+				core_mask, off,
+				NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 0), value,
+				core_mask, off,
+				NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 1), value,
+				core_mask, off,
+				NPHY_REV7_RFCTRLOVERRIDE_ID2);
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 11), 0,
+				core_mask, off,
+				NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			break;
+		case NPHY_REV7_RfctrlOverride_cmd_tx_pu:
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 2),
+				value, core_mask, off,
+				NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 1), value,
+				core_mask, off,
+				NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 0), value,
+				core_mask, off,
+				NPHY_REV7_RFCTRLOVERRIDE_ID2);
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 2), value,
+				core_mask, off,
+				NPHY_REV7_RFCTRLOVERRIDE_ID2);
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 11), 1,
+				core_mask, off,
+				NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			break;
+		case NPHY_REV7_RfctrlOverride_cmd_rxgain:
+			rfmxgain = value & 0x000ff;
+			lpfgain = value & 0x0ff00;
+			lpfgain = lpfgain >> 8;
+
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 11),
+				rfmxgain, core_mask,
+				off,
+				NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x3 << 13),
+				lpfgain, core_mask,
+				off,
+				NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			break;
+		case NPHY_REV7_RfctrlOverride_cmd_txgain:
+			tgain = value & 0x7fff;
+			lpfgain = value & 0x8000;
+			lpfgain = lpfgain >> 14;
+
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 12),
+				tgain, core_mask, off,
+				NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 13),
+				lpfgain, core_mask,
+				off,
+				NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			break;
+		}
+	}
+}
+
+static void
+wlc_phy_scale_offset_rssi_nphy(struct brcms_phy *pi, u16 scale, s8 offset,
+			       u8 coresel, u8 rail, u8 rssi_type)
+{
+	u16 valuetostuff;
+
+	offset = (offset > NPHY_RSSICAL_MAXREAD) ?
+		 NPHY_RSSICAL_MAXREAD : offset;
+	offset = (offset < (-NPHY_RSSICAL_MAXREAD - 1)) ?
+		 -NPHY_RSSICAL_MAXREAD - 1 : offset;
+
+	valuetostuff = ((scale & 0x3f) << 8) | (offset & 0x3f);
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB))
+		write_phy_reg(pi, 0x1a6, valuetostuff);
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB))
+		write_phy_reg(pi, 0x1ac, valuetostuff);
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB))
+		write_phy_reg(pi, 0x1b2, valuetostuff);
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB))
+		write_phy_reg(pi, 0x1b8, valuetostuff);
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1))
+		write_phy_reg(pi, 0x1a4, valuetostuff);
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1))
+		write_phy_reg(pi, 0x1aa, valuetostuff);
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1))
+		write_phy_reg(pi, 0x1b0, valuetostuff);
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1))
+		write_phy_reg(pi, 0x1b6, valuetostuff);
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2))
+		write_phy_reg(pi, 0x1a5, valuetostuff);
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2))
+		write_phy_reg(pi, 0x1ab, valuetostuff);
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2))
+		write_phy_reg(pi, 0x1b1, valuetostuff);
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2))
+		write_phy_reg(pi, 0x1b7, valuetostuff);
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD))
+		write_phy_reg(pi, 0x1a7, valuetostuff);
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD))
+		write_phy_reg(pi, 0x1ad, valuetostuff);
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD))
+		write_phy_reg(pi, 0x1b3, valuetostuff);
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD))
+		write_phy_reg(pi, 0x1b9, valuetostuff);
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ))
+		write_phy_reg(pi, 0x1a8, valuetostuff);
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ))
+		write_phy_reg(pi, 0x1ae, valuetostuff);
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ))
+		write_phy_reg(pi, 0x1b4, valuetostuff);
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ))
+		write_phy_reg(pi, 0x1ba, valuetostuff);
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rssi_type == NPHY_RSSI_SEL_TSSI_2G))
+		write_phy_reg(pi, 0x1a9, valuetostuff);
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rssi_type == NPHY_RSSI_SEL_TSSI_2G))
+		write_phy_reg(pi, 0x1b5, valuetostuff);
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rssi_type == NPHY_RSSI_SEL_TSSI_5G))
+		write_phy_reg(pi, 0x1af, valuetostuff);
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rssi_type == NPHY_RSSI_SEL_TSSI_5G))
+		write_phy_reg(pi, 0x1bb, valuetostuff);
+}
+
+static void brcms_phy_wr_tx_mux(struct brcms_phy *pi, u8 core)
+{
+	if (PHY_IPA(pi)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7))
+			write_radio_reg(pi,
+					((core == PHY_CORE_0) ?
+					 RADIO_2057_TX0_TX_SSI_MUX :
+					 RADIO_2057_TX1_TX_SSI_MUX),
+					(CHSPEC_IS5G(pi->radio_chanspec) ?
+					0xc : 0xe));
+		else
+			write_radio_reg(pi,
+					RADIO_2056_TX_TX_SSI_MUX |
+					((core == PHY_CORE_0) ?
+					 RADIO_2056_TX0 : RADIO_2056_TX1),
+					(CHSPEC_IS5G(pi->radio_chanspec) ?
+					0xc : 0xe));
+	} else {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			write_radio_reg(pi,
+					((core == PHY_CORE_0) ?
+					 RADIO_2057_TX0_TX_SSI_MUX :
+					 RADIO_2057_TX1_TX_SSI_MUX),
+					0x11);
+
+			if (pi->pubpi.radioid == BCM2057_ID)
+				write_radio_reg(pi,
+						RADIO_2057_IQTEST_SEL_PU, 0x1);
+
+		} else {
+			write_radio_reg(pi,
+					RADIO_2056_TX_TX_SSI_MUX |
+					((core == PHY_CORE_0) ?
+					 RADIO_2056_TX0 : RADIO_2056_TX1),
+					0x11);
+		}
+	}
+}
+
+void wlc_phy_rssisel_nphy(struct brcms_phy *pi, u8 core_code, u8 rssi_type)
+{
+	u16 mask, val;
+	u16 afectrlovr_rssi_val, rfctrlcmd_rxen_val, rfctrlcmd_coresel_val,
+	    startseq;
+	u16 rfctrlovr_rssi_val, rfctrlovr_rxen_val, rfctrlovr_coresel_val,
+	    rfctrlovr_trigger_val;
+	u16 afectrlovr_rssi_mask, rfctrlcmd_mask, rfctrlovr_mask;
+	u16 rfctrlcmd_val, rfctrlovr_val;
+	u8 core;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (core_code == RADIO_MIMO_CORESEL_OFF) {
+			mod_phy_reg(pi, 0x8f, (0x1 << 9), 0);
+			mod_phy_reg(pi, 0xa5, (0x1 << 9), 0);
+
+			mod_phy_reg(pi, 0xa6, (0x3 << 8), 0);
+			mod_phy_reg(pi, 0xa7, (0x3 << 8), 0);
+
+			mod_phy_reg(pi, 0xe5, (0x1 << 5), 0);
+			mod_phy_reg(pi, 0xe6, (0x1 << 5), 0);
+
+			mask = (0x1 << 2) |
+			       (0x1 << 3) | (0x1 << 4) | (0x1 << 5);
+			mod_phy_reg(pi, 0xf9, mask, 0);
+			mod_phy_reg(pi, 0xfb, mask, 0);
+
+		} else {
+			for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+				if (core_code == RADIO_MIMO_CORESEL_CORE1
+				    && core == PHY_CORE_1)
+					continue;
+				else if (core_code == RADIO_MIMO_CORESEL_CORE2
+					 && core == PHY_CORE_0)
+					continue;
+
+				mod_phy_reg(pi, (core == PHY_CORE_0) ?
+					    0x8f : 0xa5, (0x1 << 9), 1 << 9);
+
+				if (rssi_type == NPHY_RSSI_SEL_W1 ||
+				    rssi_type == NPHY_RSSI_SEL_W2 ||
+				    rssi_type == NPHY_RSSI_SEL_NB) {
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0xa6 : 0xa7,
+						    (0x3 << 8), 0);
+
+					mask = (0x1 << 2) |
+					       (0x1 << 3) |
+					       (0x1 << 4) | (0x1 << 5);
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0xf9 : 0xfb,
+						    mask, 0);
+
+					if (rssi_type == NPHY_RSSI_SEL_W1) {
+						if (CHSPEC_IS5G(
+							  pi->radio_chanspec)) {
+							mask = (0x1 << 2);
+							val = 1 << 2;
+						} else {
+							mask = (0x1 << 3);
+							val = 1 << 3;
+						}
+					} else if (rssi_type ==
+						   NPHY_RSSI_SEL_W2) {
+						mask = (0x1 << 4);
+						val = 1 << 4;
+					} else {
+						mask = (0x1 << 5);
+						val = 1 << 5;
+					}
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0xf9 : 0xfb,
+						    mask, val);
+
+					mask = (0x1 << 5);
+					val = 1 << 5;
+					mod_phy_reg(pi, (core == PHY_CORE_0) ?
+						    0xe5 : 0xe6, mask, val);
+				} else {
+					if (rssi_type == NPHY_RSSI_SEL_TBD) {
+						mask = (0x3 << 8);
+						val = 1 << 8;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+						mask = (0x3 << 10);
+						val = 1 << 10;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+					} else if (rssi_type ==
+						   NPHY_RSSI_SEL_IQ) {
+						mask = (0x3 << 8);
+						val = 2 << 8;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+						mask = (0x3 << 10);
+						val = 2 << 10;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+					} else {
+						mask = (0x3 << 8);
+						val = 3 << 8;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+						mask = (0x3 << 10);
+						val = 3 << 10;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+						brcms_phy_wr_tx_mux(pi, core);
+						afectrlovr_rssi_val = 1 << 9;
+						mod_phy_reg(pi,
+							   (core ==
+							    PHY_CORE_0) ? 0x8f
+							   : 0xa5, (0x1 << 9),
+							   afectrlovr_rssi_val);
+					}
+				}
+			}
+		}
+	} else {
+
+		if ((rssi_type == NPHY_RSSI_SEL_W1) ||
+		    (rssi_type == NPHY_RSSI_SEL_W2) ||
+		    (rssi_type == NPHY_RSSI_SEL_NB))
+			val = 0x0;
+		else if (rssi_type == NPHY_RSSI_SEL_TBD)
+			val = 0x1;
+		else if (rssi_type == NPHY_RSSI_SEL_IQ)
+			val = 0x2;
+		else
+			val = 0x3;
+
+		mask = ((0x3 << 12) | (0x3 << 14));
+		val = (val << 12) | (val << 14);
+		mod_phy_reg(pi, 0xa6, mask, val);
+		mod_phy_reg(pi, 0xa7, mask, val);
+
+		if ((rssi_type == NPHY_RSSI_SEL_W1) ||
+		    (rssi_type == NPHY_RSSI_SEL_W2) ||
+		    (rssi_type == NPHY_RSSI_SEL_NB)) {
+			if (rssi_type == NPHY_RSSI_SEL_W1)
+				val = 0x1;
+			if (rssi_type == NPHY_RSSI_SEL_W2)
+				val = 0x2;
+			if (rssi_type == NPHY_RSSI_SEL_NB)
+				val = 0x3;
+
+			mask = (0x3 << 4);
+			val = (val << 4);
+			mod_phy_reg(pi, 0x7a, mask, val);
+			mod_phy_reg(pi, 0x7d, mask, val);
+		}
+
+		if (core_code == RADIO_MIMO_CORESEL_OFF) {
+			afectrlovr_rssi_val = 0;
+			rfctrlcmd_rxen_val = 0;
+			rfctrlcmd_coresel_val = 0;
+			rfctrlovr_rssi_val = 0;
+			rfctrlovr_rxen_val = 0;
+			rfctrlovr_coresel_val = 0;
+			rfctrlovr_trigger_val = 0;
+			startseq = 0;
+		} else {
+			afectrlovr_rssi_val = 1;
+			rfctrlcmd_rxen_val = 1;
+			rfctrlcmd_coresel_val = core_code;
+			rfctrlovr_rssi_val = 1;
+			rfctrlovr_rxen_val = 1;
+			rfctrlovr_coresel_val = 1;
+			rfctrlovr_trigger_val = 1;
+			startseq = 1;
+		}
+
+		afectrlovr_rssi_mask = ((0x1 << 12) | (0x1 << 13));
+		afectrlovr_rssi_val = (afectrlovr_rssi_val <<
+				       12) | (afectrlovr_rssi_val << 13);
+		mod_phy_reg(pi, 0xa5, afectrlovr_rssi_mask,
+			    afectrlovr_rssi_val);
+
+		if ((rssi_type == NPHY_RSSI_SEL_W1) ||
+		    (rssi_type == NPHY_RSSI_SEL_W2) ||
+		    (rssi_type == NPHY_RSSI_SEL_NB)) {
+			rfctrlcmd_mask = ((0x1 << 8) | (0x7 << 3));
+			rfctrlcmd_val = (rfctrlcmd_rxen_val << 8) |
+					(rfctrlcmd_coresel_val << 3);
+
+			rfctrlovr_mask = ((0x1 << 5) |
+					  (0x1 << 12) |
+					  (0x1 << 1) | (0x1 << 0));
+			rfctrlovr_val = (rfctrlovr_rssi_val <<
+					 5) |
+					(rfctrlovr_rxen_val << 12) |
+					(rfctrlovr_coresel_val << 1) |
+					(rfctrlovr_trigger_val << 0);
+
+			mod_phy_reg(pi, 0x78, rfctrlcmd_mask, rfctrlcmd_val);
+			mod_phy_reg(pi, 0xec, rfctrlovr_mask, rfctrlovr_val);
+
+			mod_phy_reg(pi, 0x78, (0x1 << 0), (startseq << 0));
+			udelay(20);
+
+			mod_phy_reg(pi, 0xec, (0x1 << 0), 0);
+		}
+	}
+}
+
+int
+wlc_phy_poll_rssi_nphy(struct brcms_phy *pi, u8 rssi_type, s32 *rssi_buf,
+		       u8 nsamps)
+{
+	s16 rssi0, rssi1;
+	u16 afectrlCore1_save = 0;
+	u16 afectrlCore2_save = 0;
+	u16 afectrlOverride1_save = 0;
+	u16 afectrlOverride2_save = 0;
+	u16 rfctrlOverrideAux0_save = 0;
+	u16 rfctrlOverrideAux1_save = 0;
+	u16 rfctrlMiscReg1_save = 0;
+	u16 rfctrlMiscReg2_save = 0;
+	u16 rfctrlcmd_save = 0;
+	u16 rfctrloverride_save = 0;
+	u16 rfctrlrssiothers1_save = 0;
+	u16 rfctrlrssiothers2_save = 0;
+	s8 tmp_buf[4];
+	u8 ctr = 0, samp = 0;
+	s32 rssi_out_val;
+	u16 gpiosel_orig;
+
+	afectrlCore1_save = read_phy_reg(pi, 0xa6);
+	afectrlCore2_save = read_phy_reg(pi, 0xa7);
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		rfctrlMiscReg1_save = read_phy_reg(pi, 0xf9);
+		rfctrlMiscReg2_save = read_phy_reg(pi, 0xfb);
+		afectrlOverride1_save = read_phy_reg(pi, 0x8f);
+		afectrlOverride2_save = read_phy_reg(pi, 0xa5);
+		rfctrlOverrideAux0_save = read_phy_reg(pi, 0xe5);
+		rfctrlOverrideAux1_save = read_phy_reg(pi, 0xe6);
+	} else {
+		afectrlOverride1_save = read_phy_reg(pi, 0xa5);
+		rfctrlcmd_save = read_phy_reg(pi, 0x78);
+		rfctrloverride_save = read_phy_reg(pi, 0xec);
+		rfctrlrssiothers1_save = read_phy_reg(pi, 0x7a);
+		rfctrlrssiothers2_save = read_phy_reg(pi, 0x7d);
+	}
+
+	wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type);
+
+	gpiosel_orig = read_phy_reg(pi, 0xca);
+	if (NREV_LT(pi->pubpi.phy_rev, 2))
+		write_phy_reg(pi, 0xca, 5);
+
+	for (ctr = 0; ctr < 4; ctr++)
+		rssi_buf[ctr] = 0;
+
+	for (samp = 0; samp < nsamps; samp++) {
+		if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+			rssi0 = read_phy_reg(pi, 0x1c9);
+			rssi1 = read_phy_reg(pi, 0x1ca);
+		} else {
+			rssi0 = read_phy_reg(pi, 0x219);
+			rssi1 = read_phy_reg(pi, 0x21a);
+		}
+
+		ctr = 0;
+		tmp_buf[ctr++] = ((s8) ((rssi0 & 0x3f) << 2)) >> 2;
+		tmp_buf[ctr++] = ((s8) (((rssi0 >> 8) & 0x3f) << 2)) >> 2;
+		tmp_buf[ctr++] = ((s8) ((rssi1 & 0x3f) << 2)) >> 2;
+		tmp_buf[ctr++] = ((s8) (((rssi1 >> 8) & 0x3f) << 2)) >> 2;
+
+		for (ctr = 0; ctr < 4; ctr++)
+			rssi_buf[ctr] += tmp_buf[ctr];
+
+	}
+
+	rssi_out_val = rssi_buf[3] & 0xff;
+	rssi_out_val |= (rssi_buf[2] & 0xff) << 8;
+	rssi_out_val |= (rssi_buf[1] & 0xff) << 16;
+	rssi_out_val |= (rssi_buf[0] & 0xff) << 24;
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2))
+		write_phy_reg(pi, 0xca, gpiosel_orig);
+
+	write_phy_reg(pi, 0xa6, afectrlCore1_save);
+	write_phy_reg(pi, 0xa7, afectrlCore2_save);
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		write_phy_reg(pi, 0xf9, rfctrlMiscReg1_save);
+		write_phy_reg(pi, 0xfb, rfctrlMiscReg2_save);
+		write_phy_reg(pi, 0x8f, afectrlOverride1_save);
+		write_phy_reg(pi, 0xa5, afectrlOverride2_save);
+		write_phy_reg(pi, 0xe5, rfctrlOverrideAux0_save);
+		write_phy_reg(pi, 0xe6, rfctrlOverrideAux1_save);
+	} else {
+		write_phy_reg(pi, 0xa5, afectrlOverride1_save);
+		write_phy_reg(pi, 0x78, rfctrlcmd_save);
+		write_phy_reg(pi, 0xec, rfctrloverride_save);
+		write_phy_reg(pi, 0x7a, rfctrlrssiothers1_save);
+		write_phy_reg(pi, 0x7d, rfctrlrssiothers2_save);
+	}
+
+	return rssi_out_val;
+}
+
+s16 wlc_phy_tempsense_nphy(struct brcms_phy *pi)
+{
+	u16 core1_txrf_iqcal1_save, core1_txrf_iqcal2_save;
+	u16 core2_txrf_iqcal1_save, core2_txrf_iqcal2_save;
+	u16 pwrdet_rxtx_core1_save;
+	u16 pwrdet_rxtx_core2_save;
+	u16 afectrlCore1_save;
+	u16 afectrlCore2_save;
+	u16 afectrlOverride_save;
+	u16 afectrlOverride2_save;
+	u16 pd_pll_ts_save;
+	u16 gpioSel_save;
+	s32 radio_temp[4];
+	s32 radio_temp2[4];
+	u16 syn_tempprocsense_save;
+	s16 offset = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		u16 auxADC_Vmid, auxADC_Av, auxADC_Vmid_save, auxADC_Av_save;
+		u16 auxADC_rssi_ctrlL_save, auxADC_rssi_ctrlH_save;
+		u16 auxADC_rssi_ctrlL, auxADC_rssi_ctrlH;
+		s32 auxADC_Vl;
+		u16 RfctrlOverride5_save, RfctrlOverride6_save;
+		u16 RfctrlMiscReg5_save, RfctrlMiscReg6_save;
+		u16 RSSIMultCoef0QPowerDet_save;
+		u16 tempsense_Rcal;
+
+		syn_tempprocsense_save =
+			read_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG);
+
+		afectrlCore1_save = read_phy_reg(pi, 0xa6);
+		afectrlCore2_save = read_phy_reg(pi, 0xa7);
+		afectrlOverride_save = read_phy_reg(pi, 0x8f);
+		afectrlOverride2_save = read_phy_reg(pi, 0xa5);
+		RSSIMultCoef0QPowerDet_save = read_phy_reg(pi, 0x1ae);
+		RfctrlOverride5_save = read_phy_reg(pi, 0x346);
+		RfctrlOverride6_save = read_phy_reg(pi, 0x347);
+		RfctrlMiscReg5_save = read_phy_reg(pi, 0x344);
+		RfctrlMiscReg6_save = read_phy_reg(pi, 0x345);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
+					&auxADC_Vmid_save);
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
+					&auxADC_Av_save);
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16,
+					&auxADC_rssi_ctrlL_save);
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16,
+					&auxADC_rssi_ctrlH_save);
+
+		write_phy_reg(pi, 0x1ae, 0x0);
+
+		auxADC_rssi_ctrlL = 0x0;
+		auxADC_rssi_ctrlH = 0x20;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16,
+					 &auxADC_rssi_ctrlL);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16,
+					 &auxADC_rssi_ctrlH);
+
+		tempsense_Rcal = syn_tempprocsense_save & 0x1c;
+
+		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
+				tempsense_Rcal | 0x01);
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1),
+						  1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		mod_phy_reg(pi, 0xa6, (0x1 << 7), 0);
+		mod_phy_reg(pi, 0xa7, (0x1 << 7), 0);
+		mod_phy_reg(pi, 0x8f, (0x1 << 7), (0x1 << 7));
+		mod_phy_reg(pi, 0xa5, (0x1 << 7), (0x1 << 7));
+
+		mod_phy_reg(pi, 0xa6, (0x1 << 2), (0x1 << 2));
+		mod_phy_reg(pi, 0xa7, (0x1 << 2), (0x1 << 2));
+		mod_phy_reg(pi, 0x8f, (0x1 << 2), (0x1 << 2));
+		mod_phy_reg(pi, 0xa5, (0x1 << 2), (0x1 << 2));
+		udelay(5);
+		mod_phy_reg(pi, 0xa6, (0x1 << 2), 0);
+		mod_phy_reg(pi, 0xa7, (0x1 << 2), 0);
+		mod_phy_reg(pi, 0xa6, (0x1 << 3), 0);
+		mod_phy_reg(pi, 0xa7, (0x1 << 3), 0);
+		mod_phy_reg(pi, 0x8f, (0x1 << 3), (0x1 << 3));
+		mod_phy_reg(pi, 0xa5, (0x1 << 3), (0x1 << 3));
+		mod_phy_reg(pi, 0xa6, (0x1 << 6), 0);
+		mod_phy_reg(pi, 0xa7, (0x1 << 6), 0);
+		mod_phy_reg(pi, 0x8f, (0x1 << 6), (0x1 << 6));
+		mod_phy_reg(pi, 0xa5, (0x1 << 6), (0x1 << 6));
+
+		auxADC_Vmid = 0xA3;
+		auxADC_Av = 0x0;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
+					 &auxADC_Vmid);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
+					 &auxADC_Av);
+
+		udelay(3);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
+		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
+				tempsense_Rcal | 0x03);
+
+		udelay(5);
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
+
+		auxADC_Av = 0x7;
+		if (radio_temp[1] + radio_temp2[1] < -30) {
+			auxADC_Vmid = 0x45;
+			auxADC_Vl = 263;
+		} else if (radio_temp[1] + radio_temp2[1] < -9) {
+			auxADC_Vmid = 0x200;
+			auxADC_Vl = 467;
+		} else if (radio_temp[1] + radio_temp2[1] < 11) {
+			auxADC_Vmid = 0x266;
+			auxADC_Vl = 634;
+		} else {
+			auxADC_Vmid = 0x2D5;
+			auxADC_Vl = 816;
+		}
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
+					 &auxADC_Vmid);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
+					 &auxADC_Av);
+
+		udelay(3);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
+		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
+				tempsense_Rcal | 0x01);
+
+		udelay(5);
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
+
+		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
+				syn_tempprocsense_save);
+
+		write_phy_reg(pi, 0xa6, afectrlCore1_save);
+		write_phy_reg(pi, 0xa7, afectrlCore2_save);
+		write_phy_reg(pi, 0x8f, afectrlOverride_save);
+		write_phy_reg(pi, 0xa5, afectrlOverride2_save);
+		write_phy_reg(pi, 0x1ae, RSSIMultCoef0QPowerDet_save);
+		write_phy_reg(pi, 0x346, RfctrlOverride5_save);
+		write_phy_reg(pi, 0x347, RfctrlOverride6_save);
+		write_phy_reg(pi, 0x344, RfctrlMiscReg5_save);
+		write_phy_reg(pi, 0x345, RfctrlMiscReg5_save);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
+					 &auxADC_Vmid_save);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
+					 &auxADC_Av_save);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16,
+					 &auxADC_rssi_ctrlL_save);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16,
+					 &auxADC_rssi_ctrlH_save);
+
+		if (pi->sh->chip == BCMA_CHIP_ID_BCM5357) {
+			radio_temp[0] = (193 * (radio_temp[1] + radio_temp2[1])
+					 + 88 * (auxADC_Vl) - 27111 +
+					 128) / 256;
+		} else {
+			radio_temp[0] = (179 * (radio_temp[1] + radio_temp2[1])
+					 + 82 * (auxADC_Vl) - 28861 +
+					 128) / 256;
+		}
+
+		offset = (s16) pi->phy_tempsense_offset;
+
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		syn_tempprocsense_save =
+			read_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE);
+
+		afectrlCore1_save = read_phy_reg(pi, 0xa6);
+		afectrlCore2_save = read_phy_reg(pi, 0xa7);
+		afectrlOverride_save = read_phy_reg(pi, 0x8f);
+		afectrlOverride2_save = read_phy_reg(pi, 0xa5);
+		gpioSel_save = read_phy_reg(pi, 0xca);
+
+		write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x01);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
+		if (NREV_LT(pi->pubpi.phy_rev, 7))
+			write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x05);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
+		if (NREV_GE(pi->pubpi.phy_rev, 7))
+			write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x01);
+		else
+			write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x01);
+
+		radio_temp[0] =
+			(126 * (radio_temp[1] + radio_temp2[1]) + 3987) / 64;
+
+		write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE,
+				syn_tempprocsense_save);
+
+		write_phy_reg(pi, 0xca, gpioSel_save);
+		write_phy_reg(pi, 0xa6, afectrlCore1_save);
+		write_phy_reg(pi, 0xa7, afectrlCore2_save);
+		write_phy_reg(pi, 0x8f, afectrlOverride_save);
+		write_phy_reg(pi, 0xa5, afectrlOverride2_save);
+
+		offset = (s16) pi->phy_tempsense_offset;
+	} else {
+
+		pwrdet_rxtx_core1_save =
+			read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1);
+		pwrdet_rxtx_core2_save =
+			read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2);
+		core1_txrf_iqcal1_save =
+			read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1);
+		core1_txrf_iqcal2_save =
+			read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2);
+		core2_txrf_iqcal1_save =
+			read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1);
+		core2_txrf_iqcal2_save =
+			read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2);
+		pd_pll_ts_save = read_radio_reg(pi, RADIO_2055_PD_PLL_TS);
+
+		afectrlCore1_save = read_phy_reg(pi, 0xa6);
+		afectrlCore2_save = read_phy_reg(pi, 0xa7);
+		afectrlOverride_save = read_phy_reg(pi, 0xa5);
+		gpioSel_save = read_phy_reg(pi, 0xca);
+
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, 0x01);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, 0x01);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, 0x08);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, 0x08);
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x04);
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x04);
+		write_radio_reg(pi, RADIO_2055_PD_PLL_TS, 0x00);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
+		xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
+		xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
+		xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80);
+
+		radio_temp[0] = (radio_temp[0] + radio_temp2[0]);
+		radio_temp[1] = (radio_temp[1] + radio_temp2[1]);
+		radio_temp[2] = (radio_temp[2] + radio_temp2[2]);
+		radio_temp[3] = (radio_temp[3] + radio_temp2[3]);
+
+		radio_temp[0] =
+			(radio_temp[0] + radio_temp[1] + radio_temp[2] +
+			 radio_temp[3]);
+
+		radio_temp[0] =
+			(radio_temp[0] +
+			 (8 * 32)) * (950 - 350) / 63 + (350 * 8);
+
+		radio_temp[0] = (radio_temp[0] - (8 * 420)) / 38;
+
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1,
+				pwrdet_rxtx_core1_save);
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2,
+				pwrdet_rxtx_core2_save);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1,
+				core1_txrf_iqcal1_save);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1,
+				core2_txrf_iqcal1_save);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2,
+				core1_txrf_iqcal2_save);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2,
+				core2_txrf_iqcal2_save);
+		write_radio_reg(pi, RADIO_2055_PD_PLL_TS, pd_pll_ts_save);
+
+		write_phy_reg(pi, 0xca, gpioSel_save);
+		write_phy_reg(pi, 0xa6, afectrlCore1_save);
+		write_phy_reg(pi, 0xa7, afectrlCore2_save);
+		write_phy_reg(pi, 0xa5, afectrlOverride_save);
+	}
+
+	return (s16) radio_temp[0] + offset;
+}
+
+static void
+wlc_phy_set_rssi_2055_vcm(struct brcms_phy *pi, u8 rssi_type, u8 *vcm_buf)
+{
+	u8 core;
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+		if (rssi_type == NPHY_RSSI_SEL_NB) {
+			if (core == PHY_CORE_0) {
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE1_B0_NBRSSI_VCM,
+					      RADIO_2055_NBRSSI_VCM_I_MASK,
+					      vcm_buf[2 *
+						      core] <<
+					      RADIO_2055_NBRSSI_VCM_I_SHIFT);
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE1_RXBB_RSSI_CTRL5,
+					      RADIO_2055_NBRSSI_VCM_Q_MASK,
+					      vcm_buf[2 * core +
+						      1] <<
+					      RADIO_2055_NBRSSI_VCM_Q_SHIFT);
+			} else {
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE2_B0_NBRSSI_VCM,
+					      RADIO_2055_NBRSSI_VCM_I_MASK,
+					      vcm_buf[2 *
+						      core] <<
+					      RADIO_2055_NBRSSI_VCM_I_SHIFT);
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE2_RXBB_RSSI_CTRL5,
+					      RADIO_2055_NBRSSI_VCM_Q_MASK,
+					      vcm_buf[2 * core +
+						      1] <<
+					      RADIO_2055_NBRSSI_VCM_Q_SHIFT);
+			}
+		} else {
+			if (core == PHY_CORE_0)
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE1_RXBB_RSSI_CTRL5,
+					      RADIO_2055_WBRSSI_VCM_IQ_MASK,
+					      vcm_buf[2 *
+						      core] <<
+					      RADIO_2055_WBRSSI_VCM_IQ_SHIFT);
+			else
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE2_RXBB_RSSI_CTRL5,
+					      RADIO_2055_WBRSSI_VCM_IQ_MASK,
+					      vcm_buf[2 *
+						      core] <<
+					      RADIO_2055_WBRSSI_VCM_IQ_SHIFT);
+		}
+	}
+}
+
+static void wlc_phy_rssi_cal_nphy_rev3(struct brcms_phy *pi)
+{
+	u16 classif_state;
+	u16 clip_state[2];
+	u16 clip_off[] = { 0xffff, 0xffff };
+	s32 target_code;
+	u8 vcm, min_vcm;
+	u8 vcm_final = 0;
+	u8 result_idx;
+	s32 poll_results[8][4] = {
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0}
+	};
+	s32 poll_result_core[4] = { 0, 0, 0, 0 };
+	s32 min_d = NPHY_RSSICAL_MAXD, curr_d;
+	s32 fine_digital_offset[4];
+	s32 poll_results_min[4] = { 0, 0, 0, 0 };
+	s32 min_poll;
+	u8 vcm_level_max;
+	u8 core;
+	u8 wb_cnt;
+	u8 rssi_type;
+	u16 NPHY_Rfctrlintc1_save, NPHY_Rfctrlintc2_save;
+	u16 NPHY_AfectrlOverride1_save, NPHY_AfectrlOverride2_save;
+	u16 NPHY_AfectrlCore1_save, NPHY_AfectrlCore2_save;
+	u16 NPHY_RfctrlOverride0_save, NPHY_RfctrlOverride1_save;
+	u16 NPHY_RfctrlOverrideAux0_save, NPHY_RfctrlOverrideAux1_save;
+	u16 NPHY_RfctrlCmd_save;
+	u16 NPHY_RfctrlMiscReg1_save, NPHY_RfctrlMiscReg2_save;
+	u16 NPHY_RfctrlRSSIOTHERS1_save, NPHY_RfctrlRSSIOTHERS2_save;
+	u8 rxcore_state;
+	u16 NPHY_REV7_RfctrlOverride3_save, NPHY_REV7_RfctrlOverride4_save;
+	u16 NPHY_REV7_RfctrlOverride5_save, NPHY_REV7_RfctrlOverride6_save;
+	u16 NPHY_REV7_RfctrlMiscReg3_save, NPHY_REV7_RfctrlMiscReg4_save;
+	u16 NPHY_REV7_RfctrlMiscReg5_save, NPHY_REV7_RfctrlMiscReg6_save;
+
+	NPHY_REV7_RfctrlOverride3_save =
+		NPHY_REV7_RfctrlOverride4_save =
+		NPHY_REV7_RfctrlOverride5_save =
+		NPHY_REV7_RfctrlOverride6_save =
+		NPHY_REV7_RfctrlMiscReg3_save =
+		NPHY_REV7_RfctrlMiscReg4_save =
+		NPHY_REV7_RfctrlMiscReg5_save =
+		NPHY_REV7_RfctrlMiscReg6_save = 0;
+
+	classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
+	wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
+	wlc_phy_clip_det_nphy(pi, 0, clip_state);
+	wlc_phy_clip_det_nphy(pi, 1, clip_off);
+
+	NPHY_Rfctrlintc1_save = read_phy_reg(pi, 0x91);
+	NPHY_Rfctrlintc2_save = read_phy_reg(pi, 0x92);
+	NPHY_AfectrlOverride1_save = read_phy_reg(pi, 0x8f);
+	NPHY_AfectrlOverride2_save = read_phy_reg(pi, 0xa5);
+	NPHY_AfectrlCore1_save = read_phy_reg(pi, 0xa6);
+	NPHY_AfectrlCore2_save = read_phy_reg(pi, 0xa7);
+	NPHY_RfctrlOverride0_save = read_phy_reg(pi, 0xe7);
+	NPHY_RfctrlOverride1_save = read_phy_reg(pi, 0xec);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		NPHY_REV7_RfctrlOverride3_save = read_phy_reg(pi, 0x342);
+		NPHY_REV7_RfctrlOverride4_save = read_phy_reg(pi, 0x343);
+		NPHY_REV7_RfctrlOverride5_save = read_phy_reg(pi, 0x346);
+		NPHY_REV7_RfctrlOverride6_save = read_phy_reg(pi, 0x347);
+	}
+	NPHY_RfctrlOverrideAux0_save = read_phy_reg(pi, 0xe5);
+	NPHY_RfctrlOverrideAux1_save = read_phy_reg(pi, 0xe6);
+	NPHY_RfctrlCmd_save = read_phy_reg(pi, 0x78);
+	NPHY_RfctrlMiscReg1_save = read_phy_reg(pi, 0xf9);
+	NPHY_RfctrlMiscReg2_save = read_phy_reg(pi, 0xfb);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		NPHY_REV7_RfctrlMiscReg3_save = read_phy_reg(pi, 0x340);
+		NPHY_REV7_RfctrlMiscReg4_save = read_phy_reg(pi, 0x341);
+		NPHY_REV7_RfctrlMiscReg5_save = read_phy_reg(pi, 0x344);
+		NPHY_REV7_RfctrlMiscReg6_save = read_phy_reg(pi, 0x345);
+	}
+	NPHY_RfctrlRSSIOTHERS1_save = read_phy_reg(pi, 0x7a);
+	NPHY_RfctrlRSSIOTHERS2_save = read_phy_reg(pi, 0x7d);
+
+	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_OFF, 0,
+					 RADIO_MIMO_CORESEL_ALLRXTX);
+	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_TRSW, 1,
+					 RADIO_MIMO_CORESEL_ALLRXTX);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7))
+		wlc_phy_rfctrl_override_1tomany_nphy(
+			pi,
+			NPHY_REV7_RfctrlOverride_cmd_rxrf_pu,
+			0, 0, 0);
+	else
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0, 0);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7))
+		wlc_phy_rfctrl_override_1tomany_nphy(
+			pi,
+			NPHY_REV7_RfctrlOverride_cmd_rx_pu,
+			1, 0, 0);
+	else
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0, 0);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
+						  1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 6), 1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+	} else {
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 7), 1, 0, 0);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 6), 1, 0, 0);
+	}
+
+	if (CHSPEC_IS5G(pi->radio_chanspec)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 5),
+				0, 0, 0,
+				NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 4), 1, 0,
+				0,
+				NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		} else {
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 0, 0, 0);
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 1, 0, 0);
+		}
+
+	} else {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 4),
+				0, 0, 0,
+				NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 5), 1, 0,
+				0,
+				NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		} else {
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 0, 0, 0);
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 1, 0, 0);
+		}
+	}
+
+	rxcore_state = wlc_phy_rxcore_getstate_nphy(
+		(struct brcms_phy_pub *) pi);
+
+	vcm_level_max = 8;
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+		if ((rxcore_state & (1 << core)) == 0)
+			continue;
+
+		wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
+					       core ==
+					       PHY_CORE_0 ?
+					       RADIO_MIMO_CORESEL_CORE1 :
+					       RADIO_MIMO_CORESEL_CORE2,
+					       NPHY_RAIL_I, NPHY_RSSI_SEL_NB);
+		wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
+					       core ==
+					       PHY_CORE_0 ?
+					       RADIO_MIMO_CORESEL_CORE1 :
+					       RADIO_MIMO_CORESEL_CORE2,
+					       NPHY_RAIL_Q, NPHY_RSSI_SEL_NB);
+
+		for (vcm = 0; vcm < vcm_level_max; vcm++) {
+			if (NREV_GE(pi->pubpi.phy_rev, 7))
+				mod_radio_reg(pi, (core == PHY_CORE_0) ?
+					      RADIO_2057_NB_MASTER_CORE0 :
+					      RADIO_2057_NB_MASTER_CORE1,
+					      RADIO_2057_VCM_MASK, vcm);
+			else
+				mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC |
+					      ((core ==
+						PHY_CORE_0) ? RADIO_2056_RX0 :
+					       RADIO_2056_RX1),
+					      RADIO_2056_VCM_MASK,
+					      vcm << RADIO_2056_RSSI_VCM_SHIFT);
+
+			wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_NB,
+					       &poll_results[vcm][0],
+					       NPHY_RSSICAL_NPOLL);
+		}
+
+		for (result_idx = 0; result_idx < 4; result_idx++) {
+			if ((core == result_idx / 2) &&
+			    (result_idx % 2 == 0)) {
+
+				min_d = NPHY_RSSICAL_MAXD;
+				min_vcm = 0;
+				min_poll =
+					NPHY_RSSICAL_MAXREAD *
+					NPHY_RSSICAL_NPOLL + 1;
+				for (vcm = 0; vcm < vcm_level_max; vcm++) {
+					curr_d =
+						poll_results[vcm][result_idx] *
+						poll_results[vcm][result_idx] +
+						poll_results[vcm][result_idx +
+								  1] *
+						poll_results[vcm][result_idx +
+								  1];
+					if (curr_d < min_d) {
+						min_d = curr_d;
+						min_vcm = vcm;
+					}
+					if (poll_results[vcm][result_idx] <
+					    min_poll)
+						min_poll =
+							poll_results[vcm]
+							[result_idx];
+				}
+				vcm_final = min_vcm;
+				poll_results_min[result_idx] = min_poll;
+			}
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7))
+			mod_radio_reg(pi, (core == PHY_CORE_0) ?
+				      RADIO_2057_NB_MASTER_CORE0 :
+				      RADIO_2057_NB_MASTER_CORE1,
+				      RADIO_2057_VCM_MASK, vcm_final);
+		else
+			mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC |
+				      ((core ==
+					PHY_CORE_0) ? RADIO_2056_RX0 :
+				       RADIO_2056_RX1), RADIO_2056_VCM_MASK,
+				      vcm_final << RADIO_2056_RSSI_VCM_SHIFT);
+
+		for (result_idx = 0; result_idx < 4; result_idx++) {
+			if (core == result_idx / 2) {
+				fine_digital_offset[result_idx] =
+					(NPHY_RSSICAL_NB_TARGET *
+					 NPHY_RSSICAL_NPOLL) -
+					poll_results[vcm_final][result_idx];
+				if (fine_digital_offset[result_idx] < 0) {
+					fine_digital_offset[result_idx] =
+						abs(fine_digital_offset
+						    [result_idx]);
+					fine_digital_offset[result_idx] +=
+						(NPHY_RSSICAL_NPOLL / 2);
+					fine_digital_offset[result_idx] /=
+						NPHY_RSSICAL_NPOLL;
+					fine_digital_offset[result_idx] =
+						-fine_digital_offset[
+								    result_idx];
+				} else {
+					fine_digital_offset[result_idx] +=
+						(NPHY_RSSICAL_NPOLL / 2);
+					fine_digital_offset[result_idx] /=
+						NPHY_RSSICAL_NPOLL;
+				}
+
+				if (poll_results_min[result_idx] ==
+				    NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL)
+					fine_digital_offset[result_idx] =
+						(NPHY_RSSICAL_NB_TARGET -
+						 NPHY_RSSICAL_MAXREAD - 1);
+
+				wlc_phy_scale_offset_rssi_nphy(
+					pi, 0x0,
+					(s8)
+					fine_digital_offset
+					[result_idx],
+					(result_idx / 2 == 0) ?
+					RADIO_MIMO_CORESEL_CORE1 :
+					RADIO_MIMO_CORESEL_CORE2,
+					(result_idx % 2 == 0) ?
+					NPHY_RAIL_I : NPHY_RAIL_Q,
+					NPHY_RSSI_SEL_NB);
+			}
+		}
+
+	}
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+		if ((rxcore_state & (1 << core)) == 0)
+			continue;
+
+		for (wb_cnt = 0; wb_cnt < 2; wb_cnt++) {
+			if (wb_cnt == 0) {
+				rssi_type = NPHY_RSSI_SEL_W1;
+				target_code = NPHY_RSSICAL_W1_TARGET_REV3;
+			} else {
+				rssi_type = NPHY_RSSI_SEL_W2;
+				target_code = NPHY_RSSICAL_W2_TARGET_REV3;
+			}
+
+			wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
+						       core ==
+						       PHY_CORE_0 ?
+						       RADIO_MIMO_CORESEL_CORE1
+						       :
+						       RADIO_MIMO_CORESEL_CORE2,
+						       NPHY_RAIL_I, rssi_type);
+			wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
+						       core ==
+						       PHY_CORE_0 ?
+						       RADIO_MIMO_CORESEL_CORE1
+						       :
+						       RADIO_MIMO_CORESEL_CORE2,
+						       NPHY_RAIL_Q, rssi_type);
+
+			wlc_phy_poll_rssi_nphy(pi, rssi_type, poll_result_core,
+					       NPHY_RSSICAL_NPOLL);
+
+			for (result_idx = 0; result_idx < 4; result_idx++) {
+				if (core == result_idx / 2) {
+					fine_digital_offset[result_idx] =
+						(target_code *
+						 NPHY_RSSICAL_NPOLL) -
+						poll_result_core[result_idx];
+					if (fine_digital_offset[result_idx] <
+					    0) {
+						fine_digital_offset[result_idx]
+							= abs(
+							    fine_digital_offset
+							    [result_idx]);
+						fine_digital_offset[result_idx]
+							+= (NPHY_RSSICAL_NPOLL
+							    / 2);
+						fine_digital_offset[result_idx]
+							/= NPHY_RSSICAL_NPOLL;
+						fine_digital_offset[result_idx]
+							= -fine_digital_offset
+								[result_idx];
+					} else {
+						fine_digital_offset[result_idx]
+							+= (NPHY_RSSICAL_NPOLL
+							    / 2);
+						fine_digital_offset[result_idx]
+							/= NPHY_RSSICAL_NPOLL;
+					}
+
+					wlc_phy_scale_offset_rssi_nphy(
+						pi, 0x0,
+						(s8)
+						fine_digital_offset
+						[core *
+						 2],
+						(core == PHY_CORE_0) ?
+						RADIO_MIMO_CORESEL_CORE1 :
+						RADIO_MIMO_CORESEL_CORE2,
+						(result_idx % 2 == 0) ?
+						NPHY_RAIL_I :
+						NPHY_RAIL_Q,
+						rssi_type);
+				}
+			}
+
+		}
+	}
+
+	write_phy_reg(pi, 0x91, NPHY_Rfctrlintc1_save);
+	write_phy_reg(pi, 0x92, NPHY_Rfctrlintc2_save);
+
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+
+	mod_phy_reg(pi, 0xe7, (0x1 << 0), 1 << 0);
+	mod_phy_reg(pi, 0x78, (0x1 << 0), 1 << 0);
+	mod_phy_reg(pi, 0xe7, (0x1 << 0), 0);
+
+	mod_phy_reg(pi, 0xec, (0x1 << 0), 1 << 0);
+	mod_phy_reg(pi, 0x78, (0x1 << 1), 1 << 1);
+	mod_phy_reg(pi, 0xec, (0x1 << 0), 0);
+
+	write_phy_reg(pi, 0x8f, NPHY_AfectrlOverride1_save);
+	write_phy_reg(pi, 0xa5, NPHY_AfectrlOverride2_save);
+	write_phy_reg(pi, 0xa6, NPHY_AfectrlCore1_save);
+	write_phy_reg(pi, 0xa7, NPHY_AfectrlCore2_save);
+	write_phy_reg(pi, 0xe7, NPHY_RfctrlOverride0_save);
+	write_phy_reg(pi, 0xec, NPHY_RfctrlOverride1_save);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		write_phy_reg(pi, 0x342, NPHY_REV7_RfctrlOverride3_save);
+		write_phy_reg(pi, 0x343, NPHY_REV7_RfctrlOverride4_save);
+		write_phy_reg(pi, 0x346, NPHY_REV7_RfctrlOverride5_save);
+		write_phy_reg(pi, 0x347, NPHY_REV7_RfctrlOverride6_save);
+	}
+	write_phy_reg(pi, 0xe5, NPHY_RfctrlOverrideAux0_save);
+	write_phy_reg(pi, 0xe6, NPHY_RfctrlOverrideAux1_save);
+	write_phy_reg(pi, 0x78, NPHY_RfctrlCmd_save);
+	write_phy_reg(pi, 0xf9, NPHY_RfctrlMiscReg1_save);
+	write_phy_reg(pi, 0xfb, NPHY_RfctrlMiscReg2_save);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		write_phy_reg(pi, 0x340, NPHY_REV7_RfctrlMiscReg3_save);
+		write_phy_reg(pi, 0x341, NPHY_REV7_RfctrlMiscReg4_save);
+		write_phy_reg(pi, 0x344, NPHY_REV7_RfctrlMiscReg5_save);
+		write_phy_reg(pi, 0x345, NPHY_REV7_RfctrlMiscReg6_save);
+	}
+	write_phy_reg(pi, 0x7a, NPHY_RfctrlRSSIOTHERS1_save);
+	write_phy_reg(pi, 0x7d, NPHY_RfctrlRSSIOTHERS2_save);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			pi->rssical_cache.rssical_radio_regs_2G[0] =
+				read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0);
+			pi->rssical_cache.rssical_radio_regs_2G[1] =
+				read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1);
+		} else {
+			pi->rssical_cache.rssical_radio_regs_2G[0] =
+				read_radio_reg(pi,
+					       RADIO_2056_RX_RSSI_MISC |
+					       RADIO_2056_RX0);
+			pi->rssical_cache.rssical_radio_regs_2G[1] =
+				read_radio_reg(pi,
+					       RADIO_2056_RX_RSSI_MISC |
+					       RADIO_2056_RX1);
+		}
+
+		pi->rssical_cache.rssical_phyregs_2G[0] =
+			read_phy_reg(pi, 0x1a6);
+		pi->rssical_cache.rssical_phyregs_2G[1] =
+			read_phy_reg(pi, 0x1ac);
+		pi->rssical_cache.rssical_phyregs_2G[2] =
+			read_phy_reg(pi, 0x1b2);
+		pi->rssical_cache.rssical_phyregs_2G[3] =
+			read_phy_reg(pi, 0x1b8);
+		pi->rssical_cache.rssical_phyregs_2G[4] =
+			read_phy_reg(pi, 0x1a4);
+		pi->rssical_cache.rssical_phyregs_2G[5] =
+			read_phy_reg(pi, 0x1aa);
+		pi->rssical_cache.rssical_phyregs_2G[6] =
+			read_phy_reg(pi, 0x1b0);
+		pi->rssical_cache.rssical_phyregs_2G[7] =
+			read_phy_reg(pi, 0x1b6);
+		pi->rssical_cache.rssical_phyregs_2G[8] =
+			read_phy_reg(pi, 0x1a5);
+		pi->rssical_cache.rssical_phyregs_2G[9] =
+			read_phy_reg(pi, 0x1ab);
+		pi->rssical_cache.rssical_phyregs_2G[10] =
+			read_phy_reg(pi, 0x1b1);
+		pi->rssical_cache.rssical_phyregs_2G[11] =
+			read_phy_reg(pi, 0x1b7);
+
+		pi->nphy_rssical_chanspec_2G = pi->radio_chanspec;
+	} else {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			pi->rssical_cache.rssical_radio_regs_5G[0] =
+				read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0);
+			pi->rssical_cache.rssical_radio_regs_5G[1] =
+				read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1);
+		} else {
+			pi->rssical_cache.rssical_radio_regs_5G[0] =
+				read_radio_reg(pi,
+					       RADIO_2056_RX_RSSI_MISC |
+					       RADIO_2056_RX0);
+			pi->rssical_cache.rssical_radio_regs_5G[1] =
+				read_radio_reg(pi,
+					       RADIO_2056_RX_RSSI_MISC |
+					       RADIO_2056_RX1);
+		}
+
+		pi->rssical_cache.rssical_phyregs_5G[0] =
+			read_phy_reg(pi, 0x1a6);
+		pi->rssical_cache.rssical_phyregs_5G[1] =
+			read_phy_reg(pi, 0x1ac);
+		pi->rssical_cache.rssical_phyregs_5G[2] =
+			read_phy_reg(pi, 0x1b2);
+		pi->rssical_cache.rssical_phyregs_5G[3] =
+			read_phy_reg(pi, 0x1b8);
+		pi->rssical_cache.rssical_phyregs_5G[4] =
+			read_phy_reg(pi, 0x1a4);
+		pi->rssical_cache.rssical_phyregs_5G[5] =
+			read_phy_reg(pi, 0x1aa);
+		pi->rssical_cache.rssical_phyregs_5G[6] =
+			read_phy_reg(pi, 0x1b0);
+		pi->rssical_cache.rssical_phyregs_5G[7] =
+			read_phy_reg(pi, 0x1b6);
+		pi->rssical_cache.rssical_phyregs_5G[8] =
+			read_phy_reg(pi, 0x1a5);
+		pi->rssical_cache.rssical_phyregs_5G[9] =
+			read_phy_reg(pi, 0x1ab);
+		pi->rssical_cache.rssical_phyregs_5G[10] =
+			read_phy_reg(pi, 0x1b1);
+		pi->rssical_cache.rssical_phyregs_5G[11] =
+			read_phy_reg(pi, 0x1b7);
+
+		pi->nphy_rssical_chanspec_5G = pi->radio_chanspec;
+	}
+
+	wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
+	wlc_phy_clip_det_nphy(pi, 1, clip_state);
+}
+
+static void wlc_phy_rssi_cal_nphy_rev2(struct brcms_phy *pi, u8 rssi_type)
+{
+	s32 target_code;
+	u16 classif_state;
+	u16 clip_state[2];
+	u16 rssi_ctrl_state[2], pd_state[2];
+	u16 rfctrlintc_state[2], rfpdcorerxtx_state[2];
+	u16 rfctrlintc_override_val;
+	u16 clip_off[] = { 0xffff, 0xffff };
+	u16 rf_pd_val, pd_mask, rssi_ctrl_mask;
+	u8 vcm, min_vcm, vcm_tmp[4];
+	u8 vcm_final[4] = { 0, 0, 0, 0 };
+	u8 result_idx, ctr;
+	s32 poll_results[4][4] = {
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0}
+	};
+	s32 poll_miniq[4][2] = {
+		{0, 0},
+		{0, 0},
+		{0, 0},
+		{0, 0}
+	};
+	s32 min_d, curr_d;
+	s32 fine_digital_offset[4];
+	s32 poll_results_min[4] = { 0, 0, 0, 0 };
+	s32 min_poll;
+
+	switch (rssi_type) {
+	case NPHY_RSSI_SEL_NB:
+		target_code = NPHY_RSSICAL_NB_TARGET;
+		break;
+	case NPHY_RSSI_SEL_W1:
+		target_code = NPHY_RSSICAL_W1_TARGET;
+		break;
+	case NPHY_RSSI_SEL_W2:
+		target_code = NPHY_RSSICAL_W2_TARGET;
+		break;
+	default:
+		return;
+	}
+
+	classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
+	wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
+	wlc_phy_clip_det_nphy(pi, 0, clip_state);
+	wlc_phy_clip_det_nphy(pi, 1, clip_off);
+
+	rf_pd_val = (rssi_type == NPHY_RSSI_SEL_NB) ? 0x6 : 0x4;
+	rfctrlintc_override_val =
+		CHSPEC_IS5G(pi->radio_chanspec) ? 0x140 : 0x110;
+
+	rfctrlintc_state[0] = read_phy_reg(pi, 0x91);
+	rfpdcorerxtx_state[0] = read_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX);
+	write_phy_reg(pi, 0x91, rfctrlintc_override_val);
+	write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rf_pd_val);
+
+	rfctrlintc_state[1] = read_phy_reg(pi, 0x92);
+	rfpdcorerxtx_state[1] = read_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX);
+	write_phy_reg(pi, 0x92, rfctrlintc_override_val);
+	write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rf_pd_val);
+
+	pd_mask = RADIO_2055_NBRSSI_PD | RADIO_2055_WBRSSI_G1_PD |
+		  RADIO_2055_WBRSSI_G2_PD;
+	pd_state[0] =
+		read_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC) & pd_mask;
+	pd_state[1] =
+		read_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC) & pd_mask;
+	mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, 0);
+	mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, 0);
+	rssi_ctrl_mask = RADIO_2055_NBRSSI_SEL | RADIO_2055_WBRSSI_G1_SEL |
+			 RADIO_2055_WBRSSI_G2_SEL;
+	rssi_ctrl_state[0] =
+		read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE1) & rssi_ctrl_mask;
+	rssi_ctrl_state[1] =
+		read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE2) & rssi_ctrl_mask;
+	wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type);
+
+	wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX,
+				       NPHY_RAIL_I, rssi_type);
+	wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX,
+				       NPHY_RAIL_Q, rssi_type);
+
+	for (vcm = 0; vcm < 4; vcm++) {
+
+		vcm_tmp[0] = vcm_tmp[1] = vcm_tmp[2] = vcm_tmp[3] = vcm;
+		if (rssi_type != NPHY_RSSI_SEL_W2)
+			wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_tmp);
+
+		wlc_phy_poll_rssi_nphy(pi, rssi_type, &poll_results[vcm][0],
+				       NPHY_RSSICAL_NPOLL);
+
+		if ((rssi_type == NPHY_RSSI_SEL_W1)
+		    || (rssi_type == NPHY_RSSI_SEL_W2)) {
+			for (ctr = 0; ctr < 2; ctr++)
+				poll_miniq[vcm][ctr] =
+					min(poll_results[vcm][ctr * 2 + 0],
+					    poll_results[vcm][ctr * 2 + 1]);
+		}
+	}
+
+	for (result_idx = 0; result_idx < 4; result_idx++) {
+		min_d = NPHY_RSSICAL_MAXD;
+		min_vcm = 0;
+		min_poll = NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL + 1;
+		for (vcm = 0; vcm < 4; vcm++) {
+			curr_d = abs(((rssi_type == NPHY_RSSI_SEL_NB) ?
+				      poll_results[vcm][result_idx] :
+				      poll_miniq[vcm][result_idx / 2]) -
+				     (target_code * NPHY_RSSICAL_NPOLL));
+			if (curr_d < min_d) {
+				min_d = curr_d;
+				min_vcm = vcm;
+			}
+			if (poll_results[vcm][result_idx] < min_poll)
+				min_poll = poll_results[vcm][result_idx];
+		}
+		vcm_final[result_idx] = min_vcm;
+		poll_results_min[result_idx] = min_poll;
+	}
+
+	if (rssi_type != NPHY_RSSI_SEL_W2)
+		wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_final);
+
+	for (result_idx = 0; result_idx < 4; result_idx++) {
+		fine_digital_offset[result_idx] =
+			(target_code * NPHY_RSSICAL_NPOLL) -
+			poll_results[vcm_final[result_idx]][result_idx];
+		if (fine_digital_offset[result_idx] < 0) {
+			fine_digital_offset[result_idx] =
+				abs(fine_digital_offset[result_idx]);
+			fine_digital_offset[result_idx] +=
+				(NPHY_RSSICAL_NPOLL / 2);
+			fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL;
+			fine_digital_offset[result_idx] =
+				-fine_digital_offset[result_idx];
+		} else {
+			fine_digital_offset[result_idx] +=
+				(NPHY_RSSICAL_NPOLL / 2);
+			fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL;
+		}
+
+		if (poll_results_min[result_idx] ==
+		    NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL)
+			fine_digital_offset[result_idx] =
+				(target_code - NPHY_RSSICAL_MAXREAD - 1);
+
+		wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
+					       (s8)
+					       fine_digital_offset[result_idx],
+					       (result_idx / 2 ==
+						0) ? RADIO_MIMO_CORESEL_CORE1 :
+					       RADIO_MIMO_CORESEL_CORE2,
+					       (result_idx % 2 ==
+						0) ? NPHY_RAIL_I : NPHY_RAIL_Q,
+					       rssi_type);
+	}
+
+	mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, pd_state[0]);
+	mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, pd_state[1]);
+	if (rssi_ctrl_state[0] == RADIO_2055_NBRSSI_SEL)
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
+				     NPHY_RSSI_SEL_NB);
+	else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G1_SEL)
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
+				     NPHY_RSSI_SEL_W1);
+	else /* RADIO_2055_WBRSSI_G2_SEL */
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
+				     NPHY_RSSI_SEL_W2);
+	if (rssi_ctrl_state[1] == RADIO_2055_NBRSSI_SEL)
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
+				     NPHY_RSSI_SEL_NB);
+	else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G1_SEL)
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
+				     NPHY_RSSI_SEL_W1);
+	else /* RADIO_2055_WBRSSI_G1_SEL */
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
+				     NPHY_RSSI_SEL_W2);
+	wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, rssi_type);
+
+	write_phy_reg(pi, 0x91, rfctrlintc_state[0]);
+	write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rfpdcorerxtx_state[0]);
+	write_phy_reg(pi, 0x92, rfctrlintc_state[1]);
+	write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rfpdcorerxtx_state[1]);
+
+	wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
+	wlc_phy_clip_det_nphy(pi, 1, clip_state);
+
+	wlc_phy_resetcca_nphy(pi);
+}
+
+void wlc_phy_rssi_cal_nphy(struct brcms_phy *pi)
+{
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		wlc_phy_rssi_cal_nphy_rev3(pi);
+	} else {
+		wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_NB);
+		wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W1);
+		wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W2);
+	}
+}
+
+int
+wlc_phy_rssi_compute_nphy(struct brcms_phy *pi, struct d11rxhdr *rxh)
+{
+	s16 rxpwr, rxpwr0, rxpwr1;
+	s16 phyRx0_l, phyRx2_l;
+
+	rxpwr = 0;
+	rxpwr0 = rxh->PhyRxStatus_1 & PRXS1_nphy_PWR0_MASK;
+	rxpwr1 = (rxh->PhyRxStatus_1 & PRXS1_nphy_PWR1_MASK) >> 8;
+
+	if (rxpwr0 > 127)
+		rxpwr0 -= 256;
+	if (rxpwr1 > 127)
+		rxpwr1 -= 256;
+
+	phyRx0_l = rxh->PhyRxStatus_0 & 0x00ff;
+	phyRx2_l = rxh->PhyRxStatus_2 & 0x00ff;
+	if (phyRx2_l > 127)
+		phyRx2_l -= 256;
+
+	if (((rxpwr0 == 16) || (rxpwr0 == 32))) {
+		rxpwr0 = rxpwr1;
+		rxpwr1 = phyRx2_l;
+	}
+
+	if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MAX)
+		rxpwr = (rxpwr0 > rxpwr1) ? rxpwr0 : rxpwr1;
+	else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MIN)
+		rxpwr = (rxpwr0 < rxpwr1) ? rxpwr0 : rxpwr1;
+	else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_AVG)
+		rxpwr = (rxpwr0 + rxpwr1) >> 1;
+
+	return rxpwr;
+}
+
+static void
+wlc_phy_loadsampletable_nphy(struct brcms_phy *pi, struct cordic_iq *tone_buf,
+			     u16 num_samps)
+{
+	u16 t;
+	u32 *data_buf = NULL;
+
+	data_buf = kmalloc_array(num_samps, sizeof(u32), GFP_ATOMIC);
+	if (data_buf == NULL)
+		return;
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	for (t = 0; t < num_samps; t++)
+		data_buf[t] = ((((unsigned int)tone_buf[t].i) & 0x3ff) << 10) |
+			      (((unsigned int)tone_buf[t].q) & 0x3ff);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SAMPLEPLAY, num_samps, 0, 32,
+				 data_buf);
+
+	kfree(data_buf);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static u16
+wlc_phy_gen_load_samples_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val,
+			      u8 dac_test_mode)
+{
+	u8 phy_bw, is_phybw40;
+	u16 num_samps, t, spur;
+	s32 theta = 0, rot = 0;
+	u32 tbl_len;
+	struct cordic_iq *tone_buf = NULL;
+
+	is_phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+	phy_bw = (is_phybw40 == 1) ? 40 : 20;
+	tbl_len = (phy_bw << 3);
+
+	if (dac_test_mode == 1) {
+		spur = read_phy_reg(pi, 0x01);
+		spur = (spur >> 15) & 1;
+		phy_bw = (spur == 1) ? 82 : 80;
+		phy_bw = (is_phybw40 == 1) ? (phy_bw << 1) : phy_bw;
+
+		tbl_len = (phy_bw << 1);
+	}
+
+	tone_buf = kmalloc_array(tbl_len, sizeof(struct cordic_iq),
+				 GFP_ATOMIC);
+	if (tone_buf == NULL)
+		return 0;
+
+	num_samps = (u16) tbl_len;
+	rot = ((f_kHz * 36) / phy_bw) / 100;
+	theta = 0;
+
+	for (t = 0; t < num_samps; t++) {
+
+		tone_buf[t] = cordic_calc_iq(theta);
+
+		theta += rot;
+
+		tone_buf[t].q = (s32) FLOAT(tone_buf[t].q * max_val);
+		tone_buf[t].i = (s32) FLOAT(tone_buf[t].i * max_val);
+	}
+
+	wlc_phy_loadsampletable_nphy(pi, tone_buf, num_samps);
+
+	kfree(tone_buf);
+
+	return num_samps;
+}
+
+static void
+wlc_phy_runsamples_nphy(struct brcms_phy *pi, u16 num_samps, u16 loops,
+			u16 wait, u8 iqmode, u8 dac_test_mode,
+			bool modify_bbmult)
+{
+	u16 bb_mult;
+	u8 phy_bw, sample_cmd;
+	u16 orig_RfseqCoreActv;
+	u16 lpf_bw_ctl_override3, lpf_bw_ctl_override4, lpf_bw_ctl_miscreg3,
+	    lpf_bw_ctl_miscreg4;
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	phy_bw = 20;
+	if (CHSPEC_IS40(pi->radio_chanspec))
+		phy_bw = 40;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		lpf_bw_ctl_override3 = read_phy_reg(pi, 0x342) & (0x1 << 7);
+		lpf_bw_ctl_override4 = read_phy_reg(pi, 0x343) & (0x1 << 7);
+		if (lpf_bw_ctl_override3 | lpf_bw_ctl_override4) {
+			lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) &
+					      (0x7 << 8);
+			lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) &
+					      (0x7 << 8);
+		} else {
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi,
+				(0x1 << 7),
+				wlc_phy_read_lpf_bw_ctl_nphy
+					(pi,
+					0), 0, 0,
+				NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+			pi->nphy_sample_play_lpf_bw_ctl_ovr = true;
+
+			lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) &
+					      (0x7 << 8);
+			lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) &
+					      (0x7 << 8);
+		}
+	}
+
+	if ((pi->nphy_bb_mult_save & BB_MULT_VALID_MASK) == 0) {
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16,
+					&bb_mult);
+		pi->nphy_bb_mult_save =
+			BB_MULT_VALID_MASK | (bb_mult & BB_MULT_MASK);
+	}
+
+	if (modify_bbmult) {
+		bb_mult = (phy_bw == 20) ? 100 : 71;
+		bb_mult = (bb_mult << 8) + bb_mult;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16,
+					 &bb_mult);
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+	write_phy_reg(pi, 0xc6, num_samps - 1);
+
+	if (loops != 0xffff)
+		write_phy_reg(pi, 0xc4, loops - 1);
+	else
+		write_phy_reg(pi, 0xc4, loops);
+
+	write_phy_reg(pi, 0xc5, wait);
+
+	orig_RfseqCoreActv = read_phy_reg(pi, 0xa1);
+	or_phy_reg(pi, 0xa1, NPHY_RfseqMode_CoreActv_override);
+	if (iqmode) {
+
+		and_phy_reg(pi, 0xc2, 0x7FFF);
+
+		or_phy_reg(pi, 0xc2, 0x8000);
+	} else {
+
+		sample_cmd = (dac_test_mode == 1) ? 0x5 : 0x1;
+		write_phy_reg(pi, 0xc3, sample_cmd);
+	}
+
+	SPINWAIT(((read_phy_reg(pi, 0xa4) & 0x1) == 1), 1000);
+
+	write_phy_reg(pi, 0xa1, orig_RfseqCoreActv);
+}
+
+int
+wlc_phy_tx_tone_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val,
+		     u8 iqmode, u8 dac_test_mode, bool modify_bbmult)
+{
+	u16 num_samps;
+	u16 loops = 0xffff;
+	u16 wait = 0;
+
+	num_samps = wlc_phy_gen_load_samples_nphy(pi, f_kHz, max_val,
+						  dac_test_mode);
+	if (num_samps == 0)
+		return -EBADE;
+
+	wlc_phy_runsamples_nphy(pi, num_samps, loops, wait, iqmode,
+				dac_test_mode, modify_bbmult);
+
+	return 0;
+}
+
+void wlc_phy_stopplayback_nphy(struct brcms_phy *pi)
+{
+	u16 playback_status;
+	u16 bb_mult;
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	playback_status = read_phy_reg(pi, 0xc7);
+	if (playback_status & 0x1)
+		or_phy_reg(pi, 0xc3, NPHY_sampleCmd_STOP);
+	else if (playback_status & 0x2)
+		and_phy_reg(pi, 0xc2,
+			    (u16) ~NPHY_iqloCalCmdGctl_IQLO_CAL_EN);
+
+	and_phy_reg(pi, 0xc3, (u16) ~(0x1 << 2));
+
+	if ((pi->nphy_bb_mult_save & BB_MULT_VALID_MASK) != 0) {
+
+		bb_mult = pi->nphy_bb_mult_save & BB_MULT_MASK;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16,
+					 &bb_mult);
+
+		pi->nphy_bb_mult_save = 0;
+	}
+
+	if (NREV_IS(pi->pubpi.phy_rev, 7) || NREV_GE(pi->pubpi.phy_rev, 8)) {
+		if (pi->nphy_sample_play_lpf_bw_ctl_ovr) {
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi,
+				(0x1 << 7),
+				0, 0, 1,
+				NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			pi->nphy_sample_play_lpf_bw_ctl_ovr = false;
+		}
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static u32 *brcms_phy_get_tx_pwrctrl_tbl(struct brcms_phy *pi)
+{
+	u32 *tx_pwrctrl_tbl = NULL;
+	uint phyrev = pi->pubpi.phy_rev;
+
+	if (PHY_IPA(pi)) {
+		tx_pwrctrl_tbl =
+			wlc_phy_get_ipa_gaintbl_nphy(pi);
+	} else {
+		if (CHSPEC_IS5G(pi->radio_chanspec)) {
+			if (NREV_IS(phyrev, 3))
+				tx_pwrctrl_tbl = nphy_tpc_5GHz_txgain_rev3;
+			else if (NREV_IS(phyrev, 4))
+				tx_pwrctrl_tbl =
+					(pi->srom_fem5g.extpagain == 3) ?
+					nphy_tpc_5GHz_txgain_HiPwrEPA :
+					nphy_tpc_5GHz_txgain_rev4;
+			else
+				tx_pwrctrl_tbl = nphy_tpc_5GHz_txgain_rev5;
+		} else {
+			if (NREV_GE(phyrev, 7)) {
+				if (pi->pubpi.radiorev == 3)
+					tx_pwrctrl_tbl =
+						nphy_tpc_txgain_epa_2057rev3;
+				else if (pi->pubpi.radiorev == 5)
+					tx_pwrctrl_tbl =
+						nphy_tpc_txgain_epa_2057rev5;
+			} else {
+				if (NREV_GE(phyrev, 5) &&
+				   (pi->srom_fem2g.extpagain ==	3))
+					tx_pwrctrl_tbl =
+						nphy_tpc_txgain_HiPwrEPA;
+				else
+					tx_pwrctrl_tbl =
+						nphy_tpc_txgain_rev3;
+			}
+		}
+	}
+	return tx_pwrctrl_tbl;
+}
+
+struct nphy_txgains wlc_phy_get_tx_gain_nphy(struct brcms_phy *pi)
+{
+	u16 base_idx[2], curr_gain[2];
+	u8 core_no;
+	struct nphy_txgains target_gain;
+	u32 *tx_pwrctrl_tbl = NULL;
+
+	if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) {
+		if (pi->phyhang_avoid)
+			wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+					curr_gain);
+
+		if (pi->phyhang_avoid)
+			wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+		for (core_no = 0; core_no < 2; core_no++) {
+			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+				target_gain.ipa[core_no] =
+					curr_gain[core_no] & 0x0007;
+				target_gain.pad[core_no] =
+					((curr_gain[core_no] & 0x00F8) >> 3);
+				target_gain.pga[core_no] =
+					((curr_gain[core_no] & 0x0F00) >> 8);
+				target_gain.txgm[core_no] =
+					((curr_gain[core_no] & 0x7000) >> 12);
+				target_gain.txlpf[core_no] =
+					((curr_gain[core_no] & 0x8000) >> 15);
+			} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				target_gain.ipa[core_no] =
+					curr_gain[core_no] & 0x000F;
+				target_gain.pad[core_no] =
+					((curr_gain[core_no] & 0x00F0) >> 4);
+				target_gain.pga[core_no] =
+					((curr_gain[core_no] & 0x0F00) >> 8);
+				target_gain.txgm[core_no] =
+					((curr_gain[core_no] & 0x7000) >> 12);
+			} else {
+				target_gain.ipa[core_no] =
+					curr_gain[core_no] & 0x0003;
+				target_gain.pad[core_no] =
+					((curr_gain[core_no] & 0x000C) >> 2);
+				target_gain.pga[core_no] =
+					((curr_gain[core_no] & 0x0070) >> 4);
+				target_gain.txgm[core_no] =
+					((curr_gain[core_no] & 0x0380) >> 7);
+			}
+		}
+	} else {
+		uint phyrev = pi->pubpi.phy_rev;
+
+		base_idx[0] = (read_phy_reg(pi, 0x1ed) >> 8) & 0x7f;
+		base_idx[1] = (read_phy_reg(pi, 0x1ee) >> 8) & 0x7f;
+		for (core_no = 0; core_no < 2; core_no++) {
+			if (NREV_GE(phyrev, 3)) {
+				tx_pwrctrl_tbl =
+					brcms_phy_get_tx_pwrctrl_tbl(pi);
+				if (NREV_GE(phyrev, 7)) {
+					target_gain.ipa[core_no] =
+						(tx_pwrctrl_tbl
+						 [base_idx[core_no]]
+						 >> 16) & 0x7;
+					target_gain.pad[core_no] =
+						(tx_pwrctrl_tbl
+						 [base_idx[core_no]]
+						 >> 19) & 0x1f;
+					target_gain.pga[core_no] =
+						(tx_pwrctrl_tbl
+						 [base_idx[core_no]]
+						 >> 24) & 0xf;
+					target_gain.txgm[core_no] =
+						(tx_pwrctrl_tbl
+						 [base_idx[core_no]]
+						 >> 28) & 0x7;
+					target_gain.txlpf[core_no] =
+						(tx_pwrctrl_tbl
+						 [base_idx[core_no]]
+						 >> 31) & 0x1;
+				} else {
+					target_gain.ipa[core_no] =
+						(tx_pwrctrl_tbl
+						 [base_idx[core_no]]
+						 >> 16) & 0xf;
+					target_gain.pad[core_no] =
+						(tx_pwrctrl_tbl
+						 [base_idx[core_no]]
+						 >> 20) & 0xf;
+					target_gain.pga[core_no] =
+						(tx_pwrctrl_tbl
+						 [base_idx[core_no]]
+						 >> 24) & 0xf;
+					target_gain.txgm[core_no] =
+						(tx_pwrctrl_tbl
+						[base_idx[core_no]]
+						 >> 28) & 0x7;
+				}
+			} else {
+				target_gain.ipa[core_no] =
+					(nphy_tpc_txgain[base_idx[core_no]] >>
+					 16) & 0x3;
+				target_gain.pad[core_no] =
+					(nphy_tpc_txgain[base_idx[core_no]] >>
+					 18) & 0x3;
+				target_gain.pga[core_no] =
+					(nphy_tpc_txgain[base_idx[core_no]] >>
+					 20) & 0x7;
+				target_gain.txgm[core_no] =
+					(nphy_tpc_txgain[base_idx[core_no]] >>
+					 23) & 0x7;
+			}
+		}
+	}
+
+	return target_gain;
+}
+
+static void
+wlc_phy_iqcal_gainparams_nphy(struct brcms_phy *pi, u16 core_no,
+			      struct nphy_txgains target_gain,
+			      struct nphy_iqcal_params *params)
+{
+	u8 k;
+	int idx;
+	u16 gain_index;
+	u8 band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7))
+			params->txlpf = target_gain.txlpf[core_no];
+
+		params->txgm = target_gain.txgm[core_no];
+		params->pga = target_gain.pga[core_no];
+		params->pad = target_gain.pad[core_no];
+		params->ipa = target_gain.ipa[core_no];
+		if (NREV_GE(pi->pubpi.phy_rev, 7))
+			params->cal_gain =
+				((params->txlpf << 15) | (params->txgm << 12) |
+				 (params->pga << 8) |
+				 (params->pad << 3) | (params->ipa));
+		else
+			params->cal_gain =
+				((params->txgm << 12) | (params->pga << 8) |
+				 (params->pad << 4) | (params->ipa));
+
+		params->ncorr[0] = 0x79;
+		params->ncorr[1] = 0x79;
+		params->ncorr[2] = 0x79;
+		params->ncorr[3] = 0x79;
+		params->ncorr[4] = 0x79;
+	} else {
+
+		gain_index = ((target_gain.pad[core_no] << 0) |
+			      (target_gain.pga[core_no] << 4) |
+			      (target_gain.txgm[core_no] << 8));
+
+		idx = -1;
+		for (k = 0; k < NPHY_IQCAL_NUMGAINS; k++) {
+			if (tbl_iqcal_gainparams_nphy[band_idx][k][0] ==
+			    gain_index) {
+				idx = k;
+				break;
+			}
+		}
+
+		params->txgm = tbl_iqcal_gainparams_nphy[band_idx][k][1];
+		params->pga = tbl_iqcal_gainparams_nphy[band_idx][k][2];
+		params->pad = tbl_iqcal_gainparams_nphy[band_idx][k][3];
+		params->cal_gain = ((params->txgm << 7) | (params->pga << 4) |
+				    (params->pad << 2));
+		params->ncorr[0] = tbl_iqcal_gainparams_nphy[band_idx][k][4];
+		params->ncorr[1] = tbl_iqcal_gainparams_nphy[band_idx][k][5];
+		params->ncorr[2] = tbl_iqcal_gainparams_nphy[band_idx][k][6];
+		params->ncorr[3] = tbl_iqcal_gainparams_nphy[band_idx][k][7];
+	}
+}
+
+static void wlc_phy_txcal_radio_setup_nphy(struct brcms_phy *pi)
+{
+	u16 jtag_core, core;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		for (core = 0; core <= 1; core++) {
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] =
+				READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+						TX_SSI_MASTER);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] =
+				READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+						IQCAL_VCM_HG);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] =
+				READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+						IQCAL_IDAC);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] =
+				READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+						TSSI_VCM);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] = 0;
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] =
+				READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+						TX_SSI_MUX);
+
+			if (pi->pubpi.radiorev != 5)
+				pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] =
+					READ_RADIO_REG3(pi, RADIO_2057, TX,
+							core,
+							TSSIA);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] =
+			       READ_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] =
+				READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+						TSSI_MISC1);
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TX_SSI_MASTER, 0x0a);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 IQCAL_VCM_HG, 0x43);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 IQCAL_IDAC, 0x55);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSI_VCM, 0x00);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSIG, 0x00);
+				if (pi->use_int_tx_iqlo_cal_nphy) {
+					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+							 core, TX_SSI_MUX, 0x4);
+					if (!(pi->
+					internal_tx_iqlo_cal_tapoff_intpa_nphy))
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TSSIA, 0x31);
+					else
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TSSIA, 0x21);
+				}
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSI_MISC1, 0x00);
+			} else {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TX_SSI_MASTER, 0x06);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 IQCAL_VCM_HG, 0x43);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 IQCAL_IDAC, 0x55);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSI_VCM, 0x00);
+
+				if (pi->pubpi.radiorev != 5)
+					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+							 core, TSSIA, 0x00);
+				if (pi->use_int_tx_iqlo_cal_nphy) {
+					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+							 core, TX_SSI_MUX,
+							 0x06);
+					if (!(pi->
+					internal_tx_iqlo_cal_tapoff_intpa_nphy))
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TSSIG, 0x31);
+					else
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TSSIG, 0x21);
+				}
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSI_MISC1, 0x00);
+			}
+		}
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+		for (core = 0; core <= 1; core++) {
+			jtag_core =
+				(core ==
+				 PHY_CORE_0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_TX_SSI_MASTER |
+					       jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_IQCAL_VCM_HG |
+					       jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_IQCAL_IDAC |
+					       jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] =
+				read_radio_reg(
+					pi,
+					RADIO_2056_TX_TSSI_VCM |
+					jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_TX_AMP_DET |
+					       jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_TX_SSI_MUX |
+					       jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_TSSIA | jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_TSSIG | jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_TSSI_MISC1 |
+					       jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 9] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_TSSI_MISC2 |
+					       jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 10] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_TSSI_MISC3 |
+					       jtag_core);
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				write_radio_reg(pi,
+						RADIO_2056_TX_TX_SSI_MASTER |
+						jtag_core, 0x0a);
+				write_radio_reg(pi,
+						RADIO_2056_TX_IQCAL_VCM_HG |
+						jtag_core, 0x40);
+				write_radio_reg(pi,
+						RADIO_2056_TX_IQCAL_IDAC |
+						jtag_core, 0x55);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_VCM |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TX_AMP_DET |
+						jtag_core, 0x00);
+
+				if (PHY_IPA(pi)) {
+					write_radio_reg(
+						pi,
+						RADIO_2056_TX_TX_SSI_MUX
+						| jtag_core, 0x4);
+					write_radio_reg(pi,
+							RADIO_2056_TX_TSSIA |
+							jtag_core, 0x1);
+				} else {
+					write_radio_reg(
+						pi,
+						RADIO_2056_TX_TX_SSI_MUX
+						| jtag_core, 0x00);
+					write_radio_reg(pi,
+							RADIO_2056_TX_TSSIA |
+							jtag_core, 0x2f);
+				}
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSIG | jtag_core,
+						0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC1 |
+						jtag_core, 0x00);
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC2 |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC3 |
+						jtag_core, 0x00);
+			} else {
+				write_radio_reg(pi,
+						RADIO_2056_TX_TX_SSI_MASTER |
+						jtag_core, 0x06);
+				write_radio_reg(pi,
+						RADIO_2056_TX_IQCAL_VCM_HG |
+						jtag_core, 0x40);
+				write_radio_reg(pi,
+						RADIO_2056_TX_IQCAL_IDAC |
+						jtag_core, 0x55);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_VCM |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TX_AMP_DET |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSIA | jtag_core,
+						0x00);
+
+				if (PHY_IPA(pi)) {
+
+					write_radio_reg(
+						pi,
+						RADIO_2056_TX_TX_SSI_MUX
+						| jtag_core, 0x06);
+					if (NREV_LT(pi->pubpi.phy_rev, 5))
+						write_radio_reg(
+							pi,
+							RADIO_2056_TX_TSSIG
+							| jtag_core,
+							0x11);
+					else
+						write_radio_reg(
+							pi,
+							RADIO_2056_TX_TSSIG
+							| jtag_core,
+							0x1);
+				} else {
+					write_radio_reg(
+						pi,
+						RADIO_2056_TX_TX_SSI_MUX
+						| jtag_core, 0x00);
+					write_radio_reg(pi,
+							RADIO_2056_TX_TSSIG |
+							jtag_core, 0x20);
+				}
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC1 |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC2 |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC3 |
+						jtag_core, 0x00);
+			}
+		}
+	} else {
+
+		pi->tx_rx_cal_radio_saveregs[0] =
+			read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, 0x29);
+		pi->tx_rx_cal_radio_saveregs[1] =
+			read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, 0x54);
+
+		pi->tx_rx_cal_radio_saveregs[2] =
+			read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, 0x29);
+		pi->tx_rx_cal_radio_saveregs[3] =
+			read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, 0x54);
+
+		pi->tx_rx_cal_radio_saveregs[4] =
+			read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1);
+		pi->tx_rx_cal_radio_saveregs[5] =
+			read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2);
+
+		if ((read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand) ==
+		    0) {
+
+			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x04);
+			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x04);
+		} else {
+
+			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x20);
+			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x20);
+		}
+
+		if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+
+			or_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, 0x20);
+			or_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, 0x20);
+		} else {
+
+			and_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, 0xdf);
+			and_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, 0xdf);
+		}
+	}
+}
+
+static void wlc_phy_txcal_radio_cleanup_nphy(struct brcms_phy *pi)
+{
+	u16 jtag_core, core;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		for (core = 0; core <= 1; core++) {
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+					 TX_SSI_MASTER,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  0]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_VCM_HG,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  1]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_IDAC,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  2]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  3]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TX_SSI_MUX,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  5]);
+
+			if (pi->pubpi.radiorev != 5)
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSIA,
+						 pi->tx_rx_cal_radio_saveregs
+							     [(core * 11) + 6]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  7]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_MISC1,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  8]);
+		}
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		for (core = 0; core <= 1; core++) {
+			jtag_core = (core == PHY_CORE_0) ?
+				     RADIO_2056_TX0 : RADIO_2056_TX1;
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TX_SSI_MASTER | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 0]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_IQCAL_VCM_HG | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 1]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_IQCAL_IDAC | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 2]);
+
+			write_radio_reg(pi, RADIO_2056_TX_TSSI_VCM | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 3]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TX_AMP_DET | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 4]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TX_SSI_MUX | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 5]);
+
+			write_radio_reg(pi, RADIO_2056_TX_TSSIA | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 6]);
+
+			write_radio_reg(pi, RADIO_2056_TX_TSSIG | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 7]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TSSI_MISC1 | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 8]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TSSI_MISC2 | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 9]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TSSI_MISC3 | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 10]);
+		}
+	} else {
+
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1,
+				pi->tx_rx_cal_radio_saveregs[0]);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2,
+				pi->tx_rx_cal_radio_saveregs[1]);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1,
+				pi->tx_rx_cal_radio_saveregs[2]);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2,
+				pi->tx_rx_cal_radio_saveregs[3]);
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1,
+				pi->tx_rx_cal_radio_saveregs[4]);
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2,
+				pi->tx_rx_cal_radio_saveregs[5]);
+	}
+}
+
+static void wlc_phy_txcal_physetup_nphy(struct brcms_phy *pi)
+{
+	u16 val, mask;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa6);
+		pi->tx_rx_cal_phy_saveregs[1] = read_phy_reg(pi, 0xa7);
+
+		mask = ((0x3 << 8) | (0x3 << 10));
+		val = (0x2 << 8);
+		val |= (0x2 << 10);
+		mod_phy_reg(pi, 0xa6, mask, val);
+		mod_phy_reg(pi, 0xa7, mask, val);
+
+		val = read_phy_reg(pi, 0x8f);
+		pi->tx_rx_cal_phy_saveregs[2] = val;
+		val |= ((0x1 << 9) | (0x1 << 10));
+		write_phy_reg(pi, 0x8f, val);
+
+		val = read_phy_reg(pi, 0xa5);
+		pi->tx_rx_cal_phy_saveregs[3] = val;
+		val |= ((0x1 << 9) | (0x1 << 10));
+		write_phy_reg(pi, 0xa5, val);
+
+		pi->tx_rx_cal_phy_saveregs[4] = read_phy_reg(pi, 0x01);
+		mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16,
+					&val);
+		pi->tx_rx_cal_phy_saveregs[5] = val;
+		val = 0;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16,
+					 &val);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16,
+					&val);
+		pi->tx_rx_cal_phy_saveregs[6] = val;
+		val = 0;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16,
+					 &val);
+
+		pi->tx_rx_cal_phy_saveregs[7] = read_phy_reg(pi, 0x91);
+		pi->tx_rx_cal_phy_saveregs[8] = read_phy_reg(pi, 0x92);
+
+		if (!(pi->use_int_tx_iqlo_cal_nphy))
+			wlc_phy_rfctrlintc_override_nphy(
+				pi,
+				NPHY_RfctrlIntc_override_PA,
+				1,
+				RADIO_MIMO_CORESEL_CORE1
+				|
+				RADIO_MIMO_CORESEL_CORE2);
+		else
+			wlc_phy_rfctrlintc_override_nphy(
+				pi,
+				NPHY_RfctrlIntc_override_PA,
+				0,
+				RADIO_MIMO_CORESEL_CORE1
+				|
+				RADIO_MIMO_CORESEL_CORE2);
+
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x2, RADIO_MIMO_CORESEL_CORE1);
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x8, RADIO_MIMO_CORESEL_CORE2);
+
+		pi->tx_rx_cal_phy_saveregs[9] = read_phy_reg(pi, 0x297);
+		pi->tx_rx_cal_phy_saveregs[10] = read_phy_reg(pi, 0x29b);
+		mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (0) << 0);
+
+		mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (0) << 0);
+
+		if (NREV_IS(pi->pubpi.phy_rev, 7)
+		    || NREV_GE(pi->pubpi.phy_rev, 8))
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 7),
+				wlc_phy_read_lpf_bw_ctl_nphy
+					(pi,
+					0), 0, 0,
+				NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+		if (pi->use_int_tx_iqlo_cal_nphy
+		    && !(pi->internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
+
+			if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+
+				mod_radio_reg(pi, RADIO_2057_OVR_REG0, 1 << 4,
+					      1 << 4);
+
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					mod_radio_reg(
+						pi,
+						RADIO_2057_PAD2G_TUNE_PUS_CORE0,
+						1, 0);
+					mod_radio_reg(
+						pi,
+						RADIO_2057_PAD2G_TUNE_PUS_CORE1,
+						1, 0);
+				} else {
+					mod_radio_reg(
+					     pi,
+					     RADIO_2057_IPA5G_CASCOFFV_PU_CORE0,
+					     1, 0);
+					mod_radio_reg(
+					     pi,
+					     RADIO_2057_IPA5G_CASCOFFV_PU_CORE1,
+					     1, 0);
+				}
+			} else if (NREV_GE(pi->pubpi.phy_rev, 8)) {
+				wlc_phy_rfctrl_override_nphy_rev7(
+					pi,
+					(0x1 << 3), 0,
+					0x3, 0,
+					NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			}
+		}
+	} else {
+		pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa6);
+		pi->tx_rx_cal_phy_saveregs[1] = read_phy_reg(pi, 0xa7);
+
+		mask = ((0x3 << 12) | (0x3 << 14));
+		val = (0x2 << 12);
+		val |= (0x2 << 14);
+		mod_phy_reg(pi, 0xa6, mask, val);
+		mod_phy_reg(pi, 0xa7, mask, val);
+
+		val = read_phy_reg(pi, 0xa5);
+		pi->tx_rx_cal_phy_saveregs[2] = val;
+		val |= ((0x1 << 12) | (0x1 << 13));
+		write_phy_reg(pi, 0xa5, val);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16,
+					&val);
+		pi->tx_rx_cal_phy_saveregs[3] = val;
+		val |= 0x2000;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16,
+					 &val);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16,
+					&val);
+		pi->tx_rx_cal_phy_saveregs[4] = val;
+		val |= 0x2000;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16,
+					 &val);
+
+		pi->tx_rx_cal_phy_saveregs[5] = read_phy_reg(pi, 0x91);
+		pi->tx_rx_cal_phy_saveregs[6] = read_phy_reg(pi, 0x92);
+		val = CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120;
+		write_phy_reg(pi, 0x91, val);
+		write_phy_reg(pi, 0x92, val);
+	}
+}
+
+static void wlc_phy_txcal_phycleanup_nphy(struct brcms_phy *pi)
+{
+	u16 mask;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		write_phy_reg(pi, 0xa6, pi->tx_rx_cal_phy_saveregs[0]);
+		write_phy_reg(pi, 0xa7, pi->tx_rx_cal_phy_saveregs[1]);
+		write_phy_reg(pi, 0x8f, pi->tx_rx_cal_phy_saveregs[2]);
+		write_phy_reg(pi, 0xa5, pi->tx_rx_cal_phy_saveregs[3]);
+		write_phy_reg(pi, 0x01, pi->tx_rx_cal_phy_saveregs[4]);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16,
+					 &pi->tx_rx_cal_phy_saveregs[5]);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16,
+					 &pi->tx_rx_cal_phy_saveregs[6]);
+
+		write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[7]);
+		write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[8]);
+
+		write_phy_reg(pi, 0x297, pi->tx_rx_cal_phy_saveregs[9]);
+		write_phy_reg(pi, 0x29b, pi->tx_rx_cal_phy_saveregs[10]);
+
+		if (NREV_IS(pi->pubpi.phy_rev, 7)
+		    || NREV_GE(pi->pubpi.phy_rev, 8))
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 7), 0, 0,
+				1,
+				NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+		wlc_phy_resetcca_nphy(pi);
+
+		if (pi->use_int_tx_iqlo_cal_nphy
+		    && !(pi->internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
+
+			if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					mod_radio_reg(
+						pi,
+						RADIO_2057_PAD2G_TUNE_PUS_CORE0,
+						1, 1);
+					mod_radio_reg(
+						pi,
+						RADIO_2057_PAD2G_TUNE_PUS_CORE1,
+						1, 1);
+				} else {
+					mod_radio_reg(
+					     pi,
+					     RADIO_2057_IPA5G_CASCOFFV_PU_CORE0,
+					     1, 1);
+					mod_radio_reg(
+					     pi,
+					     RADIO_2057_IPA5G_CASCOFFV_PU_CORE1,
+					     1, 1);
+				}
+
+				mod_radio_reg(pi, RADIO_2057_OVR_REG0, 1 << 4,
+					      0);
+			} else if (NREV_GE(pi->pubpi.phy_rev, 8)) {
+				wlc_phy_rfctrl_override_nphy_rev7(
+					pi,
+					(0x1 << 3), 0,
+					0x3, 1,
+					NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			}
+		}
+	} else {
+		mask = ((0x3 << 12) | (0x3 << 14));
+		mod_phy_reg(pi, 0xa6, mask, pi->tx_rx_cal_phy_saveregs[0]);
+		mod_phy_reg(pi, 0xa7, mask, pi->tx_rx_cal_phy_saveregs[1]);
+		write_phy_reg(pi, 0xa5, pi->tx_rx_cal_phy_saveregs[2]);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16,
+					 &pi->tx_rx_cal_phy_saveregs[3]);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16,
+					 &pi->tx_rx_cal_phy_saveregs[4]);
+
+		write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[5]);
+		write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[6]);
+	}
+}
+
+void
+wlc_phy_est_tonepwr_nphy(struct brcms_phy *pi, s32 *qdBm_pwrbuf, u8 num_samps)
+{
+	u16 tssi_reg;
+	s32 temp, pwrindex[2];
+	s32 idle_tssi[2];
+	s32 rssi_buf[4];
+	s32 tssival[2];
+	u8 tssi_type;
+
+	tssi_reg = read_phy_reg(pi, 0x1e9);
+
+	temp = (s32) (tssi_reg & 0x3f);
+	idle_tssi[0] = (temp <= 31) ? temp : (temp - 64);
+
+	temp = (s32) ((tssi_reg >> 8) & 0x3f);
+	idle_tssi[1] = (temp <= 31) ? temp : (temp - 64);
+
+	tssi_type =
+		CHSPEC_IS5G(pi->radio_chanspec) ?
+		(u8)NPHY_RSSI_SEL_TSSI_5G : (u8)NPHY_RSSI_SEL_TSSI_2G;
+
+	wlc_phy_poll_rssi_nphy(pi, tssi_type, rssi_buf, num_samps);
+
+	tssival[0] = rssi_buf[0] / ((s32) num_samps);
+	tssival[1] = rssi_buf[2] / ((s32) num_samps);
+
+	pwrindex[0] = idle_tssi[0] - tssival[0] + 64;
+	pwrindex[1] = idle_tssi[1] - tssival[1] + 64;
+
+	if (pwrindex[0] < 0)
+		pwrindex[0] = 0;
+	else if (pwrindex[0] > 63)
+		pwrindex[0] = 63;
+
+	if (pwrindex[1] < 0)
+		pwrindex[1] = 0;
+	else if (pwrindex[1] > 63)
+		pwrindex[1] = 63;
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 1,
+				(u32) pwrindex[0], 32, &qdBm_pwrbuf[0]);
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 1,
+				(u32) pwrindex[1], 32, &qdBm_pwrbuf[1]);
+}
+
+static void wlc_phy_update_txcal_ladder_nphy(struct brcms_phy *pi, u16 core)
+{
+	int index;
+	u32 bbmult_scale;
+	u16 bbmult;
+	u16 tblentry;
+
+	static const struct nphy_txiqcal_ladder ladder_lo[] = {
+		{3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0},
+		{25, 0}, {25, 1}, {25, 2}, {25, 3}, {25, 4}, {25, 5},
+		{25, 6}, {25, 7}, {35, 7}, {50, 7}, {71, 7}, {100, 7}
+	};
+
+	static const struct nphy_txiqcal_ladder ladder_iq[] = {
+		{3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0},
+		{25, 0}, {35, 0}, {50, 0}, {71, 0}, {100, 0}, {100, 1},
+		{100, 2}, {100, 3}, {100, 4}, {100, 5}, {100, 6}, {100, 7}
+	};
+
+	bbmult = (core == PHY_CORE_0) ?
+		 ((pi->nphy_txcal_bbmult >> 8) & 0xff) :
+		 (pi->nphy_txcal_bbmult & 0xff);
+
+	for (index = 0; index < 18; index++) {
+		bbmult_scale = ladder_lo[index].percent * bbmult;
+		bbmult_scale /= 100;
+
+		tblentry =
+			((bbmult_scale & 0xff) << 8) | ladder_lo[index].g_env;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index, 16,
+					 &tblentry);
+
+		bbmult_scale = ladder_iq[index].percent * bbmult;
+		bbmult_scale /= 100;
+
+		tblentry =
+			((bbmult_scale & 0xff) << 8) | ladder_iq[index].g_env;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index + 32,
+					 16, &tblentry);
+	}
+}
+
+static u8 wlc_phy_txpwr_idx_cur_get_nphy(struct brcms_phy *pi, u8 core)
+{
+	u16 tmp;
+	tmp = read_phy_reg(pi, ((core == PHY_CORE_0) ? 0x1ed : 0x1ee));
+
+	tmp = (tmp & (0x7f << 8)) >> 8;
+	return (u8) tmp;
+}
+
+static void
+wlc_phy_txpwr_idx_cur_set_nphy(struct brcms_phy *pi, u8 idx0, u8 idx1)
+{
+	mod_phy_reg(pi, 0x1e7, (0x7f << 0), idx0);
+
+	if (NREV_GT(pi->pubpi.phy_rev, 1))
+		mod_phy_reg(pi, 0x222, (0xff << 0), idx1);
+}
+
+static u16 wlc_phy_ipa_get_bbmult_nphy(struct brcms_phy *pi)
+{
+	u16 m0m1;
+
+	wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1);
+
+	return m0m1;
+}
+
+static void wlc_phy_ipa_set_bbmult_nphy(struct brcms_phy *pi, u8 m0, u8 m1)
+{
+	u16 m0m1 = (u16) ((m0 << 8) | m1);
+
+	wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m0m1);
+	wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &m0m1);
+}
+
+static void
+wlc_phy_papd_cal_setup_nphy(struct brcms_phy *pi,
+			    struct nphy_papd_restore_state *state, u8 core)
+{
+	s32 tone_freq;
+	u8 off_core;
+	u16 mixgain = 0;
+
+	off_core = core ^ 0x1;
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		if (NREV_IS(pi->pubpi.phy_rev, 7)
+		    || NREV_GE(pi->pubpi.phy_rev, 8))
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 7),
+				wlc_phy_read_lpf_bw_ctl_nphy
+					(pi,
+					0), 0, 0,
+				NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			if (pi->pubpi.radiorev == 5)
+				mixgain = (core == 0) ? 0x20 : 0x00;
+			else if ((pi->pubpi.radiorev == 7)
+				 || (pi->pubpi.radiorev == 8))
+				mixgain = 0x00;
+			else if ((pi->pubpi.radiorev <= 4)
+				 || (pi->pubpi.radiorev == 6))
+				mixgain = 0x00;
+		} else {
+			if ((pi->pubpi.radiorev == 4) ||
+			    (pi->pubpi.radiorev == 6))
+				mixgain = 0x50;
+			else if ((pi->pubpi.radiorev == 3)
+				 || (pi->pubpi.radiorev == 7)
+				 || (pi->pubpi.radiorev == 8))
+				mixgain = 0x0;
+		}
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11),
+						  mixgain, (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+
+		wlc_phy_rfctrl_override_1tomany_nphy(
+			pi,
+			NPHY_REV7_RfctrlOverride_cmd_tx_pu,
+			1, (1 << core), 0);
+		wlc_phy_rfctrl_override_1tomany_nphy(
+			pi,
+			NPHY_REV7_RfctrlOverride_cmd_tx_pu,
+			0, (1 << off_core), 0);
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+						  0, 0x3, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
+						  0, (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+		state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ?
+						    0xa6 : 0xa7);
+		state->afeoverride[core] =
+			read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5);
+		state->afectrl[off_core] =
+			read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa7 : 0xa6);
+		state->afeoverride[off_core] =
+			read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa5 : 0x8f);
+
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7),
+			    (0x1 << 2), 0);
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
+				 0xa5), (0x1 << 2), (0x1 << 2));
+
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa7 : 0xa6),
+			    (0x1 << 2), (0x1 << 2));
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa5 :
+				 0x8f), (0x1 << 2), (0x1 << 2));
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			state->pwrup[core] =
+				READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+						TXRXCOUPLE_2G_PWRUP);
+			state->atten[core] =
+				READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+						TXRXCOUPLE_2G_ATTEN);
+			state->pwrup[off_core] =
+				READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+						TXRXCOUPLE_2G_PWRUP);
+			state->atten[off_core] =
+				READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+						TXRXCOUPLE_2G_ATTEN);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+					 TXRXCOUPLE_2G_PWRUP, 0xc);
+
+			if ((pi->pubpi.radiorev == 3) ||
+			    (pi->pubpi.radiorev == 4) ||
+			    (pi->pubpi.radiorev == 6))
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_2G_ATTEN, 0xf0);
+			else if (pi->pubpi.radiorev == 5)
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_2G_ATTEN,
+						 (core == 0) ? 0xf7 : 0xf2);
+			else if ((pi->pubpi.radiorev == 7)
+				 || (pi->pubpi.radiorev == 8))
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_2G_ATTEN, 0xf0);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					 TXRXCOUPLE_2G_PWRUP, 0x0);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					 TXRXCOUPLE_2G_ATTEN, 0xff);
+		} else {
+			state->pwrup[core] =
+				READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+						TXRXCOUPLE_5G_PWRUP);
+			state->atten[core] =
+				READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+						TXRXCOUPLE_5G_ATTEN);
+			state->pwrup[off_core] =
+				READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+						TXRXCOUPLE_5G_PWRUP);
+			state->atten[off_core] =
+				READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+						TXRXCOUPLE_5G_ATTEN);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+					 TXRXCOUPLE_5G_PWRUP, 0xc);
+
+			if ((pi->pubpi.radiorev == 7)
+			    || (pi->pubpi.radiorev == 8))
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_5G_ATTEN, 0xf4);
+
+			else
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_5G_ATTEN, 0xf0);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					 TXRXCOUPLE_5G_PWRUP, 0x0);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					 TXRXCOUPLE_5G_ATTEN, 0xff);
+		}
+
+		tone_freq = 4000;
+
+		wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 13), (1) << 13);
+
+		mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (NPHY_PAPD_COMP_OFF) << 0);
+
+		mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 13), (0) << 13);
+
+	} else {
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 0);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0, 0);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 0);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 1, 0x3, 0);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0x3, 0);
+
+		state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ?
+						    0xa6 : 0xa7);
+		state->afeoverride[core] =
+			read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5);
+
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7),
+			    (0x1 << 0) | (0x1 << 1) | (0x1 << 2), 0);
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
+				 0xa5),
+			    (0x1 << 0) |
+			    (0x1 << 1) |
+			    (0x1 << 2), (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
+
+		state->vga_master[core] =
+			READ_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER);
+		WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER, 0x2b);
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			state->fbmix[core] =
+				READ_RADIO_REG2(pi, RADIO_2056, RX, core,
+						TXFBMIX_G);
+			state->intpa_master[core] =
+				READ_RADIO_REG2(pi, RADIO_2056, TX, core,
+						INTPAG_MASTER);
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_G,
+					 0x03);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAG_MASTER, 0x04);
+		} else {
+			state->fbmix[core] =
+				READ_RADIO_REG2(pi, RADIO_2056, RX, core,
+						TXFBMIX_A);
+			state->intpa_master[core] =
+				READ_RADIO_REG2(pi, RADIO_2056, TX, core,
+						INTPAA_MASTER);
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_A,
+					 0x03);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAA_MASTER, 0x04);
+
+		}
+
+		tone_freq = 4000;
+
+		wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (1) << 0);
+
+		mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (0) << 0);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0);
+	}
+}
+
+static void
+wlc_phy_papd_cal_cleanup_nphy(struct brcms_phy *pi,
+			      struct nphy_papd_restore_state *state)
+{
+	u8 core;
+
+	wlc_phy_stopplayback_nphy(pi);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_2G_PWRUP, 0);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_2G_ATTEN,
+						 state->atten[core]);
+			} else {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_5G_PWRUP, 0);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_5G_ATTEN,
+						 state->atten[core]);
+			}
+		}
+
+		if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6))
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 2),
+				1, 0x3, 0,
+				NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		else
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 2),
+				0, 0x3, 1,
+				NPHY_REV7_RFCTRLOVERRIDE_ID0);
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1),
+						  0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 1, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+			write_phy_reg(pi, (core == PHY_CORE_0) ?
+				      0xa6 : 0xa7, state->afectrl[core]);
+			write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f :
+				      0xa5, state->afeoverride[core]);
+		}
+
+		wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff,
+					    (state->mm & 0xff));
+
+		if (NREV_IS(pi->pubpi.phy_rev, 7)
+		    || NREV_GE(pi->pubpi.phy_rev, 8))
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi, (0x1 << 7), 0, 0,
+				1,
+				NPHY_REV7_RFCTRLOVERRIDE_ID1);
+	} else {
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 0x3, 1);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 1);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 0, 0x3, 1);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 0, 0x3, 1);
+
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER,
+					 state->vga_master[core]);
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				WRITE_RADIO_REG2(pi, RADIO_2056, RX, core,
+						 TXFBMIX_G, state->fbmix[core]);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_MASTER,
+						 state->intpa_master[core]);
+			} else {
+				WRITE_RADIO_REG2(pi, RADIO_2056, RX, core,
+						 TXFBMIX_A, state->fbmix[core]);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAA_MASTER,
+						 state->intpa_master[core]);
+			}
+
+			write_phy_reg(pi, (core == PHY_CORE_0) ?
+				      0xa6 : 0xa7, state->afectrl[core]);
+			write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f :
+				      0xa5, state->afeoverride[core]);
+		}
+
+		wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff,
+					    (state->mm & 0xff));
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 1);
+	}
+}
+
+static void
+wlc_phy_a1_nphy(struct brcms_phy *pi, u8 core, u32 winsz, u32 start,
+		u32 end)
+{
+	u32 *buf, *src, *dst, sz;
+
+	sz = end - start + 1;
+
+	buf = kmalloc(2 * sizeof(u32) * NPHY_PAPD_EPS_TBL_SIZE, GFP_ATOMIC);
+	if (NULL == buf)
+		return;
+
+	src = buf;
+	dst = buf + NPHY_PAPD_EPS_TBL_SIZE;
+
+	wlc_phy_table_read_nphy(pi,
+				(core ==
+				 PHY_CORE_0 ? NPHY_TBL_ID_EPSILONTBL0 :
+				 NPHY_TBL_ID_EPSILONTBL1),
+				NPHY_PAPD_EPS_TBL_SIZE, 0, 32, src);
+
+	do {
+		u32 phy_a1, phy_a2;
+		s32 phy_a3, phy_a4, phy_a5, phy_a6, phy_a7;
+
+		phy_a1 = end - min(end, (winsz >> 1));
+		phy_a2 = min_t(u32, NPHY_PAPD_EPS_TBL_SIZE - 1,
+			       end + (winsz >> 1));
+		phy_a3 = phy_a2 - phy_a1 + 1;
+		phy_a6 = 0;
+		phy_a7 = 0;
+
+		do {
+			wlc_phy_papd_decode_epsilon(src[phy_a2], &phy_a4,
+						    &phy_a5);
+			phy_a6 += phy_a4;
+			phy_a7 += phy_a5;
+		} while (phy_a2-- != phy_a1);
+
+		phy_a6 /= phy_a3;
+		phy_a7 /= phy_a3;
+		dst[end] = ((u32) phy_a7 << 13) | ((u32) phy_a6 & 0x1fff);
+	} while (end-- != start);
+
+	wlc_phy_table_write_nphy(pi,
+				 (core ==
+				  PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0 :
+				 NPHY_TBL_ID_EPSILONTBL1, sz, start, 32, dst);
+
+	kfree(buf);
+}
+
+static void
+wlc_phy_a2_nphy(struct brcms_phy *pi, struct nphy_ipa_txcalgains *txgains,
+		enum phy_cal_mode cal_mode, u8 core)
+{
+	u16 phy_a1, phy_a2, phy_a3;
+	u16 phy_a4, phy_a5;
+	bool phy_a6;
+	u8 phy_a7, m[2];
+	u32 phy_a8 = 0;
+	struct nphy_txgains phy_a9;
+
+	if (NREV_LT(pi->pubpi.phy_rev, 3))
+		return;
+
+	phy_a7 = (core == PHY_CORE_0) ? 1 : 0;
+
+	phy_a6 = ((cal_mode == CAL_GCTRL)
+		  || (cal_mode == CAL_SOFT)) ? true : false;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		phy_a9 = wlc_phy_get_tx_gain_nphy(pi);
+
+		if (CHSPEC_IS2G(pi->radio_chanspec))
+			phy_a5 = ((phy_a9.txlpf[core] << 15) |
+				  (phy_a9.txgm[core] << 12) |
+				  (phy_a9.pga[core] << 8) |
+				  (txgains->gains.pad[core] << 3) |
+				  (phy_a9.ipa[core]));
+		else
+			phy_a5 = ((phy_a9.txlpf[core] << 15) |
+				  (phy_a9.txgm[core] << 12) |
+				  (txgains->gains.pga[core] << 8) |
+				  (phy_a9.pad[core] << 3) | (phy_a9.ipa[core]));
+
+		wlc_phy_rfctrl_override_1tomany_nphy(
+			pi,
+			NPHY_REV7_RfctrlOverride_cmd_txgain,
+			phy_a5, (1 << core), 0);
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			if ((pi->pubpi.radiorev <= 4)
+			    || (pi->pubpi.radiorev == 6))
+				m[core] = (pi->bw == WL_CHANSPEC_BW_40) ?
+					  60 : 79;
+			else
+				m[core] = (pi->bw == WL_CHANSPEC_BW_40) ?
+					  45 : 64;
+		} else {
+			m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? 75 : 107;
+		}
+
+		m[phy_a7] = 0;
+		wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]);
+
+		phy_a2 = 63;
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			if ((pi->pubpi.radiorev == 4)
+			    || (pi->pubpi.radiorev == 6)) {
+				phy_a1 = 30;
+				phy_a3 = 30;
+			} else {
+				phy_a1 = 25;
+				phy_a3 = 25;
+			}
+		} else {
+			if ((pi->pubpi.radiorev == 5)
+			    || (pi->pubpi.radiorev == 7)
+			    || (pi->pubpi.radiorev == 8)) {
+				phy_a1 = 25;
+				phy_a3 = 25;
+			} else {
+				phy_a1 = 35;
+				phy_a3 = 35;
+			}
+		}
+
+		if (cal_mode == CAL_GCTRL) {
+			if ((pi->pubpi.radiorev == 5)
+			    && (CHSPEC_IS2G(pi->radio_chanspec)))
+				phy_a1 = 55;
+			else if (((pi->pubpi.radiorev == 7) &&
+				  (CHSPEC_IS2G(pi->radio_chanspec))) ||
+				 ((pi->pubpi.radiorev == 8) &&
+				  (CHSPEC_IS2G(pi->radio_chanspec))))
+				phy_a1 = 60;
+			else
+				phy_a1 = 63;
+
+		} else if ((cal_mode != CAL_FULL) && (cal_mode != CAL_SOFT)) {
+
+			phy_a1 = 35;
+			phy_a3 = 35;
+		}
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (1) << 0);
+
+		mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (0) << 0);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 13), (1) << 13);
+
+		mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 13), (0) << 13);
+
+		write_phy_reg(pi, 0x2a1, 0x80);
+		write_phy_reg(pi, 0x2a2, 0x100);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x7 << 4), (11) << 4);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x7 << 8), (11) << 8);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x7 << 0), (0x3) << 0);
+
+		write_phy_reg(pi, 0x2e5, 0x20);
+
+		mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0);
+
+		mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0);
+
+		mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8);
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+						  1, ((core == 0) ? 1 : 2), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+						  0, ((core == 0) ? 2 : 1), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+
+		write_phy_reg(pi, 0x2be, 1);
+		SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000);
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+						  0, 0x3, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+
+		wlc_phy_table_write_nphy(pi,
+					 (core ==
+					  PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0
+					 : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3,
+					 32, &phy_a8);
+
+		if (cal_mode != CAL_GCTRL) {
+			if (CHSPEC_IS5G(pi->radio_chanspec))
+				wlc_phy_a1_nphy(pi, core, 5, 0, 35);
+		}
+
+		wlc_phy_rfctrl_override_1tomany_nphy(
+			pi,
+			NPHY_REV7_RfctrlOverride_cmd_txgain,
+			phy_a5, (1 << core), 1);
+
+	} else {
+
+		if (txgains) {
+			if (txgains->useindex) {
+				phy_a4 = 15 - ((txgains->index) >> 3);
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					if (NREV_GE(pi->pubpi.phy_rev, 6) &&
+					    pi->sh->chip == BCMA_CHIP_ID_BCM47162) {
+						phy_a5 = 0x10f7 | (phy_a4 << 8);
+					} else if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+						phy_a5 = 0x00f7 | (phy_a4 << 8);
+					} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+						phy_a5 = 0x10f7 | (phy_a4 << 8);
+					} else {
+						phy_a5 = 0x50f7 | (phy_a4 << 8);
+					}
+				} else {
+					phy_a5 = 0x70f7 | (phy_a4 << 8);
+				}
+				wlc_phy_rfctrl_override_nphy(pi,
+							     (0x1 << 13),
+							     phy_a5,
+							     (1 << core), 0);
+			} else {
+				wlc_phy_rfctrl_override_nphy(pi,
+							     (0x1 << 13),
+							     0x5bf7,
+							     (1 << core), 0);
+			}
+		}
+
+		if (CHSPEC_IS2G(pi->radio_chanspec))
+			m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? 45 : 64;
+		else
+			m[core] = (pi->bw == WL_CHANSPEC_BW_40) ? 75 : 107;
+
+		m[phy_a7] = 0;
+		wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]);
+
+		phy_a2 = 63;
+
+		if (cal_mode == CAL_FULL) {
+			phy_a1 = 25;
+			phy_a3 = 25;
+		} else if (cal_mode == CAL_SOFT) {
+			phy_a1 = 25;
+			phy_a3 = 25;
+		} else if (cal_mode == CAL_GCTRL) {
+			phy_a1 = 63;
+			phy_a3 = 25;
+		} else {
+
+			phy_a1 = 25;
+			phy_a3 = 25;
+		}
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (1) << 0);
+
+		mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (0) << 0);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x1 << 13), (1) << 13);
+
+			mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x1 << 13), (0) << 13);
+
+			write_phy_reg(pi, 0x2a1, 0x20);
+			write_phy_reg(pi, 0x2a2, 0x60);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0xf << 4), (9) << 4);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0xf << 8), (9) << 8);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0xf << 0), (0x2) << 0);
+
+			write_phy_reg(pi, 0x2e5, 0x20);
+		} else {
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x1 << 11), (1) << 11);
+
+			mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x1 << 11), (0) << 11);
+
+			write_phy_reg(pi, 0x2a1, 0x80);
+			write_phy_reg(pi, 0x2a2, 0x600);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x7 << 4), (0) << 4);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x7 << 8), (0) << 8);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x7 << 0), (0x3) << 0);
+
+			mod_phy_reg(pi, 0x2a0, (0x3f << 8), (0x20) << 8);
+
+		}
+
+		mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0);
+
+		mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0);
+
+		mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0x3, 0);
+
+		write_phy_reg(pi, 0x2be, 1);
+		SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0);
+
+		wlc_phy_table_write_nphy(pi,
+					 (core ==
+					  PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0
+					 : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3,
+					 32, &phy_a8);
+
+		if (cal_mode != CAL_GCTRL)
+			wlc_phy_a1_nphy(pi, core, 5, 0, 40);
+	}
+}
+
+static u8 wlc_phy_a3_nphy(struct brcms_phy *pi, u8 start_gain, u8 core)
+{
+	int phy_a1;
+	int phy_a2;
+	bool phy_a3;
+	struct nphy_ipa_txcalgains phy_a4;
+	bool phy_a5 = false;
+	bool phy_a6 = true;
+	s32 phy_a7, phy_a8;
+	u32 phy_a9;
+	int phy_a10;
+	bool phy_a11 = false;
+	int phy_a12;
+	u8 phy_a13 = 0;
+	u8 phy_a14;
+	u8 *phy_a15 = NULL;
+
+	phy_a4.useindex = true;
+	phy_a12 = start_gain;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		phy_a2 = 20;
+		phy_a1 = 1;
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			if (pi->pubpi.radiorev == 5) {
+
+				phy_a15 = pad_gain_codes_used_2057rev5;
+				phy_a13 =
+					ARRAY_SIZE(pad_gain_codes_used_2057rev5) - 1;
+
+			} else if ((pi->pubpi.radiorev == 7)
+				   || (pi->pubpi.radiorev == 8)) {
+
+				phy_a15 = pad_gain_codes_used_2057rev7;
+				phy_a13 =
+					ARRAY_SIZE(pad_gain_codes_used_2057rev7) - 1;
+
+			} else {
+
+				phy_a15 = pad_all_gain_codes_2057;
+				phy_a13 = ARRAY_SIZE(pad_all_gain_codes_2057) -
+					  1;
+			}
+
+		} else {
+
+			phy_a15 = pga_all_gain_codes_2057;
+			phy_a13 = ARRAY_SIZE(pga_all_gain_codes_2057) - 1;
+		}
+
+		phy_a14 = 0;
+
+		for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) {
+			if (CHSPEC_IS2G(pi->radio_chanspec))
+				phy_a4.gains.pad[core] =
+					(u16) phy_a15[phy_a12];
+			else
+				phy_a4.gains.pga[core] =
+					(u16) phy_a15[phy_a12];
+
+			wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core);
+
+			wlc_phy_table_read_nphy(pi,
+						(core ==
+						 PHY_CORE_0 ?
+						 NPHY_TBL_ID_EPSILONTBL0 :
+						 NPHY_TBL_ID_EPSILONTBL1), 1,
+						63, 32, &phy_a9);
+
+			wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8);
+
+			phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) ||
+				  (phy_a8 == 4095) || (phy_a8 == -4096));
+
+			if (!phy_a6 && (phy_a3 != phy_a5)) {
+				if (!phy_a3)
+					phy_a12 -= (u8) phy_a1;
+
+				phy_a11 = true;
+				break;
+			}
+
+			if (phy_a3)
+				phy_a12 += (u8) phy_a1;
+			else
+				phy_a12 -= (u8) phy_a1;
+
+			if ((phy_a12 < phy_a14) || (phy_a12 > phy_a13)) {
+				if (phy_a12 < phy_a14)
+					phy_a12 = phy_a14;
+				else
+					phy_a12 = phy_a13;
+
+				phy_a11 = true;
+				break;
+			}
+
+			phy_a6 = false;
+			phy_a5 = phy_a3;
+		}
+
+	} else {
+		phy_a2 = 10;
+		phy_a1 = 8;
+		for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) {
+			phy_a4.index = (u8) phy_a12;
+			wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core);
+
+			wlc_phy_table_read_nphy(pi,
+						(core ==
+						 PHY_CORE_0 ?
+						 NPHY_TBL_ID_EPSILONTBL0 :
+						 NPHY_TBL_ID_EPSILONTBL1), 1,
+						63, 32, &phy_a9);
+
+			wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8);
+
+			phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) ||
+				  (phy_a8 == 4095) || (phy_a8 == -4096));
+
+			if (!phy_a6 && (phy_a3 != phy_a5)) {
+				if (!phy_a3)
+					phy_a12 -= (u8) phy_a1;
+
+				phy_a11 = true;
+				break;
+			}
+
+			if (phy_a3)
+				phy_a12 += (u8) phy_a1;
+			else
+				phy_a12 -= (u8) phy_a1;
+
+			if ((phy_a12 < 0) || (phy_a12 > 127)) {
+				if (phy_a12 < 0)
+					phy_a12 = 0;
+				else
+					phy_a12 = 127;
+
+				phy_a11 = true;
+				break;
+			}
+
+			phy_a6 = false;
+			phy_a5 = phy_a3;
+		}
+
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7))
+		return (u8) phy_a15[phy_a12];
+	else
+		return (u8) phy_a12;
+
+}
+
+static void wlc_phy_a4(struct brcms_phy *pi, bool full_cal)
+{
+	struct nphy_ipa_txcalgains phy_b1[2];
+	struct nphy_papd_restore_state phy_b2;
+	bool phy_b3;
+	u8 phy_b4;
+	u8 phy_b5;
+	s16 phy_b6, phy_b7, phy_b8;
+	u16 phy_b9;
+	s16 phy_b10, phy_b11, phy_b12;
+
+	phy_b11 = 0;
+	phy_b12 = 0;
+	phy_b7 = 0;
+	phy_b8 = 0;
+	phy_b6 = 0;
+
+	if (pi->nphy_papd_skip == 1)
+		return;
+
+	phy_b3 = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
+			MCTL_EN_MAC));
+	if (!phy_b3)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	pi->nphy_force_papd_cal = false;
+
+	for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++)
+		pi->nphy_papd_tx_gain_at_last_cal[phy_b5] =
+			wlc_phy_txpwr_idx_cur_get_nphy(pi, phy_b5);
+
+	pi->nphy_papd_last_cal = pi->sh->now;
+	pi->nphy_papd_recal_counter++;
+
+	phy_b4 = pi->nphy_txpwrctrl;
+	wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL0, 64, 0, 32,
+				 nphy_papd_scaltbl);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL1, 64, 0, 32,
+				 nphy_papd_scaltbl);
+
+	phy_b9 = read_phy_reg(pi, 0x01);
+	mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
+
+	for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
+		s32 i, val = 0;
+		for (i = 0; i < 64; i++)
+			wlc_phy_table_write_nphy(pi,
+						 ((phy_b5 ==
+						   PHY_CORE_0) ?
+						  NPHY_TBL_ID_EPSILONTBL0 :
+						  NPHY_TBL_ID_EPSILONTBL1), 1,
+						 i, 32, &val);
+	}
+
+	wlc_phy_ipa_restore_tx_digi_filts_nphy(pi);
+
+	phy_b2.mm = wlc_phy_ipa_get_bbmult_nphy(pi);
+	for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
+		wlc_phy_papd_cal_setup_nphy(pi, &phy_b2, phy_b5);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				if ((pi->pubpi.radiorev == 3)
+				    || (pi->pubpi.radiorev == 4)
+				    || (pi->pubpi.radiorev == 6)) {
+					pi->nphy_papd_cal_gain_index[phy_b5] =
+						23;
+				} else if (pi->pubpi.radiorev == 5) {
+					pi->nphy_papd_cal_gain_index[phy_b5] =
+						0;
+					pi->nphy_papd_cal_gain_index[phy_b5] =
+						wlc_phy_a3_nphy(
+							pi,
+							pi->
+							nphy_papd_cal_gain_index
+							[phy_b5],
+							phy_b5);
+
+				} else if ((pi->pubpi.radiorev == 7)
+					   || (pi->pubpi.radiorev == 8)) {
+
+					pi->nphy_papd_cal_gain_index[phy_b5] =
+						0;
+					pi->nphy_papd_cal_gain_index[phy_b5] =
+						wlc_phy_a3_nphy(
+							pi,
+							pi->
+							nphy_papd_cal_gain_index
+							[phy_b5],
+							phy_b5);
+
+				}
+
+				phy_b1[phy_b5].gains.pad[phy_b5] =
+					pi->nphy_papd_cal_gain_index[phy_b5];
+
+			} else {
+				pi->nphy_papd_cal_gain_index[phy_b5] = 0;
+				pi->nphy_papd_cal_gain_index[phy_b5] =
+					wlc_phy_a3_nphy(
+						pi,
+						pi->
+						nphy_papd_cal_gain_index
+						[phy_b5], phy_b5);
+				phy_b1[phy_b5].gains.pga[phy_b5] =
+					pi->nphy_papd_cal_gain_index[phy_b5];
+			}
+		} else {
+			phy_b1[phy_b5].useindex = true;
+			phy_b1[phy_b5].index = 16;
+			phy_b1[phy_b5].index =
+				wlc_phy_a3_nphy(pi, phy_b1[phy_b5].index,
+						phy_b5);
+
+			pi->nphy_papd_cal_gain_index[phy_b5] =
+				15 - ((phy_b1[phy_b5].index) >> 3);
+		}
+
+		switch (pi->nphy_papd_cal_type) {
+		case 0:
+			wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_FULL, phy_b5);
+			break;
+		case 1:
+			wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_SOFT, phy_b5);
+			break;
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7))
+			wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2);
+	}
+
+	if (NREV_LT(pi->pubpi.phy_rev, 7))
+		wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2);
+
+	for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
+		int eps_offset = 0;
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				if (pi->pubpi.radiorev == 3)
+					eps_offset = -2;
+				else if (pi->pubpi.radiorev == 5)
+					eps_offset = 3;
+				else
+					eps_offset = -1;
+			} else {
+				eps_offset = 2;
+			}
+
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				phy_b8 = phy_b1[phy_b5].gains.pad[phy_b5];
+				phy_b10 = 0;
+				if ((pi->pubpi.radiorev == 3) ||
+				    (pi->pubpi.radiorev == 4) ||
+				    (pi->pubpi.radiorev == 6)) {
+					phy_b12 = -(
+					    nphy_papd_padgain_dlt_2g_2057rev3n4
+							     [phy_b8] + 1) / 2;
+					phy_b10 = -1;
+				} else if (pi->pubpi.radiorev == 5) {
+					phy_b12 = -(
+					    nphy_papd_padgain_dlt_2g_2057rev5
+							     [phy_b8] + 1) / 2;
+				} else if ((pi->pubpi.radiorev == 7) ||
+					   (pi->pubpi.radiorev == 8)) {
+					phy_b12 = -(
+					    nphy_papd_padgain_dlt_2g_2057rev7
+							     [phy_b8] + 1) / 2;
+				}
+			} else {
+				phy_b7 = phy_b1[phy_b5].gains.pga[phy_b5];
+				if ((pi->pubpi.radiorev == 3) ||
+				    (pi->pubpi.radiorev == 4) ||
+				    (pi->pubpi.radiorev == 6))
+					phy_b11 =
+						-(nphy_papd_pgagain_dlt_5g_2057
+						  [phy_b7]
+						  + 1) / 2;
+				else if ((pi->pubpi.radiorev == 7)
+					 || (pi->pubpi.radiorev == 8))
+					phy_b11 = -(
+					      nphy_papd_pgagain_dlt_5g_2057rev7
+							     [phy_b7] + 1) / 2;
+
+				phy_b10 = -9;
+			}
+
+			if (CHSPEC_IS2G(pi->radio_chanspec))
+				phy_b6 =
+					-60 + 27 + eps_offset + phy_b12 +
+					phy_b10;
+			else
+				phy_b6 =
+					-60 + 27 + eps_offset + phy_b11 +
+					phy_b10;
+
+			mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 :
+				    0x29c, (0x1ff << 7), (phy_b6) << 7);
+
+			pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6;
+		} else {
+			if (NREV_LT(pi->pubpi.phy_rev, 5))
+				eps_offset = 4;
+			else
+				eps_offset = 2;
+
+			phy_b7 = 15 - ((phy_b1[phy_b5].index) >> 3);
+
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				phy_b11 =
+					-(nphy_papd_pga_gain_delta_ipa_2g[
+						  phy_b7] +
+					  1) / 2;
+				phy_b10 = 0;
+			} else {
+				phy_b11 =
+					-(nphy_papd_pga_gain_delta_ipa_5g[
+						  phy_b7] +
+					  1) / 2;
+				phy_b10 = -9;
+			}
+
+			phy_b6 = -60 + 27 + eps_offset + phy_b11 + phy_b10;
+
+			mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 :
+				    0x29c, (0x1ff << 7), (phy_b6) << 7);
+
+			pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6;
+		}
+	}
+
+	mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
+		    0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
+
+	mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
+		    0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+		mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 13), (0) << 13);
+
+		mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 13), (0) << 13);
+
+	} else {
+		mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 11), (0) << 11);
+
+		mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 11), (0) << 11);
+
+	}
+	pi->nphy_papdcomp = NPHY_PAPD_COMP_ON;
+
+	write_phy_reg(pi, 0x01, phy_b9);
+
+	wlc_phy_ipa_set_tx_digi_filts_nphy(pi);
+
+	wlc_phy_txpwrctrl_enable_nphy(pi, phy_b4);
+	if (phy_b4 == PHY_TPC_HW_OFF) {
+		wlc_phy_txpwr_index_nphy(pi, (1 << 0),
+					 (s8) (pi->nphy_txpwrindex[0].
+					       index_internal), false);
+		wlc_phy_txpwr_index_nphy(pi, (1 << 1),
+					 (s8) (pi->nphy_txpwrindex[1].
+					       index_internal), false);
+	}
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+	if (!phy_b3)
+		wlapi_enable_mac(pi->sh->physhim);
+}
+
+void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype)
+{
+	struct nphy_txgains target_gain;
+	u8 tx_pwr_ctrl_state;
+	bool fullcal = true;
+	bool restore_tx_gain = false;
+	bool mphase;
+
+	if (PHY_MUTED(pi))
+		return;
+
+	if (caltype == PHY_PERICAL_AUTO)
+		fullcal = (pi->radio_chanspec != pi->nphy_txiqlocal_chanspec);
+	else if (caltype == PHY_PERICAL_PARTIAL)
+		fullcal = false;
+
+	if (pi->cal_type_override != PHY_PERICAL_AUTO)
+		fullcal =
+			(pi->cal_type_override ==
+			 PHY_PERICAL_FULL) ? true : false;
+
+	if ((pi->mphase_cal_phase_id > MPHASE_CAL_STATE_INIT)) {
+		if (pi->nphy_txiqlocal_chanspec != pi->radio_chanspec)
+			wlc_phy_cal_perical_mphase_restart(pi);
+	}
+
+	if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_RXCAL))
+		wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000);
+
+	wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	wlc_phyreg_enter((struct brcms_phy_pub *) pi);
+
+	if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_IDLE) ||
+	    (pi->mphase_cal_phase_id == MPHASE_CAL_STATE_INIT)) {
+		pi->nphy_cal_orig_pwr_idx[0] =
+			(u8) ((read_phy_reg(pi, 0x1ed) >> 8) & 0x7f);
+		pi->nphy_cal_orig_pwr_idx[1] =
+			(u8) ((read_phy_reg(pi, 0x1ee) >> 8) & 0x7f);
+
+		if (pi->nphy_txpwrctrl != PHY_TPC_HW_OFF) {
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2,
+						0x110, 16,
+						pi->nphy_cal_orig_tx_gain);
+		} else {
+			pi->nphy_cal_orig_tx_gain[0] = 0;
+			pi->nphy_cal_orig_tx_gain[1] = 0;
+		}
+	}
+	target_gain = wlc_phy_get_tx_gain_nphy(pi);
+	tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
+	wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
+
+	if (pi->antsel_type == ANTSEL_2x3)
+		wlc_phy_antsel_init((struct brcms_phy_pub *) pi, true);
+
+	mphase = (pi->mphase_cal_phase_id != MPHASE_CAL_STATE_IDLE);
+	if (!mphase) {
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			wlc_phy_precal_txgain_nphy(pi);
+			pi->nphy_cal_target_gain = wlc_phy_get_tx_gain_nphy(pi);
+			restore_tx_gain = true;
+
+			target_gain = pi->nphy_cal_target_gain;
+		}
+		if (0 ==
+		    wlc_phy_cal_txiqlo_nphy(pi, target_gain, fullcal,
+					    mphase)) {
+			if (PHY_IPA(pi))
+				wlc_phy_a4(pi, true);
+
+			wlc_phyreg_exit((struct brcms_phy_pub *) pi);
+			wlapi_enable_mac(pi->sh->physhim);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION,
+					     10000);
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+			wlc_phyreg_enter((struct brcms_phy_pub *) pi);
+
+			if (0 == wlc_phy_cal_rxiq_nphy(pi, target_gain,
+					(pi->first_cal_after_assoc ||
+					(pi->cal_type_override ==
+					 PHY_PERICAL_FULL)) ? 2 : 0, false)) {
+				wlc_phy_savecal_nphy(pi);
+
+				wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
+
+				pi->nphy_perical_last = pi->sh->now;
+			}
+		}
+		if (caltype != PHY_PERICAL_AUTO)
+			wlc_phy_rssi_cal_nphy(pi);
+
+		if (pi->first_cal_after_assoc
+		    || (pi->cal_type_override == PHY_PERICAL_FULL)) {
+			pi->first_cal_after_assoc = false;
+			wlc_phy_txpwrctrl_idle_tssi_nphy(pi);
+			wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3))
+			wlc_phy_radio205x_vcocal_nphy(pi);
+	} else {
+		switch (pi->mphase_cal_phase_id) {
+		case MPHASE_CAL_STATE_INIT:
+			pi->nphy_perical_last = pi->sh->now;
+			pi->nphy_txiqlocal_chanspec = pi->radio_chanspec;
+
+			if (NREV_GE(pi->pubpi.phy_rev, 3))
+				wlc_phy_precal_txgain_nphy(pi);
+
+			pi->nphy_cal_target_gain = wlc_phy_get_tx_gain_nphy(pi);
+			pi->mphase_cal_phase_id++;
+			break;
+
+		case MPHASE_CAL_STATE_TXPHASE0:
+		case MPHASE_CAL_STATE_TXPHASE1:
+		case MPHASE_CAL_STATE_TXPHASE2:
+		case MPHASE_CAL_STATE_TXPHASE3:
+		case MPHASE_CAL_STATE_TXPHASE4:
+		case MPHASE_CAL_STATE_TXPHASE5:
+			if ((pi->radar_percal_mask & 0x10) != 0)
+				pi->nphy_rxcal_active = true;
+
+			if (wlc_phy_cal_txiqlo_nphy
+				    (pi, pi->nphy_cal_target_gain, fullcal,
+				    true) != 0) {
+
+				wlc_phy_cal_perical_mphase_reset(pi);
+				break;
+			}
+
+			if (NREV_LE(pi->pubpi.phy_rev, 2) &&
+			    (pi->mphase_cal_phase_id ==
+			     MPHASE_CAL_STATE_TXPHASE4))
+				pi->mphase_cal_phase_id += 2;
+			else
+				pi->mphase_cal_phase_id++;
+			break;
+
+		case MPHASE_CAL_STATE_PAPDCAL:
+			if ((pi->radar_percal_mask & 0x2) != 0)
+				pi->nphy_rxcal_active = true;
+
+			if (PHY_IPA(pi))
+				wlc_phy_a4(pi, true);
+
+			pi->mphase_cal_phase_id++;
+			break;
+
+		case MPHASE_CAL_STATE_RXCAL:
+			if ((pi->radar_percal_mask & 0x1) != 0)
+				pi->nphy_rxcal_active = true;
+			if (wlc_phy_cal_rxiq_nphy(pi, target_gain,
+						  (pi->first_cal_after_assoc ||
+						   (pi->cal_type_override ==
+						    PHY_PERICAL_FULL)) ? 2 : 0,
+						  false) == 0)
+				wlc_phy_savecal_nphy(pi);
+
+			pi->mphase_cal_phase_id++;
+			break;
+
+		case MPHASE_CAL_STATE_RSSICAL:
+			if ((pi->radar_percal_mask & 0x4) != 0)
+				pi->nphy_rxcal_active = true;
+			wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
+			wlc_phy_rssi_cal_nphy(pi);
+
+			if (NREV_GE(pi->pubpi.phy_rev, 3))
+				wlc_phy_radio205x_vcocal_nphy(pi);
+
+			restore_tx_gain = true;
+
+			if (pi->first_cal_after_assoc)
+				pi->mphase_cal_phase_id++;
+			else
+				wlc_phy_cal_perical_mphase_reset(pi);
+
+			break;
+
+		case MPHASE_CAL_STATE_IDLETSSI:
+			if ((pi->radar_percal_mask & 0x8) != 0)
+				pi->nphy_rxcal_active = true;
+
+			if (pi->first_cal_after_assoc) {
+				pi->first_cal_after_assoc = false;
+				wlc_phy_txpwrctrl_idle_tssi_nphy(pi);
+				wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
+			}
+
+			wlc_phy_cal_perical_mphase_reset(pi);
+			break;
+
+		default:
+			wlc_phy_cal_perical_mphase_reset(pi);
+			break;
+		}
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (restore_tx_gain) {
+			if (tx_pwr_ctrl_state != PHY_TPC_HW_OFF) {
+
+				wlc_phy_txpwr_index_nphy(pi, 1,
+							 pi->
+							 nphy_cal_orig_pwr_idx
+							 [0], false);
+				wlc_phy_txpwr_index_nphy(pi, 2,
+							 pi->
+							 nphy_cal_orig_pwr_idx
+							 [1], false);
+
+				pi->nphy_txpwrindex[0].index = -1;
+				pi->nphy_txpwrindex[1].index = -1;
+			} else {
+				wlc_phy_txpwr_index_nphy(pi, (1 << 0),
+							 (s8) (pi->
+							       nphy_txpwrindex
+							       [0].
+							       index_internal),
+							 false);
+				wlc_phy_txpwr_index_nphy(pi, (1 << 1),
+							 (s8) (pi->
+							       nphy_txpwrindex
+							       [1].
+							       index_internal),
+							 false);
+			}
+		}
+	}
+
+	wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
+	wlc_phyreg_exit((struct brcms_phy_pub *) pi);
+	wlapi_enable_mac(pi->sh->physhim);
+}
+
+int
+wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
+			bool fullcal, bool mphase)
+{
+	u16 val;
+	u16 tbl_buf[11];
+	u8 cal_cnt;
+	u16 cal_cmd;
+	u8 num_cals, max_cal_cmds;
+	u16 core_no, cal_type;
+	u16 diq_start = 0;
+	u8 phy_bw;
+	u16 max_val;
+	u16 tone_freq;
+	u16 gain_save[2];
+	u16 cal_gain[2];
+	struct nphy_iqcal_params cal_params[2];
+	u32 tbl_len;
+	const void *tbl_ptr;
+	bool ladder_updated[2];
+	u8 mphase_cal_lastphase = 0;
+	int bcmerror = 0;
+	bool phyhang_avoid_state = false;
+
+	static const u16 tbl_tx_iqlo_cal_loft_ladder_20[] = {
+		0x0300, 0x0500, 0x0700, 0x0900, 0x0d00, 0x1100, 0x1900, 0x1901,
+		0x1902,
+		0x1903, 0x1904, 0x1905, 0x1906, 0x1907, 0x2407, 0x3207, 0x4607,
+		0x6407
+	};
+
+	static const u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = {
+		0x0200, 0x0300, 0x0600, 0x0900, 0x0d00, 0x1100, 0x1900, 0x2400,
+		0x3200,
+		0x4600, 0x6400, 0x6401, 0x6402, 0x6403, 0x6404, 0x6405, 0x6406,
+		0x6407
+	};
+
+	static const u16 tbl_tx_iqlo_cal_loft_ladder_40[] = {
+		0x0200, 0x0300, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1201,
+		0x1202,
+		0x1203, 0x1204, 0x1205, 0x1206, 0x1207, 0x1907, 0x2307, 0x3207,
+		0x4707
+	};
+
+	static const u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = {
+		0x0100, 0x0200, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1900,
+		0x2300,
+		0x3200, 0x4700, 0x4701, 0x4702, 0x4703, 0x4704, 0x4705, 0x4706,
+		0x4707
+	};
+
+	static const u16 tbl_tx_iqlo_cal_startcoefs[] = {
+		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+		0x0000
+	};
+
+	static const u16 tbl_tx_iqlo_cal_cmds_fullcal[] = {
+		0x8123, 0x8264, 0x8086, 0x8245, 0x8056,
+		0x9123, 0x9264, 0x9086, 0x9245, 0x9056
+	};
+
+	static const u16 tbl_tx_iqlo_cal_cmds_recal[] = {
+		0x8101, 0x8253, 0x8053, 0x8234, 0x8034,
+		0x9101, 0x9253, 0x9053, 0x9234, 0x9034
+	};
+
+	static const u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[] = {
+		0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+		0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+		0x0000
+	};
+
+	static const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = {
+		0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234,
+		0x9434, 0x9334, 0x9084, 0x9267, 0x9056, 0x9234
+	};
+
+	static const u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = {
+		0x8423, 0x8323, 0x8073, 0x8256, 0x8045, 0x8223,
+		0x9423, 0x9323, 0x9073, 0x9256, 0x9045, 0x9223
+	};
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+		phyhang_avoid_state = pi->phyhang_avoid;
+		pi->phyhang_avoid = false;
+	}
+
+	if (CHSPEC_IS40(pi->radio_chanspec))
+		phy_bw = 40;
+	else
+		phy_bw = 20;
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save);
+
+	for (core_no = 0; core_no <= 1; core_no++) {
+		wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain,
+					      &cal_params[core_no]);
+		cal_gain[core_no] = cal_params[core_no].cal_gain;
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain);
+
+	wlc_phy_txcal_radio_setup_nphy(pi);
+
+	wlc_phy_txcal_physetup_nphy(pi);
+
+	ladder_updated[0] = ladder_updated[1] = false;
+	if (!(NREV_GE(pi->pubpi.phy_rev, 6) ||
+	      (NREV_IS(pi->pubpi.phy_rev, 5) && PHY_IPA(pi)
+	       && (CHSPEC_IS2G(pi->radio_chanspec))))) {
+
+		if (phy_bw == 40) {
+			tbl_ptr = tbl_tx_iqlo_cal_loft_ladder_40;
+			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_loft_ladder_40);
+		} else {
+			tbl_ptr = tbl_tx_iqlo_cal_loft_ladder_20;
+			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_loft_ladder_20);
+		}
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 0,
+					 16, tbl_ptr);
+
+		if (phy_bw == 40) {
+			tbl_ptr = tbl_tx_iqlo_cal_iqimb_ladder_40;
+			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_iqimb_ladder_40);
+		} else {
+			tbl_ptr = tbl_tx_iqlo_cal_iqimb_ladder_20;
+			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_iqimb_ladder_20);
+		}
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 32,
+					 16, tbl_ptr);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7))
+		write_phy_reg(pi, 0xc2, 0x8ad9);
+	else
+		write_phy_reg(pi, 0xc2, 0x8aa9);
+
+	max_val = 250;
+	tone_freq = (phy_bw == 20) ? 2500 : 5000;
+
+	if (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_TXPHASE0) {
+		wlc_phy_runsamples_nphy(pi, phy_bw * 8, 0xffff, 0, 1, 0, false);
+		bcmerror = 0;
+	} else {
+		bcmerror =
+			wlc_phy_tx_tone_nphy(pi, tone_freq, max_val, 1, 0,
+					     false);
+	}
+
+	if (bcmerror == 0) {
+
+		if (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_TXPHASE0) {
+			tbl_ptr = pi->mphase_txcal_bestcoeffs;
+			tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs);
+			if (NREV_LT(pi->pubpi.phy_rev, 3))
+				tbl_len -= 2;
+		} else {
+			if ((!fullcal) && (pi->nphy_txiqlocal_coeffsvalid)) {
+
+				tbl_ptr = pi->nphy_txiqlocal_bestc;
+				tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc);
+				if (NREV_LT(pi->pubpi.phy_rev, 3))
+					tbl_len -= 2;
+			} else {
+
+				fullcal = true;
+
+				if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+					tbl_ptr =
+					    tbl_tx_iqlo_cal_startcoefs_nphyrev3;
+					tbl_len = ARRAY_SIZE(
+					   tbl_tx_iqlo_cal_startcoefs_nphyrev3);
+				} else {
+					tbl_ptr = tbl_tx_iqlo_cal_startcoefs;
+					tbl_len = ARRAY_SIZE(
+						    tbl_tx_iqlo_cal_startcoefs);
+				}
+			}
+		}
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 64,
+					 16, tbl_ptr);
+
+		if (fullcal) {
+			max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
+				       ARRAY_SIZE(
+				tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3) :
+				       ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_fullcal);
+		} else {
+			max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
+				       ARRAY_SIZE(
+				tbl_tx_iqlo_cal_cmds_recal_nphyrev3) :
+				       ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_recal);
+		}
+
+		if (mphase) {
+			cal_cnt = pi->mphase_txcal_cmdidx;
+			if ((cal_cnt + pi->mphase_txcal_numcmds) < max_cal_cmds)
+				num_cals = cal_cnt + pi->mphase_txcal_numcmds;
+			else
+				num_cals = max_cal_cmds;
+		} else {
+			cal_cnt = 0;
+			num_cals = max_cal_cmds;
+		}
+
+		for (; cal_cnt < num_cals; cal_cnt++) {
+
+			if (fullcal) {
+				cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
+					  tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3
+					  [cal_cnt] :
+					  tbl_tx_iqlo_cal_cmds_fullcal[cal_cnt];
+			} else {
+				cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
+					  tbl_tx_iqlo_cal_cmds_recal_nphyrev3[
+					cal_cnt]
+					  : tbl_tx_iqlo_cal_cmds_recal[cal_cnt];
+			}
+
+			core_no = ((cal_cmd & 0x3000) >> 12);
+			cal_type = ((cal_cmd & 0x0F00) >> 8);
+
+			if (NREV_GE(pi->pubpi.phy_rev, 6) ||
+			    (NREV_IS(pi->pubpi.phy_rev, 5) &&
+			     PHY_IPA(pi)
+			     && (CHSPEC_IS2G(pi->radio_chanspec)))) {
+				if (!ladder_updated[core_no]) {
+					wlc_phy_update_txcal_ladder_nphy(
+						pi,
+						core_no);
+					ladder_updated[core_no] = true;
+				}
+			}
+
+			val =
+				(cal_params[core_no].
+				 ncorr[cal_type] << 8) | NPHY_N_GCTL;
+			write_phy_reg(pi, 0xc1, val);
+
+			if ((cal_type == 1) || (cal_type == 3)
+			    || (cal_type == 4)) {
+
+				wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+							1, 69 + core_no, 16,
+							tbl_buf);
+
+				diq_start = tbl_buf[0];
+
+				tbl_buf[0] = 0;
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_IQLOCAL, 1,
+							 69 + core_no, 16,
+							 tbl_buf);
+			}
+
+			write_phy_reg(pi, 0xc0, cal_cmd);
+
+			SPINWAIT(((read_phy_reg(pi, 0xc0) & 0xc000) != 0),
+				 20000);
+			if (WARN(read_phy_reg(pi, 0xc0) & 0xc000,
+				 "HW error: txiq calib"))
+				return -EIO;
+
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+						tbl_len, 96, 16, tbl_buf);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+						 tbl_len, 64, 16, tbl_buf);
+
+			if ((cal_type == 1) || (cal_type == 3)
+			    || (cal_type == 4)) {
+
+				tbl_buf[0] = diq_start;
+
+			}
+
+		}
+
+		if (mphase) {
+			pi->mphase_txcal_cmdidx = num_cals;
+			if (pi->mphase_txcal_cmdidx >= max_cal_cmds)
+				pi->mphase_txcal_cmdidx = 0;
+		}
+
+		mphase_cal_lastphase =
+			(NREV_LE(pi->pubpi.phy_rev, 2)) ?
+			MPHASE_CAL_STATE_TXPHASE4 : MPHASE_CAL_STATE_TXPHASE5;
+
+		if (!mphase
+		    || (pi->mphase_cal_phase_id == mphase_cal_lastphase)) {
+
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 96,
+						16, tbl_buf);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80,
+						 16, tbl_buf);
+
+			if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+
+				tbl_buf[0] = 0;
+				tbl_buf[1] = 0;
+				tbl_buf[2] = 0;
+				tbl_buf[3] = 0;
+
+			}
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88,
+						 16, tbl_buf);
+
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 101,
+						16, tbl_buf);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85,
+						 16, tbl_buf);
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93,
+						 16, tbl_buf);
+
+			tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc);
+			if (NREV_LT(pi->pubpi.phy_rev, 3))
+				tbl_len -= 2;
+
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+						tbl_len, 96, 16,
+						pi->nphy_txiqlocal_bestc);
+
+			pi->nphy_txiqlocal_coeffsvalid = true;
+			pi->nphy_txiqlocal_chanspec = pi->radio_chanspec;
+		} else {
+			tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs);
+			if (NREV_LT(pi->pubpi.phy_rev, 3))
+				tbl_len -= 2;
+
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+						tbl_len, 96, 16,
+						pi->mphase_txcal_bestcoeffs);
+		}
+
+		wlc_phy_stopplayback_nphy(pi);
+
+		write_phy_reg(pi, 0xc2, 0x0000);
+
+	}
+
+	wlc_phy_txcal_phycleanup_nphy(pi);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+				 gain_save);
+
+	wlc_phy_txcal_radio_cleanup_nphy(pi);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+		if (!mphase
+		    || (pi->mphase_cal_phase_id == mphase_cal_lastphase))
+			wlc_phy_tx_iq_war_nphy(pi);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 4))
+		pi->phyhang_avoid = phyhang_avoid_state;
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+	return bcmerror;
+}
+
+static void wlc_phy_reapply_txcal_coeffs_nphy(struct brcms_phy *pi)
+{
+	u16 tbl_buf[7];
+
+	if ((pi->nphy_txiqlocal_chanspec == pi->radio_chanspec) &&
+	    (pi->nphy_txiqlocal_coeffsvalid)) {
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+					ARRAY_SIZE(tbl_buf), 80, 16, tbl_buf);
+
+		if ((pi->nphy_txiqlocal_bestc[0] != tbl_buf[0]) ||
+		    (pi->nphy_txiqlocal_bestc[1] != tbl_buf[1]) ||
+		    (pi->nphy_txiqlocal_bestc[2] != tbl_buf[2]) ||
+		    (pi->nphy_txiqlocal_bestc[3] != tbl_buf[3])) {
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80,
+						 16, pi->nphy_txiqlocal_bestc);
+
+			tbl_buf[0] = 0;
+			tbl_buf[1] = 0;
+			tbl_buf[2] = 0;
+			tbl_buf[3] = 0;
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88,
+						 16, tbl_buf);
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85,
+						 16,
+						 &pi->nphy_txiqlocal_bestc[5]);
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93,
+						 16,
+						 &pi->nphy_txiqlocal_bestc[5]);
+		}
+	}
+}
+
+void
+wlc_phy_rx_iq_coeffs_nphy(struct brcms_phy *pi, u8 write,
+			  struct nphy_iq_comp *pcomp)
+{
+	if (write) {
+		write_phy_reg(pi, 0x9a, pcomp->a0);
+		write_phy_reg(pi, 0x9b, pcomp->b0);
+		write_phy_reg(pi, 0x9c, pcomp->a1);
+		write_phy_reg(pi, 0x9d, pcomp->b1);
+	} else {
+		pcomp->a0 = read_phy_reg(pi, 0x9a);
+		pcomp->b0 = read_phy_reg(pi, 0x9b);
+		pcomp->a1 = read_phy_reg(pi, 0x9c);
+		pcomp->b1 = read_phy_reg(pi, 0x9d);
+	}
+}
+
+void
+wlc_phy_rx_iq_est_nphy(struct brcms_phy *pi, struct phy_iq_est *est,
+		       u16 num_samps, u8 wait_time, u8 wait_for_crs)
+{
+	u8 core;
+
+	write_phy_reg(pi, 0x12b, num_samps);
+	mod_phy_reg(pi, 0x12a, (0xff << 0), (wait_time << 0));
+	mod_phy_reg(pi, 0x129, NPHY_IqestCmd_iqMode,
+		    (wait_for_crs) ? NPHY_IqestCmd_iqMode : 0);
+
+	mod_phy_reg(pi, 0x129, NPHY_IqestCmd_iqstart, NPHY_IqestCmd_iqstart);
+
+	SPINWAIT(((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) != 0),
+		 10000);
+	if (WARN(read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart,
+		 "HW error: rxiq est"))
+		return;
+
+	if ((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) == 0) {
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+			est[core].i_pwr =
+				(read_phy_reg(pi,
+					      NPHY_IqestipwrAccHi(core)) << 16)
+				| read_phy_reg(pi, NPHY_IqestipwrAccLo(core));
+			est[core].q_pwr =
+				(read_phy_reg(pi,
+					      NPHY_IqestqpwrAccHi(core)) << 16)
+				| read_phy_reg(pi, NPHY_IqestqpwrAccLo(core));
+			est[core].iq_prod =
+				(read_phy_reg(pi,
+					      NPHY_IqestIqAccHi(core)) << 16) |
+				read_phy_reg(pi, NPHY_IqestIqAccLo(core));
+		}
+	}
+}
+
+#define CAL_RETRY_CNT 2
+static void wlc_phy_calc_rx_iq_comp_nphy(struct brcms_phy *pi, u8 core_mask)
+{
+	u8 curr_core;
+	struct phy_iq_est est[PHY_CORE_MAX];
+	struct nphy_iq_comp old_comp, new_comp;
+	s32 iq = 0;
+	u32 ii = 0, qq = 0;
+	s16 iq_nbits, qq_nbits, brsh, arsh;
+	s32 a, b, temp;
+	int bcmerror = 0;
+	uint cal_retry = 0;
+
+	if (core_mask == 0x0)
+		return;
+
+	wlc_phy_rx_iq_coeffs_nphy(pi, 0, &old_comp);
+	new_comp.a0 = new_comp.b0 = new_comp.a1 = new_comp.b1 = 0x0;
+	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &new_comp);
+
+cal_try:
+	wlc_phy_rx_iq_est_nphy(pi, est, 0x4000, 32, 0);
+
+	new_comp = old_comp;
+
+	for (curr_core = 0; curr_core < pi->pubpi.phy_corenum; curr_core++) {
+
+		if ((curr_core == PHY_CORE_0) && (core_mask & 0x1)) {
+			iq = est[curr_core].iq_prod;
+			ii = est[curr_core].i_pwr;
+			qq = est[curr_core].q_pwr;
+		} else if ((curr_core == PHY_CORE_1) && (core_mask & 0x2)) {
+			iq = est[curr_core].iq_prod;
+			ii = est[curr_core].i_pwr;
+			qq = est[curr_core].q_pwr;
+		} else {
+			continue;
+		}
+
+		if ((ii + qq) < NPHY_MIN_RXIQ_PWR) {
+			bcmerror = -EBADE;
+			break;
+		}
+
+		iq_nbits = wlc_phy_nbits(iq);
+		qq_nbits = wlc_phy_nbits(qq);
+
+		arsh = 10 - (30 - iq_nbits);
+		if (arsh >= 0) {
+			a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
+			temp = (s32) (ii >> arsh);
+			if (temp == 0) {
+				bcmerror = -EBADE;
+				break;
+			}
+		} else {
+			a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
+			temp = (s32) (ii << -arsh);
+			if (temp == 0) {
+				bcmerror = -EBADE;
+				break;
+			}
+		}
+
+		a /= temp;
+
+		brsh = qq_nbits - 31 + 20;
+		if (brsh >= 0) {
+			b = (qq << (31 - qq_nbits));
+			temp = (s32) (ii >> brsh);
+			if (temp == 0) {
+				bcmerror = -EBADE;
+				break;
+			}
+		} else {
+			b = (qq << (31 - qq_nbits));
+			temp = (s32) (ii << -brsh);
+			if (temp == 0) {
+				bcmerror = -EBADE;
+				break;
+			}
+		}
+		b /= temp;
+		b -= a * a;
+		b = (s32) int_sqrt((unsigned long) b);
+		b -= (1 << 10);
+
+		if ((curr_core == PHY_CORE_0) && (core_mask & 0x1)) {
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				new_comp.a0 = (s16) a & 0x3ff;
+				new_comp.b0 = (s16) b & 0x3ff;
+			} else {
+
+				new_comp.a0 = (s16) b & 0x3ff;
+				new_comp.b0 = (s16) a & 0x3ff;
+			}
+		}
+		if ((curr_core == PHY_CORE_1) && (core_mask & 0x2)) {
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				new_comp.a1 = (s16) a & 0x3ff;
+				new_comp.b1 = (s16) b & 0x3ff;
+			} else {
+
+				new_comp.a1 = (s16) b & 0x3ff;
+				new_comp.b1 = (s16) a & 0x3ff;
+			}
+		}
+	}
+
+	if (bcmerror != 0) {
+		pr_debug("%s: Failed, cnt = %d\n", __func__, cal_retry);
+
+		if (cal_retry < CAL_RETRY_CNT) {
+			cal_retry++;
+			goto cal_try;
+		}
+
+		new_comp = old_comp;
+	}
+
+	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &new_comp);
+}
+
+static void wlc_phy_rxcal_radio_setup_nphy(struct brcms_phy *pi, u8 rx_core)
+{
+	u16 offtune_val;
+	u16 bias_g = 0;
+	u16 bias_a = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		if (rx_core == PHY_CORE_0) {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				pi->tx_rx_cal_radio_saveregs[0] =
+					read_radio_reg(pi,
+					    RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP);
+				pi->tx_rx_cal_radio_saveregs[1] =
+					read_radio_reg(pi,
+					    RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN);
+
+				write_radio_reg(pi,
+					RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP,
+					0x3);
+				write_radio_reg(pi,
+					RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN,
+					0xaf);
+
+			} else {
+				pi->tx_rx_cal_radio_saveregs[0] =
+					read_radio_reg(pi,
+					    RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP);
+				pi->tx_rx_cal_radio_saveregs[1] =
+					read_radio_reg(pi,
+					    RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN);
+
+				write_radio_reg(
+					pi,
+					RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP,
+					0x3);
+				write_radio_reg(
+					pi,
+					RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN,
+					0x7f);
+			}
+
+		} else {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				pi->tx_rx_cal_radio_saveregs[0] =
+					read_radio_reg(pi,
+					    RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP);
+				pi->tx_rx_cal_radio_saveregs[1] =
+					read_radio_reg(pi,
+					    RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN);
+
+				write_radio_reg(
+					pi,
+					RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP,
+					0x3);
+				write_radio_reg(
+					pi,
+					RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN,
+					0xaf);
+
+			} else {
+				pi->tx_rx_cal_radio_saveregs[0] =
+					read_radio_reg(pi,
+					    RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP);
+				pi->tx_rx_cal_radio_saveregs[1] =
+					read_radio_reg(pi,
+					    RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN);
+
+				write_radio_reg(pi,
+					RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP,
+					0x3);
+				write_radio_reg(pi,
+					RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN,
+					0x7f);
+			}
+		}
+
+	} else {
+		if (rx_core == PHY_CORE_0) {
+			pi->tx_rx_cal_radio_saveregs[0] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_RXIQCAL_TXMUX |
+					       RADIO_2056_TX1);
+			pi->tx_rx_cal_radio_saveregs[1] =
+				read_radio_reg(pi,
+					       RADIO_2056_RX_RXIQCAL_RXMUX |
+					       RADIO_2056_RX0);
+
+			if (pi->pubpi.radiorev >= 5) {
+				pi->tx_rx_cal_radio_saveregs[2] =
+					read_radio_reg(pi,
+						       RADIO_2056_RX_RXSPARE2 |
+						       RADIO_2056_RX0);
+				pi->tx_rx_cal_radio_saveregs[3] =
+					read_radio_reg(pi,
+						       RADIO_2056_TX_TXSPARE2 |
+						       RADIO_2056_TX1);
+			}
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+
+				if (pi->pubpi.radiorev >= 5) {
+					pi->tx_rx_cal_radio_saveregs[4] =
+						read_radio_reg(pi,
+						      RADIO_2056_RX_LNAA_MASTER
+						      | RADIO_2056_RX0);
+
+					write_radio_reg(
+						pi,
+						RADIO_2056_RX_LNAA_MASTER
+						| RADIO_2056_RX0, 0x40);
+
+					write_radio_reg(pi,
+						RADIO_2056_TX_TXSPARE2 |
+						RADIO_2056_TX1, bias_a);
+
+					write_radio_reg(pi,
+						RADIO_2056_RX_RXSPARE2 |
+						RADIO_2056_RX0, bias_a);
+				} else {
+					pi->tx_rx_cal_radio_saveregs[4] =
+						read_radio_reg(pi,
+							RADIO_2056_RX_LNAA_TUNE
+							| RADIO_2056_RX0);
+
+					offtune_val =
+						(pi->tx_rx_cal_radio_saveregs
+						 [2] & 0xF0) >> 8;
+					offtune_val =
+						(offtune_val <= 0x7) ? 0xF : 0;
+
+					mod_radio_reg(pi,
+						      RADIO_2056_RX_LNAA_TUNE |
+						      RADIO_2056_RX0, 0xF0,
+						      (offtune_val << 8));
+				}
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_RXIQCAL_TXMUX |
+						RADIO_2056_TX1, 0x9);
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXIQCAL_RXMUX |
+						RADIO_2056_RX0, 0x9);
+			} else {
+				if (pi->pubpi.radiorev >= 5) {
+					pi->tx_rx_cal_radio_saveregs[4] =
+						read_radio_reg(
+						      pi,
+						      RADIO_2056_RX_LNAG_MASTER
+						    | RADIO_2056_RX0);
+
+					write_radio_reg(
+						pi,
+						RADIO_2056_RX_LNAG_MASTER
+						| RADIO_2056_RX0, 0x40);
+
+					write_radio_reg(
+						pi,
+						RADIO_2056_TX_TXSPARE2
+						|
+						RADIO_2056_TX1, bias_g);
+
+					write_radio_reg(
+						pi,
+						RADIO_2056_RX_RXSPARE2
+						|
+						RADIO_2056_RX0, bias_g);
+
+				} else {
+					pi->tx_rx_cal_radio_saveregs[4] =
+						read_radio_reg(
+							pi,
+							RADIO_2056_RX_LNAG_TUNE
+							| RADIO_2056_RX0);
+
+					offtune_val =
+						(pi->
+						 tx_rx_cal_radio_saveregs[2] &
+						 0xF0) >> 8;
+					offtune_val =
+						(offtune_val <= 0x7) ? 0xF : 0;
+
+					mod_radio_reg(pi,
+						      RADIO_2056_RX_LNAG_TUNE |
+						      RADIO_2056_RX0, 0xF0,
+						      (offtune_val << 8));
+				}
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_RXIQCAL_TXMUX |
+						RADIO_2056_TX1, 0x6);
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXIQCAL_RXMUX |
+						RADIO_2056_RX0, 0x6);
+			}
+
+		} else {
+			pi->tx_rx_cal_radio_saveregs[0] =
+				read_radio_reg(pi,
+					       RADIO_2056_TX_RXIQCAL_TXMUX |
+					       RADIO_2056_TX0);
+			pi->tx_rx_cal_radio_saveregs[1] =
+				read_radio_reg(pi,
+					       RADIO_2056_RX_RXIQCAL_RXMUX |
+					       RADIO_2056_RX1);
+
+			if (pi->pubpi.radiorev >= 5) {
+				pi->tx_rx_cal_radio_saveregs[2] =
+					read_radio_reg(pi,
+						       RADIO_2056_RX_RXSPARE2 |
+						       RADIO_2056_RX1);
+				pi->tx_rx_cal_radio_saveregs[3] =
+					read_radio_reg(pi,
+						       RADIO_2056_TX_TXSPARE2 |
+						       RADIO_2056_TX0);
+			}
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+
+				if (pi->pubpi.radiorev >= 5) {
+					pi->tx_rx_cal_radio_saveregs[4] =
+						read_radio_reg(
+						       pi,
+						       RADIO_2056_RX_LNAA_MASTER
+						       | RADIO_2056_RX1);
+
+					write_radio_reg(
+						pi,
+						RADIO_2056_RX_LNAA_MASTER |
+						RADIO_2056_RX1, 0x40);
+
+					write_radio_reg(
+						pi,
+						RADIO_2056_TX_TXSPARE2
+						|
+						RADIO_2056_TX0, bias_a);
+
+					write_radio_reg(
+						pi,
+						RADIO_2056_RX_RXSPARE2
+						|
+						RADIO_2056_RX1, bias_a);
+				} else {
+					pi->tx_rx_cal_radio_saveregs[4] =
+						read_radio_reg(
+							pi,
+							RADIO_2056_RX_LNAA_TUNE
+							| RADIO_2056_RX1);
+
+					offtune_val =
+						(pi->
+						 tx_rx_cal_radio_saveregs[2] &
+						 0xF0) >> 8;
+					offtune_val =
+						(offtune_val <= 0x7) ? 0xF : 0;
+
+					mod_radio_reg(pi,
+						      RADIO_2056_RX_LNAA_TUNE |
+						      RADIO_2056_RX1, 0xF0,
+						      (offtune_val << 8));
+				}
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_RXIQCAL_TXMUX |
+						RADIO_2056_TX0, 0x9);
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXIQCAL_RXMUX |
+						RADIO_2056_RX1, 0x9);
+			} else {
+				if (pi->pubpi.radiorev >= 5) {
+					pi->tx_rx_cal_radio_saveregs[4] =
+						read_radio_reg(
+						      pi,
+						      RADIO_2056_RX_LNAG_MASTER
+						    | RADIO_2056_RX1);
+
+					write_radio_reg(
+						pi,
+						RADIO_2056_RX_LNAG_MASTER
+						| RADIO_2056_RX1, 0x40);
+
+					write_radio_reg(
+						pi,
+						RADIO_2056_TX_TXSPARE2
+						|
+						RADIO_2056_TX0, bias_g);
+
+					write_radio_reg(
+						pi,
+						RADIO_2056_RX_RXSPARE2
+						|
+						RADIO_2056_RX1, bias_g);
+				} else {
+					pi->tx_rx_cal_radio_saveregs[4] =
+						read_radio_reg(
+							pi,
+							RADIO_2056_RX_LNAG_TUNE
+							| RADIO_2056_RX1);
+
+					offtune_val =
+						(pi->
+						 tx_rx_cal_radio_saveregs[2] &
+						 0xF0) >> 8;
+					offtune_val =
+						(offtune_val <= 0x7) ? 0xF : 0;
+
+					mod_radio_reg(pi,
+						      RADIO_2056_RX_LNAG_TUNE |
+						      RADIO_2056_RX1, 0xF0,
+						      (offtune_val << 8));
+				}
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_RXIQCAL_TXMUX |
+						RADIO_2056_TX0, 0x6);
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXIQCAL_RXMUX |
+						RADIO_2056_RX1, 0x6);
+			}
+		}
+	}
+}
+
+static void wlc_phy_rxcal_radio_cleanup_nphy(struct brcms_phy *pi, u8 rx_core)
+{
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		if (rx_core == PHY_CORE_0) {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				write_radio_reg(
+					pi,
+					RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP,
+					pi->
+					tx_rx_cal_radio_saveregs[0]);
+				write_radio_reg(
+					pi,
+					RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN,
+					pi->
+					tx_rx_cal_radio_saveregs[1]);
+
+			} else {
+				write_radio_reg(
+					pi,
+					RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP,
+					pi->
+					tx_rx_cal_radio_saveregs[0]);
+				write_radio_reg(
+					pi,
+					RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN,
+					pi->
+					tx_rx_cal_radio_saveregs[1]);
+			}
+
+		} else {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				write_radio_reg(
+					pi,
+					RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP,
+					pi->
+					tx_rx_cal_radio_saveregs[0]);
+				write_radio_reg(
+					pi,
+					RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN,
+					pi->
+					tx_rx_cal_radio_saveregs[1]);
+
+			} else {
+				write_radio_reg(
+					pi,
+					RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP,
+					pi->
+					tx_rx_cal_radio_saveregs[0]);
+				write_radio_reg(
+					pi,
+					RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN,
+					pi->
+					tx_rx_cal_radio_saveregs[1]);
+			}
+		}
+
+	} else {
+		if (rx_core == PHY_CORE_0) {
+			write_radio_reg(pi,
+					RADIO_2056_TX_RXIQCAL_TXMUX |
+					RADIO_2056_TX1,
+					pi->tx_rx_cal_radio_saveregs[0]);
+
+			write_radio_reg(pi,
+					RADIO_2056_RX_RXIQCAL_RXMUX |
+					RADIO_2056_RX0,
+					pi->tx_rx_cal_radio_saveregs[1]);
+
+			if (pi->pubpi.radiorev >= 5) {
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXSPARE2 |
+						RADIO_2056_RX0,
+						pi->
+						tx_rx_cal_radio_saveregs[2]);
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_TXSPARE2 |
+						RADIO_2056_TX1,
+						pi->
+						tx_rx_cal_radio_saveregs[3]);
+			}
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				if (pi->pubpi.radiorev >= 5)
+					write_radio_reg(
+						pi,
+						RADIO_2056_RX_LNAA_MASTER
+						| RADIO_2056_RX0,
+						pi->
+						tx_rx_cal_radio_saveregs
+						[4]);
+				else
+					write_radio_reg(
+						pi,
+						RADIO_2056_RX_LNAA_TUNE
+						| RADIO_2056_RX0,
+						pi->
+						tx_rx_cal_radio_saveregs
+						[4]);
+			} else {
+				if (pi->pubpi.radiorev >= 5)
+					write_radio_reg(
+						pi,
+						RADIO_2056_RX_LNAG_MASTER
+						| RADIO_2056_RX0,
+						pi->
+						tx_rx_cal_radio_saveregs
+						[4]);
+				else
+					write_radio_reg(
+						pi,
+						RADIO_2056_RX_LNAG_TUNE
+						| RADIO_2056_RX0,
+						pi->
+						tx_rx_cal_radio_saveregs
+						[4]);
+			}
+
+		} else {
+			write_radio_reg(pi,
+					RADIO_2056_TX_RXIQCAL_TXMUX |
+					RADIO_2056_TX0,
+					pi->tx_rx_cal_radio_saveregs[0]);
+
+			write_radio_reg(pi,
+					RADIO_2056_RX_RXIQCAL_RXMUX |
+					RADIO_2056_RX1,
+					pi->tx_rx_cal_radio_saveregs[1]);
+
+			if (pi->pubpi.radiorev >= 5) {
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXSPARE2 |
+						RADIO_2056_RX1,
+						pi->
+						tx_rx_cal_radio_saveregs[2]);
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_TXSPARE2 |
+						RADIO_2056_TX0,
+						pi->
+						tx_rx_cal_radio_saveregs[3]);
+			}
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				if (pi->pubpi.radiorev >= 5)
+					write_radio_reg(
+						pi,
+						RADIO_2056_RX_LNAA_MASTER
+						| RADIO_2056_RX1,
+						pi->
+						tx_rx_cal_radio_saveregs
+						[4]);
+				else
+					write_radio_reg(
+						pi,
+						RADIO_2056_RX_LNAA_TUNE
+						| RADIO_2056_RX1,
+						pi->
+						tx_rx_cal_radio_saveregs
+						[4]);
+			} else {
+				if (pi->pubpi.radiorev >= 5)
+					write_radio_reg(
+						pi,
+						RADIO_2056_RX_LNAG_MASTER
+						| RADIO_2056_RX1,
+						pi->
+						tx_rx_cal_radio_saveregs
+						[4]);
+				else
+					write_radio_reg(
+						pi,
+						RADIO_2056_RX_LNAG_TUNE
+						| RADIO_2056_RX1,
+						pi->
+						tx_rx_cal_radio_saveregs
+						[4]);
+			}
+		}
+	}
+}
+
+static void wlc_phy_rxcal_physetup_nphy(struct brcms_phy *pi, u8 rx_core)
+{
+	u8 tx_core;
+	u16 rx_antval, tx_antval;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7))
+		tx_core = rx_core;
+	else
+		tx_core = (rx_core == PHY_CORE_0) ? 1 : 0;
+
+	pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa2);
+	pi->tx_rx_cal_phy_saveregs[1] =
+		read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7);
+	pi->tx_rx_cal_phy_saveregs[2] =
+		read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5);
+	pi->tx_rx_cal_phy_saveregs[3] = read_phy_reg(pi, 0x91);
+	pi->tx_rx_cal_phy_saveregs[4] = read_phy_reg(pi, 0x92);
+	pi->tx_rx_cal_phy_saveregs[5] = read_phy_reg(pi, 0x7a);
+	pi->tx_rx_cal_phy_saveregs[6] = read_phy_reg(pi, 0x7d);
+	pi->tx_rx_cal_phy_saveregs[7] = read_phy_reg(pi, 0xe7);
+	pi->tx_rx_cal_phy_saveregs[8] = read_phy_reg(pi, 0xec);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		pi->tx_rx_cal_phy_saveregs[11] = read_phy_reg(pi, 0x342);
+		pi->tx_rx_cal_phy_saveregs[12] = read_phy_reg(pi, 0x343);
+		pi->tx_rx_cal_phy_saveregs[13] = read_phy_reg(pi, 0x346);
+		pi->tx_rx_cal_phy_saveregs[14] = read_phy_reg(pi, 0x347);
+	}
+
+	pi->tx_rx_cal_phy_saveregs[9] = read_phy_reg(pi, 0x297);
+	pi->tx_rx_cal_phy_saveregs[10] = read_phy_reg(pi, 0x29b);
+	mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
+		    0x29b, (0x1 << 0), (0) << 0);
+
+	mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
+		    0x29b, (0x1 << 0), (0) << 0);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0);
+
+		mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << (1 - rx_core)) << 12);
+
+	} else {
+
+		mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << tx_core) << 12);
+		mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0);
+		mod_phy_reg(pi, 0xa2, (0xf << 4), (1 << rx_core) << 4);
+		mod_phy_reg(pi, 0xa2, (0xf << 8), (1 << rx_core) << 8);
+	}
+
+	mod_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7), (0x1 << 2), 0);
+	mod_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5,
+		    (0x1 << 2), (0x1 << 2));
+	if (NREV_LT(pi->pubpi.phy_rev, 7)) {
+		mod_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7),
+			    (0x1 << 0) | (0x1 << 1), 0);
+		mod_phy_reg(pi, (rx_core == PHY_CORE_0) ?
+			    0x8f : 0xa5,
+			    (0x1 << 0) | (0x1 << 1), (0x1 << 0) | (0x1 << 1));
+	}
+
+	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_PA, 0,
+					 RADIO_MIMO_CORESEL_CORE1 |
+					 RADIO_MIMO_CORESEL_CORE2);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+						  0, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 0, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		if (CHSPEC_IS40(pi->radio_chanspec))
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi,
+				(0x1 << 7),
+				2, 0, 0,
+				NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		else
+			wlc_phy_rfctrl_override_nphy_rev7(
+				pi,
+				(0x1 << 7),
+				0, 0, 0,
+				NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
+						  0, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 0, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+	} else {
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 3, 0);
+	}
+
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x1, rx_core + 1);
+	} else {
+
+		if (rx_core == PHY_CORE_0) {
+			rx_antval = 0x1;
+			tx_antval = 0x8;
+		} else {
+			rx_antval = 0x4;
+			tx_antval = 0x2;
+		}
+
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 rx_antval, rx_core + 1);
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 tx_antval, tx_core + 1);
+	}
+}
+
+static void wlc_phy_rxcal_phycleanup_nphy(struct brcms_phy *pi, u8 rx_core)
+{
+
+	write_phy_reg(pi, 0xa2, pi->tx_rx_cal_phy_saveregs[0]);
+	write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7,
+		      pi->tx_rx_cal_phy_saveregs[1]);
+	write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5,
+		      pi->tx_rx_cal_phy_saveregs[2]);
+	write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[3]);
+	write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[4]);
+
+	write_phy_reg(pi, 0x7a, pi->tx_rx_cal_phy_saveregs[5]);
+	write_phy_reg(pi, 0x7d, pi->tx_rx_cal_phy_saveregs[6]);
+	write_phy_reg(pi, 0xe7, pi->tx_rx_cal_phy_saveregs[7]);
+	write_phy_reg(pi, 0xec, pi->tx_rx_cal_phy_saveregs[8]);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		write_phy_reg(pi, 0x342, pi->tx_rx_cal_phy_saveregs[11]);
+		write_phy_reg(pi, 0x343, pi->tx_rx_cal_phy_saveregs[12]);
+		write_phy_reg(pi, 0x346, pi->tx_rx_cal_phy_saveregs[13]);
+		write_phy_reg(pi, 0x347, pi->tx_rx_cal_phy_saveregs[14]);
+	}
+
+	write_phy_reg(pi, 0x297, pi->tx_rx_cal_phy_saveregs[9]);
+	write_phy_reg(pi, 0x29b, pi->tx_rx_cal_phy_saveregs[10]);
+}
+
+static void
+wlc_phy_rxcal_gainctrl_nphy_rev5(struct brcms_phy *pi, u8 rx_core,
+				 u16 *rxgain, u8 cal_type)
+{
+
+	u16 num_samps;
+	struct phy_iq_est est[PHY_CORE_MAX];
+	u8 tx_core;
+	struct nphy_iq_comp save_comp, zero_comp;
+	u32 i_pwr, q_pwr, curr_pwr, optim_pwr = 0, prev_pwr = 0,
+	    thresh_pwr = 10000;
+	s16 desired_log2_pwr, actual_log2_pwr, delta_pwr;
+	bool gainctrl_done = false;
+	u8 mix_tia_gain = 3;
+	s8 optim_gaintbl_index = 0, prev_gaintbl_index = 0;
+	s8 curr_gaintbl_index = 3;
+	u8 gainctrl_dirn = NPHY_RXCAL_GAIN_INIT;
+	const struct nphy_ipa_txrxgain *nphy_rxcal_gaintbl;
+	u16 hpvga, lpf_biq1, lpf_biq0, lna2, lna1;
+	int fine_gain_idx;
+	s8 txpwrindex;
+	u16 nphy_rxcal_txgain[2];
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7))
+		tx_core = rx_core;
+	else
+		tx_core = 1 - rx_core;
+
+	num_samps = 1024;
+	desired_log2_pwr = 13;
+
+	wlc_phy_rx_iq_coeffs_nphy(pi, 0, &save_comp);
+	zero_comp.a0 = zero_comp.b0 = zero_comp.a1 = zero_comp.b1 = 0x0;
+	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &zero_comp);
+
+	if (CHSPEC_IS5G(pi->radio_chanspec)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7))
+			mix_tia_gain = 3;
+		else if (NREV_GE(pi->pubpi.phy_rev, 4))
+			mix_tia_gain = 4;
+		else
+			mix_tia_gain = 6;
+		if (NREV_GE(pi->pubpi.phy_rev, 7))
+			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz_rev7;
+		else
+			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz;
+	} else {
+		if (NREV_GE(pi->pubpi.phy_rev, 7))
+			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz_rev7;
+		else
+			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz;
+	}
+
+	do {
+
+		hpvga = (NREV_GE(pi->pubpi.phy_rev, 7)) ?
+			0 : nphy_rxcal_gaintbl[curr_gaintbl_index].hpvga;
+		lpf_biq1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq1;
+		lpf_biq0 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq0;
+		lna2 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna2;
+		lna1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna1;
+		txpwrindex = nphy_rxcal_gaintbl[curr_gaintbl_index].txpwrindex;
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7))
+			wlc_phy_rfctrl_override_1tomany_nphy(
+				pi,
+				NPHY_REV7_RfctrlOverride_cmd_rxgain,
+				((lpf_biq1 << 12) |
+				 (lpf_biq0 << 8) |
+				 (mix_tia_gain << 4) | (lna2 << 2)
+				 | lna1), 0x3, 0);
+		else
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12),
+						     ((hpvga << 12) |
+						      (lpf_biq1 << 10) |
+						      (lpf_biq0 << 8) |
+						      (mix_tia_gain << 4) |
+						      (lna2 << 2) | lna1), 0x3,
+						     0);
+
+		pi->nphy_rxcal_pwr_idx[tx_core] = txpwrindex;
+
+		if (txpwrindex == -1) {
+			nphy_rxcal_txgain[0] = 0x8ff0 | pi->nphy_gmval;
+			nphy_rxcal_txgain[1] = 0x8ff0 | pi->nphy_gmval;
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+						 2, 0x110, 16,
+						 nphy_rxcal_txgain);
+		} else {
+			wlc_phy_txpwr_index_nphy(pi, tx_core + 1, txpwrindex,
+						 false);
+		}
+
+		wlc_phy_tx_tone_nphy(pi, (CHSPEC_IS40(pi->radio_chanspec)) ?
+				     NPHY_RXCAL_TONEFREQ_40MHz :
+				     NPHY_RXCAL_TONEFREQ_20MHz,
+				     NPHY_RXCAL_TONEAMP, 0, cal_type, false);
+
+		wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0);
+		i_pwr = (est[rx_core].i_pwr + num_samps / 2) / num_samps;
+		q_pwr = (est[rx_core].q_pwr + num_samps / 2) / num_samps;
+		curr_pwr = i_pwr + q_pwr;
+
+		switch (gainctrl_dirn) {
+		case NPHY_RXCAL_GAIN_INIT:
+			if (curr_pwr > thresh_pwr) {
+				gainctrl_dirn = NPHY_RXCAL_GAIN_DOWN;
+				prev_gaintbl_index = curr_gaintbl_index;
+				curr_gaintbl_index--;
+			} else {
+				gainctrl_dirn = NPHY_RXCAL_GAIN_UP;
+				prev_gaintbl_index = curr_gaintbl_index;
+				curr_gaintbl_index++;
+			}
+			break;
+
+		case NPHY_RXCAL_GAIN_UP:
+			if (curr_pwr > thresh_pwr) {
+				gainctrl_done = true;
+				optim_pwr = prev_pwr;
+				optim_gaintbl_index = prev_gaintbl_index;
+			} else {
+				prev_gaintbl_index = curr_gaintbl_index;
+				curr_gaintbl_index++;
+			}
+			break;
+
+		case NPHY_RXCAL_GAIN_DOWN:
+			if (curr_pwr > thresh_pwr) {
+				prev_gaintbl_index = curr_gaintbl_index;
+				curr_gaintbl_index--;
+			} else {
+				gainctrl_done = true;
+				optim_pwr = curr_pwr;
+				optim_gaintbl_index = curr_gaintbl_index;
+			}
+			break;
+
+		default:
+			break;
+		}
+
+		if ((curr_gaintbl_index < 0) ||
+		    (curr_gaintbl_index > NPHY_IPA_RXCAL_MAXGAININDEX)) {
+			gainctrl_done = true;
+			optim_pwr = curr_pwr;
+			optim_gaintbl_index = prev_gaintbl_index;
+		} else {
+			prev_pwr = curr_pwr;
+		}
+
+		wlc_phy_stopplayback_nphy(pi);
+	} while (!gainctrl_done);
+
+	hpvga = nphy_rxcal_gaintbl[optim_gaintbl_index].hpvga;
+	lpf_biq1 = nphy_rxcal_gaintbl[optim_gaintbl_index].lpf_biq1;
+	lpf_biq0 = nphy_rxcal_gaintbl[optim_gaintbl_index].lpf_biq0;
+	lna2 = nphy_rxcal_gaintbl[optim_gaintbl_index].lna2;
+	lna1 = nphy_rxcal_gaintbl[optim_gaintbl_index].lna1;
+	txpwrindex = nphy_rxcal_gaintbl[optim_gaintbl_index].txpwrindex;
+
+	actual_log2_pwr = wlc_phy_nbits(optim_pwr);
+	delta_pwr = desired_log2_pwr - actual_log2_pwr;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		fine_gain_idx = (int)lpf_biq1 + delta_pwr;
+
+		if (fine_gain_idx + (int)lpf_biq0 > 10)
+			lpf_biq1 = 10 - lpf_biq0;
+		else
+			lpf_biq1 = (u16) max(fine_gain_idx, 0);
+
+		wlc_phy_rfctrl_override_1tomany_nphy(
+			pi,
+			NPHY_REV7_RfctrlOverride_cmd_rxgain,
+			((lpf_biq1 << 12) |
+			 (lpf_biq0 << 8) |
+			 (mix_tia_gain << 4) |
+			 (lna2 << 2) | lna1), 0x3,
+			0);
+	} else {
+		hpvga = (u16) max(min(((int)hpvga) + delta_pwr, 10), 0);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12),
+					     ((hpvga << 12) |
+					      (lpf_biq1 << 10) |
+					      (lpf_biq0 << 8) |
+					      (mix_tia_gain << 4) |
+					      (lna2 << 2) |
+					      lna1), 0x3, 0);
+	}
+
+	if (rxgain != NULL) {
+		*rxgain++ = lna1;
+		*rxgain++ = lna2;
+		*rxgain++ = mix_tia_gain;
+		*rxgain++ = lpf_biq0;
+		*rxgain++ = lpf_biq1;
+		*rxgain = hpvga;
+	}
+
+	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &save_comp);
+}
+
+static void
+wlc_phy_rxcal_gainctrl_nphy(struct brcms_phy *pi, u8 rx_core, u16 *rxgain,
+			    u8 cal_type)
+{
+	wlc_phy_rxcal_gainctrl_nphy_rev5(pi, rx_core, rxgain, cal_type);
+}
+
+static u8
+wlc_phy_rc_sweep_nphy(struct brcms_phy *pi, u8 core_idx, u8 loopback_type)
+{
+	u32 target_bws[2] = { 9500, 21000 };
+	u32 ref_tones[2] = { 3000, 6000 };
+	u32 target_bw, ref_tone;
+
+	u32 target_pwr_ratios[2] = { 28606, 18468 };
+	u32 target_pwr_ratio, pwr_ratio, last_pwr_ratio = 0;
+
+	u16 start_rccal_ovr_val = 128;
+	u16 txlpf_rccal_lpc_ovr_val = 128;
+	u16 rxlpf_rccal_hpc_ovr_val = 159;
+
+	u16 orig_txlpf_rccal_lpc_ovr_val;
+	u16 orig_rxlpf_rccal_hpc_ovr_val;
+	u16 radio_addr_offset_rx;
+	u16 radio_addr_offset_tx;
+	u16 orig_dcBypass;
+	u16 orig_RxStrnFilt40Num[6];
+	u16 orig_RxStrnFilt40Den[4];
+	u16 orig_rfctrloverride[2];
+	u16 orig_rfctrlauxreg[2];
+	u16 orig_rfctrlrssiothers;
+	u16 tx_lpf_bw = 4;
+
+	u16 rx_lpf_bw, rx_lpf_bws[2] = { 2, 4 };
+	u16 lpf_hpc = 7, hpvga_hpc = 7;
+
+	s8 rccal_stepsize;
+	u16 rccal_val, last_rccal_val = 0, best_rccal_val = 0;
+	u32 ref_iq_vals = 0, target_iq_vals = 0;
+	u16 num_samps, log_num_samps = 10;
+	struct phy_iq_est est[PHY_CORE_MAX];
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7))
+		return 0;
+
+	num_samps = (1 << log_num_samps);
+
+	if (CHSPEC_IS40(pi->radio_chanspec)) {
+		target_bw = target_bws[1];
+		target_pwr_ratio = target_pwr_ratios[1];
+		ref_tone = ref_tones[1];
+		rx_lpf_bw = rx_lpf_bws[1];
+	} else {
+		target_bw = target_bws[0];
+		target_pwr_ratio = target_pwr_ratios[0];
+		ref_tone = ref_tones[0];
+		rx_lpf_bw = rx_lpf_bws[0];
+	}
+
+	if (core_idx == 0) {
+		radio_addr_offset_rx = RADIO_2056_RX0;
+		radio_addr_offset_tx =
+			(loopback_type == 0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
+	} else {
+		radio_addr_offset_rx = RADIO_2056_RX1;
+		radio_addr_offset_tx =
+			(loopback_type == 0) ? RADIO_2056_TX1 : RADIO_2056_TX0;
+	}
+
+	orig_txlpf_rccal_lpc_ovr_val =
+		read_radio_reg(pi,
+			       (RADIO_2056_TX_TXLPF_RCCAL |
+				radio_addr_offset_tx));
+	orig_rxlpf_rccal_hpc_ovr_val =
+		read_radio_reg(pi,
+			       (RADIO_2056_RX_RXLPF_RCCAL_HPC |
+				radio_addr_offset_rx));
+
+	orig_dcBypass = ((read_phy_reg(pi, 0x48) >> 8) & 1);
+
+	orig_RxStrnFilt40Num[0] = read_phy_reg(pi, 0x267);
+	orig_RxStrnFilt40Num[1] = read_phy_reg(pi, 0x268);
+	orig_RxStrnFilt40Num[2] = read_phy_reg(pi, 0x269);
+	orig_RxStrnFilt40Den[0] = read_phy_reg(pi, 0x26a);
+	orig_RxStrnFilt40Den[1] = read_phy_reg(pi, 0x26b);
+	orig_RxStrnFilt40Num[3] = read_phy_reg(pi, 0x26c);
+	orig_RxStrnFilt40Num[4] = read_phy_reg(pi, 0x26d);
+	orig_RxStrnFilt40Num[5] = read_phy_reg(pi, 0x26e);
+	orig_RxStrnFilt40Den[2] = read_phy_reg(pi, 0x26f);
+	orig_RxStrnFilt40Den[3] = read_phy_reg(pi, 0x270);
+
+	orig_rfctrloverride[0] = read_phy_reg(pi, 0xe7);
+	orig_rfctrloverride[1] = read_phy_reg(pi, 0xec);
+	orig_rfctrlauxreg[0] = read_phy_reg(pi, 0xf8);
+	orig_rfctrlauxreg[1] = read_phy_reg(pi, 0xfa);
+	orig_rfctrlrssiothers = read_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d);
+
+	write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx),
+			txlpf_rccal_lpc_ovr_val);
+
+	write_radio_reg(pi,
+			(RADIO_2056_RX_RXLPF_RCCAL_HPC | radio_addr_offset_rx),
+			rxlpf_rccal_hpc_ovr_val);
+
+	mod_phy_reg(pi, 0x48, (0x1 << 8), (0x1 << 8));
+
+	write_phy_reg(pi, 0x267, 0x02d4);
+	write_phy_reg(pi, 0x268, 0x0000);
+	write_phy_reg(pi, 0x269, 0x0000);
+	write_phy_reg(pi, 0x26a, 0x0000);
+	write_phy_reg(pi, 0x26b, 0x0000);
+	write_phy_reg(pi, 0x26c, 0x02d4);
+	write_phy_reg(pi, 0x26d, 0x0000);
+	write_phy_reg(pi, 0x26e, 0x0000);
+	write_phy_reg(pi, 0x26f, 0x0000);
+	write_phy_reg(pi, 0x270, 0x0000);
+
+	or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 8));
+	or_phy_reg(pi, (core_idx == 0) ? 0xec : 0xe7, (0x1 << 15));
+	or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 9));
+	or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 10));
+
+	mod_phy_reg(pi, (core_idx == 0) ? 0xfa : 0xf8,
+		    (0x7 << 10), (tx_lpf_bw << 10));
+	mod_phy_reg(pi, (core_idx == 0) ? 0xf8 : 0xfa,
+		    (0x7 << 0), (hpvga_hpc << 0));
+	mod_phy_reg(pi, (core_idx == 0) ? 0xf8 : 0xfa,
+		    (0x7 << 4), (lpf_hpc << 4));
+	mod_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d,
+		    (0x7 << 8), (rx_lpf_bw << 8));
+
+	rccal_stepsize = 16;
+	rccal_val = start_rccal_ovr_val + rccal_stepsize;
+
+	while (rccal_stepsize >= 0) {
+		write_radio_reg(pi,
+				(RADIO_2056_RX_RXLPF_RCCAL_LPC |
+				 radio_addr_offset_rx), rccal_val);
+
+		if (rccal_stepsize == 16) {
+
+			wlc_phy_tx_tone_nphy(pi, ref_tone, NPHY_RXCAL_TONEAMP,
+					     0, 1, false);
+			udelay(2);
+
+			wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0);
+
+			if (core_idx == 0)
+				ref_iq_vals =
+					max_t(u32, (est[0].i_pwr +
+						    est[0].q_pwr) >>
+					      (log_num_samps + 1),
+					      1);
+			else
+				ref_iq_vals =
+					max_t(u32, (est[1].i_pwr +
+						    est[1].q_pwr) >>
+					      (log_num_samps + 1),
+					      1);
+
+			wlc_phy_tx_tone_nphy(pi, target_bw, NPHY_RXCAL_TONEAMP,
+					     0, 1, false);
+			udelay(2);
+		}
+
+		wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0);
+
+		if (core_idx == 0)
+			target_iq_vals = (est[0].i_pwr + est[0].q_pwr) >>
+					 (log_num_samps + 1);
+		else
+			target_iq_vals =
+				(est[1].i_pwr +
+				 est[1].q_pwr) >> (log_num_samps + 1);
+
+		pwr_ratio = (uint) ((target_iq_vals << 16) / ref_iq_vals);
+
+		if (rccal_stepsize == 0)
+			rccal_stepsize--;
+		else if (rccal_stepsize == 1) {
+			last_rccal_val = rccal_val;
+			rccal_val += (pwr_ratio > target_pwr_ratio) ? 1 : -1;
+			last_pwr_ratio = pwr_ratio;
+			rccal_stepsize--;
+		} else {
+			rccal_stepsize = (rccal_stepsize >> 1);
+			rccal_val += ((pwr_ratio > target_pwr_ratio) ?
+				      rccal_stepsize : (-rccal_stepsize));
+		}
+
+		if (rccal_stepsize == -1) {
+			best_rccal_val =
+				(abs((int)last_pwr_ratio -
+				     (int)target_pwr_ratio) <
+				 abs((int)pwr_ratio -
+				     (int)target_pwr_ratio)) ? last_rccal_val :
+				rccal_val;
+
+			if (CHSPEC_IS40(pi->radio_chanspec)) {
+				if ((best_rccal_val > 140)
+				    || (best_rccal_val < 135))
+					best_rccal_val = 138;
+			} else {
+				if ((best_rccal_val > 142)
+				    || (best_rccal_val < 137))
+					best_rccal_val = 140;
+			}
+
+			write_radio_reg(pi,
+					(RADIO_2056_RX_RXLPF_RCCAL_LPC |
+					 radio_addr_offset_rx), best_rccal_val);
+		}
+	}
+
+	wlc_phy_stopplayback_nphy(pi);
+
+	write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx),
+			orig_txlpf_rccal_lpc_ovr_val);
+	write_radio_reg(pi,
+			(RADIO_2056_RX_RXLPF_RCCAL_HPC | radio_addr_offset_rx),
+			orig_rxlpf_rccal_hpc_ovr_val);
+
+	mod_phy_reg(pi, 0x48, (0x1 << 8), (orig_dcBypass << 8));
+
+	write_phy_reg(pi, 0x267, orig_RxStrnFilt40Num[0]);
+	write_phy_reg(pi, 0x268, orig_RxStrnFilt40Num[1]);
+	write_phy_reg(pi, 0x269, orig_RxStrnFilt40Num[2]);
+	write_phy_reg(pi, 0x26a, orig_RxStrnFilt40Den[0]);
+	write_phy_reg(pi, 0x26b, orig_RxStrnFilt40Den[1]);
+	write_phy_reg(pi, 0x26c, orig_RxStrnFilt40Num[3]);
+	write_phy_reg(pi, 0x26d, orig_RxStrnFilt40Num[4]);
+	write_phy_reg(pi, 0x26e, orig_RxStrnFilt40Num[5]);
+	write_phy_reg(pi, 0x26f, orig_RxStrnFilt40Den[2]);
+	write_phy_reg(pi, 0x270, orig_RxStrnFilt40Den[3]);
+
+	write_phy_reg(pi, 0xe7, orig_rfctrloverride[0]);
+	write_phy_reg(pi, 0xec, orig_rfctrloverride[1]);
+	write_phy_reg(pi, 0xf8, orig_rfctrlauxreg[0]);
+	write_phy_reg(pi, 0xfa, orig_rfctrlauxreg[1]);
+	write_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d, orig_rfctrlrssiothers);
+
+	pi->nphy_anarxlpf_adjusted = false;
+
+	return best_rccal_val - 0x80;
+}
+
+#define WAIT_FOR_SCOPE  4000
+static int wlc_phy_cal_rxiq_nphy_rev3(struct brcms_phy *pi,
+				      struct nphy_txgains target_gain,
+				      u8 cal_type, bool debug)
+{
+	u16 orig_BBConfig;
+	u8 core_no, rx_core;
+	u8 best_rccal[2];
+	u16 gain_save[2];
+	u16 cal_gain[2];
+	struct nphy_iqcal_params cal_params[2];
+	u8 rxcore_state;
+	s8 rxlpf_rccal_hpc, txlpf_rccal_lpc;
+	s8 txlpf_idac;
+	bool phyhang_avoid_state = false;
+	bool skip_rxiqcal = false;
+
+	orig_BBConfig = read_phy_reg(pi, 0x01);
+	mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+		phyhang_avoid_state = pi->phyhang_avoid;
+		pi->phyhang_avoid = false;
+	}
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save);
+
+	for (core_no = 0; core_no <= 1; core_no++) {
+		wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain,
+					      &cal_params[core_no]);
+		cal_gain[core_no] = cal_params[core_no].cal_gain;
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain);
+
+	rxcore_state = wlc_phy_rxcore_getstate_nphy(
+		(struct brcms_phy_pub *) pi);
+
+	for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) {
+
+		skip_rxiqcal =
+			((rxcore_state & (1 << rx_core)) == 0) ? true : false;
+
+		wlc_phy_rxcal_physetup_nphy(pi, rx_core);
+
+		wlc_phy_rxcal_radio_setup_nphy(pi, rx_core);
+
+		if ((!skip_rxiqcal) && ((cal_type == 0) || (cal_type == 2))) {
+
+			wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL, 0);
+
+			wlc_phy_tx_tone_nphy(pi,
+					     (CHSPEC_IS40(
+						      pi->radio_chanspec)) ?
+					     NPHY_RXCAL_TONEFREQ_40MHz :
+					     NPHY_RXCAL_TONEFREQ_20MHz,
+					     NPHY_RXCAL_TONEAMP, 0, cal_type,
+					     false);
+
+			if (debug)
+				mdelay(WAIT_FOR_SCOPE);
+
+			wlc_phy_calc_rx_iq_comp_nphy(pi, rx_core + 1);
+			wlc_phy_stopplayback_nphy(pi);
+		}
+
+		if (((cal_type == 1) || (cal_type == 2))
+		    && NREV_LT(pi->pubpi.phy_rev, 7)) {
+
+			if (rx_core == PHY_CORE_1) {
+
+				if (rxcore_state == 1)
+					wlc_phy_rxcore_setstate_nphy(
+						(struct brcms_phy_pub *) pi, 3);
+
+				wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL,
+							    1);
+
+				best_rccal[rx_core] =
+					wlc_phy_rc_sweep_nphy(pi, rx_core, 1);
+				pi->nphy_rccal_value = best_rccal[rx_core];
+
+				if (rxcore_state == 1)
+					wlc_phy_rxcore_setstate_nphy(
+						(struct brcms_phy_pub *) pi,
+						rxcore_state);
+			}
+		}
+
+		wlc_phy_rxcal_radio_cleanup_nphy(pi, rx_core);
+
+		wlc_phy_rxcal_phycleanup_nphy(pi, rx_core);
+		wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+	}
+
+	if ((cal_type == 1) || (cal_type == 2)) {
+
+		best_rccal[0] = best_rccal[1];
+		write_radio_reg(pi,
+				(RADIO_2056_RX_RXLPF_RCCAL_LPC |
+				 RADIO_2056_RX0), (best_rccal[0] | 0x80));
+
+		for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) {
+			rxlpf_rccal_hpc =
+				(((int)best_rccal[rx_core] - 12) >> 1) + 10;
+			txlpf_rccal_lpc = ((int)best_rccal[rx_core] - 12) + 10;
+
+			if (PHY_IPA(pi)) {
+				txlpf_rccal_lpc +=
+					(pi->bw == WL_CHANSPEC_BW_40) ? 24 : 12;
+				txlpf_idac = (pi->bw == WL_CHANSPEC_BW_40) ?
+					     0x0e : 0x13;
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, rx_core,
+						 TXLPF_IDAC_4, txlpf_idac);
+			}
+
+			rxlpf_rccal_hpc = max(min_t(u8, rxlpf_rccal_hpc, 31),
+					      0);
+			txlpf_rccal_lpc = max(min_t(u8, txlpf_rccal_lpc, 31),
+					      0);
+
+			write_radio_reg(pi, (RADIO_2056_RX_RXLPF_RCCAL_HPC |
+					     ((rx_core ==
+					       PHY_CORE_0) ? RADIO_2056_RX0 :
+					      RADIO_2056_RX1)),
+					(rxlpf_rccal_hpc | 0x80));
+
+			write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL |
+					     ((rx_core ==
+					       PHY_CORE_0) ? RADIO_2056_TX0 :
+					      RADIO_2056_TX1)),
+					(txlpf_rccal_lpc | 0x80));
+		}
+	}
+
+	write_phy_reg(pi, 0x01, orig_BBConfig);
+
+	wlc_phy_resetcca_nphy(pi);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7))
+		wlc_phy_rfctrl_override_1tomany_nphy(
+			pi,
+			NPHY_REV7_RfctrlOverride_cmd_rxgain,
+			0, 0x3, 1);
+	else
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1);
+
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+				 gain_save);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 4))
+		pi->phyhang_avoid = phyhang_avoid_state;
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+	return 0;
+}
+
+static int
+wlc_phy_cal_rxiq_nphy_rev2(struct brcms_phy *pi,
+			   struct nphy_txgains target_gain, bool debug)
+{
+	struct phy_iq_est est[PHY_CORE_MAX];
+	u8 core_num, rx_core, tx_core;
+	u16 lna_vals[] = { 0x3, 0x3, 0x1 };
+	u16 hpf1_vals[] = { 0x7, 0x2, 0x0 };
+	u16 hpf2_vals[] = { 0x2, 0x0, 0x0 };
+	s16 curr_hpf1, curr_hpf2, curr_hpf, curr_lna;
+	s16 desired_log2_pwr, actual_log2_pwr, hpf_change;
+	u16 orig_RfseqCoreActv, orig_AfectrlCore, orig_AfectrlOverride;
+	u16 orig_RfctrlIntcRx, orig_RfctrlIntcTx;
+	u16 num_samps;
+	u32 i_pwr, q_pwr, tot_pwr[3];
+	u8 gain_pass, use_hpf_num;
+	u16 mask, val1, val2;
+	u16 core_no;
+	u16 gain_save[2];
+	u16 cal_gain[2];
+	struct nphy_iqcal_params cal_params[2];
+	u8 phy_bw;
+	int bcmerror = 0;
+	bool first_playtone = true;
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2))
+		wlc_phy_reapply_txcal_coeffs_nphy(pi);
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save);
+
+	for (core_no = 0; core_no <= 1; core_no++) {
+		wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain,
+					      &cal_params[core_no]);
+		cal_gain[core_no] = cal_params[core_no].cal_gain;
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain);
+
+	num_samps = 1024;
+	desired_log2_pwr = 13;
+
+	for (core_num = 0; core_num < 2; core_num++) {
+
+		rx_core = core_num;
+		tx_core = 1 - core_num;
+
+		orig_RfseqCoreActv = read_phy_reg(pi, 0xa2);
+		orig_AfectrlCore = read_phy_reg(pi, (rx_core == PHY_CORE_0) ?
+						0xa6 : 0xa7);
+		orig_AfectrlOverride = read_phy_reg(pi, 0xa5);
+		orig_RfctrlIntcRx = read_phy_reg(pi, (rx_core == PHY_CORE_0) ?
+						 0x91 : 0x92);
+		orig_RfctrlIntcTx = read_phy_reg(pi, (tx_core == PHY_CORE_0) ?
+						 0x91 : 0x92);
+
+		mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << tx_core) << 12);
+		mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0);
+
+		or_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7),
+			   ((0x1 << 1) | (0x1 << 2)));
+		or_phy_reg(pi, 0xa5, ((0x1 << 1) | (0x1 << 2)));
+
+		if (((pi->nphy_rxcalparams) & 0xff000000))
+			write_phy_reg(pi,
+				      (rx_core == PHY_CORE_0) ? 0x91 : 0x92,
+				      (CHSPEC_IS5G(pi->radio_chanspec) ?
+					0x140 : 0x110));
+		else
+			write_phy_reg(pi,
+				      (rx_core == PHY_CORE_0) ? 0x91 : 0x92,
+				      (CHSPEC_IS5G(pi->radio_chanspec) ?
+				       0x180 : 0x120));
+
+		write_phy_reg(pi, (tx_core == PHY_CORE_0) ? 0x91 : 0x92,
+			      (CHSPEC_IS5G(pi->radio_chanspec) ? 0x148 :
+			       0x114));
+
+		mask = RADIO_2055_COUPLE_RX_MASK | RADIO_2055_COUPLE_TX_MASK;
+		if (rx_core == PHY_CORE_0) {
+			val1 = RADIO_2055_COUPLE_RX_MASK;
+			val2 = RADIO_2055_COUPLE_TX_MASK;
+		} else {
+			val1 = RADIO_2055_COUPLE_TX_MASK;
+			val2 = RADIO_2055_COUPLE_RX_MASK;
+		}
+
+		if ((pi->nphy_rxcalparams & 0x10000)) {
+			mod_radio_reg(pi, RADIO_2055_CORE1_GEN_SPARE2, mask,
+				      val1);
+			mod_radio_reg(pi, RADIO_2055_CORE2_GEN_SPARE2, mask,
+				      val2);
+		}
+
+		for (gain_pass = 0; gain_pass < 4; gain_pass++) {
+
+			if (debug)
+				mdelay(WAIT_FOR_SCOPE);
+
+			if (gain_pass < 3) {
+				curr_lna = lna_vals[gain_pass];
+				curr_hpf1 = hpf1_vals[gain_pass];
+				curr_hpf2 = hpf2_vals[gain_pass];
+			} else {
+
+				if (tot_pwr[1] > 10000) {
+					curr_lna = lna_vals[2];
+					curr_hpf1 = hpf1_vals[2];
+					curr_hpf2 = hpf2_vals[2];
+					use_hpf_num = 1;
+					curr_hpf = curr_hpf1;
+					actual_log2_pwr =
+						wlc_phy_nbits(tot_pwr[2]);
+				} else {
+					if (tot_pwr[0] > 10000) {
+						curr_lna = lna_vals[1];
+						curr_hpf1 = hpf1_vals[1];
+						curr_hpf2 = hpf2_vals[1];
+						use_hpf_num = 1;
+						curr_hpf = curr_hpf1;
+						actual_log2_pwr =
+							wlc_phy_nbits(
+								tot_pwr[1]);
+					} else {
+						curr_lna = lna_vals[0];
+						curr_hpf1 = hpf1_vals[0];
+						curr_hpf2 = hpf2_vals[0];
+						use_hpf_num = 2;
+						curr_hpf = curr_hpf2;
+						actual_log2_pwr =
+							wlc_phy_nbits(
+								tot_pwr[0]);
+					}
+				}
+
+				hpf_change = desired_log2_pwr - actual_log2_pwr;
+				curr_hpf += hpf_change;
+				curr_hpf = max(min_t(u16, curr_hpf, 10), 0);
+				if (use_hpf_num == 1)
+					curr_hpf1 = curr_hpf;
+				else
+					curr_hpf2 = curr_hpf;
+			}
+
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 10),
+						     ((curr_hpf2 << 8) |
+						      (curr_hpf1 << 4) |
+						      (curr_lna << 2)), 0x3, 0);
+			wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+
+			wlc_phy_stopplayback_nphy(pi);
+
+			if (first_playtone) {
+				bcmerror = wlc_phy_tx_tone_nphy(pi, 4000,
+						(u16) (pi->nphy_rxcalparams &
+						       0xffff), 0, 0, true);
+				first_playtone = false;
+			} else {
+				phy_bw = (CHSPEC_IS40(pi->radio_chanspec)) ?
+					  40 : 20;
+				wlc_phy_runsamples_nphy(pi, phy_bw * 8, 0xffff,
+							0, 0, 0, true);
+			}
+
+			if (bcmerror == 0) {
+				if (gain_pass < 3) {
+
+					wlc_phy_rx_iq_est_nphy(pi, est,
+							       num_samps, 32,
+							       0);
+					i_pwr =	(est[rx_core].i_pwr +
+						 num_samps / 2) / num_samps;
+					q_pwr =	(est[rx_core].q_pwr +
+						 num_samps / 2) / num_samps;
+					tot_pwr[gain_pass] = i_pwr + q_pwr;
+				} else {
+
+					wlc_phy_calc_rx_iq_comp_nphy(pi,
+								     (1 <<
+								      rx_core));
+				}
+
+				wlc_phy_stopplayback_nphy(pi);
+			}
+
+			if (bcmerror != 0)
+				break;
+		}
+
+		and_radio_reg(pi, RADIO_2055_CORE1_GEN_SPARE2, ~mask);
+		and_radio_reg(pi, RADIO_2055_CORE2_GEN_SPARE2, ~mask);
+
+		write_phy_reg(pi, (tx_core == PHY_CORE_0) ? 0x91 :
+			      0x92, orig_RfctrlIntcTx);
+		write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x91 :
+			      0x92, orig_RfctrlIntcRx);
+		write_phy_reg(pi, 0xa5, orig_AfectrlOverride);
+		write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 :
+			      0xa7, orig_AfectrlCore);
+		write_phy_reg(pi, 0xa2, orig_RfseqCoreActv);
+
+		if (bcmerror != 0)
+			break;
+	}
+
+	wlc_phy_rfctrl_override_nphy(pi, (0x1 << 10), 0, 0x3, 1);
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+				 gain_save);
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+	return bcmerror;
+}
+
+int
+wlc_phy_cal_rxiq_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain,
+		      u8 cal_type, bool debug)
+{
+	if (NREV_GE(pi->pubpi.phy_rev, 7))
+		cal_type = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3))
+		return wlc_phy_cal_rxiq_nphy_rev3(pi, target_gain, cal_type,
+						  debug);
+	else
+		return wlc_phy_cal_rxiq_nphy_rev2(pi, target_gain, debug);
+}
+
+void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi)
+{
+	uint core;
+	u32 txgain;
+	u16 rad_gain, dac_gain, bbmult, m1m2;
+	u8 txpi[2], chan_freq_range;
+	s32 rfpwr_offset;
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (pi->sh->sromrev < 4) {
+		txpi[0] = txpi[1] = 72;
+	} else {
+
+		chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
+		switch (chan_freq_range) {
+		case WL_CHAN_FREQ_RANGE_2G:
+		case WL_CHAN_FREQ_RANGE_5GL:
+		case WL_CHAN_FREQ_RANGE_5GM:
+		case WL_CHAN_FREQ_RANGE_5GH:
+			txpi[0] = 0;
+			txpi[1] = 0;
+			break;
+		default:
+			txpi[0] = txpi[1] = 91;
+			break;
+		}
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7))
+		txpi[0] = txpi[1] = 30;
+	else if (NREV_GE(pi->pubpi.phy_rev, 3))
+		txpi[0] = txpi[1] = 40;
+
+	if (NREV_LT(pi->pubpi.phy_rev, 7)) {
+
+		if ((txpi[0] < 40) || (txpi[0] > 100) ||
+		    (txpi[1] < 40) || (txpi[1] > 100))
+			txpi[0] = txpi[1] = 91;
+	}
+
+	pi->nphy_txpwrindex[PHY_CORE_0].index_internal = txpi[0];
+	pi->nphy_txpwrindex[PHY_CORE_1].index_internal = txpi[1];
+	pi->nphy_txpwrindex[PHY_CORE_0].index_internal_save = txpi[0];
+	pi->nphy_txpwrindex[PHY_CORE_1].index_internal_save = txpi[1];
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+		uint phyrev = pi->pubpi.phy_rev;
+
+		if (NREV_GE(phyrev, 3)) {
+			if (PHY_IPA(pi)) {
+				u32 *tx_gaintbl =
+					wlc_phy_get_ipa_gaintbl_nphy(pi);
+				txgain = tx_gaintbl[txpi[core]];
+			} else {
+				if (CHSPEC_IS5G(pi->radio_chanspec)) {
+					if (NREV_IS(phyrev, 3)) {
+						txgain =
+						      nphy_tpc_5GHz_txgain_rev3
+								   [txpi[core]];
+					} else if (NREV_IS(phyrev, 4)) {
+						txgain = (
+						  pi->srom_fem5g.extpagain ==
+						  3) ?
+						  nphy_tpc_5GHz_txgain_HiPwrEPA
+						 [txpi[core]] :
+						 nphy_tpc_5GHz_txgain_rev4
+						 [txpi[core]];
+					} else {
+						txgain =
+						      nphy_tpc_5GHz_txgain_rev5
+								   [txpi[core]];
+					}
+				} else {
+					if (NREV_GE(phyrev, 5) &&
+					    (pi->srom_fem2g.extpagain == 3)) {
+						txgain =
+							nphy_tpc_txgain_HiPwrEPA
+							[txpi[core]];
+					} else {
+						txgain = nphy_tpc_txgain_rev3
+							 [txpi[core]];
+					}
+				}
+			}
+		} else {
+			txgain = nphy_tpc_txgain[txpi[core]];
+		}
+
+		if (NREV_GE(phyrev, 3))
+			rad_gain = (txgain >> 16) & ((1 << (32 - 16 + 1)) - 1);
+		else
+			rad_gain = (txgain >> 16) & ((1 << (28 - 16 + 1)) - 1);
+
+		if (NREV_GE(phyrev, 7))
+			dac_gain = (txgain >> 8) & ((1 << (10 - 8 + 1)) - 1);
+		else
+			dac_gain = (txgain >> 8) & ((1 << (13 - 8 + 1)) - 1);
+
+		bbmult = (txgain >> 0) & ((1 << (7 - 0 + 1)) - 1);
+
+		if (NREV_GE(phyrev, 3))
+			mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
+					 0xa5), (0x1 << 8), (0x1 << 8));
+		else
+			mod_phy_reg(pi, 0xa5, (0x1 << 14), (0x1 << 14));
+
+		write_phy_reg(pi, (core == PHY_CORE_0) ? 0xaa : 0xab, dac_gain);
+
+		wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16,
+					 &rad_gain);
+
+		wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2);
+		m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00);
+		m1m2 |= ((core == PHY_CORE_0) ? (bbmult << 8) : (bbmult << 0));
+		wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2);
+
+		if (PHY_IPA(pi)) {
+			wlc_phy_table_read_nphy(pi,
+						(core ==
+						 PHY_CORE_0 ?
+						 NPHY_TBL_ID_CORE1TXPWRCTL :
+						 NPHY_TBL_ID_CORE2TXPWRCTL), 1,
+						576 + txpi[core], 32,
+						&rfpwr_offset);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+				    0x29b, (0x1ff << 4),
+				    ((s16) rfpwr_offset) << 4);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+				    0x29b, (0x1 << 2), (1) << 2);
+
+		}
+	}
+
+	and_phy_reg(pi, 0xbf, (u16) (~(0x1f << 0)));
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void
+wlc_phy_txpwr_nphy_srom_convert(u8 *srom_max, u16 *pwr_offset,
+				u8 tmp_max_pwr, u8 rate_start,
+				u8 rate_end)
+{
+	u8 rate;
+	u8 word_num, nibble_num;
+	u8 tmp_nibble;
+
+	for (rate = rate_start; rate <= rate_end; rate++) {
+		word_num = (rate - rate_start) >> 2;
+		nibble_num = (rate - rate_start) & 0x3;
+		tmp_nibble = (pwr_offset[word_num] >> 4 * nibble_num) & 0xf;
+
+		srom_max[rate] = tmp_max_pwr - 2 * tmp_nibble;
+	}
+}
+
+static void
+wlc_phy_txpwr_nphy_po_apply(u8 *srom_max, u8 pwr_offset,
+			    u8 rate_start, u8 rate_end)
+{
+	u8 rate;
+
+	for (rate = rate_start; rate <= rate_end; rate++)
+		srom_max[rate] -= 2 * pwr_offset;
+}
+
+void
+wlc_phy_ofdm_to_mcs_powers_nphy(u8 *power, u8 rate_mcs_start,
+				u8 rate_mcs_end, u8 rate_ofdm_start)
+{
+	u8 rate1, rate2;
+
+	rate2 = rate_ofdm_start;
+	for (rate1 = rate_mcs_start; rate1 <= rate_mcs_end - 1; rate1++) {
+		power[rate1] = power[rate2];
+		rate2 += (rate1 == rate_mcs_start) ? 2 : 1;
+	}
+	power[rate_mcs_end] = power[rate_mcs_end - 1];
+}
+
+void
+wlc_phy_mcs_to_ofdm_powers_nphy(u8 *power, u8 rate_ofdm_start,
+				u8 rate_ofdm_end, u8 rate_mcs_start)
+{
+	u8 rate1, rate2;
+
+	for (rate1 = rate_ofdm_start, rate2 = rate_mcs_start;
+	     rate1 <= rate_ofdm_end; rate1++, rate2++) {
+		power[rate1] = power[rate2];
+		if (rate1 == rate_ofdm_start)
+			power[++rate1] = power[rate2];
+	}
+}
+
+void wlc_phy_txpwr_apply_nphy(struct brcms_phy *pi)
+{
+	uint rate1, rate2, band_num;
+	u8 tmp_bw40po = 0, tmp_cddpo = 0, tmp_stbcpo = 0;
+	u8 tmp_max_pwr = 0;
+	u16 pwr_offsets1[2], *pwr_offsets2 = NULL;
+	u8 *tx_srom_max_rate = NULL;
+
+	for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP);
+	     band_num++) {
+		switch (band_num) {
+		case 0:
+
+			tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_2g,
+					  pi->nphy_pwrctrl_info[1].max_pwr_2g);
+
+			pwr_offsets1[0] = pi->cck2gpo;
+			wlc_phy_txpwr_nphy_srom_convert(pi->tx_srom_max_rate_2g,
+							pwr_offsets1,
+							tmp_max_pwr,
+							TXP_FIRST_CCK,
+							TXP_LAST_CCK);
+
+			pwr_offsets1[0] = (u16) (pi->ofdm2gpo & 0xffff);
+			pwr_offsets1[1] =
+				(u16) (pi->ofdm2gpo >> 16) & 0xffff;
+
+			pwr_offsets2 = pi->mcs2gpo;
+
+			tmp_cddpo = pi->cdd2gpo;
+			tmp_stbcpo = pi->stbc2gpo;
+			tmp_bw40po = pi->bw402gpo;
+
+			tx_srom_max_rate = pi->tx_srom_max_rate_2g;
+			break;
+		case 1:
+
+			tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gm,
+					  pi->nphy_pwrctrl_info[1].max_pwr_5gm);
+
+			pwr_offsets1[0] = (u16) (pi->ofdm5gpo & 0xffff);
+			pwr_offsets1[1] =
+				(u16) (pi->ofdm5gpo >> 16) & 0xffff;
+
+			pwr_offsets2 = pi->mcs5gpo;
+
+			tmp_cddpo = pi->cdd5gpo;
+			tmp_stbcpo = pi->stbc5gpo;
+			tmp_bw40po = pi->bw405gpo;
+
+			tx_srom_max_rate = pi->tx_srom_max_rate_5g_mid;
+			break;
+		case 2:
+
+			tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gl,
+					  pi->nphy_pwrctrl_info[1].max_pwr_5gl);
+
+			pwr_offsets1[0] = (u16) (pi->ofdm5glpo & 0xffff);
+			pwr_offsets1[1] =
+				(u16) (pi->ofdm5glpo >> 16) & 0xffff;
+
+			pwr_offsets2 = pi->mcs5glpo;
+
+			tmp_cddpo = pi->cdd5glpo;
+			tmp_stbcpo = pi->stbc5glpo;
+			tmp_bw40po = pi->bw405glpo;
+
+			tx_srom_max_rate = pi->tx_srom_max_rate_5g_low;
+			break;
+		case 3:
+
+			tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gh,
+					  pi->nphy_pwrctrl_info[1].max_pwr_5gh);
+
+			pwr_offsets1[0] = (u16) (pi->ofdm5ghpo & 0xffff);
+			pwr_offsets1[1] =
+				(u16) (pi->ofdm5ghpo >> 16) & 0xffff;
+
+			pwr_offsets2 = pi->mcs5ghpo;
+
+			tmp_cddpo = pi->cdd5ghpo;
+			tmp_stbcpo = pi->stbc5ghpo;
+			tmp_bw40po = pi->bw405ghpo;
+
+			tx_srom_max_rate = pi->tx_srom_max_rate_5g_hi;
+			break;
+		}
+
+		wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets1,
+						tmp_max_pwr, TXP_FIRST_OFDM,
+						TXP_LAST_OFDM);
+
+		wlc_phy_ofdm_to_mcs_powers_nphy(tx_srom_max_rate,
+						TXP_FIRST_MCS_20_SISO,
+						TXP_LAST_MCS_20_SISO,
+						TXP_FIRST_OFDM);
+
+		wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets2,
+						tmp_max_pwr,
+						TXP_FIRST_MCS_20_CDD,
+						TXP_LAST_MCS_20_CDD);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3))
+			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, tmp_cddpo,
+						    TXP_FIRST_MCS_20_CDD,
+						    TXP_LAST_MCS_20_CDD);
+
+		wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate,
+						TXP_FIRST_OFDM_20_CDD,
+						TXP_LAST_OFDM_20_CDD,
+						TXP_FIRST_MCS_20_CDD);
+
+		wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets2,
+						tmp_max_pwr,
+						TXP_FIRST_MCS_20_STBC,
+						TXP_LAST_MCS_20_STBC);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3))
+			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate,
+						    tmp_stbcpo,
+						    TXP_FIRST_MCS_20_STBC,
+						    TXP_LAST_MCS_20_STBC);
+
+		wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
+						&pwr_offsets2[2], tmp_max_pwr,
+						TXP_FIRST_MCS_20_SDM,
+						TXP_LAST_MCS_20_SDM);
+
+		if (NPHY_IS_SROM_REINTERPRET) {
+
+			wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
+							&pwr_offsets2[4],
+							tmp_max_pwr,
+							TXP_FIRST_MCS_40_SISO,
+							TXP_LAST_MCS_40_SISO);
+
+			wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate,
+							TXP_FIRST_OFDM_40_SISO,
+							TXP_LAST_OFDM_40_SISO,
+							TXP_FIRST_MCS_40_SISO);
+
+			wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
+							&pwr_offsets2[4],
+							tmp_max_pwr,
+							TXP_FIRST_MCS_40_CDD,
+							TXP_LAST_MCS_40_CDD);
+
+			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, tmp_cddpo,
+						    TXP_FIRST_MCS_40_CDD,
+						    TXP_LAST_MCS_40_CDD);
+
+			wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate,
+							TXP_FIRST_OFDM_40_CDD,
+							TXP_LAST_OFDM_40_CDD,
+							TXP_FIRST_MCS_40_CDD);
+
+			wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
+							&pwr_offsets2[4],
+							tmp_max_pwr,
+							TXP_FIRST_MCS_40_STBC,
+							TXP_LAST_MCS_40_STBC);
+
+			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate,
+						    tmp_stbcpo,
+						    TXP_FIRST_MCS_40_STBC,
+						    TXP_LAST_MCS_40_STBC);
+
+			wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
+							&pwr_offsets2[6],
+							tmp_max_pwr,
+							TXP_FIRST_MCS_40_SDM,
+							TXP_LAST_MCS_40_SDM);
+		} else {
+
+			for (rate1 = TXP_FIRST_OFDM_40_SISO, rate2 =
+				     TXP_FIRST_OFDM;
+			     rate1 <= TXP_LAST_MCS_40_SDM;
+			     rate1++, rate2++)
+				tx_srom_max_rate[rate1] =
+					tx_srom_max_rate[rate2];
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3))
+			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate,
+						    tmp_bw40po,
+						    TXP_FIRST_OFDM_40_SISO,
+						    TXP_LAST_MCS_40_SDM);
+
+		tx_srom_max_rate[TXP_MCS_32] =
+			tx_srom_max_rate[TXP_FIRST_MCS_40_CDD];
+	}
+
+	return;
+}
+
+void wlc_phy_txpower_recalc_target_nphy(struct brcms_phy *pi)
+{
+	u8 tx_pwr_ctrl_state;
+	wlc_phy_txpwr_limit_to_tbl_nphy(pi);
+	wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
+
+	tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
+
+	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
+		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
+		(void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
+		udelay(1);
+	}
+
+	wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
+
+	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
+		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
+}
+
+static bool wlc_phy_txpwr_ison_nphy(struct brcms_phy *pi)
+{
+	return read_phy_reg((pi), 0x1e7) & ((0x1 << 15) |
+					    (0x1 << 14) | (0x1 << 13));
+}
+
+u16 wlc_phy_txpwr_idx_get_nphy(struct brcms_phy *pi)
+{
+	u16 tmp;
+	u16 pwr_idx[2];
+
+	if (wlc_phy_txpwr_ison_nphy(pi)) {
+		pwr_idx[0] = wlc_phy_txpwr_idx_cur_get_nphy(pi, PHY_CORE_0);
+		pwr_idx[1] = wlc_phy_txpwr_idx_cur_get_nphy(pi, PHY_CORE_1);
+
+		tmp = (pwr_idx[0] << 8) | pwr_idx[1];
+	} else {
+		tmp = ((pi->nphy_txpwrindex[PHY_CORE_0].index_internal & 0xff)
+			<< 8) |
+			(pi->nphy_txpwrindex[PHY_CORE_1].index_internal & 0xff);
+	}
+
+	return tmp;
+}
+
+void wlc_phy_txpwr_papd_cal_nphy(struct brcms_phy *pi)
+{
+	if (PHY_IPA(pi)
+	    && (pi->nphy_force_papd_cal
+		|| (wlc_phy_txpwr_ison_nphy(pi)
+		    &&
+		    (((u32)
+		      abs(wlc_phy_txpwr_idx_cur_get_nphy(pi, 0) -
+			  pi->nphy_papd_tx_gain_at_last_cal[0]) >= 4)
+		     || ((u32)
+			 abs(wlc_phy_txpwr_idx_cur_get_nphy(pi, 1) -
+			     pi->nphy_papd_tx_gain_at_last_cal[1]) >= 4)))))
+		wlc_phy_a4(pi, true);
+}
+
+void wlc_phy_txpwrctrl_enable_nphy(struct brcms_phy *pi, u8 ctrl_type)
+{
+	u16 mask = 0, val = 0, ishw = 0;
+	u8 ctr;
+	uint core;
+	u32 tbl_offset;
+	u32 tbl_len;
+	u16 regval[84];
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	switch (ctrl_type) {
+	case PHY_TPC_HW_OFF:
+	case PHY_TPC_HW_ON:
+		pi->nphy_txpwrctrl = ctrl_type;
+		break;
+	default:
+		break;
+	}
+
+	if (ctrl_type == PHY_TPC_HW_OFF) {
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			if (wlc_phy_txpwr_ison_nphy(pi)) {
+				for (core = 0; core < pi->pubpi.phy_corenum;
+				     core++)
+					pi->nphy_txpwr_idx[core] =
+						wlc_phy_txpwr_idx_cur_get_nphy(
+							pi,
+							(u8) core);
+			}
+
+		}
+
+		tbl_len = 84;
+		tbl_offset = 64;
+		for (ctr = 0; ctr < tbl_len; ctr++)
+			regval[ctr] = 0;
+		wlc_phy_table_write_nphy(pi, 26, tbl_len, tbl_offset, 16,
+					 regval);
+		wlc_phy_table_write_nphy(pi, 27, tbl_len, tbl_offset, 16,
+					 regval);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3))
+			and_phy_reg(pi, 0x1e7,
+				    (u16) (~((0x1 << 15) |
+					     (0x1 << 14) | (0x1 << 13))));
+		else
+			and_phy_reg(pi, 0x1e7,
+				    (u16) (~((0x1 << 14) | (0x1 << 13))));
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			or_phy_reg(pi, 0x8f, (0x1 << 8));
+			or_phy_reg(pi, 0xa5, (0x1 << 8));
+		} else {
+			or_phy_reg(pi, 0xa5, (0x1 << 14));
+		}
+
+		if (NREV_IS(pi->pubpi.phy_rev, 2))
+			mod_phy_reg(pi, 0xdc, 0x00ff, 0x53);
+		else if (NREV_LT(pi->pubpi.phy_rev, 2))
+			mod_phy_reg(pi, 0xdc, 0x00ff, 0x5a);
+
+		if (NREV_LT(pi->pubpi.phy_rev, 2) &&
+		    pi->bw == WL_CHANSPEC_BW_40)
+			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_IQSWAP_WAR,
+				       MHF1_IQSWAP_WAR, BRCM_BAND_ALL);
+
+	} else {
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 84, 64,
+					 8, pi->adj_pwr_tbl_nphy);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 84, 64,
+					 8, pi->adj_pwr_tbl_nphy);
+
+		ishw = (ctrl_type == PHY_TPC_HW_ON) ? 0x1 : 0x0;
+		mask = (0x1 << 14) | (0x1 << 13);
+		val = (ishw << 14) | (ishw << 13);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			mask |= (0x1 << 15);
+			val |= (ishw << 15);
+		}
+
+		mod_phy_reg(pi, 0x1e7, mask, val);
+
+		if (CHSPEC_IS5G(pi->radio_chanspec)) {
+			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+				mod_phy_reg(pi, 0x1e7, (0x7f << 0), 0x32);
+				mod_phy_reg(pi, 0x222, (0xff << 0), 0x32);
+			} else {
+				mod_phy_reg(pi, 0x1e7, (0x7f << 0), 0x64);
+				if (NREV_GT(pi->pubpi.phy_rev, 1))
+					mod_phy_reg(pi, 0x222,
+						    (0xff << 0), 0x64);
+			}
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			if ((pi->nphy_txpwr_idx[0] != 128)
+			    && (pi->nphy_txpwr_idx[1] != 128))
+				wlc_phy_txpwr_idx_cur_set_nphy(pi,
+							       pi->
+							       nphy_txpwr_idx
+							       [0],
+							       pi->
+							       nphy_txpwr_idx
+							       [1]);
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			and_phy_reg(pi, 0x8f, ~(0x1 << 8));
+			and_phy_reg(pi, 0xa5, ~(0x1 << 8));
+		} else {
+			and_phy_reg(pi, 0xa5, ~(0x1 << 14));
+		}
+
+		if (NREV_IS(pi->pubpi.phy_rev, 2))
+			mod_phy_reg(pi, 0xdc, 0x00ff, 0x3b);
+		else if (NREV_LT(pi->pubpi.phy_rev, 2))
+			mod_phy_reg(pi, 0xdc, 0x00ff, 0x40);
+
+		if (NREV_LT(pi->pubpi.phy_rev, 2) &&
+		    pi->bw == WL_CHANSPEC_BW_40)
+			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_IQSWAP_WAR,
+				       0x0, BRCM_BAND_ALL);
+
+		if (PHY_IPA(pi)) {
+			mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
+				    0x29b, (0x1 << 2), (0) << 2);
+
+			mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
+				    0x29b, (0x1 << 2), (0) << 2);
+
+		}
+
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+void
+wlc_phy_txpwr_index_nphy(struct brcms_phy *pi, u8 core_mask, s8 txpwrindex,
+			 bool restore_cals)
+{
+	u8 core, txpwrctl_tbl;
+	u16 tx_ind0, iq_ind0, lo_ind0;
+	u16 m1m2;
+	u32 txgain;
+	u16 rad_gain, dac_gain;
+	u8 bbmult;
+	u32 iqcomp;
+	u16 iqcomp_a, iqcomp_b;
+	u32 locomp;
+	u16 tmpval;
+	u8 tx_pwr_ctrl_state;
+	s32 rfpwr_offset;
+	u16 regval[2];
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	tx_ind0 = 192;
+	iq_ind0 = 320;
+	lo_ind0 = 448;
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+		if ((core_mask & (1 << core)) == 0)
+			continue;
+
+		txpwrctl_tbl = (core == PHY_CORE_0) ? 26 : 27;
+
+		if (txpwrindex < 0) {
+			if (pi->nphy_txpwrindex[core].index < 0)
+				continue;
+
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				mod_phy_reg(pi, 0x8f,
+					    (0x1 << 8),
+					    pi->nphy_txpwrindex[core].
+					    AfectrlOverride);
+				mod_phy_reg(pi, 0xa5, (0x1 << 8),
+					    pi->nphy_txpwrindex[core].
+					    AfectrlOverride);
+			} else {
+				mod_phy_reg(pi, 0xa5,
+					    (0x1 << 14),
+					    pi->nphy_txpwrindex[core].
+					    AfectrlOverride);
+			}
+
+			write_phy_reg(pi, (core == PHY_CORE_0) ?
+				      0xaa : 0xab,
+				      pi->nphy_txpwrindex[core].AfeCtrlDacGain);
+
+			wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16,
+						 &pi->nphy_txpwrindex[core].
+						 rad_gain);
+
+			wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2);
+			m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00);
+			m1m2 |= ((core == PHY_CORE_0) ?
+				 (pi->nphy_txpwrindex[core].bbmult << 8) :
+				 (pi->nphy_txpwrindex[core].bbmult << 0));
+			wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2);
+
+			if (restore_cals) {
+				wlc_phy_table_write_nphy(
+					pi, 15, 2, (80 + 2 * core), 16,
+					&pi->nphy_txpwrindex[core].iqcomp_a);
+				wlc_phy_table_write_nphy(
+					pi, 15, 1, (85 + core), 16,
+					&pi->nphy_txpwrindex[core].locomp);
+				wlc_phy_table_write_nphy(
+					pi, 15, 1, (93 + core), 16,
+					&pi->nphy_txpwrindex[core].locomp);
+			}
+
+			wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl);
+
+			pi->nphy_txpwrindex[core].index_internal =
+				pi->nphy_txpwrindex[core].index_internal_save;
+		} else {
+
+			if (pi->nphy_txpwrindex[core].index < 0) {
+
+				if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+					mod_phy_reg(pi, 0x8f,
+						    (0x1 << 8),
+						    pi->nphy_txpwrindex[core].
+						    AfectrlOverride);
+					mod_phy_reg(pi, 0xa5, (0x1 << 8),
+						    pi->nphy_txpwrindex[core].
+						    AfectrlOverride);
+				} else {
+					pi->nphy_txpwrindex[core].
+					AfectrlOverride =
+						read_phy_reg(pi, 0xa5);
+				}
+
+				pi->nphy_txpwrindex[core].AfeCtrlDacGain =
+					read_phy_reg(pi, (core == PHY_CORE_0) ?
+							 0xaa : 0xab);
+
+				wlc_phy_table_read_nphy(pi, 7, 1,
+							(0x110 + core), 16,
+							&pi->
+							nphy_txpwrindex[core].
+							rad_gain);
+
+				wlc_phy_table_read_nphy(pi, 15, 1, 87, 16,
+							&tmpval);
+				tmpval >>= ((core == PHY_CORE_0) ? 8 : 0);
+				tmpval &= 0xff;
+				pi->nphy_txpwrindex[core].bbmult = (u8) tmpval;
+
+				wlc_phy_table_read_nphy(pi, 15, 2,
+							(80 + 2 * core), 16,
+							&pi->
+							nphy_txpwrindex[core].
+							iqcomp_a);
+
+				wlc_phy_table_read_nphy(pi, 15, 1, (85 + core),
+							16,
+							&pi->
+							nphy_txpwrindex[core].
+							locomp);
+
+				pi->nphy_txpwrindex[core].index_internal_save =
+					pi->nphy_txpwrindex[core].
+					index_internal;
+			}
+
+			tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
+			wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
+
+			if (NREV_IS(pi->pubpi.phy_rev, 1))
+				wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
+
+			wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1,
+						(tx_ind0 + txpwrindex), 32,
+						&txgain);
+
+			if (NREV_GE(pi->pubpi.phy_rev, 3))
+				rad_gain = (txgain >> 16) &
+					   ((1 << (32 - 16 + 1)) - 1);
+			else
+				rad_gain = (txgain >> 16) &
+					   ((1 << (28 - 16 + 1)) - 1);
+
+			dac_gain = (txgain >> 8) & ((1 << (13 - 8 + 1)) - 1);
+			bbmult = (txgain >> 0) & ((1 << (7 - 0 + 1)) - 1);
+
+			if (NREV_GE(pi->pubpi.phy_rev, 3))
+				mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
+						 0xa5), (0x1 << 8), (0x1 << 8));
+			else
+				mod_phy_reg(pi, 0xa5, (0x1 << 14), (0x1 << 14));
+
+			write_phy_reg(pi, (core == PHY_CORE_0) ?
+				      0xaa : 0xab, dac_gain);
+
+			wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16,
+						 &rad_gain);
+
+			wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2);
+			m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00);
+			m1m2 |= ((core == PHY_CORE_0) ?
+				(bbmult << 8) : (bbmult << 0));
+
+			wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2);
+
+			wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1,
+						(iq_ind0 + txpwrindex), 32,
+						&iqcomp);
+			iqcomp_a = (iqcomp >> 10) & ((1 << (19 - 10 + 1)) - 1);
+			iqcomp_b = (iqcomp >> 0) & ((1 << (9 - 0 + 1)) - 1);
+
+			if (restore_cals) {
+				regval[0] = (u16) iqcomp_a;
+				regval[1] = (u16) iqcomp_b;
+				wlc_phy_table_write_nphy(pi, 15, 2,
+							 (80 + 2 * core), 16,
+							 regval);
+			}
+
+			wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1,
+						(lo_ind0 + txpwrindex), 32,
+						&locomp);
+			if (restore_cals)
+				wlc_phy_table_write_nphy(pi, 15, 1, (85 + core),
+							 16, &locomp);
+
+			if (NREV_IS(pi->pubpi.phy_rev, 1))
+				wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
+
+			if (PHY_IPA(pi)) {
+				wlc_phy_table_read_nphy(pi,
+						(core == PHY_CORE_0 ?
+						 NPHY_TBL_ID_CORE1TXPWRCTL :
+						 NPHY_TBL_ID_CORE2TXPWRCTL),
+						1, 576 + txpwrindex, 32,
+						&rfpwr_offset);
+
+				mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+					    0x29b, (0x1ff << 4),
+					    ((s16) rfpwr_offset) << 4);
+
+				mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+					    0x29b, (0x1 << 2), (1) << 2);
+
+			}
+
+			wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
+		}
+
+		pi->nphy_txpwrindex[core].index = txpwrindex;
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+void
+wlc_phy_txpower_sromlimit_get_nphy(struct brcms_phy *pi, uint chan, u8 *max_pwr,
+				   u8 txp_rate_idx)
+{
+	u8 chan_freq_range;
+
+	chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, chan);
+	switch (chan_freq_range) {
+	case WL_CHAN_FREQ_RANGE_2G:
+		*max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx];
+		break;
+	case WL_CHAN_FREQ_RANGE_5GM:
+		*max_pwr = pi->tx_srom_max_rate_5g_mid[txp_rate_idx];
+		break;
+	case WL_CHAN_FREQ_RANGE_5GL:
+		*max_pwr = pi->tx_srom_max_rate_5g_low[txp_rate_idx];
+		break;
+	case WL_CHAN_FREQ_RANGE_5GH:
+		*max_pwr = pi->tx_srom_max_rate_5g_hi[txp_rate_idx];
+		break;
+	default:
+		*max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx];
+		break;
+	}
+
+	return;
+}
+
+void wlc_phy_stay_in_carriersearch_nphy(struct brcms_phy *pi, bool enable)
+{
+	u16 clip_off[] = { 0xffff, 0xffff };
+
+	if (enable) {
+		if (pi->nphy_deaf_count == 0) {
+			pi->classifier_state =
+				wlc_phy_classifier_nphy(pi, 0, 0);
+			wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
+			wlc_phy_clip_det_nphy(pi, 0, pi->clip_state);
+			wlc_phy_clip_det_nphy(pi, 1, clip_off);
+		}
+
+		pi->nphy_deaf_count++;
+
+		wlc_phy_resetcca_nphy(pi);
+
+	} else {
+		pi->nphy_deaf_count--;
+
+		if (pi->nphy_deaf_count == 0) {
+			wlc_phy_classifier_nphy(pi, (0x7 << 0),
+						pi->classifier_state);
+			wlc_phy_clip_det_nphy(pi, 1, pi->clip_state);
+		}
+	}
+}
+
+void wlc_nphy_deaf_mode(struct brcms_phy *pi, bool mode)
+{
+	wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	if (mode) {
+		if (pi->nphy_deaf_count == 0)
+			wlc_phy_stay_in_carriersearch_nphy(pi, true);
+	} else if (pi->nphy_deaf_count > 0) {
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+	}
+
+	wlapi_enable_mac(pi->sh->physhim);
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_qmath.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_qmath.c
new file mode 100644
index 0000000..b24bc57
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_qmath.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "phy_qmath.h"
+
+/*
+ * Description: This function make 16 bit unsigned multiplication.
+ * To fit the output into 16 bits the 32 bit multiplication result is right
+ * shifted by 16 bits.
+ */
+u16 qm_mulu16(u16 op1, u16 op2)
+{
+	return (u16) (((u32) op1 * (u32) op2) >> 16);
+}
+
+/*
+ * Description: This function make 16 bit multiplication and return the result
+ * in 16 bits. To fit the multiplication result into 16 bits the multiplication
+ * result is right shifted by 15 bits. Right shifting 15 bits instead of 16 bits
+ * is done to remove the extra sign bit formed due to the multiplication.
+ * When both the 16bit inputs are 0x8000 then the output is saturated to
+ * 0x7fffffff.
+ */
+s16 qm_muls16(s16 op1, s16 op2)
+{
+	s32 result;
+	if (op1 == (s16) 0x8000 && op2 == (s16) 0x8000)
+		result = 0x7fffffff;
+	else
+		result = ((s32) (op1) * (s32) (op2));
+
+	return (s16) (result >> 15);
+}
+
+/*
+ * Description: This function add two 32 bit numbers and return the 32bit
+ * result. If the result overflow 32 bits, the output will be saturated to
+ * 32bits.
+ */
+s32 qm_add32(s32 op1, s32 op2)
+{
+	s32 result;
+	result = op1 + op2;
+	if (op1 < 0 && op2 < 0 && result > 0)
+		result = 0x80000000;
+	else if (op1 > 0 && op2 > 0 && result < 0)
+		result = 0x7fffffff;
+
+	return result;
+}
+
+/*
+ * Description: This function add two 16 bit numbers and return the 16bit
+ * result. If the result overflow 16 bits, the output will be saturated to
+ * 16bits.
+ */
+s16 qm_add16(s16 op1, s16 op2)
+{
+	s16 result;
+	s32 temp = (s32) op1 + (s32) op2;
+	if (temp > (s32) 0x7fff)
+		result = (s16) 0x7fff;
+	else if (temp < (s32) 0xffff8000)
+		result = (s16) 0xffff8000;
+	else
+		result = (s16) temp;
+
+	return result;
+}
+
+/*
+ * Description: This function make 16 bit subtraction and return the 16bit
+ * result. If the result overflow 16 bits, the output will be saturated to
+ * 16bits.
+ */
+s16 qm_sub16(s16 op1, s16 op2)
+{
+	s16 result;
+	s32 temp = (s32) op1 - (s32) op2;
+	if (temp > (s32) 0x7fff)
+		result = (s16) 0x7fff;
+	else if (temp < (s32) 0xffff8000)
+		result = (s16) 0xffff8000;
+	else
+		result = (s16) temp;
+
+	return result;
+}
+
+/*
+ * Description: This function make a 32 bit saturated left shift when the
+ * specified shift is +ve. This function will make a 32 bit right shift when
+ * the specified shift is -ve. This function return the result after shifting
+ * operation.
+ */
+s32 qm_shl32(s32 op, int shift)
+{
+	int i;
+	s32 result;
+	result = op;
+	if (shift > 31)
+		shift = 31;
+	else if (shift < -31)
+		shift = -31;
+	if (shift >= 0) {
+		for (i = 0; i < shift; i++)
+			result = qm_add32(result, result);
+	} else {
+		result = result >> (-shift);
+	}
+
+	return result;
+}
+
+/*
+ * Description: This function make a 16 bit saturated left shift when the
+ * specified shift is +ve. This function will make a 16 bit right shift when
+ * the specified shift is -ve. This function return the result after shifting
+ * operation.
+ */
+s16 qm_shl16(s16 op, int shift)
+{
+	int i;
+	s16 result;
+	result = op;
+	if (shift > 15)
+		shift = 15;
+	else if (shift < -15)
+		shift = -15;
+	if (shift > 0) {
+		for (i = 0; i < shift; i++)
+			result = qm_add16(result, result);
+	} else {
+		result = result >> (-shift);
+	}
+
+	return result;
+}
+
+/*
+ * Description: This function make a 16 bit right shift when shift is +ve.
+ * This function make a 16 bit saturated left shift when shift is -ve. This
+ * function return the result of the shift operation.
+ */
+s16 qm_shr16(s16 op, int shift)
+{
+	return qm_shl16(op, -shift);
+}
+
+/*
+ * Description: This function return the number of redundant sign bits in a
+ * 32 bit number. Example: qm_norm32(0x00000080) = 23
+ */
+s16 qm_norm32(s32 op)
+{
+	u16 u16extraSignBits;
+	if (op == 0) {
+		return 31;
+	} else {
+		u16extraSignBits = 0;
+		while ((op >> 31) == (op >> 30)) {
+			u16extraSignBits++;
+			op = op << 1;
+		}
+	}
+	return u16extraSignBits;
+}
+
+/* This table is log2(1+(i/32)) where i=[0:1:32], in q.15 format */
+static const s16 log_table[] = {
+	0,
+	1455,
+	2866,
+	4236,
+	5568,
+	6863,
+	8124,
+	9352,
+	10549,
+	11716,
+	12855,
+	13968,
+	15055,
+	16117,
+	17156,
+	18173,
+	19168,
+	20143,
+	21098,
+	22034,
+	22952,
+	23852,
+	24736,
+	25604,
+	26455,
+	27292,
+	28114,
+	28922,
+	29717,
+	30498,
+	31267,
+	32024,
+	32767
+};
+
+#define LOG_TABLE_SIZE 32       /* log_table size */
+#define LOG2_LOG_TABLE_SIZE 5   /* log2(log_table size) */
+#define Q_LOG_TABLE 15          /* qformat of log_table */
+#define LOG10_2         19728   /* log10(2) in q.16 */
+
+/*
+ * Description:
+ * This routine takes the input number N and its q format qN and compute
+ * the log10(N). This routine first normalizes the input no N.	Then N is in
+ * mag*(2^x) format. mag is any number in the range 2^30-(2^31 - 1).
+ * Then log2(mag * 2^x) = log2(mag) + x is computed. From that
+ * log10(mag * 2^x) = log2(mag * 2^x) * log10(2) is computed.
+ * This routine looks the log2 value in the table considering
+ * LOG2_LOG_TABLE_SIZE+1 MSBs. As the MSB is always 1, only next
+ * LOG2_OF_LOG_TABLE_SIZE MSBs are used for table lookup. Next 16 MSBs are used
+ * for interpolation.
+ * Inputs:
+ * N - number to which log10 has to be found.
+ * qN - q format of N
+ * log10N - address where log10(N) will be written.
+ * qLog10N - address where log10N qformat will be written.
+ * Note/Problem:
+ * For accurate results input should be in normalized or near normalized form.
+ */
+void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N)
+{
+	s16 s16norm, s16tableIndex, s16errorApproximation;
+	u16 u16offset;
+	s32 s32log;
+
+	/* normalize the N. */
+	s16norm = qm_norm32(N);
+	N = N << s16norm;
+
+	/* The qformat of N after normalization.
+	 * -30 is added to treat the no as between 1.0 to 2.0
+	 * i.e. after adding the -30 to the qformat the decimal point will be
+	 * just rigtht of the MSB. (i.e. after sign bit and 1st MSB). i.e.
+	 * at the right side of 30th bit.
+	 */
+	qN = qN + s16norm - 30;
+
+	/* take the table index as the LOG2_OF_LOG_TABLE_SIZE bits right of the
+	 * MSB */
+	s16tableIndex = (s16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE)));
+
+	/* remove the MSB. the MSB is always 1 after normalization. */
+	s16tableIndex =
+		s16tableIndex & (s16) ((1 << LOG2_LOG_TABLE_SIZE) - 1);
+
+	/* remove the (1+LOG2_OF_LOG_TABLE_SIZE) MSBs in the N. */
+	N = N & ((1 << (32 - (2 + LOG2_LOG_TABLE_SIZE))) - 1);
+
+	/* take the offset as the 16 MSBS after table index.
+	 */
+	u16offset = (u16) (N >> (32 - (2 + LOG2_LOG_TABLE_SIZE + 16)));
+
+	/* look the log value in the table. */
+	s32log = log_table[s16tableIndex];      /* q.15 format */
+
+	/* interpolate using the offset. q.15 format. */
+	s16errorApproximation = (s16) qm_mulu16(u16offset,
+				(u16) (log_table[s16tableIndex + 1] -
+				       log_table[s16tableIndex]));
+
+	 /* q.15 format */
+	s32log = qm_add16((s16) s32log, s16errorApproximation);
+
+	/* adjust for the qformat of the N as
+	 * log2(mag * 2^x) = log2(mag) + x
+	 */
+	s32log = qm_add32(s32log, ((s32) -qN) << 15);   /* q.15 format */
+
+	/* normalize the result. */
+	s16norm = qm_norm32(s32log);
+
+	/* bring all the important bits into lower 16 bits */
+	/* q.15+s16norm-16 format */
+	s32log = qm_shl32(s32log, s16norm - 16);
+
+	/* compute the log10(N) by multiplying log2(N) with log10(2).
+	 * as log10(mag * 2^x) = log2(mag * 2^x) * log10(2)
+	 * log10N in q.15+s16norm-16+1 (LOG10_2 is in q.16)
+	 */
+	*log10N = qm_muls16((s16) s32log, (s16) LOG10_2);
+
+	/* write the q format of the result. */
+	*qLog10N = 15 + s16norm - 16 + 1;
+
+	return;
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_qmath.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_qmath.h
new file mode 100644
index 0000000..20e3783
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_qmath.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_QMATH_H_
+#define _BRCM_QMATH_H_
+
+#include <types.h>
+
+u16 qm_mulu16(u16 op1, u16 op2);
+
+s16 qm_muls16(s16 op1, s16 op2);
+
+s32 qm_add32(s32 op1, s32 op2);
+
+s16 qm_add16(s16 op1, s16 op2);
+
+s16 qm_sub16(s16 op1, s16 op2);
+
+s32 qm_shl32(s32 op, int shift);
+
+s16 qm_shl16(s16 op, int shift);
+
+s16 qm_shr16(s16 op, int shift);
+
+s16 qm_norm32(s32 op);
+
+void qm_log10(s32 N, s16 qN, s16 *log10N, s16 *qLog10N);
+
+#endif				/* #ifndef _BRCM_QMATH_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_radio.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_radio.h
new file mode 100644
index 0000000..c3a6754
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_radio.h
@@ -0,0 +1,1533 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_BRCM_PHY_RADIO_H_
+#define	_BRCM_PHY_RADIO_H_
+
+#define	RADIO_IDCODE			0x01
+
+#define RADIO_DEFAULT_CORE		0
+
+#define	RXC0_RSSI_RST			0x80
+#define	RXC0_MODE_RSSI			0x40
+#define	RXC0_MODE_OFF			0x20
+#define	RXC0_MODE_CM			0x10
+#define	RXC0_LAN_LOAD			0x08
+#define	RXC0_OFF_ADJ_MASK		0x07
+
+#define	TXC0_MODE_TXLPF			0x04
+#define	TXC0_PA_TSSI_EN			0x02
+#define	TXC0_TSSI_EN			0x01
+
+#define	TXC1_PA_GAIN_MASK		0x60
+#define	TXC1_PA_GAIN_3DB		0x40
+#define	TXC1_PA_GAIN_2DB		0x20
+#define	TXC1_TX_MIX_GAIN		0x10
+#define	TXC1_OFF_I_MASK			0x0c
+#define	TXC1_OFF_Q_MASK			0x03
+
+#define	RADIO_2055_READ_OFF		0x100
+#define	RADIO_2057_READ_OFF		0x200
+
+#define RADIO_2055_GEN_SPARE		0x00
+#define RADIO_2055_SP_PIN_PD		0x02
+#define RADIO_2055_SP_RSSI_CORE1	0x03
+#define RADIO_2055_SP_PD_MISC_CORE1	0x04
+#define RADIO_2055_SP_RSSI_CORE2	0x05
+#define RADIO_2055_SP_PD_MISC_CORE2	0x06
+#define RADIO_2055_SP_RX_GC1_CORE1	0x07
+#define RADIO_2055_SP_RX_GC2_CORE1	0x08
+#define RADIO_2055_SP_RX_GC1_CORE2	0x09
+#define RADIO_2055_SP_RX_GC2_CORE2	0x0a
+#define RADIO_2055_SP_LPF_BW_SELECT_CORE1 0x0b
+#define RADIO_2055_SP_LPF_BW_SELECT_CORE2 0x0c
+#define RADIO_2055_SP_TX_GC1_CORE1	0x0d
+#define RADIO_2055_SP_TX_GC2_CORE1	0x0e
+#define RADIO_2055_SP_TX_GC1_CORE2	0x0f
+#define RADIO_2055_SP_TX_GC2_CORE2	0x10
+#define RADIO_2055_MASTER_CNTRL1	0x11
+#define RADIO_2055_MASTER_CNTRL2	0x12
+#define RADIO_2055_PD_LGEN		0x13
+#define RADIO_2055_PD_PLL_TS		0x14
+#define RADIO_2055_PD_CORE1_LGBUF	0x15
+#define RADIO_2055_PD_CORE1_TX		0x16
+#define RADIO_2055_PD_CORE1_RXTX	0x17
+#define RADIO_2055_PD_CORE1_RSSI_MISC	0x18
+#define RADIO_2055_PD_CORE2_LGBUF	0x19
+#define RADIO_2055_PD_CORE2_TX		0x1a
+#define RADIO_2055_PD_CORE2_RXTX	0x1b
+#define RADIO_2055_PD_CORE2_RSSI_MISC	0x1c
+#define RADIO_2055_PWRDET_LGEN		0x1d
+#define RADIO_2055_PWRDET_LGBUF_CORE1	0x1e
+#define RADIO_2055_PWRDET_RXTX_CORE1	0x1f
+#define RADIO_2055_PWRDET_LGBUF_CORE2	0x20
+#define RADIO_2055_PWRDET_RXTX_CORE2	0x21
+#define RADIO_2055_RRCCAL_CNTRL_SPARE	0x22
+#define RADIO_2055_RRCCAL_N_OPT_SEL	0x23
+#define RADIO_2055_CAL_MISC		0x24
+#define RADIO_2055_CAL_COUNTER_OUT	0x25
+#define RADIO_2055_CAL_COUNTER_OUT2	0x26
+#define RADIO_2055_CAL_CVAR_CNTRL	0x27
+#define RADIO_2055_CAL_RVAR_CNTRL	0x28
+#define RADIO_2055_CAL_LPO_CNTRL	0x29
+#define RADIO_2055_CAL_TS		0x2a
+#define RADIO_2055_CAL_RCCAL_READ_TS	0x2b
+#define RADIO_2055_CAL_RCAL_READ_TS	0x2c
+#define RADIO_2055_PAD_DRIVER		0x2d
+#define RADIO_2055_XO_CNTRL1		0x2e
+#define RADIO_2055_XO_CNTRL2		0x2f
+#define RADIO_2055_XO_REGULATOR		0x30
+#define RADIO_2055_XO_MISC		0x31
+#define RADIO_2055_PLL_LF_C1		0x32
+#define RADIO_2055_PLL_CAL_VTH		0x33
+#define RADIO_2055_PLL_LF_C2		0x34
+#define RADIO_2055_PLL_REF		0x35
+#define RADIO_2055_PLL_LF_R1		0x36
+#define RADIO_2055_PLL_PFD_CP		0x37
+#define RADIO_2055_PLL_IDAC_CPOPAMP	0x38
+#define RADIO_2055_PLL_CP_REGULATOR	0x39
+#define RADIO_2055_PLL_RCAL		0x3a
+#define RADIO_2055_RF_PLL_MOD0		0x3b
+#define RADIO_2055_RF_PLL_MOD1		0x3c
+#define RADIO_2055_RF_MMD_IDAC1		0x3d
+#define RADIO_2055_RF_MMD_IDAC0		0x3e
+#define RADIO_2055_RF_MMD_SPARE		0x3f
+#define RADIO_2055_VCO_CAL1		0x40
+#define RADIO_2055_VCO_CAL2		0x41
+#define RADIO_2055_VCO_CAL3		0x42
+#define RADIO_2055_VCO_CAL4		0x43
+#define RADIO_2055_VCO_CAL5		0x44
+#define RADIO_2055_VCO_CAL6		0x45
+#define RADIO_2055_VCO_CAL7		0x46
+#define RADIO_2055_VCO_CAL8		0x47
+#define RADIO_2055_VCO_CAL9		0x48
+#define RADIO_2055_VCO_CAL10		0x49
+#define RADIO_2055_VCO_CAL11		0x4a
+#define RADIO_2055_VCO_CAL12		0x4b
+#define RADIO_2055_VCO_CAL13		0x4c
+#define RADIO_2055_VCO_CAL14		0x4d
+#define RADIO_2055_VCO_CAL15		0x4e
+#define RADIO_2055_VCO_CAL16		0x4f
+#define RADIO_2055_VCO_KVCO		0x50
+#define RADIO_2055_VCO_CAP_TAIL		0x51
+#define RADIO_2055_VCO_IDAC_VCO		0x52
+#define RADIO_2055_VCO_REGULATOR	0x53
+#define RADIO_2055_PLL_RF_VTH		0x54
+#define RADIO_2055_LGBUF_CEN_BUF	0x55
+#define RADIO_2055_LGEN_TUNE1		0x56
+#define RADIO_2055_LGEN_TUNE2		0x57
+#define RADIO_2055_LGEN_IDAC1		0x58
+#define RADIO_2055_LGEN_IDAC2		0x59
+#define RADIO_2055_LGEN_BIAS_CNT	0x5a
+#define RADIO_2055_LGEN_BIAS_IDAC	0x5b
+#define RADIO_2055_LGEN_RCAL		0x5c
+#define RADIO_2055_LGEN_DIV		0x5d
+#define RADIO_2055_LGEN_SPARE2		0x5e
+#define RADIO_2055_CORE1_LGBUF_A_TUNE	0x5f
+#define RADIO_2055_CORE1_LGBUF_G_TUNE	0x60
+#define RADIO_2055_CORE1_LGBUF_DIV	0x61
+#define RADIO_2055_CORE1_LGBUF_A_IDAC	0x62
+#define RADIO_2055_CORE1_LGBUF_G_IDAC	0x63
+#define RADIO_2055_CORE1_LGBUF_IDACFIL_OVR 0x64
+#define RADIO_2055_CORE1_LGBUF_SPARE	0x65
+#define RADIO_2055_CORE1_RXRF_SPC1	0x66
+#define RADIO_2055_CORE1_RXRF_REG1	0x67
+#define RADIO_2055_CORE1_RXRF_REG2	0x68
+#define RADIO_2055_CORE1_RXRF_RCAL	0x69
+#define RADIO_2055_CORE1_RXBB_BUFI_LPFCMP 0x6a
+#define RADIO_2055_CORE1_RXBB_LPF	0x6b
+#define RADIO_2055_CORE1_RXBB_MIDAC_HIPAS 0x6c
+#define RADIO_2055_CORE1_RXBB_VGA1_IDAC	0x6d
+#define RADIO_2055_CORE1_RXBB_VGA2_IDAC	0x6e
+#define RADIO_2055_CORE1_RXBB_VGA3_IDAC	0x6f
+#define RADIO_2055_CORE1_RXBB_BUFO_CTRL	0x70
+#define RADIO_2055_CORE1_RXBB_RCCAL_CTRL 0x71
+#define RADIO_2055_CORE1_RXBB_RSSI_CTRL1 0x72
+#define RADIO_2055_CORE1_RXBB_RSSI_CTRL2 0x73
+#define RADIO_2055_CORE1_RXBB_RSSI_CTRL3 0x74
+#define RADIO_2055_CORE1_RXBB_RSSI_CTRL4 0x75
+#define RADIO_2055_CORE1_RXBB_RSSI_CTRL5 0x76
+#define RADIO_2055_CORE1_RXBB_REGULATOR	0x77
+#define RADIO_2055_CORE1_RXBB_SPARE1	0x78
+#define RADIO_2055_CORE1_RXTXBB_RCAL	0x79
+#define RADIO_2055_CORE1_TXRF_SGM_PGA	0x7a
+#define RADIO_2055_CORE1_TXRF_SGM_PAD	0x7b
+#define RADIO_2055_CORE1_TXRF_CNTR_PGA1	0x7c
+#define RADIO_2055_CORE1_TXRF_CNTR_PAD1	0x7d
+#define RADIO_2055_CORE1_TX_RFPGA_IDAC	0x7e
+#define RADIO_2055_CORE1_TX_PGA_PAD_TN	0x7f
+#define RADIO_2055_CORE1_TX_PAD_IDAC1	0x80
+#define RADIO_2055_CORE1_TX_PAD_IDAC2	0x81
+#define RADIO_2055_CORE1_TX_MX_BGTRIM	0x82
+#define RADIO_2055_CORE1_TXRF_RCAL	0x83
+#define RADIO_2055_CORE1_TXRF_PAD_TSSI1	0x84
+#define RADIO_2055_CORE1_TXRF_PAD_TSSI2	0x85
+#define RADIO_2055_CORE1_TX_RF_SPARE	0x86
+#define RADIO_2055_CORE1_TXRF_IQCAL1	0x87
+#define RADIO_2055_CORE1_TXRF_IQCAL2	0x88
+#define RADIO_2055_CORE1_TXBB_RCCAL_CTRL 0x89
+#define RADIO_2055_CORE1_TXBB_LPF1	0x8a
+#define RADIO_2055_CORE1_TX_VOS_CNCL	0x8b
+#define RADIO_2055_CORE1_TX_LPF_MXGM_IDAC 0x8c
+#define RADIO_2055_CORE1_TX_BB_MXGM	0x8d
+#define RADIO_2055_CORE2_LGBUF_A_TUNE	0x8e
+#define RADIO_2055_CORE2_LGBUF_G_TUNE	0x8f
+#define RADIO_2055_CORE2_LGBUF_DIV	0x90
+#define RADIO_2055_CORE2_LGBUF_A_IDAC	0x91
+#define RADIO_2055_CORE2_LGBUF_G_IDAC	0x92
+#define RADIO_2055_CORE2_LGBUF_IDACFIL_OVR 0x93
+#define RADIO_2055_CORE2_LGBUF_SPARE	0x94
+#define RADIO_2055_CORE2_RXRF_SPC1	0x95
+#define RADIO_2055_CORE2_RXRF_REG1	0x96
+#define RADIO_2055_CORE2_RXRF_REG2	0x97
+#define RADIO_2055_CORE2_RXRF_RCAL	0x98
+#define RADIO_2055_CORE2_RXBB_BUFI_LPFCMP 0x99
+#define RADIO_2055_CORE2_RXBB_LPF	0x9a
+#define RADIO_2055_CORE2_RXBB_MIDAC_HIPAS 0x9b
+#define RADIO_2055_CORE2_RXBB_VGA1_IDAC	0x9c
+#define RADIO_2055_CORE2_RXBB_VGA2_IDAC	0x9d
+#define RADIO_2055_CORE2_RXBB_VGA3_IDAC	0x9e
+#define RADIO_2055_CORE2_RXBB_BUFO_CTRL	0x9f
+#define RADIO_2055_CORE2_RXBB_RCCAL_CTRL 0xa0
+#define RADIO_2055_CORE2_RXBB_RSSI_CTRL1 0xa1
+#define RADIO_2055_CORE2_RXBB_RSSI_CTRL2 0xa2
+#define RADIO_2055_CORE2_RXBB_RSSI_CTRL3 0xa3
+#define RADIO_2055_CORE2_RXBB_RSSI_CTRL4 0xa4
+#define RADIO_2055_CORE2_RXBB_RSSI_CTRL5 0xa5
+#define RADIO_2055_CORE2_RXBB_REGULATOR	0xa6
+#define RADIO_2055_CORE2_RXBB_SPARE1	0xa7
+#define RADIO_2055_CORE2_RXTXBB_RCAL	0xa8
+#define RADIO_2055_CORE2_TXRF_SGM_PGA	0xa9
+#define RADIO_2055_CORE2_TXRF_SGM_PAD	0xaa
+#define RADIO_2055_CORE2_TXRF_CNTR_PGA1	0xab
+#define RADIO_2055_CORE2_TXRF_CNTR_PAD1	0xac
+#define RADIO_2055_CORE2_TX_RFPGA_IDAC	0xad
+#define RADIO_2055_CORE2_TX_PGA_PAD_TN	0xae
+#define RADIO_2055_CORE2_TX_PAD_IDAC1	0xaf
+#define RADIO_2055_CORE2_TX_PAD_IDAC2	0xb0
+#define RADIO_2055_CORE2_TX_MX_BGTRIM	0xb1
+#define RADIO_2055_CORE2_TXRF_RCAL	0xb2
+#define RADIO_2055_CORE2_TXRF_PAD_TSSI1	0xb3
+#define RADIO_2055_CORE2_TXRF_PAD_TSSI2	0xb4
+#define RADIO_2055_CORE2_TX_RF_SPARE	0xb5
+#define RADIO_2055_CORE2_TXRF_IQCAL1	0xb6
+#define RADIO_2055_CORE2_TXRF_IQCAL2	0xb7
+#define RADIO_2055_CORE2_TXBB_RCCAL_CTRL 0xb8
+#define RADIO_2055_CORE2_TXBB_LPF1	0xb9
+#define RADIO_2055_CORE2_TX_VOS_CNCL	0xba
+#define RADIO_2055_CORE2_TX_LPF_MXGM_IDAC 0xbb
+#define RADIO_2055_CORE2_TX_BB_MXGM	0xbc
+#define RADIO_2055_PRG_GC_HPVGA23_21	0xbd
+#define RADIO_2055_PRG_GC_HPVGA23_22	0xbe
+#define RADIO_2055_PRG_GC_HPVGA23_23	0xbf
+#define RADIO_2055_PRG_GC_HPVGA23_24	0xc0
+#define RADIO_2055_PRG_GC_HPVGA23_25	0xc1
+#define RADIO_2055_PRG_GC_HPVGA23_26	0xc2
+#define RADIO_2055_PRG_GC_HPVGA23_27	0xc3
+#define RADIO_2055_PRG_GC_HPVGA23_28	0xc4
+#define RADIO_2055_PRG_GC_HPVGA23_29	0xc5
+#define RADIO_2055_PRG_GC_HPVGA23_30	0xc6
+#define RADIO_2055_CORE1_LNA_GAINBST	0xcd
+#define RADIO_2055_CORE1_B0_NBRSSI_VCM	0xd2
+#define RADIO_2055_CORE1_GEN_SPARE2		0xd6
+#define RADIO_2055_CORE2_LNA_GAINBST	0xd9
+#define RADIO_2055_CORE2_B0_NBRSSI_VCM	0xde
+#define RADIO_2055_CORE2_GEN_SPARE2		0xe2
+
+#define RADIO_2055_GAINBST_GAIN_DB	6
+#define RADIO_2055_GAINBST_CODE		0x6
+
+#define RADIO_2055_JTAGCTRL_MASK	0x04
+#define RADIO_2055_JTAGSYNC_MASK	0x08
+#define RADIO_2055_RRCAL_START		0x40
+#define RADIO_2055_RRCAL_RST_N		0x01
+#define RADIO_2055_CAL_LPO_ENABLE	0x80
+#define RADIO_2055_RCAL_DONE		0x80
+#define RADIO_2055_NBRSSI_VCM_I_MASK	0x03
+#define RADIO_2055_NBRSSI_VCM_I_SHIFT	0x00
+#define RADIO_2055_NBRSSI_VCM_Q_MASK	0x03
+#define RADIO_2055_NBRSSI_VCM_Q_SHIFT	0x00
+#define RADIO_2055_WBRSSI_VCM_IQ_MASK	0x0c
+#define RADIO_2055_WBRSSI_VCM_IQ_SHIFT	0x02
+#define RADIO_2055_NBRSSI_PD		0x01
+#define RADIO_2055_WBRSSI_G1_PD		0x04
+#define RADIO_2055_WBRSSI_G2_PD		0x02
+#define RADIO_2055_NBRSSI_SEL		0x01
+#define RADIO_2055_WBRSSI_G1_SEL	0x04
+#define RADIO_2055_WBRSSI_G2_SEL	0x02
+#define RADIO_2055_COUPLE_RX_MASK	0x01
+#define RADIO_2055_COUPLE_TX_MASK	0x02
+#define RADIO_2055_GAINBST_DISABLE	0x02
+#define RADIO_2055_GAINBST_VAL_MASK	0x07
+#define RADIO_2055_RXMX_GC_MASK		0x0c
+
+#define RADIO_MIMO_CORESEL_OFF		0x0
+#define RADIO_MIMO_CORESEL_CORE1	0x1
+#define RADIO_MIMO_CORESEL_CORE2	0x2
+#define RADIO_MIMO_CORESEL_CORE3	0x3
+#define RADIO_MIMO_CORESEL_CORE4	0x4
+#define RADIO_MIMO_CORESEL_ALLRX	0x5
+#define RADIO_MIMO_CORESEL_ALLTX	0x6
+#define RADIO_MIMO_CORESEL_ALLRXTX	0x7
+
+#define	RADIO_2064_READ_OFF		0x200
+
+#define RADIO_2064_REG000               0x0
+#define RADIO_2064_REG001               0x1
+#define RADIO_2064_REG002               0x2
+#define RADIO_2064_REG003               0x3
+#define RADIO_2064_REG004               0x4
+#define RADIO_2064_REG005               0x5
+#define RADIO_2064_REG006               0x6
+#define RADIO_2064_REG007               0x7
+#define RADIO_2064_REG008               0x8
+#define RADIO_2064_REG009               0x9
+#define RADIO_2064_REG00A               0xa
+#define RADIO_2064_REG00B               0xb
+#define RADIO_2064_REG00C               0xc
+#define RADIO_2064_REG00D               0xd
+#define RADIO_2064_REG00E               0xe
+#define RADIO_2064_REG00F               0xf
+#define RADIO_2064_REG010               0x10
+#define RADIO_2064_REG011               0x11
+#define RADIO_2064_REG012               0x12
+#define RADIO_2064_REG013               0x13
+#define RADIO_2064_REG014               0x14
+#define RADIO_2064_REG015               0x15
+#define RADIO_2064_REG016               0x16
+#define RADIO_2064_REG017               0x17
+#define RADIO_2064_REG018               0x18
+#define RADIO_2064_REG019               0x19
+#define RADIO_2064_REG01A               0x1a
+#define RADIO_2064_REG01B               0x1b
+#define RADIO_2064_REG01C               0x1c
+#define RADIO_2064_REG01D               0x1d
+#define RADIO_2064_REG01E               0x1e
+#define RADIO_2064_REG01F               0x1f
+#define RADIO_2064_REG020               0x20
+#define RADIO_2064_REG021               0x21
+#define RADIO_2064_REG022               0x22
+#define RADIO_2064_REG023               0x23
+#define RADIO_2064_REG024               0x24
+#define RADIO_2064_REG025               0x25
+#define RADIO_2064_REG026               0x26
+#define RADIO_2064_REG027               0x27
+#define RADIO_2064_REG028               0x28
+#define RADIO_2064_REG029               0x29
+#define RADIO_2064_REG02A               0x2a
+#define RADIO_2064_REG02B               0x2b
+#define RADIO_2064_REG02C               0x2c
+#define RADIO_2064_REG02D               0x2d
+#define RADIO_2064_REG02E               0x2e
+#define RADIO_2064_REG02F               0x2f
+#define RADIO_2064_REG030               0x30
+#define RADIO_2064_REG031               0x31
+#define RADIO_2064_REG032               0x32
+#define RADIO_2064_REG033               0x33
+#define RADIO_2064_REG034               0x34
+#define RADIO_2064_REG035               0x35
+#define RADIO_2064_REG036               0x36
+#define RADIO_2064_REG037               0x37
+#define RADIO_2064_REG038               0x38
+#define RADIO_2064_REG039               0x39
+#define RADIO_2064_REG03A               0x3a
+#define RADIO_2064_REG03B               0x3b
+#define RADIO_2064_REG03C               0x3c
+#define RADIO_2064_REG03D               0x3d
+#define RADIO_2064_REG03E               0x3e
+#define RADIO_2064_REG03F               0x3f
+#define RADIO_2064_REG040               0x40
+#define RADIO_2064_REG041               0x41
+#define RADIO_2064_REG042               0x42
+#define RADIO_2064_REG043               0x43
+#define RADIO_2064_REG044               0x44
+#define RADIO_2064_REG045               0x45
+#define RADIO_2064_REG046               0x46
+#define RADIO_2064_REG047               0x47
+#define RADIO_2064_REG048               0x48
+#define RADIO_2064_REG049               0x49
+#define RADIO_2064_REG04A               0x4a
+#define RADIO_2064_REG04B               0x4b
+#define RADIO_2064_REG04C               0x4c
+#define RADIO_2064_REG04D               0x4d
+#define RADIO_2064_REG04E               0x4e
+#define RADIO_2064_REG04F               0x4f
+#define RADIO_2064_REG050               0x50
+#define RADIO_2064_REG051               0x51
+#define RADIO_2064_REG052               0x52
+#define RADIO_2064_REG053               0x53
+#define RADIO_2064_REG054               0x54
+#define RADIO_2064_REG055               0x55
+#define RADIO_2064_REG056               0x56
+#define RADIO_2064_REG057               0x57
+#define RADIO_2064_REG058               0x58
+#define RADIO_2064_REG059               0x59
+#define RADIO_2064_REG05A               0x5a
+#define RADIO_2064_REG05B               0x5b
+#define RADIO_2064_REG05C               0x5c
+#define RADIO_2064_REG05D               0x5d
+#define RADIO_2064_REG05E               0x5e
+#define RADIO_2064_REG05F               0x5f
+#define RADIO_2064_REG060               0x60
+#define RADIO_2064_REG061               0x61
+#define RADIO_2064_REG062               0x62
+#define RADIO_2064_REG063               0x63
+#define RADIO_2064_REG064               0x64
+#define RADIO_2064_REG065               0x65
+#define RADIO_2064_REG066               0x66
+#define RADIO_2064_REG067               0x67
+#define RADIO_2064_REG068               0x68
+#define RADIO_2064_REG069               0x69
+#define RADIO_2064_REG06A               0x6a
+#define RADIO_2064_REG06B               0x6b
+#define RADIO_2064_REG06C               0x6c
+#define RADIO_2064_REG06D               0x6d
+#define RADIO_2064_REG06E               0x6e
+#define RADIO_2064_REG06F               0x6f
+#define RADIO_2064_REG070               0x70
+#define RADIO_2064_REG071               0x71
+#define RADIO_2064_REG072               0x72
+#define RADIO_2064_REG073               0x73
+#define RADIO_2064_REG074               0x74
+#define RADIO_2064_REG075               0x75
+#define RADIO_2064_REG076               0x76
+#define RADIO_2064_REG077               0x77
+#define RADIO_2064_REG078               0x78
+#define RADIO_2064_REG079               0x79
+#define RADIO_2064_REG07A               0x7a
+#define RADIO_2064_REG07B               0x7b
+#define RADIO_2064_REG07C               0x7c
+#define RADIO_2064_REG07D               0x7d
+#define RADIO_2064_REG07E               0x7e
+#define RADIO_2064_REG07F               0x7f
+#define RADIO_2064_REG080               0x80
+#define RADIO_2064_REG081               0x81
+#define RADIO_2064_REG082               0x82
+#define RADIO_2064_REG083               0x83
+#define RADIO_2064_REG084               0x84
+#define RADIO_2064_REG085               0x85
+#define RADIO_2064_REG086               0x86
+#define RADIO_2064_REG087               0x87
+#define RADIO_2064_REG088               0x88
+#define RADIO_2064_REG089               0x89
+#define RADIO_2064_REG08A               0x8a
+#define RADIO_2064_REG08B               0x8b
+#define RADIO_2064_REG08C               0x8c
+#define RADIO_2064_REG08D               0x8d
+#define RADIO_2064_REG08E               0x8e
+#define RADIO_2064_REG08F               0x8f
+#define RADIO_2064_REG090               0x90
+#define RADIO_2064_REG091               0x91
+#define RADIO_2064_REG092               0x92
+#define RADIO_2064_REG093               0x93
+#define RADIO_2064_REG094               0x94
+#define RADIO_2064_REG095               0x95
+#define RADIO_2064_REG096               0x96
+#define RADIO_2064_REG097               0x97
+#define RADIO_2064_REG098               0x98
+#define RADIO_2064_REG099               0x99
+#define RADIO_2064_REG09A               0x9a
+#define RADIO_2064_REG09B               0x9b
+#define RADIO_2064_REG09C               0x9c
+#define RADIO_2064_REG09D               0x9d
+#define RADIO_2064_REG09E               0x9e
+#define RADIO_2064_REG09F               0x9f
+#define RADIO_2064_REG0A0               0xa0
+#define RADIO_2064_REG0A1               0xa1
+#define RADIO_2064_REG0A2               0xa2
+#define RADIO_2064_REG0A3               0xa3
+#define RADIO_2064_REG0A4               0xa4
+#define RADIO_2064_REG0A5               0xa5
+#define RADIO_2064_REG0A6               0xa6
+#define RADIO_2064_REG0A7               0xa7
+#define RADIO_2064_REG0A8               0xa8
+#define RADIO_2064_REG0A9               0xa9
+#define RADIO_2064_REG0AA               0xaa
+#define RADIO_2064_REG0AB               0xab
+#define RADIO_2064_REG0AC               0xac
+#define RADIO_2064_REG0AD               0xad
+#define RADIO_2064_REG0AE               0xae
+#define RADIO_2064_REG0AF               0xaf
+#define RADIO_2064_REG0B0               0xb0
+#define RADIO_2064_REG0B1               0xb1
+#define RADIO_2064_REG0B2               0xb2
+#define RADIO_2064_REG0B3               0xb3
+#define RADIO_2064_REG0B4               0xb4
+#define RADIO_2064_REG0B5               0xb5
+#define RADIO_2064_REG0B6               0xb6
+#define RADIO_2064_REG0B7               0xb7
+#define RADIO_2064_REG0B8               0xb8
+#define RADIO_2064_REG0B9               0xb9
+#define RADIO_2064_REG0BA               0xba
+#define RADIO_2064_REG0BB               0xbb
+#define RADIO_2064_REG0BC               0xbc
+#define RADIO_2064_REG0BD               0xbd
+#define RADIO_2064_REG0BE               0xbe
+#define RADIO_2064_REG0BF               0xbf
+#define RADIO_2064_REG0C0               0xc0
+#define RADIO_2064_REG0C1               0xc1
+#define RADIO_2064_REG0C2               0xc2
+#define RADIO_2064_REG0C3               0xc3
+#define RADIO_2064_REG0C4               0xc4
+#define RADIO_2064_REG0C5               0xc5
+#define RADIO_2064_REG0C6               0xc6
+#define RADIO_2064_REG0C7               0xc7
+#define RADIO_2064_REG0C8               0xc8
+#define RADIO_2064_REG0C9               0xc9
+#define RADIO_2064_REG0CA               0xca
+#define RADIO_2064_REG0CB               0xcb
+#define RADIO_2064_REG0CC               0xcc
+#define RADIO_2064_REG0CD               0xcd
+#define RADIO_2064_REG0CE               0xce
+#define RADIO_2064_REG0CF               0xcf
+#define RADIO_2064_REG0D0               0xd0
+#define RADIO_2064_REG0D1               0xd1
+#define RADIO_2064_REG0D2               0xd2
+#define RADIO_2064_REG0D3               0xd3
+#define RADIO_2064_REG0D4               0xd4
+#define RADIO_2064_REG0D5               0xd5
+#define RADIO_2064_REG0D6               0xd6
+#define RADIO_2064_REG0D7               0xd7
+#define RADIO_2064_REG0D8               0xd8
+#define RADIO_2064_REG0D9               0xd9
+#define RADIO_2064_REG0DA               0xda
+#define RADIO_2064_REG0DB               0xdb
+#define RADIO_2064_REG0DC               0xdc
+#define RADIO_2064_REG0DD               0xdd
+#define RADIO_2064_REG0DE               0xde
+#define RADIO_2064_REG0DF               0xdf
+#define RADIO_2064_REG0E0               0xe0
+#define RADIO_2064_REG0E1               0xe1
+#define RADIO_2064_REG0E2               0xe2
+#define RADIO_2064_REG0E3               0xe3
+#define RADIO_2064_REG0E4               0xe4
+#define RADIO_2064_REG0E5               0xe5
+#define RADIO_2064_REG0E6               0xe6
+#define RADIO_2064_REG0E7               0xe7
+#define RADIO_2064_REG0E8               0xe8
+#define RADIO_2064_REG0E9               0xe9
+#define RADIO_2064_REG0EA               0xea
+#define RADIO_2064_REG0EB               0xeb
+#define RADIO_2064_REG0EC               0xec
+#define RADIO_2064_REG0ED               0xed
+#define RADIO_2064_REG0EE               0xee
+#define RADIO_2064_REG0EF               0xef
+#define RADIO_2064_REG0F0               0xf0
+#define RADIO_2064_REG0F1               0xf1
+#define RADIO_2064_REG0F2               0xf2
+#define RADIO_2064_REG0F3               0xf3
+#define RADIO_2064_REG0F4               0xf4
+#define RADIO_2064_REG0F5               0xf5
+#define RADIO_2064_REG0F6               0xf6
+#define RADIO_2064_REG0F7               0xf7
+#define RADIO_2064_REG0F8               0xf8
+#define RADIO_2064_REG0F9               0xf9
+#define RADIO_2064_REG0FA               0xfa
+#define RADIO_2064_REG0FB               0xfb
+#define RADIO_2064_REG0FC               0xfc
+#define RADIO_2064_REG0FD               0xfd
+#define RADIO_2064_REG0FE               0xfe
+#define RADIO_2064_REG0FF               0xff
+#define RADIO_2064_REG100               0x100
+#define RADIO_2064_REG101               0x101
+#define RADIO_2064_REG102               0x102
+#define RADIO_2064_REG103               0x103
+#define RADIO_2064_REG104               0x104
+#define RADIO_2064_REG105               0x105
+#define RADIO_2064_REG106               0x106
+#define RADIO_2064_REG107               0x107
+#define RADIO_2064_REG108               0x108
+#define RADIO_2064_REG109               0x109
+#define RADIO_2064_REG10A               0x10a
+#define RADIO_2064_REG10B               0x10b
+#define RADIO_2064_REG10C               0x10c
+#define RADIO_2064_REG10D               0x10d
+#define RADIO_2064_REG10E               0x10e
+#define RADIO_2064_REG10F               0x10f
+#define RADIO_2064_REG110               0x110
+#define RADIO_2064_REG111               0x111
+#define RADIO_2064_REG112               0x112
+#define RADIO_2064_REG113               0x113
+#define RADIO_2064_REG114               0x114
+#define RADIO_2064_REG115               0x115
+#define RADIO_2064_REG116               0x116
+#define RADIO_2064_REG117               0x117
+#define RADIO_2064_REG118               0x118
+#define RADIO_2064_REG119               0x119
+#define RADIO_2064_REG11A               0x11a
+#define RADIO_2064_REG11B               0x11b
+#define RADIO_2064_REG11C               0x11c
+#define RADIO_2064_REG11D               0x11d
+#define RADIO_2064_REG11E               0x11e
+#define RADIO_2064_REG11F               0x11f
+#define RADIO_2064_REG120               0x120
+#define RADIO_2064_REG121               0x121
+#define RADIO_2064_REG122               0x122
+#define RADIO_2064_REG123               0x123
+#define RADIO_2064_REG124               0x124
+#define RADIO_2064_REG125               0x125
+#define RADIO_2064_REG126               0x126
+#define RADIO_2064_REG127               0x127
+#define RADIO_2064_REG128               0x128
+#define RADIO_2064_REG129               0x129
+#define RADIO_2064_REG12A               0x12a
+#define RADIO_2064_REG12B               0x12b
+#define RADIO_2064_REG12C               0x12c
+#define RADIO_2064_REG12D               0x12d
+#define RADIO_2064_REG12E               0x12e
+#define RADIO_2064_REG12F               0x12f
+#define RADIO_2064_REG130               0x130
+
+#define RADIO_2056_SYN                           (0x0 << 12)
+#define RADIO_2056_TX0                           (0x2 << 12)
+#define RADIO_2056_TX1                           (0x3 << 12)
+#define RADIO_2056_RX0                           (0x6 << 12)
+#define RADIO_2056_RX1                           (0x7 << 12)
+#define RADIO_2056_ALLTX                         (0xe << 12)
+#define RADIO_2056_ALLRX                         (0xf << 12)
+
+#define RADIO_2056_SYN_RESERVED_ADDR0            0x0
+#define RADIO_2056_SYN_IDCODE                    0x1
+#define RADIO_2056_SYN_RESERVED_ADDR2            0x2
+#define RADIO_2056_SYN_RESERVED_ADDR3            0x3
+#define RADIO_2056_SYN_RESERVED_ADDR4            0x4
+#define RADIO_2056_SYN_RESERVED_ADDR5            0x5
+#define RADIO_2056_SYN_RESERVED_ADDR6            0x6
+#define RADIO_2056_SYN_RESERVED_ADDR7            0x7
+#define RADIO_2056_SYN_COM_CTRL                  0x8
+#define RADIO_2056_SYN_COM_PU                    0x9
+#define RADIO_2056_SYN_COM_OVR                   0xa
+#define RADIO_2056_SYN_COM_RESET                 0xb
+#define RADIO_2056_SYN_COM_RCAL                  0xc
+#define RADIO_2056_SYN_COM_RC_RXLPF              0xd
+#define RADIO_2056_SYN_COM_RC_TXLPF              0xe
+#define RADIO_2056_SYN_COM_RC_RXHPF              0xf
+#define RADIO_2056_SYN_RESERVED_ADDR16           0x10
+#define RADIO_2056_SYN_RESERVED_ADDR17           0x11
+#define RADIO_2056_SYN_RESERVED_ADDR18           0x12
+#define RADIO_2056_SYN_RESERVED_ADDR19           0x13
+#define RADIO_2056_SYN_RESERVED_ADDR20           0x14
+#define RADIO_2056_SYN_RESERVED_ADDR21           0x15
+#define RADIO_2056_SYN_RESERVED_ADDR22           0x16
+#define RADIO_2056_SYN_RESERVED_ADDR23           0x17
+#define RADIO_2056_SYN_RESERVED_ADDR24           0x18
+#define RADIO_2056_SYN_RESERVED_ADDR25           0x19
+#define RADIO_2056_SYN_RESERVED_ADDR26           0x1a
+#define RADIO_2056_SYN_RESERVED_ADDR27           0x1b
+#define RADIO_2056_SYN_RESERVED_ADDR28           0x1c
+#define RADIO_2056_SYN_RESERVED_ADDR29           0x1d
+#define RADIO_2056_SYN_RESERVED_ADDR30           0x1e
+#define RADIO_2056_SYN_RESERVED_ADDR31           0x1f
+#define RADIO_2056_SYN_GPIO_MASTER1              0x20
+#define RADIO_2056_SYN_GPIO_MASTER2              0x21
+#define RADIO_2056_SYN_TOPBIAS_MASTER            0x22
+#define RADIO_2056_SYN_TOPBIAS_RCAL              0x23
+#define RADIO_2056_SYN_AFEREG                    0x24
+#define RADIO_2056_SYN_TEMPPROCSENSE             0x25
+#define RADIO_2056_SYN_TEMPPROCSENSEIDAC         0x26
+#define RADIO_2056_SYN_TEMPPROCSENSERCAL         0x27
+#define RADIO_2056_SYN_LPO                       0x28
+#define RADIO_2056_SYN_VDDCAL_MASTER             0x29
+#define RADIO_2056_SYN_VDDCAL_IDAC               0x2a
+#define RADIO_2056_SYN_VDDCAL_STATUS             0x2b
+#define RADIO_2056_SYN_RCAL_MASTER               0x2c
+#define RADIO_2056_SYN_RCAL_CODE_OUT             0x2d
+#define RADIO_2056_SYN_RCCAL_CTRL0               0x2e
+#define RADIO_2056_SYN_RCCAL_CTRL1               0x2f
+#define RADIO_2056_SYN_RCCAL_CTRL2               0x30
+#define RADIO_2056_SYN_RCCAL_CTRL3               0x31
+#define RADIO_2056_SYN_RCCAL_CTRL4               0x32
+#define RADIO_2056_SYN_RCCAL_CTRL5               0x33
+#define RADIO_2056_SYN_RCCAL_CTRL6               0x34
+#define RADIO_2056_SYN_RCCAL_CTRL7               0x35
+#define RADIO_2056_SYN_RCCAL_CTRL8               0x36
+#define RADIO_2056_SYN_RCCAL_CTRL9               0x37
+#define RADIO_2056_SYN_RCCAL_CTRL10              0x38
+#define RADIO_2056_SYN_RCCAL_CTRL11              0x39
+#define RADIO_2056_SYN_ZCAL_SPARE1               0x3a
+#define RADIO_2056_SYN_ZCAL_SPARE2               0x3b
+#define RADIO_2056_SYN_PLL_MAST1                 0x3c
+#define RADIO_2056_SYN_PLL_MAST2                 0x3d
+#define RADIO_2056_SYN_PLL_MAST3                 0x3e
+#define RADIO_2056_SYN_PLL_BIAS_RESET            0x3f
+#define RADIO_2056_SYN_PLL_XTAL0                 0x40
+#define RADIO_2056_SYN_PLL_XTAL1                 0x41
+#define RADIO_2056_SYN_PLL_XTAL3                 0x42
+#define RADIO_2056_SYN_PLL_XTAL4                 0x43
+#define RADIO_2056_SYN_PLL_XTAL5                 0x44
+#define RADIO_2056_SYN_PLL_XTAL6                 0x45
+#define RADIO_2056_SYN_PLL_REFDIV                0x46
+#define RADIO_2056_SYN_PLL_PFD                   0x47
+#define RADIO_2056_SYN_PLL_CP1                   0x48
+#define RADIO_2056_SYN_PLL_CP2                   0x49
+#define RADIO_2056_SYN_PLL_CP3                   0x4a
+#define RADIO_2056_SYN_PLL_LOOPFILTER1           0x4b
+#define RADIO_2056_SYN_PLL_LOOPFILTER2           0x4c
+#define RADIO_2056_SYN_PLL_LOOPFILTER3           0x4d
+#define RADIO_2056_SYN_PLL_LOOPFILTER4           0x4e
+#define RADIO_2056_SYN_PLL_LOOPFILTER5           0x4f
+#define RADIO_2056_SYN_PLL_MMD1                  0x50
+#define RADIO_2056_SYN_PLL_MMD2                  0x51
+#define RADIO_2056_SYN_PLL_VCO1                  0x52
+#define RADIO_2056_SYN_PLL_VCO2                  0x53
+#define RADIO_2056_SYN_PLL_MONITOR1              0x54
+#define RADIO_2056_SYN_PLL_MONITOR2              0x55
+#define RADIO_2056_SYN_PLL_VCOCAL1               0x56
+#define RADIO_2056_SYN_PLL_VCOCAL2               0x57
+#define RADIO_2056_SYN_PLL_VCOCAL4               0x58
+#define RADIO_2056_SYN_PLL_VCOCAL5               0x59
+#define RADIO_2056_SYN_PLL_VCOCAL6               0x5a
+#define RADIO_2056_SYN_PLL_VCOCAL7               0x5b
+#define RADIO_2056_SYN_PLL_VCOCAL8               0x5c
+#define RADIO_2056_SYN_PLL_VCOCAL9               0x5d
+#define RADIO_2056_SYN_PLL_VCOCAL10              0x5e
+#define RADIO_2056_SYN_PLL_VCOCAL11              0x5f
+#define RADIO_2056_SYN_PLL_VCOCAL12              0x60
+#define RADIO_2056_SYN_PLL_VCOCAL13              0x61
+#define RADIO_2056_SYN_PLL_VREG                  0x62
+#define RADIO_2056_SYN_PLL_STATUS1               0x63
+#define RADIO_2056_SYN_PLL_STATUS2               0x64
+#define RADIO_2056_SYN_PLL_STATUS3               0x65
+#define RADIO_2056_SYN_LOGEN_PU0                 0x66
+#define RADIO_2056_SYN_LOGEN_PU1                 0x67
+#define RADIO_2056_SYN_LOGEN_PU2                 0x68
+#define RADIO_2056_SYN_LOGEN_PU3                 0x69
+#define RADIO_2056_SYN_LOGEN_PU5                 0x6a
+#define RADIO_2056_SYN_LOGEN_PU6                 0x6b
+#define RADIO_2056_SYN_LOGEN_PU7                 0x6c
+#define RADIO_2056_SYN_LOGEN_PU8                 0x6d
+#define RADIO_2056_SYN_LOGEN_BIAS_RESET          0x6e
+#define RADIO_2056_SYN_LOGEN_RCCR1               0x6f
+#define RADIO_2056_SYN_LOGEN_VCOBUF1             0x70
+#define RADIO_2056_SYN_LOGEN_MIXER1              0x71
+#define RADIO_2056_SYN_LOGEN_MIXER2              0x72
+#define RADIO_2056_SYN_LOGEN_BUF1                0x73
+#define RADIO_2056_SYN_LOGENBUF2                 0x74
+#define RADIO_2056_SYN_LOGEN_BUF3                0x75
+#define RADIO_2056_SYN_LOGEN_BUF4                0x76
+#define RADIO_2056_SYN_LOGEN_DIV1                0x77
+#define RADIO_2056_SYN_LOGEN_DIV2                0x78
+#define RADIO_2056_SYN_LOGEN_DIV3                0x79
+#define RADIO_2056_SYN_LOGEN_ACL1                0x7a
+#define RADIO_2056_SYN_LOGEN_ACL2                0x7b
+#define RADIO_2056_SYN_LOGEN_ACL3                0x7c
+#define RADIO_2056_SYN_LOGEN_ACL4                0x7d
+#define RADIO_2056_SYN_LOGEN_ACL5                0x7e
+#define RADIO_2056_SYN_LOGEN_ACL6                0x7f
+#define RADIO_2056_SYN_LOGEN_ACLOUT              0x80
+#define RADIO_2056_SYN_LOGEN_ACLCAL1             0x81
+#define RADIO_2056_SYN_LOGEN_ACLCAL2             0x82
+#define RADIO_2056_SYN_LOGEN_ACLCAL3             0x83
+#define RADIO_2056_SYN_CALEN                     0x84
+#define RADIO_2056_SYN_LOGEN_PEAKDET1            0x85
+#define RADIO_2056_SYN_LOGEN_CORE_ACL_OVR        0x86
+#define RADIO_2056_SYN_LOGEN_RX_DIFF_ACL_OVR     0x87
+#define RADIO_2056_SYN_LOGEN_TX_DIFF_ACL_OVR     0x88
+#define RADIO_2056_SYN_LOGEN_RX_CMOS_ACL_OVR     0x89
+#define RADIO_2056_SYN_LOGEN_TX_CMOS_ACL_OVR     0x8a
+#define RADIO_2056_SYN_LOGEN_VCOBUF2             0x8b
+#define RADIO_2056_SYN_LOGEN_MIXER3              0x8c
+#define RADIO_2056_SYN_LOGEN_BUF5                0x8d
+#define RADIO_2056_SYN_LOGEN_BUF6                0x8e
+#define RADIO_2056_SYN_LOGEN_CBUFRX1             0x8f
+#define RADIO_2056_SYN_LOGEN_CBUFRX2             0x90
+#define RADIO_2056_SYN_LOGEN_CBUFRX3             0x91
+#define RADIO_2056_SYN_LOGEN_CBUFRX4             0x92
+#define RADIO_2056_SYN_LOGEN_CBUFTX1             0x93
+#define RADIO_2056_SYN_LOGEN_CBUFTX2             0x94
+#define RADIO_2056_SYN_LOGEN_CBUFTX3             0x95
+#define RADIO_2056_SYN_LOGEN_CBUFTX4             0x96
+#define RADIO_2056_SYN_LOGEN_CMOSRX1             0x97
+#define RADIO_2056_SYN_LOGEN_CMOSRX2             0x98
+#define RADIO_2056_SYN_LOGEN_CMOSRX3             0x99
+#define RADIO_2056_SYN_LOGEN_CMOSRX4             0x9a
+#define RADIO_2056_SYN_LOGEN_CMOSTX1             0x9b
+#define RADIO_2056_SYN_LOGEN_CMOSTX2             0x9c
+#define RADIO_2056_SYN_LOGEN_CMOSTX3             0x9d
+#define RADIO_2056_SYN_LOGEN_CMOSTX4             0x9e
+#define RADIO_2056_SYN_LOGEN_VCOBUF2_OVRVAL      0x9f
+#define RADIO_2056_SYN_LOGEN_MIXER3_OVRVAL       0xa0
+#define RADIO_2056_SYN_LOGEN_BUF5_OVRVAL         0xa1
+#define RADIO_2056_SYN_LOGEN_BUF6_OVRVAL         0xa2
+#define RADIO_2056_SYN_LOGEN_CBUFRX1_OVRVAL      0xa3
+#define RADIO_2056_SYN_LOGEN_CBUFRX2_OVRVAL      0xa4
+#define RADIO_2056_SYN_LOGEN_CBUFRX3_OVRVAL      0xa5
+#define RADIO_2056_SYN_LOGEN_CBUFRX4_OVRVAL      0xa6
+#define RADIO_2056_SYN_LOGEN_CBUFTX1_OVRVAL      0xa7
+#define RADIO_2056_SYN_LOGEN_CBUFTX2_OVRVAL      0xa8
+#define RADIO_2056_SYN_LOGEN_CBUFTX3_OVRVAL      0xa9
+#define RADIO_2056_SYN_LOGEN_CBUFTX4_OVRVAL      0xaa
+#define RADIO_2056_SYN_LOGEN_CMOSRX1_OVRVAL      0xab
+#define RADIO_2056_SYN_LOGEN_CMOSRX2_OVRVAL      0xac
+#define RADIO_2056_SYN_LOGEN_CMOSRX3_OVRVAL      0xad
+#define RADIO_2056_SYN_LOGEN_CMOSRX4_OVRVAL      0xae
+#define RADIO_2056_SYN_LOGEN_CMOSTX1_OVRVAL      0xaf
+#define RADIO_2056_SYN_LOGEN_CMOSTX2_OVRVAL      0xb0
+#define RADIO_2056_SYN_LOGEN_CMOSTX3_OVRVAL      0xb1
+#define RADIO_2056_SYN_LOGEN_CMOSTX4_OVRVAL      0xb2
+#define RADIO_2056_SYN_LOGEN_ACL_WAITCNT         0xb3
+#define RADIO_2056_SYN_LOGEN_CORE_CALVALID       0xb4
+#define RADIO_2056_SYN_LOGEN_RX_CMOS_CALVALID    0xb5
+#define RADIO_2056_SYN_LOGEN_TX_CMOS_VALID       0xb6
+
+#define RADIO_2056_TX_RESERVED_ADDR0             0x0
+#define RADIO_2056_TX_IDCODE                     0x1
+#define RADIO_2056_TX_RESERVED_ADDR2             0x2
+#define RADIO_2056_TX_RESERVED_ADDR3             0x3
+#define RADIO_2056_TX_RESERVED_ADDR4             0x4
+#define RADIO_2056_TX_RESERVED_ADDR5             0x5
+#define RADIO_2056_TX_RESERVED_ADDR6             0x6
+#define RADIO_2056_TX_RESERVED_ADDR7             0x7
+#define RADIO_2056_TX_COM_CTRL                   0x8
+#define RADIO_2056_TX_COM_PU                     0x9
+#define RADIO_2056_TX_COM_OVR                    0xa
+#define RADIO_2056_TX_COM_RESET                  0xb
+#define RADIO_2056_TX_COM_RCAL                   0xc
+#define RADIO_2056_TX_COM_RC_RXLPF               0xd
+#define RADIO_2056_TX_COM_RC_TXLPF               0xe
+#define RADIO_2056_TX_COM_RC_RXHPF               0xf
+#define RADIO_2056_TX_RESERVED_ADDR16            0x10
+#define RADIO_2056_TX_RESERVED_ADDR17            0x11
+#define RADIO_2056_TX_RESERVED_ADDR18            0x12
+#define RADIO_2056_TX_RESERVED_ADDR19            0x13
+#define RADIO_2056_TX_RESERVED_ADDR20            0x14
+#define RADIO_2056_TX_RESERVED_ADDR21            0x15
+#define RADIO_2056_TX_RESERVED_ADDR22            0x16
+#define RADIO_2056_TX_RESERVED_ADDR23            0x17
+#define RADIO_2056_TX_RESERVED_ADDR24            0x18
+#define RADIO_2056_TX_RESERVED_ADDR25            0x19
+#define RADIO_2056_TX_RESERVED_ADDR26            0x1a
+#define RADIO_2056_TX_RESERVED_ADDR27            0x1b
+#define RADIO_2056_TX_RESERVED_ADDR28            0x1c
+#define RADIO_2056_TX_RESERVED_ADDR29            0x1d
+#define RADIO_2056_TX_RESERVED_ADDR30            0x1e
+#define RADIO_2056_TX_RESERVED_ADDR31            0x1f
+#define RADIO_2056_TX_IQCAL_GAIN_BW              0x20
+#define RADIO_2056_TX_LOFT_FINE_I                0x21
+#define RADIO_2056_TX_LOFT_FINE_Q                0x22
+#define RADIO_2056_TX_LOFT_COARSE_I              0x23
+#define RADIO_2056_TX_LOFT_COARSE_Q              0x24
+#define RADIO_2056_TX_TX_COM_MASTER1             0x25
+#define RADIO_2056_TX_TX_COM_MASTER2             0x26
+#define RADIO_2056_TX_RXIQCAL_TXMUX              0x27
+#define RADIO_2056_TX_TX_SSI_MASTER              0x28
+#define RADIO_2056_TX_IQCAL_VCM_HG               0x29
+#define RADIO_2056_TX_IQCAL_IDAC                 0x2a
+#define RADIO_2056_TX_TSSI_VCM                   0x2b
+#define RADIO_2056_TX_TX_AMP_DET                 0x2c
+#define RADIO_2056_TX_TX_SSI_MUX                 0x2d
+#define RADIO_2056_TX_TSSIA                      0x2e
+#define RADIO_2056_TX_TSSIG                      0x2f
+#define RADIO_2056_TX_TSSI_MISC1                 0x30
+#define RADIO_2056_TX_TSSI_MISC2                 0x31
+#define RADIO_2056_TX_TSSI_MISC3                 0x32
+#define RADIO_2056_TX_PA_SPARE1                  0x33
+#define RADIO_2056_TX_PA_SPARE2                  0x34
+#define RADIO_2056_TX_INTPAA_MASTER              0x35
+#define RADIO_2056_TX_INTPAA_GAIN                0x36
+#define RADIO_2056_TX_INTPAA_BOOST_TUNE          0x37
+#define RADIO_2056_TX_INTPAA_IAUX_STAT           0x38
+#define RADIO_2056_TX_INTPAA_IAUX_DYN            0x39
+#define RADIO_2056_TX_INTPAA_IMAIN_STAT          0x3a
+#define RADIO_2056_TX_INTPAA_IMAIN_DYN           0x3b
+#define RADIO_2056_TX_INTPAA_CASCBIAS            0x3c
+#define RADIO_2056_TX_INTPAA_PASLOPE             0x3d
+#define RADIO_2056_TX_INTPAA_PA_MISC             0x3e
+#define RADIO_2056_TX_INTPAG_MASTER              0x3f
+#define RADIO_2056_TX_INTPAG_GAIN                0x40
+#define RADIO_2056_TX_INTPAG_BOOST_TUNE          0x41
+#define RADIO_2056_TX_INTPAG_IAUX_STAT           0x42
+#define RADIO_2056_TX_INTPAG_IAUX_DYN            0x43
+#define RADIO_2056_TX_INTPAG_IMAIN_STAT          0x44
+#define RADIO_2056_TX_INTPAG_IMAIN_DYN           0x45
+#define RADIO_2056_TX_INTPAG_CASCBIAS            0x46
+#define RADIO_2056_TX_INTPAG_PASLOPE             0x47
+#define RADIO_2056_TX_INTPAG_PA_MISC             0x48
+#define RADIO_2056_TX_PADA_MASTER                0x49
+#define RADIO_2056_TX_PADA_IDAC                  0x4a
+#define RADIO_2056_TX_PADA_CASCBIAS              0x4b
+#define RADIO_2056_TX_PADA_GAIN                  0x4c
+#define RADIO_2056_TX_PADA_BOOST_TUNE            0x4d
+#define RADIO_2056_TX_PADA_SLOPE                 0x4e
+#define RADIO_2056_TX_PADG_MASTER                0x4f
+#define RADIO_2056_TX_PADG_IDAC                  0x50
+#define RADIO_2056_TX_PADG_CASCBIAS              0x51
+#define RADIO_2056_TX_PADG_GAIN                  0x52
+#define RADIO_2056_TX_PADG_BOOST_TUNE            0x53
+#define RADIO_2056_TX_PADG_SLOPE                 0x54
+#define RADIO_2056_TX_PGAA_MASTER                0x55
+#define RADIO_2056_TX_PGAA_IDAC                  0x56
+#define RADIO_2056_TX_PGAA_GAIN                  0x57
+#define RADIO_2056_TX_PGAA_BOOST_TUNE            0x58
+#define RADIO_2056_TX_PGAA_SLOPE                 0x59
+#define RADIO_2056_TX_PGAA_MISC                  0x5a
+#define RADIO_2056_TX_PGAG_MASTER                0x5b
+#define RADIO_2056_TX_PGAG_IDAC                  0x5c
+#define RADIO_2056_TX_PGAG_GAIN                  0x5d
+#define RADIO_2056_TX_PGAG_BOOST_TUNE            0x5e
+#define RADIO_2056_TX_PGAG_SLOPE                 0x5f
+#define RADIO_2056_TX_PGAG_MISC                  0x60
+#define RADIO_2056_TX_MIXA_MASTER                0x61
+#define RADIO_2056_TX_MIXA_BOOST_TUNE            0x62
+#define RADIO_2056_TX_MIXG                       0x63
+#define RADIO_2056_TX_MIXG_BOOST_TUNE            0x64
+#define RADIO_2056_TX_BB_GM_MASTER               0x65
+#define RADIO_2056_TX_GMBB_GM                    0x66
+#define RADIO_2056_TX_GMBB_IDAC                  0x67
+#define RADIO_2056_TX_TXLPF_MASTER               0x68
+#define RADIO_2056_TX_TXLPF_RCCAL                0x69
+#define RADIO_2056_TX_TXLPF_RCCAL_OFF0           0x6a
+#define RADIO_2056_TX_TXLPF_RCCAL_OFF1           0x6b
+#define RADIO_2056_TX_TXLPF_RCCAL_OFF2           0x6c
+#define RADIO_2056_TX_TXLPF_RCCAL_OFF3           0x6d
+#define RADIO_2056_TX_TXLPF_RCCAL_OFF4           0x6e
+#define RADIO_2056_TX_TXLPF_RCCAL_OFF5           0x6f
+#define RADIO_2056_TX_TXLPF_RCCAL_OFF6           0x70
+#define RADIO_2056_TX_TXLPF_BW                   0x71
+#define RADIO_2056_TX_TXLPF_GAIN                 0x72
+#define RADIO_2056_TX_TXLPF_IDAC                 0x73
+#define RADIO_2056_TX_TXLPF_IDAC_0               0x74
+#define RADIO_2056_TX_TXLPF_IDAC_1               0x75
+#define RADIO_2056_TX_TXLPF_IDAC_2               0x76
+#define RADIO_2056_TX_TXLPF_IDAC_3               0x77
+#define RADIO_2056_TX_TXLPF_IDAC_4               0x78
+#define RADIO_2056_TX_TXLPF_IDAC_5               0x79
+#define RADIO_2056_TX_TXLPF_IDAC_6               0x7a
+#define RADIO_2056_TX_TXLPF_OPAMP_IDAC           0x7b
+#define RADIO_2056_TX_TXLPF_MISC                 0x7c
+#define RADIO_2056_TX_TXSPARE1                   0x7d
+#define RADIO_2056_TX_TXSPARE2                   0x7e
+#define RADIO_2056_TX_TXSPARE3                   0x7f
+#define RADIO_2056_TX_TXSPARE4                   0x80
+#define RADIO_2056_TX_TXSPARE5                   0x81
+#define RADIO_2056_TX_TXSPARE6                   0x82
+#define RADIO_2056_TX_TXSPARE7                   0x83
+#define RADIO_2056_TX_TXSPARE8                   0x84
+#define RADIO_2056_TX_TXSPARE9                   0x85
+#define RADIO_2056_TX_TXSPARE10                  0x86
+#define RADIO_2056_TX_TXSPARE11                  0x87
+#define RADIO_2056_TX_TXSPARE12                  0x88
+#define RADIO_2056_TX_TXSPARE13                  0x89
+#define RADIO_2056_TX_TXSPARE14                  0x8a
+#define RADIO_2056_TX_TXSPARE15                  0x8b
+#define RADIO_2056_TX_TXSPARE16                  0x8c
+#define RADIO_2056_TX_STATUS_INTPA_GAIN          0x8d
+#define RADIO_2056_TX_STATUS_PAD_GAIN            0x8e
+#define RADIO_2056_TX_STATUS_PGA_GAIN            0x8f
+#define RADIO_2056_TX_STATUS_GM_TXLPF_GAIN       0x90
+#define RADIO_2056_TX_STATUS_TXLPF_BW            0x91
+#define RADIO_2056_TX_STATUS_TXLPF_RC            0x92
+#define RADIO_2056_TX_GMBB_IDAC0                 0x93
+#define RADIO_2056_TX_GMBB_IDAC1                 0x94
+#define RADIO_2056_TX_GMBB_IDAC2                 0x95
+#define RADIO_2056_TX_GMBB_IDAC3                 0x96
+#define RADIO_2056_TX_GMBB_IDAC4                 0x97
+#define RADIO_2056_TX_GMBB_IDAC5                 0x98
+#define RADIO_2056_TX_GMBB_IDAC6                 0x99
+#define RADIO_2056_TX_GMBB_IDAC7                 0x9a
+
+#define RADIO_2056_RX_RESERVED_ADDR0             0x0
+#define RADIO_2056_RX_IDCODE                     0x1
+#define RADIO_2056_RX_RESERVED_ADDR2             0x2
+#define RADIO_2056_RX_RESERVED_ADDR3             0x3
+#define RADIO_2056_RX_RESERVED_ADDR4             0x4
+#define RADIO_2056_RX_RESERVED_ADDR5             0x5
+#define RADIO_2056_RX_RESERVED_ADDR6             0x6
+#define RADIO_2056_RX_RESERVED_ADDR7             0x7
+#define RADIO_2056_RX_COM_CTRL                   0x8
+#define RADIO_2056_RX_COM_PU                     0x9
+#define RADIO_2056_RX_COM_OVR                    0xa
+#define RADIO_2056_RX_COM_RESET                  0xb
+#define RADIO_2056_RX_COM_RCAL                   0xc
+#define RADIO_2056_RX_COM_RC_RXLPF               0xd
+#define RADIO_2056_RX_COM_RC_TXLPF               0xe
+#define RADIO_2056_RX_COM_RC_RXHPF               0xf
+#define RADIO_2056_RX_RESERVED_ADDR16            0x10
+#define RADIO_2056_RX_RESERVED_ADDR17            0x11
+#define RADIO_2056_RX_RESERVED_ADDR18            0x12
+#define RADIO_2056_RX_RESERVED_ADDR19            0x13
+#define RADIO_2056_RX_RESERVED_ADDR20            0x14
+#define RADIO_2056_RX_RESERVED_ADDR21            0x15
+#define RADIO_2056_RX_RESERVED_ADDR22            0x16
+#define RADIO_2056_RX_RESERVED_ADDR23            0x17
+#define RADIO_2056_RX_RESERVED_ADDR24            0x18
+#define RADIO_2056_RX_RESERVED_ADDR25            0x19
+#define RADIO_2056_RX_RESERVED_ADDR26            0x1a
+#define RADIO_2056_RX_RESERVED_ADDR27            0x1b
+#define RADIO_2056_RX_RESERVED_ADDR28            0x1c
+#define RADIO_2056_RX_RESERVED_ADDR29            0x1d
+#define RADIO_2056_RX_RESERVED_ADDR30            0x1e
+#define RADIO_2056_RX_RESERVED_ADDR31            0x1f
+#define RADIO_2056_RX_RXIQCAL_RXMUX              0x20
+#define RADIO_2056_RX_RSSI_PU                    0x21
+#define RADIO_2056_RX_RSSI_SEL                   0x22
+#define RADIO_2056_RX_RSSI_GAIN                  0x23
+#define RADIO_2056_RX_RSSI_NB_IDAC               0x24
+#define RADIO_2056_RX_RSSI_WB2I_IDAC_1           0x25
+#define RADIO_2056_RX_RSSI_WB2I_IDAC_2           0x26
+#define RADIO_2056_RX_RSSI_WB2Q_IDAC_1           0x27
+#define RADIO_2056_RX_RSSI_WB2Q_IDAC_2           0x28
+#define RADIO_2056_RX_RSSI_POLE                  0x29
+#define RADIO_2056_RX_RSSI_WB1_IDAC              0x2a
+#define RADIO_2056_RX_RSSI_MISC                  0x2b
+#define RADIO_2056_RX_LNAA_MASTER                0x2c
+#define RADIO_2056_RX_LNAA_TUNE                  0x2d
+#define RADIO_2056_RX_LNAA_GAIN                  0x2e
+#define RADIO_2056_RX_LNA_A_SLOPE                0x2f
+#define RADIO_2056_RX_BIASPOLE_LNAA1_IDAC        0x30
+#define RADIO_2056_RX_LNAA2_IDAC                 0x31
+#define RADIO_2056_RX_LNA1A_MISC                 0x32
+#define RADIO_2056_RX_LNAG_MASTER                0x33
+#define RADIO_2056_RX_LNAG_TUNE                  0x34
+#define RADIO_2056_RX_LNAG_GAIN                  0x35
+#define RADIO_2056_RX_LNA_G_SLOPE                0x36
+#define RADIO_2056_RX_BIASPOLE_LNAG1_IDAC        0x37
+#define RADIO_2056_RX_LNAG2_IDAC                 0x38
+#define RADIO_2056_RX_LNA1G_MISC                 0x39
+#define RADIO_2056_RX_MIXA_MASTER                0x3a
+#define RADIO_2056_RX_MIXA_VCM                   0x3b
+#define RADIO_2056_RX_MIXA_CTRLPTAT              0x3c
+#define RADIO_2056_RX_MIXA_LOB_BIAS              0x3d
+#define RADIO_2056_RX_MIXA_CORE_IDAC             0x3e
+#define RADIO_2056_RX_MIXA_CMFB_IDAC             0x3f
+#define RADIO_2056_RX_MIXA_BIAS_AUX              0x40
+#define RADIO_2056_RX_MIXA_BIAS_MAIN             0x41
+#define RADIO_2056_RX_MIXA_BIAS_MISC             0x42
+#define RADIO_2056_RX_MIXA_MAST_BIAS             0x43
+#define RADIO_2056_RX_MIXG_MASTER                0x44
+#define RADIO_2056_RX_MIXG_VCM                   0x45
+#define RADIO_2056_RX_MIXG_CTRLPTAT              0x46
+#define RADIO_2056_RX_MIXG_LOB_BIAS              0x47
+#define RADIO_2056_RX_MIXG_CORE_IDAC             0x48
+#define RADIO_2056_RX_MIXG_CMFB_IDAC             0x49
+#define RADIO_2056_RX_MIXG_BIAS_AUX              0x4a
+#define RADIO_2056_RX_MIXG_BIAS_MAIN             0x4b
+#define RADIO_2056_RX_MIXG_BIAS_MISC             0x4c
+#define RADIO_2056_RX_MIXG_MAST_BIAS             0x4d
+#define RADIO_2056_RX_TIA_MASTER                 0x4e
+#define RADIO_2056_RX_TIA_IOPAMP                 0x4f
+#define RADIO_2056_RX_TIA_QOPAMP                 0x50
+#define RADIO_2056_RX_TIA_IMISC                  0x51
+#define RADIO_2056_RX_TIA_QMISC                  0x52
+#define RADIO_2056_RX_TIA_GAIN                   0x53
+#define RADIO_2056_RX_TIA_SPARE1                 0x54
+#define RADIO_2056_RX_TIA_SPARE2                 0x55
+#define RADIO_2056_RX_BB_LPF_MASTER              0x56
+#define RADIO_2056_RX_AACI_MASTER                0x57
+#define RADIO_2056_RX_RXLPF_IDAC                 0x58
+#define RADIO_2056_RX_RXLPF_OPAMPBIAS_LOWQ       0x59
+#define RADIO_2056_RX_RXLPF_OPAMPBIAS_HIGHQ      0x5a
+#define RADIO_2056_RX_RXLPF_BIAS_DCCANCEL        0x5b
+#define RADIO_2056_RX_RXLPF_OUTVCM               0x5c
+#define RADIO_2056_RX_RXLPF_INVCM_BODY           0x5d
+#define RADIO_2056_RX_RXLPF_CC_OP                0x5e
+#define RADIO_2056_RX_RXLPF_GAIN                 0x5f
+#define RADIO_2056_RX_RXLPF_Q_BW                 0x60
+#define RADIO_2056_RX_RXLPF_HP_CORNER_BW         0x61
+#define RADIO_2056_RX_RXLPF_RCCAL_HPC            0x62
+#define RADIO_2056_RX_RXHPF_OFF0                 0x63
+#define RADIO_2056_RX_RXHPF_OFF1                 0x64
+#define RADIO_2056_RX_RXHPF_OFF2                 0x65
+#define RADIO_2056_RX_RXHPF_OFF3                 0x66
+#define RADIO_2056_RX_RXHPF_OFF4                 0x67
+#define RADIO_2056_RX_RXHPF_OFF5                 0x68
+#define RADIO_2056_RX_RXHPF_OFF6                 0x69
+#define RADIO_2056_RX_RXHPF_OFF7                 0x6a
+#define RADIO_2056_RX_RXLPF_RCCAL_LPC            0x6b
+#define RADIO_2056_RX_RXLPF_OFF_0                0x6c
+#define RADIO_2056_RX_RXLPF_OFF_1                0x6d
+#define RADIO_2056_RX_RXLPF_OFF_2                0x6e
+#define RADIO_2056_RX_RXLPF_OFF_3                0x6f
+#define RADIO_2056_RX_RXLPF_OFF_4                0x70
+#define RADIO_2056_RX_UNUSED                     0x71
+#define RADIO_2056_RX_VGA_MASTER                 0x72
+#define RADIO_2056_RX_VGA_BIAS                   0x73
+#define RADIO_2056_RX_VGA_BIAS_DCCANCEL          0x74
+#define RADIO_2056_RX_VGA_GAIN                   0x75
+#define RADIO_2056_RX_VGA_HP_CORNER_BW           0x76
+#define RADIO_2056_RX_VGABUF_BIAS                0x77
+#define RADIO_2056_RX_VGABUF_GAIN_BW             0x78
+#define RADIO_2056_RX_TXFBMIX_A                  0x79
+#define RADIO_2056_RX_TXFBMIX_G                  0x7a
+#define RADIO_2056_RX_RXSPARE1                   0x7b
+#define RADIO_2056_RX_RXSPARE2                   0x7c
+#define RADIO_2056_RX_RXSPARE3                   0x7d
+#define RADIO_2056_RX_RXSPARE4                   0x7e
+#define RADIO_2056_RX_RXSPARE5                   0x7f
+#define RADIO_2056_RX_RXSPARE6                   0x80
+#define RADIO_2056_RX_RXSPARE7                   0x81
+#define RADIO_2056_RX_RXSPARE8                   0x82
+#define RADIO_2056_RX_RXSPARE9                   0x83
+#define RADIO_2056_RX_RXSPARE10                  0x84
+#define RADIO_2056_RX_RXSPARE11                  0x85
+#define RADIO_2056_RX_RXSPARE12                  0x86
+#define RADIO_2056_RX_RXSPARE13                  0x87
+#define RADIO_2056_RX_RXSPARE14                  0x88
+#define RADIO_2056_RX_RXSPARE15                  0x89
+#define RADIO_2056_RX_RXSPARE16                  0x8a
+#define RADIO_2056_RX_STATUS_LNAA_GAIN           0x8b
+#define RADIO_2056_RX_STATUS_LNAG_GAIN           0x8c
+#define RADIO_2056_RX_STATUS_MIXTIA_GAIN         0x8d
+#define RADIO_2056_RX_STATUS_RXLPF_GAIN          0x8e
+#define RADIO_2056_RX_STATUS_VGA_BUF_GAIN        0x8f
+#define RADIO_2056_RX_STATUS_RXLPF_Q             0x90
+#define RADIO_2056_RX_STATUS_RXLPF_BUF_BW        0x91
+#define RADIO_2056_RX_STATUS_RXLPF_VGA_HPC       0x92
+#define RADIO_2056_RX_STATUS_RXLPF_RC            0x93
+#define RADIO_2056_RX_STATUS_HPC_RC              0x94
+
+#define RADIO_2056_LNA1_A_PU		0x01
+#define RADIO_2056_LNA2_A_PU		0x02
+#define RADIO_2056_LNA1_G_PU		0x01
+#define RADIO_2056_LNA2_G_PU		0x02
+#define RADIO_2056_MIXA_PU_I		0x01
+#define RADIO_2056_MIXA_PU_Q		0x02
+#define RADIO_2056_MIXA_PU_GM		0x10
+#define RADIO_2056_MIXG_PU_I		0x01
+#define RADIO_2056_MIXG_PU_Q		0x02
+#define RADIO_2056_MIXG_PU_GM		0x10
+#define RADIO_2056_TIA_PU			0x01
+#define RADIO_2056_BB_LPF_PU		0x20
+#define RADIO_2056_W1_PU			0x02
+#define RADIO_2056_W2_PU			0x04
+#define RADIO_2056_NB_PU			0x08
+#define RADIO_2056_RSSI_W1_SEL		0x02
+#define RADIO_2056_RSSI_W2_SEL		0x04
+#define RADIO_2056_RSSI_NB_SEL		0x08
+#define RADIO_2056_VCM_MASK			0x1c
+#define RADIO_2056_RSSI_VCM_SHIFT	0x02
+
+#define RADIO_2057_DACBUF_VINCM_CORE0            0x0
+#define RADIO_2057_IDCODE                        0x1
+#define RADIO_2057_RCCAL_MASTER                  0x2
+#define RADIO_2057_RCCAL_CAP_SIZE                0x3
+#define RADIO_2057_RCAL_CONFIG                   0x4
+#define RADIO_2057_GPAIO_CONFIG                  0x5
+#define RADIO_2057_GPAIO_SEL1                    0x6
+#define RADIO_2057_GPAIO_SEL0                    0x7
+#define RADIO_2057_CLPO_CONFIG                   0x8
+#define RADIO_2057_BANDGAP_CONFIG                0x9
+#define RADIO_2057_BANDGAP_RCAL_TRIM             0xa
+#define RADIO_2057_AFEREG_CONFIG                 0xb
+#define RADIO_2057_TEMPSENSE_CONFIG              0xc
+#define RADIO_2057_XTAL_CONFIG1                  0xd
+#define RADIO_2057_XTAL_ICORE_SIZE               0xe
+#define RADIO_2057_XTAL_BUF_SIZE                 0xf
+#define RADIO_2057_XTAL_PULLCAP_SIZE             0x10
+#define RADIO_2057_RFPLL_MASTER                  0x11
+#define RADIO_2057_VCOMONITOR_VTH_L              0x12
+#define RADIO_2057_VCOMONITOR_VTH_H              0x13
+#define RADIO_2057_VCOCAL_BIASRESET_RFPLLREG_VOUT 0x14
+#define RADIO_2057_VCO_VARCSIZE_IDAC             0x15
+#define RADIO_2057_VCOCAL_COUNTVAL0              0x16
+#define RADIO_2057_VCOCAL_COUNTVAL1              0x17
+#define RADIO_2057_VCOCAL_INTCLK_COUNT           0x18
+#define RADIO_2057_VCOCAL_MASTER                 0x19
+#define RADIO_2057_VCOCAL_NUMCAPCHANGE           0x1a
+#define RADIO_2057_VCOCAL_WINSIZE                0x1b
+#define RADIO_2057_VCOCAL_DELAY_AFTER_REFRESH    0x1c
+#define RADIO_2057_VCOCAL_DELAY_AFTER_CLOSELOOP  0x1d
+#define RADIO_2057_VCOCAL_DELAY_AFTER_OPENLOOP   0x1e
+#define RADIO_2057_VCOCAL_DELAY_BEFORE_OPENLOOP  0x1f
+#define RADIO_2057_VCO_FORCECAPEN_FORCECAP1      0x20
+#define RADIO_2057_VCO_FORCECAP0                 0x21
+#define RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE 0x22
+#define RADIO_2057_RFPLL_PFD_RESET_PW            0x23
+#define RADIO_2057_RFPLL_LOOPFILTER_R2           0x24
+#define RADIO_2057_RFPLL_LOOPFILTER_R1           0x25
+#define RADIO_2057_RFPLL_LOOPFILTER_C3           0x26
+#define RADIO_2057_RFPLL_LOOPFILTER_C2           0x27
+#define RADIO_2057_RFPLL_LOOPFILTER_C1           0x28
+#define RADIO_2057_CP_KPD_IDAC                   0x29
+#define RADIO_2057_RFPLL_IDACS                   0x2a
+#define RADIO_2057_RFPLL_MISC_EN                 0x2b
+#define RADIO_2057_RFPLL_MMD0                    0x2c
+#define RADIO_2057_RFPLL_MMD1                    0x2d
+#define RADIO_2057_RFPLL_MISC_CAL_RESETN         0x2e
+#define RADIO_2057_JTAGXTAL_SIZE_CPBIAS_FILTRES  0x2f
+#define RADIO_2057_VCO_ALCREF_BBPLLXTAL_SIZE     0x30
+#define RADIO_2057_VCOCAL_READCAP0               0x31
+#define RADIO_2057_VCOCAL_READCAP1               0x32
+#define RADIO_2057_VCOCAL_STATUS                 0x33
+#define RADIO_2057_LOGEN_PUS                     0x34
+#define RADIO_2057_LOGEN_PTAT_RESETS             0x35
+#define RADIO_2057_VCOBUF_IDACS                  0x36
+#define RADIO_2057_VCOBUF_TUNE                   0x37
+#define RADIO_2057_CMOSBUF_TX2GQ_IDACS           0x38
+#define RADIO_2057_CMOSBUF_TX2GI_IDACS           0x39
+#define RADIO_2057_CMOSBUF_TX5GQ_IDACS           0x3a
+#define RADIO_2057_CMOSBUF_TX5GI_IDACS           0x3b
+#define RADIO_2057_CMOSBUF_RX2GQ_IDACS           0x3c
+#define RADIO_2057_CMOSBUF_RX2GI_IDACS           0x3d
+#define RADIO_2057_CMOSBUF_RX5GQ_IDACS           0x3e
+#define RADIO_2057_CMOSBUF_RX5GI_IDACS           0x3f
+#define RADIO_2057_LOGEN_MX2G_IDACS              0x40
+#define RADIO_2057_LOGEN_MX2G_TUNE               0x41
+#define RADIO_2057_LOGEN_MX5G_IDACS              0x42
+#define RADIO_2057_LOGEN_MX5G_TUNE               0x43
+#define RADIO_2057_LOGEN_MX5G_RCCR               0x44
+#define RADIO_2057_LOGEN_INDBUF2G_IDAC           0x45
+#define RADIO_2057_LOGEN_INDBUF2G_IBOOST         0x46
+#define RADIO_2057_LOGEN_INDBUF2G_TUNE           0x47
+#define RADIO_2057_LOGEN_INDBUF5G_IDAC           0x48
+#define RADIO_2057_LOGEN_INDBUF5G_IBOOST         0x49
+#define RADIO_2057_LOGEN_INDBUF5G_TUNE           0x4a
+#define RADIO_2057_CMOSBUF_TX_RCCR               0x4b
+#define RADIO_2057_CMOSBUF_RX_RCCR               0x4c
+#define RADIO_2057_LOGEN_SEL_PKDET               0x4d
+#define RADIO_2057_CMOSBUF_SHAREIQ_PTAT          0x4e
+#define RADIO_2057_RXTXBIAS_CONFIG_CORE0         0x4f
+#define RADIO_2057_TXGM_TXRF_PUS_CORE0           0x50
+#define RADIO_2057_TXGM_IDAC_BLEED_CORE0         0x51
+#define RADIO_2057_TXGM_GAIN_CORE0               0x56
+#define RADIO_2057_TXGM2G_PKDET_PUS_CORE0        0x57
+#define RADIO_2057_PAD2G_PTATS_CORE0             0x58
+#define RADIO_2057_PAD2G_IDACS_CORE0             0x59
+#define RADIO_2057_PAD2G_BOOST_PU_CORE0          0x5a
+#define RADIO_2057_PAD2G_CASCV_GAIN_CORE0        0x5b
+#define RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0   0x5c
+#define RADIO_2057_TXMIX2G_LODC_CORE0            0x5d
+#define RADIO_2057_PAD2G_TUNE_PUS_CORE0          0x5e
+#define RADIO_2057_IPA2G_GAIN_CORE0              0x5f
+#define RADIO_2057_TSSI2G_SPARE1_CORE0           0x60
+#define RADIO_2057_TSSI2G_SPARE2_CORE0           0x61
+#define RADIO_2057_IPA2G_TUNEV_CASCV_PTAT_CORE0  0x62
+#define RADIO_2057_IPA2G_IMAIN_CORE0             0x63
+#define RADIO_2057_IPA2G_CASCONV_CORE0           0x64
+#define RADIO_2057_IPA2G_CASCOFFV_CORE0          0x65
+#define RADIO_2057_IPA2G_BIAS_FILTER_CORE0       0x66
+#define RADIO_2057_TX5G_PKDET_CORE0              0x69
+#define RADIO_2057_PGA_PTAT_TXGM5G_PU_CORE0      0x6a
+#define RADIO_2057_PAD5G_PTATS1_CORE0            0x6b
+#define RADIO_2057_PAD5G_CLASS_PTATS2_CORE0      0x6c
+#define RADIO_2057_PGA_BOOSTPTAT_IMAIN_CORE0     0x6d
+#define RADIO_2057_PAD5G_CASCV_IMAIN_CORE0       0x6e
+#define RADIO_2057_TXMIX5G_IBOOST_PAD_IAUX_CORE0 0x6f
+#define RADIO_2057_PGA_BOOST_TUNE_CORE0          0x70
+#define RADIO_2057_PGA_GAIN_CORE0                0x71
+#define RADIO_2057_PAD5G_CASCOFFV_GAIN_PUS_CORE0 0x72
+#define RADIO_2057_TXMIX5G_BOOST_TUNE_CORE0      0x73
+#define RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE0     0x74
+#define RADIO_2057_IPA5G_IAUX_CORE0              0x75
+#define RADIO_2057_IPA5G_GAIN_CORE0              0x76
+#define RADIO_2057_TSSI5G_SPARE1_CORE0           0x77
+#define RADIO_2057_TSSI5G_SPARE2_CORE0           0x78
+#define RADIO_2057_IPA5G_CASCOFFV_PU_CORE0       0x79
+#define RADIO_2057_IPA5G_PTAT_CORE0              0x7a
+#define RADIO_2057_IPA5G_IMAIN_CORE0             0x7b
+#define RADIO_2057_IPA5G_CASCONV_CORE0           0x7c
+#define RADIO_2057_IPA5G_BIAS_FILTER_CORE0       0x7d
+#define RADIO_2057_PAD_BIAS_FILTER_BWS_CORE0     0x80
+#define RADIO_2057_TR2G_CONFIG1_CORE0_NU         0x81
+#define RADIO_2057_TR2G_CONFIG2_CORE0_NU         0x82
+#define RADIO_2057_LNA5G_RFEN_CORE0              0x83
+#define RADIO_2057_TR5G_CONFIG2_CORE0_NU         0x84
+#define RADIO_2057_RXRFBIAS_IBOOST_PU_CORE0      0x85
+#define RADIO_2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE0 0x86
+#define RADIO_2057_RXGM_CMFBITAIL_AUXPTAT_CORE0  0x87
+#define RADIO_2057_RXMIX_ICORE_RXGM_IAUX_CORE0   0x88
+#define RADIO_2057_RXMIX_CMFBITAIL_PU_CORE0      0x89
+#define RADIO_2057_LNA2_IMAIN_PTAT_PU_CORE0      0x8a
+#define RADIO_2057_LNA2_IAUX_PTAT_CORE0          0x8b
+#define RADIO_2057_LNA1_IMAIN_PTAT_PU_CORE0      0x8c
+#define RADIO_2057_LNA15G_INPUT_MATCH_TUNE_CORE0 0x8d
+#define RADIO_2057_RXRFBIAS_BANDSEL_CORE0        0x8e
+#define RADIO_2057_TIA_CONFIG_CORE0              0x8f
+#define RADIO_2057_TIA_IQGAIN_CORE0              0x90
+#define RADIO_2057_TIA_IBIAS2_CORE0              0x91
+#define RADIO_2057_TIA_IBIAS1_CORE0              0x92
+#define RADIO_2057_TIA_SPARE_Q_CORE0             0x93
+#define RADIO_2057_TIA_SPARE_I_CORE0             0x94
+#define RADIO_2057_RXMIX2G_PUS_CORE0             0x95
+#define RADIO_2057_RXMIX2G_VCMREFS_CORE0         0x96
+#define RADIO_2057_RXMIX2G_LODC_QI_CORE0         0x97
+#define RADIO_2057_W12G_BW_LNA2G_PUS_CORE0       0x98
+#define RADIO_2057_LNA2G_GAIN_CORE0              0x99
+#define RADIO_2057_LNA2G_TUNE_CORE0              0x9a
+#define RADIO_2057_RXMIX5G_PUS_CORE0             0x9b
+#define RADIO_2057_RXMIX5G_VCMREFS_CORE0         0x9c
+#define RADIO_2057_RXMIX5G_LODC_QI_CORE0         0x9d
+#define RADIO_2057_W15G_BW_LNA5G_PUS_CORE0       0x9e
+#define RADIO_2057_LNA5G_GAIN_CORE0              0x9f
+#define RADIO_2057_LNA5G_TUNE_CORE0              0xa0
+#define RADIO_2057_LPFSEL_TXRX_RXBB_PUS_CORE0    0xa1
+#define RADIO_2057_RXBB_BIAS_MASTER_CORE0        0xa2
+#define RADIO_2057_RXBB_VGABUF_IDACS_CORE0       0xa3
+#define RADIO_2057_LPF_VCMREF_TXBUF_VCMREF_CORE0 0xa4
+#define RADIO_2057_TXBUF_VINCM_CORE0             0xa5
+#define RADIO_2057_TXBUF_IDACS_CORE0             0xa6
+#define RADIO_2057_LPF_RESP_RXBUF_BW_CORE0       0xa7
+#define RADIO_2057_RXBB_CC_CORE0                 0xa8
+#define RADIO_2057_RXBB_SPARE3_CORE0             0xa9
+#define RADIO_2057_RXBB_RCCAL_HPC_CORE0          0xaa
+#define RADIO_2057_LPF_IDACS_CORE0               0xab
+#define RADIO_2057_LPFBYP_DCLOOP_BYP_IDAC_CORE0  0xac
+#define RADIO_2057_TXBUF_GAIN_CORE0              0xad
+#define RADIO_2057_AFELOOPBACK_AACI_RESP_CORE0   0xae
+#define RADIO_2057_RXBUF_DEGEN_CORE0             0xaf
+#define RADIO_2057_RXBB_SPARE2_CORE0             0xb0
+#define RADIO_2057_RXBB_SPARE1_CORE0             0xb1
+#define RADIO_2057_RSSI_MASTER_CORE0             0xb2
+#define RADIO_2057_W2_MASTER_CORE0               0xb3
+#define RADIO_2057_NB_MASTER_CORE0               0xb4
+#define RADIO_2057_W2_IDACS0_Q_CORE0             0xb5
+#define RADIO_2057_W2_IDACS1_Q_CORE0             0xb6
+#define RADIO_2057_W2_IDACS0_I_CORE0             0xb7
+#define RADIO_2057_W2_IDACS1_I_CORE0             0xb8
+#define RADIO_2057_RSSI_GPAIOSEL_W1_IDACS_CORE0  0xb9
+#define RADIO_2057_NB_IDACS_Q_CORE0              0xba
+#define RADIO_2057_NB_IDACS_I_CORE0              0xbb
+#define RADIO_2057_BACKUP4_CORE0                 0xc1
+#define RADIO_2057_BACKUP3_CORE0                 0xc2
+#define RADIO_2057_BACKUP2_CORE0                 0xc3
+#define RADIO_2057_BACKUP1_CORE0                 0xc4
+#define RADIO_2057_SPARE16_CORE0                 0xc5
+#define RADIO_2057_SPARE15_CORE0                 0xc6
+#define RADIO_2057_SPARE14_CORE0                 0xc7
+#define RADIO_2057_SPARE13_CORE0                 0xc8
+#define RADIO_2057_SPARE12_CORE0                 0xc9
+#define RADIO_2057_SPARE11_CORE0                 0xca
+#define RADIO_2057_TX2G_BIAS_RESETS_CORE0        0xcb
+#define RADIO_2057_TX5G_BIAS_RESETS_CORE0        0xcc
+#define RADIO_2057_IQTEST_SEL_PU                 0xcd
+#define RADIO_2057_XTAL_CONFIG2                  0xce
+#define RADIO_2057_BUFS_MISC_LPFBW_CORE0         0xcf
+#define RADIO_2057_TXLPF_RCCAL_CORE0             0xd0
+#define RADIO_2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE0 0xd1
+#define RADIO_2057_LPF_GAIN_CORE0                0xd2
+#define RADIO_2057_DACBUF_IDACS_BW_CORE0         0xd3
+#define RADIO_2057_RXTXBIAS_CONFIG_CORE1         0xd4
+#define RADIO_2057_TXGM_TXRF_PUS_CORE1           0xd5
+#define RADIO_2057_TXGM_IDAC_BLEED_CORE1         0xd6
+#define RADIO_2057_TXGM_GAIN_CORE1               0xdb
+#define RADIO_2057_TXGM2G_PKDET_PUS_CORE1        0xdc
+#define RADIO_2057_PAD2G_PTATS_CORE1             0xdd
+#define RADIO_2057_PAD2G_IDACS_CORE1             0xde
+#define RADIO_2057_PAD2G_BOOST_PU_CORE1          0xdf
+#define RADIO_2057_PAD2G_CASCV_GAIN_CORE1        0xe0
+#define RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1   0xe1
+#define RADIO_2057_TXMIX2G_LODC_CORE1            0xe2
+#define RADIO_2057_PAD2G_TUNE_PUS_CORE1          0xe3
+#define RADIO_2057_IPA2G_GAIN_CORE1              0xe4
+#define RADIO_2057_TSSI2G_SPARE1_CORE1           0xe5
+#define RADIO_2057_TSSI2G_SPARE2_CORE1           0xe6
+#define RADIO_2057_IPA2G_TUNEV_CASCV_PTAT_CORE1  0xe7
+#define RADIO_2057_IPA2G_IMAIN_CORE1             0xe8
+#define RADIO_2057_IPA2G_CASCONV_CORE1           0xe9
+#define RADIO_2057_IPA2G_CASCOFFV_CORE1          0xea
+#define RADIO_2057_IPA2G_BIAS_FILTER_CORE1       0xeb
+#define RADIO_2057_TX5G_PKDET_CORE1              0xee
+#define RADIO_2057_PGA_PTAT_TXGM5G_PU_CORE1      0xef
+#define RADIO_2057_PAD5G_PTATS1_CORE1            0xf0
+#define RADIO_2057_PAD5G_CLASS_PTATS2_CORE1      0xf1
+#define RADIO_2057_PGA_BOOSTPTAT_IMAIN_CORE1     0xf2
+#define RADIO_2057_PAD5G_CASCV_IMAIN_CORE1       0xf3
+#define RADIO_2057_TXMIX5G_IBOOST_PAD_IAUX_CORE1 0xf4
+#define RADIO_2057_PGA_BOOST_TUNE_CORE1          0xf5
+#define RADIO_2057_PGA_GAIN_CORE1                0xf6
+#define RADIO_2057_PAD5G_CASCOFFV_GAIN_PUS_CORE1 0xf7
+#define RADIO_2057_TXMIX5G_BOOST_TUNE_CORE1      0xf8
+#define RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE1     0xf9
+#define RADIO_2057_IPA5G_IAUX_CORE1              0xfa
+#define RADIO_2057_IPA5G_GAIN_CORE1              0xfb
+#define RADIO_2057_TSSI5G_SPARE1_CORE1           0xfc
+#define RADIO_2057_TSSI5G_SPARE2_CORE1           0xfd
+#define RADIO_2057_IPA5G_CASCOFFV_PU_CORE1       0xfe
+#define RADIO_2057_IPA5G_PTAT_CORE1              0xff
+#define RADIO_2057_IPA5G_IMAIN_CORE1             0x100
+#define RADIO_2057_IPA5G_CASCONV_CORE1           0x101
+#define RADIO_2057_IPA5G_BIAS_FILTER_CORE1       0x102
+#define RADIO_2057_PAD_BIAS_FILTER_BWS_CORE1     0x105
+#define RADIO_2057_TR2G_CONFIG1_CORE1_NU         0x106
+#define RADIO_2057_TR2G_CONFIG2_CORE1_NU         0x107
+#define RADIO_2057_LNA5G_RFEN_CORE1              0x108
+#define RADIO_2057_TR5G_CONFIG2_CORE1_NU         0x109
+#define RADIO_2057_RXRFBIAS_IBOOST_PU_CORE1      0x10a
+#define RADIO_2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE1 0x10b
+#define RADIO_2057_RXGM_CMFBITAIL_AUXPTAT_CORE1  0x10c
+#define RADIO_2057_RXMIX_ICORE_RXGM_IAUX_CORE1   0x10d
+#define RADIO_2057_RXMIX_CMFBITAIL_PU_CORE1      0x10e
+#define RADIO_2057_LNA2_IMAIN_PTAT_PU_CORE1      0x10f
+#define RADIO_2057_LNA2_IAUX_PTAT_CORE1          0x110
+#define RADIO_2057_LNA1_IMAIN_PTAT_PU_CORE1      0x111
+#define RADIO_2057_LNA15G_INPUT_MATCH_TUNE_CORE1 0x112
+#define RADIO_2057_RXRFBIAS_BANDSEL_CORE1        0x113
+#define RADIO_2057_TIA_CONFIG_CORE1              0x114
+#define RADIO_2057_TIA_IQGAIN_CORE1              0x115
+#define RADIO_2057_TIA_IBIAS2_CORE1              0x116
+#define RADIO_2057_TIA_IBIAS1_CORE1              0x117
+#define RADIO_2057_TIA_SPARE_Q_CORE1             0x118
+#define RADIO_2057_TIA_SPARE_I_CORE1             0x119
+#define RADIO_2057_RXMIX2G_PUS_CORE1             0x11a
+#define RADIO_2057_RXMIX2G_VCMREFS_CORE1         0x11b
+#define RADIO_2057_RXMIX2G_LODC_QI_CORE1         0x11c
+#define RADIO_2057_W12G_BW_LNA2G_PUS_CORE1       0x11d
+#define RADIO_2057_LNA2G_GAIN_CORE1              0x11e
+#define RADIO_2057_LNA2G_TUNE_CORE1              0x11f
+#define RADIO_2057_RXMIX5G_PUS_CORE1             0x120
+#define RADIO_2057_RXMIX5G_VCMREFS_CORE1         0x121
+#define RADIO_2057_RXMIX5G_LODC_QI_CORE1         0x122
+#define RADIO_2057_W15G_BW_LNA5G_PUS_CORE1       0x123
+#define RADIO_2057_LNA5G_GAIN_CORE1              0x124
+#define RADIO_2057_LNA5G_TUNE_CORE1              0x125
+#define RADIO_2057_LPFSEL_TXRX_RXBB_PUS_CORE1    0x126
+#define RADIO_2057_RXBB_BIAS_MASTER_CORE1        0x127
+#define RADIO_2057_RXBB_VGABUF_IDACS_CORE1       0x128
+#define RADIO_2057_LPF_VCMREF_TXBUF_VCMREF_CORE1 0x129
+#define RADIO_2057_TXBUF_VINCM_CORE1             0x12a
+#define RADIO_2057_TXBUF_IDACS_CORE1             0x12b
+#define RADIO_2057_LPF_RESP_RXBUF_BW_CORE1       0x12c
+#define RADIO_2057_RXBB_CC_CORE1                 0x12d
+#define RADIO_2057_RXBB_SPARE3_CORE1             0x12e
+#define RADIO_2057_RXBB_RCCAL_HPC_CORE1          0x12f
+#define RADIO_2057_LPF_IDACS_CORE1               0x130
+#define RADIO_2057_LPFBYP_DCLOOP_BYP_IDAC_CORE1  0x131
+#define RADIO_2057_TXBUF_GAIN_CORE1              0x132
+#define RADIO_2057_AFELOOPBACK_AACI_RESP_CORE1   0x133
+#define RADIO_2057_RXBUF_DEGEN_CORE1             0x134
+#define RADIO_2057_RXBB_SPARE2_CORE1             0x135
+#define RADIO_2057_RXBB_SPARE1_CORE1             0x136
+#define RADIO_2057_RSSI_MASTER_CORE1             0x137
+#define RADIO_2057_W2_MASTER_CORE1               0x138
+#define RADIO_2057_NB_MASTER_CORE1               0x139
+#define RADIO_2057_W2_IDACS0_Q_CORE1             0x13a
+#define RADIO_2057_W2_IDACS1_Q_CORE1             0x13b
+#define RADIO_2057_W2_IDACS0_I_CORE1             0x13c
+#define RADIO_2057_W2_IDACS1_I_CORE1             0x13d
+#define RADIO_2057_RSSI_GPAIOSEL_W1_IDACS_CORE1  0x13e
+#define RADIO_2057_NB_IDACS_Q_CORE1              0x13f
+#define RADIO_2057_NB_IDACS_I_CORE1              0x140
+#define RADIO_2057_BACKUP4_CORE1                 0x146
+#define RADIO_2057_BACKUP3_CORE1                 0x147
+#define RADIO_2057_BACKUP2_CORE1                 0x148
+#define RADIO_2057_BACKUP1_CORE1                 0x149
+#define RADIO_2057_SPARE16_CORE1                 0x14a
+#define RADIO_2057_SPARE15_CORE1                 0x14b
+#define RADIO_2057_SPARE14_CORE1                 0x14c
+#define RADIO_2057_SPARE13_CORE1                 0x14d
+#define RADIO_2057_SPARE12_CORE1                 0x14e
+#define RADIO_2057_SPARE11_CORE1                 0x14f
+#define RADIO_2057_TX2G_BIAS_RESETS_CORE1        0x150
+#define RADIO_2057_TX5G_BIAS_RESETS_CORE1        0x151
+#define RADIO_2057_SPARE8_CORE1                  0x152
+#define RADIO_2057_SPARE7_CORE1                  0x153
+#define RADIO_2057_BUFS_MISC_LPFBW_CORE1         0x154
+#define RADIO_2057_TXLPF_RCCAL_CORE1             0x155
+#define RADIO_2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE1 0x156
+#define RADIO_2057_LPF_GAIN_CORE1                0x157
+#define RADIO_2057_DACBUF_IDACS_BW_CORE1         0x158
+#define RADIO_2057_DACBUF_VINCM_CORE1            0x159
+#define RADIO_2057_RCCAL_START_R1_Q1_P1          0x15a
+#define RADIO_2057_RCCAL_X1                      0x15b
+#define RADIO_2057_RCCAL_TRC0                    0x15c
+#define RADIO_2057_RCCAL_TRC1                    0x15d
+#define RADIO_2057_RCCAL_DONE_OSCCAP             0x15e
+#define RADIO_2057_RCCAL_N0_0                    0x15f
+#define RADIO_2057_RCCAL_N0_1                    0x160
+#define RADIO_2057_RCCAL_N1_0                    0x161
+#define RADIO_2057_RCCAL_N1_1                    0x162
+#define RADIO_2057_RCAL_STATUS                   0x163
+#define RADIO_2057_XTALPUOVR_PINCTRL             0x164
+#define RADIO_2057_OVR_REG0                      0x165
+#define RADIO_2057_OVR_REG1                      0x166
+#define RADIO_2057_OVR_REG2                      0x167
+#define RADIO_2057_OVR_REG3                      0x168
+#define RADIO_2057_OVR_REG4                      0x169
+#define RADIO_2057_RCCAL_SCAP_VAL                0x16a
+#define RADIO_2057_RCCAL_BCAP_VAL                0x16b
+#define RADIO_2057_RCCAL_HPC_VAL                 0x16c
+#define RADIO_2057_RCCAL_OVERRIDES               0x16d
+#define RADIO_2057_TX0_IQCAL_GAIN_BW             0x170
+#define RADIO_2057_TX0_LOFT_FINE_I               0x171
+#define RADIO_2057_TX0_LOFT_FINE_Q               0x172
+#define RADIO_2057_TX0_LOFT_COARSE_I             0x173
+#define RADIO_2057_TX0_LOFT_COARSE_Q             0x174
+#define RADIO_2057_TX0_TX_SSI_MASTER             0x175
+#define RADIO_2057_TX0_IQCAL_VCM_HG              0x176
+#define RADIO_2057_TX0_IQCAL_IDAC                0x177
+#define RADIO_2057_TX0_TSSI_VCM                  0x178
+#define RADIO_2057_TX0_TX_SSI_MUX                0x179
+#define RADIO_2057_TX0_TSSIA                     0x17a
+#define RADIO_2057_TX0_TSSIG                     0x17b
+#define RADIO_2057_TX0_TSSI_MISC1                0x17c
+#define RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN       0x17d
+#define RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP       0x17e
+#define RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN       0x17f
+#define RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP       0x180
+#define RADIO_2057_TX1_IQCAL_GAIN_BW             0x190
+#define RADIO_2057_TX1_LOFT_FINE_I               0x191
+#define RADIO_2057_TX1_LOFT_FINE_Q               0x192
+#define RADIO_2057_TX1_LOFT_COARSE_I             0x193
+#define RADIO_2057_TX1_LOFT_COARSE_Q             0x194
+#define RADIO_2057_TX1_TX_SSI_MASTER             0x195
+#define RADIO_2057_TX1_IQCAL_VCM_HG              0x196
+#define RADIO_2057_TX1_IQCAL_IDAC                0x197
+#define RADIO_2057_TX1_TSSI_VCM                  0x198
+#define RADIO_2057_TX1_TX_SSI_MUX                0x199
+#define RADIO_2057_TX1_TSSIA                     0x19a
+#define RADIO_2057_TX1_TSSIG                     0x19b
+#define RADIO_2057_TX1_TSSI_MISC1                0x19c
+#define RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN       0x19d
+#define RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP       0x19e
+#define RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN       0x19f
+#define RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP       0x1a0
+#define RADIO_2057_AFE_VCM_CAL_MASTER_CORE0      0x1a1
+#define RADIO_2057_AFE_SET_VCM_I_CORE0           0x1a2
+#define RADIO_2057_AFE_SET_VCM_Q_CORE0           0x1a3
+#define RADIO_2057_AFE_STATUS_VCM_IQADC_CORE0    0x1a4
+#define RADIO_2057_AFE_STATUS_VCM_I_CORE0        0x1a5
+#define RADIO_2057_AFE_STATUS_VCM_Q_CORE0        0x1a6
+#define RADIO_2057_AFE_VCM_CAL_MASTER_CORE1      0x1a7
+#define RADIO_2057_AFE_SET_VCM_I_CORE1           0x1a8
+#define RADIO_2057_AFE_SET_VCM_Q_CORE1           0x1a9
+#define RADIO_2057_AFE_STATUS_VCM_IQADC_CORE1    0x1aa
+#define RADIO_2057_AFE_STATUS_VCM_I_CORE1        0x1ab
+#define RADIO_2057_AFE_STATUS_VCM_Q_CORE1        0x1ac
+
+#define RADIO_2057v7_DACBUF_VINCM_CORE0          0x1ad
+#define RADIO_2057v7_RCCAL_MASTER                0x1ae
+#define RADIO_2057v7_TR2G_CONFIG3_CORE0_NU       0x1af
+#define RADIO_2057v7_TR2G_CONFIG3_CORE1_NU       0x1b0
+#define RADIO_2057v7_LOGEN_PUS1                  0x1b1
+#define RADIO_2057v7_OVR_REG5                    0x1b2
+#define RADIO_2057v7_OVR_REG6                    0x1b3
+#define RADIO_2057v7_OVR_REG7                    0x1b4
+#define RADIO_2057v7_OVR_REG8                    0x1b5
+#define RADIO_2057v7_OVR_REG9                    0x1b6
+#define RADIO_2057v7_OVR_REG10                   0x1b7
+#define RADIO_2057v7_OVR_REG11                   0x1b8
+#define RADIO_2057v7_OVR_REG12                   0x1b9
+#define RADIO_2057v7_OVR_REG13                   0x1ba
+#define RADIO_2057v7_OVR_REG14                   0x1bb
+#define RADIO_2057v7_OVR_REG15                   0x1bc
+#define RADIO_2057v7_OVR_REG16                   0x1bd
+#define RADIO_2057v7_OVR_REG1                    0x1be
+#define RADIO_2057v7_OVR_REG18                   0x1bf
+#define RADIO_2057v7_OVR_REG19                   0x1c0
+#define RADIO_2057v7_OVR_REG20                   0x1c1
+#define RADIO_2057v7_OVR_REG21                   0x1c2
+#define RADIO_2057v7_OVR_REG2                    0x1c3
+#define RADIO_2057v7_OVR_REG23                   0x1c4
+#define RADIO_2057v7_OVR_REG24                   0x1c5
+#define RADIO_2057v7_OVR_REG25                   0x1c6
+#define RADIO_2057v7_OVR_REG26                   0x1c7
+#define RADIO_2057v7_OVR_REG27                   0x1c8
+#define RADIO_2057v7_OVR_REG28                   0x1c9
+#define RADIO_2057v7_IQTEST_SEL_PU2              0x1ca
+
+#define RADIO_2057_VCM_MASK			 0x7
+
+#endif				/* _BRCM_PHY_RADIO_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phyreg_n.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phyreg_n.h
new file mode 100644
index 0000000..a97c3a7
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phyreg_n.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define NPHY_TBL_ID_GAIN1		0
+#define NPHY_TBL_ID_GAIN2		1
+#define NPHY_TBL_ID_GAINBITS1		2
+#define NPHY_TBL_ID_GAINBITS2		3
+#define NPHY_TBL_ID_GAINLIMIT		4
+#define NPHY_TBL_ID_WRSSIGainLimit	5
+#define NPHY_TBL_ID_RFSEQ		7
+#define NPHY_TBL_ID_AFECTRL		8
+#define NPHY_TBL_ID_ANTSWCTRLLUT	9
+#define NPHY_TBL_ID_IQLOCAL		15
+#define NPHY_TBL_ID_NOISEVAR		16
+#define NPHY_TBL_ID_SAMPLEPLAY		17
+#define NPHY_TBL_ID_CORE1TXPWRCTL	26
+#define NPHY_TBL_ID_CORE2TXPWRCTL	27
+#define NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL	30
+
+#define NPHY_TBL_ID_EPSILONTBL0   31
+#define NPHY_TBL_ID_SCALARTBL0    32
+#define NPHY_TBL_ID_EPSILONTBL1   33
+#define NPHY_TBL_ID_SCALARTBL1    34
+
+#define	NPHY_TO_BPHY_OFF	0xc00
+
+#define NPHY_BandControl_currentBand			0x0001
+#define RFCC_CHIP0_PU			0x0400
+#define RFCC_POR_FORCE			0x0040
+#define RFCC_OE_POR_FORCE		0x0080
+#define NPHY_RfctrlIntc_override_OFF			0
+#define NPHY_RfctrlIntc_override_TRSW			1
+#define NPHY_RfctrlIntc_override_PA				2
+#define NPHY_RfctrlIntc_override_EXT_LNA_PU		3
+#define NPHY_RfctrlIntc_override_EXT_LNA_GAIN	4
+#define RIFS_ENABLE			0x80
+#define BPHY_BAND_SEL_UP20		0x10
+#define NPHY_MLenable			0x02
+
+#define NPHY_RfseqMode_CoreActv_override 0x0001
+#define NPHY_RfseqMode_Trigger_override	0x0002
+#define NPHY_RfseqCoreActv_TxRxChain0	(0x11)
+#define NPHY_RfseqCoreActv_TxRxChain1	(0x22)
+
+#define NPHY_RfseqTrigger_rx2tx		0x0001
+#define NPHY_RfseqTrigger_tx2rx		0x0002
+#define NPHY_RfseqTrigger_updategainh	0x0004
+#define NPHY_RfseqTrigger_updategainl	0x0008
+#define NPHY_RfseqTrigger_updategainu	0x0010
+#define NPHY_RfseqTrigger_reset2rx	0x0020
+#define NPHY_RfseqStatus_rx2tx		0x0001
+#define NPHY_RfseqStatus_tx2rx		0x0002
+#define NPHY_RfseqStatus_updategainh	0x0004
+#define NPHY_RfseqStatus_updategainl	0x0008
+#define NPHY_RfseqStatus_updategainu	0x0010
+#define NPHY_RfseqStatus_reset2rx	0x0020
+#define NPHY_ClassifierCtrl_cck_en	0x1
+#define NPHY_ClassifierCtrl_ofdm_en	0x2
+#define NPHY_ClassifierCtrl_waited_en	0x4
+#define NPHY_IQFlip_ADC1		0x0001
+#define NPHY_IQFlip_ADC2		0x0010
+#define NPHY_sampleCmd_STOP		0x0002
+
+#define RX_GF_OR_MM			0x0004
+#define RX_GF_MM_AUTO			0x0100
+
+#define NPHY_iqloCalCmdGctl_IQLO_CAL_EN	0x8000
+
+#define NPHY_IqestCmd_iqstart		0x1
+#define NPHY_IqestCmd_iqMode		0x2
+
+#define NPHY_TxPwrCtrlCmd_pwrIndex_init		0x40
+#define NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7	0x19
+
+#define PRIM_SEL_UP20		0x8000
+
+#define NPHY_RFSEQ_RX2TX		0x0
+#define NPHY_RFSEQ_TX2RX		0x1
+#define NPHY_RFSEQ_RESET2RX		0x2
+#define NPHY_RFSEQ_UPDATEGAINH		0x3
+#define NPHY_RFSEQ_UPDATEGAINL		0x4
+#define NPHY_RFSEQ_UPDATEGAINU		0x5
+
+#define NPHY_RFSEQ_CMD_NOP		0x0
+#define NPHY_RFSEQ_CMD_RXG_FBW		0x1
+#define NPHY_RFSEQ_CMD_TR_SWITCH	0x2
+#define NPHY_RFSEQ_CMD_EXT_PA		0x3
+#define NPHY_RFSEQ_CMD_RXPD_TXPD	0x4
+#define NPHY_RFSEQ_CMD_TX_GAIN		0x5
+#define NPHY_RFSEQ_CMD_RX_GAIN		0x6
+#define NPHY_RFSEQ_CMD_SET_HPF_BW	0x7
+#define NPHY_RFSEQ_CMD_CLR_HIQ_DIS	0x8
+#define NPHY_RFSEQ_CMD_END		0xf
+
+#define NPHY_REV3_RFSEQ_CMD_NOP		0x0
+#define NPHY_REV3_RFSEQ_CMD_RXG_FBW	0x1
+#define NPHY_REV3_RFSEQ_CMD_TR_SWITCH	0x2
+#define NPHY_REV3_RFSEQ_CMD_INT_PA_PU	0x3
+#define NPHY_REV3_RFSEQ_CMD_EXT_PA	0x4
+#define NPHY_REV3_RFSEQ_CMD_RXPD_TXPD	0x5
+#define NPHY_REV3_RFSEQ_CMD_TX_GAIN	0x6
+#define NPHY_REV3_RFSEQ_CMD_RX_GAIN	0x7
+#define NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS	0x8
+#define NPHY_REV3_RFSEQ_CMD_SET_HPF_H_HPC	0x9
+#define NPHY_REV3_RFSEQ_CMD_SET_LPF_H_HPC	0xa
+#define NPHY_REV3_RFSEQ_CMD_SET_HPF_M_HPC	0xb
+#define NPHY_REV3_RFSEQ_CMD_SET_LPF_M_HPC	0xc
+#define NPHY_REV3_RFSEQ_CMD_SET_HPF_L_HPC	0xd
+#define NPHY_REV3_RFSEQ_CMD_SET_LPF_L_HPC	0xe
+#define NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS	0xf
+#define NPHY_REV3_RFSEQ_CMD_END		0x1f
+
+#define NPHY_RSSI_SEL_W1		0x0
+#define NPHY_RSSI_SEL_W2		0x1
+#define NPHY_RSSI_SEL_NB		0x2
+#define NPHY_RSSI_SEL_IQ		0x3
+#define NPHY_RSSI_SEL_TSSI_2G		0x4
+#define NPHY_RSSI_SEL_TSSI_5G		0x5
+#define NPHY_RSSI_SEL_TBD		0x6
+
+#define NPHY_RAIL_I			0x0
+#define NPHY_RAIL_Q			0x1
+
+#define NPHY_FORCESIG_DECODEGATEDCLKS	0x8
+
+#define NPHY_REV7_RfctrlOverride_cmd_rxrf_pu 0x0
+#define NPHY_REV7_RfctrlOverride_cmd_rx_pu   0x1
+#define NPHY_REV7_RfctrlOverride_cmd_tx_pu   0x2
+#define NPHY_REV7_RfctrlOverride_cmd_rxgain  0x3
+#define NPHY_REV7_RfctrlOverride_cmd_txgain  0x4
+
+#define NPHY_REV7_RXGAINCODE_RFMXGAIN_MASK 0x000ff
+#define NPHY_REV7_RXGAINCODE_LPFGAIN_MASK  0x0ff00
+#define NPHY_REV7_RXGAINCODE_DVGAGAIN_MASK 0xf0000
+
+#define NPHY_REV7_TXGAINCODE_TGAIN_MASK     0x7fff
+#define NPHY_REV7_TXGAINCODE_LPFGAIN_MASK   0x8000
+#define NPHY_REV7_TXGAINCODE_BIQ0GAIN_SHIFT 14
+
+#define NPHY_REV7_RFCTRLOVERRIDE_ID0 0x0
+#define NPHY_REV7_RFCTRLOVERRIDE_ID1 0x1
+#define NPHY_REV7_RFCTRLOVERRIDE_ID2 0x2
+
+#define NPHY_IqestIqAccLo(core)  ((core == 0) ? 0x12c : 0x134)
+
+#define NPHY_IqestIqAccHi(core)  ((core == 0) ? 0x12d : 0x135)
+
+#define NPHY_IqestipwrAccLo(core)  ((core == 0) ? 0x12e : 0x136)
+
+#define NPHY_IqestipwrAccHi(core)  ((core == 0) ? 0x12f : 0x137)
+
+#define NPHY_IqestqpwrAccLo(core)  ((core == 0) ? 0x130 : 0x138)
+
+#define NPHY_IqestqpwrAccHi(core)  ((core == 0) ? 0x131 : 0x139)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phytbl_lcn.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phytbl_lcn.c
new file mode 100644
index 0000000..d7fa312
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phytbl_lcn.c
@@ -0,0 +1,3293 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <types.h>
+#include "phytbl_lcn.h"
+
+static const u32 dot11lcn_gain_tbl_rev0[] = {
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000004,
+	0x00000000,
+	0x00000004,
+	0x00000008,
+	0x00000001,
+	0x00000005,
+	0x00000009,
+	0x0000000d,
+	0x0000004d,
+	0x0000008d,
+	0x0000000d,
+	0x0000004d,
+	0x0000008d,
+	0x000000cd,
+	0x0000004f,
+	0x0000008f,
+	0x000000cf,
+	0x000000d3,
+	0x00000113,
+	0x00000513,
+	0x00000913,
+	0x00000953,
+	0x00000d53,
+	0x00001153,
+	0x00001193,
+	0x00005193,
+	0x00009193,
+	0x0000d193,
+	0x00011193,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000004,
+	0x00000000,
+	0x00000004,
+	0x00000008,
+	0x00000001,
+	0x00000005,
+	0x00000009,
+	0x0000000d,
+	0x0000004d,
+	0x0000008d,
+	0x0000000d,
+	0x0000004d,
+	0x0000008d,
+	0x000000cd,
+	0x0000004f,
+	0x0000008f,
+	0x000000cf,
+	0x000000d3,
+	0x00000113,
+	0x00000513,
+	0x00000913,
+	0x00000953,
+	0x00000d53,
+	0x00001153,
+	0x00005153,
+	0x00009153,
+	0x0000d153,
+	0x00011153,
+	0x00015153,
+	0x00019153,
+	0x0001d153,
+	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 dot11lcn_gain_tbl_rev1[] = {
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000008,
+	0x00000004,
+	0x00000008,
+	0x00000001,
+	0x00000005,
+	0x00000009,
+	0x0000000D,
+	0x00000011,
+	0x00000051,
+	0x00000091,
+	0x00000011,
+	0x00000051,
+	0x00000091,
+	0x000000d1,
+	0x00000053,
+	0x00000093,
+	0x000000d3,
+	0x000000d7,
+	0x00000117,
+	0x00000517,
+	0x00000917,
+	0x00000957,
+	0x00000d57,
+	0x00001157,
+	0x00001197,
+	0x00005197,
+	0x00009197,
+	0x0000d197,
+	0x00011197,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000008,
+	0x00000004,
+	0x00000008,
+	0x00000001,
+	0x00000005,
+	0x00000009,
+	0x0000000D,
+	0x00000011,
+	0x00000051,
+	0x00000091,
+	0x00000011,
+	0x00000051,
+	0x00000091,
+	0x000000d1,
+	0x00000053,
+	0x00000093,
+	0x000000d3,
+	0x000000d7,
+	0x00000117,
+	0x00000517,
+	0x00000917,
+	0x00000957,
+	0x00000d57,
+	0x00001157,
+	0x00005157,
+	0x00009157,
+	0x0000d157,
+	0x00011157,
+	0x00015157,
+	0x00019157,
+	0x0001d157,
+	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 dot11lcn_aux_gain_idx_tbl_rev0[] = {
+	0x0401,
+	0x0402,
+	0x0403,
+	0x0404,
+	0x0405,
+	0x0406,
+	0x0407,
+	0x0408,
+	0x0409,
+	0x040a,
+	0x058b,
+	0x058c,
+	0x058d,
+	0x058e,
+	0x058f,
+	0x0090,
+	0x0091,
+	0x0092,
+	0x0193,
+	0x0194,
+	0x0195,
+	0x0196,
+	0x0197,
+	0x0198,
+	0x0199,
+	0x019a,
+	0x019b,
+	0x019c,
+	0x019d,
+	0x019e,
+	0x019f,
+	0x01a0,
+	0x01a1,
+	0x01a2,
+	0x01a3,
+	0x01a4,
+	0x01a5,
+	0x0000,
+};
+
+static const u32 dot11lcn_gain_idx_tbl_rev0[] = {
+	0x00000000,
+	0x00000000,
+	0x10000000,
+	0x00000000,
+	0x20000000,
+	0x00000000,
+	0x30000000,
+	0x00000000,
+	0x40000000,
+	0x00000000,
+	0x50000000,
+	0x00000000,
+	0x60000000,
+	0x00000000,
+	0x70000000,
+	0x00000000,
+	0x80000000,
+	0x00000000,
+	0x90000000,
+	0x00000008,
+	0xa0000000,
+	0x00000008,
+	0xb0000000,
+	0x00000008,
+	0xc0000000,
+	0x00000008,
+	0xd0000000,
+	0x00000008,
+	0xe0000000,
+	0x00000008,
+	0xf0000000,
+	0x00000008,
+	0x00000000,
+	0x00000009,
+	0x10000000,
+	0x00000009,
+	0x20000000,
+	0x00000019,
+	0x30000000,
+	0x00000019,
+	0x40000000,
+	0x00000019,
+	0x50000000,
+	0x00000019,
+	0x60000000,
+	0x00000019,
+	0x70000000,
+	0x00000019,
+	0x80000000,
+	0x00000019,
+	0x90000000,
+	0x00000019,
+	0xa0000000,
+	0x00000019,
+	0xb0000000,
+	0x00000019,
+	0xc0000000,
+	0x00000019,
+	0xd0000000,
+	0x00000019,
+	0xe0000000,
+	0x00000019,
+	0xf0000000,
+	0x00000019,
+	0x00000000,
+	0x0000001a,
+	0x10000000,
+	0x0000001a,
+	0x20000000,
+	0x0000001a,
+	0x30000000,
+	0x0000001a,
+	0x40000000,
+	0x0000001a,
+	0x50000000,
+	0x00000002,
+	0x60000000,
+	0x00000002,
+	0x70000000,
+	0x00000002,
+	0x80000000,
+	0x00000002,
+	0x90000000,
+	0x00000002,
+	0xa0000000,
+	0x00000002,
+	0xb0000000,
+	0x00000002,
+	0xc0000000,
+	0x0000000a,
+	0xd0000000,
+	0x0000000a,
+	0xe0000000,
+	0x0000000a,
+	0xf0000000,
+	0x0000000a,
+	0x00000000,
+	0x0000000b,
+	0x10000000,
+	0x0000000b,
+	0x20000000,
+	0x0000000b,
+	0x30000000,
+	0x0000000b,
+	0x40000000,
+	0x0000000b,
+	0x50000000,
+	0x0000001b,
+	0x60000000,
+	0x0000001b,
+	0x70000000,
+	0x0000001b,
+	0x80000000,
+	0x0000001b,
+	0x90000000,
+	0x0000001b,
+	0xa0000000,
+	0x0000001b,
+	0xb0000000,
+	0x0000001b,
+	0xc0000000,
+	0x0000001b,
+	0xd0000000,
+	0x0000001b,
+	0xe0000000,
+	0x0000001b,
+	0xf0000000,
+	0x0000001b,
+	0x00000000,
+	0x0000001c,
+	0x10000000,
+	0x0000001c,
+	0x20000000,
+	0x0000001c,
+	0x30000000,
+	0x0000001c,
+	0x40000000,
+	0x0000001c,
+	0x50000000,
+	0x0000001c,
+	0x60000000,
+	0x0000001c,
+	0x70000000,
+	0x0000001c,
+	0x80000000,
+	0x0000001c,
+	0x90000000,
+	0x0000001c,
+};
+
+static const u16 dot11lcn_aux_gain_idx_tbl_2G[] = {
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0001,
+	0x0080,
+	0x0081,
+	0x0100,
+	0x0101,
+	0x0180,
+	0x0181,
+	0x0182,
+	0x0183,
+	0x0184,
+	0x0185,
+	0x0186,
+	0x0187,
+	0x0188,
+	0x0285,
+	0x0289,
+	0x028a,
+	0x028b,
+	0x028c,
+	0x028d,
+	0x028e,
+	0x028f,
+	0x0290,
+	0x0291,
+	0x0292,
+	0x0293,
+	0x0294,
+	0x0295,
+	0x0296,
+	0x0297,
+	0x0298,
+	0x0299,
+	0x029a,
+	0x0000
+};
+
+static const u8 dot11lcn_gain_val_tbl_2G[] = {
+	0xfc,
+	0x02,
+	0x08,
+	0x0e,
+	0x13,
+	0x1b,
+	0xfc,
+	0x02,
+	0x08,
+	0x0e,
+	0x13,
+	0x1b,
+	0xfc,
+	0x00,
+	0x0c,
+	0x03,
+	0xeb,
+	0xfe,
+	0x07,
+	0x0b,
+	0x0f,
+	0xfb,
+	0xfe,
+	0x01,
+	0x05,
+	0x08,
+	0x0b,
+	0x0e,
+	0x11,
+	0x14,
+	0x17,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x15,
+	0x18,
+	0x1b,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00
+};
+
+static const u32 dot11lcn_gain_idx_tbl_2G[] = {
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x10000000,
+	0x00000000,
+	0x00000000,
+	0x00000008,
+	0x10000000,
+	0x00000008,
+	0x00000000,
+	0x00000010,
+	0x10000000,
+	0x00000010,
+	0x00000000,
+	0x00000018,
+	0x10000000,
+	0x00000018,
+	0x20000000,
+	0x00000018,
+	0x30000000,
+	0x00000018,
+	0x40000000,
+	0x00000018,
+	0x50000000,
+	0x00000018,
+	0x60000000,
+	0x00000018,
+	0x70000000,
+	0x00000018,
+	0x80000000,
+	0x00000018,
+	0x50000000,
+	0x00000028,
+	0x90000000,
+	0x00000028,
+	0xa0000000,
+	0x00000028,
+	0xb0000000,
+	0x00000028,
+	0xc0000000,
+	0x00000028,
+	0xd0000000,
+	0x00000028,
+	0xe0000000,
+	0x00000028,
+	0xf0000000,
+	0x00000028,
+	0x00000000,
+	0x00000029,
+	0x10000000,
+	0x00000029,
+	0x20000000,
+	0x00000029,
+	0x30000000,
+	0x00000029,
+	0x40000000,
+	0x00000029,
+	0x50000000,
+	0x00000029,
+	0x60000000,
+	0x00000029,
+	0x70000000,
+	0x00000029,
+	0x80000000,
+	0x00000029,
+	0x90000000,
+	0x00000029,
+	0xa0000000,
+	0x00000029,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x10000000,
+	0x00000000,
+	0x00000000,
+	0x00000008,
+	0x10000000,
+	0x00000008,
+	0x00000000,
+	0x00000010,
+	0x10000000,
+	0x00000010,
+	0x00000000,
+	0x00000018,
+	0x10000000,
+	0x00000018,
+	0x20000000,
+	0x00000018,
+	0x30000000,
+	0x00000018,
+	0x40000000,
+	0x00000018,
+	0x50000000,
+	0x00000018,
+	0x60000000,
+	0x00000018,
+	0x70000000,
+	0x00000018,
+	0x80000000,
+	0x00000018,
+	0x50000000,
+	0x00000028,
+	0x90000000,
+	0x00000028,
+	0xa0000000,
+	0x00000028,
+	0xb0000000,
+	0x00000028,
+	0xc0000000,
+	0x00000028,
+	0xd0000000,
+	0x00000028,
+	0xe0000000,
+	0x00000028,
+	0xf0000000,
+	0x00000028,
+	0x00000000,
+	0x00000029,
+	0x10000000,
+	0x00000029,
+	0x20000000,
+	0x00000029,
+	0x30000000,
+	0x00000029,
+	0x40000000,
+	0x00000029,
+	0x50000000,
+	0x00000029,
+	0x60000000,
+	0x00000029,
+	0x70000000,
+	0x00000029,
+	0x80000000,
+	0x00000029,
+	0x90000000,
+	0x00000029,
+	0xa0000000,
+	0x00000029,
+	0xb0000000,
+	0x00000029,
+	0xc0000000,
+	0x00000029,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000
+};
+
+static const u32 dot11lcn_gain_tbl_2G[] = {
+	0x00000000,
+	0x00000004,
+	0x00000008,
+	0x00000001,
+	0x00000005,
+	0x00000009,
+	0x0000000d,
+	0x0000004d,
+	0x0000008d,
+	0x00000049,
+	0x00000089,
+	0x000000c9,
+	0x0000004b,
+	0x0000008b,
+	0x000000cb,
+	0x000000cf,
+	0x0000010f,
+	0x0000050f,
+	0x0000090f,
+	0x0000094f,
+	0x00000d4f,
+	0x0000114f,
+	0x0000118f,
+	0x0000518f,
+	0x0000918f,
+	0x0000d18f,
+	0x0001118f,
+	0x0001518f,
+	0x0001918f,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	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 dot11lcn_gain_tbl_extlna_2G[] = {
+	0x00000000,
+	0x00000004,
+	0x00000008,
+	0x00000001,
+	0x00000005,
+	0x00000009,
+	0x0000000d,
+	0x00000003,
+	0x00000007,
+	0x0000000b,
+	0x0000000f,
+	0x0000004f,
+	0x0000008f,
+	0x000000cf,
+	0x0000010f,
+	0x0000014f,
+	0x0000018f,
+	0x0000058f,
+	0x0000098f,
+	0x00000d8f,
+	0x00008000,
+	0x00008004,
+	0x00008008,
+	0x00008001,
+	0x00008005,
+	0x00008009,
+	0x0000800d,
+	0x00008003,
+	0x00008007,
+	0x0000800b,
+	0x0000800f,
+	0x0000804f,
+	0x0000808f,
+	0x000080cf,
+	0x0000810f,
+	0x0000814f,
+	0x0000818f,
+	0x0000858f,
+	0x0000898f,
+	0x00008d8f,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	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 dot11lcn_aux_gain_idx_tbl_extlna_2G[] = {
+	0x0400,
+	0x0400,
+	0x0400,
+	0x0400,
+	0x0400,
+	0x0400,
+	0x0400,
+	0x0400,
+	0x0400,
+	0x0401,
+	0x0402,
+	0x0403,
+	0x0404,
+	0x0483,
+	0x0484,
+	0x0485,
+	0x0486,
+	0x0583,
+	0x0584,
+	0x0585,
+	0x0587,
+	0x0588,
+	0x0589,
+	0x058a,
+	0x0687,
+	0x0688,
+	0x0689,
+	0x068a,
+	0x068b,
+	0x068c,
+	0x068d,
+	0x068e,
+	0x068f,
+	0x0690,
+	0x0691,
+	0x0692,
+	0x0693,
+	0x0000
+};
+
+static const u8 dot11lcn_gain_val_tbl_extlna_2G[] = {
+	0xfc,
+	0x02,
+	0x08,
+	0x0e,
+	0x13,
+	0x1b,
+	0xfc,
+	0x02,
+	0x08,
+	0x0e,
+	0x13,
+	0x1b,
+	0xfc,
+	0x00,
+	0x0f,
+	0x03,
+	0xeb,
+	0xfe,
+	0x07,
+	0x0b,
+	0x0f,
+	0xfb,
+	0xfe,
+	0x01,
+	0x05,
+	0x08,
+	0x0b,
+	0x0e,
+	0x11,
+	0x14,
+	0x17,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x15,
+	0x18,
+	0x1b,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00
+};
+
+static const u32 dot11lcn_gain_idx_tbl_extlna_2G[] = {
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x10000000,
+	0x00000040,
+	0x20000000,
+	0x00000040,
+	0x30000000,
+	0x00000040,
+	0x40000000,
+	0x00000040,
+	0x30000000,
+	0x00000048,
+	0x40000000,
+	0x00000048,
+	0x50000000,
+	0x00000048,
+	0x60000000,
+	0x00000048,
+	0x30000000,
+	0x00000058,
+	0x40000000,
+	0x00000058,
+	0x50000000,
+	0x00000058,
+	0x70000000,
+	0x00000058,
+	0x80000000,
+	0x00000058,
+	0x90000000,
+	0x00000058,
+	0xa0000000,
+	0x00000058,
+	0x70000000,
+	0x00000068,
+	0x80000000,
+	0x00000068,
+	0x90000000,
+	0x00000068,
+	0xa0000000,
+	0x00000068,
+	0xb0000000,
+	0x00000068,
+	0xc0000000,
+	0x00000068,
+	0xd0000000,
+	0x00000068,
+	0xe0000000,
+	0x00000068,
+	0xf0000000,
+	0x00000068,
+	0x00000000,
+	0x00000069,
+	0x10000000,
+	0x00000069,
+	0x20000000,
+	0x00000069,
+	0x30000000,
+	0x00000069,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x50000000,
+	0x00000041,
+	0x60000000,
+	0x00000041,
+	0x70000000,
+	0x00000041,
+	0x80000000,
+	0x00000041,
+	0x70000000,
+	0x00000049,
+	0x80000000,
+	0x00000049,
+	0x90000000,
+	0x00000049,
+	0xa0000000,
+	0x00000049,
+	0x70000000,
+	0x00000059,
+	0x80000000,
+	0x00000059,
+	0x90000000,
+	0x00000059,
+	0xb0000000,
+	0x00000059,
+	0xc0000000,
+	0x00000059,
+	0xd0000000,
+	0x00000059,
+	0xe0000000,
+	0x00000059,
+	0xb0000000,
+	0x00000069,
+	0xc0000000,
+	0x00000069,
+	0xd0000000,
+	0x00000069,
+	0xe0000000,
+	0x00000069,
+	0xf0000000,
+	0x00000069,
+	0x00000000,
+	0x0000006a,
+	0x10000000,
+	0x0000006a,
+	0x20000000,
+	0x0000006a,
+	0x30000000,
+	0x0000006a,
+	0x40000000,
+	0x0000006a,
+	0x50000000,
+	0x0000006a,
+	0x60000000,
+	0x0000006a,
+	0x70000000,
+	0x0000006a,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000
+};
+
+static const u32 dot11lcn_aux_gain_idx_tbl_5G[] = {
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0001,
+	0x0002,
+	0x0003,
+	0x0004,
+	0x0083,
+	0x0084,
+	0x0085,
+	0x0086,
+	0x0087,
+	0x0186,
+	0x0187,
+	0x0188,
+	0x0189,
+	0x018a,
+	0x018b,
+	0x018c,
+	0x018d,
+	0x018e,
+	0x018f,
+	0x0190,
+	0x0191,
+	0x0192,
+	0x0193,
+	0x0194,
+	0x0195,
+	0x0196,
+	0x0197,
+	0x0198,
+	0x0199,
+	0x019a,
+	0x019b,
+	0x019c,
+	0x019d,
+	0x0000
+};
+
+static const u32 dot11lcn_gain_val_tbl_5G[] = {
+	0xf7,
+	0xfd,
+	0x00,
+	0x04,
+	0x04,
+	0x04,
+	0xf7,
+	0xfd,
+	0x00,
+	0x04,
+	0x04,
+	0x04,
+	0xf6,
+	0x00,
+	0x0c,
+	0x03,
+	0xeb,
+	0xfe,
+	0x06,
+	0x0a,
+	0x10,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x15,
+	0x18,
+	0x1b,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x15,
+	0x18,
+	0x1b,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00
+};
+
+static const u32 dot11lcn_gain_idx_tbl_5G[] = {
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x10000000,
+	0x00000000,
+	0x20000000,
+	0x00000000,
+	0x30000000,
+	0x00000000,
+	0x40000000,
+	0x00000000,
+	0x30000000,
+	0x00000008,
+	0x40000000,
+	0x00000008,
+	0x50000000,
+	0x00000008,
+	0x60000000,
+	0x00000008,
+	0x70000000,
+	0x00000008,
+	0x60000000,
+	0x00000018,
+	0x70000000,
+	0x00000018,
+	0x80000000,
+	0x00000018,
+	0x90000000,
+	0x00000018,
+	0xa0000000,
+	0x00000018,
+	0xb0000000,
+	0x00000018,
+	0xc0000000,
+	0x00000018,
+	0xd0000000,
+	0x00000018,
+	0xe0000000,
+	0x00000018,
+	0xf0000000,
+	0x00000018,
+	0x00000000,
+	0x00000019,
+	0x10000000,
+	0x00000019,
+	0x20000000,
+	0x00000019,
+	0x30000000,
+	0x00000019,
+	0x40000000,
+	0x00000019,
+	0x50000000,
+	0x00000019,
+	0x60000000,
+	0x00000019,
+	0x70000000,
+	0x00000019,
+	0x80000000,
+	0x00000019,
+	0x90000000,
+	0x00000019,
+	0xa0000000,
+	0x00000019,
+	0xb0000000,
+	0x00000019,
+	0xc0000000,
+	0x00000019,
+	0xd0000000,
+	0x00000019,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	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 dot11lcn_gain_tbl_5G[] = {
+	0x00000000,
+	0x00000040,
+	0x00000080,
+	0x00000001,
+	0x00000005,
+	0x00000009,
+	0x0000000d,
+	0x00000011,
+	0x00000015,
+	0x00000055,
+	0x00000095,
+	0x00000017,
+	0x0000001b,
+	0x0000005b,
+	0x0000009b,
+	0x000000db,
+	0x0000011b,
+	0x0000015b,
+	0x0000019b,
+	0x0000059b,
+	0x0000099b,
+	0x00000d9b,
+	0x0000119b,
+	0x0000519b,
+	0x0000919b,
+	0x0000d19b,
+	0x0001119b,
+	0x0001519b,
+	0x0001919b,
+	0x0001d19b,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000
+};
+
+const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev0[] = {
+	{&dot11lcn_gain_tbl_rev0,
+	 ARRAY_SIZE(dot11lcn_gain_tbl_rev0), 18,
+	 0, 32}
+	,
+	{&dot11lcn_aux_gain_idx_tbl_rev0,
+	 ARRAY_SIZE(dot11lcn_aux_gain_idx_tbl_rev0), 14, 0, 16}
+	,
+	{&dot11lcn_gain_idx_tbl_rev0,
+	 ARRAY_SIZE(dot11lcn_gain_idx_tbl_rev0), 13, 0, 32}
+	,
+};
+
+static const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev1[] = {
+	{&dot11lcn_gain_tbl_rev1,
+	 ARRAY_SIZE(dot11lcn_gain_tbl_rev1), 18,
+	 0, 32}
+	,
+	{&dot11lcn_aux_gain_idx_tbl_rev0,
+	 ARRAY_SIZE(dot11lcn_aux_gain_idx_tbl_rev0), 14, 0, 16}
+	,
+	{&dot11lcn_gain_idx_tbl_rev0,
+	 ARRAY_SIZE(dot11lcn_gain_idx_tbl_rev0), 13, 0, 32}
+	,
+};
+
+const struct phytbl_info dot11lcnphytbl_rx_gain_info_2G_rev2[] = {
+	{&dot11lcn_gain_tbl_2G,
+	 ARRAY_SIZE(dot11lcn_gain_tbl_2G), 18, 0,
+	 32}
+	,
+	{&dot11lcn_aux_gain_idx_tbl_2G,
+	 ARRAY_SIZE(dot11lcn_aux_gain_idx_tbl_2G), 14, 0, 16}
+	,
+	{&dot11lcn_gain_idx_tbl_2G,
+	 ARRAY_SIZE(dot11lcn_gain_idx_tbl_2G),
+	 13, 0, 32}
+	,
+	{&dot11lcn_gain_val_tbl_2G,
+	 ARRAY_SIZE(dot11lcn_gain_val_tbl_2G),
+	 17, 0, 8}
+};
+
+const struct phytbl_info dot11lcnphytbl_rx_gain_info_5G_rev2[] = {
+	{&dot11lcn_gain_tbl_5G,
+	 ARRAY_SIZE(dot11lcn_gain_tbl_5G), 18, 0,
+	 32}
+	,
+	{&dot11lcn_aux_gain_idx_tbl_5G,
+	 ARRAY_SIZE(dot11lcn_aux_gain_idx_tbl_5G), 14, 0, 16}
+	,
+	{&dot11lcn_gain_idx_tbl_5G,
+	 ARRAY_SIZE(dot11lcn_gain_idx_tbl_5G),
+	 13, 0, 32}
+	,
+	{&dot11lcn_gain_val_tbl_5G,
+	 ARRAY_SIZE(dot11lcn_gain_val_tbl_5G),
+	 17, 0, 8}
+};
+
+const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_2G_rev2[] = {
+	{&dot11lcn_gain_tbl_extlna_2G,
+	 ARRAY_SIZE(dot11lcn_gain_tbl_extlna_2G), 18, 0, 32}
+	,
+	{&dot11lcn_aux_gain_idx_tbl_extlna_2G,
+	 ARRAY_SIZE(dot11lcn_aux_gain_idx_tbl_extlna_2G), 14, 0, 16}
+	,
+	{&dot11lcn_gain_idx_tbl_extlna_2G,
+	 ARRAY_SIZE(dot11lcn_gain_idx_tbl_extlna_2G), 13, 0, 32}
+	,
+	{&dot11lcn_gain_val_tbl_extlna_2G,
+	 ARRAY_SIZE(dot11lcn_gain_val_tbl_extlna_2G), 17, 0, 8}
+};
+
+const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_5G_rev2[] = {
+	{&dot11lcn_gain_tbl_5G,
+	 ARRAY_SIZE(dot11lcn_gain_tbl_5G), 18, 0,
+	 32}
+	,
+	{&dot11lcn_aux_gain_idx_tbl_5G,
+	 ARRAY_SIZE(dot11lcn_aux_gain_idx_tbl_5G), 14, 0, 16}
+	,
+	{&dot11lcn_gain_idx_tbl_5G,
+	 ARRAY_SIZE(dot11lcn_gain_idx_tbl_5G),
+	 13, 0, 32}
+	,
+	{&dot11lcn_gain_val_tbl_5G,
+	 ARRAY_SIZE(dot11lcn_gain_val_tbl_5G),
+	 17, 0, 8}
+};
+
+const u32 dot11lcnphytbl_rx_gain_info_sz_rev0 =
+	ARRAY_SIZE(dot11lcnphytbl_rx_gain_info_rev0);
+
+const u32 dot11lcnphytbl_rx_gain_info_2G_rev2_sz =
+	ARRAY_SIZE(dot11lcnphytbl_rx_gain_info_2G_rev2);
+
+const u32 dot11lcnphytbl_rx_gain_info_5G_rev2_sz =
+	ARRAY_SIZE(dot11lcnphytbl_rx_gain_info_5G_rev2);
+
+static const u16 dot11lcn_min_sig_sq_tbl_rev0[] = {
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+};
+
+static const u16 dot11lcn_noise_scale_tbl_rev0[] = {
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	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 dot11lcn_fltr_ctrl_tbl_rev0[] = {
+	0x000141f8,
+	0x000021f8,
+	0x000021fb,
+	0x000041fb,
+	0x0001fe4b,
+	0x0000217b,
+	0x00002133,
+	0x000040eb,
+	0x0001fea3,
+	0x0000024b,
+};
+
+static const u32 dot11lcn_ps_ctrl_tbl_rev0[] = {
+	0x00100001,
+	0x00200010,
+	0x00300001,
+	0x00400010,
+	0x00500022,
+	0x00600122,
+	0x00700222,
+	0x00800322,
+	0x00900422,
+	0x00a00522,
+	0x00b00622,
+	0x00c00722,
+	0x00d00822,
+	0x00f00922,
+	0x00100a22,
+	0x00200b22,
+	0x00300c22,
+	0x00400d22,
+	0x00500e22,
+	0x00600f22,
+};
+
+static const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[] = {
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+
+};
+
+static const u16 dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[] = {
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+};
+
+static const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = {
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+};
+
+static const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = {
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+};
+
+static const u16 dot11lcn_sw_ctrl_tbl_4313_ipa_rev0_combo[] = {
+	0x0005,
+	0x0006,
+	0x0009,
+	0x000a,
+	0x0005,
+	0x0006,
+	0x0009,
+	0x000a,
+	0x0005,
+	0x0006,
+	0x0009,
+	0x000a,
+	0x0005,
+	0x0006,
+	0x0009,
+	0x000a,
+	0x0005,
+	0x0006,
+	0x0009,
+	0x000a,
+	0x0005,
+	0x0006,
+	0x0009,
+	0x000a,
+	0x0005,
+	0x0006,
+	0x0009,
+	0x000a,
+	0x0005,
+	0x0006,
+	0x0009,
+	0x000a,
+	0x0005,
+	0x0006,
+	0x0009,
+	0x000a,
+	0x0005,
+	0x0006,
+	0x0009,
+	0x000a,
+	0x0005,
+	0x0006,
+	0x0009,
+	0x000a,
+	0x0005,
+	0x0006,
+	0x0009,
+	0x000a,
+	0x0005,
+	0x0006,
+	0x0009,
+	0x000a,
+	0x0005,
+	0x0006,
+	0x0009,
+	0x000a,
+	0x0005,
+	0x0006,
+	0x0009,
+	0x000a,
+	0x0005,
+	0x0006,
+	0x0009,
+	0x000a,
+};
+
+static const u16 dot11lcn_sw_ctrl_tbl_rev0[] = {
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+};
+
+static const u8 dot11lcn_nf_table_rev0[] = {
+	0x5f,
+	0x36,
+	0x29,
+	0x1f,
+	0x5f,
+	0x36,
+	0x29,
+	0x1f,
+	0x5f,
+	0x36,
+	0x29,
+	0x1f,
+	0x5f,
+	0x36,
+	0x29,
+	0x1f,
+};
+
+static const u8 dot11lcn_gain_val_tbl_rev0[] = {
+	0x09,
+	0x0f,
+	0x14,
+	0x18,
+	0xfe,
+	0x07,
+	0x0b,
+	0x0f,
+	0xfb,
+	0xfe,
+	0x01,
+	0x05,
+	0x08,
+	0x0b,
+	0x0e,
+	0x11,
+	0x14,
+	0x17,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x15,
+	0x18,
+	0x1b,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0xeb,
+	0x00,
+	0x00,
+};
+
+static const u8 dot11lcn_spur_tbl_rev0[] = {
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x02,
+	0x03,
+	0x01,
+	0x03,
+	0x02,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x02,
+	0x03,
+	0x01,
+	0x03,
+	0x02,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+};
+
+static const u16 dot11lcn_unsup_mcs_tbl_rev0[] = {
+	0x001a,
+	0x0034,
+	0x004e,
+	0x0068,
+	0x009c,
+	0x00d0,
+	0x00ea,
+	0x0104,
+	0x0034,
+	0x0068,
+	0x009c,
+	0x00d0,
+	0x0138,
+	0x01a0,
+	0x01d4,
+	0x0208,
+	0x004e,
+	0x009c,
+	0x00ea,
+	0x0138,
+	0x01d4,
+	0x0270,
+	0x02be,
+	0x030c,
+	0x0068,
+	0x00d0,
+	0x0138,
+	0x01a0,
+	0x0270,
+	0x0340,
+	0x03a8,
+	0x0410,
+	0x0018,
+	0x009c,
+	0x00d0,
+	0x0104,
+	0x00ea,
+	0x0138,
+	0x0186,
+	0x00d0,
+	0x0104,
+	0x0104,
+	0x0138,
+	0x016c,
+	0x016c,
+	0x01a0,
+	0x0138,
+	0x0186,
+	0x0186,
+	0x01d4,
+	0x0222,
+	0x0222,
+	0x0270,
+	0x0104,
+	0x0138,
+	0x016c,
+	0x0138,
+	0x016c,
+	0x01a0,
+	0x01d4,
+	0x01a0,
+	0x01d4,
+	0x0208,
+	0x0208,
+	0x023c,
+	0x0186,
+	0x01d4,
+	0x0222,
+	0x01d4,
+	0x0222,
+	0x0270,
+	0x02be,
+	0x0270,
+	0x02be,
+	0x030c,
+	0x030c,
+	0x035a,
+	0x0036,
+	0x006c,
+	0x00a2,
+	0x00d8,
+	0x0144,
+	0x01b0,
+	0x01e6,
+	0x021c,
+	0x006c,
+	0x00d8,
+	0x0144,
+	0x01b0,
+	0x0288,
+	0x0360,
+	0x03cc,
+	0x0438,
+	0x00a2,
+	0x0144,
+	0x01e6,
+	0x0288,
+	0x03cc,
+	0x0510,
+	0x05b2,
+	0x0654,
+	0x00d8,
+	0x01b0,
+	0x0288,
+	0x0360,
+	0x0510,
+	0x06c0,
+	0x0798,
+	0x0870,
+	0x0018,
+	0x0144,
+	0x01b0,
+	0x021c,
+	0x01e6,
+	0x0288,
+	0x032a,
+	0x01b0,
+	0x021c,
+	0x021c,
+	0x0288,
+	0x02f4,
+	0x02f4,
+	0x0360,
+	0x0288,
+	0x032a,
+	0x032a,
+	0x03cc,
+	0x046e,
+	0x046e,
+	0x0510,
+	0x021c,
+	0x0288,
+	0x02f4,
+	0x0288,
+	0x02f4,
+	0x0360,
+	0x03cc,
+	0x0360,
+	0x03cc,
+	0x0438,
+	0x0438,
+	0x04a4,
+	0x032a,
+	0x03cc,
+	0x046e,
+	0x03cc,
+	0x046e,
+	0x0510,
+	0x05b2,
+	0x0510,
+	0x05b2,
+	0x0654,
+	0x0654,
+	0x06f6,
+};
+
+static const u16 dot11lcn_iq_local_tbl_rev0[] = {
+	0x0200,
+	0x0300,
+	0x0400,
+	0x0600,
+	0x0800,
+	0x0b00,
+	0x1000,
+	0x1001,
+	0x1002,
+	0x1003,
+	0x1004,
+	0x1005,
+	0x1006,
+	0x1007,
+	0x1707,
+	0x2007,
+	0x2d07,
+	0x4007,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0200,
+	0x0300,
+	0x0400,
+	0x0600,
+	0x0800,
+	0x0b00,
+	0x1000,
+	0x1001,
+	0x1002,
+	0x1003,
+	0x1004,
+	0x1005,
+	0x1006,
+	0x1007,
+	0x1707,
+	0x2007,
+	0x2d07,
+	0x4007,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x4000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+};
+
+static const u32 dot11lcn_papd_compdelta_tbl_rev0[] = {
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+};
+
+const struct phytbl_info dot11lcnphytbl_info_rev0[] = {
+	{&dot11lcn_min_sig_sq_tbl_rev0,
+	 ARRAY_SIZE(dot11lcn_min_sig_sq_tbl_rev0), 2, 0, 16}
+	,
+	{&dot11lcn_noise_scale_tbl_rev0,
+	 ARRAY_SIZE(dot11lcn_noise_scale_tbl_rev0), 1, 0, 16}
+	,
+	{&dot11lcn_fltr_ctrl_tbl_rev0,
+	 ARRAY_SIZE(dot11lcn_fltr_ctrl_tbl_rev0), 11, 0, 32}
+	,
+	{&dot11lcn_ps_ctrl_tbl_rev0,
+	 ARRAY_SIZE(dot11lcn_ps_ctrl_tbl_rev0), 12, 0, 32}
+	,
+	{&dot11lcn_gain_idx_tbl_rev0,
+	 ARRAY_SIZE(dot11lcn_gain_idx_tbl_rev0), 13, 0, 32}
+	,
+	{&dot11lcn_aux_gain_idx_tbl_rev0,
+	 ARRAY_SIZE(dot11lcn_aux_gain_idx_tbl_rev0), 14, 0, 16}
+	,
+	{&dot11lcn_sw_ctrl_tbl_rev0,
+	 ARRAY_SIZE(dot11lcn_sw_ctrl_tbl_rev0), 15, 0, 16}
+	,
+	{&dot11lcn_nf_table_rev0,
+	 ARRAY_SIZE(dot11lcn_nf_table_rev0), 16,
+	 0, 8}
+	,
+	{&dot11lcn_gain_val_tbl_rev0,
+	 ARRAY_SIZE(dot11lcn_gain_val_tbl_rev0), 17, 0, 8}
+	,
+	{&dot11lcn_gain_tbl_rev0,
+	 ARRAY_SIZE(dot11lcn_gain_tbl_rev0), 18,
+	 0, 32}
+	,
+	{&dot11lcn_spur_tbl_rev0,
+	 ARRAY_SIZE(dot11lcn_spur_tbl_rev0), 20,
+	 0, 8}
+	,
+	{&dot11lcn_unsup_mcs_tbl_rev0,
+	 ARRAY_SIZE(dot11lcn_unsup_mcs_tbl_rev0), 23, 0, 16}
+	,
+	{&dot11lcn_iq_local_tbl_rev0,
+	 ARRAY_SIZE(dot11lcn_iq_local_tbl_rev0), 0, 0, 16}
+	,
+	{&dot11lcn_papd_compdelta_tbl_rev0,
+	 ARRAY_SIZE(dot11lcn_papd_compdelta_tbl_rev0), 24, 0, 32}
+	,
+};
+
+const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313 = {
+	&dot11lcn_sw_ctrl_tbl_4313_rev0,
+	ARRAY_SIZE(dot11lcn_sw_ctrl_tbl_4313_rev0), 15, 0, 16
+};
+
+const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_ipa = {
+	&dot11lcn_sw_ctrl_tbl_4313_ipa_rev0_combo,
+	ARRAY_SIZE(dot11lcn_sw_ctrl_tbl_4313_ipa_rev0_combo), 15, 0, 16
+};
+
+const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa = {
+	&dot11lcn_sw_ctrl_tbl_4313_epa_rev0,
+	ARRAY_SIZE(dot11lcn_sw_ctrl_tbl_4313_epa_rev0), 15, 0, 16
+};
+
+const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa = {
+	&dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo,
+	ARRAY_SIZE(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo), 15, 0, 16
+};
+
+const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250 = {
+	&dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0,
+	ARRAY_SIZE(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0), 15, 0, 16
+};
+
+const u32 dot11lcnphytbl_info_sz_rev0 =
+	ARRAY_SIZE(dot11lcnphytbl_info_rev0);
+
+const struct lcnphy_tx_gain_tbl_entry
+dot11lcnphy_2GHz_extPA_gaintable_rev0[128] = {
+	{3, 0, 31, 0, 72},
+	{3, 0, 31, 0, 70},
+	{3, 0, 31, 0, 68},
+	{3, 0, 30, 0, 67},
+	{3, 0, 29, 0, 68},
+	{3, 0, 28, 0, 68},
+	{3, 0, 27, 0, 69},
+	{3, 0, 26, 0, 70},
+	{3, 0, 25, 0, 70},
+	{3, 0, 24, 0, 71},
+	{3, 0, 23, 0, 72},
+	{3, 0, 23, 0, 70},
+	{3, 0, 22, 0, 71},
+	{3, 0, 21, 0, 72},
+	{3, 0, 21, 0, 70},
+	{3, 0, 21, 0, 68},
+	{3, 0, 21, 0, 66},
+	{3, 0, 21, 0, 64},
+	{3, 0, 21, 0, 63},
+	{3, 0, 20, 0, 64},
+	{3, 0, 19, 0, 65},
+	{3, 0, 19, 0, 64},
+	{3, 0, 18, 0, 65},
+	{3, 0, 18, 0, 64},
+	{3, 0, 17, 0, 65},
+	{3, 0, 17, 0, 64},
+	{3, 0, 16, 0, 65},
+	{3, 0, 16, 0, 64},
+	{3, 0, 16, 0, 62},
+	{3, 0, 16, 0, 60},
+	{3, 0, 16, 0, 58},
+	{3, 0, 15, 0, 61},
+	{3, 0, 15, 0, 59},
+	{3, 0, 14, 0, 61},
+	{3, 0, 14, 0, 60},
+	{3, 0, 14, 0, 58},
+	{3, 0, 13, 0, 60},
+	{3, 0, 13, 0, 59},
+	{3, 0, 12, 0, 62},
+	{3, 0, 12, 0, 60},
+	{3, 0, 12, 0, 58},
+	{3, 0, 11, 0, 62},
+	{3, 0, 11, 0, 60},
+	{3, 0, 11, 0, 59},
+	{3, 0, 11, 0, 57},
+	{3, 0, 10, 0, 61},
+	{3, 0, 10, 0, 59},
+	{3, 0, 10, 0, 57},
+	{3, 0, 9, 0, 62},
+	{3, 0, 9, 0, 60},
+	{3, 0, 9, 0, 58},
+	{3, 0, 9, 0, 57},
+	{3, 0, 8, 0, 62},
+	{3, 0, 8, 0, 60},
+	{3, 0, 8, 0, 58},
+	{3, 0, 8, 0, 57},
+	{3, 0, 8, 0, 55},
+	{3, 0, 7, 0, 61},
+	{3, 0, 7, 0, 60},
+	{3, 0, 7, 0, 58},
+	{3, 0, 7, 0, 56},
+	{3, 0, 7, 0, 55},
+	{3, 0, 6, 0, 62},
+	{3, 0, 6, 0, 60},
+	{3, 0, 6, 0, 58},
+	{3, 0, 6, 0, 57},
+	{3, 0, 6, 0, 55},
+	{3, 0, 6, 0, 54},
+	{3, 0, 6, 0, 52},
+	{3, 0, 5, 0, 61},
+	{3, 0, 5, 0, 59},
+	{3, 0, 5, 0, 57},
+	{3, 0, 5, 0, 56},
+	{3, 0, 5, 0, 54},
+	{3, 0, 5, 0, 53},
+	{3, 0, 5, 0, 51},
+	{3, 0, 4, 0, 62},
+	{3, 0, 4, 0, 60},
+	{3, 0, 4, 0, 58},
+	{3, 0, 4, 0, 57},
+	{3, 0, 4, 0, 55},
+	{3, 0, 4, 0, 54},
+	{3, 0, 4, 0, 52},
+	{3, 0, 4, 0, 51},
+	{3, 0, 4, 0, 49},
+	{3, 0, 4, 0, 48},
+	{3, 0, 4, 0, 46},
+	{3, 0, 3, 0, 60},
+	{3, 0, 3, 0, 58},
+	{3, 0, 3, 0, 57},
+	{3, 0, 3, 0, 55},
+	{3, 0, 3, 0, 54},
+	{3, 0, 3, 0, 52},
+	{3, 0, 3, 0, 51},
+	{3, 0, 3, 0, 49},
+	{3, 0, 3, 0, 48},
+	{3, 0, 3, 0, 46},
+	{3, 0, 3, 0, 45},
+	{3, 0, 3, 0, 44},
+	{3, 0, 3, 0, 43},
+	{3, 0, 3, 0, 41},
+	{3, 0, 2, 0, 61},
+	{3, 0, 2, 0, 59},
+	{3, 0, 2, 0, 57},
+	{3, 0, 2, 0, 56},
+	{3, 0, 2, 0, 54},
+	{3, 0, 2, 0, 53},
+	{3, 0, 2, 0, 51},
+	{3, 0, 2, 0, 50},
+	{3, 0, 2, 0, 48},
+	{3, 0, 2, 0, 47},
+	{3, 0, 2, 0, 46},
+	{3, 0, 2, 0, 44},
+	{3, 0, 2, 0, 43},
+	{3, 0, 2, 0, 42},
+	{3, 0, 2, 0, 41},
+	{3, 0, 2, 0, 39},
+	{3, 0, 2, 0, 38},
+	{3, 0, 2, 0, 37},
+	{3, 0, 2, 0, 36},
+	{3, 0, 2, 0, 35},
+	{3, 0, 2, 0, 34},
+	{3, 0, 2, 0, 33},
+	{3, 0, 2, 0, 32},
+	{3, 0, 1, 0, 63},
+	{3, 0, 1, 0, 61},
+	{3, 0, 1, 0, 59},
+	{3, 0, 1, 0, 57},
+};
+
+const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_gaintable_rev0[128] = {
+	{15, 0, 31, 0, 72},
+	{15, 0, 31, 0, 70},
+	{15, 0, 31, 0, 68},
+	{15, 0, 30, 0, 68},
+	{15, 0, 29, 0, 69},
+	{15, 0, 28, 0, 69},
+	{15, 0, 27, 0, 70},
+	{15, 0, 26, 0, 70},
+	{15, 0, 25, 0, 71},
+	{15, 0, 24, 0, 72},
+	{15, 0, 23, 0, 73},
+	{15, 0, 23, 0, 71},
+	{15, 0, 22, 0, 72},
+	{15, 0, 21, 0, 73},
+	{15, 0, 21, 0, 71},
+	{15, 0, 21, 0, 69},
+	{15, 0, 21, 0, 67},
+	{15, 0, 21, 0, 65},
+	{15, 0, 21, 0, 63},
+	{15, 0, 20, 0, 65},
+	{15, 0, 19, 0, 66},
+	{15, 0, 19, 0, 64},
+	{15, 0, 18, 0, 66},
+	{15, 0, 18, 0, 64},
+	{15, 0, 17, 0, 66},
+	{15, 0, 17, 0, 64},
+	{15, 0, 16, 0, 66},
+	{15, 0, 16, 0, 64},
+	{15, 0, 16, 0, 62},
+	{15, 0, 16, 0, 61},
+	{15, 0, 16, 0, 59},
+	{15, 0, 15, 0, 61},
+	{15, 0, 15, 0, 59},
+	{15, 0, 14, 0, 62},
+	{15, 0, 14, 0, 60},
+	{15, 0, 14, 0, 58},
+	{15, 0, 13, 0, 61},
+	{15, 0, 13, 0, 59},
+	{15, 0, 12, 0, 62},
+	{15, 0, 12, 0, 61},
+	{15, 0, 12, 0, 59},
+	{15, 0, 11, 0, 62},
+	{15, 0, 11, 0, 61},
+	{15, 0, 11, 0, 59},
+	{15, 0, 11, 0, 57},
+	{15, 0, 10, 0, 61},
+	{15, 0, 10, 0, 59},
+	{15, 0, 10, 0, 58},
+	{15, 0, 9, 0, 62},
+	{15, 0, 9, 0, 61},
+	{15, 0, 9, 0, 59},
+	{15, 0, 9, 0, 57},
+	{15, 0, 8, 0, 62},
+	{15, 0, 8, 0, 61},
+	{15, 0, 8, 0, 59},
+	{15, 0, 8, 0, 57},
+	{15, 0, 8, 0, 56},
+	{15, 0, 8, 0, 54},
+	{15, 0, 8, 0, 53},
+	{15, 0, 8, 0, 51},
+	{15, 0, 8, 0, 50},
+	{7, 0, 7, 0, 69},
+	{7, 0, 7, 0, 67},
+	{7, 0, 7, 0, 65},
+	{7, 0, 7, 0, 64},
+	{7, 0, 7, 0, 62},
+	{7, 0, 7, 0, 60},
+	{7, 0, 7, 0, 58},
+	{7, 0, 7, 0, 57},
+	{7, 0, 7, 0, 55},
+	{7, 0, 6, 0, 62},
+	{7, 0, 6, 0, 61},
+	{7, 0, 6, 0, 59},
+	{7, 0, 6, 0, 57},
+	{7, 0, 6, 0, 56},
+	{7, 0, 6, 0, 54},
+	{7, 0, 6, 0, 53},
+	{7, 0, 5, 0, 61},
+	{7, 0, 5, 0, 60},
+	{7, 0, 5, 0, 58},
+	{7, 0, 5, 0, 56},
+	{7, 0, 5, 0, 55},
+	{7, 0, 5, 0, 53},
+	{7, 0, 5, 0, 52},
+	{7, 0, 5, 0, 50},
+	{7, 0, 5, 0, 49},
+	{7, 0, 5, 0, 47},
+	{7, 0, 4, 0, 57},
+	{7, 0, 4, 0, 56},
+	{7, 0, 4, 0, 54},
+	{7, 0, 4, 0, 53},
+	{7, 0, 4, 0, 51},
+	{7, 0, 4, 0, 50},
+	{7, 0, 4, 0, 48},
+	{7, 0, 4, 0, 47},
+	{7, 0, 4, 0, 46},
+	{7, 0, 4, 0, 44},
+	{7, 0, 4, 0, 43},
+	{7, 0, 4, 0, 42},
+	{7, 0, 4, 0, 41},
+	{7, 0, 4, 0, 40},
+	{7, 0, 3, 0, 51},
+	{7, 0, 3, 0, 50},
+	{7, 0, 3, 0, 48},
+	{7, 0, 3, 0, 47},
+	{7, 0, 3, 0, 46},
+	{7, 0, 3, 0, 44},
+	{7, 0, 3, 0, 43},
+	{7, 0, 3, 0, 42},
+	{7, 0, 3, 0, 41},
+	{3, 0, 3, 0, 56},
+	{3, 0, 3, 0, 54},
+	{3, 0, 3, 0, 53},
+	{3, 0, 3, 0, 51},
+	{3, 0, 3, 0, 50},
+	{3, 0, 3, 0, 48},
+	{3, 0, 3, 0, 47},
+	{3, 0, 3, 0, 46},
+	{3, 0, 3, 0, 44},
+	{3, 0, 3, 0, 43},
+	{3, 0, 3, 0, 42},
+	{3, 0, 3, 0, 41},
+	{3, 0, 3, 0, 39},
+	{3, 0, 3, 0, 38},
+	{3, 0, 3, 0, 37},
+	{3, 0, 3, 0, 36},
+	{3, 0, 3, 0, 35},
+	{3, 0, 3, 0, 34},
+};
+
+const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_5GHz_gaintable_rev0[128] = {
+	{255, 255, 0xf0, 0, 152},
+	{255, 255, 0xf0, 0, 147},
+	{255, 255, 0xf0, 0, 143},
+	{255, 255, 0xf0, 0, 139},
+	{255, 255, 0xf0, 0, 135},
+	{255, 255, 0xf0, 0, 131},
+	{255, 255, 0xf0, 0, 128},
+	{255, 255, 0xf0, 0, 124},
+	{255, 255, 0xf0, 0, 121},
+	{255, 255, 0xf0, 0, 117},
+	{255, 255, 0xf0, 0, 114},
+	{255, 255, 0xf0, 0, 111},
+	{255, 255, 0xf0, 0, 107},
+	{255, 255, 0xf0, 0, 104},
+	{255, 255, 0xf0, 0, 101},
+	{255, 255, 0xf0, 0, 99},
+	{255, 255, 0xf0, 0, 96},
+	{255, 255, 0xf0, 0, 93},
+	{255, 255, 0xf0, 0, 90},
+	{255, 255, 0xf0, 0, 88},
+	{255, 255, 0xf0, 0, 85},
+	{255, 255, 0xf0, 0, 83},
+	{255, 255, 0xf0, 0, 81},
+	{255, 255, 0xf0, 0, 78},
+	{255, 255, 0xf0, 0, 76},
+	{255, 255, 0xf0, 0, 74},
+	{255, 255, 0xf0, 0, 72},
+	{255, 255, 0xf0, 0, 70},
+	{255, 255, 0xf0, 0, 68},
+	{255, 255, 0xf0, 0, 66},
+	{255, 255, 0xf0, 0, 64},
+	{255, 248, 0xf0, 0, 64},
+	{255, 241, 0xf0, 0, 64},
+	{255, 251, 0xe0, 0, 64},
+	{255, 244, 0xe0, 0, 64},
+	{255, 254, 0xd0, 0, 64},
+	{255, 246, 0xd0, 0, 64},
+	{255, 239, 0xd0, 0, 64},
+	{255, 249, 0xc0, 0, 64},
+	{255, 242, 0xc0, 0, 64},
+	{255, 255, 0xb0, 0, 64},
+	{255, 248, 0xb0, 0, 64},
+	{255, 241, 0xb0, 0, 64},
+	{255, 254, 0xa0, 0, 64},
+	{255, 246, 0xa0, 0, 64},
+	{255, 239, 0xa0, 0, 64},
+	{255, 255, 0x90, 0, 64},
+	{255, 248, 0x90, 0, 64},
+	{255, 241, 0x90, 0, 64},
+	{255, 234, 0x90, 0, 64},
+	{255, 255, 0x80, 0, 64},
+	{255, 248, 0x80, 0, 64},
+	{255, 241, 0x80, 0, 64},
+	{255, 234, 0x80, 0, 64},
+	{255, 255, 0x70, 0, 64},
+	{255, 248, 0x70, 0, 64},
+	{255, 241, 0x70, 0, 64},
+	{255, 234, 0x70, 0, 64},
+	{255, 227, 0x70, 0, 64},
+	{255, 221, 0x70, 0, 64},
+	{255, 215, 0x70, 0, 64},
+	{255, 208, 0x70, 0, 64},
+	{255, 203, 0x70, 0, 64},
+	{255, 197, 0x70, 0, 64},
+	{255, 255, 0x60, 0, 64},
+	{255, 248, 0x60, 0, 64},
+	{255, 241, 0x60, 0, 64},
+	{255, 234, 0x60, 0, 64},
+	{255, 227, 0x60, 0, 64},
+	{255, 221, 0x60, 0, 64},
+	{255, 255, 0x50, 0, 64},
+	{255, 248, 0x50, 0, 64},
+	{255, 241, 0x50, 0, 64},
+	{255, 234, 0x50, 0, 64},
+	{255, 227, 0x50, 0, 64},
+	{255, 221, 0x50, 0, 64},
+	{255, 215, 0x50, 0, 64},
+	{255, 208, 0x50, 0, 64},
+	{255, 255, 0x40, 0, 64},
+	{255, 248, 0x40, 0, 64},
+	{255, 241, 0x40, 0, 64},
+	{255, 234, 0x40, 0, 64},
+	{255, 227, 0x40, 0, 64},
+	{255, 221, 0x40, 0, 64},
+	{255, 215, 0x40, 0, 64},
+	{255, 208, 0x40, 0, 64},
+	{255, 203, 0x40, 0, 64},
+	{255, 197, 0x40, 0, 64},
+	{255, 255, 0x30, 0, 64},
+	{255, 248, 0x30, 0, 64},
+	{255, 241, 0x30, 0, 64},
+	{255, 234, 0x30, 0, 64},
+	{255, 227, 0x30, 0, 64},
+	{255, 221, 0x30, 0, 64},
+	{255, 215, 0x30, 0, 64},
+	{255, 208, 0x30, 0, 64},
+	{255, 203, 0x30, 0, 64},
+	{255, 197, 0x30, 0, 64},
+	{255, 191, 0x30, 0, 64},
+	{255, 186, 0x30, 0, 64},
+	{255, 181, 0x30, 0, 64},
+	{255, 175, 0x30, 0, 64},
+	{255, 255, 0x20, 0, 64},
+	{255, 248, 0x20, 0, 64},
+	{255, 241, 0x20, 0, 64},
+	{255, 234, 0x20, 0, 64},
+	{255, 227, 0x20, 0, 64},
+	{255, 221, 0x20, 0, 64},
+	{255, 215, 0x20, 0, 64},
+	{255, 208, 0x20, 0, 64},
+	{255, 203, 0x20, 0, 64},
+	{255, 197, 0x20, 0, 64},
+	{255, 191, 0x20, 0, 64},
+	{255, 186, 0x20, 0, 64},
+	{255, 181, 0x20, 0, 64},
+	{255, 175, 0x20, 0, 64},
+	{255, 170, 0x20, 0, 64},
+	{255, 166, 0x20, 0, 64},
+	{255, 161, 0x20, 0, 64},
+	{255, 156, 0x20, 0, 64},
+	{255, 152, 0x20, 0, 64},
+	{255, 148, 0x20, 0, 64},
+	{255, 143, 0x20, 0, 64},
+	{255, 139, 0x20, 0, 64},
+	{255, 135, 0x20, 0, 64},
+	{255, 132, 0x20, 0, 64},
+	{255, 255, 0x10, 0, 64},
+	{255, 248, 0x10, 0, 64},
+};
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phytbl_lcn.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phytbl_lcn.h
new file mode 100644
index 0000000..489422a
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phytbl_lcn.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <types.h>
+#include "phy_int.h"
+
+extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_rev0[];
+extern const u32 dot11lcnphytbl_rx_gain_info_sz_rev0;
+extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313;
+extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_ipa;
+extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa;
+extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_epa_combo;
+extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa;
+extern const struct phytbl_info dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250;
+
+extern const struct phytbl_info dot11lcnphytbl_info_rev0[];
+extern const u32 dot11lcnphytbl_info_sz_rev0;
+
+extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_2G_rev2[];
+extern const u32 dot11lcnphytbl_rx_gain_info_2G_rev2_sz;
+
+extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_5G_rev2[];
+extern const u32 dot11lcnphytbl_rx_gain_info_5G_rev2_sz;
+
+extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_2G_rev2[];
+
+extern const struct phytbl_info dot11lcnphytbl_rx_gain_info_extlna_5G_rev2[];
+
+struct lcnphy_tx_gain_tbl_entry {
+	unsigned char gm;
+	unsigned char pga;
+	unsigned char pad;
+	unsigned char dac;
+	unsigned char bb_mult;
+};
+
+extern const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_gaintable_rev0[];
+
+extern const struct
+lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_extPA_gaintable_rev0[];
+
+extern const struct lcnphy_tx_gain_tbl_entry dot11lcnphy_5GHz_gaintable_rev0[];
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phytbl_n.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phytbl_n.c
new file mode 100644
index 0000000..533bd4b
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phytbl_n.c
@@ -0,0 +1,10378 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <types.h>
+#include "phytbl_n.h"
+
+static const u32 frame_struct_rev0[] = {
+	0x08004a04,
+	0x00100000,
+	0x01000a05,
+	0x00100020,
+	0x09804506,
+	0x00100030,
+	0x09804507,
+	0x00100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a0c,
+	0x00100004,
+	0x01000a0d,
+	0x00100024,
+	0x0980450e,
+	0x00100034,
+	0x0980450f,
+	0x00100034,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a04,
+	0x00100000,
+	0x11008a05,
+	0x00100020,
+	0x1980c506,
+	0x00100030,
+	0x21810506,
+	0x00100030,
+	0x21810506,
+	0x00100030,
+	0x01800504,
+	0x00100030,
+	0x11808505,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000a04,
+	0x00100000,
+	0x11008a05,
+	0x00100020,
+	0x21810506,
+	0x00100030,
+	0x21810506,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a0c,
+	0x00100008,
+	0x11008a0d,
+	0x00100028,
+	0x1980c50e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x0180050c,
+	0x00100038,
+	0x1180850d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000a0c,
+	0x00100008,
+	0x11008a0d,
+	0x00100028,
+	0x2181050e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a04,
+	0x00100000,
+	0x01000a05,
+	0x00100020,
+	0x1980c506,
+	0x00100030,
+	0x1980c506,
+	0x00100030,
+	0x11808504,
+	0x00100030,
+	0x3981ca05,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x10008a04,
+	0x00100000,
+	0x3981ca05,
+	0x00100030,
+	0x1980c506,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a0c,
+	0x00100008,
+	0x01000a0d,
+	0x00100028,
+	0x1980c50e,
+	0x00100038,
+	0x1980c50e,
+	0x00100038,
+	0x1180850c,
+	0x00100038,
+	0x3981ca0d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x10008a0c,
+	0x00100008,
+	0x3981ca0d,
+	0x00100038,
+	0x1980c50e,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x00100000,
+	0x02001405,
+	0x00100040,
+	0x0b004a06,
+	0x01900060,
+	0x13008a06,
+	0x01900060,
+	0x13008a06,
+	0x01900060,
+	0x43020a04,
+	0x00100060,
+	0x1b00ca05,
+	0x00100060,
+	0x23010a07,
+	0x01500060,
+	0x40021404,
+	0x00100000,
+	0x1a00d405,
+	0x00100040,
+	0x13008a06,
+	0x01900060,
+	0x13008a06,
+	0x01900060,
+	0x23010a07,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x0200140d,
+	0x00100050,
+	0x0b004a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x43020a0c,
+	0x00100070,
+	0x1b00ca0d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x13008a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x50029404,
+	0x00100000,
+	0x32019405,
+	0x00100040,
+	0x0b004a06,
+	0x01900060,
+	0x0b004a06,
+	0x01900060,
+	0x5b02ca04,
+	0x00100060,
+	0x3b01d405,
+	0x00100060,
+	0x23010a07,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x5802d404,
+	0x00100000,
+	0x3b01d405,
+	0x00100060,
+	0x0b004a06,
+	0x01900060,
+	0x23010a07,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x5002940c,
+	0x00100010,
+	0x3201940d,
+	0x00100050,
+	0x0b004a0e,
+	0x01900070,
+	0x0b004a0e,
+	0x01900070,
+	0x5b02ca0c,
+	0x00100070,
+	0x3b01d40d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x5802d40c,
+	0x00100010,
+	0x3b01d40d,
+	0x00100070,
+	0x0b004a0e,
+	0x01900070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x000f4800,
+	0x62031405,
+	0x00100040,
+	0x53028a06,
+	0x01900060,
+	0x53028a07,
+	0x01900060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x000f4808,
+	0x6203140d,
+	0x00100048,
+	0x53028a0e,
+	0x01900068,
+	0x53028a0f,
+	0x01900068,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a0c,
+	0x00100004,
+	0x11008a0d,
+	0x00100024,
+	0x1980c50e,
+	0x00100034,
+	0x2181050e,
+	0x00100034,
+	0x2181050e,
+	0x00100034,
+	0x0180050c,
+	0x00100038,
+	0x1180850d,
+	0x00100038,
+	0x1181850d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a0c,
+	0x00100008,
+	0x11008a0d,
+	0x00100028,
+	0x2181050e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x1181850d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a04,
+	0x00100000,
+	0x01000a05,
+	0x00100020,
+	0x0180c506,
+	0x00100030,
+	0x0180c506,
+	0x00100030,
+	0x2180c50c,
+	0x00100030,
+	0x49820a0d,
+	0x0016a130,
+	0x41824a0d,
+	0x0016a130,
+	0x2981450f,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x2000ca0c,
+	0x00100000,
+	0x49820a0d,
+	0x0016a130,
+	0x1980c50e,
+	0x00100030,
+	0x41824a0d,
+	0x0016a130,
+	0x2981450f,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100008,
+	0x0200140d,
+	0x00100048,
+	0x0b004a0e,
+	0x01900068,
+	0x13008a0e,
+	0x01900068,
+	0x13008a0e,
+	0x01900068,
+	0x43020a0c,
+	0x00100070,
+	0x1b00ca0d,
+	0x00100070,
+	0x1b014a0d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x13008a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x1b014a0d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x50029404,
+	0x00100000,
+	0x32019405,
+	0x00100040,
+	0x03004a06,
+	0x01900060,
+	0x03004a06,
+	0x01900060,
+	0x6b030a0c,
+	0x00100060,
+	0x4b02140d,
+	0x0016a160,
+	0x4302540d,
+	0x0016a160,
+	0x23010a0f,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x6b03140c,
+	0x00100060,
+	0x4b02140d,
+	0x0016a160,
+	0x0b004a0e,
+	0x01900060,
+	0x4302540d,
+	0x0016a160,
+	0x23010a0f,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x00100000,
+	0x1a00d405,
+	0x00100040,
+	0x53028a06,
+	0x01900060,
+	0x5b02ca06,
+	0x01900060,
+	0x5b02ca06,
+	0x01900060,
+	0x43020a04,
+	0x00100060,
+	0x1b00ca05,
+	0x00100060,
+	0x53028a07,
+	0x0190c060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x53028a0e,
+	0x01900070,
+	0x5b02ca0e,
+	0x01900070,
+	0x5b02ca0e,
+	0x01900070,
+	0x43020a0c,
+	0x00100070,
+	0x1b00ca0d,
+	0x00100070,
+	0x53028a0f,
+	0x0190c070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x00100000,
+	0x1a00d405,
+	0x00100040,
+	0x5b02ca06,
+	0x01900060,
+	0x5b02ca06,
+	0x01900060,
+	0x53028a07,
+	0x0190c060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x5b02ca0e,
+	0x01900070,
+	0x5b02ca0e,
+	0x01900070,
+	0x53028a0f,
+	0x0190c070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	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 u8 frame_lut_rev0[] = {
+	0x02,
+	0x04,
+	0x14,
+	0x14,
+	0x03,
+	0x05,
+	0x16,
+	0x16,
+	0x0a,
+	0x0c,
+	0x1c,
+	0x1c,
+	0x0b,
+	0x0d,
+	0x1e,
+	0x1e,
+	0x06,
+	0x08,
+	0x18,
+	0x18,
+	0x07,
+	0x09,
+	0x1a,
+	0x1a,
+	0x0e,
+	0x10,
+	0x20,
+	0x28,
+	0x0f,
+	0x11,
+	0x22,
+	0x2a,
+};
+
+static const u32 tmap_tbl_rev0[] = {
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00000111,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x000aa888,
+	0x88880000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa2222220,
+	0x22222222,
+	0x22c22222,
+	0x00000222,
+	0x22000000,
+	0x2222a222,
+	0x22222222,
+	0x222222a2,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00011111,
+	0x11110000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0xa8aa88a0,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x00088aaa,
+	0xaaaa0000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xaaa8aaa0,
+	0x8aaa8aaa,
+	0xaa8a8a8a,
+	0x000aaa88,
+	0x8aaa0000,
+	0xaaa8a888,
+	0x8aa88a8a,
+	0x8a88a888,
+	0x08080a00,
+	0x0a08080a,
+	0x080a0a08,
+	0x00080808,
+	0x080a0000,
+	0x080a0808,
+	0x080a0808,
+	0x0a0a0a08,
+	0xa0a0a0a0,
+	0x80a0a080,
+	0x8080a0a0,
+	0x00008080,
+	0x80a00000,
+	0x80a080a0,
+	0xa080a0a0,
+	0x8080a0a0,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x99999000,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb90,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00aaa888,
+	0x22000000,
+	0x2222b222,
+	0x22222222,
+	0x222222b2,
+	0xb2222220,
+	0x22222222,
+	0x22d22222,
+	0x00000222,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x33000000,
+	0x3333b333,
+	0x33333333,
+	0x333333b3,
+	0xb3333330,
+	0x33333333,
+	0x33d33333,
+	0x00000333,
+	0x22000000,
+	0x2222a222,
+	0x22222222,
+	0x222222a2,
+	0xa2222220,
+	0x22222222,
+	0x22c22222,
+	0x00000222,
+	0x99b99b00,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb99,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x08aaa888,
+	0x22222200,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0x22222222,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x11111111,
+	0xf1111111,
+	0x11111111,
+	0x11f11111,
+	0x01111111,
+	0xbb9bb900,
+	0xb9b9bb99,
+	0xb99bbbbb,
+	0xbbbb9b9b,
+	0xb9bb99bb,
+	0xb99999b9,
+	0xb9b9b99b,
+	0x00000bbb,
+	0xaa000000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xa8aa88aa,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x0a888aaa,
+	0xaa000000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xa8aa88a0,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x00000aaa,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0xbbbbbb00,
+	0x999bbbbb,
+	0x9bb99b9b,
+	0xb9b9b9bb,
+	0xb9b99bbb,
+	0xb9b9b9bb,
+	0xb9bb9b99,
+	0x00000999,
+	0x8a000000,
+	0xaa88a888,
+	0xa88888aa,
+	0xa88a8a88,
+	0xa88aa88a,
+	0x88a8aaaa,
+	0xa8aa8aaa,
+	0x0888a88a,
+	0x0b0b0b00,
+	0x090b0b0b,
+	0x0b090b0b,
+	0x0909090b,
+	0x09090b0b,
+	0x09090b0b,
+	0x09090b09,
+	0x00000909,
+	0x0a000000,
+	0x0a080808,
+	0x080a080a,
+	0x080a0a08,
+	0x080a080a,
+	0x0808080a,
+	0x0a0a0a08,
+	0x0808080a,
+	0xb0b0b000,
+	0x9090b0b0,
+	0x90b09090,
+	0xb0b0b090,
+	0xb0b090b0,
+	0x90b0b0b0,
+	0xb0b09090,
+	0x00000090,
+	0x80000000,
+	0xa080a080,
+	0xa08080a0,
+	0xa0808080,
+	0xa080a080,
+	0x80a0a0a0,
+	0xa0a080a0,
+	0x00a0a0a0,
+	0x22000000,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0xf2222220,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00000111,
+	0x33000000,
+	0x3333f333,
+	0x33333333,
+	0x333333f3,
+	0xf3333330,
+	0x33333333,
+	0x33f33333,
+	0x00000333,
+	0x22000000,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0xf2222220,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x99000000,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb90,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88888000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00aaa888,
+	0x88a88a00,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x08aaa888,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	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 tdtrn_tbl_rev0[] = {
+	0x061c061c,
+	0x0050ee68,
+	0xf592fe36,
+	0xfe5212f6,
+	0x00000c38,
+	0xfe5212f6,
+	0xf592fe36,
+	0x0050ee68,
+	0x061c061c,
+	0xee680050,
+	0xfe36f592,
+	0x12f6fe52,
+	0x0c380000,
+	0x12f6fe52,
+	0xfe36f592,
+	0xee680050,
+	0x061c061c,
+	0x0050ee68,
+	0xf592fe36,
+	0xfe5212f6,
+	0x00000c38,
+	0xfe5212f6,
+	0xf592fe36,
+	0x0050ee68,
+	0x061c061c,
+	0xee680050,
+	0xfe36f592,
+	0x12f6fe52,
+	0x0c380000,
+	0x12f6fe52,
+	0xfe36f592,
+	0xee680050,
+	0x05e305e3,
+	0x004def0c,
+	0xf5f3fe47,
+	0xfe611246,
+	0x00000bc7,
+	0xfe611246,
+	0xf5f3fe47,
+	0x004def0c,
+	0x05e305e3,
+	0xef0c004d,
+	0xfe47f5f3,
+	0x1246fe61,
+	0x0bc70000,
+	0x1246fe61,
+	0xfe47f5f3,
+	0xef0c004d,
+	0x05e305e3,
+	0x004def0c,
+	0xf5f3fe47,
+	0xfe611246,
+	0x00000bc7,
+	0xfe611246,
+	0xf5f3fe47,
+	0x004def0c,
+	0x05e305e3,
+	0xef0c004d,
+	0xfe47f5f3,
+	0x1246fe61,
+	0x0bc70000,
+	0x1246fe61,
+	0xfe47f5f3,
+	0xef0c004d,
+	0xfa58fa58,
+	0xf895043b,
+	0xff4c09c0,
+	0xfbc6ffa8,
+	0xfb84f384,
+	0x0798f6f9,
+	0x05760122,
+	0x058409f6,
+	0x0b500000,
+	0x05b7f542,
+	0x08860432,
+	0x06ddfee7,
+	0xfb84f384,
+	0xf9d90664,
+	0xf7e8025c,
+	0x00fff7bd,
+	0x05a805a8,
+	0xf7bd00ff,
+	0x025cf7e8,
+	0x0664f9d9,
+	0xf384fb84,
+	0xfee706dd,
+	0x04320886,
+	0xf54205b7,
+	0x00000b50,
+	0x09f60584,
+	0x01220576,
+	0xf6f90798,
+	0xf384fb84,
+	0xffa8fbc6,
+	0x09c0ff4c,
+	0x043bf895,
+	0x02d402d4,
+	0x07de0270,
+	0xfc96079c,
+	0xf90afe94,
+	0xfe00ff2c,
+	0x02d4065d,
+	0x092a0096,
+	0x0014fbb8,
+	0xfd2cfd2c,
+	0x076afb3c,
+	0x0096f752,
+	0xf991fd87,
+	0xfb2c0200,
+	0xfeb8f960,
+	0x08e0fc96,
+	0x049802a8,
+	0xfd2cfd2c,
+	0x02a80498,
+	0xfc9608e0,
+	0xf960feb8,
+	0x0200fb2c,
+	0xfd87f991,
+	0xf7520096,
+	0xfb3c076a,
+	0xfd2cfd2c,
+	0xfbb80014,
+	0x0096092a,
+	0x065d02d4,
+	0xff2cfe00,
+	0xfe94f90a,
+	0x079cfc96,
+	0x027007de,
+	0x02d402d4,
+	0x027007de,
+	0x079cfc96,
+	0xfe94f90a,
+	0xff2cfe00,
+	0x065d02d4,
+	0x0096092a,
+	0xfbb80014,
+	0xfd2cfd2c,
+	0xfb3c076a,
+	0xf7520096,
+	0xfd87f991,
+	0x0200fb2c,
+	0xf960feb8,
+	0xfc9608e0,
+	0x02a80498,
+	0xfd2cfd2c,
+	0x049802a8,
+	0x08e0fc96,
+	0xfeb8f960,
+	0xfb2c0200,
+	0xf991fd87,
+	0x0096f752,
+	0x076afb3c,
+	0xfd2cfd2c,
+	0x0014fbb8,
+	0x092a0096,
+	0x02d4065d,
+	0xfe00ff2c,
+	0xf90afe94,
+	0xfc96079c,
+	0x07de0270,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x062a0000,
+	0xfefa0759,
+	0x08b80908,
+	0xf396fc2d,
+	0xf9d6045c,
+	0xfc4ef608,
+	0xf748f596,
+	0x07b207bf,
+	0x062a062a,
+	0xf84ef841,
+	0xf748f596,
+	0x03b209f8,
+	0xf9d6045c,
+	0x0c6a03d3,
+	0x08b80908,
+	0x0106f8a7,
+	0x062a0000,
+	0xfefaf8a7,
+	0x08b8f6f8,
+	0xf39603d3,
+	0xf9d6fba4,
+	0xfc4e09f8,
+	0xf7480a6a,
+	0x07b2f841,
+	0x062af9d6,
+	0xf84e07bf,
+	0xf7480a6a,
+	0x03b2f608,
+	0xf9d6fba4,
+	0x0c6afc2d,
+	0x08b8f6f8,
+	0x01060759,
+	0x062a0000,
+	0xfefa0759,
+	0x08b80908,
+	0xf396fc2d,
+	0xf9d6045c,
+	0xfc4ef608,
+	0xf748f596,
+	0x07b207bf,
+	0x062a062a,
+	0xf84ef841,
+	0xf748f596,
+	0x03b209f8,
+	0xf9d6045c,
+	0x0c6a03d3,
+	0x08b80908,
+	0x0106f8a7,
+	0x062a0000,
+	0xfefaf8a7,
+	0x08b8f6f8,
+	0xf39603d3,
+	0xf9d6fba4,
+	0xfc4e09f8,
+	0xf7480a6a,
+	0x07b2f841,
+	0x062af9d6,
+	0xf84e07bf,
+	0xf7480a6a,
+	0x03b2f608,
+	0xf9d6fba4,
+	0x0c6afc2d,
+	0x08b8f6f8,
+	0x01060759,
+	0x061c061c,
+	0xff30009d,
+	0xffb21141,
+	0xfd87fb54,
+	0xf65dfe59,
+	0x02eef99e,
+	0x0166f03c,
+	0xfff809b6,
+	0x000008a4,
+	0x000af42b,
+	0x00eff577,
+	0xfa840bf2,
+	0xfc02ff51,
+	0x08260f67,
+	0xfff0036f,
+	0x0842f9c3,
+	0x00000000,
+	0x063df7be,
+	0xfc910010,
+	0xf099f7da,
+	0x00af03fe,
+	0xf40e057c,
+	0x0a89ff11,
+	0x0bd5fff6,
+	0xf75c0000,
+	0xf64a0008,
+	0x0fc4fe9a,
+	0x0662fd12,
+	0x01a709a3,
+	0x04ac0279,
+	0xeebf004e,
+	0xff6300d0,
+	0xf9e4f9e4,
+	0x00d0ff63,
+	0x004eeebf,
+	0x027904ac,
+	0x09a301a7,
+	0xfd120662,
+	0xfe9a0fc4,
+	0x0008f64a,
+	0x0000f75c,
+	0xfff60bd5,
+	0xff110a89,
+	0x057cf40e,
+	0x03fe00af,
+	0xf7daf099,
+	0x0010fc91,
+	0xf7be063d,
+	0x00000000,
+	0xf9c30842,
+	0x036ffff0,
+	0x0f670826,
+	0xff51fc02,
+	0x0bf2fa84,
+	0xf57700ef,
+	0xf42b000a,
+	0x08a40000,
+	0x09b6fff8,
+	0xf03c0166,
+	0xf99e02ee,
+	0xfe59f65d,
+	0xfb54fd87,
+	0x1141ffb2,
+	0x009dff30,
+	0x05e30000,
+	0xff060705,
+	0x085408a0,
+	0xf425fc59,
+	0xfa1d042a,
+	0xfc78f67a,
+	0xf7acf60e,
+	0x075a0766,
+	0x05e305e3,
+	0xf8a6f89a,
+	0xf7acf60e,
+	0x03880986,
+	0xfa1d042a,
+	0x0bdb03a7,
+	0x085408a0,
+	0x00faf8fb,
+	0x05e30000,
+	0xff06f8fb,
+	0x0854f760,
+	0xf42503a7,
+	0xfa1dfbd6,
+	0xfc780986,
+	0xf7ac09f2,
+	0x075af89a,
+	0x05e3fa1d,
+	0xf8a60766,
+	0xf7ac09f2,
+	0x0388f67a,
+	0xfa1dfbd6,
+	0x0bdbfc59,
+	0x0854f760,
+	0x00fa0705,
+	0x05e30000,
+	0xff060705,
+	0x085408a0,
+	0xf425fc59,
+	0xfa1d042a,
+	0xfc78f67a,
+	0xf7acf60e,
+	0x075a0766,
+	0x05e305e3,
+	0xf8a6f89a,
+	0xf7acf60e,
+	0x03880986,
+	0xfa1d042a,
+	0x0bdb03a7,
+	0x085408a0,
+	0x00faf8fb,
+	0x05e30000,
+	0xff06f8fb,
+	0x0854f760,
+	0xf42503a7,
+	0xfa1dfbd6,
+	0xfc780986,
+	0xf7ac09f2,
+	0x075af89a,
+	0x05e3fa1d,
+	0xf8a60766,
+	0xf7ac09f2,
+	0x0388f67a,
+	0xfa1dfbd6,
+	0x0bdbfc59,
+	0x0854f760,
+	0x00fa0705,
+	0xfa58fa58,
+	0xf8f0fe00,
+	0x0448073d,
+	0xfdc9fe46,
+	0xf9910258,
+	0x089d0407,
+	0xfd5cf71a,
+	0x02affde0,
+	0x083e0496,
+	0xff5a0740,
+	0xff7afd97,
+	0x00fe01f1,
+	0x0009082e,
+	0xfa94ff75,
+	0xfecdf8ea,
+	0xffb0f693,
+	0xfd2cfa58,
+	0x0433ff16,
+	0xfba405dd,
+	0xfa610341,
+	0x06a606cb,
+	0x0039fd2d,
+	0x0677fa97,
+	0x01fa05e0,
+	0xf896003e,
+	0x075a068b,
+	0x012cfc3e,
+	0xfa23f98d,
+	0xfc7cfd43,
+	0xff90fc0d,
+	0x01c10982,
+	0x00c601d6,
+	0xfd2cfd2c,
+	0x01d600c6,
+	0x098201c1,
+	0xfc0dff90,
+	0xfd43fc7c,
+	0xf98dfa23,
+	0xfc3e012c,
+	0x068b075a,
+	0x003ef896,
+	0x05e001fa,
+	0xfa970677,
+	0xfd2d0039,
+	0x06cb06a6,
+	0x0341fa61,
+	0x05ddfba4,
+	0xff160433,
+	0xfa58fd2c,
+	0xf693ffb0,
+	0xf8eafecd,
+	0xff75fa94,
+	0x082e0009,
+	0x01f100fe,
+	0xfd97ff7a,
+	0x0740ff5a,
+	0x0496083e,
+	0xfde002af,
+	0xf71afd5c,
+	0x0407089d,
+	0x0258f991,
+	0xfe46fdc9,
+	0x073d0448,
+	0xfe00f8f0,
+	0xfd2cfd2c,
+	0xfce00500,
+	0xfc09fddc,
+	0xfe680157,
+	0x04c70571,
+	0xfc3aff21,
+	0xfcd70228,
+	0x056d0277,
+	0x0200fe00,
+	0x0022f927,
+	0xfe3c032b,
+	0xfc44ff3c,
+	0x03e9fbdb,
+	0x04570313,
+	0x04c9ff5c,
+	0x000d03b8,
+	0xfa580000,
+	0xfbe900d2,
+	0xf9d0fe0b,
+	0x0125fdf9,
+	0x042501bf,
+	0x0328fa2b,
+	0xffa902f0,
+	0xfa250157,
+	0x0200fe00,
+	0x03740438,
+	0xff0405fd,
+	0x030cfe52,
+	0x0037fb39,
+	0xff6904c5,
+	0x04f8fd23,
+	0xfd31fc1b,
+	0xfd2cfd2c,
+	0xfc1bfd31,
+	0xfd2304f8,
+	0x04c5ff69,
+	0xfb390037,
+	0xfe52030c,
+	0x05fdff04,
+	0x04380374,
+	0xfe000200,
+	0x0157fa25,
+	0x02f0ffa9,
+	0xfa2b0328,
+	0x01bf0425,
+	0xfdf90125,
+	0xfe0bf9d0,
+	0x00d2fbe9,
+	0x0000fa58,
+	0x03b8000d,
+	0xff5c04c9,
+	0x03130457,
+	0xfbdb03e9,
+	0xff3cfc44,
+	0x032bfe3c,
+	0xf9270022,
+	0xfe000200,
+	0x0277056d,
+	0x0228fcd7,
+	0xff21fc3a,
+	0x057104c7,
+	0x0157fe68,
+	0xfddcfc09,
+	0x0500fce0,
+	0xfd2cfd2c,
+	0x0500fce0,
+	0xfddcfc09,
+	0x0157fe68,
+	0x057104c7,
+	0xff21fc3a,
+	0x0228fcd7,
+	0x0277056d,
+	0xfe000200,
+	0xf9270022,
+	0x032bfe3c,
+	0xff3cfc44,
+	0xfbdb03e9,
+	0x03130457,
+	0xff5c04c9,
+	0x03b8000d,
+	0x0000fa58,
+	0x00d2fbe9,
+	0xfe0bf9d0,
+	0xfdf90125,
+	0x01bf0425,
+	0xfa2b0328,
+	0x02f0ffa9,
+	0x0157fa25,
+	0xfe000200,
+	0x04380374,
+	0x05fdff04,
+	0xfe52030c,
+	0xfb390037,
+	0x04c5ff69,
+	0xfd2304f8,
+	0xfc1bfd31,
+	0xfd2cfd2c,
+	0xfd31fc1b,
+	0x04f8fd23,
+	0xff6904c5,
+	0x0037fb39,
+	0x030cfe52,
+	0xff0405fd,
+	0x03740438,
+	0x0200fe00,
+	0xfa250157,
+	0xffa902f0,
+	0x0328fa2b,
+	0x042501bf,
+	0x0125fdf9,
+	0xf9d0fe0b,
+	0xfbe900d2,
+	0xfa580000,
+	0x000d03b8,
+	0x04c9ff5c,
+	0x04570313,
+	0x03e9fbdb,
+	0xfc44ff3c,
+	0xfe3c032b,
+	0x0022f927,
+	0x0200fe00,
+	0x056d0277,
+	0xfcd70228,
+	0xfc3aff21,
+	0x04c70571,
+	0xfe680157,
+	0xfc09fddc,
+	0xfce00500,
+	0x05a80000,
+	0xff1006be,
+	0x0800084a,
+	0xf49cfc7e,
+	0xfa580400,
+	0xfc9cf6da,
+	0xf800f672,
+	0x0710071c,
+	0x05a805a8,
+	0xf8f0f8e4,
+	0xf800f672,
+	0x03640926,
+	0xfa580400,
+	0x0b640382,
+	0x0800084a,
+	0x00f0f942,
+	0x05a80000,
+	0xff10f942,
+	0x0800f7b6,
+	0xf49c0382,
+	0xfa58fc00,
+	0xfc9c0926,
+	0xf800098e,
+	0x0710f8e4,
+	0x05a8fa58,
+	0xf8f0071c,
+	0xf800098e,
+	0x0364f6da,
+	0xfa58fc00,
+	0x0b64fc7e,
+	0x0800f7b6,
+	0x00f006be,
+	0x05a80000,
+	0xff1006be,
+	0x0800084a,
+	0xf49cfc7e,
+	0xfa580400,
+	0xfc9cf6da,
+	0xf800f672,
+	0x0710071c,
+	0x05a805a8,
+	0xf8f0f8e4,
+	0xf800f672,
+	0x03640926,
+	0xfa580400,
+	0x0b640382,
+	0x0800084a,
+	0x00f0f942,
+	0x05a80000,
+	0xff10f942,
+	0x0800f7b6,
+	0xf49c0382,
+	0xfa58fc00,
+	0xfc9c0926,
+	0xf800098e,
+	0x0710f8e4,
+	0x05a8fa58,
+	0xf8f0071c,
+	0xf800098e,
+	0x0364f6da,
+	0xfa58fc00,
+	0x0b64fc7e,
+	0x0800f7b6,
+	0x00f006be,
+};
+
+static const u32 intlv_tbl_rev0[] = {
+	0x00802070,
+	0x0671188d,
+	0x0a60192c,
+	0x0a300e46,
+	0x00c1188d,
+	0x080024d2,
+	0x00000070,
+};
+
+static const u16 pilot_tbl_rev0[] = {
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0xff0a,
+	0xff82,
+	0xffa0,
+	0xff28,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xff82,
+	0xffa0,
+	0xff28,
+	0xff0a,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xf83f,
+	0xfa1f,
+	0xfa97,
+	0xfab5,
+	0xf2bd,
+	0xf0bf,
+	0xffff,
+	0xffff,
+	0xf017,
+	0xf815,
+	0xf215,
+	0xf095,
+	0xf035,
+	0xf01d,
+	0xffff,
+	0xffff,
+	0xff08,
+	0xff02,
+	0xff80,
+	0xff20,
+	0xff08,
+	0xff02,
+	0xff80,
+	0xff20,
+	0xf01f,
+	0xf817,
+	0xfa15,
+	0xf295,
+	0xf0b5,
+	0xf03d,
+	0xffff,
+	0xffff,
+	0xf82a,
+	0xfa0a,
+	0xfa82,
+	0xfaa0,
+	0xf2a8,
+	0xf0aa,
+	0xffff,
+	0xffff,
+	0xf002,
+	0xf800,
+	0xf200,
+	0xf080,
+	0xf020,
+	0xf008,
+	0xffff,
+	0xffff,
+	0xf00a,
+	0xf802,
+	0xfa00,
+	0xf280,
+	0xf0a0,
+	0xf028,
+	0xffff,
+	0xffff,
+};
+
+static const u32 pltlut_tbl_rev0[] = {
+	0x76540123,
+	0x62407351,
+	0x76543201,
+	0x76540213,
+	0x76540123,
+	0x76430521,
+};
+
+static const u32 tdi_tbl20_ant0_rev0[] = {
+	0x00091226,
+	0x000a1429,
+	0x000b56ad,
+	0x000c58b0,
+	0x000d5ab3,
+	0x000e9cb6,
+	0x000f9eba,
+	0x0000c13d,
+	0x00020301,
+	0x00030504,
+	0x00040708,
+	0x0005090b,
+	0x00064b8e,
+	0x00095291,
+	0x000a5494,
+	0x000b9718,
+	0x000c9927,
+	0x000d9b2a,
+	0x000edd2e,
+	0x000fdf31,
+	0x000101b4,
+	0x000243b7,
+	0x000345bb,
+	0x000447be,
+	0x00058982,
+	0x00068c05,
+	0x00099309,
+	0x000a950c,
+	0x000bd78f,
+	0x000cd992,
+	0x000ddb96,
+	0x000f1d99,
+	0x00005fa8,
+	0x0001422c,
+	0x0002842f,
+	0x00038632,
+	0x00048835,
+	0x0005ca38,
+	0x0006ccbc,
+	0x0009d3bf,
+	0x000b1603,
+	0x000c1806,
+	0x000d1a0a,
+	0x000e1c0d,
+	0x000f5e10,
+	0x00008093,
+	0x00018297,
+	0x0002c49a,
+	0x0003c680,
+	0x0004c880,
+	0x00060b00,
+	0x00070d00,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+static const u32 tdi_tbl20_ant1_rev0[] = {
+	0x00014b26,
+	0x00028d29,
+	0x000393ad,
+	0x00049630,
+	0x0005d833,
+	0x0006da36,
+	0x00099c3a,
+	0x000a9e3d,
+	0x000bc081,
+	0x000cc284,
+	0x000dc488,
+	0x000f068b,
+	0x0000488e,
+	0x00018b91,
+	0x0002d214,
+	0x0003d418,
+	0x0004d6a7,
+	0x000618aa,
+	0x00071aae,
+	0x0009dcb1,
+	0x000b1eb4,
+	0x000c0137,
+	0x000d033b,
+	0x000e053e,
+	0x000f4702,
+	0x00008905,
+	0x00020c09,
+	0x0003128c,
+	0x0004148f,
+	0x00051712,
+	0x00065916,
+	0x00091b19,
+	0x000a1d28,
+	0x000b5f2c,
+	0x000c41af,
+	0x000d43b2,
+	0x000e85b5,
+	0x000f87b8,
+	0x0000c9bc,
+	0x00024cbf,
+	0x00035303,
+	0x00045506,
+	0x0005978a,
+	0x0006998d,
+	0x00095b90,
+	0x000a5d93,
+	0x000b9f97,
+	0x000c821a,
+	0x000d8400,
+	0x000ec600,
+	0x000fc800,
+	0x00010a00,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+static const u32 tdi_tbl40_ant0_rev0[] = {
+	0x0011a346,
+	0x00136ccf,
+	0x0014f5d9,
+	0x001641e2,
+	0x0017cb6b,
+	0x00195475,
+	0x001b2383,
+	0x001cad0c,
+	0x001e7616,
+	0x0000821f,
+	0x00020ba8,
+	0x0003d4b2,
+	0x00056447,
+	0x00072dd0,
+	0x0008b6da,
+	0x000a02e3,
+	0x000b8c6c,
+	0x000d15f6,
+	0x0011e484,
+	0x0013ae0d,
+	0x00153717,
+	0x00168320,
+	0x00180ca9,
+	0x00199633,
+	0x001b6548,
+	0x001ceed1,
+	0x001eb7db,
+	0x0000c3e4,
+	0x00024d6d,
+	0x000416f7,
+	0x0005a585,
+	0x00076f0f,
+	0x0008f818,
+	0x000a4421,
+	0x000bcdab,
+	0x000d9734,
+	0x00122649,
+	0x0013efd2,
+	0x001578dc,
+	0x0016c4e5,
+	0x00184e6e,
+	0x001a17f8,
+	0x001ba686,
+	0x001d3010,
+	0x001ef999,
+	0x00010522,
+	0x00028eac,
+	0x00045835,
+	0x0005e74a,
+	0x0007b0d3,
+	0x00093a5d,
+	0x000a85e6,
+	0x000c0f6f,
+	0x000dd8f9,
+	0x00126787,
+	0x00143111,
+	0x0015ba9a,
+	0x00170623,
+	0x00188fad,
+	0x001a5936,
+	0x001be84b,
+	0x001db1d4,
+	0x001f3b5e,
+	0x000146e7,
+	0x00031070,
+	0x000499fa,
+	0x00062888,
+	0x0007f212,
+	0x00097b9b,
+	0x000ac7a4,
+	0x000c50ae,
+	0x000e1a37,
+	0x0012a94c,
+	0x001472d5,
+	0x0015fc5f,
+	0x00174868,
+	0x0018d171,
+	0x001a9afb,
+	0x001c2989,
+	0x001df313,
+	0x001f7c9c,
+	0x000188a5,
+	0x000351af,
+	0x0004db38,
+	0x0006aa4d,
+	0x000833d7,
+	0x0009bd60,
+	0x000b0969,
+	0x000c9273,
+	0x000e5bfc,
+	0x00132a8a,
+	0x0014b414,
+	0x00163d9d,
+	0x001789a6,
+	0x001912b0,
+	0x001adc39,
+	0x001c6bce,
+	0x001e34d8,
+	0x001fbe61,
+	0x0001ca6a,
+	0x00039374,
+	0x00051cfd,
+	0x0006ec0b,
+	0x00087515,
+	0x0009fe9e,
+	0x000b4aa7,
+	0x000cd3b1,
+	0x000e9d3a,
+	0x00000000,
+	0x00000000,
+};
+
+static const u32 tdi_tbl40_ant1_rev0[] = {
+	0x001edb36,
+	0x000129ca,
+	0x0002b353,
+	0x00047cdd,
+	0x0005c8e6,
+	0x000791ef,
+	0x00091bf9,
+	0x000aaa07,
+	0x000c3391,
+	0x000dfd1a,
+	0x00120923,
+	0x0013d22d,
+	0x00155c37,
+	0x0016eacb,
+	0x00187454,
+	0x001a3dde,
+	0x001b89e7,
+	0x001d12f0,
+	0x001f1cfa,
+	0x00016b88,
+	0x00033492,
+	0x0004be1b,
+	0x00060a24,
+	0x0007d32e,
+	0x00095d38,
+	0x000aec4c,
+	0x000c7555,
+	0x000e3edf,
+	0x00124ae8,
+	0x001413f1,
+	0x0015a37b,
+	0x00172c89,
+	0x0018b593,
+	0x001a419c,
+	0x001bcb25,
+	0x001d942f,
+	0x001f63b9,
+	0x0001ad4d,
+	0x00037657,
+	0x0004c260,
+	0x00068be9,
+	0x000814f3,
+	0x0009a47c,
+	0x000b2d8a,
+	0x000cb694,
+	0x000e429d,
+	0x00128c26,
+	0x001455b0,
+	0x0015e4ba,
+	0x00176e4e,
+	0x0018f758,
+	0x001a8361,
+	0x001c0cea,
+	0x001dd674,
+	0x001fa57d,
+	0x0001ee8b,
+	0x0003b795,
+	0x0005039e,
+	0x0006cd27,
+	0x000856b1,
+	0x0009e5c6,
+	0x000b6f4f,
+	0x000cf859,
+	0x000e8462,
+	0x00130deb,
+	0x00149775,
+	0x00162603,
+	0x0017af8c,
+	0x00193896,
+	0x001ac49f,
+	0x001c4e28,
+	0x001e17b2,
+	0x0000a6c7,
+	0x00023050,
+	0x0003f9da,
+	0x00054563,
+	0x00070eec,
+	0x00089876,
+	0x000a2704,
+	0x000bb08d,
+	0x000d3a17,
+	0x001185a0,
+	0x00134f29,
+	0x0014d8b3,
+	0x001667c8,
+	0x0017f151,
+	0x00197adb,
+	0x001b0664,
+	0x001c8fed,
+	0x001e5977,
+	0x0000e805,
+	0x0002718f,
+	0x00043b18,
+	0x000586a1,
+	0x0007502b,
+	0x0008d9b4,
+	0x000a68c9,
+	0x000bf252,
+	0x000dbbdc,
+	0x0011c7e5,
+	0x001390ee,
+	0x00151a78,
+	0x0016a906,
+	0x00183290,
+	0x0019bc19,
+	0x001b4822,
+	0x001cd12c,
+	0x001e9ab5,
+	0x00000000,
+	0x00000000,
+};
+
+static const u16 bdi_tbl_rev0[] = {
+	0x0070,
+	0x0126,
+	0x012c,
+	0x0246,
+	0x048d,
+	0x04d2,
+};
+
+static const u32 chanest_tbl_rev0[] = {
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+};
+
+static const u8 mcs_tbl_rev0[] = {
+	0x00,
+	0x08,
+	0x0a,
+	0x10,
+	0x12,
+	0x19,
+	0x1a,
+	0x1c,
+	0x40,
+	0x48,
+	0x4a,
+	0x50,
+	0x52,
+	0x59,
+	0x5a,
+	0x5c,
+	0x80,
+	0x88,
+	0x8a,
+	0x90,
+	0x92,
+	0x99,
+	0x9a,
+	0x9c,
+	0xc0,
+	0xc8,
+	0xca,
+	0xd0,
+	0xd2,
+	0xd9,
+	0xda,
+	0xdc,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x01,
+	0x02,
+	0x04,
+	0x08,
+	0x09,
+	0x0a,
+	0x0c,
+	0x10,
+	0x11,
+	0x12,
+	0x14,
+	0x18,
+	0x19,
+	0x1a,
+	0x1c,
+	0x20,
+	0x21,
+	0x22,
+	0x24,
+	0x40,
+	0x41,
+	0x42,
+	0x44,
+	0x48,
+	0x49,
+	0x4a,
+	0x4c,
+	0x50,
+	0x51,
+	0x52,
+	0x54,
+	0x58,
+	0x59,
+	0x5a,
+	0x5c,
+	0x60,
+	0x61,
+	0x62,
+	0x64,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+};
+
+static const u32 noise_var_tbl0_rev0[] = {
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+};
+
+static const u32 noise_var_tbl1_rev0[] = {
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+};
+
+static const u8 est_pwr_lut_core0_rev0[] = {
+	0x50,
+	0x4f,
+	0x4e,
+	0x4d,
+	0x4c,
+	0x4b,
+	0x4a,
+	0x49,
+	0x48,
+	0x47,
+	0x46,
+	0x45,
+	0x44,
+	0x43,
+	0x42,
+	0x41,
+	0x40,
+	0x3f,
+	0x3e,
+	0x3d,
+	0x3c,
+	0x3b,
+	0x3a,
+	0x39,
+	0x38,
+	0x37,
+	0x36,
+	0x35,
+	0x34,
+	0x33,
+	0x32,
+	0x31,
+	0x30,
+	0x2f,
+	0x2e,
+	0x2d,
+	0x2c,
+	0x2b,
+	0x2a,
+	0x29,
+	0x28,
+	0x27,
+	0x26,
+	0x25,
+	0x24,
+	0x23,
+	0x22,
+	0x21,
+	0x20,
+	0x1f,
+	0x1e,
+	0x1d,
+	0x1c,
+	0x1b,
+	0x1a,
+	0x19,
+	0x18,
+	0x17,
+	0x16,
+	0x15,
+	0x14,
+	0x13,
+	0x12,
+	0x11,
+};
+
+static const u8 est_pwr_lut_core1_rev0[] = {
+	0x50,
+	0x4f,
+	0x4e,
+	0x4d,
+	0x4c,
+	0x4b,
+	0x4a,
+	0x49,
+	0x48,
+	0x47,
+	0x46,
+	0x45,
+	0x44,
+	0x43,
+	0x42,
+	0x41,
+	0x40,
+	0x3f,
+	0x3e,
+	0x3d,
+	0x3c,
+	0x3b,
+	0x3a,
+	0x39,
+	0x38,
+	0x37,
+	0x36,
+	0x35,
+	0x34,
+	0x33,
+	0x32,
+	0x31,
+	0x30,
+	0x2f,
+	0x2e,
+	0x2d,
+	0x2c,
+	0x2b,
+	0x2a,
+	0x29,
+	0x28,
+	0x27,
+	0x26,
+	0x25,
+	0x24,
+	0x23,
+	0x22,
+	0x21,
+	0x20,
+	0x1f,
+	0x1e,
+	0x1d,
+	0x1c,
+	0x1b,
+	0x1a,
+	0x19,
+	0x18,
+	0x17,
+	0x16,
+	0x15,
+	0x14,
+	0x13,
+	0x12,
+	0x11,
+};
+
+static const u8 adj_pwr_lut_core0_rev0[] = {
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+};
+
+static const u8 adj_pwr_lut_core1_rev0[] = {
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+};
+
+static const u32 gainctrl_lut_core0_rev0[] = {
+	0x03cc2b44,
+	0x03cc2b42,
+	0x03cc2b40,
+	0x03cc2b3e,
+	0x03cc2b3d,
+	0x03cc2b3b,
+	0x03c82b44,
+	0x03c82b42,
+	0x03c82b40,
+	0x03c82b3e,
+	0x03c82b3d,
+	0x03c82b3b,
+	0x03c82b39,
+	0x03c82b38,
+	0x03c82b36,
+	0x03c82b34,
+	0x03c42b44,
+	0x03c42b42,
+	0x03c42b40,
+	0x03c42b3e,
+	0x03c42b3d,
+	0x03c42b3b,
+	0x03c42b39,
+	0x03c42b38,
+	0x03c42b36,
+	0x03c42b34,
+	0x03c42b33,
+	0x03c42b32,
+	0x03c42b30,
+	0x03c42b2f,
+	0x03c42b2d,
+	0x03c02b44,
+	0x03c02b42,
+	0x03c02b40,
+	0x03c02b3e,
+	0x03c02b3d,
+	0x03c02b3b,
+	0x03c02b39,
+	0x03c02b38,
+	0x03c02b36,
+	0x03c02b34,
+	0x03b02b44,
+	0x03b02b42,
+	0x03b02b40,
+	0x03b02b3e,
+	0x03b02b3d,
+	0x03b02b3b,
+	0x03b02b39,
+	0x03b02b38,
+	0x03b02b36,
+	0x03b02b34,
+	0x03b02b33,
+	0x03b02b32,
+	0x03b02b30,
+	0x03b02b2f,
+	0x03b02b2d,
+	0x03a02b44,
+	0x03a02b42,
+	0x03a02b40,
+	0x03a02b3e,
+	0x03a02b3d,
+	0x03a02b3b,
+	0x03a02b39,
+	0x03a02b38,
+	0x03a02b36,
+	0x03a02b34,
+	0x03902b44,
+	0x03902b42,
+	0x03902b40,
+	0x03902b3e,
+	0x03902b3d,
+	0x03902b3b,
+	0x03902b39,
+	0x03902b38,
+	0x03902b36,
+	0x03902b34,
+	0x03902b33,
+	0x03902b32,
+	0x03902b30,
+	0x03802b44,
+	0x03802b42,
+	0x03802b40,
+	0x03802b3e,
+	0x03802b3d,
+	0x03802b3b,
+	0x03802b39,
+	0x03802b38,
+	0x03802b36,
+	0x03802b34,
+	0x03802b33,
+	0x03802b32,
+	0x03802b30,
+	0x03802b2f,
+	0x03802b2d,
+	0x03802b2c,
+	0x03802b2b,
+	0x03802b2a,
+	0x03802b29,
+	0x03802b27,
+	0x03802b26,
+	0x03802b25,
+	0x03802b24,
+	0x03802b23,
+	0x03802b22,
+	0x03802b21,
+	0x03802b20,
+	0x03802b1f,
+	0x03802b1e,
+	0x03802b1e,
+	0x03802b1d,
+	0x03802b1c,
+	0x03802b1b,
+	0x03802b1a,
+	0x03802b1a,
+	0x03802b19,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x00002b00,
+};
+
+static const u32 gainctrl_lut_core1_rev0[] = {
+	0x03cc2b44,
+	0x03cc2b42,
+	0x03cc2b40,
+	0x03cc2b3e,
+	0x03cc2b3d,
+	0x03cc2b3b,
+	0x03c82b44,
+	0x03c82b42,
+	0x03c82b40,
+	0x03c82b3e,
+	0x03c82b3d,
+	0x03c82b3b,
+	0x03c82b39,
+	0x03c82b38,
+	0x03c82b36,
+	0x03c82b34,
+	0x03c42b44,
+	0x03c42b42,
+	0x03c42b40,
+	0x03c42b3e,
+	0x03c42b3d,
+	0x03c42b3b,
+	0x03c42b39,
+	0x03c42b38,
+	0x03c42b36,
+	0x03c42b34,
+	0x03c42b33,
+	0x03c42b32,
+	0x03c42b30,
+	0x03c42b2f,
+	0x03c42b2d,
+	0x03c02b44,
+	0x03c02b42,
+	0x03c02b40,
+	0x03c02b3e,
+	0x03c02b3d,
+	0x03c02b3b,
+	0x03c02b39,
+	0x03c02b38,
+	0x03c02b36,
+	0x03c02b34,
+	0x03b02b44,
+	0x03b02b42,
+	0x03b02b40,
+	0x03b02b3e,
+	0x03b02b3d,
+	0x03b02b3b,
+	0x03b02b39,
+	0x03b02b38,
+	0x03b02b36,
+	0x03b02b34,
+	0x03b02b33,
+	0x03b02b32,
+	0x03b02b30,
+	0x03b02b2f,
+	0x03b02b2d,
+	0x03a02b44,
+	0x03a02b42,
+	0x03a02b40,
+	0x03a02b3e,
+	0x03a02b3d,
+	0x03a02b3b,
+	0x03a02b39,
+	0x03a02b38,
+	0x03a02b36,
+	0x03a02b34,
+	0x03902b44,
+	0x03902b42,
+	0x03902b40,
+	0x03902b3e,
+	0x03902b3d,
+	0x03902b3b,
+	0x03902b39,
+	0x03902b38,
+	0x03902b36,
+	0x03902b34,
+	0x03902b33,
+	0x03902b32,
+	0x03902b30,
+	0x03802b44,
+	0x03802b42,
+	0x03802b40,
+	0x03802b3e,
+	0x03802b3d,
+	0x03802b3b,
+	0x03802b39,
+	0x03802b38,
+	0x03802b36,
+	0x03802b34,
+	0x03802b33,
+	0x03802b32,
+	0x03802b30,
+	0x03802b2f,
+	0x03802b2d,
+	0x03802b2c,
+	0x03802b2b,
+	0x03802b2a,
+	0x03802b29,
+	0x03802b27,
+	0x03802b26,
+	0x03802b25,
+	0x03802b24,
+	0x03802b23,
+	0x03802b22,
+	0x03802b21,
+	0x03802b20,
+	0x03802b1f,
+	0x03802b1e,
+	0x03802b1e,
+	0x03802b1d,
+	0x03802b1c,
+	0x03802b1b,
+	0x03802b1a,
+	0x03802b1a,
+	0x03802b19,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x00002b00,
+};
+
+static const u32 iq_lut_core0_rev0[] = {
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+};
+
+static const u32 iq_lut_core1_rev0[] = {
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+};
+
+static const u16 loft_lut_core0_rev0[] = {
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+};
+
+static const u16 loft_lut_core1_rev0[] = {
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+};
+
+const struct phytbl_info mimophytbl_info_rev0_volatile[] = {
+	{&bdi_tbl_rev0, ARRAY_SIZE(bdi_tbl_rev0), 21, 0, 16},
+	{&pltlut_tbl_rev0, ARRAY_SIZE(pltlut_tbl_rev0), 20, 0, 32},
+	{&gainctrl_lut_core0_rev0, ARRAY_SIZE(gainctrl_lut_core0_rev0), 26, 192, 32},
+	{&gainctrl_lut_core1_rev0, ARRAY_SIZE(gainctrl_lut_core1_rev0), 27, 192, 32},
+	{&est_pwr_lut_core0_rev0, ARRAY_SIZE(est_pwr_lut_core0_rev0), 26, 0, 8},
+	{&est_pwr_lut_core1_rev0, ARRAY_SIZE(est_pwr_lut_core1_rev0), 27, 0, 8},
+	{&adj_pwr_lut_core0_rev0, ARRAY_SIZE(adj_pwr_lut_core0_rev0), 26, 64, 8},
+	{&adj_pwr_lut_core1_rev0, ARRAY_SIZE(adj_pwr_lut_core1_rev0), 27, 64, 8},
+	{&iq_lut_core0_rev0, ARRAY_SIZE(iq_lut_core0_rev0), 26, 320, 32},
+	{&iq_lut_core1_rev0, ARRAY_SIZE(iq_lut_core1_rev0), 27, 320, 32},
+	{&loft_lut_core0_rev0, ARRAY_SIZE(loft_lut_core0_rev0), 26, 448, 16},
+	{&loft_lut_core1_rev0, ARRAY_SIZE(loft_lut_core1_rev0), 27, 448, 16},
+};
+
+const struct phytbl_info mimophytbl_info_rev0[] = {
+	{&frame_struct_rev0, ARRAY_SIZE(frame_struct_rev0), 10, 0, 32},
+	{&frame_lut_rev0, ARRAY_SIZE(frame_lut_rev0), 24, 0, 8},
+	{&tmap_tbl_rev0, ARRAY_SIZE(tmap_tbl_rev0), 12, 0, 32},
+	{&tdtrn_tbl_rev0, ARRAY_SIZE(tdtrn_tbl_rev0), 14, 0, 32},
+	{&intlv_tbl_rev0, ARRAY_SIZE(intlv_tbl_rev0), 13, 0, 32},
+	{&pilot_tbl_rev0, ARRAY_SIZE(pilot_tbl_rev0), 11, 0, 16},
+	{&tdi_tbl20_ant0_rev0, ARRAY_SIZE(tdi_tbl20_ant0_rev0), 19, 128, 32},
+	{&tdi_tbl20_ant1_rev0, ARRAY_SIZE(tdi_tbl20_ant1_rev0), 19, 256, 32},
+	{&tdi_tbl40_ant0_rev0, ARRAY_SIZE(tdi_tbl40_ant0_rev0), 19, 640, 32},
+	{&tdi_tbl40_ant1_rev0, ARRAY_SIZE(tdi_tbl40_ant1_rev0), 19, 768, 32},
+	{&chanest_tbl_rev0, ARRAY_SIZE(chanest_tbl_rev0), 22, 0, 32},
+	{&mcs_tbl_rev0, ARRAY_SIZE(mcs_tbl_rev0), 18, 0, 8},
+	{&noise_var_tbl0_rev0, ARRAY_SIZE(noise_var_tbl0_rev0), 16, 0, 32},
+	{&noise_var_tbl1_rev0, ARRAY_SIZE(noise_var_tbl1_rev0), 16, 128, 32},
+};
+
+const u32 mimophytbl_info_sz_rev0 = ARRAY_SIZE(mimophytbl_info_rev0);
+const u32 mimophytbl_info_sz_rev0_volatile = ARRAY_SIZE(mimophytbl_info_rev0_volatile);
+
+static const u16 ant_swctrl_tbl_rev3[] = {
+	0x0082,
+	0x0082,
+	0x0211,
+	0x0222,
+	0x0328,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0144,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0188,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0082,
+	0x0082,
+	0x0211,
+	0x0222,
+	0x0328,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0144,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0188,
+	0x0000,
+	0x0000,
+	0x0000,
+};
+
+static const u16 ant_swctrl_tbl_rev3_1[] = {
+	0x0022,
+	0x0022,
+	0x0011,
+	0x0022,
+	0x0022,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0011,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0022,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0022,
+	0x0022,
+	0x0011,
+	0x0022,
+	0x0022,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0011,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0022,
+	0x0000,
+	0x0000,
+	0x0000,
+};
+
+static const u16 ant_swctrl_tbl_rev3_2[] = {
+	0x0088,
+	0x0088,
+	0x0044,
+	0x0088,
+	0x0088,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0044,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0088,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0088,
+	0x0088,
+	0x0044,
+	0x0088,
+	0x0088,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0044,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0088,
+	0x0000,
+	0x0000,
+	0x0000,
+};
+
+static const u16 ant_swctrl_tbl_rev3_3[] = {
+	0x022,
+	0x022,
+	0x011,
+	0x022,
+	0x000,
+	0x000,
+	0x000,
+	0x000,
+	0x011,
+	0x000,
+	0x000,
+	0x000,
+	0x022,
+	0x000,
+	0x000,
+	0x3cc,
+	0x022,
+	0x022,
+	0x011,
+	0x022,
+	0x000,
+	0x000,
+	0x000,
+	0x000,
+	0x011,
+	0x000,
+	0x000,
+	0x000,
+	0x022,
+	0x000,
+	0x000,
+	0x3cc
+};
+
+static const u32 frame_struct_rev3[] = {
+	0x08004a04,
+	0x00100000,
+	0x01000a05,
+	0x00100020,
+	0x09804506,
+	0x00100030,
+	0x09804507,
+	0x00100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a0c,
+	0x00100004,
+	0x01000a0d,
+	0x00100024,
+	0x0980450e,
+	0x00100034,
+	0x0980450f,
+	0x00100034,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a04,
+	0x00100000,
+	0x11008a05,
+	0x00100020,
+	0x1980c506,
+	0x00100030,
+	0x21810506,
+	0x00100030,
+	0x21810506,
+	0x00100030,
+	0x01800504,
+	0x00100030,
+	0x11808505,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000a04,
+	0x00100000,
+	0x11008a05,
+	0x00100020,
+	0x21810506,
+	0x00100030,
+	0x21810506,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a0c,
+	0x00100008,
+	0x11008a0d,
+	0x00100028,
+	0x1980c50e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x0180050c,
+	0x00100038,
+	0x1180850d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000a0c,
+	0x00100008,
+	0x11008a0d,
+	0x00100028,
+	0x2181050e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a04,
+	0x00100000,
+	0x01000a05,
+	0x00100020,
+	0x1980c506,
+	0x00100030,
+	0x1980c506,
+	0x00100030,
+	0x11808504,
+	0x00100030,
+	0x3981ca05,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x10008a04,
+	0x00100000,
+	0x3981ca05,
+	0x00100030,
+	0x1980c506,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a0c,
+	0x00100008,
+	0x01000a0d,
+	0x00100028,
+	0x1980c50e,
+	0x00100038,
+	0x1980c50e,
+	0x00100038,
+	0x1180850c,
+	0x00100038,
+	0x3981ca0d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x10008a0c,
+	0x00100008,
+	0x3981ca0d,
+	0x00100038,
+	0x1980c50e,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x00100000,
+	0x02001405,
+	0x00100040,
+	0x0b004a06,
+	0x01900060,
+	0x13008a06,
+	0x01900060,
+	0x13008a06,
+	0x01900060,
+	0x43020a04,
+	0x00100060,
+	0x1b00ca05,
+	0x00100060,
+	0x23010a07,
+	0x01500060,
+	0x40021404,
+	0x00100000,
+	0x1a00d405,
+	0x00100040,
+	0x13008a06,
+	0x01900060,
+	0x13008a06,
+	0x01900060,
+	0x23010a07,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x0200140d,
+	0x00100050,
+	0x0b004a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x43020a0c,
+	0x00100070,
+	0x1b00ca0d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x13008a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x50029404,
+	0x00100000,
+	0x32019405,
+	0x00100040,
+	0x0b004a06,
+	0x01900060,
+	0x0b004a06,
+	0x01900060,
+	0x5b02ca04,
+	0x00100060,
+	0x3b01d405,
+	0x00100060,
+	0x23010a07,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x5802d404,
+	0x00100000,
+	0x3b01d405,
+	0x00100060,
+	0x0b004a06,
+	0x01900060,
+	0x23010a07,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x5002940c,
+	0x00100010,
+	0x3201940d,
+	0x00100050,
+	0x0b004a0e,
+	0x01900070,
+	0x0b004a0e,
+	0x01900070,
+	0x5b02ca0c,
+	0x00100070,
+	0x3b01d40d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x5802d40c,
+	0x00100010,
+	0x3b01d40d,
+	0x00100070,
+	0x0b004a0e,
+	0x01900070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x000f4800,
+	0x62031405,
+	0x00100040,
+	0x53028a06,
+	0x01900060,
+	0x53028a07,
+	0x01900060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x000f4808,
+	0x6203140d,
+	0x00100048,
+	0x53028a0e,
+	0x01900068,
+	0x53028a0f,
+	0x01900068,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a0c,
+	0x00100004,
+	0x11008a0d,
+	0x00100024,
+	0x1980c50e,
+	0x00100034,
+	0x2181050e,
+	0x00100034,
+	0x2181050e,
+	0x00100034,
+	0x0180050c,
+	0x00100038,
+	0x1180850d,
+	0x00100038,
+	0x1181850d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a0c,
+	0x00100008,
+	0x11008a0d,
+	0x00100028,
+	0x2181050e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x1181850d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a04,
+	0x00100000,
+	0x01000a05,
+	0x00100020,
+	0x0180c506,
+	0x00100030,
+	0x0180c506,
+	0x00100030,
+	0x2180c50c,
+	0x00100030,
+	0x49820a0d,
+	0x0016a130,
+	0x41824a0d,
+	0x0016a130,
+	0x2981450f,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x2000ca0c,
+	0x00100000,
+	0x49820a0d,
+	0x0016a130,
+	0x1980c50e,
+	0x00100030,
+	0x41824a0d,
+	0x0016a130,
+	0x2981450f,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100008,
+	0x0200140d,
+	0x00100048,
+	0x0b004a0e,
+	0x01900068,
+	0x13008a0e,
+	0x01900068,
+	0x13008a0e,
+	0x01900068,
+	0x43020a0c,
+	0x00100070,
+	0x1b00ca0d,
+	0x00100070,
+	0x1b014a0d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x13008a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x1b014a0d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x50029404,
+	0x00100000,
+	0x32019405,
+	0x00100040,
+	0x03004a06,
+	0x01900060,
+	0x03004a06,
+	0x01900060,
+	0x6b030a0c,
+	0x00100060,
+	0x4b02140d,
+	0x0016a160,
+	0x4302540d,
+	0x0016a160,
+	0x23010a0f,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x6b03140c,
+	0x00100060,
+	0x4b02140d,
+	0x0016a160,
+	0x0b004a0e,
+	0x01900060,
+	0x4302540d,
+	0x0016a160,
+	0x23010a0f,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x00100000,
+	0x1a00d405,
+	0x00100040,
+	0x53028a06,
+	0x01900060,
+	0x5b02ca06,
+	0x01900060,
+	0x5b02ca06,
+	0x01900060,
+	0x43020a04,
+	0x00100060,
+	0x1b00ca05,
+	0x00100060,
+	0x53028a07,
+	0x0190c060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x53028a0e,
+	0x01900070,
+	0x5b02ca0e,
+	0x01900070,
+	0x5b02ca0e,
+	0x01900070,
+	0x43020a0c,
+	0x00100070,
+	0x1b00ca0d,
+	0x00100070,
+	0x53028a0f,
+	0x0190c070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x00100000,
+	0x1a00d405,
+	0x00100040,
+	0x5b02ca06,
+	0x01900060,
+	0x5b02ca06,
+	0x01900060,
+	0x53028a07,
+	0x0190c060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x5b02ca0e,
+	0x01900070,
+	0x5b02ca0e,
+	0x01900070,
+	0x53028a0f,
+	0x0190c070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	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 pilot_tbl_rev3[] = {
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0xff0a,
+	0xff82,
+	0xffa0,
+	0xff28,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xff82,
+	0xffa0,
+	0xff28,
+	0xff0a,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xf83f,
+	0xfa1f,
+	0xfa97,
+	0xfab5,
+	0xf2bd,
+	0xf0bf,
+	0xffff,
+	0xffff,
+	0xf017,
+	0xf815,
+	0xf215,
+	0xf095,
+	0xf035,
+	0xf01d,
+	0xffff,
+	0xffff,
+	0xff08,
+	0xff02,
+	0xff80,
+	0xff20,
+	0xff08,
+	0xff02,
+	0xff80,
+	0xff20,
+	0xf01f,
+	0xf817,
+	0xfa15,
+	0xf295,
+	0xf0b5,
+	0xf03d,
+	0xffff,
+	0xffff,
+	0xf82a,
+	0xfa0a,
+	0xfa82,
+	0xfaa0,
+	0xf2a8,
+	0xf0aa,
+	0xffff,
+	0xffff,
+	0xf002,
+	0xf800,
+	0xf200,
+	0xf080,
+	0xf020,
+	0xf008,
+	0xffff,
+	0xffff,
+	0xf00a,
+	0xf802,
+	0xfa00,
+	0xf280,
+	0xf0a0,
+	0xf028,
+	0xffff,
+	0xffff,
+};
+
+static const u32 tmap_tbl_rev3[] = {
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00000111,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x000aa888,
+	0x88880000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa2222220,
+	0x22222222,
+	0x22c22222,
+	0x00000222,
+	0x22000000,
+	0x2222a222,
+	0x22222222,
+	0x222222a2,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00011111,
+	0x11110000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0xa8aa88a0,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x00088aaa,
+	0xaaaa0000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xaaa8aaa0,
+	0x8aaa8aaa,
+	0xaa8a8a8a,
+	0x000aaa88,
+	0x8aaa0000,
+	0xaaa8a888,
+	0x8aa88a8a,
+	0x8a88a888,
+	0x08080a00,
+	0x0a08080a,
+	0x080a0a08,
+	0x00080808,
+	0x080a0000,
+	0x080a0808,
+	0x080a0808,
+	0x0a0a0a08,
+	0xa0a0a0a0,
+	0x80a0a080,
+	0x8080a0a0,
+	0x00008080,
+	0x80a00000,
+	0x80a080a0,
+	0xa080a0a0,
+	0x8080a0a0,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x99999000,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb90,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00aaa888,
+	0x22000000,
+	0x2222b222,
+	0x22222222,
+	0x222222b2,
+	0xb2222220,
+	0x22222222,
+	0x22d22222,
+	0x00000222,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x33000000,
+	0x3333b333,
+	0x33333333,
+	0x333333b3,
+	0xb3333330,
+	0x33333333,
+	0x33d33333,
+	0x00000333,
+	0x22000000,
+	0x2222a222,
+	0x22222222,
+	0x222222a2,
+	0xa2222220,
+	0x22222222,
+	0x22c22222,
+	0x00000222,
+	0x99b99b00,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb99,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x08aaa888,
+	0x22222200,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0x22222222,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x11111111,
+	0xf1111111,
+	0x11111111,
+	0x11f11111,
+	0x01111111,
+	0xbb9bb900,
+	0xb9b9bb99,
+	0xb99bbbbb,
+	0xbbbb9b9b,
+	0xb9bb99bb,
+	0xb99999b9,
+	0xb9b9b99b,
+	0x00000bbb,
+	0xaa000000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xa8aa88aa,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x0a888aaa,
+	0xaa000000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xa8aa88a0,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x00000aaa,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0xbbbbbb00,
+	0x999bbbbb,
+	0x9bb99b9b,
+	0xb9b9b9bb,
+	0xb9b99bbb,
+	0xb9b9b9bb,
+	0xb9bb9b99,
+	0x00000999,
+	0x8a000000,
+	0xaa88a888,
+	0xa88888aa,
+	0xa88a8a88,
+	0xa88aa88a,
+	0x88a8aaaa,
+	0xa8aa8aaa,
+	0x0888a88a,
+	0x0b0b0b00,
+	0x090b0b0b,
+	0x0b090b0b,
+	0x0909090b,
+	0x09090b0b,
+	0x09090b0b,
+	0x09090b09,
+	0x00000909,
+	0x0a000000,
+	0x0a080808,
+	0x080a080a,
+	0x080a0a08,
+	0x080a080a,
+	0x0808080a,
+	0x0a0a0a08,
+	0x0808080a,
+	0xb0b0b000,
+	0x9090b0b0,
+	0x90b09090,
+	0xb0b0b090,
+	0xb0b090b0,
+	0x90b0b0b0,
+	0xb0b09090,
+	0x00000090,
+	0x80000000,
+	0xa080a080,
+	0xa08080a0,
+	0xa0808080,
+	0xa080a080,
+	0x80a0a0a0,
+	0xa0a080a0,
+	0x00a0a0a0,
+	0x22000000,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0xf2222220,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00000111,
+	0x33000000,
+	0x3333f333,
+	0x33333333,
+	0x333333f3,
+	0xf3333330,
+	0x33333333,
+	0x33f33333,
+	0x00000333,
+	0x22000000,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0xf2222220,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x99000000,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb90,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88888000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00aaa888,
+	0x88a88a00,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x08aaa888,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	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 intlv_tbl_rev3[] = {
+	0x00802070,
+	0x0671188d,
+	0x0a60192c,
+	0x0a300e46,
+	0x00c1188d,
+	0x080024d2,
+	0x00000070,
+};
+
+static const u32 tdtrn_tbl_rev3[] = {
+	0x061c061c,
+	0x0050ee68,
+	0xf592fe36,
+	0xfe5212f6,
+	0x00000c38,
+	0xfe5212f6,
+	0xf592fe36,
+	0x0050ee68,
+	0x061c061c,
+	0xee680050,
+	0xfe36f592,
+	0x12f6fe52,
+	0x0c380000,
+	0x12f6fe52,
+	0xfe36f592,
+	0xee680050,
+	0x061c061c,
+	0x0050ee68,
+	0xf592fe36,
+	0xfe5212f6,
+	0x00000c38,
+	0xfe5212f6,
+	0xf592fe36,
+	0x0050ee68,
+	0x061c061c,
+	0xee680050,
+	0xfe36f592,
+	0x12f6fe52,
+	0x0c380000,
+	0x12f6fe52,
+	0xfe36f592,
+	0xee680050,
+	0x05e305e3,
+	0x004def0c,
+	0xf5f3fe47,
+	0xfe611246,
+	0x00000bc7,
+	0xfe611246,
+	0xf5f3fe47,
+	0x004def0c,
+	0x05e305e3,
+	0xef0c004d,
+	0xfe47f5f3,
+	0x1246fe61,
+	0x0bc70000,
+	0x1246fe61,
+	0xfe47f5f3,
+	0xef0c004d,
+	0x05e305e3,
+	0x004def0c,
+	0xf5f3fe47,
+	0xfe611246,
+	0x00000bc7,
+	0xfe611246,
+	0xf5f3fe47,
+	0x004def0c,
+	0x05e305e3,
+	0xef0c004d,
+	0xfe47f5f3,
+	0x1246fe61,
+	0x0bc70000,
+	0x1246fe61,
+	0xfe47f5f3,
+	0xef0c004d,
+	0xfa58fa58,
+	0xf895043b,
+	0xff4c09c0,
+	0xfbc6ffa8,
+	0xfb84f384,
+	0x0798f6f9,
+	0x05760122,
+	0x058409f6,
+	0x0b500000,
+	0x05b7f542,
+	0x08860432,
+	0x06ddfee7,
+	0xfb84f384,
+	0xf9d90664,
+	0xf7e8025c,
+	0x00fff7bd,
+	0x05a805a8,
+	0xf7bd00ff,
+	0x025cf7e8,
+	0x0664f9d9,
+	0xf384fb84,
+	0xfee706dd,
+	0x04320886,
+	0xf54205b7,
+	0x00000b50,
+	0x09f60584,
+	0x01220576,
+	0xf6f90798,
+	0xf384fb84,
+	0xffa8fbc6,
+	0x09c0ff4c,
+	0x043bf895,
+	0x02d402d4,
+	0x07de0270,
+	0xfc96079c,
+	0xf90afe94,
+	0xfe00ff2c,
+	0x02d4065d,
+	0x092a0096,
+	0x0014fbb8,
+	0xfd2cfd2c,
+	0x076afb3c,
+	0x0096f752,
+	0xf991fd87,
+	0xfb2c0200,
+	0xfeb8f960,
+	0x08e0fc96,
+	0x049802a8,
+	0xfd2cfd2c,
+	0x02a80498,
+	0xfc9608e0,
+	0xf960feb8,
+	0x0200fb2c,
+	0xfd87f991,
+	0xf7520096,
+	0xfb3c076a,
+	0xfd2cfd2c,
+	0xfbb80014,
+	0x0096092a,
+	0x065d02d4,
+	0xff2cfe00,
+	0xfe94f90a,
+	0x079cfc96,
+	0x027007de,
+	0x02d402d4,
+	0x027007de,
+	0x079cfc96,
+	0xfe94f90a,
+	0xff2cfe00,
+	0x065d02d4,
+	0x0096092a,
+	0xfbb80014,
+	0xfd2cfd2c,
+	0xfb3c076a,
+	0xf7520096,
+	0xfd87f991,
+	0x0200fb2c,
+	0xf960feb8,
+	0xfc9608e0,
+	0x02a80498,
+	0xfd2cfd2c,
+	0x049802a8,
+	0x08e0fc96,
+	0xfeb8f960,
+	0xfb2c0200,
+	0xf991fd87,
+	0x0096f752,
+	0x076afb3c,
+	0xfd2cfd2c,
+	0x0014fbb8,
+	0x092a0096,
+	0x02d4065d,
+	0xfe00ff2c,
+	0xf90afe94,
+	0xfc96079c,
+	0x07de0270,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x062a0000,
+	0xfefa0759,
+	0x08b80908,
+	0xf396fc2d,
+	0xf9d6045c,
+	0xfc4ef608,
+	0xf748f596,
+	0x07b207bf,
+	0x062a062a,
+	0xf84ef841,
+	0xf748f596,
+	0x03b209f8,
+	0xf9d6045c,
+	0x0c6a03d3,
+	0x08b80908,
+	0x0106f8a7,
+	0x062a0000,
+	0xfefaf8a7,
+	0x08b8f6f8,
+	0xf39603d3,
+	0xf9d6fba4,
+	0xfc4e09f8,
+	0xf7480a6a,
+	0x07b2f841,
+	0x062af9d6,
+	0xf84e07bf,
+	0xf7480a6a,
+	0x03b2f608,
+	0xf9d6fba4,
+	0x0c6afc2d,
+	0x08b8f6f8,
+	0x01060759,
+	0x062a0000,
+	0xfefa0759,
+	0x08b80908,
+	0xf396fc2d,
+	0xf9d6045c,
+	0xfc4ef608,
+	0xf748f596,
+	0x07b207bf,
+	0x062a062a,
+	0xf84ef841,
+	0xf748f596,
+	0x03b209f8,
+	0xf9d6045c,
+	0x0c6a03d3,
+	0x08b80908,
+	0x0106f8a7,
+	0x062a0000,
+	0xfefaf8a7,
+	0x08b8f6f8,
+	0xf39603d3,
+	0xf9d6fba4,
+	0xfc4e09f8,
+	0xf7480a6a,
+	0x07b2f841,
+	0x062af9d6,
+	0xf84e07bf,
+	0xf7480a6a,
+	0x03b2f608,
+	0xf9d6fba4,
+	0x0c6afc2d,
+	0x08b8f6f8,
+	0x01060759,
+	0x061c061c,
+	0xff30009d,
+	0xffb21141,
+	0xfd87fb54,
+	0xf65dfe59,
+	0x02eef99e,
+	0x0166f03c,
+	0xfff809b6,
+	0x000008a4,
+	0x000af42b,
+	0x00eff577,
+	0xfa840bf2,
+	0xfc02ff51,
+	0x08260f67,
+	0xfff0036f,
+	0x0842f9c3,
+	0x00000000,
+	0x063df7be,
+	0xfc910010,
+	0xf099f7da,
+	0x00af03fe,
+	0xf40e057c,
+	0x0a89ff11,
+	0x0bd5fff6,
+	0xf75c0000,
+	0xf64a0008,
+	0x0fc4fe9a,
+	0x0662fd12,
+	0x01a709a3,
+	0x04ac0279,
+	0xeebf004e,
+	0xff6300d0,
+	0xf9e4f9e4,
+	0x00d0ff63,
+	0x004eeebf,
+	0x027904ac,
+	0x09a301a7,
+	0xfd120662,
+	0xfe9a0fc4,
+	0x0008f64a,
+	0x0000f75c,
+	0xfff60bd5,
+	0xff110a89,
+	0x057cf40e,
+	0x03fe00af,
+	0xf7daf099,
+	0x0010fc91,
+	0xf7be063d,
+	0x00000000,
+	0xf9c30842,
+	0x036ffff0,
+	0x0f670826,
+	0xff51fc02,
+	0x0bf2fa84,
+	0xf57700ef,
+	0xf42b000a,
+	0x08a40000,
+	0x09b6fff8,
+	0xf03c0166,
+	0xf99e02ee,
+	0xfe59f65d,
+	0xfb54fd87,
+	0x1141ffb2,
+	0x009dff30,
+	0x05e30000,
+	0xff060705,
+	0x085408a0,
+	0xf425fc59,
+	0xfa1d042a,
+	0xfc78f67a,
+	0xf7acf60e,
+	0x075a0766,
+	0x05e305e3,
+	0xf8a6f89a,
+	0xf7acf60e,
+	0x03880986,
+	0xfa1d042a,
+	0x0bdb03a7,
+	0x085408a0,
+	0x00faf8fb,
+	0x05e30000,
+	0xff06f8fb,
+	0x0854f760,
+	0xf42503a7,
+	0xfa1dfbd6,
+	0xfc780986,
+	0xf7ac09f2,
+	0x075af89a,
+	0x05e3fa1d,
+	0xf8a60766,
+	0xf7ac09f2,
+	0x0388f67a,
+	0xfa1dfbd6,
+	0x0bdbfc59,
+	0x0854f760,
+	0x00fa0705,
+	0x05e30000,
+	0xff060705,
+	0x085408a0,
+	0xf425fc59,
+	0xfa1d042a,
+	0xfc78f67a,
+	0xf7acf60e,
+	0x075a0766,
+	0x05e305e3,
+	0xf8a6f89a,
+	0xf7acf60e,
+	0x03880986,
+	0xfa1d042a,
+	0x0bdb03a7,
+	0x085408a0,
+	0x00faf8fb,
+	0x05e30000,
+	0xff06f8fb,
+	0x0854f760,
+	0xf42503a7,
+	0xfa1dfbd6,
+	0xfc780986,
+	0xf7ac09f2,
+	0x075af89a,
+	0x05e3fa1d,
+	0xf8a60766,
+	0xf7ac09f2,
+	0x0388f67a,
+	0xfa1dfbd6,
+	0x0bdbfc59,
+	0x0854f760,
+	0x00fa0705,
+	0xfa58fa58,
+	0xf8f0fe00,
+	0x0448073d,
+	0xfdc9fe46,
+	0xf9910258,
+	0x089d0407,
+	0xfd5cf71a,
+	0x02affde0,
+	0x083e0496,
+	0xff5a0740,
+	0xff7afd97,
+	0x00fe01f1,
+	0x0009082e,
+	0xfa94ff75,
+	0xfecdf8ea,
+	0xffb0f693,
+	0xfd2cfa58,
+	0x0433ff16,
+	0xfba405dd,
+	0xfa610341,
+	0x06a606cb,
+	0x0039fd2d,
+	0x0677fa97,
+	0x01fa05e0,
+	0xf896003e,
+	0x075a068b,
+	0x012cfc3e,
+	0xfa23f98d,
+	0xfc7cfd43,
+	0xff90fc0d,
+	0x01c10982,
+	0x00c601d6,
+	0xfd2cfd2c,
+	0x01d600c6,
+	0x098201c1,
+	0xfc0dff90,
+	0xfd43fc7c,
+	0xf98dfa23,
+	0xfc3e012c,
+	0x068b075a,
+	0x003ef896,
+	0x05e001fa,
+	0xfa970677,
+	0xfd2d0039,
+	0x06cb06a6,
+	0x0341fa61,
+	0x05ddfba4,
+	0xff160433,
+	0xfa58fd2c,
+	0xf693ffb0,
+	0xf8eafecd,
+	0xff75fa94,
+	0x082e0009,
+	0x01f100fe,
+	0xfd97ff7a,
+	0x0740ff5a,
+	0x0496083e,
+	0xfde002af,
+	0xf71afd5c,
+	0x0407089d,
+	0x0258f991,
+	0xfe46fdc9,
+	0x073d0448,
+	0xfe00f8f0,
+	0xfd2cfd2c,
+	0xfce00500,
+	0xfc09fddc,
+	0xfe680157,
+	0x04c70571,
+	0xfc3aff21,
+	0xfcd70228,
+	0x056d0277,
+	0x0200fe00,
+	0x0022f927,
+	0xfe3c032b,
+	0xfc44ff3c,
+	0x03e9fbdb,
+	0x04570313,
+	0x04c9ff5c,
+	0x000d03b8,
+	0xfa580000,
+	0xfbe900d2,
+	0xf9d0fe0b,
+	0x0125fdf9,
+	0x042501bf,
+	0x0328fa2b,
+	0xffa902f0,
+	0xfa250157,
+	0x0200fe00,
+	0x03740438,
+	0xff0405fd,
+	0x030cfe52,
+	0x0037fb39,
+	0xff6904c5,
+	0x04f8fd23,
+	0xfd31fc1b,
+	0xfd2cfd2c,
+	0xfc1bfd31,
+	0xfd2304f8,
+	0x04c5ff69,
+	0xfb390037,
+	0xfe52030c,
+	0x05fdff04,
+	0x04380374,
+	0xfe000200,
+	0x0157fa25,
+	0x02f0ffa9,
+	0xfa2b0328,
+	0x01bf0425,
+	0xfdf90125,
+	0xfe0bf9d0,
+	0x00d2fbe9,
+	0x0000fa58,
+	0x03b8000d,
+	0xff5c04c9,
+	0x03130457,
+	0xfbdb03e9,
+	0xff3cfc44,
+	0x032bfe3c,
+	0xf9270022,
+	0xfe000200,
+	0x0277056d,
+	0x0228fcd7,
+	0xff21fc3a,
+	0x057104c7,
+	0x0157fe68,
+	0xfddcfc09,
+	0x0500fce0,
+	0xfd2cfd2c,
+	0x0500fce0,
+	0xfddcfc09,
+	0x0157fe68,
+	0x057104c7,
+	0xff21fc3a,
+	0x0228fcd7,
+	0x0277056d,
+	0xfe000200,
+	0xf9270022,
+	0x032bfe3c,
+	0xff3cfc44,
+	0xfbdb03e9,
+	0x03130457,
+	0xff5c04c9,
+	0x03b8000d,
+	0x0000fa58,
+	0x00d2fbe9,
+	0xfe0bf9d0,
+	0xfdf90125,
+	0x01bf0425,
+	0xfa2b0328,
+	0x02f0ffa9,
+	0x0157fa25,
+	0xfe000200,
+	0x04380374,
+	0x05fdff04,
+	0xfe52030c,
+	0xfb390037,
+	0x04c5ff69,
+	0xfd2304f8,
+	0xfc1bfd31,
+	0xfd2cfd2c,
+	0xfd31fc1b,
+	0x04f8fd23,
+	0xff6904c5,
+	0x0037fb39,
+	0x030cfe52,
+	0xff0405fd,
+	0x03740438,
+	0x0200fe00,
+	0xfa250157,
+	0xffa902f0,
+	0x0328fa2b,
+	0x042501bf,
+	0x0125fdf9,
+	0xf9d0fe0b,
+	0xfbe900d2,
+	0xfa580000,
+	0x000d03b8,
+	0x04c9ff5c,
+	0x04570313,
+	0x03e9fbdb,
+	0xfc44ff3c,
+	0xfe3c032b,
+	0x0022f927,
+	0x0200fe00,
+	0x056d0277,
+	0xfcd70228,
+	0xfc3aff21,
+	0x04c70571,
+	0xfe680157,
+	0xfc09fddc,
+	0xfce00500,
+	0x05a80000,
+	0xff1006be,
+	0x0800084a,
+	0xf49cfc7e,
+	0xfa580400,
+	0xfc9cf6da,
+	0xf800f672,
+	0x0710071c,
+	0x05a805a8,
+	0xf8f0f8e4,
+	0xf800f672,
+	0x03640926,
+	0xfa580400,
+	0x0b640382,
+	0x0800084a,
+	0x00f0f942,
+	0x05a80000,
+	0xff10f942,
+	0x0800f7b6,
+	0xf49c0382,
+	0xfa58fc00,
+	0xfc9c0926,
+	0xf800098e,
+	0x0710f8e4,
+	0x05a8fa58,
+	0xf8f0071c,
+	0xf800098e,
+	0x0364f6da,
+	0xfa58fc00,
+	0x0b64fc7e,
+	0x0800f7b6,
+	0x00f006be,
+	0x05a80000,
+	0xff1006be,
+	0x0800084a,
+	0xf49cfc7e,
+	0xfa580400,
+	0xfc9cf6da,
+	0xf800f672,
+	0x0710071c,
+	0x05a805a8,
+	0xf8f0f8e4,
+	0xf800f672,
+	0x03640926,
+	0xfa580400,
+	0x0b640382,
+	0x0800084a,
+	0x00f0f942,
+	0x05a80000,
+	0xff10f942,
+	0x0800f7b6,
+	0xf49c0382,
+	0xfa58fc00,
+	0xfc9c0926,
+	0xf800098e,
+	0x0710f8e4,
+	0x05a8fa58,
+	0xf8f0071c,
+	0xf800098e,
+	0x0364f6da,
+	0xfa58fc00,
+	0x0b64fc7e,
+	0x0800f7b6,
+	0x00f006be,
+};
+
+const u32 noise_var_tbl_rev3[] = {
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+};
+
+static const u16 mcs_tbl_rev3[] = {
+	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 u32 tdi_tbl20_ant0_rev3[] = {
+	0x00091226,
+	0x000a1429,
+	0x000b56ad,
+	0x000c58b0,
+	0x000d5ab3,
+	0x000e9cb6,
+	0x000f9eba,
+	0x0000c13d,
+	0x00020301,
+	0x00030504,
+	0x00040708,
+	0x0005090b,
+	0x00064b8e,
+	0x00095291,
+	0x000a5494,
+	0x000b9718,
+	0x000c9927,
+	0x000d9b2a,
+	0x000edd2e,
+	0x000fdf31,
+	0x000101b4,
+	0x000243b7,
+	0x000345bb,
+	0x000447be,
+	0x00058982,
+	0x00068c05,
+	0x00099309,
+	0x000a950c,
+	0x000bd78f,
+	0x000cd992,
+	0x000ddb96,
+	0x000f1d99,
+	0x00005fa8,
+	0x0001422c,
+	0x0002842f,
+	0x00038632,
+	0x00048835,
+	0x0005ca38,
+	0x0006ccbc,
+	0x0009d3bf,
+	0x000b1603,
+	0x000c1806,
+	0x000d1a0a,
+	0x000e1c0d,
+	0x000f5e10,
+	0x00008093,
+	0x00018297,
+	0x0002c49a,
+	0x0003c680,
+	0x0004c880,
+	0x00060b00,
+	0x00070d00,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+static const u32 tdi_tbl20_ant1_rev3[] = {
+	0x00014b26,
+	0x00028d29,
+	0x000393ad,
+	0x00049630,
+	0x0005d833,
+	0x0006da36,
+	0x00099c3a,
+	0x000a9e3d,
+	0x000bc081,
+	0x000cc284,
+	0x000dc488,
+	0x000f068b,
+	0x0000488e,
+	0x00018b91,
+	0x0002d214,
+	0x0003d418,
+	0x0004d6a7,
+	0x000618aa,
+	0x00071aae,
+	0x0009dcb1,
+	0x000b1eb4,
+	0x000c0137,
+	0x000d033b,
+	0x000e053e,
+	0x000f4702,
+	0x00008905,
+	0x00020c09,
+	0x0003128c,
+	0x0004148f,
+	0x00051712,
+	0x00065916,
+	0x00091b19,
+	0x000a1d28,
+	0x000b5f2c,
+	0x000c41af,
+	0x000d43b2,
+	0x000e85b5,
+	0x000f87b8,
+	0x0000c9bc,
+	0x00024cbf,
+	0x00035303,
+	0x00045506,
+	0x0005978a,
+	0x0006998d,
+	0x00095b90,
+	0x000a5d93,
+	0x000b9f97,
+	0x000c821a,
+	0x000d8400,
+	0x000ec600,
+	0x000fc800,
+	0x00010a00,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+static const u32 tdi_tbl40_ant0_rev3[] = {
+	0x0011a346,
+	0x00136ccf,
+	0x0014f5d9,
+	0x001641e2,
+	0x0017cb6b,
+	0x00195475,
+	0x001b2383,
+	0x001cad0c,
+	0x001e7616,
+	0x0000821f,
+	0x00020ba8,
+	0x0003d4b2,
+	0x00056447,
+	0x00072dd0,
+	0x0008b6da,
+	0x000a02e3,
+	0x000b8c6c,
+	0x000d15f6,
+	0x0011e484,
+	0x0013ae0d,
+	0x00153717,
+	0x00168320,
+	0x00180ca9,
+	0x00199633,
+	0x001b6548,
+	0x001ceed1,
+	0x001eb7db,
+	0x0000c3e4,
+	0x00024d6d,
+	0x000416f7,
+	0x0005a585,
+	0x00076f0f,
+	0x0008f818,
+	0x000a4421,
+	0x000bcdab,
+	0x000d9734,
+	0x00122649,
+	0x0013efd2,
+	0x001578dc,
+	0x0016c4e5,
+	0x00184e6e,
+	0x001a17f8,
+	0x001ba686,
+	0x001d3010,
+	0x001ef999,
+	0x00010522,
+	0x00028eac,
+	0x00045835,
+	0x0005e74a,
+	0x0007b0d3,
+	0x00093a5d,
+	0x000a85e6,
+	0x000c0f6f,
+	0x000dd8f9,
+	0x00126787,
+	0x00143111,
+	0x0015ba9a,
+	0x00170623,
+	0x00188fad,
+	0x001a5936,
+	0x001be84b,
+	0x001db1d4,
+	0x001f3b5e,
+	0x000146e7,
+	0x00031070,
+	0x000499fa,
+	0x00062888,
+	0x0007f212,
+	0x00097b9b,
+	0x000ac7a4,
+	0x000c50ae,
+	0x000e1a37,
+	0x0012a94c,
+	0x001472d5,
+	0x0015fc5f,
+	0x00174868,
+	0x0018d171,
+	0x001a9afb,
+	0x001c2989,
+	0x001df313,
+	0x001f7c9c,
+	0x000188a5,
+	0x000351af,
+	0x0004db38,
+	0x0006aa4d,
+	0x000833d7,
+	0x0009bd60,
+	0x000b0969,
+	0x000c9273,
+	0x000e5bfc,
+	0x00132a8a,
+	0x0014b414,
+	0x00163d9d,
+	0x001789a6,
+	0x001912b0,
+	0x001adc39,
+	0x001c6bce,
+	0x001e34d8,
+	0x001fbe61,
+	0x0001ca6a,
+	0x00039374,
+	0x00051cfd,
+	0x0006ec0b,
+	0x00087515,
+	0x0009fe9e,
+	0x000b4aa7,
+	0x000cd3b1,
+	0x000e9d3a,
+	0x00000000,
+	0x00000000,
+};
+
+static const u32 tdi_tbl40_ant1_rev3[] = {
+	0x001edb36,
+	0x000129ca,
+	0x0002b353,
+	0x00047cdd,
+	0x0005c8e6,
+	0x000791ef,
+	0x00091bf9,
+	0x000aaa07,
+	0x000c3391,
+	0x000dfd1a,
+	0x00120923,
+	0x0013d22d,
+	0x00155c37,
+	0x0016eacb,
+	0x00187454,
+	0x001a3dde,
+	0x001b89e7,
+	0x001d12f0,
+	0x001f1cfa,
+	0x00016b88,
+	0x00033492,
+	0x0004be1b,
+	0x00060a24,
+	0x0007d32e,
+	0x00095d38,
+	0x000aec4c,
+	0x000c7555,
+	0x000e3edf,
+	0x00124ae8,
+	0x001413f1,
+	0x0015a37b,
+	0x00172c89,
+	0x0018b593,
+	0x001a419c,
+	0x001bcb25,
+	0x001d942f,
+	0x001f63b9,
+	0x0001ad4d,
+	0x00037657,
+	0x0004c260,
+	0x00068be9,
+	0x000814f3,
+	0x0009a47c,
+	0x000b2d8a,
+	0x000cb694,
+	0x000e429d,
+	0x00128c26,
+	0x001455b0,
+	0x0015e4ba,
+	0x00176e4e,
+	0x0018f758,
+	0x001a8361,
+	0x001c0cea,
+	0x001dd674,
+	0x001fa57d,
+	0x0001ee8b,
+	0x0003b795,
+	0x0005039e,
+	0x0006cd27,
+	0x000856b1,
+	0x0009e5c6,
+	0x000b6f4f,
+	0x000cf859,
+	0x000e8462,
+	0x00130deb,
+	0x00149775,
+	0x00162603,
+	0x0017af8c,
+	0x00193896,
+	0x001ac49f,
+	0x001c4e28,
+	0x001e17b2,
+	0x0000a6c7,
+	0x00023050,
+	0x0003f9da,
+	0x00054563,
+	0x00070eec,
+	0x00089876,
+	0x000a2704,
+	0x000bb08d,
+	0x000d3a17,
+	0x001185a0,
+	0x00134f29,
+	0x0014d8b3,
+	0x001667c8,
+	0x0017f151,
+	0x00197adb,
+	0x001b0664,
+	0x001c8fed,
+	0x001e5977,
+	0x0000e805,
+	0x0002718f,
+	0x00043b18,
+	0x000586a1,
+	0x0007502b,
+	0x0008d9b4,
+	0x000a68c9,
+	0x000bf252,
+	0x000dbbdc,
+	0x0011c7e5,
+	0x001390ee,
+	0x00151a78,
+	0x0016a906,
+	0x00183290,
+	0x0019bc19,
+	0x001b4822,
+	0x001cd12c,
+	0x001e9ab5,
+	0x00000000,
+	0x00000000,
+};
+
+static const u32 pltlut_tbl_rev3[] = {
+	0x76540213,
+	0x62407351,
+	0x76543210,
+	0x76540213,
+	0x76540213,
+	0x76430521,
+};
+
+static const u32 chanest_tbl_rev3[] = {
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+};
+
+static const u8 frame_lut_rev3[] = {
+	0x02,
+	0x04,
+	0x14,
+	0x14,
+	0x03,
+	0x05,
+	0x16,
+	0x16,
+	0x0a,
+	0x0c,
+	0x1c,
+	0x1c,
+	0x0b,
+	0x0d,
+	0x1e,
+	0x1e,
+	0x06,
+	0x08,
+	0x18,
+	0x18,
+	0x07,
+	0x09,
+	0x1a,
+	0x1a,
+	0x0e,
+	0x10,
+	0x20,
+	0x28,
+	0x0f,
+	0x11,
+	0x22,
+	0x2a,
+};
+
+static const u8 est_pwr_lut_core0_rev3[] = {
+	0x55,
+	0x54,
+	0x54,
+	0x53,
+	0x52,
+	0x52,
+	0x51,
+	0x51,
+	0x50,
+	0x4f,
+	0x4f,
+	0x4e,
+	0x4e,
+	0x4d,
+	0x4c,
+	0x4c,
+	0x4b,
+	0x4a,
+	0x49,
+	0x49,
+	0x48,
+	0x47,
+	0x46,
+	0x46,
+	0x45,
+	0x44,
+	0x43,
+	0x42,
+	0x41,
+	0x40,
+	0x40,
+	0x3f,
+	0x3e,
+	0x3d,
+	0x3c,
+	0x3a,
+	0x39,
+	0x38,
+	0x37,
+	0x36,
+	0x35,
+	0x33,
+	0x32,
+	0x31,
+	0x2f,
+	0x2e,
+	0x2c,
+	0x2b,
+	0x29,
+	0x27,
+	0x25,
+	0x23,
+	0x21,
+	0x1f,
+	0x1d,
+	0x1a,
+	0x18,
+	0x15,
+	0x12,
+	0x0e,
+	0x0b,
+	0x07,
+	0x02,
+	0xfd,
+};
+
+static const u8 est_pwr_lut_core1_rev3[] = {
+	0x55,
+	0x54,
+	0x54,
+	0x53,
+	0x52,
+	0x52,
+	0x51,
+	0x51,
+	0x50,
+	0x4f,
+	0x4f,
+	0x4e,
+	0x4e,
+	0x4d,
+	0x4c,
+	0x4c,
+	0x4b,
+	0x4a,
+	0x49,
+	0x49,
+	0x48,
+	0x47,
+	0x46,
+	0x46,
+	0x45,
+	0x44,
+	0x43,
+	0x42,
+	0x41,
+	0x40,
+	0x40,
+	0x3f,
+	0x3e,
+	0x3d,
+	0x3c,
+	0x3a,
+	0x39,
+	0x38,
+	0x37,
+	0x36,
+	0x35,
+	0x33,
+	0x32,
+	0x31,
+	0x2f,
+	0x2e,
+	0x2c,
+	0x2b,
+	0x29,
+	0x27,
+	0x25,
+	0x23,
+	0x21,
+	0x1f,
+	0x1d,
+	0x1a,
+	0x18,
+	0x15,
+	0x12,
+	0x0e,
+	0x0b,
+	0x07,
+	0x02,
+	0xfd,
+};
+
+static const u8 adj_pwr_lut_core0_rev3[] = {
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+};
+
+static const u8 adj_pwr_lut_core1_rev3[] = {
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+};
+
+static const u32 gainctrl_lut_core0_rev3[] = {
+	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 gainctrl_lut_core1_rev3[] = {
+	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 iq_lut_core0_rev3[] = {
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	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 iq_lut_core1_rev3[] = {
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	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 loft_lut_core0_rev3[] = {
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	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 loft_lut_core1_rev3[] = {
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	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 papd_comp_rfpwr_tbl_core0_rev3[] = {
+	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 papd_comp_rfpwr_tbl_core1_rev3[] = {
+	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 papd_comp_epsilon_tbl_core0_rev3[] = {
+	0x00000000,
+	0x00001fa0,
+	0x00019f78,
+	0x0001df7e,
+	0x03fa9f86,
+	0x03fd1f90,
+	0x03fe5f8a,
+	0x03fb1f94,
+	0x03fd9fa0,
+	0x00009f98,
+	0x03fd1fac,
+	0x03ff9fa2,
+	0x03fe9fae,
+	0x00001fae,
+	0x03fddfb4,
+	0x03ff1fb8,
+	0x03ff9fbc,
+	0x03ffdfbe,
+	0x03fe9fc2,
+	0x03fedfc6,
+	0x03fedfc6,
+	0x03ff9fc8,
+	0x03ff5fc6,
+	0x03fedfc2,
+	0x03ff9fc0,
+	0x03ff5fac,
+	0x03ff5fac,
+	0x03ff9fa2,
+	0x03ff9fa6,
+	0x03ff9faa,
+	0x03ff5fb0,
+	0x03ff5fb4,
+	0x03ff1fca,
+	0x03ff5fce,
+	0x03fcdfdc,
+	0x03fb4006,
+	0x00000030,
+	0x03ff808a,
+	0x03ff80da,
+	0x0000016c,
+	0x03ff8318,
+	0x03ff063a,
+	0x03fd8bd6,
+	0x00014ffe,
+	0x00034ffe,
+	0x00034ffe,
+	0x0003cffe,
+	0x00040ffe,
+	0x00040ffe,
+	0x0003cffe,
+	0x0003cffe,
+	0x00020ffe,
+	0x03fe0ffe,
+	0x03fdcffe,
+	0x03f94ffe,
+	0x03f54ffe,
+	0x03f44ffe,
+	0x03ef8ffe,
+	0x03ee0ffe,
+	0x03ebcffe,
+	0x03e8cffe,
+	0x03e74ffe,
+	0x03e4cffe,
+	0x03e38ffe,
+};
+
+static const u32 papd_cal_scalars_tbl_core0_rev3[] = {
+	0x05af005a,
+	0x0571005e,
+	0x05040066,
+	0x04bd006c,
+	0x047d0072,
+	0x04430078,
+	0x03f70081,
+	0x03cb0087,
+	0x03870091,
+	0x035e0098,
+	0x032e00a1,
+	0x030300aa,
+	0x02d800b4,
+	0x02ae00bf,
+	0x028900ca,
+	0x026400d6,
+	0x024100e3,
+	0x022200f0,
+	0x020200ff,
+	0x01e5010e,
+	0x01ca011e,
+	0x01b0012f,
+	0x01990140,
+	0x01830153,
+	0x016c0168,
+	0x0158017d,
+	0x01450193,
+	0x013301ab,
+	0x012101c5,
+	0x011101e0,
+	0x010201fc,
+	0x00f4021a,
+	0x00e6011d,
+	0x00d9012e,
+	0x00cd0140,
+	0x00c20153,
+	0x00b70167,
+	0x00ac017c,
+	0x00a30193,
+	0x009a01ab,
+	0x009101c4,
+	0x008901df,
+	0x008101fb,
+	0x007a0219,
+	0x00730239,
+	0x006d025b,
+	0x0067027e,
+	0x006102a4,
+	0x005c02cc,
+	0x005602f6,
+	0x00520323,
+	0x004d0353,
+	0x00490385,
+	0x004503bb,
+	0x004103f3,
+	0x003d042f,
+	0x003a046f,
+	0x003704b2,
+	0x003404f9,
+	0x00310545,
+	0x002e0596,
+	0x002b05f5,
+	0x00290640,
+	0x002606a4,
+};
+
+static const u32 papd_comp_epsilon_tbl_core1_rev3[] = {
+	0x00000000,
+	0x00001fa0,
+	0x00019f78,
+	0x0001df7e,
+	0x03fa9f86,
+	0x03fd1f90,
+	0x03fe5f8a,
+	0x03fb1f94,
+	0x03fd9fa0,
+	0x00009f98,
+	0x03fd1fac,
+	0x03ff9fa2,
+	0x03fe9fae,
+	0x00001fae,
+	0x03fddfb4,
+	0x03ff1fb8,
+	0x03ff9fbc,
+	0x03ffdfbe,
+	0x03fe9fc2,
+	0x03fedfc6,
+	0x03fedfc6,
+	0x03ff9fc8,
+	0x03ff5fc6,
+	0x03fedfc2,
+	0x03ff9fc0,
+	0x03ff5fac,
+	0x03ff5fac,
+	0x03ff9fa2,
+	0x03ff9fa6,
+	0x03ff9faa,
+	0x03ff5fb0,
+	0x03ff5fb4,
+	0x03ff1fca,
+	0x03ff5fce,
+	0x03fcdfdc,
+	0x03fb4006,
+	0x00000030,
+	0x03ff808a,
+	0x03ff80da,
+	0x0000016c,
+	0x03ff8318,
+	0x03ff063a,
+	0x03fd8bd6,
+	0x00014ffe,
+	0x00034ffe,
+	0x00034ffe,
+	0x0003cffe,
+	0x00040ffe,
+	0x00040ffe,
+	0x0003cffe,
+	0x0003cffe,
+	0x00020ffe,
+	0x03fe0ffe,
+	0x03fdcffe,
+	0x03f94ffe,
+	0x03f54ffe,
+	0x03f44ffe,
+	0x03ef8ffe,
+	0x03ee0ffe,
+	0x03ebcffe,
+	0x03e8cffe,
+	0x03e74ffe,
+	0x03e4cffe,
+	0x03e38ffe,
+};
+
+static const u32 papd_cal_scalars_tbl_core1_rev3[] = {
+	0x05af005a,
+	0x0571005e,
+	0x05040066,
+	0x04bd006c,
+	0x047d0072,
+	0x04430078,
+	0x03f70081,
+	0x03cb0087,
+	0x03870091,
+	0x035e0098,
+	0x032e00a1,
+	0x030300aa,
+	0x02d800b4,
+	0x02ae00bf,
+	0x028900ca,
+	0x026400d6,
+	0x024100e3,
+	0x022200f0,
+	0x020200ff,
+	0x01e5010e,
+	0x01ca011e,
+	0x01b0012f,
+	0x01990140,
+	0x01830153,
+	0x016c0168,
+	0x0158017d,
+	0x01450193,
+	0x013301ab,
+	0x012101c5,
+	0x011101e0,
+	0x010201fc,
+	0x00f4021a,
+	0x00e6011d,
+	0x00d9012e,
+	0x00cd0140,
+	0x00c20153,
+	0x00b70167,
+	0x00ac017c,
+	0x00a30193,
+	0x009a01ab,
+	0x009101c4,
+	0x008901df,
+	0x008101fb,
+	0x007a0219,
+	0x00730239,
+	0x006d025b,
+	0x0067027e,
+	0x006102a4,
+	0x005c02cc,
+	0x005602f6,
+	0x00520323,
+	0x004d0353,
+	0x00490385,
+	0x004503bb,
+	0x004103f3,
+	0x003d042f,
+	0x003a046f,
+	0x003704b2,
+	0x003404f9,
+	0x00310545,
+	0x002e0596,
+	0x002b05f5,
+	0x00290640,
+	0x002606a4,
+};
+
+const struct phytbl_info mimophytbl_info_rev3_volatile[] = {
+	{&ant_swctrl_tbl_rev3, ARRAY_SIZE(ant_swctrl_tbl_rev3), 9, 0, 16},
+};
+
+const struct phytbl_info mimophytbl_info_rev3_volatile1[] = {
+	{&ant_swctrl_tbl_rev3_1, ARRAY_SIZE(ant_swctrl_tbl_rev3_1), 9, 0, 16},
+};
+
+const struct phytbl_info mimophytbl_info_rev3_volatile2[] = {
+	{&ant_swctrl_tbl_rev3_2, ARRAY_SIZE(ant_swctrl_tbl_rev3_2), 9, 0, 16},
+};
+
+const struct phytbl_info mimophytbl_info_rev3_volatile3[] = {
+	{&ant_swctrl_tbl_rev3_3, ARRAY_SIZE(ant_swctrl_tbl_rev3_3), 9, 0, 16},
+};
+
+const struct phytbl_info mimophytbl_info_rev3[] = {
+	{&frame_struct_rev3, ARRAY_SIZE(frame_struct_rev3), 10, 0, 32},
+	{&pilot_tbl_rev3, ARRAY_SIZE(pilot_tbl_rev3), 11, 0, 16},
+	{&tmap_tbl_rev3, ARRAY_SIZE(tmap_tbl_rev3), 12, 0, 32},
+	{&intlv_tbl_rev3, ARRAY_SIZE(intlv_tbl_rev3), 13, 0, 32},
+	{&tdtrn_tbl_rev3, ARRAY_SIZE(tdtrn_tbl_rev3), 14, 0, 32},
+	{&noise_var_tbl_rev3, ARRAY_SIZE(noise_var_tbl_rev3), 16, 0, 32},
+	{&mcs_tbl_rev3, ARRAY_SIZE(mcs_tbl_rev3), 18, 0, 16},
+	{&tdi_tbl20_ant0_rev3, ARRAY_SIZE(tdi_tbl20_ant0_rev3), 19, 128, 32},
+	{&tdi_tbl20_ant1_rev3, ARRAY_SIZE(tdi_tbl20_ant1_rev3), 19, 256, 32},
+	{&tdi_tbl40_ant0_rev3, ARRAY_SIZE(tdi_tbl40_ant0_rev3), 19, 640, 32},
+	{&tdi_tbl40_ant1_rev3, ARRAY_SIZE(tdi_tbl40_ant1_rev3), 19, 768, 32},
+	{&pltlut_tbl_rev3, ARRAY_SIZE(pltlut_tbl_rev3), 20, 0, 32},
+	{&chanest_tbl_rev3, ARRAY_SIZE(chanest_tbl_rev3), 22, 0, 32},
+	{&frame_lut_rev3, ARRAY_SIZE(frame_lut_rev3), 24, 0, 8},
+	{&est_pwr_lut_core0_rev3, ARRAY_SIZE(est_pwr_lut_core0_rev3), 26, 0, 8},
+	{&est_pwr_lut_core1_rev3, ARRAY_SIZE(est_pwr_lut_core1_rev3), 27, 0, 8},
+	{&adj_pwr_lut_core0_rev3, ARRAY_SIZE(adj_pwr_lut_core0_rev3), 26, 64, 8},
+	{&adj_pwr_lut_core1_rev3, ARRAY_SIZE(adj_pwr_lut_core1_rev3), 27, 64, 8},
+	{&gainctrl_lut_core0_rev3, ARRAY_SIZE(gainctrl_lut_core0_rev3), 26, 192, 32},
+	{&gainctrl_lut_core1_rev3, ARRAY_SIZE(gainctrl_lut_core1_rev3), 27, 192, 32},
+	{&iq_lut_core0_rev3, ARRAY_SIZE(iq_lut_core0_rev3), 26, 320, 32},
+	{&iq_lut_core1_rev3, ARRAY_SIZE(iq_lut_core1_rev3), 27, 320, 32},
+	{&loft_lut_core0_rev3, ARRAY_SIZE(loft_lut_core0_rev3), 26, 448, 16},
+	{&loft_lut_core1_rev3, ARRAY_SIZE(loft_lut_core1_rev3), 27, 448, 16}
+};
+
+const u32 mimophytbl_info_sz_rev3 = ARRAY_SIZE(mimophytbl_info_rev3);
+const u32 mimophytbl_info_sz_rev3_volatile = ARRAY_SIZE(mimophytbl_info_rev3_volatile);
+const u32 mimophytbl_info_sz_rev3_volatile1 = ARRAY_SIZE(mimophytbl_info_rev3_volatile1);
+const u32 mimophytbl_info_sz_rev3_volatile2 = ARRAY_SIZE(mimophytbl_info_rev3_volatile2);
+const u32 mimophytbl_info_sz_rev3_volatile3 = ARRAY_SIZE(mimophytbl_info_rev3_volatile3);
+
+static const u32 tmap_tbl_rev7[] = {
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00000111,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x000aa888,
+	0x88880000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa2222220,
+	0x22222222,
+	0x22c22222,
+	0x00000222,
+	0x22000000,
+	0x2222a222,
+	0x22222222,
+	0x222222a2,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00011111,
+	0x11110000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0xa8aa88a0,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x00088aaa,
+	0xaaaa0000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xaaa8aaa0,
+	0x8aaa8aaa,
+	0xaa8a8a8a,
+	0x000aaa88,
+	0x8aaa0000,
+	0xaaa8a888,
+	0x8aa88a8a,
+	0x8a88a888,
+	0x08080a00,
+	0x0a08080a,
+	0x080a0a08,
+	0x00080808,
+	0x080a0000,
+	0x080a0808,
+	0x080a0808,
+	0x0a0a0a08,
+	0xa0a0a0a0,
+	0x80a0a080,
+	0x8080a0a0,
+	0x00008080,
+	0x80a00000,
+	0x80a080a0,
+	0xa080a0a0,
+	0x8080a0a0,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x99999000,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb90,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00aaa888,
+	0x22000000,
+	0x2222b222,
+	0x22222222,
+	0x222222b2,
+	0xb2222220,
+	0x22222222,
+	0x22d22222,
+	0x00000222,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x33000000,
+	0x3333b333,
+	0x33333333,
+	0x333333b3,
+	0xb3333330,
+	0x33333333,
+	0x33d33333,
+	0x00000333,
+	0x22000000,
+	0x2222a222,
+	0x22222222,
+	0x222222a2,
+	0xa2222220,
+	0x22222222,
+	0x22c22222,
+	0x00000222,
+	0x99b99b00,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb99,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x08aaa888,
+	0x22222200,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0x22222222,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x11111111,
+	0xf1111111,
+	0x11111111,
+	0x11f11111,
+	0x01111111,
+	0xbb9bb900,
+	0xb9b9bb99,
+	0xb99bbbbb,
+	0xbbbb9b9b,
+	0xb9bb99bb,
+	0xb99999b9,
+	0xb9b9b99b,
+	0x00000bbb,
+	0xaa000000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xa8aa88aa,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x0a888aaa,
+	0xaa000000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xa8aa88a0,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x00000aaa,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0xbbbbbb00,
+	0x999bbbbb,
+	0x9bb99b9b,
+	0xb9b9b9bb,
+	0xb9b99bbb,
+	0xb9b9b9bb,
+	0xb9bb9b99,
+	0x00000999,
+	0x8a000000,
+	0xaa88a888,
+	0xa88888aa,
+	0xa88a8a88,
+	0xa88aa88a,
+	0x88a8aaaa,
+	0xa8aa8aaa,
+	0x0888a88a,
+	0x0b0b0b00,
+	0x090b0b0b,
+	0x0b090b0b,
+	0x0909090b,
+	0x09090b0b,
+	0x09090b0b,
+	0x09090b09,
+	0x00000909,
+	0x0a000000,
+	0x0a080808,
+	0x080a080a,
+	0x080a0a08,
+	0x080a080a,
+	0x0808080a,
+	0x0a0a0a08,
+	0x0808080a,
+	0xb0b0b000,
+	0x9090b0b0,
+	0x90b09090,
+	0xb0b0b090,
+	0xb0b090b0,
+	0x90b0b0b0,
+	0xb0b09090,
+	0x00000090,
+	0x80000000,
+	0xa080a080,
+	0xa08080a0,
+	0xa0808080,
+	0xa080a080,
+	0x80a0a0a0,
+	0xa0a080a0,
+	0x00a0a0a0,
+	0x22000000,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0xf2222220,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00000111,
+	0x33000000,
+	0x3333f333,
+	0x33333333,
+	0x333333f3,
+	0xf3333330,
+	0x33333333,
+	0x33f33333,
+	0x00000333,
+	0x22000000,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0xf2222220,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x99000000,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb90,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88888000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00aaa888,
+	0x88a88a00,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x000aa888,
+	0x88880000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x08aaa888,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 noise_var_tbl_rev7[] = {
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+};
+
+static const u32 papd_comp_epsilon_tbl_core0_rev7[] = {
+	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 papd_cal_scalars_tbl_core0_rev7[] = {
+	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 papd_comp_epsilon_tbl_core1_rev7[] = {
+	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 papd_cal_scalars_tbl_core1_rev7[] = {
+	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,
+};
+
+const struct phytbl_info mimophytbl_info_rev7[] = {
+	{&frame_struct_rev3, ARRAY_SIZE(frame_struct_rev3), 10, 0, 32},
+	{&pilot_tbl_rev3, ARRAY_SIZE(pilot_tbl_rev3), 11, 0, 16},
+	{&tmap_tbl_rev7, ARRAY_SIZE(tmap_tbl_rev7), 12, 0, 32},
+	{&intlv_tbl_rev3, ARRAY_SIZE(intlv_tbl_rev3), 13, 0, 32},
+	{&tdtrn_tbl_rev3, ARRAY_SIZE(tdtrn_tbl_rev3), 14, 0, 32},
+	{&noise_var_tbl_rev7, ARRAY_SIZE(noise_var_tbl_rev7), 16, 0, 32},
+	{&mcs_tbl_rev3, ARRAY_SIZE(mcs_tbl_rev3), 18, 0, 16},
+	{&tdi_tbl20_ant0_rev3, ARRAY_SIZE(tdi_tbl20_ant0_rev3), 19, 128, 32},
+	{&tdi_tbl20_ant1_rev3, ARRAY_SIZE(tdi_tbl20_ant1_rev3), 19, 256, 32},
+	{&tdi_tbl40_ant0_rev3, ARRAY_SIZE(tdi_tbl40_ant0_rev3), 19, 640, 32},
+	{&tdi_tbl40_ant1_rev3, ARRAY_SIZE(tdi_tbl40_ant1_rev3), 19, 768, 32},
+	{&pltlut_tbl_rev3, ARRAY_SIZE(pltlut_tbl_rev3), 20, 0, 32},
+	{&chanest_tbl_rev3, ARRAY_SIZE(chanest_tbl_rev3), 22, 0, 32},
+	{&frame_lut_rev3, ARRAY_SIZE(frame_lut_rev3), 24, 0, 8},
+	{&est_pwr_lut_core0_rev3, ARRAY_SIZE(est_pwr_lut_core0_rev3), 26, 0, 8},
+	{&est_pwr_lut_core1_rev3, ARRAY_SIZE(est_pwr_lut_core1_rev3), 27, 0, 8},
+	{&adj_pwr_lut_core0_rev3, ARRAY_SIZE(adj_pwr_lut_core0_rev3), 26, 64, 8},
+	{&adj_pwr_lut_core1_rev3, ARRAY_SIZE(adj_pwr_lut_core1_rev3), 27, 64, 8},
+	{&gainctrl_lut_core0_rev3, ARRAY_SIZE(gainctrl_lut_core0_rev3), 26, 192, 32},
+	{&gainctrl_lut_core1_rev3, ARRAY_SIZE(gainctrl_lut_core1_rev3), 27, 192, 32},
+	{&iq_lut_core0_rev3, ARRAY_SIZE(iq_lut_core0_rev3), 26, 320, 32},
+	{&iq_lut_core1_rev3, ARRAY_SIZE(iq_lut_core1_rev3), 27, 320, 32},
+	{&loft_lut_core0_rev3, ARRAY_SIZE(loft_lut_core0_rev3), 26, 448, 16},
+	{&loft_lut_core1_rev3, ARRAY_SIZE(loft_lut_core1_rev3), 27, 448, 16},
+	{&papd_comp_rfpwr_tbl_core0_rev3,
+	 ARRAY_SIZE(papd_comp_rfpwr_tbl_core0_rev3), 26, 576, 16},
+	{&papd_comp_rfpwr_tbl_core1_rev3,
+	 ARRAY_SIZE(papd_comp_rfpwr_tbl_core1_rev3), 27, 576, 16},
+	{&papd_comp_epsilon_tbl_core0_rev7,
+	 ARRAY_SIZE(papd_comp_epsilon_tbl_core0_rev7), 31, 0, 32},
+	{&papd_cal_scalars_tbl_core0_rev7,
+	 ARRAY_SIZE(papd_cal_scalars_tbl_core0_rev7), 32, 0, 32},
+	{&papd_comp_epsilon_tbl_core1_rev7,
+	 ARRAY_SIZE(papd_comp_epsilon_tbl_core1_rev7), 33, 0, 32},
+	{&papd_cal_scalars_tbl_core1_rev7,
+	 ARRAY_SIZE(papd_cal_scalars_tbl_core1_rev7), 34, 0, 32},
+};
+
+const u32 mimophytbl_info_sz_rev7 = ARRAY_SIZE(mimophytbl_info_rev7);
+
+const struct phytbl_info mimophytbl_info_rev16[] = {
+	{&noise_var_tbl_rev7, ARRAY_SIZE(noise_var_tbl_rev7), 16, 0, 32},
+	{&est_pwr_lut_core0_rev3, ARRAY_SIZE(est_pwr_lut_core0_rev3), 26, 0, 8},
+	{&est_pwr_lut_core1_rev3, ARRAY_SIZE(est_pwr_lut_core1_rev3), 27, 0, 8},
+	{&adj_pwr_lut_core0_rev3, ARRAY_SIZE(adj_pwr_lut_core0_rev3), 26, 64, 8},
+	{&adj_pwr_lut_core1_rev3, ARRAY_SIZE(adj_pwr_lut_core1_rev3), 27, 64, 8},
+	{&gainctrl_lut_core0_rev3, ARRAY_SIZE(gainctrl_lut_core0_rev3), 26, 192, 32},
+	{&gainctrl_lut_core1_rev3, ARRAY_SIZE(gainctrl_lut_core1_rev3), 27, 192, 32},
+	{&iq_lut_core0_rev3, ARRAY_SIZE(iq_lut_core0_rev3), 26, 320, 32},
+	{&iq_lut_core1_rev3, ARRAY_SIZE(iq_lut_core1_rev3), 27, 320, 32},
+	{&loft_lut_core0_rev3, ARRAY_SIZE(loft_lut_core0_rev3), 26, 448, 16},
+	{&loft_lut_core1_rev3, ARRAY_SIZE(loft_lut_core1_rev3), 27, 448, 16},
+};
+
+const u32 mimophytbl_info_sz_rev16 = ARRAY_SIZE(mimophytbl_info_rev16);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phytbl_n.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phytbl_n.h
new file mode 100644
index 0000000..dc8a84e
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phytbl_n.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define ANT_SWCTRL_TBL_REV3_IDX (0)
+
+#include <types.h>
+#include "phy_int.h"
+
+extern const struct phytbl_info mimophytbl_info_rev0[],
+				mimophytbl_info_rev0_volatile[];
+
+extern const u32 mimophytbl_info_sz_rev0,
+		 mimophytbl_info_sz_rev0_volatile;
+
+extern const struct phytbl_info mimophytbl_info_rev3[],
+				mimophytbl_info_rev3_volatile[],
+				mimophytbl_info_rev3_volatile1[],
+				mimophytbl_info_rev3_volatile2[],
+				mimophytbl_info_rev3_volatile3[];
+
+extern const u32 mimophytbl_info_sz_rev3,
+		 mimophytbl_info_sz_rev3_volatile,
+		 mimophytbl_info_sz_rev3_volatile1,
+		 mimophytbl_info_sz_rev3_volatile2,
+		 mimophytbl_info_sz_rev3_volatile3;
+
+extern const u32 noise_var_tbl_rev3[];
+
+extern const struct phytbl_info mimophytbl_info_rev7[];
+
+extern const u32 mimophytbl_info_sz_rev7;
+
+extern const u32 noise_var_tbl_rev7[];
+
+extern const struct phytbl_info mimophytbl_info_rev16[];
+
+extern const u32 mimophytbl_info_sz_rev16;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy_shim.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy_shim.c
new file mode 100644
index 0000000..a0de5db
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy_shim.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is "two-way" interface, acting as the SHIM layer between driver
+ * and PHY layer. The driver can optionally call this translation layer
+ * to do some preprocessing, then reach PHY. On the PHY->driver direction,
+ * all calls go through this layer since PHY doesn't have access to the
+ * driver's brcms_hardware pointer.
+ */
+#include <linux/slab.h>
+#include <net/mac80211.h>
+
+#include "main.h"
+#include "mac80211_if.h"
+#include "phy_shim.h"
+
+/* PHY SHIM module specific state */
+struct phy_shim_info {
+	struct brcms_hardware *wlc_hw;	/* pointer to main wlc_hw structure */
+	struct brcms_c_info *wlc;	/* pointer to main wlc structure */
+	struct brcms_info *wl; /* pointer to os-specific private state */
+};
+
+struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw,
+					  struct brcms_info *wl,
+					  struct brcms_c_info *wlc) {
+	struct phy_shim_info *physhim = NULL;
+
+	physhim = kzalloc(sizeof(struct phy_shim_info), GFP_ATOMIC);
+	if (!physhim)
+		return NULL;
+
+	physhim->wlc_hw = wlc_hw;
+	physhim->wlc = wlc;
+	physhim->wl = wl;
+
+	return physhim;
+}
+
+void wlc_phy_shim_detach(struct phy_shim_info *physhim)
+{
+	kfree(physhim);
+}
+
+struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim,
+				     void (*fn)(struct brcms_phy *pi),
+				     void *arg, const char *name)
+{
+	return (struct wlapi_timer *)
+			brcms_init_timer(physhim->wl, (void (*)(void *))fn,
+					 arg, name);
+}
+
+void wlapi_free_timer(struct wlapi_timer *t)
+{
+	brcms_free_timer((struct brcms_timer *)t);
+}
+
+void
+wlapi_add_timer(struct wlapi_timer *t, uint ms, int periodic)
+{
+	brcms_add_timer((struct brcms_timer *)t, ms, periodic);
+}
+
+bool wlapi_del_timer(struct wlapi_timer *t)
+{
+	return brcms_del_timer((struct brcms_timer *)t);
+}
+
+void wlapi_intrson(struct phy_shim_info *physhim)
+{
+	brcms_intrson(physhim->wl);
+}
+
+u32 wlapi_intrsoff(struct phy_shim_info *physhim)
+{
+	return brcms_intrsoff(physhim->wl);
+}
+
+void wlapi_intrsrestore(struct phy_shim_info *physhim, u32 macintmask)
+{
+	brcms_intrsrestore(physhim->wl, macintmask);
+}
+
+void wlapi_bmac_write_shm(struct phy_shim_info *physhim, uint offset, u16 v)
+{
+	brcms_b_write_shm(physhim->wlc_hw, offset, v);
+}
+
+u16 wlapi_bmac_read_shm(struct phy_shim_info *physhim, uint offset)
+{
+	return brcms_b_read_shm(physhim->wlc_hw, offset);
+}
+
+void
+wlapi_bmac_mhf(struct phy_shim_info *physhim, u8 idx, u16 mask,
+	       u16 val, int bands)
+{
+	brcms_b_mhf(physhim->wlc_hw, idx, mask, val, bands);
+}
+
+void wlapi_bmac_corereset(struct phy_shim_info *physhim, u32 flags)
+{
+	brcms_b_corereset(physhim->wlc_hw, flags);
+}
+
+void wlapi_suspend_mac_and_wait(struct phy_shim_info *physhim)
+{
+	brcms_c_suspend_mac_and_wait(physhim->wlc);
+}
+
+void wlapi_switch_macfreq(struct phy_shim_info *physhim, u8 spurmode)
+{
+	brcms_b_switch_macfreq(physhim->wlc_hw, spurmode);
+}
+
+void wlapi_enable_mac(struct phy_shim_info *physhim)
+{
+	brcms_c_enable_mac(physhim->wlc);
+}
+
+void wlapi_bmac_mctrl(struct phy_shim_info *physhim, u32 mask, u32 val)
+{
+	brcms_b_mctrl(physhim->wlc_hw, mask, val);
+}
+
+void wlapi_bmac_phy_reset(struct phy_shim_info *physhim)
+{
+	brcms_b_phy_reset(physhim->wlc_hw);
+}
+
+void wlapi_bmac_bw_set(struct phy_shim_info *physhim, u16 bw)
+{
+	brcms_b_bw_set(physhim->wlc_hw, bw);
+}
+
+u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim)
+{
+	return brcms_b_get_txant(physhim->wlc_hw);
+}
+
+void wlapi_bmac_phyclk_fgc(struct phy_shim_info *physhim, bool clk)
+{
+	brcms_b_phyclk_fgc(physhim->wlc_hw, clk);
+}
+
+void wlapi_bmac_macphyclk_set(struct phy_shim_info *physhim, bool clk)
+{
+	brcms_b_macphyclk_set(physhim->wlc_hw, clk);
+}
+
+void wlapi_bmac_core_phypll_ctl(struct phy_shim_info *physhim, bool on)
+{
+	brcms_b_core_phypll_ctl(physhim->wlc_hw, on);
+}
+
+void wlapi_bmac_core_phypll_reset(struct phy_shim_info *physhim)
+{
+	brcms_b_core_phypll_reset(physhim->wlc_hw);
+}
+
+void wlapi_bmac_ucode_wake_override_phyreg_set(struct phy_shim_info *physhim)
+{
+	brcms_c_ucode_wake_override_set(physhim->wlc_hw,
+					BRCMS_WAKE_OVERRIDE_PHYREG);
+}
+
+void wlapi_bmac_ucode_wake_override_phyreg_clear(struct phy_shim_info *physhim)
+{
+	brcms_c_ucode_wake_override_clear(physhim->wlc_hw,
+					  BRCMS_WAKE_OVERRIDE_PHYREG);
+}
+
+void
+wlapi_bmac_write_template_ram(struct phy_shim_info *physhim, int offset,
+			      int len, void *buf)
+{
+	brcms_b_write_template_ram(physhim->wlc_hw, offset, len, buf);
+}
+
+u16 wlapi_bmac_rate_shm_offset(struct phy_shim_info *physhim, u8 rate)
+{
+	return brcms_b_rate_shm_offset(physhim->wlc_hw, rate);
+}
+
+void wlapi_ucode_sample_init(struct phy_shim_info *physhim)
+{
+}
+
+void
+wlapi_copyfrom_objmem(struct phy_shim_info *physhim, uint offset, void *buf,
+		      int len, u32 sel)
+{
+	brcms_b_copyfrom_objmem(physhim->wlc_hw, offset, buf, len, sel);
+}
+
+void
+wlapi_copyto_objmem(struct phy_shim_info *physhim, uint offset, const void *buf,
+		    int l, u32 sel)
+{
+	brcms_b_copyto_objmem(physhim->wlc_hw, offset, buf, l, sel);
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy_shim.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy_shim.h
new file mode 100644
index 0000000..dd87747
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy_shim.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * phy_shim.h: stuff defined in phy_shim.c and included only by the phy
+ */
+
+#ifndef _BRCM_PHY_SHIM_H_
+#define _BRCM_PHY_SHIM_H_
+
+#include "types.h"
+
+#define RADAR_TYPE_NONE		0	/* Radar type None */
+#define RADAR_TYPE_ETSI_1	1	/* ETSI 1 Radar type */
+#define RADAR_TYPE_ETSI_2	2	/* ETSI 2 Radar type */
+#define RADAR_TYPE_ETSI_3	3	/* ETSI 3 Radar type */
+#define RADAR_TYPE_ITU_E	4	/* ITU E Radar type */
+#define RADAR_TYPE_ITU_K	5	/* ITU K Radar type */
+#define RADAR_TYPE_UNCLASSIFIED	6	/* Unclassified Radar type  */
+#define RADAR_TYPE_BIN5		7	/* long pulse radar type */
+#define RADAR_TYPE_STG2		8	/* staggered-2 radar */
+#define RADAR_TYPE_STG3		9	/* staggered-3 radar */
+#define RADAR_TYPE_FRA		10	/* French radar */
+
+/* French radar pulse widths */
+#define FRA_T1_20MHZ	52770
+#define FRA_T2_20MHZ	61538
+#define FRA_T3_20MHZ	66002
+#define FRA_T1_40MHZ	105541
+#define FRA_T2_40MHZ	123077
+#define FRA_T3_40MHZ	132004
+#define FRA_ERR_20MHZ	60
+#define FRA_ERR_40MHZ	120
+
+#define ANTSEL_NA		0 /* No boardlevel selection available */
+#define ANTSEL_2x4		1 /* 2x4 boardlevel selection available */
+#define ANTSEL_2x3		2 /* 2x3 CB2 boardlevel selection available */
+
+/* Rx Antenna diversity control values */
+#define	ANT_RX_DIV_FORCE_0	0	/* Use antenna 0 */
+#define	ANT_RX_DIV_FORCE_1	1	/* Use antenna 1 */
+#define	ANT_RX_DIV_START_1	2	/* Choose starting with 1 */
+#define	ANT_RX_DIV_START_0	3	/* Choose starting with 0 */
+#define	ANT_RX_DIV_ENABLE	3	/* APHY bbConfig Enable RX Diversity */
+#define ANT_RX_DIV_DEF		ANT_RX_DIV_START_0 /* default antdiv setting */
+
+#define WL_ANT_RX_MAX		2	/* max 2 receive antennas */
+#define WL_ANT_HT_RX_MAX	3	/* max 3 receive antennas/cores */
+#define WL_ANT_IDX_1		0	/* antenna index 1 */
+#define WL_ANT_IDX_2		1	/* antenna index 2 */
+
+/* values for n_preamble_type */
+#define BRCMS_N_PREAMBLE_MIXEDMODE	0
+#define BRCMS_N_PREAMBLE_GF		1
+#define BRCMS_N_PREAMBLE_GF_BRCM          2
+
+#define WL_TX_POWER_RATES_LEGACY	45
+#define WL_TX_POWER_MCS20_FIRST	        12
+#define WL_TX_POWER_MCS20_NUM	        16
+#define WL_TX_POWER_MCS40_FIRST	        28
+#define WL_TX_POWER_MCS40_NUM	        17
+
+
+#define WL_TX_POWER_RATES	       101
+#define WL_TX_POWER_CCK_FIRST	       0
+#define WL_TX_POWER_CCK_NUM	       4
+/* Index for first 20MHz OFDM SISO rate */
+#define WL_TX_POWER_OFDM_FIRST	       4
+/* Index for first 20MHz OFDM CDD rate */
+#define WL_TX_POWER_OFDM20_CDD_FIRST   12
+/* Index for first 40MHz OFDM SISO rate */
+#define WL_TX_POWER_OFDM40_SISO_FIRST  52
+/* Index for first 40MHz OFDM CDD rate */
+#define WL_TX_POWER_OFDM40_CDD_FIRST   60
+#define WL_TX_POWER_OFDM_NUM	       8
+/* Index for first 20MHz MCS SISO rate */
+#define WL_TX_POWER_MCS20_SISO_FIRST   20
+/* Index for first 20MHz MCS CDD rate */
+#define WL_TX_POWER_MCS20_CDD_FIRST    28
+/* Index for first 20MHz MCS STBC rate */
+#define WL_TX_POWER_MCS20_STBC_FIRST   36
+/* Index for first 20MHz MCS SDM rate */
+#define WL_TX_POWER_MCS20_SDM_FIRST    44
+/* Index for first 40MHz MCS SISO rate */
+#define WL_TX_POWER_MCS40_SISO_FIRST   68
+/* Index for first 40MHz MCS CDD rate */
+#define WL_TX_POWER_MCS40_CDD_FIRST    76
+/* Index for first 40MHz MCS STBC rate */
+#define WL_TX_POWER_MCS40_STBC_FIRST   84
+/* Index for first 40MHz MCS SDM rate */
+#define WL_TX_POWER_MCS40_SDM_FIRST    92
+#define WL_TX_POWER_MCS_1_STREAM_NUM   8
+#define WL_TX_POWER_MCS_2_STREAM_NUM   8
+/* Index for 40MHz rate MCS 32 */
+#define WL_TX_POWER_MCS_32	       100
+#define WL_TX_POWER_MCS_32_NUM	       1
+
+/* sslpnphy specifics */
+/* Index for first 20MHz MCS SISO rate */
+#define WL_TX_POWER_MCS20_SISO_FIRST_SSN   12
+
+/* struct tx_power::flags bits */
+#define WL_TX_POWER_F_ENABLED	1
+#define WL_TX_POWER_F_HW	2
+#define WL_TX_POWER_F_MIMO	4
+#define WL_TX_POWER_F_SISO	8
+
+/* values to force tx/rx chain */
+#define BRCMS_N_TXRX_CHAIN0		0
+#define BRCMS_N_TXRX_CHAIN1		1
+
+struct brcms_phy;
+
+struct phy_shim_info *wlc_phy_shim_attach(struct brcms_hardware *wlc_hw,
+					  struct brcms_info *wl,
+					  struct brcms_c_info *wlc);
+void wlc_phy_shim_detach(struct phy_shim_info *physhim);
+
+/* PHY to WL utility functions */
+struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim,
+				     void (*fn)(struct brcms_phy *pi),
+				     void *arg, const char *name);
+void wlapi_free_timer(struct wlapi_timer *t);
+void wlapi_add_timer(struct wlapi_timer *t, uint ms, int periodic);
+bool wlapi_del_timer(struct wlapi_timer *t);
+void wlapi_intrson(struct phy_shim_info *physhim);
+u32 wlapi_intrsoff(struct phy_shim_info *physhim);
+void wlapi_intrsrestore(struct phy_shim_info *physhim, u32 macintmask);
+
+void wlapi_bmac_write_shm(struct phy_shim_info *physhim, uint offset, u16 v);
+u16 wlapi_bmac_read_shm(struct phy_shim_info *physhim, uint offset);
+void wlapi_bmac_mhf(struct phy_shim_info *physhim, u8 idx, u16 mask, u16 val,
+		    int bands);
+void wlapi_bmac_corereset(struct phy_shim_info *physhim, u32 flags);
+void wlapi_suspend_mac_and_wait(struct phy_shim_info *physhim);
+void wlapi_switch_macfreq(struct phy_shim_info *physhim, u8 spurmode);
+void wlapi_enable_mac(struct phy_shim_info *physhim);
+void wlapi_bmac_mctrl(struct phy_shim_info *physhim, u32 mask, u32 val);
+void wlapi_bmac_phy_reset(struct phy_shim_info *physhim);
+void wlapi_bmac_bw_set(struct phy_shim_info *physhim, u16 bw);
+void wlapi_bmac_phyclk_fgc(struct phy_shim_info *physhim, bool clk);
+void wlapi_bmac_macphyclk_set(struct phy_shim_info *physhim, bool clk);
+void wlapi_bmac_core_phypll_ctl(struct phy_shim_info *physhim, bool on);
+void wlapi_bmac_core_phypll_reset(struct phy_shim_info *physhim);
+void wlapi_bmac_ucode_wake_override_phyreg_set(struct phy_shim_info *physhim);
+void wlapi_bmac_ucode_wake_override_phyreg_clear(struct phy_shim_info *physhim);
+void wlapi_bmac_write_template_ram(struct phy_shim_info *physhim, int o,
+				   int len, void *buf);
+u16 wlapi_bmac_rate_shm_offset(struct phy_shim_info *physhim, u8 rate);
+void wlapi_ucode_sample_init(struct phy_shim_info *physhim);
+void wlapi_copyfrom_objmem(struct phy_shim_info *physhim, uint, void *buf,
+			   int, u32 sel);
+void wlapi_copyto_objmem(struct phy_shim_info *physhim, uint, const void *buf,
+			 int, u32);
+
+void wlapi_high_update_phy_mode(struct phy_shim_info *physhim, u32 phy_mode);
+u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim);
+
+#endif				/* _BRCM_PHY_SHIM_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/pmu.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/pmu.c
new file mode 100644
index 0000000..71b8038
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/pmu.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <brcm_hw_ids.h>
+#include <chipcommon.h>
+#include <brcmu_utils.h>
+#include "pub.h"
+#include "aiutils.h"
+#include "pmu.h"
+#include "soc.h"
+
+/*
+ * external LPO crystal frequency
+ */
+#define EXT_ILP_HZ 32768
+
+/*
+ * Duration for ILP clock frequency measurment in milliseconds
+ *
+ * remark: 1000 must be an integer multiple of this duration
+ */
+#define ILP_CALC_DUR	10
+
+/* Fields in pmucontrol */
+#define	PCTL_ILP_DIV_MASK	0xffff0000
+#define	PCTL_ILP_DIV_SHIFT	16
+#define PCTL_PLL_PLLCTL_UPD	0x00000400	/* rev 2 */
+#define PCTL_NOILP_ON_WAIT	0x00000200	/* rev 1 */
+#define	PCTL_HT_REQ_EN		0x00000100
+#define	PCTL_ALP_REQ_EN		0x00000080
+#define	PCTL_XTALFREQ_MASK	0x0000007c
+#define	PCTL_XTALFREQ_SHIFT	2
+#define	PCTL_ILP_DIV_EN		0x00000002
+#define	PCTL_LPO_SEL		0x00000001
+
+/* ILP clock */
+#define	ILP_CLOCK		32000
+
+/* ALP clock on pre-PMU chips */
+#define	ALP_CLOCK		20000000
+
+/* pmustatus */
+#define PST_EXTLPOAVAIL	0x0100
+#define PST_WDRESET	0x0080
+#define	PST_INTPEND	0x0040
+#define	PST_SBCLKST	0x0030
+#define	PST_SBCLKST_ILP	0x0010
+#define	PST_SBCLKST_ALP	0x0020
+#define	PST_SBCLKST_HT	0x0030
+#define	PST_ALPAVAIL	0x0008
+#define	PST_HTAVAIL	0x0004
+#define	PST_RESINIT	0x0003
+
+/* PMU resource bit position */
+#define PMURES_BIT(bit)	(1 << (bit))
+
+/* PMU corerev and chip specific PLL controls.
+ * PMU<rev>_PLL<num>_XX where <rev> is PMU corerev and <num> is an arbitrary
+ * number to differentiate different PLLs controlled by the same PMU rev.
+ */
+
+/* pmu XtalFreqRatio */
+#define	PMU_XTALFREQ_REG_ILPCTR_MASK	0x00001FFF
+#define	PMU_XTALFREQ_REG_MEASURE_MASK	0x80000000
+#define	PMU_XTALFREQ_REG_MEASURE_SHIFT	31
+
+/* 4313 resources */
+#define	RES4313_BB_PU_RSRC		0
+#define	RES4313_ILP_REQ_RSRC		1
+#define	RES4313_XTAL_PU_RSRC		2
+#define	RES4313_ALP_AVAIL_RSRC		3
+#define	RES4313_RADIO_PU_RSRC		4
+#define	RES4313_BG_PU_RSRC		5
+#define	RES4313_VREG1P4_PU_RSRC		6
+#define	RES4313_AFE_PWRSW_RSRC		7
+#define	RES4313_RX_PWRSW_RSRC		8
+#define	RES4313_TX_PWRSW_RSRC		9
+#define	RES4313_BB_PWRSW_RSRC		10
+#define	RES4313_SYNTH_PWRSW_RSRC	11
+#define	RES4313_MISC_PWRSW_RSRC		12
+#define	RES4313_BB_PLL_PWRSW_RSRC	13
+#define	RES4313_HT_AVAIL_RSRC		14
+#define	RES4313_MACPHY_CLK_AVAIL_RSRC	15
+
+u16 si_pmu_fast_pwrup_delay(struct si_pub *sih)
+{
+	uint delay = PMU_MAX_TRANSITION_DLY;
+
+	switch (ai_get_chip_id(sih)) {
+	case BCMA_CHIP_ID_BCM43224:
+	case BCMA_CHIP_ID_BCM43225:
+	case BCMA_CHIP_ID_BCM4313:
+		delay = 3700;
+		break;
+	default:
+		break;
+	}
+
+	return (u16) delay;
+}
+
+u32 si_pmu_measure_alpclk(struct si_pub *sih)
+{
+	struct si_info *sii = container_of(sih, struct si_info, pub);
+	struct bcma_device *core;
+	u32 alp_khz;
+
+	if (ai_get_pmurev(sih) < 10)
+		return 0;
+
+	/* Remember original core before switch to chipc */
+	core = sii->icbus->drv_cc.core;
+
+	if (bcma_read32(core, CHIPCREGOFFS(pmustatus)) & PST_EXTLPOAVAIL) {
+		u32 ilp_ctr, alp_hz;
+
+		/*
+		 * Enable the reg to measure the freq,
+		 * in case it was disabled before
+		 */
+		bcma_write32(core, CHIPCREGOFFS(pmu_xtalfreq),
+			    1U << PMU_XTALFREQ_REG_MEASURE_SHIFT);
+
+		/* Delay for well over 4 ILP clocks */
+		udelay(1000);
+
+		/* Read the latched number of ALP ticks per 4 ILP ticks */
+		ilp_ctr = bcma_read32(core, CHIPCREGOFFS(pmu_xtalfreq)) &
+			  PMU_XTALFREQ_REG_ILPCTR_MASK;
+
+		/*
+		 * Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT
+		 * bit to save power
+		 */
+		bcma_write32(core, CHIPCREGOFFS(pmu_xtalfreq), 0);
+
+		/* Calculate ALP frequency */
+		alp_hz = (ilp_ctr * EXT_ILP_HZ) / 4;
+
+		/*
+		 * Round to nearest 100KHz, and at
+		 * the same time convert to KHz
+		 */
+		alp_khz = (alp_hz + 50000) / 100000 * 100;
+	} else
+		alp_khz = 0;
+
+	return alp_khz;
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/pmu.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/pmu.h
new file mode 100644
index 0000000..a014bbc
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/pmu.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#ifndef _BRCM_PMU_H_
+#define _BRCM_PMU_H_
+
+#include "types.h"
+
+u16 si_pmu_fast_pwrup_delay(struct si_pub *sih);
+u32 si_pmu_measure_alpclk(struct si_pub *sih);
+
+#endif /* _BRCM_PMU_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/pub.h
new file mode 100644
index 0000000..4da38cb
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/pub.h
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_PUB_H_
+#define _BRCM_PUB_H_
+
+#include <linux/bcma/bcma.h>
+#include <brcmu_wifi.h>
+#include "types.h"
+#include "defs.h"
+
+#define	BRCMS_NUMRATES	16	/* max # of rates in a rateset */
+
+/* phy types */
+#define	PHY_TYPE_A	0	/* Phy type A */
+#define	PHY_TYPE_G	2	/* Phy type G */
+#define	PHY_TYPE_N	4	/* Phy type N */
+#define	PHY_TYPE_LP	5	/* Phy type Low Power A/B/G */
+#define	PHY_TYPE_SSN	6	/* Phy type Single Stream N */
+#define	PHY_TYPE_LCN	8	/* Phy type Single Stream N */
+#define	PHY_TYPE_LCNXN	9	/* Phy type 2-stream N */
+#define	PHY_TYPE_HT	7	/* Phy type 3-Stream N */
+
+/* bw */
+#define BRCMS_10_MHZ	10	/* 10Mhz nphy channel bandwidth */
+#define BRCMS_20_MHZ	20	/* 20Mhz nphy channel bandwidth */
+#define BRCMS_40_MHZ	40	/* 40Mhz nphy channel bandwidth */
+
+#define	BRCMS_RSSI_MINVAL	-200	/* Low value, e.g. for forcing roam */
+#define	BRCMS_RSSI_NO_SIGNAL	-91	/* NDIS RSSI link quality cutoffs */
+#define	BRCMS_RSSI_VERY_LOW	-80	/* Very low quality cutoffs */
+#define	BRCMS_RSSI_LOW		-70	/* Low quality cutoffs */
+#define	BRCMS_RSSI_GOOD		-68	/* Good quality cutoffs */
+#define	BRCMS_RSSI_VERY_GOOD	-58	/* Very good quality cutoffs */
+#define	BRCMS_RSSI_EXCELLENT	-57	/* Excellent quality cutoffs */
+
+/* a large TX Power as an init value to factor out of min() calculations,
+ * keep low enough to fit in an s8, units are .25 dBm
+ */
+#define BRCMS_TXPWR_MAX		(127)	/* ~32 dBm = 1,500 mW */
+
+/* rate related definitions */
+#define	BRCMS_RATE_FLAG	0x80	/* Flag to indicate it is a basic rate */
+#define	BRCMS_RATE_MASK	0x7f	/* Rate value mask w/o basic rate flag */
+
+/* legacy rx Antenna diversity for SISO rates */
+#define	ANT_RX_DIV_FORCE_0	0	/* Use antenna 0 */
+#define	ANT_RX_DIV_FORCE_1	1	/* Use antenna 1 */
+#define	ANT_RX_DIV_START_1	2	/* Choose starting with 1 */
+#define	ANT_RX_DIV_START_0	3	/* Choose starting with 0 */
+#define	ANT_RX_DIV_ENABLE	3	/* APHY bbConfig Enable RX Diversity */
+/* default antdiv setting */
+#define ANT_RX_DIV_DEF		ANT_RX_DIV_START_0
+
+/* legacy rx Antenna diversity for SISO rates */
+/* Tx on antenna 0, "legacy term Main" */
+#define ANT_TX_FORCE_0		0
+/* Tx on antenna 1, "legacy term Aux" */
+#define ANT_TX_FORCE_1		1
+/* Tx on phy's last good Rx antenna */
+#define ANT_TX_LAST_RX		3
+/* driver's default tx antenna setting */
+#define ANT_TX_DEF		3
+
+/* Tx Chain values */
+/* def bitmap of txchain */
+#define TXCHAIN_DEF		0x1
+/* default bitmap of tx chains for nphy */
+#define TXCHAIN_DEF_NPHY	0x3
+/* default bitmap of tx chains for nphy */
+#define TXCHAIN_DEF_HTPHY	0x7
+/* def bitmap of rxchain */
+#define RXCHAIN_DEF		0x1
+/* default bitmap of rx chains for nphy */
+#define RXCHAIN_DEF_NPHY	0x3
+/* default bitmap of rx chains for nphy */
+#define RXCHAIN_DEF_HTPHY	0x7
+/* no antenna switch */
+#define ANTSWITCH_NONE		0
+/* antenna switch on 4321CB2, 2of3 */
+#define ANTSWITCH_TYPE_1	1
+/* antenna switch on 4321MPCI, 2of3 */
+#define ANTSWITCH_TYPE_2	2
+/* antenna switch on 4322, 2of3 */
+#define ANTSWITCH_TYPE_3	3
+
+#define RXBUFSZ		PKTBUFSZ
+
+#define MAX_STREAMS_SUPPORTED	4	/* max number of streams supported */
+
+struct brcm_rateset {
+	/* # rates in this set */
+	u32 count;
+	/* rates in 500kbps units w/hi bit set if basic */
+	u8 rates[WL_NUMRATES];
+};
+
+struct brcms_c_rateset {
+	uint count;		/* number of rates in rates[] */
+	 /* rates in 500kbps units w/hi bit set if basic */
+	u8 rates[BRCMS_NUMRATES];
+	u8 htphy_membership;	/* HT PHY Membership */
+	u8 mcs[MCSSET_LEN];	/* supported mcs index bit map */
+};
+
+/* All the HT-specific default advertised capabilities (including AMPDU)
+ * should be grouped here at one place
+ */
+#define AMPDU_DEF_MPDU_DENSITY	6	/* default mpdu density (110 ==> 4us) */
+
+/* wlc internal bss_info */
+struct brcms_bss_info {
+	u8 BSSID[ETH_ALEN];	/* network BSSID */
+	u16 flags;		/* flags for internal attributes */
+	u8 SSID_len;		/* the length of SSID */
+	u8 SSID[32];		/* SSID string */
+	s16 RSSI;		/* receive signal strength (in dBm) */
+	s16 SNR;		/* receive signal SNR in dB */
+	u16 beacon_period;	/* units are Kusec */
+	u16 chanspec;	/* Channel num, bw, ctrl_sb and band */
+	struct brcms_c_rateset rateset;	/* supported rates */
+};
+
+#define MAC80211_PROMISC_BCNS	(1 << 0)
+#define MAC80211_SCAN		(1 << 1)
+
+/*
+ * Public portion of common driver state structure.
+ * The wlc handle points at this.
+ */
+struct brcms_pub {
+	struct brcms_c_info *wlc;
+	struct ieee80211_hw *ieee_hw;
+	struct scb_ampdu *global_ampdu;
+	uint mac80211_state;
+	uint unit;		/* device instance number */
+	uint corerev;		/* core revision */
+	struct si_pub *sih;	/* SI handle (cookie for siutils calls) */
+	bool up;		/* interface up and running */
+	bool hw_off;		/* HW is off */
+	bool hw_up;		/* one time hw up/down */
+	bool _piomode;		/* true if pio mode */
+	uint _nbands;		/* # bands supported */
+	uint now;		/* # elapsed seconds */
+
+	bool delayed_down;	/* down delayed */
+	bool associated;	/* true:part of [I]BSS, false: not */
+	/* (union of stas_associated, aps_associated) */
+	bool _ampdu;		/* ampdu enabled or not */
+	u8 _n_enab;		/* bitmap of 11N + HT support */
+
+	u8 cur_etheraddr[ETH_ALEN];	/* our local ethernet address */
+
+	u32 radio_disabled;	/* bit vector for radio disabled reasons */
+
+	u16 boardrev;	/* version # of particular board */
+	u8 sromrev;		/* version # of the srom */
+	char srom_ccode[BRCM_CNTRY_BUF_SZ];	/* Country Code in SROM */
+	u32 boardflags;	/* Board specific flags from srom */
+	u32 boardflags2;	/* More board flags if sromrev >= 4 */
+	bool phy_11ncapable;	/* the PHY/HW is capable of 802.11N */
+
+	struct wl_cnt *_cnt;	/* low-level counters in driver */
+	struct dentry *dbgfs_dir;
+};
+
+enum wlc_par_id {
+	IOV_MPC = 1,
+	IOV_RTSTHRESH,
+	IOV_QTXPOWER,
+	IOV_BCN_LI_BCN		/* Beacon listen interval in # of beacons */
+};
+
+/***********************************************
+ * Feature-related macros to optimize out code *
+ * *********************************************
+ */
+
+#define ENAB_1x1	0x01
+#define ENAB_2x2	0x02
+#define ENAB_3x3	0x04
+#define ENAB_4x4	0x08
+#define SUPPORT_11N	(ENAB_1x1|ENAB_2x2)
+#define SUPPORT_HT	(ENAB_1x1|ENAB_2x2|ENAB_3x3)
+
+/* WL11N Support */
+#define AMPDU_AGG_HOST	1
+
+/* network protection config */
+#define	BRCMS_PROT_G_SPEC		1	/* SPEC g protection */
+#define	BRCMS_PROT_G_OVR		2	/* SPEC g prot override */
+#define	BRCMS_PROT_G_USER		3	/* gmode specified by user */
+#define	BRCMS_PROT_OVERLAP	4	/* overlap */
+#define	BRCMS_PROT_N_USER		10	/* nmode specified by user */
+#define	BRCMS_PROT_N_CFG		11	/* n protection */
+#define	BRCMS_PROT_N_CFG_OVR	12	/* n protection override */
+#define	BRCMS_PROT_N_NONGF	13	/* non-GF protection */
+#define	BRCMS_PROT_N_NONGF_OVR	14	/* non-GF protection override */
+#define	BRCMS_PROT_N_PAM_OVR	15	/* n preamble override */
+#define	BRCMS_PROT_N_OBSS		16	/* non-HT OBSS present */
+
+/*
+ * 54g modes (basic bits may still be overridden)
+ *
+ * GMODE_LEGACY_B
+ *	Rateset: 1b, 2b, 5.5, 11
+ *	Preamble: Long
+ *	Shortslot: Off
+ * GMODE_AUTO
+ *	Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54
+ *	Extended Rateset: 6, 9, 12, 48
+ *	Preamble: Long
+ *	Shortslot: Auto
+ * GMODE_ONLY
+ *	Rateset: 1b, 2b, 5.5b, 11b, 18, 24b, 36, 54
+ *	Extended Rateset: 6b, 9, 12b, 48
+ *	Preamble: Short required
+ *	Shortslot: Auto
+ * GMODE_B_DEFERRED
+ *	Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54
+ *	Extended Rateset: 6, 9, 12, 48
+ *	Preamble: Long
+ *	Shortslot: On
+ * GMODE_PERFORMANCE
+ *	Rateset: 1b, 2b, 5.5b, 6b, 9, 11b, 12b, 18, 24b, 36, 48, 54
+ *	Preamble: Short required
+ *	Shortslot: On and required
+ * GMODE_LRS
+ *	Rateset: 1b, 2b, 5.5b, 11b
+ *	Extended Rateset: 6, 9, 12, 18, 24, 36, 48, 54
+ *	Preamble: Long
+ *	Shortslot: Auto
+ */
+#define GMODE_LEGACY_B		0
+#define GMODE_AUTO		1
+#define GMODE_ONLY		2
+#define GMODE_B_DEFERRED	3
+#define GMODE_PERFORMANCE	4
+#define GMODE_LRS		5
+#define GMODE_MAX		6
+
+/* MCS values greater than this enable multiple streams */
+#define HIGHEST_SINGLE_STREAM_MCS	7
+
+#define	MAXBANDS		2	/* Maximum #of bands */
+
+/* max number of antenna configurations */
+#define ANT_SELCFG_MAX		4
+
+struct brcms_antselcfg {
+	u8 ant_config[ANT_SELCFG_MAX];	/* antenna configuration */
+	u8 num_antcfg;	/* number of available antenna configurations */
+};
+
+/* common functions for every port */
+struct brcms_c_info *brcms_c_attach(struct brcms_info *wl,
+				    struct bcma_device *core, uint unit,
+				    bool piomode, uint *perr);
+uint brcms_c_detach(struct brcms_c_info *wlc);
+int brcms_c_up(struct brcms_c_info *wlc);
+uint brcms_c_down(struct brcms_c_info *wlc);
+
+bool brcms_c_chipmatch(struct bcma_device *core);
+void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx);
+void brcms_c_reset(struct brcms_c_info *wlc);
+
+void brcms_c_intrson(struct brcms_c_info *wlc);
+u32 brcms_c_intrsoff(struct brcms_c_info *wlc);
+void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask);
+bool brcms_c_intrsupd(struct brcms_c_info *wlc);
+bool brcms_c_isr(struct brcms_c_info *wlc);
+bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded);
+bool brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu,
+			      struct ieee80211_hw *hw);
+bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid);
+void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx, int val);
+int brcms_c_get_header_len(void);
+void brcms_c_set_addrmatch(struct brcms_c_info *wlc, int match_reg_offset,
+			   const u8 *addr);
+void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
+			   const struct ieee80211_tx_queue_params *arg,
+			   bool suspend);
+struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc);
+void brcms_c_ampdu_flush(struct brcms_c_info *wlc, struct ieee80211_sta *sta,
+			 u16 tid);
+void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
+				  u8 ba_wsize, uint max_rx_ampdu_bytes);
+int brcms_c_module_register(struct brcms_pub *pub, const char *name,
+			    struct brcms_info *hdl,
+			    int (*down_fn)(void *handle));
+int brcms_c_module_unregister(struct brcms_pub *pub, const char *name,
+			      struct brcms_info *hdl);
+void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc);
+void brcms_c_enable_mac(struct brcms_c_info *wlc);
+void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state);
+void brcms_c_scan_start(struct brcms_c_info *wlc);
+void brcms_c_scan_stop(struct brcms_c_info *wlc);
+int brcms_c_get_curband(struct brcms_c_info *wlc);
+int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel);
+int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl);
+void brcms_c_get_current_rateset(struct brcms_c_info *wlc,
+				 struct brcm_rateset *currs);
+int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs);
+int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period);
+u16 brcms_c_get_phy_type(struct brcms_c_info *wlc, int phyidx);
+void brcms_c_set_shortslot_override(struct brcms_c_info *wlc,
+				    s8 sslot_override);
+void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval);
+u64 brcms_c_tsf_get(struct brcms_c_info *wlc);
+void brcms_c_tsf_set(struct brcms_c_info *wlc, u64 tsf);
+int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr);
+int brcms_c_get_tx_power(struct brcms_c_info *wlc);
+bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc);
+void brcms_c_mute(struct brcms_c_info *wlc, bool on);
+bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc);
+void brcms_c_start_station(struct brcms_c_info *wlc, u8 *addr);
+void brcms_c_start_ap(struct brcms_c_info *wlc, u8 *addr, const u8 *bssid,
+		      u8 *ssid, size_t ssid_len);
+void brcms_c_start_adhoc(struct brcms_c_info *wlc, u8 *addr);
+void brcms_c_update_beacon(struct brcms_c_info *wlc);
+void brcms_c_set_new_beacon(struct brcms_c_info *wlc, struct sk_buff *beacon,
+			    u16 tim_offset, u16 dtim_period);
+void brcms_c_set_new_probe_resp(struct brcms_c_info *wlc,
+				struct sk_buff *probe_resp);
+void brcms_c_enable_probe_resp(struct brcms_c_info *wlc, bool enable);
+void brcms_c_set_ssid(struct brcms_c_info *wlc, u8 *ssid, size_t ssid_len);
+
+#endif				/* _BRCM_PUB_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/rate.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/rate.c
new file mode 100644
index 0000000..0a0c0ad
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/rate.c
@@ -0,0 +1,514 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <brcmu_wifi.h>
+#include <brcmu_utils.h>
+
+#include "d11.h"
+#include "pub.h"
+#include "rate.h"
+
+/*
+ * Rate info per rate: It tells whether a rate is ofdm or not and its phy_rate
+ * value
+ */
+const u8 rate_info[BRCM_MAXRATE + 1] = {
+	/*  0     1     2     3     4     5     6     7     8     9 */
+/*   0 */ 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*  10 */ 0x00, 0x37, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x00,
+/*  20 */ 0x00, 0x00, 0x6e, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*  30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00,
+/*  40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00,
+/*  50 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*  60 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*  70 */ 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*  80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*  90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
+/* 100 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c
+};
+
+/* rates are in units of Kbps */
+const struct brcms_mcs_info mcs_table[MCS_TABLE_SIZE] = {
+	/* MCS  0: SS 1, MOD: BPSK,  CR 1/2 */
+	{6500, 13500, CEIL(6500 * 10, 9), CEIL(13500 * 10, 9), 0x00,
+	 BRCM_RATE_6M},
+	/* MCS  1: SS 1, MOD: QPSK,  CR 1/2 */
+	{13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x08,
+	 BRCM_RATE_12M},
+	/* MCS  2: SS 1, MOD: QPSK,  CR 3/4 */
+	{19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x0A,
+	 BRCM_RATE_18M},
+	/* MCS  3: SS 1, MOD: 16QAM, CR 1/2 */
+	{26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x10,
+	 BRCM_RATE_24M},
+	/* MCS  4: SS 1, MOD: 16QAM, CR 3/4 */
+	{39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x12,
+	 BRCM_RATE_36M},
+	/* MCS  5: SS 1, MOD: 64QAM, CR 2/3 */
+	{52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x19,
+	 BRCM_RATE_48M},
+	/* MCS  6: SS 1, MOD: 64QAM, CR 3/4 */
+	{58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x1A,
+	 BRCM_RATE_54M},
+	/* MCS  7: SS 1, MOD: 64QAM, CR 5/6 */
+	{65000, 135000, CEIL(65000 * 10, 9), CEIL(135000 * 10, 9), 0x1C,
+	 BRCM_RATE_54M},
+	/* MCS  8: SS 2, MOD: BPSK,  CR 1/2 */
+	{13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x40,
+	 BRCM_RATE_6M},
+	/* MCS  9: SS 2, MOD: QPSK,  CR 1/2 */
+	{26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x48,
+	 BRCM_RATE_12M},
+	/* MCS 10: SS 2, MOD: QPSK,  CR 3/4 */
+	{39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x4A,
+	 BRCM_RATE_18M},
+	/* MCS 11: SS 2, MOD: 16QAM, CR 1/2 */
+	{52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x50,
+	 BRCM_RATE_24M},
+	/* MCS 12: SS 2, MOD: 16QAM, CR 3/4 */
+	{78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x52,
+	 BRCM_RATE_36M},
+	/* MCS 13: SS 2, MOD: 64QAM, CR 2/3 */
+	{104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0x59,
+	 BRCM_RATE_48M},
+	/* MCS 14: SS 2, MOD: 64QAM, CR 3/4 */
+	{117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x5A,
+	 BRCM_RATE_54M},
+	/* MCS 15: SS 2, MOD: 64QAM, CR 5/6 */
+	{130000, 270000, CEIL(130000 * 10, 9), CEIL(270000 * 10, 9), 0x5C,
+	 BRCM_RATE_54M},
+	/* MCS 16: SS 3, MOD: BPSK,  CR 1/2 */
+	{19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x80,
+	 BRCM_RATE_6M},
+	/* MCS 17: SS 3, MOD: QPSK,  CR 1/2 */
+	{39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x88,
+	 BRCM_RATE_12M},
+	/* MCS 18: SS 3, MOD: QPSK,  CR 3/4 */
+	{58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x8A,
+	 BRCM_RATE_18M},
+	/* MCS 19: SS 3, MOD: 16QAM, CR 1/2 */
+	{78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x90,
+	 BRCM_RATE_24M},
+	/* MCS 20: SS 3, MOD: 16QAM, CR 3/4 */
+	{117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x92,
+	 BRCM_RATE_36M},
+	/* MCS 21: SS 3, MOD: 64QAM, CR 2/3 */
+	{156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0x99,
+	 BRCM_RATE_48M},
+	/* MCS 22: SS 3, MOD: 64QAM, CR 3/4 */
+	{175500, 364500, CEIL(175500 * 10, 9), CEIL(364500 * 10, 9), 0x9A,
+	 BRCM_RATE_54M},
+	/* MCS 23: SS 3, MOD: 64QAM, CR 5/6 */
+	{195000, 405000, CEIL(195000 * 10, 9), CEIL(405000 * 10, 9), 0x9B,
+	 BRCM_RATE_54M},
+	/* MCS 24: SS 4, MOD: BPSK,  CR 1/2 */
+	{26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0xC0,
+	 BRCM_RATE_6M},
+	/* MCS 25: SS 4, MOD: QPSK,  CR 1/2 */
+	{52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0xC8,
+	 BRCM_RATE_12M},
+	/* MCS 26: SS 4, MOD: QPSK,  CR 3/4 */
+	{78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0xCA,
+	 BRCM_RATE_18M},
+	/* MCS 27: SS 4, MOD: 16QAM, CR 1/2 */
+	{104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0xD0,
+	 BRCM_RATE_24M},
+	/* MCS 28: SS 4, MOD: 16QAM, CR 3/4 */
+	{156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0xD2,
+	 BRCM_RATE_36M},
+	/* MCS 29: SS 4, MOD: 64QAM, CR 2/3 */
+	{208000, 432000, CEIL(208000 * 10, 9), CEIL(432000 * 10, 9), 0xD9,
+	 BRCM_RATE_48M},
+	/* MCS 30: SS 4, MOD: 64QAM, CR 3/4 */
+	{234000, 486000, CEIL(234000 * 10, 9), CEIL(486000 * 10, 9), 0xDA,
+	 BRCM_RATE_54M},
+	/* MCS 31: SS 4, MOD: 64QAM, CR 5/6 */
+	{260000, 540000, CEIL(260000 * 10, 9), CEIL(540000 * 10, 9), 0xDB,
+	 BRCM_RATE_54M},
+	/* MCS 32: SS 1, MOD: BPSK,  CR 1/2 */
+	{0, 6000, 0, CEIL(6000 * 10, 9), 0x00, BRCM_RATE_6M},
+};
+
+/*
+ * phycfg for legacy OFDM frames: code rate, modulation scheme, spatial streams
+ * Number of spatial streams: always 1 other fields: refer to table 78 of
+ * section 17.3.2.2 of the original .11a standard
+ */
+struct legacy_phycfg {
+	u32 rate_ofdm;	/* ofdm mac rate */
+	/* phy ctl byte 3, code rate, modulation type, # of streams */
+	u8 tx_phy_ctl3;
+};
+
+/* Number of legacy_rate_cfg entries in the table */
+#define LEGACY_PHYCFG_TABLE_SIZE	12
+
+/*
+ * In CCK mode LPPHY overloads OFDM Modulation bits with CCK Data Rate
+ * Eventually MIMOPHY would also be converted to this format
+ * 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps
+ */
+static const struct
+legacy_phycfg legacy_phycfg_table[LEGACY_PHYCFG_TABLE_SIZE] = {
+	{BRCM_RATE_1M, 0x00},	/* CCK  1Mbps,  data rate  0 */
+	{BRCM_RATE_2M, 0x08},	/* CCK  2Mbps,  data rate  1 */
+	{BRCM_RATE_5M5, 0x10},	/* CCK  5.5Mbps,  data rate  2 */
+	{BRCM_RATE_11M, 0x18},	/* CCK  11Mbps,  data rate   3 */
+	/* OFDM  6Mbps,  code rate 1/2, BPSK,   1 spatial stream */
+	{BRCM_RATE_6M, 0x00},
+	/* OFDM  9Mbps,  code rate 3/4, BPSK,   1 spatial stream */
+	{BRCM_RATE_9M, 0x02},
+	/* OFDM  12Mbps, code rate 1/2, QPSK,   1 spatial stream */
+	{BRCM_RATE_12M, 0x08},
+	/* OFDM  18Mbps, code rate 3/4, QPSK,   1 spatial stream */
+	{BRCM_RATE_18M, 0x0A},
+	/* OFDM  24Mbps, code rate 1/2, 16-QAM, 1 spatial stream */
+	{BRCM_RATE_24M, 0x10},
+	/* OFDM  36Mbps, code rate 3/4, 16-QAM, 1 spatial stream */
+	{BRCM_RATE_36M, 0x12},
+	/* OFDM  48Mbps, code rate 2/3, 64-QAM, 1 spatial stream */
+	{BRCM_RATE_48M, 0x19},
+	/* OFDM  54Mbps, code rate 3/4, 64-QAM, 1 spatial stream */
+	{BRCM_RATE_54M, 0x1A},
+};
+
+/* Hardware rates (also encodes default basic rates) */
+
+const struct brcms_c_rateset cck_ofdm_mimo_rates = {
+	12,
+	/*  1b,   2b,   5.5b, 6,    9,    11b,  12,   18,   24,   36,   48, */
+	{ 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
+	/* 54 Mbps */
+	  0x6c},
+	0x00,
+	{ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  0x00, 0x00, 0x00, 0x00, 0x00}
+};
+
+const struct brcms_c_rateset ofdm_mimo_rates = {
+	8,
+	/*  6b,   9,    12b,  18,   24b,  36,   48,   54 Mbps */
+	{ 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
+	0x00,
+	{ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  0x00, 0x00, 0x00, 0x00, 0x00}
+};
+
+/* Default ratesets that include MCS32 for 40BW channels */
+static const struct brcms_c_rateset cck_ofdm_40bw_mimo_rates = {
+	12,
+	/*  1b,   2b,   5.5b, 6,    9,    11b,  12,   18,   24,   36,   48 */
+	{ 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
+	/* 54 Mbps */
+	  0x6c},
+	0x00,
+	{ 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  0x00, 0x00, 0x00, 0x00, 0x00}
+};
+
+static const struct brcms_c_rateset ofdm_40bw_mimo_rates = {
+	8,
+	/*  6b,   9,    12b,  18,   24b,  36,   48,   54 Mbps */
+	{ 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
+	0x00,
+	{ 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  0x00, 0x00, 0x00, 0x00, 0x00}
+};
+
+const struct brcms_c_rateset cck_ofdm_rates = {
+	12,
+	/*  1b,   2b, 5.5b, 6,    9,    11b,  12,   18,   24,   36,   48,*/
+	{ 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
+	/*54 Mbps */
+	  0x6c},
+	0x00,
+	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  0x00, 0x00, 0x00, 0x00, 0x00}
+};
+
+const struct brcms_c_rateset gphy_legacy_rates = {
+	4,
+	/*  1b,   2b,   5.5b, 11b Mbps */
+	{ 0x82, 0x84, 0x8b, 0x96},
+	0x00,
+	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  0x00, 0x00, 0x00, 0x00, 0x00}
+};
+
+const struct brcms_c_rateset ofdm_rates = {
+	8,
+	/*  6b,   9,    12b,  18,   24b,  36,   48,   54 Mbps */
+	{ 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
+	0x00,
+	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  0x00, 0x00, 0x00, 0x00, 0x00}
+};
+
+const struct brcms_c_rateset cck_rates = {
+	4,
+	/*  1b,   2b,   5.5,  11 Mbps */
+	{ 0x82, 0x84, 0x0b, 0x16},
+	0x00,
+	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  0x00, 0x00, 0x00, 0x00, 0x00}
+};
+
+/* check if rateset is valid.
+ * if check_brate is true, rateset without a basic rate is considered NOT valid.
+ */
+static bool brcms_c_rateset_valid(struct brcms_c_rateset *rs, bool check_brate)
+{
+	uint idx;
+
+	if (!rs->count)
+		return false;
+
+	if (!check_brate)
+		return true;
+
+	/* error if no basic rates */
+	for (idx = 0; idx < rs->count; idx++) {
+		if (rs->rates[idx] & BRCMS_RATE_FLAG)
+			return true;
+	}
+	return false;
+}
+
+void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams)
+{
+	int i;
+	for (i = txstreams; i < MAX_STREAMS_SUPPORTED; i++)
+		rs->mcs[i] = 0;
+}
+
+/*
+ * filter based on hardware rateset, and sort filtered rateset with basic
+ * bit(s) preserved, and check if resulting rateset is valid.
+*/
+bool
+brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs,
+				   const struct brcms_c_rateset *hw_rs,
+				   bool check_brate, u8 txstreams)
+{
+	u8 rateset[BRCM_MAXRATE + 1];
+	u8 r;
+	uint count;
+	uint i;
+
+	memset(rateset, 0, sizeof(rateset));
+	count = rs->count;
+
+	for (i = 0; i < count; i++) {
+		/* mask off "basic rate" bit, BRCMS_RATE_FLAG */
+		r = (int)rs->rates[i] & BRCMS_RATE_MASK;
+		if ((r > BRCM_MAXRATE) || (rate_info[r] == 0))
+			continue;
+		rateset[r] = rs->rates[i];	/* preserve basic bit! */
+	}
+
+	/* fill out the rates in order, looking at only supported rates */
+	count = 0;
+	for (i = 0; i < hw_rs->count; i++) {
+		r = hw_rs->rates[i] & BRCMS_RATE_MASK;
+		if (rateset[r])
+			rs->rates[count++] = rateset[r];
+	}
+
+	rs->count = count;
+
+	/* only set the mcs rate bit if the equivalent hw mcs bit is set */
+	for (i = 0; i < MCSSET_LEN; i++)
+		rs->mcs[i] = (rs->mcs[i] & hw_rs->mcs[i]);
+
+	if (brcms_c_rateset_valid(rs, check_brate))
+		return true;
+	else
+		return false;
+}
+
+/* calculate the rate of a rx'd frame and return it as a ratespec */
+u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp)
+{
+	int phy_type;
+	u32 rspec = PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT;
+
+	phy_type =
+	    ((rxh->RxChan & RXS_CHAN_PHYTYPE_MASK) >> RXS_CHAN_PHYTYPE_SHIFT);
+
+	if ((phy_type == PHY_TYPE_N) || (phy_type == PHY_TYPE_SSN) ||
+	    (phy_type == PHY_TYPE_LCN) || (phy_type == PHY_TYPE_HT)) {
+		switch (rxh->PhyRxStatus_0 & PRXS0_FT_MASK) {
+		case PRXS0_CCK:
+			rspec =
+				cck_phy2mac_rate(
+				((struct cck_phy_hdr *) plcp)->signal);
+			break;
+		case PRXS0_OFDM:
+			rspec =
+			    ofdm_phy2mac_rate(
+				((struct ofdm_phy_hdr *) plcp)->rlpt[0]);
+			break;
+		case PRXS0_PREN:
+			rspec = (plcp[0] & MIMO_PLCP_MCS_MASK) | RSPEC_MIMORATE;
+			if (plcp[0] & MIMO_PLCP_40MHZ) {
+				/* indicate rspec is for 40 MHz mode */
+				rspec &= ~RSPEC_BW_MASK;
+				rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
+			}
+			break;
+		case PRXS0_STDN:
+			/* fallthru */
+		default:
+			/* not supported, error condition */
+			break;
+		}
+		if (plcp3_issgi(plcp[3]))
+			rspec |= RSPEC_SHORT_GI;
+	} else
+	    if ((phy_type == PHY_TYPE_A) || (rxh->PhyRxStatus_0 & PRXS0_OFDM))
+		rspec = ofdm_phy2mac_rate(
+				((struct ofdm_phy_hdr *) plcp)->rlpt[0]);
+	else
+		rspec = cck_phy2mac_rate(
+				((struct cck_phy_hdr *) plcp)->signal);
+
+	return rspec;
+}
+
+/* copy rateset src to dst as-is (no masking or sorting) */
+void brcms_c_rateset_copy(const struct brcms_c_rateset *src,
+			  struct brcms_c_rateset *dst)
+{
+	memcpy(dst, src, sizeof(struct brcms_c_rateset));
+}
+
+/*
+ * Copy and selectively filter one rateset to another.
+ * 'basic_only' means only copy basic rates.
+ * 'rates' indicates cck (11b) and ofdm rates combinations.
+ *    - 0: cck and ofdm
+ *    - 1: cck only
+ *    - 2: ofdm only
+ * 'xmask' is the copy mask (typically 0x7f or 0xff).
+ */
+void
+brcms_c_rateset_filter(struct brcms_c_rateset *src, struct brcms_c_rateset *dst,
+		       bool basic_only, u8 rates, uint xmask, bool mcsallow)
+{
+	uint i;
+	uint r;
+	uint count;
+
+	count = 0;
+	for (i = 0; i < src->count; i++) {
+		r = src->rates[i];
+		if (basic_only && !(r & BRCMS_RATE_FLAG))
+			continue;
+		if (rates == BRCMS_RATES_CCK &&
+		    is_ofdm_rate((r & BRCMS_RATE_MASK)))
+			continue;
+		if (rates == BRCMS_RATES_OFDM &&
+		    is_cck_rate((r & BRCMS_RATE_MASK)))
+			continue;
+		dst->rates[count++] = r & xmask;
+	}
+	dst->count = count;
+	dst->htphy_membership = src->htphy_membership;
+
+	if (mcsallow && rates != BRCMS_RATES_CCK)
+		memcpy(&dst->mcs[0], &src->mcs[0], MCSSET_LEN);
+	else
+		brcms_c_rateset_mcs_clear(dst);
+}
+
+/* select rateset for a given phy_type and bandtype and filter it, sort it
+ * and fill rs_tgt with result
+ */
+void
+brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt,
+			const struct brcms_c_rateset *rs_hw,
+			uint phy_type, int bandtype, bool cck_only,
+			uint rate_mask, bool mcsallow, u8 bw, u8 txstreams)
+{
+	const struct brcms_c_rateset *rs_dflt;
+	struct brcms_c_rateset rs_sel;
+	if ((PHYTYPE_IS(phy_type, PHY_TYPE_HT)) ||
+	    (PHYTYPE_IS(phy_type, PHY_TYPE_N)) ||
+	    (PHYTYPE_IS(phy_type, PHY_TYPE_LCN)) ||
+	    (PHYTYPE_IS(phy_type, PHY_TYPE_SSN))) {
+		if (bandtype == BRCM_BAND_5G)
+			rs_dflt = (bw == BRCMS_20_MHZ ?
+				   &ofdm_mimo_rates : &ofdm_40bw_mimo_rates);
+		else
+			rs_dflt = (bw == BRCMS_20_MHZ ?
+				   &cck_ofdm_mimo_rates :
+				   &cck_ofdm_40bw_mimo_rates);
+	} else if (PHYTYPE_IS(phy_type, PHY_TYPE_LP)) {
+		rs_dflt = (bandtype == BRCM_BAND_5G) ?
+			  &ofdm_rates : &cck_ofdm_rates;
+	} else if (PHYTYPE_IS(phy_type, PHY_TYPE_A)) {
+		rs_dflt = &ofdm_rates;
+	} else if (PHYTYPE_IS(phy_type, PHY_TYPE_G)) {
+		rs_dflt = &cck_ofdm_rates;
+	} else {
+		/* should not happen, error condition */
+		rs_dflt = &cck_rates;	/* force cck */
+	}
+
+	/* if hw rateset is not supplied, assign selected rateset to it */
+	if (!rs_hw)
+		rs_hw = rs_dflt;
+
+	brcms_c_rateset_copy(rs_dflt, &rs_sel);
+	brcms_c_rateset_mcs_upd(&rs_sel, txstreams);
+	brcms_c_rateset_filter(&rs_sel, rs_tgt, false,
+			   cck_only ? BRCMS_RATES_CCK : BRCMS_RATES_CCK_OFDM,
+			   rate_mask, mcsallow);
+	brcms_c_rate_hwrs_filter_sort_validate(rs_tgt, rs_hw, false,
+					   mcsallow ? txstreams : 1);
+}
+
+s16 brcms_c_rate_legacy_phyctl(uint rate)
+{
+	uint i;
+	for (i = 0; i < LEGACY_PHYCFG_TABLE_SIZE; i++)
+		if (rate == legacy_phycfg_table[i].rate_ofdm)
+			return legacy_phycfg_table[i].tx_phy_ctl3;
+
+	return -1;
+}
+
+void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset)
+{
+	uint i;
+	for (i = 0; i < MCSSET_LEN; i++)
+		rateset->mcs[i] = 0;
+}
+
+void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset, u8 txstreams)
+{
+	memcpy(&rateset->mcs[0], &cck_ofdm_mimo_rates.mcs[0], MCSSET_LEN);
+	brcms_c_rateset_mcs_upd(rateset, txstreams);
+}
+
+/* Based on bandwidth passed, allow/disallow MCS 32 in the rateset */
+void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset, u8 bw)
+{
+	if (bw == BRCMS_40_MHZ)
+		setbit(rateset->mcs, 32);
+	else
+		clrbit(rateset->mcs, 32);
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/rate.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/rate.h
new file mode 100644
index 0000000..5bb88b7
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/rate.h
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_RATE_H_
+#define _BRCM_RATE_H_
+
+#include "types.h"
+#include "d11.h"
+#include "phy_hal.h"
+
+extern const u8 rate_info[];
+extern const struct brcms_c_rateset cck_ofdm_mimo_rates;
+extern const struct brcms_c_rateset ofdm_mimo_rates;
+extern const struct brcms_c_rateset cck_ofdm_rates;
+extern const struct brcms_c_rateset ofdm_rates;
+extern const struct brcms_c_rateset cck_rates;
+extern const struct brcms_c_rateset gphy_legacy_rates;
+extern const struct brcms_c_rateset rate_limit_1_2;
+
+struct brcms_mcs_info {
+	/* phy rate in kbps [20Mhz] */
+	u32 phy_rate_20;
+	/* phy rate in kbps [40Mhz] */
+	u32 phy_rate_40;
+	/* phy rate in kbps [20Mhz] with SGI */
+	u32 phy_rate_20_sgi;
+	/* phy rate in kbps [40Mhz] with SGI */
+	u32 phy_rate_40_sgi;
+	/* phy ctl byte 3, code rate, modulation type, # of streams */
+	u8 tx_phy_ctl3;
+	/* matching legacy ofdm rate in 500bkps */
+	u8 leg_ofdm;
+};
+
+#define BRCMS_MAXMCS	32	/* max valid mcs index */
+#define MCS_TABLE_SIZE	33	/* Number of mcs entries in the table */
+extern const struct brcms_mcs_info mcs_table[];
+
+#define MCS_TXS_MASK	0xc0	/* num tx streams - 1 bit mask */
+#define MCS_TXS_SHIFT	6	/* num tx streams - 1 bit shift */
+
+/* returns num tx streams - 1 */
+static inline u8 mcs_2_txstreams(u8 mcs)
+{
+	return (mcs_table[mcs].tx_phy_ctl3 & MCS_TXS_MASK) >> MCS_TXS_SHIFT;
+}
+
+static inline uint mcs_2_rate(u8 mcs, bool is40, bool sgi)
+{
+	if (sgi) {
+		if (is40)
+			return mcs_table[mcs].phy_rate_40_sgi;
+		return mcs_table[mcs].phy_rate_20_sgi;
+	}
+	if (is40)
+		return mcs_table[mcs].phy_rate_40;
+
+	return mcs_table[mcs].phy_rate_20;
+}
+
+/* Macro to use the rate_info table */
+#define	BRCMS_RATE_MASK_FULL 0xff /* Rate value mask with basic rate flag */
+
+/*
+ * rate spec : holds rate and mode specific information required to generate a
+ * tx frame. Legacy CCK and OFDM information is held in the same manner as was
+ * done in the past (in the lower byte) the upper 3 bytes primarily hold MIMO
+ * specific information
+ */
+
+/* rate spec bit fields */
+
+/* Either 500Kbps units or MIMO MCS idx */
+#define RSPEC_RATE_MASK		0x0000007F
+/* mimo MCS is stored in RSPEC_RATE_MASK */
+#define RSPEC_MIMORATE		0x08000000
+/* mimo bw mask */
+#define RSPEC_BW_MASK		0x00000700
+/* mimo bw shift */
+#define RSPEC_BW_SHIFT		8
+/* mimo Space/Time/Frequency mode mask */
+#define RSPEC_STF_MASK		0x00003800
+/* mimo Space/Time/Frequency mode shift */
+#define RSPEC_STF_SHIFT		11
+/* mimo coding type mask */
+#define RSPEC_CT_MASK		0x0000C000
+/* mimo coding type shift */
+#define RSPEC_CT_SHIFT		14
+/* mimo num STC streams per PLCP defn. */
+#define RSPEC_STC_MASK		0x00300000
+/* mimo num STC streams per PLCP defn. */
+#define RSPEC_STC_SHIFT		20
+/* mimo bit indicates adv coding in use */
+#define RSPEC_LDPC_CODING	0x00400000
+/* mimo bit indicates short GI in use */
+#define RSPEC_SHORT_GI		0x00800000
+/* bit indicates override both rate & mode */
+#define RSPEC_OVERRIDE		0x80000000
+/* bit indicates override rate only */
+#define RSPEC_OVERRIDE_MCS_ONLY 0x40000000
+
+static inline bool rspec_active(u32 rspec)
+{
+	return rspec & (RSPEC_RATE_MASK | RSPEC_MIMORATE);
+}
+
+static inline u8 rspec_phytxbyte2(u32 rspec)
+{
+	return (rspec & 0xff00) >> 8;
+}
+
+static inline u32 rspec_get_bw(u32 rspec)
+{
+	return (rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT;
+}
+
+static inline bool rspec_issgi(u32 rspec)
+{
+	return (rspec & RSPEC_SHORT_GI) == RSPEC_SHORT_GI;
+}
+
+static inline bool rspec_is40mhz(u32 rspec)
+{
+	u32 bw = rspec_get_bw(rspec);
+
+	return bw == PHY_TXC1_BW_40MHZ || bw == PHY_TXC1_BW_40MHZ_DUP;
+}
+
+static inline uint rspec2rate(u32 rspec)
+{
+	if (rspec & RSPEC_MIMORATE)
+		return mcs_2_rate(rspec & RSPEC_RATE_MASK, rspec_is40mhz(rspec),
+				  rspec_issgi(rspec));
+	return rspec & RSPEC_RATE_MASK;
+}
+
+static inline u8 rspec_mimoplcp3(u32 rspec)
+{
+	return (rspec & 0xf00000) >> 16;
+}
+
+static inline bool plcp3_issgi(u8 plcp)
+{
+	return (plcp & (RSPEC_SHORT_GI >> 16)) != 0;
+}
+
+static inline uint rspec_stc(u32 rspec)
+{
+	return (rspec & RSPEC_STC_MASK) >> RSPEC_STC_SHIFT;
+}
+
+static inline uint rspec_stf(u32 rspec)
+{
+	return (rspec & RSPEC_STF_MASK) >> RSPEC_STF_SHIFT;
+}
+
+static inline bool is_mcs_rate(u32 ratespec)
+{
+	return (ratespec & RSPEC_MIMORATE) != 0;
+}
+
+static inline bool is_ofdm_rate(u32 ratespec)
+{
+	return !is_mcs_rate(ratespec) &&
+	       (rate_info[ratespec & RSPEC_RATE_MASK] & BRCMS_RATE_FLAG);
+}
+
+static inline bool is_cck_rate(u32 ratespec)
+{
+	u32 rate = (ratespec & BRCMS_RATE_MASK);
+
+	return !is_mcs_rate(ratespec) && (
+			rate == BRCM_RATE_1M || rate == BRCM_RATE_2M ||
+			rate == BRCM_RATE_5M5 || rate == BRCM_RATE_11M);
+}
+
+static inline bool is_single_stream(u8 mcs)
+{
+	return mcs <= HIGHEST_SINGLE_STREAM_MCS || mcs == 32;
+}
+
+static inline u8 cck_rspec(u8 cck)
+{
+	return cck & RSPEC_RATE_MASK;
+}
+
+/* Convert encoded rate value in plcp header to numerical rates in 500 KHz
+ * increments */
+static inline u8 ofdm_phy2mac_rate(u8 rlpt)
+{
+	return wlc_phy_get_ofdm_rate_lookup()[rlpt & 0x7];
+}
+
+static inline u8 cck_phy2mac_rate(u8 signal)
+{
+	return signal/5;
+}
+
+/* Rates specified in brcms_c_rateset_filter() */
+#define BRCMS_RATES_CCK_OFDM	0
+#define BRCMS_RATES_CCK		1
+#define BRCMS_RATES_OFDM		2
+
+/* sanitize, and sort a rateset with the basic bit(s) preserved, validate
+ * rateset */
+bool brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs,
+					    const struct brcms_c_rateset *hw_rs,
+					    bool check_brate, u8 txstreams);
+/* copy rateset src to dst as-is (no masking or sorting) */
+void brcms_c_rateset_copy(const struct brcms_c_rateset *src,
+			  struct brcms_c_rateset *dst);
+
+/* would be nice to have these documented ... */
+u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp);
+
+void brcms_c_rateset_filter(struct brcms_c_rateset *src,
+			    struct brcms_c_rateset *dst, bool basic_only,
+			    u8 rates, uint xmask, bool mcsallow);
+
+void brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt,
+			     const struct brcms_c_rateset *rs_hw, uint phy_type,
+			     int bandtype, bool cck_only, uint rate_mask,
+			     bool mcsallow, u8 bw, u8 txstreams);
+
+s16 brcms_c_rate_legacy_phyctl(uint rate);
+
+void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams);
+void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset);
+void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset, u8 txstreams);
+void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset, u8 bw);
+
+#endif				/* _BRCM_RATE_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/scb.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/scb.h
new file mode 100644
index 0000000..3a3d736
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/scb.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_SCB_H_
+#define _BRCM_SCB_H_
+
+#include <linux/if_ether.h>
+#include <brcmu_utils.h>
+#include <defs.h>
+#include "types.h"
+
+#define AMPDU_TX_BA_MAX_WSIZE	64	/* max Tx ba window size (in pdu) */
+
+#define AMPDU_MAX_SCB_TID	NUMPRIO
+
+/* scb flags */
+#define SCB_WMECAP		0x0040
+#define SCB_HTCAP		0x10000	/* HT (MIMO) capable device */
+#define SCB_IS40		0x80000	/* 40MHz capable */
+#define SCB_STBCCAP		0x40000000	/* STBC Capable */
+
+#define SCB_MAGIC	0xbeefcafe
+
+/* structure to store per-tid state for the ampdu initiator */
+struct scb_ampdu_tid_ini {
+	u8 tid;		  /* initiator tid for easy lookup */
+	/* tx retry count; indexed by seq modulo */
+	u8 txretry[AMPDU_TX_BA_MAX_WSIZE];
+	struct scb *scb;  /* backptr for easy lookup */
+	u8 ba_wsize;	  /* negotiated ba window size (in pdu) */
+};
+
+struct scb_ampdu {
+	struct scb *scb;	/* back pointer for easy reference */
+	u8 mpdu_density;	/* mpdu density */
+	u8 max_pdu;		/* max pdus allowed in ampdu */
+	u8 release;		/* # of mpdus released at a time */
+	u16 min_len;		/* min mpdu len to support the density */
+	u32 max_rx_ampdu_bytes;	/* max ampdu rcv length; 8k, 16k, 32k, 64k */
+
+	/*
+	 * This could easily be a ini[] pointer and we keep this info in wl
+	 * itself instead of having mac80211 hold it for us. Also could be made
+	 * dynamic per tid instead of static.
+	 */
+	/* initiator info - per tid (NUMPRIO): */
+	struct scb_ampdu_tid_ini ini[AMPDU_MAX_SCB_TID];
+};
+
+/* station control block - one per remote MAC address */
+struct scb {
+	u32 magic;
+	u32 flags;	/* various bit flags as defined below */
+	u32 flags2;	/* various bit flags2 as defined below */
+	u8 state;	/* current state bitfield of auth/assoc process */
+	u8 ea[ETH_ALEN];	/* station address */
+	uint fragresid[NUMPRIO];/* #bytes unused in frag buffer per prio */
+
+	u16 seqctl[NUMPRIO];	/* seqctl of last received frame (for dups) */
+	/* seqctl of last received frame (for dups) for non-QoS data and
+	 * management */
+	u16 seqctl_nonqos;
+	u16 seqnum[NUMPRIO];/* WME: driver maintained sw seqnum per priority */
+
+	struct scb_ampdu scb_ampdu;	/* AMPDU state including per tid info */
+};
+
+#endif				/* _BRCM_SCB_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/stf.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/stf.c
new file mode 100644
index 0000000..0ab865d
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/stf.c
@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <net/mac80211.h>
+
+#include "types.h"
+#include "d11.h"
+#include "rate.h"
+#include "phy/phy_hal.h"
+#include "channel.h"
+#include "main.h"
+#include "stf.h"
+#include "debug.h"
+
+#define MIN_SPATIAL_EXPANSION	0
+#define MAX_SPATIAL_EXPANSION	1
+
+#define BRCMS_STF_SS_STBC_RX(wlc) (BRCMS_ISNPHY(wlc->band) && \
+	NREV_GT(wlc->band->phyrev, 3) && NREV_LE(wlc->band->phyrev, 6))
+
+#define NSTS_1	1
+#define NSTS_2	2
+#define NSTS_3	3
+#define NSTS_4	4
+
+static const u8 txcore_default[5] = {
+	(0),			/* bitmap of the core enabled */
+	(0x01),			/* For Nsts = 1, enable core 1 */
+	(0x03),			/* For Nsts = 2, enable core 1 & 2 */
+	(0x07),			/* For Nsts = 3, enable core 1, 2 & 3 */
+	(0x0f)			/* For Nsts = 4, enable all cores */
+};
+
+static void brcms_c_stf_stbc_rx_ht_update(struct brcms_c_info *wlc, int val)
+{
+	/* MIMOPHYs rev3-6 cannot receive STBC with only one rx core active */
+	if (BRCMS_STF_SS_STBC_RX(wlc)) {
+		if ((wlc->stf->rxstreams == 1) && (val != HT_CAP_RX_STBC_NO))
+			return;
+	}
+
+	if (wlc->pub->up) {
+		brcms_c_update_beacon(wlc);
+		brcms_c_update_probe_resp(wlc, true);
+	}
+}
+
+/*
+ * every WLC_TEMPSENSE_PERIOD seconds temperature check to decide whether to
+ * turn on/off txchain.
+ */
+void brcms_c_tempsense_upd(struct brcms_c_info *wlc)
+{
+	struct brcms_phy_pub *pi = wlc->band->pi;
+	uint active_chains, txchain;
+
+	/* Check if the chip is too hot. Disable one Tx chain, if it is */
+	/* high 4 bits are for Rx chain, low 4 bits are  for Tx chain */
+	active_chains = wlc_phy_stf_chain_active_get(pi);
+	txchain = active_chains & 0xf;
+
+	if (wlc->stf->txchain == wlc->stf->hw_txchain) {
+		if (txchain && (txchain < wlc->stf->hw_txchain))
+			/* turn off 1 tx chain */
+			brcms_c_stf_txchain_set(wlc, txchain, true);
+	} else if (wlc->stf->txchain < wlc->stf->hw_txchain) {
+		if (txchain == wlc->stf->hw_txchain)
+			/* turn back on txchain */
+			brcms_c_stf_txchain_set(wlc, txchain, true);
+	}
+}
+
+void
+brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, u16 *ss_algo_channel,
+			    u16 chanspec)
+{
+	struct tx_power power = { };
+	u8 siso_mcs_id, cdd_mcs_id, stbc_mcs_id;
+
+	/* Clear previous settings */
+	*ss_algo_channel = 0;
+
+	if (!wlc->pub->up) {
+		*ss_algo_channel = (u16) -1;
+		return;
+	}
+
+	wlc_phy_txpower_get_current(wlc->band->pi, &power,
+				    CHSPEC_CHANNEL(chanspec));
+
+	siso_mcs_id = (CHSPEC_IS40(chanspec)) ?
+	    WL_TX_POWER_MCS40_SISO_FIRST : WL_TX_POWER_MCS20_SISO_FIRST;
+	cdd_mcs_id = (CHSPEC_IS40(chanspec)) ?
+	    WL_TX_POWER_MCS40_CDD_FIRST : WL_TX_POWER_MCS20_CDD_FIRST;
+	stbc_mcs_id = (CHSPEC_IS40(chanspec)) ?
+	    WL_TX_POWER_MCS40_STBC_FIRST : WL_TX_POWER_MCS20_STBC_FIRST;
+
+	/* criteria to choose stf mode */
+
+	/*
+	 * the "+3dbm (12 0.25db units)" is to account for the fact that with
+	 * CDD, tx occurs on both chains
+	 */
+	if (power.target[siso_mcs_id] > (power.target[cdd_mcs_id] + 12))
+		setbit(ss_algo_channel, PHY_TXC1_MODE_SISO);
+	else
+		setbit(ss_algo_channel, PHY_TXC1_MODE_CDD);
+
+	/*
+	 * STBC is ORed into to algo channel as STBC requires per-packet SCB
+	 * capability check so cannot be default mode of operation. One of
+	 * SISO, CDD have to be set
+	 */
+	if (power.target[siso_mcs_id] <= (power.target[stbc_mcs_id] + 12))
+		setbit(ss_algo_channel, PHY_TXC1_MODE_STBC);
+}
+
+static bool brcms_c_stf_stbc_tx_set(struct brcms_c_info *wlc, s32 int_val)
+{
+	if ((int_val != AUTO) && (int_val != OFF) && (int_val != ON))
+		return false;
+
+	if ((int_val == ON) && (wlc->stf->txstreams == 1))
+		return false;
+
+	wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = (s8) int_val;
+	wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = (s8) int_val;
+
+	return true;
+}
+
+bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val)
+{
+	if ((int_val != HT_CAP_RX_STBC_NO)
+	    && (int_val != HT_CAP_RX_STBC_ONE_STREAM))
+		return false;
+
+	if (BRCMS_STF_SS_STBC_RX(wlc)) {
+		if ((int_val != HT_CAP_RX_STBC_NO)
+		    && (wlc->stf->rxstreams == 1))
+			return false;
+	}
+
+	brcms_c_stf_stbc_rx_ht_update(wlc, int_val);
+	return true;
+}
+
+static int brcms_c_stf_txcore_set(struct brcms_c_info *wlc, u8 Nsts,
+				  u8 core_mask)
+{
+	brcms_dbg_ht(wlc->hw->d11core, "wl%d: Nsts %d core_mask %x\n",
+		     wlc->pub->unit, Nsts, core_mask);
+
+	if (hweight8(core_mask) > wlc->stf->txstreams)
+		core_mask = 0;
+
+	if ((hweight8(core_mask) == wlc->stf->txstreams) &&
+	    ((core_mask & ~wlc->stf->txchain)
+	     || !(core_mask & wlc->stf->txchain)))
+		core_mask = wlc->stf->txchain;
+
+	wlc->stf->txcore[Nsts] = core_mask;
+	/* Nsts = 1..4, txcore index = 1..4 */
+	if (Nsts == 1) {
+		/* Needs to update beacon and ucode generated response
+		 * frames when 1 stream core map changed
+		 */
+		wlc->stf->phytxant = core_mask << PHY_TXC_ANT_SHIFT;
+		brcms_b_txant_set(wlc->hw, wlc->stf->phytxant);
+		if (wlc->clk) {
+			brcms_c_suspend_mac_and_wait(wlc);
+			brcms_c_beacon_phytxctl_txant_upd(wlc, wlc->bcn_rspec);
+			brcms_c_enable_mac(wlc);
+		}
+	}
+
+	return 0;
+}
+
+static int brcms_c_stf_spatial_policy_set(struct brcms_c_info *wlc, int val)
+{
+	int i;
+	u8 core_mask = 0;
+
+	brcms_dbg_ht(wlc->hw->d11core, "wl%d: val %x\n", wlc->pub->unit,
+		     val);
+
+	wlc->stf->spatial_policy = (s8) val;
+	for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++) {
+		core_mask = (val == MAX_SPATIAL_EXPANSION) ?
+		    wlc->stf->txchain : txcore_default[i];
+		brcms_c_stf_txcore_set(wlc, (u8) i, core_mask);
+	}
+	return 0;
+}
+
+/*
+ * Centralized txant update function. call it whenever wlc->stf->txant and/or
+ * wlc->stf->txchain change.
+ *
+ * Antennas are controlled by ucode indirectly, which drives PHY or GPIO to
+ * achieve various tx/rx antenna selection schemes
+ *
+ * legacy phy, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7
+ * means auto(last rx).
+ * for NREV<3, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7
+ * means last rx and do tx-antenna selection for SISO transmissions
+ * for NREV=3, bit 6 and bit _8_ means antenna 0 and 1 respectively, bit6+bit7
+ * means last rx and do tx-antenna selection for SISO transmissions
+ * for NREV>=7, bit 6 and bit 7 mean antenna 0 and 1 respectively, nit6+bit7
+ * means both cores active
+*/
+static void _brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc)
+{
+	s8 txant;
+
+	txant = (s8) wlc->stf->txant;
+	if (BRCMS_PHY_11N_CAP(wlc->band)) {
+		if (txant == ANT_TX_FORCE_0) {
+			wlc->stf->phytxant = PHY_TXC_ANT_0;
+		} else if (txant == ANT_TX_FORCE_1) {
+			wlc->stf->phytxant = PHY_TXC_ANT_1;
+
+			if (BRCMS_ISNPHY(wlc->band) &&
+			    NREV_GE(wlc->band->phyrev, 3)
+			    && NREV_LT(wlc->band->phyrev, 7))
+				wlc->stf->phytxant = PHY_TXC_ANT_2;
+		} else {
+			if (BRCMS_ISLCNPHY(wlc->band) ||
+			    BRCMS_ISSSLPNPHY(wlc->band))
+				wlc->stf->phytxant = PHY_TXC_LCNPHY_ANT_LAST;
+			else {
+				/* catch out of sync wlc->stf->txcore */
+				WARN_ON(wlc->stf->txchain <= 0);
+				wlc->stf->phytxant =
+				    wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
+			}
+		}
+	} else {
+		if (txant == ANT_TX_FORCE_0)
+			wlc->stf->phytxant = PHY_TXC_OLD_ANT_0;
+		else if (txant == ANT_TX_FORCE_1)
+			wlc->stf->phytxant = PHY_TXC_OLD_ANT_1;
+		else
+			wlc->stf->phytxant = PHY_TXC_OLD_ANT_LAST;
+	}
+
+	brcms_b_txant_set(wlc->hw, wlc->stf->phytxant);
+}
+
+int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val, bool force)
+{
+	u8 txchain = (u8) int_val;
+	u8 txstreams;
+	uint i;
+
+	if (wlc->stf->txchain == txchain)
+		return 0;
+
+	if ((txchain & ~wlc->stf->hw_txchain)
+	    || !(txchain & wlc->stf->hw_txchain))
+		return -EINVAL;
+
+	/*
+	 * if nrate override is configured to be non-SISO STF mode, reject
+	 * reducing txchain to 1
+	 */
+	txstreams = (u8) hweight8(txchain);
+	if (txstreams > MAX_STREAMS_SUPPORTED)
+		return -EINVAL;
+
+	wlc->stf->txchain = txchain;
+	wlc->stf->txstreams = txstreams;
+	brcms_c_stf_stbc_tx_set(wlc, wlc->band->band_stf_stbc_tx);
+	brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
+	brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
+	wlc->stf->txant =
+	    (wlc->stf->txstreams == 1) ? ANT_TX_FORCE_0 : ANT_TX_DEF;
+	_brcms_c_stf_phy_txant_upd(wlc);
+
+	wlc_phy_stf_chain_set(wlc->band->pi, wlc->stf->txchain,
+			      wlc->stf->rxchain);
+
+	for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++)
+		brcms_c_stf_txcore_set(wlc, (u8) i, txcore_default[i]);
+
+	return 0;
+}
+
+/*
+ * update wlc->stf->ss_opmode which represents the operational stf_ss mode
+ * we're using
+ */
+int brcms_c_stf_ss_update(struct brcms_c_info *wlc, struct brcms_band *band)
+{
+	int ret_code = 0;
+	u8 prev_stf_ss;
+	u8 upd_stf_ss;
+
+	prev_stf_ss = wlc->stf->ss_opmode;
+
+	/*
+	 * NOTE: opmode can only be SISO or CDD as STBC is decided on a
+	 * per-packet basis
+	 */
+	if (BRCMS_STBC_CAP_PHY(wlc) &&
+	    wlc->stf->ss_algosel_auto
+	    && (wlc->stf->ss_algo_channel != (u16) -1)) {
+		upd_stf_ss = (wlc->stf->txstreams == 1 ||
+			      isset(&wlc->stf->ss_algo_channel,
+				    PHY_TXC1_MODE_SISO)) ?
+				    PHY_TXC1_MODE_SISO : PHY_TXC1_MODE_CDD;
+	} else {
+		if (wlc->band != band)
+			return ret_code;
+		upd_stf_ss = (wlc->stf->txstreams == 1) ?
+				PHY_TXC1_MODE_SISO : band->band_stf_ss_mode;
+	}
+	if (prev_stf_ss != upd_stf_ss) {
+		wlc->stf->ss_opmode = upd_stf_ss;
+		brcms_b_band_stf_ss_set(wlc->hw, upd_stf_ss);
+	}
+
+	return ret_code;
+}
+
+int brcms_c_stf_attach(struct brcms_c_info *wlc)
+{
+	wlc->bandstate[BAND_2G_INDEX]->band_stf_ss_mode = PHY_TXC1_MODE_SISO;
+	wlc->bandstate[BAND_5G_INDEX]->band_stf_ss_mode = PHY_TXC1_MODE_CDD;
+
+	if (BRCMS_ISNPHY(wlc->band) &&
+	    (wlc_phy_txpower_hw_ctrl_get(wlc->band->pi) != PHY_TPC_HW_ON))
+		wlc->bandstate[BAND_2G_INDEX]->band_stf_ss_mode =
+		    PHY_TXC1_MODE_CDD;
+	brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
+	brcms_c_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
+
+	brcms_c_stf_stbc_rx_ht_update(wlc, HT_CAP_RX_STBC_NO);
+	wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = OFF;
+	wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = OFF;
+
+	if (BRCMS_STBC_CAP_PHY(wlc)) {
+		wlc->stf->ss_algosel_auto = true;
+		/* Init the default value */
+		wlc->stf->ss_algo_channel = (u16) -1;
+	}
+	return 0;
+}
+
+void brcms_c_stf_detach(struct brcms_c_info *wlc)
+{
+}
+
+void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc)
+{
+	_brcms_c_stf_phy_txant_upd(wlc);
+}
+
+void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc)
+{
+	struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom;
+
+	/* get available rx/tx chains */
+	wlc->stf->hw_txchain = sprom->txchain;
+	wlc->stf->hw_rxchain = sprom->rxchain;
+
+	/* these parameter are intended to be used for all PHY types */
+	if (wlc->stf->hw_txchain == 0 || wlc->stf->hw_txchain == 0xf) {
+		if (BRCMS_ISNPHY(wlc->band))
+			wlc->stf->hw_txchain = TXCHAIN_DEF_NPHY;
+		else
+			wlc->stf->hw_txchain = TXCHAIN_DEF;
+	}
+
+	wlc->stf->txchain = wlc->stf->hw_txchain;
+	wlc->stf->txstreams = (u8) hweight8(wlc->stf->hw_txchain);
+
+	if (wlc->stf->hw_rxchain == 0 || wlc->stf->hw_rxchain == 0xf) {
+		if (BRCMS_ISNPHY(wlc->band))
+			wlc->stf->hw_rxchain = RXCHAIN_DEF_NPHY;
+		else
+			wlc->stf->hw_rxchain = RXCHAIN_DEF;
+	}
+
+	wlc->stf->rxchain = wlc->stf->hw_rxchain;
+	wlc->stf->rxstreams = (u8) hweight8(wlc->stf->hw_rxchain);
+
+	/* initialize the txcore table */
+	memcpy(wlc->stf->txcore, txcore_default, sizeof(wlc->stf->txcore));
+
+	/* default spatial_policy */
+	wlc->stf->spatial_policy = MIN_SPATIAL_EXPANSION;
+	brcms_c_stf_spatial_policy_set(wlc, MIN_SPATIAL_EXPANSION);
+}
+
+static u16 _brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc,
+				       u32 rspec)
+{
+	u16 phytxant = wlc->stf->phytxant;
+
+	if (rspec_stf(rspec) != PHY_TXC1_MODE_SISO)
+		phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
+	else if (wlc->stf->txant == ANT_TX_DEF)
+		phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
+	phytxant &= PHY_TXC_ANT_MASK;
+	return phytxant;
+}
+
+u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, u32 rspec)
+{
+	return _brcms_c_stf_phytxchain_sel(wlc, rspec);
+}
+
+u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc, u32 rspec)
+{
+	u16 phytxant = wlc->stf->phytxant;
+	u16 mask = PHY_TXC_ANT_MASK;
+
+	/* for non-siso rates or default setting, use the available chains */
+	if (BRCMS_ISNPHY(wlc->band)) {
+		phytxant = _brcms_c_stf_phytxchain_sel(wlc, rspec);
+		mask = PHY_TXC_HTANT_MASK;
+	}
+	phytxant |= phytxant & mask;
+	return phytxant;
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/stf.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/stf.h
new file mode 100644
index 0000000..ba94930
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/stf.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_STF_H_
+#define _BRCM_STF_H_
+
+#include "types.h"
+
+int brcms_c_stf_attach(struct brcms_c_info *wlc);
+void brcms_c_stf_detach(struct brcms_c_info *wlc);
+
+void brcms_c_tempsense_upd(struct brcms_c_info *wlc);
+void brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc,
+				     u16 *ss_algo_channel, u16 chanspec);
+int brcms_c_stf_ss_update(struct brcms_c_info *wlc, struct brcms_band *band);
+void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc);
+int brcms_c_stf_txchain_set(struct brcms_c_info *wlc, s32 int_val, bool force);
+bool brcms_c_stf_stbc_rx_set(struct brcms_c_info *wlc, s32 int_val);
+void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc);
+void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc);
+u16 brcms_c_stf_phytxchain_sel(struct brcms_c_info *wlc, u32 rspec);
+u16 brcms_c_stf_d11hdrs_phyctl_txant(struct brcms_c_info *wlc, u32 rspec);
+
+#endif				/* _BRCM_STF_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/types.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/types.h
new file mode 100644
index 0000000..ae1f3ad
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/types.h
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_TYPES_H_
+#define _BRCM_TYPES_H_
+
+#include <linux/types.h>
+#include <linux/io.h>
+
+#define WL_CHAN_FREQ_RANGE_2G      0
+#define WL_CHAN_FREQ_RANGE_5GL     1
+#define WL_CHAN_FREQ_RANGE_5GM     2
+#define WL_CHAN_FREQ_RANGE_5GH     3
+
+/* boardflags */
+
+/* Board has gpio 9 controlling the PA */
+#define	BFL_PACTRL		0x00000002
+/* Not ok to power down the chip pll and oscillator */
+#define	BFL_NOPLLDOWN		0x00000020
+/* Board supports the Front End Module */
+#define BFL_FEM			0x00000800
+/* Board has an external LNA in 2.4GHz band */
+#define BFL_EXTLNA		0x00001000
+/* Board has no PA */
+#define BFL_NOPA		0x00010000
+/* Power topology uses BUCKBOOST */
+#define BFL_BUCKBOOST		0x00200000
+/* Board has FEM and switch to share antenna w/ BT */
+#define BFL_FEM_BT		0x00400000
+/* Power topology doesn't use CBUCK */
+#define BFL_NOCBUCK		0x00800000
+/* Power topology uses PALDO */
+#define BFL_PALDO		0x02000000
+/* Board has an external LNA in 5GHz band */
+#define BFL_EXTLNA_5GHz		0x10000000
+
+/* boardflags2 */
+
+/* Board has an external rxbb regulator */
+#define BFL2_RXBB_INT_REG_DIS	0x00000001
+/* Flag to implement alternative A-band PLL settings */
+#define BFL2_APLL_WAR		0x00000002
+/* Board permits enabling TX Power Control */
+#define BFL2_TXPWRCTRL_EN	0x00000004
+/* Board supports the 2X4 diversity switch */
+#define BFL2_2X4_DIV		0x00000008
+/* Board supports 5G band power gain */
+#define BFL2_5G_PWRGAIN		0x00000010
+/* Board overrides ASPM and Clkreq settings */
+#define BFL2_PCIEWAR_OVR	0x00000020
+#define BFL2_LEGACY		0x00000080
+/* 4321mcm93 board uses Skyworks FEM */
+#define BFL2_SKWRKFEM_BRD	0x00000100
+/* Board has a WAR for clock-harmonic spurs */
+#define BFL2_SPUR_WAR		0x00000200
+/* Flag to narrow G-band PLL loop b/w */
+#define BFL2_GPLL_WAR		0x00000400
+/* Tx CCK pkts on Ant 0 only */
+#define BFL2_SINGLEANT_CCK	0x00001000
+/* WAR to reduce and avoid clock-harmonic spurs in 2G */
+#define BFL2_2G_SPUR_WAR	0x00002000
+/* Flag to widen G-band PLL loop b/w */
+#define BFL2_GPLL_WAR2	        0x00010000
+#define BFL2_IPALVLSHIFT_3P3    0x00020000
+/* Use internal envelope detector for TX IQCAL */
+#define BFL2_INTERNDET_TXIQCAL  0x00040000
+/* Keep the buffered Xtal output from radio "ON". Most drivers will turn it
+ * off without this flag to save power. */
+#define BFL2_XTALBUFOUTEN       0x00080000
+
+/*
+ * board specific GPIO assignment, gpio 0-3 are also customer-configurable
+ * led
+ */
+
+/* bit 9 controls the PA on new 4306 boards */
+#define	BOARD_GPIO_PACTRL	0x200
+#define BOARD_GPIO_12		0x1000
+#define BOARD_GPIO_13		0x2000
+
+/* **** Core type/rev defaults **** */
+#define D11CONF		0x0fffffb0	/* Supported  D11 revs: 4, 5, 7-27
+					 * also need to update wlc.h MAXCOREREV
+					 */
+
+#define NCONF		0x000001ff	/* Supported nphy revs:
+					 *      0       4321a0
+					 *      1       4321a1
+					 *      2       4321b0/b1/c0/c1
+					 *      3       4322a0
+					 *      4       4322a1
+					 *      5       4716a0
+					 *      6       43222a0, 43224a0
+					 *      7       43226a0
+					 *      8       5357a0, 43236a0
+					 */
+
+#define LCNCONF		0x00000007	/* Supported lcnphy revs:
+					 *      0       4313a0, 4336a0, 4330a0
+					 *      1
+					 *      2       4330a0
+					 */
+
+#define SSLPNCONF	0x0000000f	/* Supported sslpnphy revs:
+					 *      0       4329a0/k0
+					 *      1       4329b0/4329C0
+					 *      2       4319a0
+					 *      3       5356a0
+					 */
+
+/********************************************************************
+ * Phy/Core Configuration.  Defines macros to to check core phy/rev *
+ * compile-time configuration.  Defines default core support.       *
+ * ******************************************************************
+ */
+
+/* Basic macros to check a configuration bitmask */
+
+#define CONF_HAS(config, val)	((config) & (1 << (val)))
+#define CONF_MSK(config, mask)	((config) & (mask))
+#define MSK_RANGE(low, hi)	((1 << ((hi)+1)) - (1 << (low)))
+#define CONF_RANGE(config, low, hi) (CONF_MSK(config, MSK_RANGE(low, high)))
+
+#define CONF_IS(config, val)	((config) == (1 << (val)))
+#define CONF_GE(config, val)	((config) & (0-(1 << (val))))
+#define CONF_GT(config, val)	((config) & (0-2*(1 << (val))))
+#define CONF_LT(config, val)	((config) & ((1 << (val))-1))
+#define CONF_LE(config, val)	((config) & (2*(1 << (val))-1))
+
+/* Wrappers for some of the above, specific to config constants */
+
+#define NCONF_HAS(val)	CONF_HAS(NCONF, val)
+#define NCONF_MSK(mask)	CONF_MSK(NCONF, mask)
+#define NCONF_IS(val)	CONF_IS(NCONF, val)
+#define NCONF_GE(val)	CONF_GE(NCONF, val)
+#define NCONF_GT(val)	CONF_GT(NCONF, val)
+#define NCONF_LT(val)	CONF_LT(NCONF, val)
+#define NCONF_LE(val)	CONF_LE(NCONF, val)
+
+#define LCNCONF_HAS(val)	CONF_HAS(LCNCONF, val)
+#define LCNCONF_MSK(mask)	CONF_MSK(LCNCONF, mask)
+#define LCNCONF_IS(val)		CONF_IS(LCNCONF, val)
+#define LCNCONF_GE(val)		CONF_GE(LCNCONF, val)
+#define LCNCONF_GT(val)		CONF_GT(LCNCONF, val)
+#define LCNCONF_LT(val)		CONF_LT(LCNCONF, val)
+#define LCNCONF_LE(val)		CONF_LE(LCNCONF, val)
+
+#define D11CONF_HAS(val) CONF_HAS(D11CONF, val)
+#define D11CONF_MSK(mask) CONF_MSK(D11CONF, mask)
+#define D11CONF_IS(val)	CONF_IS(D11CONF, val)
+#define D11CONF_GE(val)	CONF_GE(D11CONF, val)
+#define D11CONF_GT(val)	CONF_GT(D11CONF, val)
+#define D11CONF_LT(val)	CONF_LT(D11CONF, val)
+#define D11CONF_LE(val)	CONF_LE(D11CONF, val)
+
+#define PHYCONF_HAS(val) CONF_HAS(PHYTYPE, val)
+#define PHYCONF_IS(val)	CONF_IS(PHYTYPE, val)
+
+#define NREV_IS(var, val) \
+	(NCONF_HAS(val) && (NCONF_IS(val) || ((var) == (val))))
+
+#define NREV_GE(var, val) \
+	(NCONF_GE(val) && (!NCONF_LT(val) || ((var) >= (val))))
+
+#define NREV_GT(var, val) \
+	(NCONF_GT(val) && (!NCONF_LE(val) || ((var) > (val))))
+
+#define NREV_LT(var, val) \
+	(NCONF_LT(val) && (!NCONF_GE(val) || ((var) < (val))))
+
+#define NREV_LE(var, val) \
+	(NCONF_LE(val) && (!NCONF_GT(val) || ((var) <= (val))))
+
+#define LCNREV_IS(var, val) \
+	(LCNCONF_HAS(val) && (LCNCONF_IS(val) || ((var) == (val))))
+
+#define LCNREV_GE(var, val) \
+	(LCNCONF_GE(val) && (!LCNCONF_LT(val) || ((var) >= (val))))
+
+#define LCNREV_GT(var, val) \
+	(LCNCONF_GT(val) && (!LCNCONF_LE(val) || ((var) > (val))))
+
+#define LCNREV_LT(var, val) \
+	(LCNCONF_LT(val) && (!LCNCONF_GE(val) || ((var) < (val))))
+
+#define LCNREV_LE(var, val) \
+	(LCNCONF_LE(val) && (!LCNCONF_GT(val) || ((var) <= (val))))
+
+#define D11REV_IS(var, val) \
+	(D11CONF_HAS(val) && (D11CONF_IS(val) || ((var) == (val))))
+
+#define D11REV_GE(var, val) \
+	(D11CONF_GE(val) && (!D11CONF_LT(val) || ((var) >= (val))))
+
+#define D11REV_GT(var, val) \
+	(D11CONF_GT(val) && (!D11CONF_LE(val) || ((var) > (val))))
+
+#define D11REV_LT(var, val) \
+	(D11CONF_LT(val) && (!D11CONF_GE(val) || ((var) < (val))))
+
+#define D11REV_LE(var, val) \
+	(D11CONF_LE(val) && (!D11CONF_GT(val) || ((var) <= (val))))
+
+#define PHYTYPE_IS(var, val)\
+	(PHYCONF_HAS(val) && (PHYCONF_IS(val) || ((var) == (val))))
+
+/* Set up PHYTYPE automatically: (depends on PHY_TYPE_X, from d11.h) */
+
+#define _PHYCONF_N (1 << PHY_TYPE_N)
+#define _PHYCONF_LCN (1 << PHY_TYPE_LCN)
+#define _PHYCONF_SSLPN (1 << PHY_TYPE_SSN)
+
+#define PHYTYPE (_PHYCONF_N | _PHYCONF_LCN | _PHYCONF_SSLPN)
+
+/* Utility macro to identify 802.11n (HT) capable PHYs */
+#define PHYTYPE_11N_CAP(phytype) \
+	(PHYTYPE_IS(phytype, PHY_TYPE_N) ||	\
+	 PHYTYPE_IS(phytype, PHY_TYPE_LCN) || \
+	 PHYTYPE_IS(phytype, PHY_TYPE_SSN))
+
+/* Last but not least: shorter wlc-specific var checks */
+#define BRCMS_ISNPHY(band)		PHYTYPE_IS((band)->phytype, PHY_TYPE_N)
+#define BRCMS_ISLCNPHY(band)	PHYTYPE_IS((band)->phytype, PHY_TYPE_LCN)
+#define BRCMS_ISSSLPNPHY(band)	PHYTYPE_IS((band)->phytype, PHY_TYPE_SSN)
+
+#define BRCMS_PHY_11N_CAP(band)	PHYTYPE_11N_CAP((band)->phytype)
+
+/**********************************************************************
+ * ------------- End of Core phy/rev configuration. ----------------- *
+ * ********************************************************************
+ */
+
+#define BCMMSG(dev, fmt, args...)		\
+do {						\
+	if (brcm_msg_level & BRCM_DL_INFO)	\
+		wiphy_err(dev, "%s: " fmt, __func__, ##args);	\
+} while (0)
+
+#ifdef CONFIG_BCM47XX
+/*
+ * bcm4716 (which includes 4717 & 4718), plus 4706 on PCIe can reorder
+ * transactions. As a fix, a read after write is performed on certain places
+ * in the code. Older chips and the newer 5357 family don't require this fix.
+ */
+#define bcma_wflush16(c, o, v) \
+	({ bcma_write16(c, o, v); (void)bcma_read16(c, o); })
+#else
+#define bcma_wflush16(c, o, v)	bcma_write16(c, o, v)
+#endif				/* CONFIG_BCM47XX */
+
+/* multi-bool data type: set of bools, mbool is true if any is set */
+
+/* set one bool */
+#define mboolset(mb, bit)		((mb) |= (bit))
+/* clear one bool */
+#define mboolclr(mb, bit)		((mb) &= ~(bit))
+/* true if one bool is set */
+#define mboolisset(mb, bit)		(((mb) & (bit)) != 0)
+#define	mboolmaskset(mb, mask, val)	((mb) = (((mb) & ~(mask)) | (val)))
+
+#define CEIL(x, y)		(((x) + ((y)-1)) / (y))
+
+/* forward declarations */
+struct wiphy;
+struct ieee80211_sta;
+struct ieee80211_tx_queue_params;
+struct brcms_info;
+struct brcms_c_info;
+struct brcms_hardware;
+struct brcms_band;
+struct dma_pub;
+struct si_pub;
+struct tx_status;
+struct d11rxhdr;
+struct txpwr_limits;
+
+/* iovar structure */
+struct brcmu_iovar {
+	const char *name;	/* name for lookup and display */
+	u16 varid;	/* id for switch */
+	u16 flags;	/* driver-specific flag bits */
+	u16 type;	/* base type of argument */
+	u16 minlen;	/* min length for buffer vars */
+};
+
+/* brcm_msg_level is a bit vector with defs in defs.h */
+extern u32 brcm_msg_level;
+
+#endif				/* _BRCM_TYPES_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ucode_loader.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ucode_loader.c
new file mode 100644
index 0000000..80e3ccf
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ucode_loader.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <defs.h>
+#include "types.h"
+#include <ucode_loader.h>
+
+enum {
+	D11UCODE_NAMETAG_START = 0,
+	D11LCN0BSINITVALS24,
+	D11LCN0INITVALS24,
+	D11LCN1BSINITVALS24,
+	D11LCN1INITVALS24,
+	D11LCN2BSINITVALS24,
+	D11LCN2INITVALS24,
+	D11N0ABSINITVALS16,
+	D11N0BSINITVALS16,
+	D11N0INITVALS16,
+	D11UCODE_OVERSIGHT16_MIMO,
+	D11UCODE_OVERSIGHT16_MIMOSZ,
+	D11UCODE_OVERSIGHT24_LCN,
+	D11UCODE_OVERSIGHT24_LCNSZ,
+	D11UCODE_OVERSIGHT_BOMMAJOR,
+	D11UCODE_OVERSIGHT_BOMMINOR
+};
+
+int brcms_ucode_data_init(struct brcms_info *wl, struct brcms_ucode *ucode)
+{
+	int rc;
+
+	rc = brcms_check_firmwares(wl);
+
+	rc = rc < 0 ? rc :
+		brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn0bsinitvals24,
+				     D11LCN0BSINITVALS24);
+	rc = rc < 0 ?
+	     rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn0initvals24,
+				       D11LCN0INITVALS24);
+	rc = rc < 0 ?
+	     rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn1bsinitvals24,
+				       D11LCN1BSINITVALS24);
+	rc = rc < 0 ?
+	     rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn1initvals24,
+				       D11LCN1INITVALS24);
+	rc = rc < 0 ? rc :
+		brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn2bsinitvals24,
+				     D11LCN2BSINITVALS24);
+	rc = rc < 0 ?
+	     rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11lcn2initvals24,
+				       D11LCN2INITVALS24);
+	rc = rc < 0 ?
+	     rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11n0absinitvals16,
+				       D11N0ABSINITVALS16);
+	rc = rc < 0 ?
+	     rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11n0bsinitvals16,
+				       D11N0BSINITVALS16);
+	rc = rc < 0 ?
+	     rc : brcms_ucode_init_buf(wl, (void **)&ucode->d11n0initvals16,
+				       D11N0INITVALS16);
+	rc = rc < 0 ?
+	     rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_16_mimo,
+				       D11UCODE_OVERSIGHT16_MIMO);
+	rc = rc < 0 ?
+	     rc : brcms_ucode_init_uint(wl, &ucode->bcm43xx_16_mimosz,
+					D11UCODE_OVERSIGHT16_MIMOSZ);
+	rc = rc < 0 ?
+	     rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_24_lcn,
+				       D11UCODE_OVERSIGHT24_LCN);
+	rc = rc < 0 ?
+	     rc : brcms_ucode_init_uint(wl, &ucode->bcm43xx_24_lcnsz,
+					D11UCODE_OVERSIGHT24_LCNSZ);
+	rc = rc < 0 ?
+	     rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_bommajor,
+				       D11UCODE_OVERSIGHT_BOMMAJOR);
+	rc = rc < 0 ?
+	     rc : brcms_ucode_init_buf(wl, (void **)&ucode->bcm43xx_bomminor,
+				       D11UCODE_OVERSIGHT_BOMMINOR);
+	return rc;
+}
+
+void brcms_ucode_data_free(struct brcms_ucode *ucode)
+{
+	brcms_ucode_free_buf((void *)ucode->d11lcn0bsinitvals24);
+	brcms_ucode_free_buf((void *)ucode->d11lcn0initvals24);
+	brcms_ucode_free_buf((void *)ucode->d11lcn1bsinitvals24);
+	brcms_ucode_free_buf((void *)ucode->d11lcn1initvals24);
+	brcms_ucode_free_buf((void *)ucode->d11lcn2bsinitvals24);
+	brcms_ucode_free_buf((void *)ucode->d11lcn2initvals24);
+	brcms_ucode_free_buf((void *)ucode->d11n0absinitvals16);
+	brcms_ucode_free_buf((void *)ucode->d11n0bsinitvals16);
+	brcms_ucode_free_buf((void *)ucode->d11n0initvals16);
+	brcms_ucode_free_buf((void *)ucode->bcm43xx_16_mimo);
+	brcms_ucode_free_buf((void *)ucode->bcm43xx_24_lcn);
+	brcms_ucode_free_buf((void *)ucode->bcm43xx_bommajor);
+	brcms_ucode_free_buf((void *)ucode->bcm43xx_bomminor);
+}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ucode_loader.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ucode_loader.h
new file mode 100644
index 0000000..c87dd89
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ucode_loader.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef	_BRCM_UCODE_H_
+#define	_BRCM_UCODE_H_
+
+#include "types.h"		/* forward structure declarations */
+
+#define MIN_FW_SIZE 40000	/* minimum firmware file size in bytes */
+#define MAX_FW_SIZE 150000
+
+#define UCODE_LOADER_API_VER 0
+
+struct d11init;
+
+struct brcms_ucode {
+	struct d11init *d11lcn0bsinitvals24;
+	struct d11init *d11lcn0initvals24;
+	struct d11init *d11lcn1bsinitvals24;
+	struct d11init *d11lcn1initvals24;
+	struct d11init *d11lcn2bsinitvals24;
+	struct d11init *d11lcn2initvals24;
+	struct d11init *d11n0absinitvals16;
+	struct d11init *d11n0bsinitvals16;
+	struct d11init *d11n0initvals16;
+	__le32 *bcm43xx_16_mimo;
+	size_t bcm43xx_16_mimosz;
+	__le32 *bcm43xx_24_lcn;
+	size_t bcm43xx_24_lcnsz;
+	u32 *bcm43xx_bommajor;
+	u32 *bcm43xx_bomminor;
+};
+
+int brcms_ucode_data_init(struct brcms_info *wl, struct brcms_ucode *ucode);
+
+void brcms_ucode_data_free(struct brcms_ucode *ucode);
+
+int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, unsigned int idx);
+int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes,
+			  unsigned int idx);
+void brcms_ucode_free_buf(void *);
+int  brcms_check_firmwares(struct brcms_info *wl);
+
+#endif	/* _BRCM_UCODE_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmutil/Makefile b/drivers/net/wireless/broadcom/brcm80211/brcmutil/Makefile
new file mode 100644
index 0000000..256c91f
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmutil/Makefile
@@ -0,0 +1,23 @@
+#
+# Makefile fragment for Broadcom 802.11n Networking Device Driver Utilities
+#
+# Copyright (c) 2011 Broadcom Corporation
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ccflags-y :=				\
+	-Idrivers/net/wireless/broadcom/brcm80211/brcmutil \
+	-Idrivers/net/wireless/broadcom/brcm80211/include
+
+obj-$(CONFIG_BRCMUTIL)	+= brcmutil.o
+brcmutil-objs	= utils.o d11.o
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmutil/d11.c b/drivers/net/wireless/broadcom/brcm80211/brcmutil/d11.c
new file mode 100644
index 0000000..eb5db94
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmutil/d11.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2013 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*********************channel spec common functions*********************/
+
+#include <linux/module.h>
+
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+#include <brcmu_d11.h>
+
+static u16 d11n_sb(enum brcmu_chan_sb sb)
+{
+	switch (sb) {
+	case BRCMU_CHAN_SB_NONE:
+		return BRCMU_CHSPEC_D11N_SB_N;
+	case BRCMU_CHAN_SB_L:
+		return BRCMU_CHSPEC_D11N_SB_L;
+	case BRCMU_CHAN_SB_U:
+		return BRCMU_CHSPEC_D11N_SB_U;
+	default:
+		WARN_ON(1);
+	}
+	return 0;
+}
+
+static u16 d11n_bw(enum brcmu_chan_bw bw)
+{
+	switch (bw) {
+	case BRCMU_CHAN_BW_20:
+		return BRCMU_CHSPEC_D11N_BW_20;
+	case BRCMU_CHAN_BW_40:
+		return BRCMU_CHSPEC_D11N_BW_40;
+	default:
+		WARN_ON(1);
+	}
+	return 0;
+}
+
+static void brcmu_d11n_encchspec(struct brcmu_chan *ch)
+{
+	if (ch->bw == BRCMU_CHAN_BW_20)
+		ch->sb = BRCMU_CHAN_SB_NONE;
+
+	ch->chspec = 0;
+	brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_CH_MASK,
+			BRCMU_CHSPEC_CH_SHIFT, ch->chnum);
+	brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11N_SB_MASK,
+			0, d11n_sb(ch->sb));
+	brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11N_BW_MASK,
+			0, d11n_bw(ch->bw));
+
+	if (ch->chnum <= CH_MAX_2G_CHANNEL)
+		ch->chspec |= BRCMU_CHSPEC_D11N_BND_2G;
+	else
+		ch->chspec |= BRCMU_CHSPEC_D11N_BND_5G;
+}
+
+static u16 d11ac_bw(enum brcmu_chan_bw bw)
+{
+	switch (bw) {
+	case BRCMU_CHAN_BW_20:
+		return BRCMU_CHSPEC_D11AC_BW_20;
+	case BRCMU_CHAN_BW_40:
+		return BRCMU_CHSPEC_D11AC_BW_40;
+	case BRCMU_CHAN_BW_80:
+		return BRCMU_CHSPEC_D11AC_BW_80;
+	case BRCMU_CHAN_BW_160:
+		return BRCMU_CHSPEC_D11AC_BW_160;
+	default:
+		WARN_ON(1);
+	}
+	return 0;
+}
+
+static void brcmu_d11ac_encchspec(struct brcmu_chan *ch)
+{
+	if (ch->bw == BRCMU_CHAN_BW_20 || ch->sb == BRCMU_CHAN_SB_NONE)
+		ch->sb = BRCMU_CHAN_SB_L;
+
+	brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_CH_MASK,
+			BRCMU_CHSPEC_CH_SHIFT, ch->chnum);
+	brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11AC_SB_MASK,
+			BRCMU_CHSPEC_D11AC_SB_SHIFT, ch->sb);
+	brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11AC_BW_MASK,
+			0, d11ac_bw(ch->bw));
+
+	ch->chspec &= ~BRCMU_CHSPEC_D11AC_BND_MASK;
+	if (ch->chnum <= CH_MAX_2G_CHANNEL)
+		ch->chspec |= BRCMU_CHSPEC_D11AC_BND_2G;
+	else
+		ch->chspec |= BRCMU_CHSPEC_D11AC_BND_5G;
+}
+
+static void brcmu_d11n_decchspec(struct brcmu_chan *ch)
+{
+	u16 val;
+
+	ch->chnum = (u8)(ch->chspec & BRCMU_CHSPEC_CH_MASK);
+	ch->control_ch_num = ch->chnum;
+
+	switch (ch->chspec & BRCMU_CHSPEC_D11N_BW_MASK) {
+	case BRCMU_CHSPEC_D11N_BW_20:
+		ch->bw = BRCMU_CHAN_BW_20;
+		ch->sb = BRCMU_CHAN_SB_NONE;
+		break;
+	case BRCMU_CHSPEC_D11N_BW_40:
+		ch->bw = BRCMU_CHAN_BW_40;
+		val = ch->chspec & BRCMU_CHSPEC_D11N_SB_MASK;
+		if (val == BRCMU_CHSPEC_D11N_SB_L) {
+			ch->sb = BRCMU_CHAN_SB_L;
+			ch->control_ch_num -= CH_10MHZ_APART;
+		} else {
+			ch->sb = BRCMU_CHAN_SB_U;
+			ch->control_ch_num += CH_10MHZ_APART;
+		}
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		break;
+	}
+
+	switch (ch->chspec & BRCMU_CHSPEC_D11N_BND_MASK) {
+	case BRCMU_CHSPEC_D11N_BND_5G:
+		ch->band = BRCMU_CHAN_BAND_5G;
+		break;
+	case BRCMU_CHSPEC_D11N_BND_2G:
+		ch->band = BRCMU_CHAN_BAND_2G;
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		break;
+	}
+}
+
+static void brcmu_d11ac_decchspec(struct brcmu_chan *ch)
+{
+	u16 val;
+
+	ch->chnum = (u8)(ch->chspec & BRCMU_CHSPEC_CH_MASK);
+	ch->control_ch_num = ch->chnum;
+
+	switch (ch->chspec & BRCMU_CHSPEC_D11AC_BW_MASK) {
+	case BRCMU_CHSPEC_D11AC_BW_20:
+		ch->bw = BRCMU_CHAN_BW_20;
+		ch->sb = BRCMU_CHAN_SB_NONE;
+		break;
+	case BRCMU_CHSPEC_D11AC_BW_40:
+		ch->bw = BRCMU_CHAN_BW_40;
+		val = ch->chspec & BRCMU_CHSPEC_D11AC_SB_MASK;
+		if (val == BRCMU_CHSPEC_D11AC_SB_L) {
+			ch->sb = BRCMU_CHAN_SB_L;
+			ch->control_ch_num -= CH_10MHZ_APART;
+		} else if (val == BRCMU_CHSPEC_D11AC_SB_U) {
+			ch->sb = BRCMU_CHAN_SB_U;
+			ch->control_ch_num += CH_10MHZ_APART;
+		} else {
+			WARN_ON_ONCE(1);
+		}
+		break;
+	case BRCMU_CHSPEC_D11AC_BW_80:
+		ch->bw = BRCMU_CHAN_BW_80;
+		ch->sb = brcmu_maskget16(ch->chspec, BRCMU_CHSPEC_D11AC_SB_MASK,
+					 BRCMU_CHSPEC_D11AC_SB_SHIFT);
+		switch (ch->sb) {
+		case BRCMU_CHAN_SB_LL:
+			ch->control_ch_num -= CH_30MHZ_APART;
+			break;
+		case BRCMU_CHAN_SB_LU:
+			ch->control_ch_num -= CH_10MHZ_APART;
+			break;
+		case BRCMU_CHAN_SB_UL:
+			ch->control_ch_num += CH_10MHZ_APART;
+			break;
+		case BRCMU_CHAN_SB_UU:
+			ch->control_ch_num += CH_30MHZ_APART;
+			break;
+		default:
+			WARN_ON_ONCE(1);
+			break;
+		}
+		break;
+	case BRCMU_CHSPEC_D11AC_BW_160:
+		ch->bw = BRCMU_CHAN_BW_160;
+		ch->sb = brcmu_maskget16(ch->chspec, BRCMU_CHSPEC_D11AC_SB_MASK,
+					 BRCMU_CHSPEC_D11AC_SB_SHIFT);
+		switch (ch->sb) {
+		case BRCMU_CHAN_SB_LLL:
+			ch->control_ch_num -= CH_70MHZ_APART;
+			break;
+		case BRCMU_CHAN_SB_LLU:
+			ch->control_ch_num -= CH_50MHZ_APART;
+			break;
+		case BRCMU_CHAN_SB_LUL:
+			ch->control_ch_num -= CH_30MHZ_APART;
+			break;
+		case BRCMU_CHAN_SB_LUU:
+			ch->control_ch_num -= CH_10MHZ_APART;
+			break;
+		case BRCMU_CHAN_SB_ULL:
+			ch->control_ch_num += CH_10MHZ_APART;
+			break;
+		case BRCMU_CHAN_SB_ULU:
+			ch->control_ch_num += CH_30MHZ_APART;
+			break;
+		case BRCMU_CHAN_SB_UUL:
+			ch->control_ch_num += CH_50MHZ_APART;
+			break;
+		case BRCMU_CHAN_SB_UUU:
+			ch->control_ch_num += CH_70MHZ_APART;
+			break;
+		default:
+			WARN_ON_ONCE(1);
+			break;
+		}
+		break;
+	case BRCMU_CHSPEC_D11AC_BW_8080:
+	default:
+		WARN_ON_ONCE(1);
+		break;
+	}
+
+	switch (ch->chspec & BRCMU_CHSPEC_D11AC_BND_MASK) {
+	case BRCMU_CHSPEC_D11AC_BND_5G:
+		ch->band = BRCMU_CHAN_BAND_5G;
+		break;
+	case BRCMU_CHSPEC_D11AC_BND_2G:
+		ch->band = BRCMU_CHAN_BAND_2G;
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		break;
+	}
+}
+
+void brcmu_d11_attach(struct brcmu_d11inf *d11inf)
+{
+	if (d11inf->io_type == BRCMU_D11N_IOTYPE) {
+		d11inf->encchspec = brcmu_d11n_encchspec;
+		d11inf->decchspec = brcmu_d11n_decchspec;
+	} else {
+		d11inf->encchspec = brcmu_d11ac_encchspec;
+		d11inf->decchspec = brcmu_d11ac_decchspec;
+	}
+}
+EXPORT_SYMBOL(brcmu_d11_attach);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c b/drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c
new file mode 100644
index 0000000..0543607
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/netdevice.h>
+#include <linux/module.h>
+
+#include <brcmu_utils.h>
+
+MODULE_AUTHOR("Broadcom Corporation");
+MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver utilities.");
+MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards");
+MODULE_LICENSE("Dual BSD/GPL");
+
+struct sk_buff *brcmu_pkt_buf_get_skb(uint len)
+{
+	struct sk_buff *skb;
+
+	skb = dev_alloc_skb(len);
+	if (skb) {
+		skb_put(skb, len);
+		skb->priority = 0;
+	}
+
+	return skb;
+}
+EXPORT_SYMBOL(brcmu_pkt_buf_get_skb);
+
+/* Free the driver packet. Free the tag if present */
+void brcmu_pkt_buf_free_skb(struct sk_buff *skb)
+{
+	if (!skb)
+		return;
+
+	WARN_ON(skb->next);
+	dev_kfree_skb_any(skb);
+}
+EXPORT_SYMBOL(brcmu_pkt_buf_free_skb);
+
+/*
+ * osl multiple-precedence packet queue
+ * hi_prec is always >= the number of the highest non-empty precedence
+ */
+struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec,
+				      struct sk_buff *p)
+{
+	struct sk_buff_head *q;
+
+	if (pktq_full(pq) || pktq_pfull(pq, prec))
+		return NULL;
+
+	q = &pq->q[prec].skblist;
+	skb_queue_tail(q, p);
+	pq->len++;
+
+	if (pq->hi_prec < prec)
+		pq->hi_prec = (u8) prec;
+
+	return p;
+}
+EXPORT_SYMBOL(brcmu_pktq_penq);
+
+struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec,
+					   struct sk_buff *p)
+{
+	struct sk_buff_head *q;
+
+	if (pktq_full(pq) || pktq_pfull(pq, prec))
+		return NULL;
+
+	q = &pq->q[prec].skblist;
+	skb_queue_head(q, p);
+	pq->len++;
+
+	if (pq->hi_prec < prec)
+		pq->hi_prec = (u8) prec;
+
+	return p;
+}
+EXPORT_SYMBOL(brcmu_pktq_penq_head);
+
+struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec)
+{
+	struct sk_buff_head *q;
+	struct sk_buff *p;
+
+	q = &pq->q[prec].skblist;
+	p = skb_dequeue(q);
+	if (p == NULL)
+		return NULL;
+
+	pq->len--;
+	return p;
+}
+EXPORT_SYMBOL(brcmu_pktq_pdeq);
+
+/*
+ * precedence based dequeue with match function. Passing a NULL pointer
+ * for the match function parameter is considered to be a wildcard so
+ * any packet on the queue is returned. In that case it is no different
+ * from brcmu_pktq_pdeq() above.
+ */
+struct sk_buff *brcmu_pktq_pdeq_match(struct pktq *pq, int prec,
+				      bool (*match_fn)(struct sk_buff *skb,
+						       void *arg), void *arg)
+{
+	struct sk_buff_head *q;
+	struct sk_buff *p, *next;
+
+	q = &pq->q[prec].skblist;
+	skb_queue_walk_safe(q, p, next) {
+		if (match_fn == NULL || match_fn(p, arg)) {
+			skb_unlink(p, q);
+			pq->len--;
+			return p;
+		}
+	}
+	return NULL;
+}
+EXPORT_SYMBOL(brcmu_pktq_pdeq_match);
+
+struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec)
+{
+	struct sk_buff_head *q;
+	struct sk_buff *p;
+
+	q = &pq->q[prec].skblist;
+	p = skb_dequeue_tail(q);
+	if (p == NULL)
+		return NULL;
+
+	pq->len--;
+	return p;
+}
+EXPORT_SYMBOL(brcmu_pktq_pdeq_tail);
+
+void
+brcmu_pktq_pflush(struct pktq *pq, int prec, bool dir,
+		  bool (*fn)(struct sk_buff *, void *), void *arg)
+{
+	struct sk_buff_head *q;
+	struct sk_buff *p, *next;
+
+	q = &pq->q[prec].skblist;
+	skb_queue_walk_safe(q, p, next) {
+		if (fn == NULL || (*fn) (p, arg)) {
+			skb_unlink(p, q);
+			brcmu_pkt_buf_free_skb(p);
+			pq->len--;
+		}
+	}
+}
+EXPORT_SYMBOL(brcmu_pktq_pflush);
+
+void brcmu_pktq_flush(struct pktq *pq, bool dir,
+		      bool (*fn)(struct sk_buff *, void *), void *arg)
+{
+	int prec;
+	for (prec = 0; prec < pq->num_prec; prec++)
+		brcmu_pktq_pflush(pq, prec, dir, fn, arg);
+}
+EXPORT_SYMBOL(brcmu_pktq_flush);
+
+void brcmu_pktq_init(struct pktq *pq, int num_prec, int max_len)
+{
+	int prec;
+
+	/* pq is variable size; only zero out what's requested */
+	memset(pq, 0,
+	      offsetof(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec));
+
+	pq->num_prec = (u16) num_prec;
+
+	pq->max = (u16) max_len;
+
+	for (prec = 0; prec < num_prec; prec++) {
+		pq->q[prec].max = pq->max;
+		skb_queue_head_init(&pq->q[prec].skblist);
+	}
+}
+EXPORT_SYMBOL(brcmu_pktq_init);
+
+struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out)
+{
+	int prec;
+
+	if (pq->len == 0)
+		return NULL;
+
+	for (prec = 0; prec < pq->hi_prec; prec++)
+		if (!skb_queue_empty(&pq->q[prec].skblist))
+			break;
+
+	if (prec_out)
+		*prec_out = prec;
+
+	return skb_peek_tail(&pq->q[prec].skblist);
+}
+EXPORT_SYMBOL(brcmu_pktq_peek_tail);
+
+/* Return sum of lengths of a specific set of precedences */
+int brcmu_pktq_mlen(struct pktq *pq, uint prec_bmp)
+{
+	int prec, len;
+
+	len = 0;
+
+	for (prec = 0; prec <= pq->hi_prec; prec++)
+		if (prec_bmp & (1 << prec))
+			len += pq->q[prec].skblist.qlen;
+
+	return len;
+}
+EXPORT_SYMBOL(brcmu_pktq_mlen);
+
+/* Priority dequeue from a specific set of precedences */
+struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp,
+				      int *prec_out)
+{
+	struct sk_buff_head *q;
+	struct sk_buff *p;
+	int prec;
+
+	if (pq->len == 0)
+		return NULL;
+
+	while ((prec = pq->hi_prec) > 0 &&
+	       skb_queue_empty(&pq->q[prec].skblist))
+		pq->hi_prec--;
+
+	while ((prec_bmp & (1 << prec)) == 0 ||
+	       skb_queue_empty(&pq->q[prec].skblist))
+		if (prec-- == 0)
+			return NULL;
+
+	q = &pq->q[prec].skblist;
+	p = skb_dequeue(q);
+	if (p == NULL)
+		return NULL;
+
+	pq->len--;
+
+	if (prec_out)
+		*prec_out = prec;
+
+	return p;
+}
+EXPORT_SYMBOL(brcmu_pktq_mdeq);
+
+/* Produce a human-readable string for boardrev */
+char *brcmu_boardrev_str(u32 brev, char *buf)
+{
+	char c;
+
+	if (brev < 0x100) {
+		snprintf(buf, BRCMU_BOARDREV_LEN, "%d.%d",
+			 (brev & 0xf0) >> 4, brev & 0xf);
+	} else {
+		c = (brev & 0xf000) == 0x1000 ? 'P' : 'A';
+		snprintf(buf, BRCMU_BOARDREV_LEN, "%c%03x", c, brev & 0xfff);
+	}
+	return buf;
+}
+EXPORT_SYMBOL(brcmu_boardrev_str);
+
+char *brcmu_dotrev_str(u32 dotrev, char *buf)
+{
+	u8 dotval[4];
+
+	if (!dotrev) {
+		snprintf(buf, BRCMU_DOTREV_LEN, "unknown");
+		return buf;
+	}
+	dotval[0] = (dotrev >> 24) & 0xFF;
+	dotval[1] = (dotrev >> 16) & 0xFF;
+	dotval[2] = (dotrev >> 8) & 0xFF;
+	dotval[3] = dotrev & 0xFF;
+
+	if (dotval[3])
+		snprintf(buf, BRCMU_DOTREV_LEN, "%d.%d.%d.%d", dotval[0],
+			dotval[1], dotval[2], dotval[3]);
+	else if (dotval[2])
+		snprintf(buf, BRCMU_DOTREV_LEN, "%d.%d.%d", dotval[0],
+			dotval[1], dotval[2]);
+	else
+		snprintf(buf, BRCMU_DOTREV_LEN, "%d.%d", dotval[0],
+			dotval[1]);
+
+	return buf;
+}
+EXPORT_SYMBOL(brcmu_dotrev_str);
+
+#if defined(DEBUG)
+/* pretty hex print a pkt buffer chain */
+void brcmu_prpkt(const char *msg, struct sk_buff *p0)
+{
+	struct sk_buff *p;
+
+	if (msg && (msg[0] != '\0'))
+		pr_debug("%s:\n", msg);
+
+	for (p = p0; p; p = p->next)
+		print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, p->data, p->len);
+}
+EXPORT_SYMBOL(brcmu_prpkt);
+
+void brcmu_dbg_hex_dump(const void *data, size_t size, const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	pr_debug("%pV", &vaf);
+
+	va_end(args);
+
+	print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, data, size);
+}
+EXPORT_SYMBOL(brcmu_dbg_hex_dump);
+
+#endif				/* defined(DEBUG) */
diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
new file mode 100644
index 0000000..686f7a8
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_BRCM_HW_IDS_H_
+#define	_BRCM_HW_IDS_H_
+
+#include <linux/pci_ids.h>
+#include <linux/mmc/sdio_ids.h>
+
+#define BRCM_USB_VENDOR_ID_BROADCOM	0x0a5c
+#define BRCM_USB_VENDOR_ID_LG		0x043e
+#define BRCM_USB_VENDOR_ID_LINKSYS	0x13b1
+#define CY_USB_VENDOR_ID_CYPRESS	0x04b4
+#define BRCM_PCIE_VENDOR_ID_BROADCOM	PCI_VENDOR_ID_BROADCOM
+
+/* Chipcommon Core Chip IDs */
+#define BRCM_CC_43143_CHIP_ID		43143
+#define BRCM_CC_43235_CHIP_ID		43235
+#define BRCM_CC_43236_CHIP_ID		43236
+#define BRCM_CC_43238_CHIP_ID		43238
+#define BRCM_CC_43241_CHIP_ID		0x4324
+#define BRCM_CC_43242_CHIP_ID		43242
+#define BRCM_CC_4329_CHIP_ID		0x4329
+#define BRCM_CC_4330_CHIP_ID		0x4330
+#define BRCM_CC_4334_CHIP_ID		0x4334
+#define BRCM_CC_43340_CHIP_ID		43340
+#define BRCM_CC_43341_CHIP_ID		43341
+#define BRCM_CC_43362_CHIP_ID		43362
+#define BRCM_CC_4335_CHIP_ID		0x4335
+#define BRCM_CC_4339_CHIP_ID		0x4339
+#define BRCM_CC_43430_CHIP_ID		43430
+#define BRCM_CC_4345_CHIP_ID		0x4345
+#define BRCM_CC_43465_CHIP_ID		43465
+#define BRCM_CC_4350_CHIP_ID		0x4350
+#define BRCM_CC_43525_CHIP_ID		43525
+#define BRCM_CC_4354_CHIP_ID		0x4354
+#define BRCM_CC_4356_CHIP_ID		0x4356
+#define BRCM_CC_43566_CHIP_ID		43566
+#define BRCM_CC_43567_CHIP_ID		43567
+#define BRCM_CC_43569_CHIP_ID		43569
+#define BRCM_CC_43570_CHIP_ID		43570
+#define BRCM_CC_4358_CHIP_ID		0x4358
+#define BRCM_CC_4359_CHIP_ID		0x4359
+#define BRCM_CC_43602_CHIP_ID		43602
+#define BRCM_CC_4365_CHIP_ID		0x4365
+#define BRCM_CC_4366_CHIP_ID		0x4366
+#define BRCM_CC_43664_CHIP_ID		43664
+#define BRCM_CC_4371_CHIP_ID		0x4371
+#define CY_CC_4373_CHIP_ID		0x4373
+
+/* USB Device IDs */
+#define BRCM_USB_43143_DEVICE_ID	0xbd1e
+#define BRCM_USB_43235_LINKSYS_DEVICE_ID	0x0039
+#define BRCM_USB_43236_DEVICE_ID	0xbd17
+#define BRCM_USB_43242_DEVICE_ID	0xbd1f
+#define BRCM_USB_43242_LG_DEVICE_ID	0x3101
+#define BRCM_USB_43569_DEVICE_ID	0xbd27
+#define BRCM_USB_BCMFW_DEVICE_ID	0x0bdc
+#define CY_USB_4373_DEVICE_ID		0xbd29
+
+/* PCIE Device IDs */
+#define BRCM_PCIE_4350_DEVICE_ID	0x43a3
+#define BRCM_PCIE_4354_DEVICE_ID	0x43df
+#define BRCM_PCIE_4356_DEVICE_ID	0x43ec
+#define BRCM_PCIE_43567_DEVICE_ID	0x43d3
+#define BRCM_PCIE_43570_DEVICE_ID	0x43d9
+#define BRCM_PCIE_4358_DEVICE_ID	0x43e9
+#define BRCM_PCIE_4359_DEVICE_ID	0x43ef
+#define BRCM_PCIE_43602_DEVICE_ID	0x43ba
+#define BRCM_PCIE_43602_2G_DEVICE_ID	0x43bb
+#define BRCM_PCIE_43602_5G_DEVICE_ID	0x43bc
+#define BRCM_PCIE_43602_RAW_DEVICE_ID	43602
+#define BRCM_PCIE_4365_DEVICE_ID	0x43ca
+#define BRCM_PCIE_4365_2G_DEVICE_ID	0x43cb
+#define BRCM_PCIE_4365_5G_DEVICE_ID	0x43cc
+#define BRCM_PCIE_4366_DEVICE_ID	0x43c3
+#define BRCM_PCIE_4366_2G_DEVICE_ID	0x43c4
+#define BRCM_PCIE_4366_5G_DEVICE_ID	0x43c5
+#define BRCM_PCIE_4371_DEVICE_ID	0x440d
+
+
+/* brcmsmac IDs */
+#define BCM4313_D11N2G_ID	0x4727	/* 4313 802.11n 2.4G device */
+#define BCM43224_D11N_ID	0x4353	/* 43224 802.11n dualband device */
+#define BCM43224_D11N_ID_VEN1	0x0576	/* Vendor specific 43224 802.11n db */
+#define BCM43225_D11N2G_ID	0x4357	/* 43225 802.11n 2.4GHz device */
+#define BCM43236_D11N_ID	0x4346	/* 43236 802.11n dualband device */
+#define BCM43236_D11N2G_ID	0x4347	/* 43236 802.11n 2.4GHz device */
+
+#define BCM4313_CHIP_ID		0x4313
+#define BCM43224_CHIP_ID	43224
+
+#endif				/* _BRCM_HW_IDS_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_d11.h b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_d11.h
new file mode 100644
index 0000000..8b8b2ec
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_d11.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_BRCMU_D11_H_
+#define	_BRCMU_D11_H_
+
+/* d11 io type */
+#define BRCMU_D11N_IOTYPE		1
+#define BRCMU_D11AC_IOTYPE		2
+
+/* A chanspec (channel specification) holds the channel number, band,
+ * bandwidth and control sideband
+ */
+
+/* chanspec binary format */
+
+#define BRCMU_CHSPEC_INVALID		255
+/* bit 0~7 channel number
+ * for 80+80 channels: bit 0~3 low channel id, bit 4~7 high channel id
+ */
+#define BRCMU_CHSPEC_CH_MASK		0x00ff
+#define BRCMU_CHSPEC_CH_SHIFT		0
+#define BRCMU_CHSPEC_CHL_MASK		0x000f
+#define BRCMU_CHSPEC_CHL_SHIFT		0
+#define BRCMU_CHSPEC_CHH_MASK		0x00f0
+#define BRCMU_CHSPEC_CHH_SHIFT		4
+
+/* bit 8~16 for dot 11n IO types
+ * bit 8~9 sideband
+ * bit 10~11 bandwidth
+ * bit 12~13 spectral band
+ * bit 14~15 not used
+ */
+#define BRCMU_CHSPEC_D11N_SB_MASK	0x0300
+#define BRCMU_CHSPEC_D11N_SB_SHIFT	8
+#define  BRCMU_CHSPEC_D11N_SB_L		0x0100	/* control lower */
+#define  BRCMU_CHSPEC_D11N_SB_U		0x0200	/* control upper */
+#define  BRCMU_CHSPEC_D11N_SB_N		0x0300	/* none */
+#define BRCMU_CHSPEC_D11N_BW_MASK	0x0c00
+#define BRCMU_CHSPEC_D11N_BW_SHIFT	10
+#define  BRCMU_CHSPEC_D11N_BW_10	0x0400
+#define  BRCMU_CHSPEC_D11N_BW_20	0x0800
+#define  BRCMU_CHSPEC_D11N_BW_40	0x0c00
+#define BRCMU_CHSPEC_D11N_BND_MASK	0x3000
+#define BRCMU_CHSPEC_D11N_BND_SHIFT	12
+#define  BRCMU_CHSPEC_D11N_BND_5G	0x1000
+#define  BRCMU_CHSPEC_D11N_BND_2G	0x2000
+
+/* bit 8~16 for dot 11ac IO types
+ * bit 8~10 sideband
+ * bit 11~13 bandwidth
+ * bit 14~15 spectral band
+ */
+#define BRCMU_CHSPEC_D11AC_SB_MASK	0x0700
+#define BRCMU_CHSPEC_D11AC_SB_SHIFT	8
+#define  BRCMU_CHSPEC_D11AC_SB_LLL	0x0000
+#define  BRCMU_CHSPEC_D11AC_SB_LLU	0x0100
+#define  BRCMU_CHSPEC_D11AC_SB_LUL	0x0200
+#define  BRCMU_CHSPEC_D11AC_SB_LUU	0x0300
+#define  BRCMU_CHSPEC_D11AC_SB_ULL	0x0400
+#define  BRCMU_CHSPEC_D11AC_SB_ULU	0x0500
+#define  BRCMU_CHSPEC_D11AC_SB_UUL	0x0600
+#define  BRCMU_CHSPEC_D11AC_SB_UUU	0x0700
+#define  BRCMU_CHSPEC_D11AC_SB_LL	BRCMU_CHSPEC_D11AC_SB_LLL
+#define  BRCMU_CHSPEC_D11AC_SB_LU	BRCMU_CHSPEC_D11AC_SB_LLU
+#define  BRCMU_CHSPEC_D11AC_SB_UL	BRCMU_CHSPEC_D11AC_SB_LUL
+#define  BRCMU_CHSPEC_D11AC_SB_UU	BRCMU_CHSPEC_D11AC_SB_LUU
+#define  BRCMU_CHSPEC_D11AC_SB_L	BRCMU_CHSPEC_D11AC_SB_LLL
+#define  BRCMU_CHSPEC_D11AC_SB_U	BRCMU_CHSPEC_D11AC_SB_LLU
+#define BRCMU_CHSPEC_D11AC_BW_MASK	0x3800
+#define BRCMU_CHSPEC_D11AC_BW_SHIFT	11
+#define  BRCMU_CHSPEC_D11AC_BW_5	0x0000
+#define  BRCMU_CHSPEC_D11AC_BW_10	0x0800
+#define  BRCMU_CHSPEC_D11AC_BW_20	0x1000
+#define  BRCMU_CHSPEC_D11AC_BW_40	0x1800
+#define  BRCMU_CHSPEC_D11AC_BW_80	0x2000
+#define  BRCMU_CHSPEC_D11AC_BW_160	0x2800
+#define  BRCMU_CHSPEC_D11AC_BW_8080	0x3000
+#define BRCMU_CHSPEC_D11AC_BND_MASK	0xc000
+#define BRCMU_CHSPEC_D11AC_BND_SHIFT	14
+#define  BRCMU_CHSPEC_D11AC_BND_2G	0x0000
+#define  BRCMU_CHSPEC_D11AC_BND_3G	0x4000
+#define  BRCMU_CHSPEC_D11AC_BND_4G	0x8000
+#define  BRCMU_CHSPEC_D11AC_BND_5G	0xc000
+
+#define BRCMU_CHAN_BAND_2G		0
+#define BRCMU_CHAN_BAND_5G		1
+
+enum brcmu_chan_bw {
+	BRCMU_CHAN_BW_20,
+	BRCMU_CHAN_BW_40,
+	BRCMU_CHAN_BW_80,
+	BRCMU_CHAN_BW_80P80,
+	BRCMU_CHAN_BW_160,
+};
+
+enum brcmu_chan_sb {
+	BRCMU_CHAN_SB_NONE = -1,
+	BRCMU_CHAN_SB_LLL,
+	BRCMU_CHAN_SB_LLU,
+	BRCMU_CHAN_SB_LUL,
+	BRCMU_CHAN_SB_LUU,
+	BRCMU_CHAN_SB_ULL,
+	BRCMU_CHAN_SB_ULU,
+	BRCMU_CHAN_SB_UUL,
+	BRCMU_CHAN_SB_UUU,
+	BRCMU_CHAN_SB_L = BRCMU_CHAN_SB_LLL,
+	BRCMU_CHAN_SB_U = BRCMU_CHAN_SB_LLU,
+	BRCMU_CHAN_SB_LL = BRCMU_CHAN_SB_LLL,
+	BRCMU_CHAN_SB_LU = BRCMU_CHAN_SB_LLU,
+	BRCMU_CHAN_SB_UL = BRCMU_CHAN_SB_LUL,
+	BRCMU_CHAN_SB_UU = BRCMU_CHAN_SB_LUU,
+};
+
+/**
+ * struct brcmu_chan - stores channel formats
+ *
+ * This structure can be used with functions translating chanspec into generic
+ * channel info and the other way.
+ *
+ * @chspec: firmware specific format
+ * @chnum: center channel number
+ * @control_ch_num: control channel number
+ * @band: frequency band
+ * @bw: channel width
+ * @sb: control sideband (location of control channel against the center one)
+ */
+struct brcmu_chan {
+	u16 chspec;
+	u8 chnum;
+	u8 control_ch_num;
+	u8 band;
+	enum brcmu_chan_bw bw;
+	enum brcmu_chan_sb sb;
+};
+
+/**
+ * struct brcmu_d11inf - provides functions translating channel format
+ *
+ * @io_type: determines version of channel format used by firmware
+ * @encchspec: encodes channel info into a chanspec, requires center channel
+ *	number, ignores control one
+ * @decchspec: decodes chanspec into generic info
+ */
+struct brcmu_d11inf {
+	u8 io_type;
+
+	void (*encchspec)(struct brcmu_chan *ch);
+	void (*decchspec)(struct brcmu_chan *ch);
+};
+
+void brcmu_d11_attach(struct brcmu_d11inf *d11inf);
+
+#endif	/* _BRCMU_CHANNELS_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_utils.h b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_utils.h
new file mode 100644
index 0000000..4196952
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_utils.h
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_BRCMU_UTILS_H_
+#define	_BRCMU_UTILS_H_
+
+#include <linux/skbuff.h>
+
+/*
+ * Spin at most 'us' microseconds while 'exp' is true.
+ * Caller should explicitly test 'exp' when this completes
+ * and take appropriate error action if 'exp' is still true.
+ */
+#define SPINWAIT(exp, us) { \
+	uint countdown = (us) + 9; \
+	while ((exp) && (countdown >= 10)) {\
+		udelay(10); \
+		countdown -= 10; \
+	} \
+}
+
+/* osl multi-precedence packet queue */
+#define PKTQ_LEN_DEFAULT        128	/* Max 128 packets */
+#define PKTQ_MAX_PREC           16	/* Maximum precedence levels */
+
+#define BCME_STRLEN		64	/* Max string length for BCM errors */
+
+/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */
+#define	PKTBUFSZ	2048
+
+#ifndef setbit
+#ifndef NBBY			/* the BSD family defines NBBY */
+#define	NBBY	8		/* 8 bits per byte */
+#endif				/* #ifndef NBBY */
+#define	setbit(a, i)	(((u8 *)a)[(i)/NBBY] |= 1<<((i)%NBBY))
+#define	clrbit(a, i)	(((u8 *)a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
+#define	isset(a, i)	(((const u8 *)a)[(i)/NBBY] & (1<<((i)%NBBY)))
+#define	isclr(a, i)	((((const u8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
+#endif				/* setbit */
+
+#define	NBITS(type)	(sizeof(type) * 8)
+#define NBITVAL(nbits)	(1 << (nbits))
+#define MAXBITVAL(nbits)	((1 << (nbits)) - 1)
+#define	NBITMASK(nbits)	MAXBITVAL(nbits)
+#define MAXNBVAL(nbyte)	MAXBITVAL((nbyte) * 8)
+
+/* crc defines */
+#define CRC16_INIT_VALUE 0xffff	/* Initial CRC16 checksum value */
+#define CRC16_GOOD_VALUE 0xf0b8	/* Good final CRC16 checksum value */
+
+/* 18-bytes of Ethernet address buffer length */
+#define ETHER_ADDR_STR_LEN	18
+
+struct pktq_prec {
+	struct sk_buff_head skblist;
+	u16 max;		/* maximum number of queued packets */
+};
+
+/* multi-priority pkt queue */
+struct pktq {
+	u16 num_prec;	/* number of precedences in use */
+	u16 hi_prec;	/* rapid dequeue hint (>= highest non-empty prec) */
+	u16 max;	/* total max packets */
+	u16 len;	/* total number of packets */
+	/*
+	 * q array must be last since # of elements can be either
+	 * PKTQ_MAX_PREC or 1
+	 */
+	struct pktq_prec q[PKTQ_MAX_PREC];
+};
+
+/* operations on a specific precedence in packet queue */
+
+static inline int pktq_plen(struct pktq *pq, int prec)
+{
+	return pq->q[prec].skblist.qlen;
+}
+
+static inline int pktq_pavail(struct pktq *pq, int prec)
+{
+	return pq->q[prec].max - pq->q[prec].skblist.qlen;
+}
+
+static inline bool pktq_pfull(struct pktq *pq, int prec)
+{
+	return pq->q[prec].skblist.qlen >= pq->q[prec].max;
+}
+
+static inline bool pktq_pempty(struct pktq *pq, int prec)
+{
+	return skb_queue_empty(&pq->q[prec].skblist);
+}
+
+static inline struct sk_buff *pktq_ppeek(struct pktq *pq, int prec)
+{
+	return skb_peek(&pq->q[prec].skblist);
+}
+
+static inline struct sk_buff *pktq_ppeek_tail(struct pktq *pq, int prec)
+{
+	return skb_peek_tail(&pq->q[prec].skblist);
+}
+
+struct sk_buff *brcmu_pktq_penq(struct pktq *pq, int prec, struct sk_buff *p);
+struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec,
+				     struct sk_buff *p);
+struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec);
+struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec);
+struct sk_buff *brcmu_pktq_pdeq_match(struct pktq *pq, int prec,
+				      bool (*match_fn)(struct sk_buff *p,
+						       void *arg),
+				      void *arg);
+
+/* packet primitives */
+struct sk_buff *brcmu_pkt_buf_get_skb(uint len);
+void brcmu_pkt_buf_free_skb(struct sk_buff *skb);
+
+/* Empty the queue at particular precedence level */
+/* callback function fn(pkt, arg) returns true if pkt belongs to if */
+void brcmu_pktq_pflush(struct pktq *pq, int prec, bool dir,
+		       bool (*fn)(struct sk_buff *, void *), void *arg);
+
+/* operations on a set of precedences in packet queue */
+
+int brcmu_pktq_mlen(struct pktq *pq, uint prec_bmp);
+struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out);
+
+/* operations on packet queue as a whole */
+
+static inline int pktq_len(struct pktq *pq)
+{
+	return (int)pq->len;
+}
+
+static inline int pktq_max(struct pktq *pq)
+{
+	return (int)pq->max;
+}
+
+static inline int pktq_avail(struct pktq *pq)
+{
+	return (int)(pq->max - pq->len);
+}
+
+static inline bool pktq_full(struct pktq *pq)
+{
+	return pq->len >= pq->max;
+}
+
+static inline bool pktq_empty(struct pktq *pq)
+{
+	return pq->len == 0;
+}
+
+void brcmu_pktq_init(struct pktq *pq, int num_prec, int max_len);
+/* prec_out may be NULL if caller is not interested in return value */
+struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out);
+void brcmu_pktq_flush(struct pktq *pq, bool dir,
+		      bool (*fn)(struct sk_buff *, void *), void *arg);
+
+/* externs */
+/* ip address */
+struct ipv4_addr;
+
+/*
+ * bitfield macros using masking and shift
+ *
+ * remark: the mask parameter should be a shifted mask.
+ */
+static inline void brcmu_maskset32(u32 *var, u32 mask, u8 shift, u32 value)
+{
+	value = (value << shift) & mask;
+	*var = (*var & ~mask) | value;
+}
+static inline u32 brcmu_maskget32(u32 var, u32 mask, u8 shift)
+{
+	return (var & mask) >> shift;
+}
+static inline void brcmu_maskset16(u16 *var, u16 mask, u8 shift, u16 value)
+{
+	value = (value << shift) & mask;
+	*var = (*var & ~mask) | value;
+}
+static inline u16 brcmu_maskget16(u16 var, u16 mask, u8 shift)
+{
+	return (var & mask) >> shift;
+}
+
+/* externs */
+/* format/print */
+#ifdef DEBUG
+void brcmu_prpkt(const char *msg, struct sk_buff *p0);
+#else
+#define brcmu_prpkt(a, b)
+#endif				/* DEBUG */
+
+#ifdef DEBUG
+__printf(3, 4)
+void brcmu_dbg_hex_dump(const void *data, size_t size, const char *fmt, ...);
+#else
+__printf(3, 4)
+static inline
+void brcmu_dbg_hex_dump(const void *data, size_t size, const char *fmt, ...)
+{
+}
+#endif
+
+#define BRCMU_BOARDREV_LEN	8
+#define BRCMU_DOTREV_LEN	16
+
+char *brcmu_boardrev_str(u32 brev, char *buf);
+char *brcmu_dotrev_str(u32 dotrev, char *buf);
+
+#endif				/* _BRCMU_UTILS_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h
new file mode 100644
index 0000000..75b2a04
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_BRCMU_WIFI_H_
+#define	_BRCMU_WIFI_H_
+
+#include <linux/if_ether.h>		/* for ETH_ALEN */
+#include <linux/ieee80211.h>		/* for WLAN_PMKID_LEN */
+
+/*
+ * A chanspec (u16) holds the channel number, band, bandwidth and control
+ * sideband
+ */
+
+/* channel defines */
+#define CH_UPPER_SB			0x01
+#define CH_LOWER_SB			0x02
+#define CH_EWA_VALID			0x04
+#define CH_70MHZ_APART			14
+#define CH_50MHZ_APART			10
+#define CH_30MHZ_APART			6
+#define CH_20MHZ_APART			4
+#define CH_10MHZ_APART			2
+#define CH_5MHZ_APART			1 /* 2G band channels are 5 Mhz apart */
+#define CH_MIN_2G_CHANNEL		1
+#define CH_MAX_2G_CHANNEL		14	/* Max channel in 2G band */
+#define CH_MIN_5G_CHANNEL		34
+
+/* bandstate array indices */
+#define BAND_2G_INDEX		0	/* wlc->bandstate[x] index */
+#define BAND_5G_INDEX		1	/* wlc->bandstate[x] index */
+
+/*
+ * max # supported channels. The max channel no is 216, this is that + 1
+ * rounded up to a multiple of NBBY (8). DO NOT MAKE it > 255: channels are
+ * u8's all over
+*/
+#define	MAXCHANNEL		224
+
+#define WL_CHANSPEC_CHAN_MASK		0x00ff
+#define WL_CHANSPEC_CHAN_SHIFT		0
+
+#define WL_CHANSPEC_CTL_SB_MASK		0x0300
+#define WL_CHANSPEC_CTL_SB_SHIFT	     8
+#define WL_CHANSPEC_CTL_SB_LOWER	0x0100
+#define WL_CHANSPEC_CTL_SB_UPPER	0x0200
+#define WL_CHANSPEC_CTL_SB_NONE		0x0300
+
+#define WL_CHANSPEC_BW_MASK		0x0C00
+#define WL_CHANSPEC_BW_SHIFT		    10
+#define WL_CHANSPEC_BW_10		0x0400
+#define WL_CHANSPEC_BW_20		0x0800
+#define WL_CHANSPEC_BW_40		0x0C00
+#define WL_CHANSPEC_BW_80		0x2000
+
+#define WL_CHANSPEC_BAND_MASK		0xf000
+#define WL_CHANSPEC_BAND_SHIFT		12
+#define WL_CHANSPEC_BAND_5G		0x1000
+#define WL_CHANSPEC_BAND_2G		0x2000
+#define INVCHANSPEC			255
+
+#define WL_CHAN_VALID_HW		(1 << 0) /* valid with current HW */
+#define WL_CHAN_VALID_SW		(1 << 1) /* valid with country sett. */
+#define WL_CHAN_BAND_5G			(1 << 2) /* 5GHz-band channel */
+#define WL_CHAN_RADAR			(1 << 3) /* radar sensitive  channel */
+#define WL_CHAN_INACTIVE		(1 << 4) /* inactive due to radar */
+#define WL_CHAN_PASSIVE			(1 << 5) /* channel in passive mode */
+#define WL_CHAN_RESTRICTED		(1 << 6) /* restricted use channel */
+
+/* values for band specific 40MHz capabilities  */
+#define WLC_N_BW_20ALL			0
+#define WLC_N_BW_40ALL			1
+#define WLC_N_BW_20IN2G_40IN5G		2
+
+#define WLC_BW_20MHZ_BIT		BIT(0)
+#define WLC_BW_40MHZ_BIT		BIT(1)
+#define WLC_BW_80MHZ_BIT		BIT(2)
+#define WLC_BW_160MHZ_BIT		BIT(3)
+
+/* Bandwidth capabilities */
+#define WLC_BW_CAP_20MHZ		(WLC_BW_20MHZ_BIT)
+#define WLC_BW_CAP_40MHZ		(WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT)
+#define WLC_BW_CAP_80MHZ		(WLC_BW_80MHZ_BIT|WLC_BW_40MHZ_BIT| \
+					 WLC_BW_20MHZ_BIT)
+#define WLC_BW_CAP_160MHZ		(WLC_BW_160MHZ_BIT|WLC_BW_80MHZ_BIT| \
+					 WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT)
+#define WLC_BW_CAP_UNRESTRICTED		0xFF
+
+/* band types */
+#define	WLC_BAND_AUTO			0	/* auto-select */
+#define	WLC_BAND_5G			1	/* 5 Ghz */
+#define	WLC_BAND_2G			2	/* 2.4 Ghz */
+#define	WLC_BAND_ALL			3	/* all bands */
+
+#define CHSPEC_CHANNEL(chspec)	((u8)((chspec) & WL_CHANSPEC_CHAN_MASK))
+#define CHSPEC_BAND(chspec)	((chspec) & WL_CHANSPEC_BAND_MASK)
+
+#define CHSPEC_CTL_SB(chspec)	((chspec) & WL_CHANSPEC_CTL_SB_MASK)
+#define CHSPEC_BW(chspec)	((chspec) & WL_CHANSPEC_BW_MASK)
+
+#define CHSPEC_IS10(chspec) \
+	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10)
+
+#define CHSPEC_IS20(chspec) \
+	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20)
+
+#define CHSPEC_IS40(chspec) \
+	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)
+
+#define CHSPEC_IS80(chspec) \
+	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_80)
+
+#define CHSPEC_IS5G(chspec) \
+	(((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G)
+
+#define CHSPEC_IS2G(chspec) \
+	(((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G)
+
+#define CHSPEC_SB_NONE(chspec) \
+	(((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE)
+
+#define CHSPEC_SB_UPPER(chspec) \
+	(((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER)
+
+#define CHSPEC_SB_LOWER(chspec) \
+	(((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER)
+
+#define CHSPEC_CTL_CHAN(chspec) \
+	((CHSPEC_SB_LOWER(chspec)) ? \
+	(lower_20_sb(((chspec) & WL_CHANSPEC_CHAN_MASK))) : \
+	(upper_20_sb(((chspec) & WL_CHANSPEC_CHAN_MASK))))
+
+#define CHSPEC2BAND(chspec) (CHSPEC_IS5G(chspec) ? BRCM_BAND_5G : BRCM_BAND_2G)
+
+#define CHANSPEC_STR_LEN    8
+
+static inline int lower_20_sb(int channel)
+{
+	return channel > CH_10MHZ_APART ? (channel - CH_10MHZ_APART) : 0;
+}
+
+static inline int upper_20_sb(int channel)
+{
+	return (channel < (MAXCHANNEL - CH_10MHZ_APART)) ?
+	       channel + CH_10MHZ_APART : 0;
+}
+
+static inline int chspec_bandunit(u16 chspec)
+{
+	return CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX;
+}
+
+static inline u16 ch20mhz_chspec(int channel)
+{
+	u16 rc = channel <= CH_MAX_2G_CHANNEL ?
+		 WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G;
+
+	return	(u16)((u16)channel | WL_CHANSPEC_BW_20 |
+		      WL_CHANSPEC_CTL_SB_NONE | rc);
+}
+
+static inline int next_20mhz_chan(int channel)
+{
+	return channel < (MAXCHANNEL - CH_20MHZ_APART) ?
+	       channel + CH_20MHZ_APART : 0;
+}
+
+/* defined rate in 500kbps */
+#define BRCM_MAXRATE	108	/* in 500kbps units */
+#define BRCM_RATE_1M	2	/* in 500kbps units */
+#define BRCM_RATE_2M	4	/* in 500kbps units */
+#define BRCM_RATE_5M5	11	/* in 500kbps units */
+#define BRCM_RATE_11M	22	/* in 500kbps units */
+#define BRCM_RATE_6M	12	/* in 500kbps units */
+#define BRCM_RATE_9M	18	/* in 500kbps units */
+#define BRCM_RATE_12M	24	/* in 500kbps units */
+#define BRCM_RATE_18M	36	/* in 500kbps units */
+#define BRCM_RATE_24M	48	/* in 500kbps units */
+#define BRCM_RATE_36M	72	/* in 500kbps units */
+#define BRCM_RATE_48M	96	/* in 500kbps units */
+#define BRCM_RATE_54M	108	/* in 500kbps units */
+
+#define BRCM_2G_25MHZ_OFFSET		5	/* 2.4GHz band channel offset */
+
+#define MCSSET_LEN	16
+
+static inline bool ac_bitmap_tst(u8 bitmap, int prec)
+{
+	return (bitmap & (1 << (prec))) != 0;
+}
+
+/* Enumerate crypto algorithms */
+#define	CRYPTO_ALGO_OFF			0
+#define	CRYPTO_ALGO_WEP1		1
+#define	CRYPTO_ALGO_TKIP		2
+#define	CRYPTO_ALGO_WEP128		3
+#define CRYPTO_ALGO_AES_CCM		4
+#define CRYPTO_ALGO_AES_RESERVED1	5
+#define CRYPTO_ALGO_AES_RESERVED2	6
+#define CRYPTO_ALGO_NALG		7
+
+/* wireless security bitvec */
+
+#define WEP_ENABLED		0x0001
+#define TKIP_ENABLED		0x0002
+#define AES_ENABLED		0x0004
+#define WSEC_SWFLAG		0x0008
+/* to go into transition mode without setting wep */
+#define SES_OW_ENABLED		0x0040
+/* MFP */
+#define MFP_CAPABLE		0x0200
+#define MFP_REQUIRED		0x0400
+
+/* WPA authentication mode bitvec */
+#define WPA_AUTH_DISABLED	0x0000	/* Legacy (i.e., non-WPA) */
+#define WPA_AUTH_NONE		0x0001	/* none (IBSS) */
+#define WPA_AUTH_UNSPECIFIED	0x0002	/* over 802.1x */
+#define WPA_AUTH_PSK		0x0004	/* Pre-shared key */
+#define WPA_AUTH_RESERVED1	0x0008
+#define WPA_AUTH_RESERVED2	0x0010
+
+#define WPA2_AUTH_RESERVED1	0x0020
+#define WPA2_AUTH_UNSPECIFIED	0x0040	/* over 802.1x */
+#define WPA2_AUTH_PSK		0x0080	/* Pre-shared key */
+#define WPA2_AUTH_RESERVED3	0x0200
+#define WPA2_AUTH_RESERVED4	0x0400
+#define WPA2_AUTH_RESERVED5	0x0800
+#define WPA2_AUTH_1X_SHA256	0x1000  /* 1X with SHA256 key derivation */
+#define WPA2_AUTH_PSK_SHA256	0x8000	/* PSK with SHA256 key derivation */
+
+#define DOT11_DEFAULT_RTS_LEN		2347
+#define DOT11_DEFAULT_FRAG_LEN		2346
+
+#define DOT11_ICV_AES_LEN		8
+#define DOT11_QOS_LEN			2
+#define DOT11_IV_MAX_LEN		8
+#define DOT11_A4_HDR_LEN		30
+
+#define HT_CAP_RX_STBC_NO		0x0
+#define HT_CAP_RX_STBC_ONE_STREAM	0x1
+
+#endif				/* _BRCMU_WIFI_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/include/chipcommon.h b/drivers/net/wireless/broadcom/brcm80211/include/chipcommon.h
new file mode 100644
index 0000000..e1fd499
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/include/chipcommon.h
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_SBCHIPC_H
+#define	_SBCHIPC_H
+
+#include "defs.h"		/* for PAD macro */
+
+#define CHIPCREGOFFS(field)	offsetof(struct chipcregs, field)
+
+struct chipcregs {
+	u32 chipid;		/* 0x0 */
+	u32 capabilities;
+	u32 corecontrol;	/* corerev >= 1 */
+	u32 bist;
+
+	/* OTP */
+	u32 otpstatus;	/* 0x10, corerev >= 10 */
+	u32 otpcontrol;
+	u32 otpprog;
+	u32 otplayout;	/* corerev >= 23 */
+
+	/* Interrupt control */
+	u32 intstatus;	/* 0x20 */
+	u32 intmask;
+
+	/* Chip specific regs */
+	u32 chipcontrol;	/* 0x28, rev >= 11 */
+	u32 chipstatus;	/* 0x2c, rev >= 11 */
+
+	/* Jtag Master */
+	u32 jtagcmd;		/* 0x30, rev >= 10 */
+	u32 jtagir;
+	u32 jtagdr;
+	u32 jtagctrl;
+
+	/* serial flash interface registers */
+	u32 flashcontrol;	/* 0x40 */
+	u32 flashaddress;
+	u32 flashdata;
+	u32 PAD[1];
+
+	/* Silicon backplane configuration broadcast control */
+	u32 broadcastaddress;	/* 0x50 */
+	u32 broadcastdata;
+
+	/* gpio - cleared only by power-on-reset */
+	u32 gpiopullup;	/* 0x58, corerev >= 20 */
+	u32 gpiopulldown;	/* 0x5c, corerev >= 20 */
+	u32 gpioin;		/* 0x60 */
+	u32 gpioout;		/* 0x64 */
+	u32 gpioouten;	/* 0x68 */
+	u32 gpiocontrol;	/* 0x6C */
+	u32 gpiointpolarity;	/* 0x70 */
+	u32 gpiointmask;	/* 0x74 */
+
+	/* GPIO events corerev >= 11 */
+	u32 gpioevent;
+	u32 gpioeventintmask;
+
+	/* Watchdog timer */
+	u32 watchdog;	/* 0x80 */
+
+	/* GPIO events corerev >= 11 */
+	u32 gpioeventintpolarity;
+
+	/* GPIO based LED powersave registers corerev >= 16 */
+	u32 gpiotimerval;	/* 0x88 */
+	u32 gpiotimeroutmask;
+
+	/* clock control */
+	u32 clockcontrol_n;	/* 0x90 */
+	u32 clockcontrol_sb;	/* aka m0 */
+	u32 clockcontrol_pci;	/* aka m1 */
+	u32 clockcontrol_m2;	/* mii/uart/mipsref */
+	u32 clockcontrol_m3;	/* cpu */
+	u32 clkdiv;		/* corerev >= 3 */
+	u32 gpiodebugsel;	/* corerev >= 28 */
+	u32 capabilities_ext;	/* 0xac  */
+
+	/* pll delay registers (corerev >= 4) */
+	u32 pll_on_delay;	/* 0xb0 */
+	u32 fref_sel_delay;
+	u32 slow_clk_ctl;	/* 5 < corerev < 10 */
+	u32 PAD;
+
+	/* Instaclock registers (corerev >= 10) */
+	u32 system_clk_ctl;	/* 0xc0 */
+	u32 clkstatestretch;
+	u32 PAD[2];
+
+	/* Indirect backplane access (corerev >= 22) */
+	u32 bp_addrlow;	/* 0xd0 */
+	u32 bp_addrhigh;
+	u32 bp_data;
+	u32 PAD;
+	u32 bp_indaccess;
+	u32 PAD[3];
+
+	/* More clock dividers (corerev >= 32) */
+	u32 clkdiv2;
+	u32 PAD[2];
+
+	/* In AI chips, pointer to erom */
+	u32 eromptr;		/* 0xfc */
+
+	/* ExtBus control registers (corerev >= 3) */
+	u32 pcmcia_config;	/* 0x100 */
+	u32 pcmcia_memwait;
+	u32 pcmcia_attrwait;
+	u32 pcmcia_iowait;
+	u32 ide_config;
+	u32 ide_memwait;
+	u32 ide_attrwait;
+	u32 ide_iowait;
+	u32 prog_config;
+	u32 prog_waitcount;
+	u32 flash_config;
+	u32 flash_waitcount;
+	u32 SECI_config;	/* 0x130 SECI configuration */
+	u32 PAD[3];
+
+	/* Enhanced Coexistence Interface (ECI) registers (corerev >= 21) */
+	u32 eci_output;	/* 0x140 */
+	u32 eci_control;
+	u32 eci_inputlo;
+	u32 eci_inputmi;
+	u32 eci_inputhi;
+	u32 eci_inputintpolaritylo;
+	u32 eci_inputintpolaritymi;
+	u32 eci_inputintpolarityhi;
+	u32 eci_intmasklo;
+	u32 eci_intmaskmi;
+	u32 eci_intmaskhi;
+	u32 eci_eventlo;
+	u32 eci_eventmi;
+	u32 eci_eventhi;
+	u32 eci_eventmasklo;
+	u32 eci_eventmaskmi;
+	u32 eci_eventmaskhi;
+	u32 PAD[3];
+
+	/* SROM interface (corerev >= 32) */
+	u32 sromcontrol;	/* 0x190 */
+	u32 sromaddress;
+	u32 sromdata;
+	u32 PAD[17];
+
+	/* Clock control and hardware workarounds (corerev >= 20) */
+	u32 clk_ctl_st;	/* 0x1e0 */
+	u32 hw_war;
+	u32 PAD[70];
+
+	/* UARTs */
+	u8 uart0data;	/* 0x300 */
+	u8 uart0imr;
+	u8 uart0fcr;
+	u8 uart0lcr;
+	u8 uart0mcr;
+	u8 uart0lsr;
+	u8 uart0msr;
+	u8 uart0scratch;
+	u8 PAD[248];		/* corerev >= 1 */
+
+	u8 uart1data;	/* 0x400 */
+	u8 uart1imr;
+	u8 uart1fcr;
+	u8 uart1lcr;
+	u8 uart1mcr;
+	u8 uart1lsr;
+	u8 uart1msr;
+	u8 uart1scratch;
+	u32 PAD[62];
+
+	/* save/restore, corerev >= 48 */
+	u32 sr_capability;          /* 0x500 */
+	u32 sr_control0;            /* 0x504 */
+	u32 sr_control1;            /* 0x508 */
+	u32 gpio_control;           /* 0x50C */
+	u32 PAD[60];
+
+	/* PMU registers (corerev >= 20) */
+	u32 pmucontrol;	/* 0x600 */
+	u32 pmucapabilities;
+	u32 pmustatus;
+	u32 res_state;
+	u32 res_pending;
+	u32 pmutimer;
+	u32 min_res_mask;
+	u32 max_res_mask;
+	u32 res_table_sel;
+	u32 res_dep_mask;
+	u32 res_updn_timer;
+	u32 res_timer;
+	u32 clkstretch;
+	u32 pmuwatchdog;
+	u32 gpiosel;		/* 0x638, rev >= 1 */
+	u32 gpioenable;	/* 0x63c, rev >= 1 */
+	u32 res_req_timer_sel;
+	u32 res_req_timer;
+	u32 res_req_mask;
+	u32 pmucapabilities_ext; /* 0x64c, pmurev >=15 */
+	u32 chipcontrol_addr;	/* 0x650 */
+	u32 chipcontrol_data;	/* 0x654 */
+	u32 regcontrol_addr;
+	u32 regcontrol_data;
+	u32 pllcontrol_addr;
+	u32 pllcontrol_data;
+	u32 pmustrapopt;	/* 0x668, corerev >= 28 */
+	u32 pmu_xtalfreq;	/* 0x66C, pmurev >= 10 */
+	u32 retention_ctl;          /* 0x670, pmurev >= 15 */
+	u32 PAD[3];
+	u32 retention_grpidx;       /* 0x680 */
+	u32 retention_grpctl;       /* 0x684 */
+	u32 PAD[94];
+	u16 sromotp[768];
+};
+
+/* chipid */
+#define	CID_ID_MASK		0x0000ffff	/* Chip Id mask */
+#define	CID_REV_MASK		0x000f0000	/* Chip Revision mask */
+#define	CID_REV_SHIFT		16	/* Chip Revision shift */
+#define	CID_PKG_MASK		0x00f00000	/* Package Option mask */
+#define	CID_PKG_SHIFT		20	/* Package Option shift */
+#define	CID_CC_MASK		0x0f000000	/* CoreCount (corerev >= 4) */
+#define CID_CC_SHIFT		24
+#define	CID_TYPE_MASK		0xf0000000	/* Chip Type */
+#define CID_TYPE_SHIFT		28
+
+/* capabilities */
+#define	CC_CAP_UARTS_MASK	0x00000003	/* Number of UARTs */
+#define CC_CAP_MIPSEB		0x00000004	/* MIPS is in big-endian mode */
+#define CC_CAP_UCLKSEL		0x00000018	/* UARTs clock select */
+/* UARTs are driven by internal divided clock */
+#define CC_CAP_UINTCLK		0x00000008
+#define CC_CAP_UARTGPIO		0x00000020	/* UARTs own GPIOs 15:12 */
+#define CC_CAP_EXTBUS_MASK	0x000000c0	/* External bus mask */
+#define CC_CAP_EXTBUS_NONE	0x00000000	/* No ExtBus present */
+#define CC_CAP_EXTBUS_FULL	0x00000040	/* ExtBus: PCMCIA, IDE & Prog */
+#define CC_CAP_EXTBUS_PROG	0x00000080	/* ExtBus: ProgIf only */
+#define	CC_CAP_FLASH_MASK	0x00000700	/* Type of flash */
+#define	CC_CAP_PLL_MASK		0x00038000	/* Type of PLL */
+#define CC_CAP_PWR_CTL		0x00040000	/* Power control */
+#define CC_CAP_OTPSIZE		0x00380000	/* OTP Size (0 = none) */
+#define CC_CAP_OTPSIZE_SHIFT	19	/* OTP Size shift */
+#define CC_CAP_OTPSIZE_BASE	5	/* OTP Size base */
+#define CC_CAP_JTAGP		0x00400000	/* JTAG Master Present */
+#define CC_CAP_ROM		0x00800000	/* Internal boot rom active */
+#define CC_CAP_BKPLN64		0x08000000	/* 64-bit backplane */
+#define	CC_CAP_PMU		0x10000000	/* PMU Present, rev >= 20 */
+#define	CC_CAP_SROM		0x40000000	/* Srom Present, rev >= 32 */
+/* Nand flash present, rev >= 35 */
+#define	CC_CAP_NFLASH		0x80000000
+
+#define	CC_CAP2_SECI		0x00000001	/* SECI Present, rev >= 36 */
+/* GSIO (spi/i2c) present, rev >= 37 */
+#define	CC_CAP2_GSIO		0x00000002
+
+/* pmucapabilities */
+#define PCAP_REV_MASK	0x000000ff
+#define PCAP_RC_MASK	0x00001f00
+#define PCAP_RC_SHIFT	8
+#define PCAP_TC_MASK	0x0001e000
+#define PCAP_TC_SHIFT	13
+#define PCAP_PC_MASK	0x001e0000
+#define PCAP_PC_SHIFT	17
+#define PCAP_VC_MASK	0x01e00000
+#define PCAP_VC_SHIFT	21
+#define PCAP_CC_MASK	0x1e000000
+#define PCAP_CC_SHIFT	25
+#define PCAP5_PC_MASK	0x003e0000	/* PMU corerev >= 5 */
+#define PCAP5_PC_SHIFT	17
+#define PCAP5_VC_MASK	0x07c00000
+#define PCAP5_VC_SHIFT	22
+#define PCAP5_CC_MASK	0xf8000000
+#define PCAP5_CC_SHIFT	27
+/* pmucapabilites_ext PMU rev >= 15 */
+#define PCAPEXT_SR_SUPPORTED_MASK	(1 << 1)
+/* retention_ctl PMU rev >= 15 */
+#define PMU_RCTL_MACPHY_DISABLE_MASK        (1 << 26)
+#define PMU_RCTL_LOGIC_DISABLE_MASK         (1 << 27)
+
+
+/*
+* Maximum delay for the PMU state transition in us.
+* This is an upper bound intended for spinwaits etc.
+*/
+#define PMU_MAX_TRANSITION_DLY	15000
+
+#endif				/* _SBCHIPC_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/include/defs.h b/drivers/net/wireless/broadcom/brcm80211/include/defs.h
new file mode 100644
index 0000000..8d1e85e
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/include/defs.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_BRCM_DEFS_H_
+#define	_BRCM_DEFS_H_
+
+#include <linux/types.h>
+
+#define	SI_BUS			0
+#define	PCI_BUS			1
+#define	PCMCIA_BUS		2
+#define SDIO_BUS		3
+#define JTAG_BUS		4
+#define USB_BUS			5
+#define SPI_BUS			6
+
+#define	OFF	0
+#define	ON	1		/* ON = 1 */
+#define	AUTO	(-1)		/* Auto = -1 */
+
+/*
+ * Priority definitions according 802.1D
+ */
+#define	PRIO_8021D_NONE		2
+#define	PRIO_8021D_BK		1
+#define	PRIO_8021D_BE		0
+#define	PRIO_8021D_EE		3
+#define	PRIO_8021D_CL		4
+#define	PRIO_8021D_VI		5
+#define	PRIO_8021D_VO		6
+#define	PRIO_8021D_NC		7
+
+#define	MAXPRIO			7
+#define NUMPRIO			(MAXPRIO + 1)
+
+#define WL_NUMRATES		16	/* max # of rates in a rateset */
+
+#define BRCM_CNTRY_BUF_SZ	4	/* Country string is 3 bytes + NUL */
+
+#define BRCM_SET_CHANNEL	30
+#define BRCM_SET_SRL		32
+#define BRCM_SET_LRL		34
+#define BRCM_SET_BCNPRD		76
+
+#define BRCM_GET_CURR_RATESET	114	/* current rateset */
+#define BRCM_GET_PHYLIST	180
+
+/* Bit masks for radio disabled status - returned by WL_GET_RADIO */
+
+#define WL_RADIO_SW_DISABLE		(1<<0)
+#define WL_RADIO_HW_DISABLE		(1<<1)
+/* some countries don't support any channel */
+#define WL_RADIO_COUNTRY_DISABLE	(1<<3)
+
+/* Override bit for SET_TXPWR.  if set, ignore other level limits */
+#define WL_TXPWR_OVERRIDE	(1U<<31)
+
+/* band types */
+#define	BRCM_BAND_AUTO		0	/* auto-select */
+#define	BRCM_BAND_5G		1	/* 5 Ghz */
+#define	BRCM_BAND_2G		2	/* 2.4 Ghz */
+#define	BRCM_BAND_ALL		3	/* all bands */
+
+/* Debug levels */
+#define BRCM_DL_INFO		0x00000001
+#define BRCM_DL_MAC80211	0x00000002
+#define BRCM_DL_RX		0x00000004
+#define BRCM_DL_TX		0x00000008
+#define BRCM_DL_INT		0x00000010
+#define BRCM_DL_DMA		0x00000020
+#define BRCM_DL_HT		0x00000040
+
+/* Values for PM */
+#define PM_OFF	0
+#define PM_MAX	1
+#define PM_FAST 2
+
+/*
+ * Sonics Configuration Space Registers.
+ */
+
+/* core sbconfig regs are top 256bytes of regs */
+#define	SBCONFIGOFF		0xf00
+
+/* cpp contortions to concatenate w/arg prescan */
+#ifndef	PAD
+#define	_PADLINE(line)	pad ## line
+#define	_XSTR(line)	_PADLINE(line)
+#define	PAD		_XSTR(__LINE__)
+#endif
+
+#endif				/* _BRCM_DEFS_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/include/soc.h b/drivers/net/wireless/broadcom/brcm80211/include/soc.h
new file mode 100644
index 0000000..123cfa8
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/include/soc.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_BRCM_SOC_H
+#define	_BRCM_SOC_H
+
+#define SI_ENUM_BASE		0x18000000	/* Enumeration space base */
+
+/* Common core control flags */
+#define	SICF_BIST_EN		0x8000
+#define	SICF_PME_EN		0x4000
+#define	SICF_CORE_BITS		0x3ffc
+#define	SICF_FGC		0x0002
+#define	SICF_CLOCK_EN		0x0001
+
+/* Common core status flags */
+#define	SISF_BIST_DONE		0x8000
+#define	SISF_BIST_ERROR		0x4000
+#define	SISF_GATED_CLK		0x2000
+#define	SISF_DMA64		0x1000
+#define	SISF_CORE_BITS		0x0fff
+
+#endif				/* _BRCM_SOC_H */