162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci  Broadcom B43 wireless driver
562306a36Sopenharmony_ci  IEEE 802.11n PHY support
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci  Copyright (c) 2008 Michael Buesch <m@bues.ch>
862306a36Sopenharmony_ci  Copyright (c) 2010-2011 Rafał Miłecki <zajec5@gmail.com>
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci*/
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/cordic.h>
1462306a36Sopenharmony_ci#include <linux/delay.h>
1562306a36Sopenharmony_ci#include <linux/slab.h>
1662306a36Sopenharmony_ci#include <linux/types.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#include "b43.h"
1962306a36Sopenharmony_ci#include "phy_n.h"
2062306a36Sopenharmony_ci#include "tables_nphy.h"
2162306a36Sopenharmony_ci#include "radio_2055.h"
2262306a36Sopenharmony_ci#include "radio_2056.h"
2362306a36Sopenharmony_ci#include "radio_2057.h"
2462306a36Sopenharmony_ci#include "main.h"
2562306a36Sopenharmony_ci#include "ppr.h"
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_cistruct nphy_txgains {
2862306a36Sopenharmony_ci	u16 tx_lpf[2];
2962306a36Sopenharmony_ci	u16 txgm[2];
3062306a36Sopenharmony_ci	u16 pga[2];
3162306a36Sopenharmony_ci	u16 pad[2];
3262306a36Sopenharmony_ci	u16 ipa[2];
3362306a36Sopenharmony_ci};
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cistruct nphy_iqcal_params {
3662306a36Sopenharmony_ci	u16 tx_lpf;
3762306a36Sopenharmony_ci	u16 txgm;
3862306a36Sopenharmony_ci	u16 pga;
3962306a36Sopenharmony_ci	u16 pad;
4062306a36Sopenharmony_ci	u16 ipa;
4162306a36Sopenharmony_ci	u16 cal_gain;
4262306a36Sopenharmony_ci	u16 ncorr[5];
4362306a36Sopenharmony_ci};
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cistruct nphy_iq_est {
4662306a36Sopenharmony_ci	s32 iq0_prod;
4762306a36Sopenharmony_ci	u32 i0_pwr;
4862306a36Sopenharmony_ci	u32 q0_pwr;
4962306a36Sopenharmony_ci	s32 iq1_prod;
5062306a36Sopenharmony_ci	u32 i1_pwr;
5162306a36Sopenharmony_ci	u32 q1_pwr;
5262306a36Sopenharmony_ci};
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cienum b43_nphy_rf_sequence {
5562306a36Sopenharmony_ci	B43_RFSEQ_RX2TX,
5662306a36Sopenharmony_ci	B43_RFSEQ_TX2RX,
5762306a36Sopenharmony_ci	B43_RFSEQ_RESET2RX,
5862306a36Sopenharmony_ci	B43_RFSEQ_UPDATE_GAINH,
5962306a36Sopenharmony_ci	B43_RFSEQ_UPDATE_GAINL,
6062306a36Sopenharmony_ci	B43_RFSEQ_UPDATE_GAINU,
6162306a36Sopenharmony_ci};
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cienum n_rf_ctl_over_cmd {
6462306a36Sopenharmony_ci	N_RF_CTL_OVER_CMD_RXRF_PU = 0,
6562306a36Sopenharmony_ci	N_RF_CTL_OVER_CMD_RX_PU = 1,
6662306a36Sopenharmony_ci	N_RF_CTL_OVER_CMD_TX_PU = 2,
6762306a36Sopenharmony_ci	N_RF_CTL_OVER_CMD_RX_GAIN = 3,
6862306a36Sopenharmony_ci	N_RF_CTL_OVER_CMD_TX_GAIN = 4,
6962306a36Sopenharmony_ci};
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_cienum n_intc_override {
7262306a36Sopenharmony_ci	N_INTC_OVERRIDE_OFF = 0,
7362306a36Sopenharmony_ci	N_INTC_OVERRIDE_TRSW = 1,
7462306a36Sopenharmony_ci	N_INTC_OVERRIDE_PA = 2,
7562306a36Sopenharmony_ci	N_INTC_OVERRIDE_EXT_LNA_PU = 3,
7662306a36Sopenharmony_ci	N_INTC_OVERRIDE_EXT_LNA_GAIN = 4,
7762306a36Sopenharmony_ci};
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_cienum n_rssi_type {
8062306a36Sopenharmony_ci	N_RSSI_W1 = 0,
8162306a36Sopenharmony_ci	N_RSSI_W2,
8262306a36Sopenharmony_ci	N_RSSI_NB,
8362306a36Sopenharmony_ci	N_RSSI_IQ,
8462306a36Sopenharmony_ci	N_RSSI_TSSI_2G,
8562306a36Sopenharmony_ci	N_RSSI_TSSI_5G,
8662306a36Sopenharmony_ci	N_RSSI_TBD,
8762306a36Sopenharmony_ci};
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cienum n_rail_type {
9062306a36Sopenharmony_ci	N_RAIL_I = 0,
9162306a36Sopenharmony_ci	N_RAIL_Q = 1,
9262306a36Sopenharmony_ci};
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cistatic inline bool b43_nphy_ipa(struct b43_wldev *dev)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	enum nl80211_band band = b43_current_band(dev->wl);
9762306a36Sopenharmony_ci	return ((dev->phy.n->ipa2g_on && band == NL80211_BAND_2GHZ) ||
9862306a36Sopenharmony_ci		(dev->phy.n->ipa5g_on && band == NL80211_BAND_5GHZ));
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreGetState */
10262306a36Sopenharmony_cistatic u8 b43_nphy_get_rx_core_state(struct b43_wldev *dev)
10362306a36Sopenharmony_ci{
10462306a36Sopenharmony_ci	return (b43_phy_read(dev, B43_NPHY_RFSEQCA) & B43_NPHY_RFSEQCA_RXEN) >>
10562306a36Sopenharmony_ci		B43_NPHY_RFSEQCA_RXEN_SHIFT;
10662306a36Sopenharmony_ci}
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci/**************************************************
10962306a36Sopenharmony_ci * RF (just without b43_nphy_rf_ctl_intc_override)
11062306a36Sopenharmony_ci **************************************************/
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */
11362306a36Sopenharmony_cistatic void b43_nphy_force_rf_sequence(struct b43_wldev *dev,
11462306a36Sopenharmony_ci				       enum b43_nphy_rf_sequence seq)
11562306a36Sopenharmony_ci{
11662306a36Sopenharmony_ci	static const u16 trigger[] = {
11762306a36Sopenharmony_ci		[B43_RFSEQ_RX2TX]		= B43_NPHY_RFSEQTR_RX2TX,
11862306a36Sopenharmony_ci		[B43_RFSEQ_TX2RX]		= B43_NPHY_RFSEQTR_TX2RX,
11962306a36Sopenharmony_ci		[B43_RFSEQ_RESET2RX]		= B43_NPHY_RFSEQTR_RST2RX,
12062306a36Sopenharmony_ci		[B43_RFSEQ_UPDATE_GAINH]	= B43_NPHY_RFSEQTR_UPGH,
12162306a36Sopenharmony_ci		[B43_RFSEQ_UPDATE_GAINL]	= B43_NPHY_RFSEQTR_UPGL,
12262306a36Sopenharmony_ci		[B43_RFSEQ_UPDATE_GAINU]	= B43_NPHY_RFSEQTR_UPGU,
12362306a36Sopenharmony_ci	};
12462306a36Sopenharmony_ci	int i;
12562306a36Sopenharmony_ci	u16 seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	B43_WARN_ON(seq >= ARRAY_SIZE(trigger));
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	b43_phy_set(dev, B43_NPHY_RFSEQMODE,
13062306a36Sopenharmony_ci		    B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER);
13162306a36Sopenharmony_ci	b43_phy_set(dev, B43_NPHY_RFSEQTR, trigger[seq]);
13262306a36Sopenharmony_ci	for (i = 0; i < 200; i++) {
13362306a36Sopenharmony_ci		if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & trigger[seq]))
13462306a36Sopenharmony_ci			goto ok;
13562306a36Sopenharmony_ci		msleep(1);
13662306a36Sopenharmony_ci	}
13762306a36Sopenharmony_ci	b43err(dev->wl, "RF sequence status timeout\n");
13862306a36Sopenharmony_ciok:
13962306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
14062306a36Sopenharmony_ci}
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cistatic void b43_nphy_rf_ctl_override_rev19(struct b43_wldev *dev, u16 field,
14362306a36Sopenharmony_ci					   u16 value, u8 core, bool off,
14462306a36Sopenharmony_ci					   u8 override_id)
14562306a36Sopenharmony_ci{
14662306a36Sopenharmony_ci	/* TODO */
14762306a36Sopenharmony_ci}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverrideRev7 */
15062306a36Sopenharmony_cistatic void b43_nphy_rf_ctl_override_rev7(struct b43_wldev *dev, u16 field,
15162306a36Sopenharmony_ci					  u16 value, u8 core, bool off,
15262306a36Sopenharmony_ci					  u8 override)
15362306a36Sopenharmony_ci{
15462306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
15562306a36Sopenharmony_ci	const struct nphy_rf_control_override_rev7 *e;
15662306a36Sopenharmony_ci	u16 en_addrs[3][2] = {
15762306a36Sopenharmony_ci		{ 0x0E7, 0x0EC }, { 0x342, 0x343 }, { 0x346, 0x347 }
15862306a36Sopenharmony_ci	};
15962306a36Sopenharmony_ci	u16 en_addr;
16062306a36Sopenharmony_ci	u16 en_mask = field;
16162306a36Sopenharmony_ci	u16 val_addr;
16262306a36Sopenharmony_ci	u8 i;
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	if (phy->rev >= 19 || phy->rev < 3) {
16562306a36Sopenharmony_ci		B43_WARN_ON(1);
16662306a36Sopenharmony_ci		return;
16762306a36Sopenharmony_ci	}
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	/* Remember: we can get NULL! */
17062306a36Sopenharmony_ci	e = b43_nphy_get_rf_ctl_over_rev7(dev, field, override);
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	for (i = 0; i < 2; i++) {
17362306a36Sopenharmony_ci		if (override >= ARRAY_SIZE(en_addrs)) {
17462306a36Sopenharmony_ci			b43err(dev->wl, "Invalid override value %d\n", override);
17562306a36Sopenharmony_ci			return;
17662306a36Sopenharmony_ci		}
17762306a36Sopenharmony_ci		en_addr = en_addrs[override][i];
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci		if (e)
18062306a36Sopenharmony_ci			val_addr = (i == 0) ? e->val_addr_core0 : e->val_addr_core1;
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci		if (off) {
18362306a36Sopenharmony_ci			b43_phy_mask(dev, en_addr, ~en_mask);
18462306a36Sopenharmony_ci			if (e) /* Do it safer, better than wl */
18562306a36Sopenharmony_ci				b43_phy_mask(dev, val_addr, ~e->val_mask);
18662306a36Sopenharmony_ci		} else {
18762306a36Sopenharmony_ci			if (!core || (core & (1 << i))) {
18862306a36Sopenharmony_ci				b43_phy_set(dev, en_addr, en_mask);
18962306a36Sopenharmony_ci				if (e)
19062306a36Sopenharmony_ci					b43_phy_maskset(dev, val_addr, ~e->val_mask, (value << e->val_shift));
19162306a36Sopenharmony_ci			}
19262306a36Sopenharmony_ci		}
19362306a36Sopenharmony_ci	}
19462306a36Sopenharmony_ci}
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverideOneToMany */
19762306a36Sopenharmony_cistatic void b43_nphy_rf_ctl_override_one_to_many(struct b43_wldev *dev,
19862306a36Sopenharmony_ci						 enum n_rf_ctl_over_cmd cmd,
19962306a36Sopenharmony_ci						 u16 value, u8 core, bool off)
20062306a36Sopenharmony_ci{
20162306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
20262306a36Sopenharmony_ci	u16 tmp;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	B43_WARN_ON(phy->rev < 7);
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	switch (cmd) {
20762306a36Sopenharmony_ci	case N_RF_CTL_OVER_CMD_RXRF_PU:
20862306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_rev7(dev, 0x20, value, core, off, 1);
20962306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_rev7(dev, 0x10, value, core, off, 1);
21062306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_rev7(dev, 0x08, value, core, off, 1);
21162306a36Sopenharmony_ci		break;
21262306a36Sopenharmony_ci	case N_RF_CTL_OVER_CMD_RX_PU:
21362306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_rev7(dev, 0x4, value, core, off, 1);
21462306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 1);
21562306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_rev7(dev, 0x1, value, core, off, 1);
21662306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 2);
21762306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_rev7(dev, 0x0800, 0, core, off, 1);
21862306a36Sopenharmony_ci		break;
21962306a36Sopenharmony_ci	case N_RF_CTL_OVER_CMD_TX_PU:
22062306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_rev7(dev, 0x4, value, core, off, 0);
22162306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 1);
22262306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_rev7(dev, 0x1, value, core, off, 2);
22362306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_rev7(dev, 0x0800, 1, core, off, 1);
22462306a36Sopenharmony_ci		break;
22562306a36Sopenharmony_ci	case N_RF_CTL_OVER_CMD_RX_GAIN:
22662306a36Sopenharmony_ci		tmp = value & 0xFF;
22762306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_rev7(dev, 0x0800, tmp, core, off, 0);
22862306a36Sopenharmony_ci		tmp = value >> 8;
22962306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_rev7(dev, 0x6000, tmp, core, off, 0);
23062306a36Sopenharmony_ci		break;
23162306a36Sopenharmony_ci	case N_RF_CTL_OVER_CMD_TX_GAIN:
23262306a36Sopenharmony_ci		tmp = value & 0x7FFF;
23362306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_rev7(dev, 0x1000, tmp, core, off, 0);
23462306a36Sopenharmony_ci		tmp = value >> 14;
23562306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_rev7(dev, 0x4000, tmp, core, off, 0);
23662306a36Sopenharmony_ci		break;
23762306a36Sopenharmony_ci	}
23862306a36Sopenharmony_ci}
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */
24162306a36Sopenharmony_cistatic void b43_nphy_rf_ctl_override(struct b43_wldev *dev, u16 field,
24262306a36Sopenharmony_ci				     u16 value, u8 core, bool off)
24362306a36Sopenharmony_ci{
24462306a36Sopenharmony_ci	int i;
24562306a36Sopenharmony_ci	u8 index = fls(field);
24662306a36Sopenharmony_ci	u8 addr, en_addr, val_addr;
24762306a36Sopenharmony_ci	/* we expect only one bit set */
24862306a36Sopenharmony_ci	B43_WARN_ON(field & (~(1 << (index - 1))));
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	if (dev->phy.rev >= 3) {
25162306a36Sopenharmony_ci		const struct nphy_rf_control_override_rev3 *rf_ctrl;
25262306a36Sopenharmony_ci		for (i = 0; i < 2; i++) {
25362306a36Sopenharmony_ci			if (index == 0 || index == 16) {
25462306a36Sopenharmony_ci				b43err(dev->wl,
25562306a36Sopenharmony_ci					"Unsupported RF Ctrl Override call\n");
25662306a36Sopenharmony_ci				return;
25762306a36Sopenharmony_ci			}
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci			rf_ctrl = &tbl_rf_control_override_rev3[index - 1];
26062306a36Sopenharmony_ci			en_addr = B43_PHY_N((i == 0) ?
26162306a36Sopenharmony_ci				rf_ctrl->en_addr0 : rf_ctrl->en_addr1);
26262306a36Sopenharmony_ci			val_addr = B43_PHY_N((i == 0) ?
26362306a36Sopenharmony_ci				rf_ctrl->val_addr0 : rf_ctrl->val_addr1);
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci			if (off) {
26662306a36Sopenharmony_ci				b43_phy_mask(dev, en_addr, ~(field));
26762306a36Sopenharmony_ci				b43_phy_mask(dev, val_addr,
26862306a36Sopenharmony_ci						~(rf_ctrl->val_mask));
26962306a36Sopenharmony_ci			} else {
27062306a36Sopenharmony_ci				if (core == 0 || ((1 << i) & core)) {
27162306a36Sopenharmony_ci					b43_phy_set(dev, en_addr, field);
27262306a36Sopenharmony_ci					b43_phy_maskset(dev, val_addr,
27362306a36Sopenharmony_ci						~(rf_ctrl->val_mask),
27462306a36Sopenharmony_ci						(value << rf_ctrl->val_shift));
27562306a36Sopenharmony_ci				}
27662306a36Sopenharmony_ci			}
27762306a36Sopenharmony_ci		}
27862306a36Sopenharmony_ci	} else {
27962306a36Sopenharmony_ci		const struct nphy_rf_control_override_rev2 *rf_ctrl;
28062306a36Sopenharmony_ci		if (off) {
28162306a36Sopenharmony_ci			b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~(field));
28262306a36Sopenharmony_ci			value = 0;
28362306a36Sopenharmony_ci		} else {
28462306a36Sopenharmony_ci			b43_phy_set(dev, B43_NPHY_RFCTL_OVER, field);
28562306a36Sopenharmony_ci		}
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci		for (i = 0; i < 2; i++) {
28862306a36Sopenharmony_ci			if (index <= 1 || index == 16) {
28962306a36Sopenharmony_ci				b43err(dev->wl,
29062306a36Sopenharmony_ci					"Unsupported RF Ctrl Override call\n");
29162306a36Sopenharmony_ci				return;
29262306a36Sopenharmony_ci			}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci			if (index == 2 || index == 10 ||
29562306a36Sopenharmony_ci			    (index >= 13 && index <= 15)) {
29662306a36Sopenharmony_ci				core = 1;
29762306a36Sopenharmony_ci			}
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci			rf_ctrl = &tbl_rf_control_override_rev2[index - 2];
30062306a36Sopenharmony_ci			addr = B43_PHY_N((i == 0) ?
30162306a36Sopenharmony_ci				rf_ctrl->addr0 : rf_ctrl->addr1);
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci			if ((1 << i) & core)
30462306a36Sopenharmony_ci				b43_phy_maskset(dev, addr, ~(rf_ctrl->bmask),
30562306a36Sopenharmony_ci						(value << rf_ctrl->shift));
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci			b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x1);
30862306a36Sopenharmony_ci			b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
30962306a36Sopenharmony_ci					B43_NPHY_RFCTL_CMD_START);
31062306a36Sopenharmony_ci			udelay(1);
31162306a36Sopenharmony_ci			b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, 0xFFFE);
31262306a36Sopenharmony_ci		}
31362306a36Sopenharmony_ci	}
31462306a36Sopenharmony_ci}
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_cistatic void b43_nphy_rf_ctl_intc_override_rev7(struct b43_wldev *dev,
31762306a36Sopenharmony_ci					       enum n_intc_override intc_override,
31862306a36Sopenharmony_ci					       u16 value, u8 core_sel)
31962306a36Sopenharmony_ci{
32062306a36Sopenharmony_ci	u16 reg, tmp, tmp2, val;
32162306a36Sopenharmony_ci	int core;
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	/* TODO: What about rev19+? Revs 3+ and 7+ are a bit similar */
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	for (core = 0; core < 2; core++) {
32662306a36Sopenharmony_ci		if ((core_sel == 1 && core != 0) ||
32762306a36Sopenharmony_ci		    (core_sel == 2 && core != 1))
32862306a36Sopenharmony_ci			continue;
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci		reg = (core == 0) ? B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2;
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci		switch (intc_override) {
33362306a36Sopenharmony_ci		case N_INTC_OVERRIDE_OFF:
33462306a36Sopenharmony_ci			b43_phy_write(dev, reg, 0);
33562306a36Sopenharmony_ci			b43_phy_mask(dev, 0x2ff, ~0x2000);
33662306a36Sopenharmony_ci			b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
33762306a36Sopenharmony_ci			break;
33862306a36Sopenharmony_ci		case N_INTC_OVERRIDE_TRSW:
33962306a36Sopenharmony_ci			b43_phy_maskset(dev, reg, ~0xC0, value << 6);
34062306a36Sopenharmony_ci			b43_phy_set(dev, reg, 0x400);
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci			b43_phy_mask(dev, 0x2ff, ~0xC000 & 0xFFFF);
34362306a36Sopenharmony_ci			b43_phy_set(dev, 0x2ff, 0x2000);
34462306a36Sopenharmony_ci			b43_phy_set(dev, 0x2ff, 0x0001);
34562306a36Sopenharmony_ci			break;
34662306a36Sopenharmony_ci		case N_INTC_OVERRIDE_PA:
34762306a36Sopenharmony_ci			tmp = 0x0030;
34862306a36Sopenharmony_ci			if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
34962306a36Sopenharmony_ci				val = value << 5;
35062306a36Sopenharmony_ci			else
35162306a36Sopenharmony_ci				val = value << 4;
35262306a36Sopenharmony_ci			b43_phy_maskset(dev, reg, ~tmp, val);
35362306a36Sopenharmony_ci			b43_phy_set(dev, reg, 0x1000);
35462306a36Sopenharmony_ci			break;
35562306a36Sopenharmony_ci		case N_INTC_OVERRIDE_EXT_LNA_PU:
35662306a36Sopenharmony_ci			if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
35762306a36Sopenharmony_ci				tmp = 0x0001;
35862306a36Sopenharmony_ci				tmp2 = 0x0004;
35962306a36Sopenharmony_ci				val = value;
36062306a36Sopenharmony_ci			} else {
36162306a36Sopenharmony_ci				tmp = 0x0004;
36262306a36Sopenharmony_ci				tmp2 = 0x0001;
36362306a36Sopenharmony_ci				val = value << 2;
36462306a36Sopenharmony_ci			}
36562306a36Sopenharmony_ci			b43_phy_maskset(dev, reg, ~tmp, val);
36662306a36Sopenharmony_ci			b43_phy_mask(dev, reg, ~tmp2);
36762306a36Sopenharmony_ci			break;
36862306a36Sopenharmony_ci		case N_INTC_OVERRIDE_EXT_LNA_GAIN:
36962306a36Sopenharmony_ci			if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
37062306a36Sopenharmony_ci				tmp = 0x0002;
37162306a36Sopenharmony_ci				tmp2 = 0x0008;
37262306a36Sopenharmony_ci				val = value << 1;
37362306a36Sopenharmony_ci			} else {
37462306a36Sopenharmony_ci				tmp = 0x0008;
37562306a36Sopenharmony_ci				tmp2 = 0x0002;
37662306a36Sopenharmony_ci				val = value << 3;
37762306a36Sopenharmony_ci			}
37862306a36Sopenharmony_ci			b43_phy_maskset(dev, reg, ~tmp, val);
37962306a36Sopenharmony_ci			b43_phy_mask(dev, reg, ~tmp2);
38062306a36Sopenharmony_ci			break;
38162306a36Sopenharmony_ci		}
38262306a36Sopenharmony_ci	}
38362306a36Sopenharmony_ci}
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlIntcOverride */
38662306a36Sopenharmony_cistatic void b43_nphy_rf_ctl_intc_override(struct b43_wldev *dev,
38762306a36Sopenharmony_ci					  enum n_intc_override intc_override,
38862306a36Sopenharmony_ci					  u16 value, u8 core)
38962306a36Sopenharmony_ci{
39062306a36Sopenharmony_ci	u8 i, j;
39162306a36Sopenharmony_ci	u16 reg, tmp, val;
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	if (dev->phy.rev >= 7) {
39462306a36Sopenharmony_ci		b43_nphy_rf_ctl_intc_override_rev7(dev, intc_override, value,
39562306a36Sopenharmony_ci						   core);
39662306a36Sopenharmony_ci		return;
39762306a36Sopenharmony_ci	}
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	B43_WARN_ON(dev->phy.rev < 3);
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	for (i = 0; i < 2; i++) {
40262306a36Sopenharmony_ci		if ((core == 1 && i == 1) || (core == 2 && !i))
40362306a36Sopenharmony_ci			continue;
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci		reg = (i == 0) ?
40662306a36Sopenharmony_ci			B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2;
40762306a36Sopenharmony_ci		b43_phy_set(dev, reg, 0x400);
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci		switch (intc_override) {
41062306a36Sopenharmony_ci		case N_INTC_OVERRIDE_OFF:
41162306a36Sopenharmony_ci			b43_phy_write(dev, reg, 0);
41262306a36Sopenharmony_ci			b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
41362306a36Sopenharmony_ci			break;
41462306a36Sopenharmony_ci		case N_INTC_OVERRIDE_TRSW:
41562306a36Sopenharmony_ci			if (!i) {
41662306a36Sopenharmony_ci				b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC1,
41762306a36Sopenharmony_ci						0xFC3F, (value << 6));
41862306a36Sopenharmony_ci				b43_phy_maskset(dev, B43_NPHY_TXF_40CO_B1S1,
41962306a36Sopenharmony_ci						0xFFFE, 1);
42062306a36Sopenharmony_ci				b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
42162306a36Sopenharmony_ci						B43_NPHY_RFCTL_CMD_START);
42262306a36Sopenharmony_ci				for (j = 0; j < 100; j++) {
42362306a36Sopenharmony_ci					if (!(b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_START)) {
42462306a36Sopenharmony_ci						j = 0;
42562306a36Sopenharmony_ci						break;
42662306a36Sopenharmony_ci					}
42762306a36Sopenharmony_ci					udelay(10);
42862306a36Sopenharmony_ci				}
42962306a36Sopenharmony_ci				if (j)
43062306a36Sopenharmony_ci					b43err(dev->wl,
43162306a36Sopenharmony_ci						"intc override timeout\n");
43262306a36Sopenharmony_ci				b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S1,
43362306a36Sopenharmony_ci						0xFFFE);
43462306a36Sopenharmony_ci			} else {
43562306a36Sopenharmony_ci				b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC2,
43662306a36Sopenharmony_ci						0xFC3F, (value << 6));
43762306a36Sopenharmony_ci				b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
43862306a36Sopenharmony_ci						0xFFFE, 1);
43962306a36Sopenharmony_ci				b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
44062306a36Sopenharmony_ci						B43_NPHY_RFCTL_CMD_RXTX);
44162306a36Sopenharmony_ci				for (j = 0; j < 100; j++) {
44262306a36Sopenharmony_ci					if (!(b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_RXTX)) {
44362306a36Sopenharmony_ci						j = 0;
44462306a36Sopenharmony_ci						break;
44562306a36Sopenharmony_ci					}
44662306a36Sopenharmony_ci					udelay(10);
44762306a36Sopenharmony_ci				}
44862306a36Sopenharmony_ci				if (j)
44962306a36Sopenharmony_ci					b43err(dev->wl,
45062306a36Sopenharmony_ci						"intc override timeout\n");
45162306a36Sopenharmony_ci				b43_phy_mask(dev, B43_NPHY_RFCTL_OVER,
45262306a36Sopenharmony_ci						0xFFFE);
45362306a36Sopenharmony_ci			}
45462306a36Sopenharmony_ci			break;
45562306a36Sopenharmony_ci		case N_INTC_OVERRIDE_PA:
45662306a36Sopenharmony_ci			if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
45762306a36Sopenharmony_ci				tmp = 0x0020;
45862306a36Sopenharmony_ci				val = value << 5;
45962306a36Sopenharmony_ci			} else {
46062306a36Sopenharmony_ci				tmp = 0x0010;
46162306a36Sopenharmony_ci				val = value << 4;
46262306a36Sopenharmony_ci			}
46362306a36Sopenharmony_ci			b43_phy_maskset(dev, reg, ~tmp, val);
46462306a36Sopenharmony_ci			break;
46562306a36Sopenharmony_ci		case N_INTC_OVERRIDE_EXT_LNA_PU:
46662306a36Sopenharmony_ci			if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
46762306a36Sopenharmony_ci				tmp = 0x0001;
46862306a36Sopenharmony_ci				val = value;
46962306a36Sopenharmony_ci			} else {
47062306a36Sopenharmony_ci				tmp = 0x0004;
47162306a36Sopenharmony_ci				val = value << 2;
47262306a36Sopenharmony_ci			}
47362306a36Sopenharmony_ci			b43_phy_maskset(dev, reg, ~tmp, val);
47462306a36Sopenharmony_ci			break;
47562306a36Sopenharmony_ci		case N_INTC_OVERRIDE_EXT_LNA_GAIN:
47662306a36Sopenharmony_ci			if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
47762306a36Sopenharmony_ci				tmp = 0x0002;
47862306a36Sopenharmony_ci				val = value << 1;
47962306a36Sopenharmony_ci			} else {
48062306a36Sopenharmony_ci				tmp = 0x0008;
48162306a36Sopenharmony_ci				val = value << 3;
48262306a36Sopenharmony_ci			}
48362306a36Sopenharmony_ci			b43_phy_maskset(dev, reg, ~tmp, val);
48462306a36Sopenharmony_ci			break;
48562306a36Sopenharmony_ci		}
48662306a36Sopenharmony_ci	}
48762306a36Sopenharmony_ci}
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci/**************************************************
49062306a36Sopenharmony_ci * Various PHY ops
49162306a36Sopenharmony_ci **************************************************/
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
49462306a36Sopenharmony_cistatic void b43_nphy_write_clip_detection(struct b43_wldev *dev,
49562306a36Sopenharmony_ci					  const u16 *clip_st)
49662306a36Sopenharmony_ci{
49762306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_C1_CLIP1THRES, clip_st[0]);
49862306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_C2_CLIP1THRES, clip_st[1]);
49962306a36Sopenharmony_ci}
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
50262306a36Sopenharmony_cistatic void b43_nphy_read_clip_detection(struct b43_wldev *dev, u16 *clip_st)
50362306a36Sopenharmony_ci{
50462306a36Sopenharmony_ci	clip_st[0] = b43_phy_read(dev, B43_NPHY_C1_CLIP1THRES);
50562306a36Sopenharmony_ci	clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES);
50662306a36Sopenharmony_ci}
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */
50962306a36Sopenharmony_cistatic u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)
51062306a36Sopenharmony_ci{
51162306a36Sopenharmony_ci	u16 tmp;
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	if (dev->dev->core_rev == 16)
51462306a36Sopenharmony_ci		b43_mac_suspend(dev);
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci	tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL);
51762306a36Sopenharmony_ci	tmp &= (B43_NPHY_CLASSCTL_CCKEN | B43_NPHY_CLASSCTL_OFDMEN |
51862306a36Sopenharmony_ci		B43_NPHY_CLASSCTL_WAITEDEN);
51962306a36Sopenharmony_ci	tmp &= ~mask;
52062306a36Sopenharmony_ci	tmp |= (val & mask);
52162306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp);
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	if (dev->dev->core_rev == 16)
52462306a36Sopenharmony_ci		b43_mac_enable(dev);
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci	return tmp;
52762306a36Sopenharmony_ci}
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
53062306a36Sopenharmony_cistatic void b43_nphy_reset_cca(struct b43_wldev *dev)
53162306a36Sopenharmony_ci{
53262306a36Sopenharmony_ci	u16 bbcfg;
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci	b43_phy_force_clock(dev, 1);
53562306a36Sopenharmony_ci	bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG);
53662306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA);
53762306a36Sopenharmony_ci	udelay(1);
53862306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA);
53962306a36Sopenharmony_ci	b43_phy_force_clock(dev, 0);
54062306a36Sopenharmony_ci	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
54162306a36Sopenharmony_ci}
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/carriersearch */
54462306a36Sopenharmony_cistatic void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable)
54562306a36Sopenharmony_ci{
54662306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
54762306a36Sopenharmony_ci	struct b43_phy_n *nphy = phy->n;
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci	if (enable) {
55062306a36Sopenharmony_ci		static const u16 clip[] = { 0xFFFF, 0xFFFF };
55162306a36Sopenharmony_ci		if (nphy->deaf_count++ == 0) {
55262306a36Sopenharmony_ci			nphy->classifier_state = b43_nphy_classifier(dev, 0, 0);
55362306a36Sopenharmony_ci			b43_nphy_classifier(dev, 0x7,
55462306a36Sopenharmony_ci					    B43_NPHY_CLASSCTL_WAITEDEN);
55562306a36Sopenharmony_ci			b43_nphy_read_clip_detection(dev, nphy->clip_state);
55662306a36Sopenharmony_ci			b43_nphy_write_clip_detection(dev, clip);
55762306a36Sopenharmony_ci		}
55862306a36Sopenharmony_ci		b43_nphy_reset_cca(dev);
55962306a36Sopenharmony_ci	} else {
56062306a36Sopenharmony_ci		if (--nphy->deaf_count == 0) {
56162306a36Sopenharmony_ci			b43_nphy_classifier(dev, 0x7, nphy->classifier_state);
56262306a36Sopenharmony_ci			b43_nphy_write_clip_detection(dev, nphy->clip_state);
56362306a36Sopenharmony_ci		}
56462306a36Sopenharmony_ci	}
56562306a36Sopenharmony_ci}
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/PHY/N/Read_Lpf_Bw_Ctl */
56862306a36Sopenharmony_cistatic u16 b43_nphy_read_lpf_ctl(struct b43_wldev *dev, u16 offset)
56962306a36Sopenharmony_ci{
57062306a36Sopenharmony_ci	if (!offset)
57162306a36Sopenharmony_ci		offset = b43_is_40mhz(dev) ? 0x159 : 0x154;
57262306a36Sopenharmony_ci	return b43_ntab_read(dev, B43_NTAB16(7, offset)) & 0x7;
57362306a36Sopenharmony_ci}
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */
57662306a36Sopenharmony_cistatic void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)
57762306a36Sopenharmony_ci{
57862306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci	u8 i;
58162306a36Sopenharmony_ci	s16 tmp;
58262306a36Sopenharmony_ci	u16 data[4];
58362306a36Sopenharmony_ci	s16 gain[2];
58462306a36Sopenharmony_ci	u16 minmax[2];
58562306a36Sopenharmony_ci	static const s16 lna_gain[4] = { -2, 10, 19, 25 };
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci	if (nphy->hang_avoid)
58862306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, 1);
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci	if (nphy->gain_boost) {
59162306a36Sopenharmony_ci		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
59262306a36Sopenharmony_ci			gain[0] = 6;
59362306a36Sopenharmony_ci			gain[1] = 6;
59462306a36Sopenharmony_ci		} else {
59562306a36Sopenharmony_ci			tmp = 40370 - 315 * dev->phy.channel;
59662306a36Sopenharmony_ci			gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1));
59762306a36Sopenharmony_ci			tmp = 23242 - 224 * dev->phy.channel;
59862306a36Sopenharmony_ci			gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1));
59962306a36Sopenharmony_ci		}
60062306a36Sopenharmony_ci	} else {
60162306a36Sopenharmony_ci		gain[0] = 0;
60262306a36Sopenharmony_ci		gain[1] = 0;
60362306a36Sopenharmony_ci	}
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_ci	for (i = 0; i < 2; i++) {
60662306a36Sopenharmony_ci		if (nphy->elna_gain_config) {
60762306a36Sopenharmony_ci			data[0] = 19 + gain[i];
60862306a36Sopenharmony_ci			data[1] = 25 + gain[i];
60962306a36Sopenharmony_ci			data[2] = 25 + gain[i];
61062306a36Sopenharmony_ci			data[3] = 25 + gain[i];
61162306a36Sopenharmony_ci		} else {
61262306a36Sopenharmony_ci			data[0] = lna_gain[0] + gain[i];
61362306a36Sopenharmony_ci			data[1] = lna_gain[1] + gain[i];
61462306a36Sopenharmony_ci			data[2] = lna_gain[2] + gain[i];
61562306a36Sopenharmony_ci			data[3] = lna_gain[3] + gain[i];
61662306a36Sopenharmony_ci		}
61762306a36Sopenharmony_ci		b43_ntab_write_bulk(dev, B43_NTAB16(i, 8), 4, data);
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci		minmax[i] = 23 + gain[i];
62062306a36Sopenharmony_ci	}
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN, ~B43_NPHY_C1_MINGAIN,
62362306a36Sopenharmony_ci				minmax[0] << B43_NPHY_C1_MINGAIN_SHIFT);
62462306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN, ~B43_NPHY_C2_MINGAIN,
62562306a36Sopenharmony_ci				minmax[1] << B43_NPHY_C2_MINGAIN_SHIFT);
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_ci	if (nphy->hang_avoid)
62862306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, 0);
62962306a36Sopenharmony_ci}
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRfSeq */
63262306a36Sopenharmony_cistatic void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
63362306a36Sopenharmony_ci					u8 *events, u8 *delays, u8 length)
63462306a36Sopenharmony_ci{
63562306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
63662306a36Sopenharmony_ci	u8 i;
63762306a36Sopenharmony_ci	u8 end = (dev->phy.rev >= 3) ? 0x1F : 0x0F;
63862306a36Sopenharmony_ci	u16 offset1 = cmd << 4;
63962306a36Sopenharmony_ci	u16 offset2 = offset1 + 0x80;
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_ci	if (nphy->hang_avoid)
64262306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, true);
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB8(7, offset1), length, events);
64562306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB8(7, offset2), length, delays);
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci	for (i = length; i < 16; i++) {
64862306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB8(7, offset1 + i), end);
64962306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB8(7, offset2 + i), 1);
65062306a36Sopenharmony_ci	}
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	if (nphy->hang_avoid)
65362306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, false);
65462306a36Sopenharmony_ci}
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci/**************************************************
65762306a36Sopenharmony_ci * Radio 0x2057
65862306a36Sopenharmony_ci **************************************************/
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_cistatic void b43_radio_2057_chantab_upload(struct b43_wldev *dev,
66162306a36Sopenharmony_ci					  const struct b43_nphy_chantabent_rev7 *e_r7,
66262306a36Sopenharmony_ci					  const struct b43_nphy_chantabent_rev7_2g *e_r7_2g)
66362306a36Sopenharmony_ci{
66462306a36Sopenharmony_ci	if (e_r7_2g) {
66562306a36Sopenharmony_ci		b43_radio_write(dev, R2057_VCOCAL_COUNTVAL0, e_r7_2g->radio_vcocal_countval0);
66662306a36Sopenharmony_ci		b43_radio_write(dev, R2057_VCOCAL_COUNTVAL1, e_r7_2g->radio_vcocal_countval1);
66762306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RFPLL_REFMASTER_SPAREXTALSIZE, e_r7_2g->radio_rfpll_refmaster_sparextalsize);
66862306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, e_r7_2g->radio_rfpll_loopfilter_r1);
66962306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, e_r7_2g->radio_rfpll_loopfilter_c2);
67062306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, e_r7_2g->radio_rfpll_loopfilter_c1);
67162306a36Sopenharmony_ci		b43_radio_write(dev, R2057_CP_KPD_IDAC, e_r7_2g->radio_cp_kpd_idac);
67262306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RFPLL_MMD0, e_r7_2g->radio_rfpll_mmd0);
67362306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RFPLL_MMD1, e_r7_2g->radio_rfpll_mmd1);
67462306a36Sopenharmony_ci		b43_radio_write(dev, R2057_VCOBUF_TUNE, e_r7_2g->radio_vcobuf_tune);
67562306a36Sopenharmony_ci		b43_radio_write(dev, R2057_LOGEN_MX2G_TUNE, e_r7_2g->radio_logen_mx2g_tune);
67662306a36Sopenharmony_ci		b43_radio_write(dev, R2057_LOGEN_INDBUF2G_TUNE, e_r7_2g->radio_logen_indbuf2g_tune);
67762306a36Sopenharmony_ci		b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, e_r7_2g->radio_txmix2g_tune_boost_pu_core0);
67862306a36Sopenharmony_ci		b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE0, e_r7_2g->radio_pad2g_tune_pus_core0);
67962306a36Sopenharmony_ci		b43_radio_write(dev, R2057_LNA2G_TUNE_CORE0, e_r7_2g->radio_lna2g_tune_core0);
68062306a36Sopenharmony_ci		b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, e_r7_2g->radio_txmix2g_tune_boost_pu_core1);
68162306a36Sopenharmony_ci		b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE1, e_r7_2g->radio_pad2g_tune_pus_core1);
68262306a36Sopenharmony_ci		b43_radio_write(dev, R2057_LNA2G_TUNE_CORE1, e_r7_2g->radio_lna2g_tune_core1);
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci	} else {
68562306a36Sopenharmony_ci		b43_radio_write(dev, R2057_VCOCAL_COUNTVAL0, e_r7->radio_vcocal_countval0);
68662306a36Sopenharmony_ci		b43_radio_write(dev, R2057_VCOCAL_COUNTVAL1, e_r7->radio_vcocal_countval1);
68762306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RFPLL_REFMASTER_SPAREXTALSIZE, e_r7->radio_rfpll_refmaster_sparextalsize);
68862306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, e_r7->radio_rfpll_loopfilter_r1);
68962306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, e_r7->radio_rfpll_loopfilter_c2);
69062306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, e_r7->radio_rfpll_loopfilter_c1);
69162306a36Sopenharmony_ci		b43_radio_write(dev, R2057_CP_KPD_IDAC, e_r7->radio_cp_kpd_idac);
69262306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RFPLL_MMD0, e_r7->radio_rfpll_mmd0);
69362306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RFPLL_MMD1, e_r7->radio_rfpll_mmd1);
69462306a36Sopenharmony_ci		b43_radio_write(dev, R2057_VCOBUF_TUNE, e_r7->radio_vcobuf_tune);
69562306a36Sopenharmony_ci		b43_radio_write(dev, R2057_LOGEN_MX2G_TUNE, e_r7->radio_logen_mx2g_tune);
69662306a36Sopenharmony_ci		b43_radio_write(dev, R2057_LOGEN_MX5G_TUNE, e_r7->radio_logen_mx5g_tune);
69762306a36Sopenharmony_ci		b43_radio_write(dev, R2057_LOGEN_INDBUF2G_TUNE, e_r7->radio_logen_indbuf2g_tune);
69862306a36Sopenharmony_ci		b43_radio_write(dev, R2057_LOGEN_INDBUF5G_TUNE, e_r7->radio_logen_indbuf5g_tune);
69962306a36Sopenharmony_ci		b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, e_r7->radio_txmix2g_tune_boost_pu_core0);
70062306a36Sopenharmony_ci		b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE0, e_r7->radio_pad2g_tune_pus_core0);
70162306a36Sopenharmony_ci		b43_radio_write(dev, R2057_PGA_BOOST_TUNE_CORE0, e_r7->radio_pga_boost_tune_core0);
70262306a36Sopenharmony_ci		b43_radio_write(dev, R2057_TXMIX5G_BOOST_TUNE_CORE0, e_r7->radio_txmix5g_boost_tune_core0);
70362306a36Sopenharmony_ci		b43_radio_write(dev, R2057_PAD5G_TUNE_MISC_PUS_CORE0, e_r7->radio_pad5g_tune_misc_pus_core0);
70462306a36Sopenharmony_ci		b43_radio_write(dev, R2057_LNA2G_TUNE_CORE0, e_r7->radio_lna2g_tune_core0);
70562306a36Sopenharmony_ci		b43_radio_write(dev, R2057_LNA5G_TUNE_CORE0, e_r7->radio_lna5g_tune_core0);
70662306a36Sopenharmony_ci		b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, e_r7->radio_txmix2g_tune_boost_pu_core1);
70762306a36Sopenharmony_ci		b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE1, e_r7->radio_pad2g_tune_pus_core1);
70862306a36Sopenharmony_ci		b43_radio_write(dev, R2057_PGA_BOOST_TUNE_CORE1, e_r7->radio_pga_boost_tune_core1);
70962306a36Sopenharmony_ci		b43_radio_write(dev, R2057_TXMIX5G_BOOST_TUNE_CORE1, e_r7->radio_txmix5g_boost_tune_core1);
71062306a36Sopenharmony_ci		b43_radio_write(dev, R2057_PAD5G_TUNE_MISC_PUS_CORE1, e_r7->radio_pad5g_tune_misc_pus_core1);
71162306a36Sopenharmony_ci		b43_radio_write(dev, R2057_LNA2G_TUNE_CORE1, e_r7->radio_lna2g_tune_core1);
71262306a36Sopenharmony_ci		b43_radio_write(dev, R2057_LNA5G_TUNE_CORE1, e_r7->radio_lna5g_tune_core1);
71362306a36Sopenharmony_ci	}
71462306a36Sopenharmony_ci}
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_cistatic void b43_radio_2057_setup(struct b43_wldev *dev,
71762306a36Sopenharmony_ci				 const struct b43_nphy_chantabent_rev7 *tabent_r7,
71862306a36Sopenharmony_ci				 const struct b43_nphy_chantabent_rev7_2g *tabent_r7_2g)
71962306a36Sopenharmony_ci{
72062306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_ci	b43_radio_2057_chantab_upload(dev, tabent_r7, tabent_r7_2g);
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_ci	switch (phy->radio_rev) {
72562306a36Sopenharmony_ci	case 0 ... 4:
72662306a36Sopenharmony_ci	case 6:
72762306a36Sopenharmony_ci		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
72862306a36Sopenharmony_ci			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x3f);
72962306a36Sopenharmony_ci			b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f);
73062306a36Sopenharmony_ci			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x8);
73162306a36Sopenharmony_ci			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x8);
73262306a36Sopenharmony_ci		} else {
73362306a36Sopenharmony_ci			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x1f);
73462306a36Sopenharmony_ci			b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f);
73562306a36Sopenharmony_ci			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x8);
73662306a36Sopenharmony_ci			b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x8);
73762306a36Sopenharmony_ci		}
73862306a36Sopenharmony_ci		break;
73962306a36Sopenharmony_ci	case 9: /* e.g. PHY rev 16 */
74062306a36Sopenharmony_ci		b43_radio_write(dev, R2057_LOGEN_PTAT_RESETS, 0x20);
74162306a36Sopenharmony_ci		b43_radio_write(dev, R2057_VCOBUF_IDACS, 0x18);
74262306a36Sopenharmony_ci		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
74362306a36Sopenharmony_ci			b43_radio_write(dev, R2057_LOGEN_PTAT_RESETS, 0x38);
74462306a36Sopenharmony_ci			b43_radio_write(dev, R2057_VCOBUF_IDACS, 0x0f);
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci			if (b43_is_40mhz(dev)) {
74762306a36Sopenharmony_ci				/* TODO */
74862306a36Sopenharmony_ci			} else {
74962306a36Sopenharmony_ci				b43_radio_write(dev,
75062306a36Sopenharmony_ci						R2057_PAD_BIAS_FILTER_BWS_CORE0,
75162306a36Sopenharmony_ci						0x3c);
75262306a36Sopenharmony_ci				b43_radio_write(dev,
75362306a36Sopenharmony_ci						R2057_PAD_BIAS_FILTER_BWS_CORE1,
75462306a36Sopenharmony_ci						0x3c);
75562306a36Sopenharmony_ci			}
75662306a36Sopenharmony_ci		}
75762306a36Sopenharmony_ci		break;
75862306a36Sopenharmony_ci	case 14: /* 2 GHz only */
75962306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x1b);
76062306a36Sopenharmony_ci		b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f);
76162306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x1f);
76262306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x1f);
76362306a36Sopenharmony_ci		break;
76462306a36Sopenharmony_ci	}
76562306a36Sopenharmony_ci
76662306a36Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
76762306a36Sopenharmony_ci		u16 txmix2g_tune_boost_pu = 0;
76862306a36Sopenharmony_ci		u16 pad2g_tune_pus = 0;
76962306a36Sopenharmony_ci
77062306a36Sopenharmony_ci		if (b43_nphy_ipa(dev)) {
77162306a36Sopenharmony_ci			switch (phy->radio_rev) {
77262306a36Sopenharmony_ci			case 9:
77362306a36Sopenharmony_ci				txmix2g_tune_boost_pu = 0x0041;
77462306a36Sopenharmony_ci				/* TODO */
77562306a36Sopenharmony_ci				break;
77662306a36Sopenharmony_ci			case 14:
77762306a36Sopenharmony_ci				txmix2g_tune_boost_pu = 0x21;
77862306a36Sopenharmony_ci				pad2g_tune_pus = 0x23;
77962306a36Sopenharmony_ci				break;
78062306a36Sopenharmony_ci			}
78162306a36Sopenharmony_ci		}
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci		if (txmix2g_tune_boost_pu)
78462306a36Sopenharmony_ci			b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0,
78562306a36Sopenharmony_ci					txmix2g_tune_boost_pu);
78662306a36Sopenharmony_ci		if (pad2g_tune_pus)
78762306a36Sopenharmony_ci			b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE0,
78862306a36Sopenharmony_ci					pad2g_tune_pus);
78962306a36Sopenharmony_ci		if (txmix2g_tune_boost_pu)
79062306a36Sopenharmony_ci			b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1,
79162306a36Sopenharmony_ci					txmix2g_tune_boost_pu);
79262306a36Sopenharmony_ci		if (pad2g_tune_pus)
79362306a36Sopenharmony_ci			b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE1,
79462306a36Sopenharmony_ci					pad2g_tune_pus);
79562306a36Sopenharmony_ci	}
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_ci	usleep_range(50, 100);
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci	/* VCO calibration */
80062306a36Sopenharmony_ci	b43_radio_mask(dev, R2057_RFPLL_MISC_EN, ~0x01);
80162306a36Sopenharmony_ci	b43_radio_mask(dev, R2057_RFPLL_MISC_CAL_RESETN, ~0x04);
80262306a36Sopenharmony_ci	b43_radio_set(dev, R2057_RFPLL_MISC_CAL_RESETN, 0x4);
80362306a36Sopenharmony_ci	b43_radio_set(dev, R2057_RFPLL_MISC_EN, 0x01);
80462306a36Sopenharmony_ci	usleep_range(300, 600);
80562306a36Sopenharmony_ci}
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_ci/* Calibrate resistors in LPF of PLL?
80862306a36Sopenharmony_ci * https://bcm-v4.sipsolutions.net/PHY/radio205x_rcal
80962306a36Sopenharmony_ci */
81062306a36Sopenharmony_cistatic u8 b43_radio_2057_rcal(struct b43_wldev *dev)
81162306a36Sopenharmony_ci{
81262306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
81362306a36Sopenharmony_ci	u16 saved_regs_phy[12];
81462306a36Sopenharmony_ci	u16 saved_regs_phy_rf[6];
81562306a36Sopenharmony_ci	u16 saved_regs_radio[2] = { };
81662306a36Sopenharmony_ci	static const u16 phy_to_store[] = {
81762306a36Sopenharmony_ci		B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2,
81862306a36Sopenharmony_ci		B43_NPHY_RFCTL_LUT_TRSW_LO1, B43_NPHY_RFCTL_LUT_TRSW_LO2,
81962306a36Sopenharmony_ci		B43_NPHY_RFCTL_RXG1, B43_NPHY_RFCTL_RXG2,
82062306a36Sopenharmony_ci		B43_NPHY_RFCTL_TXG1, B43_NPHY_RFCTL_TXG2,
82162306a36Sopenharmony_ci		B43_NPHY_REV7_RF_CTL_MISC_REG3, B43_NPHY_REV7_RF_CTL_MISC_REG4,
82262306a36Sopenharmony_ci		B43_NPHY_REV7_RF_CTL_MISC_REG5, B43_NPHY_REV7_RF_CTL_MISC_REG6,
82362306a36Sopenharmony_ci	};
82462306a36Sopenharmony_ci	static const u16 phy_to_store_rf[] = {
82562306a36Sopenharmony_ci		B43_NPHY_REV3_RFCTL_OVER0, B43_NPHY_REV3_RFCTL_OVER1,
82662306a36Sopenharmony_ci		B43_NPHY_REV7_RF_CTL_OVER3, B43_NPHY_REV7_RF_CTL_OVER4,
82762306a36Sopenharmony_ci		B43_NPHY_REV7_RF_CTL_OVER5, B43_NPHY_REV7_RF_CTL_OVER6,
82862306a36Sopenharmony_ci	};
82962306a36Sopenharmony_ci	u16 tmp;
83062306a36Sopenharmony_ci	int i;
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci	/* Save */
83362306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(phy_to_store); i++)
83462306a36Sopenharmony_ci		saved_regs_phy[i] = b43_phy_read(dev, phy_to_store[i]);
83562306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(phy_to_store_rf); i++)
83662306a36Sopenharmony_ci		saved_regs_phy_rf[i] = b43_phy_read(dev, phy_to_store_rf[i]);
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ci	/* Set */
83962306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(phy_to_store); i++)
84062306a36Sopenharmony_ci		b43_phy_write(dev, phy_to_store[i], 0);
84162306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_REV3_RFCTL_OVER0, 0x07ff);
84262306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_REV3_RFCTL_OVER1, 0x07ff);
84362306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x07ff);
84462306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER4, 0x07ff);
84562306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER5, 0x007f);
84662306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER6, 0x007f);
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci	switch (phy->radio_rev) {
84962306a36Sopenharmony_ci	case 5:
85062306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_REV7_RF_CTL_OVER3, ~0x2);
85162306a36Sopenharmony_ci		udelay(10);
85262306a36Sopenharmony_ci		b43_radio_set(dev, R2057_IQTEST_SEL_PU, 0x1);
85362306a36Sopenharmony_ci		b43_radio_maskset(dev, R2057v7_IQTEST_SEL_PU2, ~0x2, 0x1);
85462306a36Sopenharmony_ci		break;
85562306a36Sopenharmony_ci	case 9:
85662306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x2);
85762306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_MISC_REG3, 0x2);
85862306a36Sopenharmony_ci		saved_regs_radio[0] = b43_radio_read(dev, R2057_IQTEST_SEL_PU);
85962306a36Sopenharmony_ci		b43_radio_write(dev, R2057_IQTEST_SEL_PU, 0x11);
86062306a36Sopenharmony_ci		break;
86162306a36Sopenharmony_ci	case 14:
86262306a36Sopenharmony_ci		saved_regs_radio[0] = b43_radio_read(dev, R2057_IQTEST_SEL_PU);
86362306a36Sopenharmony_ci		saved_regs_radio[1] = b43_radio_read(dev, R2057v7_IQTEST_SEL_PU2);
86462306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_MISC_REG3, 0x2);
86562306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x2);
86662306a36Sopenharmony_ci		b43_radio_write(dev, R2057v7_IQTEST_SEL_PU2, 0x2);
86762306a36Sopenharmony_ci		b43_radio_write(dev, R2057_IQTEST_SEL_PU, 0x1);
86862306a36Sopenharmony_ci		break;
86962306a36Sopenharmony_ci	}
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_ci	/* Enable */
87262306a36Sopenharmony_ci	b43_radio_set(dev, R2057_RCAL_CONFIG, 0x1);
87362306a36Sopenharmony_ci	udelay(10);
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_ci	/* Start */
87662306a36Sopenharmony_ci	b43_radio_set(dev, R2057_RCAL_CONFIG, 0x2);
87762306a36Sopenharmony_ci	usleep_range(100, 200);
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci	/* Stop */
88062306a36Sopenharmony_ci	b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x2);
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci	/* Wait and check for result */
88362306a36Sopenharmony_ci	if (!b43_radio_wait_value(dev, R2057_RCAL_STATUS, 1, 1, 100, 1000000)) {
88462306a36Sopenharmony_ci		b43err(dev->wl, "Radio 0x2057 rcal timeout\n");
88562306a36Sopenharmony_ci		return 0;
88662306a36Sopenharmony_ci	}
88762306a36Sopenharmony_ci	tmp = b43_radio_read(dev, R2057_RCAL_STATUS) & 0x3E;
88862306a36Sopenharmony_ci
88962306a36Sopenharmony_ci	/* Disable */
89062306a36Sopenharmony_ci	b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x1);
89162306a36Sopenharmony_ci
89262306a36Sopenharmony_ci	/* Restore */
89362306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(phy_to_store_rf); i++)
89462306a36Sopenharmony_ci		b43_phy_write(dev, phy_to_store_rf[i], saved_regs_phy_rf[i]);
89562306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(phy_to_store); i++)
89662306a36Sopenharmony_ci		b43_phy_write(dev, phy_to_store[i], saved_regs_phy[i]);
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ci	switch (phy->radio_rev) {
89962306a36Sopenharmony_ci	case 0 ... 4:
90062306a36Sopenharmony_ci	case 6:
90162306a36Sopenharmony_ci		b43_radio_maskset(dev, R2057_TEMPSENSE_CONFIG, ~0x3C, tmp);
90262306a36Sopenharmony_ci		b43_radio_maskset(dev, R2057_BANDGAP_RCAL_TRIM, ~0xF0,
90362306a36Sopenharmony_ci				  tmp << 2);
90462306a36Sopenharmony_ci		break;
90562306a36Sopenharmony_ci	case 5:
90662306a36Sopenharmony_ci		b43_radio_mask(dev, R2057_IPA2G_CASCONV_CORE0, ~0x1);
90762306a36Sopenharmony_ci		b43_radio_mask(dev, R2057v7_IQTEST_SEL_PU2, ~0x2);
90862306a36Sopenharmony_ci		break;
90962306a36Sopenharmony_ci	case 9:
91062306a36Sopenharmony_ci		b43_radio_write(dev, R2057_IQTEST_SEL_PU, saved_regs_radio[0]);
91162306a36Sopenharmony_ci		break;
91262306a36Sopenharmony_ci	case 14:
91362306a36Sopenharmony_ci		b43_radio_write(dev, R2057_IQTEST_SEL_PU, saved_regs_radio[0]);
91462306a36Sopenharmony_ci		b43_radio_write(dev, R2057v7_IQTEST_SEL_PU2, saved_regs_radio[1]);
91562306a36Sopenharmony_ci		break;
91662306a36Sopenharmony_ci	}
91762306a36Sopenharmony_ci
91862306a36Sopenharmony_ci	return tmp & 0x3e;
91962306a36Sopenharmony_ci}
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_ci/* Calibrate the internal RC oscillator?
92262306a36Sopenharmony_ci * https://bcm-v4.sipsolutions.net/PHY/radio2057_rccal
92362306a36Sopenharmony_ci */
92462306a36Sopenharmony_cistatic u16 b43_radio_2057_rccal(struct b43_wldev *dev)
92562306a36Sopenharmony_ci{
92662306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
92762306a36Sopenharmony_ci	bool special = (phy->radio_rev == 3 || phy->radio_rev == 4 ||
92862306a36Sopenharmony_ci			phy->radio_rev == 6);
92962306a36Sopenharmony_ci	u16 tmp;
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci	/* Setup cal */
93262306a36Sopenharmony_ci	if (special) {
93362306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RCCAL_MASTER, 0x61);
93462306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RCCAL_TRC0, 0xC0);
93562306a36Sopenharmony_ci	} else {
93662306a36Sopenharmony_ci		b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x61);
93762306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RCCAL_TRC0, 0xE9);
93862306a36Sopenharmony_ci	}
93962306a36Sopenharmony_ci	b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_ci	/* Start, wait, stop */
94262306a36Sopenharmony_ci	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
94362306a36Sopenharmony_ci	if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500,
94462306a36Sopenharmony_ci				  5000000))
94562306a36Sopenharmony_ci		b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n");
94662306a36Sopenharmony_ci	usleep_range(35, 70);
94762306a36Sopenharmony_ci	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
94862306a36Sopenharmony_ci	usleep_range(70, 140);
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci	/* Setup cal */
95162306a36Sopenharmony_ci	if (special) {
95262306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RCCAL_MASTER, 0x69);
95362306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RCCAL_TRC0, 0xB0);
95462306a36Sopenharmony_ci	} else {
95562306a36Sopenharmony_ci		b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x69);
95662306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RCCAL_TRC0, 0xD5);
95762306a36Sopenharmony_ci	}
95862306a36Sopenharmony_ci	b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
95962306a36Sopenharmony_ci
96062306a36Sopenharmony_ci	/* Start, wait, stop */
96162306a36Sopenharmony_ci	usleep_range(35, 70);
96262306a36Sopenharmony_ci	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
96362306a36Sopenharmony_ci	usleep_range(70, 140);
96462306a36Sopenharmony_ci	if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500,
96562306a36Sopenharmony_ci				  5000000))
96662306a36Sopenharmony_ci		b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n");
96762306a36Sopenharmony_ci	usleep_range(35, 70);
96862306a36Sopenharmony_ci	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
96962306a36Sopenharmony_ci	usleep_range(70, 140);
97062306a36Sopenharmony_ci
97162306a36Sopenharmony_ci	/* Setup cal */
97262306a36Sopenharmony_ci	if (special) {
97362306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RCCAL_MASTER, 0x73);
97462306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RCCAL_X1, 0x28);
97562306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RCCAL_TRC0, 0xB0);
97662306a36Sopenharmony_ci	} else {
97762306a36Sopenharmony_ci		b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x73);
97862306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
97962306a36Sopenharmony_ci		b43_radio_write(dev, R2057_RCCAL_TRC0, 0x99);
98062306a36Sopenharmony_ci	}
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_ci	/* Start, wait, stop */
98362306a36Sopenharmony_ci	usleep_range(35, 70);
98462306a36Sopenharmony_ci	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55);
98562306a36Sopenharmony_ci	usleep_range(70, 140);
98662306a36Sopenharmony_ci	if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500,
98762306a36Sopenharmony_ci				  5000000)) {
98862306a36Sopenharmony_ci		b43err(dev->wl, "Radio 0x2057 rcal timeout\n");
98962306a36Sopenharmony_ci		return 0;
99062306a36Sopenharmony_ci	}
99162306a36Sopenharmony_ci	tmp = b43_radio_read(dev, R2057_RCCAL_DONE_OSCCAP);
99262306a36Sopenharmony_ci	usleep_range(35, 70);
99362306a36Sopenharmony_ci	b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15);
99462306a36Sopenharmony_ci	usleep_range(70, 140);
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_ci	if (special)
99762306a36Sopenharmony_ci		b43_radio_mask(dev, R2057_RCCAL_MASTER, ~0x1);
99862306a36Sopenharmony_ci	else
99962306a36Sopenharmony_ci		b43_radio_mask(dev, R2057v7_RCCAL_MASTER, ~0x1);
100062306a36Sopenharmony_ci
100162306a36Sopenharmony_ci	return tmp;
100262306a36Sopenharmony_ci}
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_cistatic void b43_radio_2057_init_pre(struct b43_wldev *dev)
100562306a36Sopenharmony_ci{
100662306a36Sopenharmony_ci	b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, ~B43_NPHY_RFCTL_CMD_CHIP0PU);
100762306a36Sopenharmony_ci	/* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */
100862306a36Sopenharmony_ci	b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_OEPORFORCE);
100962306a36Sopenharmony_ci	b43_phy_set(dev, B43_NPHY_RFCTL_CMD, ~B43_NPHY_RFCTL_CMD_OEPORFORCE);
101062306a36Sopenharmony_ci	b43_phy_set(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_CHIP0PU);
101162306a36Sopenharmony_ci}
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_cistatic void b43_radio_2057_init_post(struct b43_wldev *dev)
101462306a36Sopenharmony_ci{
101562306a36Sopenharmony_ci	b43_radio_set(dev, R2057_XTALPUOVR_PINCTRL, 0x1);
101662306a36Sopenharmony_ci
101762306a36Sopenharmony_ci	if (0) /* FIXME: Is this BCM43217 specific? */
101862306a36Sopenharmony_ci		b43_radio_set(dev, R2057_XTALPUOVR_PINCTRL, 0x2);
101962306a36Sopenharmony_ci
102062306a36Sopenharmony_ci	b43_radio_set(dev, R2057_RFPLL_MISC_CAL_RESETN, 0x78);
102162306a36Sopenharmony_ci	b43_radio_set(dev, R2057_XTAL_CONFIG2, 0x80);
102262306a36Sopenharmony_ci	usleep_range(2000, 3000);
102362306a36Sopenharmony_ci	b43_radio_mask(dev, R2057_RFPLL_MISC_CAL_RESETN, ~0x78);
102462306a36Sopenharmony_ci	b43_radio_mask(dev, R2057_XTAL_CONFIG2, ~0x80);
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_ci	if (dev->phy.do_full_init) {
102762306a36Sopenharmony_ci		b43_radio_2057_rcal(dev);
102862306a36Sopenharmony_ci		b43_radio_2057_rccal(dev);
102962306a36Sopenharmony_ci	}
103062306a36Sopenharmony_ci	b43_radio_mask(dev, R2057_RFPLL_MASTER, ~0x8);
103162306a36Sopenharmony_ci}
103262306a36Sopenharmony_ci
103362306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/Radio/2057/Init */
103462306a36Sopenharmony_cistatic void b43_radio_2057_init(struct b43_wldev *dev)
103562306a36Sopenharmony_ci{
103662306a36Sopenharmony_ci	b43_radio_2057_init_pre(dev);
103762306a36Sopenharmony_ci	r2057_upload_inittabs(dev);
103862306a36Sopenharmony_ci	b43_radio_2057_init_post(dev);
103962306a36Sopenharmony_ci}
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ci/**************************************************
104262306a36Sopenharmony_ci * Radio 0x2056
104362306a36Sopenharmony_ci **************************************************/
104462306a36Sopenharmony_ci
104562306a36Sopenharmony_cistatic void b43_chantab_radio_2056_upload(struct b43_wldev *dev,
104662306a36Sopenharmony_ci				const struct b43_nphy_channeltab_entry_rev3 *e)
104762306a36Sopenharmony_ci{
104862306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_PLL_VCOCAL1, e->radio_syn_pll_vcocal1);
104962306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_PLL_VCOCAL2, e->radio_syn_pll_vcocal2);
105062306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_PLL_REFDIV, e->radio_syn_pll_refdiv);
105162306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_PLL_MMD2, e->radio_syn_pll_mmd2);
105262306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_PLL_MMD1, e->radio_syn_pll_mmd1);
105362306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1,
105462306a36Sopenharmony_ci					e->radio_syn_pll_loopfilter1);
105562306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2,
105662306a36Sopenharmony_ci					e->radio_syn_pll_loopfilter2);
105762306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER3,
105862306a36Sopenharmony_ci					e->radio_syn_pll_loopfilter3);
105962306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4,
106062306a36Sopenharmony_ci					e->radio_syn_pll_loopfilter4);
106162306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER5,
106262306a36Sopenharmony_ci					e->radio_syn_pll_loopfilter5);
106362306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_RESERVED_ADDR27,
106462306a36Sopenharmony_ci					e->radio_syn_reserved_addr27);
106562306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_RESERVED_ADDR28,
106662306a36Sopenharmony_ci					e->radio_syn_reserved_addr28);
106762306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_RESERVED_ADDR29,
106862306a36Sopenharmony_ci					e->radio_syn_reserved_addr29);
106962306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_LOGEN_VCOBUF1,
107062306a36Sopenharmony_ci					e->radio_syn_logen_vcobuf1);
107162306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_LOGEN_MIXER2, e->radio_syn_logen_mixer2);
107262306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_LOGEN_BUF3, e->radio_syn_logen_buf3);
107362306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_LOGEN_BUF4, e->radio_syn_logen_buf4);
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA_TUNE,
107662306a36Sopenharmony_ci					e->radio_rx0_lnaa_tune);
107762306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG_TUNE,
107862306a36Sopenharmony_ci					e->radio_rx0_lnag_tune);
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci	b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAA_BOOST_TUNE,
108162306a36Sopenharmony_ci					e->radio_tx0_intpaa_boost_tune);
108262306a36Sopenharmony_ci	b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAG_BOOST_TUNE,
108362306a36Sopenharmony_ci					e->radio_tx0_intpag_boost_tune);
108462306a36Sopenharmony_ci	b43_radio_write(dev, B2056_TX0 | B2056_TX_PADA_BOOST_TUNE,
108562306a36Sopenharmony_ci					e->radio_tx0_pada_boost_tune);
108662306a36Sopenharmony_ci	b43_radio_write(dev, B2056_TX0 | B2056_TX_PADG_BOOST_TUNE,
108762306a36Sopenharmony_ci					e->radio_tx0_padg_boost_tune);
108862306a36Sopenharmony_ci	b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAA_BOOST_TUNE,
108962306a36Sopenharmony_ci					e->radio_tx0_pgaa_boost_tune);
109062306a36Sopenharmony_ci	b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAG_BOOST_TUNE,
109162306a36Sopenharmony_ci					e->radio_tx0_pgag_boost_tune);
109262306a36Sopenharmony_ci	b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXA_BOOST_TUNE,
109362306a36Sopenharmony_ci					e->radio_tx0_mixa_boost_tune);
109462306a36Sopenharmony_ci	b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXG_BOOST_TUNE,
109562306a36Sopenharmony_ci					e->radio_tx0_mixg_boost_tune);
109662306a36Sopenharmony_ci
109762306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA_TUNE,
109862306a36Sopenharmony_ci					e->radio_rx1_lnaa_tune);
109962306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG_TUNE,
110062306a36Sopenharmony_ci					e->radio_rx1_lnag_tune);
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci	b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAA_BOOST_TUNE,
110362306a36Sopenharmony_ci					e->radio_tx1_intpaa_boost_tune);
110462306a36Sopenharmony_ci	b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAG_BOOST_TUNE,
110562306a36Sopenharmony_ci					e->radio_tx1_intpag_boost_tune);
110662306a36Sopenharmony_ci	b43_radio_write(dev, B2056_TX1 | B2056_TX_PADA_BOOST_TUNE,
110762306a36Sopenharmony_ci					e->radio_tx1_pada_boost_tune);
110862306a36Sopenharmony_ci	b43_radio_write(dev, B2056_TX1 | B2056_TX_PADG_BOOST_TUNE,
110962306a36Sopenharmony_ci					e->radio_tx1_padg_boost_tune);
111062306a36Sopenharmony_ci	b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAA_BOOST_TUNE,
111162306a36Sopenharmony_ci					e->radio_tx1_pgaa_boost_tune);
111262306a36Sopenharmony_ci	b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAG_BOOST_TUNE,
111362306a36Sopenharmony_ci					e->radio_tx1_pgag_boost_tune);
111462306a36Sopenharmony_ci	b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXA_BOOST_TUNE,
111562306a36Sopenharmony_ci					e->radio_tx1_mixa_boost_tune);
111662306a36Sopenharmony_ci	b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXG_BOOST_TUNE,
111762306a36Sopenharmony_ci					e->radio_tx1_mixg_boost_tune);
111862306a36Sopenharmony_ci}
111962306a36Sopenharmony_ci
112062306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2056Setup */
112162306a36Sopenharmony_cistatic void b43_radio_2056_setup(struct b43_wldev *dev,
112262306a36Sopenharmony_ci				const struct b43_nphy_channeltab_entry_rev3 *e)
112362306a36Sopenharmony_ci{
112462306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
112562306a36Sopenharmony_ci	struct ssb_sprom *sprom = dev->dev->bus_sprom;
112662306a36Sopenharmony_ci	enum nl80211_band band = b43_current_band(dev->wl);
112762306a36Sopenharmony_ci	u16 offset;
112862306a36Sopenharmony_ci	u8 i;
112962306a36Sopenharmony_ci	u16 bias, cbias;
113062306a36Sopenharmony_ci	u16 pag_boost, padg_boost, pgag_boost, mixg_boost;
113162306a36Sopenharmony_ci	u16 paa_boost, pada_boost, pgaa_boost, mixa_boost;
113262306a36Sopenharmony_ci	bool is_pkg_fab_smic;
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci	B43_WARN_ON(dev->phy.rev < 3);
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_ci	is_pkg_fab_smic =
113762306a36Sopenharmony_ci		((dev->dev->chip_id == BCMA_CHIP_ID_BCM43224 ||
113862306a36Sopenharmony_ci		  dev->dev->chip_id == BCMA_CHIP_ID_BCM43225 ||
113962306a36Sopenharmony_ci		  dev->dev->chip_id == BCMA_CHIP_ID_BCM43421) &&
114062306a36Sopenharmony_ci		 dev->dev->chip_pkg == BCMA_PKG_ID_BCM43224_FAB_SMIC);
114162306a36Sopenharmony_ci
114262306a36Sopenharmony_ci	b43_chantab_radio_2056_upload(dev, e);
114362306a36Sopenharmony_ci	b2056_upload_syn_pll_cp2(dev, band == NL80211_BAND_5GHZ);
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_ci	if (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
114662306a36Sopenharmony_ci	    b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
114762306a36Sopenharmony_ci		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
114862306a36Sopenharmony_ci		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F);
114962306a36Sopenharmony_ci		if (dev->dev->chip_id == BCMA_CHIP_ID_BCM4716 ||
115062306a36Sopenharmony_ci		    dev->dev->chip_id == BCMA_CHIP_ID_BCM47162) {
115162306a36Sopenharmony_ci			b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x14);
115262306a36Sopenharmony_ci			b43_radio_write(dev, B2056_SYN_PLL_CP2, 0);
115362306a36Sopenharmony_ci		} else {
115462306a36Sopenharmony_ci			b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x0B);
115562306a36Sopenharmony_ci			b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x14);
115662306a36Sopenharmony_ci		}
115762306a36Sopenharmony_ci	}
115862306a36Sopenharmony_ci	if (sprom->boardflags2_hi & B43_BFH2_GPLL_WAR2 &&
115962306a36Sopenharmony_ci	    b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
116062306a36Sopenharmony_ci		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1f);
116162306a36Sopenharmony_ci		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1f);
116262306a36Sopenharmony_ci		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x0b);
116362306a36Sopenharmony_ci		b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x20);
116462306a36Sopenharmony_ci	}
116562306a36Sopenharmony_ci	if (sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
116662306a36Sopenharmony_ci	    b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
116762306a36Sopenharmony_ci		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
116862306a36Sopenharmony_ci		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F);
116962306a36Sopenharmony_ci		b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x05);
117062306a36Sopenharmony_ci		b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x0C);
117162306a36Sopenharmony_ci	}
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ci	if (dev->phy.n->ipa2g_on && band == NL80211_BAND_2GHZ) {
117462306a36Sopenharmony_ci		for (i = 0; i < 2; i++) {
117562306a36Sopenharmony_ci			offset = i ? B2056_TX1 : B2056_TX0;
117662306a36Sopenharmony_ci			if (dev->phy.rev >= 5) {
117762306a36Sopenharmony_ci				b43_radio_write(dev,
117862306a36Sopenharmony_ci					offset | B2056_TX_PADG_IDAC, 0xcc);
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_ci				if (dev->dev->chip_id == BCMA_CHIP_ID_BCM4716 ||
118162306a36Sopenharmony_ci				    dev->dev->chip_id == BCMA_CHIP_ID_BCM47162) {
118262306a36Sopenharmony_ci					bias = 0x40;
118362306a36Sopenharmony_ci					cbias = 0x45;
118462306a36Sopenharmony_ci					pag_boost = 0x5;
118562306a36Sopenharmony_ci					pgag_boost = 0x33;
118662306a36Sopenharmony_ci					mixg_boost = 0x55;
118762306a36Sopenharmony_ci				} else {
118862306a36Sopenharmony_ci					bias = 0x25;
118962306a36Sopenharmony_ci					cbias = 0x20;
119062306a36Sopenharmony_ci					if (is_pkg_fab_smic) {
119162306a36Sopenharmony_ci						bias = 0x2a;
119262306a36Sopenharmony_ci						cbias = 0x38;
119362306a36Sopenharmony_ci					}
119462306a36Sopenharmony_ci					pag_boost = 0x4;
119562306a36Sopenharmony_ci					pgag_boost = 0x03;
119662306a36Sopenharmony_ci					mixg_boost = 0x65;
119762306a36Sopenharmony_ci				}
119862306a36Sopenharmony_ci				padg_boost = 0x77;
119962306a36Sopenharmony_ci
120062306a36Sopenharmony_ci				b43_radio_write(dev,
120162306a36Sopenharmony_ci					offset | B2056_TX_INTPAG_IMAIN_STAT,
120262306a36Sopenharmony_ci					bias);
120362306a36Sopenharmony_ci				b43_radio_write(dev,
120462306a36Sopenharmony_ci					offset | B2056_TX_INTPAG_IAUX_STAT,
120562306a36Sopenharmony_ci					bias);
120662306a36Sopenharmony_ci				b43_radio_write(dev,
120762306a36Sopenharmony_ci					offset | B2056_TX_INTPAG_CASCBIAS,
120862306a36Sopenharmony_ci					cbias);
120962306a36Sopenharmony_ci				b43_radio_write(dev,
121062306a36Sopenharmony_ci					offset | B2056_TX_INTPAG_BOOST_TUNE,
121162306a36Sopenharmony_ci					pag_boost);
121262306a36Sopenharmony_ci				b43_radio_write(dev,
121362306a36Sopenharmony_ci					offset | B2056_TX_PGAG_BOOST_TUNE,
121462306a36Sopenharmony_ci					pgag_boost);
121562306a36Sopenharmony_ci				b43_radio_write(dev,
121662306a36Sopenharmony_ci					offset | B2056_TX_PADG_BOOST_TUNE,
121762306a36Sopenharmony_ci					padg_boost);
121862306a36Sopenharmony_ci				b43_radio_write(dev,
121962306a36Sopenharmony_ci					offset | B2056_TX_MIXG_BOOST_TUNE,
122062306a36Sopenharmony_ci					mixg_boost);
122162306a36Sopenharmony_ci			} else {
122262306a36Sopenharmony_ci				bias = b43_is_40mhz(dev) ? 0x40 : 0x20;
122362306a36Sopenharmony_ci				b43_radio_write(dev,
122462306a36Sopenharmony_ci					offset | B2056_TX_INTPAG_IMAIN_STAT,
122562306a36Sopenharmony_ci					bias);
122662306a36Sopenharmony_ci				b43_radio_write(dev,
122762306a36Sopenharmony_ci					offset | B2056_TX_INTPAG_IAUX_STAT,
122862306a36Sopenharmony_ci					bias);
122962306a36Sopenharmony_ci				b43_radio_write(dev,
123062306a36Sopenharmony_ci					offset | B2056_TX_INTPAG_CASCBIAS,
123162306a36Sopenharmony_ci					0x30);
123262306a36Sopenharmony_ci			}
123362306a36Sopenharmony_ci			b43_radio_write(dev, offset | B2056_TX_PA_SPARE1, 0xee);
123462306a36Sopenharmony_ci		}
123562306a36Sopenharmony_ci	} else if (dev->phy.n->ipa5g_on && band == NL80211_BAND_5GHZ) {
123662306a36Sopenharmony_ci		u16 freq = phy->chandef->chan->center_freq;
123762306a36Sopenharmony_ci		if (freq < 5100) {
123862306a36Sopenharmony_ci			paa_boost = 0xA;
123962306a36Sopenharmony_ci			pada_boost = 0x77;
124062306a36Sopenharmony_ci			pgaa_boost = 0xF;
124162306a36Sopenharmony_ci			mixa_boost = 0xF;
124262306a36Sopenharmony_ci		} else if (freq < 5340) {
124362306a36Sopenharmony_ci			paa_boost = 0x8;
124462306a36Sopenharmony_ci			pada_boost = 0x77;
124562306a36Sopenharmony_ci			pgaa_boost = 0xFB;
124662306a36Sopenharmony_ci			mixa_boost = 0xF;
124762306a36Sopenharmony_ci		} else if (freq < 5650) {
124862306a36Sopenharmony_ci			paa_boost = 0x0;
124962306a36Sopenharmony_ci			pada_boost = 0x77;
125062306a36Sopenharmony_ci			pgaa_boost = 0xB;
125162306a36Sopenharmony_ci			mixa_boost = 0xF;
125262306a36Sopenharmony_ci		} else {
125362306a36Sopenharmony_ci			paa_boost = 0x0;
125462306a36Sopenharmony_ci			pada_boost = 0x77;
125562306a36Sopenharmony_ci			if (freq != 5825)
125662306a36Sopenharmony_ci				pgaa_boost = -(freq - 18) / 36 + 168;
125762306a36Sopenharmony_ci			else
125862306a36Sopenharmony_ci				pgaa_boost = 6;
125962306a36Sopenharmony_ci			mixa_boost = 0xF;
126062306a36Sopenharmony_ci		}
126162306a36Sopenharmony_ci
126262306a36Sopenharmony_ci		cbias = is_pkg_fab_smic ? 0x35 : 0x30;
126362306a36Sopenharmony_ci
126462306a36Sopenharmony_ci		for (i = 0; i < 2; i++) {
126562306a36Sopenharmony_ci			offset = i ? B2056_TX1 : B2056_TX0;
126662306a36Sopenharmony_ci
126762306a36Sopenharmony_ci			b43_radio_write(dev,
126862306a36Sopenharmony_ci				offset | B2056_TX_INTPAA_BOOST_TUNE, paa_boost);
126962306a36Sopenharmony_ci			b43_radio_write(dev,
127062306a36Sopenharmony_ci				offset | B2056_TX_PADA_BOOST_TUNE, pada_boost);
127162306a36Sopenharmony_ci			b43_radio_write(dev,
127262306a36Sopenharmony_ci				offset | B2056_TX_PGAA_BOOST_TUNE, pgaa_boost);
127362306a36Sopenharmony_ci			b43_radio_write(dev,
127462306a36Sopenharmony_ci				offset | B2056_TX_MIXA_BOOST_TUNE, mixa_boost);
127562306a36Sopenharmony_ci			b43_radio_write(dev,
127662306a36Sopenharmony_ci				offset | B2056_TX_TXSPARE1, 0x30);
127762306a36Sopenharmony_ci			b43_radio_write(dev,
127862306a36Sopenharmony_ci				offset | B2056_TX_PA_SPARE2, 0xee);
127962306a36Sopenharmony_ci			b43_radio_write(dev,
128062306a36Sopenharmony_ci				offset | B2056_TX_PADA_CASCBIAS, 0x03);
128162306a36Sopenharmony_ci			b43_radio_write(dev,
128262306a36Sopenharmony_ci				offset | B2056_TX_INTPAA_IAUX_STAT, 0x30);
128362306a36Sopenharmony_ci			b43_radio_write(dev,
128462306a36Sopenharmony_ci				offset | B2056_TX_INTPAA_IMAIN_STAT, 0x30);
128562306a36Sopenharmony_ci			b43_radio_write(dev,
128662306a36Sopenharmony_ci				offset | B2056_TX_INTPAA_CASCBIAS, cbias);
128762306a36Sopenharmony_ci		}
128862306a36Sopenharmony_ci	}
128962306a36Sopenharmony_ci
129062306a36Sopenharmony_ci	udelay(50);
129162306a36Sopenharmony_ci	/* VCO calibration */
129262306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_PLL_VCOCAL12, 0x00);
129362306a36Sopenharmony_ci	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38);
129462306a36Sopenharmony_ci	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x18);
129562306a36Sopenharmony_ci	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38);
129662306a36Sopenharmony_ci	b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x39);
129762306a36Sopenharmony_ci	udelay(300);
129862306a36Sopenharmony_ci}
129962306a36Sopenharmony_ci
130062306a36Sopenharmony_cistatic u8 b43_radio_2056_rcal(struct b43_wldev *dev)
130162306a36Sopenharmony_ci{
130262306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
130362306a36Sopenharmony_ci	u16 mast2, tmp;
130462306a36Sopenharmony_ci
130562306a36Sopenharmony_ci	if (phy->rev != 3)
130662306a36Sopenharmony_ci		return 0;
130762306a36Sopenharmony_ci
130862306a36Sopenharmony_ci	mast2 = b43_radio_read(dev, B2056_SYN_PLL_MAST2);
130962306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_PLL_MAST2, mast2 | 0x7);
131062306a36Sopenharmony_ci
131162306a36Sopenharmony_ci	udelay(10);
131262306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x01);
131362306a36Sopenharmony_ci	udelay(10);
131462306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x09);
131562306a36Sopenharmony_ci
131662306a36Sopenharmony_ci	if (!b43_radio_wait_value(dev, B2056_SYN_RCAL_CODE_OUT, 0x80, 0x80, 100,
131762306a36Sopenharmony_ci				  1000000)) {
131862306a36Sopenharmony_ci		b43err(dev->wl, "Radio recalibration timeout\n");
131962306a36Sopenharmony_ci		return 0;
132062306a36Sopenharmony_ci	}
132162306a36Sopenharmony_ci
132262306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x01);
132362306a36Sopenharmony_ci	tmp = b43_radio_read(dev, B2056_SYN_RCAL_CODE_OUT);
132462306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x00);
132562306a36Sopenharmony_ci
132662306a36Sopenharmony_ci	b43_radio_write(dev, B2056_SYN_PLL_MAST2, mast2);
132762306a36Sopenharmony_ci
132862306a36Sopenharmony_ci	return tmp & 0x1f;
132962306a36Sopenharmony_ci}
133062306a36Sopenharmony_ci
133162306a36Sopenharmony_cistatic void b43_radio_init2056_pre(struct b43_wldev *dev)
133262306a36Sopenharmony_ci{
133362306a36Sopenharmony_ci	b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
133462306a36Sopenharmony_ci		     ~B43_NPHY_RFCTL_CMD_CHIP0PU);
133562306a36Sopenharmony_ci	/* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */
133662306a36Sopenharmony_ci	b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
133762306a36Sopenharmony_ci		     B43_NPHY_RFCTL_CMD_OEPORFORCE);
133862306a36Sopenharmony_ci	b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
133962306a36Sopenharmony_ci		    ~B43_NPHY_RFCTL_CMD_OEPORFORCE);
134062306a36Sopenharmony_ci	b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
134162306a36Sopenharmony_ci		    B43_NPHY_RFCTL_CMD_CHIP0PU);
134262306a36Sopenharmony_ci}
134362306a36Sopenharmony_ci
134462306a36Sopenharmony_cistatic void b43_radio_init2056_post(struct b43_wldev *dev)
134562306a36Sopenharmony_ci{
134662306a36Sopenharmony_ci	b43_radio_set(dev, B2056_SYN_COM_CTRL, 0xB);
134762306a36Sopenharmony_ci	b43_radio_set(dev, B2056_SYN_COM_PU, 0x2);
134862306a36Sopenharmony_ci	b43_radio_set(dev, B2056_SYN_COM_RESET, 0x2);
134962306a36Sopenharmony_ci	msleep(1);
135062306a36Sopenharmony_ci	b43_radio_mask(dev, B2056_SYN_COM_RESET, ~0x2);
135162306a36Sopenharmony_ci	b43_radio_mask(dev, B2056_SYN_PLL_MAST2, ~0xFC);
135262306a36Sopenharmony_ci	b43_radio_mask(dev, B2056_SYN_RCCAL_CTRL0, ~0x1);
135362306a36Sopenharmony_ci	if (dev->phy.do_full_init)
135462306a36Sopenharmony_ci		b43_radio_2056_rcal(dev);
135562306a36Sopenharmony_ci}
135662306a36Sopenharmony_ci
135762306a36Sopenharmony_ci/*
135862306a36Sopenharmony_ci * Initialize a Broadcom 2056 N-radio
135962306a36Sopenharmony_ci * https://bcm-v4.sipsolutions.net/802.11/Radio/2056/Init
136062306a36Sopenharmony_ci */
136162306a36Sopenharmony_cistatic void b43_radio_init2056(struct b43_wldev *dev)
136262306a36Sopenharmony_ci{
136362306a36Sopenharmony_ci	b43_radio_init2056_pre(dev);
136462306a36Sopenharmony_ci	b2056_upload_inittabs(dev, 0, 0);
136562306a36Sopenharmony_ci	b43_radio_init2056_post(dev);
136662306a36Sopenharmony_ci}
136762306a36Sopenharmony_ci
136862306a36Sopenharmony_ci/**************************************************
136962306a36Sopenharmony_ci * Radio 0x2055
137062306a36Sopenharmony_ci **************************************************/
137162306a36Sopenharmony_ci
137262306a36Sopenharmony_cistatic void b43_chantab_radio_upload(struct b43_wldev *dev,
137362306a36Sopenharmony_ci				const struct b43_nphy_channeltab_entry_rev2 *e)
137462306a36Sopenharmony_ci{
137562306a36Sopenharmony_ci	b43_radio_write(dev, B2055_PLL_REF, e->radio_pll_ref);
137662306a36Sopenharmony_ci	b43_radio_write(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0);
137762306a36Sopenharmony_ci	b43_radio_write(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1);
137862306a36Sopenharmony_ci	b43_radio_write(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail);
137962306a36Sopenharmony_ci	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
138062306a36Sopenharmony_ci
138162306a36Sopenharmony_ci	b43_radio_write(dev, B2055_VCO_CAL1, e->radio_vco_cal1);
138262306a36Sopenharmony_ci	b43_radio_write(dev, B2055_VCO_CAL2, e->radio_vco_cal2);
138362306a36Sopenharmony_ci	b43_radio_write(dev, B2055_PLL_LFC1, e->radio_pll_lfc1);
138462306a36Sopenharmony_ci	b43_radio_write(dev, B2055_PLL_LFR1, e->radio_pll_lfr1);
138562306a36Sopenharmony_ci	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
138662306a36Sopenharmony_ci
138762306a36Sopenharmony_ci	b43_radio_write(dev, B2055_PLL_LFC2, e->radio_pll_lfc2);
138862306a36Sopenharmony_ci	b43_radio_write(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf);
138962306a36Sopenharmony_ci	b43_radio_write(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1);
139062306a36Sopenharmony_ci	b43_radio_write(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2);
139162306a36Sopenharmony_ci	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
139262306a36Sopenharmony_ci
139362306a36Sopenharmony_ci	b43_radio_write(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune);
139462306a36Sopenharmony_ci	b43_radio_write(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune);
139562306a36Sopenharmony_ci	b43_radio_write(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1);
139662306a36Sopenharmony_ci	b43_radio_write(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn);
139762306a36Sopenharmony_ci	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
139862306a36Sopenharmony_ci
139962306a36Sopenharmony_ci	b43_radio_write(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim);
140062306a36Sopenharmony_ci	b43_radio_write(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune);
140162306a36Sopenharmony_ci	b43_radio_write(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune);
140262306a36Sopenharmony_ci	b43_radio_write(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1);
140362306a36Sopenharmony_ci	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
140462306a36Sopenharmony_ci
140562306a36Sopenharmony_ci	b43_radio_write(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn);
140662306a36Sopenharmony_ci	b43_radio_write(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim);
140762306a36Sopenharmony_ci}
140862306a36Sopenharmony_ci
140962306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */
141062306a36Sopenharmony_cistatic void b43_radio_2055_setup(struct b43_wldev *dev,
141162306a36Sopenharmony_ci				const struct b43_nphy_channeltab_entry_rev2 *e)
141262306a36Sopenharmony_ci{
141362306a36Sopenharmony_ci	B43_WARN_ON(dev->phy.rev >= 3);
141462306a36Sopenharmony_ci
141562306a36Sopenharmony_ci	b43_chantab_radio_upload(dev, e);
141662306a36Sopenharmony_ci	udelay(50);
141762306a36Sopenharmony_ci	b43_radio_write(dev, B2055_VCO_CAL10, 0x05);
141862306a36Sopenharmony_ci	b43_radio_write(dev, B2055_VCO_CAL10, 0x45);
141962306a36Sopenharmony_ci	b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
142062306a36Sopenharmony_ci	b43_radio_write(dev, B2055_VCO_CAL10, 0x65);
142162306a36Sopenharmony_ci	udelay(300);
142262306a36Sopenharmony_ci}
142362306a36Sopenharmony_ci
142462306a36Sopenharmony_cistatic void b43_radio_init2055_pre(struct b43_wldev *dev)
142562306a36Sopenharmony_ci{
142662306a36Sopenharmony_ci	b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
142762306a36Sopenharmony_ci		     ~B43_NPHY_RFCTL_CMD_PORFORCE);
142862306a36Sopenharmony_ci	b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
142962306a36Sopenharmony_ci		    B43_NPHY_RFCTL_CMD_CHIP0PU |
143062306a36Sopenharmony_ci		    B43_NPHY_RFCTL_CMD_OEPORFORCE);
143162306a36Sopenharmony_ci	b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
143262306a36Sopenharmony_ci		    B43_NPHY_RFCTL_CMD_PORFORCE);
143362306a36Sopenharmony_ci}
143462306a36Sopenharmony_ci
143562306a36Sopenharmony_cistatic void b43_radio_init2055_post(struct b43_wldev *dev)
143662306a36Sopenharmony_ci{
143762306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
143862306a36Sopenharmony_ci	struct ssb_sprom *sprom = dev->dev->bus_sprom;
143962306a36Sopenharmony_ci	bool workaround = false;
144062306a36Sopenharmony_ci
144162306a36Sopenharmony_ci	if (sprom->revision < 4)
144262306a36Sopenharmony_ci		workaround = (dev->dev->board_vendor != PCI_VENDOR_ID_BROADCOM
144362306a36Sopenharmony_ci			      && dev->dev->board_type == SSB_BOARD_CB2_4321
144462306a36Sopenharmony_ci			      && dev->dev->board_rev >= 0x41);
144562306a36Sopenharmony_ci	else
144662306a36Sopenharmony_ci		workaround =
144762306a36Sopenharmony_ci			!(sprom->boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS);
144862306a36Sopenharmony_ci
144962306a36Sopenharmony_ci	b43_radio_mask(dev, B2055_MASTER1, 0xFFF3);
145062306a36Sopenharmony_ci	if (workaround) {
145162306a36Sopenharmony_ci		b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F);
145262306a36Sopenharmony_ci		b43_radio_mask(dev, B2055_C2_RX_BB_REG, 0x7F);
145362306a36Sopenharmony_ci	}
145462306a36Sopenharmony_ci	b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0xFFC0, 0x2C);
145562306a36Sopenharmony_ci	b43_radio_write(dev, B2055_CAL_MISC, 0x3C);
145662306a36Sopenharmony_ci	b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE);
145762306a36Sopenharmony_ci	b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80);
145862306a36Sopenharmony_ci	b43_radio_set(dev, B2055_CAL_MISC, 0x1);
145962306a36Sopenharmony_ci	msleep(1);
146062306a36Sopenharmony_ci	b43_radio_set(dev, B2055_CAL_MISC, 0x40);
146162306a36Sopenharmony_ci	if (!b43_radio_wait_value(dev, B2055_CAL_COUT2, 0x80, 0x80, 10, 2000))
146262306a36Sopenharmony_ci		b43err(dev->wl, "radio post init timeout\n");
146362306a36Sopenharmony_ci	b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F);
146462306a36Sopenharmony_ci	b43_switch_channel(dev, dev->phy.channel);
146562306a36Sopenharmony_ci	b43_radio_write(dev, B2055_C1_RX_BB_LPF, 0x9);
146662306a36Sopenharmony_ci	b43_radio_write(dev, B2055_C2_RX_BB_LPF, 0x9);
146762306a36Sopenharmony_ci	b43_radio_write(dev, B2055_C1_RX_BB_MIDACHP, 0x83);
146862306a36Sopenharmony_ci	b43_radio_write(dev, B2055_C2_RX_BB_MIDACHP, 0x83);
146962306a36Sopenharmony_ci	b43_radio_maskset(dev, B2055_C1_LNA_GAINBST, 0xFFF8, 0x6);
147062306a36Sopenharmony_ci	b43_radio_maskset(dev, B2055_C2_LNA_GAINBST, 0xFFF8, 0x6);
147162306a36Sopenharmony_ci	if (!nphy->gain_boost) {
147262306a36Sopenharmony_ci		b43_radio_set(dev, B2055_C1_RX_RFSPC1, 0x2);
147362306a36Sopenharmony_ci		b43_radio_set(dev, B2055_C2_RX_RFSPC1, 0x2);
147462306a36Sopenharmony_ci	} else {
147562306a36Sopenharmony_ci		b43_radio_mask(dev, B2055_C1_RX_RFSPC1, 0xFFFD);
147662306a36Sopenharmony_ci		b43_radio_mask(dev, B2055_C2_RX_RFSPC1, 0xFFFD);
147762306a36Sopenharmony_ci	}
147862306a36Sopenharmony_ci	udelay(2);
147962306a36Sopenharmony_ci}
148062306a36Sopenharmony_ci
148162306a36Sopenharmony_ci/*
148262306a36Sopenharmony_ci * Initialize a Broadcom 2055 N-radio
148362306a36Sopenharmony_ci * https://bcm-v4.sipsolutions.net/802.11/Radio/2055/Init
148462306a36Sopenharmony_ci */
148562306a36Sopenharmony_cistatic void b43_radio_init2055(struct b43_wldev *dev)
148662306a36Sopenharmony_ci{
148762306a36Sopenharmony_ci	b43_radio_init2055_pre(dev);
148862306a36Sopenharmony_ci	if (b43_status(dev) < B43_STAT_INITIALIZED) {
148962306a36Sopenharmony_ci		/* Follow wl, not specs. Do not force uploading all regs */
149062306a36Sopenharmony_ci		b2055_upload_inittab(dev, 0, 0);
149162306a36Sopenharmony_ci	} else {
149262306a36Sopenharmony_ci		bool ghz5 = b43_current_band(dev->wl) == NL80211_BAND_5GHZ;
149362306a36Sopenharmony_ci		b2055_upload_inittab(dev, ghz5, 0);
149462306a36Sopenharmony_ci	}
149562306a36Sopenharmony_ci	b43_radio_init2055_post(dev);
149662306a36Sopenharmony_ci}
149762306a36Sopenharmony_ci
149862306a36Sopenharmony_ci/**************************************************
149962306a36Sopenharmony_ci * Samples
150062306a36Sopenharmony_ci **************************************************/
150162306a36Sopenharmony_ci
150262306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/LoadSampleTable */
150362306a36Sopenharmony_cistatic int b43_nphy_load_samples(struct b43_wldev *dev,
150462306a36Sopenharmony_ci					struct cordic_iq *samples, u16 len) {
150562306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
150662306a36Sopenharmony_ci	u16 i;
150762306a36Sopenharmony_ci	u32 *data;
150862306a36Sopenharmony_ci
150962306a36Sopenharmony_ci	data = kcalloc(len, sizeof(u32), GFP_KERNEL);
151062306a36Sopenharmony_ci	if (!data) {
151162306a36Sopenharmony_ci		b43err(dev->wl, "allocation for samples loading failed\n");
151262306a36Sopenharmony_ci		return -ENOMEM;
151362306a36Sopenharmony_ci	}
151462306a36Sopenharmony_ci	if (nphy->hang_avoid)
151562306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, 1);
151662306a36Sopenharmony_ci
151762306a36Sopenharmony_ci	for (i = 0; i < len; i++) {
151862306a36Sopenharmony_ci		data[i] = (samples[i].i & 0x3FF << 10);
151962306a36Sopenharmony_ci		data[i] |= samples[i].q & 0x3FF;
152062306a36Sopenharmony_ci	}
152162306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB32(17, 0), len, data);
152262306a36Sopenharmony_ci
152362306a36Sopenharmony_ci	kfree(data);
152462306a36Sopenharmony_ci	if (nphy->hang_avoid)
152562306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, 0);
152662306a36Sopenharmony_ci	return 0;
152762306a36Sopenharmony_ci}
152862306a36Sopenharmony_ci
152962306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/GenLoadSamples */
153062306a36Sopenharmony_cistatic u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max,
153162306a36Sopenharmony_ci					bool test)
153262306a36Sopenharmony_ci{
153362306a36Sopenharmony_ci	int i;
153462306a36Sopenharmony_ci	u16 bw, len, rot, angle;
153562306a36Sopenharmony_ci	struct cordic_iq *samples;
153662306a36Sopenharmony_ci
153762306a36Sopenharmony_ci	bw = b43_is_40mhz(dev) ? 40 : 20;
153862306a36Sopenharmony_ci	len = bw << 3;
153962306a36Sopenharmony_ci
154062306a36Sopenharmony_ci	if (test) {
154162306a36Sopenharmony_ci		if (b43_phy_read(dev, B43_NPHY_BBCFG) & B43_NPHY_BBCFG_RSTRX)
154262306a36Sopenharmony_ci			bw = 82;
154362306a36Sopenharmony_ci		else
154462306a36Sopenharmony_ci			bw = 80;
154562306a36Sopenharmony_ci
154662306a36Sopenharmony_ci		if (b43_is_40mhz(dev))
154762306a36Sopenharmony_ci			bw <<= 1;
154862306a36Sopenharmony_ci
154962306a36Sopenharmony_ci		len = bw << 1;
155062306a36Sopenharmony_ci	}
155162306a36Sopenharmony_ci
155262306a36Sopenharmony_ci	samples = kcalloc(len, sizeof(struct cordic_iq), GFP_KERNEL);
155362306a36Sopenharmony_ci	if (!samples) {
155462306a36Sopenharmony_ci		b43err(dev->wl, "allocation for samples generation failed\n");
155562306a36Sopenharmony_ci		return 0;
155662306a36Sopenharmony_ci	}
155762306a36Sopenharmony_ci	rot = (((freq * 36) / bw) << 16) / 100;
155862306a36Sopenharmony_ci	angle = 0;
155962306a36Sopenharmony_ci
156062306a36Sopenharmony_ci	for (i = 0; i < len; i++) {
156162306a36Sopenharmony_ci		samples[i] = cordic_calc_iq(CORDIC_FIXED(angle));
156262306a36Sopenharmony_ci		angle += rot;
156362306a36Sopenharmony_ci		samples[i].q = CORDIC_FLOAT(samples[i].q * max);
156462306a36Sopenharmony_ci		samples[i].i = CORDIC_FLOAT(samples[i].i * max);
156562306a36Sopenharmony_ci	}
156662306a36Sopenharmony_ci
156762306a36Sopenharmony_ci	i = b43_nphy_load_samples(dev, samples, len);
156862306a36Sopenharmony_ci	kfree(samples);
156962306a36Sopenharmony_ci	return (i < 0) ? 0 : len;
157062306a36Sopenharmony_ci}
157162306a36Sopenharmony_ci
157262306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */
157362306a36Sopenharmony_cistatic void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops,
157462306a36Sopenharmony_ci				 u16 wait, bool iqmode, bool dac_test,
157562306a36Sopenharmony_ci				 bool modify_bbmult)
157662306a36Sopenharmony_ci{
157762306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
157862306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
157962306a36Sopenharmony_ci	int i;
158062306a36Sopenharmony_ci	u16 seq_mode;
158162306a36Sopenharmony_ci	u32 tmp;
158262306a36Sopenharmony_ci
158362306a36Sopenharmony_ci	b43_nphy_stay_in_carrier_search(dev, true);
158462306a36Sopenharmony_ci
158562306a36Sopenharmony_ci	if (phy->rev >= 7) {
158662306a36Sopenharmony_ci		bool lpf_bw3, lpf_bw4;
158762306a36Sopenharmony_ci
158862306a36Sopenharmony_ci		lpf_bw3 = b43_phy_read(dev, B43_NPHY_REV7_RF_CTL_OVER3) & 0x80;
158962306a36Sopenharmony_ci		lpf_bw4 = b43_phy_read(dev, B43_NPHY_REV7_RF_CTL_OVER4) & 0x80;
159062306a36Sopenharmony_ci
159162306a36Sopenharmony_ci		if (lpf_bw3 || lpf_bw4) {
159262306a36Sopenharmony_ci			/* TODO */
159362306a36Sopenharmony_ci		} else {
159462306a36Sopenharmony_ci			u16 value = b43_nphy_read_lpf_ctl(dev, 0);
159562306a36Sopenharmony_ci			if (phy->rev >= 19)
159662306a36Sopenharmony_ci				b43_nphy_rf_ctl_override_rev19(dev, 0x80, value,
159762306a36Sopenharmony_ci							       0, false, 1);
159862306a36Sopenharmony_ci			else
159962306a36Sopenharmony_ci				b43_nphy_rf_ctl_override_rev7(dev, 0x80, value,
160062306a36Sopenharmony_ci							      0, false, 1);
160162306a36Sopenharmony_ci			nphy->lpf_bw_overrode_for_sample_play = true;
160262306a36Sopenharmony_ci		}
160362306a36Sopenharmony_ci	}
160462306a36Sopenharmony_ci
160562306a36Sopenharmony_ci	if ((nphy->bb_mult_save & 0x80000000) == 0) {
160662306a36Sopenharmony_ci		tmp = b43_ntab_read(dev, B43_NTAB16(15, 87));
160762306a36Sopenharmony_ci		nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000;
160862306a36Sopenharmony_ci	}
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_ci	if (modify_bbmult) {
161162306a36Sopenharmony_ci		tmp = !b43_is_40mhz(dev) ? 0x6464 : 0x4747;
161262306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
161362306a36Sopenharmony_ci	}
161462306a36Sopenharmony_ci
161562306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_SAMP_DEPCNT, (samps - 1));
161662306a36Sopenharmony_ci
161762306a36Sopenharmony_ci	if (loops != 0xFFFF)
161862306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, (loops - 1));
161962306a36Sopenharmony_ci	else
162062306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, loops);
162162306a36Sopenharmony_ci
162262306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_SAMP_WAITCNT, wait);
162362306a36Sopenharmony_ci
162462306a36Sopenharmony_ci	seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);
162562306a36Sopenharmony_ci
162662306a36Sopenharmony_ci	b43_phy_set(dev, B43_NPHY_RFSEQMODE, B43_NPHY_RFSEQMODE_CAOVER);
162762306a36Sopenharmony_ci	if (iqmode) {
162862306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
162962306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8000);
163062306a36Sopenharmony_ci	} else {
163162306a36Sopenharmony_ci		tmp = dac_test ? 5 : 1;
163262306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_SAMP_CMD, tmp);
163362306a36Sopenharmony_ci	}
163462306a36Sopenharmony_ci	for (i = 0; i < 100; i++) {
163562306a36Sopenharmony_ci		if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & 1)) {
163662306a36Sopenharmony_ci			i = 0;
163762306a36Sopenharmony_ci			break;
163862306a36Sopenharmony_ci		}
163962306a36Sopenharmony_ci		udelay(10);
164062306a36Sopenharmony_ci	}
164162306a36Sopenharmony_ci	if (i)
164262306a36Sopenharmony_ci		b43err(dev->wl, "run samples timeout\n");
164362306a36Sopenharmony_ci
164462306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
164562306a36Sopenharmony_ci
164662306a36Sopenharmony_ci	b43_nphy_stay_in_carrier_search(dev, false);
164762306a36Sopenharmony_ci}
164862306a36Sopenharmony_ci
164962306a36Sopenharmony_ci/**************************************************
165062306a36Sopenharmony_ci * RSSI
165162306a36Sopenharmony_ci **************************************************/
165262306a36Sopenharmony_ci
165362306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */
165462306a36Sopenharmony_cistatic void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale,
165562306a36Sopenharmony_ci					s8 offset, u8 core,
165662306a36Sopenharmony_ci					enum n_rail_type rail,
165762306a36Sopenharmony_ci					enum n_rssi_type rssi_type)
165862306a36Sopenharmony_ci{
165962306a36Sopenharmony_ci	u16 tmp;
166062306a36Sopenharmony_ci	bool core1or5 = (core == 1) || (core == 5);
166162306a36Sopenharmony_ci	bool core2or5 = (core == 2) || (core == 5);
166262306a36Sopenharmony_ci
166362306a36Sopenharmony_ci	offset = clamp_val(offset, -32, 31);
166462306a36Sopenharmony_ci	tmp = ((scale & 0x3F) << 8) | (offset & 0x3F);
166562306a36Sopenharmony_ci
166662306a36Sopenharmony_ci	switch (rssi_type) {
166762306a36Sopenharmony_ci	case N_RSSI_NB:
166862306a36Sopenharmony_ci		if (core1or5 && rail == N_RAIL_I)
166962306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp);
167062306a36Sopenharmony_ci		if (core1or5 && rail == N_RAIL_Q)
167162306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp);
167262306a36Sopenharmony_ci		if (core2or5 && rail == N_RAIL_I)
167362306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp);
167462306a36Sopenharmony_ci		if (core2or5 && rail == N_RAIL_Q)
167562306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp);
167662306a36Sopenharmony_ci		break;
167762306a36Sopenharmony_ci	case N_RSSI_W1:
167862306a36Sopenharmony_ci		if (core1or5 && rail == N_RAIL_I)
167962306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp);
168062306a36Sopenharmony_ci		if (core1or5 && rail == N_RAIL_Q)
168162306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp);
168262306a36Sopenharmony_ci		if (core2or5 && rail == N_RAIL_I)
168362306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp);
168462306a36Sopenharmony_ci		if (core2or5 && rail == N_RAIL_Q)
168562306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp);
168662306a36Sopenharmony_ci		break;
168762306a36Sopenharmony_ci	case N_RSSI_W2:
168862306a36Sopenharmony_ci		if (core1or5 && rail == N_RAIL_I)
168962306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp);
169062306a36Sopenharmony_ci		if (core1or5 && rail == N_RAIL_Q)
169162306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp);
169262306a36Sopenharmony_ci		if (core2or5 && rail == N_RAIL_I)
169362306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp);
169462306a36Sopenharmony_ci		if (core2or5 && rail == N_RAIL_Q)
169562306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp);
169662306a36Sopenharmony_ci		break;
169762306a36Sopenharmony_ci	case N_RSSI_TBD:
169862306a36Sopenharmony_ci		if (core1or5 && rail == N_RAIL_I)
169962306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp);
170062306a36Sopenharmony_ci		if (core1or5 && rail == N_RAIL_Q)
170162306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp);
170262306a36Sopenharmony_ci		if (core2or5 && rail == N_RAIL_I)
170362306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp);
170462306a36Sopenharmony_ci		if (core2or5 && rail == N_RAIL_Q)
170562306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp);
170662306a36Sopenharmony_ci		break;
170762306a36Sopenharmony_ci	case N_RSSI_IQ:
170862306a36Sopenharmony_ci		if (core1or5 && rail == N_RAIL_I)
170962306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp);
171062306a36Sopenharmony_ci		if (core1or5 && rail == N_RAIL_Q)
171162306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp);
171262306a36Sopenharmony_ci		if (core2or5 && rail == N_RAIL_I)
171362306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp);
171462306a36Sopenharmony_ci		if (core2or5 && rail == N_RAIL_Q)
171562306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp);
171662306a36Sopenharmony_ci		break;
171762306a36Sopenharmony_ci	case N_RSSI_TSSI_2G:
171862306a36Sopenharmony_ci		if (core1or5)
171962306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp);
172062306a36Sopenharmony_ci		if (core2or5)
172162306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp);
172262306a36Sopenharmony_ci		break;
172362306a36Sopenharmony_ci	case N_RSSI_TSSI_5G:
172462306a36Sopenharmony_ci		if (core1or5)
172562306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp);
172662306a36Sopenharmony_ci		if (core2or5)
172762306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp);
172862306a36Sopenharmony_ci		break;
172962306a36Sopenharmony_ci	}
173062306a36Sopenharmony_ci}
173162306a36Sopenharmony_ci
173262306a36Sopenharmony_cistatic void b43_nphy_rssi_select_rev19(struct b43_wldev *dev, u8 code,
173362306a36Sopenharmony_ci				       enum n_rssi_type rssi_type)
173462306a36Sopenharmony_ci{
173562306a36Sopenharmony_ci	/* TODO */
173662306a36Sopenharmony_ci}
173762306a36Sopenharmony_ci
173862306a36Sopenharmony_cistatic void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code,
173962306a36Sopenharmony_ci				      enum n_rssi_type rssi_type)
174062306a36Sopenharmony_ci{
174162306a36Sopenharmony_ci	u8 i;
174262306a36Sopenharmony_ci	u16 reg, val;
174362306a36Sopenharmony_ci
174462306a36Sopenharmony_ci	if (code == 0) {
174562306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, 0xFDFF);
174662306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, 0xFDFF);
174762306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_AFECTL_C1, 0xFCFF);
174862306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_AFECTL_C2, 0xFCFF);
174962306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S0, 0xFFDF);
175062306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_TXF_40CO_B32S1, 0xFFDF);
175162306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0xFFC3);
175262306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0xFFC3);
175362306a36Sopenharmony_ci	} else {
175462306a36Sopenharmony_ci		for (i = 0; i < 2; i++) {
175562306a36Sopenharmony_ci			if ((code == 1 && i == 1) || (code == 2 && !i))
175662306a36Sopenharmony_ci				continue;
175762306a36Sopenharmony_ci
175862306a36Sopenharmony_ci			reg = (i == 0) ?
175962306a36Sopenharmony_ci				B43_NPHY_AFECTL_OVER1 : B43_NPHY_AFECTL_OVER;
176062306a36Sopenharmony_ci			b43_phy_maskset(dev, reg, 0xFDFF, 0x0200);
176162306a36Sopenharmony_ci
176262306a36Sopenharmony_ci			if (rssi_type == N_RSSI_W1 ||
176362306a36Sopenharmony_ci			    rssi_type == N_RSSI_W2 ||
176462306a36Sopenharmony_ci			    rssi_type == N_RSSI_NB) {
176562306a36Sopenharmony_ci				reg = (i == 0) ?
176662306a36Sopenharmony_ci					B43_NPHY_AFECTL_C1 :
176762306a36Sopenharmony_ci					B43_NPHY_AFECTL_C2;
176862306a36Sopenharmony_ci				b43_phy_maskset(dev, reg, 0xFCFF, 0);
176962306a36Sopenharmony_ci
177062306a36Sopenharmony_ci				reg = (i == 0) ?
177162306a36Sopenharmony_ci					B43_NPHY_RFCTL_LUT_TRSW_UP1 :
177262306a36Sopenharmony_ci					B43_NPHY_RFCTL_LUT_TRSW_UP2;
177362306a36Sopenharmony_ci				b43_phy_maskset(dev, reg, 0xFFC3, 0);
177462306a36Sopenharmony_ci
177562306a36Sopenharmony_ci				if (rssi_type == N_RSSI_W1)
177662306a36Sopenharmony_ci					val = (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ? 4 : 8;
177762306a36Sopenharmony_ci				else if (rssi_type == N_RSSI_W2)
177862306a36Sopenharmony_ci					val = 16;
177962306a36Sopenharmony_ci				else
178062306a36Sopenharmony_ci					val = 32;
178162306a36Sopenharmony_ci				b43_phy_set(dev, reg, val);
178262306a36Sopenharmony_ci
178362306a36Sopenharmony_ci				reg = (i == 0) ?
178462306a36Sopenharmony_ci					B43_NPHY_TXF_40CO_B1S0 :
178562306a36Sopenharmony_ci					B43_NPHY_TXF_40CO_B32S1;
178662306a36Sopenharmony_ci				b43_phy_set(dev, reg, 0x0020);
178762306a36Sopenharmony_ci			} else {
178862306a36Sopenharmony_ci				if (rssi_type == N_RSSI_TBD)
178962306a36Sopenharmony_ci					val = 0x0100;
179062306a36Sopenharmony_ci				else if (rssi_type == N_RSSI_IQ)
179162306a36Sopenharmony_ci					val = 0x0200;
179262306a36Sopenharmony_ci				else
179362306a36Sopenharmony_ci					val = 0x0300;
179462306a36Sopenharmony_ci
179562306a36Sopenharmony_ci				reg = (i == 0) ?
179662306a36Sopenharmony_ci					B43_NPHY_AFECTL_C1 :
179762306a36Sopenharmony_ci					B43_NPHY_AFECTL_C2;
179862306a36Sopenharmony_ci
179962306a36Sopenharmony_ci				b43_phy_maskset(dev, reg, 0xFCFF, val);
180062306a36Sopenharmony_ci				b43_phy_maskset(dev, reg, 0xF3FF, val << 2);
180162306a36Sopenharmony_ci
180262306a36Sopenharmony_ci				if (rssi_type != N_RSSI_IQ &&
180362306a36Sopenharmony_ci				    rssi_type != N_RSSI_TBD) {
180462306a36Sopenharmony_ci					enum nl80211_band band =
180562306a36Sopenharmony_ci						b43_current_band(dev->wl);
180662306a36Sopenharmony_ci
180762306a36Sopenharmony_ci					if (dev->phy.rev < 7) {
180862306a36Sopenharmony_ci						if (b43_nphy_ipa(dev))
180962306a36Sopenharmony_ci							val = (band == NL80211_BAND_5GHZ) ? 0xC : 0xE;
181062306a36Sopenharmony_ci						else
181162306a36Sopenharmony_ci							val = 0x11;
181262306a36Sopenharmony_ci						reg = (i == 0) ? B2056_TX0 : B2056_TX1;
181362306a36Sopenharmony_ci						reg |= B2056_TX_TX_SSI_MUX;
181462306a36Sopenharmony_ci						b43_radio_write(dev, reg, val);
181562306a36Sopenharmony_ci					}
181662306a36Sopenharmony_ci
181762306a36Sopenharmony_ci					reg = (i == 0) ?
181862306a36Sopenharmony_ci						B43_NPHY_AFECTL_OVER1 :
181962306a36Sopenharmony_ci						B43_NPHY_AFECTL_OVER;
182062306a36Sopenharmony_ci					b43_phy_set(dev, reg, 0x0200);
182162306a36Sopenharmony_ci				}
182262306a36Sopenharmony_ci			}
182362306a36Sopenharmony_ci		}
182462306a36Sopenharmony_ci	}
182562306a36Sopenharmony_ci}
182662306a36Sopenharmony_ci
182762306a36Sopenharmony_cistatic void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code,
182862306a36Sopenharmony_ci				      enum n_rssi_type rssi_type)
182962306a36Sopenharmony_ci{
183062306a36Sopenharmony_ci	u16 val;
183162306a36Sopenharmony_ci	bool rssi_w1_w2_nb = false;
183262306a36Sopenharmony_ci
183362306a36Sopenharmony_ci	switch (rssi_type) {
183462306a36Sopenharmony_ci	case N_RSSI_W1:
183562306a36Sopenharmony_ci	case N_RSSI_W2:
183662306a36Sopenharmony_ci	case N_RSSI_NB:
183762306a36Sopenharmony_ci		val = 0;
183862306a36Sopenharmony_ci		rssi_w1_w2_nb = true;
183962306a36Sopenharmony_ci		break;
184062306a36Sopenharmony_ci	case N_RSSI_TBD:
184162306a36Sopenharmony_ci		val = 1;
184262306a36Sopenharmony_ci		break;
184362306a36Sopenharmony_ci	case N_RSSI_IQ:
184462306a36Sopenharmony_ci		val = 2;
184562306a36Sopenharmony_ci		break;
184662306a36Sopenharmony_ci	default:
184762306a36Sopenharmony_ci		val = 3;
184862306a36Sopenharmony_ci	}
184962306a36Sopenharmony_ci
185062306a36Sopenharmony_ci	val = (val << 12) | (val << 14);
185162306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val);
185262306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val);
185362306a36Sopenharmony_ci
185462306a36Sopenharmony_ci	if (rssi_w1_w2_nb) {
185562306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF,
185662306a36Sopenharmony_ci				(rssi_type + 1) << 4);
185762306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF,
185862306a36Sopenharmony_ci				(rssi_type + 1) << 4);
185962306a36Sopenharmony_ci	}
186062306a36Sopenharmony_ci
186162306a36Sopenharmony_ci	if (code == 0) {
186262306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x3000);
186362306a36Sopenharmony_ci		if (rssi_w1_w2_nb) {
186462306a36Sopenharmony_ci			b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
186562306a36Sopenharmony_ci				~(B43_NPHY_RFCTL_CMD_RXEN |
186662306a36Sopenharmony_ci				  B43_NPHY_RFCTL_CMD_CORESEL));
186762306a36Sopenharmony_ci			b43_phy_mask(dev, B43_NPHY_RFCTL_OVER,
186862306a36Sopenharmony_ci				~(0x1 << 12 |
186962306a36Sopenharmony_ci				  0x1 << 5 |
187062306a36Sopenharmony_ci				  0x1 << 1 |
187162306a36Sopenharmony_ci				  0x1));
187262306a36Sopenharmony_ci			b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
187362306a36Sopenharmony_ci				~B43_NPHY_RFCTL_CMD_START);
187462306a36Sopenharmony_ci			udelay(20);
187562306a36Sopenharmony_ci			b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1);
187662306a36Sopenharmony_ci		}
187762306a36Sopenharmony_ci	} else {
187862306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x3000);
187962306a36Sopenharmony_ci		if (rssi_w1_w2_nb) {
188062306a36Sopenharmony_ci			b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
188162306a36Sopenharmony_ci				~(B43_NPHY_RFCTL_CMD_RXEN |
188262306a36Sopenharmony_ci				  B43_NPHY_RFCTL_CMD_CORESEL),
188362306a36Sopenharmony_ci				(B43_NPHY_RFCTL_CMD_RXEN |
188462306a36Sopenharmony_ci				 code << B43_NPHY_RFCTL_CMD_CORESEL_SHIFT));
188562306a36Sopenharmony_ci			b43_phy_set(dev, B43_NPHY_RFCTL_OVER,
188662306a36Sopenharmony_ci				(0x1 << 12 |
188762306a36Sopenharmony_ci				  0x1 << 5 |
188862306a36Sopenharmony_ci				  0x1 << 1 |
188962306a36Sopenharmony_ci				  0x1));
189062306a36Sopenharmony_ci			b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
189162306a36Sopenharmony_ci				B43_NPHY_RFCTL_CMD_START);
189262306a36Sopenharmony_ci			udelay(20);
189362306a36Sopenharmony_ci			b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1);
189462306a36Sopenharmony_ci		}
189562306a36Sopenharmony_ci	}
189662306a36Sopenharmony_ci}
189762306a36Sopenharmony_ci
189862306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */
189962306a36Sopenharmony_cistatic void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code,
190062306a36Sopenharmony_ci				 enum n_rssi_type type)
190162306a36Sopenharmony_ci{
190262306a36Sopenharmony_ci	if (dev->phy.rev >= 19)
190362306a36Sopenharmony_ci		b43_nphy_rssi_select_rev19(dev, code, type);
190462306a36Sopenharmony_ci	else if (dev->phy.rev >= 3)
190562306a36Sopenharmony_ci		b43_nphy_rev3_rssi_select(dev, code, type);
190662306a36Sopenharmony_ci	else
190762306a36Sopenharmony_ci		b43_nphy_rev2_rssi_select(dev, code, type);
190862306a36Sopenharmony_ci}
190962306a36Sopenharmony_ci
191062306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */
191162306a36Sopenharmony_cistatic void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev,
191262306a36Sopenharmony_ci				       enum n_rssi_type rssi_type, u8 *buf)
191362306a36Sopenharmony_ci{
191462306a36Sopenharmony_ci	int i;
191562306a36Sopenharmony_ci	for (i = 0; i < 2; i++) {
191662306a36Sopenharmony_ci		if (rssi_type == N_RSSI_NB) {
191762306a36Sopenharmony_ci			if (i == 0) {
191862306a36Sopenharmony_ci				b43_radio_maskset(dev, B2055_C1_B0NB_RSSIVCM,
191962306a36Sopenharmony_ci						  0xFC, buf[0]);
192062306a36Sopenharmony_ci				b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
192162306a36Sopenharmony_ci						  0xFC, buf[1]);
192262306a36Sopenharmony_ci			} else {
192362306a36Sopenharmony_ci				b43_radio_maskset(dev, B2055_C2_B0NB_RSSIVCM,
192462306a36Sopenharmony_ci						  0xFC, buf[2 * i]);
192562306a36Sopenharmony_ci				b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
192662306a36Sopenharmony_ci						  0xFC, buf[2 * i + 1]);
192762306a36Sopenharmony_ci			}
192862306a36Sopenharmony_ci		} else {
192962306a36Sopenharmony_ci			if (i == 0)
193062306a36Sopenharmony_ci				b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
193162306a36Sopenharmony_ci						  0xF3, buf[0] << 2);
193262306a36Sopenharmony_ci			else
193362306a36Sopenharmony_ci				b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
193462306a36Sopenharmony_ci						  0xF3, buf[2 * i + 1] << 2);
193562306a36Sopenharmony_ci		}
193662306a36Sopenharmony_ci	}
193762306a36Sopenharmony_ci}
193862306a36Sopenharmony_ci
193962306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */
194062306a36Sopenharmony_cistatic int b43_nphy_poll_rssi(struct b43_wldev *dev, enum n_rssi_type rssi_type,
194162306a36Sopenharmony_ci			      s32 *buf, u8 nsamp)
194262306a36Sopenharmony_ci{
194362306a36Sopenharmony_ci	int i;
194462306a36Sopenharmony_ci	int out;
194562306a36Sopenharmony_ci	u16 save_regs_phy[9];
194662306a36Sopenharmony_ci	u16 s[2];
194762306a36Sopenharmony_ci
194862306a36Sopenharmony_ci	/* TODO: rev7+ is treated like rev3+, what about rev19+? */
194962306a36Sopenharmony_ci
195062306a36Sopenharmony_ci	if (dev->phy.rev >= 3) {
195162306a36Sopenharmony_ci		save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
195262306a36Sopenharmony_ci		save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
195362306a36Sopenharmony_ci		save_regs_phy[2] = b43_phy_read(dev,
195462306a36Sopenharmony_ci						B43_NPHY_RFCTL_LUT_TRSW_UP1);
195562306a36Sopenharmony_ci		save_regs_phy[3] = b43_phy_read(dev,
195662306a36Sopenharmony_ci						B43_NPHY_RFCTL_LUT_TRSW_UP2);
195762306a36Sopenharmony_ci		save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
195862306a36Sopenharmony_ci		save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
195962306a36Sopenharmony_ci		save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0);
196062306a36Sopenharmony_ci		save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1);
196162306a36Sopenharmony_ci		save_regs_phy[8] = 0;
196262306a36Sopenharmony_ci	} else {
196362306a36Sopenharmony_ci		save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
196462306a36Sopenharmony_ci		save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
196562306a36Sopenharmony_ci		save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
196662306a36Sopenharmony_ci		save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_RFCTL_CMD);
196762306a36Sopenharmony_ci		save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER);
196862306a36Sopenharmony_ci		save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1);
196962306a36Sopenharmony_ci		save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2);
197062306a36Sopenharmony_ci		save_regs_phy[7] = 0;
197162306a36Sopenharmony_ci		save_regs_phy[8] = 0;
197262306a36Sopenharmony_ci	}
197362306a36Sopenharmony_ci
197462306a36Sopenharmony_ci	b43_nphy_rssi_select(dev, 5, rssi_type);
197562306a36Sopenharmony_ci
197662306a36Sopenharmony_ci	if (dev->phy.rev < 2) {
197762306a36Sopenharmony_ci		save_regs_phy[8] = b43_phy_read(dev, B43_NPHY_GPIO_SEL);
197862306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_GPIO_SEL, 5);
197962306a36Sopenharmony_ci	}
198062306a36Sopenharmony_ci
198162306a36Sopenharmony_ci	for (i = 0; i < 4; i++)
198262306a36Sopenharmony_ci		buf[i] = 0;
198362306a36Sopenharmony_ci
198462306a36Sopenharmony_ci	for (i = 0; i < nsamp; i++) {
198562306a36Sopenharmony_ci		if (dev->phy.rev < 2) {
198662306a36Sopenharmony_ci			s[0] = b43_phy_read(dev, B43_NPHY_GPIO_LOOUT);
198762306a36Sopenharmony_ci			s[1] = b43_phy_read(dev, B43_NPHY_GPIO_HIOUT);
198862306a36Sopenharmony_ci		} else {
198962306a36Sopenharmony_ci			s[0] = b43_phy_read(dev, B43_NPHY_RSSI1);
199062306a36Sopenharmony_ci			s[1] = b43_phy_read(dev, B43_NPHY_RSSI2);
199162306a36Sopenharmony_ci		}
199262306a36Sopenharmony_ci
199362306a36Sopenharmony_ci		buf[0] += ((s8)((s[0] & 0x3F) << 2)) >> 2;
199462306a36Sopenharmony_ci		buf[1] += ((s8)(((s[0] >> 8) & 0x3F) << 2)) >> 2;
199562306a36Sopenharmony_ci		buf[2] += ((s8)((s[1] & 0x3F) << 2)) >> 2;
199662306a36Sopenharmony_ci		buf[3] += ((s8)(((s[1] >> 8) & 0x3F) << 2)) >> 2;
199762306a36Sopenharmony_ci	}
199862306a36Sopenharmony_ci	out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 |
199962306a36Sopenharmony_ci		(buf[2] & 0xFF) << 8 | (buf[3] & 0xFF);
200062306a36Sopenharmony_ci
200162306a36Sopenharmony_ci	if (dev->phy.rev < 2)
200262306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_GPIO_SEL, save_regs_phy[8]);
200362306a36Sopenharmony_ci
200462306a36Sopenharmony_ci	if (dev->phy.rev >= 3) {
200562306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]);
200662306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]);
200762306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1,
200862306a36Sopenharmony_ci				save_regs_phy[2]);
200962306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2,
201062306a36Sopenharmony_ci				save_regs_phy[3]);
201162306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, save_regs_phy[4]);
201262306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]);
201362306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]);
201462306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]);
201562306a36Sopenharmony_ci	} else {
201662306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]);
201762306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]);
201862306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[2]);
201962306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_RFCTL_CMD, save_regs_phy[3]);
202062306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_RFCTL_OVER, save_regs_phy[4]);
202162306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, save_regs_phy[5]);
202262306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, save_regs_phy[6]);
202362306a36Sopenharmony_ci	}
202462306a36Sopenharmony_ci
202562306a36Sopenharmony_ci	return out;
202662306a36Sopenharmony_ci}
202762306a36Sopenharmony_ci
202862306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */
202962306a36Sopenharmony_cistatic void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
203062306a36Sopenharmony_ci{
203162306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
203262306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
203362306a36Sopenharmony_ci
203462306a36Sopenharmony_ci	u16 saved_regs_phy_rfctl[2];
203562306a36Sopenharmony_ci	u16 saved_regs_phy[22];
203662306a36Sopenharmony_ci	u16 regs_to_store_rev3[] = {
203762306a36Sopenharmony_ci		B43_NPHY_AFECTL_OVER1, B43_NPHY_AFECTL_OVER,
203862306a36Sopenharmony_ci		B43_NPHY_AFECTL_C1, B43_NPHY_AFECTL_C2,
203962306a36Sopenharmony_ci		B43_NPHY_TXF_40CO_B1S1, B43_NPHY_RFCTL_OVER,
204062306a36Sopenharmony_ci		B43_NPHY_TXF_40CO_B1S0, B43_NPHY_TXF_40CO_B32S1,
204162306a36Sopenharmony_ci		B43_NPHY_RFCTL_CMD,
204262306a36Sopenharmony_ci		B43_NPHY_RFCTL_LUT_TRSW_UP1, B43_NPHY_RFCTL_LUT_TRSW_UP2,
204362306a36Sopenharmony_ci		B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2
204462306a36Sopenharmony_ci	};
204562306a36Sopenharmony_ci	u16 regs_to_store_rev7[] = {
204662306a36Sopenharmony_ci		B43_NPHY_AFECTL_OVER1, B43_NPHY_AFECTL_OVER,
204762306a36Sopenharmony_ci		B43_NPHY_AFECTL_C1, B43_NPHY_AFECTL_C2,
204862306a36Sopenharmony_ci		B43_NPHY_TXF_40CO_B1S1, B43_NPHY_RFCTL_OVER,
204962306a36Sopenharmony_ci		B43_NPHY_REV7_RF_CTL_OVER3, B43_NPHY_REV7_RF_CTL_OVER4,
205062306a36Sopenharmony_ci		B43_NPHY_REV7_RF_CTL_OVER5, B43_NPHY_REV7_RF_CTL_OVER6,
205162306a36Sopenharmony_ci		0x2ff,
205262306a36Sopenharmony_ci		B43_NPHY_TXF_40CO_B1S0, B43_NPHY_TXF_40CO_B32S1,
205362306a36Sopenharmony_ci		B43_NPHY_RFCTL_CMD,
205462306a36Sopenharmony_ci		B43_NPHY_RFCTL_LUT_TRSW_UP1, B43_NPHY_RFCTL_LUT_TRSW_UP2,
205562306a36Sopenharmony_ci		B43_NPHY_REV7_RF_CTL_MISC_REG3, B43_NPHY_REV7_RF_CTL_MISC_REG4,
205662306a36Sopenharmony_ci		B43_NPHY_REV7_RF_CTL_MISC_REG5, B43_NPHY_REV7_RF_CTL_MISC_REG6,
205762306a36Sopenharmony_ci		B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2
205862306a36Sopenharmony_ci	};
205962306a36Sopenharmony_ci	u16 *regs_to_store;
206062306a36Sopenharmony_ci	int regs_amount;
206162306a36Sopenharmony_ci
206262306a36Sopenharmony_ci	u16 class;
206362306a36Sopenharmony_ci
206462306a36Sopenharmony_ci	u16 clip_state[2];
206562306a36Sopenharmony_ci	u16 clip_off[2] = { 0xFFFF, 0xFFFF };
206662306a36Sopenharmony_ci
206762306a36Sopenharmony_ci	u8 vcm_final = 0;
206862306a36Sopenharmony_ci	s32 offset[4];
206962306a36Sopenharmony_ci	s32 results[8][4] = { };
207062306a36Sopenharmony_ci	s32 results_min[4] = { };
207162306a36Sopenharmony_ci	s32 poll_results[4] = { };
207262306a36Sopenharmony_ci
207362306a36Sopenharmony_ci	u16 *rssical_radio_regs = NULL;
207462306a36Sopenharmony_ci	u16 *rssical_phy_regs = NULL;
207562306a36Sopenharmony_ci
207662306a36Sopenharmony_ci	u16 r; /* routing */
207762306a36Sopenharmony_ci	u8 rx_core_state;
207862306a36Sopenharmony_ci	int core, i, j, vcm;
207962306a36Sopenharmony_ci
208062306a36Sopenharmony_ci	if (dev->phy.rev >= 7) {
208162306a36Sopenharmony_ci		regs_to_store = regs_to_store_rev7;
208262306a36Sopenharmony_ci		regs_amount = ARRAY_SIZE(regs_to_store_rev7);
208362306a36Sopenharmony_ci	} else {
208462306a36Sopenharmony_ci		regs_to_store = regs_to_store_rev3;
208562306a36Sopenharmony_ci		regs_amount = ARRAY_SIZE(regs_to_store_rev3);
208662306a36Sopenharmony_ci	}
208762306a36Sopenharmony_ci	BUG_ON(regs_amount > ARRAY_SIZE(saved_regs_phy));
208862306a36Sopenharmony_ci
208962306a36Sopenharmony_ci	class = b43_nphy_classifier(dev, 0, 0);
209062306a36Sopenharmony_ci	b43_nphy_classifier(dev, 7, 4);
209162306a36Sopenharmony_ci	b43_nphy_read_clip_detection(dev, clip_state);
209262306a36Sopenharmony_ci	b43_nphy_write_clip_detection(dev, clip_off);
209362306a36Sopenharmony_ci
209462306a36Sopenharmony_ci	saved_regs_phy_rfctl[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
209562306a36Sopenharmony_ci	saved_regs_phy_rfctl[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
209662306a36Sopenharmony_ci	for (i = 0; i < regs_amount; i++)
209762306a36Sopenharmony_ci		saved_regs_phy[i] = b43_phy_read(dev, regs_to_store[i]);
209862306a36Sopenharmony_ci
209962306a36Sopenharmony_ci	b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_OFF, 0, 7);
210062306a36Sopenharmony_ci	b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 1, 7);
210162306a36Sopenharmony_ci
210262306a36Sopenharmony_ci	if (dev->phy.rev >= 7) {
210362306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_one_to_many(dev,
210462306a36Sopenharmony_ci						     N_RF_CTL_OVER_CMD_RXRF_PU,
210562306a36Sopenharmony_ci						     0, 0, false);
210662306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_one_to_many(dev,
210762306a36Sopenharmony_ci						     N_RF_CTL_OVER_CMD_RX_PU,
210862306a36Sopenharmony_ci						     1, 0, false);
210962306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_rev7(dev, 0x80, 1, 0, false, 0);
211062306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_rev7(dev, 0x40, 1, 0, false, 0);
211162306a36Sopenharmony_ci		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
211262306a36Sopenharmony_ci			b43_nphy_rf_ctl_override_rev7(dev, 0x20, 0, 0, false,
211362306a36Sopenharmony_ci						      0);
211462306a36Sopenharmony_ci			b43_nphy_rf_ctl_override_rev7(dev, 0x10, 1, 0, false,
211562306a36Sopenharmony_ci						      0);
211662306a36Sopenharmony_ci		} else {
211762306a36Sopenharmony_ci			b43_nphy_rf_ctl_override_rev7(dev, 0x10, 0, 0, false,
211862306a36Sopenharmony_ci						      0);
211962306a36Sopenharmony_ci			b43_nphy_rf_ctl_override_rev7(dev, 0x20, 1, 0, false,
212062306a36Sopenharmony_ci						      0);
212162306a36Sopenharmony_ci		}
212262306a36Sopenharmony_ci	} else {
212362306a36Sopenharmony_ci		b43_nphy_rf_ctl_override(dev, 0x1, 0, 0, false);
212462306a36Sopenharmony_ci		b43_nphy_rf_ctl_override(dev, 0x2, 1, 0, false);
212562306a36Sopenharmony_ci		b43_nphy_rf_ctl_override(dev, 0x80, 1, 0, false);
212662306a36Sopenharmony_ci		b43_nphy_rf_ctl_override(dev, 0x40, 1, 0, false);
212762306a36Sopenharmony_ci		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
212862306a36Sopenharmony_ci			b43_nphy_rf_ctl_override(dev, 0x20, 0, 0, false);
212962306a36Sopenharmony_ci			b43_nphy_rf_ctl_override(dev, 0x10, 1, 0, false);
213062306a36Sopenharmony_ci		} else {
213162306a36Sopenharmony_ci			b43_nphy_rf_ctl_override(dev, 0x10, 0, 0, false);
213262306a36Sopenharmony_ci			b43_nphy_rf_ctl_override(dev, 0x20, 1, 0, false);
213362306a36Sopenharmony_ci		}
213462306a36Sopenharmony_ci	}
213562306a36Sopenharmony_ci
213662306a36Sopenharmony_ci	rx_core_state = b43_nphy_get_rx_core_state(dev);
213762306a36Sopenharmony_ci	for (core = 0; core < 2; core++) {
213862306a36Sopenharmony_ci		if (!(rx_core_state & (1 << core)))
213962306a36Sopenharmony_ci			continue;
214062306a36Sopenharmony_ci		r = core ? B2056_RX1 : B2056_RX0;
214162306a36Sopenharmony_ci		b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, N_RAIL_I,
214262306a36Sopenharmony_ci					   N_RSSI_NB);
214362306a36Sopenharmony_ci		b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, N_RAIL_Q,
214462306a36Sopenharmony_ci					   N_RSSI_NB);
214562306a36Sopenharmony_ci
214662306a36Sopenharmony_ci		/* Grab RSSI results for every possible VCM */
214762306a36Sopenharmony_ci		for (vcm = 0; vcm < 8; vcm++) {
214862306a36Sopenharmony_ci			if (dev->phy.rev >= 7)
214962306a36Sopenharmony_ci				b43_radio_maskset(dev,
215062306a36Sopenharmony_ci						  core ? R2057_NB_MASTER_CORE1 :
215162306a36Sopenharmony_ci							 R2057_NB_MASTER_CORE0,
215262306a36Sopenharmony_ci						  ~R2057_VCM_MASK, vcm);
215362306a36Sopenharmony_ci			else
215462306a36Sopenharmony_ci				b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC,
215562306a36Sopenharmony_ci						  0xE3, vcm << 2);
215662306a36Sopenharmony_ci			b43_nphy_poll_rssi(dev, N_RSSI_NB, results[vcm], 8);
215762306a36Sopenharmony_ci		}
215862306a36Sopenharmony_ci
215962306a36Sopenharmony_ci		/* Find out which VCM got the best results */
216062306a36Sopenharmony_ci		for (i = 0; i < 4; i += 2) {
216162306a36Sopenharmony_ci			s32 currd;
216262306a36Sopenharmony_ci			s32 mind = 0x100000;
216362306a36Sopenharmony_ci			s32 minpoll = 249;
216462306a36Sopenharmony_ci			u8 minvcm = 0;
216562306a36Sopenharmony_ci			if (2 * core != i)
216662306a36Sopenharmony_ci				continue;
216762306a36Sopenharmony_ci			for (vcm = 0; vcm < 8; vcm++) {
216862306a36Sopenharmony_ci				currd = results[vcm][i] * results[vcm][i] +
216962306a36Sopenharmony_ci					results[vcm][i + 1] * results[vcm][i];
217062306a36Sopenharmony_ci				if (currd < mind) {
217162306a36Sopenharmony_ci					mind = currd;
217262306a36Sopenharmony_ci					minvcm = vcm;
217362306a36Sopenharmony_ci				}
217462306a36Sopenharmony_ci				if (results[vcm][i] < minpoll)
217562306a36Sopenharmony_ci					minpoll = results[vcm][i];
217662306a36Sopenharmony_ci			}
217762306a36Sopenharmony_ci			vcm_final = minvcm;
217862306a36Sopenharmony_ci			results_min[i] = minpoll;
217962306a36Sopenharmony_ci		}
218062306a36Sopenharmony_ci
218162306a36Sopenharmony_ci		/* Select the best VCM */
218262306a36Sopenharmony_ci		if (dev->phy.rev >= 7)
218362306a36Sopenharmony_ci			b43_radio_maskset(dev,
218462306a36Sopenharmony_ci					  core ? R2057_NB_MASTER_CORE1 :
218562306a36Sopenharmony_ci						 R2057_NB_MASTER_CORE0,
218662306a36Sopenharmony_ci					  ~R2057_VCM_MASK, vcm);
218762306a36Sopenharmony_ci		else
218862306a36Sopenharmony_ci			b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC,
218962306a36Sopenharmony_ci					  0xE3, vcm_final << 2);
219062306a36Sopenharmony_ci
219162306a36Sopenharmony_ci		for (i = 0; i < 4; i++) {
219262306a36Sopenharmony_ci			if (core != i / 2)
219362306a36Sopenharmony_ci				continue;
219462306a36Sopenharmony_ci			offset[i] = -results[vcm_final][i];
219562306a36Sopenharmony_ci			if (offset[i] < 0)
219662306a36Sopenharmony_ci				offset[i] = -((abs(offset[i]) + 4) / 8);
219762306a36Sopenharmony_ci			else
219862306a36Sopenharmony_ci				offset[i] = (offset[i] + 4) / 8;
219962306a36Sopenharmony_ci			if (results_min[i] == 248)
220062306a36Sopenharmony_ci				offset[i] = -32;
220162306a36Sopenharmony_ci			b43_nphy_scale_offset_rssi(dev, 0, offset[i],
220262306a36Sopenharmony_ci						   (i / 2 == 0) ? 1 : 2,
220362306a36Sopenharmony_ci						   (i % 2 == 0) ? N_RAIL_I : N_RAIL_Q,
220462306a36Sopenharmony_ci						   N_RSSI_NB);
220562306a36Sopenharmony_ci		}
220662306a36Sopenharmony_ci	}
220762306a36Sopenharmony_ci
220862306a36Sopenharmony_ci	for (core = 0; core < 2; core++) {
220962306a36Sopenharmony_ci		if (!(rx_core_state & (1 << core)))
221062306a36Sopenharmony_ci			continue;
221162306a36Sopenharmony_ci		for (i = 0; i < 2; i++) {
221262306a36Sopenharmony_ci			b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1,
221362306a36Sopenharmony_ci						   N_RAIL_I, i);
221462306a36Sopenharmony_ci			b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1,
221562306a36Sopenharmony_ci						   N_RAIL_Q, i);
221662306a36Sopenharmony_ci			b43_nphy_poll_rssi(dev, i, poll_results, 8);
221762306a36Sopenharmony_ci			for (j = 0; j < 4; j++) {
221862306a36Sopenharmony_ci				if (j / 2 == core) {
221962306a36Sopenharmony_ci					offset[j] = 232 - poll_results[j];
222062306a36Sopenharmony_ci					if (offset[j] < 0)
222162306a36Sopenharmony_ci						offset[j] = -(abs(offset[j] + 4) / 8);
222262306a36Sopenharmony_ci					else
222362306a36Sopenharmony_ci						offset[j] = (offset[j] + 4) / 8;
222462306a36Sopenharmony_ci					b43_nphy_scale_offset_rssi(dev, 0,
222562306a36Sopenharmony_ci						offset[2 * core], core + 1, j % 2, i);
222662306a36Sopenharmony_ci				}
222762306a36Sopenharmony_ci			}
222862306a36Sopenharmony_ci		}
222962306a36Sopenharmony_ci	}
223062306a36Sopenharmony_ci
223162306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, saved_regs_phy_rfctl[0]);
223262306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, saved_regs_phy_rfctl[1]);
223362306a36Sopenharmony_ci
223462306a36Sopenharmony_ci	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
223562306a36Sopenharmony_ci
223662306a36Sopenharmony_ci	b43_phy_set(dev, B43_NPHY_TXF_40CO_B1S1, 0x1);
223762306a36Sopenharmony_ci	b43_phy_set(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_START);
223862306a36Sopenharmony_ci	b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S1, ~0x1);
223962306a36Sopenharmony_ci
224062306a36Sopenharmony_ci	b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x1);
224162306a36Sopenharmony_ci	b43_phy_set(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_RXTX);
224262306a36Sopenharmony_ci	b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1);
224362306a36Sopenharmony_ci
224462306a36Sopenharmony_ci	for (i = 0; i < regs_amount; i++)
224562306a36Sopenharmony_ci		b43_phy_write(dev, regs_to_store[i], saved_regs_phy[i]);
224662306a36Sopenharmony_ci
224762306a36Sopenharmony_ci	/* Store for future configuration */
224862306a36Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
224962306a36Sopenharmony_ci		rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G;
225062306a36Sopenharmony_ci		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G;
225162306a36Sopenharmony_ci	} else {
225262306a36Sopenharmony_ci		rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G;
225362306a36Sopenharmony_ci		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
225462306a36Sopenharmony_ci	}
225562306a36Sopenharmony_ci	if (dev->phy.rev >= 7) {
225662306a36Sopenharmony_ci		rssical_radio_regs[0] = b43_radio_read(dev,
225762306a36Sopenharmony_ci						       R2057_NB_MASTER_CORE0);
225862306a36Sopenharmony_ci		rssical_radio_regs[1] = b43_radio_read(dev,
225962306a36Sopenharmony_ci						       R2057_NB_MASTER_CORE1);
226062306a36Sopenharmony_ci	} else {
226162306a36Sopenharmony_ci		rssical_radio_regs[0] = b43_radio_read(dev, B2056_RX0 |
226262306a36Sopenharmony_ci						       B2056_RX_RSSI_MISC);
226362306a36Sopenharmony_ci		rssical_radio_regs[1] = b43_radio_read(dev, B2056_RX1 |
226462306a36Sopenharmony_ci						       B2056_RX_RSSI_MISC);
226562306a36Sopenharmony_ci	}
226662306a36Sopenharmony_ci	rssical_phy_regs[0] = b43_phy_read(dev, B43_NPHY_RSSIMC_0I_RSSI_Z);
226762306a36Sopenharmony_ci	rssical_phy_regs[1] = b43_phy_read(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z);
226862306a36Sopenharmony_ci	rssical_phy_regs[2] = b43_phy_read(dev, B43_NPHY_RSSIMC_1I_RSSI_Z);
226962306a36Sopenharmony_ci	rssical_phy_regs[3] = b43_phy_read(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z);
227062306a36Sopenharmony_ci	rssical_phy_regs[4] = b43_phy_read(dev, B43_NPHY_RSSIMC_0I_RSSI_X);
227162306a36Sopenharmony_ci	rssical_phy_regs[5] = b43_phy_read(dev, B43_NPHY_RSSIMC_0Q_RSSI_X);
227262306a36Sopenharmony_ci	rssical_phy_regs[6] = b43_phy_read(dev, B43_NPHY_RSSIMC_1I_RSSI_X);
227362306a36Sopenharmony_ci	rssical_phy_regs[7] = b43_phy_read(dev, B43_NPHY_RSSIMC_1Q_RSSI_X);
227462306a36Sopenharmony_ci	rssical_phy_regs[8] = b43_phy_read(dev, B43_NPHY_RSSIMC_0I_RSSI_Y);
227562306a36Sopenharmony_ci	rssical_phy_regs[9] = b43_phy_read(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y);
227662306a36Sopenharmony_ci	rssical_phy_regs[10] = b43_phy_read(dev, B43_NPHY_RSSIMC_1I_RSSI_Y);
227762306a36Sopenharmony_ci	rssical_phy_regs[11] = b43_phy_read(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y);
227862306a36Sopenharmony_ci
227962306a36Sopenharmony_ci	/* Remember for which channel we store configuration */
228062306a36Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
228162306a36Sopenharmony_ci		nphy->rssical_chanspec_2G.center_freq = phy->chandef->chan->center_freq;
228262306a36Sopenharmony_ci	else
228362306a36Sopenharmony_ci		nphy->rssical_chanspec_5G.center_freq = phy->chandef->chan->center_freq;
228462306a36Sopenharmony_ci
228562306a36Sopenharmony_ci	/* End of calibration, restore configuration */
228662306a36Sopenharmony_ci	b43_nphy_classifier(dev, 7, class);
228762306a36Sopenharmony_ci	b43_nphy_write_clip_detection(dev, clip_state);
228862306a36Sopenharmony_ci}
228962306a36Sopenharmony_ci
229062306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */
229162306a36Sopenharmony_cistatic void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, enum n_rssi_type type)
229262306a36Sopenharmony_ci{
229362306a36Sopenharmony_ci	int i, j, vcm;
229462306a36Sopenharmony_ci	u8 state[4];
229562306a36Sopenharmony_ci	u8 code, val;
229662306a36Sopenharmony_ci	u16 class, override;
229762306a36Sopenharmony_ci	u8 regs_save_radio[2];
229862306a36Sopenharmony_ci	u16 regs_save_phy[2];
229962306a36Sopenharmony_ci
230062306a36Sopenharmony_ci	s32 offset[4];
230162306a36Sopenharmony_ci	u8 core;
230262306a36Sopenharmony_ci	u8 rail;
230362306a36Sopenharmony_ci
230462306a36Sopenharmony_ci	u16 clip_state[2];
230562306a36Sopenharmony_ci	u16 clip_off[2] = { 0xFFFF, 0xFFFF };
230662306a36Sopenharmony_ci	s32 results_min[4] = { };
230762306a36Sopenharmony_ci	u8 vcm_final[4] = { };
230862306a36Sopenharmony_ci	s32 results[4][4] = { };
230962306a36Sopenharmony_ci	s32 miniq[4][2] = { };
231062306a36Sopenharmony_ci
231162306a36Sopenharmony_ci	if (type == N_RSSI_NB) {
231262306a36Sopenharmony_ci		code = 0;
231362306a36Sopenharmony_ci		val = 6;
231462306a36Sopenharmony_ci	} else if (type == N_RSSI_W1 || type == N_RSSI_W2) {
231562306a36Sopenharmony_ci		code = 25;
231662306a36Sopenharmony_ci		val = 4;
231762306a36Sopenharmony_ci	} else {
231862306a36Sopenharmony_ci		B43_WARN_ON(1);
231962306a36Sopenharmony_ci		return;
232062306a36Sopenharmony_ci	}
232162306a36Sopenharmony_ci
232262306a36Sopenharmony_ci	class = b43_nphy_classifier(dev, 0, 0);
232362306a36Sopenharmony_ci	b43_nphy_classifier(dev, 7, 4);
232462306a36Sopenharmony_ci	b43_nphy_read_clip_detection(dev, clip_state);
232562306a36Sopenharmony_ci	b43_nphy_write_clip_detection(dev, clip_off);
232662306a36Sopenharmony_ci
232762306a36Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
232862306a36Sopenharmony_ci		override = 0x140;
232962306a36Sopenharmony_ci	else
233062306a36Sopenharmony_ci		override = 0x110;
233162306a36Sopenharmony_ci
233262306a36Sopenharmony_ci	regs_save_phy[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
233362306a36Sopenharmony_ci	regs_save_radio[0] = b43_radio_read(dev, B2055_C1_PD_RXTX);
233462306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, override);
233562306a36Sopenharmony_ci	b43_radio_write(dev, B2055_C1_PD_RXTX, val);
233662306a36Sopenharmony_ci
233762306a36Sopenharmony_ci	regs_save_phy[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
233862306a36Sopenharmony_ci	regs_save_radio[1] = b43_radio_read(dev, B2055_C2_PD_RXTX);
233962306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, override);
234062306a36Sopenharmony_ci	b43_radio_write(dev, B2055_C2_PD_RXTX, val);
234162306a36Sopenharmony_ci
234262306a36Sopenharmony_ci	state[0] = b43_radio_read(dev, B2055_C1_PD_RSSIMISC) & 0x07;
234362306a36Sopenharmony_ci	state[1] = b43_radio_read(dev, B2055_C2_PD_RSSIMISC) & 0x07;
234462306a36Sopenharmony_ci	b43_radio_mask(dev, B2055_C1_PD_RSSIMISC, 0xF8);
234562306a36Sopenharmony_ci	b43_radio_mask(dev, B2055_C2_PD_RSSIMISC, 0xF8);
234662306a36Sopenharmony_ci	state[2] = b43_radio_read(dev, B2055_C1_SP_RSSI) & 0x07;
234762306a36Sopenharmony_ci	state[3] = b43_radio_read(dev, B2055_C2_SP_RSSI) & 0x07;
234862306a36Sopenharmony_ci
234962306a36Sopenharmony_ci	b43_nphy_rssi_select(dev, 5, type);
235062306a36Sopenharmony_ci	b43_nphy_scale_offset_rssi(dev, 0, 0, 5, N_RAIL_I, type);
235162306a36Sopenharmony_ci	b43_nphy_scale_offset_rssi(dev, 0, 0, 5, N_RAIL_Q, type);
235262306a36Sopenharmony_ci
235362306a36Sopenharmony_ci	for (vcm = 0; vcm < 4; vcm++) {
235462306a36Sopenharmony_ci		u8 tmp[4];
235562306a36Sopenharmony_ci		for (j = 0; j < 4; j++)
235662306a36Sopenharmony_ci			tmp[j] = vcm;
235762306a36Sopenharmony_ci		if (type != N_RSSI_W2)
235862306a36Sopenharmony_ci			b43_nphy_set_rssi_2055_vcm(dev, type, tmp);
235962306a36Sopenharmony_ci		b43_nphy_poll_rssi(dev, type, results[vcm], 8);
236062306a36Sopenharmony_ci		if (type == N_RSSI_W1 || type == N_RSSI_W2)
236162306a36Sopenharmony_ci			for (j = 0; j < 2; j++)
236262306a36Sopenharmony_ci				miniq[vcm][j] = min(results[vcm][2 * j],
236362306a36Sopenharmony_ci						    results[vcm][2 * j + 1]);
236462306a36Sopenharmony_ci	}
236562306a36Sopenharmony_ci
236662306a36Sopenharmony_ci	for (i = 0; i < 4; i++) {
236762306a36Sopenharmony_ci		s32 mind = 0x100000;
236862306a36Sopenharmony_ci		u8 minvcm = 0;
236962306a36Sopenharmony_ci		s32 minpoll = 249;
237062306a36Sopenharmony_ci		s32 currd;
237162306a36Sopenharmony_ci		for (vcm = 0; vcm < 4; vcm++) {
237262306a36Sopenharmony_ci			if (type == N_RSSI_NB)
237362306a36Sopenharmony_ci				currd = abs(results[vcm][i] - code * 8);
237462306a36Sopenharmony_ci			else
237562306a36Sopenharmony_ci				currd = abs(miniq[vcm][i / 2] - code * 8);
237662306a36Sopenharmony_ci
237762306a36Sopenharmony_ci			if (currd < mind) {
237862306a36Sopenharmony_ci				mind = currd;
237962306a36Sopenharmony_ci				minvcm = vcm;
238062306a36Sopenharmony_ci			}
238162306a36Sopenharmony_ci
238262306a36Sopenharmony_ci			if (results[vcm][i] < minpoll)
238362306a36Sopenharmony_ci				minpoll = results[vcm][i];
238462306a36Sopenharmony_ci		}
238562306a36Sopenharmony_ci		results_min[i] = minpoll;
238662306a36Sopenharmony_ci		vcm_final[i] = minvcm;
238762306a36Sopenharmony_ci	}
238862306a36Sopenharmony_ci
238962306a36Sopenharmony_ci	if (type != N_RSSI_W2)
239062306a36Sopenharmony_ci		b43_nphy_set_rssi_2055_vcm(dev, type, vcm_final);
239162306a36Sopenharmony_ci
239262306a36Sopenharmony_ci	for (i = 0; i < 4; i++) {
239362306a36Sopenharmony_ci		offset[i] = (code * 8) - results[vcm_final[i]][i];
239462306a36Sopenharmony_ci
239562306a36Sopenharmony_ci		if (offset[i] < 0)
239662306a36Sopenharmony_ci			offset[i] = -((abs(offset[i]) + 4) / 8);
239762306a36Sopenharmony_ci		else
239862306a36Sopenharmony_ci			offset[i] = (offset[i] + 4) / 8;
239962306a36Sopenharmony_ci
240062306a36Sopenharmony_ci		if (results_min[i] == 248)
240162306a36Sopenharmony_ci			offset[i] = code - 32;
240262306a36Sopenharmony_ci
240362306a36Sopenharmony_ci		core = (i / 2) ? 2 : 1;
240462306a36Sopenharmony_ci		rail = (i % 2) ? N_RAIL_Q : N_RAIL_I;
240562306a36Sopenharmony_ci
240662306a36Sopenharmony_ci		b43_nphy_scale_offset_rssi(dev, 0, offset[i], core, rail,
240762306a36Sopenharmony_ci						type);
240862306a36Sopenharmony_ci	}
240962306a36Sopenharmony_ci
241062306a36Sopenharmony_ci	b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[0]);
241162306a36Sopenharmony_ci	b43_radio_maskset(dev, B2055_C2_PD_RSSIMISC, 0xF8, state[1]);
241262306a36Sopenharmony_ci
241362306a36Sopenharmony_ci	switch (state[2]) {
241462306a36Sopenharmony_ci	case 1:
241562306a36Sopenharmony_ci		b43_nphy_rssi_select(dev, 1, N_RSSI_NB);
241662306a36Sopenharmony_ci		break;
241762306a36Sopenharmony_ci	case 4:
241862306a36Sopenharmony_ci		b43_nphy_rssi_select(dev, 1, N_RSSI_W1);
241962306a36Sopenharmony_ci		break;
242062306a36Sopenharmony_ci	case 2:
242162306a36Sopenharmony_ci		b43_nphy_rssi_select(dev, 1, N_RSSI_W2);
242262306a36Sopenharmony_ci		break;
242362306a36Sopenharmony_ci	default:
242462306a36Sopenharmony_ci		b43_nphy_rssi_select(dev, 1, N_RSSI_W2);
242562306a36Sopenharmony_ci		break;
242662306a36Sopenharmony_ci	}
242762306a36Sopenharmony_ci
242862306a36Sopenharmony_ci	switch (state[3]) {
242962306a36Sopenharmony_ci	case 1:
243062306a36Sopenharmony_ci		b43_nphy_rssi_select(dev, 2, N_RSSI_NB);
243162306a36Sopenharmony_ci		break;
243262306a36Sopenharmony_ci	case 4:
243362306a36Sopenharmony_ci		b43_nphy_rssi_select(dev, 2, N_RSSI_W1);
243462306a36Sopenharmony_ci		break;
243562306a36Sopenharmony_ci	default:
243662306a36Sopenharmony_ci		b43_nphy_rssi_select(dev, 2, N_RSSI_W2);
243762306a36Sopenharmony_ci		break;
243862306a36Sopenharmony_ci	}
243962306a36Sopenharmony_ci
244062306a36Sopenharmony_ci	b43_nphy_rssi_select(dev, 0, type);
244162306a36Sopenharmony_ci
244262306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs_save_phy[0]);
244362306a36Sopenharmony_ci	b43_radio_write(dev, B2055_C1_PD_RXTX, regs_save_radio[0]);
244462306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs_save_phy[1]);
244562306a36Sopenharmony_ci	b43_radio_write(dev, B2055_C2_PD_RXTX, regs_save_radio[1]);
244662306a36Sopenharmony_ci
244762306a36Sopenharmony_ci	b43_nphy_classifier(dev, 7, class);
244862306a36Sopenharmony_ci	b43_nphy_write_clip_detection(dev, clip_state);
244962306a36Sopenharmony_ci	/* Specs don't say about reset here, but it makes wl and b43 dumps
245062306a36Sopenharmony_ci	   identical, it really seems wl performs this */
245162306a36Sopenharmony_ci	b43_nphy_reset_cca(dev);
245262306a36Sopenharmony_ci}
245362306a36Sopenharmony_ci
245462306a36Sopenharmony_ci/*
245562306a36Sopenharmony_ci * RSSI Calibration
245662306a36Sopenharmony_ci * https://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal
245762306a36Sopenharmony_ci */
245862306a36Sopenharmony_cistatic void b43_nphy_rssi_cal(struct b43_wldev *dev)
245962306a36Sopenharmony_ci{
246062306a36Sopenharmony_ci	if (dev->phy.rev >= 19) {
246162306a36Sopenharmony_ci		/* TODO */
246262306a36Sopenharmony_ci	} else if (dev->phy.rev >= 3) {
246362306a36Sopenharmony_ci		b43_nphy_rev3_rssi_cal(dev);
246462306a36Sopenharmony_ci	} else {
246562306a36Sopenharmony_ci		b43_nphy_rev2_rssi_cal(dev, N_RSSI_NB);
246662306a36Sopenharmony_ci		b43_nphy_rev2_rssi_cal(dev, N_RSSI_W1);
246762306a36Sopenharmony_ci		b43_nphy_rev2_rssi_cal(dev, N_RSSI_W2);
246862306a36Sopenharmony_ci	}
246962306a36Sopenharmony_ci}
247062306a36Sopenharmony_ci
247162306a36Sopenharmony_ci/**************************************************
247262306a36Sopenharmony_ci * Workarounds
247362306a36Sopenharmony_ci **************************************************/
247462306a36Sopenharmony_ci
247562306a36Sopenharmony_cistatic void b43_nphy_gain_ctl_workarounds_rev19(struct b43_wldev *dev)
247662306a36Sopenharmony_ci{
247762306a36Sopenharmony_ci	/* TODO */
247862306a36Sopenharmony_ci}
247962306a36Sopenharmony_ci
248062306a36Sopenharmony_cistatic void b43_nphy_gain_ctl_workarounds_rev7(struct b43_wldev *dev)
248162306a36Sopenharmony_ci{
248262306a36Sopenharmony_ci	/* TODO - should depend on phy->rev */
248362306a36Sopenharmony_ci}
248462306a36Sopenharmony_ci
248562306a36Sopenharmony_cistatic void b43_nphy_gain_ctl_workarounds_rev3(struct b43_wldev *dev)
248662306a36Sopenharmony_ci{
248762306a36Sopenharmony_ci	struct ssb_sprom *sprom = dev->dev->bus_sprom;
248862306a36Sopenharmony_ci
248962306a36Sopenharmony_ci	bool ghz5;
249062306a36Sopenharmony_ci	bool ext_lna;
249162306a36Sopenharmony_ci	u16 rssi_gain;
249262306a36Sopenharmony_ci	struct nphy_gain_ctl_workaround_entry *e;
249362306a36Sopenharmony_ci	u8 lpf_gain[6] = { 0x00, 0x06, 0x0C, 0x12, 0x12, 0x12 };
249462306a36Sopenharmony_ci	u8 lpf_bits[6] = { 0, 1, 2, 3, 3, 3 };
249562306a36Sopenharmony_ci
249662306a36Sopenharmony_ci	/* Prepare values */
249762306a36Sopenharmony_ci	ghz5 = b43_phy_read(dev, B43_NPHY_BANDCTL)
249862306a36Sopenharmony_ci		& B43_NPHY_BANDCTL_5GHZ;
249962306a36Sopenharmony_ci	ext_lna = ghz5 ? sprom->boardflags_hi & B43_BFH_EXTLNA_5GHZ :
250062306a36Sopenharmony_ci		sprom->boardflags_lo & B43_BFL_EXTLNA;
250162306a36Sopenharmony_ci	e = b43_nphy_get_gain_ctl_workaround_ent(dev, ghz5, ext_lna);
250262306a36Sopenharmony_ci	if (ghz5 && dev->phy.rev >= 5)
250362306a36Sopenharmony_ci		rssi_gain = 0x90;
250462306a36Sopenharmony_ci	else
250562306a36Sopenharmony_ci		rssi_gain = 0x50;
250662306a36Sopenharmony_ci
250762306a36Sopenharmony_ci	b43_phy_set(dev, B43_NPHY_RXCTL, 0x0040);
250862306a36Sopenharmony_ci
250962306a36Sopenharmony_ci	/* Set Clip 2 detect */
251062306a36Sopenharmony_ci	b43_phy_set(dev, B43_NPHY_C1_CGAINI, B43_NPHY_C1_CGAINI_CL2DETECT);
251162306a36Sopenharmony_ci	b43_phy_set(dev, B43_NPHY_C2_CGAINI, B43_NPHY_C2_CGAINI_CL2DETECT);
251262306a36Sopenharmony_ci
251362306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAG1_IDAC,
251462306a36Sopenharmony_ci			0x17);
251562306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX1 | B2056_RX_BIASPOLE_LNAG1_IDAC,
251662306a36Sopenharmony_ci			0x17);
251762306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG2_IDAC, 0xF0);
251862306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG2_IDAC, 0xF0);
251962306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX0 | B2056_RX_RSSI_POLE, 0x00);
252062306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX1 | B2056_RX_RSSI_POLE, 0x00);
252162306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX0 | B2056_RX_RSSI_GAIN,
252262306a36Sopenharmony_ci			rssi_gain);
252362306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX1 | B2056_RX_RSSI_GAIN,
252462306a36Sopenharmony_ci			rssi_gain);
252562306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAA1_IDAC,
252662306a36Sopenharmony_ci			0x17);
252762306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX1 | B2056_RX_BIASPOLE_LNAA1_IDAC,
252862306a36Sopenharmony_ci			0x17);
252962306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA2_IDAC, 0xFF);
253062306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA2_IDAC, 0xFF);
253162306a36Sopenharmony_ci
253262306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB8(0, 8), 4, e->lna1_gain);
253362306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB8(1, 8), 4, e->lna1_gain);
253462306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB8(0, 16), 4, e->lna2_gain);
253562306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB8(1, 16), 4, e->lna2_gain);
253662306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB8(0, 32), 10, e->gain_db);
253762306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB8(1, 32), 10, e->gain_db);
253862306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB8(2, 32), 10, e->gain_bits);
253962306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB8(3, 32), 10, e->gain_bits);
254062306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB8(0, 0x40), 6, lpf_gain);
254162306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB8(1, 0x40), 6, lpf_gain);
254262306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB8(2, 0x40), 6, lpf_bits);
254362306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB8(3, 0x40), 6, lpf_bits);
254462306a36Sopenharmony_ci
254562306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_REV3_C1_INITGAIN_A, e->init_gain);
254662306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_REV3_C2_INITGAIN_A, e->init_gain);
254762306a36Sopenharmony_ci
254862306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x106), 2,
254962306a36Sopenharmony_ci				e->rfseq_init);
255062306a36Sopenharmony_ci
255162306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_HIGAIN_A, e->cliphi_gain);
255262306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_HIGAIN_A, e->cliphi_gain);
255362306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_MEDGAIN_A, e->clipmd_gain);
255462306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_MEDGAIN_A, e->clipmd_gain);
255562306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_LOGAIN_A, e->cliplo_gain);
255662306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_LOGAIN_A, e->cliplo_gain);
255762306a36Sopenharmony_ci
255862306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_CRSMINPOWER0, 0xFF00, e->crsmin);
255962306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_CRSMINPOWERL0, 0xFF00, e->crsminl);
256062306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_CRSMINPOWERU0, 0xFF00, e->crsminu);
256162306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, e->nbclip);
256262306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, e->nbclip);
256362306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
256462306a36Sopenharmony_ci			~B43_NPHY_C1_CLIPWBTHRES_CLIP2, e->wlclip);
256562306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
256662306a36Sopenharmony_ci			~B43_NPHY_C2_CLIPWBTHRES_CLIP2, e->wlclip);
256762306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);
256862306a36Sopenharmony_ci}
256962306a36Sopenharmony_ci
257062306a36Sopenharmony_cistatic void b43_nphy_gain_ctl_workarounds_rev1_2(struct b43_wldev *dev)
257162306a36Sopenharmony_ci{
257262306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
257362306a36Sopenharmony_ci
257462306a36Sopenharmony_ci	u8 i, j;
257562306a36Sopenharmony_ci	u8 code;
257662306a36Sopenharmony_ci	u16 tmp;
257762306a36Sopenharmony_ci	u8 rfseq_events[3] = { 6, 8, 7 };
257862306a36Sopenharmony_ci	u8 rfseq_delays[3] = { 10, 30, 1 };
257962306a36Sopenharmony_ci
258062306a36Sopenharmony_ci	/* Set Clip 2 detect */
258162306a36Sopenharmony_ci	b43_phy_set(dev, B43_NPHY_C1_CGAINI, B43_NPHY_C1_CGAINI_CL2DETECT);
258262306a36Sopenharmony_ci	b43_phy_set(dev, B43_NPHY_C2_CGAINI, B43_NPHY_C2_CGAINI_CL2DETECT);
258362306a36Sopenharmony_ci
258462306a36Sopenharmony_ci	/* Set narrowband clip threshold */
258562306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 0x84);
258662306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 0x84);
258762306a36Sopenharmony_ci
258862306a36Sopenharmony_ci	if (!b43_is_40mhz(dev)) {
258962306a36Sopenharmony_ci		/* Set dwell lengths */
259062306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 0x002B);
259162306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 0x002B);
259262306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 0x0009);
259362306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 0x0009);
259462306a36Sopenharmony_ci	}
259562306a36Sopenharmony_ci
259662306a36Sopenharmony_ci	/* Set wideband clip 2 threshold */
259762306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
259862306a36Sopenharmony_ci			~B43_NPHY_C1_CLIPWBTHRES_CLIP2, 21);
259962306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
260062306a36Sopenharmony_ci			~B43_NPHY_C2_CLIPWBTHRES_CLIP2, 21);
260162306a36Sopenharmony_ci
260262306a36Sopenharmony_ci	if (!b43_is_40mhz(dev)) {
260362306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_C1_CGAINI,
260462306a36Sopenharmony_ci			~B43_NPHY_C1_CGAINI_GAINBKOFF, 0x1);
260562306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_C2_CGAINI,
260662306a36Sopenharmony_ci			~B43_NPHY_C2_CGAINI_GAINBKOFF, 0x1);
260762306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_C1_CCK_CGAINI,
260862306a36Sopenharmony_ci			~B43_NPHY_C1_CCK_CGAINI_GAINBKOFF, 0x1);
260962306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_C2_CCK_CGAINI,
261062306a36Sopenharmony_ci			~B43_NPHY_C2_CCK_CGAINI_GAINBKOFF, 0x1);
261162306a36Sopenharmony_ci	}
261262306a36Sopenharmony_ci
261362306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);
261462306a36Sopenharmony_ci
261562306a36Sopenharmony_ci	if (nphy->gain_boost) {
261662306a36Sopenharmony_ci		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ &&
261762306a36Sopenharmony_ci		    b43_is_40mhz(dev))
261862306a36Sopenharmony_ci			code = 4;
261962306a36Sopenharmony_ci		else
262062306a36Sopenharmony_ci			code = 5;
262162306a36Sopenharmony_ci	} else {
262262306a36Sopenharmony_ci		code = b43_is_40mhz(dev) ? 6 : 7;
262362306a36Sopenharmony_ci	}
262462306a36Sopenharmony_ci
262562306a36Sopenharmony_ci	/* Set HPVGA2 index */
262662306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN, ~B43_NPHY_C1_INITGAIN_HPVGA2,
262762306a36Sopenharmony_ci			code << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT);
262862306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN, ~B43_NPHY_C2_INITGAIN_HPVGA2,
262962306a36Sopenharmony_ci			code << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT);
263062306a36Sopenharmony_ci
263162306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
263262306a36Sopenharmony_ci	/* specs say about 2 loops, but wl does 4 */
263362306a36Sopenharmony_ci	for (i = 0; i < 4; i++)
263462306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, (code << 8 | 0x7C));
263562306a36Sopenharmony_ci
263662306a36Sopenharmony_ci	b43_nphy_adjust_lna_gain_table(dev);
263762306a36Sopenharmony_ci
263862306a36Sopenharmony_ci	if (nphy->elna_gain_config) {
263962306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0808);
264062306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0);
264162306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
264262306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
264362306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
264462306a36Sopenharmony_ci
264562306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0C08);
264662306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0);
264762306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
264862306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
264962306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
265062306a36Sopenharmony_ci
265162306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
265262306a36Sopenharmony_ci		/* specs say about 2 loops, but wl does 4 */
265362306a36Sopenharmony_ci		for (i = 0; i < 4; i++)
265462306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
265562306a36Sopenharmony_ci						(code << 8 | 0x74));
265662306a36Sopenharmony_ci	}
265762306a36Sopenharmony_ci
265862306a36Sopenharmony_ci	if (dev->phy.rev == 2) {
265962306a36Sopenharmony_ci		for (i = 0; i < 4; i++) {
266062306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
266162306a36Sopenharmony_ci					(0x0400 * i) + 0x0020);
266262306a36Sopenharmony_ci			for (j = 0; j < 21; j++) {
266362306a36Sopenharmony_ci				tmp = j * (i < 2 ? 3 : 1);
266462306a36Sopenharmony_ci				b43_phy_write(dev,
266562306a36Sopenharmony_ci					B43_NPHY_TABLE_DATALO, tmp);
266662306a36Sopenharmony_ci			}
266762306a36Sopenharmony_ci		}
266862306a36Sopenharmony_ci	}
266962306a36Sopenharmony_ci
267062306a36Sopenharmony_ci	b43_nphy_set_rf_sequence(dev, 5, rfseq_events, rfseq_delays, 3);
267162306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_OVER_DGAIN1,
267262306a36Sopenharmony_ci		~B43_NPHY_OVER_DGAIN_CCKDGECV & 0xFFFF,
267362306a36Sopenharmony_ci		0x5A << B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT);
267462306a36Sopenharmony_ci
267562306a36Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
267662306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_PHY_N(0xC5D), 0xFF80, 4);
267762306a36Sopenharmony_ci}
267862306a36Sopenharmony_ci
267962306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */
268062306a36Sopenharmony_cistatic void b43_nphy_gain_ctl_workarounds(struct b43_wldev *dev)
268162306a36Sopenharmony_ci{
268262306a36Sopenharmony_ci	if (dev->phy.rev >= 19)
268362306a36Sopenharmony_ci		b43_nphy_gain_ctl_workarounds_rev19(dev);
268462306a36Sopenharmony_ci	else if (dev->phy.rev >= 7)
268562306a36Sopenharmony_ci		b43_nphy_gain_ctl_workarounds_rev7(dev);
268662306a36Sopenharmony_ci	else if (dev->phy.rev >= 3)
268762306a36Sopenharmony_ci		b43_nphy_gain_ctl_workarounds_rev3(dev);
268862306a36Sopenharmony_ci	else
268962306a36Sopenharmony_ci		b43_nphy_gain_ctl_workarounds_rev1_2(dev);
269062306a36Sopenharmony_ci}
269162306a36Sopenharmony_ci
269262306a36Sopenharmony_cistatic void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
269362306a36Sopenharmony_ci{
269462306a36Sopenharmony_ci	struct ssb_sprom *sprom = dev->dev->bus_sprom;
269562306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
269662306a36Sopenharmony_ci
269762306a36Sopenharmony_ci	/* TX to RX */
269862306a36Sopenharmony_ci	u8 tx2rx_events[7] = { 4, 3, 5, 2, 1, 8, 31, };
269962306a36Sopenharmony_ci	u8 tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1, };
270062306a36Sopenharmony_ci	/* RX to TX */
270162306a36Sopenharmony_ci	u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
270262306a36Sopenharmony_ci					0x1F };
270362306a36Sopenharmony_ci	u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
270462306a36Sopenharmony_ci
270562306a36Sopenharmony_ci	static const u16 ntab7_15e_16e[] = { 0, 0x10f, 0x10f };
270662306a36Sopenharmony_ci	u8 ntab7_138_146[] = { 0x11, 0x11 };
270762306a36Sopenharmony_ci	u8 ntab7_133[] = { 0x77, 0x11, 0x11 };
270862306a36Sopenharmony_ci
270962306a36Sopenharmony_ci	u16 lpf_ofdm_20mhz[2], lpf_ofdm_40mhz[2], lpf_11b[2];
271062306a36Sopenharmony_ci	u16 bcap_val;
271162306a36Sopenharmony_ci	s16 bcap_val_11b[2], bcap_val_11n_20[2], bcap_val_11n_40[2];
271262306a36Sopenharmony_ci	u16 scap_val;
271362306a36Sopenharmony_ci	s16 scap_val_11b[2], scap_val_11n_20[2], scap_val_11n_40[2];
271462306a36Sopenharmony_ci	bool rccal_ovrd = false;
271562306a36Sopenharmony_ci
271662306a36Sopenharmony_ci	u16 bias, conv, filt;
271762306a36Sopenharmony_ci
271862306a36Sopenharmony_ci	u32 noise_tbl[2];
271962306a36Sopenharmony_ci
272062306a36Sopenharmony_ci	u32 tmp32;
272162306a36Sopenharmony_ci	u8 core;
272262306a36Sopenharmony_ci
272362306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);
272462306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01b3);
272562306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);
272662306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016e);
272762306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00cd);
272862306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
272962306a36Sopenharmony_ci
273062306a36Sopenharmony_ci	if (phy->rev == 7) {
273162306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_FINERX2_CGC, 0x10);
273262306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0xFF80, 0x0020);
273362306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0x80FF, 0x2700);
273462306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_FREQGAIN1, 0xFF80, 0x002E);
273562306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_FREQGAIN1, 0x80FF, 0x3300);
273662306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_FREQGAIN2, 0xFF80, 0x0037);
273762306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_FREQGAIN2, 0x80FF, 0x3A00);
273862306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_FREQGAIN3, 0xFF80, 0x003C);
273962306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_FREQGAIN3, 0x80FF, 0x3E00);
274062306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_FREQGAIN4, 0xFF80, 0x003E);
274162306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_FREQGAIN4, 0x80FF, 0x3F00);
274262306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_FREQGAIN5, 0xFF80, 0x0040);
274362306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_FREQGAIN5, 0x80FF, 0x4000);
274462306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_FREQGAIN6, 0xFF80, 0x0040);
274562306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_FREQGAIN6, 0x80FF, 0x4000);
274662306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0xFF80, 0x0040);
274762306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0x80FF, 0x4000);
274862306a36Sopenharmony_ci	}
274962306a36Sopenharmony_ci
275062306a36Sopenharmony_ci	if (phy->rev >= 16) {
275162306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x7ff);
275262306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x7ff);
275362306a36Sopenharmony_ci	} else if (phy->rev <= 8) {
275462306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1B0);
275562306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1B0);
275662306a36Sopenharmony_ci	}
275762306a36Sopenharmony_ci
275862306a36Sopenharmony_ci	if (phy->rev >= 16)
275962306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0xa0);
276062306a36Sopenharmony_ci	else if (phy->rev >= 8)
276162306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0x72);
276262306a36Sopenharmony_ci
276362306a36Sopenharmony_ci	b43_ntab_write(dev, B43_NTAB16(8, 0x00), 2);
276462306a36Sopenharmony_ci	b43_ntab_write(dev, B43_NTAB16(8, 0x10), 2);
276562306a36Sopenharmony_ci	tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
276662306a36Sopenharmony_ci	tmp32 &= 0xffffff;
276762306a36Sopenharmony_ci	b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
276862306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x15d), 3, ntab7_15e_16e);
276962306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16d), 3, ntab7_15e_16e);
277062306a36Sopenharmony_ci
277162306a36Sopenharmony_ci	b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays,
277262306a36Sopenharmony_ci				 ARRAY_SIZE(tx2rx_events));
277362306a36Sopenharmony_ci	if (b43_nphy_ipa(dev))
277462306a36Sopenharmony_ci		b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa,
277562306a36Sopenharmony_ci				rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa));
277662306a36Sopenharmony_ci
277762306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_0, 0x3FFF, 0x4000);
277862306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_1, 0x3FFF, 0x4000);
277962306a36Sopenharmony_ci
278062306a36Sopenharmony_ci	for (core = 0; core < 2; core++) {
278162306a36Sopenharmony_ci		lpf_ofdm_20mhz[core] = b43_nphy_read_lpf_ctl(dev, 0x154 + core * 0x10);
278262306a36Sopenharmony_ci		lpf_ofdm_40mhz[core] = b43_nphy_read_lpf_ctl(dev, 0x159 + core * 0x10);
278362306a36Sopenharmony_ci		lpf_11b[core] = b43_nphy_read_lpf_ctl(dev, 0x152 + core * 0x10);
278462306a36Sopenharmony_ci	}
278562306a36Sopenharmony_ci
278662306a36Sopenharmony_ci	bcap_val = b43_radio_read(dev, R2057_RCCAL_BCAP_VAL);
278762306a36Sopenharmony_ci	scap_val = b43_radio_read(dev, R2057_RCCAL_SCAP_VAL);
278862306a36Sopenharmony_ci
278962306a36Sopenharmony_ci	if (b43_nphy_ipa(dev)) {
279062306a36Sopenharmony_ci		bool ghz2 = b43_current_band(dev->wl) == NL80211_BAND_2GHZ;
279162306a36Sopenharmony_ci
279262306a36Sopenharmony_ci		switch (phy->radio_rev) {
279362306a36Sopenharmony_ci		case 5:
279462306a36Sopenharmony_ci			/* Check radio version (to be 0) by PHY rev for now */
279562306a36Sopenharmony_ci			if (phy->rev == 8 && b43_is_40mhz(dev)) {
279662306a36Sopenharmony_ci				for (core = 0; core < 2; core++) {
279762306a36Sopenharmony_ci					scap_val_11b[core] = scap_val;
279862306a36Sopenharmony_ci					bcap_val_11b[core] = bcap_val;
279962306a36Sopenharmony_ci					scap_val_11n_20[core] = scap_val;
280062306a36Sopenharmony_ci					bcap_val_11n_20[core] = bcap_val;
280162306a36Sopenharmony_ci					scap_val_11n_40[core] = 0xc;
280262306a36Sopenharmony_ci					bcap_val_11n_40[core] = 0xc;
280362306a36Sopenharmony_ci				}
280462306a36Sopenharmony_ci
280562306a36Sopenharmony_ci				rccal_ovrd = true;
280662306a36Sopenharmony_ci			}
280762306a36Sopenharmony_ci			if (phy->rev == 9) {
280862306a36Sopenharmony_ci				/* TODO: Radio version 1 (e.g. BCM5357B0) */
280962306a36Sopenharmony_ci			}
281062306a36Sopenharmony_ci			break;
281162306a36Sopenharmony_ci		case 7:
281262306a36Sopenharmony_ci		case 8:
281362306a36Sopenharmony_ci			for (core = 0; core < 2; core++) {
281462306a36Sopenharmony_ci				scap_val_11b[core] = scap_val;
281562306a36Sopenharmony_ci				bcap_val_11b[core] = bcap_val;
281662306a36Sopenharmony_ci				lpf_ofdm_20mhz[core] = 4;
281762306a36Sopenharmony_ci				lpf_11b[core] = 1;
281862306a36Sopenharmony_ci				if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
281962306a36Sopenharmony_ci					scap_val_11n_20[core] = 0xc;
282062306a36Sopenharmony_ci					bcap_val_11n_20[core] = 0xc;
282162306a36Sopenharmony_ci					scap_val_11n_40[core] = 0xa;
282262306a36Sopenharmony_ci					bcap_val_11n_40[core] = 0xa;
282362306a36Sopenharmony_ci				} else {
282462306a36Sopenharmony_ci					scap_val_11n_20[core] = 0x14;
282562306a36Sopenharmony_ci					bcap_val_11n_20[core] = 0x14;
282662306a36Sopenharmony_ci					scap_val_11n_40[core] = 0xf;
282762306a36Sopenharmony_ci					bcap_val_11n_40[core] = 0xf;
282862306a36Sopenharmony_ci				}
282962306a36Sopenharmony_ci			}
283062306a36Sopenharmony_ci
283162306a36Sopenharmony_ci			rccal_ovrd = true;
283262306a36Sopenharmony_ci			break;
283362306a36Sopenharmony_ci		case 9:
283462306a36Sopenharmony_ci			for (core = 0; core < 2; core++) {
283562306a36Sopenharmony_ci				bcap_val_11b[core] = bcap_val;
283662306a36Sopenharmony_ci				scap_val_11b[core] = scap_val;
283762306a36Sopenharmony_ci				lpf_11b[core] = 1;
283862306a36Sopenharmony_ci
283962306a36Sopenharmony_ci				if (ghz2) {
284062306a36Sopenharmony_ci					bcap_val_11n_20[core] = bcap_val + 13;
284162306a36Sopenharmony_ci					scap_val_11n_20[core] = scap_val + 15;
284262306a36Sopenharmony_ci				} else {
284362306a36Sopenharmony_ci					bcap_val_11n_20[core] = bcap_val + 14;
284462306a36Sopenharmony_ci					scap_val_11n_20[core] = scap_val + 15;
284562306a36Sopenharmony_ci				}
284662306a36Sopenharmony_ci				lpf_ofdm_20mhz[core] = 4;
284762306a36Sopenharmony_ci
284862306a36Sopenharmony_ci				if (ghz2) {
284962306a36Sopenharmony_ci					bcap_val_11n_40[core] = bcap_val - 7;
285062306a36Sopenharmony_ci					scap_val_11n_40[core] = scap_val - 5;
285162306a36Sopenharmony_ci				} else {
285262306a36Sopenharmony_ci					bcap_val_11n_40[core] = bcap_val + 2;
285362306a36Sopenharmony_ci					scap_val_11n_40[core] = scap_val + 4;
285462306a36Sopenharmony_ci				}
285562306a36Sopenharmony_ci				lpf_ofdm_40mhz[core] = 4;
285662306a36Sopenharmony_ci			}
285762306a36Sopenharmony_ci
285862306a36Sopenharmony_ci			rccal_ovrd = true;
285962306a36Sopenharmony_ci			break;
286062306a36Sopenharmony_ci		case 14:
286162306a36Sopenharmony_ci			for (core = 0; core < 2; core++) {
286262306a36Sopenharmony_ci				bcap_val_11b[core] = bcap_val;
286362306a36Sopenharmony_ci				scap_val_11b[core] = scap_val;
286462306a36Sopenharmony_ci				lpf_11b[core] = 1;
286562306a36Sopenharmony_ci			}
286662306a36Sopenharmony_ci
286762306a36Sopenharmony_ci			bcap_val_11n_20[0] = bcap_val + 20;
286862306a36Sopenharmony_ci			scap_val_11n_20[0] = scap_val + 20;
286962306a36Sopenharmony_ci			lpf_ofdm_20mhz[0] = 3;
287062306a36Sopenharmony_ci
287162306a36Sopenharmony_ci			bcap_val_11n_20[1] = bcap_val + 16;
287262306a36Sopenharmony_ci			scap_val_11n_20[1] = scap_val + 16;
287362306a36Sopenharmony_ci			lpf_ofdm_20mhz[1] = 3;
287462306a36Sopenharmony_ci
287562306a36Sopenharmony_ci			bcap_val_11n_40[0] = bcap_val + 20;
287662306a36Sopenharmony_ci			scap_val_11n_40[0] = scap_val + 20;
287762306a36Sopenharmony_ci			lpf_ofdm_40mhz[0] = 4;
287862306a36Sopenharmony_ci
287962306a36Sopenharmony_ci			bcap_val_11n_40[1] = bcap_val + 10;
288062306a36Sopenharmony_ci			scap_val_11n_40[1] = scap_val + 10;
288162306a36Sopenharmony_ci			lpf_ofdm_40mhz[1] = 4;
288262306a36Sopenharmony_ci
288362306a36Sopenharmony_ci			rccal_ovrd = true;
288462306a36Sopenharmony_ci			break;
288562306a36Sopenharmony_ci		}
288662306a36Sopenharmony_ci	} else {
288762306a36Sopenharmony_ci		if (phy->radio_rev == 5) {
288862306a36Sopenharmony_ci			for (core = 0; core < 2; core++) {
288962306a36Sopenharmony_ci				lpf_ofdm_20mhz[core] = 1;
289062306a36Sopenharmony_ci				lpf_ofdm_40mhz[core] = 3;
289162306a36Sopenharmony_ci				scap_val_11b[core] = scap_val;
289262306a36Sopenharmony_ci				bcap_val_11b[core] = bcap_val;
289362306a36Sopenharmony_ci				scap_val_11n_20[core] = 0x11;
289462306a36Sopenharmony_ci				scap_val_11n_40[core] = 0x11;
289562306a36Sopenharmony_ci				bcap_val_11n_20[core] = 0x13;
289662306a36Sopenharmony_ci				bcap_val_11n_40[core] = 0x13;
289762306a36Sopenharmony_ci			}
289862306a36Sopenharmony_ci
289962306a36Sopenharmony_ci			rccal_ovrd = true;
290062306a36Sopenharmony_ci		}
290162306a36Sopenharmony_ci	}
290262306a36Sopenharmony_ci	if (rccal_ovrd) {
290362306a36Sopenharmony_ci		u16 rx2tx_lut_20_11b[2], rx2tx_lut_20_11n[2], rx2tx_lut_40_11n[2];
290462306a36Sopenharmony_ci		u8 rx2tx_lut_extra = 1;
290562306a36Sopenharmony_ci
290662306a36Sopenharmony_ci		for (core = 0; core < 2; core++) {
290762306a36Sopenharmony_ci			bcap_val_11b[core] = clamp_val(bcap_val_11b[core], 0, 0x1f);
290862306a36Sopenharmony_ci			scap_val_11b[core] = clamp_val(scap_val_11b[core], 0, 0x1f);
290962306a36Sopenharmony_ci			bcap_val_11n_20[core] = clamp_val(bcap_val_11n_20[core], 0, 0x1f);
291062306a36Sopenharmony_ci			scap_val_11n_20[core] = clamp_val(scap_val_11n_20[core], 0, 0x1f);
291162306a36Sopenharmony_ci			bcap_val_11n_40[core] = clamp_val(bcap_val_11n_40[core], 0, 0x1f);
291262306a36Sopenharmony_ci			scap_val_11n_40[core] = clamp_val(scap_val_11n_40[core], 0, 0x1f);
291362306a36Sopenharmony_ci
291462306a36Sopenharmony_ci			rx2tx_lut_20_11b[core] = (rx2tx_lut_extra << 13) |
291562306a36Sopenharmony_ci						 (bcap_val_11b[core] << 8) |
291662306a36Sopenharmony_ci						 (scap_val_11b[core] << 3) |
291762306a36Sopenharmony_ci						 lpf_11b[core];
291862306a36Sopenharmony_ci			rx2tx_lut_20_11n[core] = (rx2tx_lut_extra << 13) |
291962306a36Sopenharmony_ci						 (bcap_val_11n_20[core] << 8) |
292062306a36Sopenharmony_ci						 (scap_val_11n_20[core] << 3) |
292162306a36Sopenharmony_ci						 lpf_ofdm_20mhz[core];
292262306a36Sopenharmony_ci			rx2tx_lut_40_11n[core] = (rx2tx_lut_extra << 13) |
292362306a36Sopenharmony_ci						 (bcap_val_11n_40[core] << 8) |
292462306a36Sopenharmony_ci						 (scap_val_11n_40[core] << 3) |
292562306a36Sopenharmony_ci						 lpf_ofdm_40mhz[core];
292662306a36Sopenharmony_ci		}
292762306a36Sopenharmony_ci
292862306a36Sopenharmony_ci		for (core = 0; core < 2; core++) {
292962306a36Sopenharmony_ci			b43_ntab_write(dev, B43_NTAB16(7, 0x152 + core * 16),
293062306a36Sopenharmony_ci				       rx2tx_lut_20_11b[core]);
293162306a36Sopenharmony_ci			b43_ntab_write(dev, B43_NTAB16(7, 0x153 + core * 16),
293262306a36Sopenharmony_ci				       rx2tx_lut_20_11n[core]);
293362306a36Sopenharmony_ci			b43_ntab_write(dev, B43_NTAB16(7, 0x154 + core * 16),
293462306a36Sopenharmony_ci				       rx2tx_lut_20_11n[core]);
293562306a36Sopenharmony_ci			b43_ntab_write(dev, B43_NTAB16(7, 0x155 + core * 16),
293662306a36Sopenharmony_ci				       rx2tx_lut_40_11n[core]);
293762306a36Sopenharmony_ci			b43_ntab_write(dev, B43_NTAB16(7, 0x156 + core * 16),
293862306a36Sopenharmony_ci				       rx2tx_lut_40_11n[core]);
293962306a36Sopenharmony_ci			b43_ntab_write(dev, B43_NTAB16(7, 0x157 + core * 16),
294062306a36Sopenharmony_ci				       rx2tx_lut_40_11n[core]);
294162306a36Sopenharmony_ci			b43_ntab_write(dev, B43_NTAB16(7, 0x158 + core * 16),
294262306a36Sopenharmony_ci				       rx2tx_lut_40_11n[core]);
294362306a36Sopenharmony_ci			b43_ntab_write(dev, B43_NTAB16(7, 0x159 + core * 16),
294462306a36Sopenharmony_ci				       rx2tx_lut_40_11n[core]);
294562306a36Sopenharmony_ci		}
294662306a36Sopenharmony_ci	}
294762306a36Sopenharmony_ci
294862306a36Sopenharmony_ci	b43_phy_write(dev, 0x32F, 0x3);
294962306a36Sopenharmony_ci
295062306a36Sopenharmony_ci	if (phy->radio_rev == 4 || phy->radio_rev == 6)
295162306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_rev7(dev, 4, 1, 3, false, 0);
295262306a36Sopenharmony_ci
295362306a36Sopenharmony_ci	if (phy->radio_rev == 3 || phy->radio_rev == 4 || phy->radio_rev == 6) {
295462306a36Sopenharmony_ci		if (sprom->revision &&
295562306a36Sopenharmony_ci		    sprom->boardflags2_hi & B43_BFH2_IPALVLSHIFT_3P3) {
295662306a36Sopenharmony_ci			b43_radio_write(dev, 0x5, 0x05);
295762306a36Sopenharmony_ci			b43_radio_write(dev, 0x6, 0x30);
295862306a36Sopenharmony_ci			b43_radio_write(dev, 0x7, 0x00);
295962306a36Sopenharmony_ci			b43_radio_set(dev, 0x4f, 0x1);
296062306a36Sopenharmony_ci			b43_radio_set(dev, 0xd4, 0x1);
296162306a36Sopenharmony_ci			bias = 0x1f;
296262306a36Sopenharmony_ci			conv = 0x6f;
296362306a36Sopenharmony_ci			filt = 0xaa;
296462306a36Sopenharmony_ci		} else {
296562306a36Sopenharmony_ci			bias = 0x2b;
296662306a36Sopenharmony_ci			conv = 0x7f;
296762306a36Sopenharmony_ci			filt = 0xee;
296862306a36Sopenharmony_ci		}
296962306a36Sopenharmony_ci		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
297062306a36Sopenharmony_ci			for (core = 0; core < 2; core++) {
297162306a36Sopenharmony_ci				if (core == 0) {
297262306a36Sopenharmony_ci					b43_radio_write(dev, 0x5F, bias);
297362306a36Sopenharmony_ci					b43_radio_write(dev, 0x64, conv);
297462306a36Sopenharmony_ci					b43_radio_write(dev, 0x66, filt);
297562306a36Sopenharmony_ci				} else {
297662306a36Sopenharmony_ci					b43_radio_write(dev, 0xE8, bias);
297762306a36Sopenharmony_ci					b43_radio_write(dev, 0xE9, conv);
297862306a36Sopenharmony_ci					b43_radio_write(dev, 0xEB, filt);
297962306a36Sopenharmony_ci				}
298062306a36Sopenharmony_ci			}
298162306a36Sopenharmony_ci		}
298262306a36Sopenharmony_ci	}
298362306a36Sopenharmony_ci
298462306a36Sopenharmony_ci	if (b43_nphy_ipa(dev)) {
298562306a36Sopenharmony_ci		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
298662306a36Sopenharmony_ci			if (phy->radio_rev == 3 || phy->radio_rev == 4 ||
298762306a36Sopenharmony_ci			    phy->radio_rev == 6) {
298862306a36Sopenharmony_ci				for (core = 0; core < 2; core++) {
298962306a36Sopenharmony_ci					if (core == 0)
299062306a36Sopenharmony_ci						b43_radio_write(dev, 0x51,
299162306a36Sopenharmony_ci								0x7f);
299262306a36Sopenharmony_ci					else
299362306a36Sopenharmony_ci						b43_radio_write(dev, 0xd6,
299462306a36Sopenharmony_ci								0x7f);
299562306a36Sopenharmony_ci				}
299662306a36Sopenharmony_ci			}
299762306a36Sopenharmony_ci			switch (phy->radio_rev) {
299862306a36Sopenharmony_ci			case 3:
299962306a36Sopenharmony_ci				for (core = 0; core < 2; core++) {
300062306a36Sopenharmony_ci					if (core == 0) {
300162306a36Sopenharmony_ci						b43_radio_write(dev, 0x64,
300262306a36Sopenharmony_ci								0x13);
300362306a36Sopenharmony_ci						b43_radio_write(dev, 0x5F,
300462306a36Sopenharmony_ci								0x1F);
300562306a36Sopenharmony_ci						b43_radio_write(dev, 0x66,
300662306a36Sopenharmony_ci								0xEE);
300762306a36Sopenharmony_ci						b43_radio_write(dev, 0x59,
300862306a36Sopenharmony_ci								0x8A);
300962306a36Sopenharmony_ci						b43_radio_write(dev, 0x80,
301062306a36Sopenharmony_ci								0x3E);
301162306a36Sopenharmony_ci					} else {
301262306a36Sopenharmony_ci						b43_radio_write(dev, 0x69,
301362306a36Sopenharmony_ci								0x13);
301462306a36Sopenharmony_ci						b43_radio_write(dev, 0xE8,
301562306a36Sopenharmony_ci								0x1F);
301662306a36Sopenharmony_ci						b43_radio_write(dev, 0xEB,
301762306a36Sopenharmony_ci								0xEE);
301862306a36Sopenharmony_ci						b43_radio_write(dev, 0xDE,
301962306a36Sopenharmony_ci								0x8A);
302062306a36Sopenharmony_ci						b43_radio_write(dev, 0x105,
302162306a36Sopenharmony_ci								0x3E);
302262306a36Sopenharmony_ci					}
302362306a36Sopenharmony_ci				}
302462306a36Sopenharmony_ci				break;
302562306a36Sopenharmony_ci			case 7:
302662306a36Sopenharmony_ci			case 8:
302762306a36Sopenharmony_ci				if (!b43_is_40mhz(dev)) {
302862306a36Sopenharmony_ci					b43_radio_write(dev, 0x5F, 0x14);
302962306a36Sopenharmony_ci					b43_radio_write(dev, 0xE8, 0x12);
303062306a36Sopenharmony_ci				} else {
303162306a36Sopenharmony_ci					b43_radio_write(dev, 0x5F, 0x16);
303262306a36Sopenharmony_ci					b43_radio_write(dev, 0xE8, 0x16);
303362306a36Sopenharmony_ci				}
303462306a36Sopenharmony_ci				break;
303562306a36Sopenharmony_ci			case 14:
303662306a36Sopenharmony_ci				for (core = 0; core < 2; core++) {
303762306a36Sopenharmony_ci					int o = core ? 0x85 : 0;
303862306a36Sopenharmony_ci
303962306a36Sopenharmony_ci					b43_radio_write(dev, o + R2057_IPA2G_CASCONV_CORE0, 0x13);
304062306a36Sopenharmony_ci					b43_radio_write(dev, o + R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, 0x21);
304162306a36Sopenharmony_ci					b43_radio_write(dev, o + R2057_IPA2G_BIAS_FILTER_CORE0, 0xff);
304262306a36Sopenharmony_ci					b43_radio_write(dev, o + R2057_PAD2G_IDACS_CORE0, 0x88);
304362306a36Sopenharmony_ci					b43_radio_write(dev, o + R2057_PAD2G_TUNE_PUS_CORE0, 0x23);
304462306a36Sopenharmony_ci					b43_radio_write(dev, o + R2057_IPA2G_IMAIN_CORE0, 0x16);
304562306a36Sopenharmony_ci					b43_radio_write(dev, o + R2057_PAD_BIAS_FILTER_BWS_CORE0, 0x3e);
304662306a36Sopenharmony_ci					b43_radio_write(dev, o + R2057_BACKUP1_CORE0, 0x10);
304762306a36Sopenharmony_ci				}
304862306a36Sopenharmony_ci				break;
304962306a36Sopenharmony_ci			}
305062306a36Sopenharmony_ci		} else {
305162306a36Sopenharmony_ci			u16 freq = phy->chandef->chan->center_freq;
305262306a36Sopenharmony_ci			if ((freq >= 5180 && freq <= 5230) ||
305362306a36Sopenharmony_ci			    (freq >= 5745 && freq <= 5805)) {
305462306a36Sopenharmony_ci				b43_radio_write(dev, 0x7D, 0xFF);
305562306a36Sopenharmony_ci				b43_radio_write(dev, 0xFE, 0xFF);
305662306a36Sopenharmony_ci			}
305762306a36Sopenharmony_ci		}
305862306a36Sopenharmony_ci	} else {
305962306a36Sopenharmony_ci		if (phy->radio_rev != 5) {
306062306a36Sopenharmony_ci			for (core = 0; core < 2; core++) {
306162306a36Sopenharmony_ci				if (core == 0) {
306262306a36Sopenharmony_ci					b43_radio_write(dev, 0x5c, 0x61);
306362306a36Sopenharmony_ci					b43_radio_write(dev, 0x51, 0x70);
306462306a36Sopenharmony_ci				} else {
306562306a36Sopenharmony_ci					b43_radio_write(dev, 0xe1, 0x61);
306662306a36Sopenharmony_ci					b43_radio_write(dev, 0xd6, 0x70);
306762306a36Sopenharmony_ci				}
306862306a36Sopenharmony_ci			}
306962306a36Sopenharmony_ci		}
307062306a36Sopenharmony_ci	}
307162306a36Sopenharmony_ci
307262306a36Sopenharmony_ci	if (phy->radio_rev == 4) {
307362306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0x20);
307462306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0x20);
307562306a36Sopenharmony_ci		for (core = 0; core < 2; core++) {
307662306a36Sopenharmony_ci			if (core == 0) {
307762306a36Sopenharmony_ci				b43_radio_write(dev, 0x1a1, 0x00);
307862306a36Sopenharmony_ci				b43_radio_write(dev, 0x1a2, 0x3f);
307962306a36Sopenharmony_ci				b43_radio_write(dev, 0x1a6, 0x3f);
308062306a36Sopenharmony_ci			} else {
308162306a36Sopenharmony_ci				b43_radio_write(dev, 0x1a7, 0x00);
308262306a36Sopenharmony_ci				b43_radio_write(dev, 0x1ab, 0x3f);
308362306a36Sopenharmony_ci				b43_radio_write(dev, 0x1ac, 0x3f);
308462306a36Sopenharmony_ci			}
308562306a36Sopenharmony_ci		}
308662306a36Sopenharmony_ci	} else {
308762306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_AFECTL_C1, 0x4);
308862306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x4);
308962306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_AFECTL_C2, 0x4);
309062306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4);
309162306a36Sopenharmony_ci
309262306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x1);
309362306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x1);
309462306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x1);
309562306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x1);
309662306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0);
309762306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0);
309862306a36Sopenharmony_ci
309962306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x4);
310062306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x4);
310162306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x4);
310262306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4);
310362306a36Sopenharmony_ci	}
310462306a36Sopenharmony_ci
310562306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, 0x2);
310662306a36Sopenharmony_ci
310762306a36Sopenharmony_ci	b43_ntab_write(dev, B43_NTAB32(16, 0x100), 20);
310862306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x138), 2, ntab7_138_146);
310962306a36Sopenharmony_ci	b43_ntab_write(dev, B43_NTAB16(7, 0x141), 0x77);
311062306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x133), 3, ntab7_133);
311162306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x146), 2, ntab7_138_146);
311262306a36Sopenharmony_ci	b43_ntab_write(dev, B43_NTAB16(7, 0x123), 0x77);
311362306a36Sopenharmony_ci	b43_ntab_write(dev, B43_NTAB16(7, 0x12A), 0x77);
311462306a36Sopenharmony_ci
311562306a36Sopenharmony_ci	b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x02), 1, noise_tbl);
311662306a36Sopenharmony_ci	noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D;
311762306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x02), 2, noise_tbl);
311862306a36Sopenharmony_ci
311962306a36Sopenharmony_ci	b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x7E), 1, noise_tbl);
312062306a36Sopenharmony_ci	noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D;
312162306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x7E), 2, noise_tbl);
312262306a36Sopenharmony_ci
312362306a36Sopenharmony_ci	b43_nphy_gain_ctl_workarounds(dev);
312462306a36Sopenharmony_ci
312562306a36Sopenharmony_ci	/* TODO
312662306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4,
312762306a36Sopenharmony_ci			    aux_adc_vmid_rev7_core0);
312862306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4,
312962306a36Sopenharmony_ci			    aux_adc_vmid_rev7_core1);
313062306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0C), 4,
313162306a36Sopenharmony_ci			    aux_adc_gain_rev7);
313262306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1C), 4,
313362306a36Sopenharmony_ci			    aux_adc_gain_rev7);
313462306a36Sopenharmony_ci	*/
313562306a36Sopenharmony_ci}
313662306a36Sopenharmony_ci
313762306a36Sopenharmony_cistatic void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
313862306a36Sopenharmony_ci{
313962306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
314062306a36Sopenharmony_ci	struct ssb_sprom *sprom = dev->dev->bus_sprom;
314162306a36Sopenharmony_ci
314262306a36Sopenharmony_ci	/* TX to RX */
314362306a36Sopenharmony_ci	u8 tx2rx_events[7] = { 0x4, 0x3, 0x5, 0x2, 0x1, 0x8, 0x1F };
314462306a36Sopenharmony_ci	u8 tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1 };
314562306a36Sopenharmony_ci	/* RX to TX */
314662306a36Sopenharmony_ci	u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
314762306a36Sopenharmony_ci					0x1F };
314862306a36Sopenharmony_ci	u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
314962306a36Sopenharmony_ci	u8 rx2tx_events[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0x3, 0x4, 0x1F };
315062306a36Sopenharmony_ci	u8 rx2tx_delays[9] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 };
315162306a36Sopenharmony_ci
315262306a36Sopenharmony_ci	u16 vmids[5][4] = {
315362306a36Sopenharmony_ci		{ 0xa2, 0xb4, 0xb4, 0x89, }, /* 0 */
315462306a36Sopenharmony_ci		{ 0xb4, 0xb4, 0xb4, 0x24, }, /* 1 */
315562306a36Sopenharmony_ci		{ 0xa2, 0xb4, 0xb4, 0x74, }, /* 2 */
315662306a36Sopenharmony_ci		{ 0xa2, 0xb4, 0xb4, 0x270, }, /* 3 */
315762306a36Sopenharmony_ci		{ 0xa2, 0xb4, 0xb4, 0x00, }, /* 4 and 5 */
315862306a36Sopenharmony_ci	};
315962306a36Sopenharmony_ci	u16 gains[5][4] = {
316062306a36Sopenharmony_ci		{ 0x02, 0x02, 0x02, 0x00, }, /* 0 */
316162306a36Sopenharmony_ci		{ 0x02, 0x02, 0x02, 0x02, }, /* 1 */
316262306a36Sopenharmony_ci		{ 0x02, 0x02, 0x02, 0x04, }, /* 2 */
316362306a36Sopenharmony_ci		{ 0x02, 0x02, 0x02, 0x00, }, /* 3 */
316462306a36Sopenharmony_ci		{ 0x02, 0x02, 0x02, 0x00, }, /* 4 and 5 */
316562306a36Sopenharmony_ci	};
316662306a36Sopenharmony_ci	u16 *vmid, *gain;
316762306a36Sopenharmony_ci
316862306a36Sopenharmony_ci	u8 pdet_range;
316962306a36Sopenharmony_ci	u16 tmp16;
317062306a36Sopenharmony_ci	u32 tmp32;
317162306a36Sopenharmony_ci
317262306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1f8);
317362306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1f8);
317462306a36Sopenharmony_ci
317562306a36Sopenharmony_ci	tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
317662306a36Sopenharmony_ci	tmp32 &= 0xffffff;
317762306a36Sopenharmony_ci	b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
317862306a36Sopenharmony_ci
317962306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);
318062306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01B3);
318162306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);
318262306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016E);
318362306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00CD);
318462306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
318562306a36Sopenharmony_ci
318662306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_LOGAIN_B, 0x000C);
318762306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_LOGAIN_B, 0x000C);
318862306a36Sopenharmony_ci
318962306a36Sopenharmony_ci	/* TX to RX */
319062306a36Sopenharmony_ci	b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays,
319162306a36Sopenharmony_ci				 ARRAY_SIZE(tx2rx_events));
319262306a36Sopenharmony_ci
319362306a36Sopenharmony_ci	/* RX to TX */
319462306a36Sopenharmony_ci	if (b43_nphy_ipa(dev))
319562306a36Sopenharmony_ci		b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa,
319662306a36Sopenharmony_ci				rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa));
319762306a36Sopenharmony_ci	if (nphy->hw_phyrxchain != 3 &&
319862306a36Sopenharmony_ci	    nphy->hw_phyrxchain != nphy->hw_phytxchain) {
319962306a36Sopenharmony_ci		if (b43_nphy_ipa(dev)) {
320062306a36Sopenharmony_ci			rx2tx_delays[5] = 59;
320162306a36Sopenharmony_ci			rx2tx_delays[6] = 1;
320262306a36Sopenharmony_ci			rx2tx_events[7] = 0x1F;
320362306a36Sopenharmony_ci		}
320462306a36Sopenharmony_ci		b43_nphy_set_rf_sequence(dev, 0, rx2tx_events, rx2tx_delays,
320562306a36Sopenharmony_ci					 ARRAY_SIZE(rx2tx_events));
320662306a36Sopenharmony_ci	}
320762306a36Sopenharmony_ci
320862306a36Sopenharmony_ci	tmp16 = (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) ?
320962306a36Sopenharmony_ci		0x2 : 0x9C40;
321062306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16);
321162306a36Sopenharmony_ci
321262306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_SGILTRNOFFSET, 0xF0FF, 0x0700);
321362306a36Sopenharmony_ci
321462306a36Sopenharmony_ci	if (!b43_is_40mhz(dev)) {
321562306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
321662306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);
321762306a36Sopenharmony_ci	} else {
321862306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB32(16, 3), 0x14D);
321962306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB32(16, 127), 0x14D);
322062306a36Sopenharmony_ci	}
322162306a36Sopenharmony_ci
322262306a36Sopenharmony_ci	b43_nphy_gain_ctl_workarounds(dev);
322362306a36Sopenharmony_ci
322462306a36Sopenharmony_ci	b43_ntab_write(dev, B43_NTAB16(8, 0), 2);
322562306a36Sopenharmony_ci	b43_ntab_write(dev, B43_NTAB16(8, 16), 2);
322662306a36Sopenharmony_ci
322762306a36Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
322862306a36Sopenharmony_ci		pdet_range = sprom->fem.ghz2.pdet_range;
322962306a36Sopenharmony_ci	else
323062306a36Sopenharmony_ci		pdet_range = sprom->fem.ghz5.pdet_range;
323162306a36Sopenharmony_ci	vmid = vmids[min_t(u16, pdet_range, 4)];
323262306a36Sopenharmony_ci	gain = gains[min_t(u16, pdet_range, 4)];
323362306a36Sopenharmony_ci	switch (pdet_range) {
323462306a36Sopenharmony_ci	case 3:
323562306a36Sopenharmony_ci		if (!(dev->phy.rev >= 4 &&
323662306a36Sopenharmony_ci		      b43_current_band(dev->wl) == NL80211_BAND_2GHZ))
323762306a36Sopenharmony_ci			break;
323862306a36Sopenharmony_ci		fallthrough;
323962306a36Sopenharmony_ci	case 0:
324062306a36Sopenharmony_ci	case 1:
324162306a36Sopenharmony_ci		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4, vmid);
324262306a36Sopenharmony_ci		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4, vmid);
324362306a36Sopenharmony_ci		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0c), 4, gain);
324462306a36Sopenharmony_ci		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1c), 4, gain);
324562306a36Sopenharmony_ci		break;
324662306a36Sopenharmony_ci	case 2:
324762306a36Sopenharmony_ci		if (dev->phy.rev >= 6) {
324862306a36Sopenharmony_ci			if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
324962306a36Sopenharmony_ci				vmid[3] = 0x94;
325062306a36Sopenharmony_ci			else
325162306a36Sopenharmony_ci				vmid[3] = 0x8e;
325262306a36Sopenharmony_ci			gain[3] = 3;
325362306a36Sopenharmony_ci		} else if (dev->phy.rev == 5) {
325462306a36Sopenharmony_ci			vmid[3] = 0x84;
325562306a36Sopenharmony_ci			gain[3] = 2;
325662306a36Sopenharmony_ci		}
325762306a36Sopenharmony_ci		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4, vmid);
325862306a36Sopenharmony_ci		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4, vmid);
325962306a36Sopenharmony_ci		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0c), 4, gain);
326062306a36Sopenharmony_ci		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1c), 4, gain);
326162306a36Sopenharmony_ci		break;
326262306a36Sopenharmony_ci	case 4:
326362306a36Sopenharmony_ci	case 5:
326462306a36Sopenharmony_ci		if (b43_current_band(dev->wl) != NL80211_BAND_2GHZ) {
326562306a36Sopenharmony_ci			if (pdet_range == 4) {
326662306a36Sopenharmony_ci				vmid[3] = 0x8e;
326762306a36Sopenharmony_ci				tmp16 = 0x96;
326862306a36Sopenharmony_ci				gain[3] = 0x2;
326962306a36Sopenharmony_ci			} else {
327062306a36Sopenharmony_ci				vmid[3] = 0x89;
327162306a36Sopenharmony_ci				tmp16 = 0x89;
327262306a36Sopenharmony_ci				gain[3] = 0;
327362306a36Sopenharmony_ci			}
327462306a36Sopenharmony_ci		} else {
327562306a36Sopenharmony_ci			if (pdet_range == 4) {
327662306a36Sopenharmony_ci				vmid[3] = 0x89;
327762306a36Sopenharmony_ci				tmp16 = 0x8b;
327862306a36Sopenharmony_ci				gain[3] = 0x2;
327962306a36Sopenharmony_ci			} else {
328062306a36Sopenharmony_ci				vmid[3] = 0x74;
328162306a36Sopenharmony_ci				tmp16 = 0x70;
328262306a36Sopenharmony_ci				gain[3] = 0;
328362306a36Sopenharmony_ci			}
328462306a36Sopenharmony_ci		}
328562306a36Sopenharmony_ci		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4, vmid);
328662306a36Sopenharmony_ci		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0c), 4, gain);
328762306a36Sopenharmony_ci		vmid[3] = tmp16;
328862306a36Sopenharmony_ci		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4, vmid);
328962306a36Sopenharmony_ci		b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1c), 4, gain);
329062306a36Sopenharmony_ci		break;
329162306a36Sopenharmony_ci	}
329262306a36Sopenharmony_ci
329362306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_MAST_BIAS, 0x00);
329462306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_MAST_BIAS, 0x00);
329562306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
329662306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
329762306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_AUX, 0x07);
329862306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07);
329962306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88);
330062306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88);
330162306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_CMFB_IDAC, 0x00);
330262306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_CMFB_IDAC, 0x00);
330362306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
330462306a36Sopenharmony_ci	b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
330562306a36Sopenharmony_ci
330662306a36Sopenharmony_ci	/* N PHY WAR TX Chain Update with hw_phytxchain as argument */
330762306a36Sopenharmony_ci
330862306a36Sopenharmony_ci	if ((sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
330962306a36Sopenharmony_ci	     b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ||
331062306a36Sopenharmony_ci	    (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
331162306a36Sopenharmony_ci	     b43_current_band(dev->wl) == NL80211_BAND_2GHZ))
331262306a36Sopenharmony_ci		tmp32 = 0x00088888;
331362306a36Sopenharmony_ci	else
331462306a36Sopenharmony_ci		tmp32 = 0x88888888;
331562306a36Sopenharmony_ci	b43_ntab_write(dev, B43_NTAB32(30, 1), tmp32);
331662306a36Sopenharmony_ci	b43_ntab_write(dev, B43_NTAB32(30, 2), tmp32);
331762306a36Sopenharmony_ci	b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32);
331862306a36Sopenharmony_ci
331962306a36Sopenharmony_ci	if (dev->phy.rev == 4 &&
332062306a36Sopenharmony_ci	    b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
332162306a36Sopenharmony_ci		b43_radio_write(dev, B2056_TX0 | B2056_TX_GMBB_IDAC,
332262306a36Sopenharmony_ci				0x70);
332362306a36Sopenharmony_ci		b43_radio_write(dev, B2056_TX1 | B2056_TX_GMBB_IDAC,
332462306a36Sopenharmony_ci				0x70);
332562306a36Sopenharmony_ci	}
332662306a36Sopenharmony_ci
332762306a36Sopenharmony_ci	/* Dropped probably-always-true condition */
332862306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_ED_CRS40ASSERTTHRESH0, 0x03eb);
332962306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_ED_CRS40ASSERTTHRESH1, 0x03eb);
333062306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_ED_CRS40DEASSERTTHRESH0, 0x0341);
333162306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_ED_CRS40DEASSERTTHRESH1, 0x0341);
333262306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_ED_CRS20LASSERTTHRESH0, 0x042b);
333362306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_ED_CRS20LASSERTTHRESH1, 0x042b);
333462306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_ED_CRS20LDEASSERTTHRESH0, 0x0381);
333562306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_ED_CRS20LDEASSERTTHRESH1, 0x0381);
333662306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_ED_CRS20UASSERTTHRESH0, 0x042b);
333762306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_ED_CRS20UASSERTTHRESH1, 0x042b);
333862306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_ED_CRS20UDEASSERTTHRESH0, 0x0381);
333962306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_ED_CRS20UDEASSERTTHRESH1, 0x0381);
334062306a36Sopenharmony_ci
334162306a36Sopenharmony_ci	if (dev->phy.rev >= 6 && sprom->boardflags2_lo & B43_BFL2_SINGLEANT_CCK) {
334262306a36Sopenharmony_ci		; /* TODO: 0x0080000000000000 HF */
334362306a36Sopenharmony_ci	}
334462306a36Sopenharmony_ci}
334562306a36Sopenharmony_ci
334662306a36Sopenharmony_cistatic void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
334762306a36Sopenharmony_ci{
334862306a36Sopenharmony_ci	struct ssb_sprom *sprom = dev->dev->bus_sprom;
334962306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
335062306a36Sopenharmony_ci	struct b43_phy_n *nphy = phy->n;
335162306a36Sopenharmony_ci
335262306a36Sopenharmony_ci	u8 events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 };
335362306a36Sopenharmony_ci	u8 delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 };
335462306a36Sopenharmony_ci
335562306a36Sopenharmony_ci	u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 };
335662306a36Sopenharmony_ci	u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
335762306a36Sopenharmony_ci
335862306a36Sopenharmony_ci	if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD ||
335962306a36Sopenharmony_ci	    dev->dev->board_type == BCMA_BOARD_TYPE_BCM943224M93) {
336062306a36Sopenharmony_ci		delays1[0] = 0x1;
336162306a36Sopenharmony_ci		delays1[5] = 0x14;
336262306a36Sopenharmony_ci	}
336362306a36Sopenharmony_ci
336462306a36Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ &&
336562306a36Sopenharmony_ci	    nphy->band5g_pwrgain) {
336662306a36Sopenharmony_ci		b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8);
336762306a36Sopenharmony_ci		b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8);
336862306a36Sopenharmony_ci	} else {
336962306a36Sopenharmony_ci		b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8);
337062306a36Sopenharmony_ci		b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8);
337162306a36Sopenharmony_ci	}
337262306a36Sopenharmony_ci
337362306a36Sopenharmony_ci	b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A);
337462306a36Sopenharmony_ci	b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A);
337562306a36Sopenharmony_ci	if (dev->phy.rev < 3) {
337662306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
337762306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
337862306a36Sopenharmony_ci	}
337962306a36Sopenharmony_ci
338062306a36Sopenharmony_ci	if (dev->phy.rev < 2) {
338162306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000);
338262306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0x0000);
338362306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB);
338462306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB);
338562306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x0800);
338662306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x0800);
338762306a36Sopenharmony_ci	}
338862306a36Sopenharmony_ci
338962306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
339062306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
339162306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
339262306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
339362306a36Sopenharmony_ci
339462306a36Sopenharmony_ci	b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);
339562306a36Sopenharmony_ci	b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);
339662306a36Sopenharmony_ci
339762306a36Sopenharmony_ci	b43_nphy_gain_ctl_workarounds(dev);
339862306a36Sopenharmony_ci
339962306a36Sopenharmony_ci	if (dev->phy.rev < 2) {
340062306a36Sopenharmony_ci		if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2)
340162306a36Sopenharmony_ci			b43_hf_write(dev, b43_hf_read(dev) |
340262306a36Sopenharmony_ci					B43_HF_MLADVW);
340362306a36Sopenharmony_ci	} else if (dev->phy.rev == 2) {
340462306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0);
340562306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0);
340662306a36Sopenharmony_ci	}
340762306a36Sopenharmony_ci
340862306a36Sopenharmony_ci	if (dev->phy.rev < 2)
340962306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL,
341062306a36Sopenharmony_ci				~B43_NPHY_SCRAM_SIGCTL_SCM);
341162306a36Sopenharmony_ci
341262306a36Sopenharmony_ci	/* Set phase track alpha and beta */
341362306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125);
341462306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3);
341562306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105);
341662306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E);
341762306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);
341862306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
341962306a36Sopenharmony_ci
342062306a36Sopenharmony_ci	if (dev->phy.rev < 3) {
342162306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_PIL_DW1,
342262306a36Sopenharmony_ci			     ~B43_NPHY_PIL_DW_64QAM & 0xFFFF);
342362306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5);
342462306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4);
342562306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00);
342662306a36Sopenharmony_ci	}
342762306a36Sopenharmony_ci
342862306a36Sopenharmony_ci	if (dev->phy.rev == 2)
342962306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_FINERX2_CGC,
343062306a36Sopenharmony_ci				B43_NPHY_FINERX2_CGC_DECGC);
343162306a36Sopenharmony_ci}
343262306a36Sopenharmony_ci
343362306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */
343462306a36Sopenharmony_cistatic void b43_nphy_workarounds(struct b43_wldev *dev)
343562306a36Sopenharmony_ci{
343662306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
343762306a36Sopenharmony_ci	struct b43_phy_n *nphy = phy->n;
343862306a36Sopenharmony_ci
343962306a36Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
344062306a36Sopenharmony_ci		b43_nphy_classifier(dev, 1, 0);
344162306a36Sopenharmony_ci	else
344262306a36Sopenharmony_ci		b43_nphy_classifier(dev, 1, 1);
344362306a36Sopenharmony_ci
344462306a36Sopenharmony_ci	if (nphy->hang_avoid)
344562306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, 1);
344662306a36Sopenharmony_ci
344762306a36Sopenharmony_ci	b43_phy_set(dev, B43_NPHY_IQFLIP,
344862306a36Sopenharmony_ci		    B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
344962306a36Sopenharmony_ci
345062306a36Sopenharmony_ci	/* TODO: rev19+ */
345162306a36Sopenharmony_ci	if (dev->phy.rev >= 7)
345262306a36Sopenharmony_ci		b43_nphy_workarounds_rev7plus(dev);
345362306a36Sopenharmony_ci	else if (dev->phy.rev >= 3)
345462306a36Sopenharmony_ci		b43_nphy_workarounds_rev3plus(dev);
345562306a36Sopenharmony_ci	else
345662306a36Sopenharmony_ci		b43_nphy_workarounds_rev1_2(dev);
345762306a36Sopenharmony_ci
345862306a36Sopenharmony_ci	if (nphy->hang_avoid)
345962306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, 0);
346062306a36Sopenharmony_ci}
346162306a36Sopenharmony_ci
346262306a36Sopenharmony_ci/**************************************************
346362306a36Sopenharmony_ci * Tx/Rx common
346462306a36Sopenharmony_ci **************************************************/
346562306a36Sopenharmony_ci
346662306a36Sopenharmony_ci/*
346762306a36Sopenharmony_ci * Transmits a known value for LO calibration
346862306a36Sopenharmony_ci * https://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone
346962306a36Sopenharmony_ci */
347062306a36Sopenharmony_cistatic int b43_nphy_tx_tone(struct b43_wldev *dev, u32 freq, u16 max_val,
347162306a36Sopenharmony_ci			    bool iqmode, bool dac_test, bool modify_bbmult)
347262306a36Sopenharmony_ci{
347362306a36Sopenharmony_ci	u16 samp = b43_nphy_gen_load_samples(dev, freq, max_val, dac_test);
347462306a36Sopenharmony_ci	if (samp == 0)
347562306a36Sopenharmony_ci		return -1;
347662306a36Sopenharmony_ci	b43_nphy_run_samples(dev, samp, 0xFFFF, 0, iqmode, dac_test,
347762306a36Sopenharmony_ci			     modify_bbmult);
347862306a36Sopenharmony_ci	return 0;
347962306a36Sopenharmony_ci}
348062306a36Sopenharmony_ci
348162306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */
348262306a36Sopenharmony_cistatic void b43_nphy_update_txrx_chain(struct b43_wldev *dev)
348362306a36Sopenharmony_ci{
348462306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
348562306a36Sopenharmony_ci
348662306a36Sopenharmony_ci	bool override = false;
348762306a36Sopenharmony_ci	u16 chain = 0x33;
348862306a36Sopenharmony_ci
348962306a36Sopenharmony_ci	if (nphy->txrx_chain == 0) {
349062306a36Sopenharmony_ci		chain = 0x11;
349162306a36Sopenharmony_ci		override = true;
349262306a36Sopenharmony_ci	} else if (nphy->txrx_chain == 1) {
349362306a36Sopenharmony_ci		chain = 0x22;
349462306a36Sopenharmony_ci		override = true;
349562306a36Sopenharmony_ci	}
349662306a36Sopenharmony_ci
349762306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
349862306a36Sopenharmony_ci			~(B43_NPHY_RFSEQCA_TXEN | B43_NPHY_RFSEQCA_RXEN),
349962306a36Sopenharmony_ci			chain);
350062306a36Sopenharmony_ci
350162306a36Sopenharmony_ci	if (override)
350262306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_RFSEQMODE,
350362306a36Sopenharmony_ci				B43_NPHY_RFSEQMODE_CAOVER);
350462306a36Sopenharmony_ci	else
350562306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
350662306a36Sopenharmony_ci				~B43_NPHY_RFSEQMODE_CAOVER);
350762306a36Sopenharmony_ci}
350862306a36Sopenharmony_ci
350962306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */
351062306a36Sopenharmony_cistatic void b43_nphy_stop_playback(struct b43_wldev *dev)
351162306a36Sopenharmony_ci{
351262306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
351362306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
351462306a36Sopenharmony_ci	u16 tmp;
351562306a36Sopenharmony_ci
351662306a36Sopenharmony_ci	if (nphy->hang_avoid)
351762306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, 1);
351862306a36Sopenharmony_ci
351962306a36Sopenharmony_ci	tmp = b43_phy_read(dev, B43_NPHY_SAMP_STAT);
352062306a36Sopenharmony_ci	if (tmp & 0x1)
352162306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_SAMP_CMD, B43_NPHY_SAMP_CMD_STOP);
352262306a36Sopenharmony_ci	else if (tmp & 0x2)
352362306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
352462306a36Sopenharmony_ci
352562306a36Sopenharmony_ci	b43_phy_mask(dev, B43_NPHY_SAMP_CMD, ~0x0004);
352662306a36Sopenharmony_ci
352762306a36Sopenharmony_ci	if (nphy->bb_mult_save & 0x80000000) {
352862306a36Sopenharmony_ci		tmp = nphy->bb_mult_save & 0xFFFF;
352962306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
353062306a36Sopenharmony_ci		nphy->bb_mult_save = 0;
353162306a36Sopenharmony_ci	}
353262306a36Sopenharmony_ci
353362306a36Sopenharmony_ci	if (phy->rev >= 7 && nphy->lpf_bw_overrode_for_sample_play) {
353462306a36Sopenharmony_ci		if (phy->rev >= 19)
353562306a36Sopenharmony_ci			b43_nphy_rf_ctl_override_rev19(dev, 0x80, 0, 0, true,
353662306a36Sopenharmony_ci						       1);
353762306a36Sopenharmony_ci		else
353862306a36Sopenharmony_ci			b43_nphy_rf_ctl_override_rev7(dev, 0x80, 0, 0, true, 1);
353962306a36Sopenharmony_ci		nphy->lpf_bw_overrode_for_sample_play = false;
354062306a36Sopenharmony_ci	}
354162306a36Sopenharmony_ci
354262306a36Sopenharmony_ci	if (nphy->hang_avoid)
354362306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, 0);
354462306a36Sopenharmony_ci}
354562306a36Sopenharmony_ci
354662306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/IqCalGainParams */
354762306a36Sopenharmony_cistatic void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core,
354862306a36Sopenharmony_ci					struct nphy_txgains target,
354962306a36Sopenharmony_ci					struct nphy_iqcal_params *params)
355062306a36Sopenharmony_ci{
355162306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
355262306a36Sopenharmony_ci	int i, j, indx;
355362306a36Sopenharmony_ci	u16 gain;
355462306a36Sopenharmony_ci
355562306a36Sopenharmony_ci	if (dev->phy.rev >= 3) {
355662306a36Sopenharmony_ci		params->tx_lpf = target.tx_lpf[core]; /* Rev 7+ */
355762306a36Sopenharmony_ci		params->txgm = target.txgm[core];
355862306a36Sopenharmony_ci		params->pga = target.pga[core];
355962306a36Sopenharmony_ci		params->pad = target.pad[core];
356062306a36Sopenharmony_ci		params->ipa = target.ipa[core];
356162306a36Sopenharmony_ci		if (phy->rev >= 19) {
356262306a36Sopenharmony_ci			/* TODO */
356362306a36Sopenharmony_ci		} else if (phy->rev >= 7) {
356462306a36Sopenharmony_ci			params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 3) | (params->ipa) | (params->tx_lpf << 15);
356562306a36Sopenharmony_ci		} else {
356662306a36Sopenharmony_ci			params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 4) | (params->ipa);
356762306a36Sopenharmony_ci		}
356862306a36Sopenharmony_ci		for (j = 0; j < 5; j++)
356962306a36Sopenharmony_ci			params->ncorr[j] = 0x79;
357062306a36Sopenharmony_ci	} else {
357162306a36Sopenharmony_ci		gain = (target.pad[core]) | (target.pga[core] << 4) |
357262306a36Sopenharmony_ci			(target.txgm[core] << 8);
357362306a36Sopenharmony_ci
357462306a36Sopenharmony_ci		indx = (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ?
357562306a36Sopenharmony_ci			1 : 0;
357662306a36Sopenharmony_ci		for (i = 0; i < 9; i++)
357762306a36Sopenharmony_ci			if (tbl_iqcal_gainparams[indx][i][0] == gain)
357862306a36Sopenharmony_ci				break;
357962306a36Sopenharmony_ci		i = min(i, 8);
358062306a36Sopenharmony_ci
358162306a36Sopenharmony_ci		params->txgm = tbl_iqcal_gainparams[indx][i][1];
358262306a36Sopenharmony_ci		params->pga = tbl_iqcal_gainparams[indx][i][2];
358362306a36Sopenharmony_ci		params->pad = tbl_iqcal_gainparams[indx][i][3];
358462306a36Sopenharmony_ci		params->cal_gain = (params->txgm << 7) | (params->pga << 4) |
358562306a36Sopenharmony_ci					(params->pad << 2);
358662306a36Sopenharmony_ci		for (j = 0; j < 4; j++)
358762306a36Sopenharmony_ci			params->ncorr[j] = tbl_iqcal_gainparams[indx][i][4 + j];
358862306a36Sopenharmony_ci	}
358962306a36Sopenharmony_ci}
359062306a36Sopenharmony_ci
359162306a36Sopenharmony_ci/**************************************************
359262306a36Sopenharmony_ci * Tx and Rx
359362306a36Sopenharmony_ci **************************************************/
359462306a36Sopenharmony_ci
359562306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */
359662306a36Sopenharmony_cistatic void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
359762306a36Sopenharmony_ci{
359862306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
359962306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
360062306a36Sopenharmony_ci	u8 i;
360162306a36Sopenharmony_ci	u16 bmask, val, tmp;
360262306a36Sopenharmony_ci	enum nl80211_band band = b43_current_band(dev->wl);
360362306a36Sopenharmony_ci
360462306a36Sopenharmony_ci	if (nphy->hang_avoid)
360562306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, 1);
360662306a36Sopenharmony_ci
360762306a36Sopenharmony_ci	nphy->txpwrctrl = enable;
360862306a36Sopenharmony_ci	if (!enable) {
360962306a36Sopenharmony_ci		if (dev->phy.rev >= 3 &&
361062306a36Sopenharmony_ci		    (b43_phy_read(dev, B43_NPHY_TXPCTL_CMD) &
361162306a36Sopenharmony_ci		     (B43_NPHY_TXPCTL_CMD_COEFF |
361262306a36Sopenharmony_ci		      B43_NPHY_TXPCTL_CMD_HWPCTLEN |
361362306a36Sopenharmony_ci		      B43_NPHY_TXPCTL_CMD_PCTLEN))) {
361462306a36Sopenharmony_ci			/* We disable enabled TX pwr ctl, save it's state */
361562306a36Sopenharmony_ci			nphy->tx_pwr_idx[0] = b43_phy_read(dev,
361662306a36Sopenharmony_ci						B43_NPHY_C1_TXPCTL_STAT) & 0x7f;
361762306a36Sopenharmony_ci			nphy->tx_pwr_idx[1] = b43_phy_read(dev,
361862306a36Sopenharmony_ci						B43_NPHY_C2_TXPCTL_STAT) & 0x7f;
361962306a36Sopenharmony_ci		}
362062306a36Sopenharmony_ci
362162306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6840);
362262306a36Sopenharmony_ci		for (i = 0; i < 84; i++)
362362306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0);
362462306a36Sopenharmony_ci
362562306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6C40);
362662306a36Sopenharmony_ci		for (i = 0; i < 84; i++)
362762306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0);
362862306a36Sopenharmony_ci
362962306a36Sopenharmony_ci		tmp = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN;
363062306a36Sopenharmony_ci		if (dev->phy.rev >= 3)
363162306a36Sopenharmony_ci			tmp |= B43_NPHY_TXPCTL_CMD_PCTLEN;
363262306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD, ~tmp);
363362306a36Sopenharmony_ci
363462306a36Sopenharmony_ci		if (dev->phy.rev >= 3) {
363562306a36Sopenharmony_ci			b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100);
363662306a36Sopenharmony_ci			b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100);
363762306a36Sopenharmony_ci		} else {
363862306a36Sopenharmony_ci			b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000);
363962306a36Sopenharmony_ci		}
364062306a36Sopenharmony_ci
364162306a36Sopenharmony_ci		if (dev->phy.rev == 2)
364262306a36Sopenharmony_ci			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
364362306a36Sopenharmony_ci				~B43_NPHY_BPHY_CTL3_SCALE, 0x53);
364462306a36Sopenharmony_ci		else if (dev->phy.rev < 2)
364562306a36Sopenharmony_ci			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
364662306a36Sopenharmony_ci				~B43_NPHY_BPHY_CTL3_SCALE, 0x5A);
364762306a36Sopenharmony_ci
364862306a36Sopenharmony_ci		if (dev->phy.rev < 2 && b43_is_40mhz(dev))
364962306a36Sopenharmony_ci			b43_hf_write(dev, b43_hf_read(dev) | B43_HF_TSSIRPSMW);
365062306a36Sopenharmony_ci	} else {
365162306a36Sopenharmony_ci		b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84,
365262306a36Sopenharmony_ci				    nphy->adj_pwr_tbl);
365362306a36Sopenharmony_ci		b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84,
365462306a36Sopenharmony_ci				    nphy->adj_pwr_tbl);
365562306a36Sopenharmony_ci
365662306a36Sopenharmony_ci		bmask = B43_NPHY_TXPCTL_CMD_COEFF |
365762306a36Sopenharmony_ci			B43_NPHY_TXPCTL_CMD_HWPCTLEN;
365862306a36Sopenharmony_ci		/* wl does useless check for "enable" param here */
365962306a36Sopenharmony_ci		val = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN;
366062306a36Sopenharmony_ci		if (dev->phy.rev >= 3) {
366162306a36Sopenharmony_ci			bmask |= B43_NPHY_TXPCTL_CMD_PCTLEN;
366262306a36Sopenharmony_ci			if (val)
366362306a36Sopenharmony_ci				val |= B43_NPHY_TXPCTL_CMD_PCTLEN;
366462306a36Sopenharmony_ci		}
366562306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, ~(bmask), val);
366662306a36Sopenharmony_ci
366762306a36Sopenharmony_ci		if (band == NL80211_BAND_5GHZ) {
366862306a36Sopenharmony_ci			if (phy->rev >= 19) {
366962306a36Sopenharmony_ci				/* TODO */
367062306a36Sopenharmony_ci			} else if (phy->rev >= 7) {
367162306a36Sopenharmony_ci				b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
367262306a36Sopenharmony_ci						~B43_NPHY_TXPCTL_CMD_INIT,
367362306a36Sopenharmony_ci						0x32);
367462306a36Sopenharmony_ci				b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,
367562306a36Sopenharmony_ci						~B43_NPHY_TXPCTL_INIT_PIDXI1,
367662306a36Sopenharmony_ci						0x32);
367762306a36Sopenharmony_ci			} else {
367862306a36Sopenharmony_ci				b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
367962306a36Sopenharmony_ci						~B43_NPHY_TXPCTL_CMD_INIT,
368062306a36Sopenharmony_ci						0x64);
368162306a36Sopenharmony_ci				if (phy->rev > 1)
368262306a36Sopenharmony_ci					b43_phy_maskset(dev,
368362306a36Sopenharmony_ci							B43_NPHY_TXPCTL_INIT,
368462306a36Sopenharmony_ci							~B43_NPHY_TXPCTL_INIT_PIDXI1,
368562306a36Sopenharmony_ci							0x64);
368662306a36Sopenharmony_ci			}
368762306a36Sopenharmony_ci		}
368862306a36Sopenharmony_ci
368962306a36Sopenharmony_ci		if (dev->phy.rev >= 3) {
369062306a36Sopenharmony_ci			if (nphy->tx_pwr_idx[0] != 128 &&
369162306a36Sopenharmony_ci			    nphy->tx_pwr_idx[1] != 128) {
369262306a36Sopenharmony_ci				/* Recover TX pwr ctl state */
369362306a36Sopenharmony_ci				b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
369462306a36Sopenharmony_ci						~B43_NPHY_TXPCTL_CMD_INIT,
369562306a36Sopenharmony_ci						nphy->tx_pwr_idx[0]);
369662306a36Sopenharmony_ci				if (dev->phy.rev > 1)
369762306a36Sopenharmony_ci					b43_phy_maskset(dev,
369862306a36Sopenharmony_ci						B43_NPHY_TXPCTL_INIT,
369962306a36Sopenharmony_ci						~0xff, nphy->tx_pwr_idx[1]);
370062306a36Sopenharmony_ci			}
370162306a36Sopenharmony_ci		}
370262306a36Sopenharmony_ci
370362306a36Sopenharmony_ci		if (phy->rev >= 7) {
370462306a36Sopenharmony_ci			/* TODO */
370562306a36Sopenharmony_ci		}
370662306a36Sopenharmony_ci
370762306a36Sopenharmony_ci		if (dev->phy.rev >= 3) {
370862306a36Sopenharmony_ci			b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x100);
370962306a36Sopenharmony_ci			b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x100);
371062306a36Sopenharmony_ci		} else {
371162306a36Sopenharmony_ci			b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4000);
371262306a36Sopenharmony_ci		}
371362306a36Sopenharmony_ci
371462306a36Sopenharmony_ci		if (dev->phy.rev == 2)
371562306a36Sopenharmony_ci			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x3b);
371662306a36Sopenharmony_ci		else if (dev->phy.rev < 2)
371762306a36Sopenharmony_ci			b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x40);
371862306a36Sopenharmony_ci
371962306a36Sopenharmony_ci		if (dev->phy.rev < 2 && b43_is_40mhz(dev))
372062306a36Sopenharmony_ci			b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_TSSIRPSMW);
372162306a36Sopenharmony_ci
372262306a36Sopenharmony_ci		if (b43_nphy_ipa(dev)) {
372362306a36Sopenharmony_ci			b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x4);
372462306a36Sopenharmony_ci			b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x4);
372562306a36Sopenharmony_ci		}
372662306a36Sopenharmony_ci	}
372762306a36Sopenharmony_ci
372862306a36Sopenharmony_ci	if (nphy->hang_avoid)
372962306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, 0);
373062306a36Sopenharmony_ci}
373162306a36Sopenharmony_ci
373262306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrFix */
373362306a36Sopenharmony_cistatic void b43_nphy_tx_power_fix(struct b43_wldev *dev)
373462306a36Sopenharmony_ci{
373562306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
373662306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
373762306a36Sopenharmony_ci	struct ssb_sprom *sprom = dev->dev->bus_sprom;
373862306a36Sopenharmony_ci
373962306a36Sopenharmony_ci	u8 txpi[2], bbmult, i;
374062306a36Sopenharmony_ci	u16 tmp, radio_gain, dac_gain;
374162306a36Sopenharmony_ci	u16 freq = phy->chandef->chan->center_freq;
374262306a36Sopenharmony_ci	u32 txgain;
374362306a36Sopenharmony_ci	/* u32 gaintbl; rev3+ */
374462306a36Sopenharmony_ci
374562306a36Sopenharmony_ci	if (nphy->hang_avoid)
374662306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, 1);
374762306a36Sopenharmony_ci
374862306a36Sopenharmony_ci	/* TODO: rev19+ */
374962306a36Sopenharmony_ci	if (dev->phy.rev >= 7) {
375062306a36Sopenharmony_ci		txpi[0] = txpi[1] = 30;
375162306a36Sopenharmony_ci	} else if (dev->phy.rev >= 3) {
375262306a36Sopenharmony_ci		txpi[0] = 40;
375362306a36Sopenharmony_ci		txpi[1] = 40;
375462306a36Sopenharmony_ci	} else if (sprom->revision < 4) {
375562306a36Sopenharmony_ci		txpi[0] = 72;
375662306a36Sopenharmony_ci		txpi[1] = 72;
375762306a36Sopenharmony_ci	} else {
375862306a36Sopenharmony_ci		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
375962306a36Sopenharmony_ci			txpi[0] = sprom->txpid2g[0];
376062306a36Sopenharmony_ci			txpi[1] = sprom->txpid2g[1];
376162306a36Sopenharmony_ci		} else if (freq >= 4900 && freq < 5100) {
376262306a36Sopenharmony_ci			txpi[0] = sprom->txpid5gl[0];
376362306a36Sopenharmony_ci			txpi[1] = sprom->txpid5gl[1];
376462306a36Sopenharmony_ci		} else if (freq >= 5100 && freq < 5500) {
376562306a36Sopenharmony_ci			txpi[0] = sprom->txpid5g[0];
376662306a36Sopenharmony_ci			txpi[1] = sprom->txpid5g[1];
376762306a36Sopenharmony_ci		} else if (freq >= 5500) {
376862306a36Sopenharmony_ci			txpi[0] = sprom->txpid5gh[0];
376962306a36Sopenharmony_ci			txpi[1] = sprom->txpid5gh[1];
377062306a36Sopenharmony_ci		} else {
377162306a36Sopenharmony_ci			txpi[0] = 91;
377262306a36Sopenharmony_ci			txpi[1] = 91;
377362306a36Sopenharmony_ci		}
377462306a36Sopenharmony_ci	}
377562306a36Sopenharmony_ci	if (dev->phy.rev < 7 &&
377662306a36Sopenharmony_ci	    (txpi[0] < 40 || txpi[0] > 100 || txpi[1] < 40 || txpi[1] > 100))
377762306a36Sopenharmony_ci		txpi[0] = txpi[1] = 91;
377862306a36Sopenharmony_ci
377962306a36Sopenharmony_ci	/*
378062306a36Sopenharmony_ci	for (i = 0; i < 2; i++) {
378162306a36Sopenharmony_ci		nphy->txpwrindex[i].index_internal = txpi[i];
378262306a36Sopenharmony_ci		nphy->txpwrindex[i].index_internal_save = txpi[i];
378362306a36Sopenharmony_ci	}
378462306a36Sopenharmony_ci	*/
378562306a36Sopenharmony_ci
378662306a36Sopenharmony_ci	for (i = 0; i < 2; i++) {
378762306a36Sopenharmony_ci		const u32 *table = b43_nphy_get_tx_gain_table(dev);
378862306a36Sopenharmony_ci
378962306a36Sopenharmony_ci		if (!table)
379062306a36Sopenharmony_ci			break;
379162306a36Sopenharmony_ci		txgain = *(table + txpi[i]);
379262306a36Sopenharmony_ci
379362306a36Sopenharmony_ci		if (dev->phy.rev >= 3)
379462306a36Sopenharmony_ci			radio_gain = (txgain >> 16) & 0x1FFFF;
379562306a36Sopenharmony_ci		else
379662306a36Sopenharmony_ci			radio_gain = (txgain >> 16) & 0x1FFF;
379762306a36Sopenharmony_ci
379862306a36Sopenharmony_ci		if (dev->phy.rev >= 7)
379962306a36Sopenharmony_ci			dac_gain = (txgain >> 8) & 0x7;
380062306a36Sopenharmony_ci		else
380162306a36Sopenharmony_ci			dac_gain = (txgain >> 8) & 0x3F;
380262306a36Sopenharmony_ci		bbmult = txgain & 0xFF;
380362306a36Sopenharmony_ci
380462306a36Sopenharmony_ci		if (dev->phy.rev >= 3) {
380562306a36Sopenharmony_ci			if (i == 0)
380662306a36Sopenharmony_ci				b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100);
380762306a36Sopenharmony_ci			else
380862306a36Sopenharmony_ci				b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100);
380962306a36Sopenharmony_ci		} else {
381062306a36Sopenharmony_ci			b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000);
381162306a36Sopenharmony_ci		}
381262306a36Sopenharmony_ci
381362306a36Sopenharmony_ci		if (i == 0)
381462306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN1, dac_gain);
381562306a36Sopenharmony_ci		else
381662306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN2, dac_gain);
381762306a36Sopenharmony_ci
381862306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(0x7, 0x110 + i), radio_gain);
381962306a36Sopenharmony_ci
382062306a36Sopenharmony_ci		tmp = b43_ntab_read(dev, B43_NTAB16(0xF, 0x57));
382162306a36Sopenharmony_ci		if (i == 0)
382262306a36Sopenharmony_ci			tmp = (tmp & 0x00FF) | (bbmult << 8);
382362306a36Sopenharmony_ci		else
382462306a36Sopenharmony_ci			tmp = (tmp & 0xFF00) | bbmult;
382562306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(0xF, 0x57), tmp);
382662306a36Sopenharmony_ci
382762306a36Sopenharmony_ci		if (b43_nphy_ipa(dev)) {
382862306a36Sopenharmony_ci			u32 tmp32;
382962306a36Sopenharmony_ci			u16 reg = (i == 0) ?
383062306a36Sopenharmony_ci				B43_NPHY_PAPD_EN0 : B43_NPHY_PAPD_EN1;
383162306a36Sopenharmony_ci			tmp32 = b43_ntab_read(dev, B43_NTAB32(26 + i,
383262306a36Sopenharmony_ci							      576 + txpi[i]));
383362306a36Sopenharmony_ci			b43_phy_maskset(dev, reg, 0xE00F, (u32) tmp32 << 4);
383462306a36Sopenharmony_ci			b43_phy_set(dev, reg, 0x4);
383562306a36Sopenharmony_ci		}
383662306a36Sopenharmony_ci	}
383762306a36Sopenharmony_ci
383862306a36Sopenharmony_ci	b43_phy_mask(dev, B43_NPHY_BPHY_CTL2, ~B43_NPHY_BPHY_CTL2_LUT);
383962306a36Sopenharmony_ci
384062306a36Sopenharmony_ci	if (nphy->hang_avoid)
384162306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, 0);
384262306a36Sopenharmony_ci}
384362306a36Sopenharmony_ci
384462306a36Sopenharmony_cistatic void b43_nphy_ipa_internal_tssi_setup(struct b43_wldev *dev)
384562306a36Sopenharmony_ci{
384662306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
384762306a36Sopenharmony_ci
384862306a36Sopenharmony_ci	u8 core;
384962306a36Sopenharmony_ci	u16 r; /* routing */
385062306a36Sopenharmony_ci
385162306a36Sopenharmony_ci	if (phy->rev >= 19) {
385262306a36Sopenharmony_ci		/* TODO */
385362306a36Sopenharmony_ci	} else if (phy->rev >= 7) {
385462306a36Sopenharmony_ci		for (core = 0; core < 2; core++) {
385562306a36Sopenharmony_ci			r = core ? 0x190 : 0x170;
385662306a36Sopenharmony_ci			if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
385762306a36Sopenharmony_ci				b43_radio_write(dev, r + 0x5, 0x5);
385862306a36Sopenharmony_ci				b43_radio_write(dev, r + 0x9, 0xE);
385962306a36Sopenharmony_ci				if (phy->rev != 5)
386062306a36Sopenharmony_ci					b43_radio_write(dev, r + 0xA, 0);
386162306a36Sopenharmony_ci				if (phy->rev != 7)
386262306a36Sopenharmony_ci					b43_radio_write(dev, r + 0xB, 1);
386362306a36Sopenharmony_ci				else
386462306a36Sopenharmony_ci					b43_radio_write(dev, r + 0xB, 0x31);
386562306a36Sopenharmony_ci			} else {
386662306a36Sopenharmony_ci				b43_radio_write(dev, r + 0x5, 0x9);
386762306a36Sopenharmony_ci				b43_radio_write(dev, r + 0x9, 0xC);
386862306a36Sopenharmony_ci				b43_radio_write(dev, r + 0xB, 0x0);
386962306a36Sopenharmony_ci				if (phy->rev != 5)
387062306a36Sopenharmony_ci					b43_radio_write(dev, r + 0xA, 1);
387162306a36Sopenharmony_ci				else
387262306a36Sopenharmony_ci					b43_radio_write(dev, r + 0xA, 0x31);
387362306a36Sopenharmony_ci			}
387462306a36Sopenharmony_ci			b43_radio_write(dev, r + 0x6, 0);
387562306a36Sopenharmony_ci			b43_radio_write(dev, r + 0x7, 0);
387662306a36Sopenharmony_ci			b43_radio_write(dev, r + 0x8, 3);
387762306a36Sopenharmony_ci			b43_radio_write(dev, r + 0xC, 0);
387862306a36Sopenharmony_ci		}
387962306a36Sopenharmony_ci	} else {
388062306a36Sopenharmony_ci		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
388162306a36Sopenharmony_ci			b43_radio_write(dev, B2056_SYN_RESERVED_ADDR31, 0x128);
388262306a36Sopenharmony_ci		else
388362306a36Sopenharmony_ci			b43_radio_write(dev, B2056_SYN_RESERVED_ADDR31, 0x80);
388462306a36Sopenharmony_ci		b43_radio_write(dev, B2056_SYN_RESERVED_ADDR30, 0);
388562306a36Sopenharmony_ci		b43_radio_write(dev, B2056_SYN_GPIO_MASTER1, 0x29);
388662306a36Sopenharmony_ci
388762306a36Sopenharmony_ci		for (core = 0; core < 2; core++) {
388862306a36Sopenharmony_ci			r = core ? B2056_TX1 : B2056_TX0;
388962306a36Sopenharmony_ci
389062306a36Sopenharmony_ci			b43_radio_write(dev, r | B2056_TX_IQCAL_VCM_HG, 0);
389162306a36Sopenharmony_ci			b43_radio_write(dev, r | B2056_TX_IQCAL_IDAC, 0);
389262306a36Sopenharmony_ci			b43_radio_write(dev, r | B2056_TX_TSSI_VCM, 3);
389362306a36Sopenharmony_ci			b43_radio_write(dev, r | B2056_TX_TX_AMP_DET, 0);
389462306a36Sopenharmony_ci			b43_radio_write(dev, r | B2056_TX_TSSI_MISC1, 8);
389562306a36Sopenharmony_ci			b43_radio_write(dev, r | B2056_TX_TSSI_MISC2, 0);
389662306a36Sopenharmony_ci			b43_radio_write(dev, r | B2056_TX_TSSI_MISC3, 0);
389762306a36Sopenharmony_ci			if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
389862306a36Sopenharmony_ci				b43_radio_write(dev, r | B2056_TX_TX_SSI_MASTER,
389962306a36Sopenharmony_ci						0x5);
390062306a36Sopenharmony_ci				if (phy->rev != 5)
390162306a36Sopenharmony_ci					b43_radio_write(dev, r | B2056_TX_TSSIA,
390262306a36Sopenharmony_ci							0x00);
390362306a36Sopenharmony_ci				if (phy->rev >= 5)
390462306a36Sopenharmony_ci					b43_radio_write(dev, r | B2056_TX_TSSIG,
390562306a36Sopenharmony_ci							0x31);
390662306a36Sopenharmony_ci				else
390762306a36Sopenharmony_ci					b43_radio_write(dev, r | B2056_TX_TSSIG,
390862306a36Sopenharmony_ci							0x11);
390962306a36Sopenharmony_ci				b43_radio_write(dev, r | B2056_TX_TX_SSI_MUX,
391062306a36Sopenharmony_ci						0xE);
391162306a36Sopenharmony_ci			} else {
391262306a36Sopenharmony_ci				b43_radio_write(dev, r | B2056_TX_TX_SSI_MASTER,
391362306a36Sopenharmony_ci						0x9);
391462306a36Sopenharmony_ci				b43_radio_write(dev, r | B2056_TX_TSSIA, 0x31);
391562306a36Sopenharmony_ci				b43_radio_write(dev, r | B2056_TX_TSSIG, 0x0);
391662306a36Sopenharmony_ci				b43_radio_write(dev, r | B2056_TX_TX_SSI_MUX,
391762306a36Sopenharmony_ci						0xC);
391862306a36Sopenharmony_ci			}
391962306a36Sopenharmony_ci		}
392062306a36Sopenharmony_ci	}
392162306a36Sopenharmony_ci}
392262306a36Sopenharmony_ci
392362306a36Sopenharmony_ci/*
392462306a36Sopenharmony_ci * Stop radio and transmit known signal. Then check received signal strength to
392562306a36Sopenharmony_ci * get TSSI (Transmit Signal Strength Indicator).
392662306a36Sopenharmony_ci * https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlIdleTssi
392762306a36Sopenharmony_ci */
392862306a36Sopenharmony_cistatic void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
392962306a36Sopenharmony_ci{
393062306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
393162306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
393262306a36Sopenharmony_ci
393362306a36Sopenharmony_ci	u32 tmp;
393462306a36Sopenharmony_ci	s32 rssi[4] = { };
393562306a36Sopenharmony_ci
393662306a36Sopenharmony_ci	if (phy->chandef->chan->flags & IEEE80211_CHAN_NO_IR)
393762306a36Sopenharmony_ci		return;
393862306a36Sopenharmony_ci
393962306a36Sopenharmony_ci	if (b43_nphy_ipa(dev))
394062306a36Sopenharmony_ci		b43_nphy_ipa_internal_tssi_setup(dev);
394162306a36Sopenharmony_ci
394262306a36Sopenharmony_ci	if (phy->rev >= 19)
394362306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_rev19(dev, 0x1000, 0, 3, false, 0);
394462306a36Sopenharmony_ci	else if (phy->rev >= 7)
394562306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_rev7(dev, 0x1000, 0, 3, false, 0);
394662306a36Sopenharmony_ci	else if (phy->rev >= 3)
394762306a36Sopenharmony_ci		b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, false);
394862306a36Sopenharmony_ci
394962306a36Sopenharmony_ci	b43_nphy_stop_playback(dev);
395062306a36Sopenharmony_ci	b43_nphy_tx_tone(dev, 4000, 0, false, false, false);
395162306a36Sopenharmony_ci	udelay(20);
395262306a36Sopenharmony_ci	tmp = b43_nphy_poll_rssi(dev, N_RSSI_TSSI_2G, rssi, 1);
395362306a36Sopenharmony_ci	b43_nphy_stop_playback(dev);
395462306a36Sopenharmony_ci
395562306a36Sopenharmony_ci	b43_nphy_rssi_select(dev, 0, N_RSSI_W1);
395662306a36Sopenharmony_ci
395762306a36Sopenharmony_ci	if (phy->rev >= 19)
395862306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_rev19(dev, 0x1000, 0, 3, true, 0);
395962306a36Sopenharmony_ci	else if (phy->rev >= 7)
396062306a36Sopenharmony_ci		b43_nphy_rf_ctl_override_rev7(dev, 0x1000, 0, 3, true, 0);
396162306a36Sopenharmony_ci	else if (phy->rev >= 3)
396262306a36Sopenharmony_ci		b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, true);
396362306a36Sopenharmony_ci
396462306a36Sopenharmony_ci	if (phy->rev >= 19) {
396562306a36Sopenharmony_ci		/* TODO */
396662306a36Sopenharmony_ci		return;
396762306a36Sopenharmony_ci	} else if (phy->rev >= 3) {
396862306a36Sopenharmony_ci		nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 24) & 0xFF;
396962306a36Sopenharmony_ci		nphy->pwr_ctl_info[1].idle_tssi_5g = (tmp >> 8) & 0xFF;
397062306a36Sopenharmony_ci	} else {
397162306a36Sopenharmony_ci		nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 16) & 0xFF;
397262306a36Sopenharmony_ci		nphy->pwr_ctl_info[1].idle_tssi_5g = tmp & 0xFF;
397362306a36Sopenharmony_ci	}
397462306a36Sopenharmony_ci	nphy->pwr_ctl_info[0].idle_tssi_2g = (tmp >> 24) & 0xFF;
397562306a36Sopenharmony_ci	nphy->pwr_ctl_info[1].idle_tssi_2g = (tmp >> 8) & 0xFF;
397662306a36Sopenharmony_ci}
397762306a36Sopenharmony_ci
397862306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/PHY/N/TxPwrLimitToTbl */
397962306a36Sopenharmony_cistatic void b43_nphy_tx_prepare_adjusted_power_table(struct b43_wldev *dev)
398062306a36Sopenharmony_ci{
398162306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
398262306a36Sopenharmony_ci
398362306a36Sopenharmony_ci	u8 idx, delta;
398462306a36Sopenharmony_ci	u8 i, stf_mode;
398562306a36Sopenharmony_ci
398662306a36Sopenharmony_ci	/* Array adj_pwr_tbl corresponds to the hardware table. It consists of
398762306a36Sopenharmony_ci	 * 21 groups, each containing 4 entries.
398862306a36Sopenharmony_ci	 *
398962306a36Sopenharmony_ci	 * First group has entries for CCK modulation.
399062306a36Sopenharmony_ci	 * The rest of groups has 1 entry per modulation (SISO, CDD, STBC, SDM).
399162306a36Sopenharmony_ci	 *
399262306a36Sopenharmony_ci	 * Group 0 is for CCK
399362306a36Sopenharmony_ci	 * Groups 1..4 use BPSK (group per coding rate)
399462306a36Sopenharmony_ci	 * Groups 5..8 use QPSK (group per coding rate)
399562306a36Sopenharmony_ci	 * Groups 9..12 use 16-QAM (group per coding rate)
399662306a36Sopenharmony_ci	 * Groups 13..16 use 64-QAM (group per coding rate)
399762306a36Sopenharmony_ci	 * Groups 17..20 are unknown
399862306a36Sopenharmony_ci	 */
399962306a36Sopenharmony_ci
400062306a36Sopenharmony_ci	for (i = 0; i < 4; i++)
400162306a36Sopenharmony_ci		nphy->adj_pwr_tbl[i] = nphy->tx_power_offset[i];
400262306a36Sopenharmony_ci
400362306a36Sopenharmony_ci	for (stf_mode = 0; stf_mode < 4; stf_mode++) {
400462306a36Sopenharmony_ci		delta = 0;
400562306a36Sopenharmony_ci		switch (stf_mode) {
400662306a36Sopenharmony_ci		case 0:
400762306a36Sopenharmony_ci			if (b43_is_40mhz(dev) && dev->phy.rev >= 5) {
400862306a36Sopenharmony_ci				idx = 68;
400962306a36Sopenharmony_ci			} else {
401062306a36Sopenharmony_ci				delta = 1;
401162306a36Sopenharmony_ci				idx = b43_is_40mhz(dev) ? 52 : 4;
401262306a36Sopenharmony_ci			}
401362306a36Sopenharmony_ci			break;
401462306a36Sopenharmony_ci		case 1:
401562306a36Sopenharmony_ci			idx = b43_is_40mhz(dev) ? 76 : 28;
401662306a36Sopenharmony_ci			break;
401762306a36Sopenharmony_ci		case 2:
401862306a36Sopenharmony_ci			idx = b43_is_40mhz(dev) ? 84 : 36;
401962306a36Sopenharmony_ci			break;
402062306a36Sopenharmony_ci		case 3:
402162306a36Sopenharmony_ci			idx = b43_is_40mhz(dev) ? 92 : 44;
402262306a36Sopenharmony_ci			break;
402362306a36Sopenharmony_ci		}
402462306a36Sopenharmony_ci
402562306a36Sopenharmony_ci		for (i = 0; i < 20; i++) {
402662306a36Sopenharmony_ci			nphy->adj_pwr_tbl[4 + 4 * i + stf_mode] =
402762306a36Sopenharmony_ci				nphy->tx_power_offset[idx];
402862306a36Sopenharmony_ci			if (i == 0)
402962306a36Sopenharmony_ci				idx += delta;
403062306a36Sopenharmony_ci			if (i == 14)
403162306a36Sopenharmony_ci				idx += 1 - delta;
403262306a36Sopenharmony_ci			if (i == 3 || i == 4 || i == 7 || i == 8 || i == 11 ||
403362306a36Sopenharmony_ci			    i == 13)
403462306a36Sopenharmony_ci				idx += 1;
403562306a36Sopenharmony_ci		}
403662306a36Sopenharmony_ci	}
403762306a36Sopenharmony_ci}
403862306a36Sopenharmony_ci
403962306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlSetup */
404062306a36Sopenharmony_cistatic void b43_nphy_tx_power_ctl_setup(struct b43_wldev *dev)
404162306a36Sopenharmony_ci{
404262306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
404362306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
404462306a36Sopenharmony_ci	struct ssb_sprom *sprom = dev->dev->bus_sprom;
404562306a36Sopenharmony_ci
404662306a36Sopenharmony_ci	s16 a1[2], b0[2], b1[2];
404762306a36Sopenharmony_ci	u8 idle[2];
404862306a36Sopenharmony_ci	u8 ppr_max;
404962306a36Sopenharmony_ci	s8 target[2];
405062306a36Sopenharmony_ci	s32 num, den, pwr;
405162306a36Sopenharmony_ci	u32 regval[64];
405262306a36Sopenharmony_ci
405362306a36Sopenharmony_ci	u16 freq = phy->chandef->chan->center_freq;
405462306a36Sopenharmony_ci	u16 tmp;
405562306a36Sopenharmony_ci	u16 r; /* routing */
405662306a36Sopenharmony_ci	u8 i, c;
405762306a36Sopenharmony_ci
405862306a36Sopenharmony_ci	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) {
405962306a36Sopenharmony_ci		b43_maskset32(dev, B43_MMIO_MACCTL, ~0, 0x200000);
406062306a36Sopenharmony_ci		b43_read32(dev, B43_MMIO_MACCTL);
406162306a36Sopenharmony_ci		udelay(1);
406262306a36Sopenharmony_ci	}
406362306a36Sopenharmony_ci
406462306a36Sopenharmony_ci	if (nphy->hang_avoid)
406562306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, true);
406662306a36Sopenharmony_ci
406762306a36Sopenharmony_ci	b43_phy_set(dev, B43_NPHY_TSSIMODE, B43_NPHY_TSSIMODE_EN);
406862306a36Sopenharmony_ci	if (dev->phy.rev >= 3)
406962306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD,
407062306a36Sopenharmony_ci			     ~B43_NPHY_TXPCTL_CMD_PCTLEN & 0xFFFF);
407162306a36Sopenharmony_ci	else
407262306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_TXPCTL_CMD,
407362306a36Sopenharmony_ci			    B43_NPHY_TXPCTL_CMD_PCTLEN);
407462306a36Sopenharmony_ci
407562306a36Sopenharmony_ci	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12)
407662306a36Sopenharmony_ci		b43_maskset32(dev, B43_MMIO_MACCTL, ~0x200000, 0);
407762306a36Sopenharmony_ci
407862306a36Sopenharmony_ci	if (sprom->revision < 4) {
407962306a36Sopenharmony_ci		idle[0] = nphy->pwr_ctl_info[0].idle_tssi_2g;
408062306a36Sopenharmony_ci		idle[1] = nphy->pwr_ctl_info[1].idle_tssi_2g;
408162306a36Sopenharmony_ci		target[0] = target[1] = 52;
408262306a36Sopenharmony_ci		a1[0] = a1[1] = -424;
408362306a36Sopenharmony_ci		b0[0] = b0[1] = 5612;
408462306a36Sopenharmony_ci		b1[0] = b1[1] = -1393;
408562306a36Sopenharmony_ci	} else {
408662306a36Sopenharmony_ci		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
408762306a36Sopenharmony_ci			for (c = 0; c < 2; c++) {
408862306a36Sopenharmony_ci				idle[c] = nphy->pwr_ctl_info[c].idle_tssi_2g;
408962306a36Sopenharmony_ci				target[c] = sprom->core_pwr_info[c].maxpwr_2g;
409062306a36Sopenharmony_ci				a1[c] = sprom->core_pwr_info[c].pa_2g[0];
409162306a36Sopenharmony_ci				b0[c] = sprom->core_pwr_info[c].pa_2g[1];
409262306a36Sopenharmony_ci				b1[c] = sprom->core_pwr_info[c].pa_2g[2];
409362306a36Sopenharmony_ci			}
409462306a36Sopenharmony_ci		} else if (freq >= 4900 && freq < 5100) {
409562306a36Sopenharmony_ci			for (c = 0; c < 2; c++) {
409662306a36Sopenharmony_ci				idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g;
409762306a36Sopenharmony_ci				target[c] = sprom->core_pwr_info[c].maxpwr_5gl;
409862306a36Sopenharmony_ci				a1[c] = sprom->core_pwr_info[c].pa_5gl[0];
409962306a36Sopenharmony_ci				b0[c] = sprom->core_pwr_info[c].pa_5gl[1];
410062306a36Sopenharmony_ci				b1[c] = sprom->core_pwr_info[c].pa_5gl[2];
410162306a36Sopenharmony_ci			}
410262306a36Sopenharmony_ci		} else if (freq >= 5100 && freq < 5500) {
410362306a36Sopenharmony_ci			for (c = 0; c < 2; c++) {
410462306a36Sopenharmony_ci				idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g;
410562306a36Sopenharmony_ci				target[c] = sprom->core_pwr_info[c].maxpwr_5g;
410662306a36Sopenharmony_ci				a1[c] = sprom->core_pwr_info[c].pa_5g[0];
410762306a36Sopenharmony_ci				b0[c] = sprom->core_pwr_info[c].pa_5g[1];
410862306a36Sopenharmony_ci				b1[c] = sprom->core_pwr_info[c].pa_5g[2];
410962306a36Sopenharmony_ci			}
411062306a36Sopenharmony_ci		} else if (freq >= 5500) {
411162306a36Sopenharmony_ci			for (c = 0; c < 2; c++) {
411262306a36Sopenharmony_ci				idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g;
411362306a36Sopenharmony_ci				target[c] = sprom->core_pwr_info[c].maxpwr_5gh;
411462306a36Sopenharmony_ci				a1[c] = sprom->core_pwr_info[c].pa_5gh[0];
411562306a36Sopenharmony_ci				b0[c] = sprom->core_pwr_info[c].pa_5gh[1];
411662306a36Sopenharmony_ci				b1[c] = sprom->core_pwr_info[c].pa_5gh[2];
411762306a36Sopenharmony_ci			}
411862306a36Sopenharmony_ci		} else {
411962306a36Sopenharmony_ci			idle[0] = nphy->pwr_ctl_info[0].idle_tssi_5g;
412062306a36Sopenharmony_ci			idle[1] = nphy->pwr_ctl_info[1].idle_tssi_5g;
412162306a36Sopenharmony_ci			target[0] = target[1] = 52;
412262306a36Sopenharmony_ci			a1[0] = a1[1] = -424;
412362306a36Sopenharmony_ci			b0[0] = b0[1] = 5612;
412462306a36Sopenharmony_ci			b1[0] = b1[1] = -1393;
412562306a36Sopenharmony_ci		}
412662306a36Sopenharmony_ci	}
412762306a36Sopenharmony_ci
412862306a36Sopenharmony_ci	ppr_max = b43_ppr_get_max(dev, &nphy->tx_pwr_max_ppr);
412962306a36Sopenharmony_ci	if (ppr_max) {
413062306a36Sopenharmony_ci		target[0] = ppr_max;
413162306a36Sopenharmony_ci		target[1] = ppr_max;
413262306a36Sopenharmony_ci	}
413362306a36Sopenharmony_ci
413462306a36Sopenharmony_ci	if (dev->phy.rev >= 3) {
413562306a36Sopenharmony_ci		if (sprom->fem.ghz2.tssipos)
413662306a36Sopenharmony_ci			b43_phy_set(dev, B43_NPHY_TXPCTL_ITSSI, 0x4000);
413762306a36Sopenharmony_ci		if (dev->phy.rev >= 7) {
413862306a36Sopenharmony_ci			for (c = 0; c < 2; c++) {
413962306a36Sopenharmony_ci				r = c ? 0x190 : 0x170;
414062306a36Sopenharmony_ci				if (b43_nphy_ipa(dev))
414162306a36Sopenharmony_ci					b43_radio_write(dev, r + 0x9, (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) ? 0xE : 0xC);
414262306a36Sopenharmony_ci			}
414362306a36Sopenharmony_ci		} else {
414462306a36Sopenharmony_ci			if (b43_nphy_ipa(dev)) {
414562306a36Sopenharmony_ci				tmp = (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ? 0xC : 0xE;
414662306a36Sopenharmony_ci				b43_radio_write(dev,
414762306a36Sopenharmony_ci					B2056_TX0 | B2056_TX_TX_SSI_MUX, tmp);
414862306a36Sopenharmony_ci				b43_radio_write(dev,
414962306a36Sopenharmony_ci					B2056_TX1 | B2056_TX_TX_SSI_MUX, tmp);
415062306a36Sopenharmony_ci			} else {
415162306a36Sopenharmony_ci				b43_radio_write(dev,
415262306a36Sopenharmony_ci					B2056_TX0 | B2056_TX_TX_SSI_MUX, 0x11);
415362306a36Sopenharmony_ci				b43_radio_write(dev,
415462306a36Sopenharmony_ci					B2056_TX1 | B2056_TX_TX_SSI_MUX, 0x11);
415562306a36Sopenharmony_ci			}
415662306a36Sopenharmony_ci		}
415762306a36Sopenharmony_ci	}
415862306a36Sopenharmony_ci
415962306a36Sopenharmony_ci	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) {
416062306a36Sopenharmony_ci		b43_maskset32(dev, B43_MMIO_MACCTL, ~0, 0x200000);
416162306a36Sopenharmony_ci		b43_read32(dev, B43_MMIO_MACCTL);
416262306a36Sopenharmony_ci		udelay(1);
416362306a36Sopenharmony_ci	}
416462306a36Sopenharmony_ci
416562306a36Sopenharmony_ci	if (phy->rev >= 19) {
416662306a36Sopenharmony_ci		/* TODO */
416762306a36Sopenharmony_ci	} else if (phy->rev >= 7) {
416862306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
416962306a36Sopenharmony_ci				~B43_NPHY_TXPCTL_CMD_INIT, 0x19);
417062306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,
417162306a36Sopenharmony_ci				~B43_NPHY_TXPCTL_INIT_PIDXI1, 0x19);
417262306a36Sopenharmony_ci	} else {
417362306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
417462306a36Sopenharmony_ci				~B43_NPHY_TXPCTL_CMD_INIT, 0x40);
417562306a36Sopenharmony_ci		if (dev->phy.rev > 1)
417662306a36Sopenharmony_ci			b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,
417762306a36Sopenharmony_ci				~B43_NPHY_TXPCTL_INIT_PIDXI1, 0x40);
417862306a36Sopenharmony_ci	}
417962306a36Sopenharmony_ci
418062306a36Sopenharmony_ci	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12)
418162306a36Sopenharmony_ci		b43_maskset32(dev, B43_MMIO_MACCTL, ~0x200000, 0);
418262306a36Sopenharmony_ci
418362306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_TXPCTL_N,
418462306a36Sopenharmony_ci		      0xF0 << B43_NPHY_TXPCTL_N_TSSID_SHIFT |
418562306a36Sopenharmony_ci		      3 << B43_NPHY_TXPCTL_N_NPTIL2_SHIFT);
418662306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_TXPCTL_ITSSI,
418762306a36Sopenharmony_ci		      idle[0] << B43_NPHY_TXPCTL_ITSSI_0_SHIFT |
418862306a36Sopenharmony_ci		      idle[1] << B43_NPHY_TXPCTL_ITSSI_1_SHIFT |
418962306a36Sopenharmony_ci		      B43_NPHY_TXPCTL_ITSSI_BINF);
419062306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_TXPCTL_TPWR,
419162306a36Sopenharmony_ci		      target[0] << B43_NPHY_TXPCTL_TPWR_0_SHIFT |
419262306a36Sopenharmony_ci		      target[1] << B43_NPHY_TXPCTL_TPWR_1_SHIFT);
419362306a36Sopenharmony_ci
419462306a36Sopenharmony_ci	for (c = 0; c < 2; c++) {
419562306a36Sopenharmony_ci		for (i = 0; i < 64; i++) {
419662306a36Sopenharmony_ci			num = 8 * (16 * b0[c] + b1[c] * i);
419762306a36Sopenharmony_ci			den = 32768 + a1[c] * i;
419862306a36Sopenharmony_ci			pwr = max((4 * num + den / 2) / den, -8);
419962306a36Sopenharmony_ci			if (dev->phy.rev < 3 && (i <= (31 - idle[c] + 1)))
420062306a36Sopenharmony_ci				pwr = max(pwr, target[c] + 1);
420162306a36Sopenharmony_ci			regval[i] = pwr;
420262306a36Sopenharmony_ci		}
420362306a36Sopenharmony_ci		b43_ntab_write_bulk(dev, B43_NTAB32(26 + c, 0), 64, regval);
420462306a36Sopenharmony_ci	}
420562306a36Sopenharmony_ci
420662306a36Sopenharmony_ci	b43_nphy_tx_prepare_adjusted_power_table(dev);
420762306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84, nphy->adj_pwr_tbl);
420862306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84, nphy->adj_pwr_tbl);
420962306a36Sopenharmony_ci
421062306a36Sopenharmony_ci	if (nphy->hang_avoid)
421162306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, false);
421262306a36Sopenharmony_ci}
421362306a36Sopenharmony_ci
421462306a36Sopenharmony_cistatic void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev)
421562306a36Sopenharmony_ci{
421662306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
421762306a36Sopenharmony_ci
421862306a36Sopenharmony_ci	const u32 *table = NULL;
421962306a36Sopenharmony_ci	u32 rfpwr_offset;
422062306a36Sopenharmony_ci	u8 pga_gain, pad_gain;
422162306a36Sopenharmony_ci	int i;
422262306a36Sopenharmony_ci	const s16 *rf_pwr_offset_table = NULL;
422362306a36Sopenharmony_ci
422462306a36Sopenharmony_ci	table = b43_nphy_get_tx_gain_table(dev);
422562306a36Sopenharmony_ci	if (!table)
422662306a36Sopenharmony_ci		return;
422762306a36Sopenharmony_ci
422862306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table);
422962306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table);
423062306a36Sopenharmony_ci
423162306a36Sopenharmony_ci	if (phy->rev < 3)
423262306a36Sopenharmony_ci		return;
423362306a36Sopenharmony_ci
423462306a36Sopenharmony_ci#if 0
423562306a36Sopenharmony_ci	nphy->gmval = (table[0] >> 16) & 0x7000;
423662306a36Sopenharmony_ci#endif
423762306a36Sopenharmony_ci
423862306a36Sopenharmony_ci	if (phy->rev >= 19) {
423962306a36Sopenharmony_ci		return;
424062306a36Sopenharmony_ci	} else if (phy->rev >= 7) {
424162306a36Sopenharmony_ci		rf_pwr_offset_table = b43_ntab_get_rf_pwr_offset_table(dev);
424262306a36Sopenharmony_ci		if (!rf_pwr_offset_table)
424362306a36Sopenharmony_ci			return;
424462306a36Sopenharmony_ci		/* TODO: Enable this once we have gains configured */
424562306a36Sopenharmony_ci		return;
424662306a36Sopenharmony_ci	}
424762306a36Sopenharmony_ci
424862306a36Sopenharmony_ci	for (i = 0; i < 128; i++) {
424962306a36Sopenharmony_ci		if (phy->rev >= 19) {
425062306a36Sopenharmony_ci			/* TODO */
425162306a36Sopenharmony_ci			return;
425262306a36Sopenharmony_ci		} else if (phy->rev >= 7) {
425362306a36Sopenharmony_ci			pga_gain = (table[i] >> 24) & 0xf;
425462306a36Sopenharmony_ci			pad_gain = (table[i] >> 19) & 0x1f;
425562306a36Sopenharmony_ci			if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
425662306a36Sopenharmony_ci				rfpwr_offset = rf_pwr_offset_table[pad_gain];
425762306a36Sopenharmony_ci			else
425862306a36Sopenharmony_ci				rfpwr_offset = rf_pwr_offset_table[pga_gain];
425962306a36Sopenharmony_ci		} else {
426062306a36Sopenharmony_ci			pga_gain = (table[i] >> 24) & 0xF;
426162306a36Sopenharmony_ci			if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
426262306a36Sopenharmony_ci				rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain];
426362306a36Sopenharmony_ci			else
426462306a36Sopenharmony_ci				rfpwr_offset = 0; /* FIXME */
426562306a36Sopenharmony_ci		}
426662306a36Sopenharmony_ci
426762306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB32(26, 576 + i), rfpwr_offset);
426862306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB32(27, 576 + i), rfpwr_offset);
426962306a36Sopenharmony_ci	}
427062306a36Sopenharmony_ci}
427162306a36Sopenharmony_ci
427262306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */
427362306a36Sopenharmony_cistatic void b43_nphy_pa_override(struct b43_wldev *dev, bool enable)
427462306a36Sopenharmony_ci{
427562306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
427662306a36Sopenharmony_ci	enum nl80211_band band;
427762306a36Sopenharmony_ci	u16 tmp;
427862306a36Sopenharmony_ci
427962306a36Sopenharmony_ci	if (!enable) {
428062306a36Sopenharmony_ci		nphy->rfctrl_intc1_save = b43_phy_read(dev,
428162306a36Sopenharmony_ci						       B43_NPHY_RFCTL_INTC1);
428262306a36Sopenharmony_ci		nphy->rfctrl_intc2_save = b43_phy_read(dev,
428362306a36Sopenharmony_ci						       B43_NPHY_RFCTL_INTC2);
428462306a36Sopenharmony_ci		band = b43_current_band(dev->wl);
428562306a36Sopenharmony_ci		if (dev->phy.rev >= 7) {
428662306a36Sopenharmony_ci			tmp = 0x1480;
428762306a36Sopenharmony_ci		} else if (dev->phy.rev >= 3) {
428862306a36Sopenharmony_ci			if (band == NL80211_BAND_5GHZ)
428962306a36Sopenharmony_ci				tmp = 0x600;
429062306a36Sopenharmony_ci			else
429162306a36Sopenharmony_ci				tmp = 0x480;
429262306a36Sopenharmony_ci		} else {
429362306a36Sopenharmony_ci			if (band == NL80211_BAND_5GHZ)
429462306a36Sopenharmony_ci				tmp = 0x180;
429562306a36Sopenharmony_ci			else
429662306a36Sopenharmony_ci				tmp = 0x120;
429762306a36Sopenharmony_ci		}
429862306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp);
429962306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp);
430062306a36Sopenharmony_ci	} else {
430162306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1,
430262306a36Sopenharmony_ci				nphy->rfctrl_intc1_save);
430362306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2,
430462306a36Sopenharmony_ci				nphy->rfctrl_intc2_save);
430562306a36Sopenharmony_ci	}
430662306a36Sopenharmony_ci}
430762306a36Sopenharmony_ci
430862306a36Sopenharmony_ci/*
430962306a36Sopenharmony_ci * TX low-pass filter bandwidth setup
431062306a36Sopenharmony_ci * https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw
431162306a36Sopenharmony_ci */
431262306a36Sopenharmony_cistatic void b43_nphy_tx_lpf_bw(struct b43_wldev *dev)
431362306a36Sopenharmony_ci{
431462306a36Sopenharmony_ci	u16 tmp;
431562306a36Sopenharmony_ci
431662306a36Sopenharmony_ci	if (dev->phy.rev < 3 || dev->phy.rev >= 7)
431762306a36Sopenharmony_ci		return;
431862306a36Sopenharmony_ci
431962306a36Sopenharmony_ci	if (b43_nphy_ipa(dev))
432062306a36Sopenharmony_ci		tmp = b43_is_40mhz(dev) ? 5 : 4;
432162306a36Sopenharmony_ci	else
432262306a36Sopenharmony_ci		tmp = b43_is_40mhz(dev) ? 3 : 1;
432362306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2,
432462306a36Sopenharmony_ci		      (tmp << 9) | (tmp << 6) | (tmp << 3) | tmp);
432562306a36Sopenharmony_ci
432662306a36Sopenharmony_ci	if (b43_nphy_ipa(dev)) {
432762306a36Sopenharmony_ci		tmp = b43_is_40mhz(dev) ? 4 : 1;
432862306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S2,
432962306a36Sopenharmony_ci			      (tmp << 9) | (tmp << 6) | (tmp << 3) | tmp);
433062306a36Sopenharmony_ci	}
433162306a36Sopenharmony_ci}
433262306a36Sopenharmony_ci
433362306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */
433462306a36Sopenharmony_cistatic void b43_nphy_rx_iq_est(struct b43_wldev *dev, struct nphy_iq_est *est,
433562306a36Sopenharmony_ci				u16 samps, u8 time, bool wait)
433662306a36Sopenharmony_ci{
433762306a36Sopenharmony_ci	int i;
433862306a36Sopenharmony_ci	u16 tmp;
433962306a36Sopenharmony_ci
434062306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_IQEST_SAMCNT, samps);
434162306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_IQEST_WT, ~B43_NPHY_IQEST_WT_VAL, time);
434262306a36Sopenharmony_ci	if (wait)
434362306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_MODE);
434462306a36Sopenharmony_ci	else
434562306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_IQEST_CMD, ~B43_NPHY_IQEST_CMD_MODE);
434662306a36Sopenharmony_ci
434762306a36Sopenharmony_ci	b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_START);
434862306a36Sopenharmony_ci
434962306a36Sopenharmony_ci	for (i = 1000; i; i--) {
435062306a36Sopenharmony_ci		tmp = b43_phy_read(dev, B43_NPHY_IQEST_CMD);
435162306a36Sopenharmony_ci		if (!(tmp & B43_NPHY_IQEST_CMD_START)) {
435262306a36Sopenharmony_ci			est->i0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI0) << 16) |
435362306a36Sopenharmony_ci					b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO0);
435462306a36Sopenharmony_ci			est->q0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI0) << 16) |
435562306a36Sopenharmony_ci					b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO0);
435662306a36Sopenharmony_ci			est->iq0_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI0) << 16) |
435762306a36Sopenharmony_ci					b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO0);
435862306a36Sopenharmony_ci
435962306a36Sopenharmony_ci			est->i1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI1) << 16) |
436062306a36Sopenharmony_ci					b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO1);
436162306a36Sopenharmony_ci			est->q1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI1) << 16) |
436262306a36Sopenharmony_ci					b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO1);
436362306a36Sopenharmony_ci			est->iq1_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI1) << 16) |
436462306a36Sopenharmony_ci					b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO1);
436562306a36Sopenharmony_ci			return;
436662306a36Sopenharmony_ci		}
436762306a36Sopenharmony_ci		udelay(10);
436862306a36Sopenharmony_ci	}
436962306a36Sopenharmony_ci	memset(est, 0, sizeof(*est));
437062306a36Sopenharmony_ci}
437162306a36Sopenharmony_ci
437262306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */
437362306a36Sopenharmony_cistatic void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write,
437462306a36Sopenharmony_ci					struct b43_phy_n_iq_comp *pcomp)
437562306a36Sopenharmony_ci{
437662306a36Sopenharmony_ci	if (write) {
437762306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPA0, pcomp->a0);
437862306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPB0, pcomp->b0);
437962306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPA1, pcomp->a1);
438062306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPB1, pcomp->b1);
438162306a36Sopenharmony_ci	} else {
438262306a36Sopenharmony_ci		pcomp->a0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPA0);
438362306a36Sopenharmony_ci		pcomp->b0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPB0);
438462306a36Sopenharmony_ci		pcomp->a1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPA1);
438562306a36Sopenharmony_ci		pcomp->b1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPB1);
438662306a36Sopenharmony_ci	}
438762306a36Sopenharmony_ci}
438862306a36Sopenharmony_ci
438962306a36Sopenharmony_ci#if 0
439062306a36Sopenharmony_ci/* Ready but not used anywhere */
439162306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */
439262306a36Sopenharmony_cistatic void b43_nphy_rx_cal_phy_cleanup(struct b43_wldev *dev, u8 core)
439362306a36Sopenharmony_ci{
439462306a36Sopenharmony_ci	u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
439562306a36Sopenharmony_ci
439662306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RFSEQCA, regs[0]);
439762306a36Sopenharmony_ci	if (core == 0) {
439862306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[1]);
439962306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]);
440062306a36Sopenharmony_ci	} else {
440162306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]);
440262306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]);
440362306a36Sopenharmony_ci	}
440462306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[3]);
440562306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[4]);
440662306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, regs[5]);
440762306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, regs[6]);
440862306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, regs[7]);
440962306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RFCTL_OVER, regs[8]);
441062306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]);
441162306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]);
441262306a36Sopenharmony_ci}
441362306a36Sopenharmony_ci
441462306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhySetup */
441562306a36Sopenharmony_cistatic void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core)
441662306a36Sopenharmony_ci{
441762306a36Sopenharmony_ci	u8 rxval, txval;
441862306a36Sopenharmony_ci	u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
441962306a36Sopenharmony_ci
442062306a36Sopenharmony_ci	regs[0] = b43_phy_read(dev, B43_NPHY_RFSEQCA);
442162306a36Sopenharmony_ci	if (core == 0) {
442262306a36Sopenharmony_ci		regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
442362306a36Sopenharmony_ci		regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
442462306a36Sopenharmony_ci	} else {
442562306a36Sopenharmony_ci		regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
442662306a36Sopenharmony_ci		regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
442762306a36Sopenharmony_ci	}
442862306a36Sopenharmony_ci	regs[3] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
442962306a36Sopenharmony_ci	regs[4] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
443062306a36Sopenharmony_ci	regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1);
443162306a36Sopenharmony_ci	regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2);
443262306a36Sopenharmony_ci	regs[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S1);
443362306a36Sopenharmony_ci	regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER);
443462306a36Sopenharmony_ci	regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);
443562306a36Sopenharmony_ci	regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
443662306a36Sopenharmony_ci
443762306a36Sopenharmony_ci	b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
443862306a36Sopenharmony_ci	b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
443962306a36Sopenharmony_ci
444062306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
444162306a36Sopenharmony_ci			~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF,
444262306a36Sopenharmony_ci			((1 - core) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));
444362306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN,
444462306a36Sopenharmony_ci			((1 - core) << B43_NPHY_RFSEQCA_TXEN_SHIFT));
444562306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN,
444662306a36Sopenharmony_ci			(core << B43_NPHY_RFSEQCA_RXEN_SHIFT));
444762306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXDIS,
444862306a36Sopenharmony_ci			(core << B43_NPHY_RFSEQCA_TXDIS_SHIFT));
444962306a36Sopenharmony_ci
445062306a36Sopenharmony_ci	if (core == 0) {
445162306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x0007);
445262306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0007);
445362306a36Sopenharmony_ci	} else {
445462306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x0007);
445562306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0007);
445662306a36Sopenharmony_ci	}
445762306a36Sopenharmony_ci
445862306a36Sopenharmony_ci	b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA, 0, 3);
445962306a36Sopenharmony_ci	b43_nphy_rf_ctl_override(dev, 8, 0, 3, false);
446062306a36Sopenharmony_ci	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
446162306a36Sopenharmony_ci
446262306a36Sopenharmony_ci	if (core == 0) {
446362306a36Sopenharmony_ci		rxval = 1;
446462306a36Sopenharmony_ci		txval = 8;
446562306a36Sopenharmony_ci	} else {
446662306a36Sopenharmony_ci		rxval = 4;
446762306a36Sopenharmony_ci		txval = 2;
446862306a36Sopenharmony_ci	}
446962306a36Sopenharmony_ci	b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, rxval,
447062306a36Sopenharmony_ci				      core + 1);
447162306a36Sopenharmony_ci	b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, txval,
447262306a36Sopenharmony_ci				      2 - core);
447362306a36Sopenharmony_ci}
447462306a36Sopenharmony_ci#endif
447562306a36Sopenharmony_ci
447662306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */
447762306a36Sopenharmony_cistatic void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask)
447862306a36Sopenharmony_ci{
447962306a36Sopenharmony_ci	int i;
448062306a36Sopenharmony_ci	s32 iq;
448162306a36Sopenharmony_ci	u32 ii;
448262306a36Sopenharmony_ci	u32 qq;
448362306a36Sopenharmony_ci	int iq_nbits, qq_nbits;
448462306a36Sopenharmony_ci	int arsh, brsh;
448562306a36Sopenharmony_ci	u16 tmp, a, b;
448662306a36Sopenharmony_ci
448762306a36Sopenharmony_ci	struct nphy_iq_est est;
448862306a36Sopenharmony_ci	struct b43_phy_n_iq_comp old;
448962306a36Sopenharmony_ci	struct b43_phy_n_iq_comp new = { };
449062306a36Sopenharmony_ci	bool error = false;
449162306a36Sopenharmony_ci
449262306a36Sopenharmony_ci	if (mask == 0)
449362306a36Sopenharmony_ci		return;
449462306a36Sopenharmony_ci
449562306a36Sopenharmony_ci	b43_nphy_rx_iq_coeffs(dev, false, &old);
449662306a36Sopenharmony_ci	b43_nphy_rx_iq_coeffs(dev, true, &new);
449762306a36Sopenharmony_ci	b43_nphy_rx_iq_est(dev, &est, 0x4000, 32, false);
449862306a36Sopenharmony_ci	new = old;
449962306a36Sopenharmony_ci
450062306a36Sopenharmony_ci	for (i = 0; i < 2; i++) {
450162306a36Sopenharmony_ci		if (i == 0 && (mask & 1)) {
450262306a36Sopenharmony_ci			iq = est.iq0_prod;
450362306a36Sopenharmony_ci			ii = est.i0_pwr;
450462306a36Sopenharmony_ci			qq = est.q0_pwr;
450562306a36Sopenharmony_ci		} else if (i == 1 && (mask & 2)) {
450662306a36Sopenharmony_ci			iq = est.iq1_prod;
450762306a36Sopenharmony_ci			ii = est.i1_pwr;
450862306a36Sopenharmony_ci			qq = est.q1_pwr;
450962306a36Sopenharmony_ci		} else {
451062306a36Sopenharmony_ci			continue;
451162306a36Sopenharmony_ci		}
451262306a36Sopenharmony_ci
451362306a36Sopenharmony_ci		if (ii + qq < 2) {
451462306a36Sopenharmony_ci			error = true;
451562306a36Sopenharmony_ci			break;
451662306a36Sopenharmony_ci		}
451762306a36Sopenharmony_ci
451862306a36Sopenharmony_ci		iq_nbits = fls(abs(iq));
451962306a36Sopenharmony_ci		qq_nbits = fls(qq);
452062306a36Sopenharmony_ci
452162306a36Sopenharmony_ci		arsh = iq_nbits - 20;
452262306a36Sopenharmony_ci		if (arsh >= 0) {
452362306a36Sopenharmony_ci			a = -((iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
452462306a36Sopenharmony_ci			tmp = ii >> arsh;
452562306a36Sopenharmony_ci		} else {
452662306a36Sopenharmony_ci			a = -((iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
452762306a36Sopenharmony_ci			tmp = ii << -arsh;
452862306a36Sopenharmony_ci		}
452962306a36Sopenharmony_ci		if (tmp == 0) {
453062306a36Sopenharmony_ci			error = true;
453162306a36Sopenharmony_ci			break;
453262306a36Sopenharmony_ci		}
453362306a36Sopenharmony_ci		a /= tmp;
453462306a36Sopenharmony_ci
453562306a36Sopenharmony_ci		brsh = qq_nbits - 11;
453662306a36Sopenharmony_ci		if (brsh >= 0) {
453762306a36Sopenharmony_ci			b = (qq << (31 - qq_nbits));
453862306a36Sopenharmony_ci			tmp = ii >> brsh;
453962306a36Sopenharmony_ci		} else {
454062306a36Sopenharmony_ci			b = (qq << (31 - qq_nbits));
454162306a36Sopenharmony_ci			tmp = ii << -brsh;
454262306a36Sopenharmony_ci		}
454362306a36Sopenharmony_ci		if (tmp == 0) {
454462306a36Sopenharmony_ci			error = true;
454562306a36Sopenharmony_ci			break;
454662306a36Sopenharmony_ci		}
454762306a36Sopenharmony_ci		b = int_sqrt(b / tmp - a * a) - (1 << 10);
454862306a36Sopenharmony_ci
454962306a36Sopenharmony_ci		if (i == 0 && (mask & 0x1)) {
455062306a36Sopenharmony_ci			if (dev->phy.rev >= 3) {
455162306a36Sopenharmony_ci				new.a0 = a & 0x3FF;
455262306a36Sopenharmony_ci				new.b0 = b & 0x3FF;
455362306a36Sopenharmony_ci			} else {
455462306a36Sopenharmony_ci				new.a0 = b & 0x3FF;
455562306a36Sopenharmony_ci				new.b0 = a & 0x3FF;
455662306a36Sopenharmony_ci			}
455762306a36Sopenharmony_ci		} else if (i == 1 && (mask & 0x2)) {
455862306a36Sopenharmony_ci			if (dev->phy.rev >= 3) {
455962306a36Sopenharmony_ci				new.a1 = a & 0x3FF;
456062306a36Sopenharmony_ci				new.b1 = b & 0x3FF;
456162306a36Sopenharmony_ci			} else {
456262306a36Sopenharmony_ci				new.a1 = b & 0x3FF;
456362306a36Sopenharmony_ci				new.b1 = a & 0x3FF;
456462306a36Sopenharmony_ci			}
456562306a36Sopenharmony_ci		}
456662306a36Sopenharmony_ci	}
456762306a36Sopenharmony_ci
456862306a36Sopenharmony_ci	if (error)
456962306a36Sopenharmony_ci		new = old;
457062306a36Sopenharmony_ci
457162306a36Sopenharmony_ci	b43_nphy_rx_iq_coeffs(dev, true, &new);
457262306a36Sopenharmony_ci}
457362306a36Sopenharmony_ci
457462306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */
457562306a36Sopenharmony_cistatic void b43_nphy_tx_iq_workaround(struct b43_wldev *dev)
457662306a36Sopenharmony_ci{
457762306a36Sopenharmony_ci	u16 array[4];
457862306a36Sopenharmony_ci	b43_ntab_read_bulk(dev, B43_NTAB16(0xF, 0x50), 4, array);
457962306a36Sopenharmony_ci
458062306a36Sopenharmony_ci	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW0, array[0]);
458162306a36Sopenharmony_ci	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW1, array[1]);
458262306a36Sopenharmony_ci	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW2, array[2]);
458362306a36Sopenharmony_ci	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW3, array[3]);
458462306a36Sopenharmony_ci}
458562306a36Sopenharmony_ci
458662306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SpurWar */
458762306a36Sopenharmony_cistatic void b43_nphy_spur_workaround(struct b43_wldev *dev)
458862306a36Sopenharmony_ci{
458962306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
459062306a36Sopenharmony_ci
459162306a36Sopenharmony_ci	B43_WARN_ON(dev->phy.rev < 3);
459262306a36Sopenharmony_ci
459362306a36Sopenharmony_ci	if (nphy->hang_avoid)
459462306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, 1);
459562306a36Sopenharmony_ci
459662306a36Sopenharmony_ci	if (nphy->hang_avoid)
459762306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, 0);
459862306a36Sopenharmony_ci}
459962306a36Sopenharmony_ci
460062306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */
460162306a36Sopenharmony_cistatic void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev)
460262306a36Sopenharmony_ci{
460362306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
460462306a36Sopenharmony_ci	int i, j;
460562306a36Sopenharmony_ci	u32 tmp;
460662306a36Sopenharmony_ci	u32 cur_real, cur_imag, real_part, imag_part;
460762306a36Sopenharmony_ci
460862306a36Sopenharmony_ci	u16 buffer[7];
460962306a36Sopenharmony_ci
461062306a36Sopenharmony_ci	if (nphy->hang_avoid)
461162306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, true);
461262306a36Sopenharmony_ci
461362306a36Sopenharmony_ci	b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
461462306a36Sopenharmony_ci
461562306a36Sopenharmony_ci	for (i = 0; i < 2; i++) {
461662306a36Sopenharmony_ci		tmp = ((buffer[i * 2] & 0x3FF) << 10) |
461762306a36Sopenharmony_ci			(buffer[i * 2 + 1] & 0x3FF);
461862306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
461962306a36Sopenharmony_ci				(((i + 26) << 10) | 320));
462062306a36Sopenharmony_ci		for (j = 0; j < 128; j++) {
462162306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_TABLE_DATAHI,
462262306a36Sopenharmony_ci					((tmp >> 16) & 0xFFFF));
462362306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
462462306a36Sopenharmony_ci					(tmp & 0xFFFF));
462562306a36Sopenharmony_ci		}
462662306a36Sopenharmony_ci	}
462762306a36Sopenharmony_ci
462862306a36Sopenharmony_ci	for (i = 0; i < 2; i++) {
462962306a36Sopenharmony_ci		tmp = buffer[5 + i];
463062306a36Sopenharmony_ci		real_part = (tmp >> 8) & 0xFF;
463162306a36Sopenharmony_ci		imag_part = (tmp & 0xFF);
463262306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
463362306a36Sopenharmony_ci				(((i + 26) << 10) | 448));
463462306a36Sopenharmony_ci
463562306a36Sopenharmony_ci		if (dev->phy.rev >= 3) {
463662306a36Sopenharmony_ci			cur_real = real_part;
463762306a36Sopenharmony_ci			cur_imag = imag_part;
463862306a36Sopenharmony_ci			tmp = ((cur_real & 0xFF) << 8) | (cur_imag & 0xFF);
463962306a36Sopenharmony_ci		}
464062306a36Sopenharmony_ci
464162306a36Sopenharmony_ci		for (j = 0; j < 128; j++) {
464262306a36Sopenharmony_ci			if (dev->phy.rev < 3) {
464362306a36Sopenharmony_ci				cur_real = (real_part * loscale[j] + 128) >> 8;
464462306a36Sopenharmony_ci				cur_imag = (imag_part * loscale[j] + 128) >> 8;
464562306a36Sopenharmony_ci				tmp = ((cur_real & 0xFF) << 8) |
464662306a36Sopenharmony_ci					(cur_imag & 0xFF);
464762306a36Sopenharmony_ci			}
464862306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_TABLE_DATAHI,
464962306a36Sopenharmony_ci					((tmp >> 16) & 0xFFFF));
465062306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
465162306a36Sopenharmony_ci					(tmp & 0xFFFF));
465262306a36Sopenharmony_ci		}
465362306a36Sopenharmony_ci	}
465462306a36Sopenharmony_ci
465562306a36Sopenharmony_ci	if (dev->phy.rev >= 3) {
465662306a36Sopenharmony_ci		b43_shm_write16(dev, B43_SHM_SHARED,
465762306a36Sopenharmony_ci				B43_SHM_SH_NPHY_TXPWR_INDX0, 0xFFFF);
465862306a36Sopenharmony_ci		b43_shm_write16(dev, B43_SHM_SHARED,
465962306a36Sopenharmony_ci				B43_SHM_SH_NPHY_TXPWR_INDX1, 0xFFFF);
466062306a36Sopenharmony_ci	}
466162306a36Sopenharmony_ci
466262306a36Sopenharmony_ci	if (nphy->hang_avoid)
466362306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, false);
466462306a36Sopenharmony_ci}
466562306a36Sopenharmony_ci
466662306a36Sopenharmony_ci/*
466762306a36Sopenharmony_ci * Restore RSSI Calibration
466862306a36Sopenharmony_ci * https://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal
466962306a36Sopenharmony_ci */
467062306a36Sopenharmony_cistatic void b43_nphy_restore_rssi_cal(struct b43_wldev *dev)
467162306a36Sopenharmony_ci{
467262306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
467362306a36Sopenharmony_ci
467462306a36Sopenharmony_ci	u16 *rssical_radio_regs = NULL;
467562306a36Sopenharmony_ci	u16 *rssical_phy_regs = NULL;
467662306a36Sopenharmony_ci
467762306a36Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
467862306a36Sopenharmony_ci		if (!nphy->rssical_chanspec_2G.center_freq)
467962306a36Sopenharmony_ci			return;
468062306a36Sopenharmony_ci		rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G;
468162306a36Sopenharmony_ci		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G;
468262306a36Sopenharmony_ci	} else {
468362306a36Sopenharmony_ci		if (!nphy->rssical_chanspec_5G.center_freq)
468462306a36Sopenharmony_ci			return;
468562306a36Sopenharmony_ci		rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G;
468662306a36Sopenharmony_ci		rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
468762306a36Sopenharmony_ci	}
468862306a36Sopenharmony_ci
468962306a36Sopenharmony_ci	if (dev->phy.rev >= 19) {
469062306a36Sopenharmony_ci		/* TODO */
469162306a36Sopenharmony_ci	} else if (dev->phy.rev >= 7) {
469262306a36Sopenharmony_ci		b43_radio_maskset(dev, R2057_NB_MASTER_CORE0, ~R2057_VCM_MASK,
469362306a36Sopenharmony_ci				  rssical_radio_regs[0]);
469462306a36Sopenharmony_ci		b43_radio_maskset(dev, R2057_NB_MASTER_CORE1, ~R2057_VCM_MASK,
469562306a36Sopenharmony_ci				  rssical_radio_regs[1]);
469662306a36Sopenharmony_ci	} else {
469762306a36Sopenharmony_ci		b43_radio_maskset(dev, B2056_RX0 | B2056_RX_RSSI_MISC, 0xE3,
469862306a36Sopenharmony_ci				  rssical_radio_regs[0]);
469962306a36Sopenharmony_ci		b43_radio_maskset(dev, B2056_RX1 | B2056_RX_RSSI_MISC, 0xE3,
470062306a36Sopenharmony_ci				  rssical_radio_regs[1]);
470162306a36Sopenharmony_ci	}
470262306a36Sopenharmony_ci
470362306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, rssical_phy_regs[0]);
470462306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, rssical_phy_regs[1]);
470562306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, rssical_phy_regs[2]);
470662306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, rssical_phy_regs[3]);
470762306a36Sopenharmony_ci
470862306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, rssical_phy_regs[4]);
470962306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, rssical_phy_regs[5]);
471062306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, rssical_phy_regs[6]);
471162306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, rssical_phy_regs[7]);
471262306a36Sopenharmony_ci
471362306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, rssical_phy_regs[8]);
471462306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, rssical_phy_regs[9]);
471562306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, rssical_phy_regs[10]);
471662306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]);
471762306a36Sopenharmony_ci}
471862306a36Sopenharmony_ci
471962306a36Sopenharmony_cistatic void b43_nphy_tx_cal_radio_setup_rev19(struct b43_wldev *dev)
472062306a36Sopenharmony_ci{
472162306a36Sopenharmony_ci	/* TODO */
472262306a36Sopenharmony_ci}
472362306a36Sopenharmony_ci
472462306a36Sopenharmony_cistatic void b43_nphy_tx_cal_radio_setup_rev7(struct b43_wldev *dev)
472562306a36Sopenharmony_ci{
472662306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
472762306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
472862306a36Sopenharmony_ci	u16 *save = nphy->tx_rx_cal_radio_saveregs;
472962306a36Sopenharmony_ci	int core, off;
473062306a36Sopenharmony_ci	u16 r, tmp;
473162306a36Sopenharmony_ci
473262306a36Sopenharmony_ci	for (core = 0; core < 2; core++) {
473362306a36Sopenharmony_ci		r = core ? 0x20 : 0;
473462306a36Sopenharmony_ci		off = core * 11;
473562306a36Sopenharmony_ci
473662306a36Sopenharmony_ci		save[off + 0] = b43_radio_read(dev, r + R2057_TX0_TX_SSI_MASTER);
473762306a36Sopenharmony_ci		save[off + 1] = b43_radio_read(dev, r + R2057_TX0_IQCAL_VCM_HG);
473862306a36Sopenharmony_ci		save[off + 2] = b43_radio_read(dev, r + R2057_TX0_IQCAL_IDAC);
473962306a36Sopenharmony_ci		save[off + 3] = b43_radio_read(dev, r + R2057_TX0_TSSI_VCM);
474062306a36Sopenharmony_ci		save[off + 4] = 0;
474162306a36Sopenharmony_ci		save[off + 5] = b43_radio_read(dev, r + R2057_TX0_TX_SSI_MUX);
474262306a36Sopenharmony_ci		if (phy->radio_rev != 5)
474362306a36Sopenharmony_ci			save[off + 6] = b43_radio_read(dev, r + R2057_TX0_TSSIA);
474462306a36Sopenharmony_ci		save[off + 7] = b43_radio_read(dev, r + R2057_TX0_TSSIG);
474562306a36Sopenharmony_ci		save[off + 8] = b43_radio_read(dev, r + R2057_TX0_TSSI_MISC1);
474662306a36Sopenharmony_ci
474762306a36Sopenharmony_ci		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
474862306a36Sopenharmony_ci			b43_radio_write(dev, r + R2057_TX0_TX_SSI_MASTER, 0xA);
474962306a36Sopenharmony_ci			b43_radio_write(dev, r + R2057_TX0_IQCAL_VCM_HG, 0x43);
475062306a36Sopenharmony_ci			b43_radio_write(dev, r + R2057_TX0_IQCAL_IDAC, 0x55);
475162306a36Sopenharmony_ci			b43_radio_write(dev, r + R2057_TX0_TSSI_VCM, 0);
475262306a36Sopenharmony_ci			b43_radio_write(dev, r + R2057_TX0_TSSIG, 0);
475362306a36Sopenharmony_ci			if (nphy->use_int_tx_iq_lo_cal) {
475462306a36Sopenharmony_ci				b43_radio_write(dev, r + R2057_TX0_TX_SSI_MUX, 0x4);
475562306a36Sopenharmony_ci				tmp = true ? 0x31 : 0x21; /* TODO */
475662306a36Sopenharmony_ci				b43_radio_write(dev, r + R2057_TX0_TSSIA, tmp);
475762306a36Sopenharmony_ci			}
475862306a36Sopenharmony_ci			b43_radio_write(dev, r + R2057_TX0_TSSI_MISC1, 0x00);
475962306a36Sopenharmony_ci		} else {
476062306a36Sopenharmony_ci			b43_radio_write(dev, r + R2057_TX0_TX_SSI_MASTER, 0x6);
476162306a36Sopenharmony_ci			b43_radio_write(dev, r + R2057_TX0_IQCAL_VCM_HG, 0x43);
476262306a36Sopenharmony_ci			b43_radio_write(dev, r + R2057_TX0_IQCAL_IDAC, 0x55);
476362306a36Sopenharmony_ci			b43_radio_write(dev, r + R2057_TX0_TSSI_VCM, 0);
476462306a36Sopenharmony_ci
476562306a36Sopenharmony_ci			if (phy->radio_rev != 5)
476662306a36Sopenharmony_ci				b43_radio_write(dev, r + R2057_TX0_TSSIA, 0);
476762306a36Sopenharmony_ci			if (nphy->use_int_tx_iq_lo_cal) {
476862306a36Sopenharmony_ci				b43_radio_write(dev, r + R2057_TX0_TX_SSI_MUX, 0x6);
476962306a36Sopenharmony_ci				tmp = true ? 0x31 : 0x21; /* TODO */
477062306a36Sopenharmony_ci				b43_radio_write(dev, r + R2057_TX0_TSSIG, tmp);
477162306a36Sopenharmony_ci			}
477262306a36Sopenharmony_ci			b43_radio_write(dev, r + R2057_TX0_TSSI_MISC1, 0);
477362306a36Sopenharmony_ci		}
477462306a36Sopenharmony_ci	}
477562306a36Sopenharmony_ci}
477662306a36Sopenharmony_ci
477762306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */
477862306a36Sopenharmony_cistatic void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev)
477962306a36Sopenharmony_ci{
478062306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
478162306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
478262306a36Sopenharmony_ci	u16 *save = nphy->tx_rx_cal_radio_saveregs;
478362306a36Sopenharmony_ci	u16 tmp;
478462306a36Sopenharmony_ci	u8 offset, i;
478562306a36Sopenharmony_ci
478662306a36Sopenharmony_ci	if (phy->rev >= 19) {
478762306a36Sopenharmony_ci		b43_nphy_tx_cal_radio_setup_rev19(dev);
478862306a36Sopenharmony_ci	} else if (phy->rev >= 7) {
478962306a36Sopenharmony_ci		b43_nphy_tx_cal_radio_setup_rev7(dev);
479062306a36Sopenharmony_ci	} else if (phy->rev >= 3) {
479162306a36Sopenharmony_ci	    for (i = 0; i < 2; i++) {
479262306a36Sopenharmony_ci		tmp = (i == 0) ? 0x2000 : 0x3000;
479362306a36Sopenharmony_ci		offset = i * 11;
479462306a36Sopenharmony_ci
479562306a36Sopenharmony_ci		save[offset + 0] = b43_radio_read(dev, B2055_CAL_RVARCTL);
479662306a36Sopenharmony_ci		save[offset + 1] = b43_radio_read(dev, B2055_CAL_LPOCTL);
479762306a36Sopenharmony_ci		save[offset + 2] = b43_radio_read(dev, B2055_CAL_TS);
479862306a36Sopenharmony_ci		save[offset + 3] = b43_radio_read(dev, B2055_CAL_RCCALRTS);
479962306a36Sopenharmony_ci		save[offset + 4] = b43_radio_read(dev, B2055_CAL_RCALRTS);
480062306a36Sopenharmony_ci		save[offset + 5] = b43_radio_read(dev, B2055_PADDRV);
480162306a36Sopenharmony_ci		save[offset + 6] = b43_radio_read(dev, B2055_XOCTL1);
480262306a36Sopenharmony_ci		save[offset + 7] = b43_radio_read(dev, B2055_XOCTL2);
480362306a36Sopenharmony_ci		save[offset + 8] = b43_radio_read(dev, B2055_XOREGUL);
480462306a36Sopenharmony_ci		save[offset + 9] = b43_radio_read(dev, B2055_XOMISC);
480562306a36Sopenharmony_ci		save[offset + 10] = b43_radio_read(dev, B2055_PLL_LFC1);
480662306a36Sopenharmony_ci
480762306a36Sopenharmony_ci		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
480862306a36Sopenharmony_ci			b43_radio_write(dev, tmp | B2055_CAL_RVARCTL, 0x0A);
480962306a36Sopenharmony_ci			b43_radio_write(dev, tmp | B2055_CAL_LPOCTL, 0x40);
481062306a36Sopenharmony_ci			b43_radio_write(dev, tmp | B2055_CAL_TS, 0x55);
481162306a36Sopenharmony_ci			b43_radio_write(dev, tmp | B2055_CAL_RCCALRTS, 0);
481262306a36Sopenharmony_ci			b43_radio_write(dev, tmp | B2055_CAL_RCALRTS, 0);
481362306a36Sopenharmony_ci			if (nphy->ipa5g_on) {
481462306a36Sopenharmony_ci				b43_radio_write(dev, tmp | B2055_PADDRV, 4);
481562306a36Sopenharmony_ci				b43_radio_write(dev, tmp | B2055_XOCTL1, 1);
481662306a36Sopenharmony_ci			} else {
481762306a36Sopenharmony_ci				b43_radio_write(dev, tmp | B2055_PADDRV, 0);
481862306a36Sopenharmony_ci				b43_radio_write(dev, tmp | B2055_XOCTL1, 0x2F);
481962306a36Sopenharmony_ci			}
482062306a36Sopenharmony_ci			b43_radio_write(dev, tmp | B2055_XOCTL2, 0);
482162306a36Sopenharmony_ci		} else {
482262306a36Sopenharmony_ci			b43_radio_write(dev, tmp | B2055_CAL_RVARCTL, 0x06);
482362306a36Sopenharmony_ci			b43_radio_write(dev, tmp | B2055_CAL_LPOCTL, 0x40);
482462306a36Sopenharmony_ci			b43_radio_write(dev, tmp | B2055_CAL_TS, 0x55);
482562306a36Sopenharmony_ci			b43_radio_write(dev, tmp | B2055_CAL_RCCALRTS, 0);
482662306a36Sopenharmony_ci			b43_radio_write(dev, tmp | B2055_CAL_RCALRTS, 0);
482762306a36Sopenharmony_ci			b43_radio_write(dev, tmp | B2055_XOCTL1, 0);
482862306a36Sopenharmony_ci			if (nphy->ipa2g_on) {
482962306a36Sopenharmony_ci				b43_radio_write(dev, tmp | B2055_PADDRV, 6);
483062306a36Sopenharmony_ci				b43_radio_write(dev, tmp | B2055_XOCTL2,
483162306a36Sopenharmony_ci					(dev->phy.rev < 5) ? 0x11 : 0x01);
483262306a36Sopenharmony_ci			} else {
483362306a36Sopenharmony_ci				b43_radio_write(dev, tmp | B2055_PADDRV, 0);
483462306a36Sopenharmony_ci				b43_radio_write(dev, tmp | B2055_XOCTL2, 0);
483562306a36Sopenharmony_ci			}
483662306a36Sopenharmony_ci		}
483762306a36Sopenharmony_ci		b43_radio_write(dev, tmp | B2055_XOREGUL, 0);
483862306a36Sopenharmony_ci		b43_radio_write(dev, tmp | B2055_XOMISC, 0);
483962306a36Sopenharmony_ci		b43_radio_write(dev, tmp | B2055_PLL_LFC1, 0);
484062306a36Sopenharmony_ci	    }
484162306a36Sopenharmony_ci	} else {
484262306a36Sopenharmony_ci		save[0] = b43_radio_read(dev, B2055_C1_TX_RF_IQCAL1);
484362306a36Sopenharmony_ci		b43_radio_write(dev, B2055_C1_TX_RF_IQCAL1, 0x29);
484462306a36Sopenharmony_ci
484562306a36Sopenharmony_ci		save[1] = b43_radio_read(dev, B2055_C1_TX_RF_IQCAL2);
484662306a36Sopenharmony_ci		b43_radio_write(dev, B2055_C1_TX_RF_IQCAL2, 0x54);
484762306a36Sopenharmony_ci
484862306a36Sopenharmony_ci		save[2] = b43_radio_read(dev, B2055_C2_TX_RF_IQCAL1);
484962306a36Sopenharmony_ci		b43_radio_write(dev, B2055_C2_TX_RF_IQCAL1, 0x29);
485062306a36Sopenharmony_ci
485162306a36Sopenharmony_ci		save[3] = b43_radio_read(dev, B2055_C2_TX_RF_IQCAL2);
485262306a36Sopenharmony_ci		b43_radio_write(dev, B2055_C2_TX_RF_IQCAL2, 0x54);
485362306a36Sopenharmony_ci
485462306a36Sopenharmony_ci		save[3] = b43_radio_read(dev, B2055_C1_PWRDET_RXTX);
485562306a36Sopenharmony_ci		save[4] = b43_radio_read(dev, B2055_C2_PWRDET_RXTX);
485662306a36Sopenharmony_ci
485762306a36Sopenharmony_ci		if (!(b43_phy_read(dev, B43_NPHY_BANDCTL) &
485862306a36Sopenharmony_ci		    B43_NPHY_BANDCTL_5GHZ)) {
485962306a36Sopenharmony_ci			b43_radio_write(dev, B2055_C1_PWRDET_RXTX, 0x04);
486062306a36Sopenharmony_ci			b43_radio_write(dev, B2055_C2_PWRDET_RXTX, 0x04);
486162306a36Sopenharmony_ci		} else {
486262306a36Sopenharmony_ci			b43_radio_write(dev, B2055_C1_PWRDET_RXTX, 0x20);
486362306a36Sopenharmony_ci			b43_radio_write(dev, B2055_C2_PWRDET_RXTX, 0x20);
486462306a36Sopenharmony_ci		}
486562306a36Sopenharmony_ci
486662306a36Sopenharmony_ci		if (dev->phy.rev < 2) {
486762306a36Sopenharmony_ci			b43_radio_set(dev, B2055_C1_TX_BB_MXGM, 0x20);
486862306a36Sopenharmony_ci			b43_radio_set(dev, B2055_C2_TX_BB_MXGM, 0x20);
486962306a36Sopenharmony_ci		} else {
487062306a36Sopenharmony_ci			b43_radio_mask(dev, B2055_C1_TX_BB_MXGM, ~0x20);
487162306a36Sopenharmony_ci			b43_radio_mask(dev, B2055_C2_TX_BB_MXGM, ~0x20);
487262306a36Sopenharmony_ci		}
487362306a36Sopenharmony_ci	}
487462306a36Sopenharmony_ci}
487562306a36Sopenharmony_ci
487662306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */
487762306a36Sopenharmony_cistatic void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core)
487862306a36Sopenharmony_ci{
487962306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
488062306a36Sopenharmony_ci	int i;
488162306a36Sopenharmony_ci	u16 scale, entry;
488262306a36Sopenharmony_ci
488362306a36Sopenharmony_ci	u16 tmp = nphy->txcal_bbmult;
488462306a36Sopenharmony_ci	if (core == 0)
488562306a36Sopenharmony_ci		tmp >>= 8;
488662306a36Sopenharmony_ci	tmp &= 0xff;
488762306a36Sopenharmony_ci
488862306a36Sopenharmony_ci	for (i = 0; i < 18; i++) {
488962306a36Sopenharmony_ci		scale = (ladder_lo[i].percent * tmp) / 100;
489062306a36Sopenharmony_ci		entry = ((scale & 0xFF) << 8) | ladder_lo[i].g_env;
489162306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(15, i), entry);
489262306a36Sopenharmony_ci
489362306a36Sopenharmony_ci		scale = (ladder_iq[i].percent * tmp) / 100;
489462306a36Sopenharmony_ci		entry = ((scale & 0xFF) << 8) | ladder_iq[i].g_env;
489562306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(15, i + 32), entry);
489662306a36Sopenharmony_ci	}
489762306a36Sopenharmony_ci}
489862306a36Sopenharmony_ci
489962306a36Sopenharmony_cistatic void b43_nphy_pa_set_tx_dig_filter(struct b43_wldev *dev, u16 offset,
490062306a36Sopenharmony_ci					  const s16 *filter)
490162306a36Sopenharmony_ci{
490262306a36Sopenharmony_ci	int i;
490362306a36Sopenharmony_ci
490462306a36Sopenharmony_ci	offset = B43_PHY_N(offset);
490562306a36Sopenharmony_ci
490662306a36Sopenharmony_ci	for (i = 0; i < 15; i++, offset++)
490762306a36Sopenharmony_ci		b43_phy_write(dev, offset, filter[i]);
490862306a36Sopenharmony_ci}
490962306a36Sopenharmony_ci
491062306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */
491162306a36Sopenharmony_cistatic void b43_nphy_ext_pa_set_tx_dig_filters(struct b43_wldev *dev)
491262306a36Sopenharmony_ci{
491362306a36Sopenharmony_ci	b43_nphy_pa_set_tx_dig_filter(dev, 0x2C5,
491462306a36Sopenharmony_ci				      tbl_tx_filter_coef_rev4[2]);
491562306a36Sopenharmony_ci}
491662306a36Sopenharmony_ci
491762306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */
491862306a36Sopenharmony_cistatic void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev)
491962306a36Sopenharmony_ci{
492062306a36Sopenharmony_ci	/* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */
492162306a36Sopenharmony_ci	static const u16 offset[] = { 0x186, 0x195, 0x2C5 };
492262306a36Sopenharmony_ci	static const s16 dig_filter_phy_rev16[] = {
492362306a36Sopenharmony_ci		-375, 136, -407, 208, -1527,
492462306a36Sopenharmony_ci		956, 93, 186, 93, 230,
492562306a36Sopenharmony_ci		-44, 230, 201, -191, 201,
492662306a36Sopenharmony_ci	};
492762306a36Sopenharmony_ci	int i;
492862306a36Sopenharmony_ci
492962306a36Sopenharmony_ci	for (i = 0; i < 3; i++)
493062306a36Sopenharmony_ci		b43_nphy_pa_set_tx_dig_filter(dev, offset[i],
493162306a36Sopenharmony_ci					      tbl_tx_filter_coef_rev4[i]);
493262306a36Sopenharmony_ci
493362306a36Sopenharmony_ci	/* Verified with BCM43227 and BCM43228 */
493462306a36Sopenharmony_ci	if (dev->phy.rev == 16)
493562306a36Sopenharmony_ci		b43_nphy_pa_set_tx_dig_filter(dev, 0x186, dig_filter_phy_rev16);
493662306a36Sopenharmony_ci
493762306a36Sopenharmony_ci	/* Verified with BCM43131 and BCM43217 */
493862306a36Sopenharmony_ci	if (dev->phy.rev == 17) {
493962306a36Sopenharmony_ci		b43_nphy_pa_set_tx_dig_filter(dev, 0x186, dig_filter_phy_rev16);
494062306a36Sopenharmony_ci		b43_nphy_pa_set_tx_dig_filter(dev, 0x195,
494162306a36Sopenharmony_ci					      tbl_tx_filter_coef_rev4[1]);
494262306a36Sopenharmony_ci	}
494362306a36Sopenharmony_ci
494462306a36Sopenharmony_ci	if (b43_is_40mhz(dev)) {
494562306a36Sopenharmony_ci		b43_nphy_pa_set_tx_dig_filter(dev, 0x186,
494662306a36Sopenharmony_ci					      tbl_tx_filter_coef_rev4[3]);
494762306a36Sopenharmony_ci	} else {
494862306a36Sopenharmony_ci		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
494962306a36Sopenharmony_ci			b43_nphy_pa_set_tx_dig_filter(dev, 0x186,
495062306a36Sopenharmony_ci						      tbl_tx_filter_coef_rev4[5]);
495162306a36Sopenharmony_ci		if (dev->phy.channel == 14)
495262306a36Sopenharmony_ci			b43_nphy_pa_set_tx_dig_filter(dev, 0x186,
495362306a36Sopenharmony_ci						      tbl_tx_filter_coef_rev4[6]);
495462306a36Sopenharmony_ci	}
495562306a36Sopenharmony_ci}
495662306a36Sopenharmony_ci
495762306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */
495862306a36Sopenharmony_cistatic struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev)
495962306a36Sopenharmony_ci{
496062306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
496162306a36Sopenharmony_ci
496262306a36Sopenharmony_ci	u16 curr_gain[2];
496362306a36Sopenharmony_ci	struct nphy_txgains target;
496462306a36Sopenharmony_ci	const u32 *table = NULL;
496562306a36Sopenharmony_ci
496662306a36Sopenharmony_ci	if (!nphy->txpwrctrl) {
496762306a36Sopenharmony_ci		int i;
496862306a36Sopenharmony_ci
496962306a36Sopenharmony_ci		if (nphy->hang_avoid)
497062306a36Sopenharmony_ci			b43_nphy_stay_in_carrier_search(dev, true);
497162306a36Sopenharmony_ci		b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, curr_gain);
497262306a36Sopenharmony_ci		if (nphy->hang_avoid)
497362306a36Sopenharmony_ci			b43_nphy_stay_in_carrier_search(dev, false);
497462306a36Sopenharmony_ci
497562306a36Sopenharmony_ci		for (i = 0; i < 2; ++i) {
497662306a36Sopenharmony_ci			if (dev->phy.rev >= 7) {
497762306a36Sopenharmony_ci				target.ipa[i] = curr_gain[i] & 0x0007;
497862306a36Sopenharmony_ci				target.pad[i] = (curr_gain[i] & 0x00F8) >> 3;
497962306a36Sopenharmony_ci				target.pga[i] = (curr_gain[i] & 0x0F00) >> 8;
498062306a36Sopenharmony_ci				target.txgm[i] = (curr_gain[i] & 0x7000) >> 12;
498162306a36Sopenharmony_ci				target.tx_lpf[i] = (curr_gain[i] & 0x8000) >> 15;
498262306a36Sopenharmony_ci			} else if (dev->phy.rev >= 3) {
498362306a36Sopenharmony_ci				target.ipa[i] = curr_gain[i] & 0x000F;
498462306a36Sopenharmony_ci				target.pad[i] = (curr_gain[i] & 0x00F0) >> 4;
498562306a36Sopenharmony_ci				target.pga[i] = (curr_gain[i] & 0x0F00) >> 8;
498662306a36Sopenharmony_ci				target.txgm[i] = (curr_gain[i] & 0x7000) >> 12;
498762306a36Sopenharmony_ci			} else {
498862306a36Sopenharmony_ci				target.ipa[i] = curr_gain[i] & 0x0003;
498962306a36Sopenharmony_ci				target.pad[i] = (curr_gain[i] & 0x000C) >> 2;
499062306a36Sopenharmony_ci				target.pga[i] = (curr_gain[i] & 0x0070) >> 4;
499162306a36Sopenharmony_ci				target.txgm[i] = (curr_gain[i] & 0x0380) >> 7;
499262306a36Sopenharmony_ci			}
499362306a36Sopenharmony_ci		}
499462306a36Sopenharmony_ci	} else {
499562306a36Sopenharmony_ci		int i;
499662306a36Sopenharmony_ci		u16 index[2];
499762306a36Sopenharmony_ci		index[0] = (b43_phy_read(dev, B43_NPHY_C1_TXPCTL_STAT) &
499862306a36Sopenharmony_ci			B43_NPHY_TXPCTL_STAT_BIDX) >>
499962306a36Sopenharmony_ci			B43_NPHY_TXPCTL_STAT_BIDX_SHIFT;
500062306a36Sopenharmony_ci		index[1] = (b43_phy_read(dev, B43_NPHY_C2_TXPCTL_STAT) &
500162306a36Sopenharmony_ci			B43_NPHY_TXPCTL_STAT_BIDX) >>
500262306a36Sopenharmony_ci			B43_NPHY_TXPCTL_STAT_BIDX_SHIFT;
500362306a36Sopenharmony_ci
500462306a36Sopenharmony_ci		for (i = 0; i < 2; ++i) {
500562306a36Sopenharmony_ci			table = b43_nphy_get_tx_gain_table(dev);
500662306a36Sopenharmony_ci			if (!table)
500762306a36Sopenharmony_ci				break;
500862306a36Sopenharmony_ci
500962306a36Sopenharmony_ci			if (dev->phy.rev >= 7) {
501062306a36Sopenharmony_ci				target.ipa[i] = (table[index[i]] >> 16) & 0x7;
501162306a36Sopenharmony_ci				target.pad[i] = (table[index[i]] >> 19) & 0x1F;
501262306a36Sopenharmony_ci				target.pga[i] = (table[index[i]] >> 24) & 0xF;
501362306a36Sopenharmony_ci				target.txgm[i] = (table[index[i]] >> 28) & 0x7;
501462306a36Sopenharmony_ci				target.tx_lpf[i] = (table[index[i]] >> 31) & 0x1;
501562306a36Sopenharmony_ci			} else if (dev->phy.rev >= 3) {
501662306a36Sopenharmony_ci				target.ipa[i] = (table[index[i]] >> 16) & 0xF;
501762306a36Sopenharmony_ci				target.pad[i] = (table[index[i]] >> 20) & 0xF;
501862306a36Sopenharmony_ci				target.pga[i] = (table[index[i]] >> 24) & 0xF;
501962306a36Sopenharmony_ci				target.txgm[i] = (table[index[i]] >> 28) & 0xF;
502062306a36Sopenharmony_ci			} else {
502162306a36Sopenharmony_ci				target.ipa[i] = (table[index[i]] >> 16) & 0x3;
502262306a36Sopenharmony_ci				target.pad[i] = (table[index[i]] >> 18) & 0x3;
502362306a36Sopenharmony_ci				target.pga[i] = (table[index[i]] >> 20) & 0x7;
502462306a36Sopenharmony_ci				target.txgm[i] = (table[index[i]] >> 23) & 0x7;
502562306a36Sopenharmony_ci			}
502662306a36Sopenharmony_ci		}
502762306a36Sopenharmony_ci	}
502862306a36Sopenharmony_ci
502962306a36Sopenharmony_ci	return target;
503062306a36Sopenharmony_ci}
503162306a36Sopenharmony_ci
503262306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhyCleanup */
503362306a36Sopenharmony_cistatic void b43_nphy_tx_cal_phy_cleanup(struct b43_wldev *dev)
503462306a36Sopenharmony_ci{
503562306a36Sopenharmony_ci	u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
503662306a36Sopenharmony_ci
503762306a36Sopenharmony_ci	if (dev->phy.rev >= 3) {
503862306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[0]);
503962306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]);
504062306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]);
504162306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[3]);
504262306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_BBCFG, regs[4]);
504362306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(8, 3), regs[5]);
504462306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(8, 19), regs[6]);
504562306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[7]);
504662306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[8]);
504762306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]);
504862306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]);
504962306a36Sopenharmony_ci		b43_nphy_reset_cca(dev);
505062306a36Sopenharmony_ci	} else {
505162306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, regs[0]);
505262306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, regs[1]);
505362306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]);
505462306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(8, 2), regs[3]);
505562306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(8, 18), regs[4]);
505662306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[5]);
505762306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[6]);
505862306a36Sopenharmony_ci	}
505962306a36Sopenharmony_ci}
506062306a36Sopenharmony_ci
506162306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */
506262306a36Sopenharmony_cistatic void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev)
506362306a36Sopenharmony_ci{
506462306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
506562306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
506662306a36Sopenharmony_ci	u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
506762306a36Sopenharmony_ci	u16 tmp;
506862306a36Sopenharmony_ci
506962306a36Sopenharmony_ci	regs[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
507062306a36Sopenharmony_ci	regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
507162306a36Sopenharmony_ci	if (dev->phy.rev >= 3) {
507262306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0xF0FF, 0x0A00);
507362306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0xF0FF, 0x0A00);
507462306a36Sopenharmony_ci
507562306a36Sopenharmony_ci		tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
507662306a36Sopenharmony_ci		regs[2] = tmp;
507762306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, tmp | 0x0600);
507862306a36Sopenharmony_ci
507962306a36Sopenharmony_ci		tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
508062306a36Sopenharmony_ci		regs[3] = tmp;
508162306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x0600);
508262306a36Sopenharmony_ci
508362306a36Sopenharmony_ci		regs[4] = b43_phy_read(dev, B43_NPHY_BBCFG);
508462306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_BBCFG,
508562306a36Sopenharmony_ci			     ~B43_NPHY_BBCFG_RSTRX & 0xFFFF);
508662306a36Sopenharmony_ci
508762306a36Sopenharmony_ci		tmp = b43_ntab_read(dev, B43_NTAB16(8, 3));
508862306a36Sopenharmony_ci		regs[5] = tmp;
508962306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(8, 3), 0);
509062306a36Sopenharmony_ci
509162306a36Sopenharmony_ci		tmp = b43_ntab_read(dev, B43_NTAB16(8, 19));
509262306a36Sopenharmony_ci		regs[6] = tmp;
509362306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(8, 19), 0);
509462306a36Sopenharmony_ci		regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
509562306a36Sopenharmony_ci		regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
509662306a36Sopenharmony_ci
509762306a36Sopenharmony_ci		if (!nphy->use_int_tx_iq_lo_cal)
509862306a36Sopenharmony_ci			b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA,
509962306a36Sopenharmony_ci						      1, 3);
510062306a36Sopenharmony_ci		else
510162306a36Sopenharmony_ci			b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA,
510262306a36Sopenharmony_ci						      0, 3);
510362306a36Sopenharmony_ci		b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 2, 1);
510462306a36Sopenharmony_ci		b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 8, 2);
510562306a36Sopenharmony_ci
510662306a36Sopenharmony_ci		regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);
510762306a36Sopenharmony_ci		regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
510862306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
510962306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
511062306a36Sopenharmony_ci
511162306a36Sopenharmony_ci		tmp = b43_nphy_read_lpf_ctl(dev, 0);
511262306a36Sopenharmony_ci		if (phy->rev >= 19)
511362306a36Sopenharmony_ci			b43_nphy_rf_ctl_override_rev19(dev, 0x80, tmp, 0, false,
511462306a36Sopenharmony_ci						       1);
511562306a36Sopenharmony_ci		else if (phy->rev >= 7)
511662306a36Sopenharmony_ci			b43_nphy_rf_ctl_override_rev7(dev, 0x80, tmp, 0, false,
511762306a36Sopenharmony_ci						      1);
511862306a36Sopenharmony_ci
511962306a36Sopenharmony_ci		if (nphy->use_int_tx_iq_lo_cal && true /* FIXME */) {
512062306a36Sopenharmony_ci			if (phy->rev >= 19) {
512162306a36Sopenharmony_ci				b43_nphy_rf_ctl_override_rev19(dev, 0x8, 0, 0x3,
512262306a36Sopenharmony_ci							       false, 0);
512362306a36Sopenharmony_ci			} else if (phy->rev >= 8) {
512462306a36Sopenharmony_ci				b43_nphy_rf_ctl_override_rev7(dev, 0x8, 0, 0x3,
512562306a36Sopenharmony_ci							      false, 0);
512662306a36Sopenharmony_ci			} else if (phy->rev == 7) {
512762306a36Sopenharmony_ci				b43_radio_maskset(dev, R2057_OVR_REG0, 1 << 4, 1 << 4);
512862306a36Sopenharmony_ci				if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
512962306a36Sopenharmony_ci					b43_radio_maskset(dev, R2057_PAD2G_TUNE_PUS_CORE0, ~1, 0);
513062306a36Sopenharmony_ci					b43_radio_maskset(dev, R2057_PAD2G_TUNE_PUS_CORE1, ~1, 0);
513162306a36Sopenharmony_ci				} else {
513262306a36Sopenharmony_ci					b43_radio_maskset(dev, R2057_IPA5G_CASCOFFV_PU_CORE0, ~1, 0);
513362306a36Sopenharmony_ci					b43_radio_maskset(dev, R2057_IPA5G_CASCOFFV_PU_CORE1, ~1, 0);
513462306a36Sopenharmony_ci				}
513562306a36Sopenharmony_ci			}
513662306a36Sopenharmony_ci		}
513762306a36Sopenharmony_ci	} else {
513862306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, 0xA000);
513962306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, 0xA000);
514062306a36Sopenharmony_ci		tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
514162306a36Sopenharmony_ci		regs[2] = tmp;
514262306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x3000);
514362306a36Sopenharmony_ci		tmp = b43_ntab_read(dev, B43_NTAB16(8, 2));
514462306a36Sopenharmony_ci		regs[3] = tmp;
514562306a36Sopenharmony_ci		tmp |= 0x2000;
514662306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(8, 2), tmp);
514762306a36Sopenharmony_ci		tmp = b43_ntab_read(dev, B43_NTAB16(8, 18));
514862306a36Sopenharmony_ci		regs[4] = tmp;
514962306a36Sopenharmony_ci		tmp |= 0x2000;
515062306a36Sopenharmony_ci		b43_ntab_write(dev, B43_NTAB16(8, 18), tmp);
515162306a36Sopenharmony_ci		regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
515262306a36Sopenharmony_ci		regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
515362306a36Sopenharmony_ci		if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
515462306a36Sopenharmony_ci			tmp = 0x0180;
515562306a36Sopenharmony_ci		else
515662306a36Sopenharmony_ci			tmp = 0x0120;
515762306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp);
515862306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp);
515962306a36Sopenharmony_ci	}
516062306a36Sopenharmony_ci}
516162306a36Sopenharmony_ci
516262306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */
516362306a36Sopenharmony_cistatic void b43_nphy_save_cal(struct b43_wldev *dev)
516462306a36Sopenharmony_ci{
516562306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
516662306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
516762306a36Sopenharmony_ci
516862306a36Sopenharmony_ci	struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
516962306a36Sopenharmony_ci	u16 *txcal_radio_regs = NULL;
517062306a36Sopenharmony_ci	struct b43_chanspec *iqcal_chanspec;
517162306a36Sopenharmony_ci	u16 *table = NULL;
517262306a36Sopenharmony_ci
517362306a36Sopenharmony_ci	if (nphy->hang_avoid)
517462306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, 1);
517562306a36Sopenharmony_ci
517662306a36Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
517762306a36Sopenharmony_ci		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G;
517862306a36Sopenharmony_ci		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G;
517962306a36Sopenharmony_ci		iqcal_chanspec = &nphy->iqcal_chanspec_2G;
518062306a36Sopenharmony_ci		table = nphy->cal_cache.txcal_coeffs_2G;
518162306a36Sopenharmony_ci	} else {
518262306a36Sopenharmony_ci		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G;
518362306a36Sopenharmony_ci		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G;
518462306a36Sopenharmony_ci		iqcal_chanspec = &nphy->iqcal_chanspec_5G;
518562306a36Sopenharmony_ci		table = nphy->cal_cache.txcal_coeffs_5G;
518662306a36Sopenharmony_ci	}
518762306a36Sopenharmony_ci
518862306a36Sopenharmony_ci	b43_nphy_rx_iq_coeffs(dev, false, rxcal_coeffs);
518962306a36Sopenharmony_ci	/* TODO use some definitions */
519062306a36Sopenharmony_ci	if (phy->rev >= 19) {
519162306a36Sopenharmony_ci		/* TODO */
519262306a36Sopenharmony_ci	} else if (phy->rev >= 7) {
519362306a36Sopenharmony_ci		txcal_radio_regs[0] = b43_radio_read(dev,
519462306a36Sopenharmony_ci						     R2057_TX0_LOFT_FINE_I);
519562306a36Sopenharmony_ci		txcal_radio_regs[1] = b43_radio_read(dev,
519662306a36Sopenharmony_ci						     R2057_TX0_LOFT_FINE_Q);
519762306a36Sopenharmony_ci		txcal_radio_regs[4] = b43_radio_read(dev,
519862306a36Sopenharmony_ci						     R2057_TX0_LOFT_COARSE_I);
519962306a36Sopenharmony_ci		txcal_radio_regs[5] = b43_radio_read(dev,
520062306a36Sopenharmony_ci						     R2057_TX0_LOFT_COARSE_Q);
520162306a36Sopenharmony_ci		txcal_radio_regs[2] = b43_radio_read(dev,
520262306a36Sopenharmony_ci						     R2057_TX1_LOFT_FINE_I);
520362306a36Sopenharmony_ci		txcal_radio_regs[3] = b43_radio_read(dev,
520462306a36Sopenharmony_ci						     R2057_TX1_LOFT_FINE_Q);
520562306a36Sopenharmony_ci		txcal_radio_regs[6] = b43_radio_read(dev,
520662306a36Sopenharmony_ci						     R2057_TX1_LOFT_COARSE_I);
520762306a36Sopenharmony_ci		txcal_radio_regs[7] = b43_radio_read(dev,
520862306a36Sopenharmony_ci						     R2057_TX1_LOFT_COARSE_Q);
520962306a36Sopenharmony_ci	} else if (phy->rev >= 3) {
521062306a36Sopenharmony_ci		txcal_radio_regs[0] = b43_radio_read(dev, 0x2021);
521162306a36Sopenharmony_ci		txcal_radio_regs[1] = b43_radio_read(dev, 0x2022);
521262306a36Sopenharmony_ci		txcal_radio_regs[2] = b43_radio_read(dev, 0x3021);
521362306a36Sopenharmony_ci		txcal_radio_regs[3] = b43_radio_read(dev, 0x3022);
521462306a36Sopenharmony_ci		txcal_radio_regs[4] = b43_radio_read(dev, 0x2023);
521562306a36Sopenharmony_ci		txcal_radio_regs[5] = b43_radio_read(dev, 0x2024);
521662306a36Sopenharmony_ci		txcal_radio_regs[6] = b43_radio_read(dev, 0x3023);
521762306a36Sopenharmony_ci		txcal_radio_regs[7] = b43_radio_read(dev, 0x3024);
521862306a36Sopenharmony_ci	} else {
521962306a36Sopenharmony_ci		txcal_radio_regs[0] = b43_radio_read(dev, 0x8B);
522062306a36Sopenharmony_ci		txcal_radio_regs[1] = b43_radio_read(dev, 0xBA);
522162306a36Sopenharmony_ci		txcal_radio_regs[2] = b43_radio_read(dev, 0x8D);
522262306a36Sopenharmony_ci		txcal_radio_regs[3] = b43_radio_read(dev, 0xBC);
522362306a36Sopenharmony_ci	}
522462306a36Sopenharmony_ci	iqcal_chanspec->center_freq = dev->phy.chandef->chan->center_freq;
522562306a36Sopenharmony_ci	iqcal_chanspec->channel_type =
522662306a36Sopenharmony_ci				cfg80211_get_chandef_type(dev->phy.chandef);
522762306a36Sopenharmony_ci	b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 8, table);
522862306a36Sopenharmony_ci
522962306a36Sopenharmony_ci	if (nphy->hang_avoid)
523062306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, 0);
523162306a36Sopenharmony_ci}
523262306a36Sopenharmony_ci
523362306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */
523462306a36Sopenharmony_cistatic void b43_nphy_restore_cal(struct b43_wldev *dev)
523562306a36Sopenharmony_ci{
523662306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
523762306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
523862306a36Sopenharmony_ci
523962306a36Sopenharmony_ci	u16 coef[4];
524062306a36Sopenharmony_ci	u16 *loft = NULL;
524162306a36Sopenharmony_ci	u16 *table = NULL;
524262306a36Sopenharmony_ci
524362306a36Sopenharmony_ci	int i;
524462306a36Sopenharmony_ci	u16 *txcal_radio_regs = NULL;
524562306a36Sopenharmony_ci	struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
524662306a36Sopenharmony_ci
524762306a36Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
524862306a36Sopenharmony_ci		if (!nphy->iqcal_chanspec_2G.center_freq)
524962306a36Sopenharmony_ci			return;
525062306a36Sopenharmony_ci		table = nphy->cal_cache.txcal_coeffs_2G;
525162306a36Sopenharmony_ci		loft = &nphy->cal_cache.txcal_coeffs_2G[5];
525262306a36Sopenharmony_ci	} else {
525362306a36Sopenharmony_ci		if (!nphy->iqcal_chanspec_5G.center_freq)
525462306a36Sopenharmony_ci			return;
525562306a36Sopenharmony_ci		table = nphy->cal_cache.txcal_coeffs_5G;
525662306a36Sopenharmony_ci		loft = &nphy->cal_cache.txcal_coeffs_5G[5];
525762306a36Sopenharmony_ci	}
525862306a36Sopenharmony_ci
525962306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4, table);
526062306a36Sopenharmony_ci
526162306a36Sopenharmony_ci	for (i = 0; i < 4; i++) {
526262306a36Sopenharmony_ci		if (dev->phy.rev >= 3)
526362306a36Sopenharmony_ci			coef[i] = table[i];
526462306a36Sopenharmony_ci		else
526562306a36Sopenharmony_ci			coef[i] = 0;
526662306a36Sopenharmony_ci	}
526762306a36Sopenharmony_ci
526862306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, coef);
526962306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, loft);
527062306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2, loft);
527162306a36Sopenharmony_ci
527262306a36Sopenharmony_ci	if (dev->phy.rev < 2)
527362306a36Sopenharmony_ci		b43_nphy_tx_iq_workaround(dev);
527462306a36Sopenharmony_ci
527562306a36Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
527662306a36Sopenharmony_ci		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G;
527762306a36Sopenharmony_ci		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G;
527862306a36Sopenharmony_ci	} else {
527962306a36Sopenharmony_ci		txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G;
528062306a36Sopenharmony_ci		rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G;
528162306a36Sopenharmony_ci	}
528262306a36Sopenharmony_ci
528362306a36Sopenharmony_ci	/* TODO use some definitions */
528462306a36Sopenharmony_ci	if (phy->rev >= 19) {
528562306a36Sopenharmony_ci		/* TODO */
528662306a36Sopenharmony_ci	} else if (phy->rev >= 7) {
528762306a36Sopenharmony_ci		b43_radio_write(dev, R2057_TX0_LOFT_FINE_I,
528862306a36Sopenharmony_ci				txcal_radio_regs[0]);
528962306a36Sopenharmony_ci		b43_radio_write(dev, R2057_TX0_LOFT_FINE_Q,
529062306a36Sopenharmony_ci				txcal_radio_regs[1]);
529162306a36Sopenharmony_ci		b43_radio_write(dev, R2057_TX0_LOFT_COARSE_I,
529262306a36Sopenharmony_ci				txcal_radio_regs[4]);
529362306a36Sopenharmony_ci		b43_radio_write(dev, R2057_TX0_LOFT_COARSE_Q,
529462306a36Sopenharmony_ci				txcal_radio_regs[5]);
529562306a36Sopenharmony_ci		b43_radio_write(dev, R2057_TX1_LOFT_FINE_I,
529662306a36Sopenharmony_ci				txcal_radio_regs[2]);
529762306a36Sopenharmony_ci		b43_radio_write(dev, R2057_TX1_LOFT_FINE_Q,
529862306a36Sopenharmony_ci				txcal_radio_regs[3]);
529962306a36Sopenharmony_ci		b43_radio_write(dev, R2057_TX1_LOFT_COARSE_I,
530062306a36Sopenharmony_ci				txcal_radio_regs[6]);
530162306a36Sopenharmony_ci		b43_radio_write(dev, R2057_TX1_LOFT_COARSE_Q,
530262306a36Sopenharmony_ci				txcal_radio_regs[7]);
530362306a36Sopenharmony_ci	} else if (phy->rev >= 3) {
530462306a36Sopenharmony_ci		b43_radio_write(dev, 0x2021, txcal_radio_regs[0]);
530562306a36Sopenharmony_ci		b43_radio_write(dev, 0x2022, txcal_radio_regs[1]);
530662306a36Sopenharmony_ci		b43_radio_write(dev, 0x3021, txcal_radio_regs[2]);
530762306a36Sopenharmony_ci		b43_radio_write(dev, 0x3022, txcal_radio_regs[3]);
530862306a36Sopenharmony_ci		b43_radio_write(dev, 0x2023, txcal_radio_regs[4]);
530962306a36Sopenharmony_ci		b43_radio_write(dev, 0x2024, txcal_radio_regs[5]);
531062306a36Sopenharmony_ci		b43_radio_write(dev, 0x3023, txcal_radio_regs[6]);
531162306a36Sopenharmony_ci		b43_radio_write(dev, 0x3024, txcal_radio_regs[7]);
531262306a36Sopenharmony_ci	} else {
531362306a36Sopenharmony_ci		b43_radio_write(dev, 0x8B, txcal_radio_regs[0]);
531462306a36Sopenharmony_ci		b43_radio_write(dev, 0xBA, txcal_radio_regs[1]);
531562306a36Sopenharmony_ci		b43_radio_write(dev, 0x8D, txcal_radio_regs[2]);
531662306a36Sopenharmony_ci		b43_radio_write(dev, 0xBC, txcal_radio_regs[3]);
531762306a36Sopenharmony_ci	}
531862306a36Sopenharmony_ci	b43_nphy_rx_iq_coeffs(dev, true, rxcal_coeffs);
531962306a36Sopenharmony_ci}
532062306a36Sopenharmony_ci
532162306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/CalTxIqlo */
532262306a36Sopenharmony_cistatic int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
532362306a36Sopenharmony_ci				struct nphy_txgains target,
532462306a36Sopenharmony_ci				bool full, bool mphase)
532562306a36Sopenharmony_ci{
532662306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
532762306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
532862306a36Sopenharmony_ci	int i;
532962306a36Sopenharmony_ci	int error = 0;
533062306a36Sopenharmony_ci	int freq;
533162306a36Sopenharmony_ci	bool avoid = false;
533262306a36Sopenharmony_ci	u8 length;
533362306a36Sopenharmony_ci	u16 tmp, core, type, count, max, numb, last = 0, cmd;
533462306a36Sopenharmony_ci	const u16 *table;
533562306a36Sopenharmony_ci	bool phy6or5x;
533662306a36Sopenharmony_ci
533762306a36Sopenharmony_ci	u16 buffer[11];
533862306a36Sopenharmony_ci	u16 diq_start = 0;
533962306a36Sopenharmony_ci	u16 save[2];
534062306a36Sopenharmony_ci	u16 gain[2];
534162306a36Sopenharmony_ci	struct nphy_iqcal_params params[2];
534262306a36Sopenharmony_ci	bool updated[2] = { };
534362306a36Sopenharmony_ci
534462306a36Sopenharmony_ci	b43_nphy_stay_in_carrier_search(dev, true);
534562306a36Sopenharmony_ci
534662306a36Sopenharmony_ci	if (dev->phy.rev >= 4) {
534762306a36Sopenharmony_ci		avoid = nphy->hang_avoid;
534862306a36Sopenharmony_ci		nphy->hang_avoid = false;
534962306a36Sopenharmony_ci	}
535062306a36Sopenharmony_ci
535162306a36Sopenharmony_ci	b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, save);
535262306a36Sopenharmony_ci
535362306a36Sopenharmony_ci	for (i = 0; i < 2; i++) {
535462306a36Sopenharmony_ci		b43_nphy_iq_cal_gain_params(dev, i, target, &params[i]);
535562306a36Sopenharmony_ci		gain[i] = params[i].cal_gain;
535662306a36Sopenharmony_ci	}
535762306a36Sopenharmony_ci
535862306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain);
535962306a36Sopenharmony_ci
536062306a36Sopenharmony_ci	b43_nphy_tx_cal_radio_setup(dev);
536162306a36Sopenharmony_ci	b43_nphy_tx_cal_phy_setup(dev);
536262306a36Sopenharmony_ci
536362306a36Sopenharmony_ci	phy6or5x = dev->phy.rev >= 6 ||
536462306a36Sopenharmony_ci		(dev->phy.rev == 5 && nphy->ipa2g_on &&
536562306a36Sopenharmony_ci		b43_current_band(dev->wl) == NL80211_BAND_2GHZ);
536662306a36Sopenharmony_ci	if (phy6or5x) {
536762306a36Sopenharmony_ci		if (b43_is_40mhz(dev)) {
536862306a36Sopenharmony_ci			b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18,
536962306a36Sopenharmony_ci					tbl_tx_iqlo_cal_loft_ladder_40);
537062306a36Sopenharmony_ci			b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18,
537162306a36Sopenharmony_ci					tbl_tx_iqlo_cal_iqimb_ladder_40);
537262306a36Sopenharmony_ci		} else {
537362306a36Sopenharmony_ci			b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18,
537462306a36Sopenharmony_ci					tbl_tx_iqlo_cal_loft_ladder_20);
537562306a36Sopenharmony_ci			b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18,
537662306a36Sopenharmony_ci					tbl_tx_iqlo_cal_iqimb_ladder_20);
537762306a36Sopenharmony_ci		}
537862306a36Sopenharmony_ci	}
537962306a36Sopenharmony_ci
538062306a36Sopenharmony_ci	if (phy->rev >= 19) {
538162306a36Sopenharmony_ci		/* TODO */
538262306a36Sopenharmony_ci	} else if (phy->rev >= 7) {
538362306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AD9);
538462306a36Sopenharmony_ci	} else {
538562306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9);
538662306a36Sopenharmony_ci	}
538762306a36Sopenharmony_ci
538862306a36Sopenharmony_ci	if (!b43_is_40mhz(dev))
538962306a36Sopenharmony_ci		freq = 2500;
539062306a36Sopenharmony_ci	else
539162306a36Sopenharmony_ci		freq = 5000;
539262306a36Sopenharmony_ci
539362306a36Sopenharmony_ci	if (nphy->mphase_cal_phase_id > 2)
539462306a36Sopenharmony_ci		b43_nphy_run_samples(dev, (b43_is_40mhz(dev) ? 40 : 20) * 8,
539562306a36Sopenharmony_ci				     0xFFFF, 0, true, false, false);
539662306a36Sopenharmony_ci	else
539762306a36Sopenharmony_ci		error = b43_nphy_tx_tone(dev, freq, 250, true, false, false);
539862306a36Sopenharmony_ci
539962306a36Sopenharmony_ci	if (error == 0) {
540062306a36Sopenharmony_ci		if (nphy->mphase_cal_phase_id > 2) {
540162306a36Sopenharmony_ci			table = nphy->mphase_txcal_bestcoeffs;
540262306a36Sopenharmony_ci			length = 11;
540362306a36Sopenharmony_ci			if (dev->phy.rev < 3)
540462306a36Sopenharmony_ci				length -= 2;
540562306a36Sopenharmony_ci		} else {
540662306a36Sopenharmony_ci			if (!full && nphy->txiqlocal_coeffsvalid) {
540762306a36Sopenharmony_ci				table = nphy->txiqlocal_bestc;
540862306a36Sopenharmony_ci				length = 11;
540962306a36Sopenharmony_ci				if (dev->phy.rev < 3)
541062306a36Sopenharmony_ci					length -= 2;
541162306a36Sopenharmony_ci			} else {
541262306a36Sopenharmony_ci				full = true;
541362306a36Sopenharmony_ci				if (dev->phy.rev >= 3) {
541462306a36Sopenharmony_ci					table = tbl_tx_iqlo_cal_startcoefs_nphyrev3;
541562306a36Sopenharmony_ci					length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3;
541662306a36Sopenharmony_ci				} else {
541762306a36Sopenharmony_ci					table = tbl_tx_iqlo_cal_startcoefs;
541862306a36Sopenharmony_ci					length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS;
541962306a36Sopenharmony_ci				}
542062306a36Sopenharmony_ci			}
542162306a36Sopenharmony_ci		}
542262306a36Sopenharmony_ci
542362306a36Sopenharmony_ci		b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length, table);
542462306a36Sopenharmony_ci
542562306a36Sopenharmony_ci		if (full) {
542662306a36Sopenharmony_ci			if (dev->phy.rev >= 3)
542762306a36Sopenharmony_ci				max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3;
542862306a36Sopenharmony_ci			else
542962306a36Sopenharmony_ci				max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL;
543062306a36Sopenharmony_ci		} else {
543162306a36Sopenharmony_ci			if (dev->phy.rev >= 3)
543262306a36Sopenharmony_ci				max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3;
543362306a36Sopenharmony_ci			else
543462306a36Sopenharmony_ci				max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL;
543562306a36Sopenharmony_ci		}
543662306a36Sopenharmony_ci
543762306a36Sopenharmony_ci		if (mphase) {
543862306a36Sopenharmony_ci			count = nphy->mphase_txcal_cmdidx;
543962306a36Sopenharmony_ci			numb = min(max,
544062306a36Sopenharmony_ci				(u16)(count + nphy->mphase_txcal_numcmds));
544162306a36Sopenharmony_ci		} else {
544262306a36Sopenharmony_ci			count = 0;
544362306a36Sopenharmony_ci			numb = max;
544462306a36Sopenharmony_ci		}
544562306a36Sopenharmony_ci
544662306a36Sopenharmony_ci		for (; count < numb; count++) {
544762306a36Sopenharmony_ci			if (full) {
544862306a36Sopenharmony_ci				if (dev->phy.rev >= 3)
544962306a36Sopenharmony_ci					cmd = tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[count];
545062306a36Sopenharmony_ci				else
545162306a36Sopenharmony_ci					cmd = tbl_tx_iqlo_cal_cmds_fullcal[count];
545262306a36Sopenharmony_ci			} else {
545362306a36Sopenharmony_ci				if (dev->phy.rev >= 3)
545462306a36Sopenharmony_ci					cmd = tbl_tx_iqlo_cal_cmds_recal_nphyrev3[count];
545562306a36Sopenharmony_ci				else
545662306a36Sopenharmony_ci					cmd = tbl_tx_iqlo_cal_cmds_recal[count];
545762306a36Sopenharmony_ci			}
545862306a36Sopenharmony_ci
545962306a36Sopenharmony_ci			core = (cmd & 0x3000) >> 12;
546062306a36Sopenharmony_ci			type = (cmd & 0x0F00) >> 8;
546162306a36Sopenharmony_ci
546262306a36Sopenharmony_ci			if (phy6or5x && !updated[core]) {
546362306a36Sopenharmony_ci				b43_nphy_update_tx_cal_ladder(dev, core);
546462306a36Sopenharmony_ci				updated[core] = true;
546562306a36Sopenharmony_ci			}
546662306a36Sopenharmony_ci
546762306a36Sopenharmony_ci			tmp = (params[core].ncorr[type] << 8) | 0x66;
546862306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDNNUM, tmp);
546962306a36Sopenharmony_ci
547062306a36Sopenharmony_ci			if (type == 1 || type == 3 || type == 4) {
547162306a36Sopenharmony_ci				buffer[0] = b43_ntab_read(dev,
547262306a36Sopenharmony_ci						B43_NTAB16(15, 69 + core));
547362306a36Sopenharmony_ci				diq_start = buffer[0];
547462306a36Sopenharmony_ci				buffer[0] = 0;
547562306a36Sopenharmony_ci				b43_ntab_write(dev, B43_NTAB16(15, 69 + core),
547662306a36Sopenharmony_ci						0);
547762306a36Sopenharmony_ci			}
547862306a36Sopenharmony_ci
547962306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_IQLOCAL_CMD, cmd);
548062306a36Sopenharmony_ci			for (i = 0; i < 2000; i++) {
548162306a36Sopenharmony_ci				tmp = b43_phy_read(dev, B43_NPHY_IQLOCAL_CMD);
548262306a36Sopenharmony_ci				if (tmp & 0xC000)
548362306a36Sopenharmony_ci					break;
548462306a36Sopenharmony_ci				udelay(10);
548562306a36Sopenharmony_ci			}
548662306a36Sopenharmony_ci
548762306a36Sopenharmony_ci			b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
548862306a36Sopenharmony_ci						buffer);
548962306a36Sopenharmony_ci			b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length,
549062306a36Sopenharmony_ci						buffer);
549162306a36Sopenharmony_ci
549262306a36Sopenharmony_ci			if (type == 1 || type == 3 || type == 4)
549362306a36Sopenharmony_ci				buffer[0] = diq_start;
549462306a36Sopenharmony_ci		}
549562306a36Sopenharmony_ci
549662306a36Sopenharmony_ci		if (mphase)
549762306a36Sopenharmony_ci			nphy->mphase_txcal_cmdidx = (numb >= max) ? 0 : numb;
549862306a36Sopenharmony_ci
549962306a36Sopenharmony_ci		last = (dev->phy.rev < 3) ? 6 : 7;
550062306a36Sopenharmony_ci
550162306a36Sopenharmony_ci		if (!mphase || nphy->mphase_cal_phase_id == last) {
550262306a36Sopenharmony_ci			b43_ntab_write_bulk(dev, B43_NTAB16(15, 96), 4, buffer);
550362306a36Sopenharmony_ci			b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 4, buffer);
550462306a36Sopenharmony_ci			if (dev->phy.rev < 3) {
550562306a36Sopenharmony_ci				buffer[0] = 0;
550662306a36Sopenharmony_ci				buffer[1] = 0;
550762306a36Sopenharmony_ci				buffer[2] = 0;
550862306a36Sopenharmony_ci				buffer[3] = 0;
550962306a36Sopenharmony_ci			}
551062306a36Sopenharmony_ci			b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4,
551162306a36Sopenharmony_ci						buffer);
551262306a36Sopenharmony_ci			b43_ntab_read_bulk(dev, B43_NTAB16(15, 101), 2,
551362306a36Sopenharmony_ci						buffer);
551462306a36Sopenharmony_ci			b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2,
551562306a36Sopenharmony_ci						buffer);
551662306a36Sopenharmony_ci			b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2,
551762306a36Sopenharmony_ci						buffer);
551862306a36Sopenharmony_ci			length = 11;
551962306a36Sopenharmony_ci			if (dev->phy.rev < 3)
552062306a36Sopenharmony_ci				length -= 2;
552162306a36Sopenharmony_ci			b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
552262306a36Sopenharmony_ci						nphy->txiqlocal_bestc);
552362306a36Sopenharmony_ci			nphy->txiqlocal_coeffsvalid = true;
552462306a36Sopenharmony_ci			nphy->txiqlocal_chanspec.center_freq =
552562306a36Sopenharmony_ci						phy->chandef->chan->center_freq;
552662306a36Sopenharmony_ci			nphy->txiqlocal_chanspec.channel_type =
552762306a36Sopenharmony_ci					cfg80211_get_chandef_type(phy->chandef);
552862306a36Sopenharmony_ci		} else {
552962306a36Sopenharmony_ci			length = 11;
553062306a36Sopenharmony_ci			if (dev->phy.rev < 3)
553162306a36Sopenharmony_ci				length -= 2;
553262306a36Sopenharmony_ci			b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
553362306a36Sopenharmony_ci						nphy->mphase_txcal_bestcoeffs);
553462306a36Sopenharmony_ci		}
553562306a36Sopenharmony_ci
553662306a36Sopenharmony_ci		b43_nphy_stop_playback(dev);
553762306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0);
553862306a36Sopenharmony_ci	}
553962306a36Sopenharmony_ci
554062306a36Sopenharmony_ci	b43_nphy_tx_cal_phy_cleanup(dev);
554162306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, save);
554262306a36Sopenharmony_ci
554362306a36Sopenharmony_ci	if (dev->phy.rev < 2 && (!mphase || nphy->mphase_cal_phase_id == last))
554462306a36Sopenharmony_ci		b43_nphy_tx_iq_workaround(dev);
554562306a36Sopenharmony_ci
554662306a36Sopenharmony_ci	if (dev->phy.rev >= 4)
554762306a36Sopenharmony_ci		nphy->hang_avoid = avoid;
554862306a36Sopenharmony_ci
554962306a36Sopenharmony_ci	b43_nphy_stay_in_carrier_search(dev, false);
555062306a36Sopenharmony_ci
555162306a36Sopenharmony_ci	return error;
555262306a36Sopenharmony_ci}
555362306a36Sopenharmony_ci
555462306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/ReapplyTxCalCoeffs */
555562306a36Sopenharmony_cistatic void b43_nphy_reapply_tx_cal_coeffs(struct b43_wldev *dev)
555662306a36Sopenharmony_ci{
555762306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
555862306a36Sopenharmony_ci	u8 i;
555962306a36Sopenharmony_ci	u16 buffer[7];
556062306a36Sopenharmony_ci	bool equal = true;
556162306a36Sopenharmony_ci
556262306a36Sopenharmony_ci	if (!nphy->txiqlocal_coeffsvalid ||
556362306a36Sopenharmony_ci	    nphy->txiqlocal_chanspec.center_freq != dev->phy.chandef->chan->center_freq ||
556462306a36Sopenharmony_ci	    nphy->txiqlocal_chanspec.channel_type != cfg80211_get_chandef_type(dev->phy.chandef))
556562306a36Sopenharmony_ci		return;
556662306a36Sopenharmony_ci
556762306a36Sopenharmony_ci	b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
556862306a36Sopenharmony_ci	for (i = 0; i < 4; i++) {
556962306a36Sopenharmony_ci		if (buffer[i] != nphy->txiqlocal_bestc[i]) {
557062306a36Sopenharmony_ci			equal = false;
557162306a36Sopenharmony_ci			break;
557262306a36Sopenharmony_ci		}
557362306a36Sopenharmony_ci	}
557462306a36Sopenharmony_ci
557562306a36Sopenharmony_ci	if (!equal) {
557662306a36Sopenharmony_ci		b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4,
557762306a36Sopenharmony_ci					nphy->txiqlocal_bestc);
557862306a36Sopenharmony_ci		for (i = 0; i < 4; i++)
557962306a36Sopenharmony_ci			buffer[i] = 0;
558062306a36Sopenharmony_ci		b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4,
558162306a36Sopenharmony_ci					buffer);
558262306a36Sopenharmony_ci		b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2,
558362306a36Sopenharmony_ci					&nphy->txiqlocal_bestc[5]);
558462306a36Sopenharmony_ci		b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2,
558562306a36Sopenharmony_ci					&nphy->txiqlocal_bestc[5]);
558662306a36Sopenharmony_ci	}
558762306a36Sopenharmony_ci}
558862306a36Sopenharmony_ci
558962306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIqRev2 */
559062306a36Sopenharmony_cistatic int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,
559162306a36Sopenharmony_ci			struct nphy_txgains target, u8 type, bool debug)
559262306a36Sopenharmony_ci{
559362306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
559462306a36Sopenharmony_ci	int i, j, index;
559562306a36Sopenharmony_ci	u8 rfctl[2];
559662306a36Sopenharmony_ci	u8 afectl_core;
559762306a36Sopenharmony_ci	u16 tmp[6];
559862306a36Sopenharmony_ci	u16 cur_hpf1, cur_hpf2, cur_lna;
559962306a36Sopenharmony_ci	u32 real, imag;
560062306a36Sopenharmony_ci	enum nl80211_band band;
560162306a36Sopenharmony_ci
560262306a36Sopenharmony_ci	u8 use;
560362306a36Sopenharmony_ci	u16 cur_hpf;
560462306a36Sopenharmony_ci	u16 lna[3] = { 3, 3, 1 };
560562306a36Sopenharmony_ci	u16 hpf1[3] = { 7, 2, 0 };
560662306a36Sopenharmony_ci	u16 hpf2[3] = { 2, 0, 0 };
560762306a36Sopenharmony_ci	u32 power[3] = { };
560862306a36Sopenharmony_ci	u16 gain_save[2];
560962306a36Sopenharmony_ci	u16 cal_gain[2];
561062306a36Sopenharmony_ci	struct nphy_iqcal_params cal_params[2];
561162306a36Sopenharmony_ci	struct nphy_iq_est est;
561262306a36Sopenharmony_ci	int ret = 0;
561362306a36Sopenharmony_ci	bool playtone = true;
561462306a36Sopenharmony_ci	int desired = 13;
561562306a36Sopenharmony_ci
561662306a36Sopenharmony_ci	b43_nphy_stay_in_carrier_search(dev, 1);
561762306a36Sopenharmony_ci
561862306a36Sopenharmony_ci	if (dev->phy.rev < 2)
561962306a36Sopenharmony_ci		b43_nphy_reapply_tx_cal_coeffs(dev);
562062306a36Sopenharmony_ci	b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save);
562162306a36Sopenharmony_ci	for (i = 0; i < 2; i++) {
562262306a36Sopenharmony_ci		b43_nphy_iq_cal_gain_params(dev, i, target, &cal_params[i]);
562362306a36Sopenharmony_ci		cal_gain[i] = cal_params[i].cal_gain;
562462306a36Sopenharmony_ci	}
562562306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, cal_gain);
562662306a36Sopenharmony_ci
562762306a36Sopenharmony_ci	for (i = 0; i < 2; i++) {
562862306a36Sopenharmony_ci		if (i == 0) {
562962306a36Sopenharmony_ci			rfctl[0] = B43_NPHY_RFCTL_INTC1;
563062306a36Sopenharmony_ci			rfctl[1] = B43_NPHY_RFCTL_INTC2;
563162306a36Sopenharmony_ci			afectl_core = B43_NPHY_AFECTL_C1;
563262306a36Sopenharmony_ci		} else {
563362306a36Sopenharmony_ci			rfctl[0] = B43_NPHY_RFCTL_INTC2;
563462306a36Sopenharmony_ci			rfctl[1] = B43_NPHY_RFCTL_INTC1;
563562306a36Sopenharmony_ci			afectl_core = B43_NPHY_AFECTL_C2;
563662306a36Sopenharmony_ci		}
563762306a36Sopenharmony_ci
563862306a36Sopenharmony_ci		tmp[1] = b43_phy_read(dev, B43_NPHY_RFSEQCA);
563962306a36Sopenharmony_ci		tmp[2] = b43_phy_read(dev, afectl_core);
564062306a36Sopenharmony_ci		tmp[3] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
564162306a36Sopenharmony_ci		tmp[4] = b43_phy_read(dev, rfctl[0]);
564262306a36Sopenharmony_ci		tmp[5] = b43_phy_read(dev, rfctl[1]);
564362306a36Sopenharmony_ci
564462306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
564562306a36Sopenharmony_ci				~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF,
564662306a36Sopenharmony_ci				((1 - i) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));
564762306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN,
564862306a36Sopenharmony_ci				(1 - i));
564962306a36Sopenharmony_ci		b43_phy_set(dev, afectl_core, 0x0006);
565062306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0006);
565162306a36Sopenharmony_ci
565262306a36Sopenharmony_ci		band = b43_current_band(dev->wl);
565362306a36Sopenharmony_ci
565462306a36Sopenharmony_ci		if (nphy->rxcalparams & 0xFF000000) {
565562306a36Sopenharmony_ci			if (band == NL80211_BAND_5GHZ)
565662306a36Sopenharmony_ci				b43_phy_write(dev, rfctl[0], 0x140);
565762306a36Sopenharmony_ci			else
565862306a36Sopenharmony_ci				b43_phy_write(dev, rfctl[0], 0x110);
565962306a36Sopenharmony_ci		} else {
566062306a36Sopenharmony_ci			if (band == NL80211_BAND_5GHZ)
566162306a36Sopenharmony_ci				b43_phy_write(dev, rfctl[0], 0x180);
566262306a36Sopenharmony_ci			else
566362306a36Sopenharmony_ci				b43_phy_write(dev, rfctl[0], 0x120);
566462306a36Sopenharmony_ci		}
566562306a36Sopenharmony_ci
566662306a36Sopenharmony_ci		if (band == NL80211_BAND_5GHZ)
566762306a36Sopenharmony_ci			b43_phy_write(dev, rfctl[1], 0x148);
566862306a36Sopenharmony_ci		else
566962306a36Sopenharmony_ci			b43_phy_write(dev, rfctl[1], 0x114);
567062306a36Sopenharmony_ci
567162306a36Sopenharmony_ci		if (nphy->rxcalparams & 0x10000) {
567262306a36Sopenharmony_ci			b43_radio_maskset(dev, B2055_C1_GENSPARE2, 0xFC,
567362306a36Sopenharmony_ci					(i + 1));
567462306a36Sopenharmony_ci			b43_radio_maskset(dev, B2055_C2_GENSPARE2, 0xFC,
567562306a36Sopenharmony_ci					(2 - i));
567662306a36Sopenharmony_ci		}
567762306a36Sopenharmony_ci
567862306a36Sopenharmony_ci		for (j = 0; j < 4; j++) {
567962306a36Sopenharmony_ci			if (j < 3) {
568062306a36Sopenharmony_ci				cur_lna = lna[j];
568162306a36Sopenharmony_ci				cur_hpf1 = hpf1[j];
568262306a36Sopenharmony_ci				cur_hpf2 = hpf2[j];
568362306a36Sopenharmony_ci			} else {
568462306a36Sopenharmony_ci				if (power[1] > 10000) {
568562306a36Sopenharmony_ci					use = 1;
568662306a36Sopenharmony_ci					cur_hpf = cur_hpf1;
568762306a36Sopenharmony_ci					index = 2;
568862306a36Sopenharmony_ci				} else {
568962306a36Sopenharmony_ci					if (power[0] > 10000) {
569062306a36Sopenharmony_ci						use = 1;
569162306a36Sopenharmony_ci						cur_hpf = cur_hpf1;
569262306a36Sopenharmony_ci						index = 1;
569362306a36Sopenharmony_ci					} else {
569462306a36Sopenharmony_ci						index = 0;
569562306a36Sopenharmony_ci						use = 2;
569662306a36Sopenharmony_ci						cur_hpf = cur_hpf2;
569762306a36Sopenharmony_ci					}
569862306a36Sopenharmony_ci				}
569962306a36Sopenharmony_ci				cur_lna = lna[index];
570062306a36Sopenharmony_ci				cur_hpf1 = hpf1[index];
570162306a36Sopenharmony_ci				cur_hpf2 = hpf2[index];
570262306a36Sopenharmony_ci				cur_hpf += desired - hweight32(power[index]);
570362306a36Sopenharmony_ci				cur_hpf = clamp_val(cur_hpf, 0, 10);
570462306a36Sopenharmony_ci				if (use == 1)
570562306a36Sopenharmony_ci					cur_hpf1 = cur_hpf;
570662306a36Sopenharmony_ci				else
570762306a36Sopenharmony_ci					cur_hpf2 = cur_hpf;
570862306a36Sopenharmony_ci			}
570962306a36Sopenharmony_ci
571062306a36Sopenharmony_ci			tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) |
571162306a36Sopenharmony_ci					(cur_lna << 2));
571262306a36Sopenharmony_ci			b43_nphy_rf_ctl_override(dev, 0x400, tmp[0], 3,
571362306a36Sopenharmony_ci									false);
571462306a36Sopenharmony_ci			b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
571562306a36Sopenharmony_ci			b43_nphy_stop_playback(dev);
571662306a36Sopenharmony_ci
571762306a36Sopenharmony_ci			if (playtone) {
571862306a36Sopenharmony_ci				ret = b43_nphy_tx_tone(dev, 4000,
571962306a36Sopenharmony_ci						(nphy->rxcalparams & 0xFFFF),
572062306a36Sopenharmony_ci						false, false, true);
572162306a36Sopenharmony_ci				playtone = false;
572262306a36Sopenharmony_ci			} else {
572362306a36Sopenharmony_ci				b43_nphy_run_samples(dev, 160, 0xFFFF, 0, false,
572462306a36Sopenharmony_ci						     false, true);
572562306a36Sopenharmony_ci			}
572662306a36Sopenharmony_ci
572762306a36Sopenharmony_ci			if (ret == 0) {
572862306a36Sopenharmony_ci				if (j < 3) {
572962306a36Sopenharmony_ci					b43_nphy_rx_iq_est(dev, &est, 1024, 32,
573062306a36Sopenharmony_ci									false);
573162306a36Sopenharmony_ci					if (i == 0) {
573262306a36Sopenharmony_ci						real = est.i0_pwr;
573362306a36Sopenharmony_ci						imag = est.q0_pwr;
573462306a36Sopenharmony_ci					} else {
573562306a36Sopenharmony_ci						real = est.i1_pwr;
573662306a36Sopenharmony_ci						imag = est.q1_pwr;
573762306a36Sopenharmony_ci					}
573862306a36Sopenharmony_ci					power[i] = ((real + imag) / 1024) + 1;
573962306a36Sopenharmony_ci				} else {
574062306a36Sopenharmony_ci					b43_nphy_calc_rx_iq_comp(dev, 1 << i);
574162306a36Sopenharmony_ci				}
574262306a36Sopenharmony_ci				b43_nphy_stop_playback(dev);
574362306a36Sopenharmony_ci			}
574462306a36Sopenharmony_ci
574562306a36Sopenharmony_ci			if (ret != 0)
574662306a36Sopenharmony_ci				break;
574762306a36Sopenharmony_ci		}
574862306a36Sopenharmony_ci
574962306a36Sopenharmony_ci		b43_radio_mask(dev, B2055_C1_GENSPARE2, 0xFC);
575062306a36Sopenharmony_ci		b43_radio_mask(dev, B2055_C2_GENSPARE2, 0xFC);
575162306a36Sopenharmony_ci		b43_phy_write(dev, rfctl[1], tmp[5]);
575262306a36Sopenharmony_ci		b43_phy_write(dev, rfctl[0], tmp[4]);
575362306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp[3]);
575462306a36Sopenharmony_ci		b43_phy_write(dev, afectl_core, tmp[2]);
575562306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_RFSEQCA, tmp[1]);
575662306a36Sopenharmony_ci
575762306a36Sopenharmony_ci		if (ret != 0)
575862306a36Sopenharmony_ci			break;
575962306a36Sopenharmony_ci	}
576062306a36Sopenharmony_ci
576162306a36Sopenharmony_ci	b43_nphy_rf_ctl_override(dev, 0x400, 0, 3, true);
576262306a36Sopenharmony_ci	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
576362306a36Sopenharmony_ci	b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save);
576462306a36Sopenharmony_ci
576562306a36Sopenharmony_ci	b43_nphy_stay_in_carrier_search(dev, 0);
576662306a36Sopenharmony_ci
576762306a36Sopenharmony_ci	return ret;
576862306a36Sopenharmony_ci}
576962306a36Sopenharmony_ci
577062306a36Sopenharmony_cistatic int b43_nphy_rev3_cal_rx_iq(struct b43_wldev *dev,
577162306a36Sopenharmony_ci			struct nphy_txgains target, u8 type, bool debug)
577262306a36Sopenharmony_ci{
577362306a36Sopenharmony_ci	return -1;
577462306a36Sopenharmony_ci}
577562306a36Sopenharmony_ci
577662306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIq */
577762306a36Sopenharmony_cistatic int b43_nphy_cal_rx_iq(struct b43_wldev *dev,
577862306a36Sopenharmony_ci			struct nphy_txgains target, u8 type, bool debug)
577962306a36Sopenharmony_ci{
578062306a36Sopenharmony_ci	if (dev->phy.rev >= 7)
578162306a36Sopenharmony_ci		type = 0;
578262306a36Sopenharmony_ci
578362306a36Sopenharmony_ci	if (dev->phy.rev >= 3)
578462306a36Sopenharmony_ci		return b43_nphy_rev3_cal_rx_iq(dev, target, type, debug);
578562306a36Sopenharmony_ci	else
578662306a36Sopenharmony_ci		return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug);
578762306a36Sopenharmony_ci}
578862306a36Sopenharmony_ci
578962306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */
579062306a36Sopenharmony_cistatic void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask)
579162306a36Sopenharmony_ci{
579262306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
579362306a36Sopenharmony_ci	struct b43_phy_n *nphy = phy->n;
579462306a36Sopenharmony_ci	/* u16 buf[16]; it's rev3+ */
579562306a36Sopenharmony_ci
579662306a36Sopenharmony_ci	nphy->phyrxchain = mask;
579762306a36Sopenharmony_ci
579862306a36Sopenharmony_ci	if (0 /* FIXME clk */)
579962306a36Sopenharmony_ci		return;
580062306a36Sopenharmony_ci
580162306a36Sopenharmony_ci	b43_mac_suspend(dev);
580262306a36Sopenharmony_ci
580362306a36Sopenharmony_ci	if (nphy->hang_avoid)
580462306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, true);
580562306a36Sopenharmony_ci
580662306a36Sopenharmony_ci	b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN,
580762306a36Sopenharmony_ci			(mask & 0x3) << B43_NPHY_RFSEQCA_RXEN_SHIFT);
580862306a36Sopenharmony_ci
580962306a36Sopenharmony_ci	if ((mask & 0x3) != 0x3) {
581062306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 1);
581162306a36Sopenharmony_ci		if (dev->phy.rev >= 3) {
581262306a36Sopenharmony_ci			/* TODO */
581362306a36Sopenharmony_ci		}
581462306a36Sopenharmony_ci	} else {
581562306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 0x1E);
581662306a36Sopenharmony_ci		if (dev->phy.rev >= 3) {
581762306a36Sopenharmony_ci			/* TODO */
581862306a36Sopenharmony_ci		}
581962306a36Sopenharmony_ci	}
582062306a36Sopenharmony_ci
582162306a36Sopenharmony_ci	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
582262306a36Sopenharmony_ci
582362306a36Sopenharmony_ci	if (nphy->hang_avoid)
582462306a36Sopenharmony_ci		b43_nphy_stay_in_carrier_search(dev, false);
582562306a36Sopenharmony_ci
582662306a36Sopenharmony_ci	b43_mac_enable(dev);
582762306a36Sopenharmony_ci}
582862306a36Sopenharmony_ci
582962306a36Sopenharmony_cistatic enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev,
583062306a36Sopenharmony_ci							bool ignore_tssi)
583162306a36Sopenharmony_ci{
583262306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
583362306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
583462306a36Sopenharmony_ci	struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan;
583562306a36Sopenharmony_ci	struct b43_ppr *ppr = &nphy->tx_pwr_max_ppr;
583662306a36Sopenharmony_ci	u8 max; /* qdBm */
583762306a36Sopenharmony_ci
583862306a36Sopenharmony_ci	if (nphy->tx_pwr_last_recalc_freq == channel->center_freq &&
583962306a36Sopenharmony_ci	    nphy->tx_pwr_last_recalc_limit == phy->desired_txpower)
584062306a36Sopenharmony_ci		return B43_TXPWR_RES_DONE;
584162306a36Sopenharmony_ci
584262306a36Sopenharmony_ci	/* Make sure we have a clean PPR */
584362306a36Sopenharmony_ci	b43_ppr_clear(dev, ppr);
584462306a36Sopenharmony_ci
584562306a36Sopenharmony_ci	/* HW limitations */
584662306a36Sopenharmony_ci	b43_ppr_load_max_from_sprom(dev, ppr, B43_BAND_2G);
584762306a36Sopenharmony_ci
584862306a36Sopenharmony_ci	/* Regulatory & user settings */
584962306a36Sopenharmony_ci	max = INT_TO_Q52(phy->chandef->chan->max_power);
585062306a36Sopenharmony_ci	if (phy->desired_txpower)
585162306a36Sopenharmony_ci		max = min_t(u8, max, INT_TO_Q52(phy->desired_txpower));
585262306a36Sopenharmony_ci	b43_ppr_apply_max(dev, ppr, max);
585362306a36Sopenharmony_ci	if (b43_debug(dev, B43_DBG_XMITPOWER))
585462306a36Sopenharmony_ci		b43dbg(dev->wl, "Calculated TX power: " Q52_FMT "\n",
585562306a36Sopenharmony_ci		       Q52_ARG(b43_ppr_get_max(dev, ppr)));
585662306a36Sopenharmony_ci
585762306a36Sopenharmony_ci	/* TODO: Enable this once we get gains working */
585862306a36Sopenharmony_ci#if 0
585962306a36Sopenharmony_ci	/* Some extra gains */
586062306a36Sopenharmony_ci	hw_gain = 6; /* N-PHY specific */
586162306a36Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
586262306a36Sopenharmony_ci		hw_gain += sprom->antenna_gain.a0;
586362306a36Sopenharmony_ci	else
586462306a36Sopenharmony_ci		hw_gain += sprom->antenna_gain.a1;
586562306a36Sopenharmony_ci	b43_ppr_add(dev, ppr, -hw_gain);
586662306a36Sopenharmony_ci#endif
586762306a36Sopenharmony_ci
586862306a36Sopenharmony_ci	/* Make sure we didn't go too low */
586962306a36Sopenharmony_ci	b43_ppr_apply_min(dev, ppr, INT_TO_Q52(8));
587062306a36Sopenharmony_ci
587162306a36Sopenharmony_ci	/* Apply */
587262306a36Sopenharmony_ci	b43_mac_suspend(dev);
587362306a36Sopenharmony_ci	b43_nphy_tx_power_ctl_setup(dev);
587462306a36Sopenharmony_ci	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) {
587562306a36Sopenharmony_ci		b43_maskset32(dev, B43_MMIO_MACCTL, ~0, B43_MACCTL_PHY_LOCK);
587662306a36Sopenharmony_ci		b43_read32(dev, B43_MMIO_MACCTL);
587762306a36Sopenharmony_ci		udelay(1);
587862306a36Sopenharmony_ci	}
587962306a36Sopenharmony_ci	b43_nphy_tx_power_ctrl(dev, nphy->txpwrctrl);
588062306a36Sopenharmony_ci	if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12)
588162306a36Sopenharmony_ci		b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_PHY_LOCK, 0);
588262306a36Sopenharmony_ci	b43_mac_enable(dev);
588362306a36Sopenharmony_ci
588462306a36Sopenharmony_ci	nphy->tx_pwr_last_recalc_freq = channel->center_freq;
588562306a36Sopenharmony_ci	nphy->tx_pwr_last_recalc_limit = phy->desired_txpower;
588662306a36Sopenharmony_ci
588762306a36Sopenharmony_ci	return B43_TXPWR_RES_DONE;
588862306a36Sopenharmony_ci}
588962306a36Sopenharmony_ci
589062306a36Sopenharmony_ci/**************************************************
589162306a36Sopenharmony_ci * N-PHY init
589262306a36Sopenharmony_ci **************************************************/
589362306a36Sopenharmony_ci
589462306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */
589562306a36Sopenharmony_cistatic void b43_nphy_update_mimo_config(struct b43_wldev *dev, s32 preamble)
589662306a36Sopenharmony_ci{
589762306a36Sopenharmony_ci	u16 mimocfg = b43_phy_read(dev, B43_NPHY_MIMOCFG);
589862306a36Sopenharmony_ci
589962306a36Sopenharmony_ci	mimocfg |= B43_NPHY_MIMOCFG_AUTO;
590062306a36Sopenharmony_ci	if (preamble == 1)
590162306a36Sopenharmony_ci		mimocfg |= B43_NPHY_MIMOCFG_GFMIX;
590262306a36Sopenharmony_ci	else
590362306a36Sopenharmony_ci		mimocfg &= ~B43_NPHY_MIMOCFG_GFMIX;
590462306a36Sopenharmony_ci
590562306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_MIMOCFG, mimocfg);
590662306a36Sopenharmony_ci}
590762306a36Sopenharmony_ci
590862306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/BPHYInit */
590962306a36Sopenharmony_cistatic void b43_nphy_bphy_init(struct b43_wldev *dev)
591062306a36Sopenharmony_ci{
591162306a36Sopenharmony_ci	unsigned int i;
591262306a36Sopenharmony_ci	u16 val;
591362306a36Sopenharmony_ci
591462306a36Sopenharmony_ci	val = 0x1E1F;
591562306a36Sopenharmony_ci	for (i = 0; i < 16; i++) {
591662306a36Sopenharmony_ci		b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val);
591762306a36Sopenharmony_ci		val -= 0x202;
591862306a36Sopenharmony_ci	}
591962306a36Sopenharmony_ci	val = 0x3E3F;
592062306a36Sopenharmony_ci	for (i = 0; i < 16; i++) {
592162306a36Sopenharmony_ci		b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val);
592262306a36Sopenharmony_ci		val -= 0x202;
592362306a36Sopenharmony_ci	}
592462306a36Sopenharmony_ci	b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668);
592562306a36Sopenharmony_ci}
592662306a36Sopenharmony_ci
592762306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */
592862306a36Sopenharmony_cistatic void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init)
592962306a36Sopenharmony_ci{
593062306a36Sopenharmony_ci	if (dev->phy.rev >= 7)
593162306a36Sopenharmony_ci		return;
593262306a36Sopenharmony_ci
593362306a36Sopenharmony_ci	if (dev->phy.rev >= 3) {
593462306a36Sopenharmony_ci		if (!init)
593562306a36Sopenharmony_ci			return;
593662306a36Sopenharmony_ci		if (0 /* FIXME */) {
593762306a36Sopenharmony_ci			b43_ntab_write(dev, B43_NTAB16(9, 2), 0x211);
593862306a36Sopenharmony_ci			b43_ntab_write(dev, B43_NTAB16(9, 3), 0x222);
593962306a36Sopenharmony_ci			b43_ntab_write(dev, B43_NTAB16(9, 8), 0x144);
594062306a36Sopenharmony_ci			b43_ntab_write(dev, B43_NTAB16(9, 12), 0x188);
594162306a36Sopenharmony_ci		}
594262306a36Sopenharmony_ci	} else {
594362306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0);
594462306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0);
594562306a36Sopenharmony_ci
594662306a36Sopenharmony_ci		switch (dev->dev->bus_type) {
594762306a36Sopenharmony_ci#ifdef CONFIG_B43_BCMA
594862306a36Sopenharmony_ci		case B43_BUS_BCMA:
594962306a36Sopenharmony_ci			bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc,
595062306a36Sopenharmony_ci						 0xFC00, 0xFC00);
595162306a36Sopenharmony_ci			break;
595262306a36Sopenharmony_ci#endif
595362306a36Sopenharmony_ci#ifdef CONFIG_B43_SSB
595462306a36Sopenharmony_ci		case B43_BUS_SSB:
595562306a36Sopenharmony_ci			ssb_chipco_gpio_control(&dev->dev->sdev->bus->chipco,
595662306a36Sopenharmony_ci						0xFC00, 0xFC00);
595762306a36Sopenharmony_ci			break;
595862306a36Sopenharmony_ci#endif
595962306a36Sopenharmony_ci		}
596062306a36Sopenharmony_ci
596162306a36Sopenharmony_ci		b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0);
596262306a36Sopenharmony_ci		b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, 0xFC00);
596362306a36Sopenharmony_ci		b43_maskset16(dev, B43_MMIO_GPIO_CONTROL, (~0xFC00 & 0xFFFF),
596462306a36Sopenharmony_ci			      0);
596562306a36Sopenharmony_ci
596662306a36Sopenharmony_ci		if (init) {
596762306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
596862306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
596962306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
597062306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
597162306a36Sopenharmony_ci		}
597262306a36Sopenharmony_ci	}
597362306a36Sopenharmony_ci}
597462306a36Sopenharmony_ci
597562306a36Sopenharmony_ci/* http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N */
597662306a36Sopenharmony_cistatic int b43_phy_initn(struct b43_wldev *dev)
597762306a36Sopenharmony_ci{
597862306a36Sopenharmony_ci	struct ssb_sprom *sprom = dev->dev->bus_sprom;
597962306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
598062306a36Sopenharmony_ci	struct b43_phy_n *nphy = phy->n;
598162306a36Sopenharmony_ci	u8 tx_pwr_state;
598262306a36Sopenharmony_ci	struct nphy_txgains target;
598362306a36Sopenharmony_ci	u16 tmp;
598462306a36Sopenharmony_ci	bool do_rssi_cal;
598562306a36Sopenharmony_ci
598662306a36Sopenharmony_ci	u16 clip[2];
598762306a36Sopenharmony_ci	bool do_cal = false;
598862306a36Sopenharmony_ci
598962306a36Sopenharmony_ci	if ((dev->phy.rev >= 3) &&
599062306a36Sopenharmony_ci	   (sprom->boardflags_lo & B43_BFL_EXTLNA) &&
599162306a36Sopenharmony_ci	   (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)) {
599262306a36Sopenharmony_ci		switch (dev->dev->bus_type) {
599362306a36Sopenharmony_ci#ifdef CONFIG_B43_BCMA
599462306a36Sopenharmony_ci		case B43_BUS_BCMA:
599562306a36Sopenharmony_ci			bcma_cc_set32(&dev->dev->bdev->bus->drv_cc,
599662306a36Sopenharmony_ci				      BCMA_CC_CHIPCTL, 0x40);
599762306a36Sopenharmony_ci			break;
599862306a36Sopenharmony_ci#endif
599962306a36Sopenharmony_ci#ifdef CONFIG_B43_SSB
600062306a36Sopenharmony_ci		case B43_BUS_SSB:
600162306a36Sopenharmony_ci			chipco_set32(&dev->dev->sdev->bus->chipco,
600262306a36Sopenharmony_ci				     SSB_CHIPCO_CHIPCTL, 0x40);
600362306a36Sopenharmony_ci			break;
600462306a36Sopenharmony_ci#endif
600562306a36Sopenharmony_ci		}
600662306a36Sopenharmony_ci	}
600762306a36Sopenharmony_ci	nphy->use_int_tx_iq_lo_cal = b43_nphy_ipa(dev) ||
600862306a36Sopenharmony_ci		phy->rev >= 7 ||
600962306a36Sopenharmony_ci		(phy->rev >= 5 &&
601062306a36Sopenharmony_ci		 sprom->boardflags2_hi & B43_BFH2_INTERNDET_TXIQCAL);
601162306a36Sopenharmony_ci	nphy->deaf_count = 0;
601262306a36Sopenharmony_ci	b43_nphy_tables_init(dev);
601362306a36Sopenharmony_ci	nphy->crsminpwr_adjusted = false;
601462306a36Sopenharmony_ci	nphy->noisevars_adjusted = false;
601562306a36Sopenharmony_ci
601662306a36Sopenharmony_ci	/* Clear all overrides */
601762306a36Sopenharmony_ci	if (dev->phy.rev >= 3) {
601862306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, 0);
601962306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
602062306a36Sopenharmony_ci		if (phy->rev >= 7) {
602162306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0);
602262306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER4, 0);
602362306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER5, 0);
602462306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER6, 0);
602562306a36Sopenharmony_ci		}
602662306a36Sopenharmony_ci		if (phy->rev >= 19) {
602762306a36Sopenharmony_ci			/* TODO */
602862306a36Sopenharmony_ci		}
602962306a36Sopenharmony_ci
603062306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, 0);
603162306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, 0);
603262306a36Sopenharmony_ci	} else {
603362306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
603462306a36Sopenharmony_ci	}
603562306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 0);
603662306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 0);
603762306a36Sopenharmony_ci	if (dev->phy.rev < 6) {
603862306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0);
603962306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0);
604062306a36Sopenharmony_ci	}
604162306a36Sopenharmony_ci	b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
604262306a36Sopenharmony_ci		     ~(B43_NPHY_RFSEQMODE_CAOVER |
604362306a36Sopenharmony_ci		       B43_NPHY_RFSEQMODE_TROVER));
604462306a36Sopenharmony_ci	if (dev->phy.rev >= 3)
604562306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, 0);
604662306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 0);
604762306a36Sopenharmony_ci
604862306a36Sopenharmony_ci	if (dev->phy.rev <= 2) {
604962306a36Sopenharmony_ci		tmp = (dev->phy.rev == 2) ? 0x3B : 0x40;
605062306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
605162306a36Sopenharmony_ci				~B43_NPHY_BPHY_CTL3_SCALE,
605262306a36Sopenharmony_ci				tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT);
605362306a36Sopenharmony_ci	}
605462306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20);
605562306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20);
605662306a36Sopenharmony_ci
605762306a36Sopenharmony_ci	if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD ||
605862306a36Sopenharmony_ci	    (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&
605962306a36Sopenharmony_ci	     dev->dev->board_type == BCMA_BOARD_TYPE_BCM943224M93))
606062306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0);
606162306a36Sopenharmony_ci	else
606262306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8);
606362306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 0xC8);
606462306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50);
606562306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30);
606662306a36Sopenharmony_ci
606762306a36Sopenharmony_ci	if (phy->rev < 8)
606862306a36Sopenharmony_ci		b43_nphy_update_mimo_config(dev, nphy->preamble_override);
606962306a36Sopenharmony_ci
607062306a36Sopenharmony_ci	b43_nphy_update_txrx_chain(dev);
607162306a36Sopenharmony_ci
607262306a36Sopenharmony_ci	if (phy->rev < 2) {
607362306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8);
607462306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4);
607562306a36Sopenharmony_ci	}
607662306a36Sopenharmony_ci
607762306a36Sopenharmony_ci	if (b43_nphy_ipa(dev)) {
607862306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_PAPD_EN0, 0x1);
607962306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ0, 0x007F,
608062306a36Sopenharmony_ci				nphy->papd_epsilon_offset[0] << 7);
608162306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_PAPD_EN1, 0x1);
608262306a36Sopenharmony_ci		b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ1, 0x007F,
608362306a36Sopenharmony_ci				nphy->papd_epsilon_offset[1] << 7);
608462306a36Sopenharmony_ci		b43_nphy_int_pa_set_tx_dig_filters(dev);
608562306a36Sopenharmony_ci	} else if (phy->rev >= 5) {
608662306a36Sopenharmony_ci		b43_nphy_ext_pa_set_tx_dig_filters(dev);
608762306a36Sopenharmony_ci	}
608862306a36Sopenharmony_ci
608962306a36Sopenharmony_ci	b43_nphy_workarounds(dev);
609062306a36Sopenharmony_ci
609162306a36Sopenharmony_ci	/* Reset CCA, in init code it differs a little from standard way */
609262306a36Sopenharmony_ci	b43_phy_force_clock(dev, 1);
609362306a36Sopenharmony_ci	tmp = b43_phy_read(dev, B43_NPHY_BBCFG);
609462306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA);
609562306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA);
609662306a36Sopenharmony_ci	b43_phy_force_clock(dev, 0);
609762306a36Sopenharmony_ci
609862306a36Sopenharmony_ci	b43_mac_phy_clock_set(dev, true);
609962306a36Sopenharmony_ci
610062306a36Sopenharmony_ci	if (phy->rev < 7) {
610162306a36Sopenharmony_ci		b43_nphy_pa_override(dev, false);
610262306a36Sopenharmony_ci		b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
610362306a36Sopenharmony_ci		b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
610462306a36Sopenharmony_ci		b43_nphy_pa_override(dev, true);
610562306a36Sopenharmony_ci	}
610662306a36Sopenharmony_ci
610762306a36Sopenharmony_ci	b43_nphy_classifier(dev, 0, 0);
610862306a36Sopenharmony_ci	b43_nphy_read_clip_detection(dev, clip);
610962306a36Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
611062306a36Sopenharmony_ci		b43_nphy_bphy_init(dev);
611162306a36Sopenharmony_ci
611262306a36Sopenharmony_ci	tx_pwr_state = nphy->txpwrctrl;
611362306a36Sopenharmony_ci	b43_nphy_tx_power_ctrl(dev, false);
611462306a36Sopenharmony_ci	b43_nphy_tx_power_fix(dev);
611562306a36Sopenharmony_ci	b43_nphy_tx_power_ctl_idle_tssi(dev);
611662306a36Sopenharmony_ci	b43_nphy_tx_power_ctl_setup(dev);
611762306a36Sopenharmony_ci	b43_nphy_tx_gain_table_upload(dev);
611862306a36Sopenharmony_ci
611962306a36Sopenharmony_ci	if (nphy->phyrxchain != 3)
612062306a36Sopenharmony_ci		b43_nphy_set_rx_core_state(dev, nphy->phyrxchain);
612162306a36Sopenharmony_ci	if (nphy->mphase_cal_phase_id > 0) {
612262306a36Sopenharmony_ci		;/* TODO PHY Periodic Calibration Multi-Phase Restart */
612362306a36Sopenharmony_ci	}
612462306a36Sopenharmony_ci
612562306a36Sopenharmony_ci	do_rssi_cal = false;
612662306a36Sopenharmony_ci	if (phy->rev >= 3) {
612762306a36Sopenharmony_ci		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
612862306a36Sopenharmony_ci			do_rssi_cal = !nphy->rssical_chanspec_2G.center_freq;
612962306a36Sopenharmony_ci		else
613062306a36Sopenharmony_ci			do_rssi_cal = !nphy->rssical_chanspec_5G.center_freq;
613162306a36Sopenharmony_ci
613262306a36Sopenharmony_ci		if (do_rssi_cal)
613362306a36Sopenharmony_ci			b43_nphy_rssi_cal(dev);
613462306a36Sopenharmony_ci		else
613562306a36Sopenharmony_ci			b43_nphy_restore_rssi_cal(dev);
613662306a36Sopenharmony_ci	} else {
613762306a36Sopenharmony_ci		b43_nphy_rssi_cal(dev);
613862306a36Sopenharmony_ci	}
613962306a36Sopenharmony_ci
614062306a36Sopenharmony_ci	if (!((nphy->measure_hold & 0x6) != 0)) {
614162306a36Sopenharmony_ci		if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
614262306a36Sopenharmony_ci			do_cal = !nphy->iqcal_chanspec_2G.center_freq;
614362306a36Sopenharmony_ci		else
614462306a36Sopenharmony_ci			do_cal = !nphy->iqcal_chanspec_5G.center_freq;
614562306a36Sopenharmony_ci
614662306a36Sopenharmony_ci		if (nphy->mute)
614762306a36Sopenharmony_ci			do_cal = false;
614862306a36Sopenharmony_ci
614962306a36Sopenharmony_ci		if (do_cal) {
615062306a36Sopenharmony_ci			target = b43_nphy_get_tx_gains(dev);
615162306a36Sopenharmony_ci
615262306a36Sopenharmony_ci			if (nphy->antsel_type == 2)
615362306a36Sopenharmony_ci				b43_nphy_superswitch_init(dev, true);
615462306a36Sopenharmony_ci			if (nphy->perical != 2) {
615562306a36Sopenharmony_ci				b43_nphy_rssi_cal(dev);
615662306a36Sopenharmony_ci				if (phy->rev >= 3) {
615762306a36Sopenharmony_ci					nphy->cal_orig_pwr_idx[0] =
615862306a36Sopenharmony_ci					    nphy->txpwrindex[0].index_internal;
615962306a36Sopenharmony_ci					nphy->cal_orig_pwr_idx[1] =
616062306a36Sopenharmony_ci					    nphy->txpwrindex[1].index_internal;
616162306a36Sopenharmony_ci					/* TODO N PHY Pre Calibrate TX Gain */
616262306a36Sopenharmony_ci					target = b43_nphy_get_tx_gains(dev);
616362306a36Sopenharmony_ci				}
616462306a36Sopenharmony_ci				if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false))
616562306a36Sopenharmony_ci					if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0)
616662306a36Sopenharmony_ci						b43_nphy_save_cal(dev);
616762306a36Sopenharmony_ci			} else if (nphy->mphase_cal_phase_id == 0) {
616862306a36Sopenharmony_ci				;/* N PHY Periodic Calibration with arg 3 */
616962306a36Sopenharmony_ci			}
617062306a36Sopenharmony_ci		} else {
617162306a36Sopenharmony_ci			b43_nphy_restore_cal(dev);
617262306a36Sopenharmony_ci		}
617362306a36Sopenharmony_ci	}
617462306a36Sopenharmony_ci
617562306a36Sopenharmony_ci	b43_nphy_tx_pwr_ctrl_coef_setup(dev);
617662306a36Sopenharmony_ci	b43_nphy_tx_power_ctrl(dev, tx_pwr_state);
617762306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_TXMACIF_HOLDOFF, 0x0015);
617862306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320);
617962306a36Sopenharmony_ci	if (phy->rev >= 3 && phy->rev <= 6)
618062306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x0032);
618162306a36Sopenharmony_ci	b43_nphy_tx_lpf_bw(dev);
618262306a36Sopenharmony_ci	if (phy->rev >= 3)
618362306a36Sopenharmony_ci		b43_nphy_spur_workaround(dev);
618462306a36Sopenharmony_ci
618562306a36Sopenharmony_ci	return 0;
618662306a36Sopenharmony_ci}
618762306a36Sopenharmony_ci
618862306a36Sopenharmony_ci/**************************************************
618962306a36Sopenharmony_ci * Channel switching ops.
619062306a36Sopenharmony_ci **************************************************/
619162306a36Sopenharmony_ci
619262306a36Sopenharmony_cistatic void b43_chantab_phy_upload(struct b43_wldev *dev,
619362306a36Sopenharmony_ci				   const struct b43_phy_n_sfo_cfg *e)
619462306a36Sopenharmony_ci{
619562306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a);
619662306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2);
619762306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_BW3, e->phy_bw3);
619862306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_BW4, e->phy_bw4);
619962306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_BW5, e->phy_bw5);
620062306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_BW6, e->phy_bw6);
620162306a36Sopenharmony_ci}
620262306a36Sopenharmony_ci
620362306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PmuSpurAvoid */
620462306a36Sopenharmony_cistatic void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid)
620562306a36Sopenharmony_ci{
620662306a36Sopenharmony_ci	switch (dev->dev->bus_type) {
620762306a36Sopenharmony_ci#ifdef CONFIG_B43_BCMA
620862306a36Sopenharmony_ci	case B43_BUS_BCMA:
620962306a36Sopenharmony_ci		bcma_pmu_spuravoid_pllupdate(&dev->dev->bdev->bus->drv_cc,
621062306a36Sopenharmony_ci					     avoid);
621162306a36Sopenharmony_ci		break;
621262306a36Sopenharmony_ci#endif
621362306a36Sopenharmony_ci#ifdef CONFIG_B43_SSB
621462306a36Sopenharmony_ci	case B43_BUS_SSB:
621562306a36Sopenharmony_ci		ssb_pmu_spuravoid_pllupdate(&dev->dev->sdev->bus->chipco,
621662306a36Sopenharmony_ci					    avoid);
621762306a36Sopenharmony_ci		break;
621862306a36Sopenharmony_ci#endif
621962306a36Sopenharmony_ci	}
622062306a36Sopenharmony_ci}
622162306a36Sopenharmony_ci
622262306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */
622362306a36Sopenharmony_cistatic void b43_nphy_channel_setup(struct b43_wldev *dev,
622462306a36Sopenharmony_ci				const struct b43_phy_n_sfo_cfg *e,
622562306a36Sopenharmony_ci				struct ieee80211_channel *new_channel)
622662306a36Sopenharmony_ci{
622762306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
622862306a36Sopenharmony_ci	struct b43_phy_n *nphy = dev->phy.n;
622962306a36Sopenharmony_ci	int ch = new_channel->hw_value;
623062306a36Sopenharmony_ci	u16 tmp16;
623162306a36Sopenharmony_ci
623262306a36Sopenharmony_ci	if (new_channel->band == NL80211_BAND_5GHZ) {
623362306a36Sopenharmony_ci		/* Switch to 2 GHz for a moment to access B43_PHY_B_BBCFG */
623462306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
623562306a36Sopenharmony_ci
623662306a36Sopenharmony_ci		tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR);
623762306a36Sopenharmony_ci		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4);
623862306a36Sopenharmony_ci		/* Put BPHY in the reset */
623962306a36Sopenharmony_ci		b43_phy_set(dev, B43_PHY_B_BBCFG,
624062306a36Sopenharmony_ci			    B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX);
624162306a36Sopenharmony_ci		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16);
624262306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ);
624362306a36Sopenharmony_ci	} else if (new_channel->band == NL80211_BAND_2GHZ) {
624462306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
624562306a36Sopenharmony_ci		tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR);
624662306a36Sopenharmony_ci		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4);
624762306a36Sopenharmony_ci		/* Take BPHY out of the reset */
624862306a36Sopenharmony_ci		b43_phy_mask(dev, B43_PHY_B_BBCFG,
624962306a36Sopenharmony_ci			     (u16)~(B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX));
625062306a36Sopenharmony_ci		b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16);
625162306a36Sopenharmony_ci	}
625262306a36Sopenharmony_ci
625362306a36Sopenharmony_ci	b43_chantab_phy_upload(dev, e);
625462306a36Sopenharmony_ci
625562306a36Sopenharmony_ci	if (new_channel->hw_value == 14) {
625662306a36Sopenharmony_ci		b43_nphy_classifier(dev, 2, 0);
625762306a36Sopenharmony_ci		b43_phy_set(dev, B43_PHY_B_TEST, 0x0800);
625862306a36Sopenharmony_ci	} else {
625962306a36Sopenharmony_ci		b43_nphy_classifier(dev, 2, 2);
626062306a36Sopenharmony_ci		if (new_channel->band == NL80211_BAND_2GHZ)
626162306a36Sopenharmony_ci			b43_phy_mask(dev, B43_PHY_B_TEST, ~0x840);
626262306a36Sopenharmony_ci	}
626362306a36Sopenharmony_ci
626462306a36Sopenharmony_ci	if (!nphy->txpwrctrl)
626562306a36Sopenharmony_ci		b43_nphy_tx_power_fix(dev);
626662306a36Sopenharmony_ci
626762306a36Sopenharmony_ci	if (dev->phy.rev < 3)
626862306a36Sopenharmony_ci		b43_nphy_adjust_lna_gain_table(dev);
626962306a36Sopenharmony_ci
627062306a36Sopenharmony_ci	b43_nphy_tx_lpf_bw(dev);
627162306a36Sopenharmony_ci
627262306a36Sopenharmony_ci	if (dev->phy.rev >= 3 &&
627362306a36Sopenharmony_ci	    dev->phy.n->spur_avoid != B43_SPUR_AVOID_DISABLE) {
627462306a36Sopenharmony_ci		u8 spuravoid = 0;
627562306a36Sopenharmony_ci
627662306a36Sopenharmony_ci		if (dev->phy.n->spur_avoid == B43_SPUR_AVOID_FORCE) {
627762306a36Sopenharmony_ci			spuravoid = 1;
627862306a36Sopenharmony_ci		} else if (phy->rev >= 19) {
627962306a36Sopenharmony_ci			/* TODO */
628062306a36Sopenharmony_ci		} else if (phy->rev >= 18) {
628162306a36Sopenharmony_ci			/* TODO */
628262306a36Sopenharmony_ci		} else if (phy->rev >= 17) {
628362306a36Sopenharmony_ci			/* TODO: Off for channels 1-11, but check 12-14! */
628462306a36Sopenharmony_ci		} else if (phy->rev >= 16) {
628562306a36Sopenharmony_ci			/* TODO: Off for 2 GHz, but check 5 GHz! */
628662306a36Sopenharmony_ci		} else if (phy->rev >= 7) {
628762306a36Sopenharmony_ci			if (!b43_is_40mhz(dev)) { /* 20MHz */
628862306a36Sopenharmony_ci				if (ch == 13 || ch == 14 || ch == 153)
628962306a36Sopenharmony_ci					spuravoid = 1;
629062306a36Sopenharmony_ci			} else { /* 40 MHz */
629162306a36Sopenharmony_ci				if (ch == 54)
629262306a36Sopenharmony_ci					spuravoid = 1;
629362306a36Sopenharmony_ci			}
629462306a36Sopenharmony_ci		} else {
629562306a36Sopenharmony_ci			if (!b43_is_40mhz(dev)) { /* 20MHz */
629662306a36Sopenharmony_ci				if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14)
629762306a36Sopenharmony_ci					spuravoid = 1;
629862306a36Sopenharmony_ci			} else { /* 40MHz */
629962306a36Sopenharmony_ci				if (nphy->aband_spurwar_en &&
630062306a36Sopenharmony_ci				    (ch == 38 || ch == 102 || ch == 118))
630162306a36Sopenharmony_ci					spuravoid = dev->dev->chip_id == 0x4716;
630262306a36Sopenharmony_ci			}
630362306a36Sopenharmony_ci		}
630462306a36Sopenharmony_ci
630562306a36Sopenharmony_ci		b43_nphy_pmu_spur_avoid(dev, spuravoid);
630662306a36Sopenharmony_ci
630762306a36Sopenharmony_ci		b43_mac_switch_freq(dev, spuravoid);
630862306a36Sopenharmony_ci
630962306a36Sopenharmony_ci		if (dev->phy.rev == 3 || dev->phy.rev == 4)
631062306a36Sopenharmony_ci			b43_wireless_core_phy_pll_reset(dev);
631162306a36Sopenharmony_ci
631262306a36Sopenharmony_ci		if (spuravoid)
631362306a36Sopenharmony_ci			b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTRX);
631462306a36Sopenharmony_ci		else
631562306a36Sopenharmony_ci			b43_phy_mask(dev, B43_NPHY_BBCFG,
631662306a36Sopenharmony_ci				     ~B43_NPHY_BBCFG_RSTRX & 0xFFFF);
631762306a36Sopenharmony_ci
631862306a36Sopenharmony_ci		b43_nphy_reset_cca(dev);
631962306a36Sopenharmony_ci
632062306a36Sopenharmony_ci		/* wl sets useless phy_isspuravoid here */
632162306a36Sopenharmony_ci	}
632262306a36Sopenharmony_ci
632362306a36Sopenharmony_ci	b43_phy_write(dev, B43_NPHY_NDATAT_DUP40, 0x3830);
632462306a36Sopenharmony_ci
632562306a36Sopenharmony_ci	if (phy->rev >= 3)
632662306a36Sopenharmony_ci		b43_nphy_spur_workaround(dev);
632762306a36Sopenharmony_ci}
632862306a36Sopenharmony_ci
632962306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */
633062306a36Sopenharmony_cistatic int b43_nphy_set_channel(struct b43_wldev *dev,
633162306a36Sopenharmony_ci				struct ieee80211_channel *channel,
633262306a36Sopenharmony_ci				enum nl80211_channel_type channel_type)
633362306a36Sopenharmony_ci{
633462306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
633562306a36Sopenharmony_ci
633662306a36Sopenharmony_ci	const struct b43_nphy_channeltab_entry_rev2 *tabent_r2 = NULL;
633762306a36Sopenharmony_ci	const struct b43_nphy_channeltab_entry_rev3 *tabent_r3 = NULL;
633862306a36Sopenharmony_ci	const struct b43_nphy_chantabent_rev7 *tabent_r7 = NULL;
633962306a36Sopenharmony_ci	const struct b43_nphy_chantabent_rev7_2g *tabent_r7_2g = NULL;
634062306a36Sopenharmony_ci
634162306a36Sopenharmony_ci	u8 tmp;
634262306a36Sopenharmony_ci
634362306a36Sopenharmony_ci	if (phy->rev >= 19) {
634462306a36Sopenharmony_ci		return -ESRCH;
634562306a36Sopenharmony_ci		/* TODO */
634662306a36Sopenharmony_ci	} else if (phy->rev >= 7) {
634762306a36Sopenharmony_ci		r2057_get_chantabent_rev7(dev, channel->center_freq,
634862306a36Sopenharmony_ci					  &tabent_r7, &tabent_r7_2g);
634962306a36Sopenharmony_ci		if (!tabent_r7 && !tabent_r7_2g)
635062306a36Sopenharmony_ci			return -ESRCH;
635162306a36Sopenharmony_ci	} else if (phy->rev >= 3) {
635262306a36Sopenharmony_ci		tabent_r3 = b43_nphy_get_chantabent_rev3(dev,
635362306a36Sopenharmony_ci							channel->center_freq);
635462306a36Sopenharmony_ci		if (!tabent_r3)
635562306a36Sopenharmony_ci			return -ESRCH;
635662306a36Sopenharmony_ci	} else {
635762306a36Sopenharmony_ci		tabent_r2 = b43_nphy_get_chantabent_rev2(dev,
635862306a36Sopenharmony_ci							channel->hw_value);
635962306a36Sopenharmony_ci		if (!tabent_r2)
636062306a36Sopenharmony_ci			return -ESRCH;
636162306a36Sopenharmony_ci	}
636262306a36Sopenharmony_ci
636362306a36Sopenharmony_ci	/* Channel is set later in common code, but we need to set it on our
636462306a36Sopenharmony_ci	   own to let this function's subcalls work properly. */
636562306a36Sopenharmony_ci	phy->channel = channel->hw_value;
636662306a36Sopenharmony_ci
636762306a36Sopenharmony_ci#if 0
636862306a36Sopenharmony_ci	if (b43_channel_type_is_40mhz(phy->channel_type) !=
636962306a36Sopenharmony_ci		b43_channel_type_is_40mhz(channel_type))
637062306a36Sopenharmony_ci		; /* TODO: BMAC BW Set (channel_type) */
637162306a36Sopenharmony_ci#endif
637262306a36Sopenharmony_ci
637362306a36Sopenharmony_ci	if (channel_type == NL80211_CHAN_HT40PLUS) {
637462306a36Sopenharmony_ci		b43_phy_set(dev, B43_NPHY_RXCTL, B43_NPHY_RXCTL_BSELU20);
637562306a36Sopenharmony_ci		if (phy->rev >= 7)
637662306a36Sopenharmony_ci			b43_phy_set(dev, 0x310, 0x8000);
637762306a36Sopenharmony_ci	} else if (channel_type == NL80211_CHAN_HT40MINUS) {
637862306a36Sopenharmony_ci		b43_phy_mask(dev, B43_NPHY_RXCTL, ~B43_NPHY_RXCTL_BSELU20);
637962306a36Sopenharmony_ci		if (phy->rev >= 7)
638062306a36Sopenharmony_ci			b43_phy_mask(dev, 0x310, (u16)~0x8000);
638162306a36Sopenharmony_ci	}
638262306a36Sopenharmony_ci
638362306a36Sopenharmony_ci	if (phy->rev >= 19) {
638462306a36Sopenharmony_ci		/* TODO */
638562306a36Sopenharmony_ci	} else if (phy->rev >= 7) {
638662306a36Sopenharmony_ci		const struct b43_phy_n_sfo_cfg *phy_regs = tabent_r7 ?
638762306a36Sopenharmony_ci			&(tabent_r7->phy_regs) : &(tabent_r7_2g->phy_regs);
638862306a36Sopenharmony_ci
638962306a36Sopenharmony_ci		if (phy->radio_rev <= 4 || phy->radio_rev == 6) {
639062306a36Sopenharmony_ci			tmp = (channel->band == NL80211_BAND_5GHZ) ? 2 : 0;
639162306a36Sopenharmony_ci			b43_radio_maskset(dev, R2057_TIA_CONFIG_CORE0, ~2, tmp);
639262306a36Sopenharmony_ci			b43_radio_maskset(dev, R2057_TIA_CONFIG_CORE1, ~2, tmp);
639362306a36Sopenharmony_ci		}
639462306a36Sopenharmony_ci
639562306a36Sopenharmony_ci		b43_radio_2057_setup(dev, tabent_r7, tabent_r7_2g);
639662306a36Sopenharmony_ci		b43_nphy_channel_setup(dev, phy_regs, channel);
639762306a36Sopenharmony_ci	} else if (phy->rev >= 3) {
639862306a36Sopenharmony_ci		tmp = (channel->band == NL80211_BAND_5GHZ) ? 4 : 0;
639962306a36Sopenharmony_ci		b43_radio_maskset(dev, 0x08, 0xFFFB, tmp);
640062306a36Sopenharmony_ci		b43_radio_2056_setup(dev, tabent_r3);
640162306a36Sopenharmony_ci		b43_nphy_channel_setup(dev, &(tabent_r3->phy_regs), channel);
640262306a36Sopenharmony_ci	} else {
640362306a36Sopenharmony_ci		tmp = (channel->band == NL80211_BAND_5GHZ) ? 0x0020 : 0x0050;
640462306a36Sopenharmony_ci		b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp);
640562306a36Sopenharmony_ci		b43_radio_2055_setup(dev, tabent_r2);
640662306a36Sopenharmony_ci		b43_nphy_channel_setup(dev, &(tabent_r2->phy_regs), channel);
640762306a36Sopenharmony_ci	}
640862306a36Sopenharmony_ci
640962306a36Sopenharmony_ci	return 0;
641062306a36Sopenharmony_ci}
641162306a36Sopenharmony_ci
641262306a36Sopenharmony_ci/**************************************************
641362306a36Sopenharmony_ci * Basic PHY ops.
641462306a36Sopenharmony_ci **************************************************/
641562306a36Sopenharmony_ci
641662306a36Sopenharmony_cistatic int b43_nphy_op_allocate(struct b43_wldev *dev)
641762306a36Sopenharmony_ci{
641862306a36Sopenharmony_ci	struct b43_phy_n *nphy;
641962306a36Sopenharmony_ci
642062306a36Sopenharmony_ci	nphy = kzalloc(sizeof(*nphy), GFP_KERNEL);
642162306a36Sopenharmony_ci	if (!nphy)
642262306a36Sopenharmony_ci		return -ENOMEM;
642362306a36Sopenharmony_ci
642462306a36Sopenharmony_ci	dev->phy.n = nphy;
642562306a36Sopenharmony_ci
642662306a36Sopenharmony_ci	return 0;
642762306a36Sopenharmony_ci}
642862306a36Sopenharmony_ci
642962306a36Sopenharmony_cistatic void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
643062306a36Sopenharmony_ci{
643162306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
643262306a36Sopenharmony_ci	struct b43_phy_n *nphy = phy->n;
643362306a36Sopenharmony_ci	struct ssb_sprom *sprom = dev->dev->bus_sprom;
643462306a36Sopenharmony_ci
643562306a36Sopenharmony_ci	memset(nphy, 0, sizeof(*nphy));
643662306a36Sopenharmony_ci
643762306a36Sopenharmony_ci	nphy->hang_avoid = (phy->rev == 3 || phy->rev == 4);
643862306a36Sopenharmony_ci	nphy->spur_avoid = (phy->rev >= 3) ?
643962306a36Sopenharmony_ci				B43_SPUR_AVOID_AUTO : B43_SPUR_AVOID_DISABLE;
644062306a36Sopenharmony_ci	nphy->gain_boost = true; /* this way we follow wl, assume it is true */
644162306a36Sopenharmony_ci	nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */
644262306a36Sopenharmony_ci	nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */
644362306a36Sopenharmony_ci	nphy->perical = 2; /* avoid additional rssi cal on init (like wl) */
644462306a36Sopenharmony_ci	/* 128 can mean disabled-by-default state of TX pwr ctl. Max value is
644562306a36Sopenharmony_ci	 * 0x7f == 127 and we check for 128 when restoring TX pwr ctl. */
644662306a36Sopenharmony_ci	nphy->tx_pwr_idx[0] = 128;
644762306a36Sopenharmony_ci	nphy->tx_pwr_idx[1] = 128;
644862306a36Sopenharmony_ci
644962306a36Sopenharmony_ci	/* Hardware TX power control and 5GHz power gain */
645062306a36Sopenharmony_ci	nphy->txpwrctrl = false;
645162306a36Sopenharmony_ci	nphy->pwg_gain_5ghz = false;
645262306a36Sopenharmony_ci	if (dev->phy.rev >= 3 ||
645362306a36Sopenharmony_ci	    (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&
645462306a36Sopenharmony_ci	     (dev->dev->core_rev == 11 || dev->dev->core_rev == 12))) {
645562306a36Sopenharmony_ci		nphy->txpwrctrl = true;
645662306a36Sopenharmony_ci		nphy->pwg_gain_5ghz = true;
645762306a36Sopenharmony_ci	} else if (sprom->revision >= 4) {
645862306a36Sopenharmony_ci		if (dev->phy.rev >= 2 &&
645962306a36Sopenharmony_ci		    (sprom->boardflags2_lo & B43_BFL2_TXPWRCTRL_EN)) {
646062306a36Sopenharmony_ci			nphy->txpwrctrl = true;
646162306a36Sopenharmony_ci#ifdef CONFIG_B43_SSB
646262306a36Sopenharmony_ci			if (dev->dev->bus_type == B43_BUS_SSB &&
646362306a36Sopenharmony_ci			    dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI) {
646462306a36Sopenharmony_ci				struct pci_dev *pdev =
646562306a36Sopenharmony_ci					dev->dev->sdev->bus->host_pci;
646662306a36Sopenharmony_ci				if (pdev->device == 0x4328 ||
646762306a36Sopenharmony_ci				    pdev->device == 0x432a)
646862306a36Sopenharmony_ci					nphy->pwg_gain_5ghz = true;
646962306a36Sopenharmony_ci			}
647062306a36Sopenharmony_ci#endif
647162306a36Sopenharmony_ci		} else if (sprom->boardflags2_lo & B43_BFL2_5G_PWRGAIN) {
647262306a36Sopenharmony_ci			nphy->pwg_gain_5ghz = true;
647362306a36Sopenharmony_ci		}
647462306a36Sopenharmony_ci	}
647562306a36Sopenharmony_ci
647662306a36Sopenharmony_ci	if (dev->phy.rev >= 3) {
647762306a36Sopenharmony_ci		nphy->ipa2g_on = sprom->fem.ghz2.extpa_gain == 2;
647862306a36Sopenharmony_ci		nphy->ipa5g_on = sprom->fem.ghz5.extpa_gain == 2;
647962306a36Sopenharmony_ci	}
648062306a36Sopenharmony_ci}
648162306a36Sopenharmony_ci
648262306a36Sopenharmony_cistatic void b43_nphy_op_free(struct b43_wldev *dev)
648362306a36Sopenharmony_ci{
648462306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
648562306a36Sopenharmony_ci	struct b43_phy_n *nphy = phy->n;
648662306a36Sopenharmony_ci
648762306a36Sopenharmony_ci	kfree(nphy);
648862306a36Sopenharmony_ci	phy->n = NULL;
648962306a36Sopenharmony_ci}
649062306a36Sopenharmony_ci
649162306a36Sopenharmony_cistatic int b43_nphy_op_init(struct b43_wldev *dev)
649262306a36Sopenharmony_ci{
649362306a36Sopenharmony_ci	return b43_phy_initn(dev);
649462306a36Sopenharmony_ci}
649562306a36Sopenharmony_ci
649662306a36Sopenharmony_cistatic inline void check_phyreg(struct b43_wldev *dev, u16 offset)
649762306a36Sopenharmony_ci{
649862306a36Sopenharmony_ci#if B43_DEBUG
649962306a36Sopenharmony_ci	if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) {
650062306a36Sopenharmony_ci		/* OFDM registers are onnly available on A/G-PHYs */
650162306a36Sopenharmony_ci		b43err(dev->wl, "Invalid OFDM PHY access at "
650262306a36Sopenharmony_ci		       "0x%04X on N-PHY\n", offset);
650362306a36Sopenharmony_ci		dump_stack();
650462306a36Sopenharmony_ci	}
650562306a36Sopenharmony_ci	if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) {
650662306a36Sopenharmony_ci		/* Ext-G registers are only available on G-PHYs */
650762306a36Sopenharmony_ci		b43err(dev->wl, "Invalid EXT-G PHY access at "
650862306a36Sopenharmony_ci		       "0x%04X on N-PHY\n", offset);
650962306a36Sopenharmony_ci		dump_stack();
651062306a36Sopenharmony_ci	}
651162306a36Sopenharmony_ci#endif /* B43_DEBUG */
651262306a36Sopenharmony_ci}
651362306a36Sopenharmony_ci
651462306a36Sopenharmony_cistatic void b43_nphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
651562306a36Sopenharmony_ci				 u16 set)
651662306a36Sopenharmony_ci{
651762306a36Sopenharmony_ci	check_phyreg(dev, reg);
651862306a36Sopenharmony_ci	b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
651962306a36Sopenharmony_ci	b43_maskset16(dev, B43_MMIO_PHY_DATA, mask, set);
652062306a36Sopenharmony_ci	dev->phy.writes_counter = 1;
652162306a36Sopenharmony_ci}
652262306a36Sopenharmony_ci
652362306a36Sopenharmony_cistatic u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg)
652462306a36Sopenharmony_ci{
652562306a36Sopenharmony_ci	/* Register 1 is a 32-bit register. */
652662306a36Sopenharmony_ci	B43_WARN_ON(dev->phy.rev < 7 && reg == 1);
652762306a36Sopenharmony_ci
652862306a36Sopenharmony_ci	if (dev->phy.rev >= 7)
652962306a36Sopenharmony_ci		reg |= 0x200; /* Radio 0x2057 */
653062306a36Sopenharmony_ci	else
653162306a36Sopenharmony_ci		reg |= 0x100;
653262306a36Sopenharmony_ci
653362306a36Sopenharmony_ci	b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);
653462306a36Sopenharmony_ci	return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
653562306a36Sopenharmony_ci}
653662306a36Sopenharmony_ci
653762306a36Sopenharmony_cistatic void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
653862306a36Sopenharmony_ci{
653962306a36Sopenharmony_ci	/* Register 1 is a 32-bit register. */
654062306a36Sopenharmony_ci	B43_WARN_ON(dev->phy.rev < 7 && reg == 1);
654162306a36Sopenharmony_ci
654262306a36Sopenharmony_ci	b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);
654362306a36Sopenharmony_ci	b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
654462306a36Sopenharmony_ci}
654562306a36Sopenharmony_ci
654662306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */
654762306a36Sopenharmony_cistatic void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
654862306a36Sopenharmony_ci					bool blocked)
654962306a36Sopenharmony_ci{
655062306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
655162306a36Sopenharmony_ci
655262306a36Sopenharmony_ci	if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
655362306a36Sopenharmony_ci		b43err(dev->wl, "MAC not suspended\n");
655462306a36Sopenharmony_ci
655562306a36Sopenharmony_ci	if (blocked) {
655662306a36Sopenharmony_ci		if (phy->rev >= 19) {
655762306a36Sopenharmony_ci			/* TODO */
655862306a36Sopenharmony_ci		} else if (phy->rev >= 8) {
655962306a36Sopenharmony_ci			b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
656062306a36Sopenharmony_ci				     ~B43_NPHY_RFCTL_CMD_CHIP0PU);
656162306a36Sopenharmony_ci		} else if (phy->rev >= 7) {
656262306a36Sopenharmony_ci			/* Nothing needed */
656362306a36Sopenharmony_ci		} else if (phy->rev >= 3) {
656462306a36Sopenharmony_ci			b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
656562306a36Sopenharmony_ci				     ~B43_NPHY_RFCTL_CMD_CHIP0PU);
656662306a36Sopenharmony_ci
656762306a36Sopenharmony_ci			b43_radio_mask(dev, 0x09, ~0x2);
656862306a36Sopenharmony_ci
656962306a36Sopenharmony_ci			b43_radio_write(dev, 0x204D, 0);
657062306a36Sopenharmony_ci			b43_radio_write(dev, 0x2053, 0);
657162306a36Sopenharmony_ci			b43_radio_write(dev, 0x2058, 0);
657262306a36Sopenharmony_ci			b43_radio_write(dev, 0x205E, 0);
657362306a36Sopenharmony_ci			b43_radio_mask(dev, 0x2062, ~0xF0);
657462306a36Sopenharmony_ci			b43_radio_write(dev, 0x2064, 0);
657562306a36Sopenharmony_ci
657662306a36Sopenharmony_ci			b43_radio_write(dev, 0x304D, 0);
657762306a36Sopenharmony_ci			b43_radio_write(dev, 0x3053, 0);
657862306a36Sopenharmony_ci			b43_radio_write(dev, 0x3058, 0);
657962306a36Sopenharmony_ci			b43_radio_write(dev, 0x305E, 0);
658062306a36Sopenharmony_ci			b43_radio_mask(dev, 0x3062, ~0xF0);
658162306a36Sopenharmony_ci			b43_radio_write(dev, 0x3064, 0);
658262306a36Sopenharmony_ci		}
658362306a36Sopenharmony_ci	} else {
658462306a36Sopenharmony_ci		if (phy->rev >= 19) {
658562306a36Sopenharmony_ci			/* TODO */
658662306a36Sopenharmony_ci		} else if (phy->rev >= 7) {
658762306a36Sopenharmony_ci			if (!dev->phy.radio_on)
658862306a36Sopenharmony_ci				b43_radio_2057_init(dev);
658962306a36Sopenharmony_ci			b43_switch_channel(dev, dev->phy.channel);
659062306a36Sopenharmony_ci		} else if (phy->rev >= 3) {
659162306a36Sopenharmony_ci			if (!dev->phy.radio_on)
659262306a36Sopenharmony_ci				b43_radio_init2056(dev);
659362306a36Sopenharmony_ci			b43_switch_channel(dev, dev->phy.channel);
659462306a36Sopenharmony_ci		} else {
659562306a36Sopenharmony_ci			b43_radio_init2055(dev);
659662306a36Sopenharmony_ci		}
659762306a36Sopenharmony_ci	}
659862306a36Sopenharmony_ci}
659962306a36Sopenharmony_ci
660062306a36Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */
660162306a36Sopenharmony_cistatic void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
660262306a36Sopenharmony_ci{
660362306a36Sopenharmony_ci	struct b43_phy *phy = &dev->phy;
660462306a36Sopenharmony_ci	u16 override = on ? 0x0 : 0x7FFF;
660562306a36Sopenharmony_ci	u16 core = on ? 0xD : 0x00FD;
660662306a36Sopenharmony_ci
660762306a36Sopenharmony_ci	if (phy->rev >= 19) {
660862306a36Sopenharmony_ci		/* TODO */
660962306a36Sopenharmony_ci	} else if (phy->rev >= 3) {
661062306a36Sopenharmony_ci		if (on) {
661162306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
661262306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
661362306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);
661462306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
661562306a36Sopenharmony_ci		} else {
661662306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
661762306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
661862306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
661962306a36Sopenharmony_ci			b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);
662062306a36Sopenharmony_ci		}
662162306a36Sopenharmony_ci	} else {
662262306a36Sopenharmony_ci		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
662362306a36Sopenharmony_ci	}
662462306a36Sopenharmony_ci}
662562306a36Sopenharmony_ci
662662306a36Sopenharmony_cistatic int b43_nphy_op_switch_channel(struct b43_wldev *dev,
662762306a36Sopenharmony_ci				      unsigned int new_channel)
662862306a36Sopenharmony_ci{
662962306a36Sopenharmony_ci	struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan;
663062306a36Sopenharmony_ci	enum nl80211_channel_type channel_type =
663162306a36Sopenharmony_ci		cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef);
663262306a36Sopenharmony_ci
663362306a36Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
663462306a36Sopenharmony_ci		if ((new_channel < 1) || (new_channel > 14))
663562306a36Sopenharmony_ci			return -EINVAL;
663662306a36Sopenharmony_ci	} else {
663762306a36Sopenharmony_ci		if (new_channel > 200)
663862306a36Sopenharmony_ci			return -EINVAL;
663962306a36Sopenharmony_ci	}
664062306a36Sopenharmony_ci
664162306a36Sopenharmony_ci	return b43_nphy_set_channel(dev, channel, channel_type);
664262306a36Sopenharmony_ci}
664362306a36Sopenharmony_ci
664462306a36Sopenharmony_cistatic unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev)
664562306a36Sopenharmony_ci{
664662306a36Sopenharmony_ci	if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
664762306a36Sopenharmony_ci		return 1;
664862306a36Sopenharmony_ci	return 36;
664962306a36Sopenharmony_ci}
665062306a36Sopenharmony_ci
665162306a36Sopenharmony_ciconst struct b43_phy_operations b43_phyops_n = {
665262306a36Sopenharmony_ci	.allocate		= b43_nphy_op_allocate,
665362306a36Sopenharmony_ci	.free			= b43_nphy_op_free,
665462306a36Sopenharmony_ci	.prepare_structs	= b43_nphy_op_prepare_structs,
665562306a36Sopenharmony_ci	.init			= b43_nphy_op_init,
665662306a36Sopenharmony_ci	.phy_maskset		= b43_nphy_op_maskset,
665762306a36Sopenharmony_ci	.radio_read		= b43_nphy_op_radio_read,
665862306a36Sopenharmony_ci	.radio_write		= b43_nphy_op_radio_write,
665962306a36Sopenharmony_ci	.software_rfkill	= b43_nphy_op_software_rfkill,
666062306a36Sopenharmony_ci	.switch_analog		= b43_nphy_op_switch_analog,
666162306a36Sopenharmony_ci	.switch_channel		= b43_nphy_op_switch_channel,
666262306a36Sopenharmony_ci	.get_default_chan	= b43_nphy_op_get_default_chan,
666362306a36Sopenharmony_ci	.recalc_txpower		= b43_nphy_op_recalc_txpower,
666462306a36Sopenharmony_ci};
6665