aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless/b43
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/b43')
-rw-r--r--drivers/net/wireless/b43/Kconfig92
-rw-r--r--drivers/net/wireless/b43/Makefile6
-rw-r--r--drivers/net/wireless/b43/b43.h227
-rw-r--r--drivers/net/wireless/b43/bus.c255
-rw-r--r--drivers/net/wireless/b43/bus.h80
-rw-r--r--drivers/net/wireless/b43/debugfs.c10
-rw-r--r--drivers/net/wireless/b43/debugfs.h2
-rw-r--r--drivers/net/wireless/b43/dma.c355
-rw-r--r--drivers/net/wireless/b43/dma.h26
-rw-r--r--drivers/net/wireless/b43/leds.c31
-rw-r--r--drivers/net/wireless/b43/lo.c16
-rw-r--r--drivers/net/wireless/b43/main.c1827
-rw-r--r--drivers/net/wireless/b43/main.h45
-rw-r--r--drivers/net/wireless/b43/pcmcia.c15
-rw-r--r--drivers/net/wireless/b43/phy_a.c23
-rw-r--r--drivers/net/wireless/b43/phy_common.c179
-rw-r--r--drivers/net/wireless/b43/phy_common.h22
-rw-r--r--drivers/net/wireless/b43/phy_g.c134
-rw-r--r--drivers/net/wireless/b43/phy_g.h2
-rw-r--r--drivers/net/wireless/b43/phy_ht.c1140
-rw-r--r--drivers/net/wireless/b43/phy_ht.h136
-rw-r--r--drivers/net/wireless/b43/phy_lcn.c902
-rw-r--r--drivers/net/wireless/b43/phy_lcn.h31
-rw-r--r--drivers/net/wireless/b43/phy_lp.c153
-rw-r--r--drivers/net/wireless/b43/phy_n.c5508
-rw-r--r--drivers/net/wireless/b43/phy_n.h167
-rw-r--r--drivers/net/wireless/b43/pio.c76
-rw-r--r--drivers/net/wireless/b43/radio_2055.c3
-rw-r--r--drivers/net/wireless/b43/radio_2055.h5
-rw-r--r--drivers/net/wireless/b43/radio_2056.c1361
-rw-r--r--drivers/net/wireless/b43/radio_2056.h32
-rw-r--r--drivers/net/wireless/b43/radio_2057.c141
-rw-r--r--drivers/net/wireless/b43/radio_2057.h430
-rw-r--r--drivers/net/wireless/b43/radio_2059.c155
-rw-r--r--drivers/net/wireless/b43/radio_2059.h46
-rw-r--r--drivers/net/wireless/b43/rfkill.c11
-rw-r--r--drivers/net/wireless/b43/sdio.c8
-rw-r--r--drivers/net/wireless/b43/sdio.h4
-rw-r--r--drivers/net/wireless/b43/sysfs.c4
-rw-r--r--drivers/net/wireless/b43/tables.c2
-rw-r--r--drivers/net/wireless/b43/tables_lpphy.c17
-rw-r--r--drivers/net/wireless/b43/tables_nphy.c1483
-rw-r--r--drivers/net/wireless/b43/tables_nphy.h103
-rw-r--r--drivers/net/wireless/b43/tables_phy_ht.c836
-rw-r--r--drivers/net/wireless/b43/tables_phy_ht.h26
-rw-r--r--drivers/net/wireless/b43/tables_phy_lcn.c724
-rw-r--r--drivers/net/wireless/b43/tables_phy_lcn.h24
-rw-r--r--drivers/net/wireless/b43/wa.c28
-rw-r--r--drivers/net/wireless/b43/xmit.c278
-rw-r--r--drivers/net/wireless/b43/xmit.h94
50 files changed, 14050 insertions, 3225 deletions
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index 47033f6a1c2..40fd9b7b142 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -1,7 +1,8 @@
config B43
tristate "Broadcom 43xx wireless support (mac80211 stack)"
- depends on SSB_POSSIBLE && MAC80211 && HAS_DMA
- select SSB
+ 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.
@@ -26,6 +27,35 @@ config B43
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
@@ -43,7 +73,7 @@ config B43_PCICORE_AUTOSELECT
config B43_PCMCIA
bool "Broadcom 43xx PCMCIA device support"
- depends on B43 && SSB_PCMCIAHOST_POSSIBLE
+ depends on B43 && B43_SSB && SSB_PCMCIAHOST_POSSIBLE
select SSB_PCMCIAHOST
---help---
Broadcom 43xx PCMCIA device support.
@@ -62,8 +92,8 @@ config B43_PCMCIA
If unsure, say N.
config B43_SDIO
- bool "Broadcom 43xx SDIO device support (EXPERIMENTAL)"
- depends on B43 && SSB_SDIOHOST_POSSIBLE && EXPERIMENTAL
+ 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.
@@ -80,33 +110,57 @@ config B43_SDIO
#Data transfers to the device via PIO. We want it as a fallback even
# if we can do DMA.
+config B43_BCMA_PIO
+ bool
+ depends on B43 && B43_BCMA
+ select BCMA_BLOCKIO
+ default y
+
config B43_PIO
bool
- depends on B43
+ depends on B43 && B43_SSB
select SSB_BLOCKIO
default y
config B43_PHY_N
- bool "Support for 802.11n (N-PHY) devices (EXPERIMENTAL)"
- depends on B43 && EXPERIMENTAL
+ bool "Support for 802.11n (N-PHY) devices"
+ depends on B43
+ default y
---help---
Support for the N-PHY.
- This enables support for devices with N-PHY revision up to 2.
+ This enables support for devices with N-PHY.
Say N if you expect high stability and performance. Saying Y will not
affect other devices support and may provide support for basic needs.
config B43_PHY_LP
- bool "Support for low-power (LP-PHY) devices (EXPERIMENTAL)"
- depends on B43 && EXPERIMENTAL
+ bool "Support for low-power (LP-PHY) devices"
+ depends on B43 && B43_SSB
default y
---help---
Support for the LP-PHY.
The LP-PHY is a low-power PHY built into some notebooks
- and embedded devices. It supports 802.11a/g
+ 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) devices"
+ depends on B43 && B43_BCMA
+ default y
+ ---help---
+ Support for the HT-PHY.
+
+ Enables support for BCM4331 and possibly other chipsets with that PHY.
+
+config B43_PHY_LCN
+ bool "Support for LCN-PHY devices (BROKEN)"
+ depends on B43 && BROKEN
+ ---help---
+ Support for the LCN-PHY.
+
+ Say N, this is BROKEN and crashes driver.
+
# This config option automatically enables b43 LEDS support,
# if it's possible.
config B43_LEDS
@@ -128,8 +182,8 @@ config B43_DEBUG
Broadcom 43xx debugging.
This adds additional runtime sanity checks and statistics to the driver.
- These checks and statistics might me expensive and hurt runtime performance
- of your system.
+ 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.
@@ -137,13 +191,3 @@ config B43_DEBUG
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.
-
-config B43_FORCE_PIO
- bool "Force usage of PIO instead of DMA"
- depends on B43 && B43_DEBUG
- ---help---
- This will disable DMA and always enable PIO instead.
-
- Say N!
- This is only for debugging the PIO engine code. You do
- _NOT_ want to enable this.
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile
index cef334a8c66..098fe9ee709 100644
--- a/drivers/net/wireless/b43/Makefile
+++ b/drivers/net/wireless/b43/Makefile
@@ -1,14 +1,20 @@
b43-y += main.o
+b43-y += bus.o
b43-y += tables.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-y += phy_g.o
b43-y += phy_a.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-y += sysfs.o
b43-y += xmit.o
b43-y += lo.o
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index bd4cb75b6ca..4113b693476 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -5,21 +5,19 @@
#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"
-/* The unique identifier of the firmware that's officially supported by
- * this driver version. */
-#define B43_SUPPORTED_FIRMWARE_ID "FW13"
-
-
#ifdef CONFIG_B43_DEBUG
# define B43_DEBUG 1
#else
@@ -90,6 +88,8 @@
#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
@@ -108,21 +108,61 @@
#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_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 */
@@ -152,6 +192,9 @@
#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 */
@@ -165,6 +208,14 @@
#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
@@ -191,16 +242,18 @@ enum {
#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_HOSTFLO 0x005E /* Hostflags for ucode options (low) */
-#define B43_SHM_SH_HOSTFMI 0x0060 /* Hostflags for ucode options (middle) */
-#define B43_SHM_SH_HOSTFHI 0x0062 /* Hostflags for ucode options (high) */
+#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_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) */
@@ -232,7 +285,9 @@ enum {
#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 */
@@ -361,6 +416,12 @@ enum {
#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
@@ -414,6 +475,29 @@ enum {
#define B43_MACCMD_CCA 0x00000008 /* Clear channel assessment */
#define B43_MACCMD_BGNOISE 0x00000010 /* Background noise */
+/* 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_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) */
@@ -567,6 +651,10 @@ struct b43_dma {
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;
@@ -603,6 +691,7 @@ struct b43_key {
};
/* 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)
@@ -642,14 +731,16 @@ enum b43_firmware_file_type {
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 occured while requesting. Firmware reqest
- * can not continue, as any other reqest will also fail. */
+ /* A fatal error occurred while requesting. Firmware request
+ * can not continue, as any other request will also fail. */
int fatal_failure;
};
@@ -666,6 +757,12 @@ struct b43_firmware_file {
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 */
@@ -682,6 +779,9 @@ struct b43_firmware {
/* 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;
@@ -705,8 +805,10 @@ enum {
/* Data structure for one wireless device (802.11 core) */
struct b43_wldev {
- struct ssb_device *dev;
+ 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. */
@@ -785,12 +887,9 @@ struct b43_wl {
* handler, only. This basically is just the IRQ mask register. */
spinlock_t hardirq_lock;
- /* The number of queues that were registered with the mac80211 subsystem
- * initially. This is a backup copy of hw->queues in case hw->queues has
- * to be dynamically lowered at runtime (Firmware does not support QoS).
- * hw->queues has to be restored to the original value before unregistering
- * from the mac80211 subsystem. */
- u16 mac80211_initially_registered_queues;
+ /* 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.
@@ -816,10 +915,6 @@ struct b43_wl {
char rng_name[30 + 1];
#endif /* CONFIG_B43_HWRNG */
- /* List of all wireless devices on this chip */
- struct list_head devlist;
- u8 nr_devs;
-
bool radiotap_enabled;
bool radio_enabled;
@@ -831,7 +926,7 @@ struct b43_wl {
struct work_struct beacon_update_trigger;
/* The current QOS parameters for the 4 queues. */
- struct b43_qos_params qos_params[4];
+ 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
@@ -840,14 +935,21 @@ struct b43_wl {
/* Packet transmit work */
struct work_struct tx_work;
+
/* Queue of packets to be transmitted. */
- struct sk_buff_head tx_queue;
+ 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[110] __attribute__((__aligned__(8)));
+ u8 pio_scratchspace[118] __attribute__((__aligned__(8)));
u8 pio_tailspace[4] __attribute__((__aligned__(8)));
};
@@ -874,27 +976,74 @@ static inline int b43_is_mode(struct b43_wl *wl, int type)
*/
static inline enum ieee80211_band b43_current_band(struct b43_wl *wl)
{
- return wl->hw->conf.channel->band;
+ 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 ssb_read16(dev->dev, offset);
+ return dev->dev->read16(dev->dev, offset);
}
static inline void b43_write16(struct b43_wldev *dev, u16 offset, u16 value)
{
- ssb_write16(dev->dev, offset, value);
+ dev->dev->write16(dev->dev, offset, value);
+}
+
+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 ssb_read32(dev->dev, offset);
+ return dev->dev->read32(dev->dev, offset);
}
static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value)
{
- ssb_write32(dev->dev, offset, 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)
@@ -902,21 +1051,11 @@ static inline bool b43_using_pio_transfers(struct b43_wldev *dev)
return dev->__using_pio_transfers;
}
-#ifdef CONFIG_B43_FORCE_PIO
-# define B43_PIO_DEFAULT 1
-#else
-# define B43_PIO_DEFAULT 0
-#endif
-
/* Message printing */
-void b43info(struct b43_wl *wl, const char *fmt, ...)
- __attribute__ ((format(printf, 2, 3)));
-void b43err(struct b43_wl *wl, const char *fmt, ...)
- __attribute__ ((format(printf, 2, 3)));
-void b43warn(struct b43_wl *wl, const char *fmt, ...)
- __attribute__ ((format(printf, 2, 3)));
-void b43dbg(struct b43_wl *wl, const char *fmt, ...)
- __attribute__ ((format(printf, 2, 3)));
+__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.
diff --git a/drivers/net/wireless/b43/bus.c b/drivers/net/wireless/b43/bus.c
new file mode 100644
index 00000000000..565fdbdd691
--- /dev/null
+++ b/drivers/net/wireless/b43/bus.c
@@ -0,0 +1,255 @@
+/*
+
+ 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.
+
+*/
+
+#include "b43.h"
+#include "bus.h"
+
+/* BCMA */
+#ifdef CONFIG_B43_BCMA
+static int b43_bus_bcma_bus_may_powerdown(struct b43_bus_dev *dev)
+{
+ return 0; /* bcma_bus_may_powerdown(dev->bdev->bus); */
+}
+static int b43_bus_bcma_bus_powerup(struct b43_bus_dev *dev,
+ bool dynamic_pctl)
+{
+ return 0; /* bcma_bus_powerup(dev->sdev->bus, dynamic_pctl); */
+}
+static int b43_bus_bcma_device_is_enabled(struct b43_bus_dev *dev)
+{
+ return bcma_core_is_enabled(dev->bdev);
+}
+static void b43_bus_bcma_device_enable(struct b43_bus_dev *dev,
+ u32 core_specific_flags)
+{
+ bcma_core_enable(dev->bdev, core_specific_flags);
+}
+static void b43_bus_bcma_device_disable(struct b43_bus_dev *dev,
+ u32 core_specific_flags)
+{
+ bcma_core_disable(dev->bdev, core_specific_flags);
+}
+static u16 b43_bus_bcma_read16(struct b43_bus_dev *dev, u16 offset)
+{
+ return bcma_read16(dev->bdev, offset);
+}
+static u32 b43_bus_bcma_read32(struct b43_bus_dev *dev, u16 offset)
+{
+ return bcma_read32(dev->bdev, offset);
+}
+static
+void b43_bus_bcma_write16(struct b43_bus_dev *dev, u16 offset, u16 value)
+{
+ bcma_write16(dev->bdev, offset, value);
+}
+static
+void b43_bus_bcma_write32(struct b43_bus_dev *dev, u16 offset, u32 value)
+{
+ bcma_write32(dev->bdev, offset, value);
+}
+static
+void b43_bus_bcma_block_read(struct b43_bus_dev *dev, void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ bcma_block_read(dev->bdev, buffer, count, offset, reg_width);
+}
+static
+void b43_bus_bcma_block_write(struct b43_bus_dev *dev, const void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ bcma_block_write(dev->bdev, buffer, count, offset, reg_width);
+}
+
+struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core)
+{
+ struct b43_bus_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return NULL;
+
+ dev->bus_type = B43_BUS_BCMA;
+ dev->bdev = core;
+
+ dev->bus_may_powerdown = b43_bus_bcma_bus_may_powerdown;
+ dev->bus_powerup = b43_bus_bcma_bus_powerup;
+ dev->device_is_enabled = b43_bus_bcma_device_is_enabled;
+ dev->device_enable = b43_bus_bcma_device_enable;
+ dev->device_disable = b43_bus_bcma_device_disable;
+
+ dev->read16 = b43_bus_bcma_read16;
+ dev->read32 = b43_bus_bcma_read32;
+ dev->write16 = b43_bus_bcma_write16;
+ dev->write32 = b43_bus_bcma_write32;
+ dev->block_read = b43_bus_bcma_block_read;
+ dev->block_write = b43_bus_bcma_block_write;
+
+ dev->dev = &core->dev;
+ dev->dma_dev = core->dma_dev;
+ dev->irq = core->irq;
+
+ dev->board_vendor = core->bus->boardinfo.vendor;
+ dev->board_type = core->bus->boardinfo.type;
+ dev->board_rev = core->bus->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/b43/bus.h b/drivers/net/wireless/b43/bus.h
new file mode 100644
index 00000000000..f3205c6988b
--- /dev/null
+++ b/drivers/net/wireless/b43/bus.h
@@ -0,0 +1,80 @@
+#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);
+
+ 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_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/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c
index 59f59fa4033..e807bd93064 100644
--- a/drivers/net/wireless/b43/debugfs.c
+++ b/drivers/net/wireless/b43/debugfs.c
@@ -4,7 +4,7 @@
debugfs driver debugging code
- Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
+ 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
@@ -500,12 +500,6 @@ out:
#undef fappend
-static int b43_debugfs_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
@@ -624,7 +618,7 @@ out_unlock:
.read = _read, \
.write = _write, \
.fops = { \
- .open = b43_debugfs_open, \
+ .open = simple_open, \
.read = b43_debugfs_read, \
.write = b43_debugfs_write, \
.llseek = generic_file_llseek, \
diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h
index 822aad8842f..50517b801cb 100644
--- a/drivers/net/wireless/b43/debugfs.h
+++ b/drivers/net/wireless/b43/debugfs.h
@@ -86,7 +86,7 @@ void b43_debugfs_log_txstat(struct b43_wldev *dev,
static inline bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature)
{
- return 0;
+ return false;
}
static inline void b43_debugfs_init(void)
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 3d5566e7af0..1d7982afc0a 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -4,7 +4,7 @@
DMA ringbuffer and descriptor allocation/management
- Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+ 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
@@ -47,6 +47,38 @@
* 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
@@ -77,10 +109,9 @@ static void op32_fill_descriptor(struct b43_dmaring *ring,
slot = (int)(&(desc->dma32) - descbase);
B43_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 |= ssb_dma_translation(ring->dev->dev);
+ 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;
@@ -170,11 +201,10 @@ static void op64_fill_descriptor(struct b43_dmaring *ring,
slot = (int)(&(desc->dma64) - descbase);
B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
- addrlo = (u32) (dmaaddr & 0xFFFFFFFF);
- addrhi = (((u64) dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK);
- addrext = (((u64) dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
- addrhi |= (ssb_dma_translation(ring->dev->dev) << 1);
+ 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)
@@ -379,43 +409,42 @@ static inline
struct b43_dmadesc_meta *meta)
{
if (meta->skb) {
- dev_kfree_skb_any(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)
{
- gfp_t flags = GFP_KERNEL;
-
/* 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. Testing
- * has shown that 4K is sufficient for the latter as long as the buffer
- * does not cross an 8K boundary.
- *
- * For unknown reasons - possibly a hardware error - the BCM4311 rev
- * 02, which uses 64-bit DMA, needs the ring buffer in very low memory,
- * which accounts for the GFP_DMA flag below.
- *
- * The flags here must match the flags in free_ringmemory below!
+ * 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.
*/
- if (ring->type == B43_DMA_64BIT)
- flags |= GFP_DMA;
- ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev,
- B43_DMA_RINGMEMSIZE,
- &(ring->dmabase), flags);
- if (!ring->descbase) {
- b43err(ring->dev->wl, "DMA ringmemory allocation failed\n");
+ 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;
- }
- memset(ring->descbase, 0, B43_DMA_RINGMEMSIZE);
return 0;
}
static void free_ringmemory(struct b43_dmaring *ring)
{
- dma_free_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE,
+ 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);
}
@@ -658,36 +687,37 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
int err = 0;
u32 value;
u32 addrext;
- u32 trans = ssb_dma_translation(ring->dev->dev);
+ 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);
- addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
value = B43_DMA64_TXENABLE;
value |= (addrext << B43_DMA64_TXADDREXT_SHIFT)
& B43_DMA64_TXADDREXT_MASK;
+ if (!parity)
+ value |= B43_DMA64_TXPARITYDISABLE;
b43_dma_write(ring, B43_DMA64_TXCTL, value);
- b43_dma_write(ring, B43_DMA64_TXRINGLO,
- (ringbase & 0xFFFFFFFF));
- b43_dma_write(ring, B43_DMA64_TXRINGHI,
- ((ringbase >> 32) &
- ~SSB_DMA_TRANSLATION_MASK)
- | (trans << 1));
+ 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);
- addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
value = B43_DMA32_TXENABLE;
value |= (addrext << B43_DMA32_TXADDREXT_SHIFT)
& B43_DMA32_TXADDREXT_MASK;
+ if (!parity)
+ value |= B43_DMA32_TXPARITYDISABLE;
b43_dma_write(ring, B43_DMA32_TXCTL, value);
- b43_dma_write(ring, B43_DMA32_TXRING,
- (ringbase & ~SSB_DMA_TRANSLATION_MASK)
- | trans);
+ b43_dma_write(ring, B43_DMA32_TXRING, addrlo);
}
} else {
err = alloc_initial_descbuffers(ring);
@@ -695,35 +725,34 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
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);
- addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
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,
- (ringbase & 0xFFFFFFFF));
- b43_dma_write(ring, B43_DMA64_RXRINGHI,
- ((ringbase >> 32) &
- ~SSB_DMA_TRANSLATION_MASK)
- | (trans << 1));
+ 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);
- addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
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,
- (ringbase & ~SSB_DMA_TRANSLATION_MASK)
- | trans);
+ b43_dma_write(ring, B43_DMA32_RXRING, addrlo);
b43_dma_write(ring, B43_DMA32_RXINDEX, ring->nr_slots *
sizeof(struct b43_dmadesc32));
}
@@ -757,14 +786,14 @@ static void dmacontroller_cleanup(struct b43_dmaring *ring)
static void free_all_descbuffers(struct b43_dmaring *ring)
{
- struct b43_dmadesc_generic *desc;
struct b43_dmadesc_meta *meta;
int i;
if (!ring->used_slots)
return;
for (i = 0; i < ring->nr_slots; i++) {
- desc = ring->ops->idx2desc(ring, i, &meta);
+ /* 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);
@@ -786,9 +815,23 @@ static u64 supported_dma_mask(struct b43_wldev *dev)
u32 tmp;
u16 mmio_base;
- tmp = b43_read32(dev, SSB_TMSHIGH);
- if (tmp & SSB_TMSHIGH_DMA64)
- return DMA_BIT_MASK(64);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ tmp = bcma_aread32(dev->dev->bdev, BCMA_IOST);
+ if (tmp & BCMA_IOST_DMA64)
+ return DMA_BIT_MASK(64);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
+ if (tmp & SSB_TMSHIGH_DMA64)
+ return DMA_BIT_MASK(64);
+ break;
+#endif
+ }
+
mmio_base = b43_dmacontroller_base(0, 0);
b43_write32(dev, mmio_base + B43_DMA32_TXCTL, B43_DMA32_TXADDREXT_MASK);
tmp = b43_read32(dev, mmio_base + B43_DMA32_TXCTL);
@@ -845,12 +888,21 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
else
ring->ops = &dma32_ops;
if (for_tx) {
- ring->tx = 1;
+ ring->tx = true;
ring->current_slot = -1;
} else {
if (ring->index == 0) {
- ring->rx_buffersize = B43_DMA0_RX_BUFFERSIZE;
- ring->frameoffset = B43_DMA0_RX_FRAMEOFFSET;
+ 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);
}
@@ -1007,26 +1059,23 @@ void b43_dma_free(struct b43_wldev *dev)
static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask)
{
u64 orig_mask = mask;
- bool fallback = 0;
+ 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(dev->dev->dma_dev, mask);
- if (!err) {
- err = dma_set_coherent_mask(dev->dev->dma_dev, mask);
- if (!err)
- break;
- }
+ 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 = 1;
+ fallback = true;
continue;
}
if (mask == DMA_BIT_MASK(32)) {
mask = DMA_BIT_MASK(30);
- fallback = 1;
+ fallback = true;
continue;
}
b43err(dev->wl, "The machine/kernel does not support "
@@ -1043,6 +1092,25 @@ static int b43_dma_set_mask(struct b43_wldev *dev, u64 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 1;
+
+#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 1;
+#endif
+ return 0;
+}
+
int b43_dma_init(struct b43_wldev *dev)
{
struct b43_dma *dma = &dev->dma;
@@ -1056,6 +1124,27 @@ int b43_dma_init(struct b43_wldev *dev)
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);
@@ -1084,7 +1173,7 @@ int b43_dma_init(struct b43_wldev *dev)
goto err_destroy_mcast;
/* No support for the TX status DMA ring. */
- B43_WARN_ON(dev->dev->id.revision < 5);
+ B43_WARN_ON(dev->dev->core_rev < 5);
b43dbg(dev->wl, "%u-bit DMA initialized\n",
(unsigned int)type);
@@ -1213,7 +1302,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
memset(meta, 0, sizeof(*meta));
meta->skb = skb;
- meta->is_last_fragment = 1;
+ meta->is_last_fragment = true;
priv_info->bouncebuffer = NULL;
meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
@@ -1360,7 +1449,7 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *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);
+ ieee80211_free_txskb(dev->wl->hw, skb);
err = 0;
goto out;
}
@@ -1371,8 +1460,10 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
if ((free_slots(ring) < TX_SLOTS_PER_FRAME) ||
should_inject_overflow(ring)) {
/* This TX ring is full. */
- ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb));
- ring->stopped = 1;
+ 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);
}
@@ -1387,10 +1478,13 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
{
const struct b43_dma_ops *ops;
struct b43_dmaring *ring;
- struct b43_dmadesc_generic *desc;
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, err_out2;
ring = parse_cookie(dev, status->cookie, &slot);
if (unlikely(!ring))
@@ -1403,19 +1497,43 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
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. */
- b43dbg(dev->wl, "Out of order TX status report on DMA ring %d. "
- "Expected %d, but got %d\n",
- ring->index, firstused, slot);
- return;
+ * 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 once.
+ */
+ if (!err_out2)
+ b43dbg(dev->wl,
+ "Out of order TX status report on DMA ring %d. Expected %d, but got %d\n",
+ ring->index, firstused, slot);
+ err_out2 = 1;
+ return;
+ }
}
ops = ring->ops;
while (1) {
B43_WARN_ON(slot < 0 || slot >= ring->nr_slots);
- desc = ops->idx2desc(ring, slot, &meta);
+ /* 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) "
@@ -1423,11 +1541,13 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
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));
+ b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb));
- unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1);
+ unmap_descbuffer(ring, meta->dmaaddr,
+ meta->skb->len, 1);
kfree(priv_info->bouncebuffer);
priv_info->bouncebuffer = NULL;
} else {
@@ -1439,8 +1559,9 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
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. */
+ /* 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);
@@ -1451,9 +1572,18 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
/*
* Call back to inform the ieee80211 subsystem about
- * the status of the transmission.
+ * 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
*/
- frame_succeed = b43_fill_txstatus_report(dev, info, status);
+ 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++;
@@ -1481,21 +1611,32 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
/* Everything unmapped and free'd. So it's not used anymore. */
ring->used_slots--;
- if (meta->is_last_fragment) {
+ 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);
- ring->stopped = 0;
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)
@@ -1536,7 +1677,7 @@ static void dma_rx(struct b43_dmaring *ring, int *slot)
dmaaddr = meta->dmaaddr;
goto drop_recycle_buffer;
}
- if (unlikely(len > ring->rx_buffersize)) {
+ 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
@@ -1584,6 +1725,25 @@ drop_recycle_buffer:
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;
@@ -1599,6 +1759,7 @@ void b43_dma_rx(struct b43_dmaring *ring)
dma_rx(ring, &slot);
update_max_used_slots(ring, ++used_slots);
}
+ wmb();
ops->set_current_rxslot(ring, slot);
ring->current_slot = slot;
}
diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h
index a01c2100f16..df8c8cdcbdb 100644
--- a/drivers/net/wireless/b43/dma.h
+++ b/drivers/net/wireless/b43/dma.h
@@ -9,7 +9,7 @@
/* DMA-Interrupt reasons. */
#define B43_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \
| (1 << 14) | (1 << 15))
-#define B43_DMAIRQ_NONFATALMASK (1 << 13)
+#define B43_DMAIRQ_RDESC_UFLOW (1 << 13)
#define B43_DMAIRQ_RX_DONE (1 << 16)
/*** 32-bit DMA Engine. ***/
@@ -20,6 +20,7 @@
#define B43_DMA32_TXSUSPEND 0x00000002
#define B43_DMA32_TXLOOPBACK 0x00000004
#define B43_DMA32_TXFLUSH 0x00000010
+#define B43_DMA32_TXPARITYDISABLE 0x00000800
#define B43_DMA32_TXADDREXT_MASK 0x00030000
#define B43_DMA32_TXADDREXT_SHIFT 16
#define B43_DMA32_TXRING 0x04
@@ -44,6 +45,7 @@
#define B43_DMA32_RXFROFF_MASK 0x000000FE
#define B43_DMA32_RXFROFF_SHIFT 1
#define B43_DMA32_RXDIRECTFIFO 0x00000100
+#define B43_DMA32_RXPARITYDISABLE 0x00000800
#define B43_DMA32_RXADDREXT_MASK 0x00030000
#define B43_DMA32_RXADDREXT_SHIFT 16
#define B43_DMA32_RXRING 0x14
@@ -84,6 +86,7 @@ struct b43_dmadesc32 {
#define B43_DMA64_TXSUSPEND 0x00000002
#define B43_DMA64_TXLOOPBACK 0x00000004
#define B43_DMA64_TXFLUSH 0x00000010
+#define B43_DMA64_TXPARITYDISABLE 0x00000800
#define B43_DMA64_TXADDREXT_MASK 0x00030000
#define B43_DMA64_TXADDREXT_SHIFT 16
#define B43_DMA64_TXINDEX 0x04
@@ -111,6 +114,7 @@ struct b43_dmadesc32 {
#define B43_DMA64_RXFROFF_MASK 0x000000FE
#define B43_DMA64_RXFROFF_SHIFT 1
#define B43_DMA64_RXDIRECTFIFO 0x00000100
+#define B43_DMA64_RXPARITYDISABLE 0x00000800
#define B43_DMA64_RXADDREXT_MASK 0x00030000
#define B43_DMA64_RXADDREXT_SHIFT 16
#define B43_DMA64_RXINDEX 0x24
@@ -157,13 +161,17 @@ struct b43_dmadesc_generic {
} __packed;
/* Misc DMA constants */
-#define B43_DMA_RINGMEMSIZE PAGE_SIZE
-#define B43_DMA0_RX_FRAMEOFFSET 30
+#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 64
-#define B43_DMA0_RX_BUFFERSIZE IEEE80211_MAX_FRAME_LEN
+#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))
@@ -208,6 +216,12 @@ enum b43_dmatype {
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;
@@ -281,6 +295,8 @@ int b43_dma_tx(struct b43_wldev *dev,
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,
diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c
index c587115dd2b..d79ab2a227e 100644
--- a/drivers/net/wireless/b43/leds.c
+++ b/drivers/net/wireless/b43/leds.c
@@ -5,7 +5,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
+ 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>
@@ -74,7 +74,7 @@ static void b43_led_update(struct b43_wldev *dev,
if (radio_enabled)
turn_on = atomic_read(&led->state) != LED_OFF;
else
- turn_on = 0;
+ turn_on = false;
if (turn_on == led->hw_state)
return;
led->hw_state = turn_on;
@@ -215,28 +215,27 @@ static void b43_led_get_sprominfo(struct b43_wldev *dev,
enum b43_led_behaviour *behaviour,
bool *activelow)
{
- struct ssb_bus *bus = dev->dev->bus;
u8 sprom[4];
- sprom[0] = bus->sprom.gpio0;
- sprom[1] = bus->sprom.gpio1;
- sprom[2] = bus->sprom.gpio2;
- sprom[3] = bus->sprom.gpio3;
+ 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[led_index] == 0xFF) {
/* There is no LED information in the SPROM
* for this LED. Hardcode it here. */
- *activelow = 0;
+ *activelow = false;
switch (led_index) {
case 0:
*behaviour = B43_LED_ACTIVITY;
- *activelow = 1;
- if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ)
+ *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 (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK)
+ if (dev->dev->board_vendor == PCI_VENDOR_ID_ASUSTEK)
*behaviour = B43_LED_ASSOC;
break;
case 2:
@@ -268,11 +267,11 @@ void b43_leds_init(struct b43_wldev *dev)
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 = 1;
+ led->hw_state = true;
atomic_set(&led->state, 1);
} else {
b43_led_turn_off(dev, led->index, led->activelow);
- led->hw_state = 0;
+ led->hw_state = false;
atomic_set(&led->state, 0);
}
}
@@ -281,19 +280,19 @@ void b43_leds_init(struct b43_wldev *dev)
led = &dev->wl->leds.led_tx;
if (led->wl) {
b43_led_turn_off(dev, led->index, led->activelow);
- led->hw_state = 0;
+ 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 = 0;
+ 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 = 0;
+ led->hw_state = false;
atomic_set(&led->state, 0);
}
diff --git a/drivers/net/wireless/b43/lo.c b/drivers/net/wireless/b43/lo.c
index 94e4f1378fc..916123a3d74 100644
--- a/drivers/net/wireless/b43/lo.c
+++ b/drivers/net/wireless/b43/lo.c
@@ -6,7 +6,7 @@
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 <mb@bu3sch.de>
+ 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>
@@ -98,7 +98,7 @@ static u16 lo_measure_feedthrough(struct b43_wldev *dev,
rfover |= pga;
rfover |= lna;
rfover |= trsw_rx;
- if ((dev->dev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA)
+ if ((dev->dev->bus_sprom->boardflags_lo & B43_BFL_EXTLNA)
&& phy->rev > 6)
rfover |= B43_PHY_RFOVERVAL_EXTLNA;
@@ -301,14 +301,12 @@ static void lo_measure_gain_values(struct b43_wldev *dev,
max_rx_gain = 0;
if (has_loopback_gain(phy)) {
- int trsw_rx = 0;
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;
- trsw_rx = 0x20;
}
} else
trsw_rx_gain = max_rx_gain;
@@ -387,7 +385,7 @@ struct lo_g_saved_values {
static void lo_measure_setup(struct b43_wldev *dev,
struct lo_g_saved_values *sav)
{
- struct ssb_sprom *sprom = &dev->dev->bus->sprom;
+ 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;
@@ -828,7 +826,7 @@ void b43_gphy_dc_lt_init(struct b43_wldev *dev, bool update_all)
const struct b43_rfatt *rfatt;
const struct b43_bbatt *bbatt;
u64 power_vector;
- bool table_changed = 0;
+ bool table_changed = false;
BUILD_BUG_ON(B43_DC_LT_SIZE != 32);
B43_WARN_ON(lo->rfatt_list.len * lo->bbatt_list.len > 64);
@@ -878,7 +876,7 @@ void b43_gphy_dc_lt_init(struct b43_wldev *dev, bool update_all)
lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xFF00)
| (val & 0x00FF);
}
- table_changed = 1;
+ table_changed = true;
}
if (table_changed) {
/* The table changed in memory. Update the hardware table. */
@@ -940,7 +938,7 @@ void b43_lo_g_maintanance_work(struct b43_wldev *dev)
unsigned long now;
unsigned long expire;
struct b43_lo_calib *cal, *tmp;
- bool current_item_expired = 0;
+ bool current_item_expired = false;
bool hwpctl;
if (!lo)
@@ -970,7 +968,7 @@ void b43_lo_g_maintanance_work(struct b43_wldev *dev)
if (b43_compare_bbatt(&cal->bbatt, &gphy->bbatt) &&
b43_compare_rfatt(&cal->rfatt, &gphy->rfatt)) {
B43_WARN_ON(current_item_expired);
- current_item_expired = 1;
+ current_item_expired = true;
}
if (b43_debug(dev, B43_DBG_LO)) {
b43dbg(dev->wl, "LO: Item BB(%u), RF(%u,%u), "
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 22bc9f17f63..0d6a0bb1f87 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -4,9 +4,10 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>
Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005-2009 Michael Buesch <mb@bu3sch.de>
+ 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>
@@ -33,11 +34,10 @@
#include <linux/delay.h>
#include <linux/init.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
#include <linux/firmware.h>
-#include <linux/wireless.h>
#include <linux/workqueue.h>
#include <linux/skbuff.h>
#include <linux/io.h>
@@ -65,13 +65,14 @@ 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_SUPPORTED_FIRMWARE_ID);
MODULE_FIRMWARE("b43/ucode11.fw");
MODULE_FIRMWARE("b43/ucode13.fw");
MODULE_FIRMWARE("b43/ucode14.fw");
MODULE_FIRMWARE("b43/ucode15.fw");
+MODULE_FIRMWARE("b43/ucode16_mimo.fw");
MODULE_FIRMWARE("b43/ucode5.fw");
MODULE_FIRMWARE("b43/ucode9.fw");
@@ -108,10 +109,26 @@ 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 = B43_PIO_DEFAULT;
+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, 0x17, BCMA_ANY_CLASS),
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS),
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1D, BCMA_ANY_CLASS),
+ BCMA_CORETABLE_END
+};
+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),
@@ -125,8 +142,8 @@ static const struct ssb_device_id b43_ssb_tbl[] = {
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 16),
SSB_DEVTABLE_END
};
-
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
@@ -165,7 +182,7 @@ static struct ieee80211_rate __b43_ratetable[] = {
#define b43_g_ratetable (__b43_ratetable + 0)
#define b43_g_ratetable_size 12
-#define CHAN4G(_channel, _freq, _flags) { \
+#define CHAN2G(_channel, _freq, _flags) { \
.band = IEEE80211_BAND_2GHZ, \
.center_freq = (_freq), \
.hw_value = (_channel), \
@@ -174,23 +191,31 @@ static struct ieee80211_rate __b43_ratetable[] = {
.max_power = 30, \
}
static struct ieee80211_channel b43_2ghz_chantable[] = {
- CHAN4G(1, 2412, 0),
- CHAN4G(2, 2417, 0),
- CHAN4G(3, 2422, 0),
- CHAN4G(4, 2427, 0),
- CHAN4G(5, 2432, 0),
- CHAN4G(6, 2437, 0),
- CHAN4G(7, 2442, 0),
- CHAN4G(8, 2447, 0),
- CHAN4G(9, 2452, 0),
- CHAN4G(10, 2457, 0),
- CHAN4G(11, 2462, 0),
- CHAN4G(12, 2467, 0),
- CHAN4G(13, 2472, 0),
- CHAN4G(14, 2484, 0),
+ 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),
};
-#undef CHAN4G
+#undef CHAN2G
+#define CHAN4G(_channel, _flags) { \
+ .band = IEEE80211_BAND_5GHZ, \
+ .center_freq = 4000 + (5 * (_channel)), \
+ .hw_value = (_channel), \
+ .flags = (_flags), \
+ .max_antenna_gain = 0, \
+ .max_power = 30, \
+}
#define CHAN5G(_channel, _flags) { \
.band = IEEE80211_BAND_5GHZ, \
.center_freq = 5000 + (5 * (_channel)), \
@@ -200,6 +225,18 @@ static struct ieee80211_channel b43_2ghz_chantable[] = {
.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),
@@ -243,18 +280,7 @@ static struct ieee80211_channel b43_5ghz_nphy_chantable[] = {
CHAN5G(170, 0), CHAN5G(172, 0),
CHAN5G(174, 0), CHAN5G(176, 0),
CHAN5G(178, 0), CHAN5G(180, 0),
- CHAN5G(182, 0), CHAN5G(184, 0),
- CHAN5G(186, 0), CHAN5G(188, 0),
- CHAN5G(190, 0), CHAN5G(192, 0),
- CHAN5G(194, 0), CHAN5G(196, 0),
- CHAN5G(198, 0), CHAN5G(200, 0),
- CHAN5G(202, 0), CHAN5G(204, 0),
- CHAN5G(206, 0), CHAN5G(208, 0),
- CHAN5G(210, 0), CHAN5G(212, 0),
- CHAN5G(214, 0), CHAN5G(216, 0),
- CHAN5G(218, 0), CHAN5G(220, 0),
- CHAN5G(222, 0), CHAN5G(224, 0),
- CHAN5G(226, 0), CHAN5G(228, 0),
+ CHAN5G(182, 0),
};
static struct ieee80211_channel b43_5ghz_aphy_chantable[] = {
@@ -278,6 +304,7 @@ static struct ieee80211_channel b43_5ghz_aphy_chantable[] = {
CHAN5G(208, 0), CHAN5G(212, 0),
CHAN5G(216, 0),
};
+#undef CHAN4G
#undef CHAN5G
static struct ieee80211_supported_band b43_band_5GHz_nphy = {
@@ -308,6 +335,10 @@ 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)
{
@@ -514,11 +545,11 @@ u64 b43_hf_read(struct b43_wldev *dev)
{
u64 ret;
- ret = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI);
+ 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_HOSTFMI);
+ 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_HOSTFLO);
+ ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF1);
return ret;
}
@@ -531,9 +562,9 @@ void b43_hf_write(struct b43_wldev *dev, u64 value)
lo = (value & 0x00000000FFFFULL);
mi = (value & 0x0000FFFF0000ULL) >> 16;
hi = (value & 0xFFFF00000000ULL) >> 32;
- b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO, lo);
- b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFMI, mi);
- b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI, hi);
+ 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) */
@@ -547,7 +578,7 @@ void b43_tsf_read(struct b43_wldev *dev, u64 *tsf)
{
u32 low, high;
- B43_WARN_ON(dev->dev->id.revision < 3);
+ B43_WARN_ON(dev->dev->core_rev < 3);
/* The hardware guarantees us an atomic read, if we
* read the low register first. */
@@ -561,22 +592,14 @@ void b43_tsf_read(struct b43_wldev *dev, u64 *tsf)
static void b43_time_lock(struct b43_wldev *dev)
{
- u32 macctl;
-
- macctl = b43_read32(dev, B43_MMIO_MACCTL);
- macctl |= B43_MACCTL_TBTTHOLD;
- b43_write32(dev, B43_MMIO_MACCTL, macctl);
+ 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)
{
- u32 macctl;
-
- macctl = b43_read32(dev, B43_MMIO_MACCTL);
- macctl &= ~B43_MACCTL_TBTTHOLD;
- b43_write32(dev, B43_MMIO_MACCTL, macctl);
+ b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_TBTTHOLD, 0);
/* Commit the write */
b43_read32(dev, B43_MMIO_MACCTL);
}
@@ -585,7 +608,7 @@ static void b43_tsf_write_locked(struct b43_wldev *dev, u64 tsf)
{
u32 low, high;
- B43_WARN_ON(dev->dev->id.revision < 3);
+ B43_WARN_ON(dev->dev->core_rev < 3);
low = tsf;
high = (tsf >> 32);
@@ -712,52 +735,59 @@ void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on)
for (i = 0; i < 5; i++)
b43_ram_write(dev, i * 4, buffer[i]);
- b43_write16(dev, 0x0568, 0x0000);
- if (dev->dev->id.revision < 11)
- b43_write16(dev, 0x07C0, 0x0000);
+ b43_write16(dev, B43_MMIO_XMTSEL, 0x0000);
+
+ if (dev->dev->core_rev < 11)
+ b43_write16(dev, B43_MMIO_WEPCTL, 0x0000);
else
- b43_write16(dev, 0x07C0, 0x0100);
+ b43_write16(dev, B43_MMIO_WEPCTL, 0x0100);
+
value = (ofdm ? 0x41 : 0x40);
- b43_write16(dev, 0x050C, value);
- if ((phy->type == B43_PHYTYPE_N) || (phy->type == B43_PHYTYPE_LP))
- b43_write16(dev, 0x0514, 0x1A02);
- b43_write16(dev, 0x0508, 0x0000);
- b43_write16(dev, 0x050A, 0x0000);
- b43_write16(dev, 0x054C, 0x0000);
- b43_write16(dev, 0x056A, 0x0014);
- b43_write16(dev, 0x0568, 0x0826);
- b43_write16(dev, 0x0500, 0x0000);
- if (!pa_on && (phy->type == B43_PHYTYPE_N)) {
- //SPEC TODO
- }
+ 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:
- b43_write16(dev, 0x0502, 0x00D0);
+ case B43_PHYTYPE_LCN:
+ b43_write16(dev, B43_MMIO_TXE0_AUX, 0x00D0);
break;
case B43_PHYTYPE_LP:
- b43_write16(dev, 0x0502, 0x0050);
+ b43_write16(dev, B43_MMIO_TXE0_AUX, 0x0050);
break;
default:
- b43_write16(dev, 0x0502, 0x0030);
+ 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, 0x050E);
+ value = b43_read16(dev, B43_MMIO_TXE0_STATUS);
if (value & 0x0080)
break;
udelay(10);
}
for (i = 0x00; i < 0x0A; i++) {
- value = b43_read16(dev, 0x050E);
+ value = b43_read16(dev, B43_MMIO_TXE0_STATUS);
if (value & 0x0400)
break;
udelay(10);
}
for (i = 0x00; i < 0x19; i++) {
- value = b43_read16(dev, 0x0690);
+ value = b43_read16(dev, B43_MMIO_IFSSTAT);
if (!(value & 0x0100))
break;
udelay(10);
@@ -1098,17 +1128,17 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags)
B43_WARN_ON((ps_flags & B43_PS_AWAKE) && (ps_flags & B43_PS_ASLEEP));
if (ps_flags & B43_PS_ENABLED) {
- hwps = 1;
+ hwps = true;
} else if (ps_flags & B43_PS_DISABLED) {
- hwps = 0;
+ 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 = 1;
+ awake = true;
} else if (ps_flags & B43_PS_ASLEEP) {
- awake = 0;
+ 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
@@ -1116,8 +1146,8 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags)
}
/* FIXME: For now we force awake-on and hwps-off */
- hwps = 0;
- awake = 1;
+ hwps = false;
+ awake = true;
macctl = b43_read32(dev, B43_MMIO_MACCTL);
if (hwps)
@@ -1131,7 +1161,7 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags)
b43_write32(dev, B43_MMIO_MACCTL, macctl);
/* Commit write */
b43_read32(dev, B43_MMIO_MACCTL);
- if (awake && dev->dev->id.revision >= 5) {
+ 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,
@@ -1143,29 +1173,74 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags)
}
}
-void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags)
+#ifdef CONFIG_B43_BCMA
+static void b43_bcma_phy_reset(struct b43_wldev *dev)
{
- u32 tmslow;
- u32 macctl;
+ 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);
+
+ 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 */
- ssb_device_enable(dev->dev, flags);
+ b43_device_enable(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 &= ~B43_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);
+ 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
@@ -1176,7 +1251,7 @@ void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags)
macctl = b43_read32(dev, B43_MMIO_MACCTL);
macctl &= ~B43_MACCTL_GMODE;
- if (flags & B43_TMSLOW_GMODE)
+ if (gmode)
macctl |= B43_MACCTL_GMODE;
macctl |= B43_MACCTL_IHR_ENABLED;
b43_write32(dev, B43_MMIO_MACCTL, macctl);
@@ -1214,7 +1289,7 @@ static void drain_txstatus_queue(struct b43_wldev *dev)
{
u32 dummy;
- if (dev->dev->id.revision < 5)
+ if (dev->dev->core_rev < 5)
return;
/* Read all entries from the microcode TXstatus FIFO
* and throw them away.
@@ -1231,17 +1306,19 @@ static u32 b43_jssi_read(struct b43_wldev *dev)
{
u32 val = 0;
- val = b43_shm_read16(dev, B43_SHM_SHARED, 0x08A);
+ val = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_JSSI1);
val <<= 16;
- val |= b43_shm_read16(dev, B43_SHM_SHARED, 0x088);
+ 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, 0x088, (jssi & 0x0000FFFF));
- b43_shm_write16(dev, B43_SHM_SHARED, 0x08A, (jssi & 0xFFFF0000) >> 16);
+ 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)
@@ -1259,7 +1336,7 @@ static void b43_calculate_link_quality(struct b43_wldev *dev)
return;
if (dev->noisecalc.calculation_running)
return;
- dev->noisecalc.calculation_running = 1;
+ dev->noisecalc.calculation_running = true;
dev->noisecalc.nr_samples = 0;
b43_generate_noise_sample(dev);
@@ -1328,7 +1405,7 @@ static void handle_irq_noise(struct b43_wldev *dev)
average -= 48;
dev->stats.link_noise = average;
- dev->noisecalc.calculation_running = 0;
+ dev->noisecalc.calculation_running = false;
return;
}
generate_new:
@@ -1344,7 +1421,7 @@ static void handle_irq_tbtt_indication(struct b43_wldev *dev)
b43_power_saving_ctl_bits(dev, 0);
}
if (b43_is_mode(dev->wl, NL80211_IFTYPE_ADHOC))
- dev->dfq_valid = 1;
+ dev->dfq_valid = true;
}
static void handle_irq_atim_end(struct b43_wldev *dev)
@@ -1353,7 +1430,7 @@ static void handle_irq_atim_end(struct b43_wldev *dev)
b43_write32(dev, B43_MMIO_MACCMD,
b43_read32(dev, B43_MMIO_MACCMD)
| B43_MACCMD_DFQ_VALID);
- dev->dfq_valid = 0;
+ dev->dfq_valid = false;
}
}
@@ -1420,9 +1497,9 @@ u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev,
/* Get the mask of available antennas. */
if (dev->phy.gmode)
- antenna_mask = dev->dev->bus->sprom.ant_available_bg;
+ antenna_mask = dev->dev->bus_sprom->ant_available_bg;
else
- antenna_mask = dev->dev->bus->sprom.ant_available_a;
+ 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. */
@@ -1459,14 +1536,14 @@ static void b43_write_beacon_template(struct b43_wldev *dev,
unsigned int i, len, variable_len;
const struct ieee80211_mgmt *bcn;
const u8 *ie;
- bool tim_found = 0;
+ 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((size_t) dev->wl->current_beacon->len,
+ len = min_t(size_t, dev->wl->current_beacon->len,
0x200 - sizeof(struct b43_plcp_hdr6));
rate = ieee80211_get_tx_rate(dev->wl->hw, info)->hw_value;
@@ -1508,7 +1585,7 @@ static void b43_write_beacon_template(struct b43_wldev *dev,
/* A valid TIM is at least 4 bytes long. */
if (ie_len < 4)
break;
- tim_found = 1;
+ tim_found = true;
tim_position = sizeof(struct b43_plcp_hdr6);
tim_position += offsetof(struct ieee80211_mgmt, u.beacon.variable);
@@ -1544,8 +1621,8 @@ static void b43_upload_beacon0(struct b43_wldev *dev)
if (wl->beacon0_uploaded)
return;
- b43_write_beacon_template(dev, 0x68, 0x18);
- wl->beacon0_uploaded = 1;
+ 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)
@@ -1554,8 +1631,8 @@ static void b43_upload_beacon1(struct b43_wldev *dev)
if (wl->beacon1_uploaded)
return;
- b43_write_beacon_template(dev, 0x468, 0x1A);
- wl->beacon1_uploaded = 1;
+ 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)
@@ -1564,7 +1641,8 @@ static void handle_irq_beacon(struct b43_wldev *dev)
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_MESH_POINT) &&
+ !b43_is_mode(wl, NL80211_IFTYPE_ADHOC))
return;
/* This is the bottom half of the asynchronous beacon update. */
@@ -1586,7 +1664,7 @@ static void handle_irq_beacon(struct b43_wldev *dev)
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 = 0;
+ wl->beacon_templates_virgin = false;
b43_upload_beacon0(dev);
b43_upload_beacon1(dev);
cmd = b43_read32(dev, B43_MMIO_MACCMD);
@@ -1637,7 +1715,7 @@ static void b43_beacon_update_trigger_work(struct work_struct *work)
mutex_lock(&wl->mutex);
dev = wl->current_dev;
if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
- if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
+ if (b43_bus_host_is_sdio(dev->dev)) {
/* wl->mutex is enough. */
b43_do_beacon_update_trigger_work(dev);
mmiowb();
@@ -1674,15 +1752,15 @@ static void b43_update_templates(struct b43_wl *wl)
if (wl->current_beacon)
dev_kfree_skb_any(wl->current_beacon);
wl->current_beacon = beacon;
- wl->beacon0_uploaded = 0;
- wl->beacon1_uploaded = 0;
+ wl->beacon0_uploaded = false;
+ wl->beacon1_uploaded = false;
ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger);
}
static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
{
b43_time_lock(dev);
- if (dev->dev->id.revision >= 3) {
+ 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 {
@@ -1820,30 +1898,18 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev)
}
}
- if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK |
- B43_DMAIRQ_NONFATALMASK))) {
- if (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 "
+ 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 = 1;
- b43_controller_restart(dev, "DMA error");
- return;
- }
- if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) {
- b43err(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]);
- }
+ /* 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))
@@ -1862,6 +1928,11 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev)
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);
@@ -1916,10 +1987,10 @@ static irqreturn_t b43_do_interrupt(struct b43_wldev *dev)
return IRQ_NONE;
reason &= dev->irq_mask;
if (!reason)
- return IRQ_HANDLED;
+ return IRQ_NONE;
dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON)
- & 0x0001DC00;
+ & 0x0001FC00;
dev->dma_reason[1] = b43_read32(dev, B43_MMIO_DMA1_REASON)
& 0x0000DC00;
dev->dma_reason[2] = b43_read32(dev, B43_MMIO_DMA2_REASON)
@@ -1993,6 +2064,7 @@ void b43_do_release_fw(struct b43_firmware_file *fw)
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);
@@ -2013,11 +2085,18 @@ static void b43_print_fw_helptext(struct b43_wl *wl, bool error)
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)
+ struct b43_firmware_file *fw, bool async)
{
- const struct firmware *blob;
struct b43_fw_header *hdr;
u32 size;
int err;
@@ -2056,11 +2135,30 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx,
B43_WARN_ON(1);
return -ENOSYS;
}
- err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev);
+ 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);
+ "Firmware file \"%s\" not found\n",
+ ctx->fwname);
return err;
} else if (err) {
snprintf(ctx->errors[ctx->req_type],
@@ -2069,14 +2167,15 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx,
ctx->fwname, err);
return err;
}
- if (blob->size < sizeof(struct b43_fw_header))
+fw_ready:
+ if (ctx->blob->size < sizeof(struct b43_fw_header))
goto err_format;
- hdr = (struct b43_fw_header *)(blob->data);
+ 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 != blob->size - sizeof(struct b43_fw_header))
+ if (size != ctx->blob->size - sizeof(struct b43_fw_header))
goto err_format;
/* fallthrough */
case B43_FW_TYPE_IV:
@@ -2087,7 +2186,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx,
goto err_format;
}
- fw->data = blob;
+ fw->data = ctx->blob;
fw->filename = name;
fw->type = ctx->req_type;
@@ -2097,7 +2196,7 @@ err_format:
snprintf(ctx->errors[ctx->req_type],
sizeof(ctx->errors[ctx->req_type]),
"Firmware file \"%s\" format error.\n", ctx->fwname);
- release_firmware(blob);
+ release_firmware(ctx->blob);
return -EPROTO;
}
@@ -2106,28 +2205,49 @@ 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;
- const u8 rev = ctx->dev->dev->id.revision;
+ const u8 rev = ctx->dev->dev->core_rev;
const char *filename;
u32 tmshigh;
int err;
+ /* Files for HT and LCN were found by trying one by one */
+
/* Get microcode */
- tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH);
- if ((rev >= 5) && (rev <= 10))
+ if ((rev >= 5) && (rev <= 10)) {
filename = "ucode5";
- else if ((rev >= 11) && (rev <= 12))
+ } else if ((rev >= 11) && (rev <= 12)) {
filename = "ucode11";
- else if (rev == 13)
+ } else if (rev == 13) {
filename = "ucode13";
- else if (rev == 14)
+ } else if (rev == 14) {
filename = "ucode14";
- else if (rev == 15)
+ } else if (rev == 15) {
filename = "ucode15";
- else if ((rev >= 16) && (rev <= 20))
- filename = "ucode16_mimo";
- else
- goto err_no_ucode;
- err = b43_do_request_fw(ctx, filename, &fw->ucode);
+ } else {
+ switch (dev->phy.type) {
+ case B43_PHYTYPE_N:
+ if (rev >= 16)
+ filename = "ucode16_mimo";
+ else
+ goto err_no_ucode;
+ break;
+ case B43_PHYTYPE_HT:
+ if (rev == 29)
+ filename = "ucode29_mimo";
+ else
+ goto err_no_ucode;
+ break;
+ case B43_PHYTYPE_LCN:
+ if (rev == 24)
+ filename = "ucode24_mimo";
+ else
+ goto err_no_ucode;
+ break;
+ default:
+ goto err_no_ucode;
+ }
+ }
+ err = b43_do_request_fw(ctx, filename, &fw->ucode, true);
if (err)
goto err_load;
@@ -2138,12 +2258,12 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
filename = NULL;
else
goto err_no_pcm;
- fw->pcm_request_failed = 0;
- err = b43_do_request_fw(ctx, filename, &fw->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 = 1;
+ fw->pcm_request_failed = true;
} else if (err)
goto err_load;
@@ -2151,6 +2271,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
switch (dev->phy.type) {
case B43_PHYTYPE_A:
if ((rev >= 5) && (rev <= 10)) {
+ tmshigh = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY)
filename = "a0g1initvals5";
else
@@ -2184,10 +2305,22 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
else
goto err_no_initvals;
break;
+ case B43_PHYTYPE_HT:
+ if (rev == 29)
+ filename = "ht0initvals29";
+ else
+ goto err_no_initvals;
+ break;
+ case B43_PHYTYPE_LCN:
+ if (rev == 24)
+ filename = "lcn0initvals24";
+ else
+ goto err_no_initvals;
+ break;
default:
goto err_no_initvals;
}
- err = b43_do_request_fw(ctx, filename, &fw->initvals);
+ err = b43_do_request_fw(ctx, filename, &fw->initvals, false);
if (err)
goto err_load;
@@ -2195,6 +2328,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
switch (dev->phy.type) {
case B43_PHYTYPE_A:
if ((rev >= 5) && (rev <= 10)) {
+ tmshigh = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);
if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY)
filename = "a0g1bsinitvals5";
else
@@ -2230,13 +2364,27 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
else
goto err_no_initvals;
break;
+ case B43_PHYTYPE_HT:
+ if (rev == 29)
+ filename = "ht0bsinitvals29";
+ else
+ goto err_no_initvals;
+ break;
+ case B43_PHYTYPE_LCN:
+ if (rev == 24)
+ filename = "lcn0bsinitvals24";
+ else
+ goto err_no_initvals;
+ break;
default:
goto err_no_initvals;
}
- err = b43_do_request_fw(ctx, filename, &fw->initvals_band);
+ 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:
@@ -2268,8 +2416,15 @@ error:
return err;
}
-static int b43_request_firmware(struct b43_wldev *dev)
+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;
@@ -2277,37 +2432,55 @@ static int b43_request_firmware(struct b43_wldev *dev)
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
- return -ENOMEM;
+ return;
ctx->dev = dev;
ctx->req_type = B43_FWTYPE_PROPRIETARY;
err = b43_try_request_fw(ctx);
if (!err)
- goto out; /* Successfully loaded it. */
- err = ctx->fatal_failure;
- 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 out; /* Successfully loaded it. */
- err = ctx->fatal_failure;
- 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, errmsg);
+ b43err(dev->wl, "%s", errmsg);
}
b43_print_fw_helptext(dev->wl, 1);
- err = -ENOENT;
+ 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);
- return err;
}
static int b43_upload_microcode(struct b43_wldev *dev)
@@ -2357,10 +2530,8 @@ static int b43_upload_microcode(struct b43_wldev *dev)
b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_ALL);
/* Start the microcode PSM */
- macctl = b43_read32(dev, B43_MMIO_MACCTL);
- macctl &= ~B43_MACCTL_PSM_JMP0;
- macctl |= B43_MACCTL_PSM_RUN;
- b43_write32(dev, B43_MMIO_MACCTL, macctl);
+ b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_PSM_JMP0,
+ B43_MACCTL_PSM_RUN);
/* Wait for the microcode to load and respond */
i = 0;
@@ -2395,13 +2566,17 @@ static int b43_upload_microcode(struct b43_wldev *dev)
}
dev->fw.rev = fwrev;
dev->fw.patch = fwpatch;
- dev->fw.opensource = (fwdate == 0xFFFF);
+ 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));
- /* Default to use-all-queues. */
- dev->wl->hw->queues = dev->wl->mac80211_initially_registered_queues;
- dev->qos_enabled = !!modparam_qos;
+ dev->qos_enabled = dev->wl->hw->queues > 1;
/* Default to firmware/hardware crypto acceleration. */
- dev->hwcrypto_enabled = 1;
+ dev->hwcrypto_enabled = true;
if (dev->fw.opensource) {
u16 fwcapa;
@@ -2415,16 +2590,10 @@ static int b43_upload_microcode(struct b43_wldev *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 = 0;
- }
- if (!(fwcapa & B43_FWCAPA_QOS)) {
- b43info(dev->wl, "QoS not supported by firmware\n");
- /* Disable QoS. Tweak hw->queues to 1. It will be restored before
- * ieee80211_unregister to make sure the networking core can
- * properly free possible resources. */
- dev->wl->hw->queues = 1;
- dev->qos_enabled = 0;
+ 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",
@@ -2440,9 +2609,9 @@ static int b43_upload_microcode(struct b43_wldev *dev)
snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u",
dev->fw.rev, dev->fw.patch);
- wiphy->hw_version = dev->dev->id.coreid;
+ wiphy->hw_version = dev->dev->core_id;
- if (b43_is_old_txhdr_format(dev)) {
+ 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. "
@@ -2454,10 +2623,9 @@ static int b43_upload_microcode(struct b43_wldev *dev)
return 0;
error:
- macctl = b43_read32(dev, B43_MMIO_MACCTL);
- macctl &= ~B43_MACCTL_PSM_RUN;
- macctl |= B43_MACCTL_PSM_JMP0;
- b43_write32(dev, B43_MMIO_MACCTL, macctl);
+ /* Stop the microcode PSM. */
+ b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_PSM_RUN,
+ B43_MACCTL_PSM_JMP0);
return err;
}
@@ -2530,76 +2698,105 @@ static int b43_upload_initvals(struct b43_wldev *dev)
struct b43_firmware *fw = &dev->fw;
const struct b43_iv *ivals;
size_t count;
- int err;
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);
- err = b43_write_initvals(dev, ivals, count,
+ return b43_write_initvals(dev, ivals, count,
fw->initvals.data->size - hdr_len);
- if (err)
- goto out;
- if (fw->initvals_band.data) {
- 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);
- err = b43_write_initvals(dev, ivals, count,
- fw->initvals_band.data->size - hdr_len);
- if (err)
- goto out;
- }
-out:
+}
- return err;
+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)
{
- struct ssb_bus *bus = dev->dev->bus;
- struct ssb_device *gpiodev, *pcidev = NULL;
+#ifdef CONFIG_B43_SSB
+ struct ssb_device *gpiodev;
+#endif
u32 mask, set;
- b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
- & ~B43_MACCTL_GPOUTSMSK);
-
- b43_write16(dev, B43_MMIO_GPIO_MASK, b43_read16(dev, B43_MMIO_GPIO_MASK)
- | 0x000F);
+ 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->bus->chip_id == 0x4301) {
+ 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);
- mask |= 0x0180;
- set |= 0x0180;
- }
- if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) {
+ /* 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;
}
- if (dev->dev->id.revision >= 2)
- mask |= 0x0010; /* FIXME: This is redundant. */
-#ifdef CONFIG_SSB_DRIVER_PCICORE
- pcidev = bus->pcicore.dev;
+ 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
- gpiodev = bus->chipco.dev ? : pcidev;
- if (!gpiodev)
- return 0;
- ssb_write32(gpiodev, B43_GPIO_CONTROL,
- (ssb_read32(gpiodev, B43_GPIO_CONTROL)
- & mask) | set);
+#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;
}
@@ -2607,16 +2804,24 @@ static int b43_gpio_init(struct b43_wldev *dev)
/* Turn off all GPIO stuff. Call this on module unload, for example. */
static void b43_gpio_cleanup(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->dev->bus;
- struct ssb_device *gpiodev, *pcidev = NULL;
+#ifdef CONFIG_B43_SSB
+ struct ssb_device *gpiodev;
+#endif
-#ifdef CONFIG_SSB_DRIVER_PCICORE
- pcidev = bus->pcicore.dev;
+ 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
- gpiodev = bus->chipco.dev ? : pcidev;
- if (!gpiodev)
- return;
- ssb_write32(gpiodev, B43_GPIO_CONTROL, 0);
+#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 */
@@ -2638,9 +2843,7 @@ void b43_mac_enable(struct b43_wldev *dev)
dev->mac_suspended--;
B43_WARN_ON(dev->mac_suspended < 0);
if (dev->mac_suspended == 0) {
- b43_write32(dev, B43_MMIO_MACCTL,
- b43_read32(dev, B43_MMIO_MACCTL)
- | B43_MACCTL_ENABLED);
+ b43_maskset32(dev, B43_MMIO_MACCTL, ~0, B43_MACCTL_ENABLED);
b43_write32(dev, B43_MMIO_GEN_IRQ_REASON,
B43_IRQ_MAC_SUSPENDED);
/* Commit writes */
@@ -2661,9 +2864,7 @@ void b43_mac_suspend(struct b43_wldev *dev)
if (dev->mac_suspended == 0) {
b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
- b43_write32(dev, B43_MMIO_MACCTL,
- b43_read32(dev, B43_MMIO_MACCTL)
- & ~B43_MACCTL_ENABLED);
+ 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--) {
@@ -2685,6 +2886,35 @@ 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
+ }
+}
+
static void b43_adjust_opmode(struct b43_wldev *dev)
{
struct b43_wl *wl = dev->wl;
@@ -2721,15 +2951,15 @@ static void b43_adjust_opmode(struct b43_wldev *dev)
/* 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)
+ 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->bus->chip_id == 0x4306 &&
- dev->dev->bus->chip_rev == 3)
+ if (dev->dev->chip_id == 0x4306 &&
+ dev->dev->chip_rev == 3)
cfp_pretbtt = 100;
else
cfp_pretbtt = 50;
@@ -2740,15 +2970,10 @@ static void b43_adjust_opmode(struct b43_wldev *dev)
* 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_write32(dev, B43_MMIO_MACCTL,
- b43_read32(dev, B43_MMIO_MACCTL)
- & ~B43_MACCTL_DISCPMQ);
- } else {
- b43_write32(dev, B43_MMIO_MACCTL,
- b43_read32(dev, B43_MMIO_MACCTL)
- | B43_MACCTL_DISCPMQ);
- }
+ 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)
@@ -2773,6 +2998,8 @@ static void b43_rate_memory_init(struct b43_wldev *dev)
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_12MB, 1);
b43_rate_memory_write(dev, B43_OFDM_RATE_18MB, 1);
@@ -2841,7 +3068,7 @@ static int b43_chip_init(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
int err;
- u32 value32, macctl;
+ u32 macctl;
u16 value16;
/* Initialize the MAC control */
@@ -2851,9 +3078,6 @@ static int b43_chip_init(struct b43_wldev *dev)
macctl |= B43_MACCTL_INFRA;
b43_write32(dev, B43_MMIO_MACCTL, macctl);
- err = b43_request_firmware(dev);
- if (err)
- goto out;
err = b43_upload_microcode(dev);
if (err)
goto out; /* firmware is released later */
@@ -2866,6 +3090,10 @@ static int b43_chip_init(struct b43_wldev *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);
@@ -2887,22 +3115,20 @@ static int b43_chip_init(struct b43_wldev *dev)
b43_write16(dev, 0x005E, value16);
}
b43_write32(dev, 0x0100, 0x01000000);
- if (dev->dev->id.revision < 5)
+ if (dev->dev->core_rev < 5)
b43_write32(dev, 0x010C, 0x01000000);
- b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
- & ~B43_MACCTL_INFRA);
- b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
- | B43_MACCTL_INFRA);
+ 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, 0x0074, 0x0000);
+ 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->id.revision < 3) {
+ if (dev->dev->core_rev < 3) {
b43_write16(dev, 0x060E, 0x0000);
b43_write16(dev, 0x0610, 0x8000);
b43_write16(dev, 0x0604, 0x0000);
@@ -2912,19 +3138,29 @@ static int b43_chip_init(struct b43_wldev *dev)
b43_write32(dev, 0x018C, 0x02000000);
}
b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, 0x00004000);
- b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001DC00);
+ 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);
- value32 = ssb_read32(dev->dev, SSB_TMSLOW);
- value32 |= 0x00100000;
- ssb_write32(dev->dev, SSB_TMSLOW, value32);
+ b43_mac_phy_clock_set(dev, true);
- b43_write16(dev, B43_MMIO_POWERUP_DELAY,
- dev->dev->bus->chipco.fast_pwrup_delay);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ /* FIXME: 0xE74 is quite common, but should be read from CC */
+ b43_write16(dev, B43_MMIO_POWERUP_DELAY, 0xE74);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ b43_write16(dev, B43_MMIO_POWERUP_DELAY,
+ dev->dev->sdev->bus->chipco.fast_pwrup_delay);
+ break;
+#endif
+ }
err = 0;
b43dbg(dev->wl, "Chip initialized\n");
@@ -3087,7 +3323,7 @@ static int b43_validate_chipaccess(struct b43_wldev *dev)
b43_shm_write32(dev, B43_SHM_SHARED, 0, backup0);
b43_shm_write32(dev, B43_SHM_SHARED, 4, backup4);
- if ((dev->dev->id.revision >= 3) && (dev->dev->id.revision <= 10)) {
+ 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);
@@ -3160,10 +3396,10 @@ static int b43_rng_init(struct b43_wl *wl)
wl->rng.name = wl->rng_name;
wl->rng.data_read = b43_rng_read;
wl->rng.priv = (unsigned long)wl;
- wl->rng_initialized = 1;
+ wl->rng_initialized = true;
err = hwrng_register(&wl->rng);
if (err) {
- wl->rng_initialized = 0;
+ wl->rng_initialized = false;
b43err(wl, "Failed to register the random "
"number generator (%d)\n", err);
}
@@ -3177,6 +3413,7 @@ 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);
@@ -3186,15 +3423,26 @@ static void b43_tx_work(struct work_struct *work)
return;
}
- while (skb_queue_len(&wl->tx_queue)) {
- skb = skb_dequeue(&wl->tx_queue);
+ 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 (b43_using_pio_transfers(dev))
- err = b43_pio_tx(dev, skb);
- else
- err = b43_dma_tx(dev, skb);
- if (unlikely(err))
- dev_kfree_skb(skb); /* Drop it */
+ if (!err)
+ wl->tx_queue_stopped[queue_num] = 0;
}
#if B43_DEBUG
@@ -3203,22 +3451,25 @@ static void b43_tx_work(struct work_struct *work)
mutex_unlock(&wl->mutex);
}
-static int b43_op_tx(struct ieee80211_hw *hw,
- struct sk_buff *skb)
+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. */
- dev_kfree_skb_any(skb);
- return NETDEV_TX_OK;
+ ieee80211_free_txskb(hw, skb);
+ return;
}
B43_WARN_ON(skb_shinfo(skb)->nr_frags);
- skb_queue_tail(&wl->tx_queue, skb);
- ieee80211_queue_work(wl->hw, &wl->tx_work);
-
- return NETDEV_TX_OK;
+ 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,
@@ -3360,7 +3611,8 @@ static void b43_qos_init(struct b43_wldev *dev)
b43dbg(dev->wl, "QoS enabled\n");
}
-static int b43_op_conf_tx(struct ieee80211_hw *hw, u16 _queue,
+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);
@@ -3407,7 +3659,7 @@ static int b43_op_get_stats(struct ieee80211_hw *hw,
return 0;
}
-static u64 b43_op_get_tsf(struct ieee80211_hw *hw)
+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;
@@ -3426,7 +3678,8 @@ static u64 b43_op_get_tsf(struct ieee80211_hw *hw)
return tsf;
}
-static void b43_op_set_tsf(struct ieee80211_hw *hw, u64 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;
@@ -3440,25 +3693,6 @@ static void b43_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)
mutex_unlock(&wl->mutex);
}
-static void b43_put_phy_into_reset(struct b43_wldev *dev)
-{
- struct ssb_device *sdev = dev->dev;
- u32 tmslow;
-
- tmslow = ssb_read32(sdev, SSB_TMSLOW);
- tmslow &= ~B43_TMSLOW_GMODE;
- tmslow |= B43_TMSLOW_PHYRESET;
- tmslow |= SSB_TMSLOW_FGC;
- ssb_write32(sdev, SSB_TMSLOW, tmslow);
- msleep(1);
-
- tmslow = ssb_read32(sdev, SSB_TMSLOW);
- tmslow &= ~SSB_TMSLOW_FGC;
- tmslow |= B43_TMSLOW_PHYRESET;
- ssb_write32(sdev, SSB_TMSLOW, tmslow);
- msleep(1);
-}
-
static const char *band_to_string(enum ieee80211_band band)
{
switch (band) {
@@ -3474,94 +3708,75 @@ static const char *band_to_string(enum ieee80211_band band)
}
/* Expects wl->mutex locked */
-static int b43_switch_band(struct b43_wl *wl, struct ieee80211_channel *chan)
+static int b43_switch_band(struct b43_wldev *dev,
+ struct ieee80211_channel *chan)
{
- struct b43_wldev *up_dev = NULL;
- struct b43_wldev *down_dev;
- struct b43_wldev *d;
- int err;
- bool uninitialized_var(gmode);
- int prev_status;
+ struct b43_phy *phy = &dev->phy;
+ bool gmode;
+ u32 tmp;
- /* Find a device and PHY which supports the band. */
- list_for_each_entry(d, &wl->devlist, list) {
- switch (chan->band) {
- case IEEE80211_BAND_5GHZ:
- if (d->phy.supports_5ghz) {
- up_dev = d;
- gmode = 0;
- }
- break;
- case IEEE80211_BAND_2GHZ:
- if (d->phy.supports_2ghz) {
- up_dev = d;
- gmode = 1;
- }
- break;
- default:
- B43_WARN_ON(1);
- return -EINVAL;
- }
- if (up_dev)
- break;
+ switch (chan->band) {
+ case IEEE80211_BAND_5GHZ:
+ gmode = false;
+ break;
+ case IEEE80211_BAND_2GHZ:
+ gmode = true;
+ break;
+ default:
+ B43_WARN_ON(1);
+ return -EINVAL;
}
- if (!up_dev) {
- b43err(wl, "Could not find a device for %s-GHz band operation\n",
+
+ 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 ((up_dev == wl->current_dev) &&
- (!!wl->current_dev->phy.gmode == !!gmode)) {
+
+ if (!!phy->gmode == !!gmode) {
/* This device is already running. */
return 0;
}
- b43dbg(wl, "Switching to %s-GHz band\n",
- band_to_string(chan->band));
- down_dev = wl->current_dev;
- prev_status = b43_status(down_dev);
- /* Shutdown the currently running core. */
- if (prev_status >= B43_STAT_STARTED)
- down_dev = b43_wireless_core_stop(down_dev);
- if (prev_status >= B43_STAT_INITIALIZED)
- b43_wireless_core_exit(down_dev);
+ b43dbg(dev->wl, "Switching to %s GHz band\n",
+ band_to_string(chan->band));
- if (down_dev != up_dev) {
- /* We switch to a different core, so we put PHY into
- * RESET on the old core. */
- b43_put_phy_into_reset(down_dev);
+ /* 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);
- /* Now start the new core. */
- up_dev->phy.gmode = gmode;
- if (prev_status >= B43_STAT_INITIALIZED) {
- err = b43_wireless_core_init(up_dev);
- if (err) {
- b43err(wl, "Fatal: Could not initialize device for "
- "selected %s-GHz band\n",
- band_to_string(chan->band));
- goto init_failure;
- }
- }
- if (prev_status >= B43_STAT_STARTED) {
- err = b43_wireless_core_start(up_dev);
- if (err) {
- b43err(wl, "Fatal: Coult not start device for "
- "selected %s-GHz band\n",
- band_to_string(chan->band));
- b43_wireless_core_exit(up_dev);
- goto init_failure;
- }
- }
- B43_WARN_ON(b43_status(up_dev) != prev_status);
+ b43_upload_initvals_band(dev);
- wl->current_dev = up_dev;
+ b43_phy_init(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. */
@@ -3588,14 +3803,26 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
struct ieee80211_conf *conf = &hw->conf;
int antenna;
int err = 0;
+ bool reload_bss = false;
mutex_lock(&wl->mutex);
+ dev = wl->current_dev;
+
+ b43_mac_suspend(dev);
+
/* Switch the band (if necessary). This might change the active core. */
- err = b43_switch_band(wl, conf->channel);
+ err = b43_switch_band(dev, conf->chandef.chan);
if (err)
goto out_unlock_mutex;
- dev = wl->current_dev;
+
+ /* Need to reload all settings if the core changed */
+ if (dev != wl->current_dev) {
+ dev = wl->current_dev;
+ changed = ~0;
+ reload_bss = true;
+ }
+
phy = &dev->phy;
if (conf_is_ht(conf))
@@ -3604,8 +3831,6 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
else
phy->is_40mhz = false;
- b43_mac_suspend(dev);
-
if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
b43_set_retry_limits(dev, conf->short_frame_max_tx_count,
conf->long_frame_max_tx_count);
@@ -3615,8 +3840,8 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
/* Switch to the requested channel.
* The firmware takes care of races with the TX handler. */
- if (conf->channel->hw_value != phy->channel)
- b43_switch_channel(dev, conf->channel->hw_value);
+ if (conf->chandef.chan->hw_value != phy->channel)
+ b43_switch_channel(dev, conf->chandef.chan->hw_value);
dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_MONITOR);
@@ -3656,6 +3881,9 @@ out_mac_enable:
out_unlock_mutex:
mutex_unlock(&wl->mutex);
+ if (wl->vif && reload_bss)
+ b43_op_bss_info_changed(hw, wl->vif, &wl->vif->bss_conf, ~0);
+
return err;
}
@@ -3744,7 +3972,8 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
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)))
+ b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) &&
+ conf->beacon_int)
b43_set_beacon_int(dev, conf->beacon_int);
if (changed & BSS_CHANGED_BASIC_RATES)
@@ -3776,6 +4005,20 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
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;
@@ -3917,10 +4160,14 @@ out_unlock:
* 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 = dev->wl;
+ 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;
@@ -3938,7 +4185,7 @@ redo:
/* Disable interrupts on the device. */
b43_set_status(dev, B43_STAT_INITIALIZED);
- if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
+ 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 */
@@ -3951,7 +4198,7 @@ redo:
/* Synchronize and free the interrupt handlers. Unlock to avoid deadlocks. */
orig_dev = dev;
mutex_unlock(&wl->mutex);
- if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
+ if (b43_bus_host_is_sdio(dev->dev)) {
b43_sdio_free_irq(dev);
} else {
synchronize_irq(dev->dev->irq);
@@ -3969,9 +4216,15 @@ redo:
mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
B43_WARN_ON(mask != 0xFFFFFFFF && mask);
- /* Drain the TX queue */
- while (skb_queue_len(&wl->tx_queue))
- dev_kfree_skb(skb_dequeue(&wl->tx_queue));
+ /* 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);
@@ -3988,7 +4241,7 @@ static int b43_wireless_core_start(struct b43_wldev *dev)
B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED);
drain_txstatus_queue(dev);
- if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
+ 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");
@@ -3999,7 +4252,8 @@ static int b43_wireless_core_start(struct b43_wldev *dev)
b43_interrupt_thread_handler,
IRQF_SHARED, KBUILD_MODNAME, dev);
if (err) {
- b43err(dev->wl, "Cannot request IRQ-%d\n", dev->dev->irq);
+ b43err(dev->wl, "Cannot request IRQ-%d\n",
+ dev->dev->irq);
goto out;
}
}
@@ -4012,7 +4266,7 @@ static int b43_wireless_core_start(struct b43_wldev *dev)
b43_mac_enable(dev);
b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
- /* Start maintainance work */
+ /* Start maintenance work */
b43_periodic_tasks_setup(dev);
b43_leds_init(dev);
@@ -4022,6 +4276,35 @@ 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)
{
@@ -4066,35 +4349,67 @@ static int b43_phy_versioning(struct b43_wldev *dev)
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
default:
unsupported = 1;
- };
+ }
if (unsupported) {
- b43err(dev->wl, "FOUND UNSUPPORTED PHY "
- "(Analog %u, Type %u, Revision %u)\n",
- analog_type, phy_type, phy_rev);
+ 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;
}
- b43dbg(dev->wl, "Found PHY: Analog %u, Type %u, Revision %u\n",
- analog_type, phy_type, phy_rev);
+ 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 (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;
+ if (dev->dev->core_rev >= 24) {
+ u16 radio24[3];
+
+ for (tmp = 0; tmp < 3; tmp++) {
+ b43_write16(dev, B43_MMIO_RADIO24_CONTROL, tmp);
+ radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA);
+ }
+
+ /* Broadcom uses "id" for our "ver" and has separated "ver" */
+ /* radio_ver = (radio24[0] & 0xF0) >> 4; */
+
+ radio_manuf = 0x17F;
+ radio_ver = (radio24[2] << 8) | radio24[1];
+ radio_rev = (radio24[0] & 0xF);
} else {
- b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID);
- tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
- b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID);
- tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH) << 16;
- }
- radio_manuf = (tmp & 0x00000FFF);
- radio_ver = (tmp & 0x0FFFF000) >> 12;
- radio_rev = (tmp & 0xF0000000) >> 28;
+ if (dev->dev->chip_id == 0x4317) {
+ if (dev->dev->chip_rev == 0)
+ tmp = 0x3205017F;
+ else if (dev->dev->chip_rev == 1)
+ tmp = 0x4205017F;
+ else
+ tmp = 0x5205017F;
+ } else {
+ b43_write16(dev, B43_MMIO_RADIO_CONTROL,
+ B43_RADIOCTL_ID);
+ tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
+ b43_write16(dev, B43_MMIO_RADIO_CONTROL,
+ B43_RADIOCTL_ID);
+ tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH)
+ << 16;
+ }
+ radio_manuf = (tmp & 0x00000FFF);
+ radio_ver = (tmp & 0x0FFFF000) >> 12;
+ radio_rev = (tmp & 0xF0000000) >> 28;
+ }
+
if (radio_manuf != 0x17F /* Broadcom */)
unsupported = 1;
switch (phy_type) {
@@ -4122,6 +4437,14 @@ static int b43_phy_versioning(struct b43_wldev *dev)
if (radio_ver != 0x2062 && radio_ver != 0x2063)
unsupported = 1;
break;
+ case B43_PHYTYPE_HT:
+ if (radio_ver != 0x2059)
+ unsupported = 1;
+ break;
+ case B43_PHYTYPE_LCN:
+ if (radio_ver != 0x2064)
+ unsupported = 1;
+ break;
default:
B43_WARN_ON(1);
}
@@ -4154,18 +4477,18 @@ static void setup_struct_phy_for_init(struct b43_wldev *dev,
atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
#if B43_DEBUG
- phy->phy_locked = 0;
- phy->radio_locked = 0;
+ phy->phy_locked = false;
+ phy->radio_locked = false;
#endif
}
static void setup_struct_wldev_for_init(struct b43_wldev *dev)
{
- dev->dfq_valid = 0;
+ 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 = 1;
+ dev->radio_hw_enable = true;
/* Stats */
memset(&dev->stats, 0, sizeof(dev->stats));
@@ -4187,7 +4510,7 @@ static void setup_struct_wldev_for_init(struct b43_wldev *dev)
static void b43_bluetooth_coext_enable(struct b43_wldev *dev)
{
- struct ssb_sprom *sprom = &dev->dev->bus->sprom;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
u64 hf;
if (!modparam_btcoex)
@@ -4214,33 +4537,27 @@ static void b43_bluetooth_coext_disable(struct b43_wldev *dev)
static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev)
{
-#ifdef CONFIG_SSB_DRIVER_PCICORE
- struct ssb_bus *bus = dev->dev->bus;
+ struct ssb_bus *bus;
u32 tmp;
- if (bus->pcicore.dev &&
- bus->pcicore.dev->id.coreid == SSB_DEV_PCI &&
- bus->pcicore.dev->id.revision <= 5) {
- /* IMCFGLO timeouts workaround. */
- tmp = ssb_read32(dev->dev, SSB_IMCFGLO);
- switch (bus->bustype) {
- case SSB_BUSTYPE_PCI:
- case SSB_BUSTYPE_PCMCIA:
- tmp &= ~SSB_IMCFGLO_REQTO;
- tmp &= ~SSB_IMCFGLO_SERTO;
- tmp |= 0x32;
- break;
- case SSB_BUSTYPE_SSB:
- tmp &= ~SSB_IMCFGLO_REQTO;
- tmp &= ~SSB_IMCFGLO_SERTO;
- tmp |= 0x53;
- break;
- default:
- break;
- }
- ssb_write32(dev->dev, SSB_IMCFGLO, 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);
}
-#endif /* CONFIG_SSB_DRIVER_PCICORE */
}
static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle)
@@ -4282,22 +4599,28 @@ static void b43_set_pretbtt(struct b43_wldev *dev)
/* Locking: wl->mutex */
static void b43_wireless_core_exit(struct b43_wldev *dev)
{
- u32 macctl;
-
B43_WARN_ON(dev && b43_status(dev) > B43_STAT_INITIALIZED);
if (!dev || b43_status(dev) != B43_STAT_INITIALIZED)
return;
- /* Unregister HW RNG driver */
- b43_rng_exit(dev->wl);
-
b43_set_status(dev, B43_STAT_UNINIT);
/* Stop the microcode PSM. */
- macctl = b43_read32(dev, B43_MMIO_MACCTL);
- macctl &= ~B43_MACCTL_PSM_RUN;
- macctl |= B43_MACCTL_PSM_JMP0;
- b43_write32(dev, B43_MMIO_MACCTL, macctl);
+ 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_core_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);
@@ -4308,36 +4631,46 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
dev->wl->current_beacon = NULL;
}
- ssb_device_disable(dev->dev, 0);
- ssb_bus_may_powerdown(dev->dev->bus);
+ 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_bus *bus = dev->dev->bus;
- struct ssb_sprom *sprom = &bus->sprom;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy *phy = &dev->phy;
int err;
u64 hf;
- u32 tmp;
B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT);
- err = ssb_bus_powerup(bus, 0);
+ err = b43_bus_powerup(dev, 0);
if (err)
goto out;
- if (!ssb_device_is_enabled(dev->dev)) {
- tmp = phy->gmode ? B43_TMSLOW_GMODE : 0;
- b43_wireless_core_reset(dev, tmp);
- }
+ 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. */
- ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci[0],
+ dev->dev->bdev, true);
+ bcma_core_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);
@@ -4350,7 +4683,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
if (err)
goto err_busdown;
b43_shm_write16(dev, B43_SHM_SHARED,
- B43_SHM_SH_WLCOREREV, dev->dev->id.revision);
+ B43_SHM_SH_WLCOREREV, dev->dev->core_rev);
hf = b43_hf_read(dev);
if (phy->type == B43_PHYTYPE_G) {
hf |= B43_HF_SYMW;
@@ -4367,9 +4700,10 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
}
if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)
hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */
-#ifdef CONFIG_SSB_DRIVER_PCICORE
- if ((bus->bustype == SSB_BUSTYPE_PCI) &&
- (bus->pcicore.dev->id.revision <= 10))
+#if 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;
@@ -4397,13 +4731,18 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
/* Maximum Contention Window */
b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF);
- if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) ||
- (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) ||
- dev->use_pio) {
- dev->__using_pio_transfers = 1;
+ 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 = 0;
+ dev->__using_pio_transfers = false;
err = b43_dma_init(dev);
}
if (err)
@@ -4412,7 +4751,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
b43_set_synth_pu_delay(dev, 1);
b43_bluetooth_coext_enable(dev);
- ssb_bus_powerup(bus, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW));
+ b43_bus_powerup(dev, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW));
b43_upload_card_macaddress(dev);
b43_security_init(dev);
@@ -4420,16 +4759,13 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
b43_set_status(dev, B43_STAT_INITIALIZED);
- /* Register HW RNG driver */
- b43_rng_init(dev->wl);
-
out:
return err;
err_chip_exit:
b43_chip_exit(dev);
err_busdown:
- ssb_bus_may_powerdown(bus);
+ b43_bus_may_powerdown(dev);
B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT);
return err;
}
@@ -4457,7 +4793,7 @@ static int b43_op_add_interface(struct ieee80211_hw *hw,
b43dbg(wl, "Adding Interface type %d\n", vif->type);
dev = wl->current_dev;
- wl->operating = 1;
+ wl->operating = true;
wl->vif = vif;
wl->if_type = vif->type;
memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
@@ -4471,6 +4807,9 @@ static int b43_op_add_interface(struct ieee80211_hw *hw,
out_mutex_unlock:
mutex_unlock(&wl->mutex);
+ if (err == 0)
+ b43_op_bss_info_changed(hw, vif, &vif->bss_conf, ~0);
+
return err;
}
@@ -4488,7 +4827,7 @@ static void b43_op_remove_interface(struct ieee80211_hw *hw,
B43_WARN_ON(wl->vif != vif);
wl->vif = NULL;
- wl->operating = 0;
+ wl->operating = false;
b43_adjust_opmode(dev);
memset(wl->mac_addr, 0, ETH_ALEN);
@@ -4510,12 +4849,12 @@ static int b43_op_start(struct ieee80211_hw *hw)
memset(wl->bssid, 0, ETH_ALEN);
memset(wl->mac_addr, 0, ETH_ALEN);
wl->filter_flags = 0;
- wl->radiotap_enabled = 0;
+ wl->radiotap_enabled = false;
b43_qos_clear(wl);
- wl->beacon0_uploaded = 0;
- wl->beacon1_uploaded = 0;
- wl->beacon_templates_virgin = 1;
- wl->radio_enabled = 1;
+ wl->beacon0_uploaded = false;
+ wl->beacon1_uploaded = false;
+ wl->beacon_templates_virgin = true;
+ wl->radio_enabled = true;
mutex_lock(&wl->mutex);
@@ -4541,6 +4880,15 @@ static int b43_op_start(struct ieee80211_hw *hw)
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;
}
@@ -4551,6 +4899,9 @@ static void b43_op_stop(struct ieee80211_hw *hw)
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);
@@ -4558,11 +4909,11 @@ static void b43_op_stop(struct ieee80211_hw *hw)
goto out_unlock;
}
b43_wireless_core_exit(dev);
- wl->radio_enabled = 0;
+ wl->radio_enabled = false;
out_unlock:
mutex_unlock(&wl->mutex);
-
+out:
cancel_work_sync(&(wl->txpower_adjust_work));
}
@@ -4625,7 +4976,7 @@ static int b43_op_get_survey(struct ieee80211_hw *hw, int idx,
if (idx != 0)
return -ENOENT;
- survey->channel = conf->channel;
+ survey->channel = conf->chandef.chan;
survey->filled = SURVEY_INFO_NOISE_DBM;
survey->noise = dev->stats.link_noise;
@@ -4697,10 +5048,18 @@ out:
if (err)
wl->current_dev = NULL; /* Failed to init the dev. */
mutex_unlock(&wl->mutex);
- if (err)
+
+ if (err) {
b43err(wl, "Controller restart FAILED\n");
- else
- b43info(wl, "Controller restarted\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,
@@ -4732,14 +5091,85 @@ static void b43_wireless_core_detach(struct b43_wldev *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 */
+ case 0x4313: /* BCM4311 */
+ case 0x431a: /* BCM4318 */
+ case 0x432a: /* BCM4321 */
+ case 0x432d: /* BCM4322 */
+ case 0x4352: /* BCM43222 */
+ 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_A:
+ *have_2ghz_phy = false;
+ *have_5ghz_phy = true;
+ return;
+ 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 ssb_bus *bus = dev->dev->bus;
- struct pci_dev *pdev = (bus->bustype == SSB_BUSTYPE_PCI) ? bus->host_pci : NULL;
+ struct b43_phy *phy = &dev->phy;
int err;
- bool have_2ghz_phy = 0, have_5ghz_phy = 0;
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.
@@ -4748,74 +5178,69 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
* that in core_init(), too.
*/
- err = ssb_bus_powerup(bus, 0);
+ err = b43_bus_powerup(dev, 0);
if (err) {
b43err(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_2ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY);
- have_5ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_5GHZ_PHY);
- } else
- B43_WARN_ON(1);
+ 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;
- dev->phy.radio_on = 1;
- tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
- b43_wireless_core_reset(dev, tmp);
+ b43_wireless_core_reset(dev, dev->phy.gmode);
+ /* Get the PHY type. */
err = b43_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_2ghz_phy = 0;
- have_5ghz_phy = 0;
- switch (dev->phy.type) {
- case B43_PHYTYPE_A:
- have_5ghz_phy = 1;
- break;
- case B43_PHYTYPE_LP: //FIXME not always!
-#if 0 //FIXME enabling 5GHz causes a NULL pointer dereference
- have_5ghz_phy = 1;
-#endif
- case B43_PHYTYPE_G:
- case B43_PHYTYPE_N:
- have_2ghz_phy = 1;
- break;
- default:
- B43_WARN_ON(1);
- }
+
+ /* 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 */
+ switch (dev->phy.type) {
+ case B43_PHYTYPE_A:
+ case B43_PHYTYPE_G:
+ case B43_PHYTYPE_N:
+ case B43_PHYTYPE_LP:
+ case B43_PHYTYPE_HT:
+ b43warn(wl, "5 GHz band is unsupported on this PHY\n");
+ have_5ghz_phy = false;
}
- if (dev->phy.type == B43_PHYTYPE_A) {
- /* FIXME */
- b43err(wl, "IEEE 802.11a devices are unsupported\n");
+
+ if (!have_2ghz_phy && !have_5ghz_phy) {
+ b43err(wl, "b43 can't support any band on this device\n");
err = -EOPNOTSUPP;
goto err_powerdown;
}
- if (1 /* disable A-PHY */) {
- /* FIXME: For now we disable the A-PHY on multi-PHY devices. */
- if (dev->phy.type != B43_PHYTYPE_N &&
- dev->phy.type != B43_PHYTYPE_LP) {
- have_2ghz_phy = 1;
- have_5ghz_phy = 0;
- }
- }
err = b43_phy_allocate(dev);
if (err)
goto err_powerdown;
dev->phy.gmode = have_2ghz_phy;
- tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
- b43_wireless_core_reset(dev, tmp);
+ b43_wireless_core_reset(dev, dev->phy.gmode);
err = b43_validate_chipaccess(dev);
if (err)
@@ -4830,8 +5255,8 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
INIT_WORK(&dev->restart_work, b43_chip_reset);
dev->phy.ops->switch_analog(dev, 0);
- ssb_device_disable(dev->dev, 0);
- ssb_bus_may_powerdown(bus);
+ b43_device_disable(dev, 0);
+ b43_bus_may_powerdown(dev);
out:
return err;
@@ -4839,11 +5264,11 @@ out:
err_phy_free:
b43_phy_free(dev);
err_powerdown:
- ssb_bus_may_powerdown(bus);
+ b43_bus_may_powerdown(dev);
return err;
}
-static void b43_one_core_detach(struct ssb_device *dev)
+static void b43_one_core_detach(struct b43_bus_dev *dev)
{
struct b43_wldev *wldev;
struct b43_wl *wl;
@@ -4851,38 +5276,20 @@ static void b43_one_core_detach(struct ssb_device *dev)
/* Do not cancel ieee80211-workqueue based work here.
* See comment in b43_remove(). */
- wldev = ssb_get_drvdata(dev);
+ wldev = b43_bus_get_wldev(dev);
wl = wldev->wl;
b43_debugfs_remove_device(wldev);
b43_wireless_core_detach(wldev);
list_del(&wldev->list);
- wl->nr_devs--;
- ssb_set_drvdata(dev, NULL);
+ b43_bus_set_wldev(dev, NULL);
kfree(wldev);
}
-static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
+static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl)
{
struct b43_wldev *wldev;
- struct pci_dev *pdev;
int err = -ENOMEM;
- if (!list_empty(&wl->devlist)) {
- /* We are not the first core on this chip. */
- pdev = (dev->bus->bustype == SSB_BUSTYPE_PCI) ? dev->bus->host_pci : NULL;
- /* Only special chips support more than one wireless
- * core, although some of the other chips have more than
- * one wireless core as well. Check for this and
- * bail out early.
- */
- if (!pdev ||
- ((pdev->device != 0x4321) &&
- (pdev->device != 0x4313) && (pdev->device != 0x431A))) {
- b43dbg(wl, "Ignoring unconnected 802.11 core\n");
- return -ENODEV;
- }
- }
-
wldev = kzalloc(sizeof(*wldev), GFP_KERNEL);
if (!wldev)
goto out;
@@ -4898,9 +5305,7 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
if (err)
goto err_kfree_wldev;
- list_add(&wldev->list, &wl->devlist);
- wl->nr_devs++;
- ssb_set_drvdata(dev, wldev);
+ b43_bus_set_wldev(dev, wldev);
b43_debugfs_add_device(wldev);
out:
@@ -4917,16 +5322,17 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
(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->boardinfo.rev == 0x74)
+ bus->chip_id == 0x4301 && bus->sprom.board_rev == 0x74)
bus->sprom.boardflags_lo |= B43_BFL_BTCOEXIST;
if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
- bus->boardinfo.type == 0x4E && bus->boardinfo.rev > 0x40)
+ bus->boardinfo.type == 0x4E && bus->sprom.board_rev > 0x40)
bus->sprom.boardflags_lo |= B43_BFL_PACTRL;
if (bus->bustype == SSB_BUSTYPE_PCI) {
pdev = bus->host_pci;
@@ -4941,27 +5347,27 @@ static void b43_sprom_fixup(struct ssb_bus *bus)
}
}
-static void b43_wireless_exit(struct ssb_device *dev, struct b43_wl *wl)
+static void b43_wireless_exit(struct b43_bus_dev *dev, struct b43_wl *wl)
{
struct ieee80211_hw *hw = wl->hw;
- ssb_set_devtypedata(dev, NULL);
+ ssb_set_devtypedata(dev->sdev, NULL);
ieee80211_free_hw(hw);
}
+#endif
-static int b43_wireless_init(struct ssb_device *dev)
+static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
{
- struct ssb_sprom *sprom = &dev->bus->sprom;
+ struct ssb_sprom *sprom = dev->bus_sprom;
struct ieee80211_hw *hw;
struct b43_wl *wl;
- int err = -ENOMEM;
-
- b43_sprom_fixup(dev->bus);
+ 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");
- goto out;
+ return ERR_PTR(-ENOMEM);
}
wl = hw_to_b43_wl(hw);
@@ -4976,8 +5382,9 @@ static int b43_wireless_init(struct ssb_device *dev)
BIT(NL80211_IFTYPE_WDS) |
BIT(NL80211_IFTYPE_ADHOC);
- hw->queues = modparam_qos ? 4 : 1;
- wl->mac80211_initially_registered_queues = hw->queues;
+ hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
+
+ wl->hw_registred = false;
hw->max_rates = 2;
SET_IEEE80211_DEV(hw, dev->dev);
if (is_valid_ether_addr(sprom->et1mac))
@@ -4989,88 +5396,180 @@ static int b43_wireless_init(struct ssb_device *dev)
wl->hw = hw;
mutex_init(&wl->mutex);
spin_lock_init(&wl->hardirq_lock);
- INIT_LIST_HEAD(&wl->devlist);
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);
- skb_queue_head_init(&wl->tx_queue);
- ssb_set_devtypedata(dev, wl);
- b43info(wl, "Broadcom %04X WLAN found (core revision %u)\n",
- dev->bus->chip_id, dev->id.revision);
- err = 0;
-out:
- return err;
+ /* 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;
}
-static int b43_probe(struct ssb_device *dev, const struct ssb_device_id *id)
+#ifdef CONFIG_B43_BCMA
+static int b43_bcma_probe(struct bcma_device *core)
{
+ struct b43_bus_dev *dev;
struct b43_wl *wl;
int err;
- int first = 0;
- wl = ssb_get_devtypedata(dev);
- if (!wl) {
- /* Probing the first core. Must setup common struct b43_wl */
- first = 1;
- err = b43_wireless_init(dev);
- if (err)
- goto out;
- wl = ssb_get_devtypedata(dev);
- B43_WARN_ON(!wl);
+ 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 err_wireless_exit;
+ goto bcma_err_wireless_exit;
- if (first) {
- err = ieee80211_register_hw(wl->hw);
- if (err)
- goto err_one_core_detach;
- b43_leds_register(wl->current_dev);
+ /* setup and start work to load firmware */
+ INIT_WORK(&wl->firmware_load, b43_request_firmware);
+ schedule_work(&wl->firmware_load);
+
+bcma_out:
+ return err;
+
+bcma_err_wireless_exit:
+ ieee80211_free_hw(wl->hw);
+ 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);
}
- out:
+ b43_one_core_detach(wldev->dev);
+
+ /* Unregister HW RNG driver */
+ b43_rng_exit(wl);
+
+ b43_leds_unregister(wl);
+
+ ieee80211_free_hw(wl->hw);
+}
+
+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_one_core_detach:
- b43_one_core_detach(dev);
- err_wireless_exit:
- if (first)
- b43_wireless_exit(dev, wl);
+err_ssb_wireless_exit:
+ b43_wireless_exit(dev, wl);
+err_ssb_kfree_dev:
+ kfree(dev);
return err;
}
-static void b43_remove(struct ssb_device *dev)
+static void b43_ssb_remove(struct ssb_device *sdev)
{
- struct b43_wl *wl = ssb_get_devtypedata(dev);
- struct b43_wldev *wldev = ssb_get_drvdata(dev);
+ 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 (wl->current_dev == wldev) {
- /* Restore the queues count before unregistering, because firmware detect
- * might have modified it. Restoring is important, so the networking
- * stack can properly free resources. */
- wl->hw->queues = wl->mac80211_initially_registered_queues;
+ 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);
- if (list_empty(&wl->devlist)) {
- b43_leds_unregister(wl);
- /* Last core on the chip unregistered.
- * We can destroy common struct b43_wl.
- */
- b43_wireless_exit(dev, wl);
- }
+ /* Unregister HW RNG driver */
+ b43_rng_exit(wl);
+
+ b43_leds_unregister(wl);
+ b43_wireless_exit(dev, wl);
}
+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)
{
@@ -5081,13 +5580,6 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason)
ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
}
-static struct ssb_driver b43_ssb_driver = {
- .name = KBUILD_MODNAME,
- .id_table = b43_ssb_tbl,
- .probe = b43_probe,
- .remove = b43_remove,
-};
-
static void b43_print_driverinfo(void)
{
const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "",
@@ -5109,8 +5601,7 @@ static void b43_print_driverinfo(void)
feat_sdio = "S";
#endif
printk(KERN_INFO "Broadcom 43xx driver loaded "
- "[ Features: %s%s%s%s%s, Firmware-ID: "
- B43_SUPPORTED_FIRMWARE_ID " ]\n",
+ "[ Features: %s%s%s%s%s ]\n",
feat_pci, feat_pcmcia, feat_nphy,
feat_leds, feat_sdio);
}
@@ -5126,14 +5617,27 @@ static int __init b43_init(void)
err = b43_sdio_init();
if (err)
goto err_pcmcia_exit;
- err = ssb_driver_register(&b43_ssb_driver);
+#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_pcmcia_exit:
b43_pcmcia_exit();
@@ -5144,7 +5648,12 @@ err_dfs_exit:
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_pcmcia_exit();
b43_debugfs_exit();
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h
index 40db03678d9..f476fc337d6 100644
--- a/drivers/net/wireless/b43/main.h
+++ b/drivers/net/wireless/b43/main.h
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Stefano Brivio <stefano.brivio@polimi.it>
- Michael Buesch <mb@bu3sch.de>
+ Michael Buesch <m@bues.ch>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -58,41 +58,6 @@ enum b43_verbosity {
#endif
};
-
-/* Lightweight function to convert a frequency (in Mhz) to a channel number. */
-static inline u8 b43_freq_to_channel_5ghz(int freq)
-{
- return ((freq - 5000) / 5);
-}
-static inline u8 b43_freq_to_channel_2ghz(int freq)
-{
- u8 channel;
-
- if (freq == 2484)
- channel = 14;
- else
- channel = (freq - 2407) / 5;
-
- return channel;
-}
-
-/* Lightweight function to convert a channel number to a frequency (in Mhz). */
-static inline int b43_channel_to_freq_5ghz(u8 channel)
-{
- return (5000 + (5 * channel));
-}
-static inline int b43_channel_to_freq_2ghz(u8 channel)
-{
- int freq;
-
- if (channel == 14)
- freq = 2484;
- else
- freq = 2407 + (5 * channel);
-
- return freq;
-}
-
static inline int b43_is_cck_rate(int rate)
{
return (rate == B43_CCK_RATE_1MB ||
@@ -121,7 +86,7 @@ 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, u32 flags);
+void b43_wireless_core_reset(struct b43_wldev *dev, bool gmode);
void b43_controller_restart(struct b43_wldev *dev, const char *reason);
@@ -133,12 +98,12 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags);
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);
struct b43_request_fw_context;
-int b43_do_request_fw(struct b43_request_fw_context *ctx,
- const char *name,
- struct b43_firmware_file *fw);
+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/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c
index 7dcba5fafdc..55f2bd7f8f7 100644
--- a/drivers/net/wireless/b43/pcmcia.c
+++ b/drivers/net/wireless/b43/pcmcia.c
@@ -2,7 +2,7 @@
Broadcom B43 wireless driver
- Copyright (c) 2007 Michael Buesch <mb@bu3sch.de>
+ 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
@@ -25,6 +25,7 @@
#include <linux/ssb/ssb.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ciscode.h>
@@ -32,7 +33,7 @@
#include <pcmcia/cisreg.h>
-static /*const */ struct pcmcia_device_id b43_pcmcia_tbl[] = {
+static const struct pcmcia_device_id b43_pcmcia_tbl[] = {
PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448),
PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476),
PCMCIA_DEVICE_NULL,
@@ -59,7 +60,7 @@ static int b43_pcmcia_resume(struct pcmcia_device *dev)
# define b43_pcmcia_resume NULL
#endif /* CONFIG_PM */
-static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
+static int b43_pcmcia_probe(struct pcmcia_device *dev)
{
struct ssb_bus *ssb;
int err = -ENOMEM;
@@ -109,7 +110,7 @@ out_error:
return err;
}
-static void __devexit b43_pcmcia_remove(struct pcmcia_device *dev)
+static void b43_pcmcia_remove(struct pcmcia_device *dev)
{
struct ssb_bus *ssb = dev->priv;
@@ -124,11 +125,15 @@ static struct pcmcia_driver b43_pcmcia_driver = {
.name = "b43-pcmcia",
.id_table = b43_pcmcia_tbl,
.probe = b43_pcmcia_probe,
- .remove = __devexit_p(b43_pcmcia_remove),
+ .remove = b43_pcmcia_remove,
.suspend = b43_pcmcia_suspend,
.resume = b43_pcmcia_resume,
};
+/*
+ * These are not module init/exit functions!
+ * The module_pcmcia_driver() helper cannot be used here.
+ */
int b43_pcmcia_init(void)
{
return pcmcia_register_driver(&b43_pcmcia_driver);
diff --git a/drivers/net/wireless/b43/phy_a.c b/drivers/net/wireless/b43/phy_a.c
index b6428ec16dd..a6c38104693 100644
--- a/drivers/net/wireless/b43/phy_a.c
+++ b/drivers/net/wireless/b43/phy_a.c
@@ -5,7 +5,7 @@
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 <mb@bu3sch.de>
+ 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>
@@ -265,7 +265,6 @@ static void hardware_pctl_init_aphy(struct b43_wldev *dev)
void b43_phy_inita(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->dev->bus;
struct b43_phy *phy = &dev->phy;
/* This lowlevel A-PHY init is also called from G-PHY init.
@@ -296,9 +295,9 @@ void b43_phy_inita(struct b43_wldev *dev)
b43_radio_init2060(dev);
- if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
- ((bus->boardinfo.type == SSB_BOARD_BU4306) ||
- (bus->boardinfo.type == SSB_BOARD_BU4309))) {
+ if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) &&
+ ((dev->dev->board_type == SSB_BOARD_BU4306) ||
+ (dev->dev->board_type == SSB_BOARD_BU4309))) {
; //TODO: A PHY LO
}
@@ -311,7 +310,7 @@ void b43_phy_inita(struct b43_wldev *dev)
}
if ((phy->type == B43_PHYTYPE_G) &&
- (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)) {
+ (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)) {
b43_phy_maskset(dev, B43_PHY_OFDM(0x6E), 0xE000, 0x3CF);
}
}
@@ -323,17 +322,17 @@ static int b43_aphy_init_tssi2dbm_table(struct b43_wldev *dev)
struct b43_phy_a *aphy = phy->a;
s16 pab0, pab1, pab2;
- pab0 = (s16) (dev->dev->bus->sprom.pa1b0);
- pab1 = (s16) (dev->dev->bus->sprom.pa1b1);
- pab2 = (s16) (dev->dev->bus->sprom.pa1b2);
+ pab0 = (s16) (dev->dev->bus_sprom->pa1b0);
+ pab1 = (s16) (dev->dev->bus_sprom->pa1b1);
+ pab2 = (s16) (dev->dev->bus_sprom->pa1b2);
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_a != 0 &&
- (s8) dev->dev->bus->sprom.itssi_a != -1)
+ if ((s8) dev->dev->bus_sprom->itssi_a != 0 &&
+ (s8) dev->dev->bus_sprom->itssi_a != -1)
aphy->tgt_idle_tssi =
- (s8) (dev->dev->bus->sprom.itssi_a);
+ (s8) (dev->dev->bus_sprom->itssi_a);
else
aphy->tgt_idle_tssi = 62;
aphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0,
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index b5c5ce94d3f..08244b3b327 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -5,7 +5,7 @@
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 <mb@bu3sch.de>
+ 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>
@@ -31,6 +31,8 @@
#include "phy_a.h"
#include "phy_n.h"
#include "phy_lp.h"
+#include "phy_ht.h"
+#include "phy_lcn.h"
#include "b43.h"
#include "main.h"
@@ -59,6 +61,16 @@ int b43_phy_allocate(struct b43_wldev *dev)
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;
}
if (B43_WARN_ON(!phy->ops))
return -ENODEV;
@@ -84,12 +96,16 @@ int b43_phy_init(struct b43_wldev *dev)
phy->channel = ops->get_default_chan(dev);
- ops->software_rfkill(dev, false);
+ 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;
+
/* Make sure to switch hardware and firmware (SHM) to
* the default channel. */
err = b43_switch_channel(dev, ops->get_default_chan(dev));
@@ -101,10 +117,11 @@ int b43_phy_init(struct b43_wldev *dev)
return 0;
err_phy_exit:
+ phy->do_full_init = true;
if (ops->exit)
ops->exit(dev);
err_block_rf:
- ops->software_rfkill(dev, true);
+ b43_software_rfkill(dev, true);
return err;
}
@@ -113,7 +130,8 @@ void b43_phy_exit(struct b43_wldev *dev)
{
const struct b43_phy_operations *ops = dev->phy.ops;
- ops->software_rfkill(dev, true);
+ b43_software_rfkill(dev, true);
+ dev->phy.do_full_init = true;
if (ops->exit)
ops->exit(dev);
}
@@ -121,9 +139,9 @@ void b43_phy_exit(struct b43_wldev *dev)
bool b43_has_hardware_pctl(struct b43_wldev *dev)
{
if (!dev->phy.hardware_power_control)
- return 0;
+ return false;
if (!dev->phy.ops->supports_hwpctl)
- return 0;
+ return false;
return dev->phy.ops->supports_hwpctl(dev);
}
@@ -133,7 +151,7 @@ void b43_radio_lock(struct b43_wldev *dev)
#if B43_DEBUG
B43_WARN_ON(dev->phy.radio_locked);
- dev->phy.radio_locked = 1;
+ dev->phy.radio_locked = true;
#endif
macctl = b43_read32(dev, B43_MMIO_MACCTL);
@@ -151,7 +169,7 @@ void b43_radio_unlock(struct b43_wldev *dev)
#if B43_DEBUG
B43_WARN_ON(!dev->phy.radio_locked);
- dev->phy.radio_locked = 0;
+ dev->phy.radio_locked = false;
#endif
/* Commit any write */
@@ -166,9 +184,9 @@ void b43_phy_lock(struct b43_wldev *dev)
{
#if B43_DEBUG
B43_WARN_ON(dev->phy.phy_locked);
- dev->phy.phy_locked = 1;
+ dev->phy.phy_locked = true;
#endif
- B43_WARN_ON(dev->dev->id.revision < 3);
+ 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);
@@ -178,9 +196,9 @@ void b43_phy_unlock(struct b43_wldev *dev)
{
#if B43_DEBUG
B43_WARN_ON(!dev->phy.phy_locked);
- dev->phy.phy_locked = 0;
+ dev->phy.phy_locked = false;
#endif
- B43_WARN_ON(dev->dev->id.revision < 3);
+ B43_WARN_ON(dev->dev->core_rev < 3);
if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP))
b43_power_saving_ctl_bits(dev, 0);
@@ -228,6 +246,21 @@ void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
(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);
@@ -285,6 +318,90 @@ void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 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);
@@ -368,8 +485,8 @@ void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags)
/* The next check will be needed in two seconds, or later. */
phy->next_txpwr_check_time = round_jiffies(now + (HZ * 2));
- if ((dev->dev->bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
- (dev->dev->bus->boardinfo.type == SSB_BOARD_BU4306))
+ 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));
@@ -416,7 +533,7 @@ int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset)
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_HOSTFLO)
+ if (b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF1)
& B43_HF_CCKBOOST)
average = (average >= 13) ? (average - 13) : 0;
}
@@ -436,6 +553,38 @@ bool b43_channel_type_is_40mhz(enum nl80211_channel_type channel_type)
channel_type == NL80211_CHAN_HT40PLUS);
}
+/* 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);
+
+ 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)
{
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h
index 2401bee8b08..4ad6240d9ff 100644
--- a/drivers/net/wireless/b43/phy_common.h
+++ b/drivers/net/wireless/b43/phy_common.h
@@ -194,6 +194,8 @@ struct b43_phy_a;
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. */
@@ -216,6 +218,10 @@ struct b43_phy {
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;
};
/* Band support flags. */
@@ -225,9 +231,12 @@ struct b43_phy {
/* HT info */
bool is_40mhz;
- /* GMODE bit enabled? */
+ /* 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_ */
@@ -359,6 +368,12 @@ void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set);
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);
@@ -378,6 +393,9 @@ void b43_phy_lock(struct b43_wldev *dev);
*/
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
*/
@@ -438,6 +456,8 @@ void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on);
bool b43_channel_type_is_40mhz(enum nl80211_channel_type channel_type);
+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/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c
index be482816701..8f5c14bc10e 100644
--- a/drivers/net/wireless/b43/phy_g.c
+++ b/drivers/net/wireless/b43/phy_g.c
@@ -5,7 +5,7 @@
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 <mb@bu3sch.de>
+ 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>
@@ -718,7 +718,7 @@ static void b43_calc_nrssi_threshold(struct b43_wldev *dev)
B43_WARN_ON(phy->type != B43_PHYTYPE_G);
if (!phy->gmode ||
- !(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) {
+ !(dev->dev->bus_sprom->boardflags_lo & B43_BFL_RSSI)) {
tmp16 = b43_nrssi_hw_read(dev, 0x20);
if (tmp16 >= 0x20)
tmp16 -= 0x40;
@@ -897,7 +897,7 @@ b43_radio_interference_mitigation_enable(struct b43_wldev *dev, int mode)
if (b43_phy_read(dev, 0x0033) & 0x0800)
break;
- gphy->aci_enable = 1;
+ gphy->aci_enable = true;
phy_stacksave(B43_PHY_RADIO_BITFIELD);
phy_stacksave(B43_PHY_G_CRS);
@@ -1038,7 +1038,7 @@ b43_radio_interference_mitigation_disable(struct b43_wldev *dev, int mode)
if (!(b43_phy_read(dev, 0x0033) & 0x0800))
break;
- gphy->aci_enable = 0;
+ gphy->aci_enable = false;
phy_stackrestore(B43_PHY_RADIO_BITFIELD);
phy_stackrestore(B43_PHY_G_CRS);
@@ -1114,7 +1114,7 @@ static u16 radio2050_rfover_val(struct b43_wldev *dev,
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
- struct ssb_sprom *sprom = &(dev->dev->bus->sprom);
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
if (!phy->gmode)
return 0;
@@ -1491,7 +1491,6 @@ static u16 b43_radio_init2050(struct b43_wldev *dev)
static void b43_phy_initb5(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->dev->bus;
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
u16 offset, value;
@@ -1500,8 +1499,8 @@ static void b43_phy_initb5(struct b43_wldev *dev)
if (phy->analog == 1) {
b43_radio_set(dev, 0x007A, 0x0050);
}
- if ((bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM) &&
- (bus->boardinfo.type != SSB_BOARD_BU4306)) {
+ 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);
@@ -1588,6 +1587,7 @@ static void b43_phy_initb5(struct b43_wldev *dev)
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;
@@ -1620,7 +1620,7 @@ static void b43_phy_initb6(struct b43_wldev *dev)
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) {
+ if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_ALTIQ) {
b43_radio_write16(dev, 0x5D, 0xFA);
b43_radio_write16(dev, 0x5E, 0xD8);
} else {
@@ -1671,7 +1671,7 @@ static void b43_phy_initb6(struct b43_wldev *dev)
b43_radio_write16(dev, 0x50, 0x20);
}
if (phy->radio_rev <= 2) {
- b43_radio_write16(dev, 0x7C, 0x20);
+ b43_radio_write16(dev, 0x50, 0x20);
b43_radio_write16(dev, 0x5A, 0x70);
b43_radio_write16(dev, 0x5B, 0x7B);
b43_radio_write16(dev, 0x5C, 0xB0);
@@ -1687,9 +1687,8 @@ static void b43_phy_initb6(struct b43_wldev *dev)
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 <= 5) {
+ 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);
@@ -1787,7 +1786,7 @@ static void b43_calc_loopback_gain(struct b43_wldev *dev)
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 (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);
@@ -1922,7 +1921,6 @@ static void b43_hardware_pctl_init_gphy(struct b43_wldev *dev)
/* Initialize B/G PHY power control */
static void b43_phy_init_pctl(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->dev->bus;
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
struct b43_rfatt old_rfatt;
@@ -1931,8 +1929,8 @@ static void b43_phy_init_pctl(struct b43_wldev *dev)
B43_WARN_ON(phy->type != B43_PHYTYPE_G);
- if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
- (bus->boardinfo.type == SSB_BOARD_BU4306))
+ if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) &&
+ (dev->dev->board_type == SSB_BOARD_BU4306))
return;
b43_phy_write(dev, 0x0028, 0x8018);
@@ -1958,10 +1956,10 @@ static void b43_phy_init_pctl(struct b43_wldev *dev)
bbatt.att = 11;
if (phy->radio_rev == 8) {
rfatt.att = 15;
- rfatt.with_padmix = 1;
+ rfatt.with_padmix = true;
} else {
rfatt.att = 9;
- rfatt.with_padmix = 0;
+ rfatt.with_padmix = false;
}
b43_set_txpower_g(dev, &bbatt, &rfatt, 0);
}
@@ -2053,7 +2051,7 @@ static void b43_phy_initg(struct b43_wldev *dev)
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)
+ 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);
@@ -2066,7 +2064,7 @@ static void b43_phy_initg(struct b43_wldev *dev)
b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078);
}
- if (!(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) {
+ 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.
@@ -2088,8 +2086,8 @@ static void b43_phy_initg(struct b43_wldev *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->bus->chip_id == 0x4306
- && dev->dev->bus->chip_package == 2) || 0) {
+ 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);
}
@@ -2105,7 +2103,7 @@ void b43_gphy_channel_switch(struct b43_wldev *dev,
b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel));
if (channel == 14) {
- if (dev->dev->bus->sprom.country_code ==
+ if (dev->dev->bus_sprom->country_code ==
SSB_SPROM1CCODE_JAPAN)
b43_hf_write(dev,
b43_hf_read(dev) & ~B43_HF_ACPR);
@@ -2136,17 +2134,17 @@ static void default_baseband_attenuation(struct b43_wldev *dev,
static void default_radio_attenuation(struct b43_wldev *dev,
struct b43_rfatt *rf)
{
- struct ssb_bus *bus = dev->dev->bus;
+ struct b43_bus_dev *bdev = dev->dev;
struct b43_phy *phy = &dev->phy;
- rf->with_padmix = 0;
+ rf->with_padmix = false;
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM &&
- bus->boardinfo.type == SSB_BOARD_BCM4309G) {
- if (bus->boardinfo.rev < 0x43) {
+ 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 (bus->boardinfo.rev < 0x51) {
+ } else if (dev->dev->board_rev < 0x51) {
rf->att = 3;
return;
}
@@ -2172,21 +2170,21 @@ static void default_radio_attenuation(struct b43_wldev *dev,
return;
case 1:
if (phy->type == B43_PHYTYPE_G) {
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type == SSB_BOARD_BCM4309G
- && bus->boardinfo.rev >= 30)
+ if (bdev->board_vendor == SSB_BOARDVENDOR_BCM
+ && bdev->board_type == SSB_BOARD_BCM4309G
+ && bdev->board_rev >= 30)
rf->att = 3;
- else if (bus->boardinfo.vendor ==
+ else if (bdev->board_vendor ==
SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type ==
+ && bdev->board_type ==
SSB_BOARD_BU4306)
rf->att = 3;
else
rf->att = 1;
} else {
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type == SSB_BOARD_BCM4309G
- && bus->boardinfo.rev >= 30)
+ if (bdev->board_vendor == SSB_BOARDVENDOR_BCM
+ && bdev->board_type == SSB_BOARD_BCM4309G
+ && bdev->board_rev >= 30)
rf->att = 7;
else
rf->att = 6;
@@ -2194,16 +2192,16 @@ static void default_radio_attenuation(struct b43_wldev *dev,
return;
case 2:
if (phy->type == B43_PHYTYPE_G) {
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type == SSB_BOARD_BCM4309G
- && bus->boardinfo.rev >= 30)
+ if (bdev->board_vendor == SSB_BOARDVENDOR_BCM
+ && bdev->board_type == SSB_BOARD_BCM4309G
+ && bdev->board_rev >= 30)
rf->att = 3;
- else if (bus->boardinfo.vendor ==
+ else if (bdev->board_vendor ==
SSB_BOARDVENDOR_BCM
- && bus->boardinfo.type ==
+ && bdev->board_type ==
SSB_BOARD_BU4306)
rf->att = 5;
- else if (bus->chip_id == 0x4320)
+ else if (bdev->chip_id == 0x4320)
rf->att = 4;
else
rf->att = 3;
@@ -2223,7 +2221,7 @@ static void default_radio_attenuation(struct b43_wldev *dev,
return;
case 8:
rf->att = 0xA;
- rf->with_padmix = 1;
+ rf->with_padmix = true;
return;
case 9:
default:
@@ -2384,29 +2382,29 @@ static int b43_gphy_init_tssi2dbm_table(struct b43_wldev *dev)
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);
+ 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->bus->chip_id == 0x4301) &&
+ B43_WARN_ON((dev->dev->chip_id == 0x4301) &&
(phy->radio_ver != 0x2050)); /* Not supported anymore */
- gphy->dyn_tssi_tbl = 0;
+ 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) {
+ 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);
+ (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 = 1;
+ gphy->dyn_tssi_tbl = true;
} else {
/* pabX values not set in SPROM. */
gphy->tgt_idle_tssi = 52;
@@ -2506,7 +2504,7 @@ static void b43_gphy_op_free(struct b43_wldev *dev)
if (gphy->dyn_tssi_tbl)
kfree(gphy->tssi2dbm);
- gphy->dyn_tssi_tbl = 0;
+ gphy->dyn_tssi_tbl = false;
gphy->tssi2dbm = NULL;
kfree(gphy);
@@ -2533,11 +2531,11 @@ static int b43_gphy_op_prepare_hardware(struct b43_wldev *dev)
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 = 0;
+ phy->gmode = false;
b43_wireless_core_reset(dev, 0);
b43_phy_initg(dev);
- phy->gmode = 1;
- b43_wireless_core_reset(dev, B43_TMSLOW_GMODE);
+ phy->gmode = true;
+ b43_wireless_core_reset(dev, 1);
}
return 0;
@@ -2615,7 +2613,7 @@ static void b43_gphy_op_software_rfkill(struct b43_wldev *dev,
gphy->radio_off_context.rfover);
b43_phy_write(dev, B43_PHY_RFOVERVAL,
gphy->radio_off_context.rfoverval);
- gphy->radio_off_context.valid = 0;
+ gphy->radio_off_context.valid = false;
}
channel = phy->channel;
b43_gphy_channel_switch(dev, 6, 1);
@@ -2628,7 +2626,7 @@ static void b43_gphy_op_software_rfkill(struct b43_wldev *dev,
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 = 1;
+ gphy->radio_off_context.valid = true;
b43_phy_write(dev, B43_PHY_RFOVER, rfover | 0x008C);
b43_phy_write(dev, B43_PHY_RFOVERVAL, rfoverval & 0xFF73);
}
@@ -2713,10 +2711,10 @@ static int b43_gphy_op_interf_mitigation(struct b43_wldev *dev,
if ((phy->rev == 0) || (!phy->gmode))
return -ENODEV;
- gphy->aci_wlan_automatic = 0;
+ gphy->aci_wlan_automatic = false;
switch (mode) {
case B43_INTERFMODE_AUTOWLAN:
- gphy->aci_wlan_automatic = 1;
+ gphy->aci_wlan_automatic = true;
if (gphy->aci_enable)
mode = B43_INTERFMODE_MANUALWLAN;
else
@@ -2737,8 +2735,8 @@ static int b43_gphy_op_interf_mitigation(struct b43_wldev *dev,
b43_radio_interference_mitigation_disable(dev, currentmode);
if (mode == B43_INTERFMODE_NONE) {
- gphy->aci_enable = 0;
- gphy->aci_hw_rssi = 0;
+ gphy->aci_enable = false;
+ gphy->aci_hw_rssi = false;
} else
b43_radio_interference_mitigation_enable(dev, mode);
gphy->interfmode = mode;
@@ -2840,7 +2838,7 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev)
B43_TXCTL_TXMIX;
rfatt += 2;
bbatt += 2;
- } else if (dev->dev->bus->sprom.
+ } else if (dev->dev->bus_sprom->
boardflags_lo &
B43_BFL_PACTRL) {
bbatt += 4 * (rfatt - 2);
@@ -2914,14 +2912,14 @@ static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev,
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 = 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;
+ dev->dev->bus_sprom->maxpwr_bg = max_pwr;
}
/* Get desired power (in Q5.2) */
@@ -3014,7 +3012,7 @@ 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))
+ if (!(dev->dev->bus_sprom->boardflags_lo & B43_BFL_RSSI))
return;
b43_mac_suspend(dev);
diff --git a/drivers/net/wireless/b43/phy_g.h b/drivers/net/wireless/b43/phy_g.h
index 8569fdd4c6b..5413c906a3e 100644
--- a/drivers/net/wireless/b43/phy_g.h
+++ b/drivers/net/wireless/b43/phy_g.h
@@ -164,7 +164,7 @@ struct b43_phy_g {
/* Current Interference Mitigation mode */
int interfmode;
/* Stack of saved values from the Interference Mitigation code.
- * Each value in the stack is layed out as follows:
+ * Each value in the stack is laid out as follows:
* bit 0-11: offset
* bit 12-15: register ID
* bit 16-32: value
diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c
new file mode 100644
index 00000000000..5d6833f1849
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_ht.c
@@ -0,0 +1,1140 @@
+/*
+
+ 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, 0x2b, ~0x1);
+ b43_radio_mask(dev, 0x2e, ~0x4);
+ b43_radio_set(dev, 0x2e, 0x4);
+ b43_radio_set(dev, 0x2b, 0x1);
+
+ udelay(300);
+}
+
+static void b43_radio_2059_init(struct b43_wldev *dev)
+{
+ const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3 };
+ const u16 radio_values[3][2] = {
+ { 0x61, 0xE9 }, { 0x69, 0xD5 }, { 0x73, 0x99 },
+ };
+ u16 i, j;
+
+ b43_radio_write(dev, R2059_ALL | 0x51, 0x0070);
+ b43_radio_write(dev, R2059_ALL | 0x5a, 0x0003);
+
+ for (i = 0; i < ARRAY_SIZE(routing); i++)
+ b43_radio_set(dev, routing[i] | 0x146, 0x3);
+
+ b43_radio_set(dev, 0x2e, 0x0078);
+ b43_radio_set(dev, 0xc0, 0x0080);
+ msleep(2);
+ b43_radio_mask(dev, 0x2e, ~0x0078);
+ b43_radio_mask(dev, 0xc0, ~0x0080);
+
+ if (1) { /* FIXME */
+ b43_radio_set(dev, R2059_C3 | 0x4, 0x1);
+ udelay(10);
+ b43_radio_set(dev, R2059_C3 | 0x0BF, 0x1);
+ b43_radio_maskset(dev, R2059_C3 | 0x19B, 0x3, 0x2);
+
+ b43_radio_set(dev, R2059_C3 | 0x4, 0x2);
+ udelay(100);
+ b43_radio_mask(dev, R2059_C3 | 0x4, ~0x2);
+
+ for (i = 0; i < 10000; i++) {
+ if (b43_radio_read(dev, R2059_C3 | 0x145) & 1) {
+ i = 0;
+ break;
+ }
+ udelay(100);
+ }
+ if (i)
+ b43err(dev->wl, "radio 0x945 timeout\n");
+
+ b43_radio_mask(dev, R2059_C3 | 0x4, ~0x1);
+ b43_radio_set(dev, 0xa, 0x60);
+
+ for (i = 0; i < 3; i++) {
+ b43_radio_write(dev, 0x17F, radio_values[i][0]);
+ b43_radio_write(dev, 0x13D, 0x6E);
+ b43_radio_write(dev, 0x13E, radio_values[i][1]);
+ b43_radio_write(dev, 0x13C, 0x55);
+
+ for (j = 0; j < 10000; j++) {
+ if (b43_radio_read(dev, 0x140) & 2) {
+ j = 0;
+ break;
+ }
+ udelay(500);
+ }
+ if (j)
+ b43err(dev->wl, "radio 0x140 timeout\n");
+
+ b43_radio_write(dev, 0x13C, 0x15);
+ }
+
+ b43_radio_mask(dev, 0x17F, ~0x1);
+ }
+
+ b43_radio_mask(dev, 0x11, ~0x0008);
+}
+
+/**************************************************
+ * 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;
+ 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);
+}
+
+/**************************************************
+ * 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) == IEEE80211_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.channel_freq;
+ int i, c;
+
+ if (b43_current_band(dev->wl) == IEEE80211_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;
+ u16 tmp;
+
+ /* 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);
+
+ /* Values has been taken from wlc_bmac_switch_macfreq comments */
+ switch (spuravoid) {
+ case 2: /* 126MHz */
+ tmp = 0x2082;
+ break;
+ case 1: /* 123MHz */
+ tmp = 0x5341;
+ break;
+ default: /* 120MHz */
+ tmp = 0x8889;
+ }
+
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, tmp);
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
+
+ /* TODO: reset PLL */
+
+ 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)
+{
+ bool old_band_5ghz;
+
+ old_band_5ghz = b43_phy_read(dev, B43_PHY_HT_BANDCTL) & 0; /* FIXME */
+ if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) {
+ /* TODO */
+ } else if (new_channel->band == IEEE80211_BAND_2GHZ && old_band_5ghz) {
+ /* TODO */
+ }
+
+ b43_phy_write(dev, B43_PHY_HT_BW1, e->bw1);
+ b43_phy_write(dev, B43_PHY_HT_BW2, e->bw2);
+ b43_phy_write(dev, B43_PHY_HT_BW3, e->bw3);
+ b43_phy_write(dev, B43_PHY_HT_BW4, e->bw4);
+ b43_phy_write(dev, B43_PHY_HT_BW5, e->bw5);
+ b43_phy_write(dev, B43_PHY_HT_BW6, e->bw6);
+
+ 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 == IEEE80211_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) == IEEE80211_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) == IEEE80211_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");
+
+ /* In the following PHY ops we copy wl's dummy behaviour.
+ * TODO: Find out if reads (currently hidden in masks/masksets) are
+ * needed and replace following ops with just writes or w&r.
+ * Note: B43_PHY_HT_RF_CTL1 register is tricky, wrong operation can
+ * cause delayed (!) machine lock up. */
+ if (blocked) {
+ b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, 0);
+ } else {
+ b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, 0);
+ b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, 0, 0x1);
+ b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, 0);
+ b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, 0, 0x2);
+
+ 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) == IEEE80211_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) == IEEE80211_BAND_2GHZ)
+ return 11;
+ return 36;
+}
+
+/**************************************************
+ * R/W ops.
+ **************************************************/
+
+static u16 b43_phy_ht_op_read(struct b43_wldev *dev, u16 reg)
+{
+ b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+ return b43_read16(dev, B43_MMIO_PHY_DATA);
+}
+
+static void b43_phy_ht_op_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+ b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+ b43_write16(dev, B43_MMIO_PHY_DATA, value);
+}
+
+static void b43_phy_ht_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
+ u16 set)
+{
+ b43_write16(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_write16(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_write16(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_read = b43_phy_ht_op_read,
+ .phy_write = b43_phy_ht_op_write,
+ .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/b43/phy_ht.h b/drivers/net/wireless/b43/phy_ht.h
new file mode 100644
index 00000000000..6cae370d101
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_ht.h
@@ -0,0 +1,136 @@
+#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_CTL1 B43_PHY_EXTG(0x010)
+
+#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_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/b43/phy_lcn.c b/drivers/net/wireless/b43/phy_lcn.c
new file mode 100644
index 00000000000..0bafa3b1703
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_lcn.c
@@ -0,0 +1,902 @@
+/*
+
+ 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,
+};
+
+/* In theory it's PHY common function, move if needed */
+/* brcms_b_switch_macfreq */
+static void b43_phy_switch_macfreq(struct b43_wldev *dev, u8 spurmode)
+{
+ if (dev->dev->chip_id == 43224 || dev->dev->chip_id == 43225) {
+ 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;
+ }
+ }
+}
+
+/**************************************************
+ * 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) == IEEE80211_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) == IEEE80211_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_phy_switch_macfreq(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) == IEEE80211_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) == IEEE80211_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) == IEEE80211_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 u16 b43_phy_lcn_op_read(struct b43_wldev *dev, u16 reg)
+{
+ b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+ return b43_read16(dev, B43_MMIO_PHY_DATA);
+}
+
+static void b43_phy_lcn_op_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+ b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+ b43_write16(dev, B43_MMIO_PHY_DATA, value);
+}
+
+static void b43_phy_lcn_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
+ u16 set)
+{
+ b43_write16(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_write16(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_write16(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_read = b43_phy_lcn_op_read,
+ .phy_write = b43_phy_lcn_op_write,
+ .phy_maskset = b43_phy_lcn_op_maskset,
+ .radio_read = b43_phy_lcn_op_radio_read,
+ .radio_write = b43_phy_lcn_op_radio_write,
+ .software_rfkill = b43_phy_lcn_op_software_rfkill,
+ .switch_analog = b43_phy_lcn_op_switch_analog,
+ .switch_channel = b43_phy_lcn_op_switch_channel,
+ .get_default_chan = b43_phy_lcn_op_get_default_chan,
+ .recalc_txpower = b43_phy_lcn_op_recalc_txpower,
+ .adjust_txpower = b43_phy_lcn_op_adjust_txpower,
+};
diff --git a/drivers/net/wireless/b43/phy_lcn.h b/drivers/net/wireless/b43/phy_lcn.h
new file mode 100644
index 00000000000..6a7092e13ff
--- /dev/null
+++ b/drivers/net/wireless/b43/phy_lcn.h
@@ -0,0 +1,31 @@
+#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/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index fd50eb11624..92190dacf68 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -3,7 +3,7 @@
Broadcom B43 wireless driver
IEEE 802.11a/g LP-PHY driver
- Copyright (c) 2008-2009 Michael Buesch <mb@bu3sch.de>
+ 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
@@ -85,85 +85,79 @@ static void b43_lpphy_op_free(struct b43_wldev *dev)
/* 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;
- struct ssb_bus *bus = dev->dev->bus;
u16 cckpo, maxpwr;
u32 ofdmpo;
int i;
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
- lpphy->tx_isolation_med_band = bus->sprom.tri2g;
- lpphy->bx_arch = bus->sprom.bxa2g;
- lpphy->rx_pwr_offset = bus->sprom.rxpo2g;
- lpphy->rssi_vf = bus->sprom.rssismf2g;
- lpphy->rssi_vc = bus->sprom.rssismc2g;
- lpphy->rssi_gs = bus->sprom.rssisav2g;
- lpphy->txpa[0] = bus->sprom.pa0b0;
- lpphy->txpa[1] = bus->sprom.pa0b1;
- lpphy->txpa[2] = bus->sprom.pa0b2;
- maxpwr = bus->sprom.maxpwr_bg;
+ 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 = bus->sprom.cck2gpo;
- /*
- * We don't read SPROM's opo as specs say. On rev8 SPROMs
- * opo == ofdm2gpo and we don't know any SSB with LP-PHY
- * and SPROM rev below 8.
- */
- B43_WARN_ON(bus->sprom.revision < 8);
- ofdmpo = bus->sprom.ofdm2gpo;
+ 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 = bus->sprom.ofdm2gpo;
+ ofdmpo = sprom->ofdm2gpo;
for (i = 4; i < 15; i++) {
lpphy->tx_max_rate[i] =
maxpwr - (ofdmpo & 0xF) * 2;
ofdmpo >>= 4;
}
} else {
- ofdmpo &= 0xFF;
+ 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 - ofdmpo;
+ lpphy->tx_max_rate[i] = maxpwr - opo;
}
} else { /* 5GHz */
- lpphy->tx_isolation_low_band = bus->sprom.tri5gl;
- lpphy->tx_isolation_med_band = bus->sprom.tri5g;
- lpphy->tx_isolation_hi_band = bus->sprom.tri5gh;
- lpphy->bx_arch = bus->sprom.bxa5g;
- lpphy->rx_pwr_offset = bus->sprom.rxpo5g;
- lpphy->rssi_vf = bus->sprom.rssismf5g;
- lpphy->rssi_vc = bus->sprom.rssismc5g;
- lpphy->rssi_gs = bus->sprom.rssisav5g;
- lpphy->txpa[0] = bus->sprom.pa1b0;
- lpphy->txpa[1] = bus->sprom.pa1b1;
- lpphy->txpa[2] = bus->sprom.pa1b2;
- lpphy->txpal[0] = bus->sprom.pa1lob0;
- lpphy->txpal[1] = bus->sprom.pa1lob1;
- lpphy->txpal[2] = bus->sprom.pa1lob2;
- lpphy->txpah[0] = bus->sprom.pa1hib0;
- lpphy->txpah[1] = bus->sprom.pa1hib1;
- lpphy->txpah[2] = bus->sprom.pa1hib2;
- maxpwr = bus->sprom.maxpwr_al;
- ofdmpo = bus->sprom.ofdm5glpo;
+ 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 = bus->sprom.maxpwr_a;
- ofdmpo = bus->sprom.ofdm5gpo;
+ 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 = bus->sprom.maxpwr_ah;
- ofdmpo = bus->sprom.ofdm5ghpo;
+ 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;
@@ -214,7 +208,8 @@ static void lpphy_table_init(struct b43_wldev *dev)
static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->dev->bus;
+ 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;
@@ -242,9 +237,9 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
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 ((bus->sprom.boardflags_lo & B43_BFL_FEM) &&
+ if ((sprom->boardflags_lo & B43_BFL_FEM) &&
((b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
- (bus->sprom.boardflags_hi & B43_BFH_PAREF))) {
+ (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) {
@@ -260,7 +255,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
}
tmp = lpphy->rssi_vf | lpphy->rssi_vc << 4 | 0xA000;
b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_0, tmp);
- if (bus->sprom.boardflags_hi & B43_BFH_RSSIINV)
+ 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);
@@ -268,7 +263,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_LPPHY_RX_RADIO_CTL,
0xFFF9, (lpphy->bx_arch << 1));
if (dev->phy.rev == 1 &&
- (bus->sprom.boardflags_hi & B43_BFH_FEM_BT)) {
+ (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);
@@ -286,8 +281,8 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
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) == IEEE80211_BAND_5GHZ ||
- (bus->boardinfo.type == 0x048A) || ((dev->phy.rev == 0) &&
- (bus->sprom.boardflags_lo & B43_BFL_FEM))) {
+ (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);
@@ -297,7 +292,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
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 ||
- (bus->sprom.boardflags_lo & B43_BFL_FEM)) {
+ (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);
@@ -316,15 +311,15 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
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 && (bus->sprom.boardflags_hi & B43_BFH_PAREF)) {
+ 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 ((bus->sprom.boardflags_hi & B43_BFH_FEM_BT) &&
- (bus->chip_id == 0x5354) &&
- (bus->chip_package == SSB_CHIPPACK_BCM4712S)) {
+ 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);
@@ -412,7 +407,6 @@ static void lpphy_restore_dig_flt_state(struct b43_wldev *dev)
static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->dev->bus;
struct b43_phy_lp *lpphy = dev->phy.lp;
b43_phy_write(dev, B43_LPPHY_AFE_DAC_CTL, 0x50);
@@ -432,7 +426,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
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 (bus->boardinfo.rev >= 0x18) {
+ 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 {
@@ -449,7 +443,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
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 ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
+ 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 {
@@ -467,7 +461,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x12);
b43_phy_maskset(dev, B43_LPPHY_GAINMISMATCH, 0x0FFF, 0x9000);
- if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
+ 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);
}
@@ -492,7 +486,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
0x2000 | ((u16)lpphy->rssi_gs << 10) |
((u16)lpphy->rssi_vc << 4) | lpphy->rssi_vf);
- if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
+ 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);
@@ -519,7 +513,7 @@ struct b2062_freqdata {
static void lpphy_2062_init(struct b43_wldev *dev)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
- struct ssb_bus *bus = dev->dev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
u32 crystalfreq, tmp, ref;
unsigned int i;
const struct b2062_freqdata *fd = NULL;
@@ -697,7 +691,7 @@ static void lpphy_radio_init(struct b43_wldev *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->bus->chip_id == 0x4325) {
+ if (dev->dev->chip_id == 0x4325) {
// TODO SSB PMU recalibration
}
}
@@ -736,9 +730,9 @@ 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 = 1;
+ lpphy->crs_usr_disable = true;
else
- lpphy->crs_sys_disable = 1;
+ lpphy->crs_sys_disable = true;
b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x80);
}
@@ -747,9 +741,9 @@ 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 = 0;
+ lpphy->crs_usr_disable = false;
else
- lpphy->crs_sys_disable = 0;
+ lpphy->crs_sys_disable = false;
if (!lpphy->crs_usr_disable && !lpphy->crs_sys_disable) {
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
@@ -1289,7 +1283,7 @@ finish:
static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->dev->bus;
+ 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;
@@ -1840,7 +1834,6 @@ static void lpphy_papd_cal(struct b43_wldev *dev, struct lpphy_tx_gains gains,
static void lpphy_papd_cal_txpwr(struct b43_wldev *dev)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
- struct ssb_bus *bus = dev->dev->bus;
struct lpphy_tx_gains gains, oldgains;
int old_txpctl, old_afe_ovr, old_rf, old_bbmult;
@@ -1854,7 +1847,7 @@ static void lpphy_papd_cal_txpwr(struct b43_wldev *dev)
lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
- if (bus->chip_id == 0x4325 && bus->chip_rev == 0)
+ 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);
@@ -1870,7 +1863,6 @@ 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;
- struct ssb_bus *bus = dev->dev->bus;
const struct lpphy_rx_iq_comp *iqcomp = NULL;
struct lpphy_tx_gains nogains, oldgains;
u16 tmp;
@@ -1879,7 +1871,7 @@ static int lpphy_rx_iq_cal(struct b43_wldev *dev, bool noise, bool tx,
memset(&nogains, 0, sizeof(nogains));
memset(&oldgains, 0, sizeof(oldgains));
- if (bus->chip_id == 0x5354) {
+ 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];
@@ -2408,11 +2400,9 @@ static const struct b206x_channel b2063_chantbl[] = {
static void lpphy_b2062_reset_pll_bias(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->dev->bus;
-
b43_radio_write(dev, B2062_S_RFPLL_CTL2, 0xFF);
udelay(20);
- if (bus->chip_id == 0x5354) {
+ if (dev->dev->chip_id == 0x5354) {
b43_radio_write(dev, B2062_N_COMM1, 4);
b43_radio_write(dev, B2062_S_RFPLL_CTL2, 4);
} else {
@@ -2432,7 +2422,7 @@ 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->bus;
+ 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;
@@ -2522,7 +2512,7 @@ static void lpphy_b2063_vco_calib(struct b43_wldev *dev)
static int lpphy_b2063_tune(struct b43_wldev *dev,
unsigned int channel)
{
- struct ssb_bus *bus = dev->dev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
static const struct b206x_channel *chandata = NULL;
u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
@@ -2670,6 +2660,11 @@ 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);
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index ab81ed8b19d..86569f6a870 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -3,7 +3,8 @@
Broadcom B43 wireless driver
IEEE 802.11n PHY support
- Copyright (c) 2008 Michael Buesch <mb@bu3sch.de>
+ 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
@@ -31,6 +32,7 @@
#include "tables_nphy.h"
#include "radio_2055.h"
#include "radio_2056.h"
+#include "radio_2057.h"
#include "main.h"
struct nphy_txgains {
@@ -67,78 +69,656 @@ enum b43_nphy_rf_sequence {
B43_RFSEQ_UPDATE_GAINU,
};
-enum b43_nphy_rssi_type {
- B43_NPHY_RSSI_X = 0,
- B43_NPHY_RSSI_Y,
- B43_NPHY_RSSI_Z,
- B43_NPHY_RSSI_PWRDET,
- B43_NPHY_RSSI_TSSI_I,
- B43_NPHY_RSSI_TSSI_Q,
- B43_NPHY_RSSI_TBD,
+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,
};
-static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev,
- bool enable);
-static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
- u8 *events, u8 *delays, u8 length);
+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 ieee80211_band band = b43_current_band(dev->wl);
+ return ((dev->phy.n->ipa2g_on && band == IEEE80211_BAND_2GHZ) ||
+ (dev->phy.n->ipa5g_on && band == IEEE80211_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 void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
- u16 value, u8 core, bool off);
-static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
- u16 value, u8 core);
+ 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);
-void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
-{//TODO
+ 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_op_adjust_txpower(struct b43_wldev *dev)
-{//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)
+{
+ 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;
+
+ /* 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));
+ }
+ }
+ }
}
-static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev,
- bool ignore_tssi)
-{//TODO
- return B43_TXPWR_RES_DONE;
+/* 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_chantab_radio_upload(struct b43_wldev *dev,
- const struct b43_nphy_channeltab_entry_rev2 *e)
+static void b43_nphy_rf_ctl_intc_override_rev7(struct b43_wldev *dev,
+ enum n_intc_override intc_override,
+ u16 value, u8 core_sel)
{
- 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 */
+ u16 reg, tmp, tmp2, val;
+ int core;
- 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 */
+ for (core = 0; core < 2; core++) {
+ if ((core_sel == 1 && core != 0) ||
+ (core_sel == 2 && core != 1))
+ continue;
- 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 */
+ reg = (core == 0) ? B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2;
- 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 */
+ 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:
+ b43_phy_maskset(dev, reg, ~0xC0, value << 6);
+ b43_phy_set(dev, reg, 0x400);
- 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_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) == IEEE80211_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) == IEEE80211_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) == IEEE80211_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;
+ }
+ }
+}
- 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/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) == IEEE80211_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) == IEEE80211_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) == IEEE80211_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/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) == IEEE80211_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
+ **************************************************/
+
+/* http://bcm-v4.sipsolutions.net/PHY/radio2057_rcal */
+static u8 b43_radio_2057_rcal(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ u16 tmp;
+
+ if (phy->radio_rev == 5) {
+ b43_phy_mask(dev, 0x342, ~0x2);
+ udelay(10);
+ b43_radio_set(dev, R2057_IQTEST_SEL_PU, 0x1);
+ b43_radio_maskset(dev, 0x1ca, ~0x2, 0x1);
+ }
+
+ b43_radio_set(dev, R2057_RCAL_CONFIG, 0x1);
+ udelay(10);
+ b43_radio_set(dev, R2057_RCAL_CONFIG, 0x3);
+ if (!b43_radio_wait_value(dev, R2057_RCCAL_N1_1, 1, 1, 100, 1000000)) {
+ b43err(dev->wl, "Radio 0x2057 rcal timeout\n");
+ return 0;
+ }
+ b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x2);
+ tmp = b43_radio_read(dev, R2057_RCAL_STATUS) & 0x3E;
+ b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x1);
+
+ if (phy->radio_rev == 5) {
+ b43_radio_mask(dev, R2057_IPA2G_CASCONV_CORE0, ~0x1);
+ b43_radio_mask(dev, 0x1ca, ~0x2);
+ }
+ if (phy->radio_rev <= 4 || phy->radio_rev == 6) {
+ b43_radio_maskset(dev, R2057_TEMPSENSE_CONFIG, ~0x3C, tmp);
+ b43_radio_maskset(dev, R2057_BANDGAP_RCAL_TRIM, ~0xF0,
+ tmp << 2);
+ }
+
+ return tmp & 0x3e;
+}
+
+/* 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;
+
+ if (special) {
+ b43_radio_write(dev, R2057_RCCAL_MASTER, 0x61);
+ b43_radio_write(dev, R2057_RCCAL_TRC0, 0xC0);
+ } else {
+ b43_radio_write(dev, 0x1AE, 0x61);
+ b43_radio_write(dev, R2057_RCCAL_TRC0, 0xE1);
+ }
+ b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
+ b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
+ if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 1, 1, 500,
+ 5000000))
+ b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n");
+ b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
+ if (special) {
+ b43_radio_write(dev, R2057_RCCAL_MASTER, 0x69);
+ b43_radio_write(dev, R2057_RCCAL_TRC0, 0xB0);
+ } else {
+ b43_radio_write(dev, 0x1AE, 0x69);
+ b43_radio_write(dev, R2057_RCCAL_TRC0, 0xD5);
+ }
+ b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
+ b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
+ if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 1, 1, 500,
+ 5000000))
+ b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n");
+ b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
+ 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, 0x1AE, 0x73);
+ b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
+ b43_radio_write(dev, R2057_RCCAL_TRC0, 0x99);
+ }
+ b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
+ if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 1, 1, 500,
+ 5000000)) {
+ b43err(dev->wl, "Radio 0x2057 rcal timeout\n");
+ return 0;
+ }
+ tmp = b43_radio_read(dev, R2057_RCCAL_DONE_OSCCAP);
+ b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
+ 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);
+
+ b43_radio_set(dev, R2057_RFPLL_MISC_CAL_RESETN, 0x78);
+ b43_radio_set(dev, R2057_XTAL_CONFIG2, 0x80);
+ mdelay(2);
+ 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)
{
@@ -218,10 +798,171 @@ static void b43_chantab_radio_2056_upload(struct b43_wldev *dev,
static void b43_radio_2056_setup(struct b43_wldev *dev,
const struct b43_nphy_channeltab_entry_rev3 *e)
{
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
+ enum ieee80211_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);
- /* TODO */
+ b2056_upload_syn_pll_cp2(dev, band == IEEE80211_BAND_5GHZ);
+
+ if (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
+ b43_current_band(dev->wl) == IEEE80211_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) == IEEE80211_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) == IEEE80211_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 == IEEE80211_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 = dev->phy.is_40mhz ? 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 == IEEE80211_BAND_5GHZ) {
+ u16 freq = dev->phy.channel_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);
@@ -232,15 +973,2093 @@ static void b43_radio_2056_setup(struct b43_wldev *dev,
udelay(300);
}
-static void b43_chantab_phy_upload(struct b43_wldev *dev,
- const struct b43_phy_n_sfo_cfg *e)
+static u8 b43_radio_2056_rcal(struct b43_wldev *dev)
{
- 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);
+ 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) == IEEE80211_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 = kzalloc(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 = (dev->phy.is_40mhz) ? 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 (dev->phy.is_40mhz)
+ 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)
+{
+ struct b43_phy_n *nphy = dev->phy.n;
+ int i;
+ u16 seq_mode;
+ u32 tmp;
+
+ b43_nphy_stay_in_carrier_search(dev, true);
+
+ if ((nphy->bb_mult_save & 0x80000000) == 0) {
+ tmp = b43_ntab_read(dev, B43_NTAB16(15, 87));
+ nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000;
+ }
+
+ /* TODO: add modify_bbmult argument */
+ if (!dev->phy.is_40mhz)
+ tmp = 0x6464;
+ else
+ tmp = 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 {
+ if (dac_test)
+ b43_phy_write(dev, B43_NPHY_SAMP_CMD, 5);
+ else
+ b43_phy_write(dev, B43_NPHY_SAMP_CMD, 1);
+ }
+ 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_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) == IEEE80211_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 ieee80211_band band =
+ b43_current_band(dev->wl);
+
+ if (b43_nphy_ipa(dev))
+ val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE;
+ else
+ val = 0x11;
+ reg = (i == 0) ? 0x2000 : 0x3000;
+ reg |= B2055_PADDRV;
+ 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 >= 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];
+
+ 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_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,
+ 0x342, 0x343, 0x346, 0x347,
+ 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,
+ 0x340, 0x341, 0x344, 0x345,
+ 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) {
+ /* TODO */
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
+ } else {
+ }
+ } 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) == IEEE80211_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)
+ ;
+ 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)
+ ;
+ 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) == IEEE80211_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) {
+ } 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) == IEEE80211_BAND_2GHZ)
+ nphy->rssical_chanspec_2G.center_freq = dev->phy.channel_freq;
+ else
+ nphy->rssical_chanspec_5G.center_freq = dev->phy.channel_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) == IEEE80211_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 >= 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_rev3plus(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 (!dev->phy.is_40mhz) {
+ /* 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 (!dev->phy.is_40mhz) {
+ 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) == IEEE80211_BAND_2GHZ &&
+ dev->phy.is_40mhz)
+ code = 4;
+ else
+ code = 5;
+ } else {
+ code = dev->phy.is_40mhz ? 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) == IEEE80211_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 >= 7)
+ ; /* TODO */
+ else if (dev->phy.rev >= 3)
+ b43_nphy_gain_ctl_workarounds_rev3plus(dev);
+ else
+ b43_nphy_gain_ctl_workarounds_rev1_2(dev);
+}
+
+/* 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 = (dev->phy.is_40mhz) ? 0x159 : 0x154;
+ return b43_ntab_read(dev, B43_NTAB16(7, offset)) & 0x7;
+}
+
+static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
+{
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
+ struct b43_phy *phy = &dev->phy;
+
+ 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 };
+
+ u16 ntab7_15e_16e[] = { 0x10f, 0x10f };
+ u8 ntab7_138_146[] = { 0x11, 0x11 };
+ u8 ntab7_133[] = { 0x77, 0x11, 0x11 };
+
+ u16 lpf_20, lpf_40, lpf_11b;
+ u16 bcap_val, bcap_val_11b, bcap_val_11n_20, bcap_val_11n_40;
+ u16 scap_val, scap_val_11b, scap_val_11n_20, scap_val_11n_40;
+ bool rccal_ovrd = false;
+
+ u16 rx2tx_lut_20_11b, rx2tx_lut_20_11n, rx2tx_lut_40_11n;
+ u16 bias, conv, filt;
+
+ u32 tmp32;
+ u8 core;
+
+ 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 <= 8) {
+ b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1B0);
+ b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1B0);
+ }
+ 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, 0x15e), 2, ntab7_15e_16e);
+ b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16e), 2, ntab7_15e_16e);
+
+ 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);
+
+ lpf_20 = b43_nphy_read_lpf_ctl(dev, 0x154);
+ lpf_40 = b43_nphy_read_lpf_ctl(dev, 0x159);
+ lpf_11b = b43_nphy_read_lpf_ctl(dev, 0x152);
+ if (b43_nphy_ipa(dev)) {
+ if ((phy->radio_rev == 5 && phy->is_40mhz) ||
+ phy->radio_rev == 7 || phy->radio_rev == 8) {
+ bcap_val = b43_radio_read(dev, 0x16b);
+ scap_val = b43_radio_read(dev, 0x16a);
+ scap_val_11b = scap_val;
+ bcap_val_11b = bcap_val;
+ if (phy->radio_rev == 5 && phy->is_40mhz) {
+ scap_val_11n_20 = scap_val;
+ bcap_val_11n_20 = bcap_val;
+ scap_val_11n_40 = bcap_val_11n_40 = 0xc;
+ rccal_ovrd = true;
+ } else { /* Rev 7/8 */
+ lpf_20 = 4;
+ lpf_11b = 1;
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+ scap_val_11n_20 = 0xc;
+ bcap_val_11n_20 = 0xc;
+ scap_val_11n_40 = 0xa;
+ bcap_val_11n_40 = 0xa;
+ } else {
+ scap_val_11n_20 = 0x14;
+ bcap_val_11n_20 = 0x14;
+ scap_val_11n_40 = 0xf;
+ bcap_val_11n_40 = 0xf;
+ }
+ rccal_ovrd = true;
+ }
+ }
+ } else {
+ if (phy->radio_rev == 5) {
+ lpf_20 = 1;
+ lpf_40 = 3;
+ bcap_val = b43_radio_read(dev, 0x16b);
+ scap_val = b43_radio_read(dev, 0x16a);
+ scap_val_11b = scap_val;
+ bcap_val_11b = bcap_val;
+ scap_val_11n_20 = 0x11;
+ scap_val_11n_40 = 0x11;
+ bcap_val_11n_20 = 0x13;
+ bcap_val_11n_40 = 0x13;
+ rccal_ovrd = true;
+ }
+ }
+ if (rccal_ovrd) {
+ rx2tx_lut_20_11b = (bcap_val_11b << 8) |
+ (scap_val_11b << 3) |
+ lpf_11b;
+ rx2tx_lut_20_11n = (bcap_val_11n_20 << 8) |
+ (scap_val_11n_20 << 3) |
+ lpf_20;
+ rx2tx_lut_40_11n = (bcap_val_11n_40 << 8) |
+ (scap_val_11n_40 << 3) |
+ lpf_40;
+ for (core = 0; core < 2; core++) {
+ b43_ntab_write(dev, B43_NTAB16(7, 0x152 + core * 16),
+ rx2tx_lut_20_11b);
+ b43_ntab_write(dev, B43_NTAB16(7, 0x153 + core * 16),
+ rx2tx_lut_20_11n);
+ b43_ntab_write(dev, B43_NTAB16(7, 0x154 + core * 16),
+ rx2tx_lut_20_11n);
+ b43_ntab_write(dev, B43_NTAB16(7, 0x155 + core * 16),
+ rx2tx_lut_40_11n);
+ b43_ntab_write(dev, B43_NTAB16(7, 0x156 + core * 16),
+ rx2tx_lut_40_11n);
+ b43_ntab_write(dev, B43_NTAB16(7, 0x157 + core * 16),
+ rx2tx_lut_40_11n);
+ b43_ntab_write(dev, B43_NTAB16(7, 0x158 + core * 16),
+ rx2tx_lut_40_11n);
+ b43_ntab_write(dev, B43_NTAB16(7, 0x159 + core * 16),
+ rx2tx_lut_40_11n);
+ }
+ b43_nphy_rf_ctl_override_rev7(dev, 16, 1, 3, false, 2);
+ }
+ 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) == IEEE80211_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) == IEEE80211_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);
+ }
+ }
+ if (phy->radio_rev == 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);
+ }
+ }
+ } else if (phy->radio_rev == 7 || phy->radio_rev == 8) {
+ if (!phy->is_40mhz) {
+ 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);
+ }
+ }
+ } else {
+ u16 freq = phy->channel_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), 0x20);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0x20);
+
+ 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_NTAB16(7, 0x138), 2, ntab7_138_146);
+ b43_ntab_write(dev, B43_NTAB16(7, 0x141), 0x77);
+ b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x133), 3, ntab7_133);
+ b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x146), 2, ntab7_138_146);
+ b43_ntab_write(dev, B43_NTAB16(7, 0x123), 0x77);
+ b43_ntab_write(dev, B43_NTAB16(7, 0x12A), 0x77);
+
+ if (!phy->is_40mhz) {
+ b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x18D);
+ b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x18D);
+ } else {
+ b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x14D);
+ b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x14D);
+ }
+
+ 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) == IEEE80211_BAND_2GHZ) ?
+ 0x2 : 0x9C40;
+ b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16);
+
+ b43_phy_maskset(dev, B43_NPHY_SGILTRNOFFSET, 0xF0FF, 0x0700);
+
+ if (!dev->phy.is_40mhz) {
+ 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) == IEEE80211_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) == IEEE80211_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) == IEEE80211_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) != IEEE80211_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) == IEEE80211_BAND_5GHZ) ||
+ (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
+ b43_current_band(dev->wl) == IEEE80211_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) == IEEE80211_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) == IEEE80211_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) == IEEE80211_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);
+
+ 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)
+{
+ 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);
+ 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_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 (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)
+{
+ int i, j, indx;
+ u16 gain;
+
+ if (dev->phy.rev >= 3) {
+ params->txgm = target.txgm[core];
+ params->pga = target.pga[core];
+ params->pad = target.pad[core];
+ params->ipa = target.ipa[core];
+ 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) == IEEE80211_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
+ **************************************************/
+
+static void b43_nphy_op_adjust_txpower(struct b43_wldev *dev)
+{//TODO
+}
+
+static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev,
+ bool ignore_tssi)
+{//TODO
+ return B43_TXPWR_RES_DONE;
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */
@@ -248,15 +3067,25 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
{
struct b43_phy_n *nphy = dev->phy.n;
u8 i;
- u16 tmp;
+ u16 bmask, val, tmp;
+ enum ieee80211_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)
- ; /* TODO */
+ 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++)
@@ -285,10 +3114,67 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
~B43_NPHY_BPHY_CTL3_SCALE, 0x5A);
- if (dev->phy.rev < 2 && 0)
- ; /* TODO */
+ if (dev->phy.rev < 2 && dev->phy.is_40mhz)
+ b43_hf_write(dev, b43_hf_read(dev) | B43_HF_TSSIRPSMW);
} else {
- b43err(dev->wl, "enabling tx pwr ctrl not implemented yet\n");
+ 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 == IEEE80211_BAND_5GHZ) {
+ b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
+ ~B43_NPHY_TXPCTL_CMD_INIT, 0x64);
+ if (dev->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 (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 && dev->phy.is_40mhz)
+ 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)
@@ -299,7 +3185,7 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
{
struct b43_phy_n *nphy = dev->phy.n;
- struct ssb_sprom *sprom = &(dev->dev->bus->sprom);
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
u8 txpi[2], bbmult, i;
u16 tmp, radio_gain, dac_gain;
@@ -310,7 +3196,9 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
if (nphy->hang_avoid)
b43_nphy_stay_in_carrier_search(dev, 1);
- if (dev->phy.rev >= 3) {
+ 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) {
@@ -334,6 +3222,9 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
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++) {
@@ -343,16 +3234,17 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
*/
for (i = 0; i < 2; i++) {
- if (dev->phy.rev >= 3) {
- /* FIXME: support 5GHz */
- txgain = b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]];
+ txgain = *(b43_nphy_get_tx_gain_table(dev) + txpi[i]);
+
+ if (dev->phy.rev >= 3)
radio_gain = (txgain >> 16) & 0x1FFFF;
- } else {
- txgain = b43_ntab_tx_gain_rev0_1_2[txpi[i]];
+ else
radio_gain = (txgain >> 16) & 0x1FFF;
- }
- dac_gain = (txgain >> 8) & 0x3F;
+ if (dev->phy.rev >= 7)
+ dac_gain = (txgain >> 8) & 0x7;
+ else
+ dac_gain = (txgain >> 8) & 0x3F;
bbmult = txgain & 0xFF;
if (dev->phy.rev >= 3) {
@@ -369,22 +3261,24 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
else
b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN2, dac_gain);
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D10 + i);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, radio_gain);
-
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C57);
- tmp = b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
+ 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_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C57);
- b43_phy_write(dev, B43_NPHY_TABLE_DATALO, tmp);
-
- if (0)
- ; /* TODO */
+ 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);
@@ -393,156 +3287,388 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
b43_nphy_stay_in_carrier_search(dev, 0);
}
-
-/* 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)
+static void b43_nphy_ipa_internal_tssi_setup(struct b43_wldev *dev)
{
- B43_WARN_ON(dev->phy.rev >= 3);
+ struct b43_phy *phy = &dev->phy;
- 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);
+ u8 core;
+ u16 r; /* routing */
+
+ if (phy->rev >= 7) {
+ for (core = 0; core < 2; core++) {
+ r = core ? 0x190 : 0x170;
+ if (b43_current_band(dev->wl) == IEEE80211_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) == IEEE80211_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) == IEEE80211_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);
+ }
+ }
+ }
}
-static void b43_radio_init2055_pre(struct b43_wldev *dev)
+/*
+ * 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)
{
- 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);
+ struct b43_phy *phy = &dev->phy;
+ struct b43_phy_n *nphy = dev->phy.n;
+
+ u32 tmp;
+ s32 rssi[4] = { };
+
+ /* TODO: check if we can transmit */
+
+ if (b43_nphy_ipa(dev))
+ b43_nphy_ipa_internal_tssi_setup(dev);
+
+ if (phy->rev >= 7)
+ b43_nphy_rf_ctl_override_rev7(dev, 0x2000, 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, 0xFA0, 0, 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 >= 7)
+ b43_nphy_rf_ctl_override_rev7(dev, 0x2000, 0, 3, true, 0);
+ else if (phy->rev >= 3)
+ b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, true);
+
+ 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;
}
-static void b43_radio_init2055_post(struct b43_wldev *dev)
+/* 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;
- struct ssb_sprom *sprom = &(dev->dev->bus->sprom);
- struct ssb_boardinfo *binfo = &(dev->dev->bus->boardinfo);
- int i;
- u16 val;
- bool workaround = false;
- if (sprom->revision < 4)
- workaround = (binfo->vendor != PCI_VENDOR_ID_BROADCOM ||
- binfo->type != 0x46D ||
- binfo->rev < 0x41);
- else
- workaround =
- !(sprom->boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS);
+ 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
+ */
- 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);
- for (i = 0; i < 200; i++) {
- val = b43_radio_read(dev, B2055_CAL_COUT2);
- if (val & 0x80) {
- i = 0;
+ 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 (dev->phy.is_40mhz && dev->phy.rev >= 5) {
+ idx = 68;
+ } else {
+ delta = 1;
+ idx = dev->phy.is_40mhz ? 52 : 4;
+ }
+ break;
+ case 1:
+ idx = dev->phy.is_40mhz ? 76 : 28;
+ break;
+ case 2:
+ idx = dev->phy.is_40mhz ? 84 : 36;
+ break;
+ case 3:
+ idx = dev->phy.is_40mhz ? 92 : 44;
break;
}
- udelay(10);
- }
- if (i)
- 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);
+
+ 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;
+ }
}
- 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)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlSetup */
+static void b43_nphy_tx_power_ctl_setup(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);
+ 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];
+ s8 target[2];
+ s32 num, den, pwr;
+ u32 regval[64];
+
+ u16 freq = dev->phy.channel_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 {
- bool ghz5 = b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ;
- b2055_upload_inittab(dev, ghz5, 0);
+ if (b43_current_band(dev->wl) == IEEE80211_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;
+ }
}
- b43_radio_init2055_post(dev);
-}
+ /* target[0] = target[1] = nphy->tx_power_max; */
-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);
-}
+ 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) == IEEE80211_BAND_2GHZ) ? 0xE : 0xC);
+ }
+ } else {
+ if (b43_nphy_ipa(dev)) {
+ tmp = (b43_current_band(dev->wl) == IEEE80211_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);
+ }
+ }
+ }
-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 (nphy->init_por)
- Call Radio 2056 Recalibrate
- */
-}
+ 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);
+ }
-/*
- * 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);
+ if (dev->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);
}
-/*
- * Upload the N-PHY tables.
- * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables
- */
-static void b43_nphy_tables_init(struct b43_wldev *dev)
+static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev)
{
- if (dev->phy.rev < 3)
- b43_nphy_rev0_1_2_tables_init(dev);
- else
- b43_nphy_rev3plus_tables_init(dev);
+ struct b43_phy *phy = &dev->phy;
+
+ const u32 *table = NULL;
+ u32 rfpwr_offset;
+ u8 pga_gain;
+ int i;
+
+ table = b43_nphy_get_tx_gain_table(dev);
+ 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) {
+#if 0
+ nphy->gmval = (table[0] >> 16) & 0x7000;
+#endif
+
+ for (i = 0; i < 128; i++) {
+ pga_gain = (table[i] >> 24) & 0xF;
+ if (b43_current_band(dev->wl) == IEEE80211_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 */
@@ -582,14 +3708,10 @@ static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable)
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw */
static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev)
{
- struct b43_phy_n *nphy = dev->phy.n;
u16 tmp;
- enum ieee80211_band band = b43_current_band(dev->wl);
- bool ipa = (nphy->ipa2g_on && band == IEEE80211_BAND_2GHZ) ||
- (nphy->ipa5g_on && band == IEEE80211_BAND_5GHZ);
if (dev->phy.rev >= 3) {
- if (ipa) {
+ if (b43_nphy_ipa(dev)) {
tmp = 4;
b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2,
(((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
@@ -601,78 +3723,6 @@ static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev)
}
}
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
-static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force)
-{
- u32 tmslow;
-
- if (dev->phy.type != B43_PHYTYPE_N)
- return;
-
- tmslow = ssb_read32(dev->dev, SSB_TMSLOW);
- if (force)
- tmslow |= SSB_TMSLOW_FGC;
- else
- tmslow &= ~SSB_TMSLOW_FGC;
- ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
-static void b43_nphy_reset_cca(struct b43_wldev *dev)
-{
- u16 bbcfg;
-
- b43_nphy_bmac_clock_fgc(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_nphy_bmac_clock_fgc(dev, 0);
- b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
-}
-
-/* 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/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/RxIqEst */
static void b43_nphy_rx_iq_est(struct b43_wldev *dev, struct nphy_iq_est *est,
u16 samps, u8 time, bool wait)
@@ -798,8 +3848,8 @@ static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core)
b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0007);
}
- b43_nphy_rf_control_intc_override(dev, 2, 0, 3);
- b43_nphy_rf_control_override(dev, 8, 0, 3, false);
+ 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) {
@@ -809,8 +3859,10 @@ static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core)
rxval = 4;
txval = 2;
}
- b43_nphy_rf_control_intc_override(dev, 1, rxval, (core + 1));
- b43_nphy_rf_control_intc_override(dev, 1, txval, (2 - core));
+ 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
@@ -916,11 +3968,7 @@ static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask)
static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev)
{
u16 array[4];
- int i;
-
- b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C50);
- for (i = 0; i < 4; i++)
- array[i] = b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
+ 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]);
@@ -928,127 +3976,6 @@ static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev)
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW3, array[3]);
}
-/* 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/SuperSwitchInit */
-static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init)
-{
- 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);
-
- ssb_chipco_gpio_control(&dev->dev->bus->chipco, 0xFC00,
- 0xFC00);
- b43_write32(dev, B43_MMIO_MACCTL,
- b43_read32(dev, B43_MMIO_MACCTL) &
- ~B43_MACCTL_GPOUTSMSK);
- b43_write16(dev, B43_MMIO_GPIO_MASK,
- b43_read16(dev, B43_MMIO_GPIO_MASK) | 0xFC00);
- b43_write16(dev, B43_MMIO_GPIO_CONTROL,
- b43_read16(dev, B43_MMIO_GPIO_CONTROL) & ~0xFC00);
-
- 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/N/classifier */
-static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)
-{
- u16 tmp;
-
- if (dev->dev->id.revision == 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->id.revision == 16)
- b43_mac_enable(dev);
-
- return tmp;
-}
-
-/* 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, 0);
- 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/802.11/PHY/N/stop-playback */
-static void b43_nphy_stop_playback(struct b43_wldev *dev)
-{
- 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 (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, 0);
-}
-
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SpurWar */
static void b43_nphy_spur_workaround(struct b43_wldev *dev)
{
@@ -1108,439 +4035,6 @@ static void b43_nphy_spur_workaround(struct b43_wldev *dev)
b43_nphy_stay_in_carrier_search(dev, 0);
}
-/* 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) == IEEE80211_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/WorkaroundsGainCtrl */
-static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev)
-{
- struct b43_phy_n *nphy = dev->phy.n;
- u8 i, j;
- u8 code;
- u16 tmp;
-
- /* TODO: for PHY >= 3
- s8 *lna1_gain, *lna2_gain;
- u8 *gain_db, *gain_bits;
- u16 *rfseq_init;
- u8 lpf_gain[6] = { 0x00, 0x06, 0x0C, 0x12, 0x12, 0x12 };
- u8 lpf_bits[6] = { 0, 1, 2, 3, 3, 3 };
- */
-
- u8 rfseq_events[3] = { 6, 8, 7 };
- u8 rfseq_delays[3] = { 10, 30, 1 };
-
- if (dev->phy.rev >= 3) {
- /* TODO */
- } else {
- /* 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 (!dev->phy.is_40mhz) {
- /* 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 (!dev->phy.is_40mhz) {
- 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) == IEEE80211_BAND_2GHZ &&
- dev->phy.is_40mhz)
- code = 4;
- else
- code = 5;
- } else {
- code = dev->phy.is_40mhz ? 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) == IEEE80211_BAND_2GHZ)
- b43_phy_maskset(dev, B43_PHY_N(0xC5D),
- 0xFF80, 4);
- }
- }
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */
-static void b43_nphy_workarounds(struct b43_wldev *dev)
-{
- struct ssb_bus *bus = dev->dev->bus;
- 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 (b43_current_band(dev->wl) == IEEE80211_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);
-
- if (dev->phy.rev >= 3) {
- /* TODO */
- } else {
- if (b43_current_band(dev->wl) == IEEE80211_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);
- 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);
-
- if (bus->sprom.boardflags2_lo & 0x100 &&
- bus->boardinfo.type == 0x8B) {
- delays1[0] = 0x1;
- delays1[5] = 0x14;
- }
- b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);
- b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);
-
- b43_nphy_gain_ctrl_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);
-
- 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);
- }
-
- if (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, 0);
-}
-
-/* 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 = kzalloc(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 = (dev->phy.is_40mhz) ? 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 (dev->phy.is_40mhz)
- 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)
-{
- struct b43_phy_n *nphy = dev->phy.n;
- int i;
- u16 seq_mode;
- u32 tmp;
-
- if (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, 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 (!dev->phy.is_40mhz)
- tmp = 0x6464;
- else
- tmp = 0x4747;
- b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
-
- if (nphy->hang_avoid)
- b43_nphy_stay_in_carrier_search(dev, false);
-
- 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 {
- if (dac_test)
- b43_phy_write(dev, B43_NPHY_SAMP_CMD, 5);
- else
- b43_phy_write(dev, B43_NPHY_SAMP_CMD, 1);
- }
- 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);
-}
-
-/*
- * 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)
-{
- 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);
- return 0;
-}
-
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */
static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev)
{
@@ -1607,776 +4101,6 @@ static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev)
b43_nphy_stay_in_carrier_search(dev, false);
}
-/* 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);
-}
-
-/* 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);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */
-static void b43_nphy_rf_control_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 << core) & i) != 0) {
- 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 ((core & (1 << i)) != 0)
- 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);
- }
- }
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlIntcOverride */
-static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
- u16 value, u8 core)
-{
- u8 i, j;
- u16 reg, tmp, val;
-
- B43_WARN_ON(dev->phy.rev < 3);
- B43_WARN_ON(field > 4);
-
- 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_mask(dev, reg, 0xFBFF);
-
- switch (field) {
- case 0:
- b43_phy_write(dev, reg, 0);
- b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
- break;
- case 1:
- 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 2:
- if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
- tmp = 0x0020;
- val = value << 5;
- } else {
- tmp = 0x0010;
- val = value << 4;
- }
- b43_phy_maskset(dev, reg, ~tmp, val);
- break;
- case 3:
- if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
- tmp = 0x0001;
- val = value;
- } else {
- tmp = 0x0004;
- val = value << 2;
- }
- b43_phy_maskset(dev, reg, ~tmp, val);
- break;
- case 4:
- if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
- tmp = 0x0002;
- val = value << 1;
- } else {
- tmp = 0x0008;
- val = value << 3;
- }
- b43_phy_maskset(dev, reg, ~tmp, val);
- break;
- }
- }
-}
-
-/* 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/ScaleOffsetRssi */
-static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale,
- s8 offset, u8 core, u8 rail,
- enum b43_nphy_rssi_type 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);
-
- if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp);
- if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp);
- if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp);
- if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp);
-
- if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_X))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp);
- if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_X))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp);
- if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_X))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp);
- if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_X))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp);
-
- if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp);
- if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp);
- if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp);
- if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp);
-
- if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp);
- if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp);
- if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp);
- if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp);
-
- if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp);
- if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp);
- if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp);
- if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp);
-
- if (core1or5 && (type == B43_NPHY_RSSI_TSSI_I))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp);
- if (core2or5 && (type == B43_NPHY_RSSI_TSSI_I))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp);
-
- if (core1or5 && (type == B43_NPHY_RSSI_TSSI_Q))
- b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp);
- if (core2or5 && (type == B43_NPHY_RSSI_TSSI_Q))
- b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp);
-}
-
-static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
-{
- u16 val;
-
- if (type < 3)
- val = 0;
- else if (type == 6)
- val = 1;
- else if (type == 3)
- val = 2;
- else
- 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 (type < 3) {
- b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF,
- (type + 1) << 4);
- b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF,
- (type + 1) << 4);
- }
-
- if (code == 0) {
- b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x3000);
- if (type < 3) {
- 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 (type < 3) {
- 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);
- }
- }
-}
-
-static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
-{
- struct b43_phy_n *nphy = dev->phy.n;
- 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 (type < 3) {
- 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 (type == 0)
- val = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? 4 : 8;
- else if (type == 1)
- 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 (type == 6)
- val = 0x0100;
- else if (type == 3)
- 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 (type != 3 && type != 6) {
- enum ieee80211_band band =
- b43_current_band(dev->wl);
-
- if ((nphy->ipa2g_on &&
- band == IEEE80211_BAND_2GHZ) ||
- (nphy->ipa5g_on &&
- band == IEEE80211_BAND_5GHZ))
- val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE;
- else
- val = 0x11;
- reg = (i == 0) ? 0x2000 : 0x3000;
- reg |= B2055_PADDRV;
- b43_radio_write16(dev, reg, val);
-
- reg = (i == 0) ?
- B43_NPHY_AFECTL_OVER1 :
- B43_NPHY_AFECTL_OVER;
- b43_phy_set(dev, reg, 0x0200);
- }
- }
- }
- }
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */
-static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
-{
- 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, u8 type, u8 *buf)
-{
- int i;
- for (i = 0; i < 2; i++) {
- if (type == 2) {
- 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, u8 type, s32 *buf,
- u8 nsamp)
-{
- int i;
- int out;
- u16 save_regs_phy[9];
- u16 s[2];
-
- if (dev->phy.rev >= 3) {
- save_regs_phy[0] = b43_phy_read(dev,
- B43_NPHY_RFCTL_LUT_TRSW_UP1);
- save_regs_phy[1] = b43_phy_read(dev,
- B43_NPHY_RFCTL_LUT_TRSW_UP2);
- save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
- save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
- 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);
- } else if (dev->phy.rev == 2) {
- 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);
- }
-
- b43_nphy_rssi_select(dev, 5, 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_RFCTL_LUT_TRSW_UP1,
- save_regs_phy[0]);
- b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2,
- save_regs_phy[1]);
- b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[2]);
- b43_phy_write(dev, B43_NPHY_AFECTL_C2, 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 if (dev->phy.rev == 2) {
- 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/RSSICal */
-static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
-{
- int i, j;
- u8 state[4];
- u8 code, val;
- u16 class, override;
- u8 regs_save_radio[2];
- u16 regs_save_phy[2];
-
- s8 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 == 2) {
- code = 0;
- val = 6;
- } else if (type < 2) {
- 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) == IEEE80211_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_read16(dev, B2055_C1_PD_RXTX);
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, override);
- b43_radio_write16(dev, B2055_C1_PD_RXTX, val);
-
- regs_save_phy[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
- regs_save_radio[1] = b43_radio_read16(dev, B2055_C2_PD_RXTX);
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, override);
- b43_radio_write16(dev, B2055_C2_PD_RXTX, val);
-
- state[0] = b43_radio_read16(dev, B2055_C1_PD_RSSIMISC) & 0x07;
- state[1] = b43_radio_read16(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_read16(dev, B2055_C1_SP_RSSI) & 0x07;
- state[3] = b43_radio_read16(dev, B2055_C2_SP_RSSI) & 0x07;
-
- b43_nphy_rssi_select(dev, 5, type);
- b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 0, type);
- b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 1, type);
-
- for (i = 0; i < 4; i++) {
- u8 tmp[4];
- for (j = 0; j < 4; j++)
- tmp[j] = i;
- if (type != 1)
- b43_nphy_set_rssi_2055_vcm(dev, type, tmp);
- b43_nphy_poll_rssi(dev, type, results[i], 8);
- if (type < 2)
- for (j = 0; j < 2; j++)
- miniq[i][j] = min(results[i][2 * j],
- results[i][2 * j + 1]);
- }
-
- for (i = 0; i < 4; i++) {
- s32 mind = 40;
- u8 minvcm = 0;
- s32 minpoll = 249;
- s32 curr;
- for (j = 0; j < 4; j++) {
- if (type == 2)
- curr = abs(results[j][i]);
- else
- curr = abs(miniq[j][i / 2] - code * 8);
-
- if (curr < mind) {
- mind = curr;
- minvcm = j;
- }
-
- if (results[j][i] < minpoll)
- minpoll = results[j][i];
- }
- results_min[i] = minpoll;
- vcm_final[i] = minvcm;
- }
-
- if (type != 1)
- 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) ? 1 : 0;
-
- 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, 2);
- break;
- case 4:
- b43_nphy_rssi_select(dev, 1, 0);
- break;
- case 2:
- b43_nphy_rssi_select(dev, 1, 1);
- break;
- default:
- b43_nphy_rssi_select(dev, 1, 1);
- break;
- }
-
- switch (state[3]) {
- case 1:
- b43_nphy_rssi_select(dev, 2, 2);
- break;
- case 4:
- b43_nphy_rssi_select(dev, 2, 0);
- break;
- default:
- b43_nphy_rssi_select(dev, 2, 1);
- break;
- }
-
- b43_nphy_rssi_select(dev, 0, type);
-
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs_save_phy[0]);
- b43_radio_write16(dev, B2055_C1_PD_RXTX, regs_save_radio[0]);
- b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs_save_phy[1]);
- b43_radio_write16(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);
-}
-
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */
-static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
-{
- /* TODO */
-}
-
-/*
- * 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 >= 3) {
- b43_nphy_rev3_rssi_cal(dev);
- } else {
- b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Z);
- b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_X);
- b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Y);
- }
-}
-
/*
* Restore RSSI Calibration
* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal
@@ -2400,9 +4124,13 @@ static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev)
rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
}
- /* TODO use some definitions */
- b43_radio_maskset(dev, 0x602B, 0xE3, rssical_radio_regs[0]);
- b43_radio_maskset(dev, 0x702B, 0xE3, rssical_radio_regs[1]);
+ if (dev->phy.rev >= 7) {
+ } 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]);
@@ -2420,24 +4148,6 @@ static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev)
b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]);
}
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetIpaGainTbl */
-static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev)
-{
- if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
- if (dev->phy.rev >= 6) {
- /* TODO If the chip is 47162
- return txpwrctrl_tx_gain_ipa_rev5 */
- return txpwrctrl_tx_gain_ipa_rev6;
- } else if (dev->phy.rev >= 5) {
- return txpwrctrl_tx_gain_ipa_rev5;
- } else {
- return txpwrctrl_tx_gain_ipa;
- }
- } else {
- return txpwrctrl_tx_gain_ipa_5g;
- }
-}
-
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */
static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev)
{
@@ -2451,75 +4161,75 @@ static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev)
tmp = (i == 0) ? 0x2000 : 0x3000;
offset = i * 11;
- save[offset + 0] = b43_radio_read16(dev, B2055_CAL_RVARCTL);
- save[offset + 1] = b43_radio_read16(dev, B2055_CAL_LPOCTL);
- save[offset + 2] = b43_radio_read16(dev, B2055_CAL_TS);
- save[offset + 3] = b43_radio_read16(dev, B2055_CAL_RCCALRTS);
- save[offset + 4] = b43_radio_read16(dev, B2055_CAL_RCALRTS);
- save[offset + 5] = b43_radio_read16(dev, B2055_PADDRV);
- save[offset + 6] = b43_radio_read16(dev, B2055_XOCTL1);
- save[offset + 7] = b43_radio_read16(dev, B2055_XOCTL2);
- save[offset + 8] = b43_radio_read16(dev, B2055_XOREGUL);
- save[offset + 9] = b43_radio_read16(dev, B2055_XOMISC);
- save[offset + 10] = b43_radio_read16(dev, B2055_PLL_LFC1);
+ 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) == IEEE80211_BAND_5GHZ) {
- b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x0A);
- b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40);
- b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55);
- b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0);
- b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0);
+ 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_write16(dev, tmp | B2055_PADDRV, 4);
- b43_radio_write16(dev, tmp | B2055_XOCTL1, 1);
+ b43_radio_write(dev, tmp | B2055_PADDRV, 4);
+ b43_radio_write(dev, tmp | B2055_XOCTL1, 1);
} else {
- b43_radio_write16(dev, tmp | B2055_PADDRV, 0);
- b43_radio_write16(dev, tmp | B2055_XOCTL1, 0x2F);
+ b43_radio_write(dev, tmp | B2055_PADDRV, 0);
+ b43_radio_write(dev, tmp | B2055_XOCTL1, 0x2F);
}
- b43_radio_write16(dev, tmp | B2055_XOCTL2, 0);
+ b43_radio_write(dev, tmp | B2055_XOCTL2, 0);
} else {
- b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x06);
- b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40);
- b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55);
- b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0);
- b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0);
- b43_radio_write16(dev, tmp | B2055_XOCTL1, 0);
+ 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_write16(dev, tmp | B2055_PADDRV, 6);
- b43_radio_write16(dev, tmp | B2055_XOCTL2,
+ b43_radio_write(dev, tmp | B2055_PADDRV, 6);
+ b43_radio_write(dev, tmp | B2055_XOCTL2,
(dev->phy.rev < 5) ? 0x11 : 0x01);
} else {
- b43_radio_write16(dev, tmp | B2055_PADDRV, 0);
- b43_radio_write16(dev, tmp | B2055_XOCTL2, 0);
+ b43_radio_write(dev, tmp | B2055_PADDRV, 0);
+ b43_radio_write(dev, tmp | B2055_XOCTL2, 0);
}
}
- b43_radio_write16(dev, tmp | B2055_XOREGUL, 0);
- b43_radio_write16(dev, tmp | B2055_XOMISC, 0);
- b43_radio_write16(dev, tmp | B2055_PLL_LFC1, 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_read16(dev, B2055_C1_TX_RF_IQCAL1);
- b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL1, 0x29);
+ 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_read16(dev, B2055_C1_TX_RF_IQCAL2);
- b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL2, 0x54);
+ 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_read16(dev, B2055_C2_TX_RF_IQCAL1);
- b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL1, 0x29);
+ 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_read16(dev, B2055_C2_TX_RF_IQCAL2);
- b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL2, 0x54);
+ 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_read16(dev, B2055_C1_PWRDET_RXTX);
- save[4] = b43_radio_read16(dev, B2055_C2_PWRDET_RXTX);
+ 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_write16(dev, B2055_C1_PWRDET_RXTX, 0x04);
- b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x04);
+ b43_radio_write(dev, B2055_C1_PWRDET_RXTX, 0x04);
+ b43_radio_write(dev, B2055_C2_PWRDET_RXTX, 0x04);
} else {
- b43_radio_write16(dev, B2055_C1_PWRDET_RXTX, 0x20);
- b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x20);
+ b43_radio_write(dev, B2055_C1_PWRDET_RXTX, 0x20);
+ b43_radio_write(dev, B2055_C2_PWRDET_RXTX, 0x20);
}
if (dev->phy.rev < 2) {
@@ -2532,44 +4242,6 @@ static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev)
}
}
-/* 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)
-{
- int i, j, indx;
- u16 gain;
-
- if (dev->phy.rev >= 3) {
- params->txgm = target.txgm[core];
- params->pga = target.pga[core];
- params->pad = target.pad[core];
- params->ipa = target.ipa[core];
- 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) == IEEE80211_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];
- }
-}
-
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */
static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core)
{
@@ -2672,35 +4344,13 @@ static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev)
B43_NPHY_TXPCTL_STAT_BIDX_SHIFT;
for (i = 0; i < 2; ++i) {
+ table = b43_nphy_get_tx_gain_table(dev);
if (dev->phy.rev >= 3) {
- enum ieee80211_band band =
- b43_current_band(dev->wl);
-
- if ((nphy->ipa2g_on &&
- band == IEEE80211_BAND_2GHZ) ||
- (nphy->ipa5g_on &&
- band == IEEE80211_BAND_5GHZ)) {
- table = b43_nphy_get_ipa_gain_table(dev);
- } else {
- if (band == IEEE80211_BAND_5GHZ) {
- if (dev->phy.rev == 3)
- table = b43_ntab_tx_gain_rev3_5ghz;
- else if (dev->phy.rev == 4)
- table = b43_ntab_tx_gain_rev4_5ghz;
- else
- table = b43_ntab_tx_gain_rev5plus_5ghz;
- } else {
- table = b43_ntab_tx_gain_rev3plus_2ghz;
- }
- }
-
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 {
- table = b43_ntab_tx_gain_rev0_1_2;
-
target.ipa[i] = (table[index[i]] >> 16) & 0x3;
target.pad[i] = (table[index[i]] >> 18) & 0x3;
target.pga[i] = (table[index[i]] >> 20) & 0x7;
@@ -2775,9 +4425,9 @@ static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev)
regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
- b43_nphy_rf_control_intc_override(dev, 2, 1, 3);
- b43_nphy_rf_control_intc_override(dev, 1, 2, 1);
- b43_nphy_rf_control_intc_override(dev, 1, 8, 2);
+ b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA, 1, 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);
@@ -2937,7 +4587,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
int freq;
bool avoid = false;
u8 length;
- u16 tmp, core, type, count, max, numb, last, cmd;
+ u16 tmp, core, type, count, max, numb, last = 0, cmd;
const u16 *table;
bool phy6or5x;
@@ -2952,7 +4602,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
if (dev->phy.rev >= 4) {
avoid = nphy->hang_avoid;
- nphy->hang_avoid = 0;
+ nphy->hang_avoid = false;
}
b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, save);
@@ -3062,7 +4712,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
if (phy6or5x && updated[core] == 0) {
b43_nphy_update_tx_cal_ladder(dev, core);
- updated[core] = 1;
+ updated[core] = true;
}
tmp = (params[core].ncorr[type] << 8) | 0x66;
@@ -3310,7 +4960,7 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,
tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) |
(cur_lna << 2));
- b43_nphy_rf_control_override(dev, 0x400, tmp[0], 3,
+ 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);
@@ -3359,7 +5009,7 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,
break;
}
- b43_nphy_rf_control_override(dev, 0x400, 0, 3, true);
+ 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);
@@ -3384,17 +5034,6 @@ static int b43_nphy_cal_rx_iq(struct b43_wldev *dev,
return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug);
}
-/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */
-static void b43_nphy_mac_phy_clock_set(struct b43_wldev *dev, bool on)
-{
- u32 tmslow = ssb_read32(dev->dev, SSB_TMSLOW);
- if (on)
- tmslow |= B43_TMSLOW_MACPHYCLKEN;
- else
- tmslow &= ~B43_TMSLOW_MACPHYCLKEN;
- ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
-}
-
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */
static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask)
{
@@ -3435,13 +5074,92 @@ static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask)
b43_mac_enable(dev);
}
-/*
- * Init N-PHY
- * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N
- */
-int b43_phy_initn(struct b43_wldev *dev)
+/**************************************************
+ * 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)
{
- struct ssb_bus *bus = dev->dev->bus;
+ 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;
@@ -3454,9 +5172,22 @@ int b43_phy_initn(struct b43_wldev *dev)
bool do_cal = false;
if ((dev->phy.rev >= 3) &&
- (bus->sprom.boardflags_lo & B43_BFL_EXTLNA) &&
+ (sprom->boardflags_lo & B43_BFL_EXTLNA) &&
(b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) {
- chipco_set32(&dev->dev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ bcma_cc_set32(&dev->dev->bdev->bus->drv_cc,
+ BCMA_CC_CHIPCTL, 0x40);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ chipco_set32(&dev->dev->sdev->bus->chipco,
+ SSB_CHIPCO_CHIPCTL, 0x40);
+ break;
+#endif
+ }
}
nphy->deaf_count = 0;
b43_nphy_tables_init(dev);
@@ -3494,9 +5225,9 @@ int b43_phy_initn(struct b43_wldev *dev)
b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20);
b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20);
- if (bus->sprom.boardflags2_lo & 0x100 ||
- (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
- bus->boardinfo.type == 0x8B))
+ 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);
@@ -3513,8 +5244,7 @@ int b43_phy_initn(struct b43_wldev *dev)
}
tmp2 = b43_current_band(dev->wl);
- if ((nphy->ipa2g_on && tmp2 == IEEE80211_BAND_2GHZ) ||
- (nphy->ipa5g_on && tmp2 == IEEE80211_BAND_5GHZ)) {
+ 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);
@@ -3529,13 +5259,13 @@ int b43_phy_initn(struct b43_wldev *dev)
b43_nphy_workarounds(dev);
/* Reset CCA, in init code it differs a little from standard way */
- b43_nphy_bmac_clock_fgc(dev, 1);
+ 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_nphy_bmac_clock_fgc(dev, 0);
+ b43_phy_force_clock(dev, 0);
- b43_nphy_mac_phy_clock_set(dev, true);
+ b43_mac_phy_clock_set(dev, true);
b43_nphy_pa_override(dev, false);
b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
@@ -3550,17 +5280,9 @@ int b43_phy_initn(struct b43_wldev *dev)
tx_pwr_state = nphy->txpwrctrl;
b43_nphy_tx_power_ctrl(dev, false);
b43_nphy_tx_power_fix(dev);
- /* TODO N PHY TX Power Control Idle TSSI */
- /* TODO N PHY TX Power Control Setup */
-
- if (phy->rev >= 3) {
- /* TODO */
- } else {
- b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128,
- b43_ntab_tx_gain_rev0_1_2);
- b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128,
- b43_ntab_tx_gain_rev0_1_2);
- }
+ 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);
@@ -3621,7 +5343,7 @@ int b43_phy_initn(struct b43_wldev *dev)
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, 0x0014);
+ b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x0032);
b43_nphy_tx_lp_fbw(dev);
if (phy->rev >= 3)
b43_nphy_spur_workaround(dev);
@@ -3629,6 +5351,40 @@ int b43_phy_initn(struct b43_wldev *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,
@@ -3636,24 +5392,25 @@ static void b43_nphy_channel_setup(struct b43_wldev *dev,
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = dev->phy.n;
+ int ch = new_channel->hw_value;
u16 old_band_5ghz;
- u32 tmp32;
+ u16 tmp16;
old_band_5ghz =
b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ;
if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) {
- tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR);
- b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4);
+ tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR);
+ b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4);
b43_phy_set(dev, B43_PHY_B_BBCFG, 0xC000);
- b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32);
+ 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 == IEEE80211_BAND_2GHZ && old_band_5ghz) {
b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
- tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR);
- b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4);
+ tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR);
+ b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4);
b43_phy_mask(dev, B43_PHY_B_BBCFG, 0x3FFF);
- b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32);
+ b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16);
}
b43_chantab_phy_upload(dev, e);
@@ -3675,8 +5432,41 @@ static void b43_nphy_channel_setup(struct b43_wldev *dev,
b43_nphy_tx_lp_fbw(dev);
- if (dev->phy.rev >= 3 && 0) {
- /* TODO */
+ if (dev->phy.rev >= 3 &&
+ dev->phy.n->spur_avoid != B43_SPUR_AVOID_DISABLE) {
+ bool avoid = false;
+ if (dev->phy.n->spur_avoid == B43_SPUR_AVOID_FORCE) {
+ avoid = true;
+ } else if (!b43_channel_type_is_40mhz(phy->channel_type)) {
+ if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14)
+ avoid = true;
+ } else { /* 40MHz */
+ if (nphy->aband_spurwar_en &&
+ (ch == 38 || ch == 102 || ch == 118))
+ avoid = dev->dev->chip_id == 0x4716;
+ }
+
+ b43_nphy_pmu_spur_avoid(dev, avoid);
+
+ if (dev->dev->chip_id == 43222 || dev->dev->chip_id == 43224 ||
+ dev->dev->chip_id == 43225) {
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW,
+ avoid ? 0x5341 : 0x8889);
+ b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
+ }
+
+ if (dev->phy.rev == 3 || dev->phy.rev == 4)
+ ; /* TODO: reset PLL */
+
+ if (avoid)
+ 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);
@@ -3692,8 +5482,8 @@ static int b43_nphy_set_channel(struct b43_wldev *dev,
{
struct b43_phy *phy = &dev->phy;
- const struct b43_nphy_channeltab_entry_rev2 *tabent_r2;
- const struct b43_nphy_channeltab_entry_rev3 *tabent_r3;
+ const struct b43_nphy_channeltab_entry_rev2 *tabent_r2 = NULL;
+ const struct b43_nphy_channeltab_entry_rev3 *tabent_r3 = NULL;
u8 tmp;
@@ -3740,6 +5530,10 @@ static int b43_nphy_set_channel(struct b43_wldev *dev,
return 0;
}
+/**************************************************
+ * Basic PHY ops.
+ **************************************************/
+
static int b43_nphy_op_allocate(struct b43_wldev *dev)
{
struct b43_phy_n *nphy;
@@ -3756,14 +5550,53 @@ 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)
@@ -3817,16 +5650,18 @@ static void b43_nphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
{
check_phyreg(dev, reg);
b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
- b43_write16(dev, B43_MMIO_PHY_DATA,
- (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
+ b43_maskset16(dev, B43_MMIO_PHY_DATA, mask, set);
}
static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg)
{
/* Register 1 is a 32-bit register. */
B43_WARN_ON(reg == 1);
- /* N-PHY needs 0x100 for read access */
- reg |= 0x100;
+
+ if (dev->phy.rev >= 7)
+ reg |= 0x200; /* Radio 0x2057 */
+ else
+ reg |= 0x100;
b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
@@ -3851,7 +5686,9 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
if (blocked) {
b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
~B43_NPHY_RFCTL_CMD_CHIP0PU);
- if (dev->phy.rev >= 3) {
+ if (dev->phy.rev >= 7) {
+ /* TODO */
+ } else if (dev->phy.rev >= 3) {
b43_radio_mask(dev, 0x09, ~0x2);
b43_radio_write(dev, 0x204D, 0);
@@ -3869,8 +5706,13 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
b43_radio_write(dev, 0x3064, 0);
}
} else {
- if (dev->phy.rev >= 3) {
- b43_radio_init2056(dev);
+ if (dev->phy.rev >= 7) {
+ if (!dev->phy.radio_on)
+ b43_radio_2057_init(dev);
+ b43_switch_channel(dev, dev->phy.channel);
+ } else if (dev->phy.rev >= 3) {
+ if (!dev->phy.radio_on)
+ b43_radio_init2056(dev);
b43_switch_channel(dev, dev->phy.channel);
} else {
b43_radio_init2055(dev);
@@ -3878,17 +5720,35 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
}
}
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */
static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
{
- b43_phy_write(dev, B43_NPHY_AFECTL_OVER,
- on ? 0 : 0x7FFF);
+ u16 override = on ? 0x0 : 0x7FFF;
+ u16 core = on ? 0xD : 0x00FD;
+
+ if (dev->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.channel;
- enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type;
+ 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) == IEEE80211_BAND_2GHZ) {
if ((new_channel < 1) || (new_channel > 14))
diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h
index 001e841f118..ecfbf66dbc3 100644
--- a/drivers/net/wireless/b43/phy_n.h
+++ b/drivers/net/wireless/b43/phy_n.h
@@ -54,10 +54,15 @@
#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 */
@@ -107,10 +112,15 @@
#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 */
@@ -703,19 +713,161 @@
#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 controll init */
+#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_PHY_B_BBCFG B43_PHY_N_BMODE(0x001) /* BB config */
#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;
@@ -759,11 +911,18 @@ struct b43_phy_n_txpwrindex {
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;
@@ -783,10 +942,15 @@ struct b43_phy_n {
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;
u8 txrx_chain;
@@ -799,6 +963,7 @@ struct b43_phy_n {
u16 classifier_state;
u16 clip_state[2];
+ enum b43_nphy_spur_avoid spur_avoid;
bool aband_spurwar_en;
bool gband_spurwar_en;
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index aa12273ae71..a4ff5e2a42b 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -4,7 +4,7 @@
PIO data transfer
- Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de>
+ 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
@@ -111,7 +111,7 @@ static u16 index_to_pioqueue_base(struct b43_wldev *dev,
B43_MMIO_PIO11_BASE5,
};
- if (dev->dev->id.revision >= 11) {
+ if (dev->dev->core_rev >= 11) {
B43_WARN_ON(index >= ARRAY_SIZE(bases_rev11));
return bases_rev11[index];
}
@@ -121,14 +121,14 @@ static u16 index_to_pioqueue_base(struct b43_wldev *dev,
static u16 pio_txqueue_offset(struct b43_wldev *dev)
{
- if (dev->dev->id.revision >= 11)
+ if (dev->dev->core_rev >= 11)
return 0x18;
return 0;
}
static u16 pio_rxqueue_offset(struct b43_wldev *dev)
{
- if (dev->dev->id.revision >= 11)
+ if (dev->dev->core_rev >= 11)
return 0x38;
return 8;
}
@@ -144,7 +144,7 @@ static struct b43_pio_txqueue *b43_setup_pioqueue_tx(struct b43_wldev *dev,
if (!q)
return NULL;
q->dev = dev;
- q->rev = dev->dev->id.revision;
+ q->rev = dev->dev->core_rev;
q->mmio_base = index_to_pioqueue_base(dev, index) +
pio_txqueue_offset(dev);
q->index = index;
@@ -178,7 +178,7 @@ static struct b43_pio_rxqueue *b43_setup_pioqueue_rx(struct b43_wldev *dev,
if (!q)
return NULL;
q->dev = dev;
- q->rev = dev->dev->id.revision;
+ q->rev = dev->dev->core_rev;
q->mmio_base = index_to_pioqueue_base(dev, index) +
pio_rxqueue_offset(dev);
@@ -196,7 +196,7 @@ static void b43_pio_cancel_tx_packets(struct b43_pio_txqueue *q)
for (i = 0; i < ARRAY_SIZE(q->packets); i++) {
pack = &(q->packets[i]);
if (pack->skb) {
- dev_kfree_skb_any(pack->skb);
+ ieee80211_free_txskb(q->dev->wl->hw, pack->skb);
pack->skb = NULL;
}
}
@@ -339,7 +339,7 @@ static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI;
b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
- ssb_block_write(dev->dev, data, (data_len & ~1),
+ b43_block_write(dev, data, (data_len & ~1),
q->mmio_base + B43_PIO_TXDATA,
sizeof(u16));
if (data_len & 1) {
@@ -351,7 +351,7 @@ static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
tail[0] = data[data_len - 1];
tail[1] = 0;
- ssb_block_write(dev->dev, tail, 2,
+ b43_block_write(dev, tail, 2,
q->mmio_base + B43_PIO_TXDATA,
sizeof(u16));
}
@@ -393,7 +393,7 @@ static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31;
b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
- ssb_block_write(dev->dev, data, (data_len & ~3),
+ b43_block_write(dev, data, (data_len & ~3),
q->mmio_base + B43_PIO8_TXDATA,
sizeof(u32));
if (data_len & 3) {
@@ -421,7 +421,7 @@ static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
break;
}
b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
- ssb_block_write(dev->dev, tail, 4,
+ b43_block_write(dev, tail, 4,
q->mmio_base + B43_PIO8_TXDATA,
sizeof(u32));
}
@@ -539,7 +539,7 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb)
/* Not enough memory on the queue. */
err = -EBUSY;
ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb));
- q->stopped = 1;
+ q->stopped = true;
goto out;
}
@@ -552,7 +552,7 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *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);
+ ieee80211_free_txskb(dev->wl->hw, skb);
err = 0;
goto out;
}
@@ -566,7 +566,7 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb)
(q->free_packet_slots == 0)) {
/* The queue is full. */
ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb));
- q->stopped = 1;
+ q->stopped = true;
}
out:
@@ -601,7 +601,7 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev,
if (q->stopped) {
ieee80211_wake_queue(dev->wl->hw, q->queue_prio);
- q->stopped = 0;
+ q->stopped = false;
}
}
@@ -611,15 +611,25 @@ 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;
+ 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));
- memset(rxhdr, 0, 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) {
@@ -627,7 +637,7 @@ static bool pio_rx_frame(struct b43_pio_rxqueue *q)
ctl = b43_piorx_read32(q, B43_PIO8_RXCTL);
if (!(ctl & B43_PIO8_RXCTL_FRAMERDY))
- return 0;
+ return false;
b43_piorx_write32(q, B43_PIO8_RXCTL,
B43_PIO8_RXCTL_FRAMERDY);
for (i = 0; i < 10; i++) {
@@ -641,7 +651,7 @@ static bool pio_rx_frame(struct b43_pio_rxqueue *q)
ctl = b43_piorx_read16(q, B43_PIO_RXCTL);
if (!(ctl & B43_PIO_RXCTL_FRAMERDY))
- return 0;
+ return false;
b43_piorx_write16(q, B43_PIO_RXCTL,
B43_PIO_RXCTL_FRAMERDY);
for (i = 0; i < 10; i++) {
@@ -652,16 +662,16 @@ static bool pio_rx_frame(struct b43_pio_rxqueue *q)
}
}
b43dbg(q->dev->wl, "PIO RX timed out\n");
- return 1;
+ return true;
data_ready:
/* Get the preamble (RX header) */
if (q->rev >= 8) {
- ssb_block_read(dev->dev, rxhdr, sizeof(*rxhdr),
+ b43_block_read(dev, rxhdr, rxhdr_size,
q->mmio_base + B43_PIO8_RXDATA,
sizeof(u32));
} else {
- ssb_block_read(dev->dev, rxhdr, sizeof(*rxhdr),
+ b43_block_read(dev, rxhdr, rxhdr_size,
q->mmio_base + B43_PIO_RXDATA,
sizeof(u16));
}
@@ -676,7 +686,15 @@ data_ready:
goto rx_error;
}
- macstat = le32_to_cpu(rxhdr->mac_status);
+ 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. */
@@ -697,7 +715,7 @@ data_ready:
skb_reserve(skb, 2);
skb_put(skb, len + padding);
if (q->rev >= 8) {
- ssb_block_read(dev->dev, skb->data + padding, (len & ~3),
+ b43_block_read(dev, skb->data + padding, (len & ~3),
q->mmio_base + B43_PIO8_RXDATA,
sizeof(u32));
if (len & 3) {
@@ -705,7 +723,7 @@ data_ready:
BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4);
/* Read the last few bytes. */
- ssb_block_read(dev->dev, tail, 4,
+ b43_block_read(dev, tail, 4,
q->mmio_base + B43_PIO8_RXDATA,
sizeof(u32));
switch (len & 3) {
@@ -724,7 +742,7 @@ data_ready:
}
}
} else {
- ssb_block_read(dev->dev, skb->data + padding, (len & ~1),
+ b43_block_read(dev, skb->data + padding, (len & ~1),
q->mmio_base + B43_PIO_RXDATA,
sizeof(u16));
if (len & 1) {
@@ -732,7 +750,7 @@ data_ready:
BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2);
/* Read the last byte. */
- ssb_block_read(dev->dev, tail, 2,
+ b43_block_read(dev, tail, 2,
q->mmio_base + B43_PIO_RXDATA,
sizeof(u16));
skb->data[len + padding - 1] = tail[0];
@@ -741,7 +759,7 @@ data_ready:
b43_rx(q->dev, skb, rxhdr);
- return 1;
+ return true;
rx_error:
if (err_msg)
@@ -751,7 +769,7 @@ rx_error:
else
b43_piorx_write16(q, B43_PIO_RXCTL, B43_PIO_RXCTL_DATARDY);
- return 1;
+ return true;
}
void b43_pio_rx(struct b43_pio_rxqueue *q)
diff --git a/drivers/net/wireless/b43/radio_2055.c b/drivers/net/wireless/b43/radio_2055.c
index 44c6dea6688..5289a18ddd8 100644
--- a/drivers/net/wireless/b43/radio_2055.c
+++ b/drivers/net/wireless/b43/radio_2055.c
@@ -3,7 +3,8 @@
Broadcom B43 wireless driver
IEEE 802.11n PHY and radio device data tables
- Copyright (c) 2008 Michael Buesch <mb@bu3sch.de>
+ 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
diff --git a/drivers/net/wireless/b43/radio_2055.h b/drivers/net/wireless/b43/radio_2055.h
index d9bfa0f21b7..67f96122f8d 100644
--- a/drivers/net/wireless/b43/radio_2055.h
+++ b/drivers/net/wireless/b43/radio_2055.h
@@ -251,4 +251,9 @@ struct b43_nphy_channeltab_entry_rev2 {
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/b43/radio_2056.c b/drivers/net/wireless/b43/radio_2056.c
index 8890df06702..2ce25607c60 100644
--- a/drivers/net/wireless/b43/radio_2056.c
+++ b/drivers/net/wireless/b43/radio_2056.c
@@ -3,6 +3,8 @@
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
@@ -46,7 +48,7 @@ struct b2056_inittabs_pts {
unsigned int rx_length;
};
-static const struct b2056_inittab_entry b2056_inittab_rev3_syn[] = {
+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, },
@@ -230,7 +232,7 @@ static const struct b2056_inittab_entry b2056_inittab_rev3_syn[] = {
[B2056_SYN_LOGEN_TX_CMOS_VALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
};
-static const struct b2056_inittab_entry b2056_inittab_rev3_tx[] = {
+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, },
@@ -378,7 +380,7 @@ static const struct b2056_inittab_entry b2056_inittab_rev3_tx[] = {
[B2056_TX_STATUS_TXLPF_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
};
-static const struct b2056_inittab_entry b2056_inittab_rev3_rx[] = {
+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, },
@@ -528,7 +530,7 @@ static const struct b2056_inittab_entry b2056_inittab_rev3_rx[] = {
[B2056_RX_STATUS_HPC_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
};
-static const struct b2056_inittab_entry b2056_inittab_rev4_syn[] = {
+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, },
@@ -712,7 +714,7 @@ static const struct b2056_inittab_entry b2056_inittab_rev4_syn[] = {
[B2056_SYN_LOGEN_TX_CMOS_VALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
};
-static const struct b2056_inittab_entry b2056_inittab_rev4_tx[] = {
+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, },
@@ -860,7 +862,7 @@ static const struct b2056_inittab_entry b2056_inittab_rev4_tx[] = {
[B2056_TX_STATUS_TXLPF_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
};
-static const struct b2056_inittab_entry b2056_inittab_rev4_rx[] = {
+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, },
@@ -1010,7 +1012,7 @@ static const struct b2056_inittab_entry b2056_inittab_rev4_rx[] = {
[B2056_RX_STATUS_HPC_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
};
-static const struct b2056_inittab_entry b2056_inittab_rev5_syn[] = {
+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, },
@@ -1194,7 +1196,7 @@ static const struct b2056_inittab_entry b2056_inittab_rev5_syn[] = {
[B2056_SYN_LOGEN_TX_CMOS_VALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
};
-static const struct b2056_inittab_entry b2056_inittab_rev5_tx[] = {
+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, },
@@ -1350,7 +1352,7 @@ static const struct b2056_inittab_entry b2056_inittab_rev5_tx[] = {
[B2056_TX_GMBB_IDAC7] = { .ghz5 = 0x0075, .ghz2 = 0x0075, UPLOAD, },
};
-static const struct b2056_inittab_entry b2056_inittab_rev5_rx[] = {
+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, },
@@ -1500,7 +1502,7 @@ static const struct b2056_inittab_entry b2056_inittab_rev5_rx[] = {
[B2056_RX_STATUS_HPC_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
};
-static const struct b2056_inittab_entry b2056_inittab_rev6_syn[] = {
+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, },
@@ -1570,14 +1572,14 @@ static const struct b2056_inittab_entry b2056_inittab_rev6_syn[] = {
[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_PFD] = { .ghz5 = 0x0006, .ghz2 = 0x0006, UPLOAD, },
[B2056_SYN_PLL_CP1] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
- [B2056_SYN_PLL_CP2] = { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
+ [B2056_SYN_PLL_CP2] = { .ghz5 = 0x003f, .ghz2 = 0x003f, UPLOAD, },
[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_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 = 0x0006, .ghz2 = 0x0006, 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, },
@@ -1684,7 +1686,7 @@ static const struct b2056_inittab_entry b2056_inittab_rev6_syn[] = {
[B2056_SYN_LOGEN_TX_CMOS_VALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
};
-static const struct b2056_inittab_entry b2056_inittab_rev6_tx[] = {
+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, },
@@ -1840,7 +1842,7 @@ static const struct b2056_inittab_entry b2056_inittab_rev6_tx[] = {
[B2056_TX_GMBB_IDAC7] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
};
-static const struct b2056_inittab_entry b2056_inittab_rev6_rx[] = {
+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, },
@@ -1990,7 +1992,7 @@ static const struct b2056_inittab_entry b2056_inittab_rev6_rx[] = {
[B2056_RX_STATUS_HPC_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
};
-static const struct b2056_inittab_entry b2056_inittab_rev7_syn[] = {
+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, },
@@ -2174,7 +2176,7 @@ static const struct b2056_inittab_entry b2056_inittab_rev7_syn[] = {
[B2056_SYN_LOGEN_TX_CMOS_VALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
};
-static const struct b2056_inittab_entry b2056_inittab_rev7_tx[] = {
+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, },
@@ -2330,7 +2332,7 @@ static const struct b2056_inittab_entry b2056_inittab_rev7_tx[] = {
[B2056_TX_GMBB_IDAC7] = { .ghz5 = 0x0075, .ghz2 = 0x0075, UPLOAD, },
};
-static const struct b2056_inittab_entry b2056_inittab_rev7_rx[] = {
+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, },
@@ -2480,7 +2482,7 @@ static const struct b2056_inittab_entry b2056_inittab_rev7_rx[] = {
[B2056_RX_STATUS_HPC_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
};
-static const struct b2056_inittab_entry b2056_inittab_rev8_syn[] = {
+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, },
@@ -2664,7 +2666,7 @@ static const struct b2056_inittab_entry b2056_inittab_rev8_syn[] = {
[B2056_SYN_LOGEN_TX_CMOS_VALID] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
};
-static const struct b2056_inittab_entry b2056_inittab_rev8_tx[] = {
+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, },
@@ -2820,7 +2822,7 @@ static const struct b2056_inittab_entry b2056_inittab_rev8_tx[] = {
[B2056_TX_GMBB_IDAC7] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
};
-static const struct b2056_inittab_entry b2056_inittab_rev8_rx[] = {
+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, },
@@ -2970,24 +2972,69 @@ static const struct b2056_inittab_entry b2056_inittab_rev8_rx[] = {
[B2056_RX_STATUS_HPC_RC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
};
-#define INITTABSPTS(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)
+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, },
+};
-struct b2056_inittabs_pts b2056_inittabs[] = {
- [3] = { INITTABSPTS(b2056_inittab_rev3) },
- [4] = { INITTABSPTS(b2056_inittab_rev4) },
- [5] = { INITTABSPTS(b2056_inittab_rev5) },
- [6] = { INITTABSPTS(b2056_inittab_rev6) },
- [7] = { INITTABSPTS(b2056_inittab_rev7) },
- [8] = { INITTABSPTS(b2056_inittab_rev8) },
- [9] = { INITTABSPTS(b2056_inittab_rev7) },
+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, \
@@ -3039,7 +3086,7 @@ struct b2056_inittabs_pts b2056_inittabs[] = {
.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_rev3[] = {
+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,
@@ -4034,7 +4081,7 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev3[] =
},
};
-static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev4[] = {
+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,
@@ -5029,7 +5076,7 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev4[] =
},
};
-static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev5[] = {
+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,
@@ -6024,7 +6071,7 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev5[] =
},
};
-static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev6[] = {
+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,
@@ -7019,7 +7066,7 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev6[] =
},
};
-static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev7_9[] = {
+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,
@@ -8014,7 +8061,7 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev7_9[]
},
};
-static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev8[] = {
+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,
@@ -9009,6 +9056,1154 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev8[] =
},
};
+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,
@@ -9033,13 +10228,13 @@ static void b2056_upload_inittab(struct b43_wldev *dev, bool ghz5,
void b2056_upload_inittabs(struct b43_wldev *dev,
bool ghz5, bool ignore_uploadflag)
{
- struct b2056_inittabs_pts *pts;
+ const struct b2056_inittabs_pts *pts;
- if (dev->phy.rev >= ARRAY_SIZE(b2056_inittabs)) {
+ pts = b43_nphy_get_inittabs_rev3(dev);
+ if (!pts) {
B43_WARN_ON(1);
return;
}
- pts = &b2056_inittabs[dev->phy.rev];
b2056_upload_inittab(dev, ghz5, ignore_uploadflag,
B2056_SYN, pts->syn, pts->syn_length);
@@ -9053,41 +10248,65 @@ void b2056_upload_inittabs(struct b43_wldev *dev,
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 (dev->phy.rev) {
+ switch (phy->rev) {
case 3:
- e = b43_nphy_channeltab_rev3;
- length = ARRAY_SIZE(b43_nphy_channeltab_rev3);
+ e = b43_nphy_channeltab_phy_rev3;
+ length = ARRAY_SIZE(b43_nphy_channeltab_phy_rev3);
break;
case 4:
- e = b43_nphy_channeltab_rev4;
- length = ARRAY_SIZE(b43_nphy_channeltab_rev4);
- break;
- case 5:
- e = b43_nphy_channeltab_rev5;
- length = ARRAY_SIZE(b43_nphy_channeltab_rev5);
- break;
- case 6:
- e = b43_nphy_channeltab_rev6;
- length = ARRAY_SIZE(b43_nphy_channeltab_rev6);
- break;
- case 7:
- case 9:
- e = b43_nphy_channeltab_rev7_9;
- length = ARRAY_SIZE(b43_nphy_channeltab_rev7_9);
- break;
- case 8:
- e = b43_nphy_channeltab_rev8;
- length = ARRAY_SIZE(b43_nphy_channeltab_rev8);
+ e = b43_nphy_channeltab_phy_rev4;
+ length = ARRAY_SIZE(b43_nphy_channeltab_phy_rev4);
break;
default:
- B43_WARN_ON(1);
- return NULL;
+ 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++) {
diff --git a/drivers/net/wireless/b43/radio_2056.h b/drivers/net/wireless/b43/radio_2056.h
index d601f6e7e31..5b86673459f 100644
--- a/drivers/net/wireless/b43/radio_2056.h
+++ b/drivers/net/wireless/b43/radio_2056.h
@@ -1,29 +1,3 @@
-/*
-
- Broadcom B43 wireless driver
-
- Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
-
- Some parts of the code in this file are derived from the brcm80211
- driver Copyright (c) 2010 Broadcom 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_RADIO_2056_H_
#define B43_RADIO_2056_H_
@@ -1116,5 +1090,11 @@ struct b43_nphy_channeltab_entry_rev3 {
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/b43/radio_2057.c b/drivers/net/wireless/b43/radio_2057.c
new file mode 100644
index 00000000000..d61d6830c5c
--- /dev/null
+++ b/drivers/net/wireless/b43/radio_2057.c
@@ -0,0 +1,141 @@
+/*
+
+ 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[42][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[44][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[45][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[54][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 },
+};
+
+static u16 r2057_rev8_init[54][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 },
+};
+
+void r2057_upload_inittabs(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ u16 *table = NULL;
+ u16 size, i;
+
+ if (phy->rev == 7) {
+ table = r2057_rev4_init[0];
+ size = ARRAY_SIZE(r2057_rev4_init);
+ } else if (phy->rev == 8 || phy->rev == 9) {
+ if (phy->radio_rev == 5) {
+ if (phy->radio_rev == 8) {
+ table = r2057_rev5_init[0];
+ size = ARRAY_SIZE(r2057_rev5_init);
+ } else {
+ table = r2057_rev5a_init[0];
+ size = ARRAY_SIZE(r2057_rev5a_init);
+ }
+ } else if (phy->radio_rev == 7) {
+ table = r2057_rev7_init[0];
+ size = ARRAY_SIZE(r2057_rev7_init);
+ } else if (phy->radio_rev == 9) {
+ table = r2057_rev8_init[0];
+ size = ARRAY_SIZE(r2057_rev8_init);
+ }
+ }
+
+ if (table) {
+ for (i = 0; i < 10; i++) {
+ pr_info("radio_write 0x%X ", *table);
+ table++;
+ pr_info("0x%X\n", *table);
+ table++;
+ }
+ }
+}
diff --git a/drivers/net/wireless/b43/radio_2057.h b/drivers/net/wireless/b43/radio_2057.h
new file mode 100644
index 00000000000..eeebd8fbeb0
--- /dev/null
+++ b/drivers/net/wireless/b43/radio_2057.h
@@ -0,0 +1,430 @@
+#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
+#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
+#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
+#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
+#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
+
+void r2057_upload_inittabs(struct b43_wldev *dev);
+
+#endif /* B43_RADIO_2057_H_ */
diff --git a/drivers/net/wireless/b43/radio_2059.c b/drivers/net/wireless/b43/radio_2059.c
new file mode 100644
index 00000000000..38e31d857e3
--- /dev/null
+++ b/drivers/net/wireless/b43/radio_2059.c
@@ -0,0 +1,155 @@
+/*
+
+ 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"
+
+#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
+
+static const struct b43_phy_ht_channeltab_e_radio2059 b43_phy_ht_channeltab_radio2059[] = {
+ { .freq = 2412,
+ RADIOREGS(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
+ 0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
+ },
+ { .freq = 2417,
+ RADIOREGS(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
+ 0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
+ },
+ { .freq = 2422,
+ RADIOREGS(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
+ 0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
+ },
+ { .freq = 2427,
+ RADIOREGS(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
+ 0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
+ },
+ { .freq = 2432,
+ RADIOREGS(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
+ 0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
+ },
+ { .freq = 2437,
+ RADIOREGS(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
+ 0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
+ },
+ { .freq = 2442,
+ RADIOREGS(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
+ 0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
+ },
+ { .freq = 2447,
+ RADIOREGS(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
+ 0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
+ },
+ { .freq = 2452,
+ RADIOREGS(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
+ 0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
+ },
+ { .freq = 2457,
+ RADIOREGS(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
+ 0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
+ },
+ { .freq = 2462,
+ RADIOREGS(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
+ 0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x61, 0x03,
+ 0x00, 0x00, 0x00, 0xf0, 0x00),
+ 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),
+ },
+};
+
+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/b43/radio_2059.h b/drivers/net/wireless/b43/radio_2059.h
new file mode 100644
index 00000000000..40a82d7f510
--- /dev/null
+++ b/drivers/net/wireless/b43/radio_2059.h
@@ -0,0 +1,46 @@
+#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
+
+/* 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;
+};
+
+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/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c
index 86bc0a0f735..70c2fcedd1b 100644
--- a/drivers/net/wireless/b43/rfkill.c
+++ b/drivers/net/wireless/b43/rfkill.c
@@ -3,7 +3,7 @@
Broadcom B43 wireless driver
RFKILL support
- Copyright (c) 2007 Michael Buesch <mb@bu3sch.de>
+ 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
@@ -37,17 +37,16 @@ void b43_rfkill_poll(struct ieee80211_hw *hw)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev = wl->current_dev;
- struct ssb_bus *bus = dev->dev->bus;
bool enabled;
bool brought_up = false;
mutex_lock(&wl->mutex);
if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) {
- if (ssb_bus_powerup(bus, 0)) {
+ if (b43_bus_powerup(dev, 0)) {
mutex_unlock(&wl->mutex);
return;
}
- ssb_device_enable(dev->dev, 0);
+ b43_device_enable(dev, 0);
brought_up = true;
}
@@ -63,8 +62,8 @@ void b43_rfkill_poll(struct ieee80211_hw *hw)
}
if (brought_up) {
- ssb_device_disable(dev->dev, 0);
- ssb_bus_may_powerdown(bus);
+ b43_device_disable(dev, 0);
+ b43_bus_may_powerdown(dev);
}
mutex_unlock(&wl->mutex);
diff --git a/drivers/net/wireless/b43/sdio.c b/drivers/net/wireless/b43/sdio.c
index 09e2dfd7b17..59a52180069 100644
--- a/drivers/net/wireless/b43/sdio.c
+++ b/drivers/net/wireless/b43/sdio.c
@@ -4,7 +4,7 @@
* SDIO over Sonics Silicon Backplane bus glue for b43.
*
* Copyright (C) 2009 Albert Herranz
- * Copyright (C) 2009 Michael Buesch <mb@bu3sch.de>
+ * 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
@@ -66,7 +66,7 @@ static void b43_sdio_interrupt_dispatcher(struct sdio_func *func)
int b43_sdio_request_irq(struct b43_wldev *dev,
void (*handler)(struct b43_wldev *dev))
{
- struct ssb_bus *bus = dev->dev->bus;
+ 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;
@@ -82,7 +82,7 @@ int b43_sdio_request_irq(struct b43_wldev *dev,
void b43_sdio_free_irq(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->dev->bus;
+ struct ssb_bus *bus = dev->dev->sdev->bus;
struct sdio_func *func = bus->host_sdio;
struct b43_sdio *sdio = sdio_get_drvdata(func);
@@ -94,7 +94,7 @@ void b43_sdio_free_irq(struct b43_wldev *dev)
}
static int b43_sdio_probe(struct sdio_func *func,
- const struct sdio_device_id *id)
+ const struct sdio_device_id *id)
{
struct b43_sdio *sdio;
struct sdio_func_tuple *tuple;
diff --git a/drivers/net/wireless/b43/sdio.h b/drivers/net/wireless/b43/sdio.h
index fb633094403..1e93926f388 100644
--- a/drivers/net/wireless/b43/sdio.h
+++ b/drivers/net/wireless/b43/sdio.h
@@ -25,12 +25,12 @@ void b43_sdio_exit(void);
#else /* CONFIG_B43_SDIO */
-int b43_sdio_request_irq(struct b43_wldev *dev,
+static inline int b43_sdio_request_irq(struct b43_wldev *dev,
void (*handler)(struct b43_wldev *dev))
{
return -ENODEV;
}
-void b43_sdio_free_irq(struct b43_wldev *dev)
+static inline void b43_sdio_free_irq(struct b43_wldev *dev)
{
}
static inline int b43_sdio_init(void)
diff --git a/drivers/net/wireless/b43/sysfs.c b/drivers/net/wireless/b43/sysfs.c
index f1ae4e05a32..3190493bd07 100644
--- a/drivers/net/wireless/b43/sysfs.c
+++ b/drivers/net/wireless/b43/sysfs.c
@@ -4,7 +4,7 @@
SYSFS support routines
- Copyright (c) 2006 Michael Buesch <mb@bu3sch.de>
+ 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
@@ -40,7 +40,7 @@ static int get_integer(const char *buf, size_t count)
if (count == 0)
goto out;
- count = min(count, (size_t) 10);
+ count = min_t(size_t, count, 10);
memcpy(tmp, buf, count);
ret = simple_strtol(tmp, NULL, 10);
out:
diff --git a/drivers/net/wireless/b43/tables.c b/drivers/net/wireless/b43/tables.c
index 1ef9a6463ec..ea288df8aee 100644
--- a/drivers/net/wireless/b43/tables.c
+++ b/drivers/net/wireless/b43/tables.c
@@ -4,7 +4,7 @@
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 <mb@bu3sch.de>
+ 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>
diff --git a/drivers/net/wireless/b43/tables_lpphy.c b/drivers/net/wireless/b43/tables_lpphy.c
index 61027ee84fb..cff187c5616 100644
--- a/drivers/net/wireless/b43/tables_lpphy.c
+++ b/drivers/net/wireless/b43/tables_lpphy.c
@@ -3,7 +3,7 @@
Broadcom B43 wireless driver
IEEE 802.11a/g LP-PHY and radio device data tables
- Copyright (c) 2009 Michael Buesch <mb@bu3sch.de>
+ 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
@@ -2304,7 +2304,6 @@ void lpphy_rev0_1_table_init(struct b43_wldev *dev)
void lpphy_rev2plus_table_init(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->dev->bus;
int i;
B43_WARN_ON(dev->phy.rev < 2);
@@ -2341,7 +2340,7 @@ void lpphy_rev2plus_table_init(struct b43_wldev *dev)
b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0),
ARRAY_SIZE(lpphy_papd_mult_table), lpphy_papd_mult_table);
- if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
+ 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),
@@ -2416,12 +2415,12 @@ void lpphy_write_gain_table_bulk(struct b43_wldev *dev, int offset, int count,
void lpphy_init_tx_gain_table(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->dev->bus;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
switch (dev->phy.rev) {
case 0:
- if ((bus->sprom.boardflags_hi & B43_BFH_NOPA) ||
- (bus->sprom.boardflags_lo & B43_BFL_HGPA))
+ 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) == IEEE80211_BAND_2GHZ)
@@ -2432,8 +2431,8 @@ void lpphy_init_tx_gain_table(struct b43_wldev *dev)
lpphy_rev0_5ghz_tx_gain_table);
break;
case 1:
- if ((bus->sprom.boardflags_hi & B43_BFH_NOPA) ||
- (bus->sprom.boardflags_lo & B43_BFL_HGPA))
+ 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) == IEEE80211_BAND_2GHZ)
@@ -2444,7 +2443,7 @@ void lpphy_init_tx_gain_table(struct b43_wldev *dev)
lpphy_rev1_5ghz_tx_gain_table);
break;
default:
- if (bus->sprom.boardflags_hi & B43_BFH_NOPA)
+ 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) == IEEE80211_BAND_2GHZ)
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c
index dc8ef09a855..4047c05e380 100644
--- a/drivers/net/wireless/b43/tables_nphy.c
+++ b/drivers/net/wireless/b43/tables_nphy.c
@@ -3,7 +3,8 @@
Broadcom B43 wireless driver
IEEE 802.11n PHY data tables
- Copyright (c) 2008 Michael Buesch <mb@bu3sch.de>
+ 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
@@ -1097,7 +1098,1056 @@ static const u32 b43_ntab_tmap[] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000,
};
-const u32 b43_ntab_tx_gain_rev0_1_2[] = {
+/* 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,
+ }
+};
+
+/* 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,
@@ -1132,7 +2182,7 @@ const u32 b43_ntab_tx_gain_rev0_1_2[] = {
0x03801442, 0x03801344, 0x03801342, 0x00002b00,
};
-const u32 b43_ntab_tx_gain_rev3plus_2ghz[] = {
+static const u32 b43_ntab_tx_gain_rev3plus_2ghz[] = {
0x1f410044, 0x1f410042, 0x1f410040, 0x1f41003e,
0x1f41003c, 0x1f41003b, 0x1f410039, 0x1f410037,
0x1e410044, 0x1e410042, 0x1e410040, 0x1e41003e,
@@ -1167,7 +2217,7 @@ const u32 b43_ntab_tx_gain_rev3plus_2ghz[] = {
0x1041003c, 0x1041003b, 0x10410039, 0x10410037,
};
-const u32 b43_ntab_tx_gain_rev3_5ghz[] = {
+static const u32 b43_ntab_tx_gain_rev3_5ghz[] = {
0xcff70044, 0xcff70042, 0xcff70040, 0xcff7003e,
0xcff7003c, 0xcff7003b, 0xcff70039, 0xcff70037,
0xcef70044, 0xcef70042, 0xcef70040, 0xcef7003e,
@@ -1202,7 +2252,7 @@ const u32 b43_ntab_tx_gain_rev3_5ghz[] = {
0xc0f7003c, 0xc0f7003b, 0xc0f70039, 0xc0f70037,
};
-const u32 b43_ntab_tx_gain_rev4_5ghz[] = {
+static const u32 b43_ntab_tx_gain_rev4_5ghz[] = {
0x2ff20044, 0x2ff20042, 0x2ff20040, 0x2ff2003e,
0x2ff2003c, 0x2ff2003b, 0x2ff20039, 0x2ff20037,
0x2ef20044, 0x2ef20042, 0x2ef20040, 0x2ef2003e,
@@ -1237,7 +2287,7 @@ const u32 b43_ntab_tx_gain_rev4_5ghz[] = {
0x20d2003a, 0x20d20038, 0x20d20036, 0x20d20034,
};
-const u32 b43_ntab_tx_gain_rev5plus_5ghz[] = {
+static const u32 b43_ntab_tx_gain_rev5plus_5ghz[] = {
0x0f62004a, 0x0f620048, 0x0f620046, 0x0f620044,
0x0f620042, 0x0f620040, 0x0f62003e, 0x0f62003c,
0x0e620044, 0x0e620042, 0x0e620040, 0x0e62003e,
@@ -1272,7 +2322,7 @@ const u32 b43_ntab_tx_gain_rev5plus_5ghz[] = {
0x0062003b, 0x00620039, 0x00620037, 0x00620035,
};
-const u32 txpwrctrl_tx_gain_ipa[] = {
+static const u32 txpwrctrl_tx_gain_ipa[] = {
0x5ff7002d, 0x5ff7002b, 0x5ff7002a, 0x5ff70029,
0x5ff70028, 0x5ff70027, 0x5ff70026, 0x5ff70025,
0x5ef7002d, 0x5ef7002b, 0x5ef7002a, 0x5ef70029,
@@ -1307,7 +2357,7 @@ const u32 txpwrctrl_tx_gain_ipa[] = {
0x50f70028, 0x50f70027, 0x50f70026, 0x50f70025,
};
-const u32 txpwrctrl_tx_gain_ipa_rev5[] = {
+static const u32 txpwrctrl_tx_gain_ipa_rev5[] = {
0x1ff7002d, 0x1ff7002b, 0x1ff7002a, 0x1ff70029,
0x1ff70028, 0x1ff70027, 0x1ff70026, 0x1ff70025,
0x1ef7002d, 0x1ef7002b, 0x1ef7002a, 0x1ef70029,
@@ -1342,7 +2392,7 @@ const u32 txpwrctrl_tx_gain_ipa_rev5[] = {
0x10f70028, 0x10f70027, 0x10f70026, 0x10f70025,
};
-const u32 txpwrctrl_tx_gain_ipa_rev6[] = {
+static const u32 txpwrctrl_tx_gain_ipa_rev6[] = {
0x0ff7002d, 0x0ff7002b, 0x0ff7002a, 0x0ff70029,
0x0ff70028, 0x0ff70027, 0x0ff70026, 0x0ff70025,
0x0ef7002d, 0x0ef7002b, 0x0ef7002a, 0x0ef70029,
@@ -1377,7 +2427,7 @@ const u32 txpwrctrl_tx_gain_ipa_rev6[] = {
0x00f70028, 0x00f70027, 0x00f70026, 0x00f70025,
};
-const u32 txpwrctrl_tx_gain_ipa_5g[] = {
+static const u32 txpwrctrl_tx_gain_ipa_5g[] = {
0x7ff70035, 0x7ff70033, 0x7ff70032, 0x7ff70031,
0x7ff7002f, 0x7ff7002e, 0x7ff7002d, 0x7ff7002b,
0x7ff7002a, 0x7ff70029, 0x7ff70028, 0x7ff70027,
@@ -1412,6 +2462,11 @@ const u32 txpwrctrl_tx_gain_ipa_5g[] = {
0x70f70021, 0x70f70020, 0x70f70020, 0x70f7001f,
};
+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
+};
+
const u16 tbl_iqcal_gainparams[2][9][8] = {
{
{ 0x000, 0, 0, 2, 0x69, 0x69, 0x69, 0x69 },
@@ -1577,7 +2632,7 @@ const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = {
const s16 tbl_tx_filter_coef_rev4[7][15] = {
{ -377, 137, -407, 208, -1527,
956, 93, 186, 93, 230,
- -44, 230, 20, -191, 201 },
+ -44, 230, 201, -191, 201 },
{ -77, 20, -98, 49, -93,
60, 56, 111, 56, 26,
-5, 26, 34, -32, 34 },
@@ -1622,11 +2677,11 @@ const struct nphy_rf_control_override_rev3 tbl_rf_control_override_rev3[] = {
{ 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) */
- { 0x0016, 4, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0010 (fls 5) */
+ { 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, 6, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0080 (fls 8) */
- { 0x0100, 7, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0100 (fls 9) */
+ { 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) */
@@ -1635,6 +2690,155 @@ const struct nphy_rf_control_override_rev3 tbl_rf_control_override_rev3[] = {
{ 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, 0x0F8, 0x0FA, 0x0080, 7 },
+ { 0x0400, 0x0F8, 0x0FA, 0x0070, 4 },
+ { 0x0800, 0x07B, 0x07E, 0xFFFF, 0 },
+ { 0x1000, 0x07C, 0x07F, 0xFFFF, 0 },
+ { 0x6000, 0x348, 0x349, 0xFFFF, 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! */
+ 0x1076, 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
@@ -1690,9 +2894,8 @@ u32 b43_ntab_read(struct b43_wldev *dev, u32 offset)
break;
case B43_NTAB_32BIT:
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
- value = b43_phy_read(dev, B43_NPHY_TABLE_DATAHI);
- value <<= 16;
- value |= b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
+ 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);
@@ -1716,6 +2919,12 @@ void b43_ntab_read_bulk(struct b43_wldev *dev, u32 offset,
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;
@@ -1726,9 +2935,10 @@ void b43_ntab_read_bulk(struct b43_wldev *dev, u32 offset,
data += 2;
break;
case B43_NTAB_32BIT:
- *((u32 *)data) = b43_phy_read(dev, B43_NPHY_TABLE_DATAHI);
- *((u32 *)data) <<= 16;
- *((u32 *)data) |= b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
+ *((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:
@@ -1784,6 +2994,13 @@ void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset,
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;
@@ -1811,26 +3028,74 @@ void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset,
}
#define ntab_upload(dev, offset, data) do { \
- b43_ntab_write_bulk(dev, offset, offset##_SIZE, data); \
+ b43_ntab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
} while (0)
-void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *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) == IEEE80211_BAND_5GHZ)
+ antswlut = sprom->fem.ghz5.antswlut;
+ else
+ antswlut = sprom->fem.ghz2.antswlut;
+
/* Static tables */
- 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);
+ 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);
+ 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);
+ }
+
+ /* 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);
@@ -1847,11 +3112,147 @@ void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev)
ntab_upload(dev, B43_NTAB_C1_LOFEEDTH, b43_ntab_loftlt1);
}
-void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev)
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables */
+void b43_nphy_tables_init(struct b43_wldev *dev)
{
- /* Static tables */
- /* TODO */
+ if (dev->phy.rev >= 3)
+ b43_nphy_tables_init_rev3(dev);
+ else
+ b43_nphy_tables_init_rev0(dev);
+}
- /* Volatile tables */
- /* TODO */
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetIpaGainTbl */
+static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev)
+{
+ if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+ if (dev->phy.rev >= 6) {
+ if (dev->dev->chip_id == 47162)
+ return txpwrctrl_tx_gain_ipa_rev5;
+ return txpwrctrl_tx_gain_ipa_rev6;
+ } else if (dev->phy.rev >= 5) {
+ return txpwrctrl_tx_gain_ipa_rev5;
+ } else {
+ return txpwrctrl_tx_gain_ipa;
+ }
+ } else {
+ return txpwrctrl_tx_gain_ipa_5g;
+ }
+}
+
+const u32 *b43_nphy_get_tx_gain_table(struct b43_wldev *dev)
+{
+ enum ieee80211_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 == IEEE80211_BAND_2GHZ) ||
+ (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ)) {
+ return b43_nphy_get_ipa_gain_table(dev);
+ } else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
+ if (dev->phy.rev == 3)
+ return b43_ntab_tx_gain_rev3_5ghz;
+ if (dev->phy.rev == 4)
+ return sprom->fem.ghz5.extpa_gain == 3 ?
+ b43_ntab_tx_gain_rev4_5ghz :
+ b43_ntab_tx_gain_rev4_5ghz; /* FIXME */
+ else
+ return b43_ntab_tx_gain_rev5plus_5ghz;
+ } else {
+ if (dev->phy.rev >= 5 && sprom->fem.ghz5.extpa_gain == 3)
+ return b43_ntab_tx_gain_rev3plus_2ghz; /* FIXME */
+ else
+ return b43_ntab_tx_gain_rev3plus_2ghz;
+ }
+}
+
+struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
+ struct b43_wldev *dev, bool ghz5, bool ext_lna)
+{
+ 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 && dev->phy.rev >= 6) {
+ if (dev->phy.radio_rev == 11 &&
+ !b43_channel_type_is_40mhz(dev->phy.channel_type))
+ e->cliplo_gain = 0x2d;
+ } else if (!ghz5 && dev->phy.rev >= 5) {
+ static const int gain_data[] = {0x0062, 0x0064, 0x006a, 0x106a,
+ 0x106c, 0x1074, 0x107c, 0x207c};
+ u8 tr_iso = dev->dev->bus_sprom->fem.ghz2.tr_iso;
+
+ if (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;
+ }
+ if (tr_iso > 7)
+ tr_iso = 3;
+ e->cliplo_gain = gain_data[tr_iso];
+
+ } else if (ghz5 && dev->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/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h
index 4ec593ba3ee..3a58aee4c4c 100644
--- a/drivers/net/wireless/b43/tables_nphy.h
+++ b/drivers/net/wireless/b43/tables_nphy.h
@@ -35,16 +35,41 @@ struct nphy_rf_control_override_rev3 {
u8 val_addr1;
};
-/* 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);
-const struct b43_nphy_channeltab_entry_rev3 *
-b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq);
+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];
-/* The N-PHY tables. */
+ 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
@@ -90,25 +115,56 @@ b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq);
#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_C1_ESTPLT B43_NTAB8 (0x1B, 0x000) /* Estimate Power Lookup Table Core 1 */
-#define B43_NTAB_C1_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_C1_ADJPLT B43_NTAB8 (0x1B, 0x040) /* Adjust Power Lookup Table Core 1 */
-#define B43_NTAB_C1_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_C1_GAINCTL B43_NTAB32(0x1B, 0x0C0) /* Gain Control Lookup Table Core 1 */
-#define B43_NTAB_C1_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_C1_IQLT B43_NTAB32(0x1B, 0x140) /* IQ Lookup Table Core 1 */
-#define B43_NTAB_C1_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)
+
#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
@@ -127,19 +183,12 @@ 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_rev0_1_2_tables_init(struct b43_wldev *dev);
-void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev);
+void b43_nphy_tables_init(struct b43_wldev *dev);
+
+const u32 *b43_nphy_get_tx_gain_table(struct b43_wldev *dev);
-extern const u32 b43_ntab_tx_gain_rev0_1_2[];
-extern const u32 b43_ntab_tx_gain_rev3plus_2ghz[];
-extern const u32 b43_ntab_tx_gain_rev3_5ghz[];
-extern const u32 b43_ntab_tx_gain_rev4_5ghz[];
-extern const u32 b43_ntab_tx_gain_rev5plus_5ghz[];
+extern const s8 b43_ntab_papd_pga_gain_delta_ipa_2g[];
-extern const u32 txpwrctrl_tx_gain_ipa[];
-extern const u32 txpwrctrl_tx_gain_ipa_rev5[];
-extern const u32 txpwrctrl_tx_gain_ipa_rev6[];
-extern const u32 txpwrctrl_tx_gain_ipa_5g[];
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[];
@@ -161,5 +210,7 @@ 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/b43/tables_phy_ht.c b/drivers/net/wireless/b43/tables_phy_ht.c
new file mode 100644
index 00000000000..176c49d74ef
--- /dev/null
+++ b/drivers/net/wireless/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/b43/tables_phy_ht.h b/drivers/net/wireless/b43/tables_phy_ht.h
new file mode 100644
index 00000000000..1b5ef2bc770
--- /dev/null
+++ b/drivers/net/wireless/b43/tables_phy_ht.h
@@ -0,0 +1,26 @@
+#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/b43/tables_phy_lcn.c b/drivers/net/wireless/b43/tables_phy_lcn.c
new file mode 100644
index 00000000000..e347b8d80ea
--- /dev/null
+++ b/drivers/net/wireless/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) == IEEE80211_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/b43/tables_phy_lcn.h b/drivers/net/wireless/b43/tables_phy_lcn.h
new file mode 100644
index 00000000000..caff9db6831
--- /dev/null
+++ b/drivers/net/wireless/b43/tables_phy_lcn.h
@@ -0,0 +1,24 @@
+#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/b43/wa.c b/drivers/net/wireless/b43/wa.c
index 9a335da65b4..c218c08fb2f 100644
--- a/drivers/net/wireless/b43/wa.c
+++ b/drivers/net/wireless/b43/wa.c
@@ -5,7 +5,7 @@
PHY workarounds.
Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005-2007 Michael Buesch <mbuesch@freenet.de>
+ 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
@@ -441,7 +441,7 @@ static void b43_wa_altagc(struct b43_wldev *dev)
static void b43_wa_tr_ltov(struct b43_wldev *dev) /* TR Lookup Table Original Values */
{
- b43_gtab_write(dev, B43_GTAB_ORIGTR, 0, 0xC480);
+ b43_gtab_write(dev, B43_GTAB_ORIGTR, 0, 0x7654);
}
static void b43_wa_cpll_nonpilot(struct b43_wldev *dev)
@@ -458,17 +458,15 @@ static void b43_wa_rssi_adc(struct b43_wldev *dev)
static void b43_wa_boards_a(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->dev->bus;
-
- if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM &&
- bus->boardinfo.type == SSB_BOARD_BU4306 &&
- bus->boardinfo.rev < 0x30) {
+ if (dev->dev->board_vendor == SSB_BOARDVENDOR_BCM &&
+ dev->dev->board_type == SSB_BOARD_BU4306 &&
+ dev->dev->board_rev < 0x30) {
b43_phy_write(dev, 0x0010, 0xE000);
b43_phy_write(dev, 0x0013, 0x0140);
b43_phy_write(dev, 0x0014, 0x0280);
} else {
- if (bus->boardinfo.type == SSB_BOARD_MP4318 &&
- bus->boardinfo.rev < 0x20) {
+ if (dev->dev->board_type == SSB_BOARD_MP4318 &&
+ dev->dev->board_rev < 0x20) {
b43_phy_write(dev, 0x0013, 0x0210);
b43_phy_write(dev, 0x0014, 0x0840);
} else {
@@ -486,19 +484,19 @@ static void b43_wa_boards_a(struct b43_wldev *dev)
static void b43_wa_boards_g(struct b43_wldev *dev)
{
- struct ssb_bus *bus = dev->dev->bus;
+ struct ssb_sprom *sprom = dev->dev->bus_sprom;
struct b43_phy *phy = &dev->phy;
- if (bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM ||
- bus->boardinfo.type != SSB_BOARD_BU4306 ||
- bus->boardinfo.rev != 0x17) {
+ 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 ((bus->sprom.boardflags_lo & B43_BFL_EXTLNA) &&
+ 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);
@@ -510,7 +508,7 @@ static void b43_wa_boards_g(struct b43_wldev *dev)
}
}
}
- if (bus->sprom.boardflags_lo & B43_BFL_FEM) {
+ if (sprom->boardflags_lo & B43_BFL_FEM) {
b43_phy_write(dev, B43_PHY_GTABCTL, 0x3120);
b43_phy_write(dev, B43_PHY_GTABDATA, 0xC480);
}
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index e6b0528f3b5..6e6ef3fc224 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -6,7 +6,7 @@
Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
Copyright (C) 2005 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (C) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+ 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>
@@ -32,6 +32,36 @@
#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)
@@ -145,6 +175,35 @@ void b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp,
}
}
+/* 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)
{
switch (bitrate) {
@@ -198,6 +257,9 @@ int b43_generate_txhdr(struct b43_wldev *dev,
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;
@@ -216,7 +278,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
else
txhdr->phy_rate = b43_plcp_get_ratecode_cck(rate);
txhdr->mac_frame_ctl = wlhdr->frame_control;
- memcpy(txhdr->tx_receiver, wlhdr->addr1, 6);
+ memcpy(txhdr->tx_receiver, wlhdr->addr1, ETH_ALEN);
/* Calculate duration for fallback rate */
if ((rate_fb == rate) ||
@@ -228,7 +290,8 @@ int b43_generate_txhdr(struct b43_wldev *dev,
txhdr->dur_fb = wlhdr->duration_id;
} else {
txhdr->dur_fb = ieee80211_generic_frame_duration(
- dev->wl->hw, info->control.vif, fragment_len, fbrate);
+ dev->wl->hw, info->control.vif, info->band,
+ fragment_len, fbrate);
}
plcp_fragment_len = fragment_len + FCS_LEN;
@@ -265,8 +328,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
/* 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_key(info->control.hw_key, skb_frag,
- IEEE80211_TKIP_P1_KEY, (u8*)phase1key);
+ 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];
@@ -275,17 +337,24 @@ int b43_generate_txhdr(struct b43_wldev *dev,
/* iv16 */
memcpy(txhdr->iv + 10, ((u8 *) wlhdr) + wlhdr_len, 3);
} else {
- iv_len = min((size_t) info->control.hw_key->iv_len,
+ 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);
}
}
- if (b43_is_old_txhdr_format(dev)) {
- b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp),
+ 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);
- } else {
- b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->new_format.plcp),
+ 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);
@@ -310,7 +379,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
phy_ctl |= B43_TXH_PHY_SHORTPRMBL;
- switch (b43_ieee80211_antenna_sanitize(dev, info->antenna_sel_tx)) {
+ switch (b43_ieee80211_antenna_sanitize(dev, 0)) {
case 0: /* Default */
phy_ctl |= B43_TXH_PHY_ANT01AUTO;
break;
@@ -339,7 +408,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
mac_ctl |= B43_TXH_MAC_HWSEQ;
if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
mac_ctl |= B43_TXH_MAC_STMSDU;
- if (phy->type == B43_PHYTYPE_A)
+ if (!phy->gmode)
mac_ctl |= B43_TXH_MAC_5GHZ;
/* Overwrite rates[0].count to make the retry calculation
@@ -358,10 +427,10 @@ int b43_generate_txhdr(struct b43_wldev *dev,
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;
+ struct ieee80211_hdr *uninitialized_var(hdr);
int rts_rate, rts_rate_fb;
int rts_rate_ofdm, rts_rate_fb_ofdm;
- struct b43_plcp_hdr6 *plcp;
+ 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);
@@ -372,14 +441,21 @@ int b43_generate_txhdr(struct b43_wldev *dev,
rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
- struct ieee80211_cts *cts;
+ struct ieee80211_cts *uninitialized_var(cts);
- if (b43_is_old_txhdr_format(dev)) {
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_598:
cts = (struct ieee80211_cts *)
- (txhdr->old_format.rts_frame);
- } else {
+ (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->new_format.rts_frame);
+ (txhdr->format_410.rts_frame);
+ break;
}
ieee80211_ctstoself_get(dev->wl->hw, info->control.vif,
fragment_data, fragment_len,
@@ -387,14 +463,21 @@ int b43_generate_txhdr(struct b43_wldev *dev,
mac_ctl |= B43_TXH_MAC_SENDCTS;
len = sizeof(struct ieee80211_cts);
} else {
- struct ieee80211_rts *rts;
+ struct ieee80211_rts *uninitialized_var(rts);
- if (b43_is_old_txhdr_format(dev)) {
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_598:
rts = (struct ieee80211_rts *)
- (txhdr->old_format.rts_frame);
- } else {
+ (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->new_format.rts_frame);
+ (txhdr->format_410.rts_frame);
+ break;
}
ieee80211_rts_get(dev->wl->hw, info->control.vif,
fragment_data, fragment_len,
@@ -405,22 +488,36 @@ int b43_generate_txhdr(struct b43_wldev *dev,
len += FCS_LEN;
/* Generate the PLCP headers for the RTS/CTS frame */
- if (b43_is_old_txhdr_format(dev))
- plcp = &txhdr->old_format.rts_plcp;
- else
- plcp = &txhdr->new_format.rts_plcp;
+ 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);
- if (b43_is_old_txhdr_format(dev)) {
+ switch (dev->fw.hdr_format) {
+ case B43_FW_HDR_598:
hdr = (struct ieee80211_hdr *)
- (&txhdr->old_format.rts_frame);
- } else {
+ (&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->new_format.rts_frame);
+ (&txhdr->format_410.rts_frame);
+ break;
}
txhdr->rts_dur_fb = hdr->duration_id;
@@ -437,13 +534,35 @@ int b43_generate_txhdr(struct b43_wldev *dev,
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 */
- if (b43_is_old_txhdr_format(dev))
- txhdr->old_format.cookie = cpu_to_le16(cookie);
- else
- txhdr->new_format.cookie = cpu_to_le16(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);
@@ -474,7 +593,7 @@ static s8 b43_rssi_postprocess(struct b43_wldev *dev,
else
tmp -= 3;
} else {
- if (dev->dev->bus->sprom.
+ if (dev->dev->bus_sprom->
boardflags_lo & B43_BFL_RSSI) {
if (in_rssi > 63)
in_rssi = 63;
@@ -539,20 +658,31 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
struct ieee80211_hdr *wlhdr;
const struct b43_rxhdr_fw4 *rxhdr = _rxhdr;
__le16 fctl;
- u16 phystat0, phystat3, chanstat, mactime;
- u32 macstat;
+ u16 phystat0, phystat3;
+ u16 uninitialized_var(chanstat), uninitialized_var(mactime);
+ u32 uninitialized_var(macstat);
u16 chanid;
u16 phytype;
- int padding;
+ 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);
- macstat = le32_to_cpu(rxhdr->mac_status);
- mactime = le16_to_cpu(rxhdr->mac_time);
- chanstat = le16_to_cpu(rxhdr->channel);
+ 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;
+ }
phytype = chanstat & B43_RX_CHAN_PHYTYPE;
if (unlikely(macstat & B43_RX_MAC_FCSERR)) {
@@ -610,29 +740,43 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
}
/* Link quality statistics */
- if ((chanstat & B43_RX_CHAN_PHYTYPE) == B43_PHYTYPE_N) {
-// s8 rssi = max(rxhdr->power0, rxhdr->power1);
- //TODO: Find out what the rssi value is (dBm or percentage?)
- // and also find out what the maximum possible value is.
- // Fill status.ssi and status.signal fields.
- } else {
+ 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_A:
+ 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)
- status.rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp,
+ rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp,
phytype == B43_PHYTYPE_A);
else
- status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp);
- if (unlikely(status.rate_idx == -1)) {
+ 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);
/*
@@ -652,7 +796,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
status.mactime += mactime;
if (low_mactime_now <= mactime)
status.mactime -= 0x10000;
- status.flag |= RX_FLAG_TSFT;
+ status.flag |= RX_FLAG_MACTIME_START;
}
chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT;
@@ -662,25 +806,30 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
B43_WARN_ON(1);
/* FIXME: We don't really know which value the "chanid" contains.
* So the following assignment might be wrong. */
- status.freq = b43_channel_to_freq_5ghz(chanid);
+ status.freq =
+ ieee80211_channel_to_frequency(chanid, status.band);
break;
case B43_PHYTYPE_G:
status.band = IEEE80211_BAND_2GHZ;
- /* chanid is the radio channel cookie value as used
- * to tune the radio. */
- status.freq = chanid + 2400;
+ /* 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) {
+ if (chanstat & B43_RX_CHAN_5GHZ)
status.band = IEEE80211_BAND_5GHZ;
- status.freq = b43_freq_to_channel_5ghz(chanid);
- } else {
+ else
status.band = IEEE80211_BAND_2GHZ;
- status.freq = b43_freq_to_channel_2ghz(chanid);
- }
+ status.freq =
+ ieee80211_channel_to_frequency(chanid, status.band);
break;
default:
B43_WARN_ON(1);
@@ -695,7 +844,6 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
#endif
return;
drop:
- b43dbg(dev->wl, "RX: Packet dropped\n");
dev_kfree_skb_any(skb);
}
@@ -732,7 +880,7 @@ bool b43_fill_txstatus_report(struct b43_wldev *dev,
struct ieee80211_tx_info *report,
const struct b43_txstatus *status)
{
- bool frame_success = 1;
+ bool frame_success = true;
int retry_limit;
/* preserve the confiured retry limit before clearing the status
@@ -748,7 +896,7 @@ bool b43_fill_txstatus_report(struct b43_wldev *dev,
/* The frame was not ACKed... */
if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) {
/* ...but we expected an ACK. */
- frame_success = 0;
+ frame_success = false;
}
}
if (status->frame_count == 0) {
diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h
index d4cf9b390af..98d90747836 100644
--- a/drivers/net/wireless/b43/xmit.h
+++ b/drivers/net/wireless/b43/xmit.h
@@ -46,7 +46,24 @@ struct b43_txhdr {
__le32 timeout; /* Timeout */
union {
- /* The new r410 format. */
+ /* 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 */
@@ -57,9 +74,9 @@ struct b43_txhdr {
__u8 rts_frame[16]; /* The RTS frame (if used) */
PAD_BYTES(2);
struct b43_plcp_hdr6 plcp; /* Main PLCP header */
- } new_format __packed;
+ } format_410 __packed;
- /* The old r351 format. */
+ /* Tested with 351.126 */
struct {
PAD_BYTES(2);
__le16 cookie; /* TX frame cookie */
@@ -68,11 +85,17 @@ struct b43_txhdr {
__u8 rts_frame[16]; /* The RTS frame (if used) */
PAD_BYTES(2);
struct b43_plcp_hdr6 plcp; /* Main PLCP header */
- } old_format __packed;
+ } 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_USEFBR 0x10000000 /* Use fallback rate for this AMPDU */
#define B43_TXH_MAC_KEYIDX 0x0FF00000 /* Security key index */
@@ -160,19 +183,18 @@ struct b43_txhdr {
#define B43_TXH_PHY1_MODUL_QAM256 0x2000 /* QAM256 */
-/* r351 firmware compatibility stuff. */
-static inline
-bool b43_is_old_txhdr_format(struct b43_wldev *dev)
-{
- return (dev->fw.rev <= 351);
-}
-
static inline
size_t b43_txhdr_size(struct b43_wldev *dev)
{
- if (b43_is_old_txhdr_format(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 104 + sizeof(struct b43_plcp_hdr6);
+ }
+ return 0;
}
@@ -226,11 +248,47 @@ struct b43_rxhdr_fw4 {
__s8 power1; /* PHY RX Status 1: Power 1 */
} __packed;
} __packed;
- __le16 phy_status2; /* PHY RX Status 2 */
- __le16 phy_status3; /* PHY RX Status 3 */
- __le32 mac_status; /* MAC RX status */
- __le16 mac_time;
- __le16 channel;
+ 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 */