brintos

brintos / linux-shallow public Read only

0
0
Text · 196.9 KiB · 4bb005b Raw
6665 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 4  Broadcom B43 wireless driver5  IEEE 802.11n PHY support6 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			else351				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 ops491 **************************************************/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 0x2057658 **************************************************/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_rcal809 */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_rccal923 */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	else999		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 0x20561043 **************************************************/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			else1258				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-radio1359 * https://bcm-v4.sipsolutions.net/802.11/Radio/2056/Init1360 */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 0x20551370 **************************************************/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_BROADCOM1443			      && dev->dev->board_type == SSB_BOARD_CB2_43211444			      && dev->dev->board_rev >= 0x41);1445	else1446		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-radio1483 * https://bcm-v4.sipsolutions.net/802.11/Radio/2055/Init1484 */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 * Samples1500 **************************************************/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		else1544			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			else1599				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	else1620		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 * RSSI1651 **************************************************/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				else1780					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				else1793					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						else1811							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	else1907		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			else1933				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_RSSIO22044	};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_RSSIO22058	};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			else2154				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		else2188			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			else2198				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					else2223						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	else2283		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	else2330		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			else2375				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		else2398			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 dumps2450	   identical, it really seems wl performs this */2451	b43_nphy_reset_cca(dev);2452}2453 2454/*2455 * RSSI Calibration2456 * https://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal2457 */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 * Workarounds2473 **************************************************/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	/* TODO - should depend on phy->rev */2483}2484 2485static void b43_nphy_gain_ctl_workarounds_rev3(struct b43_wldev *dev)2486{2487	struct ssb_sprom *sprom = dev->dev->bus_sprom;2488 2489	bool ghz5;2490	bool ext_lna;2491	u16 rssi_gain;2492	struct nphy_gain_ctl_workaround_entry *e;2493	u8 lpf_gain[6] = { 0x00, 0x06, 0x0C, 0x12, 0x12, 0x12 };2494	u8 lpf_bits[6] = { 0, 1, 2, 3, 3, 3 };2495 2496	/* Prepare values */2497	ghz5 = b43_phy_read(dev, B43_NPHY_BANDCTL)2498		& B43_NPHY_BANDCTL_5GHZ;2499	ext_lna = ghz5 ? sprom->boardflags_hi & B43_BFH_EXTLNA_5GHZ :2500		sprom->boardflags_lo & B43_BFL_EXTLNA;2501	e = b43_nphy_get_gain_ctl_workaround_ent(dev, ghz5, ext_lna);2502	if (ghz5 && dev->phy.rev >= 5)2503		rssi_gain = 0x90;2504	else2505		rssi_gain = 0x50;2506 2507	b43_phy_set(dev, B43_NPHY_RXCTL, 0x0040);2508 2509	/* Set Clip 2 detect */2510	b43_phy_set(dev, B43_NPHY_C1_CGAINI, B43_NPHY_C1_CGAINI_CL2DETECT);2511	b43_phy_set(dev, B43_NPHY_C2_CGAINI, B43_NPHY_C2_CGAINI_CL2DETECT);2512 2513	b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAG1_IDAC,2514			0x17);2515	b43_radio_write(dev, B2056_RX1 | B2056_RX_BIASPOLE_LNAG1_IDAC,2516			0x17);2517	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG2_IDAC, 0xF0);2518	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG2_IDAC, 0xF0);2519	b43_radio_write(dev, B2056_RX0 | B2056_RX_RSSI_POLE, 0x00);2520	b43_radio_write(dev, B2056_RX1 | B2056_RX_RSSI_POLE, 0x00);2521	b43_radio_write(dev, B2056_RX0 | B2056_RX_RSSI_GAIN,2522			rssi_gain);2523	b43_radio_write(dev, B2056_RX1 | B2056_RX_RSSI_GAIN,2524			rssi_gain);2525	b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAA1_IDAC,2526			0x17);2527	b43_radio_write(dev, B2056_RX1 | B2056_RX_BIASPOLE_LNAA1_IDAC,2528			0x17);2529	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA2_IDAC, 0xFF);2530	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA2_IDAC, 0xFF);2531 2532	b43_ntab_write_bulk(dev, B43_NTAB8(0, 8), 4, e->lna1_gain);2533	b43_ntab_write_bulk(dev, B43_NTAB8(1, 8), 4, e->lna1_gain);2534	b43_ntab_write_bulk(dev, B43_NTAB8(0, 16), 4, e->lna2_gain);2535	b43_ntab_write_bulk(dev, B43_NTAB8(1, 16), 4, e->lna2_gain);2536	b43_ntab_write_bulk(dev, B43_NTAB8(0, 32), 10, e->gain_db);2537	b43_ntab_write_bulk(dev, B43_NTAB8(1, 32), 10, e->gain_db);2538	b43_ntab_write_bulk(dev, B43_NTAB8(2, 32), 10, e->gain_bits);2539	b43_ntab_write_bulk(dev, B43_NTAB8(3, 32), 10, e->gain_bits);2540	b43_ntab_write_bulk(dev, B43_NTAB8(0, 0x40), 6, lpf_gain);2541	b43_ntab_write_bulk(dev, B43_NTAB8(1, 0x40), 6, lpf_gain);2542	b43_ntab_write_bulk(dev, B43_NTAB8(2, 0x40), 6, lpf_bits);2543	b43_ntab_write_bulk(dev, B43_NTAB8(3, 0x40), 6, lpf_bits);2544 2545	b43_phy_write(dev, B43_NPHY_REV3_C1_INITGAIN_A, e->init_gain);2546	b43_phy_write(dev, B43_NPHY_REV3_C2_INITGAIN_A, e->init_gain);2547 2548	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x106), 2,2549				e->rfseq_init);2550 2551	b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_HIGAIN_A, e->cliphi_gain);2552	b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_HIGAIN_A, e->cliphi_gain);2553	b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_MEDGAIN_A, e->clipmd_gain);2554	b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_MEDGAIN_A, e->clipmd_gain);2555	b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_LOGAIN_A, e->cliplo_gain);2556	b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_LOGAIN_A, e->cliplo_gain);2557 2558	b43_phy_maskset(dev, B43_NPHY_CRSMINPOWER0, 0xFF00, e->crsmin);2559	b43_phy_maskset(dev, B43_NPHY_CRSMINPOWERL0, 0xFF00, e->crsminl);2560	b43_phy_maskset(dev, B43_NPHY_CRSMINPOWERU0, 0xFF00, e->crsminu);2561	b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, e->nbclip);2562	b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, e->nbclip);2563	b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,2564			~B43_NPHY_C1_CLIPWBTHRES_CLIP2, e->wlclip);2565	b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,2566			~B43_NPHY_C2_CLIPWBTHRES_CLIP2, e->wlclip);2567	b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);2568}2569 2570static void b43_nphy_gain_ctl_workarounds_rev1_2(struct b43_wldev *dev)2571{2572	struct b43_phy_n *nphy = dev->phy.n;2573 2574	u8 i, j;2575	u8 code;2576	u16 tmp;2577	u8 rfseq_events[3] = { 6, 8, 7 };2578	u8 rfseq_delays[3] = { 10, 30, 1 };2579 2580	/* Set Clip 2 detect */2581	b43_phy_set(dev, B43_NPHY_C1_CGAINI, B43_NPHY_C1_CGAINI_CL2DETECT);2582	b43_phy_set(dev, B43_NPHY_C2_CGAINI, B43_NPHY_C2_CGAINI_CL2DETECT);2583 2584	/* Set narrowband clip threshold */2585	b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 0x84);2586	b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 0x84);2587 2588	if (!b43_is_40mhz(dev)) {2589		/* Set dwell lengths */2590		b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 0x002B);2591		b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 0x002B);2592		b43_phy_write(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 0x0009);2593		b43_phy_write(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 0x0009);2594	}2595 2596	/* Set wideband clip 2 threshold */2597	b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,2598			~B43_NPHY_C1_CLIPWBTHRES_CLIP2, 21);2599	b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,2600			~B43_NPHY_C2_CLIPWBTHRES_CLIP2, 21);2601 2602	if (!b43_is_40mhz(dev)) {2603		b43_phy_maskset(dev, B43_NPHY_C1_CGAINI,2604			~B43_NPHY_C1_CGAINI_GAINBKOFF, 0x1);2605		b43_phy_maskset(dev, B43_NPHY_C2_CGAINI,2606			~B43_NPHY_C2_CGAINI_GAINBKOFF, 0x1);2607		b43_phy_maskset(dev, B43_NPHY_C1_CCK_CGAINI,2608			~B43_NPHY_C1_CCK_CGAINI_GAINBKOFF, 0x1);2609		b43_phy_maskset(dev, B43_NPHY_C2_CCK_CGAINI,2610			~B43_NPHY_C2_CCK_CGAINI_GAINBKOFF, 0x1);2611	}2612 2613	b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);2614 2615	if (nphy->gain_boost) {2616		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ &&2617		    b43_is_40mhz(dev))2618			code = 4;2619		else2620			code = 5;2621	} else {2622		code = b43_is_40mhz(dev) ? 6 : 7;2623	}2624 2625	/* Set HPVGA2 index */2626	b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN, ~B43_NPHY_C1_INITGAIN_HPVGA2,2627			code << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT);2628	b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN, ~B43_NPHY_C2_INITGAIN_HPVGA2,2629			code << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT);2630 2631	b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);2632	/* specs say about 2 loops, but wl does 4 */2633	for (i = 0; i < 4; i++)2634		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, (code << 8 | 0x7C));2635 2636	b43_nphy_adjust_lna_gain_table(dev);2637 2638	if (nphy->elna_gain_config) {2639		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0808);2640		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0);2641		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);2642		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);2643		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);2644 2645		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0C08);2646		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0);2647		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);2648		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);2649		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);2650 2651		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);2652		/* specs say about 2 loops, but wl does 4 */2653		for (i = 0; i < 4; i++)2654			b43_phy_write(dev, B43_NPHY_TABLE_DATALO,2655						(code << 8 | 0x74));2656	}2657 2658	if (dev->phy.rev == 2) {2659		for (i = 0; i < 4; i++) {2660			b43_phy_write(dev, B43_NPHY_TABLE_ADDR,2661					(0x0400 * i) + 0x0020);2662			for (j = 0; j < 21; j++) {2663				tmp = j * (i < 2 ? 3 : 1);2664				b43_phy_write(dev,2665					B43_NPHY_TABLE_DATALO, tmp);2666			}2667		}2668	}2669 2670	b43_nphy_set_rf_sequence(dev, 5, rfseq_events, rfseq_delays, 3);2671	b43_phy_maskset(dev, B43_NPHY_OVER_DGAIN1,2672		~B43_NPHY_OVER_DGAIN_CCKDGECV & 0xFFFF,2673		0x5A << B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT);2674 2675	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)2676		b43_phy_maskset(dev, B43_PHY_N(0xC5D), 0xFF80, 4);2677}2678 2679/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */2680static void b43_nphy_gain_ctl_workarounds(struct b43_wldev *dev)2681{2682	if (dev->phy.rev >= 19)2683		b43_nphy_gain_ctl_workarounds_rev19(dev);2684	else if (dev->phy.rev >= 7)2685		b43_nphy_gain_ctl_workarounds_rev7(dev);2686	else if (dev->phy.rev >= 3)2687		b43_nphy_gain_ctl_workarounds_rev3(dev);2688	else2689		b43_nphy_gain_ctl_workarounds_rev1_2(dev);2690}2691 2692static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)2693{2694	struct ssb_sprom *sprom = dev->dev->bus_sprom;2695	struct b43_phy *phy = &dev->phy;2696 2697	/* TX to RX */2698	u8 tx2rx_events[7] = { 4, 3, 5, 2, 1, 8, 31, };2699	u8 tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1, };2700	/* RX to TX */2701	u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,2702					0x1F };2703	u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };2704 2705	static const u16 ntab7_15e_16e[] = { 0, 0x10f, 0x10f };2706	u8 ntab7_138_146[] = { 0x11, 0x11 };2707	u8 ntab7_133[] = { 0x77, 0x11, 0x11 };2708 2709	u16 lpf_ofdm_20mhz[2], lpf_ofdm_40mhz[2], lpf_11b[2];2710	u16 bcap_val;2711	s16 bcap_val_11b[2], bcap_val_11n_20[2], bcap_val_11n_40[2];2712	u16 scap_val;2713	s16 scap_val_11b[2], scap_val_11n_20[2], scap_val_11n_40[2];2714	bool rccal_ovrd = false;2715 2716	u16 bias, conv, filt;2717 2718	u32 noise_tbl[2];2719 2720	u32 tmp32;2721	u8 core;2722 2723	b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);2724	b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01b3);2725	b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);2726	b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016e);2727	b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00cd);2728	b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);2729 2730	if (phy->rev == 7) {2731		b43_phy_set(dev, B43_NPHY_FINERX2_CGC, 0x10);2732		b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0xFF80, 0x0020);2733		b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0x80FF, 0x2700);2734		b43_phy_maskset(dev, B43_NPHY_FREQGAIN1, 0xFF80, 0x002E);2735		b43_phy_maskset(dev, B43_NPHY_FREQGAIN1, 0x80FF, 0x3300);2736		b43_phy_maskset(dev, B43_NPHY_FREQGAIN2, 0xFF80, 0x0037);2737		b43_phy_maskset(dev, B43_NPHY_FREQGAIN2, 0x80FF, 0x3A00);2738		b43_phy_maskset(dev, B43_NPHY_FREQGAIN3, 0xFF80, 0x003C);2739		b43_phy_maskset(dev, B43_NPHY_FREQGAIN3, 0x80FF, 0x3E00);2740		b43_phy_maskset(dev, B43_NPHY_FREQGAIN4, 0xFF80, 0x003E);2741		b43_phy_maskset(dev, B43_NPHY_FREQGAIN4, 0x80FF, 0x3F00);2742		b43_phy_maskset(dev, B43_NPHY_FREQGAIN5, 0xFF80, 0x0040);2743		b43_phy_maskset(dev, B43_NPHY_FREQGAIN5, 0x80FF, 0x4000);2744		b43_phy_maskset(dev, B43_NPHY_FREQGAIN6, 0xFF80, 0x0040);2745		b43_phy_maskset(dev, B43_NPHY_FREQGAIN6, 0x80FF, 0x4000);2746		b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0xFF80, 0x0040);2747		b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0x80FF, 0x4000);2748	}2749 2750	if (phy->rev >= 16) {2751		b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x7ff);2752		b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x7ff);2753	} else if (phy->rev <= 8) {2754		b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1B0);2755		b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1B0);2756	}2757 2758	if (phy->rev >= 16)2759		b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0xa0);2760	else if (phy->rev >= 8)2761		b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0x72);2762 2763	b43_ntab_write(dev, B43_NTAB16(8, 0x00), 2);2764	b43_ntab_write(dev, B43_NTAB16(8, 0x10), 2);2765	tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));2766	tmp32 &= 0xffffff;2767	b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);2768	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x15d), 3, ntab7_15e_16e);2769	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16d), 3, ntab7_15e_16e);2770 2771	b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays,2772				 ARRAY_SIZE(tx2rx_events));2773	if (b43_nphy_ipa(dev))2774		b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa,2775				rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa));2776 2777	b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_0, 0x3FFF, 0x4000);2778	b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_1, 0x3FFF, 0x4000);2779 2780	for (core = 0; core < 2; core++) {2781		lpf_ofdm_20mhz[core] = b43_nphy_read_lpf_ctl(dev, 0x154 + core * 0x10);2782		lpf_ofdm_40mhz[core] = b43_nphy_read_lpf_ctl(dev, 0x159 + core * 0x10);2783		lpf_11b[core] = b43_nphy_read_lpf_ctl(dev, 0x152 + core * 0x10);2784	}2785 2786	bcap_val = b43_radio_read(dev, R2057_RCCAL_BCAP_VAL);2787	scap_val = b43_radio_read(dev, R2057_RCCAL_SCAP_VAL);2788 2789	if (b43_nphy_ipa(dev)) {2790		bool ghz2 = b43_current_band(dev->wl) == NL80211_BAND_2GHZ;2791 2792		switch (phy->radio_rev) {2793		case 5:2794			/* Check radio version (to be 0) by PHY rev for now */2795			if (phy->rev == 8 && b43_is_40mhz(dev)) {2796				for (core = 0; core < 2; core++) {2797					scap_val_11b[core] = scap_val;2798					bcap_val_11b[core] = bcap_val;2799					scap_val_11n_20[core] = scap_val;2800					bcap_val_11n_20[core] = bcap_val;2801					scap_val_11n_40[core] = 0xc;2802					bcap_val_11n_40[core] = 0xc;2803				}2804 2805				rccal_ovrd = true;2806			}2807			if (phy->rev == 9) {2808				/* TODO: Radio version 1 (e.g. BCM5357B0) */2809			}2810			break;2811		case 7:2812		case 8:2813			for (core = 0; core < 2; core++) {2814				scap_val_11b[core] = scap_val;2815				bcap_val_11b[core] = bcap_val;2816				lpf_ofdm_20mhz[core] = 4;2817				lpf_11b[core] = 1;2818				if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {2819					scap_val_11n_20[core] = 0xc;2820					bcap_val_11n_20[core] = 0xc;2821					scap_val_11n_40[core] = 0xa;2822					bcap_val_11n_40[core] = 0xa;2823				} else {2824					scap_val_11n_20[core] = 0x14;2825					bcap_val_11n_20[core] = 0x14;2826					scap_val_11n_40[core] = 0xf;2827					bcap_val_11n_40[core] = 0xf;2828				}2829			}2830 2831			rccal_ovrd = true;2832			break;2833		case 9:2834			for (core = 0; core < 2; core++) {2835				bcap_val_11b[core] = bcap_val;2836				scap_val_11b[core] = scap_val;2837				lpf_11b[core] = 1;2838 2839				if (ghz2) {2840					bcap_val_11n_20[core] = bcap_val + 13;2841					scap_val_11n_20[core] = scap_val + 15;2842				} else {2843					bcap_val_11n_20[core] = bcap_val + 14;2844					scap_val_11n_20[core] = scap_val + 15;2845				}2846				lpf_ofdm_20mhz[core] = 4;2847 2848				if (ghz2) {2849					bcap_val_11n_40[core] = bcap_val - 7;2850					scap_val_11n_40[core] = scap_val - 5;2851				} else {2852					bcap_val_11n_40[core] = bcap_val + 2;2853					scap_val_11n_40[core] = scap_val + 4;2854				}2855				lpf_ofdm_40mhz[core] = 4;2856			}2857 2858			rccal_ovrd = true;2859			break;2860		case 14:2861			for (core = 0; core < 2; core++) {2862				bcap_val_11b[core] = bcap_val;2863				scap_val_11b[core] = scap_val;2864				lpf_11b[core] = 1;2865			}2866 2867			bcap_val_11n_20[0] = bcap_val + 20;2868			scap_val_11n_20[0] = scap_val + 20;2869			lpf_ofdm_20mhz[0] = 3;2870 2871			bcap_val_11n_20[1] = bcap_val + 16;2872			scap_val_11n_20[1] = scap_val + 16;2873			lpf_ofdm_20mhz[1] = 3;2874 2875			bcap_val_11n_40[0] = bcap_val + 20;2876			scap_val_11n_40[0] = scap_val + 20;2877			lpf_ofdm_40mhz[0] = 4;2878 2879			bcap_val_11n_40[1] = bcap_val + 10;2880			scap_val_11n_40[1] = scap_val + 10;2881			lpf_ofdm_40mhz[1] = 4;2882 2883			rccal_ovrd = true;2884			break;2885		}2886	} else {2887		if (phy->radio_rev == 5) {2888			for (core = 0; core < 2; core++) {2889				lpf_ofdm_20mhz[core] = 1;2890				lpf_ofdm_40mhz[core] = 3;2891				scap_val_11b[core] = scap_val;2892				bcap_val_11b[core] = bcap_val;2893				scap_val_11n_20[core] = 0x11;2894				scap_val_11n_40[core] = 0x11;2895				bcap_val_11n_20[core] = 0x13;2896				bcap_val_11n_40[core] = 0x13;2897			}2898 2899			rccal_ovrd = true;2900		}2901	}2902	if (rccal_ovrd) {2903		u16 rx2tx_lut_20_11b[2], rx2tx_lut_20_11n[2], rx2tx_lut_40_11n[2];2904		u8 rx2tx_lut_extra = 1;2905 2906		for (core = 0; core < 2; core++) {2907			bcap_val_11b[core] = clamp_val(bcap_val_11b[core], 0, 0x1f);2908			scap_val_11b[core] = clamp_val(scap_val_11b[core], 0, 0x1f);2909			bcap_val_11n_20[core] = clamp_val(bcap_val_11n_20[core], 0, 0x1f);2910			scap_val_11n_20[core] = clamp_val(scap_val_11n_20[core], 0, 0x1f);2911			bcap_val_11n_40[core] = clamp_val(bcap_val_11n_40[core], 0, 0x1f);2912			scap_val_11n_40[core] = clamp_val(scap_val_11n_40[core], 0, 0x1f);2913 2914			rx2tx_lut_20_11b[core] = (rx2tx_lut_extra << 13) |2915						 (bcap_val_11b[core] << 8) |2916						 (scap_val_11b[core] << 3) |2917						 lpf_11b[core];2918			rx2tx_lut_20_11n[core] = (rx2tx_lut_extra << 13) |2919						 (bcap_val_11n_20[core] << 8) |2920						 (scap_val_11n_20[core] << 3) |2921						 lpf_ofdm_20mhz[core];2922			rx2tx_lut_40_11n[core] = (rx2tx_lut_extra << 13) |2923						 (bcap_val_11n_40[core] << 8) |2924						 (scap_val_11n_40[core] << 3) |2925						 lpf_ofdm_40mhz[core];2926		}2927 2928		for (core = 0; core < 2; core++) {2929			b43_ntab_write(dev, B43_NTAB16(7, 0x152 + core * 16),2930				       rx2tx_lut_20_11b[core]);2931			b43_ntab_write(dev, B43_NTAB16(7, 0x153 + core * 16),2932				       rx2tx_lut_20_11n[core]);2933			b43_ntab_write(dev, B43_NTAB16(7, 0x154 + core * 16),2934				       rx2tx_lut_20_11n[core]);2935			b43_ntab_write(dev, B43_NTAB16(7, 0x155 + core * 16),2936				       rx2tx_lut_40_11n[core]);2937			b43_ntab_write(dev, B43_NTAB16(7, 0x156 + core * 16),2938				       rx2tx_lut_40_11n[core]);2939			b43_ntab_write(dev, B43_NTAB16(7, 0x157 + core * 16),2940				       rx2tx_lut_40_11n[core]);2941			b43_ntab_write(dev, B43_NTAB16(7, 0x158 + core * 16),2942				       rx2tx_lut_40_11n[core]);2943			b43_ntab_write(dev, B43_NTAB16(7, 0x159 + core * 16),2944				       rx2tx_lut_40_11n[core]);2945		}2946	}2947 2948	b43_phy_write(dev, 0x32F, 0x3);2949 2950	if (phy->radio_rev == 4 || phy->radio_rev == 6)2951		b43_nphy_rf_ctl_override_rev7(dev, 4, 1, 3, false, 0);2952 2953	if (phy->radio_rev == 3 || phy->radio_rev == 4 || phy->radio_rev == 6) {2954		if (sprom->revision &&2955		    sprom->boardflags2_hi & B43_BFH2_IPALVLSHIFT_3P3) {2956			b43_radio_write(dev, 0x5, 0x05);2957			b43_radio_write(dev, 0x6, 0x30);2958			b43_radio_write(dev, 0x7, 0x00);2959			b43_radio_set(dev, 0x4f, 0x1);2960			b43_radio_set(dev, 0xd4, 0x1);2961			bias = 0x1f;2962			conv = 0x6f;2963			filt = 0xaa;2964		} else {2965			bias = 0x2b;2966			conv = 0x7f;2967			filt = 0xee;2968		}2969		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {2970			for (core = 0; core < 2; core++) {2971				if (core == 0) {2972					b43_radio_write(dev, 0x5F, bias);2973					b43_radio_write(dev, 0x64, conv);2974					b43_radio_write(dev, 0x66, filt);2975				} else {2976					b43_radio_write(dev, 0xE8, bias);2977					b43_radio_write(dev, 0xE9, conv);2978					b43_radio_write(dev, 0xEB, filt);2979				}2980			}2981		}2982	}2983 2984	if (b43_nphy_ipa(dev)) {2985		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {2986			if (phy->radio_rev == 3 || phy->radio_rev == 4 ||2987			    phy->radio_rev == 6) {2988				for (core = 0; core < 2; core++) {2989					if (core == 0)2990						b43_radio_write(dev, 0x51,2991								0x7f);2992					else2993						b43_radio_write(dev, 0xd6,2994								0x7f);2995				}2996			}2997			switch (phy->radio_rev) {2998			case 3:2999				for (core = 0; core < 2; core++) {3000					if (core == 0) {3001						b43_radio_write(dev, 0x64,3002								0x13);3003						b43_radio_write(dev, 0x5F,3004								0x1F);3005						b43_radio_write(dev, 0x66,3006								0xEE);3007						b43_radio_write(dev, 0x59,3008								0x8A);3009						b43_radio_write(dev, 0x80,3010								0x3E);3011					} else {3012						b43_radio_write(dev, 0x69,3013								0x13);3014						b43_radio_write(dev, 0xE8,3015								0x1F);3016						b43_radio_write(dev, 0xEB,3017								0xEE);3018						b43_radio_write(dev, 0xDE,3019								0x8A);3020						b43_radio_write(dev, 0x105,3021								0x3E);3022					}3023				}3024				break;3025			case 7:3026			case 8:3027				if (!b43_is_40mhz(dev)) {3028					b43_radio_write(dev, 0x5F, 0x14);3029					b43_radio_write(dev, 0xE8, 0x12);3030				} else {3031					b43_radio_write(dev, 0x5F, 0x16);3032					b43_radio_write(dev, 0xE8, 0x16);3033				}3034				break;3035			case 14:3036				for (core = 0; core < 2; core++) {3037					int o = core ? 0x85 : 0;3038 3039					b43_radio_write(dev, o + R2057_IPA2G_CASCONV_CORE0, 0x13);3040					b43_radio_write(dev, o + R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, 0x21);3041					b43_radio_write(dev, o + R2057_IPA2G_BIAS_FILTER_CORE0, 0xff);3042					b43_radio_write(dev, o + R2057_PAD2G_IDACS_CORE0, 0x88);3043					b43_radio_write(dev, o + R2057_PAD2G_TUNE_PUS_CORE0, 0x23);3044					b43_radio_write(dev, o + R2057_IPA2G_IMAIN_CORE0, 0x16);3045					b43_radio_write(dev, o + R2057_PAD_BIAS_FILTER_BWS_CORE0, 0x3e);3046					b43_radio_write(dev, o + R2057_BACKUP1_CORE0, 0x10);3047				}3048				break;3049			}3050		} else {3051			u16 freq = phy->chandef->chan->center_freq;3052			if ((freq >= 5180 && freq <= 5230) ||3053			    (freq >= 5745 && freq <= 5805)) {3054				b43_radio_write(dev, 0x7D, 0xFF);3055				b43_radio_write(dev, 0xFE, 0xFF);3056			}3057		}3058	} else {3059		if (phy->radio_rev != 5) {3060			for (core = 0; core < 2; core++) {3061				if (core == 0) {3062					b43_radio_write(dev, 0x5c, 0x61);3063					b43_radio_write(dev, 0x51, 0x70);3064				} else {3065					b43_radio_write(dev, 0xe1, 0x61);3066					b43_radio_write(dev, 0xd6, 0x70);3067				}3068			}3069		}3070	}3071 3072	if (phy->radio_rev == 4) {3073		b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0x20);3074		b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0x20);3075		for (core = 0; core < 2; core++) {3076			if (core == 0) {3077				b43_radio_write(dev, 0x1a1, 0x00);3078				b43_radio_write(dev, 0x1a2, 0x3f);3079				b43_radio_write(dev, 0x1a6, 0x3f);3080			} else {3081				b43_radio_write(dev, 0x1a7, 0x00);3082				b43_radio_write(dev, 0x1ab, 0x3f);3083				b43_radio_write(dev, 0x1ac, 0x3f);3084			}3085		}3086	} else {3087		b43_phy_set(dev, B43_NPHY_AFECTL_C1, 0x4);3088		b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x4);3089		b43_phy_set(dev, B43_NPHY_AFECTL_C2, 0x4);3090		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4);3091 3092		b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x1);3093		b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x1);3094		b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x1);3095		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x1);3096		b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0);3097		b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0);3098 3099		b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x4);3100		b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x4);3101		b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x4);3102		b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4);3103	}3104 3105	b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, 0x2);3106 3107	b43_ntab_write(dev, B43_NTAB32(16, 0x100), 20);3108	b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x138), 2, ntab7_138_146);3109	b43_ntab_write(dev, B43_NTAB16(7, 0x141), 0x77);3110	b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x133), 3, ntab7_133);3111	b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x146), 2, ntab7_138_146);3112	b43_ntab_write(dev, B43_NTAB16(7, 0x123), 0x77);3113	b43_ntab_write(dev, B43_NTAB16(7, 0x12A), 0x77);3114 3115	b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x02), 1, noise_tbl);3116	noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D;3117	b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x02), 2, noise_tbl);3118 3119	b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x7E), 1, noise_tbl);3120	noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D;3121	b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x7E), 2, noise_tbl);3122 3123	b43_nphy_gain_ctl_workarounds(dev);3124 3125	/* TODO3126	b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4,3127			    aux_adc_vmid_rev7_core0);3128	b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4,3129			    aux_adc_vmid_rev7_core1);3130	b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0C), 4,3131			    aux_adc_gain_rev7);3132	b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1C), 4,3133			    aux_adc_gain_rev7);3134	*/3135}3136 3137static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)3138{3139	struct b43_phy_n *nphy = dev->phy.n;3140	struct ssb_sprom *sprom = dev->dev->bus_sprom;3141 3142	/* TX to RX */3143	u8 tx2rx_events[7] = { 0x4, 0x3, 0x5, 0x2, 0x1, 0x8, 0x1F };3144	u8 tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1 };3145	/* RX to TX */3146	u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,3147					0x1F };3148	u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };3149	u8 rx2tx_events[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0x3, 0x4, 0x1F };3150	u8 rx2tx_delays[9] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 };3151 3152	u16 vmids[5][4] = {3153		{ 0xa2, 0xb4, 0xb4, 0x89, }, /* 0 */3154		{ 0xb4, 0xb4, 0xb4, 0x24, }, /* 1 */3155		{ 0xa2, 0xb4, 0xb4, 0x74, }, /* 2 */3156		{ 0xa2, 0xb4, 0xb4, 0x270, }, /* 3 */3157		{ 0xa2, 0xb4, 0xb4, 0x00, }, /* 4 and 5 */3158	};3159	u16 gains[5][4] = {3160		{ 0x02, 0x02, 0x02, 0x00, }, /* 0 */3161		{ 0x02, 0x02, 0x02, 0x02, }, /* 1 */3162		{ 0x02, 0x02, 0x02, 0x04, }, /* 2 */3163		{ 0x02, 0x02, 0x02, 0x00, }, /* 3 */3164		{ 0x02, 0x02, 0x02, 0x00, }, /* 4 and 5 */3165	};3166	u16 *vmid, *gain;3167 3168	u8 pdet_range;3169	u16 tmp16;3170	u32 tmp32;3171 3172	b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1f8);3173	b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1f8);3174 3175	tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));3176	tmp32 &= 0xffffff;3177	b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);3178 3179	b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);3180	b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01B3);3181	b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);3182	b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016E);3183	b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00CD);3184	b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);3185 3186	b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_LOGAIN_B, 0x000C);3187	b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_LOGAIN_B, 0x000C);3188 3189	/* TX to RX */3190	b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays,3191				 ARRAY_SIZE(tx2rx_events));3192 3193	/* RX to TX */3194	if (b43_nphy_ipa(dev))3195		b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa,3196				rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa));3197	if (nphy->hw_phyrxchain != 3 &&3198	    nphy->hw_phyrxchain != nphy->hw_phytxchain) {3199		if (b43_nphy_ipa(dev)) {3200			rx2tx_delays[5] = 59;3201			rx2tx_delays[6] = 1;3202			rx2tx_events[7] = 0x1F;3203		}3204		b43_nphy_set_rf_sequence(dev, 0, rx2tx_events, rx2tx_delays,3205					 ARRAY_SIZE(rx2tx_events));3206	}3207 3208	tmp16 = (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) ?3209		0x2 : 0x9C40;3210	b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16);3211 3212	b43_phy_maskset(dev, B43_NPHY_SGILTRNOFFSET, 0xF0FF, 0x0700);3213 3214	if (!b43_is_40mhz(dev)) {3215		b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);3216		b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);3217	} else {3218		b43_ntab_write(dev, B43_NTAB32(16, 3), 0x14D);3219		b43_ntab_write(dev, B43_NTAB32(16, 127), 0x14D);3220	}3221 3222	b43_nphy_gain_ctl_workarounds(dev);3223 3224	b43_ntab_write(dev, B43_NTAB16(8, 0), 2);3225	b43_ntab_write(dev, B43_NTAB16(8, 16), 2);3226 3227	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)3228		pdet_range = sprom->fem.ghz2.pdet_range;3229	else3230		pdet_range = sprom->fem.ghz5.pdet_range;3231	vmid = vmids[min_t(u16, pdet_range, 4)];3232	gain = gains[min_t(u16, pdet_range, 4)];3233	switch (pdet_range) {3234	case 3:3235		if (!(dev->phy.rev >= 4 &&3236		      b43_current_band(dev->wl) == NL80211_BAND_2GHZ))3237			break;3238		fallthrough;3239	case 0:3240	case 1:3241		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4, vmid);3242		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4, vmid);3243		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0c), 4, gain);3244		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1c), 4, gain);3245		break;3246	case 2:3247		if (dev->phy.rev >= 6) {3248			if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)3249				vmid[3] = 0x94;3250			else3251				vmid[3] = 0x8e;3252			gain[3] = 3;3253		} else if (dev->phy.rev == 5) {3254			vmid[3] = 0x84;3255			gain[3] = 2;3256		}3257		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4, vmid);3258		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4, vmid);3259		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0c), 4, gain);3260		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1c), 4, gain);3261		break;3262	case 4:3263	case 5:3264		if (b43_current_band(dev->wl) != NL80211_BAND_2GHZ) {3265			if (pdet_range == 4) {3266				vmid[3] = 0x8e;3267				tmp16 = 0x96;3268				gain[3] = 0x2;3269			} else {3270				vmid[3] = 0x89;3271				tmp16 = 0x89;3272				gain[3] = 0;3273			}3274		} else {3275			if (pdet_range == 4) {3276				vmid[3] = 0x89;3277				tmp16 = 0x8b;3278				gain[3] = 0x2;3279			} else {3280				vmid[3] = 0x74;3281				tmp16 = 0x70;3282				gain[3] = 0;3283			}3284		}3285		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4, vmid);3286		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0c), 4, gain);3287		vmid[3] = tmp16;3288		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4, vmid);3289		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1c), 4, gain);3290		break;3291	}3292 3293	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_MAST_BIAS, 0x00);3294	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_MAST_BIAS, 0x00);3295	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN, 0x06);3296	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN, 0x06);3297	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_AUX, 0x07);3298	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07);3299	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88);3300	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88);3301	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_CMFB_IDAC, 0x00);3302	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_CMFB_IDAC, 0x00);3303	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00);3304	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00);3305 3306	/* N PHY WAR TX Chain Update with hw_phytxchain as argument */3307 3308	if ((sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&3309	     b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ||3310	    (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&3311	     b43_current_band(dev->wl) == NL80211_BAND_2GHZ))3312		tmp32 = 0x00088888;3313	else3314		tmp32 = 0x88888888;3315	b43_ntab_write(dev, B43_NTAB32(30, 1), tmp32);3316	b43_ntab_write(dev, B43_NTAB32(30, 2), tmp32);3317	b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32);3318 3319	if (dev->phy.rev == 4 &&3320	    b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {3321		b43_radio_write(dev, B2056_TX0 | B2056_TX_GMBB_IDAC,3322				0x70);3323		b43_radio_write(dev, B2056_TX1 | B2056_TX_GMBB_IDAC,3324				0x70);3325	}3326 3327	/* Dropped probably-always-true condition */3328	b43_phy_write(dev, B43_NPHY_ED_CRS40ASSERTTHRESH0, 0x03eb);3329	b43_phy_write(dev, B43_NPHY_ED_CRS40ASSERTTHRESH1, 0x03eb);3330	b43_phy_write(dev, B43_NPHY_ED_CRS40DEASSERTTHRESH0, 0x0341);3331	b43_phy_write(dev, B43_NPHY_ED_CRS40DEASSERTTHRESH1, 0x0341);3332	b43_phy_write(dev, B43_NPHY_ED_CRS20LASSERTTHRESH0, 0x042b);3333	b43_phy_write(dev, B43_NPHY_ED_CRS20LASSERTTHRESH1, 0x042b);3334	b43_phy_write(dev, B43_NPHY_ED_CRS20LDEASSERTTHRESH0, 0x0381);3335	b43_phy_write(dev, B43_NPHY_ED_CRS20LDEASSERTTHRESH1, 0x0381);3336	b43_phy_write(dev, B43_NPHY_ED_CRS20UASSERTTHRESH0, 0x042b);3337	b43_phy_write(dev, B43_NPHY_ED_CRS20UASSERTTHRESH1, 0x042b);3338	b43_phy_write(dev, B43_NPHY_ED_CRS20UDEASSERTTHRESH0, 0x0381);3339	b43_phy_write(dev, B43_NPHY_ED_CRS20UDEASSERTTHRESH1, 0x0381);3340 3341	if (dev->phy.rev >= 6 && sprom->boardflags2_lo & B43_BFL2_SINGLEANT_CCK) {3342		; /* TODO: 0x0080000000000000 HF */3343	}3344}3345 3346static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)3347{3348	struct ssb_sprom *sprom = dev->dev->bus_sprom;3349	struct b43_phy *phy = &dev->phy;3350	struct b43_phy_n *nphy = phy->n;3351 3352	u8 events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 };3353	u8 delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 };3354 3355	u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 };3356	u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };3357 3358	if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD ||3359	    dev->dev->board_type == BCMA_BOARD_TYPE_BCM943224M93) {3360		delays1[0] = 0x1;3361		delays1[5] = 0x14;3362	}3363 3364	if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ &&3365	    nphy->band5g_pwrgain) {3366		b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8);3367		b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8);3368	} else {3369		b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8);3370		b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8);3371	}3372 3373	b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A);3374	b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A);3375	if (dev->phy.rev < 3) {3376		b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);3377		b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);3378	}3379 3380	if (dev->phy.rev < 2) {3381		b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000);3382		b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0x0000);3383		b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB);3384		b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB);3385		b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x0800);3386		b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x0800);3387	}3388 3389	b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);3390	b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);3391	b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);3392	b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);3393 3394	b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);3395	b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);3396 3397	b43_nphy_gain_ctl_workarounds(dev);3398 3399	if (dev->phy.rev < 2) {3400		if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2)3401			b43_hf_write(dev, b43_hf_read(dev) |3402					B43_HF_MLADVW);3403	} else if (dev->phy.rev == 2) {3404		b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0);3405		b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0);3406	}3407 3408	if (dev->phy.rev < 2)3409		b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL,3410				~B43_NPHY_SCRAM_SIGCTL_SCM);3411 3412	/* Set phase track alpha and beta */3413	b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125);3414	b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3);3415	b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105);3416	b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E);3417	b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);3418	b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);3419 3420	if (dev->phy.rev < 3) {3421		b43_phy_mask(dev, B43_NPHY_PIL_DW1,3422			     ~B43_NPHY_PIL_DW_64QAM & 0xFFFF);3423		b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5);3424		b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4);3425		b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00);3426	}3427 3428	if (dev->phy.rev == 2)3429		b43_phy_set(dev, B43_NPHY_FINERX2_CGC,3430				B43_NPHY_FINERX2_CGC_DECGC);3431}3432 3433/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */3434static void b43_nphy_workarounds(struct b43_wldev *dev)3435{3436	struct b43_phy *phy = &dev->phy;3437	struct b43_phy_n *nphy = phy->n;3438 3439	if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)3440		b43_nphy_classifier(dev, 1, 0);3441	else3442		b43_nphy_classifier(dev, 1, 1);3443 3444	if (nphy->hang_avoid)3445		b43_nphy_stay_in_carrier_search(dev, 1);3446 3447	b43_phy_set(dev, B43_NPHY_IQFLIP,3448		    B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);3449 3450	/* TODO: rev19+ */3451	if (dev->phy.rev >= 7)3452		b43_nphy_workarounds_rev7plus(dev);3453	else if (dev->phy.rev >= 3)3454		b43_nphy_workarounds_rev3plus(dev);3455	else3456		b43_nphy_workarounds_rev1_2(dev);3457 3458	if (nphy->hang_avoid)3459		b43_nphy_stay_in_carrier_search(dev, 0);3460}3461 3462/**************************************************3463 * Tx/Rx common3464 **************************************************/3465 3466/*3467 * Transmits a known value for LO calibration3468 * https://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone3469 */3470static int b43_nphy_tx_tone(struct b43_wldev *dev, u32 freq, u16 max_val,3471			    bool iqmode, bool dac_test, bool modify_bbmult)3472{3473	u16 samp = b43_nphy_gen_load_samples(dev, freq, max_val, dac_test);3474	if (samp == 0)3475		return -1;3476	b43_nphy_run_samples(dev, samp, 0xFFFF, 0, iqmode, dac_test,3477			     modify_bbmult);3478	return 0;3479}3480 3481/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */3482static void b43_nphy_update_txrx_chain(struct b43_wldev *dev)3483{3484	struct b43_phy_n *nphy = dev->phy.n;3485 3486	bool override = false;3487	u16 chain = 0x33;3488 3489	if (nphy->txrx_chain == 0) {3490		chain = 0x11;3491		override = true;3492	} else if (nphy->txrx_chain == 1) {3493		chain = 0x22;3494		override = true;3495	}3496 3497	b43_phy_maskset(dev, B43_NPHY_RFSEQCA,3498			~(B43_NPHY_RFSEQCA_TXEN | B43_NPHY_RFSEQCA_RXEN),3499			chain);3500 3501	if (override)3502		b43_phy_set(dev, B43_NPHY_RFSEQMODE,3503				B43_NPHY_RFSEQMODE_CAOVER);3504	else3505		b43_phy_mask(dev, B43_NPHY_RFSEQMODE,3506				~B43_NPHY_RFSEQMODE_CAOVER);3507}3508 3509/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */3510static void b43_nphy_stop_playback(struct b43_wldev *dev)3511{3512	struct b43_phy *phy = &dev->phy;3513	struct b43_phy_n *nphy = dev->phy.n;3514	u16 tmp;3515 3516	if (nphy->hang_avoid)3517		b43_nphy_stay_in_carrier_search(dev, 1);3518 3519	tmp = b43_phy_read(dev, B43_NPHY_SAMP_STAT);3520	if (tmp & 0x1)3521		b43_phy_set(dev, B43_NPHY_SAMP_CMD, B43_NPHY_SAMP_CMD_STOP);3522	else if (tmp & 0x2)3523		b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);3524 3525	b43_phy_mask(dev, B43_NPHY_SAMP_CMD, ~0x0004);3526 3527	if (nphy->bb_mult_save & 0x80000000) {3528		tmp = nphy->bb_mult_save & 0xFFFF;3529		b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);3530		nphy->bb_mult_save = 0;3531	}3532 3533	if (phy->rev >= 7 && nphy->lpf_bw_overrode_for_sample_play) {3534		if (phy->rev >= 19)3535			b43_nphy_rf_ctl_override_rev19(dev, 0x80, 0, 0, true,3536						       1);3537		else3538			b43_nphy_rf_ctl_override_rev7(dev, 0x80, 0, 0, true, 1);3539		nphy->lpf_bw_overrode_for_sample_play = false;3540	}3541 3542	if (nphy->hang_avoid)3543		b43_nphy_stay_in_carrier_search(dev, 0);3544}3545 3546/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/IqCalGainParams */3547static void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core,3548					struct nphy_txgains target,3549					struct nphy_iqcal_params *params)3550{3551	struct b43_phy *phy = &dev->phy;3552	int i, j, indx;3553	u16 gain;3554 3555	if (dev->phy.rev >= 3) {3556		params->tx_lpf = target.tx_lpf[core]; /* Rev 7+ */3557		params->txgm = target.txgm[core];3558		params->pga = target.pga[core];3559		params->pad = target.pad[core];3560		params->ipa = target.ipa[core];3561		if (phy->rev >= 19) {3562			/* TODO */3563		} else if (phy->rev >= 7) {3564			params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 3) | (params->ipa) | (params->tx_lpf << 15);3565		} else {3566			params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 4) | (params->ipa);3567		}3568		for (j = 0; j < 5; j++)3569			params->ncorr[j] = 0x79;3570	} else {3571		gain = (target.pad[core]) | (target.pga[core] << 4) |3572			(target.txgm[core] << 8);3573 3574		indx = (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ?3575			1 : 0;3576		for (i = 0; i < 9; i++)3577			if (tbl_iqcal_gainparams[indx][i][0] == gain)3578				break;3579		i = min(i, 8);3580 3581		params->txgm = tbl_iqcal_gainparams[indx][i][1];3582		params->pga = tbl_iqcal_gainparams[indx][i][2];3583		params->pad = tbl_iqcal_gainparams[indx][i][3];3584		params->cal_gain = (params->txgm << 7) | (params->pga << 4) |3585					(params->pad << 2);3586		for (j = 0; j < 4; j++)3587			params->ncorr[j] = tbl_iqcal_gainparams[indx][i][4 + j];3588	}3589}3590 3591/**************************************************3592 * Tx and Rx3593 **************************************************/3594 3595/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */3596static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)3597{3598	struct b43_phy *phy = &dev->phy;3599	struct b43_phy_n *nphy = dev->phy.n;3600	u8 i;3601	u16 bmask, val, tmp;3602	enum nl80211_band band = b43_current_band(dev->wl);3603 3604	if (nphy->hang_avoid)3605		b43_nphy_stay_in_carrier_search(dev, 1);3606 3607	nphy->txpwrctrl = enable;3608	if (!enable) {3609		if (dev->phy.rev >= 3 &&3610		    (b43_phy_read(dev, B43_NPHY_TXPCTL_CMD) &3611		     (B43_NPHY_TXPCTL_CMD_COEFF |3612		      B43_NPHY_TXPCTL_CMD_HWPCTLEN |3613		      B43_NPHY_TXPCTL_CMD_PCTLEN))) {3614			/* We disable enabled TX pwr ctl, save it's state */3615			nphy->tx_pwr_idx[0] = b43_phy_read(dev,3616						B43_NPHY_C1_TXPCTL_STAT) & 0x7f;3617			nphy->tx_pwr_idx[1] = b43_phy_read(dev,3618						B43_NPHY_C2_TXPCTL_STAT) & 0x7f;3619		}3620 3621		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6840);3622		for (i = 0; i < 84; i++)3623			b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0);3624 3625		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6C40);3626		for (i = 0; i < 84; i++)3627			b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0);3628 3629		tmp = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN;3630		if (dev->phy.rev >= 3)3631			tmp |= B43_NPHY_TXPCTL_CMD_PCTLEN;3632		b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD, ~tmp);3633 3634		if (dev->phy.rev >= 3) {3635			b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100);3636			b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100);3637		} else {3638			b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000);3639		}3640 3641		if (dev->phy.rev == 2)3642			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,3643				~B43_NPHY_BPHY_CTL3_SCALE, 0x53);3644		else if (dev->phy.rev < 2)3645			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,3646				~B43_NPHY_BPHY_CTL3_SCALE, 0x5A);3647 3648		if (dev->phy.rev < 2 && b43_is_40mhz(dev))3649			b43_hf_write(dev, b43_hf_read(dev) | B43_HF_TSSIRPSMW);3650	} else {3651		b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84,3652				    nphy->adj_pwr_tbl);3653		b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84,3654				    nphy->adj_pwr_tbl);3655 3656		bmask = B43_NPHY_TXPCTL_CMD_COEFF |3657			B43_NPHY_TXPCTL_CMD_HWPCTLEN;3658		/* wl does useless check for "enable" param here */3659		val = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN;3660		if (dev->phy.rev >= 3) {3661			bmask |= B43_NPHY_TXPCTL_CMD_PCTLEN;3662			if (val)3663				val |= B43_NPHY_TXPCTL_CMD_PCTLEN;3664		}3665		b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, ~(bmask), val);3666 3667		if (band == NL80211_BAND_5GHZ) {3668			if (phy->rev >= 19) {3669				/* TODO */3670			} else if (phy->rev >= 7) {3671				b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,3672						~B43_NPHY_TXPCTL_CMD_INIT,3673						0x32);3674				b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,3675						~B43_NPHY_TXPCTL_INIT_PIDXI1,3676						0x32);3677			} else {3678				b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,3679						~B43_NPHY_TXPCTL_CMD_INIT,3680						0x64);3681				if (phy->rev > 1)3682					b43_phy_maskset(dev,3683							B43_NPHY_TXPCTL_INIT,3684							~B43_NPHY_TXPCTL_INIT_PIDXI1,3685							0x64);3686			}3687		}3688 3689		if (dev->phy.rev >= 3) {3690			if (nphy->tx_pwr_idx[0] != 128 &&3691			    nphy->tx_pwr_idx[1] != 128) {3692				/* Recover TX pwr ctl state */3693				b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,3694						~B43_NPHY_TXPCTL_CMD_INIT,3695						nphy->tx_pwr_idx[0]);3696				if (dev->phy.rev > 1)3697					b43_phy_maskset(dev,3698						B43_NPHY_TXPCTL_INIT,3699						~0xff, nphy->tx_pwr_idx[1]);3700			}3701		}3702 3703		if (phy->rev >= 7) {3704			/* TODO */3705		}3706 3707		if (dev->phy.rev >= 3) {3708			b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x100);3709			b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x100);3710		} else {3711			b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4000);3712		}3713 3714		if (dev->phy.rev == 2)3715			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x3b);3716		else if (dev->phy.rev < 2)3717			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x40);3718 3719		if (dev->phy.rev < 2 && b43_is_40mhz(dev))3720			b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_TSSIRPSMW);3721 3722		if (b43_nphy_ipa(dev)) {3723			b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x4);3724			b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x4);3725		}3726	}3727 3728	if (nphy->hang_avoid)3729		b43_nphy_stay_in_carrier_search(dev, 0);3730}3731 3732/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrFix */3733static void b43_nphy_tx_power_fix(struct b43_wldev *dev)3734{3735	struct b43_phy *phy = &dev->phy;3736	struct b43_phy_n *nphy = dev->phy.n;3737	struct ssb_sprom *sprom = dev->dev->bus_sprom;3738 3739	u8 txpi[2], bbmult, i;3740	u16 tmp, radio_gain, dac_gain;3741	u16 freq = phy->chandef->chan->center_freq;3742	u32 txgain;3743	/* u32 gaintbl; rev3+ */3744 3745	if (nphy->hang_avoid)3746		b43_nphy_stay_in_carrier_search(dev, 1);3747 3748	/* TODO: rev19+ */3749	if (dev->phy.rev >= 7) {3750		txpi[0] = txpi[1] = 30;3751	} else if (dev->phy.rev >= 3) {3752		txpi[0] = 40;3753		txpi[1] = 40;3754	} else if (sprom->revision < 4) {3755		txpi[0] = 72;3756		txpi[1] = 72;3757	} else {3758		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {3759			txpi[0] = sprom->txpid2g[0];3760			txpi[1] = sprom->txpid2g[1];3761		} else if (freq >= 4900 && freq < 5100) {3762			txpi[0] = sprom->txpid5gl[0];3763			txpi[1] = sprom->txpid5gl[1];3764		} else if (freq >= 5100 && freq < 5500) {3765			txpi[0] = sprom->txpid5g[0];3766			txpi[1] = sprom->txpid5g[1];3767		} else if (freq >= 5500) {3768			txpi[0] = sprom->txpid5gh[0];3769			txpi[1] = sprom->txpid5gh[1];3770		} else {3771			txpi[0] = 91;3772			txpi[1] = 91;3773		}3774	}3775	if (dev->phy.rev < 7 &&3776	    (txpi[0] < 40 || txpi[0] > 100 || txpi[1] < 40 || txpi[1] > 100))3777		txpi[0] = txpi[1] = 91;3778 3779	/*3780	for (i = 0; i < 2; i++) {3781		nphy->txpwrindex[i].index_internal = txpi[i];3782		nphy->txpwrindex[i].index_internal_save = txpi[i];3783	}3784	*/3785 3786	for (i = 0; i < 2; i++) {3787		const u32 *table = b43_nphy_get_tx_gain_table(dev);3788 3789		if (!table)3790			break;3791		txgain = *(table + txpi[i]);3792 3793		if (dev->phy.rev >= 3)3794			radio_gain = (txgain >> 16) & 0x1FFFF;3795		else3796			radio_gain = (txgain >> 16) & 0x1FFF;3797 3798		if (dev->phy.rev >= 7)3799			dac_gain = (txgain >> 8) & 0x7;3800		else3801			dac_gain = (txgain >> 8) & 0x3F;3802		bbmult = txgain & 0xFF;3803 3804		if (dev->phy.rev >= 3) {3805			if (i == 0)3806				b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100);3807			else3808				b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100);3809		} else {3810			b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000);3811		}3812 3813		if (i == 0)3814			b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN1, dac_gain);3815		else3816			b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN2, dac_gain);3817 3818		b43_ntab_write(dev, B43_NTAB16(0x7, 0x110 + i), radio_gain);3819 3820		tmp = b43_ntab_read(dev, B43_NTAB16(0xF, 0x57));3821		if (i == 0)3822			tmp = (tmp & 0x00FF) | (bbmult << 8);3823		else3824			tmp = (tmp & 0xFF00) | bbmult;3825		b43_ntab_write(dev, B43_NTAB16(0xF, 0x57), tmp);3826 3827		if (b43_nphy_ipa(dev)) {3828			u32 tmp32;3829			u16 reg = (i == 0) ?3830				B43_NPHY_PAPD_EN0 : B43_NPHY_PAPD_EN1;3831			tmp32 = b43_ntab_read(dev, B43_NTAB32(26 + i,3832							      576 + txpi[i]));3833			b43_phy_maskset(dev, reg, 0xE00F, (u32) tmp32 << 4);3834			b43_phy_set(dev, reg, 0x4);3835		}3836	}3837 3838	b43_phy_mask(dev, B43_NPHY_BPHY_CTL2, ~B43_NPHY_BPHY_CTL2_LUT);3839 3840	if (nphy->hang_avoid)3841		b43_nphy_stay_in_carrier_search(dev, 0);3842}3843 3844static void b43_nphy_ipa_internal_tssi_setup(struct b43_wldev *dev)3845{3846	struct b43_phy *phy = &dev->phy;3847 3848	u8 core;3849	u16 r; /* routing */3850 3851	if (phy->rev >= 19) {3852		/* TODO */3853	} else if (phy->rev >= 7) {3854		for (core = 0; core < 2; core++) {3855			r = core ? 0x190 : 0x170;3856			if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {3857				b43_radio_write(dev, r + 0x5, 0x5);3858				b43_radio_write(dev, r + 0x9, 0xE);3859				if (phy->rev != 5)3860					b43_radio_write(dev, r + 0xA, 0);3861				if (phy->rev != 7)3862					b43_radio_write(dev, r + 0xB, 1);3863				else3864					b43_radio_write(dev, r + 0xB, 0x31);3865			} else {3866				b43_radio_write(dev, r + 0x5, 0x9);3867				b43_radio_write(dev, r + 0x9, 0xC);3868				b43_radio_write(dev, r + 0xB, 0x0);3869				if (phy->rev != 5)3870					b43_radio_write(dev, r + 0xA, 1);3871				else3872					b43_radio_write(dev, r + 0xA, 0x31);3873			}3874			b43_radio_write(dev, r + 0x6, 0);3875			b43_radio_write(dev, r + 0x7, 0);3876			b43_radio_write(dev, r + 0x8, 3);3877			b43_radio_write(dev, r + 0xC, 0);3878		}3879	} else {3880		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)3881			b43_radio_write(dev, B2056_SYN_RESERVED_ADDR31, 0x128);3882		else3883			b43_radio_write(dev, B2056_SYN_RESERVED_ADDR31, 0x80);3884		b43_radio_write(dev, B2056_SYN_RESERVED_ADDR30, 0);3885		b43_radio_write(dev, B2056_SYN_GPIO_MASTER1, 0x29);3886 3887		for (core = 0; core < 2; core++) {3888			r = core ? B2056_TX1 : B2056_TX0;3889 3890			b43_radio_write(dev, r | B2056_TX_IQCAL_VCM_HG, 0);3891			b43_radio_write(dev, r | B2056_TX_IQCAL_IDAC, 0);3892			b43_radio_write(dev, r | B2056_TX_TSSI_VCM, 3);3893			b43_radio_write(dev, r | B2056_TX_TX_AMP_DET, 0);3894			b43_radio_write(dev, r | B2056_TX_TSSI_MISC1, 8);3895			b43_radio_write(dev, r | B2056_TX_TSSI_MISC2, 0);3896			b43_radio_write(dev, r | B2056_TX_TSSI_MISC3, 0);3897			if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {3898				b43_radio_write(dev, r | B2056_TX_TX_SSI_MASTER,3899						0x5);3900				if (phy->rev != 5)3901					b43_radio_write(dev, r | B2056_TX_TSSIA,3902							0x00);3903				if (phy->rev >= 5)3904					b43_radio_write(dev, r | B2056_TX_TSSIG,3905							0x31);3906				else3907					b43_radio_write(dev, r | B2056_TX_TSSIG,3908							0x11);3909				b43_radio_write(dev, r | B2056_TX_TX_SSI_MUX,3910						0xE);3911			} else {3912				b43_radio_write(dev, r | B2056_TX_TX_SSI_MASTER,3913						0x9);3914				b43_radio_write(dev, r | B2056_TX_TSSIA, 0x31);3915				b43_radio_write(dev, r | B2056_TX_TSSIG, 0x0);3916				b43_radio_write(dev, r | B2056_TX_TX_SSI_MUX,3917						0xC);3918			}3919		}3920	}3921}3922 3923/*3924 * Stop radio and transmit known signal. Then check received signal strength to3925 * get TSSI (Transmit Signal Strength Indicator).3926 * https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlIdleTssi3927 */3928static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev)3929{3930	struct b43_phy *phy = &dev->phy;3931	struct b43_phy_n *nphy = dev->phy.n;3932 3933	u32 tmp;3934	s32 rssi[4] = { };3935 3936	if (phy->chandef->chan->flags & IEEE80211_CHAN_NO_IR)3937		return;3938 3939	if (b43_nphy_ipa(dev))3940		b43_nphy_ipa_internal_tssi_setup(dev);3941 3942	if (phy->rev >= 19)3943		b43_nphy_rf_ctl_override_rev19(dev, 0x1000, 0, 3, false, 0);3944	else if (phy->rev >= 7)3945		b43_nphy_rf_ctl_override_rev7(dev, 0x1000, 0, 3, false, 0);3946	else if (phy->rev >= 3)3947		b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, false);3948 3949	b43_nphy_stop_playback(dev);3950	b43_nphy_tx_tone(dev, 4000, 0, false, false, false);3951	udelay(20);3952	tmp = b43_nphy_poll_rssi(dev, N_RSSI_TSSI_2G, rssi, 1);3953	b43_nphy_stop_playback(dev);3954 3955	b43_nphy_rssi_select(dev, 0, N_RSSI_W1);3956 3957	if (phy->rev >= 19)3958		b43_nphy_rf_ctl_override_rev19(dev, 0x1000, 0, 3, true, 0);3959	else if (phy->rev >= 7)3960		b43_nphy_rf_ctl_override_rev7(dev, 0x1000, 0, 3, true, 0);3961	else if (phy->rev >= 3)3962		b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, true);3963 3964	if (phy->rev >= 19) {3965		/* TODO */3966		return;3967	} else if (phy->rev >= 3) {3968		nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 24) & 0xFF;3969		nphy->pwr_ctl_info[1].idle_tssi_5g = (tmp >> 8) & 0xFF;3970	} else {3971		nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 16) & 0xFF;3972		nphy->pwr_ctl_info[1].idle_tssi_5g = tmp & 0xFF;3973	}3974	nphy->pwr_ctl_info[0].idle_tssi_2g = (tmp >> 24) & 0xFF;3975	nphy->pwr_ctl_info[1].idle_tssi_2g = (tmp >> 8) & 0xFF;3976}3977 3978/* https://bcm-v4.sipsolutions.net/PHY/N/TxPwrLimitToTbl */3979static void b43_nphy_tx_prepare_adjusted_power_table(struct b43_wldev *dev)3980{3981	struct b43_phy_n *nphy = dev->phy.n;3982 3983	u8 idx, delta;3984	u8 i, stf_mode;3985 3986	/* Array adj_pwr_tbl corresponds to the hardware table. It consists of3987	 * 21 groups, each containing 4 entries.3988	 *3989	 * First group has entries for CCK modulation.3990	 * The rest of groups has 1 entry per modulation (SISO, CDD, STBC, SDM).3991	 *3992	 * Group 0 is for CCK3993	 * Groups 1..4 use BPSK (group per coding rate)3994	 * Groups 5..8 use QPSK (group per coding rate)3995	 * Groups 9..12 use 16-QAM (group per coding rate)3996	 * Groups 13..16 use 64-QAM (group per coding rate)3997	 * Groups 17..20 are unknown3998	 */3999 4000	for (i = 0; i < 4; i++)4001		nphy->adj_pwr_tbl[i] = nphy->tx_power_offset[i];4002 4003	for (stf_mode = 0; stf_mode < 4; stf_mode++) {4004		delta = 0;4005		switch (stf_mode) {4006		case 0:4007			if (b43_is_40mhz(dev) && dev->phy.rev >= 5) {4008				idx = 68;4009			} else {4010				delta = 1;4011				idx = b43_is_40mhz(dev) ? 52 : 4;4012			}4013			break;4014		case 1:4015			idx = b43_is_40mhz(dev) ? 76 : 28;4016			break;4017		case 2:4018			idx = b43_is_40mhz(dev) ? 84 : 36;4019			break;4020		case 3:4021			idx = b43_is_40mhz(dev) ? 92 : 44;4022			break;4023		}4024 4025		for (i = 0; i < 20; i++) {4026			nphy->adj_pwr_tbl[4 + 4 * i + stf_mode] =4027				nphy->tx_power_offset[idx];4028			if (i == 0)4029				idx += delta;4030			if (i == 14)4031				idx += 1 - delta;4032			if (i == 3 || i == 4 || i == 7 || i == 8 || i == 11 ||4033			    i == 13)4034				idx += 1;4035		}4036	}4037}4038 4039/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlSetup */4040static void b43_nphy_tx_power_ctl_setup(struct b43_wldev *dev)4041{4042	struct b43_phy *phy = &dev->phy;4043	struct b43_phy_n *nphy = dev->phy.n;4044	struct ssb_sprom *sprom = dev->dev->bus_sprom;4045 4046	s16 a1[2], b0[2], b1[2];4047	u8 idle[2];4048	u8 ppr_max;4049	s8 target[2];4050	s32 num, den, pwr;4051	u32 regval[64];4052 4053	u16 freq = phy->chandef->chan->center_freq;4054	u16 tmp;4055	u16 r; /* routing */4056	u8 i, c;4057 4058	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) {4059		b43_maskset32(dev, B43_MMIO_MACCTL, ~0, 0x200000);4060		b43_read32(dev, B43_MMIO_MACCTL);4061		udelay(1);4062	}4063 4064	if (nphy->hang_avoid)4065		b43_nphy_stay_in_carrier_search(dev, true);4066 4067	b43_phy_set(dev, B43_NPHY_TSSIMODE, B43_NPHY_TSSIMODE_EN);4068	if (dev->phy.rev >= 3)4069		b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD,4070			     ~B43_NPHY_TXPCTL_CMD_PCTLEN & 0xFFFF);4071	else4072		b43_phy_set(dev, B43_NPHY_TXPCTL_CMD,4073			    B43_NPHY_TXPCTL_CMD_PCTLEN);4074 4075	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12)4076		b43_maskset32(dev, B43_MMIO_MACCTL, ~0x200000, 0);4077 4078	if (sprom->revision < 4) {4079		idle[0] = nphy->pwr_ctl_info[0].idle_tssi_2g;4080		idle[1] = nphy->pwr_ctl_info[1].idle_tssi_2g;4081		target[0] = target[1] = 52;4082		a1[0] = a1[1] = -424;4083		b0[0] = b0[1] = 5612;4084		b1[0] = b1[1] = -1393;4085	} else {4086		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {4087			for (c = 0; c < 2; c++) {4088				idle[c] = nphy->pwr_ctl_info[c].idle_tssi_2g;4089				target[c] = sprom->core_pwr_info[c].maxpwr_2g;4090				a1[c] = sprom->core_pwr_info[c].pa_2g[0];4091				b0[c] = sprom->core_pwr_info[c].pa_2g[1];4092				b1[c] = sprom->core_pwr_info[c].pa_2g[2];4093			}4094		} else if (freq >= 4900 && freq < 5100) {4095			for (c = 0; c < 2; c++) {4096				idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g;4097				target[c] = sprom->core_pwr_info[c].maxpwr_5gl;4098				a1[c] = sprom->core_pwr_info[c].pa_5gl[0];4099				b0[c] = sprom->core_pwr_info[c].pa_5gl[1];4100				b1[c] = sprom->core_pwr_info[c].pa_5gl[2];4101			}4102		} else if (freq >= 5100 && freq < 5500) {4103			for (c = 0; c < 2; c++) {4104				idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g;4105				target[c] = sprom->core_pwr_info[c].maxpwr_5g;4106				a1[c] = sprom->core_pwr_info[c].pa_5g[0];4107				b0[c] = sprom->core_pwr_info[c].pa_5g[1];4108				b1[c] = sprom->core_pwr_info[c].pa_5g[2];4109			}4110		} else if (freq >= 5500) {4111			for (c = 0; c < 2; c++) {4112				idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g;4113				target[c] = sprom->core_pwr_info[c].maxpwr_5gh;4114				a1[c] = sprom->core_pwr_info[c].pa_5gh[0];4115				b0[c] = sprom->core_pwr_info[c].pa_5gh[1];4116				b1[c] = sprom->core_pwr_info[c].pa_5gh[2];4117			}4118		} else {4119			idle[0] = nphy->pwr_ctl_info[0].idle_tssi_5g;4120			idle[1] = nphy->pwr_ctl_info[1].idle_tssi_5g;4121			target[0] = target[1] = 52;4122			a1[0] = a1[1] = -424;4123			b0[0] = b0[1] = 5612;4124			b1[0] = b1[1] = -1393;4125		}4126	}4127 4128	ppr_max = b43_ppr_get_max(dev, &nphy->tx_pwr_max_ppr);4129	if (ppr_max) {4130		target[0] = ppr_max;4131		target[1] = ppr_max;4132	}4133 4134	if (dev->phy.rev >= 3) {4135		if (sprom->fem.ghz2.tssipos)4136			b43_phy_set(dev, B43_NPHY_TXPCTL_ITSSI, 0x4000);4137		if (dev->phy.rev >= 7) {4138			for (c = 0; c < 2; c++) {4139				r = c ? 0x190 : 0x170;4140				if (b43_nphy_ipa(dev))4141					b43_radio_write(dev, r + 0x9, (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) ? 0xE : 0xC);4142			}4143		} else {4144			if (b43_nphy_ipa(dev)) {4145				tmp = (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ? 0xC : 0xE;4146				b43_radio_write(dev,4147					B2056_TX0 | B2056_TX_TX_SSI_MUX, tmp);4148				b43_radio_write(dev,4149					B2056_TX1 | B2056_TX_TX_SSI_MUX, tmp);4150			} else {4151				b43_radio_write(dev,4152					B2056_TX0 | B2056_TX_TX_SSI_MUX, 0x11);4153				b43_radio_write(dev,4154					B2056_TX1 | B2056_TX_TX_SSI_MUX, 0x11);4155			}4156		}4157	}4158 4159	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) {4160		b43_maskset32(dev, B43_MMIO_MACCTL, ~0, 0x200000);4161		b43_read32(dev, B43_MMIO_MACCTL);4162		udelay(1);4163	}4164 4165	if (phy->rev >= 19) {4166		/* TODO */4167	} else if (phy->rev >= 7) {4168		b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,4169				~B43_NPHY_TXPCTL_CMD_INIT, 0x19);4170		b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,4171				~B43_NPHY_TXPCTL_INIT_PIDXI1, 0x19);4172	} else {4173		b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,4174				~B43_NPHY_TXPCTL_CMD_INIT, 0x40);4175		if (dev->phy.rev > 1)4176			b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,4177				~B43_NPHY_TXPCTL_INIT_PIDXI1, 0x40);4178	}4179 4180	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12)4181		b43_maskset32(dev, B43_MMIO_MACCTL, ~0x200000, 0);4182 4183	b43_phy_write(dev, B43_NPHY_TXPCTL_N,4184		      0xF0 << B43_NPHY_TXPCTL_N_TSSID_SHIFT |4185		      3 << B43_NPHY_TXPCTL_N_NPTIL2_SHIFT);4186	b43_phy_write(dev, B43_NPHY_TXPCTL_ITSSI,4187		      idle[0] << B43_NPHY_TXPCTL_ITSSI_0_SHIFT |4188		      idle[1] << B43_NPHY_TXPCTL_ITSSI_1_SHIFT |4189		      B43_NPHY_TXPCTL_ITSSI_BINF);4190	b43_phy_write(dev, B43_NPHY_TXPCTL_TPWR,4191		      target[0] << B43_NPHY_TXPCTL_TPWR_0_SHIFT |4192		      target[1] << B43_NPHY_TXPCTL_TPWR_1_SHIFT);4193 4194	for (c = 0; c < 2; c++) {4195		for (i = 0; i < 64; i++) {4196			num = 8 * (16 * b0[c] + b1[c] * i);4197			den = 32768 + a1[c] * i;4198			pwr = max((4 * num + den / 2) / den, -8);4199			if (dev->phy.rev < 3 && (i <= (31 - idle[c] + 1)))4200				pwr = max(pwr, target[c] + 1);4201			regval[i] = pwr;4202		}4203		b43_ntab_write_bulk(dev, B43_NTAB32(26 + c, 0), 64, regval);4204	}4205 4206	b43_nphy_tx_prepare_adjusted_power_table(dev);4207	b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84, nphy->adj_pwr_tbl);4208	b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84, nphy->adj_pwr_tbl);4209 4210	if (nphy->hang_avoid)4211		b43_nphy_stay_in_carrier_search(dev, false);4212}4213 4214static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev)4215{4216	struct b43_phy *phy = &dev->phy;4217 4218	const u32 *table = NULL;4219	u32 rfpwr_offset;4220	u8 pga_gain, pad_gain;4221	int i;4222	const s16 *rf_pwr_offset_table = NULL;4223 4224	table = b43_nphy_get_tx_gain_table(dev);4225	if (!table)4226		return;4227 4228	b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table);4229	b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table);4230 4231	if (phy->rev < 3)4232		return;4233 4234#if 04235	nphy->gmval = (table[0] >> 16) & 0x7000;4236#endif4237 4238	if (phy->rev >= 19) {4239		return;4240	} else if (phy->rev >= 7) {4241		rf_pwr_offset_table = b43_ntab_get_rf_pwr_offset_table(dev);4242		if (!rf_pwr_offset_table)4243			return;4244		/* TODO: Enable this once we have gains configured */4245		return;4246	}4247 4248	for (i = 0; i < 128; i++) {4249		if (phy->rev >= 19) {4250			/* TODO */4251			return;4252		} else if (phy->rev >= 7) {4253			pga_gain = (table[i] >> 24) & 0xf;4254			pad_gain = (table[i] >> 19) & 0x1f;4255			if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)4256				rfpwr_offset = rf_pwr_offset_table[pad_gain];4257			else4258				rfpwr_offset = rf_pwr_offset_table[pga_gain];4259		} else {4260			pga_gain = (table[i] >> 24) & 0xF;4261			if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)4262				rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain];4263			else4264				rfpwr_offset = 0; /* FIXME */4265		}4266 4267		b43_ntab_write(dev, B43_NTAB32(26, 576 + i), rfpwr_offset);4268		b43_ntab_write(dev, B43_NTAB32(27, 576 + i), rfpwr_offset);4269	}4270}4271 4272/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */4273static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable)4274{4275	struct b43_phy_n *nphy = dev->phy.n;4276	enum nl80211_band band;4277	u16 tmp;4278 4279	if (!enable) {4280		nphy->rfctrl_intc1_save = b43_phy_read(dev,4281						       B43_NPHY_RFCTL_INTC1);4282		nphy->rfctrl_intc2_save = b43_phy_read(dev,4283						       B43_NPHY_RFCTL_INTC2);4284		band = b43_current_band(dev->wl);4285		if (dev->phy.rev >= 7) {4286			tmp = 0x1480;4287		} else if (dev->phy.rev >= 3) {4288			if (band == NL80211_BAND_5GHZ)4289				tmp = 0x600;4290			else4291				tmp = 0x480;4292		} else {4293			if (band == NL80211_BAND_5GHZ)4294				tmp = 0x180;4295			else4296				tmp = 0x120;4297		}4298		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp);4299		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp);4300	} else {4301		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1,4302				nphy->rfctrl_intc1_save);4303		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2,4304				nphy->rfctrl_intc2_save);4305	}4306}4307 4308/*4309 * TX low-pass filter bandwidth setup4310 * https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw4311 */4312static void b43_nphy_tx_lpf_bw(struct b43_wldev *dev)4313{4314	u16 tmp;4315 4316	if (dev->phy.rev < 3 || dev->phy.rev >= 7)4317		return;4318 4319	if (b43_nphy_ipa(dev))4320		tmp = b43_is_40mhz(dev) ? 5 : 4;4321	else4322		tmp = b43_is_40mhz(dev) ? 3 : 1;4323	b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2,4324		      (tmp << 9) | (tmp << 6) | (tmp << 3) | tmp);4325 4326	if (b43_nphy_ipa(dev)) {4327		tmp = b43_is_40mhz(dev) ? 4 : 1;4328		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S2,4329			      (tmp << 9) | (tmp << 6) | (tmp << 3) | tmp);4330	}4331}4332 4333/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */4334static void b43_nphy_rx_iq_est(struct b43_wldev *dev, struct nphy_iq_est *est,4335				u16 samps, u8 time, bool wait)4336{4337	int i;4338	u16 tmp;4339 4340	b43_phy_write(dev, B43_NPHY_IQEST_SAMCNT, samps);4341	b43_phy_maskset(dev, B43_NPHY_IQEST_WT, ~B43_NPHY_IQEST_WT_VAL, time);4342	if (wait)4343		b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_MODE);4344	else4345		b43_phy_mask(dev, B43_NPHY_IQEST_CMD, ~B43_NPHY_IQEST_CMD_MODE);4346 4347	b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_START);4348 4349	for (i = 1000; i; i--) {4350		tmp = b43_phy_read(dev, B43_NPHY_IQEST_CMD);4351		if (!(tmp & B43_NPHY_IQEST_CMD_START)) {4352			est->i0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI0) << 16) |4353					b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO0);4354			est->q0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI0) << 16) |4355					b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO0);4356			est->iq0_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI0) << 16) |4357					b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO0);4358 4359			est->i1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI1) << 16) |4360					b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO1);4361			est->q1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI1) << 16) |4362					b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO1);4363			est->iq1_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI1) << 16) |4364					b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO1);4365			return;4366		}4367		udelay(10);4368	}4369	memset(est, 0, sizeof(*est));4370}4371 4372/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */4373static void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write,4374					struct b43_phy_n_iq_comp *pcomp)4375{4376	if (write) {4377		b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPA0, pcomp->a0);4378		b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPB0, pcomp->b0);4379		b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPA1, pcomp->a1);4380		b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPB1, pcomp->b1);4381	} else {4382		pcomp->a0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPA0);4383		pcomp->b0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPB0);4384		pcomp->a1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPA1);4385		pcomp->b1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPB1);4386	}4387}4388 4389#if 04390/* Ready but not used anywhere */4391/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */4392static void b43_nphy_rx_cal_phy_cleanup(struct b43_wldev *dev, u8 core)4393{4394	u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;4395 4396	b43_phy_write(dev, B43_NPHY_RFSEQCA, regs[0]);4397	if (core == 0) {4398		b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[1]);4399		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]);4400	} else {4401		b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]);4402		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]);4403	}4404	b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[3]);4405	b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[4]);4406	b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, regs[5]);4407	b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, regs[6]);4408	b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, regs[7]);4409	b43_phy_write(dev, B43_NPHY_RFCTL_OVER, regs[8]);4410	b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]);4411	b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]);4412}4413 4414/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhySetup */4415static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core)4416{4417	u8 rxval, txval;4418	u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;4419 4420	regs[0] = b43_phy_read(dev, B43_NPHY_RFSEQCA);4421	if (core == 0) {4422		regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);4423		regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);4424	} else {4425		regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);4426		regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);4427	}4428	regs[3] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);4429	regs[4] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);4430	regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1);4431	regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2);4432	regs[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S1);4433	regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER);4434	regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);4435	regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);4436 4437	b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);4438	b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);4439 4440	b43_phy_maskset(dev, B43_NPHY_RFSEQCA,4441			~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF,4442			((1 - core) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));4443	b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN,4444			((1 - core) << B43_NPHY_RFSEQCA_TXEN_SHIFT));4445	b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN,4446			(core << B43_NPHY_RFSEQCA_RXEN_SHIFT));4447	b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXDIS,4448			(core << B43_NPHY_RFSEQCA_TXDIS_SHIFT));4449 4450	if (core == 0) {4451		b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x0007);4452		b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0007);4453	} else {4454		b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x0007);4455		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0007);4456	}4457 4458	b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA, 0, 3);4459	b43_nphy_rf_ctl_override(dev, 8, 0, 3, false);4460	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);4461 4462	if (core == 0) {4463		rxval = 1;4464		txval = 8;4465	} else {4466		rxval = 4;4467		txval = 2;4468	}4469	b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, rxval,4470				      core + 1);4471	b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, txval,4472				      2 - core);4473}4474#endif4475 4476/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */4477static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask)4478{4479	int i;4480	s32 iq;4481	u32 ii;4482	u32 qq;4483	int iq_nbits, qq_nbits;4484	int arsh, brsh;4485	u16 tmp, a, b;4486 4487	struct nphy_iq_est est;4488	struct b43_phy_n_iq_comp old;4489	struct b43_phy_n_iq_comp new = { };4490	bool error = false;4491 4492	if (mask == 0)4493		return;4494 4495	b43_nphy_rx_iq_coeffs(dev, false, &old);4496	b43_nphy_rx_iq_coeffs(dev, true, &new);4497	b43_nphy_rx_iq_est(dev, &est, 0x4000, 32, false);4498	new = old;4499 4500	for (i = 0; i < 2; i++) {4501		if (i == 0 && (mask & 1)) {4502			iq = est.iq0_prod;4503			ii = est.i0_pwr;4504			qq = est.q0_pwr;4505		} else if (i == 1 && (mask & 2)) {4506			iq = est.iq1_prod;4507			ii = est.i1_pwr;4508			qq = est.q1_pwr;4509		} else {4510			continue;4511		}4512 4513		if (ii + qq < 2) {4514			error = true;4515			break;4516		}4517 4518		iq_nbits = fls(abs(iq));4519		qq_nbits = fls(qq);4520 4521		arsh = iq_nbits - 20;4522		if (arsh >= 0) {4523			a = -((iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));4524			tmp = ii >> arsh;4525		} else {4526			a = -((iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));4527			tmp = ii << -arsh;4528		}4529		if (tmp == 0) {4530			error = true;4531			break;4532		}4533		a /= tmp;4534 4535		brsh = qq_nbits - 11;4536		if (brsh >= 0) {4537			b = (qq << (31 - qq_nbits));4538			tmp = ii >> brsh;4539		} else {4540			b = (qq << (31 - qq_nbits));4541			tmp = ii << -brsh;4542		}4543		if (tmp == 0) {4544			error = true;4545			break;4546		}4547		b = int_sqrt(b / tmp - a * a) - (1 << 10);4548 4549		if (i == 0 && (mask & 0x1)) {4550			if (dev->phy.rev >= 3) {4551				new.a0 = a & 0x3FF;4552				new.b0 = b & 0x3FF;4553			} else {4554				new.a0 = b & 0x3FF;4555				new.b0 = a & 0x3FF;4556			}4557		} else if (i == 1 && (mask & 0x2)) {4558			if (dev->phy.rev >= 3) {4559				new.a1 = a & 0x3FF;4560				new.b1 = b & 0x3FF;4561			} else {4562				new.a1 = b & 0x3FF;4563				new.b1 = a & 0x3FF;4564			}4565		}4566	}4567 4568	if (error)4569		new = old;4570 4571	b43_nphy_rx_iq_coeffs(dev, true, &new);4572}4573 4574/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */4575static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev)4576{4577	u16 array[4];4578	b43_ntab_read_bulk(dev, B43_NTAB16(0xF, 0x50), 4, array);4579 4580	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW0, array[0]);4581	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW1, array[1]);4582	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW2, array[2]);4583	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW3, array[3]);4584}4585 4586/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SpurWar */4587static void b43_nphy_spur_workaround(struct b43_wldev *dev)4588{4589	struct b43_phy_n *nphy = dev->phy.n;4590 4591	B43_WARN_ON(dev->phy.rev < 3);4592 4593	if (nphy->hang_avoid)4594		b43_nphy_stay_in_carrier_search(dev, 1);4595 4596	if (nphy->hang_avoid)4597		b43_nphy_stay_in_carrier_search(dev, 0);4598}4599 4600/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */4601static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev)4602{4603	struct b43_phy_n *nphy = dev->phy.n;4604	int i, j;4605	u32 tmp;4606	u32 cur_real, cur_imag, real_part, imag_part;4607 4608	u16 buffer[7];4609 4610	if (nphy->hang_avoid)4611		b43_nphy_stay_in_carrier_search(dev, true);4612 4613	b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);4614 4615	for (i = 0; i < 2; i++) {4616		tmp = ((buffer[i * 2] & 0x3FF) << 10) |4617			(buffer[i * 2 + 1] & 0x3FF);4618		b43_phy_write(dev, B43_NPHY_TABLE_ADDR,4619				(((i + 26) << 10) | 320));4620		for (j = 0; j < 128; j++) {4621			b43_phy_write(dev, B43_NPHY_TABLE_DATAHI,4622					((tmp >> 16) & 0xFFFF));4623			b43_phy_write(dev, B43_NPHY_TABLE_DATALO,4624					(tmp & 0xFFFF));4625		}4626	}4627 4628	for (i = 0; i < 2; i++) {4629		tmp = buffer[5 + i];4630		real_part = (tmp >> 8) & 0xFF;4631		imag_part = (tmp & 0xFF);4632		b43_phy_write(dev, B43_NPHY_TABLE_ADDR,4633				(((i + 26) << 10) | 448));4634 4635		if (dev->phy.rev >= 3) {4636			cur_real = real_part;4637			cur_imag = imag_part;4638			tmp = ((cur_real & 0xFF) << 8) | (cur_imag & 0xFF);4639		}4640 4641		for (j = 0; j < 128; j++) {4642			if (dev->phy.rev < 3) {4643				cur_real = (real_part * loscale[j] + 128) >> 8;4644				cur_imag = (imag_part * loscale[j] + 128) >> 8;4645				tmp = ((cur_real & 0xFF) << 8) |4646					(cur_imag & 0xFF);4647			}4648			b43_phy_write(dev, B43_NPHY_TABLE_DATAHI,4649					((tmp >> 16) & 0xFFFF));4650			b43_phy_write(dev, B43_NPHY_TABLE_DATALO,4651					(tmp & 0xFFFF));4652		}4653	}4654 4655	if (dev->phy.rev >= 3) {4656		b43_shm_write16(dev, B43_SHM_SHARED,4657				B43_SHM_SH_NPHY_TXPWR_INDX0, 0xFFFF);4658		b43_shm_write16(dev, B43_SHM_SHARED,4659				B43_SHM_SH_NPHY_TXPWR_INDX1, 0xFFFF);4660	}4661 4662	if (nphy->hang_avoid)4663		b43_nphy_stay_in_carrier_search(dev, false);4664}4665 4666/*4667 * Restore RSSI Calibration4668 * https://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal4669 */4670static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev)4671{4672	struct b43_phy_n *nphy = dev->phy.n;4673 4674	u16 *rssical_radio_regs = NULL;4675	u16 *rssical_phy_regs = NULL;4676 4677	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {4678		if (!nphy->rssical_chanspec_2G.center_freq)4679			return;4680		rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G;4681		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G;4682	} else {4683		if (!nphy->rssical_chanspec_5G.center_freq)4684			return;4685		rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G;4686		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;4687	}4688 4689	if (dev->phy.rev >= 19) {4690		/* TODO */4691	} else if (dev->phy.rev >= 7) {4692		b43_radio_maskset(dev, R2057_NB_MASTER_CORE0, ~R2057_VCM_MASK,4693				  rssical_radio_regs[0]);4694		b43_radio_maskset(dev, R2057_NB_MASTER_CORE1, ~R2057_VCM_MASK,4695				  rssical_radio_regs[1]);4696	} else {4697		b43_radio_maskset(dev, B2056_RX0 | B2056_RX_RSSI_MISC, 0xE3,4698				  rssical_radio_regs[0]);4699		b43_radio_maskset(dev, B2056_RX1 | B2056_RX_RSSI_MISC, 0xE3,4700				  rssical_radio_regs[1]);4701	}4702 4703	b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, rssical_phy_regs[0]);4704	b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, rssical_phy_regs[1]);4705	b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, rssical_phy_regs[2]);4706	b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, rssical_phy_regs[3]);4707 4708	b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, rssical_phy_regs[4]);4709	b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, rssical_phy_regs[5]);4710	b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, rssical_phy_regs[6]);4711	b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, rssical_phy_regs[7]);4712 4713	b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, rssical_phy_regs[8]);4714	b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, rssical_phy_regs[9]);4715	b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, rssical_phy_regs[10]);4716	b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]);4717}4718 4719static void b43_nphy_tx_cal_radio_setup_rev19(struct b43_wldev *dev)4720{4721	/* TODO */4722}4723 4724static void b43_nphy_tx_cal_radio_setup_rev7(struct b43_wldev *dev)4725{4726	struct b43_phy *phy = &dev->phy;4727	struct b43_phy_n *nphy = dev->phy.n;4728	u16 *save = nphy->tx_rx_cal_radio_saveregs;4729	int core, off;4730	u16 r, tmp;4731 4732	for (core = 0; core < 2; core++) {4733		r = core ? 0x20 : 0;4734		off = core * 11;4735 4736		save[off + 0] = b43_radio_read(dev, r + R2057_TX0_TX_SSI_MASTER);4737		save[off + 1] = b43_radio_read(dev, r + R2057_TX0_IQCAL_VCM_HG);4738		save[off + 2] = b43_radio_read(dev, r + R2057_TX0_IQCAL_IDAC);4739		save[off + 3] = b43_radio_read(dev, r + R2057_TX0_TSSI_VCM);4740		save[off + 4] = 0;4741		save[off + 5] = b43_radio_read(dev, r + R2057_TX0_TX_SSI_MUX);4742		if (phy->radio_rev != 5)4743			save[off + 6] = b43_radio_read(dev, r + R2057_TX0_TSSIA);4744		save[off + 7] = b43_radio_read(dev, r + R2057_TX0_TSSIG);4745		save[off + 8] = b43_radio_read(dev, r + R2057_TX0_TSSI_MISC1);4746 4747		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {4748			b43_radio_write(dev, r + R2057_TX0_TX_SSI_MASTER, 0xA);4749			b43_radio_write(dev, r + R2057_TX0_IQCAL_VCM_HG, 0x43);4750			b43_radio_write(dev, r + R2057_TX0_IQCAL_IDAC, 0x55);4751			b43_radio_write(dev, r + R2057_TX0_TSSI_VCM, 0);4752			b43_radio_write(dev, r + R2057_TX0_TSSIG, 0);4753			if (nphy->use_int_tx_iq_lo_cal) {4754				b43_radio_write(dev, r + R2057_TX0_TX_SSI_MUX, 0x4);4755				tmp = true ? 0x31 : 0x21; /* TODO */4756				b43_radio_write(dev, r + R2057_TX0_TSSIA, tmp);4757			}4758			b43_radio_write(dev, r + R2057_TX0_TSSI_MISC1, 0x00);4759		} else {4760			b43_radio_write(dev, r + R2057_TX0_TX_SSI_MASTER, 0x6);4761			b43_radio_write(dev, r + R2057_TX0_IQCAL_VCM_HG, 0x43);4762			b43_radio_write(dev, r + R2057_TX0_IQCAL_IDAC, 0x55);4763			b43_radio_write(dev, r + R2057_TX0_TSSI_VCM, 0);4764 4765			if (phy->radio_rev != 5)4766				b43_radio_write(dev, r + R2057_TX0_TSSIA, 0);4767			if (nphy->use_int_tx_iq_lo_cal) {4768				b43_radio_write(dev, r + R2057_TX0_TX_SSI_MUX, 0x6);4769				tmp = true ? 0x31 : 0x21; /* TODO */4770				b43_radio_write(dev, r + R2057_TX0_TSSIG, tmp);4771			}4772			b43_radio_write(dev, r + R2057_TX0_TSSI_MISC1, 0);4773		}4774	}4775}4776 4777/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */4778static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev)4779{4780	struct b43_phy *phy = &dev->phy;4781	struct b43_phy_n *nphy = dev->phy.n;4782	u16 *save = nphy->tx_rx_cal_radio_saveregs;4783	u16 tmp;4784	u8 offset, i;4785 4786	if (phy->rev >= 19) {4787		b43_nphy_tx_cal_radio_setup_rev19(dev);4788	} else if (phy->rev >= 7) {4789		b43_nphy_tx_cal_radio_setup_rev7(dev);4790	} else if (phy->rev >= 3) {4791	    for (i = 0; i < 2; i++) {4792		tmp = (i == 0) ? 0x2000 : 0x3000;4793		offset = i * 11;4794 4795		save[offset + 0] = b43_radio_read(dev, B2055_CAL_RVARCTL);4796		save[offset + 1] = b43_radio_read(dev, B2055_CAL_LPOCTL);4797		save[offset + 2] = b43_radio_read(dev, B2055_CAL_TS);4798		save[offset + 3] = b43_radio_read(dev, B2055_CAL_RCCALRTS);4799		save[offset + 4] = b43_radio_read(dev, B2055_CAL_RCALRTS);4800		save[offset + 5] = b43_radio_read(dev, B2055_PADDRV);4801		save[offset + 6] = b43_radio_read(dev, B2055_XOCTL1);4802		save[offset + 7] = b43_radio_read(dev, B2055_XOCTL2);4803		save[offset + 8] = b43_radio_read(dev, B2055_XOREGUL);4804		save[offset + 9] = b43_radio_read(dev, B2055_XOMISC);4805		save[offset + 10] = b43_radio_read(dev, B2055_PLL_LFC1);4806 4807		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {4808			b43_radio_write(dev, tmp | B2055_CAL_RVARCTL, 0x0A);4809			b43_radio_write(dev, tmp | B2055_CAL_LPOCTL, 0x40);4810			b43_radio_write(dev, tmp | B2055_CAL_TS, 0x55);4811			b43_radio_write(dev, tmp | B2055_CAL_RCCALRTS, 0);4812			b43_radio_write(dev, tmp | B2055_CAL_RCALRTS, 0);4813			if (nphy->ipa5g_on) {4814				b43_radio_write(dev, tmp | B2055_PADDRV, 4);4815				b43_radio_write(dev, tmp | B2055_XOCTL1, 1);4816			} else {4817				b43_radio_write(dev, tmp | B2055_PADDRV, 0);4818				b43_radio_write(dev, tmp | B2055_XOCTL1, 0x2F);4819			}4820			b43_radio_write(dev, tmp | B2055_XOCTL2, 0);4821		} else {4822			b43_radio_write(dev, tmp | B2055_CAL_RVARCTL, 0x06);4823			b43_radio_write(dev, tmp | B2055_CAL_LPOCTL, 0x40);4824			b43_radio_write(dev, tmp | B2055_CAL_TS, 0x55);4825			b43_radio_write(dev, tmp | B2055_CAL_RCCALRTS, 0);4826			b43_radio_write(dev, tmp | B2055_CAL_RCALRTS, 0);4827			b43_radio_write(dev, tmp | B2055_XOCTL1, 0);4828			if (nphy->ipa2g_on) {4829				b43_radio_write(dev, tmp | B2055_PADDRV, 6);4830				b43_radio_write(dev, tmp | B2055_XOCTL2,4831					(dev->phy.rev < 5) ? 0x11 : 0x01);4832			} else {4833				b43_radio_write(dev, tmp | B2055_PADDRV, 0);4834				b43_radio_write(dev, tmp | B2055_XOCTL2, 0);4835			}4836		}4837		b43_radio_write(dev, tmp | B2055_XOREGUL, 0);4838		b43_radio_write(dev, tmp | B2055_XOMISC, 0);4839		b43_radio_write(dev, tmp | B2055_PLL_LFC1, 0);4840	    }4841	} else {4842		save[0] = b43_radio_read(dev, B2055_C1_TX_RF_IQCAL1);4843		b43_radio_write(dev, B2055_C1_TX_RF_IQCAL1, 0x29);4844 4845		save[1] = b43_radio_read(dev, B2055_C1_TX_RF_IQCAL2);4846		b43_radio_write(dev, B2055_C1_TX_RF_IQCAL2, 0x54);4847 4848		save[2] = b43_radio_read(dev, B2055_C2_TX_RF_IQCAL1);4849		b43_radio_write(dev, B2055_C2_TX_RF_IQCAL1, 0x29);4850 4851		save[3] = b43_radio_read(dev, B2055_C2_TX_RF_IQCAL2);4852		b43_radio_write(dev, B2055_C2_TX_RF_IQCAL2, 0x54);4853 4854		save[3] = b43_radio_read(dev, B2055_C1_PWRDET_RXTX);4855		save[4] = b43_radio_read(dev, B2055_C2_PWRDET_RXTX);4856 4857		if (!(b43_phy_read(dev, B43_NPHY_BANDCTL) &4858		    B43_NPHY_BANDCTL_5GHZ)) {4859			b43_radio_write(dev, B2055_C1_PWRDET_RXTX, 0x04);4860			b43_radio_write(dev, B2055_C2_PWRDET_RXTX, 0x04);4861		} else {4862			b43_radio_write(dev, B2055_C1_PWRDET_RXTX, 0x20);4863			b43_radio_write(dev, B2055_C2_PWRDET_RXTX, 0x20);4864		}4865 4866		if (dev->phy.rev < 2) {4867			b43_radio_set(dev, B2055_C1_TX_BB_MXGM, 0x20);4868			b43_radio_set(dev, B2055_C2_TX_BB_MXGM, 0x20);4869		} else {4870			b43_radio_mask(dev, B2055_C1_TX_BB_MXGM, ~0x20);4871			b43_radio_mask(dev, B2055_C2_TX_BB_MXGM, ~0x20);4872		}4873	}4874}4875 4876/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */4877static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core)4878{4879	struct b43_phy_n *nphy = dev->phy.n;4880	int i;4881	u16 scale, entry;4882 4883	u16 tmp = nphy->txcal_bbmult;4884	if (core == 0)4885		tmp >>= 8;4886	tmp &= 0xff;4887 4888	for (i = 0; i < 18; i++) {4889		scale = (ladder_lo[i].percent * tmp) / 100;4890		entry = ((scale & 0xFF) << 8) | ladder_lo[i].g_env;4891		b43_ntab_write(dev, B43_NTAB16(15, i), entry);4892 4893		scale = (ladder_iq[i].percent * tmp) / 100;4894		entry = ((scale & 0xFF) << 8) | ladder_iq[i].g_env;4895		b43_ntab_write(dev, B43_NTAB16(15, i + 32), entry);4896	}4897}4898 4899static void b43_nphy_pa_set_tx_dig_filter(struct b43_wldev *dev, u16 offset,4900					  const s16 *filter)4901{4902	int i;4903 4904	offset = B43_PHY_N(offset);4905 4906	for (i = 0; i < 15; i++, offset++)4907		b43_phy_write(dev, offset, filter[i]);4908}4909 4910/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */4911static void b43_nphy_ext_pa_set_tx_dig_filters(struct b43_wldev *dev)4912{4913	b43_nphy_pa_set_tx_dig_filter(dev, 0x2C5,4914				      tbl_tx_filter_coef_rev4[2]);4915}4916 4917/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */4918static void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev)4919{4920	/* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */4921	static const u16 offset[] = { 0x186, 0x195, 0x2C5 };4922	static const s16 dig_filter_phy_rev16[] = {4923		-375, 136, -407, 208, -1527,4924		956, 93, 186, 93, 230,4925		-44, 230, 201, -191, 201,4926	};4927	int i;4928 4929	for (i = 0; i < 3; i++)4930		b43_nphy_pa_set_tx_dig_filter(dev, offset[i],4931					      tbl_tx_filter_coef_rev4[i]);4932 4933	/* Verified with BCM43227 and BCM43228 */4934	if (dev->phy.rev == 16)4935		b43_nphy_pa_set_tx_dig_filter(dev, 0x186, dig_filter_phy_rev16);4936 4937	/* Verified with BCM43131 and BCM43217 */4938	if (dev->phy.rev == 17) {4939		b43_nphy_pa_set_tx_dig_filter(dev, 0x186, dig_filter_phy_rev16);4940		b43_nphy_pa_set_tx_dig_filter(dev, 0x195,4941					      tbl_tx_filter_coef_rev4[1]);4942	}4943 4944	if (b43_is_40mhz(dev)) {4945		b43_nphy_pa_set_tx_dig_filter(dev, 0x186,4946					      tbl_tx_filter_coef_rev4[3]);4947	} else {4948		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)4949			b43_nphy_pa_set_tx_dig_filter(dev, 0x186,4950						      tbl_tx_filter_coef_rev4[5]);4951		if (dev->phy.channel == 14)4952			b43_nphy_pa_set_tx_dig_filter(dev, 0x186,4953						      tbl_tx_filter_coef_rev4[6]);4954	}4955}4956 4957/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */4958static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev)4959{4960	struct b43_phy_n *nphy = dev->phy.n;4961 4962	u16 curr_gain[2];4963	struct nphy_txgains target;4964	const u32 *table = NULL;4965 4966	if (!nphy->txpwrctrl) {4967		int i;4968 4969		if (nphy->hang_avoid)4970			b43_nphy_stay_in_carrier_search(dev, true);4971		b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, curr_gain);4972		if (nphy->hang_avoid)4973			b43_nphy_stay_in_carrier_search(dev, false);4974 4975		for (i = 0; i < 2; ++i) {4976			if (dev->phy.rev >= 7) {4977				target.ipa[i] = curr_gain[i] & 0x0007;4978				target.pad[i] = (curr_gain[i] & 0x00F8) >> 3;4979				target.pga[i] = (curr_gain[i] & 0x0F00) >> 8;4980				target.txgm[i] = (curr_gain[i] & 0x7000) >> 12;4981				target.tx_lpf[i] = (curr_gain[i] & 0x8000) >> 15;4982			} else if (dev->phy.rev >= 3) {4983				target.ipa[i] = curr_gain[i] & 0x000F;4984				target.pad[i] = (curr_gain[i] & 0x00F0) >> 4;4985				target.pga[i] = (curr_gain[i] & 0x0F00) >> 8;4986				target.txgm[i] = (curr_gain[i] & 0x7000) >> 12;4987			} else {4988				target.ipa[i] = curr_gain[i] & 0x0003;4989				target.pad[i] = (curr_gain[i] & 0x000C) >> 2;4990				target.pga[i] = (curr_gain[i] & 0x0070) >> 4;4991				target.txgm[i] = (curr_gain[i] & 0x0380) >> 7;4992			}4993		}4994	} else {4995		int i;4996		u16 index[2];4997		index[0] = (b43_phy_read(dev, B43_NPHY_C1_TXPCTL_STAT) &4998			B43_NPHY_TXPCTL_STAT_BIDX) >>4999			B43_NPHY_TXPCTL_STAT_BIDX_SHIFT;5000		index[1] = (b43_phy_read(dev, B43_NPHY_C2_TXPCTL_STAT) &5001			B43_NPHY_TXPCTL_STAT_BIDX) >>5002			B43_NPHY_TXPCTL_STAT_BIDX_SHIFT;5003 5004		for (i = 0; i < 2; ++i) {5005			table = b43_nphy_get_tx_gain_table(dev);5006			if (!table)5007				break;5008 5009			if (dev->phy.rev >= 7) {5010				target.ipa[i] = (table[index[i]] >> 16) & 0x7;5011				target.pad[i] = (table[index[i]] >> 19) & 0x1F;5012				target.pga[i] = (table[index[i]] >> 24) & 0xF;5013				target.txgm[i] = (table[index[i]] >> 28) & 0x7;5014				target.tx_lpf[i] = (table[index[i]] >> 31) & 0x1;5015			} else if (dev->phy.rev >= 3) {5016				target.ipa[i] = (table[index[i]] >> 16) & 0xF;5017				target.pad[i] = (table[index[i]] >> 20) & 0xF;5018				target.pga[i] = (table[index[i]] >> 24) & 0xF;5019				target.txgm[i] = (table[index[i]] >> 28) & 0xF;5020			} else {5021				target.ipa[i] = (table[index[i]] >> 16) & 0x3;5022				target.pad[i] = (table[index[i]] >> 18) & 0x3;5023				target.pga[i] = (table[index[i]] >> 20) & 0x7;5024				target.txgm[i] = (table[index[i]] >> 23) & 0x7;5025			}5026		}5027	}5028 5029	return target;5030}5031 5032/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhyCleanup */5033static void b43_nphy_tx_cal_phy_cleanup(struct b43_wldev *dev)5034{5035	u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;5036 5037	if (dev->phy.rev >= 3) {5038		b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[0]);5039		b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]);5040		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]);5041		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[3]);5042		b43_phy_write(dev, B43_NPHY_BBCFG, regs[4]);5043		b43_ntab_write(dev, B43_NTAB16(8, 3), regs[5]);5044		b43_ntab_write(dev, B43_NTAB16(8, 19), regs[6]);5045		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[7]);5046		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[8]);5047		b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]);5048		b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]);5049		b43_nphy_reset_cca(dev);5050	} else {5051		b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, regs[0]);5052		b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, regs[1]);5053		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]);5054		b43_ntab_write(dev, B43_NTAB16(8, 2), regs[3]);5055		b43_ntab_write(dev, B43_NTAB16(8, 18), regs[4]);5056		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[5]);5057		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[6]);5058	}5059}5060 5061/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */5062static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev)5063{5064	struct b43_phy *phy = &dev->phy;5065	struct b43_phy_n *nphy = dev->phy.n;5066	u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;5067	u16 tmp;5068 5069	regs[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);5070	regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);5071	if (dev->phy.rev >= 3) {5072		b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0xF0FF, 0x0A00);5073		b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0xF0FF, 0x0A00);5074 5075		tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);5076		regs[2] = tmp;5077		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, tmp | 0x0600);5078 5079		tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);5080		regs[3] = tmp;5081		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x0600);5082 5083		regs[4] = b43_phy_read(dev, B43_NPHY_BBCFG);5084		b43_phy_mask(dev, B43_NPHY_BBCFG,5085			     ~B43_NPHY_BBCFG_RSTRX & 0xFFFF);5086 5087		tmp = b43_ntab_read(dev, B43_NTAB16(8, 3));5088		regs[5] = tmp;5089		b43_ntab_write(dev, B43_NTAB16(8, 3), 0);5090 5091		tmp = b43_ntab_read(dev, B43_NTAB16(8, 19));5092		regs[6] = tmp;5093		b43_ntab_write(dev, B43_NTAB16(8, 19), 0);5094		regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);5095		regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);5096 5097		if (!nphy->use_int_tx_iq_lo_cal)5098			b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA,5099						      1, 3);5100		else5101			b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA,5102						      0, 3);5103		b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 2, 1);5104		b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 8, 2);5105 5106		regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);5107		regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);5108		b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);5109		b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);5110 5111		tmp = b43_nphy_read_lpf_ctl(dev, 0);5112		if (phy->rev >= 19)5113			b43_nphy_rf_ctl_override_rev19(dev, 0x80, tmp, 0, false,5114						       1);5115		else if (phy->rev >= 7)5116			b43_nphy_rf_ctl_override_rev7(dev, 0x80, tmp, 0, false,5117						      1);5118 5119		if (nphy->use_int_tx_iq_lo_cal && true /* FIXME */) {5120			if (phy->rev >= 19) {5121				b43_nphy_rf_ctl_override_rev19(dev, 0x8, 0, 0x3,5122							       false, 0);5123			} else if (phy->rev >= 8) {5124				b43_nphy_rf_ctl_override_rev7(dev, 0x8, 0, 0x3,5125							      false, 0);5126			} else if (phy->rev == 7) {5127				b43_radio_maskset(dev, R2057_OVR_REG0, 1 << 4, 1 << 4);5128				if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {5129					b43_radio_maskset(dev, R2057_PAD2G_TUNE_PUS_CORE0, ~1, 0);5130					b43_radio_maskset(dev, R2057_PAD2G_TUNE_PUS_CORE1, ~1, 0);5131				} else {5132					b43_radio_maskset(dev, R2057_IPA5G_CASCOFFV_PU_CORE0, ~1, 0);5133					b43_radio_maskset(dev, R2057_IPA5G_CASCOFFV_PU_CORE1, ~1, 0);5134				}5135			}5136		}5137	} else {5138		b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, 0xA000);5139		b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, 0xA000);5140		tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);5141		regs[2] = tmp;5142		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x3000);5143		tmp = b43_ntab_read(dev, B43_NTAB16(8, 2));5144		regs[3] = tmp;5145		tmp |= 0x2000;5146		b43_ntab_write(dev, B43_NTAB16(8, 2), tmp);5147		tmp = b43_ntab_read(dev, B43_NTAB16(8, 18));5148		regs[4] = tmp;5149		tmp |= 0x2000;5150		b43_ntab_write(dev, B43_NTAB16(8, 18), tmp);5151		regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);5152		regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);5153		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)5154			tmp = 0x0180;5155		else5156			tmp = 0x0120;5157		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp);5158		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp);5159	}5160}5161 5162/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */5163static void b43_nphy_save_cal(struct b43_wldev *dev)5164{5165	struct b43_phy *phy = &dev->phy;5166	struct b43_phy_n *nphy = dev->phy.n;5167 5168	struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;5169	u16 *txcal_radio_regs = NULL;5170	struct b43_chanspec *iqcal_chanspec;5171	u16 *table = NULL;5172 5173	if (nphy->hang_avoid)5174		b43_nphy_stay_in_carrier_search(dev, 1);5175 5176	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {5177		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G;5178		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G;5179		iqcal_chanspec = &nphy->iqcal_chanspec_2G;5180		table = nphy->cal_cache.txcal_coeffs_2G;5181	} else {5182		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G;5183		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G;5184		iqcal_chanspec = &nphy->iqcal_chanspec_5G;5185		table = nphy->cal_cache.txcal_coeffs_5G;5186	}5187 5188	b43_nphy_rx_iq_coeffs(dev, false, rxcal_coeffs);5189	/* TODO use some definitions */5190	if (phy->rev >= 19) {5191		/* TODO */5192	} else if (phy->rev >= 7) {5193		txcal_radio_regs[0] = b43_radio_read(dev,5194						     R2057_TX0_LOFT_FINE_I);5195		txcal_radio_regs[1] = b43_radio_read(dev,5196						     R2057_TX0_LOFT_FINE_Q);5197		txcal_radio_regs[4] = b43_radio_read(dev,5198						     R2057_TX0_LOFT_COARSE_I);5199		txcal_radio_regs[5] = b43_radio_read(dev,5200						     R2057_TX0_LOFT_COARSE_Q);5201		txcal_radio_regs[2] = b43_radio_read(dev,5202						     R2057_TX1_LOFT_FINE_I);5203		txcal_radio_regs[3] = b43_radio_read(dev,5204						     R2057_TX1_LOFT_FINE_Q);5205		txcal_radio_regs[6] = b43_radio_read(dev,5206						     R2057_TX1_LOFT_COARSE_I);5207		txcal_radio_regs[7] = b43_radio_read(dev,5208						     R2057_TX1_LOFT_COARSE_Q);5209	} else if (phy->rev >= 3) {5210		txcal_radio_regs[0] = b43_radio_read(dev, 0x2021);5211		txcal_radio_regs[1] = b43_radio_read(dev, 0x2022);5212		txcal_radio_regs[2] = b43_radio_read(dev, 0x3021);5213		txcal_radio_regs[3] = b43_radio_read(dev, 0x3022);5214		txcal_radio_regs[4] = b43_radio_read(dev, 0x2023);5215		txcal_radio_regs[5] = b43_radio_read(dev, 0x2024);5216		txcal_radio_regs[6] = b43_radio_read(dev, 0x3023);5217		txcal_radio_regs[7] = b43_radio_read(dev, 0x3024);5218	} else {5219		txcal_radio_regs[0] = b43_radio_read(dev, 0x8B);5220		txcal_radio_regs[1] = b43_radio_read(dev, 0xBA);5221		txcal_radio_regs[2] = b43_radio_read(dev, 0x8D);5222		txcal_radio_regs[3] = b43_radio_read(dev, 0xBC);5223	}5224	iqcal_chanspec->center_freq = dev->phy.chandef->chan->center_freq;5225	iqcal_chanspec->channel_type =5226				cfg80211_get_chandef_type(dev->phy.chandef);5227	b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 8, table);5228 5229	if (nphy->hang_avoid)5230		b43_nphy_stay_in_carrier_search(dev, 0);5231}5232 5233/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */5234static void b43_nphy_restore_cal(struct b43_wldev *dev)5235{5236	struct b43_phy *phy = &dev->phy;5237	struct b43_phy_n *nphy = dev->phy.n;5238 5239	u16 coef[4];5240	u16 *loft = NULL;5241	u16 *table = NULL;5242 5243	int i;5244	u16 *txcal_radio_regs = NULL;5245	struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;5246 5247	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {5248		if (!nphy->iqcal_chanspec_2G.center_freq)5249			return;5250		table = nphy->cal_cache.txcal_coeffs_2G;5251		loft = &nphy->cal_cache.txcal_coeffs_2G[5];5252	} else {5253		if (!nphy->iqcal_chanspec_5G.center_freq)5254			return;5255		table = nphy->cal_cache.txcal_coeffs_5G;5256		loft = &nphy->cal_cache.txcal_coeffs_5G[5];5257	}5258 5259	b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4, table);5260 5261	for (i = 0; i < 4; i++) {5262		if (dev->phy.rev >= 3)5263			coef[i] = table[i];5264		else5265			coef[i] = 0;5266	}5267 5268	b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, coef);5269	b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, loft);5270	b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2, loft);5271 5272	if (dev->phy.rev < 2)5273		b43_nphy_tx_iq_workaround(dev);5274 5275	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {5276		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G;5277		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G;5278	} else {5279		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G;5280		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G;5281	}5282 5283	/* TODO use some definitions */5284	if (phy->rev >= 19) {5285		/* TODO */5286	} else if (phy->rev >= 7) {5287		b43_radio_write(dev, R2057_TX0_LOFT_FINE_I,5288				txcal_radio_regs[0]);5289		b43_radio_write(dev, R2057_TX0_LOFT_FINE_Q,5290				txcal_radio_regs[1]);5291		b43_radio_write(dev, R2057_TX0_LOFT_COARSE_I,5292				txcal_radio_regs[4]);5293		b43_radio_write(dev, R2057_TX0_LOFT_COARSE_Q,5294				txcal_radio_regs[5]);5295		b43_radio_write(dev, R2057_TX1_LOFT_FINE_I,5296				txcal_radio_regs[2]);5297		b43_radio_write(dev, R2057_TX1_LOFT_FINE_Q,5298				txcal_radio_regs[3]);5299		b43_radio_write(dev, R2057_TX1_LOFT_COARSE_I,5300				txcal_radio_regs[6]);5301		b43_radio_write(dev, R2057_TX1_LOFT_COARSE_Q,5302				txcal_radio_regs[7]);5303	} else if (phy->rev >= 3) {5304		b43_radio_write(dev, 0x2021, txcal_radio_regs[0]);5305		b43_radio_write(dev, 0x2022, txcal_radio_regs[1]);5306		b43_radio_write(dev, 0x3021, txcal_radio_regs[2]);5307		b43_radio_write(dev, 0x3022, txcal_radio_regs[3]);5308		b43_radio_write(dev, 0x2023, txcal_radio_regs[4]);5309		b43_radio_write(dev, 0x2024, txcal_radio_regs[5]);5310		b43_radio_write(dev, 0x3023, txcal_radio_regs[6]);5311		b43_radio_write(dev, 0x3024, txcal_radio_regs[7]);5312	} else {5313		b43_radio_write(dev, 0x8B, txcal_radio_regs[0]);5314		b43_radio_write(dev, 0xBA, txcal_radio_regs[1]);5315		b43_radio_write(dev, 0x8D, txcal_radio_regs[2]);5316		b43_radio_write(dev, 0xBC, txcal_radio_regs[3]);5317	}5318	b43_nphy_rx_iq_coeffs(dev, true, rxcal_coeffs);5319}5320 5321/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/CalTxIqlo */5322static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,5323				struct nphy_txgains target,5324				bool full, bool mphase)5325{5326	struct b43_phy *phy = &dev->phy;5327	struct b43_phy_n *nphy = dev->phy.n;5328	int i;5329	int error = 0;5330	int freq;5331	bool avoid = false;5332	u8 length;5333	u16 tmp, core, type, count, max, numb, last = 0, cmd;5334	const u16 *table;5335	bool phy6or5x;5336 5337	u16 buffer[11];5338	u16 diq_start = 0;5339	u16 save[2];5340	u16 gain[2];5341	struct nphy_iqcal_params params[2];5342	bool updated[2] = { };5343 5344	b43_nphy_stay_in_carrier_search(dev, true);5345 5346	if (dev->phy.rev >= 4) {5347		avoid = nphy->hang_avoid;5348		nphy->hang_avoid = false;5349	}5350 5351	b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, save);5352 5353	for (i = 0; i < 2; i++) {5354		b43_nphy_iq_cal_gain_params(dev, i, target, &params[i]);5355		gain[i] = params[i].cal_gain;5356	}5357 5358	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain);5359 5360	b43_nphy_tx_cal_radio_setup(dev);5361	b43_nphy_tx_cal_phy_setup(dev);5362 5363	phy6or5x = dev->phy.rev >= 6 ||5364		(dev->phy.rev == 5 && nphy->ipa2g_on &&5365		b43_current_band(dev->wl) == NL80211_BAND_2GHZ);5366	if (phy6or5x) {5367		if (b43_is_40mhz(dev)) {5368			b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18,5369					tbl_tx_iqlo_cal_loft_ladder_40);5370			b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18,5371					tbl_tx_iqlo_cal_iqimb_ladder_40);5372		} else {5373			b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18,5374					tbl_tx_iqlo_cal_loft_ladder_20);5375			b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18,5376					tbl_tx_iqlo_cal_iqimb_ladder_20);5377		}5378	}5379 5380	if (phy->rev >= 19) {5381		/* TODO */5382	} else if (phy->rev >= 7) {5383		b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AD9);5384	} else {5385		b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9);5386	}5387 5388	if (!b43_is_40mhz(dev))5389		freq = 2500;5390	else5391		freq = 5000;5392 5393	if (nphy->mphase_cal_phase_id > 2)5394		b43_nphy_run_samples(dev, (b43_is_40mhz(dev) ? 40 : 20) * 8,5395				     0xFFFF, 0, true, false, false);5396	else5397		error = b43_nphy_tx_tone(dev, freq, 250, true, false, false);5398 5399	if (error == 0) {5400		if (nphy->mphase_cal_phase_id > 2) {5401			table = nphy->mphase_txcal_bestcoeffs;5402			length = 11;5403			if (dev->phy.rev < 3)5404				length -= 2;5405		} else {5406			if (!full && nphy->txiqlocal_coeffsvalid) {5407				table = nphy->txiqlocal_bestc;5408				length = 11;5409				if (dev->phy.rev < 3)5410					length -= 2;5411			} else {5412				full = true;5413				if (dev->phy.rev >= 3) {5414					table = tbl_tx_iqlo_cal_startcoefs_nphyrev3;5415					length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3;5416				} else {5417					table = tbl_tx_iqlo_cal_startcoefs;5418					length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS;5419				}5420			}5421		}5422 5423		b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length, table);5424 5425		if (full) {5426			if (dev->phy.rev >= 3)5427				max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3;5428			else5429				max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL;5430		} else {5431			if (dev->phy.rev >= 3)5432				max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3;5433			else5434				max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL;5435		}5436 5437		if (mphase) {5438			count = nphy->mphase_txcal_cmdidx;5439			numb = min(max,5440				(u16)(count + nphy->mphase_txcal_numcmds));5441		} else {5442			count = 0;5443			numb = max;5444		}5445 5446		for (; count < numb; count++) {5447			if (full) {5448				if (dev->phy.rev >= 3)5449					cmd = tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[count];5450				else5451					cmd = tbl_tx_iqlo_cal_cmds_fullcal[count];5452			} else {5453				if (dev->phy.rev >= 3)5454					cmd = tbl_tx_iqlo_cal_cmds_recal_nphyrev3[count];5455				else5456					cmd = tbl_tx_iqlo_cal_cmds_recal[count];5457			}5458 5459			core = (cmd & 0x3000) >> 12;5460			type = (cmd & 0x0F00) >> 8;5461 5462			if (phy6or5x && !updated[core]) {5463				b43_nphy_update_tx_cal_ladder(dev, core);5464				updated[core] = true;5465			}5466 5467			tmp = (params[core].ncorr[type] << 8) | 0x66;5468			b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDNNUM, tmp);5469 5470			if (type == 1 || type == 3 || type == 4) {5471				buffer[0] = b43_ntab_read(dev,5472						B43_NTAB16(15, 69 + core));5473				diq_start = buffer[0];5474				buffer[0] = 0;5475				b43_ntab_write(dev, B43_NTAB16(15, 69 + core),5476						0);5477			}5478 5479			b43_phy_write(dev, B43_NPHY_IQLOCAL_CMD, cmd);5480			for (i = 0; i < 2000; i++) {5481				tmp = b43_phy_read(dev, B43_NPHY_IQLOCAL_CMD);5482				if (tmp & 0xC000)5483					break;5484				udelay(10);5485			}5486 5487			b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,5488						buffer);5489			b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length,5490						buffer);5491 5492			if (type == 1 || type == 3 || type == 4)5493				buffer[0] = diq_start;5494		}5495 5496		if (mphase)5497			nphy->mphase_txcal_cmdidx = (numb >= max) ? 0 : numb;5498 5499		last = (dev->phy.rev < 3) ? 6 : 7;5500 5501		if (!mphase || nphy->mphase_cal_phase_id == last) {5502			b43_ntab_write_bulk(dev, B43_NTAB16(15, 96), 4, buffer);5503			b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 4, buffer);5504			if (dev->phy.rev < 3) {5505				buffer[0] = 0;5506				buffer[1] = 0;5507				buffer[2] = 0;5508				buffer[3] = 0;5509			}5510			b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4,5511						buffer);5512			b43_ntab_read_bulk(dev, B43_NTAB16(15, 101), 2,5513						buffer);5514			b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2,5515						buffer);5516			b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2,5517						buffer);5518			length = 11;5519			if (dev->phy.rev < 3)5520				length -= 2;5521			b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,5522						nphy->txiqlocal_bestc);5523			nphy->txiqlocal_coeffsvalid = true;5524			nphy->txiqlocal_chanspec.center_freq =5525						phy->chandef->chan->center_freq;5526			nphy->txiqlocal_chanspec.channel_type =5527					cfg80211_get_chandef_type(phy->chandef);5528		} else {5529			length = 11;5530			if (dev->phy.rev < 3)5531				length -= 2;5532			b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,5533						nphy->mphase_txcal_bestcoeffs);5534		}5535 5536		b43_nphy_stop_playback(dev);5537		b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0);5538	}5539 5540	b43_nphy_tx_cal_phy_cleanup(dev);5541	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, save);5542 5543	if (dev->phy.rev < 2 && (!mphase || nphy->mphase_cal_phase_id == last))5544		b43_nphy_tx_iq_workaround(dev);5545 5546	if (dev->phy.rev >= 4)5547		nphy->hang_avoid = avoid;5548 5549	b43_nphy_stay_in_carrier_search(dev, false);5550 5551	return error;5552}5553 5554/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/ReapplyTxCalCoeffs */5555static void b43_nphy_reapply_tx_cal_coeffs(struct b43_wldev *dev)5556{5557	struct b43_phy_n *nphy = dev->phy.n;5558	u8 i;5559	u16 buffer[7];5560	bool equal = true;5561 5562	if (!nphy->txiqlocal_coeffsvalid ||5563	    nphy->txiqlocal_chanspec.center_freq != dev->phy.chandef->chan->center_freq ||5564	    nphy->txiqlocal_chanspec.channel_type != cfg80211_get_chandef_type(dev->phy.chandef))5565		return;5566 5567	b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);5568	for (i = 0; i < 4; i++) {5569		if (buffer[i] != nphy->txiqlocal_bestc[i]) {5570			equal = false;5571			break;5572		}5573	}5574 5575	if (!equal) {5576		b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4,5577					nphy->txiqlocal_bestc);5578		for (i = 0; i < 4; i++)5579			buffer[i] = 0;5580		b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4,5581					buffer);5582		b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2,5583					&nphy->txiqlocal_bestc[5]);5584		b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2,5585					&nphy->txiqlocal_bestc[5]);5586	}5587}5588 5589/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIqRev2 */5590static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,5591			struct nphy_txgains target, u8 type, bool debug)5592{5593	struct b43_phy_n *nphy = dev->phy.n;5594	int i, j, index;5595	u8 rfctl[2];5596	u8 afectl_core;5597	u16 tmp[6];5598	u16 cur_hpf1, cur_hpf2, cur_lna;5599	u32 real, imag;5600	enum nl80211_band band;5601 5602	u8 use;5603	u16 cur_hpf;5604	u16 lna[3] = { 3, 3, 1 };5605	u16 hpf1[3] = { 7, 2, 0 };5606	u16 hpf2[3] = { 2, 0, 0 };5607	u32 power[3] = { };5608	u16 gain_save[2];5609	u16 cal_gain[2];5610	struct nphy_iqcal_params cal_params[2];5611	struct nphy_iq_est est;5612	int ret = 0;5613	bool playtone = true;5614	int desired = 13;5615 5616	b43_nphy_stay_in_carrier_search(dev, 1);5617 5618	if (dev->phy.rev < 2)5619		b43_nphy_reapply_tx_cal_coeffs(dev);5620	b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save);5621	for (i = 0; i < 2; i++) {5622		b43_nphy_iq_cal_gain_params(dev, i, target, &cal_params[i]);5623		cal_gain[i] = cal_params[i].cal_gain;5624	}5625	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, cal_gain);5626 5627	for (i = 0; i < 2; i++) {5628		if (i == 0) {5629			rfctl[0] = B43_NPHY_RFCTL_INTC1;5630			rfctl[1] = B43_NPHY_RFCTL_INTC2;5631			afectl_core = B43_NPHY_AFECTL_C1;5632		} else {5633			rfctl[0] = B43_NPHY_RFCTL_INTC2;5634			rfctl[1] = B43_NPHY_RFCTL_INTC1;5635			afectl_core = B43_NPHY_AFECTL_C2;5636		}5637 5638		tmp[1] = b43_phy_read(dev, B43_NPHY_RFSEQCA);5639		tmp[2] = b43_phy_read(dev, afectl_core);5640		tmp[3] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);5641		tmp[4] = b43_phy_read(dev, rfctl[0]);5642		tmp[5] = b43_phy_read(dev, rfctl[1]);5643 5644		b43_phy_maskset(dev, B43_NPHY_RFSEQCA,5645				~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF,5646				((1 - i) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));5647		b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN,5648				(1 - i));5649		b43_phy_set(dev, afectl_core, 0x0006);5650		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0006);5651 5652		band = b43_current_band(dev->wl);5653 5654		if (nphy->rxcalparams & 0xFF000000) {5655			if (band == NL80211_BAND_5GHZ)5656				b43_phy_write(dev, rfctl[0], 0x140);5657			else5658				b43_phy_write(dev, rfctl[0], 0x110);5659		} else {5660			if (band == NL80211_BAND_5GHZ)5661				b43_phy_write(dev, rfctl[0], 0x180);5662			else5663				b43_phy_write(dev, rfctl[0], 0x120);5664		}5665 5666		if (band == NL80211_BAND_5GHZ)5667			b43_phy_write(dev, rfctl[1], 0x148);5668		else5669			b43_phy_write(dev, rfctl[1], 0x114);5670 5671		if (nphy->rxcalparams & 0x10000) {5672			b43_radio_maskset(dev, B2055_C1_GENSPARE2, 0xFC,5673					(i + 1));5674			b43_radio_maskset(dev, B2055_C2_GENSPARE2, 0xFC,5675					(2 - i));5676		}5677 5678		for (j = 0; j < 4; j++) {5679			if (j < 3) {5680				cur_lna = lna[j];5681				cur_hpf1 = hpf1[j];5682				cur_hpf2 = hpf2[j];5683			} else {5684				if (power[1] > 10000) {5685					use = 1;5686					cur_hpf = cur_hpf1;5687					index = 2;5688				} else {5689					if (power[0] > 10000) {5690						use = 1;5691						cur_hpf = cur_hpf1;5692						index = 1;5693					} else {5694						index = 0;5695						use = 2;5696						cur_hpf = cur_hpf2;5697					}5698				}5699				cur_lna = lna[index];5700				cur_hpf1 = hpf1[index];5701				cur_hpf2 = hpf2[index];5702				cur_hpf += desired - hweight32(power[index]);5703				cur_hpf = clamp_val(cur_hpf, 0, 10);5704				if (use == 1)5705					cur_hpf1 = cur_hpf;5706				else5707					cur_hpf2 = cur_hpf;5708			}5709 5710			tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) |5711					(cur_lna << 2));5712			b43_nphy_rf_ctl_override(dev, 0x400, tmp[0], 3,5713									false);5714			b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);5715			b43_nphy_stop_playback(dev);5716 5717			if (playtone) {5718				ret = b43_nphy_tx_tone(dev, 4000,5719						(nphy->rxcalparams & 0xFFFF),5720						false, false, true);5721				playtone = false;5722			} else {5723				b43_nphy_run_samples(dev, 160, 0xFFFF, 0, false,5724						     false, true);5725			}5726 5727			if (ret == 0) {5728				if (j < 3) {5729					b43_nphy_rx_iq_est(dev, &est, 1024, 32,5730									false);5731					if (i == 0) {5732						real = est.i0_pwr;5733						imag = est.q0_pwr;5734					} else {5735						real = est.i1_pwr;5736						imag = est.q1_pwr;5737					}5738					power[i] = ((real + imag) / 1024) + 1;5739				} else {5740					b43_nphy_calc_rx_iq_comp(dev, 1 << i);5741				}5742				b43_nphy_stop_playback(dev);5743			}5744 5745			if (ret != 0)5746				break;5747		}5748 5749		b43_radio_mask(dev, B2055_C1_GENSPARE2, 0xFC);5750		b43_radio_mask(dev, B2055_C2_GENSPARE2, 0xFC);5751		b43_phy_write(dev, rfctl[1], tmp[5]);5752		b43_phy_write(dev, rfctl[0], tmp[4]);5753		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp[3]);5754		b43_phy_write(dev, afectl_core, tmp[2]);5755		b43_phy_write(dev, B43_NPHY_RFSEQCA, tmp[1]);5756 5757		if (ret != 0)5758			break;5759	}5760 5761	b43_nphy_rf_ctl_override(dev, 0x400, 0, 3, true);5762	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);5763	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save);5764 5765	b43_nphy_stay_in_carrier_search(dev, 0);5766 5767	return ret;5768}5769 5770static int b43_nphy_rev3_cal_rx_iq(struct b43_wldev *dev,5771			struct nphy_txgains target, u8 type, bool debug)5772{5773	return -1;5774}5775 5776/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIq */5777static int b43_nphy_cal_rx_iq(struct b43_wldev *dev,5778			struct nphy_txgains target, u8 type, bool debug)5779{5780	if (dev->phy.rev >= 7)5781		type = 0;5782 5783	if (dev->phy.rev >= 3)5784		return b43_nphy_rev3_cal_rx_iq(dev, target, type, debug);5785	else5786		return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug);5787}5788 5789/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */5790static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask)5791{5792	struct b43_phy *phy = &dev->phy;5793	struct b43_phy_n *nphy = phy->n;5794	/* u16 buf[16]; it's rev3+ */5795 5796	nphy->phyrxchain = mask;5797 5798	if (0 /* FIXME clk */)5799		return;5800 5801	b43_mac_suspend(dev);5802 5803	if (nphy->hang_avoid)5804		b43_nphy_stay_in_carrier_search(dev, true);5805 5806	b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN,5807			(mask & 0x3) << B43_NPHY_RFSEQCA_RXEN_SHIFT);5808 5809	if ((mask & 0x3) != 0x3) {5810		b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 1);5811		if (dev->phy.rev >= 3) {5812			/* TODO */5813		}5814	} else {5815		b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 0x1E);5816		if (dev->phy.rev >= 3) {5817			/* TODO */5818		}5819	}5820 5821	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);5822 5823	if (nphy->hang_avoid)5824		b43_nphy_stay_in_carrier_search(dev, false);5825 5826	b43_mac_enable(dev);5827}5828 5829static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev,5830							bool ignore_tssi)5831{5832	struct b43_phy *phy = &dev->phy;5833	struct b43_phy_n *nphy = dev->phy.n;5834	struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan;5835	struct b43_ppr *ppr = &nphy->tx_pwr_max_ppr;5836	u8 max; /* qdBm */5837 5838	if (nphy->tx_pwr_last_recalc_freq == channel->center_freq &&5839	    nphy->tx_pwr_last_recalc_limit == phy->desired_txpower)5840		return B43_TXPWR_RES_DONE;5841 5842	/* Make sure we have a clean PPR */5843	b43_ppr_clear(dev, ppr);5844 5845	/* HW limitations */5846	b43_ppr_load_max_from_sprom(dev, ppr, B43_BAND_2G);5847 5848	/* Regulatory & user settings */5849	max = INT_TO_Q52(phy->chandef->chan->max_power);5850	if (phy->desired_txpower)5851		max = min_t(u8, max, INT_TO_Q52(phy->desired_txpower));5852	b43_ppr_apply_max(dev, ppr, max);5853	if (b43_debug(dev, B43_DBG_XMITPOWER))5854		b43dbg(dev->wl, "Calculated TX power: " Q52_FMT "\n",5855		       Q52_ARG(b43_ppr_get_max(dev, ppr)));5856 5857	/* TODO: Enable this once we get gains working */5858#if 05859	/* Some extra gains */5860	hw_gain = 6; /* N-PHY specific */5861	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)5862		hw_gain += sprom->antenna_gain.a0;5863	else5864		hw_gain += sprom->antenna_gain.a1;5865	b43_ppr_add(dev, ppr, -hw_gain);5866#endif5867 5868	/* Make sure we didn't go too low */5869	b43_ppr_apply_min(dev, ppr, INT_TO_Q52(8));5870 5871	/* Apply */5872	b43_mac_suspend(dev);5873	b43_nphy_tx_power_ctl_setup(dev);5874	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) {5875		b43_maskset32(dev, B43_MMIO_MACCTL, ~0, B43_MACCTL_PHY_LOCK);5876		b43_read32(dev, B43_MMIO_MACCTL);5877		udelay(1);5878	}5879	b43_nphy_tx_power_ctrl(dev, nphy->txpwrctrl);5880	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12)5881		b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_PHY_LOCK, 0);5882	b43_mac_enable(dev);5883 5884	nphy->tx_pwr_last_recalc_freq = channel->center_freq;5885	nphy->tx_pwr_last_recalc_limit = phy->desired_txpower;5886 5887	return B43_TXPWR_RES_DONE;5888}5889 5890/**************************************************5891 * N-PHY init5892 **************************************************/5893 5894/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */5895static void b43_nphy_update_mimo_config(struct b43_wldev *dev, s32 preamble)5896{5897	u16 mimocfg = b43_phy_read(dev, B43_NPHY_MIMOCFG);5898 5899	mimocfg |= B43_NPHY_MIMOCFG_AUTO;5900	if (preamble == 1)5901		mimocfg |= B43_NPHY_MIMOCFG_GFMIX;5902	else5903		mimocfg &= ~B43_NPHY_MIMOCFG_GFMIX;5904 5905	b43_phy_write(dev, B43_NPHY_MIMOCFG, mimocfg);5906}5907 5908/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/BPHYInit */5909static void b43_nphy_bphy_init(struct b43_wldev *dev)5910{5911	unsigned int i;5912	u16 val;5913 5914	val = 0x1E1F;5915	for (i = 0; i < 16; i++) {5916		b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val);5917		val -= 0x202;5918	}5919	val = 0x3E3F;5920	for (i = 0; i < 16; i++) {5921		b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val);5922		val -= 0x202;5923	}5924	b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668);5925}5926 5927/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */5928static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init)5929{5930	if (dev->phy.rev >= 7)5931		return;5932 5933	if (dev->phy.rev >= 3) {5934		if (!init)5935			return;5936		if (0 /* FIXME */) {5937			b43_ntab_write(dev, B43_NTAB16(9, 2), 0x211);5938			b43_ntab_write(dev, B43_NTAB16(9, 3), 0x222);5939			b43_ntab_write(dev, B43_NTAB16(9, 8), 0x144);5940			b43_ntab_write(dev, B43_NTAB16(9, 12), 0x188);5941		}5942	} else {5943		b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0);5944		b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0);5945 5946		switch (dev->dev->bus_type) {5947#ifdef CONFIG_B43_BCMA5948		case B43_BUS_BCMA:5949			bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc,5950						 0xFC00, 0xFC00);5951			break;5952#endif5953#ifdef CONFIG_B43_SSB5954		case B43_BUS_SSB:5955			ssb_chipco_gpio_control(&dev->dev->sdev->bus->chipco,5956						0xFC00, 0xFC00);5957			break;5958#endif5959		}5960 5961		b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0);5962		b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, 0xFC00);5963		b43_maskset16(dev, B43_MMIO_GPIO_CONTROL, (~0xFC00 & 0xFFFF),5964			      0);5965 5966		if (init) {5967			b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);5968			b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);5969			b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);5970			b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);5971		}5972	}5973}5974 5975/* http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N */5976static int b43_phy_initn(struct b43_wldev *dev)5977{5978	struct ssb_sprom *sprom = dev->dev->bus_sprom;5979	struct b43_phy *phy = &dev->phy;5980	struct b43_phy_n *nphy = phy->n;5981	u8 tx_pwr_state;5982	struct nphy_txgains target;5983	u16 tmp;5984	bool do_rssi_cal;5985 5986	u16 clip[2];5987	bool do_cal = false;5988 5989	if ((dev->phy.rev >= 3) &&5990	   (sprom->boardflags_lo & B43_BFL_EXTLNA) &&5991	   (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)) {5992		switch (dev->dev->bus_type) {5993#ifdef CONFIG_B43_BCMA5994		case B43_BUS_BCMA:5995			bcma_cc_set32(&dev->dev->bdev->bus->drv_cc,5996				      BCMA_CC_CHIPCTL, 0x40);5997			break;5998#endif5999#ifdef CONFIG_B43_SSB6000		case B43_BUS_SSB:6001			chipco_set32(&dev->dev->sdev->bus->chipco,6002				     SSB_CHIPCO_CHIPCTL, 0x40);6003			break;6004#endif6005		}6006	}6007	nphy->use_int_tx_iq_lo_cal = b43_nphy_ipa(dev) ||6008		phy->rev >= 7 ||6009		(phy->rev >= 5 &&6010		 sprom->boardflags2_hi & B43_BFH2_INTERNDET_TXIQCAL);6011	nphy->deaf_count = 0;6012	b43_nphy_tables_init(dev);6013	nphy->crsminpwr_adjusted = false;6014	nphy->noisevars_adjusted = false;6015 6016	/* Clear all overrides */6017	if (dev->phy.rev >= 3) {6018		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, 0);6019		b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);6020		if (phy->rev >= 7) {6021			b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0);6022			b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER4, 0);6023			b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER5, 0);6024			b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER6, 0);6025		}6026		if (phy->rev >= 19) {6027			/* TODO */6028		}6029 6030		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, 0);6031		b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, 0);6032	} else {6033		b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);6034	}6035	b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 0);6036	b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 0);6037	if (dev->phy.rev < 6) {6038		b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0);6039		b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0);6040	}6041	b43_phy_mask(dev, B43_NPHY_RFSEQMODE,6042		     ~(B43_NPHY_RFSEQMODE_CAOVER |6043		       B43_NPHY_RFSEQMODE_TROVER));6044	if (dev->phy.rev >= 3)6045		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, 0);6046	b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 0);6047 6048	if (dev->phy.rev <= 2) {6049		tmp = (dev->phy.rev == 2) ? 0x3B : 0x40;6050		b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,6051				~B43_NPHY_BPHY_CTL3_SCALE,6052				tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT);6053	}6054	b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20);6055	b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20);6056 6057	if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD ||6058	    (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&6059	     dev->dev->board_type == BCMA_BOARD_TYPE_BCM943224M93))6060		b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0);6061	else6062		b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8);6063	b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 0xC8);6064	b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50);6065	b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30);6066 6067	if (phy->rev < 8)6068		b43_nphy_update_mimo_config(dev, nphy->preamble_override);6069 6070	b43_nphy_update_txrx_chain(dev);6071 6072	if (phy->rev < 2) {6073		b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8);6074		b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4);6075	}6076 6077	if (b43_nphy_ipa(dev)) {6078		b43_phy_set(dev, B43_NPHY_PAPD_EN0, 0x1);6079		b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ0, 0x007F,6080				nphy->papd_epsilon_offset[0] << 7);6081		b43_phy_set(dev, B43_NPHY_PAPD_EN1, 0x1);6082		b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ1, 0x007F,6083				nphy->papd_epsilon_offset[1] << 7);6084		b43_nphy_int_pa_set_tx_dig_filters(dev);6085	} else if (phy->rev >= 5) {6086		b43_nphy_ext_pa_set_tx_dig_filters(dev);6087	}6088 6089	b43_nphy_workarounds(dev);6090 6091	/* Reset CCA, in init code it differs a little from standard way */6092	b43_phy_force_clock(dev, 1);6093	tmp = b43_phy_read(dev, B43_NPHY_BBCFG);6094	b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA);6095	b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA);6096	b43_phy_force_clock(dev, 0);6097 6098	b43_mac_phy_clock_set(dev, true);6099 6100	if (phy->rev < 7) {6101		b43_nphy_pa_override(dev, false);6102		b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);6103		b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);6104		b43_nphy_pa_override(dev, true);6105	}6106 6107	b43_nphy_classifier(dev, 0, 0);6108	b43_nphy_read_clip_detection(dev, clip);6109	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)6110		b43_nphy_bphy_init(dev);6111 6112	tx_pwr_state = nphy->txpwrctrl;6113	b43_nphy_tx_power_ctrl(dev, false);6114	b43_nphy_tx_power_fix(dev);6115	b43_nphy_tx_power_ctl_idle_tssi(dev);6116	b43_nphy_tx_power_ctl_setup(dev);6117	b43_nphy_tx_gain_table_upload(dev);6118 6119	if (nphy->phyrxchain != 3)6120		b43_nphy_set_rx_core_state(dev, nphy->phyrxchain);6121	if (nphy->mphase_cal_phase_id > 0) {6122		;/* TODO PHY Periodic Calibration Multi-Phase Restart */6123	}6124 6125	do_rssi_cal = false;6126	if (phy->rev >= 3) {6127		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)6128			do_rssi_cal = !nphy->rssical_chanspec_2G.center_freq;6129		else6130			do_rssi_cal = !nphy->rssical_chanspec_5G.center_freq;6131 6132		if (do_rssi_cal)6133			b43_nphy_rssi_cal(dev);6134		else6135			b43_nphy_restore_rssi_cal(dev);6136	} else {6137		b43_nphy_rssi_cal(dev);6138	}6139 6140	if (!((nphy->measure_hold & 0x6) != 0)) {6141		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)6142			do_cal = !nphy->iqcal_chanspec_2G.center_freq;6143		else6144			do_cal = !nphy->iqcal_chanspec_5G.center_freq;6145 6146		if (nphy->mute)6147			do_cal = false;6148 6149		if (do_cal) {6150			target = b43_nphy_get_tx_gains(dev);6151 6152			if (nphy->antsel_type == 2)6153				b43_nphy_superswitch_init(dev, true);6154			if (nphy->perical != 2) {6155				b43_nphy_rssi_cal(dev);6156				if (phy->rev >= 3) {6157					nphy->cal_orig_pwr_idx[0] =6158					    nphy->txpwrindex[0].index_internal;6159					nphy->cal_orig_pwr_idx[1] =6160					    nphy->txpwrindex[1].index_internal;6161					/* TODO N PHY Pre Calibrate TX Gain */6162					target = b43_nphy_get_tx_gains(dev);6163				}6164				if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false))6165					if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0)6166						b43_nphy_save_cal(dev);6167			} else if (nphy->mphase_cal_phase_id == 0) {6168				;/* N PHY Periodic Calibration with arg 3 */6169			}6170		} else {6171			b43_nphy_restore_cal(dev);6172		}6173	}6174 6175	b43_nphy_tx_pwr_ctrl_coef_setup(dev);6176	b43_nphy_tx_power_ctrl(dev, tx_pwr_state);6177	b43_phy_write(dev, B43_NPHY_TXMACIF_HOLDOFF, 0x0015);6178	b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320);6179	if (phy->rev >= 3 && phy->rev <= 6)6180		b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x0032);6181	b43_nphy_tx_lpf_bw(dev);6182	if (phy->rev >= 3)6183		b43_nphy_spur_workaround(dev);6184 6185	return 0;6186}6187 6188/**************************************************6189 * Channel switching ops.6190 **************************************************/6191 6192static void b43_chantab_phy_upload(struct b43_wldev *dev,6193				   const struct b43_phy_n_sfo_cfg *e)6194{6195	b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a);6196	b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2);6197	b43_phy_write(dev, B43_NPHY_BW3, e->phy_bw3);6198	b43_phy_write(dev, B43_NPHY_BW4, e->phy_bw4);6199	b43_phy_write(dev, B43_NPHY_BW5, e->phy_bw5);6200	b43_phy_write(dev, B43_NPHY_BW6, e->phy_bw6);6201}6202 6203/* https://bcm-v4.sipsolutions.net/802.11/PmuSpurAvoid */6204static void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid)6205{6206	switch (dev->dev->bus_type) {6207#ifdef CONFIG_B43_BCMA6208	case B43_BUS_BCMA:6209		bcma_pmu_spuravoid_pllupdate(&dev->dev->bdev->bus->drv_cc,6210					     avoid);6211		break;6212#endif6213#ifdef CONFIG_B43_SSB6214	case B43_BUS_SSB:6215		ssb_pmu_spuravoid_pllupdate(&dev->dev->sdev->bus->chipco,6216					    avoid);6217		break;6218#endif6219	}6220}6221 6222/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */6223static void b43_nphy_channel_setup(struct b43_wldev *dev,6224				const struct b43_phy_n_sfo_cfg *e,6225				struct ieee80211_channel *new_channel)6226{6227	struct b43_phy *phy = &dev->phy;6228	struct b43_phy_n *nphy = dev->phy.n;6229	int ch = new_channel->hw_value;6230	u16 tmp16;6231 6232	if (new_channel->band == NL80211_BAND_5GHZ) {6233		/* Switch to 2 GHz for a moment to access B43_PHY_B_BBCFG */6234		b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);6235 6236		tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR);6237		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4);6238		/* Put BPHY in the reset */6239		b43_phy_set(dev, B43_PHY_B_BBCFG,6240			    B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX);6241		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16);6242		b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ);6243	} else if (new_channel->band == NL80211_BAND_2GHZ) {6244		b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);6245		tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR);6246		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4);6247		/* Take BPHY out of the reset */6248		b43_phy_mask(dev, B43_PHY_B_BBCFG,6249			     ~(B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX) & 0xffff);6250		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16);6251	}6252 6253	b43_chantab_phy_upload(dev, e);6254 6255	if (new_channel->hw_value == 14) {6256		b43_nphy_classifier(dev, 2, 0);6257		b43_phy_set(dev, B43_PHY_B_TEST, 0x0800);6258	} else {6259		b43_nphy_classifier(dev, 2, 2);6260		if (new_channel->band == NL80211_BAND_2GHZ)6261			b43_phy_mask(dev, B43_PHY_B_TEST, ~0x840);6262	}6263 6264	if (!nphy->txpwrctrl)6265		b43_nphy_tx_power_fix(dev);6266 6267	if (dev->phy.rev < 3)6268		b43_nphy_adjust_lna_gain_table(dev);6269 6270	b43_nphy_tx_lpf_bw(dev);6271 6272	if (dev->phy.rev >= 3 &&6273	    dev->phy.n->spur_avoid != B43_SPUR_AVOID_DISABLE) {6274		u8 spuravoid = 0;6275 6276		if (dev->phy.n->spur_avoid == B43_SPUR_AVOID_FORCE) {6277			spuravoid = 1;6278		} else if (phy->rev >= 19) {6279			/* TODO */6280		} else if (phy->rev >= 18) {6281			/* TODO */6282		} else if (phy->rev >= 17) {6283			/* TODO: Off for channels 1-11, but check 12-14! */6284		} else if (phy->rev >= 16) {6285			/* TODO: Off for 2 GHz, but check 5 GHz! */6286		} else if (phy->rev >= 7) {6287			if (!b43_is_40mhz(dev)) { /* 20MHz */6288				if (ch == 13 || ch == 14 || ch == 153)6289					spuravoid = 1;6290			} else { /* 40 MHz */6291				if (ch == 54)6292					spuravoid = 1;6293			}6294		} else {6295			if (!b43_is_40mhz(dev)) { /* 20MHz */6296				if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14)6297					spuravoid = 1;6298			} else { /* 40MHz */6299				if (nphy->aband_spurwar_en &&6300				    (ch == 38 || ch == 102 || ch == 118))6301					spuravoid = dev->dev->chip_id == 0x4716;6302			}6303		}6304 6305		b43_nphy_pmu_spur_avoid(dev, spuravoid);6306 6307		b43_mac_switch_freq(dev, spuravoid);6308 6309		if (dev->phy.rev == 3 || dev->phy.rev == 4)6310			b43_wireless_core_phy_pll_reset(dev);6311 6312		if (spuravoid)6313			b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTRX);6314		else6315			b43_phy_mask(dev, B43_NPHY_BBCFG,6316				     ~B43_NPHY_BBCFG_RSTRX & 0xFFFF);6317 6318		b43_nphy_reset_cca(dev);6319 6320		/* wl sets useless phy_isspuravoid here */6321	}6322 6323	b43_phy_write(dev, B43_NPHY_NDATAT_DUP40, 0x3830);6324 6325	if (phy->rev >= 3)6326		b43_nphy_spur_workaround(dev);6327}6328 6329/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */6330static int b43_nphy_set_channel(struct b43_wldev *dev,6331				struct ieee80211_channel *channel,6332				enum nl80211_channel_type channel_type)6333{6334	struct b43_phy *phy = &dev->phy;6335 6336	const struct b43_nphy_channeltab_entry_rev2 *tabent_r2 = NULL;6337	const struct b43_nphy_channeltab_entry_rev3 *tabent_r3 = NULL;6338	const struct b43_nphy_chantabent_rev7 *tabent_r7 = NULL;6339	const struct b43_nphy_chantabent_rev7_2g *tabent_r7_2g = NULL;6340 6341	u8 tmp;6342 6343	if (phy->rev >= 19) {6344		return -ESRCH;6345		/* TODO */6346	} else if (phy->rev >= 7) {6347		r2057_get_chantabent_rev7(dev, channel->center_freq,6348					  &tabent_r7, &tabent_r7_2g);6349		if (!tabent_r7 && !tabent_r7_2g)6350			return -ESRCH;6351	} else if (phy->rev >= 3) {6352		tabent_r3 = b43_nphy_get_chantabent_rev3(dev,6353							channel->center_freq);6354		if (!tabent_r3)6355			return -ESRCH;6356	} else {6357		tabent_r2 = b43_nphy_get_chantabent_rev2(dev,6358							channel->hw_value);6359		if (!tabent_r2)6360			return -ESRCH;6361	}6362 6363	/* Channel is set later in common code, but we need to set it on our6364	   own to let this function's subcalls work properly. */6365	phy->channel = channel->hw_value;6366 6367#if 06368	if (b43_channel_type_is_40mhz(phy->channel_type) !=6369		b43_channel_type_is_40mhz(channel_type))6370		; /* TODO: BMAC BW Set (channel_type) */6371#endif6372 6373	if (channel_type == NL80211_CHAN_HT40PLUS) {6374		b43_phy_set(dev, B43_NPHY_RXCTL, B43_NPHY_RXCTL_BSELU20);6375		if (phy->rev >= 7)6376			b43_phy_set(dev, 0x310, 0x8000);6377	} else if (channel_type == NL80211_CHAN_HT40MINUS) {6378		b43_phy_mask(dev, B43_NPHY_RXCTL, ~B43_NPHY_RXCTL_BSELU20);6379		if (phy->rev >= 7)6380			b43_phy_mask(dev, 0x310, 0x7fff);6381	}6382 6383	if (phy->rev >= 19) {6384		/* TODO */6385	} else if (phy->rev >= 7) {6386		const struct b43_phy_n_sfo_cfg *phy_regs = tabent_r7 ?6387			&(tabent_r7->phy_regs) : &(tabent_r7_2g->phy_regs);6388 6389		if (phy->radio_rev <= 4 || phy->radio_rev == 6) {6390			tmp = (channel->band == NL80211_BAND_5GHZ) ? 2 : 0;6391			b43_radio_maskset(dev, R2057_TIA_CONFIG_CORE0, ~2, tmp);6392			b43_radio_maskset(dev, R2057_TIA_CONFIG_CORE1, ~2, tmp);6393		}6394 6395		b43_radio_2057_setup(dev, tabent_r7, tabent_r7_2g);6396		b43_nphy_channel_setup(dev, phy_regs, channel);6397	} else if (phy->rev >= 3) {6398		tmp = (channel->band == NL80211_BAND_5GHZ) ? 4 : 0;6399		b43_radio_maskset(dev, 0x08, 0xFFFB, tmp);6400		b43_radio_2056_setup(dev, tabent_r3);6401		b43_nphy_channel_setup(dev, &(tabent_r3->phy_regs), channel);6402	} else {6403		tmp = (channel->band == NL80211_BAND_5GHZ) ? 0x0020 : 0x0050;6404		b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp);6405		b43_radio_2055_setup(dev, tabent_r2);6406		b43_nphy_channel_setup(dev, &(tabent_r2->phy_regs), channel);6407	}6408 6409	return 0;6410}6411 6412/**************************************************6413 * Basic PHY ops.6414 **************************************************/6415 6416static int b43_nphy_op_allocate(struct b43_wldev *dev)6417{6418	struct b43_phy_n *nphy;6419 6420	nphy = kzalloc(sizeof(*nphy), GFP_KERNEL);6421	if (!nphy)6422		return -ENOMEM;6423 6424	dev->phy.n = nphy;6425 6426	return 0;6427}6428 6429static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)6430{6431	struct b43_phy *phy = &dev->phy;6432	struct b43_phy_n *nphy = phy->n;6433	struct ssb_sprom *sprom = dev->dev->bus_sprom;6434 6435	memset(nphy, 0, sizeof(*nphy));6436 6437	nphy->hang_avoid = (phy->rev == 3 || phy->rev == 4);6438	nphy->spur_avoid = (phy->rev >= 3) ?6439				B43_SPUR_AVOID_AUTO : B43_SPUR_AVOID_DISABLE;6440	nphy->gain_boost = true; /* this way we follow wl, assume it is true */6441	nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */6442	nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */6443	nphy->perical = 2; /* avoid additional rssi cal on init (like wl) */6444	/* 128 can mean disabled-by-default state of TX pwr ctl. Max value is6445	 * 0x7f == 127 and we check for 128 when restoring TX pwr ctl. */6446	nphy->tx_pwr_idx[0] = 128;6447	nphy->tx_pwr_idx[1] = 128;6448 6449	/* Hardware TX power control and 5GHz power gain */6450	nphy->txpwrctrl = false;6451	nphy->pwg_gain_5ghz = false;6452	if (dev->phy.rev >= 3 ||6453	    (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&6454	     (dev->dev->core_rev == 11 || dev->dev->core_rev == 12))) {6455		nphy->txpwrctrl = true;6456		nphy->pwg_gain_5ghz = true;6457	} else if (sprom->revision >= 4) {6458		if (dev->phy.rev >= 2 &&6459		    (sprom->boardflags2_lo & B43_BFL2_TXPWRCTRL_EN)) {6460			nphy->txpwrctrl = true;6461#ifdef CONFIG_B43_SSB6462			if (dev->dev->bus_type == B43_BUS_SSB &&6463			    dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI) {6464				struct pci_dev *pdev =6465					dev->dev->sdev->bus->host_pci;6466				if (pdev->device == 0x4328 ||6467				    pdev->device == 0x432a)6468					nphy->pwg_gain_5ghz = true;6469			}6470#endif6471		} else if (sprom->boardflags2_lo & B43_BFL2_5G_PWRGAIN) {6472			nphy->pwg_gain_5ghz = true;6473		}6474	}6475 6476	if (dev->phy.rev >= 3) {6477		nphy->ipa2g_on = sprom->fem.ghz2.extpa_gain == 2;6478		nphy->ipa5g_on = sprom->fem.ghz5.extpa_gain == 2;6479	}6480}6481 6482static void b43_nphy_op_free(struct b43_wldev *dev)6483{6484	struct b43_phy *phy = &dev->phy;6485	struct b43_phy_n *nphy = phy->n;6486 6487	kfree(nphy);6488	phy->n = NULL;6489}6490 6491static int b43_nphy_op_init(struct b43_wldev *dev)6492{6493	return b43_phy_initn(dev);6494}6495 6496static inline void check_phyreg(struct b43_wldev *dev, u16 offset)6497{6498#if B43_DEBUG6499	if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) {6500		/* OFDM registers are onnly available on A/G-PHYs */6501		b43err(dev->wl, "Invalid OFDM PHY access at "6502		       "0x%04X on N-PHY\n", offset);6503		dump_stack();6504	}6505	if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) {6506		/* Ext-G registers are only available on G-PHYs */6507		b43err(dev->wl, "Invalid EXT-G PHY access at "6508		       "0x%04X on N-PHY\n", offset);6509		dump_stack();6510	}6511#endif /* B43_DEBUG */6512}6513 6514static void b43_nphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,6515				 u16 set)6516{6517	check_phyreg(dev, reg);6518	b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);6519	b43_maskset16(dev, B43_MMIO_PHY_DATA, mask, set);6520	dev->phy.writes_counter = 1;6521}6522 6523static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg)6524{6525	/* Register 1 is a 32-bit register. */6526	B43_WARN_ON(dev->phy.rev < 7 && reg == 1);6527 6528	if (dev->phy.rev >= 7)6529		reg |= 0x200; /* Radio 0x2057 */6530	else6531		reg |= 0x100;6532 6533	b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);6534	return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);6535}6536 6537static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)6538{6539	/* Register 1 is a 32-bit register. */6540	B43_WARN_ON(dev->phy.rev < 7 && reg == 1);6541 6542	b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);6543	b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);6544}6545 6546/* https://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */6547static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,6548					bool blocked)6549{6550	struct b43_phy *phy = &dev->phy;6551 6552	if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)6553		b43err(dev->wl, "MAC not suspended\n");6554 6555	if (blocked) {6556		if (phy->rev >= 19) {6557			/* TODO */6558		} else if (phy->rev >= 8) {6559			b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,6560				     ~B43_NPHY_RFCTL_CMD_CHIP0PU);6561		} else if (phy->rev >= 7) {6562			/* Nothing needed */6563		} else if (phy->rev >= 3) {6564			b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,6565				     ~B43_NPHY_RFCTL_CMD_CHIP0PU);6566 6567			b43_radio_mask(dev, 0x09, ~0x2);6568 6569			b43_radio_write(dev, 0x204D, 0);6570			b43_radio_write(dev, 0x2053, 0);6571			b43_radio_write(dev, 0x2058, 0);6572			b43_radio_write(dev, 0x205E, 0);6573			b43_radio_mask(dev, 0x2062, ~0xF0);6574			b43_radio_write(dev, 0x2064, 0);6575 6576			b43_radio_write(dev, 0x304D, 0);6577			b43_radio_write(dev, 0x3053, 0);6578			b43_radio_write(dev, 0x3058, 0);6579			b43_radio_write(dev, 0x305E, 0);6580			b43_radio_mask(dev, 0x3062, ~0xF0);6581			b43_radio_write(dev, 0x3064, 0);6582		}6583	} else {6584		if (phy->rev >= 19) {6585			/* TODO */6586		} else if (phy->rev >= 7) {6587			if (!dev->phy.radio_on)6588				b43_radio_2057_init(dev);6589			b43_switch_channel(dev, dev->phy.channel);6590		} else if (phy->rev >= 3) {6591			if (!dev->phy.radio_on)6592				b43_radio_init2056(dev);6593			b43_switch_channel(dev, dev->phy.channel);6594		} else {6595			b43_radio_init2055(dev);6596		}6597	}6598}6599 6600/* https://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */6601static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)6602{6603	struct b43_phy *phy = &dev->phy;6604	u16 override = on ? 0x0 : 0x7FFF;6605	u16 core = on ? 0xD : 0x00FD;6606 6607	if (phy->rev >= 19) {6608		/* TODO */6609	} else if (phy->rev >= 3) {6610		if (on) {6611			b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);6612			b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);6613			b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);6614			b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);6615		} else {6616			b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);6617			b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);6618			b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);6619			b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);6620		}6621	} else {6622		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);6623	}6624}6625 6626static int b43_nphy_op_switch_channel(struct b43_wldev *dev,6627				      unsigned int new_channel)6628{6629	struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan;6630	enum nl80211_channel_type channel_type =6631		cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef);6632 6633	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {6634		if ((new_channel < 1) || (new_channel > 14))6635			return -EINVAL;6636	} else {6637		if (new_channel > 200)6638			return -EINVAL;6639	}6640 6641	return b43_nphy_set_channel(dev, channel, channel_type);6642}6643 6644static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev)6645{6646	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)6647		return 1;6648	return 36;6649}6650 6651const struct b43_phy_operations b43_phyops_n = {6652	.allocate		= b43_nphy_op_allocate,6653	.free			= b43_nphy_op_free,6654	.prepare_structs	= b43_nphy_op_prepare_structs,6655	.init			= b43_nphy_op_init,6656	.phy_maskset		= b43_nphy_op_maskset,6657	.radio_read		= b43_nphy_op_radio_read,6658	.radio_write		= b43_nphy_op_radio_write,6659	.software_rfkill	= b43_nphy_op_software_rfkill,6660	.switch_analog		= b43_nphy_op_switch_analog,6661	.switch_channel		= b43_nphy_op_switch_channel,6662	.get_default_chan	= b43_nphy_op_get_default_chan,6663	.recalc_txpower		= b43_nphy_op_recalc_txpower,6664};6665