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, ¶ms[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