cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

phy_n.c (201698B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3
      4  Broadcom B43 wireless driver
      5  IEEE 802.11n PHY support
      6
      7  Copyright (c) 2008 Michael Buesch <m@bues.ch>
      8  Copyright (c) 2010-2011 Rafał Miłecki <zajec5@gmail.com>
      9
     10
     11*/
     12
     13#include <linux/cordic.h>
     14#include <linux/delay.h>
     15#include <linux/slab.h>
     16#include <linux/types.h>
     17
     18#include "b43.h"
     19#include "phy_n.h"
     20#include "tables_nphy.h"
     21#include "radio_2055.h"
     22#include "radio_2056.h"
     23#include "radio_2057.h"
     24#include "main.h"
     25#include "ppr.h"
     26
     27struct nphy_txgains {
     28	u16 tx_lpf[2];
     29	u16 txgm[2];
     30	u16 pga[2];
     31	u16 pad[2];
     32	u16 ipa[2];
     33};
     34
     35struct nphy_iqcal_params {
     36	u16 tx_lpf;
     37	u16 txgm;
     38	u16 pga;
     39	u16 pad;
     40	u16 ipa;
     41	u16 cal_gain;
     42	u16 ncorr[5];
     43};
     44
     45struct nphy_iq_est {
     46	s32 iq0_prod;
     47	u32 i0_pwr;
     48	u32 q0_pwr;
     49	s32 iq1_prod;
     50	u32 i1_pwr;
     51	u32 q1_pwr;
     52};
     53
     54enum b43_nphy_rf_sequence {
     55	B43_RFSEQ_RX2TX,
     56	B43_RFSEQ_TX2RX,
     57	B43_RFSEQ_RESET2RX,
     58	B43_RFSEQ_UPDATE_GAINH,
     59	B43_RFSEQ_UPDATE_GAINL,
     60	B43_RFSEQ_UPDATE_GAINU,
     61};
     62
     63enum n_rf_ctl_over_cmd {
     64	N_RF_CTL_OVER_CMD_RXRF_PU = 0,
     65	N_RF_CTL_OVER_CMD_RX_PU = 1,
     66	N_RF_CTL_OVER_CMD_TX_PU = 2,
     67	N_RF_CTL_OVER_CMD_RX_GAIN = 3,
     68	N_RF_CTL_OVER_CMD_TX_GAIN = 4,
     69};
     70
     71enum n_intc_override {
     72	N_INTC_OVERRIDE_OFF = 0,
     73	N_INTC_OVERRIDE_TRSW = 1,
     74	N_INTC_OVERRIDE_PA = 2,
     75	N_INTC_OVERRIDE_EXT_LNA_PU = 3,
     76	N_INTC_OVERRIDE_EXT_LNA_GAIN = 4,
     77};
     78
     79enum n_rssi_type {
     80	N_RSSI_W1 = 0,
     81	N_RSSI_W2,
     82	N_RSSI_NB,
     83	N_RSSI_IQ,
     84	N_RSSI_TSSI_2G,
     85	N_RSSI_TSSI_5G,
     86	N_RSSI_TBD,
     87};
     88
     89enum n_rail_type {
     90	N_RAIL_I = 0,
     91	N_RAIL_Q = 1,
     92};
     93
     94static inline bool b43_nphy_ipa(struct b43_wldev *dev)
     95{
     96	enum nl80211_band band = b43_current_band(dev->wl);
     97	return ((dev->phy.n->ipa2g_on && band == NL80211_BAND_2GHZ) ||
     98		(dev->phy.n->ipa5g_on && band == NL80211_BAND_5GHZ));
     99}
    100
    101/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreGetState */
    102static u8 b43_nphy_get_rx_core_state(struct b43_wldev *dev)
    103{
    104	return (b43_phy_read(dev, B43_NPHY_RFSEQCA) & B43_NPHY_RFSEQCA_RXEN) >>
    105		B43_NPHY_RFSEQCA_RXEN_SHIFT;
    106}
    107
    108/**************************************************
    109 * RF (just without b43_nphy_rf_ctl_intc_override)
    110 **************************************************/
    111
    112/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */
    113static void b43_nphy_force_rf_sequence(struct b43_wldev *dev,
    114				       enum b43_nphy_rf_sequence seq)
    115{
    116	static const u16 trigger[] = {
    117		[B43_RFSEQ_RX2TX]		= B43_NPHY_RFSEQTR_RX2TX,
    118		[B43_RFSEQ_TX2RX]		= B43_NPHY_RFSEQTR_TX2RX,
    119		[B43_RFSEQ_RESET2RX]		= B43_NPHY_RFSEQTR_RST2RX,
    120		[B43_RFSEQ_UPDATE_GAINH]	= B43_NPHY_RFSEQTR_UPGH,
    121		[B43_RFSEQ_UPDATE_GAINL]	= B43_NPHY_RFSEQTR_UPGL,
    122		[B43_RFSEQ_UPDATE_GAINU]	= B43_NPHY_RFSEQTR_UPGU,
    123	};
    124	int i;
    125	u16 seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);
    126
    127	B43_WARN_ON(seq >= ARRAY_SIZE(trigger));
    128
    129	b43_phy_set(dev, B43_NPHY_RFSEQMODE,
    130		    B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER);
    131	b43_phy_set(dev, B43_NPHY_RFSEQTR, trigger[seq]);
    132	for (i = 0; i < 200; i++) {
    133		if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & trigger[seq]))
    134			goto ok;
    135		msleep(1);
    136	}
    137	b43err(dev->wl, "RF sequence status timeout\n");
    138ok:
    139	b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
    140}
    141
    142static void b43_nphy_rf_ctl_override_rev19(struct b43_wldev *dev, u16 field,
    143					   u16 value, u8 core, bool off,
    144					   u8 override_id)
    145{
    146	/* TODO */
    147}
    148
    149/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverrideRev7 */
    150static void b43_nphy_rf_ctl_override_rev7(struct b43_wldev *dev, u16 field,
    151					  u16 value, u8 core, bool off,
    152					  u8 override)
    153{
    154	struct b43_phy *phy = &dev->phy;
    155	const struct nphy_rf_control_override_rev7 *e;
    156	u16 en_addrs[3][2] = {
    157		{ 0x0E7, 0x0EC }, { 0x342, 0x343 }, { 0x346, 0x347 }
    158	};
    159	u16 en_addr;
    160	u16 en_mask = field;
    161	u16 val_addr;
    162	u8 i;
    163
    164	if (phy->rev >= 19 || phy->rev < 3) {
    165		B43_WARN_ON(1);
    166		return;
    167	}
    168
    169	/* Remember: we can get NULL! */
    170	e = b43_nphy_get_rf_ctl_over_rev7(dev, field, override);
    171
    172	for (i = 0; i < 2; i++) {
    173		if (override >= ARRAY_SIZE(en_addrs)) {
    174			b43err(dev->wl, "Invalid override value %d\n", override);
    175			return;
    176		}
    177		en_addr = en_addrs[override][i];
    178
    179		if (e)
    180			val_addr = (i == 0) ? e->val_addr_core0 : e->val_addr_core1;
    181
    182		if (off) {
    183			b43_phy_mask(dev, en_addr, ~en_mask);
    184			if (e) /* Do it safer, better than wl */
    185				b43_phy_mask(dev, val_addr, ~e->val_mask);
    186		} else {
    187			if (!core || (core & (1 << i))) {
    188				b43_phy_set(dev, en_addr, en_mask);
    189				if (e)
    190					b43_phy_maskset(dev, val_addr, ~e->val_mask, (value << e->val_shift));
    191			}
    192		}
    193	}
    194}
    195
    196/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverideOneToMany */
    197static void b43_nphy_rf_ctl_override_one_to_many(struct b43_wldev *dev,
    198						 enum n_rf_ctl_over_cmd cmd,
    199						 u16 value, u8 core, bool off)
    200{
    201	struct b43_phy *phy = &dev->phy;
    202	u16 tmp;
    203
    204	B43_WARN_ON(phy->rev < 7);
    205
    206	switch (cmd) {
    207	case N_RF_CTL_OVER_CMD_RXRF_PU:
    208		b43_nphy_rf_ctl_override_rev7(dev, 0x20, value, core, off, 1);
    209		b43_nphy_rf_ctl_override_rev7(dev, 0x10, value, core, off, 1);
    210		b43_nphy_rf_ctl_override_rev7(dev, 0x08, value, core, off, 1);
    211		break;
    212	case N_RF_CTL_OVER_CMD_RX_PU:
    213		b43_nphy_rf_ctl_override_rev7(dev, 0x4, value, core, off, 1);
    214		b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 1);
    215		b43_nphy_rf_ctl_override_rev7(dev, 0x1, value, core, off, 1);
    216		b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 2);
    217		b43_nphy_rf_ctl_override_rev7(dev, 0x0800, 0, core, off, 1);
    218		break;
    219	case N_RF_CTL_OVER_CMD_TX_PU:
    220		b43_nphy_rf_ctl_override_rev7(dev, 0x4, value, core, off, 0);
    221		b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 1);
    222		b43_nphy_rf_ctl_override_rev7(dev, 0x1, value, core, off, 2);
    223		b43_nphy_rf_ctl_override_rev7(dev, 0x0800, 1, core, off, 1);
    224		break;
    225	case N_RF_CTL_OVER_CMD_RX_GAIN:
    226		tmp = value & 0xFF;
    227		b43_nphy_rf_ctl_override_rev7(dev, 0x0800, tmp, core, off, 0);
    228		tmp = value >> 8;
    229		b43_nphy_rf_ctl_override_rev7(dev, 0x6000, tmp, core, off, 0);
    230		break;
    231	case N_RF_CTL_OVER_CMD_TX_GAIN:
    232		tmp = value & 0x7FFF;
    233		b43_nphy_rf_ctl_override_rev7(dev, 0x1000, tmp, core, off, 0);
    234		tmp = value >> 14;
    235		b43_nphy_rf_ctl_override_rev7(dev, 0x4000, tmp, core, off, 0);
    236		break;
    237	}
    238}
    239
    240/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */
    241static void b43_nphy_rf_ctl_override(struct b43_wldev *dev, u16 field,
    242				     u16 value, u8 core, bool off)
    243{
    244	int i;
    245	u8 index = fls(field);
    246	u8 addr, en_addr, val_addr;
    247	/* we expect only one bit set */
    248	B43_WARN_ON(field & (~(1 << (index - 1))));
    249
    250	if (dev->phy.rev >= 3) {
    251		const struct nphy_rf_control_override_rev3 *rf_ctrl;
    252		for (i = 0; i < 2; i++) {
    253			if (index == 0 || index == 16) {
    254				b43err(dev->wl,
    255					"Unsupported RF Ctrl Override call\n");
    256				return;
    257			}
    258
    259			rf_ctrl = &tbl_rf_control_override_rev3[index - 1];
    260			en_addr = B43_PHY_N((i == 0) ?
    261				rf_ctrl->en_addr0 : rf_ctrl->en_addr1);
    262			val_addr = B43_PHY_N((i == 0) ?
    263				rf_ctrl->val_addr0 : rf_ctrl->val_addr1);
    264
    265			if (off) {
    266				b43_phy_mask(dev, en_addr, ~(field));
    267				b43_phy_mask(dev, val_addr,
    268						~(rf_ctrl->val_mask));
    269			} else {
    270				if (core == 0 || ((1 << i) & core)) {
    271					b43_phy_set(dev, en_addr, field);
    272					b43_phy_maskset(dev, val_addr,
    273						~(rf_ctrl->val_mask),
    274						(value << rf_ctrl->val_shift));
    275				}
    276			}
    277		}
    278	} else {
    279		const struct nphy_rf_control_override_rev2 *rf_ctrl;
    280		if (off) {
    281			b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~(field));
    282			value = 0;
    283		} else {
    284			b43_phy_set(dev, B43_NPHY_RFCTL_OVER, field);
    285		}
    286
    287		for (i = 0; i < 2; i++) {
    288			if (index <= 1 || index == 16) {
    289				b43err(dev->wl,
    290					"Unsupported RF Ctrl Override call\n");
    291				return;
    292			}
    293
    294			if (index == 2 || index == 10 ||
    295			    (index >= 13 && index <= 15)) {
    296				core = 1;
    297			}
    298
    299			rf_ctrl = &tbl_rf_control_override_rev2[index - 2];
    300			addr = B43_PHY_N((i == 0) ?
    301				rf_ctrl->addr0 : rf_ctrl->addr1);
    302
    303			if ((1 << i) & core)
    304				b43_phy_maskset(dev, addr, ~(rf_ctrl->bmask),
    305						(value << rf_ctrl->shift));
    306
    307			b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x1);
    308			b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
    309					B43_NPHY_RFCTL_CMD_START);
    310			udelay(1);
    311			b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, 0xFFFE);
    312		}
    313	}
    314}
    315
    316static void b43_nphy_rf_ctl_intc_override_rev7(struct b43_wldev *dev,
    317					       enum n_intc_override intc_override,
    318					       u16 value, u8 core_sel)
    319{
    320	u16 reg, tmp, tmp2, val;
    321	int core;
    322
    323	/* TODO: What about rev19+? Revs 3+ and 7+ are a bit similar */
    324
    325	for (core = 0; core < 2; core++) {
    326		if ((core_sel == 1 && core != 0) ||
    327		    (core_sel == 2 && core != 1))
    328			continue;
    329
    330		reg = (core == 0) ? B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2;
    331
    332		switch (intc_override) {
    333		case N_INTC_OVERRIDE_OFF:
    334			b43_phy_write(dev, reg, 0);
    335			b43_phy_mask(dev, 0x2ff, ~0x2000);
    336			b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
    337			break;
    338		case N_INTC_OVERRIDE_TRSW:
    339			b43_phy_maskset(dev, reg, ~0xC0, value << 6);
    340			b43_phy_set(dev, reg, 0x400);
    341
    342			b43_phy_mask(dev, 0x2ff, ~0xC000 & 0xFFFF);
    343			b43_phy_set(dev, 0x2ff, 0x2000);
    344			b43_phy_set(dev, 0x2ff, 0x0001);
    345			break;
    346		case N_INTC_OVERRIDE_PA:
    347			tmp = 0x0030;
    348			if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
    349				val = value << 5;
    350			else
    351				val = value << 4;
    352			b43_phy_maskset(dev, reg, ~tmp, val);
    353			b43_phy_set(dev, reg, 0x1000);
    354			break;
    355		case N_INTC_OVERRIDE_EXT_LNA_PU:
    356			if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
    357				tmp = 0x0001;
    358				tmp2 = 0x0004;
    359				val = value;
    360			} else {
    361				tmp = 0x0004;
    362				tmp2 = 0x0001;
    363				val = value << 2;
    364			}
    365			b43_phy_maskset(dev, reg, ~tmp, val);
    366			b43_phy_mask(dev, reg, ~tmp2);
    367			break;
    368		case N_INTC_OVERRIDE_EXT_LNA_GAIN:
    369			if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
    370				tmp = 0x0002;
    371				tmp2 = 0x0008;
    372				val = value << 1;
    373			} else {
    374				tmp = 0x0008;
    375				tmp2 = 0x0002;
    376				val = value << 3;
    377			}
    378			b43_phy_maskset(dev, reg, ~tmp, val);
    379			b43_phy_mask(dev, reg, ~tmp2);
    380			break;
    381		}
    382	}
    383}
    384
    385/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlIntcOverride */
    386static void b43_nphy_rf_ctl_intc_override(struct b43_wldev *dev,
    387					  enum n_intc_override intc_override,
    388					  u16 value, u8 core)
    389{
    390	u8 i, j;
    391	u16 reg, tmp, val;
    392
    393	if (dev->phy.rev >= 7) {
    394		b43_nphy_rf_ctl_intc_override_rev7(dev, intc_override, value,
    395						   core);
    396		return;
    397	}
    398
    399	B43_WARN_ON(dev->phy.rev < 3);
    400
    401	for (i = 0; i < 2; i++) {
    402		if ((core == 1 && i == 1) || (core == 2 && !i))
    403			continue;
    404
    405		reg = (i == 0) ?
    406			B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2;
    407		b43_phy_set(dev, reg, 0x400);
    408
    409		switch (intc_override) {
    410		case N_INTC_OVERRIDE_OFF:
    411			b43_phy_write(dev, reg, 0);
    412			b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
    413			break;
    414		case N_INTC_OVERRIDE_TRSW:
    415			if (!i) {
    416				b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC1,
    417						0xFC3F, (value << 6));
    418				b43_phy_maskset(dev, B43_NPHY_TXF_40CO_B1S1,
    419						0xFFFE, 1);
    420				b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
    421						B43_NPHY_RFCTL_CMD_START);
    422				for (j = 0; j < 100; j++) {
    423					if (!(b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_START)) {
    424						j = 0;
    425						break;
    426					}
    427					udelay(10);
    428				}
    429				if (j)
    430					b43err(dev->wl,
    431						"intc override timeout\n");
    432				b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S1,
    433						0xFFFE);
    434			} else {
    435				b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC2,
    436						0xFC3F, (value << 6));
    437				b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
    438						0xFFFE, 1);
    439				b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
    440						B43_NPHY_RFCTL_CMD_RXTX);
    441				for (j = 0; j < 100; j++) {
    442					if (!(b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_RXTX)) {
    443						j = 0;
    444						break;
    445					}
    446					udelay(10);
    447				}
    448				if (j)
    449					b43err(dev->wl,
    450						"intc override timeout\n");
    451				b43_phy_mask(dev, B43_NPHY_RFCTL_OVER,
    452						0xFFFE);
    453			}
    454			break;
    455		case N_INTC_OVERRIDE_PA:
    456			if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
    457				tmp = 0x0020;
    458				val = value << 5;
    459			} else {
    460				tmp = 0x0010;
    461				val = value << 4;
    462			}
    463			b43_phy_maskset(dev, reg, ~tmp, val);
    464			break;
    465		case N_INTC_OVERRIDE_EXT_LNA_PU:
    466			if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
    467				tmp = 0x0001;
    468				val = value;
    469			} else {
    470				tmp = 0x0004;
    471				val = value << 2;
    472			}
    473			b43_phy_maskset(dev, reg, ~tmp, val);
    474			break;
    475		case N_INTC_OVERRIDE_EXT_LNA_GAIN:
    476			if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
    477				tmp = 0x0002;
    478				val = value << 1;
    479			} else {
    480				tmp = 0x0008;
    481				val = value << 3;
    482			}
    483			b43_phy_maskset(dev, reg, ~tmp, val);
    484			break;
    485		}
    486	}
    487}
    488
    489/**************************************************
    490 * Various PHY ops
    491 **************************************************/
    492
    493/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
    494static void b43_nphy_write_clip_detection(struct b43_wldev *dev,
    495					  const u16 *clip_st)
    496{
    497	b43_phy_write(dev, B43_NPHY_C1_CLIP1THRES, clip_st[0]);
    498	b43_phy_write(dev, B43_NPHY_C2_CLIP1THRES, clip_st[1]);
    499}
    500
    501/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
    502static void b43_nphy_read_clip_detection(struct b43_wldev *dev, u16 *clip_st)
    503{
    504	clip_st[0] = b43_phy_read(dev, B43_NPHY_C1_CLIP1THRES);
    505	clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES);
    506}
    507
    508/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */
    509static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)
    510{
    511	u16 tmp;
    512
    513	if (dev->dev->core_rev == 16)
    514		b43_mac_suspend(dev);
    515
    516	tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL);
    517	tmp &= (B43_NPHY_CLASSCTL_CCKEN | B43_NPHY_CLASSCTL_OFDMEN |
    518		B43_NPHY_CLASSCTL_WAITEDEN);
    519	tmp &= ~mask;
    520	tmp |= (val & mask);
    521	b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp);
    522
    523	if (dev->dev->core_rev == 16)
    524		b43_mac_enable(dev);
    525
    526	return tmp;
    527}
    528
    529/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
    530static void b43_nphy_reset_cca(struct b43_wldev *dev)
    531{
    532	u16 bbcfg;
    533
    534	b43_phy_force_clock(dev, 1);
    535	bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG);
    536	b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA);
    537	udelay(1);
    538	b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA);
    539	b43_phy_force_clock(dev, 0);
    540	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
    541}
    542
    543/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/carriersearch */
    544static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable)
    545{
    546	struct b43_phy *phy = &dev->phy;
    547	struct b43_phy_n *nphy = phy->n;
    548
    549	if (enable) {
    550		static const u16 clip[] = { 0xFFFF, 0xFFFF };
    551		if (nphy->deaf_count++ == 0) {
    552			nphy->classifier_state = b43_nphy_classifier(dev, 0, 0);
    553			b43_nphy_classifier(dev, 0x7,
    554					    B43_NPHY_CLASSCTL_WAITEDEN);
    555			b43_nphy_read_clip_detection(dev, nphy->clip_state);
    556			b43_nphy_write_clip_detection(dev, clip);
    557		}
    558		b43_nphy_reset_cca(dev);
    559	} else {
    560		if (--nphy->deaf_count == 0) {
    561			b43_nphy_classifier(dev, 0x7, nphy->classifier_state);
    562			b43_nphy_write_clip_detection(dev, nphy->clip_state);
    563		}
    564	}
    565}
    566
    567/* https://bcm-v4.sipsolutions.net/PHY/N/Read_Lpf_Bw_Ctl */
    568static u16 b43_nphy_read_lpf_ctl(struct b43_wldev *dev, u16 offset)
    569{
    570	if (!offset)
    571		offset = b43_is_40mhz(dev) ? 0x159 : 0x154;
    572	return b43_ntab_read(dev, B43_NTAB16(7, offset)) & 0x7;
    573}
    574
    575/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */
    576static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)
    577{
    578	struct b43_phy_n *nphy = dev->phy.n;
    579
    580	u8 i;
    581	s16 tmp;
    582	u16 data[4];
    583	s16 gain[2];
    584	u16 minmax[2];
    585	static const s16 lna_gain[4] = { -2, 10, 19, 25 };
    586
    587	if (nphy->hang_avoid)
    588		b43_nphy_stay_in_carrier_search(dev, 1);
    589
    590	if (nphy->gain_boost) {
    591		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
    592			gain[0] = 6;
    593			gain[1] = 6;
    594		} else {
    595			tmp = 40370 - 315 * dev->phy.channel;
    596			gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1));
    597			tmp = 23242 - 224 * dev->phy.channel;
    598			gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1));
    599		}
    600	} else {
    601		gain[0] = 0;
    602		gain[1] = 0;
    603	}
    604
    605	for (i = 0; i < 2; i++) {
    606		if (nphy->elna_gain_config) {
    607			data[0] = 19 + gain[i];
    608			data[1] = 25 + gain[i];
    609			data[2] = 25 + gain[i];
    610			data[3] = 25 + gain[i];
    611		} else {
    612			data[0] = lna_gain[0] + gain[i];
    613			data[1] = lna_gain[1] + gain[i];
    614			data[2] = lna_gain[2] + gain[i];
    615			data[3] = lna_gain[3] + gain[i];
    616		}
    617		b43_ntab_write_bulk(dev, B43_NTAB16(i, 8), 4, data);
    618
    619		minmax[i] = 23 + gain[i];
    620	}
    621
    622	b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN, ~B43_NPHY_C1_MINGAIN,
    623				minmax[0] << B43_NPHY_C1_MINGAIN_SHIFT);
    624	b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN, ~B43_NPHY_C2_MINGAIN,
    625				minmax[1] << B43_NPHY_C2_MINGAIN_SHIFT);
    626
    627	if (nphy->hang_avoid)
    628		b43_nphy_stay_in_carrier_search(dev, 0);
    629}
    630
    631/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRfSeq */
    632static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
    633					u8 *events, u8 *delays, u8 length)
    634{
    635	struct b43_phy_n *nphy = dev->phy.n;
    636	u8 i;
    637	u8 end = (dev->phy.rev >= 3) ? 0x1F : 0x0F;
    638	u16 offset1 = cmd << 4;
    639	u16 offset2 = offset1 + 0x80;
    640
    641	if (nphy->hang_avoid)
    642		b43_nphy_stay_in_carrier_search(dev, true);
    643
    644	b43_ntab_write_bulk(dev, B43_NTAB8(7, offset1), length, events);
    645	b43_ntab_write_bulk(dev, B43_NTAB8(7, offset2), length, delays);
    646
    647	for (i = length; i < 16; i++) {
    648		b43_ntab_write(dev, B43_NTAB8(7, offset1 + i), end);
    649		b43_ntab_write(dev, B43_NTAB8(7, offset2 + i), 1);
    650	}
    651
    652	if (nphy->hang_avoid)
    653		b43_nphy_stay_in_carrier_search(dev, false);
    654}
    655
    656/**************************************************
    657 * Radio 0x2057
    658 **************************************************/
    659
    660static void b43_radio_2057_chantab_upload(struct b43_wldev *dev,
    661					  const struct b43_nphy_chantabent_rev7 *e_r7,
    662					  const struct b43_nphy_chantabent_rev7_2g *e_r7_2g)
    663{
    664	if (e_r7_2g) {
    665		b43_radio_write(dev, R2057_VCOCAL_COUNTVAL0, e_r7_2g->radio_vcocal_countval0);
    666		b43_radio_write(dev, R2057_VCOCAL_COUNTVAL1, e_r7_2g->radio_vcocal_countval1);
    667		b43_radio_write(dev, R2057_RFPLL_REFMASTER_SPAREXTALSIZE, e_r7_2g->radio_rfpll_refmaster_sparextalsize);
    668		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, e_r7_2g->radio_rfpll_loopfilter_r1);
    669		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, e_r7_2g->radio_rfpll_loopfilter_c2);
    670		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, e_r7_2g->radio_rfpll_loopfilter_c1);
    671		b43_radio_write(dev, R2057_CP_KPD_IDAC, e_r7_2g->radio_cp_kpd_idac);
    672		b43_radio_write(dev, R2057_RFPLL_MMD0, e_r7_2g->radio_rfpll_mmd0);
    673		b43_radio_write(dev, R2057_RFPLL_MMD1, e_r7_2g->radio_rfpll_mmd1);
    674		b43_radio_write(dev, R2057_VCOBUF_TUNE, e_r7_2g->radio_vcobuf_tune);
    675		b43_radio_write(dev, R2057_LOGEN_MX2G_TUNE, e_r7_2g->radio_logen_mx2g_tune);
    676		b43_radio_write(dev, R2057_LOGEN_INDBUF2G_TUNE, e_r7_2g->radio_logen_indbuf2g_tune);
    677		b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, e_r7_2g->radio_txmix2g_tune_boost_pu_core0);
    678		b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE0, e_r7_2g->radio_pad2g_tune_pus_core0);
    679		b43_radio_write(dev, R2057_LNA2G_TUNE_CORE0, e_r7_2g->radio_lna2g_tune_core0);
    680		b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, e_r7_2g->radio_txmix2g_tune_boost_pu_core1);
    681		b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE1, e_r7_2g->radio_pad2g_tune_pus_core1);
    682		b43_radio_write(dev, R2057_LNA2G_TUNE_CORE1, e_r7_2g->radio_lna2g_tune_core1);
    683
    684	} else {
    685		b43_radio_write(dev, R2057_VCOCAL_COUNTVAL0, e_r7->radio_vcocal_countval0);
    686		b43_radio_write(dev, R2057_VCOCAL_COUNTVAL1, e_r7->radio_vcocal_countval1);
    687		b43_radio_write(dev, R2057_RFPLL_REFMASTER_SPAREXTALSIZE, e_r7->radio_rfpll_refmaster_sparextalsize);
    688		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, e_r7->radio_rfpll_loopfilter_r1);
    689		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, e_r7->radio_rfpll_loopfilter_c2);
    690		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, e_r7->radio_rfpll_loopfilter_c1);
    691		b43_radio_write(dev, R2057_CP_KPD_IDAC, e_r7->radio_cp_kpd_idac);
    692		b43_radio_write(dev, R2057_RFPLL_MMD0, e_r7->radio_rfpll_mmd0);
    693		b43_radio_write(dev, R2057_RFPLL_MMD1, e_r7->radio_rfpll_mmd1);
    694		b43_radio_write(dev, R2057_VCOBUF_TUNE, e_r7->radio_vcobuf_tune);
    695		b43_radio_write(dev, R2057_LOGEN_MX2G_TUNE, e_r7->radio_logen_mx2g_tune);
    696		b43_radio_write(dev, R2057_LOGEN_MX5G_TUNE, e_r7->radio_logen_mx5g_tune);
    697		b43_radio_write(dev, R2057_LOGEN_INDBUF2G_TUNE, e_r7->radio_logen_indbuf2g_tune);
    698		b43_radio_write(dev, R2057_LOGEN_INDBUF5G_TUNE, e_r7->radio_logen_indbuf5g_tune);
    699		b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, e_r7->radio_txmix2g_tune_boost_pu_core0);
    700		b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE0, e_r7->radio_pad2g_tune_pus_core0);
    701		b43_radio_write(dev, R2057_PGA_BOOST_TUNE_CORE0, e_r7->radio_pga_boost_tune_core0);
    702		b43_radio_write(dev, R2057_TXMIX5G_BOOST_TUNE_CORE0, e_r7->radio_txmix5g_boost_tune_core0);
    703		b43_radio_write(dev, R2057_PAD5G_TUNE_MISC_PUS_CORE0, e_r7->radio_pad5g_tune_misc_pus_core0);
    704		b43_radio_write(dev, R2057_LNA2G_TUNE_CORE0, e_r7->radio_lna2g_tune_core0);
    705		b43_radio_write(dev, R2057_LNA5G_TUNE_CORE0, e_r7->radio_lna5g_tune_core0);
    706		b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, e_r7->radio_txmix2g_tune_boost_pu_core1);
    707		b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE1, e_r7->radio_pad2g_tune_pus_core1);
    708		b43_radio_write(dev, R2057_PGA_BOOST_TUNE_CORE1, e_r7->radio_pga_boost_tune_core1);
    709		b43_radio_write(dev, R2057_TXMIX5G_BOOST_TUNE_CORE1, e_r7->radio_txmix5g_boost_tune_core1);
    710		b43_radio_write(dev, R2057_PAD5G_TUNE_MISC_PUS_CORE1, e_r7->radio_pad5g_tune_misc_pus_core1);
    711		b43_radio_write(dev, R2057_LNA2G_TUNE_CORE1, e_r7->radio_lna2g_tune_core1);
    712		b43_radio_write(dev, R2057_LNA5G_TUNE_CORE1, e_r7->radio_lna5g_tune_core1);
    713	}
    714}
    715
    716static void b43_radio_2057_setup(struct b43_wldev *dev,
    717				 const struct b43_nphy_chantabent_rev7 *tabent_r7,
    718				 const struct b43_nphy_chantabent_rev7_2g *tabent_r7_2g)
    719{
    720	struct b43_phy *phy = &dev->phy;
    721
    722	b43_radio_2057_chantab_upload(dev, tabent_r7, tabent_r7_2g);
    723
    724	switch (phy->radio_rev) {
    725	case 0 ... 4:
    726	case 6:
    727		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
    728			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x3f);
    729			b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f);
    730			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x8);
    731			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x8);
    732		} else {
    733			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x1f);
    734			b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f);
    735			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x8);
    736			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x8);
    737		}
    738		break;
    739	case 9: /* e.g. PHY rev 16 */
    740		b43_radio_write(dev, R2057_LOGEN_PTAT_RESETS, 0x20);
    741		b43_radio_write(dev, R2057_VCOBUF_IDACS, 0x18);
    742		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
    743			b43_radio_write(dev, R2057_LOGEN_PTAT_RESETS, 0x38);
    744			b43_radio_write(dev, R2057_VCOBUF_IDACS, 0x0f);
    745
    746			if (b43_is_40mhz(dev)) {
    747				/* TODO */
    748			} else {
    749				b43_radio_write(dev,
    750						R2057_PAD_BIAS_FILTER_BWS_CORE0,
    751						0x3c);
    752				b43_radio_write(dev,
    753						R2057_PAD_BIAS_FILTER_BWS_CORE1,
    754						0x3c);
    755			}
    756		}
    757		break;
    758	case 14: /* 2 GHz only */
    759		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x1b);
    760		b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f);
    761		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x1f);
    762		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x1f);
    763		break;
    764	}
    765
    766	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
    767		u16 txmix2g_tune_boost_pu = 0;
    768		u16 pad2g_tune_pus = 0;
    769
    770		if (b43_nphy_ipa(dev)) {
    771			switch (phy->radio_rev) {
    772			case 9:
    773				txmix2g_tune_boost_pu = 0x0041;
    774				/* TODO */
    775				break;
    776			case 14:
    777				txmix2g_tune_boost_pu = 0x21;
    778				pad2g_tune_pus = 0x23;
    779				break;
    780			}
    781		}
    782
    783		if (txmix2g_tune_boost_pu)
    784			b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0,
    785					txmix2g_tune_boost_pu);
    786		if (pad2g_tune_pus)
    787			b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE0,
    788					pad2g_tune_pus);
    789		if (txmix2g_tune_boost_pu)
    790			b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1,
    791					txmix2g_tune_boost_pu);
    792		if (pad2g_tune_pus)
    793			b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE1,
    794					pad2g_tune_pus);
    795	}
    796
    797	usleep_range(50, 100);
    798
    799	/* VCO calibration */
    800	b43_radio_mask(dev, R2057_RFPLL_MISC_EN, ~0x01);
    801	b43_radio_mask(dev, R2057_RFPLL_MISC_CAL_RESETN, ~0x04);
    802	b43_radio_set(dev, R2057_RFPLL_MISC_CAL_RESETN, 0x4);
    803	b43_radio_set(dev, R2057_RFPLL_MISC_EN, 0x01);
    804	usleep_range(300, 600);
    805}
    806
    807/* Calibrate resistors in LPF of PLL?
    808 * https://bcm-v4.sipsolutions.net/PHY/radio205x_rcal
    809 */
    810static u8 b43_radio_2057_rcal(struct b43_wldev *dev)
    811{
    812	struct b43_phy *phy = &dev->phy;
    813	u16 saved_regs_phy[12];
    814	u16 saved_regs_phy_rf[6];
    815	u16 saved_regs_radio[2] = { };
    816	static const u16 phy_to_store[] = {
    817		B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2,
    818		B43_NPHY_RFCTL_LUT_TRSW_LO1, B43_NPHY_RFCTL_LUT_TRSW_LO2,
    819		B43_NPHY_RFCTL_RXG1, B43_NPHY_RFCTL_RXG2,
    820		B43_NPHY_RFCTL_TXG1, B43_NPHY_RFCTL_TXG2,
    821		B43_NPHY_REV7_RF_CTL_MISC_REG3, B43_NPHY_REV7_RF_CTL_MISC_REG4,
    822		B43_NPHY_REV7_RF_CTL_MISC_REG5, B43_NPHY_REV7_RF_CTL_MISC_REG6,
    823	};
    824	static const u16 phy_to_store_rf[] = {
    825		B43_NPHY_REV3_RFCTL_OVER0, B43_NPHY_REV3_RFCTL_OVER1,
    826		B43_NPHY_REV7_RF_CTL_OVER3, B43_NPHY_REV7_RF_CTL_OVER4,
    827		B43_NPHY_REV7_RF_CTL_OVER5, B43_NPHY_REV7_RF_CTL_OVER6,
    828	};
    829	u16 tmp;
    830	int i;
    831
    832	/* Save */
    833	for (i = 0; i < ARRAY_SIZE(phy_to_store); i++)
    834		saved_regs_phy[i] = b43_phy_read(dev, phy_to_store[i]);
    835	for (i = 0; i < ARRAY_SIZE(phy_to_store_rf); i++)
    836		saved_regs_phy_rf[i] = b43_phy_read(dev, phy_to_store_rf[i]);
    837
    838	/* Set */
    839	for (i = 0; i < ARRAY_SIZE(phy_to_store); i++)
    840		b43_phy_write(dev, phy_to_store[i], 0);
    841	b43_phy_write(dev, B43_NPHY_REV3_RFCTL_OVER0, 0x07ff);
    842	b43_phy_write(dev, B43_NPHY_REV3_RFCTL_OVER1, 0x07ff);
    843	b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x07ff);
    844	b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER4, 0x07ff);
    845	b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER5, 0x007f);
    846	b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER6, 0x007f);
    847
    848	switch (phy->radio_rev) {
    849	case 5:
    850		b43_phy_mask(dev, B43_NPHY_REV7_RF_CTL_OVER3, ~0x2);
    851		udelay(10);
    852		b43_radio_set(dev, R2057_IQTEST_SEL_PU, 0x1);
    853		b43_radio_maskset(dev, R2057v7_IQTEST_SEL_PU2, ~0x2, 0x1);
    854		break;
    855	case 9:
    856		b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x2);
    857		b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_MISC_REG3, 0x2);
    858		saved_regs_radio[0] = b43_radio_read(dev, R2057_IQTEST_SEL_PU);
    859		b43_radio_write(dev, R2057_IQTEST_SEL_PU, 0x11);
    860		break;
    861	case 14:
    862		saved_regs_radio[0] = b43_radio_read(dev, R2057_IQTEST_SEL_PU);
    863		saved_regs_radio[1] = b43_radio_read(dev, R2057v7_IQTEST_SEL_PU2);
    864		b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_MISC_REG3, 0x2);
    865		b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x2);
    866		b43_radio_write(dev, R2057v7_IQTEST_SEL_PU2, 0x2);
    867		b43_radio_write(dev, R2057_IQTEST_SEL_PU, 0x1);
    868		break;
    869	}
    870
    871	/* Enable */
    872	b43_radio_set(dev, R2057_RCAL_CONFIG, 0x1);
    873	udelay(10);
    874
    875	/* Start */
    876	b43_radio_set(dev, R2057_RCAL_CONFIG, 0x2);
    877	usleep_range(100, 200);
    878
    879	/* Stop */
    880	b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x2);
    881
    882	/* Wait and check for result */
    883	if (!b43_radio_wait_value(dev, R2057_RCAL_STATUS, 1, 1, 100, 1000000)) {
    884		b43err(dev->wl, "Radio 0x2057 rcal timeout\n");
    885		return 0;
    886	}
    887	tmp = b43_radio_read(dev, R2057_RCAL_STATUS) & 0x3E;
    888
    889	/* Disable */
    890	b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x1);
    891
    892	/* Restore */
    893	for (i = 0; i < ARRAY_SIZE(phy_to_store_rf); i++)
    894		b43_phy_write(dev, phy_to_store_rf[i], saved_regs_phy_rf[i]);
    895	for (i = 0; i < ARRAY_SIZE(phy_to_store); i++)
    896		b43_phy_write(dev, phy_to_store[i], saved_regs_phy[i]);
    897
    898	switch (phy->radio_rev) {
    899	case 0 ... 4:
    900	case 6:
    901		b43_radio_maskset(dev, R2057_TEMPSENSE_CONFIG, ~0x3C, tmp);
    902		b43_radio_maskset(dev, R2057_BANDGAP_RCAL_TRIM, ~0xF0,
    903				  tmp << 2);
    904		break;
    905	case 5:
    906		b43_radio_mask(dev, R2057_IPA2G_CASCONV_CORE0, ~0x1);
    907		b43_radio_mask(dev, R2057v7_IQTEST_SEL_PU2, ~0x2);
    908		break;
    909	case 9:
    910		b43_radio_write(dev, R2057_IQTEST_SEL_PU, saved_regs_radio[0]);
    911		break;
    912	case 14:
    913		b43_radio_write(dev, R2057_IQTEST_SEL_PU, saved_regs_radio[0]);
    914		b43_radio_write(dev, R2057v7_IQTEST_SEL_PU2, saved_regs_radio[1]);
    915		break;
    916	}
    917
    918	return tmp & 0x3e;
    919}
    920
    921/* Calibrate the internal RC oscillator?
    922 * https://bcm-v4.sipsolutions.net/PHY/radio2057_rccal
    923 */
    924static u16 b43_radio_2057_rccal(struct b43_wldev *dev)
    925{
    926	struct b43_phy *phy = &dev->phy;
    927	bool special = (phy->radio_rev == 3 || phy->radio_rev == 4 ||
    928			phy->radio_rev == 6);
    929	u16 tmp;
    930
    931	/* Setup cal */
    932	if (special) {
    933		b43_radio_write(dev, R2057_RCCAL_MASTER, 0x61);
    934		b43_radio_write(dev, R2057_RCCAL_TRC0, 0xC0);
    935	} else {
    936		b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x61);
    937		b43_radio_write(dev, R2057_RCCAL_TRC0, 0xE9);
    938	}
    939	b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
    940
    941	/* Start, wait, stop */
    942	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
    943	if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500,
    944				  5000000))
    945		b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n");
    946	usleep_range(35, 70);
    947	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
    948	usleep_range(70, 140);
    949
    950	/* Setup cal */
    951	if (special) {
    952		b43_radio_write(dev, R2057_RCCAL_MASTER, 0x69);
    953		b43_radio_write(dev, R2057_RCCAL_TRC0, 0xB0);
    954	} else {
    955		b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x69);
    956		b43_radio_write(dev, R2057_RCCAL_TRC0, 0xD5);
    957	}
    958	b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
    959
    960	/* Start, wait, stop */
    961	usleep_range(35, 70);
    962	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
    963	usleep_range(70, 140);
    964	if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500,
    965				  5000000))
    966		b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n");
    967	usleep_range(35, 70);
    968	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
    969	usleep_range(70, 140);
    970
    971	/* Setup cal */
    972	if (special) {
    973		b43_radio_write(dev, R2057_RCCAL_MASTER, 0x73);
    974		b43_radio_write(dev, R2057_RCCAL_X1, 0x28);
    975		b43_radio_write(dev, R2057_RCCAL_TRC0, 0xB0);
    976	} else {
    977		b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x73);
    978		b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
    979		b43_radio_write(dev, R2057_RCCAL_TRC0, 0x99);
    980	}
    981
    982	/* Start, wait, stop */
    983	usleep_range(35, 70);
    984	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
    985	usleep_range(70, 140);
    986	if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500,
    987				  5000000)) {
    988		b43err(dev->wl, "Radio 0x2057 rcal timeout\n");
    989		return 0;
    990	}
    991	tmp = b43_radio_read(dev, R2057_RCCAL_DONE_OSCCAP);
    992	usleep_range(35, 70);
    993	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
    994	usleep_range(70, 140);
    995
    996	if (special)
    997		b43_radio_mask(dev, R2057_RCCAL_MASTER, ~0x1);
    998	else
    999		b43_radio_mask(dev, R2057v7_RCCAL_MASTER, ~0x1);
   1000
   1001	return tmp;
   1002}
   1003
   1004static void b43_radio_2057_init_pre(struct b43_wldev *dev)
   1005{
   1006	b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, ~B43_NPHY_RFCTL_CMD_CHIP0PU);
   1007	/* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */
   1008	b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_OEPORFORCE);
   1009	b43_phy_set(dev, B43_NPHY_RFCTL_CMD, ~B43_NPHY_RFCTL_CMD_OEPORFORCE);
   1010	b43_phy_set(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_CHIP0PU);
   1011}
   1012
   1013static void b43_radio_2057_init_post(struct b43_wldev *dev)
   1014{
   1015	b43_radio_set(dev, R2057_XTALPUOVR_PINCTRL, 0x1);
   1016
   1017	if (0) /* FIXME: Is this BCM43217 specific? */
   1018		b43_radio_set(dev, R2057_XTALPUOVR_PINCTRL, 0x2);
   1019
   1020	b43_radio_set(dev, R2057_RFPLL_MISC_CAL_RESETN, 0x78);
   1021	b43_radio_set(dev, R2057_XTAL_CONFIG2, 0x80);
   1022	usleep_range(2000, 3000);
   1023	b43_radio_mask(dev, R2057_RFPLL_MISC_CAL_RESETN, ~0x78);
   1024	b43_radio_mask(dev, R2057_XTAL_CONFIG2, ~0x80);
   1025
   1026	if (dev->phy.do_full_init) {
   1027		b43_radio_2057_rcal(dev);
   1028		b43_radio_2057_rccal(dev);
   1029	}
   1030	b43_radio_mask(dev, R2057_RFPLL_MASTER, ~0x8);
   1031}
   1032
   1033/* https://bcm-v4.sipsolutions.net/802.11/Radio/2057/Init */
   1034static void b43_radio_2057_init(struct b43_wldev *dev)
   1035{
   1036	b43_radio_2057_init_pre(dev);
   1037	r2057_upload_inittabs(dev);
   1038	b43_radio_2057_init_post(dev);
   1039}
   1040
   1041/**************************************************
   1042 * Radio 0x2056
   1043 **************************************************/
   1044
   1045static void b43_chantab_radio_2056_upload(struct b43_wldev *dev,
   1046				const struct b43_nphy_channeltab_entry_rev3 *e)
   1047{
   1048	b43_radio_write(dev, B2056_SYN_PLL_VCOCAL1, e->radio_syn_pll_vcocal1);
   1049	b43_radio_write(dev, B2056_SYN_PLL_VCOCAL2, e->radio_syn_pll_vcocal2);
   1050	b43_radio_write(dev, B2056_SYN_PLL_REFDIV, e->radio_syn_pll_refdiv);
   1051	b43_radio_write(dev, B2056_SYN_PLL_MMD2, e->radio_syn_pll_mmd2);
   1052	b43_radio_write(dev, B2056_SYN_PLL_MMD1, e->radio_syn_pll_mmd1);
   1053	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1,
   1054					e->radio_syn_pll_loopfilter1);
   1055	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2,
   1056					e->radio_syn_pll_loopfilter2);
   1057	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER3,
   1058					e->radio_syn_pll_loopfilter3);
   1059	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4,
   1060					e->radio_syn_pll_loopfilter4);
   1061	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER5,
   1062					e->radio_syn_pll_loopfilter5);
   1063	b43_radio_write(dev, B2056_SYN_RESERVED_ADDR27,
   1064					e->radio_syn_reserved_addr27);
   1065	b43_radio_write(dev, B2056_SYN_RESERVED_ADDR28,
   1066					e->radio_syn_reserved_addr28);
   1067	b43_radio_write(dev, B2056_SYN_RESERVED_ADDR29,
   1068					e->radio_syn_reserved_addr29);
   1069	b43_radio_write(dev, B2056_SYN_LOGEN_VCOBUF1,
   1070					e->radio_syn_logen_vcobuf1);
   1071	b43_radio_write(dev, B2056_SYN_LOGEN_MIXER2, e->radio_syn_logen_mixer2);
   1072	b43_radio_write(dev, B2056_SYN_LOGEN_BUF3, e->radio_syn_logen_buf3);
   1073	b43_radio_write(dev, B2056_SYN_LOGEN_BUF4, e->radio_syn_logen_buf4);
   1074
   1075	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA_TUNE,
   1076					e->radio_rx0_lnaa_tune);
   1077	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG_TUNE,
   1078					e->radio_rx0_lnag_tune);
   1079
   1080	b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAA_BOOST_TUNE,
   1081					e->radio_tx0_intpaa_boost_tune);
   1082	b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAG_BOOST_TUNE,
   1083					e->radio_tx0_intpag_boost_tune);
   1084	b43_radio_write(dev, B2056_TX0 | B2056_TX_PADA_BOOST_TUNE,
   1085					e->radio_tx0_pada_boost_tune);
   1086	b43_radio_write(dev, B2056_TX0 | B2056_TX_PADG_BOOST_TUNE,
   1087					e->radio_tx0_padg_boost_tune);
   1088	b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAA_BOOST_TUNE,
   1089					e->radio_tx0_pgaa_boost_tune);
   1090	b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAG_BOOST_TUNE,
   1091					e->radio_tx0_pgag_boost_tune);
   1092	b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXA_BOOST_TUNE,
   1093					e->radio_tx0_mixa_boost_tune);
   1094	b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXG_BOOST_TUNE,
   1095					e->radio_tx0_mixg_boost_tune);
   1096
   1097	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA_TUNE,
   1098					e->radio_rx1_lnaa_tune);
   1099	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG_TUNE,
   1100					e->radio_rx1_lnag_tune);
   1101
   1102	b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAA_BOOST_TUNE,
   1103					e->radio_tx1_intpaa_boost_tune);
   1104	b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAG_BOOST_TUNE,
   1105					e->radio_tx1_intpag_boost_tune);
   1106	b43_radio_write(dev, B2056_TX1 | B2056_TX_PADA_BOOST_TUNE,
   1107					e->radio_tx1_pada_boost_tune);
   1108	b43_radio_write(dev, B2056_TX1 | B2056_TX_PADG_BOOST_TUNE,
   1109					e->radio_tx1_padg_boost_tune);
   1110	b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAA_BOOST_TUNE,
   1111					e->radio_tx1_pgaa_boost_tune);
   1112	b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAG_BOOST_TUNE,
   1113					e->radio_tx1_pgag_boost_tune);
   1114	b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXA_BOOST_TUNE,
   1115					e->radio_tx1_mixa_boost_tune);
   1116	b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXG_BOOST_TUNE,
   1117					e->radio_tx1_mixg_boost_tune);
   1118}
   1119
   1120/* https://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2056Setup */
   1121static void b43_radio_2056_setup(struct b43_wldev *dev,
   1122				const struct b43_nphy_channeltab_entry_rev3 *e)
   1123{
   1124	struct b43_phy *phy = &dev->phy;
   1125	struct ssb_sprom *sprom = dev->dev->bus_sprom;
   1126	enum nl80211_band band = b43_current_band(dev->wl);
   1127	u16 offset;
   1128	u8 i;
   1129	u16 bias, cbias;
   1130	u16 pag_boost, padg_boost, pgag_boost, mixg_boost;
   1131	u16 paa_boost, pada_boost, pgaa_boost, mixa_boost;
   1132	bool is_pkg_fab_smic;
   1133
   1134	B43_WARN_ON(dev->phy.rev < 3);
   1135
   1136	is_pkg_fab_smic =
   1137		((dev->dev->chip_id == BCMA_CHIP_ID_BCM43224 ||
   1138		  dev->dev->chip_id == BCMA_CHIP_ID_BCM43225 ||
   1139		  dev->dev->chip_id == BCMA_CHIP_ID_BCM43421) &&
   1140		 dev->dev->chip_pkg == BCMA_PKG_ID_BCM43224_FAB_SMIC);
   1141
   1142	b43_chantab_radio_2056_upload(dev, e);
   1143	b2056_upload_syn_pll_cp2(dev, band == NL80211_BAND_5GHZ);
   1144
   1145	if (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
   1146	    b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
   1147		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
   1148		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F);
   1149		if (dev->dev->chip_id == BCMA_CHIP_ID_BCM4716 ||
   1150		    dev->dev->chip_id == BCMA_CHIP_ID_BCM47162) {
   1151			b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x14);
   1152			b43_radio_write(dev, B2056_SYN_PLL_CP2, 0);
   1153		} else {
   1154			b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x0B);
   1155			b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x14);
   1156		}
   1157	}
   1158	if (sprom->boardflags2_hi & B43_BFH2_GPLL_WAR2 &&
   1159	    b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
   1160		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1f);
   1161		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1f);
   1162		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x0b);
   1163		b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x20);
   1164	}
   1165	if (sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
   1166	    b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
   1167		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
   1168		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F);
   1169		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x05);
   1170		b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x0C);
   1171	}
   1172
   1173	if (dev->phy.n->ipa2g_on && band == NL80211_BAND_2GHZ) {
   1174		for (i = 0; i < 2; i++) {
   1175			offset = i ? B2056_TX1 : B2056_TX0;
   1176			if (dev->phy.rev >= 5) {
   1177				b43_radio_write(dev,
   1178					offset | B2056_TX_PADG_IDAC, 0xcc);
   1179
   1180				if (dev->dev->chip_id == BCMA_CHIP_ID_BCM4716 ||
   1181				    dev->dev->chip_id == BCMA_CHIP_ID_BCM47162) {
   1182					bias = 0x40;
   1183					cbias = 0x45;
   1184					pag_boost = 0x5;
   1185					pgag_boost = 0x33;
   1186					mixg_boost = 0x55;
   1187				} else {
   1188					bias = 0x25;
   1189					cbias = 0x20;
   1190					if (is_pkg_fab_smic) {
   1191						bias = 0x2a;
   1192						cbias = 0x38;
   1193					}
   1194					pag_boost = 0x4;
   1195					pgag_boost = 0x03;
   1196					mixg_boost = 0x65;
   1197				}
   1198				padg_boost = 0x77;
   1199
   1200				b43_radio_write(dev,
   1201					offset | B2056_TX_INTPAG_IMAIN_STAT,
   1202					bias);
   1203				b43_radio_write(dev,
   1204					offset | B2056_TX_INTPAG_IAUX_STAT,
   1205					bias);
   1206				b43_radio_write(dev,
   1207					offset | B2056_TX_INTPAG_CASCBIAS,
   1208					cbias);
   1209				b43_radio_write(dev,
   1210					offset | B2056_TX_INTPAG_BOOST_TUNE,
   1211					pag_boost);
   1212				b43_radio_write(dev,
   1213					offset | B2056_TX_PGAG_BOOST_TUNE,
   1214					pgag_boost);
   1215				b43_radio_write(dev,
   1216					offset | B2056_TX_PADG_BOOST_TUNE,
   1217					padg_boost);
   1218				b43_radio_write(dev,
   1219					offset | B2056_TX_MIXG_BOOST_TUNE,
   1220					mixg_boost);
   1221			} else {
   1222				bias = b43_is_40mhz(dev) ? 0x40 : 0x20;
   1223				b43_radio_write(dev,
   1224					offset | B2056_TX_INTPAG_IMAIN_STAT,
   1225					bias);
   1226				b43_radio_write(dev,
   1227					offset | B2056_TX_INTPAG_IAUX_STAT,
   1228					bias);
   1229				b43_radio_write(dev,
   1230					offset | B2056_TX_INTPAG_CASCBIAS,
   1231					0x30);
   1232			}
   1233			b43_radio_write(dev, offset | B2056_TX_PA_SPARE1, 0xee);
   1234		}
   1235	} else if (dev->phy.n->ipa5g_on && band == NL80211_BAND_5GHZ) {
   1236		u16 freq = phy->chandef->chan->center_freq;
   1237		if (freq < 5100) {
   1238			paa_boost = 0xA;
   1239			pada_boost = 0x77;
   1240			pgaa_boost = 0xF;
   1241			mixa_boost = 0xF;
   1242		} else if (freq < 5340) {
   1243			paa_boost = 0x8;
   1244			pada_boost = 0x77;
   1245			pgaa_boost = 0xFB;
   1246			mixa_boost = 0xF;
   1247		} else if (freq < 5650) {
   1248			paa_boost = 0x0;
   1249			pada_boost = 0x77;
   1250			pgaa_boost = 0xB;
   1251			mixa_boost = 0xF;
   1252		} else {
   1253			paa_boost = 0x0;
   1254			pada_boost = 0x77;
   1255			if (freq != 5825)
   1256				pgaa_boost = -(freq - 18) / 36 + 168;
   1257			else
   1258				pgaa_boost = 6;
   1259			mixa_boost = 0xF;
   1260		}
   1261
   1262		cbias = is_pkg_fab_smic ? 0x35 : 0x30;
   1263
   1264		for (i = 0; i < 2; i++) {
   1265			offset = i ? B2056_TX1 : B2056_TX0;
   1266
   1267			b43_radio_write(dev,
   1268				offset | B2056_TX_INTPAA_BOOST_TUNE, paa_boost);
   1269			b43_radio_write(dev,
   1270				offset | B2056_TX_PADA_BOOST_TUNE, pada_boost);
   1271			b43_radio_write(dev,
   1272				offset | B2056_TX_PGAA_BOOST_TUNE, pgaa_boost);
   1273			b43_radio_write(dev,
   1274				offset | B2056_TX_MIXA_BOOST_TUNE, mixa_boost);
   1275			b43_radio_write(dev,
   1276				offset | B2056_TX_TXSPARE1, 0x30);
   1277			b43_radio_write(dev,
   1278				offset | B2056_TX_PA_SPARE2, 0xee);
   1279			b43_radio_write(dev,
   1280				offset | B2056_TX_PADA_CASCBIAS, 0x03);
   1281			b43_radio_write(dev,
   1282				offset | B2056_TX_INTPAA_IAUX_STAT, 0x30);
   1283			b43_radio_write(dev,
   1284				offset | B2056_TX_INTPAA_IMAIN_STAT, 0x30);
   1285			b43_radio_write(dev,
   1286				offset | B2056_TX_INTPAA_CASCBIAS, cbias);
   1287		}
   1288	}
   1289
   1290	udelay(50);
   1291	/* VCO calibration */
   1292	b43_radio_write(dev, B2056_SYN_PLL_VCOCAL12, 0x00);
   1293	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38);
   1294	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x18);
   1295	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38);
   1296	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x39);
   1297	udelay(300);
   1298}
   1299
   1300static u8 b43_radio_2056_rcal(struct b43_wldev *dev)
   1301{
   1302	struct b43_phy *phy = &dev->phy;
   1303	u16 mast2, tmp;
   1304
   1305	if (phy->rev != 3)
   1306		return 0;
   1307
   1308	mast2 = b43_radio_read(dev, B2056_SYN_PLL_MAST2);
   1309	b43_radio_write(dev, B2056_SYN_PLL_MAST2, mast2 | 0x7);
   1310
   1311	udelay(10);
   1312	b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x01);
   1313	udelay(10);
   1314	b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x09);
   1315
   1316	if (!b43_radio_wait_value(dev, B2056_SYN_RCAL_CODE_OUT, 0x80, 0x80, 100,
   1317				  1000000)) {
   1318		b43err(dev->wl, "Radio recalibration timeout\n");
   1319		return 0;
   1320	}
   1321
   1322	b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x01);
   1323	tmp = b43_radio_read(dev, B2056_SYN_RCAL_CODE_OUT);
   1324	b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x00);
   1325
   1326	b43_radio_write(dev, B2056_SYN_PLL_MAST2, mast2);
   1327
   1328	return tmp & 0x1f;
   1329}
   1330
   1331static void b43_radio_init2056_pre(struct b43_wldev *dev)
   1332{
   1333	b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
   1334		     ~B43_NPHY_RFCTL_CMD_CHIP0PU);
   1335	/* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */
   1336	b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
   1337		     B43_NPHY_RFCTL_CMD_OEPORFORCE);
   1338	b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
   1339		    ~B43_NPHY_RFCTL_CMD_OEPORFORCE);
   1340	b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
   1341		    B43_NPHY_RFCTL_CMD_CHIP0PU);
   1342}
   1343
   1344static void b43_radio_init2056_post(struct b43_wldev *dev)
   1345{
   1346	b43_radio_set(dev, B2056_SYN_COM_CTRL, 0xB);
   1347	b43_radio_set(dev, B2056_SYN_COM_PU, 0x2);
   1348	b43_radio_set(dev, B2056_SYN_COM_RESET, 0x2);
   1349	msleep(1);
   1350	b43_radio_mask(dev, B2056_SYN_COM_RESET, ~0x2);
   1351	b43_radio_mask(dev, B2056_SYN_PLL_MAST2, ~0xFC);
   1352	b43_radio_mask(dev, B2056_SYN_RCCAL_CTRL0, ~0x1);
   1353	if (dev->phy.do_full_init)
   1354		b43_radio_2056_rcal(dev);
   1355}
   1356
   1357/*
   1358 * Initialize a Broadcom 2056 N-radio
   1359 * https://bcm-v4.sipsolutions.net/802.11/Radio/2056/Init
   1360 */
   1361static void b43_radio_init2056(struct b43_wldev *dev)
   1362{
   1363	b43_radio_init2056_pre(dev);
   1364	b2056_upload_inittabs(dev, 0, 0);
   1365	b43_radio_init2056_post(dev);
   1366}
   1367
   1368/**************************************************
   1369 * Radio 0x2055
   1370 **************************************************/
   1371
   1372static void b43_chantab_radio_upload(struct b43_wldev *dev,
   1373				const struct b43_nphy_channeltab_entry_rev2 *e)
   1374{
   1375	b43_radio_write(dev, B2055_PLL_REF, e->radio_pll_ref);
   1376	b43_radio_write(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0);
   1377	b43_radio_write(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1);
   1378	b43_radio_write(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail);
   1379	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
   1380
   1381	b43_radio_write(dev, B2055_VCO_CAL1, e->radio_vco_cal1);
   1382	b43_radio_write(dev, B2055_VCO_CAL2, e->radio_vco_cal2);
   1383	b43_radio_write(dev, B2055_PLL_LFC1, e->radio_pll_lfc1);
   1384	b43_radio_write(dev, B2055_PLL_LFR1, e->radio_pll_lfr1);
   1385	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
   1386
   1387	b43_radio_write(dev, B2055_PLL_LFC2, e->radio_pll_lfc2);
   1388	b43_radio_write(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf);
   1389	b43_radio_write(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1);
   1390	b43_radio_write(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2);
   1391	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
   1392
   1393	b43_radio_write(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune);
   1394	b43_radio_write(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune);
   1395	b43_radio_write(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1);
   1396	b43_radio_write(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn);
   1397	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
   1398
   1399	b43_radio_write(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim);
   1400	b43_radio_write(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune);
   1401	b43_radio_write(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune);
   1402	b43_radio_write(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1);
   1403	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
   1404
   1405	b43_radio_write(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn);
   1406	b43_radio_write(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim);
   1407}
   1408
   1409/* https://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */
   1410static void b43_radio_2055_setup(struct b43_wldev *dev,
   1411				const struct b43_nphy_channeltab_entry_rev2 *e)
   1412{
   1413	B43_WARN_ON(dev->phy.rev >= 3);
   1414
   1415	b43_chantab_radio_upload(dev, e);
   1416	udelay(50);
   1417	b43_radio_write(dev, B2055_VCO_CAL10, 0x05);
   1418	b43_radio_write(dev, B2055_VCO_CAL10, 0x45);
   1419	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
   1420	b43_radio_write(dev, B2055_VCO_CAL10, 0x65);
   1421	udelay(300);
   1422}
   1423
   1424static void b43_radio_init2055_pre(struct b43_wldev *dev)
   1425{
   1426	b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
   1427		     ~B43_NPHY_RFCTL_CMD_PORFORCE);
   1428	b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
   1429		    B43_NPHY_RFCTL_CMD_CHIP0PU |
   1430		    B43_NPHY_RFCTL_CMD_OEPORFORCE);
   1431	b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
   1432		    B43_NPHY_RFCTL_CMD_PORFORCE);
   1433}
   1434
   1435static void b43_radio_init2055_post(struct b43_wldev *dev)
   1436{
   1437	struct b43_phy_n *nphy = dev->phy.n;
   1438	struct ssb_sprom *sprom = dev->dev->bus_sprom;
   1439	bool workaround = false;
   1440
   1441	if (sprom->revision < 4)
   1442		workaround = (dev->dev->board_vendor != PCI_VENDOR_ID_BROADCOM
   1443			      && dev->dev->board_type == SSB_BOARD_CB2_4321
   1444			      && dev->dev->board_rev >= 0x41);
   1445	else
   1446		workaround =
   1447			!(sprom->boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS);
   1448
   1449	b43_radio_mask(dev, B2055_MASTER1, 0xFFF3);
   1450	if (workaround) {
   1451		b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F);
   1452		b43_radio_mask(dev, B2055_C2_RX_BB_REG, 0x7F);
   1453	}
   1454	b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0xFFC0, 0x2C);
   1455	b43_radio_write(dev, B2055_CAL_MISC, 0x3C);
   1456	b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE);
   1457	b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80);
   1458	b43_radio_set(dev, B2055_CAL_MISC, 0x1);
   1459	msleep(1);
   1460	b43_radio_set(dev, B2055_CAL_MISC, 0x40);
   1461	if (!b43_radio_wait_value(dev, B2055_CAL_COUT2, 0x80, 0x80, 10, 2000))
   1462		b43err(dev->wl, "radio post init timeout\n");
   1463	b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F);
   1464	b43_switch_channel(dev, dev->phy.channel);
   1465	b43_radio_write(dev, B2055_C1_RX_BB_LPF, 0x9);
   1466	b43_radio_write(dev, B2055_C2_RX_BB_LPF, 0x9);
   1467	b43_radio_write(dev, B2055_C1_RX_BB_MIDACHP, 0x83);
   1468	b43_radio_write(dev, B2055_C2_RX_BB_MIDACHP, 0x83);
   1469	b43_radio_maskset(dev, B2055_C1_LNA_GAINBST, 0xFFF8, 0x6);
   1470	b43_radio_maskset(dev, B2055_C2_LNA_GAINBST, 0xFFF8, 0x6);
   1471	if (!nphy->gain_boost) {
   1472		b43_radio_set(dev, B2055_C1_RX_RFSPC1, 0x2);
   1473		b43_radio_set(dev, B2055_C2_RX_RFSPC1, 0x2);
   1474	} else {
   1475		b43_radio_mask(dev, B2055_C1_RX_RFSPC1, 0xFFFD);
   1476		b43_radio_mask(dev, B2055_C2_RX_RFSPC1, 0xFFFD);
   1477	}
   1478	udelay(2);
   1479}
   1480
   1481/*
   1482 * Initialize a Broadcom 2055 N-radio
   1483 * https://bcm-v4.sipsolutions.net/802.11/Radio/2055/Init
   1484 */
   1485static void b43_radio_init2055(struct b43_wldev *dev)
   1486{
   1487	b43_radio_init2055_pre(dev);
   1488	if (b43_status(dev) < B43_STAT_INITIALIZED) {
   1489		/* Follow wl, not specs. Do not force uploading all regs */
   1490		b2055_upload_inittab(dev, 0, 0);
   1491	} else {
   1492		bool ghz5 = b43_current_band(dev->wl) == NL80211_BAND_5GHZ;
   1493		b2055_upload_inittab(dev, ghz5, 0);
   1494	}
   1495	b43_radio_init2055_post(dev);
   1496}
   1497
   1498/**************************************************
   1499 * Samples
   1500 **************************************************/
   1501
   1502/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/LoadSampleTable */
   1503static int b43_nphy_load_samples(struct b43_wldev *dev,
   1504					struct cordic_iq *samples, u16 len) {
   1505	struct b43_phy_n *nphy = dev->phy.n;
   1506	u16 i;
   1507	u32 *data;
   1508
   1509	data = kcalloc(len, sizeof(u32), GFP_KERNEL);
   1510	if (!data) {
   1511		b43err(dev->wl, "allocation for samples loading failed\n");
   1512		return -ENOMEM;
   1513	}
   1514	if (nphy->hang_avoid)
   1515		b43_nphy_stay_in_carrier_search(dev, 1);
   1516
   1517	for (i = 0; i < len; i++) {
   1518		data[i] = (samples[i].i & 0x3FF << 10);
   1519		data[i] |= samples[i].q & 0x3FF;
   1520	}
   1521	b43_ntab_write_bulk(dev, B43_NTAB32(17, 0), len, data);
   1522
   1523	kfree(data);
   1524	if (nphy->hang_avoid)
   1525		b43_nphy_stay_in_carrier_search(dev, 0);
   1526	return 0;
   1527}
   1528
   1529/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/GenLoadSamples */
   1530static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max,
   1531					bool test)
   1532{
   1533	int i;
   1534	u16 bw, len, rot, angle;
   1535	struct cordic_iq *samples;
   1536
   1537	bw = b43_is_40mhz(dev) ? 40 : 20;
   1538	len = bw << 3;
   1539
   1540	if (test) {
   1541		if (b43_phy_read(dev, B43_NPHY_BBCFG) & B43_NPHY_BBCFG_RSTRX)
   1542			bw = 82;
   1543		else
   1544			bw = 80;
   1545
   1546		if (b43_is_40mhz(dev))
   1547			bw <<= 1;
   1548
   1549		len = bw << 1;
   1550	}
   1551
   1552	samples = kcalloc(len, sizeof(struct cordic_iq), GFP_KERNEL);
   1553	if (!samples) {
   1554		b43err(dev->wl, "allocation for samples generation failed\n");
   1555		return 0;
   1556	}
   1557	rot = (((freq * 36) / bw) << 16) / 100;
   1558	angle = 0;
   1559
   1560	for (i = 0; i < len; i++) {
   1561		samples[i] = cordic_calc_iq(CORDIC_FIXED(angle));
   1562		angle += rot;
   1563		samples[i].q = CORDIC_FLOAT(samples[i].q * max);
   1564		samples[i].i = CORDIC_FLOAT(samples[i].i * max);
   1565	}
   1566
   1567	i = b43_nphy_load_samples(dev, samples, len);
   1568	kfree(samples);
   1569	return (i < 0) ? 0 : len;
   1570}
   1571
   1572/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */
   1573static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops,
   1574				 u16 wait, bool iqmode, bool dac_test,
   1575				 bool modify_bbmult)
   1576{
   1577	struct b43_phy *phy = &dev->phy;
   1578	struct b43_phy_n *nphy = dev->phy.n;
   1579	int i;
   1580	u16 seq_mode;
   1581	u32 tmp;
   1582
   1583	b43_nphy_stay_in_carrier_search(dev, true);
   1584
   1585	if (phy->rev >= 7) {
   1586		bool lpf_bw3, lpf_bw4;
   1587
   1588		lpf_bw3 = b43_phy_read(dev, B43_NPHY_REV7_RF_CTL_OVER3) & 0x80;
   1589		lpf_bw4 = b43_phy_read(dev, B43_NPHY_REV7_RF_CTL_OVER4) & 0x80;
   1590
   1591		if (lpf_bw3 || lpf_bw4) {
   1592			/* TODO */
   1593		} else {
   1594			u16 value = b43_nphy_read_lpf_ctl(dev, 0);
   1595			if (phy->rev >= 19)
   1596				b43_nphy_rf_ctl_override_rev19(dev, 0x80, value,
   1597							       0, false, 1);
   1598			else
   1599				b43_nphy_rf_ctl_override_rev7(dev, 0x80, value,
   1600							      0, false, 1);
   1601			nphy->lpf_bw_overrode_for_sample_play = true;
   1602		}
   1603	}
   1604
   1605	if ((nphy->bb_mult_save & 0x80000000) == 0) {
   1606		tmp = b43_ntab_read(dev, B43_NTAB16(15, 87));
   1607		nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000;
   1608	}
   1609
   1610	if (modify_bbmult) {
   1611		tmp = !b43_is_40mhz(dev) ? 0x6464 : 0x4747;
   1612		b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
   1613	}
   1614
   1615	b43_phy_write(dev, B43_NPHY_SAMP_DEPCNT, (samps - 1));
   1616
   1617	if (loops != 0xFFFF)
   1618		b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, (loops - 1));
   1619	else
   1620		b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, loops);
   1621
   1622	b43_phy_write(dev, B43_NPHY_SAMP_WAITCNT, wait);
   1623
   1624	seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);
   1625
   1626	b43_phy_set(dev, B43_NPHY_RFSEQMODE, B43_NPHY_RFSEQMODE_CAOVER);
   1627	if (iqmode) {
   1628		b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
   1629		b43_phy_set(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8000);
   1630	} else {
   1631		tmp = dac_test ? 5 : 1;
   1632		b43_phy_write(dev, B43_NPHY_SAMP_CMD, tmp);
   1633	}
   1634	for (i = 0; i < 100; i++) {
   1635		if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & 1)) {
   1636			i = 0;
   1637			break;
   1638		}
   1639		udelay(10);
   1640	}
   1641	if (i)
   1642		b43err(dev->wl, "run samples timeout\n");
   1643
   1644	b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
   1645
   1646	b43_nphy_stay_in_carrier_search(dev, false);
   1647}
   1648
   1649/**************************************************
   1650 * RSSI
   1651 **************************************************/
   1652
   1653/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */
   1654static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale,
   1655					s8 offset, u8 core,
   1656					enum n_rail_type rail,
   1657					enum n_rssi_type rssi_type)
   1658{
   1659	u16 tmp;
   1660	bool core1or5 = (core == 1) || (core == 5);
   1661	bool core2or5 = (core == 2) || (core == 5);
   1662
   1663	offset = clamp_val(offset, -32, 31);
   1664	tmp = ((scale & 0x3F) << 8) | (offset & 0x3F);
   1665
   1666	switch (rssi_type) {
   1667	case N_RSSI_NB:
   1668		if (core1or5 && rail == N_RAIL_I)
   1669			b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp);
   1670		if (core1or5 && rail == N_RAIL_Q)
   1671			b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp);
   1672		if (core2or5 && rail == N_RAIL_I)
   1673			b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp);
   1674		if (core2or5 && rail == N_RAIL_Q)
   1675			b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp);
   1676		break;
   1677	case N_RSSI_W1:
   1678		if (core1or5 && rail == N_RAIL_I)
   1679			b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp);
   1680		if (core1or5 && rail == N_RAIL_Q)
   1681			b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp);
   1682		if (core2or5 && rail == N_RAIL_I)
   1683			b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp);
   1684		if (core2or5 && rail == N_RAIL_Q)
   1685			b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp);
   1686		break;
   1687	case N_RSSI_W2:
   1688		if (core1or5 && rail == N_RAIL_I)
   1689			b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp);
   1690		if (core1or5 && rail == N_RAIL_Q)
   1691			b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp);
   1692		if (core2or5 && rail == N_RAIL_I)
   1693			b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp);
   1694		if (core2or5 && rail == N_RAIL_Q)
   1695			b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp);
   1696		break;
   1697	case N_RSSI_TBD:
   1698		if (core1or5 && rail == N_RAIL_I)
   1699			b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp);
   1700		if (core1or5 && rail == N_RAIL_Q)
   1701			b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp);
   1702		if (core2or5 && rail == N_RAIL_I)
   1703			b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp);
   1704		if (core2or5 && rail == N_RAIL_Q)
   1705			b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp);
   1706		break;
   1707	case N_RSSI_IQ:
   1708		if (core1or5 && rail == N_RAIL_I)
   1709			b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp);
   1710		if (core1or5 && rail == N_RAIL_Q)
   1711			b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp);
   1712		if (core2or5 && rail == N_RAIL_I)
   1713			b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp);
   1714		if (core2or5 && rail == N_RAIL_Q)
   1715			b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp);
   1716		break;
   1717	case N_RSSI_TSSI_2G:
   1718		if (core1or5)
   1719			b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp);
   1720		if (core2or5)
   1721			b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp);
   1722		break;
   1723	case N_RSSI_TSSI_5G:
   1724		if (core1or5)
   1725			b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp);
   1726		if (core2or5)
   1727			b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp);
   1728		break;
   1729	}
   1730}
   1731
   1732static void b43_nphy_rssi_select_rev19(struct b43_wldev *dev, u8 code,
   1733				       enum n_rssi_type rssi_type)
   1734{
   1735	/* TODO */
   1736}
   1737
   1738static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code,
   1739				      enum n_rssi_type rssi_type)
   1740{
   1741	u8 i;
   1742	u16 reg, val;
   1743
   1744	if (code == 0) {
   1745		b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, 0xFDFF);
   1746		b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, 0xFDFF);
   1747		b43_phy_mask(dev, B43_NPHY_AFECTL_C1, 0xFCFF);
   1748		b43_phy_mask(dev, B43_NPHY_AFECTL_C2, 0xFCFF);
   1749		b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S0, 0xFFDF);
   1750		b43_phy_mask(dev, B43_NPHY_TXF_40CO_B32S1, 0xFFDF);
   1751		b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0xFFC3);
   1752		b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0xFFC3);
   1753	} else {
   1754		for (i = 0; i < 2; i++) {
   1755			if ((code == 1 && i == 1) || (code == 2 && !i))
   1756				continue;
   1757
   1758			reg = (i == 0) ?
   1759				B43_NPHY_AFECTL_OVER1 : B43_NPHY_AFECTL_OVER;
   1760			b43_phy_maskset(dev, reg, 0xFDFF, 0x0200);
   1761
   1762			if (rssi_type == N_RSSI_W1 ||
   1763			    rssi_type == N_RSSI_W2 ||
   1764			    rssi_type == N_RSSI_NB) {
   1765				reg = (i == 0) ?
   1766					B43_NPHY_AFECTL_C1 :
   1767					B43_NPHY_AFECTL_C2;
   1768				b43_phy_maskset(dev, reg, 0xFCFF, 0);
   1769
   1770				reg = (i == 0) ?
   1771					B43_NPHY_RFCTL_LUT_TRSW_UP1 :
   1772					B43_NPHY_RFCTL_LUT_TRSW_UP2;
   1773				b43_phy_maskset(dev, reg, 0xFFC3, 0);
   1774
   1775				if (rssi_type == N_RSSI_W1)
   1776					val = (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ? 4 : 8;
   1777				else if (rssi_type == N_RSSI_W2)
   1778					val = 16;
   1779				else
   1780					val = 32;
   1781				b43_phy_set(dev, reg, val);
   1782
   1783				reg = (i == 0) ?
   1784					B43_NPHY_TXF_40CO_B1S0 :
   1785					B43_NPHY_TXF_40CO_B32S1;
   1786				b43_phy_set(dev, reg, 0x0020);
   1787			} else {
   1788				if (rssi_type == N_RSSI_TBD)
   1789					val = 0x0100;
   1790				else if (rssi_type == N_RSSI_IQ)
   1791					val = 0x0200;
   1792				else
   1793					val = 0x0300;
   1794
   1795				reg = (i == 0) ?
   1796					B43_NPHY_AFECTL_C1 :
   1797					B43_NPHY_AFECTL_C2;
   1798
   1799				b43_phy_maskset(dev, reg, 0xFCFF, val);
   1800				b43_phy_maskset(dev, reg, 0xF3FF, val << 2);
   1801
   1802				if (rssi_type != N_RSSI_IQ &&
   1803				    rssi_type != N_RSSI_TBD) {
   1804					enum nl80211_band band =
   1805						b43_current_band(dev->wl);
   1806
   1807					if (dev->phy.rev < 7) {
   1808						if (b43_nphy_ipa(dev))
   1809							val = (band == NL80211_BAND_5GHZ) ? 0xC : 0xE;
   1810						else
   1811							val = 0x11;
   1812						reg = (i == 0) ? B2056_TX0 : B2056_TX1;
   1813						reg |= B2056_TX_TX_SSI_MUX;
   1814						b43_radio_write(dev, reg, val);
   1815					}
   1816
   1817					reg = (i == 0) ?
   1818						B43_NPHY_AFECTL_OVER1 :
   1819						B43_NPHY_AFECTL_OVER;
   1820					b43_phy_set(dev, reg, 0x0200);
   1821				}
   1822			}
   1823		}
   1824	}
   1825}
   1826
   1827static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code,
   1828				      enum n_rssi_type rssi_type)
   1829{
   1830	u16 val;
   1831	bool rssi_w1_w2_nb = false;
   1832
   1833	switch (rssi_type) {
   1834	case N_RSSI_W1:
   1835	case N_RSSI_W2:
   1836	case N_RSSI_NB:
   1837		val = 0;
   1838		rssi_w1_w2_nb = true;
   1839		break;
   1840	case N_RSSI_TBD:
   1841		val = 1;
   1842		break;
   1843	case N_RSSI_IQ:
   1844		val = 2;
   1845		break;
   1846	default:
   1847		val = 3;
   1848	}
   1849
   1850	val = (val << 12) | (val << 14);
   1851	b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val);
   1852	b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val);
   1853
   1854	if (rssi_w1_w2_nb) {
   1855		b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF,
   1856				(rssi_type + 1) << 4);
   1857		b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF,
   1858				(rssi_type + 1) << 4);
   1859	}
   1860
   1861	if (code == 0) {
   1862		b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x3000);
   1863		if (rssi_w1_w2_nb) {
   1864			b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
   1865				~(B43_NPHY_RFCTL_CMD_RXEN |
   1866				  B43_NPHY_RFCTL_CMD_CORESEL));
   1867			b43_phy_mask(dev, B43_NPHY_RFCTL_OVER,
   1868				~(0x1 << 12 |
   1869				  0x1 << 5 |
   1870				  0x1 << 1 |
   1871				  0x1));
   1872			b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
   1873				~B43_NPHY_RFCTL_CMD_START);
   1874			udelay(20);
   1875			b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1);
   1876		}
   1877	} else {
   1878		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x3000);
   1879		if (rssi_w1_w2_nb) {
   1880			b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
   1881				~(B43_NPHY_RFCTL_CMD_RXEN |
   1882				  B43_NPHY_RFCTL_CMD_CORESEL),
   1883				(B43_NPHY_RFCTL_CMD_RXEN |
   1884				 code << B43_NPHY_RFCTL_CMD_CORESEL_SHIFT));
   1885			b43_phy_set(dev, B43_NPHY_RFCTL_OVER,
   1886				(0x1 << 12 |
   1887				  0x1 << 5 |
   1888				  0x1 << 1 |
   1889				  0x1));
   1890			b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
   1891				B43_NPHY_RFCTL_CMD_START);
   1892			udelay(20);
   1893			b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1);
   1894		}
   1895	}
   1896}
   1897
   1898/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */
   1899static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code,
   1900				 enum n_rssi_type type)
   1901{
   1902	if (dev->phy.rev >= 19)
   1903		b43_nphy_rssi_select_rev19(dev, code, type);
   1904	else if (dev->phy.rev >= 3)
   1905		b43_nphy_rev3_rssi_select(dev, code, type);
   1906	else
   1907		b43_nphy_rev2_rssi_select(dev, code, type);
   1908}
   1909
   1910/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */
   1911static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev,
   1912				       enum n_rssi_type rssi_type, u8 *buf)
   1913{
   1914	int i;
   1915	for (i = 0; i < 2; i++) {
   1916		if (rssi_type == N_RSSI_NB) {
   1917			if (i == 0) {
   1918				b43_radio_maskset(dev, B2055_C1_B0NB_RSSIVCM,
   1919						  0xFC, buf[0]);
   1920				b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
   1921						  0xFC, buf[1]);
   1922			} else {
   1923				b43_radio_maskset(dev, B2055_C2_B0NB_RSSIVCM,
   1924						  0xFC, buf[2 * i]);
   1925				b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
   1926						  0xFC, buf[2 * i + 1]);
   1927			}
   1928		} else {
   1929			if (i == 0)
   1930				b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
   1931						  0xF3, buf[0] << 2);
   1932			else
   1933				b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
   1934						  0xF3, buf[2 * i + 1] << 2);
   1935		}
   1936	}
   1937}
   1938
   1939/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */
   1940static int b43_nphy_poll_rssi(struct b43_wldev *dev, enum n_rssi_type rssi_type,
   1941			      s32 *buf, u8 nsamp)
   1942{
   1943	int i;
   1944	int out;
   1945	u16 save_regs_phy[9];
   1946	u16 s[2];
   1947
   1948	/* TODO: rev7+ is treated like rev3+, what about rev19+? */
   1949
   1950	if (dev->phy.rev >= 3) {
   1951		save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
   1952		save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
   1953		save_regs_phy[2] = b43_phy_read(dev,
   1954						B43_NPHY_RFCTL_LUT_TRSW_UP1);
   1955		save_regs_phy[3] = b43_phy_read(dev,
   1956						B43_NPHY_RFCTL_LUT_TRSW_UP2);
   1957		save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
   1958		save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
   1959		save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0);
   1960		save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1);
   1961		save_regs_phy[8] = 0;
   1962	} else {
   1963		save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
   1964		save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
   1965		save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
   1966		save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_RFCTL_CMD);
   1967		save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER);
   1968		save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1);
   1969		save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2);
   1970		save_regs_phy[7] = 0;
   1971		save_regs_phy[8] = 0;
   1972	}
   1973
   1974	b43_nphy_rssi_select(dev, 5, rssi_type);
   1975
   1976	if (dev->phy.rev < 2) {
   1977		save_regs_phy[8] = b43_phy_read(dev, B43_NPHY_GPIO_SEL);
   1978		b43_phy_write(dev, B43_NPHY_GPIO_SEL, 5);
   1979	}
   1980
   1981	for (i = 0; i < 4; i++)
   1982		buf[i] = 0;
   1983
   1984	for (i = 0; i < nsamp; i++) {
   1985		if (dev->phy.rev < 2) {
   1986			s[0] = b43_phy_read(dev, B43_NPHY_GPIO_LOOUT);
   1987			s[1] = b43_phy_read(dev, B43_NPHY_GPIO_HIOUT);
   1988		} else {
   1989			s[0] = b43_phy_read(dev, B43_NPHY_RSSI1);
   1990			s[1] = b43_phy_read(dev, B43_NPHY_RSSI2);
   1991		}
   1992
   1993		buf[0] += ((s8)((s[0] & 0x3F) << 2)) >> 2;
   1994		buf[1] += ((s8)(((s[0] >> 8) & 0x3F) << 2)) >> 2;
   1995		buf[2] += ((s8)((s[1] & 0x3F) << 2)) >> 2;
   1996		buf[3] += ((s8)(((s[1] >> 8) & 0x3F) << 2)) >> 2;
   1997	}
   1998	out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 |
   1999		(buf[2] & 0xFF) << 8 | (buf[3] & 0xFF);
   2000
   2001	if (dev->phy.rev < 2)
   2002		b43_phy_write(dev, B43_NPHY_GPIO_SEL, save_regs_phy[8]);
   2003
   2004	if (dev->phy.rev >= 3) {
   2005		b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]);
   2006		b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]);
   2007		b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1,
   2008				save_regs_phy[2]);
   2009		b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2,
   2010				save_regs_phy[3]);
   2011		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, save_regs_phy[4]);
   2012		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]);
   2013		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]);
   2014		b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]);
   2015	} else {
   2016		b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]);
   2017		b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]);
   2018		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[2]);
   2019		b43_phy_write(dev, B43_NPHY_RFCTL_CMD, save_regs_phy[3]);
   2020		b43_phy_write(dev, B43_NPHY_RFCTL_OVER, save_regs_phy[4]);
   2021		b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, save_regs_phy[5]);
   2022		b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, save_regs_phy[6]);
   2023	}
   2024
   2025	return out;
   2026}
   2027
   2028/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */
   2029static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
   2030{
   2031	struct b43_phy *phy = &dev->phy;
   2032	struct b43_phy_n *nphy = dev->phy.n;
   2033
   2034	u16 saved_regs_phy_rfctl[2];
   2035	u16 saved_regs_phy[22];
   2036	u16 regs_to_store_rev3[] = {
   2037		B43_NPHY_AFECTL_OVER1, B43_NPHY_AFECTL_OVER,
   2038		B43_NPHY_AFECTL_C1, B43_NPHY_AFECTL_C2,
   2039		B43_NPHY_TXF_40CO_B1S1, B43_NPHY_RFCTL_OVER,
   2040		B43_NPHY_TXF_40CO_B1S0, B43_NPHY_TXF_40CO_B32S1,
   2041		B43_NPHY_RFCTL_CMD,
   2042		B43_NPHY_RFCTL_LUT_TRSW_UP1, B43_NPHY_RFCTL_LUT_TRSW_UP2,
   2043		B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2
   2044	};
   2045	u16 regs_to_store_rev7[] = {
   2046		B43_NPHY_AFECTL_OVER1, B43_NPHY_AFECTL_OVER,
   2047		B43_NPHY_AFECTL_C1, B43_NPHY_AFECTL_C2,
   2048		B43_NPHY_TXF_40CO_B1S1, B43_NPHY_RFCTL_OVER,
   2049		B43_NPHY_REV7_RF_CTL_OVER3, B43_NPHY_REV7_RF_CTL_OVER4,
   2050		B43_NPHY_REV7_RF_CTL_OVER5, B43_NPHY_REV7_RF_CTL_OVER6,
   2051		0x2ff,
   2052		B43_NPHY_TXF_40CO_B1S0, B43_NPHY_TXF_40CO_B32S1,
   2053		B43_NPHY_RFCTL_CMD,
   2054		B43_NPHY_RFCTL_LUT_TRSW_UP1, B43_NPHY_RFCTL_LUT_TRSW_UP2,
   2055		B43_NPHY_REV7_RF_CTL_MISC_REG3, B43_NPHY_REV7_RF_CTL_MISC_REG4,
   2056		B43_NPHY_REV7_RF_CTL_MISC_REG5, B43_NPHY_REV7_RF_CTL_MISC_REG6,
   2057		B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2
   2058	};
   2059	u16 *regs_to_store;
   2060	int regs_amount;
   2061
   2062	u16 class;
   2063
   2064	u16 clip_state[2];
   2065	u16 clip_off[2] = { 0xFFFF, 0xFFFF };
   2066
   2067	u8 vcm_final = 0;
   2068	s32 offset[4];
   2069	s32 results[8][4] = { };
   2070	s32 results_min[4] = { };
   2071	s32 poll_results[4] = { };
   2072
   2073	u16 *rssical_radio_regs = NULL;
   2074	u16 *rssical_phy_regs = NULL;
   2075
   2076	u16 r; /* routing */
   2077	u8 rx_core_state;
   2078	int core, i, j, vcm;
   2079
   2080	if (dev->phy.rev >= 7) {
   2081		regs_to_store = regs_to_store_rev7;
   2082		regs_amount = ARRAY_SIZE(regs_to_store_rev7);
   2083	} else {
   2084		regs_to_store = regs_to_store_rev3;
   2085		regs_amount = ARRAY_SIZE(regs_to_store_rev3);
   2086	}
   2087	BUG_ON(regs_amount > ARRAY_SIZE(saved_regs_phy));
   2088
   2089	class = b43_nphy_classifier(dev, 0, 0);
   2090	b43_nphy_classifier(dev, 7, 4);
   2091	b43_nphy_read_clip_detection(dev, clip_state);
   2092	b43_nphy_write_clip_detection(dev, clip_off);
   2093
   2094	saved_regs_phy_rfctl[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
   2095	saved_regs_phy_rfctl[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
   2096	for (i = 0; i < regs_amount; i++)
   2097		saved_regs_phy[i] = b43_phy_read(dev, regs_to_store[i]);
   2098
   2099	b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_OFF, 0, 7);
   2100	b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 1, 7);
   2101
   2102	if (dev->phy.rev >= 7) {
   2103		b43_nphy_rf_ctl_override_one_to_many(dev,
   2104						     N_RF_CTL_OVER_CMD_RXRF_PU,
   2105						     0, 0, false);
   2106		b43_nphy_rf_ctl_override_one_to_many(dev,
   2107						     N_RF_CTL_OVER_CMD_RX_PU,
   2108						     1, 0, false);
   2109		b43_nphy_rf_ctl_override_rev7(dev, 0x80, 1, 0, false, 0);
   2110		b43_nphy_rf_ctl_override_rev7(dev, 0x40, 1, 0, false, 0);
   2111		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
   2112			b43_nphy_rf_ctl_override_rev7(dev, 0x20, 0, 0, false,
   2113						      0);
   2114			b43_nphy_rf_ctl_override_rev7(dev, 0x10, 1, 0, false,
   2115						      0);
   2116		} else {
   2117			b43_nphy_rf_ctl_override_rev7(dev, 0x10, 0, 0, false,
   2118						      0);
   2119			b43_nphy_rf_ctl_override_rev7(dev, 0x20, 1, 0, false,
   2120						      0);
   2121		}
   2122	} else {
   2123		b43_nphy_rf_ctl_override(dev, 0x1, 0, 0, false);
   2124		b43_nphy_rf_ctl_override(dev, 0x2, 1, 0, false);
   2125		b43_nphy_rf_ctl_override(dev, 0x80, 1, 0, false);
   2126		b43_nphy_rf_ctl_override(dev, 0x40, 1, 0, false);
   2127		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
   2128			b43_nphy_rf_ctl_override(dev, 0x20, 0, 0, false);
   2129			b43_nphy_rf_ctl_override(dev, 0x10, 1, 0, false);
   2130		} else {
   2131			b43_nphy_rf_ctl_override(dev, 0x10, 0, 0, false);
   2132			b43_nphy_rf_ctl_override(dev, 0x20, 1, 0, false);
   2133		}
   2134	}
   2135
   2136	rx_core_state = b43_nphy_get_rx_core_state(dev);
   2137	for (core = 0; core < 2; core++) {
   2138		if (!(rx_core_state & (1 << core)))
   2139			continue;
   2140		r = core ? B2056_RX1 : B2056_RX0;
   2141		b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, N_RAIL_I,
   2142					   N_RSSI_NB);
   2143		b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, N_RAIL_Q,
   2144					   N_RSSI_NB);
   2145
   2146		/* Grab RSSI results for every possible VCM */
   2147		for (vcm = 0; vcm < 8; vcm++) {
   2148			if (dev->phy.rev >= 7)
   2149				b43_radio_maskset(dev,
   2150						  core ? R2057_NB_MASTER_CORE1 :
   2151							 R2057_NB_MASTER_CORE0,
   2152						  ~R2057_VCM_MASK, vcm);
   2153			else
   2154				b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC,
   2155						  0xE3, vcm << 2);
   2156			b43_nphy_poll_rssi(dev, N_RSSI_NB, results[vcm], 8);
   2157		}
   2158
   2159		/* Find out which VCM got the best results */
   2160		for (i = 0; i < 4; i += 2) {
   2161			s32 currd;
   2162			s32 mind = 0x100000;
   2163			s32 minpoll = 249;
   2164			u8 minvcm = 0;
   2165			if (2 * core != i)
   2166				continue;
   2167			for (vcm = 0; vcm < 8; vcm++) {
   2168				currd = results[vcm][i] * results[vcm][i] +
   2169					results[vcm][i + 1] * results[vcm][i];
   2170				if (currd < mind) {
   2171					mind = currd;
   2172					minvcm = vcm;
   2173				}
   2174				if (results[vcm][i] < minpoll)
   2175					minpoll = results[vcm][i];
   2176			}
   2177			vcm_final = minvcm;
   2178			results_min[i] = minpoll;
   2179		}
   2180
   2181		/* Select the best VCM */
   2182		if (dev->phy.rev >= 7)
   2183			b43_radio_maskset(dev,
   2184					  core ? R2057_NB_MASTER_CORE1 :
   2185						 R2057_NB_MASTER_CORE0,
   2186					  ~R2057_VCM_MASK, vcm);
   2187		else
   2188			b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC,
   2189					  0xE3, vcm_final << 2);
   2190
   2191		for (i = 0; i < 4; i++) {
   2192			if (core != i / 2)
   2193				continue;
   2194			offset[i] = -results[vcm_final][i];
   2195			if (offset[i] < 0)
   2196				offset[i] = -((abs(offset[i]) + 4) / 8);
   2197			else
   2198				offset[i] = (offset[i] + 4) / 8;
   2199			if (results_min[i] == 248)
   2200				offset[i] = -32;
   2201			b43_nphy_scale_offset_rssi(dev, 0, offset[i],
   2202						   (i / 2 == 0) ? 1 : 2,
   2203						   (i % 2 == 0) ? N_RAIL_I : N_RAIL_Q,
   2204						   N_RSSI_NB);
   2205		}
   2206	}
   2207
   2208	for (core = 0; core < 2; core++) {
   2209		if (!(rx_core_state & (1 << core)))
   2210			continue;
   2211		for (i = 0; i < 2; i++) {
   2212			b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1,
   2213						   N_RAIL_I, i);
   2214			b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1,
   2215						   N_RAIL_Q, i);
   2216			b43_nphy_poll_rssi(dev, i, poll_results, 8);
   2217			for (j = 0; j < 4; j++) {
   2218				if (j / 2 == core) {
   2219					offset[j] = 232 - poll_results[j];
   2220					if (offset[j] < 0)
   2221						offset[j] = -(abs(offset[j] + 4) / 8);
   2222					else
   2223						offset[j] = (offset[j] + 4) / 8;
   2224					b43_nphy_scale_offset_rssi(dev, 0,
   2225						offset[2 * core], core + 1, j % 2, i);
   2226				}
   2227			}
   2228		}
   2229	}
   2230
   2231	b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, saved_regs_phy_rfctl[0]);
   2232	b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, saved_regs_phy_rfctl[1]);
   2233
   2234	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
   2235
   2236	b43_phy_set(dev, B43_NPHY_TXF_40CO_B1S1, 0x1);
   2237	b43_phy_set(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_START);
   2238	b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S1, ~0x1);
   2239
   2240	b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x1);
   2241	b43_phy_set(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_RXTX);
   2242	b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1);
   2243
   2244	for (i = 0; i < regs_amount; i++)
   2245		b43_phy_write(dev, regs_to_store[i], saved_regs_phy[i]);
   2246
   2247	/* Store for future configuration */
   2248	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
   2249		rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G;
   2250		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G;
   2251	} else {
   2252		rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G;
   2253		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
   2254	}
   2255	if (dev->phy.rev >= 7) {
   2256		rssical_radio_regs[0] = b43_radio_read(dev,
   2257						       R2057_NB_MASTER_CORE0);
   2258		rssical_radio_regs[1] = b43_radio_read(dev,
   2259						       R2057_NB_MASTER_CORE1);
   2260	} else {
   2261		rssical_radio_regs[0] = b43_radio_read(dev, B2056_RX0 |
   2262						       B2056_RX_RSSI_MISC);
   2263		rssical_radio_regs[1] = b43_radio_read(dev, B2056_RX1 |
   2264						       B2056_RX_RSSI_MISC);
   2265	}
   2266	rssical_phy_regs[0] = b43_phy_read(dev, B43_NPHY_RSSIMC_0I_RSSI_Z);
   2267	rssical_phy_regs[1] = b43_phy_read(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z);
   2268	rssical_phy_regs[2] = b43_phy_read(dev, B43_NPHY_RSSIMC_1I_RSSI_Z);
   2269	rssical_phy_regs[3] = b43_phy_read(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z);
   2270	rssical_phy_regs[4] = b43_phy_read(dev, B43_NPHY_RSSIMC_0I_RSSI_X);
   2271	rssical_phy_regs[5] = b43_phy_read(dev, B43_NPHY_RSSIMC_0Q_RSSI_X);
   2272	rssical_phy_regs[6] = b43_phy_read(dev, B43_NPHY_RSSIMC_1I_RSSI_X);
   2273	rssical_phy_regs[7] = b43_phy_read(dev, B43_NPHY_RSSIMC_1Q_RSSI_X);
   2274	rssical_phy_regs[8] = b43_phy_read(dev, B43_NPHY_RSSIMC_0I_RSSI_Y);
   2275	rssical_phy_regs[9] = b43_phy_read(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y);
   2276	rssical_phy_regs[10] = b43_phy_read(dev, B43_NPHY_RSSIMC_1I_RSSI_Y);
   2277	rssical_phy_regs[11] = b43_phy_read(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y);
   2278
   2279	/* Remember for which channel we store configuration */
   2280	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
   2281		nphy->rssical_chanspec_2G.center_freq = phy->chandef->chan->center_freq;
   2282	else
   2283		nphy->rssical_chanspec_5G.center_freq = phy->chandef->chan->center_freq;
   2284
   2285	/* End of calibration, restore configuration */
   2286	b43_nphy_classifier(dev, 7, class);
   2287	b43_nphy_write_clip_detection(dev, clip_state);
   2288}
   2289
   2290/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */
   2291static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, enum n_rssi_type type)
   2292{
   2293	int i, j, vcm;
   2294	u8 state[4];
   2295	u8 code, val;
   2296	u16 class, override;
   2297	u8 regs_save_radio[2];
   2298	u16 regs_save_phy[2];
   2299
   2300	s32 offset[4];
   2301	u8 core;
   2302	u8 rail;
   2303
   2304	u16 clip_state[2];
   2305	u16 clip_off[2] = { 0xFFFF, 0xFFFF };
   2306	s32 results_min[4] = { };
   2307	u8 vcm_final[4] = { };
   2308	s32 results[4][4] = { };
   2309	s32 miniq[4][2] = { };
   2310
   2311	if (type == N_RSSI_NB) {
   2312		code = 0;
   2313		val = 6;
   2314	} else if (type == N_RSSI_W1 || type == N_RSSI_W2) {
   2315		code = 25;
   2316		val = 4;
   2317	} else {
   2318		B43_WARN_ON(1);
   2319		return;
   2320	}
   2321
   2322	class = b43_nphy_classifier(dev, 0, 0);
   2323	b43_nphy_classifier(dev, 7, 4);
   2324	b43_nphy_read_clip_detection(dev, clip_state);
   2325	b43_nphy_write_clip_detection(dev, clip_off);
   2326
   2327	if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
   2328		override = 0x140;
   2329	else
   2330		override = 0x110;
   2331
   2332	regs_save_phy[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
   2333	regs_save_radio[0] = b43_radio_read(dev, B2055_C1_PD_RXTX);
   2334	b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, override);
   2335	b43_radio_write(dev, B2055_C1_PD_RXTX, val);
   2336
   2337	regs_save_phy[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
   2338	regs_save_radio[1] = b43_radio_read(dev, B2055_C2_PD_RXTX);
   2339	b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, override);
   2340	b43_radio_write(dev, B2055_C2_PD_RXTX, val);
   2341
   2342	state[0] = b43_radio_read(dev, B2055_C1_PD_RSSIMISC) & 0x07;
   2343	state[1] = b43_radio_read(dev, B2055_C2_PD_RSSIMISC) & 0x07;
   2344	b43_radio_mask(dev, B2055_C1_PD_RSSIMISC, 0xF8);
   2345	b43_radio_mask(dev, B2055_C2_PD_RSSIMISC, 0xF8);
   2346	state[2] = b43_radio_read(dev, B2055_C1_SP_RSSI) & 0x07;
   2347	state[3] = b43_radio_read(dev, B2055_C2_SP_RSSI) & 0x07;
   2348
   2349	b43_nphy_rssi_select(dev, 5, type);
   2350	b43_nphy_scale_offset_rssi(dev, 0, 0, 5, N_RAIL_I, type);
   2351	b43_nphy_scale_offset_rssi(dev, 0, 0, 5, N_RAIL_Q, type);
   2352
   2353	for (vcm = 0; vcm < 4; vcm++) {
   2354		u8 tmp[4];
   2355		for (j = 0; j < 4; j++)
   2356			tmp[j] = vcm;
   2357		if (type != N_RSSI_W2)
   2358			b43_nphy_set_rssi_2055_vcm(dev, type, tmp);
   2359		b43_nphy_poll_rssi(dev, type, results[vcm], 8);
   2360		if (type == N_RSSI_W1 || type == N_RSSI_W2)
   2361			for (j = 0; j < 2; j++)
   2362				miniq[vcm][j] = min(results[vcm][2 * j],
   2363						    results[vcm][2 * j + 1]);
   2364	}
   2365
   2366	for (i = 0; i < 4; i++) {
   2367		s32 mind = 0x100000;
   2368		u8 minvcm = 0;
   2369		s32 minpoll = 249;
   2370		s32 currd;
   2371		for (vcm = 0; vcm < 4; vcm++) {
   2372			if (type == N_RSSI_NB)
   2373				currd = abs(results[vcm][i] - code * 8);
   2374			else
   2375				currd = abs(miniq[vcm][i / 2] - code * 8);
   2376
   2377			if (currd < mind) {
   2378				mind = currd;
   2379				minvcm = vcm;
   2380			}
   2381
   2382			if (results[vcm][i] < minpoll)
   2383				minpoll = results[vcm][i];
   2384		}
   2385		results_min[i] = minpoll;
   2386		vcm_final[i] = minvcm;
   2387	}
   2388
   2389	if (type != N_RSSI_W2)
   2390		b43_nphy_set_rssi_2055_vcm(dev, type, vcm_final);
   2391
   2392	for (i = 0; i < 4; i++) {
   2393		offset[i] = (code * 8) - results[vcm_final[i]][i];
   2394
   2395		if (offset[i] < 0)
   2396			offset[i] = -((abs(offset[i]) + 4) / 8);
   2397		else
   2398			offset[i] = (offset[i] + 4) / 8;
   2399
   2400		if (results_min[i] == 248)
   2401			offset[i] = code - 32;
   2402
   2403		core = (i / 2) ? 2 : 1;
   2404		rail = (i % 2) ? N_RAIL_Q : N_RAIL_I;
   2405
   2406		b43_nphy_scale_offset_rssi(dev, 0, offset[i], core, rail,
   2407						type);
   2408	}
   2409
   2410	b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[0]);
   2411	b43_radio_maskset(dev, B2055_C2_PD_RSSIMISC, 0xF8, state[1]);
   2412
   2413	switch (state[2]) {
   2414	case 1:
   2415		b43_nphy_rssi_select(dev, 1, N_RSSI_NB);
   2416		break;
   2417	case 4:
   2418		b43_nphy_rssi_select(dev, 1, N_RSSI_W1);
   2419		break;
   2420	case 2:
   2421		b43_nphy_rssi_select(dev, 1, N_RSSI_W2);
   2422		break;
   2423	default:
   2424		b43_nphy_rssi_select(dev, 1, N_RSSI_W2);
   2425		break;
   2426	}
   2427
   2428	switch (state[3]) {
   2429	case 1:
   2430		b43_nphy_rssi_select(dev, 2, N_RSSI_NB);
   2431		break;
   2432	case 4:
   2433		b43_nphy_rssi_select(dev, 2, N_RSSI_W1);
   2434		break;
   2435	default:
   2436		b43_nphy_rssi_select(dev, 2, N_RSSI_W2);
   2437		break;
   2438	}
   2439
   2440	b43_nphy_rssi_select(dev, 0, type);
   2441
   2442	b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs_save_phy[0]);
   2443	b43_radio_write(dev, B2055_C1_PD_RXTX, regs_save_radio[0]);
   2444	b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs_save_phy[1]);
   2445	b43_radio_write(dev, B2055_C2_PD_RXTX, regs_save_radio[1]);
   2446
   2447	b43_nphy_classifier(dev, 7, class);
   2448	b43_nphy_write_clip_detection(dev, clip_state);
   2449	/* Specs don't say about reset here, but it makes wl and b43 dumps
   2450	   identical, it really seems wl performs this */
   2451	b43_nphy_reset_cca(dev);
   2452}
   2453
   2454/*
   2455 * RSSI Calibration
   2456 * https://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal
   2457 */
   2458static void b43_nphy_rssi_cal(struct b43_wldev *dev)
   2459{
   2460	if (dev->phy.rev >= 19) {
   2461		/* TODO */
   2462	} else if (dev->phy.rev >= 3) {
   2463		b43_nphy_rev3_rssi_cal(dev);
   2464	} else {
   2465		b43_nphy_rev2_rssi_cal(dev, N_RSSI_NB);
   2466		b43_nphy_rev2_rssi_cal(dev, N_RSSI_W1);
   2467		b43_nphy_rev2_rssi_cal(dev, N_RSSI_W2);
   2468	}
   2469}
   2470
   2471/**************************************************
   2472 * Workarounds
   2473 **************************************************/
   2474
   2475static void b43_nphy_gain_ctl_workarounds_rev19(struct b43_wldev *dev)
   2476{
   2477	/* TODO */
   2478}
   2479
   2480static void b43_nphy_gain_ctl_workarounds_rev7(struct b43_wldev *dev)
   2481{
   2482	struct b43_phy *phy = &dev->phy;
   2483
   2484	switch (phy->rev) {
   2485	/* TODO */
   2486	}
   2487}
   2488
   2489static void b43_nphy_gain_ctl_workarounds_rev3(struct b43_wldev *dev)
   2490{
   2491	struct ssb_sprom *sprom = dev->dev->bus_sprom;
   2492
   2493	bool ghz5;
   2494	bool ext_lna;
   2495	u16 rssi_gain;
   2496	struct nphy_gain_ctl_workaround_entry *e;
   2497	u8 lpf_gain[6] = { 0x00, 0x06, 0x0C, 0x12, 0x12, 0x12 };
   2498	u8 lpf_bits[6] = { 0, 1, 2, 3, 3, 3 };
   2499
   2500	/* Prepare values */
   2501	ghz5 = b43_phy_read(dev, B43_NPHY_BANDCTL)
   2502		& B43_NPHY_BANDCTL_5GHZ;
   2503	ext_lna = ghz5 ? sprom->boardflags_hi & B43_BFH_EXTLNA_5GHZ :
   2504		sprom->boardflags_lo & B43_BFL_EXTLNA;
   2505	e = b43_nphy_get_gain_ctl_workaround_ent(dev, ghz5, ext_lna);
   2506	if (ghz5 && dev->phy.rev >= 5)
   2507		rssi_gain = 0x90;
   2508	else
   2509		rssi_gain = 0x50;
   2510
   2511	b43_phy_set(dev, B43_NPHY_RXCTL, 0x0040);
   2512
   2513	/* Set Clip 2 detect */
   2514	b43_phy_set(dev, B43_NPHY_C1_CGAINI, B43_NPHY_C1_CGAINI_CL2DETECT);
   2515	b43_phy_set(dev, B43_NPHY_C2_CGAINI, B43_NPHY_C2_CGAINI_CL2DETECT);
   2516
   2517	b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAG1_IDAC,
   2518			0x17);
   2519	b43_radio_write(dev, B2056_RX1 | B2056_RX_BIASPOLE_LNAG1_IDAC,
   2520			0x17);
   2521	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG2_IDAC, 0xF0);
   2522	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG2_IDAC, 0xF0);
   2523	b43_radio_write(dev, B2056_RX0 | B2056_RX_RSSI_POLE, 0x00);
   2524	b43_radio_write(dev, B2056_RX1 | B2056_RX_RSSI_POLE, 0x00);
   2525	b43_radio_write(dev, B2056_RX0 | B2056_RX_RSSI_GAIN,
   2526			rssi_gain);
   2527	b43_radio_write(dev, B2056_RX1 | B2056_RX_RSSI_GAIN,
   2528			rssi_gain);
   2529	b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAA1_IDAC,
   2530			0x17);
   2531	b43_radio_write(dev, B2056_RX1 | B2056_RX_BIASPOLE_LNAA1_IDAC,
   2532			0x17);
   2533	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA2_IDAC, 0xFF);
   2534	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA2_IDAC, 0xFF);
   2535
   2536	b43_ntab_write_bulk(dev, B43_NTAB8(0, 8), 4, e->lna1_gain);
   2537	b43_ntab_write_bulk(dev, B43_NTAB8(1, 8), 4, e->lna1_gain);
   2538	b43_ntab_write_bulk(dev, B43_NTAB8(0, 16), 4, e->lna2_gain);
   2539	b43_ntab_write_bulk(dev, B43_NTAB8(1, 16), 4, e->lna2_gain);
   2540	b43_ntab_write_bulk(dev, B43_NTAB8(0, 32), 10, e->gain_db);
   2541	b43_ntab_write_bulk(dev, B43_NTAB8(1, 32), 10, e->gain_db);
   2542	b43_ntab_write_bulk(dev, B43_NTAB8(2, 32), 10, e->gain_bits);
   2543	b43_ntab_write_bulk(dev, B43_NTAB8(3, 32), 10, e->gain_bits);
   2544	b43_ntab_write_bulk(dev, B43_NTAB8(0, 0x40), 6, lpf_gain);
   2545	b43_ntab_write_bulk(dev, B43_NTAB8(1, 0x40), 6, lpf_gain);
   2546	b43_ntab_write_bulk(dev, B43_NTAB8(2, 0x40), 6, lpf_bits);
   2547	b43_ntab_write_bulk(dev, B43_NTAB8(3, 0x40), 6, lpf_bits);
   2548
   2549	b43_phy_write(dev, B43_NPHY_REV3_C1_INITGAIN_A, e->init_gain);
   2550	b43_phy_write(dev, B43_NPHY_REV3_C2_INITGAIN_A, e->init_gain);
   2551
   2552	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x106), 2,
   2553				e->rfseq_init);
   2554
   2555	b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_HIGAIN_A, e->cliphi_gain);
   2556	b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_HIGAIN_A, e->cliphi_gain);
   2557	b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_MEDGAIN_A, e->clipmd_gain);
   2558	b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_MEDGAIN_A, e->clipmd_gain);
   2559	b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_LOGAIN_A, e->cliplo_gain);
   2560	b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_LOGAIN_A, e->cliplo_gain);
   2561
   2562	b43_phy_maskset(dev, B43_NPHY_CRSMINPOWER0, 0xFF00, e->crsmin);
   2563	b43_phy_maskset(dev, B43_NPHY_CRSMINPOWERL0, 0xFF00, e->crsminl);
   2564	b43_phy_maskset(dev, B43_NPHY_CRSMINPOWERU0, 0xFF00, e->crsminu);
   2565	b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, e->nbclip);
   2566	b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, e->nbclip);
   2567	b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
   2568			~B43_NPHY_C1_CLIPWBTHRES_CLIP2, e->wlclip);
   2569	b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
   2570			~B43_NPHY_C2_CLIPWBTHRES_CLIP2, e->wlclip);
   2571	b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);
   2572}
   2573
   2574static void b43_nphy_gain_ctl_workarounds_rev1_2(struct b43_wldev *dev)
   2575{
   2576	struct b43_phy_n *nphy = dev->phy.n;
   2577
   2578	u8 i, j;
   2579	u8 code;
   2580	u16 tmp;
   2581	u8 rfseq_events[3] = { 6, 8, 7 };
   2582	u8 rfseq_delays[3] = { 10, 30, 1 };
   2583
   2584	/* Set Clip 2 detect */
   2585	b43_phy_set(dev, B43_NPHY_C1_CGAINI, B43_NPHY_C1_CGAINI_CL2DETECT);
   2586	b43_phy_set(dev, B43_NPHY_C2_CGAINI, B43_NPHY_C2_CGAINI_CL2DETECT);
   2587
   2588	/* Set narrowband clip threshold */
   2589	b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 0x84);
   2590	b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 0x84);
   2591
   2592	if (!b43_is_40mhz(dev)) {
   2593		/* Set dwell lengths */
   2594		b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 0x002B);
   2595		b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 0x002B);
   2596		b43_phy_write(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 0x0009);
   2597		b43_phy_write(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 0x0009);
   2598	}
   2599
   2600	/* Set wideband clip 2 threshold */
   2601	b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
   2602			~B43_NPHY_C1_CLIPWBTHRES_CLIP2, 21);
   2603	b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
   2604			~B43_NPHY_C2_CLIPWBTHRES_CLIP2, 21);
   2605
   2606	if (!b43_is_40mhz(dev)) {
   2607		b43_phy_maskset(dev, B43_NPHY_C1_CGAINI,
   2608			~B43_NPHY_C1_CGAINI_GAINBKOFF, 0x1);
   2609		b43_phy_maskset(dev, B43_NPHY_C2_CGAINI,
   2610			~B43_NPHY_C2_CGAINI_GAINBKOFF, 0x1);
   2611		b43_phy_maskset(dev, B43_NPHY_C1_CCK_CGAINI,
   2612			~B43_NPHY_C1_CCK_CGAINI_GAINBKOFF, 0x1);
   2613		b43_phy_maskset(dev, B43_NPHY_C2_CCK_CGAINI,
   2614			~B43_NPHY_C2_CCK_CGAINI_GAINBKOFF, 0x1);
   2615	}
   2616
   2617	b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);
   2618
   2619	if (nphy->gain_boost) {
   2620		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ &&
   2621		    b43_is_40mhz(dev))
   2622			code = 4;
   2623		else
   2624			code = 5;
   2625	} else {
   2626		code = b43_is_40mhz(dev) ? 6 : 7;
   2627	}
   2628
   2629	/* Set HPVGA2 index */
   2630	b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN, ~B43_NPHY_C1_INITGAIN_HPVGA2,
   2631			code << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT);
   2632	b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN, ~B43_NPHY_C2_INITGAIN_HPVGA2,
   2633			code << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT);
   2634
   2635	b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
   2636	/* specs say about 2 loops, but wl does 4 */
   2637	for (i = 0; i < 4; i++)
   2638		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, (code << 8 | 0x7C));
   2639
   2640	b43_nphy_adjust_lna_gain_table(dev);
   2641
   2642	if (nphy->elna_gain_config) {
   2643		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0808);
   2644		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0);
   2645		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
   2646		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
   2647		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
   2648
   2649		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0C08);
   2650		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0);
   2651		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
   2652		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
   2653		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
   2654
   2655		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
   2656		/* specs say about 2 loops, but wl does 4 */
   2657		for (i = 0; i < 4; i++)
   2658			b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
   2659						(code << 8 | 0x74));
   2660	}
   2661
   2662	if (dev->phy.rev == 2) {
   2663		for (i = 0; i < 4; i++) {
   2664			b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
   2665					(0x0400 * i) + 0x0020);
   2666			for (j = 0; j < 21; j++) {
   2667				tmp = j * (i < 2 ? 3 : 1);
   2668				b43_phy_write(dev,
   2669					B43_NPHY_TABLE_DATALO, tmp);
   2670			}
   2671		}
   2672	}
   2673
   2674	b43_nphy_set_rf_sequence(dev, 5, rfseq_events, rfseq_delays, 3);
   2675	b43_phy_maskset(dev, B43_NPHY_OVER_DGAIN1,
   2676		~B43_NPHY_OVER_DGAIN_CCKDGECV & 0xFFFF,
   2677		0x5A << B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT);
   2678
   2679	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
   2680		b43_phy_maskset(dev, B43_PHY_N(0xC5D), 0xFF80, 4);
   2681}
   2682
   2683/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */
   2684static void b43_nphy_gain_ctl_workarounds(struct b43_wldev *dev)
   2685{
   2686	if (dev->phy.rev >= 19)
   2687		b43_nphy_gain_ctl_workarounds_rev19(dev);
   2688	else if (dev->phy.rev >= 7)
   2689		b43_nphy_gain_ctl_workarounds_rev7(dev);
   2690	else if (dev->phy.rev >= 3)
   2691		b43_nphy_gain_ctl_workarounds_rev3(dev);
   2692	else
   2693		b43_nphy_gain_ctl_workarounds_rev1_2(dev);
   2694}
   2695
   2696static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
   2697{
   2698	struct ssb_sprom *sprom = dev->dev->bus_sprom;
   2699	struct b43_phy *phy = &dev->phy;
   2700
   2701	/* TX to RX */
   2702	u8 tx2rx_events[7] = { 4, 3, 5, 2, 1, 8, 31, };
   2703	u8 tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1, };
   2704	/* RX to TX */
   2705	u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
   2706					0x1F };
   2707	u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
   2708
   2709	static const u16 ntab7_15e_16e[] = { 0, 0x10f, 0x10f };
   2710	u8 ntab7_138_146[] = { 0x11, 0x11 };
   2711	u8 ntab7_133[] = { 0x77, 0x11, 0x11 };
   2712
   2713	u16 lpf_ofdm_20mhz[2], lpf_ofdm_40mhz[2], lpf_11b[2];
   2714	u16 bcap_val;
   2715	s16 bcap_val_11b[2], bcap_val_11n_20[2], bcap_val_11n_40[2];
   2716	u16 scap_val;
   2717	s16 scap_val_11b[2], scap_val_11n_20[2], scap_val_11n_40[2];
   2718	bool rccal_ovrd = false;
   2719
   2720	u16 bias, conv, filt;
   2721
   2722	u32 noise_tbl[2];
   2723
   2724	u32 tmp32;
   2725	u8 core;
   2726
   2727	b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);
   2728	b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01b3);
   2729	b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);
   2730	b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016e);
   2731	b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00cd);
   2732	b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
   2733
   2734	if (phy->rev == 7) {
   2735		b43_phy_set(dev, B43_NPHY_FINERX2_CGC, 0x10);
   2736		b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0xFF80, 0x0020);
   2737		b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0x80FF, 0x2700);
   2738		b43_phy_maskset(dev, B43_NPHY_FREQGAIN1, 0xFF80, 0x002E);
   2739		b43_phy_maskset(dev, B43_NPHY_FREQGAIN1, 0x80FF, 0x3300);
   2740		b43_phy_maskset(dev, B43_NPHY_FREQGAIN2, 0xFF80, 0x0037);
   2741		b43_phy_maskset(dev, B43_NPHY_FREQGAIN2, 0x80FF, 0x3A00);
   2742		b43_phy_maskset(dev, B43_NPHY_FREQGAIN3, 0xFF80, 0x003C);
   2743		b43_phy_maskset(dev, B43_NPHY_FREQGAIN3, 0x80FF, 0x3E00);
   2744		b43_phy_maskset(dev, B43_NPHY_FREQGAIN4, 0xFF80, 0x003E);
   2745		b43_phy_maskset(dev, B43_NPHY_FREQGAIN4, 0x80FF, 0x3F00);
   2746		b43_phy_maskset(dev, B43_NPHY_FREQGAIN5, 0xFF80, 0x0040);
   2747		b43_phy_maskset(dev, B43_NPHY_FREQGAIN5, 0x80FF, 0x4000);
   2748		b43_phy_maskset(dev, B43_NPHY_FREQGAIN6, 0xFF80, 0x0040);
   2749		b43_phy_maskset(dev, B43_NPHY_FREQGAIN6, 0x80FF, 0x4000);
   2750		b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0xFF80, 0x0040);
   2751		b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0x80FF, 0x4000);
   2752	}
   2753
   2754	if (phy->rev >= 16) {
   2755		b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x7ff);
   2756		b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x7ff);
   2757	} else if (phy->rev <= 8) {
   2758		b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1B0);
   2759		b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1B0);
   2760	}
   2761
   2762	if (phy->rev >= 16)
   2763		b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0xa0);
   2764	else if (phy->rev >= 8)
   2765		b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0x72);
   2766
   2767	b43_ntab_write(dev, B43_NTAB16(8, 0x00), 2);
   2768	b43_ntab_write(dev, B43_NTAB16(8, 0x10), 2);
   2769	tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
   2770	tmp32 &= 0xffffff;
   2771	b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
   2772	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x15d), 3, ntab7_15e_16e);
   2773	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16d), 3, ntab7_15e_16e);
   2774
   2775	b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays,
   2776				 ARRAY_SIZE(tx2rx_events));
   2777	if (b43_nphy_ipa(dev))
   2778		b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa,
   2779				rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa));
   2780
   2781	b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_0, 0x3FFF, 0x4000);
   2782	b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_1, 0x3FFF, 0x4000);
   2783
   2784	for (core = 0; core < 2; core++) {
   2785		lpf_ofdm_20mhz[core] = b43_nphy_read_lpf_ctl(dev, 0x154 + core * 0x10);
   2786		lpf_ofdm_40mhz[core] = b43_nphy_read_lpf_ctl(dev, 0x159 + core * 0x10);
   2787		lpf_11b[core] = b43_nphy_read_lpf_ctl(dev, 0x152 + core * 0x10);
   2788	}
   2789
   2790	bcap_val = b43_radio_read(dev, R2057_RCCAL_BCAP_VAL);
   2791	scap_val = b43_radio_read(dev, R2057_RCCAL_SCAP_VAL);
   2792
   2793	if (b43_nphy_ipa(dev)) {
   2794		bool ghz2 = b43_current_band(dev->wl) == NL80211_BAND_2GHZ;
   2795
   2796		switch (phy->radio_rev) {
   2797		case 5:
   2798			/* Check radio version (to be 0) by PHY rev for now */
   2799			if (phy->rev == 8 && b43_is_40mhz(dev)) {
   2800				for (core = 0; core < 2; core++) {
   2801					scap_val_11b[core] = scap_val;
   2802					bcap_val_11b[core] = bcap_val;
   2803					scap_val_11n_20[core] = scap_val;
   2804					bcap_val_11n_20[core] = bcap_val;
   2805					scap_val_11n_40[core] = 0xc;
   2806					bcap_val_11n_40[core] = 0xc;
   2807				}
   2808
   2809				rccal_ovrd = true;
   2810			}
   2811			if (phy->rev == 9) {
   2812				/* TODO: Radio version 1 (e.g. BCM5357B0) */
   2813			}
   2814			break;
   2815		case 7:
   2816		case 8:
   2817			for (core = 0; core < 2; core++) {
   2818				scap_val_11b[core] = scap_val;
   2819				bcap_val_11b[core] = bcap_val;
   2820				lpf_ofdm_20mhz[core] = 4;
   2821				lpf_11b[core] = 1;
   2822				if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
   2823					scap_val_11n_20[core] = 0xc;
   2824					bcap_val_11n_20[core] = 0xc;
   2825					scap_val_11n_40[core] = 0xa;
   2826					bcap_val_11n_40[core] = 0xa;
   2827				} else {
   2828					scap_val_11n_20[core] = 0x14;
   2829					bcap_val_11n_20[core] = 0x14;
   2830					scap_val_11n_40[core] = 0xf;
   2831					bcap_val_11n_40[core] = 0xf;
   2832				}
   2833			}
   2834
   2835			rccal_ovrd = true;
   2836			break;
   2837		case 9:
   2838			for (core = 0; core < 2; core++) {
   2839				bcap_val_11b[core] = bcap_val;
   2840				scap_val_11b[core] = scap_val;
   2841				lpf_11b[core] = 1;
   2842
   2843				if (ghz2) {
   2844					bcap_val_11n_20[core] = bcap_val + 13;
   2845					scap_val_11n_20[core] = scap_val + 15;
   2846				} else {
   2847					bcap_val_11n_20[core] = bcap_val + 14;
   2848					scap_val_11n_20[core] = scap_val + 15;
   2849				}
   2850				lpf_ofdm_20mhz[core] = 4;
   2851
   2852				if (ghz2) {
   2853					bcap_val_11n_40[core] = bcap_val - 7;
   2854					scap_val_11n_40[core] = scap_val - 5;
   2855				} else {
   2856					bcap_val_11n_40[core] = bcap_val + 2;
   2857					scap_val_11n_40[core] = scap_val + 4;
   2858				}
   2859				lpf_ofdm_40mhz[core] = 4;
   2860			}
   2861
   2862			rccal_ovrd = true;
   2863			break;
   2864		case 14:
   2865			for (core = 0; core < 2; core++) {
   2866				bcap_val_11b[core] = bcap_val;
   2867				scap_val_11b[core] = scap_val;
   2868				lpf_11b[core] = 1;
   2869			}
   2870
   2871			bcap_val_11n_20[0] = bcap_val + 20;
   2872			scap_val_11n_20[0] = scap_val + 20;
   2873			lpf_ofdm_20mhz[0] = 3;
   2874
   2875			bcap_val_11n_20[1] = bcap_val + 16;
   2876			scap_val_11n_20[1] = scap_val + 16;
   2877			lpf_ofdm_20mhz[1] = 3;
   2878
   2879			bcap_val_11n_40[0] = bcap_val + 20;
   2880			scap_val_11n_40[0] = scap_val + 20;
   2881			lpf_ofdm_40mhz[0] = 4;
   2882
   2883			bcap_val_11n_40[1] = bcap_val + 10;
   2884			scap_val_11n_40[1] = scap_val + 10;
   2885			lpf_ofdm_40mhz[1] = 4;
   2886
   2887			rccal_ovrd = true;
   2888			break;
   2889		}
   2890	} else {
   2891		if (phy->radio_rev == 5) {
   2892			for (core = 0; core < 2; core++) {
   2893				lpf_ofdm_20mhz[core] = 1;
   2894				lpf_ofdm_40mhz[core] = 3;
   2895				scap_val_11b[core] = scap_val;
   2896				bcap_val_11b[core] = bcap_val;
   2897				scap_val_11n_20[core] = 0x11;
   2898				scap_val_11n_40[core] = 0x11;
   2899				bcap_val_11n_20[core] = 0x13;
   2900				bcap_val_11n_40[core] = 0x13;
   2901			}
   2902
   2903			rccal_ovrd = true;
   2904		}
   2905	}
   2906	if (rccal_ovrd) {
   2907		u16 rx2tx_lut_20_11b[2], rx2tx_lut_20_11n[2], rx2tx_lut_40_11n[2];
   2908		u8 rx2tx_lut_extra = 1;
   2909
   2910		for (core = 0; core < 2; core++) {
   2911			bcap_val_11b[core] = clamp_val(bcap_val_11b[core], 0, 0x1f);
   2912			scap_val_11b[core] = clamp_val(scap_val_11b[core], 0, 0x1f);
   2913			bcap_val_11n_20[core] = clamp_val(bcap_val_11n_20[core], 0, 0x1f);
   2914			scap_val_11n_20[core] = clamp_val(scap_val_11n_20[core], 0, 0x1f);
   2915			bcap_val_11n_40[core] = clamp_val(bcap_val_11n_40[core], 0, 0x1f);
   2916			scap_val_11n_40[core] = clamp_val(scap_val_11n_40[core], 0, 0x1f);
   2917
   2918			rx2tx_lut_20_11b[core] = (rx2tx_lut_extra << 13) |
   2919						 (bcap_val_11b[core] << 8) |
   2920						 (scap_val_11b[core] << 3) |
   2921						 lpf_11b[core];
   2922			rx2tx_lut_20_11n[core] = (rx2tx_lut_extra << 13) |
   2923						 (bcap_val_11n_20[core] << 8) |
   2924						 (scap_val_11n_20[core] << 3) |
   2925						 lpf_ofdm_20mhz[core];
   2926			rx2tx_lut_40_11n[core] = (rx2tx_lut_extra << 13) |
   2927						 (bcap_val_11n_40[core] << 8) |
   2928						 (scap_val_11n_40[core] << 3) |
   2929						 lpf_ofdm_40mhz[core];
   2930		}
   2931
   2932		for (core = 0; core < 2; core++) {
   2933			b43_ntab_write(dev, B43_NTAB16(7, 0x152 + core * 16),
   2934				       rx2tx_lut_20_11b[core]);
   2935			b43_ntab_write(dev, B43_NTAB16(7, 0x153 + core * 16),
   2936				       rx2tx_lut_20_11n[core]);
   2937			b43_ntab_write(dev, B43_NTAB16(7, 0x154 + core * 16),
   2938				       rx2tx_lut_20_11n[core]);
   2939			b43_ntab_write(dev, B43_NTAB16(7, 0x155 + core * 16),
   2940				       rx2tx_lut_40_11n[core]);
   2941			b43_ntab_write(dev, B43_NTAB16(7, 0x156 + core * 16),
   2942				       rx2tx_lut_40_11n[core]);
   2943			b43_ntab_write(dev, B43_NTAB16(7, 0x157 + core * 16),
   2944				       rx2tx_lut_40_11n[core]);
   2945			b43_ntab_write(dev, B43_NTAB16(7, 0x158 + core * 16),
   2946				       rx2tx_lut_40_11n[core]);
   2947			b43_ntab_write(dev, B43_NTAB16(7, 0x159 + core * 16),
   2948				       rx2tx_lut_40_11n[core]);
   2949		}
   2950	}
   2951
   2952	b43_phy_write(dev, 0x32F, 0x3);
   2953
   2954	if (phy->radio_rev == 4 || phy->radio_rev == 6)
   2955		b43_nphy_rf_ctl_override_rev7(dev, 4, 1, 3, false, 0);
   2956
   2957	if (phy->radio_rev == 3 || phy->radio_rev == 4 || phy->radio_rev == 6) {
   2958		if (sprom->revision &&
   2959		    sprom->boardflags2_hi & B43_BFH2_IPALVLSHIFT_3P3) {
   2960			b43_radio_write(dev, 0x5, 0x05);
   2961			b43_radio_write(dev, 0x6, 0x30);
   2962			b43_radio_write(dev, 0x7, 0x00);
   2963			b43_radio_set(dev, 0x4f, 0x1);
   2964			b43_radio_set(dev, 0xd4, 0x1);
   2965			bias = 0x1f;
   2966			conv = 0x6f;
   2967			filt = 0xaa;
   2968		} else {
   2969			bias = 0x2b;
   2970			conv = 0x7f;
   2971			filt = 0xee;
   2972		}
   2973		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
   2974			for (core = 0; core < 2; core++) {
   2975				if (core == 0) {
   2976					b43_radio_write(dev, 0x5F, bias);
   2977					b43_radio_write(dev, 0x64, conv);
   2978					b43_radio_write(dev, 0x66, filt);
   2979				} else {
   2980					b43_radio_write(dev, 0xE8, bias);
   2981					b43_radio_write(dev, 0xE9, conv);
   2982					b43_radio_write(dev, 0xEB, filt);
   2983				}
   2984			}
   2985		}
   2986	}
   2987
   2988	if (b43_nphy_ipa(dev)) {
   2989		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
   2990			if (phy->radio_rev == 3 || phy->radio_rev == 4 ||
   2991			    phy->radio_rev == 6) {
   2992				for (core = 0; core < 2; core++) {
   2993					if (core == 0)
   2994						b43_radio_write(dev, 0x51,
   2995								0x7f);
   2996					else
   2997						b43_radio_write(dev, 0xd6,
   2998								0x7f);
   2999				}
   3000			}
   3001			switch (phy->radio_rev) {
   3002			case 3:
   3003				for (core = 0; core < 2; core++) {
   3004					if (core == 0) {
   3005						b43_radio_write(dev, 0x64,
   3006								0x13);
   3007						b43_radio_write(dev, 0x5F,
   3008								0x1F);
   3009						b43_radio_write(dev, 0x66,
   3010								0xEE);
   3011						b43_radio_write(dev, 0x59,
   3012								0x8A);
   3013						b43_radio_write(dev, 0x80,
   3014								0x3E);
   3015					} else {
   3016						b43_radio_write(dev, 0x69,
   3017								0x13);
   3018						b43_radio_write(dev, 0xE8,
   3019								0x1F);
   3020						b43_radio_write(dev, 0xEB,
   3021								0xEE);
   3022						b43_radio_write(dev, 0xDE,
   3023								0x8A);
   3024						b43_radio_write(dev, 0x105,
   3025								0x3E);
   3026					}
   3027				}
   3028				break;
   3029			case 7:
   3030			case 8:
   3031				if (!b43_is_40mhz(dev)) {
   3032					b43_radio_write(dev, 0x5F, 0x14);
   3033					b43_radio_write(dev, 0xE8, 0x12);
   3034				} else {
   3035					b43_radio_write(dev, 0x5F, 0x16);
   3036					b43_radio_write(dev, 0xE8, 0x16);
   3037				}
   3038				break;
   3039			case 14:
   3040				for (core = 0; core < 2; core++) {
   3041					int o = core ? 0x85 : 0;
   3042
   3043					b43_radio_write(dev, o + R2057_IPA2G_CASCONV_CORE0, 0x13);
   3044					b43_radio_write(dev, o + R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, 0x21);
   3045					b43_radio_write(dev, o + R2057_IPA2G_BIAS_FILTER_CORE0, 0xff);
   3046					b43_radio_write(dev, o + R2057_PAD2G_IDACS_CORE0, 0x88);
   3047					b43_radio_write(dev, o + R2057_PAD2G_TUNE_PUS_CORE0, 0x23);
   3048					b43_radio_write(dev, o + R2057_IPA2G_IMAIN_CORE0, 0x16);
   3049					b43_radio_write(dev, o + R2057_PAD_BIAS_FILTER_BWS_CORE0, 0x3e);
   3050					b43_radio_write(dev, o + R2057_BACKUP1_CORE0, 0x10);
   3051				}
   3052				break;
   3053			}
   3054		} else {
   3055			u16 freq = phy->chandef->chan->center_freq;
   3056			if ((freq >= 5180 && freq <= 5230) ||
   3057			    (freq >= 5745 && freq <= 5805)) {
   3058				b43_radio_write(dev, 0x7D, 0xFF);
   3059				b43_radio_write(dev, 0xFE, 0xFF);
   3060			}
   3061		}
   3062	} else {
   3063		if (phy->radio_rev != 5) {
   3064			for (core = 0; core < 2; core++) {
   3065				if (core == 0) {
   3066					b43_radio_write(dev, 0x5c, 0x61);
   3067					b43_radio_write(dev, 0x51, 0x70);
   3068				} else {
   3069					b43_radio_write(dev, 0xe1, 0x61);
   3070					b43_radio_write(dev, 0xd6, 0x70);
   3071				}
   3072			}
   3073		}
   3074	}
   3075
   3076	if (phy->radio_rev == 4) {
   3077		b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0x20);
   3078		b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0x20);
   3079		for (core = 0; core < 2; core++) {
   3080			if (core == 0) {
   3081				b43_radio_write(dev, 0x1a1, 0x00);
   3082				b43_radio_write(dev, 0x1a2, 0x3f);
   3083				b43_radio_write(dev, 0x1a6, 0x3f);
   3084			} else {
   3085				b43_radio_write(dev, 0x1a7, 0x00);
   3086				b43_radio_write(dev, 0x1ab, 0x3f);
   3087				b43_radio_write(dev, 0x1ac, 0x3f);
   3088			}
   3089		}
   3090	} else {
   3091		b43_phy_set(dev, B43_NPHY_AFECTL_C1, 0x4);
   3092		b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x4);
   3093		b43_phy_set(dev, B43_NPHY_AFECTL_C2, 0x4);
   3094		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4);
   3095
   3096		b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x1);
   3097		b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x1);
   3098		b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x1);
   3099		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x1);
   3100		b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0);
   3101		b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0);
   3102
   3103		b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x4);
   3104		b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x4);
   3105		b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x4);
   3106		b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4);
   3107	}
   3108
   3109	b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, 0x2);
   3110
   3111	b43_ntab_write(dev, B43_NTAB32(16, 0x100), 20);
   3112	b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x138), 2, ntab7_138_146);
   3113	b43_ntab_write(dev, B43_NTAB16(7, 0x141), 0x77);
   3114	b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x133), 3, ntab7_133);
   3115	b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x146), 2, ntab7_138_146);
   3116	b43_ntab_write(dev, B43_NTAB16(7, 0x123), 0x77);
   3117	b43_ntab_write(dev, B43_NTAB16(7, 0x12A), 0x77);
   3118
   3119	b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x02), 1, noise_tbl);
   3120	noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D;
   3121	b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x02), 2, noise_tbl);
   3122
   3123	b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x7E), 1, noise_tbl);
   3124	noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D;
   3125	b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x7E), 2, noise_tbl);
   3126
   3127	b43_nphy_gain_ctl_workarounds(dev);
   3128
   3129	/* TODO
   3130	b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4,
   3131			    aux_adc_vmid_rev7_core0);
   3132	b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4,
   3133			    aux_adc_vmid_rev7_core1);
   3134	b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0C), 4,
   3135			    aux_adc_gain_rev7);
   3136	b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1C), 4,
   3137			    aux_adc_gain_rev7);
   3138	*/
   3139}
   3140
   3141static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
   3142{
   3143	struct b43_phy_n *nphy = dev->phy.n;
   3144	struct ssb_sprom *sprom = dev->dev->bus_sprom;
   3145
   3146	/* TX to RX */
   3147	u8 tx2rx_events[7] = { 0x4, 0x3, 0x5, 0x2, 0x1, 0x8, 0x1F };
   3148	u8 tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1 };
   3149	/* RX to TX */
   3150	u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
   3151					0x1F };
   3152	u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
   3153	u8 rx2tx_events[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0x3, 0x4, 0x1F };
   3154	u8 rx2tx_delays[9] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 };
   3155
   3156	u16 vmids[5][4] = {
   3157		{ 0xa2, 0xb4, 0xb4, 0x89, }, /* 0 */
   3158		{ 0xb4, 0xb4, 0xb4, 0x24, }, /* 1 */
   3159		{ 0xa2, 0xb4, 0xb4, 0x74, }, /* 2 */
   3160		{ 0xa2, 0xb4, 0xb4, 0x270, }, /* 3 */
   3161		{ 0xa2, 0xb4, 0xb4, 0x00, }, /* 4 and 5 */
   3162	};
   3163	u16 gains[5][4] = {
   3164		{ 0x02, 0x02, 0x02, 0x00, }, /* 0 */
   3165		{ 0x02, 0x02, 0x02, 0x02, }, /* 1 */
   3166		{ 0x02, 0x02, 0x02, 0x04, }, /* 2 */
   3167		{ 0x02, 0x02, 0x02, 0x00, }, /* 3 */
   3168		{ 0x02, 0x02, 0x02, 0x00, }, /* 4 and 5 */
   3169	};
   3170	u16 *vmid, *gain;
   3171
   3172	u8 pdet_range;
   3173	u16 tmp16;
   3174	u32 tmp32;
   3175
   3176	b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1f8);
   3177	b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1f8);
   3178
   3179	tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
   3180	tmp32 &= 0xffffff;
   3181	b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
   3182
   3183	b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);
   3184	b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01B3);
   3185	b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);
   3186	b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016E);
   3187	b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00CD);
   3188	b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
   3189
   3190	b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_LOGAIN_B, 0x000C);
   3191	b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_LOGAIN_B, 0x000C);
   3192
   3193	/* TX to RX */
   3194	b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays,
   3195				 ARRAY_SIZE(tx2rx_events));
   3196
   3197	/* RX to TX */
   3198	if (b43_nphy_ipa(dev))
   3199		b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa,
   3200				rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa));
   3201	if (nphy->hw_phyrxchain != 3 &&
   3202	    nphy->hw_phyrxchain != nphy->hw_phytxchain) {
   3203		if (b43_nphy_ipa(dev)) {
   3204			rx2tx_delays[5] = 59;
   3205			rx2tx_delays[6] = 1;
   3206			rx2tx_events[7] = 0x1F;
   3207		}
   3208		b43_nphy_set_rf_sequence(dev, 0, rx2tx_events, rx2tx_delays,
   3209					 ARRAY_SIZE(rx2tx_events));
   3210	}
   3211
   3212	tmp16 = (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) ?
   3213		0x2 : 0x9C40;
   3214	b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16);
   3215
   3216	b43_phy_maskset(dev, B43_NPHY_SGILTRNOFFSET, 0xF0FF, 0x0700);
   3217
   3218	if (!b43_is_40mhz(dev)) {
   3219		b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
   3220		b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);
   3221	} else {
   3222		b43_ntab_write(dev, B43_NTAB32(16, 3), 0x14D);
   3223		b43_ntab_write(dev, B43_NTAB32(16, 127), 0x14D);
   3224	}
   3225
   3226	b43_nphy_gain_ctl_workarounds(dev);
   3227
   3228	b43_ntab_write(dev, B43_NTAB16(8, 0), 2);
   3229	b43_ntab_write(dev, B43_NTAB16(8, 16), 2);
   3230
   3231	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
   3232		pdet_range = sprom->fem.ghz2.pdet_range;
   3233	else
   3234		pdet_range = sprom->fem.ghz5.pdet_range;
   3235	vmid = vmids[min_t(u16, pdet_range, 4)];
   3236	gain = gains[min_t(u16, pdet_range, 4)];
   3237	switch (pdet_range) {
   3238	case 3:
   3239		if (!(dev->phy.rev >= 4 &&
   3240		      b43_current_band(dev->wl) == NL80211_BAND_2GHZ))
   3241			break;
   3242		fallthrough;
   3243	case 0:
   3244	case 1:
   3245		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4, vmid);
   3246		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4, vmid);
   3247		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0c), 4, gain);
   3248		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1c), 4, gain);
   3249		break;
   3250	case 2:
   3251		if (dev->phy.rev >= 6) {
   3252			if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
   3253				vmid[3] = 0x94;
   3254			else
   3255				vmid[3] = 0x8e;
   3256			gain[3] = 3;
   3257		} else if (dev->phy.rev == 5) {
   3258			vmid[3] = 0x84;
   3259			gain[3] = 2;
   3260		}
   3261		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4, vmid);
   3262		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4, vmid);
   3263		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0c), 4, gain);
   3264		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1c), 4, gain);
   3265		break;
   3266	case 4:
   3267	case 5:
   3268		if (b43_current_band(dev->wl) != NL80211_BAND_2GHZ) {
   3269			if (pdet_range == 4) {
   3270				vmid[3] = 0x8e;
   3271				tmp16 = 0x96;
   3272				gain[3] = 0x2;
   3273			} else {
   3274				vmid[3] = 0x89;
   3275				tmp16 = 0x89;
   3276				gain[3] = 0;
   3277			}
   3278		} else {
   3279			if (pdet_range == 4) {
   3280				vmid[3] = 0x89;
   3281				tmp16 = 0x8b;
   3282				gain[3] = 0x2;
   3283			} else {
   3284				vmid[3] = 0x74;
   3285				tmp16 = 0x70;
   3286				gain[3] = 0;
   3287			}
   3288		}
   3289		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4, vmid);
   3290		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0c), 4, gain);
   3291		vmid[3] = tmp16;
   3292		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4, vmid);
   3293		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1c), 4, gain);
   3294		break;
   3295	}
   3296
   3297	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_MAST_BIAS, 0x00);
   3298	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_MAST_BIAS, 0x00);
   3299	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
   3300	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
   3301	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_AUX, 0x07);
   3302	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07);
   3303	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88);
   3304	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88);
   3305	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_CMFB_IDAC, 0x00);
   3306	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_CMFB_IDAC, 0x00);
   3307	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
   3308	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
   3309
   3310	/* N PHY WAR TX Chain Update with hw_phytxchain as argument */
   3311
   3312	if ((sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
   3313	     b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ||
   3314	    (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
   3315	     b43_current_band(dev->wl) == NL80211_BAND_2GHZ))
   3316		tmp32 = 0x00088888;
   3317	else
   3318		tmp32 = 0x88888888;
   3319	b43_ntab_write(dev, B43_NTAB32(30, 1), tmp32);
   3320	b43_ntab_write(dev, B43_NTAB32(30, 2), tmp32);
   3321	b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32);
   3322
   3323	if (dev->phy.rev == 4 &&
   3324	    b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
   3325		b43_radio_write(dev, B2056_TX0 | B2056_TX_GMBB_IDAC,
   3326				0x70);
   3327		b43_radio_write(dev, B2056_TX1 | B2056_TX_GMBB_IDAC,
   3328				0x70);
   3329	}
   3330
   3331	/* Dropped probably-always-true condition */
   3332	b43_phy_write(dev, B43_NPHY_ED_CRS40ASSERTTHRESH0, 0x03eb);
   3333	b43_phy_write(dev, B43_NPHY_ED_CRS40ASSERTTHRESH1, 0x03eb);
   3334	b43_phy_write(dev, B43_NPHY_ED_CRS40DEASSERTTHRESH0, 0x0341);
   3335	b43_phy_write(dev, B43_NPHY_ED_CRS40DEASSERTTHRESH1, 0x0341);
   3336	b43_phy_write(dev, B43_NPHY_ED_CRS20LASSERTTHRESH0, 0x042b);
   3337	b43_phy_write(dev, B43_NPHY_ED_CRS20LASSERTTHRESH1, 0x042b);
   3338	b43_phy_write(dev, B43_NPHY_ED_CRS20LDEASSERTTHRESH0, 0x0381);
   3339	b43_phy_write(dev, B43_NPHY_ED_CRS20LDEASSERTTHRESH1, 0x0381);
   3340	b43_phy_write(dev, B43_NPHY_ED_CRS20UASSERTTHRESH0, 0x042b);
   3341	b43_phy_write(dev, B43_NPHY_ED_CRS20UASSERTTHRESH1, 0x042b);
   3342	b43_phy_write(dev, B43_NPHY_ED_CRS20UDEASSERTTHRESH0, 0x0381);
   3343	b43_phy_write(dev, B43_NPHY_ED_CRS20UDEASSERTTHRESH1, 0x0381);
   3344
   3345	if (dev->phy.rev >= 6 && sprom->boardflags2_lo & B43_BFL2_SINGLEANT_CCK) {
   3346		; /* TODO: 0x0080000000000000 HF */
   3347	}
   3348}
   3349
   3350static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
   3351{
   3352	struct ssb_sprom *sprom = dev->dev->bus_sprom;
   3353	struct b43_phy *phy = &dev->phy;
   3354	struct b43_phy_n *nphy = phy->n;
   3355
   3356	u8 events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 };
   3357	u8 delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 };
   3358
   3359	u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 };
   3360	u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
   3361
   3362	if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD ||
   3363	    dev->dev->board_type == BCMA_BOARD_TYPE_BCM943224M93) {
   3364		delays1[0] = 0x1;
   3365		delays1[5] = 0x14;
   3366	}
   3367
   3368	if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ &&
   3369	    nphy->band5g_pwrgain) {
   3370		b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8);
   3371		b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8);
   3372	} else {
   3373		b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8);
   3374		b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8);
   3375	}
   3376
   3377	b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A);
   3378	b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A);
   3379	if (dev->phy.rev < 3) {
   3380		b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
   3381		b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
   3382	}
   3383
   3384	if (dev->phy.rev < 2) {
   3385		b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000);
   3386		b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0x0000);
   3387		b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB);
   3388		b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB);
   3389		b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x0800);
   3390		b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x0800);
   3391	}
   3392
   3393	b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
   3394	b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
   3395	b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
   3396	b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
   3397
   3398	b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);
   3399	b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);
   3400
   3401	b43_nphy_gain_ctl_workarounds(dev);
   3402
   3403	if (dev->phy.rev < 2) {
   3404		if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2)
   3405			b43_hf_write(dev, b43_hf_read(dev) |
   3406					B43_HF_MLADVW);
   3407	} else if (dev->phy.rev == 2) {
   3408		b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0);
   3409		b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0);
   3410	}
   3411
   3412	if (dev->phy.rev < 2)
   3413		b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL,
   3414				~B43_NPHY_SCRAM_SIGCTL_SCM);
   3415
   3416	/* Set phase track alpha and beta */
   3417	b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125);
   3418	b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3);
   3419	b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105);
   3420	b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E);
   3421	b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);
   3422	b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
   3423
   3424	if (dev->phy.rev < 3) {
   3425		b43_phy_mask(dev, B43_NPHY_PIL_DW1,
   3426			     ~B43_NPHY_PIL_DW_64QAM & 0xFFFF);
   3427		b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5);
   3428		b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4);
   3429		b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00);
   3430	}
   3431
   3432	if (dev->phy.rev == 2)
   3433		b43_phy_set(dev, B43_NPHY_FINERX2_CGC,
   3434				B43_NPHY_FINERX2_CGC_DECGC);
   3435}
   3436
   3437/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */
   3438static void b43_nphy_workarounds(struct b43_wldev *dev)
   3439{
   3440	struct b43_phy *phy = &dev->phy;
   3441	struct b43_phy_n *nphy = phy->n;
   3442
   3443	if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
   3444		b43_nphy_classifier(dev, 1, 0);
   3445	else
   3446		b43_nphy_classifier(dev, 1, 1);
   3447
   3448	if (nphy->hang_avoid)
   3449		b43_nphy_stay_in_carrier_search(dev, 1);
   3450
   3451	b43_phy_set(dev, B43_NPHY_IQFLIP,
   3452		    B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
   3453
   3454	/* TODO: rev19+ */
   3455	if (dev->phy.rev >= 7)
   3456		b43_nphy_workarounds_rev7plus(dev);
   3457	else if (dev->phy.rev >= 3)
   3458		b43_nphy_workarounds_rev3plus(dev);
   3459	else
   3460		b43_nphy_workarounds_rev1_2(dev);
   3461
   3462	if (nphy->hang_avoid)
   3463		b43_nphy_stay_in_carrier_search(dev, 0);
   3464}
   3465
   3466/**************************************************
   3467 * Tx/Rx common
   3468 **************************************************/
   3469
   3470/*
   3471 * Transmits a known value for LO calibration
   3472 * https://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone
   3473 */
   3474static int b43_nphy_tx_tone(struct b43_wldev *dev, u32 freq, u16 max_val,
   3475			    bool iqmode, bool dac_test, bool modify_bbmult)
   3476{
   3477	u16 samp = b43_nphy_gen_load_samples(dev, freq, max_val, dac_test);
   3478	if (samp == 0)
   3479		return -1;
   3480	b43_nphy_run_samples(dev, samp, 0xFFFF, 0, iqmode, dac_test,
   3481			     modify_bbmult);
   3482	return 0;
   3483}
   3484
   3485/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */
   3486static void b43_nphy_update_txrx_chain(struct b43_wldev *dev)
   3487{
   3488	struct b43_phy_n *nphy = dev->phy.n;
   3489
   3490	bool override = false;
   3491	u16 chain = 0x33;
   3492
   3493	if (nphy->txrx_chain == 0) {
   3494		chain = 0x11;
   3495		override = true;
   3496	} else if (nphy->txrx_chain == 1) {
   3497		chain = 0x22;
   3498		override = true;
   3499	}
   3500
   3501	b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
   3502			~(B43_NPHY_RFSEQCA_TXEN | B43_NPHY_RFSEQCA_RXEN),
   3503			chain);
   3504
   3505	if (override)
   3506		b43_phy_set(dev, B43_NPHY_RFSEQMODE,
   3507				B43_NPHY_RFSEQMODE_CAOVER);
   3508	else
   3509		b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
   3510				~B43_NPHY_RFSEQMODE_CAOVER);
   3511}
   3512
   3513/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */
   3514static void b43_nphy_stop_playback(struct b43_wldev *dev)
   3515{
   3516	struct b43_phy *phy = &dev->phy;
   3517	struct b43_phy_n *nphy = dev->phy.n;
   3518	u16 tmp;
   3519
   3520	if (nphy->hang_avoid)
   3521		b43_nphy_stay_in_carrier_search(dev, 1);
   3522
   3523	tmp = b43_phy_read(dev, B43_NPHY_SAMP_STAT);
   3524	if (tmp & 0x1)
   3525		b43_phy_set(dev, B43_NPHY_SAMP_CMD, B43_NPHY_SAMP_CMD_STOP);
   3526	else if (tmp & 0x2)
   3527		b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
   3528
   3529	b43_phy_mask(dev, B43_NPHY_SAMP_CMD, ~0x0004);
   3530
   3531	if (nphy->bb_mult_save & 0x80000000) {
   3532		tmp = nphy->bb_mult_save & 0xFFFF;
   3533		b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
   3534		nphy->bb_mult_save = 0;
   3535	}
   3536
   3537	if (phy->rev >= 7 && nphy->lpf_bw_overrode_for_sample_play) {
   3538		if (phy->rev >= 19)
   3539			b43_nphy_rf_ctl_override_rev19(dev, 0x80, 0, 0, true,
   3540						       1);
   3541		else
   3542			b43_nphy_rf_ctl_override_rev7(dev, 0x80, 0, 0, true, 1);
   3543		nphy->lpf_bw_overrode_for_sample_play = false;
   3544	}
   3545
   3546	if (nphy->hang_avoid)
   3547		b43_nphy_stay_in_carrier_search(dev, 0);
   3548}
   3549
   3550/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/IqCalGainParams */
   3551static void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core,
   3552					struct nphy_txgains target,
   3553					struct nphy_iqcal_params *params)
   3554{
   3555	struct b43_phy *phy = &dev->phy;
   3556	int i, j, indx;
   3557	u16 gain;
   3558
   3559	if (dev->phy.rev >= 3) {
   3560		params->tx_lpf = target.tx_lpf[core]; /* Rev 7+ */
   3561		params->txgm = target.txgm[core];
   3562		params->pga = target.pga[core];
   3563		params->pad = target.pad[core];
   3564		params->ipa = target.ipa[core];
   3565		if (phy->rev >= 19) {
   3566			/* TODO */
   3567		} else if (phy->rev >= 7) {
   3568			params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 3) | (params->ipa) | (params->tx_lpf << 15);
   3569		} else {
   3570			params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 4) | (params->ipa);
   3571		}
   3572		for (j = 0; j < 5; j++)
   3573			params->ncorr[j] = 0x79;
   3574	} else {
   3575		gain = (target.pad[core]) | (target.pga[core] << 4) |
   3576			(target.txgm[core] << 8);
   3577
   3578		indx = (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ?
   3579			1 : 0;
   3580		for (i = 0; i < 9; i++)
   3581			if (tbl_iqcal_gainparams[indx][i][0] == gain)
   3582				break;
   3583		i = min(i, 8);
   3584
   3585		params->txgm = tbl_iqcal_gainparams[indx][i][1];
   3586		params->pga = tbl_iqcal_gainparams[indx][i][2];
   3587		params->pad = tbl_iqcal_gainparams[indx][i][3];
   3588		params->cal_gain = (params->txgm << 7) | (params->pga << 4) |
   3589					(params->pad << 2);
   3590		for (j = 0; j < 4; j++)
   3591			params->ncorr[j] = tbl_iqcal_gainparams[indx][i][4 + j];
   3592	}
   3593}
   3594
   3595/**************************************************
   3596 * Tx and Rx
   3597 **************************************************/
   3598
   3599/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */
   3600static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
   3601{
   3602	struct b43_phy *phy = &dev->phy;
   3603	struct b43_phy_n *nphy = dev->phy.n;
   3604	u8 i;
   3605	u16 bmask, val, tmp;
   3606	enum nl80211_band band = b43_current_band(dev->wl);
   3607
   3608	if (nphy->hang_avoid)
   3609		b43_nphy_stay_in_carrier_search(dev, 1);
   3610
   3611	nphy->txpwrctrl = enable;
   3612	if (!enable) {
   3613		if (dev->phy.rev >= 3 &&
   3614		    (b43_phy_read(dev, B43_NPHY_TXPCTL_CMD) &
   3615		     (B43_NPHY_TXPCTL_CMD_COEFF |
   3616		      B43_NPHY_TXPCTL_CMD_HWPCTLEN |
   3617		      B43_NPHY_TXPCTL_CMD_PCTLEN))) {
   3618			/* We disable enabled TX pwr ctl, save it's state */
   3619			nphy->tx_pwr_idx[0] = b43_phy_read(dev,
   3620						B43_NPHY_C1_TXPCTL_STAT) & 0x7f;
   3621			nphy->tx_pwr_idx[1] = b43_phy_read(dev,
   3622						B43_NPHY_C2_TXPCTL_STAT) & 0x7f;
   3623		}
   3624
   3625		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6840);
   3626		for (i = 0; i < 84; i++)
   3627			b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0);
   3628
   3629		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6C40);
   3630		for (i = 0; i < 84; i++)
   3631			b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0);
   3632
   3633		tmp = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN;
   3634		if (dev->phy.rev >= 3)
   3635			tmp |= B43_NPHY_TXPCTL_CMD_PCTLEN;
   3636		b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD, ~tmp);
   3637
   3638		if (dev->phy.rev >= 3) {
   3639			b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100);
   3640			b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100);
   3641		} else {
   3642			b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000);
   3643		}
   3644
   3645		if (dev->phy.rev == 2)
   3646			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
   3647				~B43_NPHY_BPHY_CTL3_SCALE, 0x53);
   3648		else if (dev->phy.rev < 2)
   3649			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
   3650				~B43_NPHY_BPHY_CTL3_SCALE, 0x5A);
   3651
   3652		if (dev->phy.rev < 2 && b43_is_40mhz(dev))
   3653			b43_hf_write(dev, b43_hf_read(dev) | B43_HF_TSSIRPSMW);
   3654	} else {
   3655		b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84,
   3656				    nphy->adj_pwr_tbl);
   3657		b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84,
   3658				    nphy->adj_pwr_tbl);
   3659
   3660		bmask = B43_NPHY_TXPCTL_CMD_COEFF |
   3661			B43_NPHY_TXPCTL_CMD_HWPCTLEN;
   3662		/* wl does useless check for "enable" param here */
   3663		val = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN;
   3664		if (dev->phy.rev >= 3) {
   3665			bmask |= B43_NPHY_TXPCTL_CMD_PCTLEN;
   3666			if (val)
   3667				val |= B43_NPHY_TXPCTL_CMD_PCTLEN;
   3668		}
   3669		b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, ~(bmask), val);
   3670
   3671		if (band == NL80211_BAND_5GHZ) {
   3672			if (phy->rev >= 19) {
   3673				/* TODO */
   3674			} else if (phy->rev >= 7) {
   3675				b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
   3676						~B43_NPHY_TXPCTL_CMD_INIT,
   3677						0x32);
   3678				b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,
   3679						~B43_NPHY_TXPCTL_INIT_PIDXI1,
   3680						0x32);
   3681			} else {
   3682				b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
   3683						~B43_NPHY_TXPCTL_CMD_INIT,
   3684						0x64);
   3685				if (phy->rev > 1)
   3686					b43_phy_maskset(dev,
   3687							B43_NPHY_TXPCTL_INIT,
   3688							~B43_NPHY_TXPCTL_INIT_PIDXI1,
   3689							0x64);
   3690			}
   3691		}
   3692
   3693		if (dev->phy.rev >= 3) {
   3694			if (nphy->tx_pwr_idx[0] != 128 &&
   3695			    nphy->tx_pwr_idx[1] != 128) {
   3696				/* Recover TX pwr ctl state */
   3697				b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
   3698						~B43_NPHY_TXPCTL_CMD_INIT,
   3699						nphy->tx_pwr_idx[0]);
   3700				if (dev->phy.rev > 1)
   3701					b43_phy_maskset(dev,
   3702						B43_NPHY_TXPCTL_INIT,
   3703						~0xff, nphy->tx_pwr_idx[1]);
   3704			}
   3705		}
   3706
   3707		if (phy->rev >= 7) {
   3708			/* TODO */
   3709		}
   3710
   3711		if (dev->phy.rev >= 3) {
   3712			b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x100);
   3713			b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x100);
   3714		} else {
   3715			b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4000);
   3716		}
   3717
   3718		if (dev->phy.rev == 2)
   3719			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x3b);
   3720		else if (dev->phy.rev < 2)
   3721			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x40);
   3722
   3723		if (dev->phy.rev < 2 && b43_is_40mhz(dev))
   3724			b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_TSSIRPSMW);
   3725
   3726		if (b43_nphy_ipa(dev)) {
   3727			b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x4);
   3728			b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x4);
   3729		}
   3730	}
   3731
   3732	if (nphy->hang_avoid)
   3733		b43_nphy_stay_in_carrier_search(dev, 0);
   3734}
   3735
   3736/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrFix */
   3737static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
   3738{
   3739	struct b43_phy *phy = &dev->phy;
   3740	struct b43_phy_n *nphy = dev->phy.n;
   3741	struct ssb_sprom *sprom = dev->dev->bus_sprom;
   3742
   3743	u8 txpi[2], bbmult, i;
   3744	u16 tmp, radio_gain, dac_gain;
   3745	u16 freq = phy->chandef->chan->center_freq;
   3746	u32 txgain;
   3747	/* u32 gaintbl; rev3+ */
   3748
   3749	if (nphy->hang_avoid)
   3750		b43_nphy_stay_in_carrier_search(dev, 1);
   3751
   3752	/* TODO: rev19+ */
   3753	if (dev->phy.rev >= 7) {
   3754		txpi[0] = txpi[1] = 30;
   3755	} else if (dev->phy.rev >= 3) {
   3756		txpi[0] = 40;
   3757		txpi[1] = 40;
   3758	} else if (sprom->revision < 4) {
   3759		txpi[0] = 72;
   3760		txpi[1] = 72;
   3761	} else {
   3762		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
   3763			txpi[0] = sprom->txpid2g[0];
   3764			txpi[1] = sprom->txpid2g[1];
   3765		} else if (freq >= 4900 && freq < 5100) {
   3766			txpi[0] = sprom->txpid5gl[0];
   3767			txpi[1] = sprom->txpid5gl[1];
   3768		} else if (freq >= 5100 && freq < 5500) {
   3769			txpi[0] = sprom->txpid5g[0];
   3770			txpi[1] = sprom->txpid5g[1];
   3771		} else if (freq >= 5500) {
   3772			txpi[0] = sprom->txpid5gh[0];
   3773			txpi[1] = sprom->txpid5gh[1];
   3774		} else {
   3775			txpi[0] = 91;
   3776			txpi[1] = 91;
   3777		}
   3778	}
   3779	if (dev->phy.rev < 7 &&
   3780	    (txpi[0] < 40 || txpi[0] > 100 || txpi[1] < 40 || txpi[1] > 100))
   3781		txpi[0] = txpi[1] = 91;
   3782
   3783	/*
   3784	for (i = 0; i < 2; i++) {
   3785		nphy->txpwrindex[i].index_internal = txpi[i];
   3786		nphy->txpwrindex[i].index_internal_save = txpi[i];
   3787	}
   3788	*/
   3789
   3790	for (i = 0; i < 2; i++) {
   3791		const u32 *table = b43_nphy_get_tx_gain_table(dev);
   3792
   3793		if (!table)
   3794			break;
   3795		txgain = *(table + txpi[i]);
   3796
   3797		if (dev->phy.rev >= 3)
   3798			radio_gain = (txgain >> 16) & 0x1FFFF;
   3799		else
   3800			radio_gain = (txgain >> 16) & 0x1FFF;
   3801
   3802		if (dev->phy.rev >= 7)
   3803			dac_gain = (txgain >> 8) & 0x7;
   3804		else
   3805			dac_gain = (txgain >> 8) & 0x3F;
   3806		bbmult = txgain & 0xFF;
   3807
   3808		if (dev->phy.rev >= 3) {
   3809			if (i == 0)
   3810				b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100);
   3811			else
   3812				b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100);
   3813		} else {
   3814			b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000);
   3815		}
   3816
   3817		if (i == 0)
   3818			b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN1, dac_gain);
   3819		else
   3820			b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN2, dac_gain);
   3821
   3822		b43_ntab_write(dev, B43_NTAB16(0x7, 0x110 + i), radio_gain);
   3823
   3824		tmp = b43_ntab_read(dev, B43_NTAB16(0xF, 0x57));
   3825		if (i == 0)
   3826			tmp = (tmp & 0x00FF) | (bbmult << 8);
   3827		else
   3828			tmp = (tmp & 0xFF00) | bbmult;
   3829		b43_ntab_write(dev, B43_NTAB16(0xF, 0x57), tmp);
   3830
   3831		if (b43_nphy_ipa(dev)) {
   3832			u32 tmp32;
   3833			u16 reg = (i == 0) ?
   3834				B43_NPHY_PAPD_EN0 : B43_NPHY_PAPD_EN1;
   3835			tmp32 = b43_ntab_read(dev, B43_NTAB32(26 + i,
   3836							      576 + txpi[i]));
   3837			b43_phy_maskset(dev, reg, 0xE00F, (u32) tmp32 << 4);
   3838			b43_phy_set(dev, reg, 0x4);
   3839		}
   3840	}
   3841
   3842	b43_phy_mask(dev, B43_NPHY_BPHY_CTL2, ~B43_NPHY_BPHY_CTL2_LUT);
   3843
   3844	if (nphy->hang_avoid)
   3845		b43_nphy_stay_in_carrier_search(dev, 0);
   3846}
   3847
   3848static void b43_nphy_ipa_internal_tssi_setup(struct b43_wldev *dev)
   3849{
   3850	struct b43_phy *phy = &dev->phy;
   3851
   3852	u8 core;
   3853	u16 r; /* routing */
   3854
   3855	if (phy->rev >= 19) {
   3856		/* TODO */
   3857	} else if (phy->rev >= 7) {
   3858		for (core = 0; core < 2; core++) {
   3859			r = core ? 0x190 : 0x170;
   3860			if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
   3861				b43_radio_write(dev, r + 0x5, 0x5);
   3862				b43_radio_write(dev, r + 0x9, 0xE);
   3863				if (phy->rev != 5)
   3864					b43_radio_write(dev, r + 0xA, 0);
   3865				if (phy->rev != 7)
   3866					b43_radio_write(dev, r + 0xB, 1);
   3867				else
   3868					b43_radio_write(dev, r + 0xB, 0x31);
   3869			} else {
   3870				b43_radio_write(dev, r + 0x5, 0x9);
   3871				b43_radio_write(dev, r + 0x9, 0xC);
   3872				b43_radio_write(dev, r + 0xB, 0x0);
   3873				if (phy->rev != 5)
   3874					b43_radio_write(dev, r + 0xA, 1);
   3875				else
   3876					b43_radio_write(dev, r + 0xA, 0x31);
   3877			}
   3878			b43_radio_write(dev, r + 0x6, 0);
   3879			b43_radio_write(dev, r + 0x7, 0);
   3880			b43_radio_write(dev, r + 0x8, 3);
   3881			b43_radio_write(dev, r + 0xC, 0);
   3882		}
   3883	} else {
   3884		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
   3885			b43_radio_write(dev, B2056_SYN_RESERVED_ADDR31, 0x128);
   3886		else
   3887			b43_radio_write(dev, B2056_SYN_RESERVED_ADDR31, 0x80);
   3888		b43_radio_write(dev, B2056_SYN_RESERVED_ADDR30, 0);
   3889		b43_radio_write(dev, B2056_SYN_GPIO_MASTER1, 0x29);
   3890
   3891		for (core = 0; core < 2; core++) {
   3892			r = core ? B2056_TX1 : B2056_TX0;
   3893
   3894			b43_radio_write(dev, r | B2056_TX_IQCAL_VCM_HG, 0);
   3895			b43_radio_write(dev, r | B2056_TX_IQCAL_IDAC, 0);
   3896			b43_radio_write(dev, r | B2056_TX_TSSI_VCM, 3);
   3897			b43_radio_write(dev, r | B2056_TX_TX_AMP_DET, 0);
   3898			b43_radio_write(dev, r | B2056_TX_TSSI_MISC1, 8);
   3899			b43_radio_write(dev, r | B2056_TX_TSSI_MISC2, 0);
   3900			b43_radio_write(dev, r | B2056_TX_TSSI_MISC3, 0);
   3901			if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
   3902				b43_radio_write(dev, r | B2056_TX_TX_SSI_MASTER,
   3903						0x5);
   3904				if (phy->rev != 5)
   3905					b43_radio_write(dev, r | B2056_TX_TSSIA,
   3906							0x00);
   3907				if (phy->rev >= 5)
   3908					b43_radio_write(dev, r | B2056_TX_TSSIG,
   3909							0x31);
   3910				else
   3911					b43_radio_write(dev, r | B2056_TX_TSSIG,
   3912							0x11);
   3913				b43_radio_write(dev, r | B2056_TX_TX_SSI_MUX,
   3914						0xE);
   3915			} else {
   3916				b43_radio_write(dev, r | B2056_TX_TX_SSI_MASTER,
   3917						0x9);
   3918				b43_radio_write(dev, r | B2056_TX_TSSIA, 0x31);
   3919				b43_radio_write(dev, r | B2056_TX_TSSIG, 0x0);
   3920				b43_radio_write(dev, r | B2056_TX_TX_SSI_MUX,
   3921						0xC);
   3922			}
   3923		}
   3924	}
   3925}
   3926
   3927/*
   3928 * Stop radio and transmit known signal. Then check received signal strength to
   3929 * get TSSI (Transmit Signal Strength Indicator).
   3930 * https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlIdleTssi
   3931 */
   3932static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
   3933{
   3934	struct b43_phy *phy = &dev->phy;
   3935	struct b43_phy_n *nphy = dev->phy.n;
   3936
   3937	u32 tmp;
   3938	s32 rssi[4] = { };
   3939
   3940	if (phy->chandef->chan->flags & IEEE80211_CHAN_NO_IR)
   3941		return;
   3942
   3943	if (b43_nphy_ipa(dev))
   3944		b43_nphy_ipa_internal_tssi_setup(dev);
   3945
   3946	if (phy->rev >= 19)
   3947		b43_nphy_rf_ctl_override_rev19(dev, 0x1000, 0, 3, false, 0);
   3948	else if (phy->rev >= 7)
   3949		b43_nphy_rf_ctl_override_rev7(dev, 0x1000, 0, 3, false, 0);
   3950	else if (phy->rev >= 3)
   3951		b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, false);
   3952
   3953	b43_nphy_stop_playback(dev);
   3954	b43_nphy_tx_tone(dev, 4000, 0, false, false, false);
   3955	udelay(20);
   3956	tmp = b43_nphy_poll_rssi(dev, N_RSSI_TSSI_2G, rssi, 1);
   3957	b43_nphy_stop_playback(dev);
   3958
   3959	b43_nphy_rssi_select(dev, 0, N_RSSI_W1);
   3960
   3961	if (phy->rev >= 19)
   3962		b43_nphy_rf_ctl_override_rev19(dev, 0x1000, 0, 3, true, 0);
   3963	else if (phy->rev >= 7)
   3964		b43_nphy_rf_ctl_override_rev7(dev, 0x1000, 0, 3, true, 0);
   3965	else if (phy->rev >= 3)
   3966		b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, true);
   3967
   3968	if (phy->rev >= 19) {
   3969		/* TODO */
   3970		return;
   3971	} else if (phy->rev >= 3) {
   3972		nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 24) & 0xFF;
   3973		nphy->pwr_ctl_info[1].idle_tssi_5g = (tmp >> 8) & 0xFF;
   3974	} else {
   3975		nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 16) & 0xFF;
   3976		nphy->pwr_ctl_info[1].idle_tssi_5g = tmp & 0xFF;
   3977	}
   3978	nphy->pwr_ctl_info[0].idle_tssi_2g = (tmp >> 24) & 0xFF;
   3979	nphy->pwr_ctl_info[1].idle_tssi_2g = (tmp >> 8) & 0xFF;
   3980}
   3981
   3982/* https://bcm-v4.sipsolutions.net/PHY/N/TxPwrLimitToTbl */
   3983static void b43_nphy_tx_prepare_adjusted_power_table(struct b43_wldev *dev)
   3984{
   3985	struct b43_phy_n *nphy = dev->phy.n;
   3986
   3987	u8 idx, delta;
   3988	u8 i, stf_mode;
   3989
   3990	/* Array adj_pwr_tbl corresponds to the hardware table. It consists of
   3991	 * 21 groups, each containing 4 entries.
   3992	 *
   3993	 * First group has entries for CCK modulation.
   3994	 * The rest of groups has 1 entry per modulation (SISO, CDD, STBC, SDM).
   3995	 *
   3996	 * Group 0 is for CCK
   3997	 * Groups 1..4 use BPSK (group per coding rate)
   3998	 * Groups 5..8 use QPSK (group per coding rate)
   3999	 * Groups 9..12 use 16-QAM (group per coding rate)
   4000	 * Groups 13..16 use 64-QAM (group per coding rate)
   4001	 * Groups 17..20 are unknown
   4002	 */
   4003
   4004	for (i = 0; i < 4; i++)
   4005		nphy->adj_pwr_tbl[i] = nphy->tx_power_offset[i];
   4006
   4007	for (stf_mode = 0; stf_mode < 4; stf_mode++) {
   4008		delta = 0;
   4009		switch (stf_mode) {
   4010		case 0:
   4011			if (b43_is_40mhz(dev) && dev->phy.rev >= 5) {
   4012				idx = 68;
   4013			} else {
   4014				delta = 1;
   4015				idx = b43_is_40mhz(dev) ? 52 : 4;
   4016			}
   4017			break;
   4018		case 1:
   4019			idx = b43_is_40mhz(dev) ? 76 : 28;
   4020			break;
   4021		case 2:
   4022			idx = b43_is_40mhz(dev) ? 84 : 36;
   4023			break;
   4024		case 3:
   4025			idx = b43_is_40mhz(dev) ? 92 : 44;
   4026			break;
   4027		}
   4028
   4029		for (i = 0; i < 20; i++) {
   4030			nphy->adj_pwr_tbl[4 + 4 * i + stf_mode] =
   4031				nphy->tx_power_offset[idx];
   4032			if (i == 0)
   4033				idx += delta;
   4034			if (i == 14)
   4035				idx += 1 - delta;
   4036			if (i == 3 || i == 4 || i == 7 || i == 8 || i == 11 ||
   4037			    i == 13)
   4038				idx += 1;
   4039		}
   4040	}
   4041}
   4042
   4043/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlSetup */
   4044static void b43_nphy_tx_power_ctl_setup(struct b43_wldev *dev)
   4045{
   4046	struct b43_phy *phy = &dev->phy;
   4047	struct b43_phy_n *nphy = dev->phy.n;
   4048	struct ssb_sprom *sprom = dev->dev->bus_sprom;
   4049
   4050	s16 a1[2], b0[2], b1[2];
   4051	u8 idle[2];
   4052	u8 ppr_max;
   4053	s8 target[2];
   4054	s32 num, den, pwr;
   4055	u32 regval[64];
   4056
   4057	u16 freq = phy->chandef->chan->center_freq;
   4058	u16 tmp;
   4059	u16 r; /* routing */
   4060	u8 i, c;
   4061
   4062	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) {
   4063		b43_maskset32(dev, B43_MMIO_MACCTL, ~0, 0x200000);
   4064		b43_read32(dev, B43_MMIO_MACCTL);
   4065		udelay(1);
   4066	}
   4067
   4068	if (nphy->hang_avoid)
   4069		b43_nphy_stay_in_carrier_search(dev, true);
   4070
   4071	b43_phy_set(dev, B43_NPHY_TSSIMODE, B43_NPHY_TSSIMODE_EN);
   4072	if (dev->phy.rev >= 3)
   4073		b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD,
   4074			     ~B43_NPHY_TXPCTL_CMD_PCTLEN & 0xFFFF);
   4075	else
   4076		b43_phy_set(dev, B43_NPHY_TXPCTL_CMD,
   4077			    B43_NPHY_TXPCTL_CMD_PCTLEN);
   4078
   4079	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12)
   4080		b43_maskset32(dev, B43_MMIO_MACCTL, ~0x200000, 0);
   4081
   4082	if (sprom->revision < 4) {
   4083		idle[0] = nphy->pwr_ctl_info[0].idle_tssi_2g;
   4084		idle[1] = nphy->pwr_ctl_info[1].idle_tssi_2g;
   4085		target[0] = target[1] = 52;
   4086		a1[0] = a1[1] = -424;
   4087		b0[0] = b0[1] = 5612;
   4088		b1[0] = b1[1] = -1393;
   4089	} else {
   4090		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
   4091			for (c = 0; c < 2; c++) {
   4092				idle[c] = nphy->pwr_ctl_info[c].idle_tssi_2g;
   4093				target[c] = sprom->core_pwr_info[c].maxpwr_2g;
   4094				a1[c] = sprom->core_pwr_info[c].pa_2g[0];
   4095				b0[c] = sprom->core_pwr_info[c].pa_2g[1];
   4096				b1[c] = sprom->core_pwr_info[c].pa_2g[2];
   4097			}
   4098		} else if (freq >= 4900 && freq < 5100) {
   4099			for (c = 0; c < 2; c++) {
   4100				idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g;
   4101				target[c] = sprom->core_pwr_info[c].maxpwr_5gl;
   4102				a1[c] = sprom->core_pwr_info[c].pa_5gl[0];
   4103				b0[c] = sprom->core_pwr_info[c].pa_5gl[1];
   4104				b1[c] = sprom->core_pwr_info[c].pa_5gl[2];
   4105			}
   4106		} else if (freq >= 5100 && freq < 5500) {
   4107			for (c = 0; c < 2; c++) {
   4108				idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g;
   4109				target[c] = sprom->core_pwr_info[c].maxpwr_5g;
   4110				a1[c] = sprom->core_pwr_info[c].pa_5g[0];
   4111				b0[c] = sprom->core_pwr_info[c].pa_5g[1];
   4112				b1[c] = sprom->core_pwr_info[c].pa_5g[2];
   4113			}
   4114		} else if (freq >= 5500) {
   4115			for (c = 0; c < 2; c++) {
   4116				idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g;
   4117				target[c] = sprom->core_pwr_info[c].maxpwr_5gh;
   4118				a1[c] = sprom->core_pwr_info[c].pa_5gh[0];
   4119				b0[c] = sprom->core_pwr_info[c].pa_5gh[1];
   4120				b1[c] = sprom->core_pwr_info[c].pa_5gh[2];
   4121			}
   4122		} else {
   4123			idle[0] = nphy->pwr_ctl_info[0].idle_tssi_5g;
   4124			idle[1] = nphy->pwr_ctl_info[1].idle_tssi_5g;
   4125			target[0] = target[1] = 52;
   4126			a1[0] = a1[1] = -424;
   4127			b0[0] = b0[1] = 5612;
   4128			b1[0] = b1[1] = -1393;
   4129		}
   4130	}
   4131
   4132	ppr_max = b43_ppr_get_max(dev, &nphy->tx_pwr_max_ppr);
   4133	if (ppr_max) {
   4134		target[0] = ppr_max;
   4135		target[1] = ppr_max;
   4136	}
   4137
   4138	if (dev->phy.rev >= 3) {
   4139		if (sprom->fem.ghz2.tssipos)
   4140			b43_phy_set(dev, B43_NPHY_TXPCTL_ITSSI, 0x4000);
   4141		if (dev->phy.rev >= 7) {
   4142			for (c = 0; c < 2; c++) {
   4143				r = c ? 0x190 : 0x170;
   4144				if (b43_nphy_ipa(dev))
   4145					b43_radio_write(dev, r + 0x9, (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) ? 0xE : 0xC);
   4146			}
   4147		} else {
   4148			if (b43_nphy_ipa(dev)) {
   4149				tmp = (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ? 0xC : 0xE;
   4150				b43_radio_write(dev,
   4151					B2056_TX0 | B2056_TX_TX_SSI_MUX, tmp);
   4152				b43_radio_write(dev,
   4153					B2056_TX1 | B2056_TX_TX_SSI_MUX, tmp);
   4154			} else {
   4155				b43_radio_write(dev,
   4156					B2056_TX0 | B2056_TX_TX_SSI_MUX, 0x11);
   4157				b43_radio_write(dev,
   4158					B2056_TX1 | B2056_TX_TX_SSI_MUX, 0x11);
   4159			}
   4160		}
   4161	}
   4162
   4163	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) {
   4164		b43_maskset32(dev, B43_MMIO_MACCTL, ~0, 0x200000);
   4165		b43_read32(dev, B43_MMIO_MACCTL);
   4166		udelay(1);
   4167	}
   4168
   4169	if (phy->rev >= 19) {
   4170		/* TODO */
   4171	} else if (phy->rev >= 7) {
   4172		b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
   4173				~B43_NPHY_TXPCTL_CMD_INIT, 0x19);
   4174		b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,
   4175				~B43_NPHY_TXPCTL_INIT_PIDXI1, 0x19);
   4176	} else {
   4177		b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
   4178				~B43_NPHY_TXPCTL_CMD_INIT, 0x40);
   4179		if (dev->phy.rev > 1)
   4180			b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,
   4181				~B43_NPHY_TXPCTL_INIT_PIDXI1, 0x40);
   4182	}
   4183
   4184	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12)
   4185		b43_maskset32(dev, B43_MMIO_MACCTL, ~0x200000, 0);
   4186
   4187	b43_phy_write(dev, B43_NPHY_TXPCTL_N,
   4188		      0xF0 << B43_NPHY_TXPCTL_N_TSSID_SHIFT |
   4189		      3 << B43_NPHY_TXPCTL_N_NPTIL2_SHIFT);
   4190	b43_phy_write(dev, B43_NPHY_TXPCTL_ITSSI,
   4191		      idle[0] << B43_NPHY_TXPCTL_ITSSI_0_SHIFT |
   4192		      idle[1] << B43_NPHY_TXPCTL_ITSSI_1_SHIFT |
   4193		      B43_NPHY_TXPCTL_ITSSI_BINF);
   4194	b43_phy_write(dev, B43_NPHY_TXPCTL_TPWR,
   4195		      target[0] << B43_NPHY_TXPCTL_TPWR_0_SHIFT |
   4196		      target[1] << B43_NPHY_TXPCTL_TPWR_1_SHIFT);
   4197
   4198	for (c = 0; c < 2; c++) {
   4199		for (i = 0; i < 64; i++) {
   4200			num = 8 * (16 * b0[c] + b1[c] * i);
   4201			den = 32768 + a1[c] * i;
   4202			pwr = max((4 * num + den / 2) / den, -8);
   4203			if (dev->phy.rev < 3 && (i <= (31 - idle[c] + 1)))
   4204				pwr = max(pwr, target[c] + 1);
   4205			regval[i] = pwr;
   4206		}
   4207		b43_ntab_write_bulk(dev, B43_NTAB32(26 + c, 0), 64, regval);
   4208	}
   4209
   4210	b43_nphy_tx_prepare_adjusted_power_table(dev);
   4211	b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84, nphy->adj_pwr_tbl);
   4212	b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84, nphy->adj_pwr_tbl);
   4213
   4214	if (nphy->hang_avoid)
   4215		b43_nphy_stay_in_carrier_search(dev, false);
   4216}
   4217
   4218static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev)
   4219{
   4220	struct b43_phy *phy = &dev->phy;
   4221
   4222	const u32 *table = NULL;
   4223	u32 rfpwr_offset;
   4224	u8 pga_gain, pad_gain;
   4225	int i;
   4226	const s16 *rf_pwr_offset_table = NULL;
   4227
   4228	table = b43_nphy_get_tx_gain_table(dev);
   4229	if (!table)
   4230		return;
   4231
   4232	b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table);
   4233	b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table);
   4234
   4235	if (phy->rev < 3)
   4236		return;
   4237
   4238#if 0
   4239	nphy->gmval = (table[0] >> 16) & 0x7000;
   4240#endif
   4241
   4242	if (phy->rev >= 19) {
   4243		return;
   4244	} else if (phy->rev >= 7) {
   4245		rf_pwr_offset_table = b43_ntab_get_rf_pwr_offset_table(dev);
   4246		if (!rf_pwr_offset_table)
   4247			return;
   4248		/* TODO: Enable this once we have gains configured */
   4249		return;
   4250	}
   4251
   4252	for (i = 0; i < 128; i++) {
   4253		if (phy->rev >= 19) {
   4254			/* TODO */
   4255			return;
   4256		} else if (phy->rev >= 7) {
   4257			pga_gain = (table[i] >> 24) & 0xf;
   4258			pad_gain = (table[i] >> 19) & 0x1f;
   4259			if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
   4260				rfpwr_offset = rf_pwr_offset_table[pad_gain];
   4261			else
   4262				rfpwr_offset = rf_pwr_offset_table[pga_gain];
   4263		} else {
   4264			pga_gain = (table[i] >> 24) & 0xF;
   4265			if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
   4266				rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain];
   4267			else
   4268				rfpwr_offset = 0; /* FIXME */
   4269		}
   4270
   4271		b43_ntab_write(dev, B43_NTAB32(26, 576 + i), rfpwr_offset);
   4272		b43_ntab_write(dev, B43_NTAB32(27, 576 + i), rfpwr_offset);
   4273	}
   4274}
   4275
   4276/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */
   4277static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable)
   4278{
   4279	struct b43_phy_n *nphy = dev->phy.n;
   4280	enum nl80211_band band;
   4281	u16 tmp;
   4282
   4283	if (!enable) {
   4284		nphy->rfctrl_intc1_save = b43_phy_read(dev,
   4285						       B43_NPHY_RFCTL_INTC1);
   4286		nphy->rfctrl_intc2_save = b43_phy_read(dev,
   4287						       B43_NPHY_RFCTL_INTC2);
   4288		band = b43_current_band(dev->wl);
   4289		if (dev->phy.rev >= 7) {
   4290			tmp = 0x1480;
   4291		} else if (dev->phy.rev >= 3) {
   4292			if (band == NL80211_BAND_5GHZ)
   4293				tmp = 0x600;
   4294			else
   4295				tmp = 0x480;
   4296		} else {
   4297			if (band == NL80211_BAND_5GHZ)
   4298				tmp = 0x180;
   4299			else
   4300				tmp = 0x120;
   4301		}
   4302		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp);
   4303		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp);
   4304	} else {
   4305		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1,
   4306				nphy->rfctrl_intc1_save);
   4307		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2,
   4308				nphy->rfctrl_intc2_save);
   4309	}
   4310}
   4311
   4312/*
   4313 * TX low-pass filter bandwidth setup
   4314 * https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw
   4315 */
   4316static void b43_nphy_tx_lpf_bw(struct b43_wldev *dev)
   4317{
   4318	u16 tmp;
   4319
   4320	if (dev->phy.rev < 3 || dev->phy.rev >= 7)
   4321		return;
   4322
   4323	if (b43_nphy_ipa(dev))
   4324		tmp = b43_is_40mhz(dev) ? 5 : 4;
   4325	else
   4326		tmp = b43_is_40mhz(dev) ? 3 : 1;
   4327	b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2,
   4328		      (tmp << 9) | (tmp << 6) | (tmp << 3) | tmp);
   4329
   4330	if (b43_nphy_ipa(dev)) {
   4331		tmp = b43_is_40mhz(dev) ? 4 : 1;
   4332		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S2,
   4333			      (tmp << 9) | (tmp << 6) | (tmp << 3) | tmp);
   4334	}
   4335}
   4336
   4337/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */
   4338static void b43_nphy_rx_iq_est(struct b43_wldev *dev, struct nphy_iq_est *est,
   4339				u16 samps, u8 time, bool wait)
   4340{
   4341	int i;
   4342	u16 tmp;
   4343
   4344	b43_phy_write(dev, B43_NPHY_IQEST_SAMCNT, samps);
   4345	b43_phy_maskset(dev, B43_NPHY_IQEST_WT, ~B43_NPHY_IQEST_WT_VAL, time);
   4346	if (wait)
   4347		b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_MODE);
   4348	else
   4349		b43_phy_mask(dev, B43_NPHY_IQEST_CMD, ~B43_NPHY_IQEST_CMD_MODE);
   4350
   4351	b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_START);
   4352
   4353	for (i = 1000; i; i--) {
   4354		tmp = b43_phy_read(dev, B43_NPHY_IQEST_CMD);
   4355		if (!(tmp & B43_NPHY_IQEST_CMD_START)) {
   4356			est->i0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI0) << 16) |
   4357					b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO0);
   4358			est->q0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI0) << 16) |
   4359					b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO0);
   4360			est->iq0_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI0) << 16) |
   4361					b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO0);
   4362
   4363			est->i1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI1) << 16) |
   4364					b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO1);
   4365			est->q1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI1) << 16) |
   4366					b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO1);
   4367			est->iq1_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI1) << 16) |
   4368					b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO1);
   4369			return;
   4370		}
   4371		udelay(10);
   4372	}
   4373	memset(est, 0, sizeof(*est));
   4374}
   4375
   4376/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */
   4377static void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write,
   4378					struct b43_phy_n_iq_comp *pcomp)
   4379{
   4380	if (write) {
   4381		b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPA0, pcomp->a0);
   4382		b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPB0, pcomp->b0);
   4383		b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPA1, pcomp->a1);
   4384		b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPB1, pcomp->b1);
   4385	} else {
   4386		pcomp->a0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPA0);
   4387		pcomp->b0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPB0);
   4388		pcomp->a1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPA1);
   4389		pcomp->b1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPB1);
   4390	}
   4391}
   4392
   4393#if 0
   4394/* Ready but not used anywhere */
   4395/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */
   4396static void b43_nphy_rx_cal_phy_cleanup(struct b43_wldev *dev, u8 core)
   4397{
   4398	u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
   4399
   4400	b43_phy_write(dev, B43_NPHY_RFSEQCA, regs[0]);
   4401	if (core == 0) {
   4402		b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[1]);
   4403		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]);
   4404	} else {
   4405		b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]);
   4406		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]);
   4407	}
   4408	b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[3]);
   4409	b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[4]);
   4410	b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, regs[5]);
   4411	b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, regs[6]);
   4412	b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, regs[7]);
   4413	b43_phy_write(dev, B43_NPHY_RFCTL_OVER, regs[8]);
   4414	b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]);
   4415	b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]);
   4416}
   4417
   4418/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhySetup */
   4419static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core)
   4420{
   4421	u8 rxval, txval;
   4422	u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
   4423
   4424	regs[0] = b43_phy_read(dev, B43_NPHY_RFSEQCA);
   4425	if (core == 0) {
   4426		regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
   4427		regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
   4428	} else {
   4429		regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
   4430		regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
   4431	}
   4432	regs[3] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
   4433	regs[4] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
   4434	regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1);
   4435	regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2);
   4436	regs[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S1);
   4437	regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER);
   4438	regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);
   4439	regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
   4440
   4441	b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
   4442	b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
   4443
   4444	b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
   4445			~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF,
   4446			((1 - core) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));
   4447	b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN,
   4448			((1 - core) << B43_NPHY_RFSEQCA_TXEN_SHIFT));
   4449	b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN,
   4450			(core << B43_NPHY_RFSEQCA_RXEN_SHIFT));
   4451	b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXDIS,
   4452			(core << B43_NPHY_RFSEQCA_TXDIS_SHIFT));
   4453
   4454	if (core == 0) {
   4455		b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x0007);
   4456		b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0007);
   4457	} else {
   4458		b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x0007);
   4459		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0007);
   4460	}
   4461
   4462	b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA, 0, 3);
   4463	b43_nphy_rf_ctl_override(dev, 8, 0, 3, false);
   4464	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
   4465
   4466	if (core == 0) {
   4467		rxval = 1;
   4468		txval = 8;
   4469	} else {
   4470		rxval = 4;
   4471		txval = 2;
   4472	}
   4473	b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, rxval,
   4474				      core + 1);
   4475	b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, txval,
   4476				      2 - core);
   4477}
   4478#endif
   4479
   4480/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */
   4481static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask)
   4482{
   4483	int i;
   4484	s32 iq;
   4485	u32 ii;
   4486	u32 qq;
   4487	int iq_nbits, qq_nbits;
   4488	int arsh, brsh;
   4489	u16 tmp, a, b;
   4490
   4491	struct nphy_iq_est est;
   4492	struct b43_phy_n_iq_comp old;
   4493	struct b43_phy_n_iq_comp new = { };
   4494	bool error = false;
   4495
   4496	if (mask == 0)
   4497		return;
   4498
   4499	b43_nphy_rx_iq_coeffs(dev, false, &old);
   4500	b43_nphy_rx_iq_coeffs(dev, true, &new);
   4501	b43_nphy_rx_iq_est(dev, &est, 0x4000, 32, false);
   4502	new = old;
   4503
   4504	for (i = 0; i < 2; i++) {
   4505		if (i == 0 && (mask & 1)) {
   4506			iq = est.iq0_prod;
   4507			ii = est.i0_pwr;
   4508			qq = est.q0_pwr;
   4509		} else if (i == 1 && (mask & 2)) {
   4510			iq = est.iq1_prod;
   4511			ii = est.i1_pwr;
   4512			qq = est.q1_pwr;
   4513		} else {
   4514			continue;
   4515		}
   4516
   4517		if (ii + qq < 2) {
   4518			error = true;
   4519			break;
   4520		}
   4521
   4522		iq_nbits = fls(abs(iq));
   4523		qq_nbits = fls(qq);
   4524
   4525		arsh = iq_nbits - 20;
   4526		if (arsh >= 0) {
   4527			a = -((iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
   4528			tmp = ii >> arsh;
   4529		} else {
   4530			a = -((iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
   4531			tmp = ii << -arsh;
   4532		}
   4533		if (tmp == 0) {
   4534			error = true;
   4535			break;
   4536		}
   4537		a /= tmp;
   4538
   4539		brsh = qq_nbits - 11;
   4540		if (brsh >= 0) {
   4541			b = (qq << (31 - qq_nbits));
   4542			tmp = ii >> brsh;
   4543		} else {
   4544			b = (qq << (31 - qq_nbits));
   4545			tmp = ii << -brsh;
   4546		}
   4547		if (tmp == 0) {
   4548			error = true;
   4549			break;
   4550		}
   4551		b = int_sqrt(b / tmp - a * a) - (1 << 10);
   4552
   4553		if (i == 0 && (mask & 0x1)) {
   4554			if (dev->phy.rev >= 3) {
   4555				new.a0 = a & 0x3FF;
   4556				new.b0 = b & 0x3FF;
   4557			} else {
   4558				new.a0 = b & 0x3FF;
   4559				new.b0 = a & 0x3FF;
   4560			}
   4561		} else if (i == 1 && (mask & 0x2)) {
   4562			if (dev->phy.rev >= 3) {
   4563				new.a1 = a & 0x3FF;
   4564				new.b1 = b & 0x3FF;
   4565			} else {
   4566				new.a1 = b & 0x3FF;
   4567				new.b1 = a & 0x3FF;
   4568			}
   4569		}
   4570	}
   4571
   4572	if (error)
   4573		new = old;
   4574
   4575	b43_nphy_rx_iq_coeffs(dev, true, &new);
   4576}
   4577
   4578/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */
   4579static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev)
   4580{
   4581	u16 array[4];
   4582	b43_ntab_read_bulk(dev, B43_NTAB16(0xF, 0x50), 4, array);
   4583
   4584	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW0, array[0]);
   4585	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW1, array[1]);
   4586	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW2, array[2]);
   4587	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW3, array[3]);
   4588}
   4589
   4590/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SpurWar */
   4591static void b43_nphy_spur_workaround(struct b43_wldev *dev)
   4592{
   4593	struct b43_phy_n *nphy = dev->phy.n;
   4594
   4595	B43_WARN_ON(dev->phy.rev < 3);
   4596
   4597	if (nphy->hang_avoid)
   4598		b43_nphy_stay_in_carrier_search(dev, 1);
   4599
   4600	if (nphy->hang_avoid)
   4601		b43_nphy_stay_in_carrier_search(dev, 0);
   4602}
   4603
   4604/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */
   4605static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev)
   4606{
   4607	struct b43_phy_n *nphy = dev->phy.n;
   4608	int i, j;
   4609	u32 tmp;
   4610	u32 cur_real, cur_imag, real_part, imag_part;
   4611
   4612	u16 buffer[7];
   4613
   4614	if (nphy->hang_avoid)
   4615		b43_nphy_stay_in_carrier_search(dev, true);
   4616
   4617	b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
   4618
   4619	for (i = 0; i < 2; i++) {
   4620		tmp = ((buffer[i * 2] & 0x3FF) << 10) |
   4621			(buffer[i * 2 + 1] & 0x3FF);
   4622		b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
   4623				(((i + 26) << 10) | 320));
   4624		for (j = 0; j < 128; j++) {
   4625			b43_phy_write(dev, B43_NPHY_TABLE_DATAHI,
   4626					((tmp >> 16) & 0xFFFF));
   4627			b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
   4628					(tmp & 0xFFFF));
   4629		}
   4630	}
   4631
   4632	for (i = 0; i < 2; i++) {
   4633		tmp = buffer[5 + i];
   4634		real_part = (tmp >> 8) & 0xFF;
   4635		imag_part = (tmp & 0xFF);
   4636		b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
   4637				(((i + 26) << 10) | 448));
   4638
   4639		if (dev->phy.rev >= 3) {
   4640			cur_real = real_part;
   4641			cur_imag = imag_part;
   4642			tmp = ((cur_real & 0xFF) << 8) | (cur_imag & 0xFF);
   4643		}
   4644
   4645		for (j = 0; j < 128; j++) {
   4646			if (dev->phy.rev < 3) {
   4647				cur_real = (real_part * loscale[j] + 128) >> 8;
   4648				cur_imag = (imag_part * loscale[j] + 128) >> 8;
   4649				tmp = ((cur_real & 0xFF) << 8) |
   4650					(cur_imag & 0xFF);
   4651			}
   4652			b43_phy_write(dev, B43_NPHY_TABLE_DATAHI,
   4653					((tmp >> 16) & 0xFFFF));
   4654			b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
   4655					(tmp & 0xFFFF));
   4656		}
   4657	}
   4658
   4659	if (dev->phy.rev >= 3) {
   4660		b43_shm_write16(dev, B43_SHM_SHARED,
   4661				B43_SHM_SH_NPHY_TXPWR_INDX0, 0xFFFF);
   4662		b43_shm_write16(dev, B43_SHM_SHARED,
   4663				B43_SHM_SH_NPHY_TXPWR_INDX1, 0xFFFF);
   4664	}
   4665
   4666	if (nphy->hang_avoid)
   4667		b43_nphy_stay_in_carrier_search(dev, false);
   4668}
   4669
   4670/*
   4671 * Restore RSSI Calibration
   4672 * https://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal
   4673 */
   4674static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev)
   4675{
   4676	struct b43_phy_n *nphy = dev->phy.n;
   4677
   4678	u16 *rssical_radio_regs = NULL;
   4679	u16 *rssical_phy_regs = NULL;
   4680
   4681	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
   4682		if (!nphy->rssical_chanspec_2G.center_freq)
   4683			return;
   4684		rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G;
   4685		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G;
   4686	} else {
   4687		if (!nphy->rssical_chanspec_5G.center_freq)
   4688			return;
   4689		rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G;
   4690		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
   4691	}
   4692
   4693	if (dev->phy.rev >= 19) {
   4694		/* TODO */
   4695	} else if (dev->phy.rev >= 7) {
   4696		b43_radio_maskset(dev, R2057_NB_MASTER_CORE0, ~R2057_VCM_MASK,
   4697				  rssical_radio_regs[0]);
   4698		b43_radio_maskset(dev, R2057_NB_MASTER_CORE1, ~R2057_VCM_MASK,
   4699				  rssical_radio_regs[1]);
   4700	} else {
   4701		b43_radio_maskset(dev, B2056_RX0 | B2056_RX_RSSI_MISC, 0xE3,
   4702				  rssical_radio_regs[0]);
   4703		b43_radio_maskset(dev, B2056_RX1 | B2056_RX_RSSI_MISC, 0xE3,
   4704				  rssical_radio_regs[1]);
   4705	}
   4706
   4707	b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, rssical_phy_regs[0]);
   4708	b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, rssical_phy_regs[1]);
   4709	b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, rssical_phy_regs[2]);
   4710	b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, rssical_phy_regs[3]);
   4711
   4712	b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, rssical_phy_regs[4]);
   4713	b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, rssical_phy_regs[5]);
   4714	b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, rssical_phy_regs[6]);
   4715	b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, rssical_phy_regs[7]);
   4716
   4717	b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, rssical_phy_regs[8]);
   4718	b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, rssical_phy_regs[9]);
   4719	b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, rssical_phy_regs[10]);
   4720	b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]);
   4721}
   4722
   4723static void b43_nphy_tx_cal_radio_setup_rev19(struct b43_wldev *dev)
   4724{
   4725	/* TODO */
   4726}
   4727
   4728static void b43_nphy_tx_cal_radio_setup_rev7(struct b43_wldev *dev)
   4729{
   4730	struct b43_phy *phy = &dev->phy;
   4731	struct b43_phy_n *nphy = dev->phy.n;
   4732	u16 *save = nphy->tx_rx_cal_radio_saveregs;
   4733	int core, off;
   4734	u16 r, tmp;
   4735
   4736	for (core = 0; core < 2; core++) {
   4737		r = core ? 0x20 : 0;
   4738		off = core * 11;
   4739
   4740		save[off + 0] = b43_radio_read(dev, r + R2057_TX0_TX_SSI_MASTER);
   4741		save[off + 1] = b43_radio_read(dev, r + R2057_TX0_IQCAL_VCM_HG);
   4742		save[off + 2] = b43_radio_read(dev, r + R2057_TX0_IQCAL_IDAC);
   4743		save[off + 3] = b43_radio_read(dev, r + R2057_TX0_TSSI_VCM);
   4744		save[off + 4] = 0;
   4745		save[off + 5] = b43_radio_read(dev, r + R2057_TX0_TX_SSI_MUX);
   4746		if (phy->radio_rev != 5)
   4747			save[off + 6] = b43_radio_read(dev, r + R2057_TX0_TSSIA);
   4748		save[off + 7] = b43_radio_read(dev, r + R2057_TX0_TSSIG);
   4749		save[off + 8] = b43_radio_read(dev, r + R2057_TX0_TSSI_MISC1);
   4750
   4751		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
   4752			b43_radio_write(dev, r + R2057_TX0_TX_SSI_MASTER, 0xA);
   4753			b43_radio_write(dev, r + R2057_TX0_IQCAL_VCM_HG, 0x43);
   4754			b43_radio_write(dev, r + R2057_TX0_IQCAL_IDAC, 0x55);
   4755			b43_radio_write(dev, r + R2057_TX0_TSSI_VCM, 0);
   4756			b43_radio_write(dev, r + R2057_TX0_TSSIG, 0);
   4757			if (nphy->use_int_tx_iq_lo_cal) {
   4758				b43_radio_write(dev, r + R2057_TX0_TX_SSI_MUX, 0x4);
   4759				tmp = true ? 0x31 : 0x21; /* TODO */
   4760				b43_radio_write(dev, r + R2057_TX0_TSSIA, tmp);
   4761			}
   4762			b43_radio_write(dev, r + R2057_TX0_TSSI_MISC1, 0x00);
   4763		} else {
   4764			b43_radio_write(dev, r + R2057_TX0_TX_SSI_MASTER, 0x6);
   4765			b43_radio_write(dev, r + R2057_TX0_IQCAL_VCM_HG, 0x43);
   4766			b43_radio_write(dev, r + R2057_TX0_IQCAL_IDAC, 0x55);
   4767			b43_radio_write(dev, r + R2057_TX0_TSSI_VCM, 0);
   4768
   4769			if (phy->radio_rev != 5)
   4770				b43_radio_write(dev, r + R2057_TX0_TSSIA, 0);
   4771			if (nphy->use_int_tx_iq_lo_cal) {
   4772				b43_radio_write(dev, r + R2057_TX0_TX_SSI_MUX, 0x6);
   4773				tmp = true ? 0x31 : 0x21; /* TODO */
   4774				b43_radio_write(dev, r + R2057_TX0_TSSIG, tmp);
   4775			}
   4776			b43_radio_write(dev, r + R2057_TX0_TSSI_MISC1, 0);
   4777		}
   4778	}
   4779}
   4780
   4781/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */
   4782static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev)
   4783{
   4784	struct b43_phy *phy = &dev->phy;
   4785	struct b43_phy_n *nphy = dev->phy.n;
   4786	u16 *save = nphy->tx_rx_cal_radio_saveregs;
   4787	u16 tmp;
   4788	u8 offset, i;
   4789
   4790	if (phy->rev >= 19) {
   4791		b43_nphy_tx_cal_radio_setup_rev19(dev);
   4792	} else if (phy->rev >= 7) {
   4793		b43_nphy_tx_cal_radio_setup_rev7(dev);
   4794	} else if (phy->rev >= 3) {
   4795	    for (i = 0; i < 2; i++) {
   4796		tmp = (i == 0) ? 0x2000 : 0x3000;
   4797		offset = i * 11;
   4798
   4799		save[offset + 0] = b43_radio_read(dev, B2055_CAL_RVARCTL);
   4800		save[offset + 1] = b43_radio_read(dev, B2055_CAL_LPOCTL);
   4801		save[offset + 2] = b43_radio_read(dev, B2055_CAL_TS);
   4802		save[offset + 3] = b43_radio_read(dev, B2055_CAL_RCCALRTS);
   4803		save[offset + 4] = b43_radio_read(dev, B2055_CAL_RCALRTS);
   4804		save[offset + 5] = b43_radio_read(dev, B2055_PADDRV);
   4805		save[offset + 6] = b43_radio_read(dev, B2055_XOCTL1);
   4806		save[offset + 7] = b43_radio_read(dev, B2055_XOCTL2);
   4807		save[offset + 8] = b43_radio_read(dev, B2055_XOREGUL);
   4808		save[offset + 9] = b43_radio_read(dev, B2055_XOMISC);
   4809		save[offset + 10] = b43_radio_read(dev, B2055_PLL_LFC1);
   4810
   4811		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
   4812			b43_radio_write(dev, tmp | B2055_CAL_RVARCTL, 0x0A);
   4813			b43_radio_write(dev, tmp | B2055_CAL_LPOCTL, 0x40);
   4814			b43_radio_write(dev, tmp | B2055_CAL_TS, 0x55);
   4815			b43_radio_write(dev, tmp | B2055_CAL_RCCALRTS, 0);
   4816			b43_radio_write(dev, tmp | B2055_CAL_RCALRTS, 0);
   4817			if (nphy->ipa5g_on) {
   4818				b43_radio_write(dev, tmp | B2055_PADDRV, 4);
   4819				b43_radio_write(dev, tmp | B2055_XOCTL1, 1);
   4820			} else {
   4821				b43_radio_write(dev, tmp | B2055_PADDRV, 0);
   4822				b43_radio_write(dev, tmp | B2055_XOCTL1, 0x2F);
   4823			}
   4824			b43_radio_write(dev, tmp | B2055_XOCTL2, 0);
   4825		} else {
   4826			b43_radio_write(dev, tmp | B2055_CAL_RVARCTL, 0x06);
   4827			b43_radio_write(dev, tmp | B2055_CAL_LPOCTL, 0x40);
   4828			b43_radio_write(dev, tmp | B2055_CAL_TS, 0x55);
   4829			b43_radio_write(dev, tmp | B2055_CAL_RCCALRTS, 0);
   4830			b43_radio_write(dev, tmp | B2055_CAL_RCALRTS, 0);
   4831			b43_radio_write(dev, tmp | B2055_XOCTL1, 0);
   4832			if (nphy->ipa2g_on) {
   4833				b43_radio_write(dev, tmp | B2055_PADDRV, 6);
   4834				b43_radio_write(dev, tmp | B2055_XOCTL2,
   4835					(dev->phy.rev < 5) ? 0x11 : 0x01);
   4836			} else {
   4837				b43_radio_write(dev, tmp | B2055_PADDRV, 0);
   4838				b43_radio_write(dev, tmp | B2055_XOCTL2, 0);
   4839			}
   4840		}
   4841		b43_radio_write(dev, tmp | B2055_XOREGUL, 0);
   4842		b43_radio_write(dev, tmp | B2055_XOMISC, 0);
   4843		b43_radio_write(dev, tmp | B2055_PLL_LFC1, 0);
   4844	    }
   4845	} else {
   4846		save[0] = b43_radio_read(dev, B2055_C1_TX_RF_IQCAL1);
   4847		b43_radio_write(dev, B2055_C1_TX_RF_IQCAL1, 0x29);
   4848
   4849		save[1] = b43_radio_read(dev, B2055_C1_TX_RF_IQCAL2);
   4850		b43_radio_write(dev, B2055_C1_TX_RF_IQCAL2, 0x54);
   4851
   4852		save[2] = b43_radio_read(dev, B2055_C2_TX_RF_IQCAL1);
   4853		b43_radio_write(dev, B2055_C2_TX_RF_IQCAL1, 0x29);
   4854
   4855		save[3] = b43_radio_read(dev, B2055_C2_TX_RF_IQCAL2);
   4856		b43_radio_write(dev, B2055_C2_TX_RF_IQCAL2, 0x54);
   4857
   4858		save[3] = b43_radio_read(dev, B2055_C1_PWRDET_RXTX);
   4859		save[4] = b43_radio_read(dev, B2055_C2_PWRDET_RXTX);
   4860
   4861		if (!(b43_phy_read(dev, B43_NPHY_BANDCTL) &
   4862		    B43_NPHY_BANDCTL_5GHZ)) {
   4863			b43_radio_write(dev, B2055_C1_PWRDET_RXTX, 0x04);
   4864			b43_radio_write(dev, B2055_C2_PWRDET_RXTX, 0x04);
   4865		} else {
   4866			b43_radio_write(dev, B2055_C1_PWRDET_RXTX, 0x20);
   4867			b43_radio_write(dev, B2055_C2_PWRDET_RXTX, 0x20);
   4868		}
   4869
   4870		if (dev->phy.rev < 2) {
   4871			b43_radio_set(dev, B2055_C1_TX_BB_MXGM, 0x20);
   4872			b43_radio_set(dev, B2055_C2_TX_BB_MXGM, 0x20);
   4873		} else {
   4874			b43_radio_mask(dev, B2055_C1_TX_BB_MXGM, ~0x20);
   4875			b43_radio_mask(dev, B2055_C2_TX_BB_MXGM, ~0x20);
   4876		}
   4877	}
   4878}
   4879
   4880/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */
   4881static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core)
   4882{
   4883	struct b43_phy_n *nphy = dev->phy.n;
   4884	int i;
   4885	u16 scale, entry;
   4886
   4887	u16 tmp = nphy->txcal_bbmult;
   4888	if (core == 0)
   4889		tmp >>= 8;
   4890	tmp &= 0xff;
   4891
   4892	for (i = 0; i < 18; i++) {
   4893		scale = (ladder_lo[i].percent * tmp) / 100;
   4894		entry = ((scale & 0xFF) << 8) | ladder_lo[i].g_env;
   4895		b43_ntab_write(dev, B43_NTAB16(15, i), entry);
   4896
   4897		scale = (ladder_iq[i].percent * tmp) / 100;
   4898		entry = ((scale & 0xFF) << 8) | ladder_iq[i].g_env;
   4899		b43_ntab_write(dev, B43_NTAB16(15, i + 32), entry);
   4900	}
   4901}
   4902
   4903static void b43_nphy_pa_set_tx_dig_filter(struct b43_wldev *dev, u16 offset,
   4904					  const s16 *filter)
   4905{
   4906	int i;
   4907
   4908	offset = B43_PHY_N(offset);
   4909
   4910	for (i = 0; i < 15; i++, offset++)
   4911		b43_phy_write(dev, offset, filter[i]);
   4912}
   4913
   4914/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */
   4915static void b43_nphy_ext_pa_set_tx_dig_filters(struct b43_wldev *dev)
   4916{
   4917	b43_nphy_pa_set_tx_dig_filter(dev, 0x2C5,
   4918				      tbl_tx_filter_coef_rev4[2]);
   4919}
   4920
   4921/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */
   4922static void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev)
   4923{
   4924	/* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */
   4925	static const u16 offset[] = { 0x186, 0x195, 0x2C5 };
   4926	static const s16 dig_filter_phy_rev16[] = {
   4927		-375, 136, -407, 208, -1527,
   4928		956, 93, 186, 93, 230,
   4929		-44, 230, 201, -191, 201,
   4930	};
   4931	int i;
   4932
   4933	for (i = 0; i < 3; i++)
   4934		b43_nphy_pa_set_tx_dig_filter(dev, offset[i],
   4935					      tbl_tx_filter_coef_rev4[i]);
   4936
   4937	/* Verified with BCM43227 and BCM43228 */
   4938	if (dev->phy.rev == 16)
   4939		b43_nphy_pa_set_tx_dig_filter(dev, 0x186, dig_filter_phy_rev16);
   4940
   4941	/* Verified with BCM43131 and BCM43217 */
   4942	if (dev->phy.rev == 17) {
   4943		b43_nphy_pa_set_tx_dig_filter(dev, 0x186, dig_filter_phy_rev16);
   4944		b43_nphy_pa_set_tx_dig_filter(dev, 0x195,
   4945					      tbl_tx_filter_coef_rev4[1]);
   4946	}
   4947
   4948	if (b43_is_40mhz(dev)) {
   4949		b43_nphy_pa_set_tx_dig_filter(dev, 0x186,
   4950					      tbl_tx_filter_coef_rev4[3]);
   4951	} else {
   4952		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
   4953			b43_nphy_pa_set_tx_dig_filter(dev, 0x186,
   4954						      tbl_tx_filter_coef_rev4[5]);
   4955		if (dev->phy.channel == 14)
   4956			b43_nphy_pa_set_tx_dig_filter(dev, 0x186,
   4957						      tbl_tx_filter_coef_rev4[6]);
   4958	}
   4959}
   4960
   4961/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */
   4962static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev)
   4963{
   4964	struct b43_phy_n *nphy = dev->phy.n;
   4965
   4966	u16 curr_gain[2];
   4967	struct nphy_txgains target;
   4968	const u32 *table = NULL;
   4969
   4970	if (!nphy->txpwrctrl) {
   4971		int i;
   4972
   4973		if (nphy->hang_avoid)
   4974			b43_nphy_stay_in_carrier_search(dev, true);
   4975		b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, curr_gain);
   4976		if (nphy->hang_avoid)
   4977			b43_nphy_stay_in_carrier_search(dev, false);
   4978
   4979		for (i = 0; i < 2; ++i) {
   4980			if (dev->phy.rev >= 7) {
   4981				target.ipa[i] = curr_gain[i] & 0x0007;
   4982				target.pad[i] = (curr_gain[i] & 0x00F8) >> 3;
   4983				target.pga[i] = (curr_gain[i] & 0x0F00) >> 8;
   4984				target.txgm[i] = (curr_gain[i] & 0x7000) >> 12;
   4985				target.tx_lpf[i] = (curr_gain[i] & 0x8000) >> 15;
   4986			} else if (dev->phy.rev >= 3) {
   4987				target.ipa[i] = curr_gain[i] & 0x000F;
   4988				target.pad[i] = (curr_gain[i] & 0x00F0) >> 4;
   4989				target.pga[i] = (curr_gain[i] & 0x0F00) >> 8;
   4990				target.txgm[i] = (curr_gain[i] & 0x7000) >> 12;
   4991			} else {
   4992				target.ipa[i] = curr_gain[i] & 0x0003;
   4993				target.pad[i] = (curr_gain[i] & 0x000C) >> 2;
   4994				target.pga[i] = (curr_gain[i] & 0x0070) >> 4;
   4995				target.txgm[i] = (curr_gain[i] & 0x0380) >> 7;
   4996			}
   4997		}
   4998	} else {
   4999		int i;
   5000		u16 index[2];
   5001		index[0] = (b43_phy_read(dev, B43_NPHY_C1_TXPCTL_STAT) &
   5002			B43_NPHY_TXPCTL_STAT_BIDX) >>
   5003			B43_NPHY_TXPCTL_STAT_BIDX_SHIFT;
   5004		index[1] = (b43_phy_read(dev, B43_NPHY_C2_TXPCTL_STAT) &
   5005			B43_NPHY_TXPCTL_STAT_BIDX) >>
   5006			B43_NPHY_TXPCTL_STAT_BIDX_SHIFT;
   5007
   5008		for (i = 0; i < 2; ++i) {
   5009			table = b43_nphy_get_tx_gain_table(dev);
   5010			if (!table)
   5011				break;
   5012
   5013			if (dev->phy.rev >= 7) {
   5014				target.ipa[i] = (table[index[i]] >> 16) & 0x7;
   5015				target.pad[i] = (table[index[i]] >> 19) & 0x1F;
   5016				target.pga[i] = (table[index[i]] >> 24) & 0xF;
   5017				target.txgm[i] = (table[index[i]] >> 28) & 0x7;
   5018				target.tx_lpf[i] = (table[index[i]] >> 31) & 0x1;
   5019			} else if (dev->phy.rev >= 3) {
   5020				target.ipa[i] = (table[index[i]] >> 16) & 0xF;
   5021				target.pad[i] = (table[index[i]] >> 20) & 0xF;
   5022				target.pga[i] = (table[index[i]] >> 24) & 0xF;
   5023				target.txgm[i] = (table[index[i]] >> 28) & 0xF;
   5024			} else {
   5025				target.ipa[i] = (table[index[i]] >> 16) & 0x3;
   5026				target.pad[i] = (table[index[i]] >> 18) & 0x3;
   5027				target.pga[i] = (table[index[i]] >> 20) & 0x7;
   5028				target.txgm[i] = (table[index[i]] >> 23) & 0x7;
   5029			}
   5030		}
   5031	}
   5032
   5033	return target;
   5034}
   5035
   5036/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhyCleanup */
   5037static void b43_nphy_tx_cal_phy_cleanup(struct b43_wldev *dev)
   5038{
   5039	u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
   5040
   5041	if (dev->phy.rev >= 3) {
   5042		b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[0]);
   5043		b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]);
   5044		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]);
   5045		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[3]);
   5046		b43_phy_write(dev, B43_NPHY_BBCFG, regs[4]);
   5047		b43_ntab_write(dev, B43_NTAB16(8, 3), regs[5]);
   5048		b43_ntab_write(dev, B43_NTAB16(8, 19), regs[6]);
   5049		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[7]);
   5050		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[8]);
   5051		b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]);
   5052		b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]);
   5053		b43_nphy_reset_cca(dev);
   5054	} else {
   5055		b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, regs[0]);
   5056		b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, regs[1]);
   5057		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]);
   5058		b43_ntab_write(dev, B43_NTAB16(8, 2), regs[3]);
   5059		b43_ntab_write(dev, B43_NTAB16(8, 18), regs[4]);
   5060		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[5]);
   5061		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[6]);
   5062	}
   5063}
   5064
   5065/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */
   5066static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev)
   5067{
   5068	struct b43_phy *phy = &dev->phy;
   5069	struct b43_phy_n *nphy = dev->phy.n;
   5070	u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
   5071	u16 tmp;
   5072
   5073	regs[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
   5074	regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
   5075	if (dev->phy.rev >= 3) {
   5076		b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0xF0FF, 0x0A00);
   5077		b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0xF0FF, 0x0A00);
   5078
   5079		tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
   5080		regs[2] = tmp;
   5081		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, tmp | 0x0600);
   5082
   5083		tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
   5084		regs[3] = tmp;
   5085		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x0600);
   5086
   5087		regs[4] = b43_phy_read(dev, B43_NPHY_BBCFG);
   5088		b43_phy_mask(dev, B43_NPHY_BBCFG,
   5089			     ~B43_NPHY_BBCFG_RSTRX & 0xFFFF);
   5090
   5091		tmp = b43_ntab_read(dev, B43_NTAB16(8, 3));
   5092		regs[5] = tmp;
   5093		b43_ntab_write(dev, B43_NTAB16(8, 3), 0);
   5094
   5095		tmp = b43_ntab_read(dev, B43_NTAB16(8, 19));
   5096		regs[6] = tmp;
   5097		b43_ntab_write(dev, B43_NTAB16(8, 19), 0);
   5098		regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
   5099		regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
   5100
   5101		if (!nphy->use_int_tx_iq_lo_cal)
   5102			b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA,
   5103						      1, 3);
   5104		else
   5105			b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA,
   5106						      0, 3);
   5107		b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 2, 1);
   5108		b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 8, 2);
   5109
   5110		regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);
   5111		regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
   5112		b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
   5113		b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
   5114
   5115		tmp = b43_nphy_read_lpf_ctl(dev, 0);
   5116		if (phy->rev >= 19)
   5117			b43_nphy_rf_ctl_override_rev19(dev, 0x80, tmp, 0, false,
   5118						       1);
   5119		else if (phy->rev >= 7)
   5120			b43_nphy_rf_ctl_override_rev7(dev, 0x80, tmp, 0, false,
   5121						      1);
   5122
   5123		if (nphy->use_int_tx_iq_lo_cal && true /* FIXME */) {
   5124			if (phy->rev >= 19) {
   5125				b43_nphy_rf_ctl_override_rev19(dev, 0x8, 0, 0x3,
   5126							       false, 0);
   5127			} else if (phy->rev >= 8) {
   5128				b43_nphy_rf_ctl_override_rev7(dev, 0x8, 0, 0x3,
   5129							      false, 0);
   5130			} else if (phy->rev == 7) {
   5131				b43_radio_maskset(dev, R2057_OVR_REG0, 1 << 4, 1 << 4);
   5132				if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
   5133					b43_radio_maskset(dev, R2057_PAD2G_TUNE_PUS_CORE0, ~1, 0);
   5134					b43_radio_maskset(dev, R2057_PAD2G_TUNE_PUS_CORE1, ~1, 0);
   5135				} else {
   5136					b43_radio_maskset(dev, R2057_IPA5G_CASCOFFV_PU_CORE0, ~1, 0);
   5137					b43_radio_maskset(dev, R2057_IPA5G_CASCOFFV_PU_CORE1, ~1, 0);
   5138				}
   5139			}
   5140		}
   5141	} else {
   5142		b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, 0xA000);
   5143		b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, 0xA000);
   5144		tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
   5145		regs[2] = tmp;
   5146		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x3000);
   5147		tmp = b43_ntab_read(dev, B43_NTAB16(8, 2));
   5148		regs[3] = tmp;
   5149		tmp |= 0x2000;
   5150		b43_ntab_write(dev, B43_NTAB16(8, 2), tmp);
   5151		tmp = b43_ntab_read(dev, B43_NTAB16(8, 18));
   5152		regs[4] = tmp;
   5153		tmp |= 0x2000;
   5154		b43_ntab_write(dev, B43_NTAB16(8, 18), tmp);
   5155		regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
   5156		regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
   5157		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
   5158			tmp = 0x0180;
   5159		else
   5160			tmp = 0x0120;
   5161		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp);
   5162		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp);
   5163	}
   5164}
   5165
   5166/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */
   5167static void b43_nphy_save_cal(struct b43_wldev *dev)
   5168{
   5169	struct b43_phy *phy = &dev->phy;
   5170	struct b43_phy_n *nphy = dev->phy.n;
   5171
   5172	struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
   5173	u16 *txcal_radio_regs = NULL;
   5174	struct b43_chanspec *iqcal_chanspec;
   5175	u16 *table = NULL;
   5176
   5177	if (nphy->hang_avoid)
   5178		b43_nphy_stay_in_carrier_search(dev, 1);
   5179
   5180	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
   5181		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G;
   5182		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G;
   5183		iqcal_chanspec = &nphy->iqcal_chanspec_2G;
   5184		table = nphy->cal_cache.txcal_coeffs_2G;
   5185	} else {
   5186		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G;
   5187		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G;
   5188		iqcal_chanspec = &nphy->iqcal_chanspec_5G;
   5189		table = nphy->cal_cache.txcal_coeffs_5G;
   5190	}
   5191
   5192	b43_nphy_rx_iq_coeffs(dev, false, rxcal_coeffs);
   5193	/* TODO use some definitions */
   5194	if (phy->rev >= 19) {
   5195		/* TODO */
   5196	} else if (phy->rev >= 7) {
   5197		txcal_radio_regs[0] = b43_radio_read(dev,
   5198						     R2057_TX0_LOFT_FINE_I);
   5199		txcal_radio_regs[1] = b43_radio_read(dev,
   5200						     R2057_TX0_LOFT_FINE_Q);
   5201		txcal_radio_regs[4] = b43_radio_read(dev,
   5202						     R2057_TX0_LOFT_COARSE_I);
   5203		txcal_radio_regs[5] = b43_radio_read(dev,
   5204						     R2057_TX0_LOFT_COARSE_Q);
   5205		txcal_radio_regs[2] = b43_radio_read(dev,
   5206						     R2057_TX1_LOFT_FINE_I);
   5207		txcal_radio_regs[3] = b43_radio_read(dev,
   5208						     R2057_TX1_LOFT_FINE_Q);
   5209		txcal_radio_regs[6] = b43_radio_read(dev,
   5210						     R2057_TX1_LOFT_COARSE_I);
   5211		txcal_radio_regs[7] = b43_radio_read(dev,
   5212						     R2057_TX1_LOFT_COARSE_Q);
   5213	} else if (phy->rev >= 3) {
   5214		txcal_radio_regs[0] = b43_radio_read(dev, 0x2021);
   5215		txcal_radio_regs[1] = b43_radio_read(dev, 0x2022);
   5216		txcal_radio_regs[2] = b43_radio_read(dev, 0x3021);
   5217		txcal_radio_regs[3] = b43_radio_read(dev, 0x3022);
   5218		txcal_radio_regs[4] = b43_radio_read(dev, 0x2023);
   5219		txcal_radio_regs[5] = b43_radio_read(dev, 0x2024);
   5220		txcal_radio_regs[6] = b43_radio_read(dev, 0x3023);
   5221		txcal_radio_regs[7] = b43_radio_read(dev, 0x3024);
   5222	} else {
   5223		txcal_radio_regs[0] = b43_radio_read(dev, 0x8B);
   5224		txcal_radio_regs[1] = b43_radio_read(dev, 0xBA);
   5225		txcal_radio_regs[2] = b43_radio_read(dev, 0x8D);
   5226		txcal_radio_regs[3] = b43_radio_read(dev, 0xBC);
   5227	}
   5228	iqcal_chanspec->center_freq = dev->phy.chandef->chan->center_freq;
   5229	iqcal_chanspec->channel_type =
   5230				cfg80211_get_chandef_type(dev->phy.chandef);
   5231	b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 8, table);
   5232
   5233	if (nphy->hang_avoid)
   5234		b43_nphy_stay_in_carrier_search(dev, 0);
   5235}
   5236
   5237/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */
   5238static void b43_nphy_restore_cal(struct b43_wldev *dev)
   5239{
   5240	struct b43_phy *phy = &dev->phy;
   5241	struct b43_phy_n *nphy = dev->phy.n;
   5242
   5243	u16 coef[4];
   5244	u16 *loft = NULL;
   5245	u16 *table = NULL;
   5246
   5247	int i;
   5248	u16 *txcal_radio_regs = NULL;
   5249	struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
   5250
   5251	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
   5252		if (!nphy->iqcal_chanspec_2G.center_freq)
   5253			return;
   5254		table = nphy->cal_cache.txcal_coeffs_2G;
   5255		loft = &nphy->cal_cache.txcal_coeffs_2G[5];
   5256	} else {
   5257		if (!nphy->iqcal_chanspec_5G.center_freq)
   5258			return;
   5259		table = nphy->cal_cache.txcal_coeffs_5G;
   5260		loft = &nphy->cal_cache.txcal_coeffs_5G[5];
   5261	}
   5262
   5263	b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4, table);
   5264
   5265	for (i = 0; i < 4; i++) {
   5266		if (dev->phy.rev >= 3)
   5267			coef[i] = table[i];
   5268		else
   5269			coef[i] = 0;
   5270	}
   5271
   5272	b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, coef);
   5273	b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, loft);
   5274	b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2, loft);
   5275
   5276	if (dev->phy.rev < 2)
   5277		b43_nphy_tx_iq_workaround(dev);
   5278
   5279	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
   5280		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G;
   5281		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G;
   5282	} else {
   5283		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G;
   5284		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G;
   5285	}
   5286
   5287	/* TODO use some definitions */
   5288	if (phy->rev >= 19) {
   5289		/* TODO */
   5290	} else if (phy->rev >= 7) {
   5291		b43_radio_write(dev, R2057_TX0_LOFT_FINE_I,
   5292				txcal_radio_regs[0]);
   5293		b43_radio_write(dev, R2057_TX0_LOFT_FINE_Q,
   5294				txcal_radio_regs[1]);
   5295		b43_radio_write(dev, R2057_TX0_LOFT_COARSE_I,
   5296				txcal_radio_regs[4]);
   5297		b43_radio_write(dev, R2057_TX0_LOFT_COARSE_Q,
   5298				txcal_radio_regs[5]);
   5299		b43_radio_write(dev, R2057_TX1_LOFT_FINE_I,
   5300				txcal_radio_regs[2]);
   5301		b43_radio_write(dev, R2057_TX1_LOFT_FINE_Q,
   5302				txcal_radio_regs[3]);
   5303		b43_radio_write(dev, R2057_TX1_LOFT_COARSE_I,
   5304				txcal_radio_regs[6]);
   5305		b43_radio_write(dev, R2057_TX1_LOFT_COARSE_Q,
   5306				txcal_radio_regs[7]);
   5307	} else if (phy->rev >= 3) {
   5308		b43_radio_write(dev, 0x2021, txcal_radio_regs[0]);
   5309		b43_radio_write(dev, 0x2022, txcal_radio_regs[1]);
   5310		b43_radio_write(dev, 0x3021, txcal_radio_regs[2]);
   5311		b43_radio_write(dev, 0x3022, txcal_radio_regs[3]);
   5312		b43_radio_write(dev, 0x2023, txcal_radio_regs[4]);
   5313		b43_radio_write(dev, 0x2024, txcal_radio_regs[5]);
   5314		b43_radio_write(dev, 0x3023, txcal_radio_regs[6]);
   5315		b43_radio_write(dev, 0x3024, txcal_radio_regs[7]);
   5316	} else {
   5317		b43_radio_write(dev, 0x8B, txcal_radio_regs[0]);
   5318		b43_radio_write(dev, 0xBA, txcal_radio_regs[1]);
   5319		b43_radio_write(dev, 0x8D, txcal_radio_regs[2]);
   5320		b43_radio_write(dev, 0xBC, txcal_radio_regs[3]);
   5321	}
   5322	b43_nphy_rx_iq_coeffs(dev, true, rxcal_coeffs);
   5323}
   5324
   5325/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/CalTxIqlo */
   5326static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
   5327				struct nphy_txgains target,
   5328				bool full, bool mphase)
   5329{
   5330	struct b43_phy *phy = &dev->phy;
   5331	struct b43_phy_n *nphy = dev->phy.n;
   5332	int i;
   5333	int error = 0;
   5334	int freq;
   5335	bool avoid = false;
   5336	u8 length;
   5337	u16 tmp, core, type, count, max, numb, last = 0, cmd;
   5338	const u16 *table;
   5339	bool phy6or5x;
   5340
   5341	u16 buffer[11];
   5342	u16 diq_start = 0;
   5343	u16 save[2];
   5344	u16 gain[2];
   5345	struct nphy_iqcal_params params[2];
   5346	bool updated[2] = { };
   5347
   5348	b43_nphy_stay_in_carrier_search(dev, true);
   5349
   5350	if (dev->phy.rev >= 4) {
   5351		avoid = nphy->hang_avoid;
   5352		nphy->hang_avoid = false;
   5353	}
   5354
   5355	b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, save);
   5356
   5357	for (i = 0; i < 2; i++) {
   5358		b43_nphy_iq_cal_gain_params(dev, i, target, &params[i]);
   5359		gain[i] = params[i].cal_gain;
   5360	}
   5361
   5362	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain);
   5363
   5364	b43_nphy_tx_cal_radio_setup(dev);
   5365	b43_nphy_tx_cal_phy_setup(dev);
   5366
   5367	phy6or5x = dev->phy.rev >= 6 ||
   5368		(dev->phy.rev == 5 && nphy->ipa2g_on &&
   5369		b43_current_band(dev->wl) == NL80211_BAND_2GHZ);
   5370	if (phy6or5x) {
   5371		if (b43_is_40mhz(dev)) {
   5372			b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18,
   5373					tbl_tx_iqlo_cal_loft_ladder_40);
   5374			b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18,
   5375					tbl_tx_iqlo_cal_iqimb_ladder_40);
   5376		} else {
   5377			b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18,
   5378					tbl_tx_iqlo_cal_loft_ladder_20);
   5379			b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18,
   5380					tbl_tx_iqlo_cal_iqimb_ladder_20);
   5381		}
   5382	}
   5383
   5384	if (phy->rev >= 19) {
   5385		/* TODO */
   5386	} else if (phy->rev >= 7) {
   5387		b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AD9);
   5388	} else {
   5389		b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9);
   5390	}
   5391
   5392	if (!b43_is_40mhz(dev))
   5393		freq = 2500;
   5394	else
   5395		freq = 5000;
   5396
   5397	if (nphy->mphase_cal_phase_id > 2)
   5398		b43_nphy_run_samples(dev, (b43_is_40mhz(dev) ? 40 : 20) * 8,
   5399				     0xFFFF, 0, true, false, false);
   5400	else
   5401		error = b43_nphy_tx_tone(dev, freq, 250, true, false, false);
   5402
   5403	if (error == 0) {
   5404		if (nphy->mphase_cal_phase_id > 2) {
   5405			table = nphy->mphase_txcal_bestcoeffs;
   5406			length = 11;
   5407			if (dev->phy.rev < 3)
   5408				length -= 2;
   5409		} else {
   5410			if (!full && nphy->txiqlocal_coeffsvalid) {
   5411				table = nphy->txiqlocal_bestc;
   5412				length = 11;
   5413				if (dev->phy.rev < 3)
   5414					length -= 2;
   5415			} else {
   5416				full = true;
   5417				if (dev->phy.rev >= 3) {
   5418					table = tbl_tx_iqlo_cal_startcoefs_nphyrev3;
   5419					length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3;
   5420				} else {
   5421					table = tbl_tx_iqlo_cal_startcoefs;
   5422					length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS;
   5423				}
   5424			}
   5425		}
   5426
   5427		b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length, table);
   5428
   5429		if (full) {
   5430			if (dev->phy.rev >= 3)
   5431				max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3;
   5432			else
   5433				max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL;
   5434		} else {
   5435			if (dev->phy.rev >= 3)
   5436				max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3;
   5437			else
   5438				max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL;
   5439		}
   5440
   5441		if (mphase) {
   5442			count = nphy->mphase_txcal_cmdidx;
   5443			numb = min(max,
   5444				(u16)(count + nphy->mphase_txcal_numcmds));
   5445		} else {
   5446			count = 0;
   5447			numb = max;
   5448		}
   5449
   5450		for (; count < numb; count++) {
   5451			if (full) {
   5452				if (dev->phy.rev >= 3)
   5453					cmd = tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[count];
   5454				else
   5455					cmd = tbl_tx_iqlo_cal_cmds_fullcal[count];
   5456			} else {
   5457				if (dev->phy.rev >= 3)
   5458					cmd = tbl_tx_iqlo_cal_cmds_recal_nphyrev3[count];
   5459				else
   5460					cmd = tbl_tx_iqlo_cal_cmds_recal[count];
   5461			}
   5462
   5463			core = (cmd & 0x3000) >> 12;
   5464			type = (cmd & 0x0F00) >> 8;
   5465
   5466			if (phy6or5x && !updated[core]) {
   5467				b43_nphy_update_tx_cal_ladder(dev, core);
   5468				updated[core] = true;
   5469			}
   5470
   5471			tmp = (params[core].ncorr[type] << 8) | 0x66;
   5472			b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDNNUM, tmp);
   5473
   5474			if (type == 1 || type == 3 || type == 4) {
   5475				buffer[0] = b43_ntab_read(dev,
   5476						B43_NTAB16(15, 69 + core));
   5477				diq_start = buffer[0];
   5478				buffer[0] = 0;
   5479				b43_ntab_write(dev, B43_NTAB16(15, 69 + core),
   5480						0);
   5481			}
   5482
   5483			b43_phy_write(dev, B43_NPHY_IQLOCAL_CMD, cmd);
   5484			for (i = 0; i < 2000; i++) {
   5485				tmp = b43_phy_read(dev, B43_NPHY_IQLOCAL_CMD);
   5486				if (tmp & 0xC000)
   5487					break;
   5488				udelay(10);
   5489			}
   5490
   5491			b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
   5492						buffer);
   5493			b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length,
   5494						buffer);
   5495
   5496			if (type == 1 || type == 3 || type == 4)
   5497				buffer[0] = diq_start;
   5498		}
   5499
   5500		if (mphase)
   5501			nphy->mphase_txcal_cmdidx = (numb >= max) ? 0 : numb;
   5502
   5503		last = (dev->phy.rev < 3) ? 6 : 7;
   5504
   5505		if (!mphase || nphy->mphase_cal_phase_id == last) {
   5506			b43_ntab_write_bulk(dev, B43_NTAB16(15, 96), 4, buffer);
   5507			b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 4, buffer);
   5508			if (dev->phy.rev < 3) {
   5509				buffer[0] = 0;
   5510				buffer[1] = 0;
   5511				buffer[2] = 0;
   5512				buffer[3] = 0;
   5513			}
   5514			b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4,
   5515						buffer);
   5516			b43_ntab_read_bulk(dev, B43_NTAB16(15, 101), 2,
   5517						buffer);
   5518			b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2,
   5519						buffer);
   5520			b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2,
   5521						buffer);
   5522			length = 11;
   5523			if (dev->phy.rev < 3)
   5524				length -= 2;
   5525			b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
   5526						nphy->txiqlocal_bestc);
   5527			nphy->txiqlocal_coeffsvalid = true;
   5528			nphy->txiqlocal_chanspec.center_freq =
   5529						phy->chandef->chan->center_freq;
   5530			nphy->txiqlocal_chanspec.channel_type =
   5531					cfg80211_get_chandef_type(phy->chandef);
   5532		} else {
   5533			length = 11;
   5534			if (dev->phy.rev < 3)
   5535				length -= 2;
   5536			b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
   5537						nphy->mphase_txcal_bestcoeffs);
   5538		}
   5539
   5540		b43_nphy_stop_playback(dev);
   5541		b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0);
   5542	}
   5543
   5544	b43_nphy_tx_cal_phy_cleanup(dev);
   5545	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, save);
   5546
   5547	if (dev->phy.rev < 2 && (!mphase || nphy->mphase_cal_phase_id == last))
   5548		b43_nphy_tx_iq_workaround(dev);
   5549
   5550	if (dev->phy.rev >= 4)
   5551		nphy->hang_avoid = avoid;
   5552
   5553	b43_nphy_stay_in_carrier_search(dev, false);
   5554
   5555	return error;
   5556}
   5557
   5558/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/ReapplyTxCalCoeffs */
   5559static void b43_nphy_reapply_tx_cal_coeffs(struct b43_wldev *dev)
   5560{
   5561	struct b43_phy_n *nphy = dev->phy.n;
   5562	u8 i;
   5563	u16 buffer[7];
   5564	bool equal = true;
   5565
   5566	if (!nphy->txiqlocal_coeffsvalid ||
   5567	    nphy->txiqlocal_chanspec.center_freq != dev->phy.chandef->chan->center_freq ||
   5568	    nphy->txiqlocal_chanspec.channel_type != cfg80211_get_chandef_type(dev->phy.chandef))
   5569		return;
   5570
   5571	b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
   5572	for (i = 0; i < 4; i++) {
   5573		if (buffer[i] != nphy->txiqlocal_bestc[i]) {
   5574			equal = false;
   5575			break;
   5576		}
   5577	}
   5578
   5579	if (!equal) {
   5580		b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4,
   5581					nphy->txiqlocal_bestc);
   5582		for (i = 0; i < 4; i++)
   5583			buffer[i] = 0;
   5584		b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4,
   5585					buffer);
   5586		b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2,
   5587					&nphy->txiqlocal_bestc[5]);
   5588		b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2,
   5589					&nphy->txiqlocal_bestc[5]);
   5590	}
   5591}
   5592
   5593/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIqRev2 */
   5594static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,
   5595			struct nphy_txgains target, u8 type, bool debug)
   5596{
   5597	struct b43_phy_n *nphy = dev->phy.n;
   5598	int i, j, index;
   5599	u8 rfctl[2];
   5600	u8 afectl_core;
   5601	u16 tmp[6];
   5602	u16 cur_hpf1, cur_hpf2, cur_lna;
   5603	u32 real, imag;
   5604	enum nl80211_band band;
   5605
   5606	u8 use;
   5607	u16 cur_hpf;
   5608	u16 lna[3] = { 3, 3, 1 };
   5609	u16 hpf1[3] = { 7, 2, 0 };
   5610	u16 hpf2[3] = { 2, 0, 0 };
   5611	u32 power[3] = { };
   5612	u16 gain_save[2];
   5613	u16 cal_gain[2];
   5614	struct nphy_iqcal_params cal_params[2];
   5615	struct nphy_iq_est est;
   5616	int ret = 0;
   5617	bool playtone = true;
   5618	int desired = 13;
   5619
   5620	b43_nphy_stay_in_carrier_search(dev, 1);
   5621
   5622	if (dev->phy.rev < 2)
   5623		b43_nphy_reapply_tx_cal_coeffs(dev);
   5624	b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save);
   5625	for (i = 0; i < 2; i++) {
   5626		b43_nphy_iq_cal_gain_params(dev, i, target, &cal_params[i]);
   5627		cal_gain[i] = cal_params[i].cal_gain;
   5628	}
   5629	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, cal_gain);
   5630
   5631	for (i = 0; i < 2; i++) {
   5632		if (i == 0) {
   5633			rfctl[0] = B43_NPHY_RFCTL_INTC1;
   5634			rfctl[1] = B43_NPHY_RFCTL_INTC2;
   5635			afectl_core = B43_NPHY_AFECTL_C1;
   5636		} else {
   5637			rfctl[0] = B43_NPHY_RFCTL_INTC2;
   5638			rfctl[1] = B43_NPHY_RFCTL_INTC1;
   5639			afectl_core = B43_NPHY_AFECTL_C2;
   5640		}
   5641
   5642		tmp[1] = b43_phy_read(dev, B43_NPHY_RFSEQCA);
   5643		tmp[2] = b43_phy_read(dev, afectl_core);
   5644		tmp[3] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
   5645		tmp[4] = b43_phy_read(dev, rfctl[0]);
   5646		tmp[5] = b43_phy_read(dev, rfctl[1]);
   5647
   5648		b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
   5649				~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF,
   5650				((1 - i) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));
   5651		b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN,
   5652				(1 - i));
   5653		b43_phy_set(dev, afectl_core, 0x0006);
   5654		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0006);
   5655
   5656		band = b43_current_band(dev->wl);
   5657
   5658		if (nphy->rxcalparams & 0xFF000000) {
   5659			if (band == NL80211_BAND_5GHZ)
   5660				b43_phy_write(dev, rfctl[0], 0x140);
   5661			else
   5662				b43_phy_write(dev, rfctl[0], 0x110);
   5663		} else {
   5664			if (band == NL80211_BAND_5GHZ)
   5665				b43_phy_write(dev, rfctl[0], 0x180);
   5666			else
   5667				b43_phy_write(dev, rfctl[0], 0x120);
   5668		}
   5669
   5670		if (band == NL80211_BAND_5GHZ)
   5671			b43_phy_write(dev, rfctl[1], 0x148);
   5672		else
   5673			b43_phy_write(dev, rfctl[1], 0x114);
   5674
   5675		if (nphy->rxcalparams & 0x10000) {
   5676			b43_radio_maskset(dev, B2055_C1_GENSPARE2, 0xFC,
   5677					(i + 1));
   5678			b43_radio_maskset(dev, B2055_C2_GENSPARE2, 0xFC,
   5679					(2 - i));
   5680		}
   5681
   5682		for (j = 0; j < 4; j++) {
   5683			if (j < 3) {
   5684				cur_lna = lna[j];
   5685				cur_hpf1 = hpf1[j];
   5686				cur_hpf2 = hpf2[j];
   5687			} else {
   5688				if (power[1] > 10000) {
   5689					use = 1;
   5690					cur_hpf = cur_hpf1;
   5691					index = 2;
   5692				} else {
   5693					if (power[0] > 10000) {
   5694						use = 1;
   5695						cur_hpf = cur_hpf1;
   5696						index = 1;
   5697					} else {
   5698						index = 0;
   5699						use = 2;
   5700						cur_hpf = cur_hpf2;
   5701					}
   5702				}
   5703				cur_lna = lna[index];
   5704				cur_hpf1 = hpf1[index];
   5705				cur_hpf2 = hpf2[index];
   5706				cur_hpf += desired - hweight32(power[index]);
   5707				cur_hpf = clamp_val(cur_hpf, 0, 10);
   5708				if (use == 1)
   5709					cur_hpf1 = cur_hpf;
   5710				else
   5711					cur_hpf2 = cur_hpf;
   5712			}
   5713
   5714			tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) |
   5715					(cur_lna << 2));
   5716			b43_nphy_rf_ctl_override(dev, 0x400, tmp[0], 3,
   5717									false);
   5718			b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
   5719			b43_nphy_stop_playback(dev);
   5720
   5721			if (playtone) {
   5722				ret = b43_nphy_tx_tone(dev, 4000,
   5723						(nphy->rxcalparams & 0xFFFF),
   5724						false, false, true);
   5725				playtone = false;
   5726			} else {
   5727				b43_nphy_run_samples(dev, 160, 0xFFFF, 0, false,
   5728						     false, true);
   5729			}
   5730
   5731			if (ret == 0) {
   5732				if (j < 3) {
   5733					b43_nphy_rx_iq_est(dev, &est, 1024, 32,
   5734									false);
   5735					if (i == 0) {
   5736						real = est.i0_pwr;
   5737						imag = est.q0_pwr;
   5738					} else {
   5739						real = est.i1_pwr;
   5740						imag = est.q1_pwr;
   5741					}
   5742					power[i] = ((real + imag) / 1024) + 1;
   5743				} else {
   5744					b43_nphy_calc_rx_iq_comp(dev, 1 << i);
   5745				}
   5746				b43_nphy_stop_playback(dev);
   5747			}
   5748
   5749			if (ret != 0)
   5750				break;
   5751		}
   5752
   5753		b43_radio_mask(dev, B2055_C1_GENSPARE2, 0xFC);
   5754		b43_radio_mask(dev, B2055_C2_GENSPARE2, 0xFC);
   5755		b43_phy_write(dev, rfctl[1], tmp[5]);
   5756		b43_phy_write(dev, rfctl[0], tmp[4]);
   5757		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp[3]);
   5758		b43_phy_write(dev, afectl_core, tmp[2]);
   5759		b43_phy_write(dev, B43_NPHY_RFSEQCA, tmp[1]);
   5760
   5761		if (ret != 0)
   5762			break;
   5763	}
   5764
   5765	b43_nphy_rf_ctl_override(dev, 0x400, 0, 3, true);
   5766	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
   5767	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save);
   5768
   5769	b43_nphy_stay_in_carrier_search(dev, 0);
   5770
   5771	return ret;
   5772}
   5773
   5774static int b43_nphy_rev3_cal_rx_iq(struct b43_wldev *dev,
   5775			struct nphy_txgains target, u8 type, bool debug)
   5776{
   5777	return -1;
   5778}
   5779
   5780/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIq */
   5781static int b43_nphy_cal_rx_iq(struct b43_wldev *dev,
   5782			struct nphy_txgains target, u8 type, bool debug)
   5783{
   5784	if (dev->phy.rev >= 7)
   5785		type = 0;
   5786
   5787	if (dev->phy.rev >= 3)
   5788		return b43_nphy_rev3_cal_rx_iq(dev, target, type, debug);
   5789	else
   5790		return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug);
   5791}
   5792
   5793/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */
   5794static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask)
   5795{
   5796	struct b43_phy *phy = &dev->phy;
   5797	struct b43_phy_n *nphy = phy->n;
   5798	/* u16 buf[16]; it's rev3+ */
   5799
   5800	nphy->phyrxchain = mask;
   5801
   5802	if (0 /* FIXME clk */)
   5803		return;
   5804
   5805	b43_mac_suspend(dev);
   5806
   5807	if (nphy->hang_avoid)
   5808		b43_nphy_stay_in_carrier_search(dev, true);
   5809
   5810	b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN,
   5811			(mask & 0x3) << B43_NPHY_RFSEQCA_RXEN_SHIFT);
   5812
   5813	if ((mask & 0x3) != 0x3) {
   5814		b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 1);
   5815		if (dev->phy.rev >= 3) {
   5816			/* TODO */
   5817		}
   5818	} else {
   5819		b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 0x1E);
   5820		if (dev->phy.rev >= 3) {
   5821			/* TODO */
   5822		}
   5823	}
   5824
   5825	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
   5826
   5827	if (nphy->hang_avoid)
   5828		b43_nphy_stay_in_carrier_search(dev, false);
   5829
   5830	b43_mac_enable(dev);
   5831}
   5832
   5833static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev,
   5834							bool ignore_tssi)
   5835{
   5836	struct b43_phy *phy = &dev->phy;
   5837	struct b43_phy_n *nphy = dev->phy.n;
   5838	struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan;
   5839	struct b43_ppr *ppr = &nphy->tx_pwr_max_ppr;
   5840	u8 max; /* qdBm */
   5841
   5842	if (nphy->tx_pwr_last_recalc_freq == channel->center_freq &&
   5843	    nphy->tx_pwr_last_recalc_limit == phy->desired_txpower)
   5844		return B43_TXPWR_RES_DONE;
   5845
   5846	/* Make sure we have a clean PPR */
   5847	b43_ppr_clear(dev, ppr);
   5848
   5849	/* HW limitations */
   5850	b43_ppr_load_max_from_sprom(dev, ppr, B43_BAND_2G);
   5851
   5852	/* Regulatory & user settings */
   5853	max = INT_TO_Q52(phy->chandef->chan->max_power);
   5854	if (phy->desired_txpower)
   5855		max = min_t(u8, max, INT_TO_Q52(phy->desired_txpower));
   5856	b43_ppr_apply_max(dev, ppr, max);
   5857	if (b43_debug(dev, B43_DBG_XMITPOWER))
   5858		b43dbg(dev->wl, "Calculated TX power: " Q52_FMT "\n",
   5859		       Q52_ARG(b43_ppr_get_max(dev, ppr)));
   5860
   5861	/* TODO: Enable this once we get gains working */
   5862#if 0
   5863	/* Some extra gains */
   5864	hw_gain = 6; /* N-PHY specific */
   5865	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
   5866		hw_gain += sprom->antenna_gain.a0;
   5867	else
   5868		hw_gain += sprom->antenna_gain.a1;
   5869	b43_ppr_add(dev, ppr, -hw_gain);
   5870#endif
   5871
   5872	/* Make sure we didn't go too low */
   5873	b43_ppr_apply_min(dev, ppr, INT_TO_Q52(8));
   5874
   5875	/* Apply */
   5876	b43_mac_suspend(dev);
   5877	b43_nphy_tx_power_ctl_setup(dev);
   5878	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) {
   5879		b43_maskset32(dev, B43_MMIO_MACCTL, ~0, B43_MACCTL_PHY_LOCK);
   5880		b43_read32(dev, B43_MMIO_MACCTL);
   5881		udelay(1);
   5882	}
   5883	b43_nphy_tx_power_ctrl(dev, nphy->txpwrctrl);
   5884	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12)
   5885		b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_PHY_LOCK, 0);
   5886	b43_mac_enable(dev);
   5887
   5888	nphy->tx_pwr_last_recalc_freq = channel->center_freq;
   5889	nphy->tx_pwr_last_recalc_limit = phy->desired_txpower;
   5890
   5891	return B43_TXPWR_RES_DONE;
   5892}
   5893
   5894/**************************************************
   5895 * N-PHY init
   5896 **************************************************/
   5897
   5898/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */
   5899static void b43_nphy_update_mimo_config(struct b43_wldev *dev, s32 preamble)
   5900{
   5901	u16 mimocfg = b43_phy_read(dev, B43_NPHY_MIMOCFG);
   5902
   5903	mimocfg |= B43_NPHY_MIMOCFG_AUTO;
   5904	if (preamble == 1)
   5905		mimocfg |= B43_NPHY_MIMOCFG_GFMIX;
   5906	else
   5907		mimocfg &= ~B43_NPHY_MIMOCFG_GFMIX;
   5908
   5909	b43_phy_write(dev, B43_NPHY_MIMOCFG, mimocfg);
   5910}
   5911
   5912/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/BPHYInit */
   5913static void b43_nphy_bphy_init(struct b43_wldev *dev)
   5914{
   5915	unsigned int i;
   5916	u16 val;
   5917
   5918	val = 0x1E1F;
   5919	for (i = 0; i < 16; i++) {
   5920		b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val);
   5921		val -= 0x202;
   5922	}
   5923	val = 0x3E3F;
   5924	for (i = 0; i < 16; i++) {
   5925		b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val);
   5926		val -= 0x202;
   5927	}
   5928	b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668);
   5929}
   5930
   5931/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */
   5932static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init)
   5933{
   5934	if (dev->phy.rev >= 7)
   5935		return;
   5936
   5937	if (dev->phy.rev >= 3) {
   5938		if (!init)
   5939			return;
   5940		if (0 /* FIXME */) {
   5941			b43_ntab_write(dev, B43_NTAB16(9, 2), 0x211);
   5942			b43_ntab_write(dev, B43_NTAB16(9, 3), 0x222);
   5943			b43_ntab_write(dev, B43_NTAB16(9, 8), 0x144);
   5944			b43_ntab_write(dev, B43_NTAB16(9, 12), 0x188);
   5945		}
   5946	} else {
   5947		b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0);
   5948		b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0);
   5949
   5950		switch (dev->dev->bus_type) {
   5951#ifdef CONFIG_B43_BCMA
   5952		case B43_BUS_BCMA:
   5953			bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc,
   5954						 0xFC00, 0xFC00);
   5955			break;
   5956#endif
   5957#ifdef CONFIG_B43_SSB
   5958		case B43_BUS_SSB:
   5959			ssb_chipco_gpio_control(&dev->dev->sdev->bus->chipco,
   5960						0xFC00, 0xFC00);
   5961			break;
   5962#endif
   5963		}
   5964
   5965		b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0);
   5966		b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, 0xFC00);
   5967		b43_maskset16(dev, B43_MMIO_GPIO_CONTROL, (~0xFC00 & 0xFFFF),
   5968			      0);
   5969
   5970		if (init) {
   5971			b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
   5972			b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
   5973			b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
   5974			b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
   5975		}
   5976	}
   5977}
   5978
   5979/* http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N */
   5980static int b43_phy_initn(struct b43_wldev *dev)
   5981{
   5982	struct ssb_sprom *sprom = dev->dev->bus_sprom;
   5983	struct b43_phy *phy = &dev->phy;
   5984	struct b43_phy_n *nphy = phy->n;
   5985	u8 tx_pwr_state;
   5986	struct nphy_txgains target;
   5987	u16 tmp;
   5988	bool do_rssi_cal;
   5989
   5990	u16 clip[2];
   5991	bool do_cal = false;
   5992
   5993	if ((dev->phy.rev >= 3) &&
   5994	   (sprom->boardflags_lo & B43_BFL_EXTLNA) &&
   5995	   (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)) {
   5996		switch (dev->dev->bus_type) {
   5997#ifdef CONFIG_B43_BCMA
   5998		case B43_BUS_BCMA:
   5999			bcma_cc_set32(&dev->dev->bdev->bus->drv_cc,
   6000				      BCMA_CC_CHIPCTL, 0x40);
   6001			break;
   6002#endif
   6003#ifdef CONFIG_B43_SSB
   6004		case B43_BUS_SSB:
   6005			chipco_set32(&dev->dev->sdev->bus->chipco,
   6006				     SSB_CHIPCO_CHIPCTL, 0x40);
   6007			break;
   6008#endif
   6009		}
   6010	}
   6011	nphy->use_int_tx_iq_lo_cal = b43_nphy_ipa(dev) ||
   6012		phy->rev >= 7 ||
   6013		(phy->rev >= 5 &&
   6014		 sprom->boardflags2_hi & B43_BFH2_INTERNDET_TXIQCAL);
   6015	nphy->deaf_count = 0;
   6016	b43_nphy_tables_init(dev);
   6017	nphy->crsminpwr_adjusted = false;
   6018	nphy->noisevars_adjusted = false;
   6019
   6020	/* Clear all overrides */
   6021	if (dev->phy.rev >= 3) {
   6022		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, 0);
   6023		b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
   6024		if (phy->rev >= 7) {
   6025			b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0);
   6026			b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER4, 0);
   6027			b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER5, 0);
   6028			b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER6, 0);
   6029		}
   6030		if (phy->rev >= 19) {
   6031			/* TODO */
   6032		}
   6033
   6034		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, 0);
   6035		b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, 0);
   6036	} else {
   6037		b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
   6038	}
   6039	b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 0);
   6040	b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 0);
   6041	if (dev->phy.rev < 6) {
   6042		b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0);
   6043		b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0);
   6044	}
   6045	b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
   6046		     ~(B43_NPHY_RFSEQMODE_CAOVER |
   6047		       B43_NPHY_RFSEQMODE_TROVER));
   6048	if (dev->phy.rev >= 3)
   6049		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, 0);
   6050	b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 0);
   6051
   6052	if (dev->phy.rev <= 2) {
   6053		tmp = (dev->phy.rev == 2) ? 0x3B : 0x40;
   6054		b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
   6055				~B43_NPHY_BPHY_CTL3_SCALE,
   6056				tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT);
   6057	}
   6058	b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20);
   6059	b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20);
   6060
   6061	if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD ||
   6062	    (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&
   6063	     dev->dev->board_type == BCMA_BOARD_TYPE_BCM943224M93))
   6064		b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0);
   6065	else
   6066		b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8);
   6067	b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 0xC8);
   6068	b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50);
   6069	b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30);
   6070
   6071	if (phy->rev < 8)
   6072		b43_nphy_update_mimo_config(dev, nphy->preamble_override);
   6073
   6074	b43_nphy_update_txrx_chain(dev);
   6075
   6076	if (phy->rev < 2) {
   6077		b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8);
   6078		b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4);
   6079	}
   6080
   6081	if (b43_nphy_ipa(dev)) {
   6082		b43_phy_set(dev, B43_NPHY_PAPD_EN0, 0x1);
   6083		b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ0, 0x007F,
   6084				nphy->papd_epsilon_offset[0] << 7);
   6085		b43_phy_set(dev, B43_NPHY_PAPD_EN1, 0x1);
   6086		b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ1, 0x007F,
   6087				nphy->papd_epsilon_offset[1] << 7);
   6088		b43_nphy_int_pa_set_tx_dig_filters(dev);
   6089	} else if (phy->rev >= 5) {
   6090		b43_nphy_ext_pa_set_tx_dig_filters(dev);
   6091	}
   6092
   6093	b43_nphy_workarounds(dev);
   6094
   6095	/* Reset CCA, in init code it differs a little from standard way */
   6096	b43_phy_force_clock(dev, 1);
   6097	tmp = b43_phy_read(dev, B43_NPHY_BBCFG);
   6098	b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA);
   6099	b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA);
   6100	b43_phy_force_clock(dev, 0);
   6101
   6102	b43_mac_phy_clock_set(dev, true);
   6103
   6104	if (phy->rev < 7) {
   6105		b43_nphy_pa_override(dev, false);
   6106		b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
   6107		b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
   6108		b43_nphy_pa_override(dev, true);
   6109	}
   6110
   6111	b43_nphy_classifier(dev, 0, 0);
   6112	b43_nphy_read_clip_detection(dev, clip);
   6113	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
   6114		b43_nphy_bphy_init(dev);
   6115
   6116	tx_pwr_state = nphy->txpwrctrl;
   6117	b43_nphy_tx_power_ctrl(dev, false);
   6118	b43_nphy_tx_power_fix(dev);
   6119	b43_nphy_tx_power_ctl_idle_tssi(dev);
   6120	b43_nphy_tx_power_ctl_setup(dev);
   6121	b43_nphy_tx_gain_table_upload(dev);
   6122
   6123	if (nphy->phyrxchain != 3)
   6124		b43_nphy_set_rx_core_state(dev, nphy->phyrxchain);
   6125	if (nphy->mphase_cal_phase_id > 0) {
   6126		;/* TODO PHY Periodic Calibration Multi-Phase Restart */
   6127	}
   6128
   6129	do_rssi_cal = false;
   6130	if (phy->rev >= 3) {
   6131		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
   6132			do_rssi_cal = !nphy->rssical_chanspec_2G.center_freq;
   6133		else
   6134			do_rssi_cal = !nphy->rssical_chanspec_5G.center_freq;
   6135
   6136		if (do_rssi_cal)
   6137			b43_nphy_rssi_cal(dev);
   6138		else
   6139			b43_nphy_restore_rssi_cal(dev);
   6140	} else {
   6141		b43_nphy_rssi_cal(dev);
   6142	}
   6143
   6144	if (!((nphy->measure_hold & 0x6) != 0)) {
   6145		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
   6146			do_cal = !nphy->iqcal_chanspec_2G.center_freq;
   6147		else
   6148			do_cal = !nphy->iqcal_chanspec_5G.center_freq;
   6149
   6150		if (nphy->mute)
   6151			do_cal = false;
   6152
   6153		if (do_cal) {
   6154			target = b43_nphy_get_tx_gains(dev);
   6155
   6156			if (nphy->antsel_type == 2)
   6157				b43_nphy_superswitch_init(dev, true);
   6158			if (nphy->perical != 2) {
   6159				b43_nphy_rssi_cal(dev);
   6160				if (phy->rev >= 3) {
   6161					nphy->cal_orig_pwr_idx[0] =
   6162					    nphy->txpwrindex[0].index_internal;
   6163					nphy->cal_orig_pwr_idx[1] =
   6164					    nphy->txpwrindex[1].index_internal;
   6165					/* TODO N PHY Pre Calibrate TX Gain */
   6166					target = b43_nphy_get_tx_gains(dev);
   6167				}
   6168				if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false))
   6169					if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0)
   6170						b43_nphy_save_cal(dev);
   6171			} else if (nphy->mphase_cal_phase_id == 0) {
   6172				;/* N PHY Periodic Calibration with arg 3 */
   6173			}
   6174		} else {
   6175			b43_nphy_restore_cal(dev);
   6176		}
   6177	}
   6178
   6179	b43_nphy_tx_pwr_ctrl_coef_setup(dev);
   6180	b43_nphy_tx_power_ctrl(dev, tx_pwr_state);
   6181	b43_phy_write(dev, B43_NPHY_TXMACIF_HOLDOFF, 0x0015);
   6182	b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320);
   6183	if (phy->rev >= 3 && phy->rev <= 6)
   6184		b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x0032);
   6185	b43_nphy_tx_lpf_bw(dev);
   6186	if (phy->rev >= 3)
   6187		b43_nphy_spur_workaround(dev);
   6188
   6189	return 0;
   6190}
   6191
   6192/**************************************************
   6193 * Channel switching ops.
   6194 **************************************************/
   6195
   6196static void b43_chantab_phy_upload(struct b43_wldev *dev,
   6197				   const struct b43_phy_n_sfo_cfg *e)
   6198{
   6199	b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a);
   6200	b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2);
   6201	b43_phy_write(dev, B43_NPHY_BW3, e->phy_bw3);
   6202	b43_phy_write(dev, B43_NPHY_BW4, e->phy_bw4);
   6203	b43_phy_write(dev, B43_NPHY_BW5, e->phy_bw5);
   6204	b43_phy_write(dev, B43_NPHY_BW6, e->phy_bw6);
   6205}
   6206
   6207/* https://bcm-v4.sipsolutions.net/802.11/PmuSpurAvoid */
   6208static void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid)
   6209{
   6210	switch (dev->dev->bus_type) {
   6211#ifdef CONFIG_B43_BCMA
   6212	case B43_BUS_BCMA:
   6213		bcma_pmu_spuravoid_pllupdate(&dev->dev->bdev->bus->drv_cc,
   6214					     avoid);
   6215		break;
   6216#endif
   6217#ifdef CONFIG_B43_SSB
   6218	case B43_BUS_SSB:
   6219		ssb_pmu_spuravoid_pllupdate(&dev->dev->sdev->bus->chipco,
   6220					    avoid);
   6221		break;
   6222#endif
   6223	}
   6224}
   6225
   6226/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */
   6227static void b43_nphy_channel_setup(struct b43_wldev *dev,
   6228				const struct b43_phy_n_sfo_cfg *e,
   6229				struct ieee80211_channel *new_channel)
   6230{
   6231	struct b43_phy *phy = &dev->phy;
   6232	struct b43_phy_n *nphy = dev->phy.n;
   6233	int ch = new_channel->hw_value;
   6234	u16 tmp16;
   6235
   6236	if (new_channel->band == NL80211_BAND_5GHZ) {
   6237		/* Switch to 2 GHz for a moment to access B43_PHY_B_BBCFG */
   6238		b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
   6239
   6240		tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR);
   6241		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4);
   6242		/* Put BPHY in the reset */
   6243		b43_phy_set(dev, B43_PHY_B_BBCFG,
   6244			    B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX);
   6245		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16);
   6246		b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ);
   6247	} else if (new_channel->band == NL80211_BAND_2GHZ) {
   6248		b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
   6249		tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR);
   6250		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4);
   6251		/* Take BPHY out of the reset */
   6252		b43_phy_mask(dev, B43_PHY_B_BBCFG,
   6253			     (u16)~(B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX));
   6254		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16);
   6255	}
   6256
   6257	b43_chantab_phy_upload(dev, e);
   6258
   6259	if (new_channel->hw_value == 14) {
   6260		b43_nphy_classifier(dev, 2, 0);
   6261		b43_phy_set(dev, B43_PHY_B_TEST, 0x0800);
   6262	} else {
   6263		b43_nphy_classifier(dev, 2, 2);
   6264		if (new_channel->band == NL80211_BAND_2GHZ)
   6265			b43_phy_mask(dev, B43_PHY_B_TEST, ~0x840);
   6266	}
   6267
   6268	if (!nphy->txpwrctrl)
   6269		b43_nphy_tx_power_fix(dev);
   6270
   6271	if (dev->phy.rev < 3)
   6272		b43_nphy_adjust_lna_gain_table(dev);
   6273
   6274	b43_nphy_tx_lpf_bw(dev);
   6275
   6276	if (dev->phy.rev >= 3 &&
   6277	    dev->phy.n->spur_avoid != B43_SPUR_AVOID_DISABLE) {
   6278		u8 spuravoid = 0;
   6279
   6280		if (dev->phy.n->spur_avoid == B43_SPUR_AVOID_FORCE) {
   6281			spuravoid = 1;
   6282		} else if (phy->rev >= 19) {
   6283			/* TODO */
   6284		} else if (phy->rev >= 18) {
   6285			/* TODO */
   6286		} else if (phy->rev >= 17) {
   6287			/* TODO: Off for channels 1-11, but check 12-14! */
   6288		} else if (phy->rev >= 16) {
   6289			/* TODO: Off for 2 GHz, but check 5 GHz! */
   6290		} else if (phy->rev >= 7) {
   6291			if (!b43_is_40mhz(dev)) { /* 20MHz */
   6292				if (ch == 13 || ch == 14 || ch == 153)
   6293					spuravoid = 1;
   6294			} else { /* 40 MHz */
   6295				if (ch == 54)
   6296					spuravoid = 1;
   6297			}
   6298		} else {
   6299			if (!b43_is_40mhz(dev)) { /* 20MHz */
   6300				if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14)
   6301					spuravoid = 1;
   6302			} else { /* 40MHz */
   6303				if (nphy->aband_spurwar_en &&
   6304				    (ch == 38 || ch == 102 || ch == 118))
   6305					spuravoid = dev->dev->chip_id == 0x4716;
   6306			}
   6307		}
   6308
   6309		b43_nphy_pmu_spur_avoid(dev, spuravoid);
   6310
   6311		b43_mac_switch_freq(dev, spuravoid);
   6312
   6313		if (dev->phy.rev == 3 || dev->phy.rev == 4)
   6314			b43_wireless_core_phy_pll_reset(dev);
   6315
   6316		if (spuravoid)
   6317			b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTRX);
   6318		else
   6319			b43_phy_mask(dev, B43_NPHY_BBCFG,
   6320				     ~B43_NPHY_BBCFG_RSTRX & 0xFFFF);
   6321
   6322		b43_nphy_reset_cca(dev);
   6323
   6324		/* wl sets useless phy_isspuravoid here */
   6325	}
   6326
   6327	b43_phy_write(dev, B43_NPHY_NDATAT_DUP40, 0x3830);
   6328
   6329	if (phy->rev >= 3)
   6330		b43_nphy_spur_workaround(dev);
   6331}
   6332
   6333/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */
   6334static int b43_nphy_set_channel(struct b43_wldev *dev,
   6335				struct ieee80211_channel *channel,
   6336				enum nl80211_channel_type channel_type)
   6337{
   6338	struct b43_phy *phy = &dev->phy;
   6339
   6340	const struct b43_nphy_channeltab_entry_rev2 *tabent_r2 = NULL;
   6341	const struct b43_nphy_channeltab_entry_rev3 *tabent_r3 = NULL;
   6342	const struct b43_nphy_chantabent_rev7 *tabent_r7 = NULL;
   6343	const struct b43_nphy_chantabent_rev7_2g *tabent_r7_2g = NULL;
   6344
   6345	u8 tmp;
   6346
   6347	if (phy->rev >= 19) {
   6348		return -ESRCH;
   6349		/* TODO */
   6350	} else if (phy->rev >= 7) {
   6351		r2057_get_chantabent_rev7(dev, channel->center_freq,
   6352					  &tabent_r7, &tabent_r7_2g);
   6353		if (!tabent_r7 && !tabent_r7_2g)
   6354			return -ESRCH;
   6355	} else if (phy->rev >= 3) {
   6356		tabent_r3 = b43_nphy_get_chantabent_rev3(dev,
   6357							channel->center_freq);
   6358		if (!tabent_r3)
   6359			return -ESRCH;
   6360	} else {
   6361		tabent_r2 = b43_nphy_get_chantabent_rev2(dev,
   6362							channel->hw_value);
   6363		if (!tabent_r2)
   6364			return -ESRCH;
   6365	}
   6366
   6367	/* Channel is set later in common code, but we need to set it on our
   6368	   own to let this function's subcalls work properly. */
   6369	phy->channel = channel->hw_value;
   6370
   6371#if 0
   6372	if (b43_channel_type_is_40mhz(phy->channel_type) !=
   6373		b43_channel_type_is_40mhz(channel_type))
   6374		; /* TODO: BMAC BW Set (channel_type) */
   6375#endif
   6376
   6377	if (channel_type == NL80211_CHAN_HT40PLUS) {
   6378		b43_phy_set(dev, B43_NPHY_RXCTL, B43_NPHY_RXCTL_BSELU20);
   6379		if (phy->rev >= 7)
   6380			b43_phy_set(dev, 0x310, 0x8000);
   6381	} else if (channel_type == NL80211_CHAN_HT40MINUS) {
   6382		b43_phy_mask(dev, B43_NPHY_RXCTL, ~B43_NPHY_RXCTL_BSELU20);
   6383		if (phy->rev >= 7)
   6384			b43_phy_mask(dev, 0x310, (u16)~0x8000);
   6385	}
   6386
   6387	if (phy->rev >= 19) {
   6388		/* TODO */
   6389	} else if (phy->rev >= 7) {
   6390		const struct b43_phy_n_sfo_cfg *phy_regs = tabent_r7 ?
   6391			&(tabent_r7->phy_regs) : &(tabent_r7_2g->phy_regs);
   6392
   6393		if (phy->radio_rev <= 4 || phy->radio_rev == 6) {
   6394			tmp = (channel->band == NL80211_BAND_5GHZ) ? 2 : 0;
   6395			b43_radio_maskset(dev, R2057_TIA_CONFIG_CORE0, ~2, tmp);
   6396			b43_radio_maskset(dev, R2057_TIA_CONFIG_CORE1, ~2, tmp);
   6397		}
   6398
   6399		b43_radio_2057_setup(dev, tabent_r7, tabent_r7_2g);
   6400		b43_nphy_channel_setup(dev, phy_regs, channel);
   6401	} else if (phy->rev >= 3) {
   6402		tmp = (channel->band == NL80211_BAND_5GHZ) ? 4 : 0;
   6403		b43_radio_maskset(dev, 0x08, 0xFFFB, tmp);
   6404		b43_radio_2056_setup(dev, tabent_r3);
   6405		b43_nphy_channel_setup(dev, &(tabent_r3->phy_regs), channel);
   6406	} else {
   6407		tmp = (channel->band == NL80211_BAND_5GHZ) ? 0x0020 : 0x0050;
   6408		b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp);
   6409		b43_radio_2055_setup(dev, tabent_r2);
   6410		b43_nphy_channel_setup(dev, &(tabent_r2->phy_regs), channel);
   6411	}
   6412
   6413	return 0;
   6414}
   6415
   6416/**************************************************
   6417 * Basic PHY ops.
   6418 **************************************************/
   6419
   6420static int b43_nphy_op_allocate(struct b43_wldev *dev)
   6421{
   6422	struct b43_phy_n *nphy;
   6423
   6424	nphy = kzalloc(sizeof(*nphy), GFP_KERNEL);
   6425	if (!nphy)
   6426		return -ENOMEM;
   6427
   6428	dev->phy.n = nphy;
   6429
   6430	return 0;
   6431}
   6432
   6433static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
   6434{
   6435	struct b43_phy *phy = &dev->phy;
   6436	struct b43_phy_n *nphy = phy->n;
   6437	struct ssb_sprom *sprom = dev->dev->bus_sprom;
   6438
   6439	memset(nphy, 0, sizeof(*nphy));
   6440
   6441	nphy->hang_avoid = (phy->rev == 3 || phy->rev == 4);
   6442	nphy->spur_avoid = (phy->rev >= 3) ?
   6443				B43_SPUR_AVOID_AUTO : B43_SPUR_AVOID_DISABLE;
   6444	nphy->gain_boost = true; /* this way we follow wl, assume it is true */
   6445	nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */
   6446	nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */
   6447	nphy->perical = 2; /* avoid additional rssi cal on init (like wl) */
   6448	/* 128 can mean disabled-by-default state of TX pwr ctl. Max value is
   6449	 * 0x7f == 127 and we check for 128 when restoring TX pwr ctl. */
   6450	nphy->tx_pwr_idx[0] = 128;
   6451	nphy->tx_pwr_idx[1] = 128;
   6452
   6453	/* Hardware TX power control and 5GHz power gain */
   6454	nphy->txpwrctrl = false;
   6455	nphy->pwg_gain_5ghz = false;
   6456	if (dev->phy.rev >= 3 ||
   6457	    (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&
   6458	     (dev->dev->core_rev == 11 || dev->dev->core_rev == 12))) {
   6459		nphy->txpwrctrl = true;
   6460		nphy->pwg_gain_5ghz = true;
   6461	} else if (sprom->revision >= 4) {
   6462		if (dev->phy.rev >= 2 &&
   6463		    (sprom->boardflags2_lo & B43_BFL2_TXPWRCTRL_EN)) {
   6464			nphy->txpwrctrl = true;
   6465#ifdef CONFIG_B43_SSB
   6466			if (dev->dev->bus_type == B43_BUS_SSB &&
   6467			    dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI) {
   6468				struct pci_dev *pdev =
   6469					dev->dev->sdev->bus->host_pci;
   6470				if (pdev->device == 0x4328 ||
   6471				    pdev->device == 0x432a)
   6472					nphy->pwg_gain_5ghz = true;
   6473			}
   6474#endif
   6475		} else if (sprom->boardflags2_lo & B43_BFL2_5G_PWRGAIN) {
   6476			nphy->pwg_gain_5ghz = true;
   6477		}
   6478	}
   6479
   6480	if (dev->phy.rev >= 3) {
   6481		nphy->ipa2g_on = sprom->fem.ghz2.extpa_gain == 2;
   6482		nphy->ipa5g_on = sprom->fem.ghz5.extpa_gain == 2;
   6483	}
   6484}
   6485
   6486static void b43_nphy_op_free(struct b43_wldev *dev)
   6487{
   6488	struct b43_phy *phy = &dev->phy;
   6489	struct b43_phy_n *nphy = phy->n;
   6490
   6491	kfree(nphy);
   6492	phy->n = NULL;
   6493}
   6494
   6495static int b43_nphy_op_init(struct b43_wldev *dev)
   6496{
   6497	return b43_phy_initn(dev);
   6498}
   6499
   6500static inline void check_phyreg(struct b43_wldev *dev, u16 offset)
   6501{
   6502#if B43_DEBUG
   6503	if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) {
   6504		/* OFDM registers are onnly available on A/G-PHYs */
   6505		b43err(dev->wl, "Invalid OFDM PHY access at "
   6506		       "0x%04X on N-PHY\n", offset);
   6507		dump_stack();
   6508	}
   6509	if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) {
   6510		/* Ext-G registers are only available on G-PHYs */
   6511		b43err(dev->wl, "Invalid EXT-G PHY access at "
   6512		       "0x%04X on N-PHY\n", offset);
   6513		dump_stack();
   6514	}
   6515#endif /* B43_DEBUG */
   6516}
   6517
   6518static void b43_nphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
   6519				 u16 set)
   6520{
   6521	check_phyreg(dev, reg);
   6522	b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
   6523	b43_maskset16(dev, B43_MMIO_PHY_DATA, mask, set);
   6524	dev->phy.writes_counter = 1;
   6525}
   6526
   6527static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg)
   6528{
   6529	/* Register 1 is a 32-bit register. */
   6530	B43_WARN_ON(dev->phy.rev < 7 && reg == 1);
   6531
   6532	if (dev->phy.rev >= 7)
   6533		reg |= 0x200; /* Radio 0x2057 */
   6534	else
   6535		reg |= 0x100;
   6536
   6537	b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);
   6538	return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
   6539}
   6540
   6541static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
   6542{
   6543	/* Register 1 is a 32-bit register. */
   6544	B43_WARN_ON(dev->phy.rev < 7 && reg == 1);
   6545
   6546	b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);
   6547	b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
   6548}
   6549
   6550/* https://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */
   6551static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
   6552					bool blocked)
   6553{
   6554	struct b43_phy *phy = &dev->phy;
   6555
   6556	if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
   6557		b43err(dev->wl, "MAC not suspended\n");
   6558
   6559	if (blocked) {
   6560		if (phy->rev >= 19) {
   6561			/* TODO */
   6562		} else if (phy->rev >= 8) {
   6563			b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
   6564				     ~B43_NPHY_RFCTL_CMD_CHIP0PU);
   6565		} else if (phy->rev >= 7) {
   6566			/* Nothing needed */
   6567		} else if (phy->rev >= 3) {
   6568			b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
   6569				     ~B43_NPHY_RFCTL_CMD_CHIP0PU);
   6570
   6571			b43_radio_mask(dev, 0x09, ~0x2);
   6572
   6573			b43_radio_write(dev, 0x204D, 0);
   6574			b43_radio_write(dev, 0x2053, 0);
   6575			b43_radio_write(dev, 0x2058, 0);
   6576			b43_radio_write(dev, 0x205E, 0);
   6577			b43_radio_mask(dev, 0x2062, ~0xF0);
   6578			b43_radio_write(dev, 0x2064, 0);
   6579
   6580			b43_radio_write(dev, 0x304D, 0);
   6581			b43_radio_write(dev, 0x3053, 0);
   6582			b43_radio_write(dev, 0x3058, 0);
   6583			b43_radio_write(dev, 0x305E, 0);
   6584			b43_radio_mask(dev, 0x3062, ~0xF0);
   6585			b43_radio_write(dev, 0x3064, 0);
   6586		}
   6587	} else {
   6588		if (phy->rev >= 19) {
   6589			/* TODO */
   6590		} else if (phy->rev >= 7) {
   6591			if (!dev->phy.radio_on)
   6592				b43_radio_2057_init(dev);
   6593			b43_switch_channel(dev, dev->phy.channel);
   6594		} else if (phy->rev >= 3) {
   6595			if (!dev->phy.radio_on)
   6596				b43_radio_init2056(dev);
   6597			b43_switch_channel(dev, dev->phy.channel);
   6598		} else {
   6599			b43_radio_init2055(dev);
   6600		}
   6601	}
   6602}
   6603
   6604/* https://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */
   6605static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
   6606{
   6607	struct b43_phy *phy = &dev->phy;
   6608	u16 override = on ? 0x0 : 0x7FFF;
   6609	u16 core = on ? 0xD : 0x00FD;
   6610
   6611	if (phy->rev >= 19) {
   6612		/* TODO */
   6613	} else if (phy->rev >= 3) {
   6614		if (on) {
   6615			b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
   6616			b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
   6617			b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);
   6618			b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
   6619		} else {
   6620			b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
   6621			b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
   6622			b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
   6623			b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);
   6624		}
   6625	} else {
   6626		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
   6627	}
   6628}
   6629
   6630static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
   6631				      unsigned int new_channel)
   6632{
   6633	struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan;
   6634	enum nl80211_channel_type channel_type =
   6635		cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef);
   6636
   6637	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
   6638		if ((new_channel < 1) || (new_channel > 14))
   6639			return -EINVAL;
   6640	} else {
   6641		if (new_channel > 200)
   6642			return -EINVAL;
   6643	}
   6644
   6645	return b43_nphy_set_channel(dev, channel, channel_type);
   6646}
   6647
   6648static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev)
   6649{
   6650	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
   6651		return 1;
   6652	return 36;
   6653}
   6654
   6655const struct b43_phy_operations b43_phyops_n = {
   6656	.allocate		= b43_nphy_op_allocate,
   6657	.free			= b43_nphy_op_free,
   6658	.prepare_structs	= b43_nphy_op_prepare_structs,
   6659	.init			= b43_nphy_op_init,
   6660	.phy_maskset		= b43_nphy_op_maskset,
   6661	.radio_read		= b43_nphy_op_radio_read,
   6662	.radio_write		= b43_nphy_op_radio_write,
   6663	.software_rfkill	= b43_nphy_op_software_rfkill,
   6664	.switch_analog		= b43_nphy_op_switch_analog,
   6665	.switch_channel		= b43_nphy_op_switch_channel,
   6666	.get_default_chan	= b43_nphy_op_get_default_chan,
   6667	.recalc_txpower		= b43_nphy_op_recalc_txpower,
   6668};