18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci Broadcom B43 wireless driver 58c2ecf20Sopenharmony_ci IEEE 802.11n PHY support 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci Copyright (c) 2008 Michael Buesch <m@bues.ch> 88c2ecf20Sopenharmony_ci Copyright (c) 2010-2011 Rafał Miłecki <zajec5@gmail.com> 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci*/ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <linux/cordic.h> 148c2ecf20Sopenharmony_ci#include <linux/delay.h> 158c2ecf20Sopenharmony_ci#include <linux/slab.h> 168c2ecf20Sopenharmony_ci#include <linux/types.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include "b43.h" 198c2ecf20Sopenharmony_ci#include "phy_n.h" 208c2ecf20Sopenharmony_ci#include "tables_nphy.h" 218c2ecf20Sopenharmony_ci#include "radio_2055.h" 228c2ecf20Sopenharmony_ci#include "radio_2056.h" 238c2ecf20Sopenharmony_ci#include "radio_2057.h" 248c2ecf20Sopenharmony_ci#include "main.h" 258c2ecf20Sopenharmony_ci#include "ppr.h" 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistruct nphy_txgains { 288c2ecf20Sopenharmony_ci u16 tx_lpf[2]; 298c2ecf20Sopenharmony_ci u16 txgm[2]; 308c2ecf20Sopenharmony_ci u16 pga[2]; 318c2ecf20Sopenharmony_ci u16 pad[2]; 328c2ecf20Sopenharmony_ci u16 ipa[2]; 338c2ecf20Sopenharmony_ci}; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistruct nphy_iqcal_params { 368c2ecf20Sopenharmony_ci u16 tx_lpf; 378c2ecf20Sopenharmony_ci u16 txgm; 388c2ecf20Sopenharmony_ci u16 pga; 398c2ecf20Sopenharmony_ci u16 pad; 408c2ecf20Sopenharmony_ci u16 ipa; 418c2ecf20Sopenharmony_ci u16 cal_gain; 428c2ecf20Sopenharmony_ci u16 ncorr[5]; 438c2ecf20Sopenharmony_ci}; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistruct nphy_iq_est { 468c2ecf20Sopenharmony_ci s32 iq0_prod; 478c2ecf20Sopenharmony_ci u32 i0_pwr; 488c2ecf20Sopenharmony_ci u32 q0_pwr; 498c2ecf20Sopenharmony_ci s32 iq1_prod; 508c2ecf20Sopenharmony_ci u32 i1_pwr; 518c2ecf20Sopenharmony_ci u32 q1_pwr; 528c2ecf20Sopenharmony_ci}; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cienum b43_nphy_rf_sequence { 558c2ecf20Sopenharmony_ci B43_RFSEQ_RX2TX, 568c2ecf20Sopenharmony_ci B43_RFSEQ_TX2RX, 578c2ecf20Sopenharmony_ci B43_RFSEQ_RESET2RX, 588c2ecf20Sopenharmony_ci B43_RFSEQ_UPDATE_GAINH, 598c2ecf20Sopenharmony_ci B43_RFSEQ_UPDATE_GAINL, 608c2ecf20Sopenharmony_ci B43_RFSEQ_UPDATE_GAINU, 618c2ecf20Sopenharmony_ci}; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cienum n_rf_ctl_over_cmd { 648c2ecf20Sopenharmony_ci N_RF_CTL_OVER_CMD_RXRF_PU = 0, 658c2ecf20Sopenharmony_ci N_RF_CTL_OVER_CMD_RX_PU = 1, 668c2ecf20Sopenharmony_ci N_RF_CTL_OVER_CMD_TX_PU = 2, 678c2ecf20Sopenharmony_ci N_RF_CTL_OVER_CMD_RX_GAIN = 3, 688c2ecf20Sopenharmony_ci N_RF_CTL_OVER_CMD_TX_GAIN = 4, 698c2ecf20Sopenharmony_ci}; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_cienum n_intc_override { 728c2ecf20Sopenharmony_ci N_INTC_OVERRIDE_OFF = 0, 738c2ecf20Sopenharmony_ci N_INTC_OVERRIDE_TRSW = 1, 748c2ecf20Sopenharmony_ci N_INTC_OVERRIDE_PA = 2, 758c2ecf20Sopenharmony_ci N_INTC_OVERRIDE_EXT_LNA_PU = 3, 768c2ecf20Sopenharmony_ci N_INTC_OVERRIDE_EXT_LNA_GAIN = 4, 778c2ecf20Sopenharmony_ci}; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cienum n_rssi_type { 808c2ecf20Sopenharmony_ci N_RSSI_W1 = 0, 818c2ecf20Sopenharmony_ci N_RSSI_W2, 828c2ecf20Sopenharmony_ci N_RSSI_NB, 838c2ecf20Sopenharmony_ci N_RSSI_IQ, 848c2ecf20Sopenharmony_ci N_RSSI_TSSI_2G, 858c2ecf20Sopenharmony_ci N_RSSI_TSSI_5G, 868c2ecf20Sopenharmony_ci N_RSSI_TBD, 878c2ecf20Sopenharmony_ci}; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cienum n_rail_type { 908c2ecf20Sopenharmony_ci N_RAIL_I = 0, 918c2ecf20Sopenharmony_ci N_RAIL_Q = 1, 928c2ecf20Sopenharmony_ci}; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_cistatic inline bool b43_nphy_ipa(struct b43_wldev *dev) 958c2ecf20Sopenharmony_ci{ 968c2ecf20Sopenharmony_ci enum nl80211_band band = b43_current_band(dev->wl); 978c2ecf20Sopenharmony_ci return ((dev->phy.n->ipa2g_on && band == NL80211_BAND_2GHZ) || 988c2ecf20Sopenharmony_ci (dev->phy.n->ipa5g_on && band == NL80211_BAND_5GHZ)); 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreGetState */ 1028c2ecf20Sopenharmony_cistatic u8 b43_nphy_get_rx_core_state(struct b43_wldev *dev) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci return (b43_phy_read(dev, B43_NPHY_RFSEQCA) & B43_NPHY_RFSEQCA_RXEN) >> 1058c2ecf20Sopenharmony_ci B43_NPHY_RFSEQCA_RXEN_SHIFT; 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci/************************************************** 1098c2ecf20Sopenharmony_ci * RF (just without b43_nphy_rf_ctl_intc_override) 1108c2ecf20Sopenharmony_ci **************************************************/ 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */ 1138c2ecf20Sopenharmony_cistatic void b43_nphy_force_rf_sequence(struct b43_wldev *dev, 1148c2ecf20Sopenharmony_ci enum b43_nphy_rf_sequence seq) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci static const u16 trigger[] = { 1178c2ecf20Sopenharmony_ci [B43_RFSEQ_RX2TX] = B43_NPHY_RFSEQTR_RX2TX, 1188c2ecf20Sopenharmony_ci [B43_RFSEQ_TX2RX] = B43_NPHY_RFSEQTR_TX2RX, 1198c2ecf20Sopenharmony_ci [B43_RFSEQ_RESET2RX] = B43_NPHY_RFSEQTR_RST2RX, 1208c2ecf20Sopenharmony_ci [B43_RFSEQ_UPDATE_GAINH] = B43_NPHY_RFSEQTR_UPGH, 1218c2ecf20Sopenharmony_ci [B43_RFSEQ_UPDATE_GAINL] = B43_NPHY_RFSEQTR_UPGL, 1228c2ecf20Sopenharmony_ci [B43_RFSEQ_UPDATE_GAINU] = B43_NPHY_RFSEQTR_UPGU, 1238c2ecf20Sopenharmony_ci }; 1248c2ecf20Sopenharmony_ci int i; 1258c2ecf20Sopenharmony_ci u16 seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci B43_WARN_ON(seq >= ARRAY_SIZE(trigger)); 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_RFSEQMODE, 1308c2ecf20Sopenharmony_ci B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER); 1318c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_RFSEQTR, trigger[seq]); 1328c2ecf20Sopenharmony_ci for (i = 0; i < 200; i++) { 1338c2ecf20Sopenharmony_ci if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & trigger[seq])) 1348c2ecf20Sopenharmony_ci goto ok; 1358c2ecf20Sopenharmony_ci msleep(1); 1368c2ecf20Sopenharmony_ci } 1378c2ecf20Sopenharmony_ci b43err(dev->wl, "RF sequence status timeout\n"); 1388c2ecf20Sopenharmony_ciok: 1398c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode); 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic void b43_nphy_rf_ctl_override_rev19(struct b43_wldev *dev, u16 field, 1438c2ecf20Sopenharmony_ci u16 value, u8 core, bool off, 1448c2ecf20Sopenharmony_ci u8 override_id) 1458c2ecf20Sopenharmony_ci{ 1468c2ecf20Sopenharmony_ci /* TODO */ 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverrideRev7 */ 1508c2ecf20Sopenharmony_cistatic void b43_nphy_rf_ctl_override_rev7(struct b43_wldev *dev, u16 field, 1518c2ecf20Sopenharmony_ci u16 value, u8 core, bool off, 1528c2ecf20Sopenharmony_ci u8 override) 1538c2ecf20Sopenharmony_ci{ 1548c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 1558c2ecf20Sopenharmony_ci const struct nphy_rf_control_override_rev7 *e; 1568c2ecf20Sopenharmony_ci u16 en_addrs[3][2] = { 1578c2ecf20Sopenharmony_ci { 0x0E7, 0x0EC }, { 0x342, 0x343 }, { 0x346, 0x347 } 1588c2ecf20Sopenharmony_ci }; 1598c2ecf20Sopenharmony_ci u16 en_addr; 1608c2ecf20Sopenharmony_ci u16 en_mask = field; 1618c2ecf20Sopenharmony_ci u16 val_addr; 1628c2ecf20Sopenharmony_ci u8 i; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci if (phy->rev >= 19 || phy->rev < 3) { 1658c2ecf20Sopenharmony_ci B43_WARN_ON(1); 1668c2ecf20Sopenharmony_ci return; 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci /* Remember: we can get NULL! */ 1708c2ecf20Sopenharmony_ci e = b43_nphy_get_rf_ctl_over_rev7(dev, field, override); 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 1738c2ecf20Sopenharmony_ci if (override >= ARRAY_SIZE(en_addrs)) { 1748c2ecf20Sopenharmony_ci b43err(dev->wl, "Invalid override value %d\n", override); 1758c2ecf20Sopenharmony_ci return; 1768c2ecf20Sopenharmony_ci } 1778c2ecf20Sopenharmony_ci en_addr = en_addrs[override][i]; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci if (e) 1808c2ecf20Sopenharmony_ci val_addr = (i == 0) ? e->val_addr_core0 : e->val_addr_core1; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci if (off) { 1838c2ecf20Sopenharmony_ci b43_phy_mask(dev, en_addr, ~en_mask); 1848c2ecf20Sopenharmony_ci if (e) /* Do it safer, better than wl */ 1858c2ecf20Sopenharmony_ci b43_phy_mask(dev, val_addr, ~e->val_mask); 1868c2ecf20Sopenharmony_ci } else { 1878c2ecf20Sopenharmony_ci if (!core || (core & (1 << i))) { 1888c2ecf20Sopenharmony_ci b43_phy_set(dev, en_addr, en_mask); 1898c2ecf20Sopenharmony_ci if (e) 1908c2ecf20Sopenharmony_ci b43_phy_maskset(dev, val_addr, ~e->val_mask, (value << e->val_shift)); 1918c2ecf20Sopenharmony_ci } 1928c2ecf20Sopenharmony_ci } 1938c2ecf20Sopenharmony_ci } 1948c2ecf20Sopenharmony_ci} 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverideOneToMany */ 1978c2ecf20Sopenharmony_cistatic void b43_nphy_rf_ctl_override_one_to_many(struct b43_wldev *dev, 1988c2ecf20Sopenharmony_ci enum n_rf_ctl_over_cmd cmd, 1998c2ecf20Sopenharmony_ci u16 value, u8 core, bool off) 2008c2ecf20Sopenharmony_ci{ 2018c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 2028c2ecf20Sopenharmony_ci u16 tmp; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci B43_WARN_ON(phy->rev < 7); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci switch (cmd) { 2078c2ecf20Sopenharmony_ci case N_RF_CTL_OVER_CMD_RXRF_PU: 2088c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x20, value, core, off, 1); 2098c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x10, value, core, off, 1); 2108c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x08, value, core, off, 1); 2118c2ecf20Sopenharmony_ci break; 2128c2ecf20Sopenharmony_ci case N_RF_CTL_OVER_CMD_RX_PU: 2138c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x4, value, core, off, 1); 2148c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 1); 2158c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x1, value, core, off, 1); 2168c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 2); 2178c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x0800, 0, core, off, 1); 2188c2ecf20Sopenharmony_ci break; 2198c2ecf20Sopenharmony_ci case N_RF_CTL_OVER_CMD_TX_PU: 2208c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x4, value, core, off, 0); 2218c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x2, value, core, off, 1); 2228c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x1, value, core, off, 2); 2238c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x0800, 1, core, off, 1); 2248c2ecf20Sopenharmony_ci break; 2258c2ecf20Sopenharmony_ci case N_RF_CTL_OVER_CMD_RX_GAIN: 2268c2ecf20Sopenharmony_ci tmp = value & 0xFF; 2278c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x0800, tmp, core, off, 0); 2288c2ecf20Sopenharmony_ci tmp = value >> 8; 2298c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x6000, tmp, core, off, 0); 2308c2ecf20Sopenharmony_ci break; 2318c2ecf20Sopenharmony_ci case N_RF_CTL_OVER_CMD_TX_GAIN: 2328c2ecf20Sopenharmony_ci tmp = value & 0x7FFF; 2338c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x1000, tmp, core, off, 0); 2348c2ecf20Sopenharmony_ci tmp = value >> 14; 2358c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x4000, tmp, core, off, 0); 2368c2ecf20Sopenharmony_ci break; 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci} 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */ 2418c2ecf20Sopenharmony_cistatic void b43_nphy_rf_ctl_override(struct b43_wldev *dev, u16 field, 2428c2ecf20Sopenharmony_ci u16 value, u8 core, bool off) 2438c2ecf20Sopenharmony_ci{ 2448c2ecf20Sopenharmony_ci int i; 2458c2ecf20Sopenharmony_ci u8 index = fls(field); 2468c2ecf20Sopenharmony_ci u8 addr, en_addr, val_addr; 2478c2ecf20Sopenharmony_ci /* we expect only one bit set */ 2488c2ecf20Sopenharmony_ci B43_WARN_ON(field & (~(1 << (index - 1)))); 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) { 2518c2ecf20Sopenharmony_ci const struct nphy_rf_control_override_rev3 *rf_ctrl; 2528c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 2538c2ecf20Sopenharmony_ci if (index == 0 || index == 16) { 2548c2ecf20Sopenharmony_ci b43err(dev->wl, 2558c2ecf20Sopenharmony_ci "Unsupported RF Ctrl Override call\n"); 2568c2ecf20Sopenharmony_ci return; 2578c2ecf20Sopenharmony_ci } 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci rf_ctrl = &tbl_rf_control_override_rev3[index - 1]; 2608c2ecf20Sopenharmony_ci en_addr = B43_PHY_N((i == 0) ? 2618c2ecf20Sopenharmony_ci rf_ctrl->en_addr0 : rf_ctrl->en_addr1); 2628c2ecf20Sopenharmony_ci val_addr = B43_PHY_N((i == 0) ? 2638c2ecf20Sopenharmony_ci rf_ctrl->val_addr0 : rf_ctrl->val_addr1); 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci if (off) { 2668c2ecf20Sopenharmony_ci b43_phy_mask(dev, en_addr, ~(field)); 2678c2ecf20Sopenharmony_ci b43_phy_mask(dev, val_addr, 2688c2ecf20Sopenharmony_ci ~(rf_ctrl->val_mask)); 2698c2ecf20Sopenharmony_ci } else { 2708c2ecf20Sopenharmony_ci if (core == 0 || ((1 << i) & core)) { 2718c2ecf20Sopenharmony_ci b43_phy_set(dev, en_addr, field); 2728c2ecf20Sopenharmony_ci b43_phy_maskset(dev, val_addr, 2738c2ecf20Sopenharmony_ci ~(rf_ctrl->val_mask), 2748c2ecf20Sopenharmony_ci (value << rf_ctrl->val_shift)); 2758c2ecf20Sopenharmony_ci } 2768c2ecf20Sopenharmony_ci } 2778c2ecf20Sopenharmony_ci } 2788c2ecf20Sopenharmony_ci } else { 2798c2ecf20Sopenharmony_ci const struct nphy_rf_control_override_rev2 *rf_ctrl; 2808c2ecf20Sopenharmony_ci if (off) { 2818c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~(field)); 2828c2ecf20Sopenharmony_ci value = 0; 2838c2ecf20Sopenharmony_ci } else { 2848c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_RFCTL_OVER, field); 2858c2ecf20Sopenharmony_ci } 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 2888c2ecf20Sopenharmony_ci if (index <= 1 || index == 16) { 2898c2ecf20Sopenharmony_ci b43err(dev->wl, 2908c2ecf20Sopenharmony_ci "Unsupported RF Ctrl Override call\n"); 2918c2ecf20Sopenharmony_ci return; 2928c2ecf20Sopenharmony_ci } 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci if (index == 2 || index == 10 || 2958c2ecf20Sopenharmony_ci (index >= 13 && index <= 15)) { 2968c2ecf20Sopenharmony_ci core = 1; 2978c2ecf20Sopenharmony_ci } 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci rf_ctrl = &tbl_rf_control_override_rev2[index - 2]; 3008c2ecf20Sopenharmony_ci addr = B43_PHY_N((i == 0) ? 3018c2ecf20Sopenharmony_ci rf_ctrl->addr0 : rf_ctrl->addr1); 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci if ((1 << i) & core) 3048c2ecf20Sopenharmony_ci b43_phy_maskset(dev, addr, ~(rf_ctrl->bmask), 3058c2ecf20Sopenharmony_ci (value << rf_ctrl->shift)); 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x1); 3088c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_RFCTL_CMD, 3098c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_CMD_START); 3108c2ecf20Sopenharmony_ci udelay(1); 3118c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, 0xFFFE); 3128c2ecf20Sopenharmony_ci } 3138c2ecf20Sopenharmony_ci } 3148c2ecf20Sopenharmony_ci} 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_cistatic void b43_nphy_rf_ctl_intc_override_rev7(struct b43_wldev *dev, 3178c2ecf20Sopenharmony_ci enum n_intc_override intc_override, 3188c2ecf20Sopenharmony_ci u16 value, u8 core_sel) 3198c2ecf20Sopenharmony_ci{ 3208c2ecf20Sopenharmony_ci u16 reg, tmp, tmp2, val; 3218c2ecf20Sopenharmony_ci int core; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci /* TODO: What about rev19+? Revs 3+ and 7+ are a bit similar */ 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci for (core = 0; core < 2; core++) { 3268c2ecf20Sopenharmony_ci if ((core_sel == 1 && core != 0) || 3278c2ecf20Sopenharmony_ci (core_sel == 2 && core != 1)) 3288c2ecf20Sopenharmony_ci continue; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci reg = (core == 0) ? B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci switch (intc_override) { 3338c2ecf20Sopenharmony_ci case N_INTC_OVERRIDE_OFF: 3348c2ecf20Sopenharmony_ci b43_phy_write(dev, reg, 0); 3358c2ecf20Sopenharmony_ci b43_phy_mask(dev, 0x2ff, ~0x2000); 3368c2ecf20Sopenharmony_ci b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); 3378c2ecf20Sopenharmony_ci break; 3388c2ecf20Sopenharmony_ci case N_INTC_OVERRIDE_TRSW: 3398c2ecf20Sopenharmony_ci b43_phy_maskset(dev, reg, ~0xC0, value << 6); 3408c2ecf20Sopenharmony_ci b43_phy_set(dev, reg, 0x400); 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci b43_phy_mask(dev, 0x2ff, ~0xC000 & 0xFFFF); 3438c2ecf20Sopenharmony_ci b43_phy_set(dev, 0x2ff, 0x2000); 3448c2ecf20Sopenharmony_ci b43_phy_set(dev, 0x2ff, 0x0001); 3458c2ecf20Sopenharmony_ci break; 3468c2ecf20Sopenharmony_ci case N_INTC_OVERRIDE_PA: 3478c2ecf20Sopenharmony_ci tmp = 0x0030; 3488c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) 3498c2ecf20Sopenharmony_ci val = value << 5; 3508c2ecf20Sopenharmony_ci else 3518c2ecf20Sopenharmony_ci val = value << 4; 3528c2ecf20Sopenharmony_ci b43_phy_maskset(dev, reg, ~tmp, val); 3538c2ecf20Sopenharmony_ci b43_phy_set(dev, reg, 0x1000); 3548c2ecf20Sopenharmony_ci break; 3558c2ecf20Sopenharmony_ci case N_INTC_OVERRIDE_EXT_LNA_PU: 3568c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { 3578c2ecf20Sopenharmony_ci tmp = 0x0001; 3588c2ecf20Sopenharmony_ci tmp2 = 0x0004; 3598c2ecf20Sopenharmony_ci val = value; 3608c2ecf20Sopenharmony_ci } else { 3618c2ecf20Sopenharmony_ci tmp = 0x0004; 3628c2ecf20Sopenharmony_ci tmp2 = 0x0001; 3638c2ecf20Sopenharmony_ci val = value << 2; 3648c2ecf20Sopenharmony_ci } 3658c2ecf20Sopenharmony_ci b43_phy_maskset(dev, reg, ~tmp, val); 3668c2ecf20Sopenharmony_ci b43_phy_mask(dev, reg, ~tmp2); 3678c2ecf20Sopenharmony_ci break; 3688c2ecf20Sopenharmony_ci case N_INTC_OVERRIDE_EXT_LNA_GAIN: 3698c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { 3708c2ecf20Sopenharmony_ci tmp = 0x0002; 3718c2ecf20Sopenharmony_ci tmp2 = 0x0008; 3728c2ecf20Sopenharmony_ci val = value << 1; 3738c2ecf20Sopenharmony_ci } else { 3748c2ecf20Sopenharmony_ci tmp = 0x0008; 3758c2ecf20Sopenharmony_ci tmp2 = 0x0002; 3768c2ecf20Sopenharmony_ci val = value << 3; 3778c2ecf20Sopenharmony_ci } 3788c2ecf20Sopenharmony_ci b43_phy_maskset(dev, reg, ~tmp, val); 3798c2ecf20Sopenharmony_ci b43_phy_mask(dev, reg, ~tmp2); 3808c2ecf20Sopenharmony_ci break; 3818c2ecf20Sopenharmony_ci } 3828c2ecf20Sopenharmony_ci } 3838c2ecf20Sopenharmony_ci} 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlIntcOverride */ 3868c2ecf20Sopenharmony_cistatic void b43_nphy_rf_ctl_intc_override(struct b43_wldev *dev, 3878c2ecf20Sopenharmony_ci enum n_intc_override intc_override, 3888c2ecf20Sopenharmony_ci u16 value, u8 core) 3898c2ecf20Sopenharmony_ci{ 3908c2ecf20Sopenharmony_ci u8 i, j; 3918c2ecf20Sopenharmony_ci u16 reg, tmp, val; 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci if (dev->phy.rev >= 7) { 3948c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_intc_override_rev7(dev, intc_override, value, 3958c2ecf20Sopenharmony_ci core); 3968c2ecf20Sopenharmony_ci return; 3978c2ecf20Sopenharmony_ci } 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci B43_WARN_ON(dev->phy.rev < 3); 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 4028c2ecf20Sopenharmony_ci if ((core == 1 && i == 1) || (core == 2 && !i)) 4038c2ecf20Sopenharmony_ci continue; 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci reg = (i == 0) ? 4068c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2; 4078c2ecf20Sopenharmony_ci b43_phy_set(dev, reg, 0x400); 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci switch (intc_override) { 4108c2ecf20Sopenharmony_ci case N_INTC_OVERRIDE_OFF: 4118c2ecf20Sopenharmony_ci b43_phy_write(dev, reg, 0); 4128c2ecf20Sopenharmony_ci b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); 4138c2ecf20Sopenharmony_ci break; 4148c2ecf20Sopenharmony_ci case N_INTC_OVERRIDE_TRSW: 4158c2ecf20Sopenharmony_ci if (!i) { 4168c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC1, 4178c2ecf20Sopenharmony_ci 0xFC3F, (value << 6)); 4188c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_TXF_40CO_B1S1, 4198c2ecf20Sopenharmony_ci 0xFFFE, 1); 4208c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_RFCTL_CMD, 4218c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_CMD_START); 4228c2ecf20Sopenharmony_ci for (j = 0; j < 100; j++) { 4238c2ecf20Sopenharmony_ci if (!(b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_START)) { 4248c2ecf20Sopenharmony_ci j = 0; 4258c2ecf20Sopenharmony_ci break; 4268c2ecf20Sopenharmony_ci } 4278c2ecf20Sopenharmony_ci udelay(10); 4288c2ecf20Sopenharmony_ci } 4298c2ecf20Sopenharmony_ci if (j) 4308c2ecf20Sopenharmony_ci b43err(dev->wl, 4318c2ecf20Sopenharmony_ci "intc override timeout\n"); 4328c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S1, 4338c2ecf20Sopenharmony_ci 0xFFFE); 4348c2ecf20Sopenharmony_ci } else { 4358c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC2, 4368c2ecf20Sopenharmony_ci 0xFC3F, (value << 6)); 4378c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 4388c2ecf20Sopenharmony_ci 0xFFFE, 1); 4398c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_RFCTL_CMD, 4408c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_CMD_RXTX); 4418c2ecf20Sopenharmony_ci for (j = 0; j < 100; j++) { 4428c2ecf20Sopenharmony_ci if (!(b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_RXTX)) { 4438c2ecf20Sopenharmony_ci j = 0; 4448c2ecf20Sopenharmony_ci break; 4458c2ecf20Sopenharmony_ci } 4468c2ecf20Sopenharmony_ci udelay(10); 4478c2ecf20Sopenharmony_ci } 4488c2ecf20Sopenharmony_ci if (j) 4498c2ecf20Sopenharmony_ci b43err(dev->wl, 4508c2ecf20Sopenharmony_ci "intc override timeout\n"); 4518c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, 4528c2ecf20Sopenharmony_ci 0xFFFE); 4538c2ecf20Sopenharmony_ci } 4548c2ecf20Sopenharmony_ci break; 4558c2ecf20Sopenharmony_ci case N_INTC_OVERRIDE_PA: 4568c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { 4578c2ecf20Sopenharmony_ci tmp = 0x0020; 4588c2ecf20Sopenharmony_ci val = value << 5; 4598c2ecf20Sopenharmony_ci } else { 4608c2ecf20Sopenharmony_ci tmp = 0x0010; 4618c2ecf20Sopenharmony_ci val = value << 4; 4628c2ecf20Sopenharmony_ci } 4638c2ecf20Sopenharmony_ci b43_phy_maskset(dev, reg, ~tmp, val); 4648c2ecf20Sopenharmony_ci break; 4658c2ecf20Sopenharmony_ci case N_INTC_OVERRIDE_EXT_LNA_PU: 4668c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { 4678c2ecf20Sopenharmony_ci tmp = 0x0001; 4688c2ecf20Sopenharmony_ci val = value; 4698c2ecf20Sopenharmony_ci } else { 4708c2ecf20Sopenharmony_ci tmp = 0x0004; 4718c2ecf20Sopenharmony_ci val = value << 2; 4728c2ecf20Sopenharmony_ci } 4738c2ecf20Sopenharmony_ci b43_phy_maskset(dev, reg, ~tmp, val); 4748c2ecf20Sopenharmony_ci break; 4758c2ecf20Sopenharmony_ci case N_INTC_OVERRIDE_EXT_LNA_GAIN: 4768c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { 4778c2ecf20Sopenharmony_ci tmp = 0x0002; 4788c2ecf20Sopenharmony_ci val = value << 1; 4798c2ecf20Sopenharmony_ci } else { 4808c2ecf20Sopenharmony_ci tmp = 0x0008; 4818c2ecf20Sopenharmony_ci val = value << 3; 4828c2ecf20Sopenharmony_ci } 4838c2ecf20Sopenharmony_ci b43_phy_maskset(dev, reg, ~tmp, val); 4848c2ecf20Sopenharmony_ci break; 4858c2ecf20Sopenharmony_ci } 4868c2ecf20Sopenharmony_ci } 4878c2ecf20Sopenharmony_ci} 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci/************************************************** 4908c2ecf20Sopenharmony_ci * Various PHY ops 4918c2ecf20Sopenharmony_ci **************************************************/ 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */ 4948c2ecf20Sopenharmony_cistatic void b43_nphy_write_clip_detection(struct b43_wldev *dev, 4958c2ecf20Sopenharmony_ci const u16 *clip_st) 4968c2ecf20Sopenharmony_ci{ 4978c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_C1_CLIP1THRES, clip_st[0]); 4988c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_C2_CLIP1THRES, clip_st[1]); 4998c2ecf20Sopenharmony_ci} 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */ 5028c2ecf20Sopenharmony_cistatic void b43_nphy_read_clip_detection(struct b43_wldev *dev, u16 *clip_st) 5038c2ecf20Sopenharmony_ci{ 5048c2ecf20Sopenharmony_ci clip_st[0] = b43_phy_read(dev, B43_NPHY_C1_CLIP1THRES); 5058c2ecf20Sopenharmony_ci clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES); 5068c2ecf20Sopenharmony_ci} 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */ 5098c2ecf20Sopenharmony_cistatic u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val) 5108c2ecf20Sopenharmony_ci{ 5118c2ecf20Sopenharmony_ci u16 tmp; 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci if (dev->dev->core_rev == 16) 5148c2ecf20Sopenharmony_ci b43_mac_suspend(dev); 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL); 5178c2ecf20Sopenharmony_ci tmp &= (B43_NPHY_CLASSCTL_CCKEN | B43_NPHY_CLASSCTL_OFDMEN | 5188c2ecf20Sopenharmony_ci B43_NPHY_CLASSCTL_WAITEDEN); 5198c2ecf20Sopenharmony_ci tmp &= ~mask; 5208c2ecf20Sopenharmony_ci tmp |= (val & mask); 5218c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp); 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci if (dev->dev->core_rev == 16) 5248c2ecf20Sopenharmony_ci b43_mac_enable(dev); 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci return tmp; 5278c2ecf20Sopenharmony_ci} 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */ 5308c2ecf20Sopenharmony_cistatic void b43_nphy_reset_cca(struct b43_wldev *dev) 5318c2ecf20Sopenharmony_ci{ 5328c2ecf20Sopenharmony_ci u16 bbcfg; 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci b43_phy_force_clock(dev, 1); 5358c2ecf20Sopenharmony_ci bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG); 5368c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA); 5378c2ecf20Sopenharmony_ci udelay(1); 5388c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA); 5398c2ecf20Sopenharmony_ci b43_phy_force_clock(dev, 0); 5408c2ecf20Sopenharmony_ci b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); 5418c2ecf20Sopenharmony_ci} 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/carriersearch */ 5448c2ecf20Sopenharmony_cistatic void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable) 5458c2ecf20Sopenharmony_ci{ 5468c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 5478c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = phy->n; 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci if (enable) { 5508c2ecf20Sopenharmony_ci static const u16 clip[] = { 0xFFFF, 0xFFFF }; 5518c2ecf20Sopenharmony_ci if (nphy->deaf_count++ == 0) { 5528c2ecf20Sopenharmony_ci nphy->classifier_state = b43_nphy_classifier(dev, 0, 0); 5538c2ecf20Sopenharmony_ci b43_nphy_classifier(dev, 0x7, 5548c2ecf20Sopenharmony_ci B43_NPHY_CLASSCTL_WAITEDEN); 5558c2ecf20Sopenharmony_ci b43_nphy_read_clip_detection(dev, nphy->clip_state); 5568c2ecf20Sopenharmony_ci b43_nphy_write_clip_detection(dev, clip); 5578c2ecf20Sopenharmony_ci } 5588c2ecf20Sopenharmony_ci b43_nphy_reset_cca(dev); 5598c2ecf20Sopenharmony_ci } else { 5608c2ecf20Sopenharmony_ci if (--nphy->deaf_count == 0) { 5618c2ecf20Sopenharmony_ci b43_nphy_classifier(dev, 0x7, nphy->classifier_state); 5628c2ecf20Sopenharmony_ci b43_nphy_write_clip_detection(dev, nphy->clip_state); 5638c2ecf20Sopenharmony_ci } 5648c2ecf20Sopenharmony_ci } 5658c2ecf20Sopenharmony_ci} 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/PHY/N/Read_Lpf_Bw_Ctl */ 5688c2ecf20Sopenharmony_cistatic u16 b43_nphy_read_lpf_ctl(struct b43_wldev *dev, u16 offset) 5698c2ecf20Sopenharmony_ci{ 5708c2ecf20Sopenharmony_ci if (!offset) 5718c2ecf20Sopenharmony_ci offset = b43_is_40mhz(dev) ? 0x159 : 0x154; 5728c2ecf20Sopenharmony_ci return b43_ntab_read(dev, B43_NTAB16(7, offset)) & 0x7; 5738c2ecf20Sopenharmony_ci} 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */ 5768c2ecf20Sopenharmony_cistatic void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev) 5778c2ecf20Sopenharmony_ci{ 5788c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci u8 i; 5818c2ecf20Sopenharmony_ci s16 tmp; 5828c2ecf20Sopenharmony_ci u16 data[4]; 5838c2ecf20Sopenharmony_ci s16 gain[2]; 5848c2ecf20Sopenharmony_ci u16 minmax[2]; 5858c2ecf20Sopenharmony_ci static const s16 lna_gain[4] = { -2, 10, 19, 25 }; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 5888c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, 1); 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci if (nphy->gain_boost) { 5918c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { 5928c2ecf20Sopenharmony_ci gain[0] = 6; 5938c2ecf20Sopenharmony_ci gain[1] = 6; 5948c2ecf20Sopenharmony_ci } else { 5958c2ecf20Sopenharmony_ci tmp = 40370 - 315 * dev->phy.channel; 5968c2ecf20Sopenharmony_ci gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1)); 5978c2ecf20Sopenharmony_ci tmp = 23242 - 224 * dev->phy.channel; 5988c2ecf20Sopenharmony_ci gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1)); 5998c2ecf20Sopenharmony_ci } 6008c2ecf20Sopenharmony_ci } else { 6018c2ecf20Sopenharmony_ci gain[0] = 0; 6028c2ecf20Sopenharmony_ci gain[1] = 0; 6038c2ecf20Sopenharmony_ci } 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 6068c2ecf20Sopenharmony_ci if (nphy->elna_gain_config) { 6078c2ecf20Sopenharmony_ci data[0] = 19 + gain[i]; 6088c2ecf20Sopenharmony_ci data[1] = 25 + gain[i]; 6098c2ecf20Sopenharmony_ci data[2] = 25 + gain[i]; 6108c2ecf20Sopenharmony_ci data[3] = 25 + gain[i]; 6118c2ecf20Sopenharmony_ci } else { 6128c2ecf20Sopenharmony_ci data[0] = lna_gain[0] + gain[i]; 6138c2ecf20Sopenharmony_ci data[1] = lna_gain[1] + gain[i]; 6148c2ecf20Sopenharmony_ci data[2] = lna_gain[2] + gain[i]; 6158c2ecf20Sopenharmony_ci data[3] = lna_gain[3] + gain[i]; 6168c2ecf20Sopenharmony_ci } 6178c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(i, 8), 4, data); 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci minmax[i] = 23 + gain[i]; 6208c2ecf20Sopenharmony_ci } 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN, ~B43_NPHY_C1_MINGAIN, 6238c2ecf20Sopenharmony_ci minmax[0] << B43_NPHY_C1_MINGAIN_SHIFT); 6248c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN, ~B43_NPHY_C2_MINGAIN, 6258c2ecf20Sopenharmony_ci minmax[1] << B43_NPHY_C2_MINGAIN_SHIFT); 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 6288c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, 0); 6298c2ecf20Sopenharmony_ci} 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRfSeq */ 6328c2ecf20Sopenharmony_cistatic void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd, 6338c2ecf20Sopenharmony_ci u8 *events, u8 *delays, u8 length) 6348c2ecf20Sopenharmony_ci{ 6358c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 6368c2ecf20Sopenharmony_ci u8 i; 6378c2ecf20Sopenharmony_ci u8 end = (dev->phy.rev >= 3) ? 0x1F : 0x0F; 6388c2ecf20Sopenharmony_ci u16 offset1 = cmd << 4; 6398c2ecf20Sopenharmony_ci u16 offset2 = offset1 + 0x80; 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 6428c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, true); 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB8(7, offset1), length, events); 6458c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB8(7, offset2), length, delays); 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci for (i = length; i < 16; i++) { 6488c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB8(7, offset1 + i), end); 6498c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB8(7, offset2 + i), 1); 6508c2ecf20Sopenharmony_ci } 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 6538c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, false); 6548c2ecf20Sopenharmony_ci} 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci/************************************************** 6578c2ecf20Sopenharmony_ci * Radio 0x2057 6588c2ecf20Sopenharmony_ci **************************************************/ 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_cistatic void b43_radio_2057_chantab_upload(struct b43_wldev *dev, 6618c2ecf20Sopenharmony_ci const struct b43_nphy_chantabent_rev7 *e_r7, 6628c2ecf20Sopenharmony_ci const struct b43_nphy_chantabent_rev7_2g *e_r7_2g) 6638c2ecf20Sopenharmony_ci{ 6648c2ecf20Sopenharmony_ci if (e_r7_2g) { 6658c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_VCOCAL_COUNTVAL0, e_r7_2g->radio_vcocal_countval0); 6668c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_VCOCAL_COUNTVAL1, e_r7_2g->radio_vcocal_countval1); 6678c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RFPLL_REFMASTER_SPAREXTALSIZE, e_r7_2g->radio_rfpll_refmaster_sparextalsize); 6688c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, e_r7_2g->radio_rfpll_loopfilter_r1); 6698c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, e_r7_2g->radio_rfpll_loopfilter_c2); 6708c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, e_r7_2g->radio_rfpll_loopfilter_c1); 6718c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_CP_KPD_IDAC, e_r7_2g->radio_cp_kpd_idac); 6728c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RFPLL_MMD0, e_r7_2g->radio_rfpll_mmd0); 6738c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RFPLL_MMD1, e_r7_2g->radio_rfpll_mmd1); 6748c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_VCOBUF_TUNE, e_r7_2g->radio_vcobuf_tune); 6758c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_LOGEN_MX2G_TUNE, e_r7_2g->radio_logen_mx2g_tune); 6768c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_LOGEN_INDBUF2G_TUNE, e_r7_2g->radio_logen_indbuf2g_tune); 6778c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, e_r7_2g->radio_txmix2g_tune_boost_pu_core0); 6788c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE0, e_r7_2g->radio_pad2g_tune_pus_core0); 6798c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_LNA2G_TUNE_CORE0, e_r7_2g->radio_lna2g_tune_core0); 6808c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, e_r7_2g->radio_txmix2g_tune_boost_pu_core1); 6818c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE1, e_r7_2g->radio_pad2g_tune_pus_core1); 6828c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_LNA2G_TUNE_CORE1, e_r7_2g->radio_lna2g_tune_core1); 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_ci } else { 6858c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_VCOCAL_COUNTVAL0, e_r7->radio_vcocal_countval0); 6868c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_VCOCAL_COUNTVAL1, e_r7->radio_vcocal_countval1); 6878c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RFPLL_REFMASTER_SPAREXTALSIZE, e_r7->radio_rfpll_refmaster_sparextalsize); 6888c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, e_r7->radio_rfpll_loopfilter_r1); 6898c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, e_r7->radio_rfpll_loopfilter_c2); 6908c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, e_r7->radio_rfpll_loopfilter_c1); 6918c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_CP_KPD_IDAC, e_r7->radio_cp_kpd_idac); 6928c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RFPLL_MMD0, e_r7->radio_rfpll_mmd0); 6938c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RFPLL_MMD1, e_r7->radio_rfpll_mmd1); 6948c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_VCOBUF_TUNE, e_r7->radio_vcobuf_tune); 6958c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_LOGEN_MX2G_TUNE, e_r7->radio_logen_mx2g_tune); 6968c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_LOGEN_MX5G_TUNE, e_r7->radio_logen_mx5g_tune); 6978c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_LOGEN_INDBUF2G_TUNE, e_r7->radio_logen_indbuf2g_tune); 6988c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_LOGEN_INDBUF5G_TUNE, e_r7->radio_logen_indbuf5g_tune); 6998c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, e_r7->radio_txmix2g_tune_boost_pu_core0); 7008c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE0, e_r7->radio_pad2g_tune_pus_core0); 7018c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_PGA_BOOST_TUNE_CORE0, e_r7->radio_pga_boost_tune_core0); 7028c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_TXMIX5G_BOOST_TUNE_CORE0, e_r7->radio_txmix5g_boost_tune_core0); 7038c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_PAD5G_TUNE_MISC_PUS_CORE0, e_r7->radio_pad5g_tune_misc_pus_core0); 7048c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_LNA2G_TUNE_CORE0, e_r7->radio_lna2g_tune_core0); 7058c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_LNA5G_TUNE_CORE0, e_r7->radio_lna5g_tune_core0); 7068c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, e_r7->radio_txmix2g_tune_boost_pu_core1); 7078c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE1, e_r7->radio_pad2g_tune_pus_core1); 7088c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_PGA_BOOST_TUNE_CORE1, e_r7->radio_pga_boost_tune_core1); 7098c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_TXMIX5G_BOOST_TUNE_CORE1, e_r7->radio_txmix5g_boost_tune_core1); 7108c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_PAD5G_TUNE_MISC_PUS_CORE1, e_r7->radio_pad5g_tune_misc_pus_core1); 7118c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_LNA2G_TUNE_CORE1, e_r7->radio_lna2g_tune_core1); 7128c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_LNA5G_TUNE_CORE1, e_r7->radio_lna5g_tune_core1); 7138c2ecf20Sopenharmony_ci } 7148c2ecf20Sopenharmony_ci} 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_cistatic void b43_radio_2057_setup(struct b43_wldev *dev, 7178c2ecf20Sopenharmony_ci const struct b43_nphy_chantabent_rev7 *tabent_r7, 7188c2ecf20Sopenharmony_ci const struct b43_nphy_chantabent_rev7_2g *tabent_r7_2g) 7198c2ecf20Sopenharmony_ci{ 7208c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci b43_radio_2057_chantab_upload(dev, tabent_r7, tabent_r7_2g); 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci switch (phy->radio_rev) { 7258c2ecf20Sopenharmony_ci case 0 ... 4: 7268c2ecf20Sopenharmony_ci case 6: 7278c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { 7288c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x3f); 7298c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f); 7308c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x8); 7318c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x8); 7328c2ecf20Sopenharmony_ci } else { 7338c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x1f); 7348c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f); 7358c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x8); 7368c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x8); 7378c2ecf20Sopenharmony_ci } 7388c2ecf20Sopenharmony_ci break; 7398c2ecf20Sopenharmony_ci case 9: /* e.g. PHY rev 16 */ 7408c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_LOGEN_PTAT_RESETS, 0x20); 7418c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_VCOBUF_IDACS, 0x18); 7428c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { 7438c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_LOGEN_PTAT_RESETS, 0x38); 7448c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_VCOBUF_IDACS, 0x0f); 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci if (b43_is_40mhz(dev)) { 7478c2ecf20Sopenharmony_ci /* TODO */ 7488c2ecf20Sopenharmony_ci } else { 7498c2ecf20Sopenharmony_ci b43_radio_write(dev, 7508c2ecf20Sopenharmony_ci R2057_PAD_BIAS_FILTER_BWS_CORE0, 7518c2ecf20Sopenharmony_ci 0x3c); 7528c2ecf20Sopenharmony_ci b43_radio_write(dev, 7538c2ecf20Sopenharmony_ci R2057_PAD_BIAS_FILTER_BWS_CORE1, 7548c2ecf20Sopenharmony_ci 0x3c); 7558c2ecf20Sopenharmony_ci } 7568c2ecf20Sopenharmony_ci } 7578c2ecf20Sopenharmony_ci break; 7588c2ecf20Sopenharmony_ci case 14: /* 2 GHz only */ 7598c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_R1, 0x1b); 7608c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_CP_KPD_IDAC, 0x3f); 7618c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C1, 0x1f); 7628c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RFPLL_LOOPFILTER_C2, 0x1f); 7638c2ecf20Sopenharmony_ci break; 7648c2ecf20Sopenharmony_ci } 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { 7678c2ecf20Sopenharmony_ci u16 txmix2g_tune_boost_pu = 0; 7688c2ecf20Sopenharmony_ci u16 pad2g_tune_pus = 0; 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci if (b43_nphy_ipa(dev)) { 7718c2ecf20Sopenharmony_ci switch (phy->radio_rev) { 7728c2ecf20Sopenharmony_ci case 9: 7738c2ecf20Sopenharmony_ci txmix2g_tune_boost_pu = 0x0041; 7748c2ecf20Sopenharmony_ci /* TODO */ 7758c2ecf20Sopenharmony_ci break; 7768c2ecf20Sopenharmony_ci case 14: 7778c2ecf20Sopenharmony_ci txmix2g_tune_boost_pu = 0x21; 7788c2ecf20Sopenharmony_ci pad2g_tune_pus = 0x23; 7798c2ecf20Sopenharmony_ci break; 7808c2ecf20Sopenharmony_ci } 7818c2ecf20Sopenharmony_ci } 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci if (txmix2g_tune_boost_pu) 7848c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, 7858c2ecf20Sopenharmony_ci txmix2g_tune_boost_pu); 7868c2ecf20Sopenharmony_ci if (pad2g_tune_pus) 7878c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE0, 7888c2ecf20Sopenharmony_ci pad2g_tune_pus); 7898c2ecf20Sopenharmony_ci if (txmix2g_tune_boost_pu) 7908c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, 7918c2ecf20Sopenharmony_ci txmix2g_tune_boost_pu); 7928c2ecf20Sopenharmony_ci if (pad2g_tune_pus) 7938c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_PAD2G_TUNE_PUS_CORE1, 7948c2ecf20Sopenharmony_ci pad2g_tune_pus); 7958c2ecf20Sopenharmony_ci } 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci usleep_range(50, 100); 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci /* VCO calibration */ 8008c2ecf20Sopenharmony_ci b43_radio_mask(dev, R2057_RFPLL_MISC_EN, ~0x01); 8018c2ecf20Sopenharmony_ci b43_radio_mask(dev, R2057_RFPLL_MISC_CAL_RESETN, ~0x04); 8028c2ecf20Sopenharmony_ci b43_radio_set(dev, R2057_RFPLL_MISC_CAL_RESETN, 0x4); 8038c2ecf20Sopenharmony_ci b43_radio_set(dev, R2057_RFPLL_MISC_EN, 0x01); 8048c2ecf20Sopenharmony_ci usleep_range(300, 600); 8058c2ecf20Sopenharmony_ci} 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci/* Calibrate resistors in LPF of PLL? 8088c2ecf20Sopenharmony_ci * https://bcm-v4.sipsolutions.net/PHY/radio205x_rcal 8098c2ecf20Sopenharmony_ci */ 8108c2ecf20Sopenharmony_cistatic u8 b43_radio_2057_rcal(struct b43_wldev *dev) 8118c2ecf20Sopenharmony_ci{ 8128c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 8138c2ecf20Sopenharmony_ci u16 saved_regs_phy[12]; 8148c2ecf20Sopenharmony_ci u16 saved_regs_phy_rf[6]; 8158c2ecf20Sopenharmony_ci u16 saved_regs_radio[2] = { }; 8168c2ecf20Sopenharmony_ci static const u16 phy_to_store[] = { 8178c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2, 8188c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_LUT_TRSW_LO1, B43_NPHY_RFCTL_LUT_TRSW_LO2, 8198c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_RXG1, B43_NPHY_RFCTL_RXG2, 8208c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_TXG1, B43_NPHY_RFCTL_TXG2, 8218c2ecf20Sopenharmony_ci B43_NPHY_REV7_RF_CTL_MISC_REG3, B43_NPHY_REV7_RF_CTL_MISC_REG4, 8228c2ecf20Sopenharmony_ci B43_NPHY_REV7_RF_CTL_MISC_REG5, B43_NPHY_REV7_RF_CTL_MISC_REG6, 8238c2ecf20Sopenharmony_ci }; 8248c2ecf20Sopenharmony_ci static const u16 phy_to_store_rf[] = { 8258c2ecf20Sopenharmony_ci B43_NPHY_REV3_RFCTL_OVER0, B43_NPHY_REV3_RFCTL_OVER1, 8268c2ecf20Sopenharmony_ci B43_NPHY_REV7_RF_CTL_OVER3, B43_NPHY_REV7_RF_CTL_OVER4, 8278c2ecf20Sopenharmony_ci B43_NPHY_REV7_RF_CTL_OVER5, B43_NPHY_REV7_RF_CTL_OVER6, 8288c2ecf20Sopenharmony_ci }; 8298c2ecf20Sopenharmony_ci u16 tmp; 8308c2ecf20Sopenharmony_ci int i; 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci /* Save */ 8338c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(phy_to_store); i++) 8348c2ecf20Sopenharmony_ci saved_regs_phy[i] = b43_phy_read(dev, phy_to_store[i]); 8358c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(phy_to_store_rf); i++) 8368c2ecf20Sopenharmony_ci saved_regs_phy_rf[i] = b43_phy_read(dev, phy_to_store_rf[i]); 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci /* Set */ 8398c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(phy_to_store); i++) 8408c2ecf20Sopenharmony_ci b43_phy_write(dev, phy_to_store[i], 0); 8418c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_REV3_RFCTL_OVER0, 0x07ff); 8428c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_REV3_RFCTL_OVER1, 0x07ff); 8438c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x07ff); 8448c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER4, 0x07ff); 8458c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER5, 0x007f); 8468c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER6, 0x007f); 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci switch (phy->radio_rev) { 8498c2ecf20Sopenharmony_ci case 5: 8508c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_REV7_RF_CTL_OVER3, ~0x2); 8518c2ecf20Sopenharmony_ci udelay(10); 8528c2ecf20Sopenharmony_ci b43_radio_set(dev, R2057_IQTEST_SEL_PU, 0x1); 8538c2ecf20Sopenharmony_ci b43_radio_maskset(dev, R2057v7_IQTEST_SEL_PU2, ~0x2, 0x1); 8548c2ecf20Sopenharmony_ci break; 8558c2ecf20Sopenharmony_ci case 9: 8568c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x2); 8578c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_MISC_REG3, 0x2); 8588c2ecf20Sopenharmony_ci saved_regs_radio[0] = b43_radio_read(dev, R2057_IQTEST_SEL_PU); 8598c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_IQTEST_SEL_PU, 0x11); 8608c2ecf20Sopenharmony_ci break; 8618c2ecf20Sopenharmony_ci case 14: 8628c2ecf20Sopenharmony_ci saved_regs_radio[0] = b43_radio_read(dev, R2057_IQTEST_SEL_PU); 8638c2ecf20Sopenharmony_ci saved_regs_radio[1] = b43_radio_read(dev, R2057v7_IQTEST_SEL_PU2); 8648c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_MISC_REG3, 0x2); 8658c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0x2); 8668c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057v7_IQTEST_SEL_PU2, 0x2); 8678c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_IQTEST_SEL_PU, 0x1); 8688c2ecf20Sopenharmony_ci break; 8698c2ecf20Sopenharmony_ci } 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci /* Enable */ 8728c2ecf20Sopenharmony_ci b43_radio_set(dev, R2057_RCAL_CONFIG, 0x1); 8738c2ecf20Sopenharmony_ci udelay(10); 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci /* Start */ 8768c2ecf20Sopenharmony_ci b43_radio_set(dev, R2057_RCAL_CONFIG, 0x2); 8778c2ecf20Sopenharmony_ci usleep_range(100, 200); 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci /* Stop */ 8808c2ecf20Sopenharmony_ci b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x2); 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci /* Wait and check for result */ 8838c2ecf20Sopenharmony_ci if (!b43_radio_wait_value(dev, R2057_RCAL_STATUS, 1, 1, 100, 1000000)) { 8848c2ecf20Sopenharmony_ci b43err(dev->wl, "Radio 0x2057 rcal timeout\n"); 8858c2ecf20Sopenharmony_ci return 0; 8868c2ecf20Sopenharmony_ci } 8878c2ecf20Sopenharmony_ci tmp = b43_radio_read(dev, R2057_RCAL_STATUS) & 0x3E; 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci /* Disable */ 8908c2ecf20Sopenharmony_ci b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x1); 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci /* Restore */ 8938c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(phy_to_store_rf); i++) 8948c2ecf20Sopenharmony_ci b43_phy_write(dev, phy_to_store_rf[i], saved_regs_phy_rf[i]); 8958c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(phy_to_store); i++) 8968c2ecf20Sopenharmony_ci b43_phy_write(dev, phy_to_store[i], saved_regs_phy[i]); 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci switch (phy->radio_rev) { 8998c2ecf20Sopenharmony_ci case 0 ... 4: 9008c2ecf20Sopenharmony_ci case 6: 9018c2ecf20Sopenharmony_ci b43_radio_maskset(dev, R2057_TEMPSENSE_CONFIG, ~0x3C, tmp); 9028c2ecf20Sopenharmony_ci b43_radio_maskset(dev, R2057_BANDGAP_RCAL_TRIM, ~0xF0, 9038c2ecf20Sopenharmony_ci tmp << 2); 9048c2ecf20Sopenharmony_ci break; 9058c2ecf20Sopenharmony_ci case 5: 9068c2ecf20Sopenharmony_ci b43_radio_mask(dev, R2057_IPA2G_CASCONV_CORE0, ~0x1); 9078c2ecf20Sopenharmony_ci b43_radio_mask(dev, R2057v7_IQTEST_SEL_PU2, ~0x2); 9088c2ecf20Sopenharmony_ci break; 9098c2ecf20Sopenharmony_ci case 9: 9108c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_IQTEST_SEL_PU, saved_regs_radio[0]); 9118c2ecf20Sopenharmony_ci break; 9128c2ecf20Sopenharmony_ci case 14: 9138c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_IQTEST_SEL_PU, saved_regs_radio[0]); 9148c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057v7_IQTEST_SEL_PU2, saved_regs_radio[1]); 9158c2ecf20Sopenharmony_ci break; 9168c2ecf20Sopenharmony_ci } 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci return tmp & 0x3e; 9198c2ecf20Sopenharmony_ci} 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci/* Calibrate the internal RC oscillator? 9228c2ecf20Sopenharmony_ci * https://bcm-v4.sipsolutions.net/PHY/radio2057_rccal 9238c2ecf20Sopenharmony_ci */ 9248c2ecf20Sopenharmony_cistatic u16 b43_radio_2057_rccal(struct b43_wldev *dev) 9258c2ecf20Sopenharmony_ci{ 9268c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 9278c2ecf20Sopenharmony_ci bool special = (phy->radio_rev == 3 || phy->radio_rev == 4 || 9288c2ecf20Sopenharmony_ci phy->radio_rev == 6); 9298c2ecf20Sopenharmony_ci u16 tmp; 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci /* Setup cal */ 9328c2ecf20Sopenharmony_ci if (special) { 9338c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RCCAL_MASTER, 0x61); 9348c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RCCAL_TRC0, 0xC0); 9358c2ecf20Sopenharmony_ci } else { 9368c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x61); 9378c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RCCAL_TRC0, 0xE9); 9388c2ecf20Sopenharmony_ci } 9398c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RCCAL_X1, 0x6E); 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci /* Start, wait, stop */ 9428c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55); 9438c2ecf20Sopenharmony_ci if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500, 9448c2ecf20Sopenharmony_ci 5000000)) 9458c2ecf20Sopenharmony_ci b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n"); 9468c2ecf20Sopenharmony_ci usleep_range(35, 70); 9478c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15); 9488c2ecf20Sopenharmony_ci usleep_range(70, 140); 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci /* Setup cal */ 9518c2ecf20Sopenharmony_ci if (special) { 9528c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RCCAL_MASTER, 0x69); 9538c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RCCAL_TRC0, 0xB0); 9548c2ecf20Sopenharmony_ci } else { 9558c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x69); 9568c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RCCAL_TRC0, 0xD5); 9578c2ecf20Sopenharmony_ci } 9588c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RCCAL_X1, 0x6E); 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci /* Start, wait, stop */ 9618c2ecf20Sopenharmony_ci usleep_range(35, 70); 9628c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55); 9638c2ecf20Sopenharmony_ci usleep_range(70, 140); 9648c2ecf20Sopenharmony_ci if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500, 9658c2ecf20Sopenharmony_ci 5000000)) 9668c2ecf20Sopenharmony_ci b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n"); 9678c2ecf20Sopenharmony_ci usleep_range(35, 70); 9688c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15); 9698c2ecf20Sopenharmony_ci usleep_range(70, 140); 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_ci /* Setup cal */ 9728c2ecf20Sopenharmony_ci if (special) { 9738c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RCCAL_MASTER, 0x73); 9748c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RCCAL_X1, 0x28); 9758c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RCCAL_TRC0, 0xB0); 9768c2ecf20Sopenharmony_ci } else { 9778c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057v7_RCCAL_MASTER, 0x73); 9788c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RCCAL_X1, 0x6E); 9798c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RCCAL_TRC0, 0x99); 9808c2ecf20Sopenharmony_ci } 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci /* Start, wait, stop */ 9838c2ecf20Sopenharmony_ci usleep_range(35, 70); 9848c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x55); 9858c2ecf20Sopenharmony_ci usleep_range(70, 140); 9868c2ecf20Sopenharmony_ci if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500, 9878c2ecf20Sopenharmony_ci 5000000)) { 9888c2ecf20Sopenharmony_ci b43err(dev->wl, "Radio 0x2057 rcal timeout\n"); 9898c2ecf20Sopenharmony_ci return 0; 9908c2ecf20Sopenharmony_ci } 9918c2ecf20Sopenharmony_ci tmp = b43_radio_read(dev, R2057_RCCAL_DONE_OSCCAP); 9928c2ecf20Sopenharmony_ci usleep_range(35, 70); 9938c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_RCCAL_START_R1_Q1_P1, 0x15); 9948c2ecf20Sopenharmony_ci usleep_range(70, 140); 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci if (special) 9978c2ecf20Sopenharmony_ci b43_radio_mask(dev, R2057_RCCAL_MASTER, ~0x1); 9988c2ecf20Sopenharmony_ci else 9998c2ecf20Sopenharmony_ci b43_radio_mask(dev, R2057v7_RCCAL_MASTER, ~0x1); 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci return tmp; 10028c2ecf20Sopenharmony_ci} 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_cistatic void b43_radio_2057_init_pre(struct b43_wldev *dev) 10058c2ecf20Sopenharmony_ci{ 10068c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, ~B43_NPHY_RFCTL_CMD_CHIP0PU); 10078c2ecf20Sopenharmony_ci /* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */ 10088c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_OEPORFORCE); 10098c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_RFCTL_CMD, ~B43_NPHY_RFCTL_CMD_OEPORFORCE); 10108c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_CHIP0PU); 10118c2ecf20Sopenharmony_ci} 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_cistatic void b43_radio_2057_init_post(struct b43_wldev *dev) 10148c2ecf20Sopenharmony_ci{ 10158c2ecf20Sopenharmony_ci b43_radio_set(dev, R2057_XTALPUOVR_PINCTRL, 0x1); 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci if (0) /* FIXME: Is this BCM43217 specific? */ 10188c2ecf20Sopenharmony_ci b43_radio_set(dev, R2057_XTALPUOVR_PINCTRL, 0x2); 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ci b43_radio_set(dev, R2057_RFPLL_MISC_CAL_RESETN, 0x78); 10218c2ecf20Sopenharmony_ci b43_radio_set(dev, R2057_XTAL_CONFIG2, 0x80); 10228c2ecf20Sopenharmony_ci usleep_range(2000, 3000); 10238c2ecf20Sopenharmony_ci b43_radio_mask(dev, R2057_RFPLL_MISC_CAL_RESETN, ~0x78); 10248c2ecf20Sopenharmony_ci b43_radio_mask(dev, R2057_XTAL_CONFIG2, ~0x80); 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci if (dev->phy.do_full_init) { 10278c2ecf20Sopenharmony_ci b43_radio_2057_rcal(dev); 10288c2ecf20Sopenharmony_ci b43_radio_2057_rccal(dev); 10298c2ecf20Sopenharmony_ci } 10308c2ecf20Sopenharmony_ci b43_radio_mask(dev, R2057_RFPLL_MASTER, ~0x8); 10318c2ecf20Sopenharmony_ci} 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/Radio/2057/Init */ 10348c2ecf20Sopenharmony_cistatic void b43_radio_2057_init(struct b43_wldev *dev) 10358c2ecf20Sopenharmony_ci{ 10368c2ecf20Sopenharmony_ci b43_radio_2057_init_pre(dev); 10378c2ecf20Sopenharmony_ci r2057_upload_inittabs(dev); 10388c2ecf20Sopenharmony_ci b43_radio_2057_init_post(dev); 10398c2ecf20Sopenharmony_ci} 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_ci/************************************************** 10428c2ecf20Sopenharmony_ci * Radio 0x2056 10438c2ecf20Sopenharmony_ci **************************************************/ 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_cistatic void b43_chantab_radio_2056_upload(struct b43_wldev *dev, 10468c2ecf20Sopenharmony_ci const struct b43_nphy_channeltab_entry_rev3 *e) 10478c2ecf20Sopenharmony_ci{ 10488c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_VCOCAL1, e->radio_syn_pll_vcocal1); 10498c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_VCOCAL2, e->radio_syn_pll_vcocal2); 10508c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_REFDIV, e->radio_syn_pll_refdiv); 10518c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_MMD2, e->radio_syn_pll_mmd2); 10528c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_MMD1, e->radio_syn_pll_mmd1); 10538c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 10548c2ecf20Sopenharmony_ci e->radio_syn_pll_loopfilter1); 10558c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 10568c2ecf20Sopenharmony_ci e->radio_syn_pll_loopfilter2); 10578c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER3, 10588c2ecf20Sopenharmony_ci e->radio_syn_pll_loopfilter3); 10598c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 10608c2ecf20Sopenharmony_ci e->radio_syn_pll_loopfilter4); 10618c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER5, 10628c2ecf20Sopenharmony_ci e->radio_syn_pll_loopfilter5); 10638c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_RESERVED_ADDR27, 10648c2ecf20Sopenharmony_ci e->radio_syn_reserved_addr27); 10658c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_RESERVED_ADDR28, 10668c2ecf20Sopenharmony_ci e->radio_syn_reserved_addr28); 10678c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_RESERVED_ADDR29, 10688c2ecf20Sopenharmony_ci e->radio_syn_reserved_addr29); 10698c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_LOGEN_VCOBUF1, 10708c2ecf20Sopenharmony_ci e->radio_syn_logen_vcobuf1); 10718c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_LOGEN_MIXER2, e->radio_syn_logen_mixer2); 10728c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_LOGEN_BUF3, e->radio_syn_logen_buf3); 10738c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_LOGEN_BUF4, e->radio_syn_logen_buf4); 10748c2ecf20Sopenharmony_ci 10758c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA_TUNE, 10768c2ecf20Sopenharmony_ci e->radio_rx0_lnaa_tune); 10778c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG_TUNE, 10788c2ecf20Sopenharmony_ci e->radio_rx0_lnag_tune); 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAA_BOOST_TUNE, 10818c2ecf20Sopenharmony_ci e->radio_tx0_intpaa_boost_tune); 10828c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAG_BOOST_TUNE, 10838c2ecf20Sopenharmony_ci e->radio_tx0_intpag_boost_tune); 10848c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_TX0 | B2056_TX_PADA_BOOST_TUNE, 10858c2ecf20Sopenharmony_ci e->radio_tx0_pada_boost_tune); 10868c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_TX0 | B2056_TX_PADG_BOOST_TUNE, 10878c2ecf20Sopenharmony_ci e->radio_tx0_padg_boost_tune); 10888c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAA_BOOST_TUNE, 10898c2ecf20Sopenharmony_ci e->radio_tx0_pgaa_boost_tune); 10908c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAG_BOOST_TUNE, 10918c2ecf20Sopenharmony_ci e->radio_tx0_pgag_boost_tune); 10928c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXA_BOOST_TUNE, 10938c2ecf20Sopenharmony_ci e->radio_tx0_mixa_boost_tune); 10948c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXG_BOOST_TUNE, 10958c2ecf20Sopenharmony_ci e->radio_tx0_mixg_boost_tune); 10968c2ecf20Sopenharmony_ci 10978c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA_TUNE, 10988c2ecf20Sopenharmony_ci e->radio_rx1_lnaa_tune); 10998c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG_TUNE, 11008c2ecf20Sopenharmony_ci e->radio_rx1_lnag_tune); 11018c2ecf20Sopenharmony_ci 11028c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAA_BOOST_TUNE, 11038c2ecf20Sopenharmony_ci e->radio_tx1_intpaa_boost_tune); 11048c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAG_BOOST_TUNE, 11058c2ecf20Sopenharmony_ci e->radio_tx1_intpag_boost_tune); 11068c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_TX1 | B2056_TX_PADA_BOOST_TUNE, 11078c2ecf20Sopenharmony_ci e->radio_tx1_pada_boost_tune); 11088c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_TX1 | B2056_TX_PADG_BOOST_TUNE, 11098c2ecf20Sopenharmony_ci e->radio_tx1_padg_boost_tune); 11108c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAA_BOOST_TUNE, 11118c2ecf20Sopenharmony_ci e->radio_tx1_pgaa_boost_tune); 11128c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAG_BOOST_TUNE, 11138c2ecf20Sopenharmony_ci e->radio_tx1_pgag_boost_tune); 11148c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXA_BOOST_TUNE, 11158c2ecf20Sopenharmony_ci e->radio_tx1_mixa_boost_tune); 11168c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXG_BOOST_TUNE, 11178c2ecf20Sopenharmony_ci e->radio_tx1_mixg_boost_tune); 11188c2ecf20Sopenharmony_ci} 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2056Setup */ 11218c2ecf20Sopenharmony_cistatic void b43_radio_2056_setup(struct b43_wldev *dev, 11228c2ecf20Sopenharmony_ci const struct b43_nphy_channeltab_entry_rev3 *e) 11238c2ecf20Sopenharmony_ci{ 11248c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 11258c2ecf20Sopenharmony_ci struct ssb_sprom *sprom = dev->dev->bus_sprom; 11268c2ecf20Sopenharmony_ci enum nl80211_band band = b43_current_band(dev->wl); 11278c2ecf20Sopenharmony_ci u16 offset; 11288c2ecf20Sopenharmony_ci u8 i; 11298c2ecf20Sopenharmony_ci u16 bias, cbias; 11308c2ecf20Sopenharmony_ci u16 pag_boost, padg_boost, pgag_boost, mixg_boost; 11318c2ecf20Sopenharmony_ci u16 paa_boost, pada_boost, pgaa_boost, mixa_boost; 11328c2ecf20Sopenharmony_ci bool is_pkg_fab_smic; 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_ci B43_WARN_ON(dev->phy.rev < 3); 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci is_pkg_fab_smic = 11378c2ecf20Sopenharmony_ci ((dev->dev->chip_id == BCMA_CHIP_ID_BCM43224 || 11388c2ecf20Sopenharmony_ci dev->dev->chip_id == BCMA_CHIP_ID_BCM43225 || 11398c2ecf20Sopenharmony_ci dev->dev->chip_id == BCMA_CHIP_ID_BCM43421) && 11408c2ecf20Sopenharmony_ci dev->dev->chip_pkg == BCMA_PKG_ID_BCM43224_FAB_SMIC); 11418c2ecf20Sopenharmony_ci 11428c2ecf20Sopenharmony_ci b43_chantab_radio_2056_upload(dev, e); 11438c2ecf20Sopenharmony_ci b2056_upload_syn_pll_cp2(dev, band == NL80211_BAND_5GHZ); 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_ci if (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR && 11468c2ecf20Sopenharmony_ci b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { 11478c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F); 11488c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F); 11498c2ecf20Sopenharmony_ci if (dev->dev->chip_id == BCMA_CHIP_ID_BCM4716 || 11508c2ecf20Sopenharmony_ci dev->dev->chip_id == BCMA_CHIP_ID_BCM47162) { 11518c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x14); 11528c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_CP2, 0); 11538c2ecf20Sopenharmony_ci } else { 11548c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x0B); 11558c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x14); 11568c2ecf20Sopenharmony_ci } 11578c2ecf20Sopenharmony_ci } 11588c2ecf20Sopenharmony_ci if (sprom->boardflags2_hi & B43_BFH2_GPLL_WAR2 && 11598c2ecf20Sopenharmony_ci b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { 11608c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1f); 11618c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1f); 11628c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x0b); 11638c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x20); 11648c2ecf20Sopenharmony_ci } 11658c2ecf20Sopenharmony_ci if (sprom->boardflags2_lo & B43_BFL2_APLL_WAR && 11668c2ecf20Sopenharmony_ci b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { 11678c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F); 11688c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F); 11698c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x05); 11708c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x0C); 11718c2ecf20Sopenharmony_ci } 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci if (dev->phy.n->ipa2g_on && band == NL80211_BAND_2GHZ) { 11748c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 11758c2ecf20Sopenharmony_ci offset = i ? B2056_TX1 : B2056_TX0; 11768c2ecf20Sopenharmony_ci if (dev->phy.rev >= 5) { 11778c2ecf20Sopenharmony_ci b43_radio_write(dev, 11788c2ecf20Sopenharmony_ci offset | B2056_TX_PADG_IDAC, 0xcc); 11798c2ecf20Sopenharmony_ci 11808c2ecf20Sopenharmony_ci if (dev->dev->chip_id == BCMA_CHIP_ID_BCM4716 || 11818c2ecf20Sopenharmony_ci dev->dev->chip_id == BCMA_CHIP_ID_BCM47162) { 11828c2ecf20Sopenharmony_ci bias = 0x40; 11838c2ecf20Sopenharmony_ci cbias = 0x45; 11848c2ecf20Sopenharmony_ci pag_boost = 0x5; 11858c2ecf20Sopenharmony_ci pgag_boost = 0x33; 11868c2ecf20Sopenharmony_ci mixg_boost = 0x55; 11878c2ecf20Sopenharmony_ci } else { 11888c2ecf20Sopenharmony_ci bias = 0x25; 11898c2ecf20Sopenharmony_ci cbias = 0x20; 11908c2ecf20Sopenharmony_ci if (is_pkg_fab_smic) { 11918c2ecf20Sopenharmony_ci bias = 0x2a; 11928c2ecf20Sopenharmony_ci cbias = 0x38; 11938c2ecf20Sopenharmony_ci } 11948c2ecf20Sopenharmony_ci pag_boost = 0x4; 11958c2ecf20Sopenharmony_ci pgag_boost = 0x03; 11968c2ecf20Sopenharmony_ci mixg_boost = 0x65; 11978c2ecf20Sopenharmony_ci } 11988c2ecf20Sopenharmony_ci padg_boost = 0x77; 11998c2ecf20Sopenharmony_ci 12008c2ecf20Sopenharmony_ci b43_radio_write(dev, 12018c2ecf20Sopenharmony_ci offset | B2056_TX_INTPAG_IMAIN_STAT, 12028c2ecf20Sopenharmony_ci bias); 12038c2ecf20Sopenharmony_ci b43_radio_write(dev, 12048c2ecf20Sopenharmony_ci offset | B2056_TX_INTPAG_IAUX_STAT, 12058c2ecf20Sopenharmony_ci bias); 12068c2ecf20Sopenharmony_ci b43_radio_write(dev, 12078c2ecf20Sopenharmony_ci offset | B2056_TX_INTPAG_CASCBIAS, 12088c2ecf20Sopenharmony_ci cbias); 12098c2ecf20Sopenharmony_ci b43_radio_write(dev, 12108c2ecf20Sopenharmony_ci offset | B2056_TX_INTPAG_BOOST_TUNE, 12118c2ecf20Sopenharmony_ci pag_boost); 12128c2ecf20Sopenharmony_ci b43_radio_write(dev, 12138c2ecf20Sopenharmony_ci offset | B2056_TX_PGAG_BOOST_TUNE, 12148c2ecf20Sopenharmony_ci pgag_boost); 12158c2ecf20Sopenharmony_ci b43_radio_write(dev, 12168c2ecf20Sopenharmony_ci offset | B2056_TX_PADG_BOOST_TUNE, 12178c2ecf20Sopenharmony_ci padg_boost); 12188c2ecf20Sopenharmony_ci b43_radio_write(dev, 12198c2ecf20Sopenharmony_ci offset | B2056_TX_MIXG_BOOST_TUNE, 12208c2ecf20Sopenharmony_ci mixg_boost); 12218c2ecf20Sopenharmony_ci } else { 12228c2ecf20Sopenharmony_ci bias = b43_is_40mhz(dev) ? 0x40 : 0x20; 12238c2ecf20Sopenharmony_ci b43_radio_write(dev, 12248c2ecf20Sopenharmony_ci offset | B2056_TX_INTPAG_IMAIN_STAT, 12258c2ecf20Sopenharmony_ci bias); 12268c2ecf20Sopenharmony_ci b43_radio_write(dev, 12278c2ecf20Sopenharmony_ci offset | B2056_TX_INTPAG_IAUX_STAT, 12288c2ecf20Sopenharmony_ci bias); 12298c2ecf20Sopenharmony_ci b43_radio_write(dev, 12308c2ecf20Sopenharmony_ci offset | B2056_TX_INTPAG_CASCBIAS, 12318c2ecf20Sopenharmony_ci 0x30); 12328c2ecf20Sopenharmony_ci } 12338c2ecf20Sopenharmony_ci b43_radio_write(dev, offset | B2056_TX_PA_SPARE1, 0xee); 12348c2ecf20Sopenharmony_ci } 12358c2ecf20Sopenharmony_ci } else if (dev->phy.n->ipa5g_on && band == NL80211_BAND_5GHZ) { 12368c2ecf20Sopenharmony_ci u16 freq = phy->chandef->chan->center_freq; 12378c2ecf20Sopenharmony_ci if (freq < 5100) { 12388c2ecf20Sopenharmony_ci paa_boost = 0xA; 12398c2ecf20Sopenharmony_ci pada_boost = 0x77; 12408c2ecf20Sopenharmony_ci pgaa_boost = 0xF; 12418c2ecf20Sopenharmony_ci mixa_boost = 0xF; 12428c2ecf20Sopenharmony_ci } else if (freq < 5340) { 12438c2ecf20Sopenharmony_ci paa_boost = 0x8; 12448c2ecf20Sopenharmony_ci pada_boost = 0x77; 12458c2ecf20Sopenharmony_ci pgaa_boost = 0xFB; 12468c2ecf20Sopenharmony_ci mixa_boost = 0xF; 12478c2ecf20Sopenharmony_ci } else if (freq < 5650) { 12488c2ecf20Sopenharmony_ci paa_boost = 0x0; 12498c2ecf20Sopenharmony_ci pada_boost = 0x77; 12508c2ecf20Sopenharmony_ci pgaa_boost = 0xB; 12518c2ecf20Sopenharmony_ci mixa_boost = 0xF; 12528c2ecf20Sopenharmony_ci } else { 12538c2ecf20Sopenharmony_ci paa_boost = 0x0; 12548c2ecf20Sopenharmony_ci pada_boost = 0x77; 12558c2ecf20Sopenharmony_ci if (freq != 5825) 12568c2ecf20Sopenharmony_ci pgaa_boost = -(freq - 18) / 36 + 168; 12578c2ecf20Sopenharmony_ci else 12588c2ecf20Sopenharmony_ci pgaa_boost = 6; 12598c2ecf20Sopenharmony_ci mixa_boost = 0xF; 12608c2ecf20Sopenharmony_ci } 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_ci cbias = is_pkg_fab_smic ? 0x35 : 0x30; 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 12658c2ecf20Sopenharmony_ci offset = i ? B2056_TX1 : B2056_TX0; 12668c2ecf20Sopenharmony_ci 12678c2ecf20Sopenharmony_ci b43_radio_write(dev, 12688c2ecf20Sopenharmony_ci offset | B2056_TX_INTPAA_BOOST_TUNE, paa_boost); 12698c2ecf20Sopenharmony_ci b43_radio_write(dev, 12708c2ecf20Sopenharmony_ci offset | B2056_TX_PADA_BOOST_TUNE, pada_boost); 12718c2ecf20Sopenharmony_ci b43_radio_write(dev, 12728c2ecf20Sopenharmony_ci offset | B2056_TX_PGAA_BOOST_TUNE, pgaa_boost); 12738c2ecf20Sopenharmony_ci b43_radio_write(dev, 12748c2ecf20Sopenharmony_ci offset | B2056_TX_MIXA_BOOST_TUNE, mixa_boost); 12758c2ecf20Sopenharmony_ci b43_radio_write(dev, 12768c2ecf20Sopenharmony_ci offset | B2056_TX_TXSPARE1, 0x30); 12778c2ecf20Sopenharmony_ci b43_radio_write(dev, 12788c2ecf20Sopenharmony_ci offset | B2056_TX_PA_SPARE2, 0xee); 12798c2ecf20Sopenharmony_ci b43_radio_write(dev, 12808c2ecf20Sopenharmony_ci offset | B2056_TX_PADA_CASCBIAS, 0x03); 12818c2ecf20Sopenharmony_ci b43_radio_write(dev, 12828c2ecf20Sopenharmony_ci offset | B2056_TX_INTPAA_IAUX_STAT, 0x30); 12838c2ecf20Sopenharmony_ci b43_radio_write(dev, 12848c2ecf20Sopenharmony_ci offset | B2056_TX_INTPAA_IMAIN_STAT, 0x30); 12858c2ecf20Sopenharmony_ci b43_radio_write(dev, 12868c2ecf20Sopenharmony_ci offset | B2056_TX_INTPAA_CASCBIAS, cbias); 12878c2ecf20Sopenharmony_ci } 12888c2ecf20Sopenharmony_ci } 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci udelay(50); 12918c2ecf20Sopenharmony_ci /* VCO calibration */ 12928c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_VCOCAL12, 0x00); 12938c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38); 12948c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x18); 12958c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38); 12968c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x39); 12978c2ecf20Sopenharmony_ci udelay(300); 12988c2ecf20Sopenharmony_ci} 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_cistatic u8 b43_radio_2056_rcal(struct b43_wldev *dev) 13018c2ecf20Sopenharmony_ci{ 13028c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 13038c2ecf20Sopenharmony_ci u16 mast2, tmp; 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_ci if (phy->rev != 3) 13068c2ecf20Sopenharmony_ci return 0; 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci mast2 = b43_radio_read(dev, B2056_SYN_PLL_MAST2); 13098c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_MAST2, mast2 | 0x7); 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci udelay(10); 13128c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x01); 13138c2ecf20Sopenharmony_ci udelay(10); 13148c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x09); 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_ci if (!b43_radio_wait_value(dev, B2056_SYN_RCAL_CODE_OUT, 0x80, 0x80, 100, 13178c2ecf20Sopenharmony_ci 1000000)) { 13188c2ecf20Sopenharmony_ci b43err(dev->wl, "Radio recalibration timeout\n"); 13198c2ecf20Sopenharmony_ci return 0; 13208c2ecf20Sopenharmony_ci } 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x01); 13238c2ecf20Sopenharmony_ci tmp = b43_radio_read(dev, B2056_SYN_RCAL_CODE_OUT); 13248c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_RCAL_MASTER, 0x00); 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_PLL_MAST2, mast2); 13278c2ecf20Sopenharmony_ci 13288c2ecf20Sopenharmony_ci return tmp & 0x1f; 13298c2ecf20Sopenharmony_ci} 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_cistatic void b43_radio_init2056_pre(struct b43_wldev *dev) 13328c2ecf20Sopenharmony_ci{ 13338c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, 13348c2ecf20Sopenharmony_ci ~B43_NPHY_RFCTL_CMD_CHIP0PU); 13358c2ecf20Sopenharmony_ci /* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */ 13368c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, 13378c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_CMD_OEPORFORCE); 13388c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_RFCTL_CMD, 13398c2ecf20Sopenharmony_ci ~B43_NPHY_RFCTL_CMD_OEPORFORCE); 13408c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_RFCTL_CMD, 13418c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_CMD_CHIP0PU); 13428c2ecf20Sopenharmony_ci} 13438c2ecf20Sopenharmony_ci 13448c2ecf20Sopenharmony_cistatic void b43_radio_init2056_post(struct b43_wldev *dev) 13458c2ecf20Sopenharmony_ci{ 13468c2ecf20Sopenharmony_ci b43_radio_set(dev, B2056_SYN_COM_CTRL, 0xB); 13478c2ecf20Sopenharmony_ci b43_radio_set(dev, B2056_SYN_COM_PU, 0x2); 13488c2ecf20Sopenharmony_ci b43_radio_set(dev, B2056_SYN_COM_RESET, 0x2); 13498c2ecf20Sopenharmony_ci msleep(1); 13508c2ecf20Sopenharmony_ci b43_radio_mask(dev, B2056_SYN_COM_RESET, ~0x2); 13518c2ecf20Sopenharmony_ci b43_radio_mask(dev, B2056_SYN_PLL_MAST2, ~0xFC); 13528c2ecf20Sopenharmony_ci b43_radio_mask(dev, B2056_SYN_RCCAL_CTRL0, ~0x1); 13538c2ecf20Sopenharmony_ci if (dev->phy.do_full_init) 13548c2ecf20Sopenharmony_ci b43_radio_2056_rcal(dev); 13558c2ecf20Sopenharmony_ci} 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_ci/* 13588c2ecf20Sopenharmony_ci * Initialize a Broadcom 2056 N-radio 13598c2ecf20Sopenharmony_ci * https://bcm-v4.sipsolutions.net/802.11/Radio/2056/Init 13608c2ecf20Sopenharmony_ci */ 13618c2ecf20Sopenharmony_cistatic void b43_radio_init2056(struct b43_wldev *dev) 13628c2ecf20Sopenharmony_ci{ 13638c2ecf20Sopenharmony_ci b43_radio_init2056_pre(dev); 13648c2ecf20Sopenharmony_ci b2056_upload_inittabs(dev, 0, 0); 13658c2ecf20Sopenharmony_ci b43_radio_init2056_post(dev); 13668c2ecf20Sopenharmony_ci} 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci/************************************************** 13698c2ecf20Sopenharmony_ci * Radio 0x2055 13708c2ecf20Sopenharmony_ci **************************************************/ 13718c2ecf20Sopenharmony_ci 13728c2ecf20Sopenharmony_cistatic void b43_chantab_radio_upload(struct b43_wldev *dev, 13738c2ecf20Sopenharmony_ci const struct b43_nphy_channeltab_entry_rev2 *e) 13748c2ecf20Sopenharmony_ci{ 13758c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_PLL_REF, e->radio_pll_ref); 13768c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0); 13778c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1); 13788c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail); 13798c2ecf20Sopenharmony_ci b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ 13808c2ecf20Sopenharmony_ci 13818c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_VCO_CAL1, e->radio_vco_cal1); 13828c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_VCO_CAL2, e->radio_vco_cal2); 13838c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_PLL_LFC1, e->radio_pll_lfc1); 13848c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_PLL_LFR1, e->radio_pll_lfr1); 13858c2ecf20Sopenharmony_ci b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ 13868c2ecf20Sopenharmony_ci 13878c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_PLL_LFC2, e->radio_pll_lfc2); 13888c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf); 13898c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1); 13908c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2); 13918c2ecf20Sopenharmony_ci b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ 13928c2ecf20Sopenharmony_ci 13938c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune); 13948c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune); 13958c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1); 13968c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn); 13978c2ecf20Sopenharmony_ci b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim); 14008c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune); 14018c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune); 14028c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1); 14038c2ecf20Sopenharmony_ci b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ 14048c2ecf20Sopenharmony_ci 14058c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn); 14068c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim); 14078c2ecf20Sopenharmony_ci} 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */ 14108c2ecf20Sopenharmony_cistatic void b43_radio_2055_setup(struct b43_wldev *dev, 14118c2ecf20Sopenharmony_ci const struct b43_nphy_channeltab_entry_rev2 *e) 14128c2ecf20Sopenharmony_ci{ 14138c2ecf20Sopenharmony_ci B43_WARN_ON(dev->phy.rev >= 3); 14148c2ecf20Sopenharmony_ci 14158c2ecf20Sopenharmony_ci b43_chantab_radio_upload(dev, e); 14168c2ecf20Sopenharmony_ci udelay(50); 14178c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_VCO_CAL10, 0x05); 14188c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_VCO_CAL10, 0x45); 14198c2ecf20Sopenharmony_ci b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ 14208c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_VCO_CAL10, 0x65); 14218c2ecf20Sopenharmony_ci udelay(300); 14228c2ecf20Sopenharmony_ci} 14238c2ecf20Sopenharmony_ci 14248c2ecf20Sopenharmony_cistatic void b43_radio_init2055_pre(struct b43_wldev *dev) 14258c2ecf20Sopenharmony_ci{ 14268c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, 14278c2ecf20Sopenharmony_ci ~B43_NPHY_RFCTL_CMD_PORFORCE); 14288c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_RFCTL_CMD, 14298c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_CMD_CHIP0PU | 14308c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_CMD_OEPORFORCE); 14318c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_RFCTL_CMD, 14328c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_CMD_PORFORCE); 14338c2ecf20Sopenharmony_ci} 14348c2ecf20Sopenharmony_ci 14358c2ecf20Sopenharmony_cistatic void b43_radio_init2055_post(struct b43_wldev *dev) 14368c2ecf20Sopenharmony_ci{ 14378c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 14388c2ecf20Sopenharmony_ci struct ssb_sprom *sprom = dev->dev->bus_sprom; 14398c2ecf20Sopenharmony_ci bool workaround = false; 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_ci if (sprom->revision < 4) 14428c2ecf20Sopenharmony_ci workaround = (dev->dev->board_vendor != PCI_VENDOR_ID_BROADCOM 14438c2ecf20Sopenharmony_ci && dev->dev->board_type == SSB_BOARD_CB2_4321 14448c2ecf20Sopenharmony_ci && dev->dev->board_rev >= 0x41); 14458c2ecf20Sopenharmony_ci else 14468c2ecf20Sopenharmony_ci workaround = 14478c2ecf20Sopenharmony_ci !(sprom->boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS); 14488c2ecf20Sopenharmony_ci 14498c2ecf20Sopenharmony_ci b43_radio_mask(dev, B2055_MASTER1, 0xFFF3); 14508c2ecf20Sopenharmony_ci if (workaround) { 14518c2ecf20Sopenharmony_ci b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F); 14528c2ecf20Sopenharmony_ci b43_radio_mask(dev, B2055_C2_RX_BB_REG, 0x7F); 14538c2ecf20Sopenharmony_ci } 14548c2ecf20Sopenharmony_ci b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0xFFC0, 0x2C); 14558c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_CAL_MISC, 0x3C); 14568c2ecf20Sopenharmony_ci b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE); 14578c2ecf20Sopenharmony_ci b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80); 14588c2ecf20Sopenharmony_ci b43_radio_set(dev, B2055_CAL_MISC, 0x1); 14598c2ecf20Sopenharmony_ci msleep(1); 14608c2ecf20Sopenharmony_ci b43_radio_set(dev, B2055_CAL_MISC, 0x40); 14618c2ecf20Sopenharmony_ci if (!b43_radio_wait_value(dev, B2055_CAL_COUT2, 0x80, 0x80, 10, 2000)) 14628c2ecf20Sopenharmony_ci b43err(dev->wl, "radio post init timeout\n"); 14638c2ecf20Sopenharmony_ci b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F); 14648c2ecf20Sopenharmony_ci b43_switch_channel(dev, dev->phy.channel); 14658c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C1_RX_BB_LPF, 0x9); 14668c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C2_RX_BB_LPF, 0x9); 14678c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C1_RX_BB_MIDACHP, 0x83); 14688c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C2_RX_BB_MIDACHP, 0x83); 14698c2ecf20Sopenharmony_ci b43_radio_maskset(dev, B2055_C1_LNA_GAINBST, 0xFFF8, 0x6); 14708c2ecf20Sopenharmony_ci b43_radio_maskset(dev, B2055_C2_LNA_GAINBST, 0xFFF8, 0x6); 14718c2ecf20Sopenharmony_ci if (!nphy->gain_boost) { 14728c2ecf20Sopenharmony_ci b43_radio_set(dev, B2055_C1_RX_RFSPC1, 0x2); 14738c2ecf20Sopenharmony_ci b43_radio_set(dev, B2055_C2_RX_RFSPC1, 0x2); 14748c2ecf20Sopenharmony_ci } else { 14758c2ecf20Sopenharmony_ci b43_radio_mask(dev, B2055_C1_RX_RFSPC1, 0xFFFD); 14768c2ecf20Sopenharmony_ci b43_radio_mask(dev, B2055_C2_RX_RFSPC1, 0xFFFD); 14778c2ecf20Sopenharmony_ci } 14788c2ecf20Sopenharmony_ci udelay(2); 14798c2ecf20Sopenharmony_ci} 14808c2ecf20Sopenharmony_ci 14818c2ecf20Sopenharmony_ci/* 14828c2ecf20Sopenharmony_ci * Initialize a Broadcom 2055 N-radio 14838c2ecf20Sopenharmony_ci * https://bcm-v4.sipsolutions.net/802.11/Radio/2055/Init 14848c2ecf20Sopenharmony_ci */ 14858c2ecf20Sopenharmony_cistatic void b43_radio_init2055(struct b43_wldev *dev) 14868c2ecf20Sopenharmony_ci{ 14878c2ecf20Sopenharmony_ci b43_radio_init2055_pre(dev); 14888c2ecf20Sopenharmony_ci if (b43_status(dev) < B43_STAT_INITIALIZED) { 14898c2ecf20Sopenharmony_ci /* Follow wl, not specs. Do not force uploading all regs */ 14908c2ecf20Sopenharmony_ci b2055_upload_inittab(dev, 0, 0); 14918c2ecf20Sopenharmony_ci } else { 14928c2ecf20Sopenharmony_ci bool ghz5 = b43_current_band(dev->wl) == NL80211_BAND_5GHZ; 14938c2ecf20Sopenharmony_ci b2055_upload_inittab(dev, ghz5, 0); 14948c2ecf20Sopenharmony_ci } 14958c2ecf20Sopenharmony_ci b43_radio_init2055_post(dev); 14968c2ecf20Sopenharmony_ci} 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci/************************************************** 14998c2ecf20Sopenharmony_ci * Samples 15008c2ecf20Sopenharmony_ci **************************************************/ 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/LoadSampleTable */ 15038c2ecf20Sopenharmony_cistatic int b43_nphy_load_samples(struct b43_wldev *dev, 15048c2ecf20Sopenharmony_ci struct cordic_iq *samples, u16 len) { 15058c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 15068c2ecf20Sopenharmony_ci u16 i; 15078c2ecf20Sopenharmony_ci u32 *data; 15088c2ecf20Sopenharmony_ci 15098c2ecf20Sopenharmony_ci data = kcalloc(len, sizeof(u32), GFP_KERNEL); 15108c2ecf20Sopenharmony_ci if (!data) { 15118c2ecf20Sopenharmony_ci b43err(dev->wl, "allocation for samples loading failed\n"); 15128c2ecf20Sopenharmony_ci return -ENOMEM; 15138c2ecf20Sopenharmony_ci } 15148c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 15158c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, 1); 15168c2ecf20Sopenharmony_ci 15178c2ecf20Sopenharmony_ci for (i = 0; i < len; i++) { 15188c2ecf20Sopenharmony_ci data[i] = (samples[i].i & 0x3FF << 10); 15198c2ecf20Sopenharmony_ci data[i] |= samples[i].q & 0x3FF; 15208c2ecf20Sopenharmony_ci } 15218c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB32(17, 0), len, data); 15228c2ecf20Sopenharmony_ci 15238c2ecf20Sopenharmony_ci kfree(data); 15248c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 15258c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, 0); 15268c2ecf20Sopenharmony_ci return 0; 15278c2ecf20Sopenharmony_ci} 15288c2ecf20Sopenharmony_ci 15298c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/GenLoadSamples */ 15308c2ecf20Sopenharmony_cistatic u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max, 15318c2ecf20Sopenharmony_ci bool test) 15328c2ecf20Sopenharmony_ci{ 15338c2ecf20Sopenharmony_ci int i; 15348c2ecf20Sopenharmony_ci u16 bw, len, rot, angle; 15358c2ecf20Sopenharmony_ci struct cordic_iq *samples; 15368c2ecf20Sopenharmony_ci 15378c2ecf20Sopenharmony_ci bw = b43_is_40mhz(dev) ? 40 : 20; 15388c2ecf20Sopenharmony_ci len = bw << 3; 15398c2ecf20Sopenharmony_ci 15408c2ecf20Sopenharmony_ci if (test) { 15418c2ecf20Sopenharmony_ci if (b43_phy_read(dev, B43_NPHY_BBCFG) & B43_NPHY_BBCFG_RSTRX) 15428c2ecf20Sopenharmony_ci bw = 82; 15438c2ecf20Sopenharmony_ci else 15448c2ecf20Sopenharmony_ci bw = 80; 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_ci if (b43_is_40mhz(dev)) 15478c2ecf20Sopenharmony_ci bw <<= 1; 15488c2ecf20Sopenharmony_ci 15498c2ecf20Sopenharmony_ci len = bw << 1; 15508c2ecf20Sopenharmony_ci } 15518c2ecf20Sopenharmony_ci 15528c2ecf20Sopenharmony_ci samples = kcalloc(len, sizeof(struct cordic_iq), GFP_KERNEL); 15538c2ecf20Sopenharmony_ci if (!samples) { 15548c2ecf20Sopenharmony_ci b43err(dev->wl, "allocation for samples generation failed\n"); 15558c2ecf20Sopenharmony_ci return 0; 15568c2ecf20Sopenharmony_ci } 15578c2ecf20Sopenharmony_ci rot = (((freq * 36) / bw) << 16) / 100; 15588c2ecf20Sopenharmony_ci angle = 0; 15598c2ecf20Sopenharmony_ci 15608c2ecf20Sopenharmony_ci for (i = 0; i < len; i++) { 15618c2ecf20Sopenharmony_ci samples[i] = cordic_calc_iq(CORDIC_FIXED(angle)); 15628c2ecf20Sopenharmony_ci angle += rot; 15638c2ecf20Sopenharmony_ci samples[i].q = CORDIC_FLOAT(samples[i].q * max); 15648c2ecf20Sopenharmony_ci samples[i].i = CORDIC_FLOAT(samples[i].i * max); 15658c2ecf20Sopenharmony_ci } 15668c2ecf20Sopenharmony_ci 15678c2ecf20Sopenharmony_ci i = b43_nphy_load_samples(dev, samples, len); 15688c2ecf20Sopenharmony_ci kfree(samples); 15698c2ecf20Sopenharmony_ci return (i < 0) ? 0 : len; 15708c2ecf20Sopenharmony_ci} 15718c2ecf20Sopenharmony_ci 15728c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */ 15738c2ecf20Sopenharmony_cistatic void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops, 15748c2ecf20Sopenharmony_ci u16 wait, bool iqmode, bool dac_test, 15758c2ecf20Sopenharmony_ci bool modify_bbmult) 15768c2ecf20Sopenharmony_ci{ 15778c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 15788c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 15798c2ecf20Sopenharmony_ci int i; 15808c2ecf20Sopenharmony_ci u16 seq_mode; 15818c2ecf20Sopenharmony_ci u32 tmp; 15828c2ecf20Sopenharmony_ci 15838c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, true); 15848c2ecf20Sopenharmony_ci 15858c2ecf20Sopenharmony_ci if (phy->rev >= 7) { 15868c2ecf20Sopenharmony_ci bool lpf_bw3, lpf_bw4; 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_ci lpf_bw3 = b43_phy_read(dev, B43_NPHY_REV7_RF_CTL_OVER3) & 0x80; 15898c2ecf20Sopenharmony_ci lpf_bw4 = b43_phy_read(dev, B43_NPHY_REV7_RF_CTL_OVER4) & 0x80; 15908c2ecf20Sopenharmony_ci 15918c2ecf20Sopenharmony_ci if (lpf_bw3 || lpf_bw4) { 15928c2ecf20Sopenharmony_ci /* TODO */ 15938c2ecf20Sopenharmony_ci } else { 15948c2ecf20Sopenharmony_ci u16 value = b43_nphy_read_lpf_ctl(dev, 0); 15958c2ecf20Sopenharmony_ci if (phy->rev >= 19) 15968c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev19(dev, 0x80, value, 15978c2ecf20Sopenharmony_ci 0, false, 1); 15988c2ecf20Sopenharmony_ci else 15998c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x80, value, 16008c2ecf20Sopenharmony_ci 0, false, 1); 16018c2ecf20Sopenharmony_ci nphy->lpf_bw_overrode_for_sample_play = true; 16028c2ecf20Sopenharmony_ci } 16038c2ecf20Sopenharmony_ci } 16048c2ecf20Sopenharmony_ci 16058c2ecf20Sopenharmony_ci if ((nphy->bb_mult_save & 0x80000000) == 0) { 16068c2ecf20Sopenharmony_ci tmp = b43_ntab_read(dev, B43_NTAB16(15, 87)); 16078c2ecf20Sopenharmony_ci nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000; 16088c2ecf20Sopenharmony_ci } 16098c2ecf20Sopenharmony_ci 16108c2ecf20Sopenharmony_ci if (modify_bbmult) { 16118c2ecf20Sopenharmony_ci tmp = !b43_is_40mhz(dev) ? 0x6464 : 0x4747; 16128c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(15, 87), tmp); 16138c2ecf20Sopenharmony_ci } 16148c2ecf20Sopenharmony_ci 16158c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_SAMP_DEPCNT, (samps - 1)); 16168c2ecf20Sopenharmony_ci 16178c2ecf20Sopenharmony_ci if (loops != 0xFFFF) 16188c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, (loops - 1)); 16198c2ecf20Sopenharmony_ci else 16208c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, loops); 16218c2ecf20Sopenharmony_ci 16228c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_SAMP_WAITCNT, wait); 16238c2ecf20Sopenharmony_ci 16248c2ecf20Sopenharmony_ci seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE); 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_RFSEQMODE, B43_NPHY_RFSEQMODE_CAOVER); 16278c2ecf20Sopenharmony_ci if (iqmode) { 16288c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF); 16298c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8000); 16308c2ecf20Sopenharmony_ci } else { 16318c2ecf20Sopenharmony_ci tmp = dac_test ? 5 : 1; 16328c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_SAMP_CMD, tmp); 16338c2ecf20Sopenharmony_ci } 16348c2ecf20Sopenharmony_ci for (i = 0; i < 100; i++) { 16358c2ecf20Sopenharmony_ci if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & 1)) { 16368c2ecf20Sopenharmony_ci i = 0; 16378c2ecf20Sopenharmony_ci break; 16388c2ecf20Sopenharmony_ci } 16398c2ecf20Sopenharmony_ci udelay(10); 16408c2ecf20Sopenharmony_ci } 16418c2ecf20Sopenharmony_ci if (i) 16428c2ecf20Sopenharmony_ci b43err(dev->wl, "run samples timeout\n"); 16438c2ecf20Sopenharmony_ci 16448c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode); 16458c2ecf20Sopenharmony_ci 16468c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, false); 16478c2ecf20Sopenharmony_ci} 16488c2ecf20Sopenharmony_ci 16498c2ecf20Sopenharmony_ci/************************************************** 16508c2ecf20Sopenharmony_ci * RSSI 16518c2ecf20Sopenharmony_ci **************************************************/ 16528c2ecf20Sopenharmony_ci 16538c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */ 16548c2ecf20Sopenharmony_cistatic void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale, 16558c2ecf20Sopenharmony_ci s8 offset, u8 core, 16568c2ecf20Sopenharmony_ci enum n_rail_type rail, 16578c2ecf20Sopenharmony_ci enum n_rssi_type rssi_type) 16588c2ecf20Sopenharmony_ci{ 16598c2ecf20Sopenharmony_ci u16 tmp; 16608c2ecf20Sopenharmony_ci bool core1or5 = (core == 1) || (core == 5); 16618c2ecf20Sopenharmony_ci bool core2or5 = (core == 2) || (core == 5); 16628c2ecf20Sopenharmony_ci 16638c2ecf20Sopenharmony_ci offset = clamp_val(offset, -32, 31); 16648c2ecf20Sopenharmony_ci tmp = ((scale & 0x3F) << 8) | (offset & 0x3F); 16658c2ecf20Sopenharmony_ci 16668c2ecf20Sopenharmony_ci switch (rssi_type) { 16678c2ecf20Sopenharmony_ci case N_RSSI_NB: 16688c2ecf20Sopenharmony_ci if (core1or5 && rail == N_RAIL_I) 16698c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp); 16708c2ecf20Sopenharmony_ci if (core1or5 && rail == N_RAIL_Q) 16718c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp); 16728c2ecf20Sopenharmony_ci if (core2or5 && rail == N_RAIL_I) 16738c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp); 16748c2ecf20Sopenharmony_ci if (core2or5 && rail == N_RAIL_Q) 16758c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp); 16768c2ecf20Sopenharmony_ci break; 16778c2ecf20Sopenharmony_ci case N_RSSI_W1: 16788c2ecf20Sopenharmony_ci if (core1or5 && rail == N_RAIL_I) 16798c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp); 16808c2ecf20Sopenharmony_ci if (core1or5 && rail == N_RAIL_Q) 16818c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp); 16828c2ecf20Sopenharmony_ci if (core2or5 && rail == N_RAIL_I) 16838c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp); 16848c2ecf20Sopenharmony_ci if (core2or5 && rail == N_RAIL_Q) 16858c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp); 16868c2ecf20Sopenharmony_ci break; 16878c2ecf20Sopenharmony_ci case N_RSSI_W2: 16888c2ecf20Sopenharmony_ci if (core1or5 && rail == N_RAIL_I) 16898c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp); 16908c2ecf20Sopenharmony_ci if (core1or5 && rail == N_RAIL_Q) 16918c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp); 16928c2ecf20Sopenharmony_ci if (core2or5 && rail == N_RAIL_I) 16938c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp); 16948c2ecf20Sopenharmony_ci if (core2or5 && rail == N_RAIL_Q) 16958c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp); 16968c2ecf20Sopenharmony_ci break; 16978c2ecf20Sopenharmony_ci case N_RSSI_TBD: 16988c2ecf20Sopenharmony_ci if (core1or5 && rail == N_RAIL_I) 16998c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp); 17008c2ecf20Sopenharmony_ci if (core1or5 && rail == N_RAIL_Q) 17018c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp); 17028c2ecf20Sopenharmony_ci if (core2or5 && rail == N_RAIL_I) 17038c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp); 17048c2ecf20Sopenharmony_ci if (core2or5 && rail == N_RAIL_Q) 17058c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp); 17068c2ecf20Sopenharmony_ci break; 17078c2ecf20Sopenharmony_ci case N_RSSI_IQ: 17088c2ecf20Sopenharmony_ci if (core1or5 && rail == N_RAIL_I) 17098c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp); 17108c2ecf20Sopenharmony_ci if (core1or5 && rail == N_RAIL_Q) 17118c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp); 17128c2ecf20Sopenharmony_ci if (core2or5 && rail == N_RAIL_I) 17138c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp); 17148c2ecf20Sopenharmony_ci if (core2or5 && rail == N_RAIL_Q) 17158c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp); 17168c2ecf20Sopenharmony_ci break; 17178c2ecf20Sopenharmony_ci case N_RSSI_TSSI_2G: 17188c2ecf20Sopenharmony_ci if (core1or5) 17198c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp); 17208c2ecf20Sopenharmony_ci if (core2or5) 17218c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp); 17228c2ecf20Sopenharmony_ci break; 17238c2ecf20Sopenharmony_ci case N_RSSI_TSSI_5G: 17248c2ecf20Sopenharmony_ci if (core1or5) 17258c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp); 17268c2ecf20Sopenharmony_ci if (core2or5) 17278c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp); 17288c2ecf20Sopenharmony_ci break; 17298c2ecf20Sopenharmony_ci } 17308c2ecf20Sopenharmony_ci} 17318c2ecf20Sopenharmony_ci 17328c2ecf20Sopenharmony_cistatic void b43_nphy_rssi_select_rev19(struct b43_wldev *dev, u8 code, 17338c2ecf20Sopenharmony_ci enum n_rssi_type rssi_type) 17348c2ecf20Sopenharmony_ci{ 17358c2ecf20Sopenharmony_ci /* TODO */ 17368c2ecf20Sopenharmony_ci} 17378c2ecf20Sopenharmony_ci 17388c2ecf20Sopenharmony_cistatic void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, 17398c2ecf20Sopenharmony_ci enum n_rssi_type rssi_type) 17408c2ecf20Sopenharmony_ci{ 17418c2ecf20Sopenharmony_ci u8 i; 17428c2ecf20Sopenharmony_ci u16 reg, val; 17438c2ecf20Sopenharmony_ci 17448c2ecf20Sopenharmony_ci if (code == 0) { 17458c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, 0xFDFF); 17468c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, 0xFDFF); 17478c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_AFECTL_C1, 0xFCFF); 17488c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_AFECTL_C2, 0xFCFF); 17498c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S0, 0xFFDF); 17508c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_TXF_40CO_B32S1, 0xFFDF); 17518c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0xFFC3); 17528c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0xFFC3); 17538c2ecf20Sopenharmony_ci } else { 17548c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 17558c2ecf20Sopenharmony_ci if ((code == 1 && i == 1) || (code == 2 && !i)) 17568c2ecf20Sopenharmony_ci continue; 17578c2ecf20Sopenharmony_ci 17588c2ecf20Sopenharmony_ci reg = (i == 0) ? 17598c2ecf20Sopenharmony_ci B43_NPHY_AFECTL_OVER1 : B43_NPHY_AFECTL_OVER; 17608c2ecf20Sopenharmony_ci b43_phy_maskset(dev, reg, 0xFDFF, 0x0200); 17618c2ecf20Sopenharmony_ci 17628c2ecf20Sopenharmony_ci if (rssi_type == N_RSSI_W1 || 17638c2ecf20Sopenharmony_ci rssi_type == N_RSSI_W2 || 17648c2ecf20Sopenharmony_ci rssi_type == N_RSSI_NB) { 17658c2ecf20Sopenharmony_ci reg = (i == 0) ? 17668c2ecf20Sopenharmony_ci B43_NPHY_AFECTL_C1 : 17678c2ecf20Sopenharmony_ci B43_NPHY_AFECTL_C2; 17688c2ecf20Sopenharmony_ci b43_phy_maskset(dev, reg, 0xFCFF, 0); 17698c2ecf20Sopenharmony_ci 17708c2ecf20Sopenharmony_ci reg = (i == 0) ? 17718c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_LUT_TRSW_UP1 : 17728c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_LUT_TRSW_UP2; 17738c2ecf20Sopenharmony_ci b43_phy_maskset(dev, reg, 0xFFC3, 0); 17748c2ecf20Sopenharmony_ci 17758c2ecf20Sopenharmony_ci if (rssi_type == N_RSSI_W1) 17768c2ecf20Sopenharmony_ci val = (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ? 4 : 8; 17778c2ecf20Sopenharmony_ci else if (rssi_type == N_RSSI_W2) 17788c2ecf20Sopenharmony_ci val = 16; 17798c2ecf20Sopenharmony_ci else 17808c2ecf20Sopenharmony_ci val = 32; 17818c2ecf20Sopenharmony_ci b43_phy_set(dev, reg, val); 17828c2ecf20Sopenharmony_ci 17838c2ecf20Sopenharmony_ci reg = (i == 0) ? 17848c2ecf20Sopenharmony_ci B43_NPHY_TXF_40CO_B1S0 : 17858c2ecf20Sopenharmony_ci B43_NPHY_TXF_40CO_B32S1; 17868c2ecf20Sopenharmony_ci b43_phy_set(dev, reg, 0x0020); 17878c2ecf20Sopenharmony_ci } else { 17888c2ecf20Sopenharmony_ci if (rssi_type == N_RSSI_TBD) 17898c2ecf20Sopenharmony_ci val = 0x0100; 17908c2ecf20Sopenharmony_ci else if (rssi_type == N_RSSI_IQ) 17918c2ecf20Sopenharmony_ci val = 0x0200; 17928c2ecf20Sopenharmony_ci else 17938c2ecf20Sopenharmony_ci val = 0x0300; 17948c2ecf20Sopenharmony_ci 17958c2ecf20Sopenharmony_ci reg = (i == 0) ? 17968c2ecf20Sopenharmony_ci B43_NPHY_AFECTL_C1 : 17978c2ecf20Sopenharmony_ci B43_NPHY_AFECTL_C2; 17988c2ecf20Sopenharmony_ci 17998c2ecf20Sopenharmony_ci b43_phy_maskset(dev, reg, 0xFCFF, val); 18008c2ecf20Sopenharmony_ci b43_phy_maskset(dev, reg, 0xF3FF, val << 2); 18018c2ecf20Sopenharmony_ci 18028c2ecf20Sopenharmony_ci if (rssi_type != N_RSSI_IQ && 18038c2ecf20Sopenharmony_ci rssi_type != N_RSSI_TBD) { 18048c2ecf20Sopenharmony_ci enum nl80211_band band = 18058c2ecf20Sopenharmony_ci b43_current_band(dev->wl); 18068c2ecf20Sopenharmony_ci 18078c2ecf20Sopenharmony_ci if (dev->phy.rev < 7) { 18088c2ecf20Sopenharmony_ci if (b43_nphy_ipa(dev)) 18098c2ecf20Sopenharmony_ci val = (band == NL80211_BAND_5GHZ) ? 0xC : 0xE; 18108c2ecf20Sopenharmony_ci else 18118c2ecf20Sopenharmony_ci val = 0x11; 18128c2ecf20Sopenharmony_ci reg = (i == 0) ? B2056_TX0 : B2056_TX1; 18138c2ecf20Sopenharmony_ci reg |= B2056_TX_TX_SSI_MUX; 18148c2ecf20Sopenharmony_ci b43_radio_write(dev, reg, val); 18158c2ecf20Sopenharmony_ci } 18168c2ecf20Sopenharmony_ci 18178c2ecf20Sopenharmony_ci reg = (i == 0) ? 18188c2ecf20Sopenharmony_ci B43_NPHY_AFECTL_OVER1 : 18198c2ecf20Sopenharmony_ci B43_NPHY_AFECTL_OVER; 18208c2ecf20Sopenharmony_ci b43_phy_set(dev, reg, 0x0200); 18218c2ecf20Sopenharmony_ci } 18228c2ecf20Sopenharmony_ci } 18238c2ecf20Sopenharmony_ci } 18248c2ecf20Sopenharmony_ci } 18258c2ecf20Sopenharmony_ci} 18268c2ecf20Sopenharmony_ci 18278c2ecf20Sopenharmony_cistatic void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, 18288c2ecf20Sopenharmony_ci enum n_rssi_type rssi_type) 18298c2ecf20Sopenharmony_ci{ 18308c2ecf20Sopenharmony_ci u16 val; 18318c2ecf20Sopenharmony_ci bool rssi_w1_w2_nb = false; 18328c2ecf20Sopenharmony_ci 18338c2ecf20Sopenharmony_ci switch (rssi_type) { 18348c2ecf20Sopenharmony_ci case N_RSSI_W1: 18358c2ecf20Sopenharmony_ci case N_RSSI_W2: 18368c2ecf20Sopenharmony_ci case N_RSSI_NB: 18378c2ecf20Sopenharmony_ci val = 0; 18388c2ecf20Sopenharmony_ci rssi_w1_w2_nb = true; 18398c2ecf20Sopenharmony_ci break; 18408c2ecf20Sopenharmony_ci case N_RSSI_TBD: 18418c2ecf20Sopenharmony_ci val = 1; 18428c2ecf20Sopenharmony_ci break; 18438c2ecf20Sopenharmony_ci case N_RSSI_IQ: 18448c2ecf20Sopenharmony_ci val = 2; 18458c2ecf20Sopenharmony_ci break; 18468c2ecf20Sopenharmony_ci default: 18478c2ecf20Sopenharmony_ci val = 3; 18488c2ecf20Sopenharmony_ci } 18498c2ecf20Sopenharmony_ci 18508c2ecf20Sopenharmony_ci val = (val << 12) | (val << 14); 18518c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val); 18528c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val); 18538c2ecf20Sopenharmony_ci 18548c2ecf20Sopenharmony_ci if (rssi_w1_w2_nb) { 18558c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF, 18568c2ecf20Sopenharmony_ci (rssi_type + 1) << 4); 18578c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF, 18588c2ecf20Sopenharmony_ci (rssi_type + 1) << 4); 18598c2ecf20Sopenharmony_ci } 18608c2ecf20Sopenharmony_ci 18618c2ecf20Sopenharmony_ci if (code == 0) { 18628c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x3000); 18638c2ecf20Sopenharmony_ci if (rssi_w1_w2_nb) { 18648c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, 18658c2ecf20Sopenharmony_ci ~(B43_NPHY_RFCTL_CMD_RXEN | 18668c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_CMD_CORESEL)); 18678c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, 18688c2ecf20Sopenharmony_ci ~(0x1 << 12 | 18698c2ecf20Sopenharmony_ci 0x1 << 5 | 18708c2ecf20Sopenharmony_ci 0x1 << 1 | 18718c2ecf20Sopenharmony_ci 0x1)); 18728c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, 18738c2ecf20Sopenharmony_ci ~B43_NPHY_RFCTL_CMD_START); 18748c2ecf20Sopenharmony_ci udelay(20); 18758c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1); 18768c2ecf20Sopenharmony_ci } 18778c2ecf20Sopenharmony_ci } else { 18788c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x3000); 18798c2ecf20Sopenharmony_ci if (rssi_w1_w2_nb) { 18808c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 18818c2ecf20Sopenharmony_ci ~(B43_NPHY_RFCTL_CMD_RXEN | 18828c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_CMD_CORESEL), 18838c2ecf20Sopenharmony_ci (B43_NPHY_RFCTL_CMD_RXEN | 18848c2ecf20Sopenharmony_ci code << B43_NPHY_RFCTL_CMD_CORESEL_SHIFT)); 18858c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 18868c2ecf20Sopenharmony_ci (0x1 << 12 | 18878c2ecf20Sopenharmony_ci 0x1 << 5 | 18888c2ecf20Sopenharmony_ci 0x1 << 1 | 18898c2ecf20Sopenharmony_ci 0x1)); 18908c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_RFCTL_CMD, 18918c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_CMD_START); 18928c2ecf20Sopenharmony_ci udelay(20); 18938c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1); 18948c2ecf20Sopenharmony_ci } 18958c2ecf20Sopenharmony_ci } 18968c2ecf20Sopenharmony_ci} 18978c2ecf20Sopenharmony_ci 18988c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */ 18998c2ecf20Sopenharmony_cistatic void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, 19008c2ecf20Sopenharmony_ci enum n_rssi_type type) 19018c2ecf20Sopenharmony_ci{ 19028c2ecf20Sopenharmony_ci if (dev->phy.rev >= 19) 19038c2ecf20Sopenharmony_ci b43_nphy_rssi_select_rev19(dev, code, type); 19048c2ecf20Sopenharmony_ci else if (dev->phy.rev >= 3) 19058c2ecf20Sopenharmony_ci b43_nphy_rev3_rssi_select(dev, code, type); 19068c2ecf20Sopenharmony_ci else 19078c2ecf20Sopenharmony_ci b43_nphy_rev2_rssi_select(dev, code, type); 19088c2ecf20Sopenharmony_ci} 19098c2ecf20Sopenharmony_ci 19108c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */ 19118c2ecf20Sopenharmony_cistatic void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, 19128c2ecf20Sopenharmony_ci enum n_rssi_type rssi_type, u8 *buf) 19138c2ecf20Sopenharmony_ci{ 19148c2ecf20Sopenharmony_ci int i; 19158c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 19168c2ecf20Sopenharmony_ci if (rssi_type == N_RSSI_NB) { 19178c2ecf20Sopenharmony_ci if (i == 0) { 19188c2ecf20Sopenharmony_ci b43_radio_maskset(dev, B2055_C1_B0NB_RSSIVCM, 19198c2ecf20Sopenharmony_ci 0xFC, buf[0]); 19208c2ecf20Sopenharmony_ci b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5, 19218c2ecf20Sopenharmony_ci 0xFC, buf[1]); 19228c2ecf20Sopenharmony_ci } else { 19238c2ecf20Sopenharmony_ci b43_radio_maskset(dev, B2055_C2_B0NB_RSSIVCM, 19248c2ecf20Sopenharmony_ci 0xFC, buf[2 * i]); 19258c2ecf20Sopenharmony_ci b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5, 19268c2ecf20Sopenharmony_ci 0xFC, buf[2 * i + 1]); 19278c2ecf20Sopenharmony_ci } 19288c2ecf20Sopenharmony_ci } else { 19298c2ecf20Sopenharmony_ci if (i == 0) 19308c2ecf20Sopenharmony_ci b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5, 19318c2ecf20Sopenharmony_ci 0xF3, buf[0] << 2); 19328c2ecf20Sopenharmony_ci else 19338c2ecf20Sopenharmony_ci b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5, 19348c2ecf20Sopenharmony_ci 0xF3, buf[2 * i + 1] << 2); 19358c2ecf20Sopenharmony_ci } 19368c2ecf20Sopenharmony_ci } 19378c2ecf20Sopenharmony_ci} 19388c2ecf20Sopenharmony_ci 19398c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */ 19408c2ecf20Sopenharmony_cistatic int b43_nphy_poll_rssi(struct b43_wldev *dev, enum n_rssi_type rssi_type, 19418c2ecf20Sopenharmony_ci s32 *buf, u8 nsamp) 19428c2ecf20Sopenharmony_ci{ 19438c2ecf20Sopenharmony_ci int i; 19448c2ecf20Sopenharmony_ci int out; 19458c2ecf20Sopenharmony_ci u16 save_regs_phy[9]; 19468c2ecf20Sopenharmony_ci u16 s[2]; 19478c2ecf20Sopenharmony_ci 19488c2ecf20Sopenharmony_ci /* TODO: rev7+ is treated like rev3+, what about rev19+? */ 19498c2ecf20Sopenharmony_ci 19508c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) { 19518c2ecf20Sopenharmony_ci save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); 19528c2ecf20Sopenharmony_ci save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); 19538c2ecf20Sopenharmony_ci save_regs_phy[2] = b43_phy_read(dev, 19548c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_LUT_TRSW_UP1); 19558c2ecf20Sopenharmony_ci save_regs_phy[3] = b43_phy_read(dev, 19568c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_LUT_TRSW_UP2); 19578c2ecf20Sopenharmony_ci save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1); 19588c2ecf20Sopenharmony_ci save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); 19598c2ecf20Sopenharmony_ci save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0); 19608c2ecf20Sopenharmony_ci save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1); 19618c2ecf20Sopenharmony_ci save_regs_phy[8] = 0; 19628c2ecf20Sopenharmony_ci } else { 19638c2ecf20Sopenharmony_ci save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); 19648c2ecf20Sopenharmony_ci save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); 19658c2ecf20Sopenharmony_ci save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); 19668c2ecf20Sopenharmony_ci save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_RFCTL_CMD); 19678c2ecf20Sopenharmony_ci save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER); 19688c2ecf20Sopenharmony_ci save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1); 19698c2ecf20Sopenharmony_ci save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2); 19708c2ecf20Sopenharmony_ci save_regs_phy[7] = 0; 19718c2ecf20Sopenharmony_ci save_regs_phy[8] = 0; 19728c2ecf20Sopenharmony_ci } 19738c2ecf20Sopenharmony_ci 19748c2ecf20Sopenharmony_ci b43_nphy_rssi_select(dev, 5, rssi_type); 19758c2ecf20Sopenharmony_ci 19768c2ecf20Sopenharmony_ci if (dev->phy.rev < 2) { 19778c2ecf20Sopenharmony_ci save_regs_phy[8] = b43_phy_read(dev, B43_NPHY_GPIO_SEL); 19788c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_GPIO_SEL, 5); 19798c2ecf20Sopenharmony_ci } 19808c2ecf20Sopenharmony_ci 19818c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 19828c2ecf20Sopenharmony_ci buf[i] = 0; 19838c2ecf20Sopenharmony_ci 19848c2ecf20Sopenharmony_ci for (i = 0; i < nsamp; i++) { 19858c2ecf20Sopenharmony_ci if (dev->phy.rev < 2) { 19868c2ecf20Sopenharmony_ci s[0] = b43_phy_read(dev, B43_NPHY_GPIO_LOOUT); 19878c2ecf20Sopenharmony_ci s[1] = b43_phy_read(dev, B43_NPHY_GPIO_HIOUT); 19888c2ecf20Sopenharmony_ci } else { 19898c2ecf20Sopenharmony_ci s[0] = b43_phy_read(dev, B43_NPHY_RSSI1); 19908c2ecf20Sopenharmony_ci s[1] = b43_phy_read(dev, B43_NPHY_RSSI2); 19918c2ecf20Sopenharmony_ci } 19928c2ecf20Sopenharmony_ci 19938c2ecf20Sopenharmony_ci buf[0] += ((s8)((s[0] & 0x3F) << 2)) >> 2; 19948c2ecf20Sopenharmony_ci buf[1] += ((s8)(((s[0] >> 8) & 0x3F) << 2)) >> 2; 19958c2ecf20Sopenharmony_ci buf[2] += ((s8)((s[1] & 0x3F) << 2)) >> 2; 19968c2ecf20Sopenharmony_ci buf[3] += ((s8)(((s[1] >> 8) & 0x3F) << 2)) >> 2; 19978c2ecf20Sopenharmony_ci } 19988c2ecf20Sopenharmony_ci out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 | 19998c2ecf20Sopenharmony_ci (buf[2] & 0xFF) << 8 | (buf[3] & 0xFF); 20008c2ecf20Sopenharmony_ci 20018c2ecf20Sopenharmony_ci if (dev->phy.rev < 2) 20028c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_GPIO_SEL, save_regs_phy[8]); 20038c2ecf20Sopenharmony_ci 20048c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) { 20058c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]); 20068c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]); 20078c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 20088c2ecf20Sopenharmony_ci save_regs_phy[2]); 20098c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 20108c2ecf20Sopenharmony_ci save_regs_phy[3]); 20118c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, save_regs_phy[4]); 20128c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]); 20138c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]); 20148c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]); 20158c2ecf20Sopenharmony_ci } else { 20168c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]); 20178c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]); 20188c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[2]); 20198c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_CMD, save_regs_phy[3]); 20208c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_OVER, save_regs_phy[4]); 20218c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, save_regs_phy[5]); 20228c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, save_regs_phy[6]); 20238c2ecf20Sopenharmony_ci } 20248c2ecf20Sopenharmony_ci 20258c2ecf20Sopenharmony_ci return out; 20268c2ecf20Sopenharmony_ci} 20278c2ecf20Sopenharmony_ci 20288c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */ 20298c2ecf20Sopenharmony_cistatic void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) 20308c2ecf20Sopenharmony_ci{ 20318c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 20328c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 20338c2ecf20Sopenharmony_ci 20348c2ecf20Sopenharmony_ci u16 saved_regs_phy_rfctl[2]; 20358c2ecf20Sopenharmony_ci u16 saved_regs_phy[22]; 20368c2ecf20Sopenharmony_ci u16 regs_to_store_rev3[] = { 20378c2ecf20Sopenharmony_ci B43_NPHY_AFECTL_OVER1, B43_NPHY_AFECTL_OVER, 20388c2ecf20Sopenharmony_ci B43_NPHY_AFECTL_C1, B43_NPHY_AFECTL_C2, 20398c2ecf20Sopenharmony_ci B43_NPHY_TXF_40CO_B1S1, B43_NPHY_RFCTL_OVER, 20408c2ecf20Sopenharmony_ci B43_NPHY_TXF_40CO_B1S0, B43_NPHY_TXF_40CO_B32S1, 20418c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_CMD, 20428c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_LUT_TRSW_UP1, B43_NPHY_RFCTL_LUT_TRSW_UP2, 20438c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2 20448c2ecf20Sopenharmony_ci }; 20458c2ecf20Sopenharmony_ci u16 regs_to_store_rev7[] = { 20468c2ecf20Sopenharmony_ci B43_NPHY_AFECTL_OVER1, B43_NPHY_AFECTL_OVER, 20478c2ecf20Sopenharmony_ci B43_NPHY_AFECTL_C1, B43_NPHY_AFECTL_C2, 20488c2ecf20Sopenharmony_ci B43_NPHY_TXF_40CO_B1S1, B43_NPHY_RFCTL_OVER, 20498c2ecf20Sopenharmony_ci B43_NPHY_REV7_RF_CTL_OVER3, B43_NPHY_REV7_RF_CTL_OVER4, 20508c2ecf20Sopenharmony_ci B43_NPHY_REV7_RF_CTL_OVER5, B43_NPHY_REV7_RF_CTL_OVER6, 20518c2ecf20Sopenharmony_ci 0x2ff, 20528c2ecf20Sopenharmony_ci B43_NPHY_TXF_40CO_B1S0, B43_NPHY_TXF_40CO_B32S1, 20538c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_CMD, 20548c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_LUT_TRSW_UP1, B43_NPHY_RFCTL_LUT_TRSW_UP2, 20558c2ecf20Sopenharmony_ci B43_NPHY_REV7_RF_CTL_MISC_REG3, B43_NPHY_REV7_RF_CTL_MISC_REG4, 20568c2ecf20Sopenharmony_ci B43_NPHY_REV7_RF_CTL_MISC_REG5, B43_NPHY_REV7_RF_CTL_MISC_REG6, 20578c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_RSSIO1, B43_NPHY_RFCTL_RSSIO2 20588c2ecf20Sopenharmony_ci }; 20598c2ecf20Sopenharmony_ci u16 *regs_to_store; 20608c2ecf20Sopenharmony_ci int regs_amount; 20618c2ecf20Sopenharmony_ci 20628c2ecf20Sopenharmony_ci u16 class; 20638c2ecf20Sopenharmony_ci 20648c2ecf20Sopenharmony_ci u16 clip_state[2]; 20658c2ecf20Sopenharmony_ci u16 clip_off[2] = { 0xFFFF, 0xFFFF }; 20668c2ecf20Sopenharmony_ci 20678c2ecf20Sopenharmony_ci u8 vcm_final = 0; 20688c2ecf20Sopenharmony_ci s32 offset[4]; 20698c2ecf20Sopenharmony_ci s32 results[8][4] = { }; 20708c2ecf20Sopenharmony_ci s32 results_min[4] = { }; 20718c2ecf20Sopenharmony_ci s32 poll_results[4] = { }; 20728c2ecf20Sopenharmony_ci 20738c2ecf20Sopenharmony_ci u16 *rssical_radio_regs = NULL; 20748c2ecf20Sopenharmony_ci u16 *rssical_phy_regs = NULL; 20758c2ecf20Sopenharmony_ci 20768c2ecf20Sopenharmony_ci u16 r; /* routing */ 20778c2ecf20Sopenharmony_ci u8 rx_core_state; 20788c2ecf20Sopenharmony_ci int core, i, j, vcm; 20798c2ecf20Sopenharmony_ci 20808c2ecf20Sopenharmony_ci if (dev->phy.rev >= 7) { 20818c2ecf20Sopenharmony_ci regs_to_store = regs_to_store_rev7; 20828c2ecf20Sopenharmony_ci regs_amount = ARRAY_SIZE(regs_to_store_rev7); 20838c2ecf20Sopenharmony_ci } else { 20848c2ecf20Sopenharmony_ci regs_to_store = regs_to_store_rev3; 20858c2ecf20Sopenharmony_ci regs_amount = ARRAY_SIZE(regs_to_store_rev3); 20868c2ecf20Sopenharmony_ci } 20878c2ecf20Sopenharmony_ci BUG_ON(regs_amount > ARRAY_SIZE(saved_regs_phy)); 20888c2ecf20Sopenharmony_ci 20898c2ecf20Sopenharmony_ci class = b43_nphy_classifier(dev, 0, 0); 20908c2ecf20Sopenharmony_ci b43_nphy_classifier(dev, 7, 4); 20918c2ecf20Sopenharmony_ci b43_nphy_read_clip_detection(dev, clip_state); 20928c2ecf20Sopenharmony_ci b43_nphy_write_clip_detection(dev, clip_off); 20938c2ecf20Sopenharmony_ci 20948c2ecf20Sopenharmony_ci saved_regs_phy_rfctl[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); 20958c2ecf20Sopenharmony_ci saved_regs_phy_rfctl[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); 20968c2ecf20Sopenharmony_ci for (i = 0; i < regs_amount; i++) 20978c2ecf20Sopenharmony_ci saved_regs_phy[i] = b43_phy_read(dev, regs_to_store[i]); 20988c2ecf20Sopenharmony_ci 20998c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_OFF, 0, 7); 21008c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 1, 7); 21018c2ecf20Sopenharmony_ci 21028c2ecf20Sopenharmony_ci if (dev->phy.rev >= 7) { 21038c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_one_to_many(dev, 21048c2ecf20Sopenharmony_ci N_RF_CTL_OVER_CMD_RXRF_PU, 21058c2ecf20Sopenharmony_ci 0, 0, false); 21068c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_one_to_many(dev, 21078c2ecf20Sopenharmony_ci N_RF_CTL_OVER_CMD_RX_PU, 21088c2ecf20Sopenharmony_ci 1, 0, false); 21098c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x80, 1, 0, false, 0); 21108c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x40, 1, 0, false, 0); 21118c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { 21128c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x20, 0, 0, false, 21138c2ecf20Sopenharmony_ci 0); 21148c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x10, 1, 0, false, 21158c2ecf20Sopenharmony_ci 0); 21168c2ecf20Sopenharmony_ci } else { 21178c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x10, 0, 0, false, 21188c2ecf20Sopenharmony_ci 0); 21198c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x20, 1, 0, false, 21208c2ecf20Sopenharmony_ci 0); 21218c2ecf20Sopenharmony_ci } 21228c2ecf20Sopenharmony_ci } else { 21238c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override(dev, 0x1, 0, 0, false); 21248c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override(dev, 0x2, 1, 0, false); 21258c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override(dev, 0x80, 1, 0, false); 21268c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override(dev, 0x40, 1, 0, false); 21278c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { 21288c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override(dev, 0x20, 0, 0, false); 21298c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override(dev, 0x10, 1, 0, false); 21308c2ecf20Sopenharmony_ci } else { 21318c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override(dev, 0x10, 0, 0, false); 21328c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override(dev, 0x20, 1, 0, false); 21338c2ecf20Sopenharmony_ci } 21348c2ecf20Sopenharmony_ci } 21358c2ecf20Sopenharmony_ci 21368c2ecf20Sopenharmony_ci rx_core_state = b43_nphy_get_rx_core_state(dev); 21378c2ecf20Sopenharmony_ci for (core = 0; core < 2; core++) { 21388c2ecf20Sopenharmony_ci if (!(rx_core_state & (1 << core))) 21398c2ecf20Sopenharmony_ci continue; 21408c2ecf20Sopenharmony_ci r = core ? B2056_RX1 : B2056_RX0; 21418c2ecf20Sopenharmony_ci b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, N_RAIL_I, 21428c2ecf20Sopenharmony_ci N_RSSI_NB); 21438c2ecf20Sopenharmony_ci b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, N_RAIL_Q, 21448c2ecf20Sopenharmony_ci N_RSSI_NB); 21458c2ecf20Sopenharmony_ci 21468c2ecf20Sopenharmony_ci /* Grab RSSI results for every possible VCM */ 21478c2ecf20Sopenharmony_ci for (vcm = 0; vcm < 8; vcm++) { 21488c2ecf20Sopenharmony_ci if (dev->phy.rev >= 7) 21498c2ecf20Sopenharmony_ci b43_radio_maskset(dev, 21508c2ecf20Sopenharmony_ci core ? R2057_NB_MASTER_CORE1 : 21518c2ecf20Sopenharmony_ci R2057_NB_MASTER_CORE0, 21528c2ecf20Sopenharmony_ci ~R2057_VCM_MASK, vcm); 21538c2ecf20Sopenharmony_ci else 21548c2ecf20Sopenharmony_ci b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC, 21558c2ecf20Sopenharmony_ci 0xE3, vcm << 2); 21568c2ecf20Sopenharmony_ci b43_nphy_poll_rssi(dev, N_RSSI_NB, results[vcm], 8); 21578c2ecf20Sopenharmony_ci } 21588c2ecf20Sopenharmony_ci 21598c2ecf20Sopenharmony_ci /* Find out which VCM got the best results */ 21608c2ecf20Sopenharmony_ci for (i = 0; i < 4; i += 2) { 21618c2ecf20Sopenharmony_ci s32 currd; 21628c2ecf20Sopenharmony_ci s32 mind = 0x100000; 21638c2ecf20Sopenharmony_ci s32 minpoll = 249; 21648c2ecf20Sopenharmony_ci u8 minvcm = 0; 21658c2ecf20Sopenharmony_ci if (2 * core != i) 21668c2ecf20Sopenharmony_ci continue; 21678c2ecf20Sopenharmony_ci for (vcm = 0; vcm < 8; vcm++) { 21688c2ecf20Sopenharmony_ci currd = results[vcm][i] * results[vcm][i] + 21698c2ecf20Sopenharmony_ci results[vcm][i + 1] * results[vcm][i]; 21708c2ecf20Sopenharmony_ci if (currd < mind) { 21718c2ecf20Sopenharmony_ci mind = currd; 21728c2ecf20Sopenharmony_ci minvcm = vcm; 21738c2ecf20Sopenharmony_ci } 21748c2ecf20Sopenharmony_ci if (results[vcm][i] < minpoll) 21758c2ecf20Sopenharmony_ci minpoll = results[vcm][i]; 21768c2ecf20Sopenharmony_ci } 21778c2ecf20Sopenharmony_ci vcm_final = minvcm; 21788c2ecf20Sopenharmony_ci results_min[i] = minpoll; 21798c2ecf20Sopenharmony_ci } 21808c2ecf20Sopenharmony_ci 21818c2ecf20Sopenharmony_ci /* Select the best VCM */ 21828c2ecf20Sopenharmony_ci if (dev->phy.rev >= 7) 21838c2ecf20Sopenharmony_ci b43_radio_maskset(dev, 21848c2ecf20Sopenharmony_ci core ? R2057_NB_MASTER_CORE1 : 21858c2ecf20Sopenharmony_ci R2057_NB_MASTER_CORE0, 21868c2ecf20Sopenharmony_ci ~R2057_VCM_MASK, vcm); 21878c2ecf20Sopenharmony_ci else 21888c2ecf20Sopenharmony_ci b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC, 21898c2ecf20Sopenharmony_ci 0xE3, vcm_final << 2); 21908c2ecf20Sopenharmony_ci 21918c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) { 21928c2ecf20Sopenharmony_ci if (core != i / 2) 21938c2ecf20Sopenharmony_ci continue; 21948c2ecf20Sopenharmony_ci offset[i] = -results[vcm_final][i]; 21958c2ecf20Sopenharmony_ci if (offset[i] < 0) 21968c2ecf20Sopenharmony_ci offset[i] = -((abs(offset[i]) + 4) / 8); 21978c2ecf20Sopenharmony_ci else 21988c2ecf20Sopenharmony_ci offset[i] = (offset[i] + 4) / 8; 21998c2ecf20Sopenharmony_ci if (results_min[i] == 248) 22008c2ecf20Sopenharmony_ci offset[i] = -32; 22018c2ecf20Sopenharmony_ci b43_nphy_scale_offset_rssi(dev, 0, offset[i], 22028c2ecf20Sopenharmony_ci (i / 2 == 0) ? 1 : 2, 22038c2ecf20Sopenharmony_ci (i % 2 == 0) ? N_RAIL_I : N_RAIL_Q, 22048c2ecf20Sopenharmony_ci N_RSSI_NB); 22058c2ecf20Sopenharmony_ci } 22068c2ecf20Sopenharmony_ci } 22078c2ecf20Sopenharmony_ci 22088c2ecf20Sopenharmony_ci for (core = 0; core < 2; core++) { 22098c2ecf20Sopenharmony_ci if (!(rx_core_state & (1 << core))) 22108c2ecf20Sopenharmony_ci continue; 22118c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 22128c2ecf20Sopenharmony_ci b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 22138c2ecf20Sopenharmony_ci N_RAIL_I, i); 22148c2ecf20Sopenharmony_ci b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 22158c2ecf20Sopenharmony_ci N_RAIL_Q, i); 22168c2ecf20Sopenharmony_ci b43_nphy_poll_rssi(dev, i, poll_results, 8); 22178c2ecf20Sopenharmony_ci for (j = 0; j < 4; j++) { 22188c2ecf20Sopenharmony_ci if (j / 2 == core) { 22198c2ecf20Sopenharmony_ci offset[j] = 232 - poll_results[j]; 22208c2ecf20Sopenharmony_ci if (offset[j] < 0) 22218c2ecf20Sopenharmony_ci offset[j] = -(abs(offset[j] + 4) / 8); 22228c2ecf20Sopenharmony_ci else 22238c2ecf20Sopenharmony_ci offset[j] = (offset[j] + 4) / 8; 22248c2ecf20Sopenharmony_ci b43_nphy_scale_offset_rssi(dev, 0, 22258c2ecf20Sopenharmony_ci offset[2 * core], core + 1, j % 2, i); 22268c2ecf20Sopenharmony_ci } 22278c2ecf20Sopenharmony_ci } 22288c2ecf20Sopenharmony_ci } 22298c2ecf20Sopenharmony_ci } 22308c2ecf20Sopenharmony_ci 22318c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, saved_regs_phy_rfctl[0]); 22328c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, saved_regs_phy_rfctl[1]); 22338c2ecf20Sopenharmony_ci 22348c2ecf20Sopenharmony_ci b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); 22358c2ecf20Sopenharmony_ci 22368c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_TXF_40CO_B1S1, 0x1); 22378c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_START); 22388c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S1, ~0x1); 22398c2ecf20Sopenharmony_ci 22408c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x1); 22418c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_RFCTL_CMD, B43_NPHY_RFCTL_CMD_RXTX); 22428c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1); 22438c2ecf20Sopenharmony_ci 22448c2ecf20Sopenharmony_ci for (i = 0; i < regs_amount; i++) 22458c2ecf20Sopenharmony_ci b43_phy_write(dev, regs_to_store[i], saved_regs_phy[i]); 22468c2ecf20Sopenharmony_ci 22478c2ecf20Sopenharmony_ci /* Store for future configuration */ 22488c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { 22498c2ecf20Sopenharmony_ci rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G; 22508c2ecf20Sopenharmony_ci rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G; 22518c2ecf20Sopenharmony_ci } else { 22528c2ecf20Sopenharmony_ci rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G; 22538c2ecf20Sopenharmony_ci rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; 22548c2ecf20Sopenharmony_ci } 22558c2ecf20Sopenharmony_ci if (dev->phy.rev >= 7) { 22568c2ecf20Sopenharmony_ci rssical_radio_regs[0] = b43_radio_read(dev, 22578c2ecf20Sopenharmony_ci R2057_NB_MASTER_CORE0); 22588c2ecf20Sopenharmony_ci rssical_radio_regs[1] = b43_radio_read(dev, 22598c2ecf20Sopenharmony_ci R2057_NB_MASTER_CORE1); 22608c2ecf20Sopenharmony_ci } else { 22618c2ecf20Sopenharmony_ci rssical_radio_regs[0] = b43_radio_read(dev, B2056_RX0 | 22628c2ecf20Sopenharmony_ci B2056_RX_RSSI_MISC); 22638c2ecf20Sopenharmony_ci rssical_radio_regs[1] = b43_radio_read(dev, B2056_RX1 | 22648c2ecf20Sopenharmony_ci B2056_RX_RSSI_MISC); 22658c2ecf20Sopenharmony_ci } 22668c2ecf20Sopenharmony_ci rssical_phy_regs[0] = b43_phy_read(dev, B43_NPHY_RSSIMC_0I_RSSI_Z); 22678c2ecf20Sopenharmony_ci rssical_phy_regs[1] = b43_phy_read(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z); 22688c2ecf20Sopenharmony_ci rssical_phy_regs[2] = b43_phy_read(dev, B43_NPHY_RSSIMC_1I_RSSI_Z); 22698c2ecf20Sopenharmony_ci rssical_phy_regs[3] = b43_phy_read(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z); 22708c2ecf20Sopenharmony_ci rssical_phy_regs[4] = b43_phy_read(dev, B43_NPHY_RSSIMC_0I_RSSI_X); 22718c2ecf20Sopenharmony_ci rssical_phy_regs[5] = b43_phy_read(dev, B43_NPHY_RSSIMC_0Q_RSSI_X); 22728c2ecf20Sopenharmony_ci rssical_phy_regs[6] = b43_phy_read(dev, B43_NPHY_RSSIMC_1I_RSSI_X); 22738c2ecf20Sopenharmony_ci rssical_phy_regs[7] = b43_phy_read(dev, B43_NPHY_RSSIMC_1Q_RSSI_X); 22748c2ecf20Sopenharmony_ci rssical_phy_regs[8] = b43_phy_read(dev, B43_NPHY_RSSIMC_0I_RSSI_Y); 22758c2ecf20Sopenharmony_ci rssical_phy_regs[9] = b43_phy_read(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y); 22768c2ecf20Sopenharmony_ci rssical_phy_regs[10] = b43_phy_read(dev, B43_NPHY_RSSIMC_1I_RSSI_Y); 22778c2ecf20Sopenharmony_ci rssical_phy_regs[11] = b43_phy_read(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y); 22788c2ecf20Sopenharmony_ci 22798c2ecf20Sopenharmony_ci /* Remember for which channel we store configuration */ 22808c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) 22818c2ecf20Sopenharmony_ci nphy->rssical_chanspec_2G.center_freq = phy->chandef->chan->center_freq; 22828c2ecf20Sopenharmony_ci else 22838c2ecf20Sopenharmony_ci nphy->rssical_chanspec_5G.center_freq = phy->chandef->chan->center_freq; 22848c2ecf20Sopenharmony_ci 22858c2ecf20Sopenharmony_ci /* End of calibration, restore configuration */ 22868c2ecf20Sopenharmony_ci b43_nphy_classifier(dev, 7, class); 22878c2ecf20Sopenharmony_ci b43_nphy_write_clip_detection(dev, clip_state); 22888c2ecf20Sopenharmony_ci} 22898c2ecf20Sopenharmony_ci 22908c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */ 22918c2ecf20Sopenharmony_cistatic void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, enum n_rssi_type type) 22928c2ecf20Sopenharmony_ci{ 22938c2ecf20Sopenharmony_ci int i, j, vcm; 22948c2ecf20Sopenharmony_ci u8 state[4]; 22958c2ecf20Sopenharmony_ci u8 code, val; 22968c2ecf20Sopenharmony_ci u16 class, override; 22978c2ecf20Sopenharmony_ci u8 regs_save_radio[2]; 22988c2ecf20Sopenharmony_ci u16 regs_save_phy[2]; 22998c2ecf20Sopenharmony_ci 23008c2ecf20Sopenharmony_ci s32 offset[4]; 23018c2ecf20Sopenharmony_ci u8 core; 23028c2ecf20Sopenharmony_ci u8 rail; 23038c2ecf20Sopenharmony_ci 23048c2ecf20Sopenharmony_ci u16 clip_state[2]; 23058c2ecf20Sopenharmony_ci u16 clip_off[2] = { 0xFFFF, 0xFFFF }; 23068c2ecf20Sopenharmony_ci s32 results_min[4] = { }; 23078c2ecf20Sopenharmony_ci u8 vcm_final[4] = { }; 23088c2ecf20Sopenharmony_ci s32 results[4][4] = { }; 23098c2ecf20Sopenharmony_ci s32 miniq[4][2] = { }; 23108c2ecf20Sopenharmony_ci 23118c2ecf20Sopenharmony_ci if (type == N_RSSI_NB) { 23128c2ecf20Sopenharmony_ci code = 0; 23138c2ecf20Sopenharmony_ci val = 6; 23148c2ecf20Sopenharmony_ci } else if (type == N_RSSI_W1 || type == N_RSSI_W2) { 23158c2ecf20Sopenharmony_ci code = 25; 23168c2ecf20Sopenharmony_ci val = 4; 23178c2ecf20Sopenharmony_ci } else { 23188c2ecf20Sopenharmony_ci B43_WARN_ON(1); 23198c2ecf20Sopenharmony_ci return; 23208c2ecf20Sopenharmony_ci } 23218c2ecf20Sopenharmony_ci 23228c2ecf20Sopenharmony_ci class = b43_nphy_classifier(dev, 0, 0); 23238c2ecf20Sopenharmony_ci b43_nphy_classifier(dev, 7, 4); 23248c2ecf20Sopenharmony_ci b43_nphy_read_clip_detection(dev, clip_state); 23258c2ecf20Sopenharmony_ci b43_nphy_write_clip_detection(dev, clip_off); 23268c2ecf20Sopenharmony_ci 23278c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) 23288c2ecf20Sopenharmony_ci override = 0x140; 23298c2ecf20Sopenharmony_ci else 23308c2ecf20Sopenharmony_ci override = 0x110; 23318c2ecf20Sopenharmony_ci 23328c2ecf20Sopenharmony_ci regs_save_phy[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); 23338c2ecf20Sopenharmony_ci regs_save_radio[0] = b43_radio_read(dev, B2055_C1_PD_RXTX); 23348c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, override); 23358c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C1_PD_RXTX, val); 23368c2ecf20Sopenharmony_ci 23378c2ecf20Sopenharmony_ci regs_save_phy[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); 23388c2ecf20Sopenharmony_ci regs_save_radio[1] = b43_radio_read(dev, B2055_C2_PD_RXTX); 23398c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, override); 23408c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C2_PD_RXTX, val); 23418c2ecf20Sopenharmony_ci 23428c2ecf20Sopenharmony_ci state[0] = b43_radio_read(dev, B2055_C1_PD_RSSIMISC) & 0x07; 23438c2ecf20Sopenharmony_ci state[1] = b43_radio_read(dev, B2055_C2_PD_RSSIMISC) & 0x07; 23448c2ecf20Sopenharmony_ci b43_radio_mask(dev, B2055_C1_PD_RSSIMISC, 0xF8); 23458c2ecf20Sopenharmony_ci b43_radio_mask(dev, B2055_C2_PD_RSSIMISC, 0xF8); 23468c2ecf20Sopenharmony_ci state[2] = b43_radio_read(dev, B2055_C1_SP_RSSI) & 0x07; 23478c2ecf20Sopenharmony_ci state[3] = b43_radio_read(dev, B2055_C2_SP_RSSI) & 0x07; 23488c2ecf20Sopenharmony_ci 23498c2ecf20Sopenharmony_ci b43_nphy_rssi_select(dev, 5, type); 23508c2ecf20Sopenharmony_ci b43_nphy_scale_offset_rssi(dev, 0, 0, 5, N_RAIL_I, type); 23518c2ecf20Sopenharmony_ci b43_nphy_scale_offset_rssi(dev, 0, 0, 5, N_RAIL_Q, type); 23528c2ecf20Sopenharmony_ci 23538c2ecf20Sopenharmony_ci for (vcm = 0; vcm < 4; vcm++) { 23548c2ecf20Sopenharmony_ci u8 tmp[4]; 23558c2ecf20Sopenharmony_ci for (j = 0; j < 4; j++) 23568c2ecf20Sopenharmony_ci tmp[j] = vcm; 23578c2ecf20Sopenharmony_ci if (type != N_RSSI_W2) 23588c2ecf20Sopenharmony_ci b43_nphy_set_rssi_2055_vcm(dev, type, tmp); 23598c2ecf20Sopenharmony_ci b43_nphy_poll_rssi(dev, type, results[vcm], 8); 23608c2ecf20Sopenharmony_ci if (type == N_RSSI_W1 || type == N_RSSI_W2) 23618c2ecf20Sopenharmony_ci for (j = 0; j < 2; j++) 23628c2ecf20Sopenharmony_ci miniq[vcm][j] = min(results[vcm][2 * j], 23638c2ecf20Sopenharmony_ci results[vcm][2 * j + 1]); 23648c2ecf20Sopenharmony_ci } 23658c2ecf20Sopenharmony_ci 23668c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) { 23678c2ecf20Sopenharmony_ci s32 mind = 0x100000; 23688c2ecf20Sopenharmony_ci u8 minvcm = 0; 23698c2ecf20Sopenharmony_ci s32 minpoll = 249; 23708c2ecf20Sopenharmony_ci s32 currd; 23718c2ecf20Sopenharmony_ci for (vcm = 0; vcm < 4; vcm++) { 23728c2ecf20Sopenharmony_ci if (type == N_RSSI_NB) 23738c2ecf20Sopenharmony_ci currd = abs(results[vcm][i] - code * 8); 23748c2ecf20Sopenharmony_ci else 23758c2ecf20Sopenharmony_ci currd = abs(miniq[vcm][i / 2] - code * 8); 23768c2ecf20Sopenharmony_ci 23778c2ecf20Sopenharmony_ci if (currd < mind) { 23788c2ecf20Sopenharmony_ci mind = currd; 23798c2ecf20Sopenharmony_ci minvcm = vcm; 23808c2ecf20Sopenharmony_ci } 23818c2ecf20Sopenharmony_ci 23828c2ecf20Sopenharmony_ci if (results[vcm][i] < minpoll) 23838c2ecf20Sopenharmony_ci minpoll = results[vcm][i]; 23848c2ecf20Sopenharmony_ci } 23858c2ecf20Sopenharmony_ci results_min[i] = minpoll; 23868c2ecf20Sopenharmony_ci vcm_final[i] = minvcm; 23878c2ecf20Sopenharmony_ci } 23888c2ecf20Sopenharmony_ci 23898c2ecf20Sopenharmony_ci if (type != N_RSSI_W2) 23908c2ecf20Sopenharmony_ci b43_nphy_set_rssi_2055_vcm(dev, type, vcm_final); 23918c2ecf20Sopenharmony_ci 23928c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) { 23938c2ecf20Sopenharmony_ci offset[i] = (code * 8) - results[vcm_final[i]][i]; 23948c2ecf20Sopenharmony_ci 23958c2ecf20Sopenharmony_ci if (offset[i] < 0) 23968c2ecf20Sopenharmony_ci offset[i] = -((abs(offset[i]) + 4) / 8); 23978c2ecf20Sopenharmony_ci else 23988c2ecf20Sopenharmony_ci offset[i] = (offset[i] + 4) / 8; 23998c2ecf20Sopenharmony_ci 24008c2ecf20Sopenharmony_ci if (results_min[i] == 248) 24018c2ecf20Sopenharmony_ci offset[i] = code - 32; 24028c2ecf20Sopenharmony_ci 24038c2ecf20Sopenharmony_ci core = (i / 2) ? 2 : 1; 24048c2ecf20Sopenharmony_ci rail = (i % 2) ? N_RAIL_Q : N_RAIL_I; 24058c2ecf20Sopenharmony_ci 24068c2ecf20Sopenharmony_ci b43_nphy_scale_offset_rssi(dev, 0, offset[i], core, rail, 24078c2ecf20Sopenharmony_ci type); 24088c2ecf20Sopenharmony_ci } 24098c2ecf20Sopenharmony_ci 24108c2ecf20Sopenharmony_ci b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[0]); 24118c2ecf20Sopenharmony_ci b43_radio_maskset(dev, B2055_C2_PD_RSSIMISC, 0xF8, state[1]); 24128c2ecf20Sopenharmony_ci 24138c2ecf20Sopenharmony_ci switch (state[2]) { 24148c2ecf20Sopenharmony_ci case 1: 24158c2ecf20Sopenharmony_ci b43_nphy_rssi_select(dev, 1, N_RSSI_NB); 24168c2ecf20Sopenharmony_ci break; 24178c2ecf20Sopenharmony_ci case 4: 24188c2ecf20Sopenharmony_ci b43_nphy_rssi_select(dev, 1, N_RSSI_W1); 24198c2ecf20Sopenharmony_ci break; 24208c2ecf20Sopenharmony_ci case 2: 24218c2ecf20Sopenharmony_ci b43_nphy_rssi_select(dev, 1, N_RSSI_W2); 24228c2ecf20Sopenharmony_ci break; 24238c2ecf20Sopenharmony_ci default: 24248c2ecf20Sopenharmony_ci b43_nphy_rssi_select(dev, 1, N_RSSI_W2); 24258c2ecf20Sopenharmony_ci break; 24268c2ecf20Sopenharmony_ci } 24278c2ecf20Sopenharmony_ci 24288c2ecf20Sopenharmony_ci switch (state[3]) { 24298c2ecf20Sopenharmony_ci case 1: 24308c2ecf20Sopenharmony_ci b43_nphy_rssi_select(dev, 2, N_RSSI_NB); 24318c2ecf20Sopenharmony_ci break; 24328c2ecf20Sopenharmony_ci case 4: 24338c2ecf20Sopenharmony_ci b43_nphy_rssi_select(dev, 2, N_RSSI_W1); 24348c2ecf20Sopenharmony_ci break; 24358c2ecf20Sopenharmony_ci default: 24368c2ecf20Sopenharmony_ci b43_nphy_rssi_select(dev, 2, N_RSSI_W2); 24378c2ecf20Sopenharmony_ci break; 24388c2ecf20Sopenharmony_ci } 24398c2ecf20Sopenharmony_ci 24408c2ecf20Sopenharmony_ci b43_nphy_rssi_select(dev, 0, type); 24418c2ecf20Sopenharmony_ci 24428c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs_save_phy[0]); 24438c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C1_PD_RXTX, regs_save_radio[0]); 24448c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs_save_phy[1]); 24458c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C2_PD_RXTX, regs_save_radio[1]); 24468c2ecf20Sopenharmony_ci 24478c2ecf20Sopenharmony_ci b43_nphy_classifier(dev, 7, class); 24488c2ecf20Sopenharmony_ci b43_nphy_write_clip_detection(dev, clip_state); 24498c2ecf20Sopenharmony_ci /* Specs don't say about reset here, but it makes wl and b43 dumps 24508c2ecf20Sopenharmony_ci identical, it really seems wl performs this */ 24518c2ecf20Sopenharmony_ci b43_nphy_reset_cca(dev); 24528c2ecf20Sopenharmony_ci} 24538c2ecf20Sopenharmony_ci 24548c2ecf20Sopenharmony_ci/* 24558c2ecf20Sopenharmony_ci * RSSI Calibration 24568c2ecf20Sopenharmony_ci * https://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal 24578c2ecf20Sopenharmony_ci */ 24588c2ecf20Sopenharmony_cistatic void b43_nphy_rssi_cal(struct b43_wldev *dev) 24598c2ecf20Sopenharmony_ci{ 24608c2ecf20Sopenharmony_ci if (dev->phy.rev >= 19) { 24618c2ecf20Sopenharmony_ci /* TODO */ 24628c2ecf20Sopenharmony_ci } else if (dev->phy.rev >= 3) { 24638c2ecf20Sopenharmony_ci b43_nphy_rev3_rssi_cal(dev); 24648c2ecf20Sopenharmony_ci } else { 24658c2ecf20Sopenharmony_ci b43_nphy_rev2_rssi_cal(dev, N_RSSI_NB); 24668c2ecf20Sopenharmony_ci b43_nphy_rev2_rssi_cal(dev, N_RSSI_W1); 24678c2ecf20Sopenharmony_ci b43_nphy_rev2_rssi_cal(dev, N_RSSI_W2); 24688c2ecf20Sopenharmony_ci } 24698c2ecf20Sopenharmony_ci} 24708c2ecf20Sopenharmony_ci 24718c2ecf20Sopenharmony_ci/************************************************** 24728c2ecf20Sopenharmony_ci * Workarounds 24738c2ecf20Sopenharmony_ci **************************************************/ 24748c2ecf20Sopenharmony_ci 24758c2ecf20Sopenharmony_cistatic void b43_nphy_gain_ctl_workarounds_rev19(struct b43_wldev *dev) 24768c2ecf20Sopenharmony_ci{ 24778c2ecf20Sopenharmony_ci /* TODO */ 24788c2ecf20Sopenharmony_ci} 24798c2ecf20Sopenharmony_ci 24808c2ecf20Sopenharmony_cistatic void b43_nphy_gain_ctl_workarounds_rev7(struct b43_wldev *dev) 24818c2ecf20Sopenharmony_ci{ 24828c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 24838c2ecf20Sopenharmony_ci 24848c2ecf20Sopenharmony_ci switch (phy->rev) { 24858c2ecf20Sopenharmony_ci /* TODO */ 24868c2ecf20Sopenharmony_ci } 24878c2ecf20Sopenharmony_ci} 24888c2ecf20Sopenharmony_ci 24898c2ecf20Sopenharmony_cistatic void b43_nphy_gain_ctl_workarounds_rev3(struct b43_wldev *dev) 24908c2ecf20Sopenharmony_ci{ 24918c2ecf20Sopenharmony_ci struct ssb_sprom *sprom = dev->dev->bus_sprom; 24928c2ecf20Sopenharmony_ci 24938c2ecf20Sopenharmony_ci bool ghz5; 24948c2ecf20Sopenharmony_ci bool ext_lna; 24958c2ecf20Sopenharmony_ci u16 rssi_gain; 24968c2ecf20Sopenharmony_ci struct nphy_gain_ctl_workaround_entry *e; 24978c2ecf20Sopenharmony_ci u8 lpf_gain[6] = { 0x00, 0x06, 0x0C, 0x12, 0x12, 0x12 }; 24988c2ecf20Sopenharmony_ci u8 lpf_bits[6] = { 0, 1, 2, 3, 3, 3 }; 24998c2ecf20Sopenharmony_ci 25008c2ecf20Sopenharmony_ci /* Prepare values */ 25018c2ecf20Sopenharmony_ci ghz5 = b43_phy_read(dev, B43_NPHY_BANDCTL) 25028c2ecf20Sopenharmony_ci & B43_NPHY_BANDCTL_5GHZ; 25038c2ecf20Sopenharmony_ci ext_lna = ghz5 ? sprom->boardflags_hi & B43_BFH_EXTLNA_5GHZ : 25048c2ecf20Sopenharmony_ci sprom->boardflags_lo & B43_BFL_EXTLNA; 25058c2ecf20Sopenharmony_ci e = b43_nphy_get_gain_ctl_workaround_ent(dev, ghz5, ext_lna); 25068c2ecf20Sopenharmony_ci if (ghz5 && dev->phy.rev >= 5) 25078c2ecf20Sopenharmony_ci rssi_gain = 0x90; 25088c2ecf20Sopenharmony_ci else 25098c2ecf20Sopenharmony_ci rssi_gain = 0x50; 25108c2ecf20Sopenharmony_ci 25118c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_RXCTL, 0x0040); 25128c2ecf20Sopenharmony_ci 25138c2ecf20Sopenharmony_ci /* Set Clip 2 detect */ 25148c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_C1_CGAINI, B43_NPHY_C1_CGAINI_CL2DETECT); 25158c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_C2_CGAINI, B43_NPHY_C2_CGAINI_CL2DETECT); 25168c2ecf20Sopenharmony_ci 25178c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAG1_IDAC, 25188c2ecf20Sopenharmony_ci 0x17); 25198c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX1 | B2056_RX_BIASPOLE_LNAG1_IDAC, 25208c2ecf20Sopenharmony_ci 0x17); 25218c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG2_IDAC, 0xF0); 25228c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG2_IDAC, 0xF0); 25238c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX0 | B2056_RX_RSSI_POLE, 0x00); 25248c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX1 | B2056_RX_RSSI_POLE, 0x00); 25258c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX0 | B2056_RX_RSSI_GAIN, 25268c2ecf20Sopenharmony_ci rssi_gain); 25278c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX1 | B2056_RX_RSSI_GAIN, 25288c2ecf20Sopenharmony_ci rssi_gain); 25298c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAA1_IDAC, 25308c2ecf20Sopenharmony_ci 0x17); 25318c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX1 | B2056_RX_BIASPOLE_LNAA1_IDAC, 25328c2ecf20Sopenharmony_ci 0x17); 25338c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA2_IDAC, 0xFF); 25348c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA2_IDAC, 0xFF); 25358c2ecf20Sopenharmony_ci 25368c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB8(0, 8), 4, e->lna1_gain); 25378c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB8(1, 8), 4, e->lna1_gain); 25388c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB8(0, 16), 4, e->lna2_gain); 25398c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB8(1, 16), 4, e->lna2_gain); 25408c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB8(0, 32), 10, e->gain_db); 25418c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB8(1, 32), 10, e->gain_db); 25428c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB8(2, 32), 10, e->gain_bits); 25438c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB8(3, 32), 10, e->gain_bits); 25448c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB8(0, 0x40), 6, lpf_gain); 25458c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB8(1, 0x40), 6, lpf_gain); 25468c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB8(2, 0x40), 6, lpf_bits); 25478c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB8(3, 0x40), 6, lpf_bits); 25488c2ecf20Sopenharmony_ci 25498c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_REV3_C1_INITGAIN_A, e->init_gain); 25508c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_REV3_C2_INITGAIN_A, e->init_gain); 25518c2ecf20Sopenharmony_ci 25528c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x106), 2, 25538c2ecf20Sopenharmony_ci e->rfseq_init); 25548c2ecf20Sopenharmony_ci 25558c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_HIGAIN_A, e->cliphi_gain); 25568c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_HIGAIN_A, e->cliphi_gain); 25578c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_MEDGAIN_A, e->clipmd_gain); 25588c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_MEDGAIN_A, e->clipmd_gain); 25598c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_LOGAIN_A, e->cliplo_gain); 25608c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_LOGAIN_A, e->cliplo_gain); 25618c2ecf20Sopenharmony_ci 25628c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_CRSMINPOWER0, 0xFF00, e->crsmin); 25638c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_CRSMINPOWERL0, 0xFF00, e->crsminl); 25648c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_CRSMINPOWERU0, 0xFF00, e->crsminu); 25658c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, e->nbclip); 25668c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, e->nbclip); 25678c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES, 25688c2ecf20Sopenharmony_ci ~B43_NPHY_C1_CLIPWBTHRES_CLIP2, e->wlclip); 25698c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES, 25708c2ecf20Sopenharmony_ci ~B43_NPHY_C2_CLIPWBTHRES_CLIP2, e->wlclip); 25718c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C); 25728c2ecf20Sopenharmony_ci} 25738c2ecf20Sopenharmony_ci 25748c2ecf20Sopenharmony_cistatic void b43_nphy_gain_ctl_workarounds_rev1_2(struct b43_wldev *dev) 25758c2ecf20Sopenharmony_ci{ 25768c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 25778c2ecf20Sopenharmony_ci 25788c2ecf20Sopenharmony_ci u8 i, j; 25798c2ecf20Sopenharmony_ci u8 code; 25808c2ecf20Sopenharmony_ci u16 tmp; 25818c2ecf20Sopenharmony_ci u8 rfseq_events[3] = { 6, 8, 7 }; 25828c2ecf20Sopenharmony_ci u8 rfseq_delays[3] = { 10, 30, 1 }; 25838c2ecf20Sopenharmony_ci 25848c2ecf20Sopenharmony_ci /* Set Clip 2 detect */ 25858c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_C1_CGAINI, B43_NPHY_C1_CGAINI_CL2DETECT); 25868c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_C2_CGAINI, B43_NPHY_C2_CGAINI_CL2DETECT); 25878c2ecf20Sopenharmony_ci 25888c2ecf20Sopenharmony_ci /* Set narrowband clip threshold */ 25898c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 0x84); 25908c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 0x84); 25918c2ecf20Sopenharmony_ci 25928c2ecf20Sopenharmony_ci if (!b43_is_40mhz(dev)) { 25938c2ecf20Sopenharmony_ci /* Set dwell lengths */ 25948c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 0x002B); 25958c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 0x002B); 25968c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 0x0009); 25978c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 0x0009); 25988c2ecf20Sopenharmony_ci } 25998c2ecf20Sopenharmony_ci 26008c2ecf20Sopenharmony_ci /* Set wideband clip 2 threshold */ 26018c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES, 26028c2ecf20Sopenharmony_ci ~B43_NPHY_C1_CLIPWBTHRES_CLIP2, 21); 26038c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES, 26048c2ecf20Sopenharmony_ci ~B43_NPHY_C2_CLIPWBTHRES_CLIP2, 21); 26058c2ecf20Sopenharmony_ci 26068c2ecf20Sopenharmony_ci if (!b43_is_40mhz(dev)) { 26078c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_C1_CGAINI, 26088c2ecf20Sopenharmony_ci ~B43_NPHY_C1_CGAINI_GAINBKOFF, 0x1); 26098c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_C2_CGAINI, 26108c2ecf20Sopenharmony_ci ~B43_NPHY_C2_CGAINI_GAINBKOFF, 0x1); 26118c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_C1_CCK_CGAINI, 26128c2ecf20Sopenharmony_ci ~B43_NPHY_C1_CCK_CGAINI_GAINBKOFF, 0x1); 26138c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_C2_CCK_CGAINI, 26148c2ecf20Sopenharmony_ci ~B43_NPHY_C2_CCK_CGAINI_GAINBKOFF, 0x1); 26158c2ecf20Sopenharmony_ci } 26168c2ecf20Sopenharmony_ci 26178c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C); 26188c2ecf20Sopenharmony_ci 26198c2ecf20Sopenharmony_ci if (nphy->gain_boost) { 26208c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ && 26218c2ecf20Sopenharmony_ci b43_is_40mhz(dev)) 26228c2ecf20Sopenharmony_ci code = 4; 26238c2ecf20Sopenharmony_ci else 26248c2ecf20Sopenharmony_ci code = 5; 26258c2ecf20Sopenharmony_ci } else { 26268c2ecf20Sopenharmony_ci code = b43_is_40mhz(dev) ? 6 : 7; 26278c2ecf20Sopenharmony_ci } 26288c2ecf20Sopenharmony_ci 26298c2ecf20Sopenharmony_ci /* Set HPVGA2 index */ 26308c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN, ~B43_NPHY_C1_INITGAIN_HPVGA2, 26318c2ecf20Sopenharmony_ci code << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT); 26328c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN, ~B43_NPHY_C2_INITGAIN_HPVGA2, 26338c2ecf20Sopenharmony_ci code << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT); 26348c2ecf20Sopenharmony_ci 26358c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06); 26368c2ecf20Sopenharmony_ci /* specs say about 2 loops, but wl does 4 */ 26378c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 26388c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_DATALO, (code << 8 | 0x7C)); 26398c2ecf20Sopenharmony_ci 26408c2ecf20Sopenharmony_ci b43_nphy_adjust_lna_gain_table(dev); 26418c2ecf20Sopenharmony_ci 26428c2ecf20Sopenharmony_ci if (nphy->elna_gain_config) { 26438c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0808); 26448c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0); 26458c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); 26468c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); 26478c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); 26488c2ecf20Sopenharmony_ci 26498c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0C08); 26508c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0); 26518c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); 26528c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); 26538c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); 26548c2ecf20Sopenharmony_ci 26558c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06); 26568c2ecf20Sopenharmony_ci /* specs say about 2 loops, but wl does 4 */ 26578c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 26588c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 26598c2ecf20Sopenharmony_ci (code << 8 | 0x74)); 26608c2ecf20Sopenharmony_ci } 26618c2ecf20Sopenharmony_ci 26628c2ecf20Sopenharmony_ci if (dev->phy.rev == 2) { 26638c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) { 26648c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 26658c2ecf20Sopenharmony_ci (0x0400 * i) + 0x0020); 26668c2ecf20Sopenharmony_ci for (j = 0; j < 21; j++) { 26678c2ecf20Sopenharmony_ci tmp = j * (i < 2 ? 3 : 1); 26688c2ecf20Sopenharmony_ci b43_phy_write(dev, 26698c2ecf20Sopenharmony_ci B43_NPHY_TABLE_DATALO, tmp); 26708c2ecf20Sopenharmony_ci } 26718c2ecf20Sopenharmony_ci } 26728c2ecf20Sopenharmony_ci } 26738c2ecf20Sopenharmony_ci 26748c2ecf20Sopenharmony_ci b43_nphy_set_rf_sequence(dev, 5, rfseq_events, rfseq_delays, 3); 26758c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_OVER_DGAIN1, 26768c2ecf20Sopenharmony_ci ~B43_NPHY_OVER_DGAIN_CCKDGECV & 0xFFFF, 26778c2ecf20Sopenharmony_ci 0x5A << B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT); 26788c2ecf20Sopenharmony_ci 26798c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) 26808c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_PHY_N(0xC5D), 0xFF80, 4); 26818c2ecf20Sopenharmony_ci} 26828c2ecf20Sopenharmony_ci 26838c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */ 26848c2ecf20Sopenharmony_cistatic void b43_nphy_gain_ctl_workarounds(struct b43_wldev *dev) 26858c2ecf20Sopenharmony_ci{ 26868c2ecf20Sopenharmony_ci if (dev->phy.rev >= 19) 26878c2ecf20Sopenharmony_ci b43_nphy_gain_ctl_workarounds_rev19(dev); 26888c2ecf20Sopenharmony_ci else if (dev->phy.rev >= 7) 26898c2ecf20Sopenharmony_ci b43_nphy_gain_ctl_workarounds_rev7(dev); 26908c2ecf20Sopenharmony_ci else if (dev->phy.rev >= 3) 26918c2ecf20Sopenharmony_ci b43_nphy_gain_ctl_workarounds_rev3(dev); 26928c2ecf20Sopenharmony_ci else 26938c2ecf20Sopenharmony_ci b43_nphy_gain_ctl_workarounds_rev1_2(dev); 26948c2ecf20Sopenharmony_ci} 26958c2ecf20Sopenharmony_ci 26968c2ecf20Sopenharmony_cistatic void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) 26978c2ecf20Sopenharmony_ci{ 26988c2ecf20Sopenharmony_ci struct ssb_sprom *sprom = dev->dev->bus_sprom; 26998c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 27008c2ecf20Sopenharmony_ci 27018c2ecf20Sopenharmony_ci /* TX to RX */ 27028c2ecf20Sopenharmony_ci u8 tx2rx_events[7] = { 4, 3, 5, 2, 1, 8, 31, }; 27038c2ecf20Sopenharmony_ci u8 tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1, }; 27048c2ecf20Sopenharmony_ci /* RX to TX */ 27058c2ecf20Sopenharmony_ci u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3, 27068c2ecf20Sopenharmony_ci 0x1F }; 27078c2ecf20Sopenharmony_ci u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; 27088c2ecf20Sopenharmony_ci 27098c2ecf20Sopenharmony_ci static const u16 ntab7_15e_16e[] = { 0, 0x10f, 0x10f }; 27108c2ecf20Sopenharmony_ci u8 ntab7_138_146[] = { 0x11, 0x11 }; 27118c2ecf20Sopenharmony_ci u8 ntab7_133[] = { 0x77, 0x11, 0x11 }; 27128c2ecf20Sopenharmony_ci 27138c2ecf20Sopenharmony_ci u16 lpf_ofdm_20mhz[2], lpf_ofdm_40mhz[2], lpf_11b[2]; 27148c2ecf20Sopenharmony_ci u16 bcap_val; 27158c2ecf20Sopenharmony_ci s16 bcap_val_11b[2], bcap_val_11n_20[2], bcap_val_11n_40[2]; 27168c2ecf20Sopenharmony_ci u16 scap_val; 27178c2ecf20Sopenharmony_ci s16 scap_val_11b[2], scap_val_11n_20[2], scap_val_11n_40[2]; 27188c2ecf20Sopenharmony_ci bool rccal_ovrd = false; 27198c2ecf20Sopenharmony_ci 27208c2ecf20Sopenharmony_ci u16 bias, conv, filt; 27218c2ecf20Sopenharmony_ci 27228c2ecf20Sopenharmony_ci u32 noise_tbl[2]; 27238c2ecf20Sopenharmony_ci 27248c2ecf20Sopenharmony_ci u32 tmp32; 27258c2ecf20Sopenharmony_ci u8 core; 27268c2ecf20Sopenharmony_ci 27278c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125); 27288c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01b3); 27298c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105); 27308c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016e); 27318c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00cd); 27328c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020); 27338c2ecf20Sopenharmony_ci 27348c2ecf20Sopenharmony_ci if (phy->rev == 7) { 27358c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_FINERX2_CGC, 0x10); 27368c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0xFF80, 0x0020); 27378c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0x80FF, 0x2700); 27388c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_FREQGAIN1, 0xFF80, 0x002E); 27398c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_FREQGAIN1, 0x80FF, 0x3300); 27408c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_FREQGAIN2, 0xFF80, 0x0037); 27418c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_FREQGAIN2, 0x80FF, 0x3A00); 27428c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_FREQGAIN3, 0xFF80, 0x003C); 27438c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_FREQGAIN3, 0x80FF, 0x3E00); 27448c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_FREQGAIN4, 0xFF80, 0x003E); 27458c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_FREQGAIN4, 0x80FF, 0x3F00); 27468c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_FREQGAIN5, 0xFF80, 0x0040); 27478c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_FREQGAIN5, 0x80FF, 0x4000); 27488c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_FREQGAIN6, 0xFF80, 0x0040); 27498c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_FREQGAIN6, 0x80FF, 0x4000); 27508c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0xFF80, 0x0040); 27518c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0x80FF, 0x4000); 27528c2ecf20Sopenharmony_ci } 27538c2ecf20Sopenharmony_ci 27548c2ecf20Sopenharmony_ci if (phy->rev >= 16) { 27558c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x7ff); 27568c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x7ff); 27578c2ecf20Sopenharmony_ci } else if (phy->rev <= 8) { 27588c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1B0); 27598c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1B0); 27608c2ecf20Sopenharmony_ci } 27618c2ecf20Sopenharmony_ci 27628c2ecf20Sopenharmony_ci if (phy->rev >= 16) 27638c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0xa0); 27648c2ecf20Sopenharmony_ci else if (phy->rev >= 8) 27658c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0x72); 27668c2ecf20Sopenharmony_ci 27678c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 0x00), 2); 27688c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 0x10), 2); 27698c2ecf20Sopenharmony_ci tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0)); 27708c2ecf20Sopenharmony_ci tmp32 &= 0xffffff; 27718c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32); 27728c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x15d), 3, ntab7_15e_16e); 27738c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16d), 3, ntab7_15e_16e); 27748c2ecf20Sopenharmony_ci 27758c2ecf20Sopenharmony_ci b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays, 27768c2ecf20Sopenharmony_ci ARRAY_SIZE(tx2rx_events)); 27778c2ecf20Sopenharmony_ci if (b43_nphy_ipa(dev)) 27788c2ecf20Sopenharmony_ci b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa, 27798c2ecf20Sopenharmony_ci rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa)); 27808c2ecf20Sopenharmony_ci 27818c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_0, 0x3FFF, 0x4000); 27828c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_1, 0x3FFF, 0x4000); 27838c2ecf20Sopenharmony_ci 27848c2ecf20Sopenharmony_ci for (core = 0; core < 2; core++) { 27858c2ecf20Sopenharmony_ci lpf_ofdm_20mhz[core] = b43_nphy_read_lpf_ctl(dev, 0x154 + core * 0x10); 27868c2ecf20Sopenharmony_ci lpf_ofdm_40mhz[core] = b43_nphy_read_lpf_ctl(dev, 0x159 + core * 0x10); 27878c2ecf20Sopenharmony_ci lpf_11b[core] = b43_nphy_read_lpf_ctl(dev, 0x152 + core * 0x10); 27888c2ecf20Sopenharmony_ci } 27898c2ecf20Sopenharmony_ci 27908c2ecf20Sopenharmony_ci bcap_val = b43_radio_read(dev, R2057_RCCAL_BCAP_VAL); 27918c2ecf20Sopenharmony_ci scap_val = b43_radio_read(dev, R2057_RCCAL_SCAP_VAL); 27928c2ecf20Sopenharmony_ci 27938c2ecf20Sopenharmony_ci if (b43_nphy_ipa(dev)) { 27948c2ecf20Sopenharmony_ci bool ghz2 = b43_current_band(dev->wl) == NL80211_BAND_2GHZ; 27958c2ecf20Sopenharmony_ci 27968c2ecf20Sopenharmony_ci switch (phy->radio_rev) { 27978c2ecf20Sopenharmony_ci case 5: 27988c2ecf20Sopenharmony_ci /* Check radio version (to be 0) by PHY rev for now */ 27998c2ecf20Sopenharmony_ci if (phy->rev == 8 && b43_is_40mhz(dev)) { 28008c2ecf20Sopenharmony_ci for (core = 0; core < 2; core++) { 28018c2ecf20Sopenharmony_ci scap_val_11b[core] = scap_val; 28028c2ecf20Sopenharmony_ci bcap_val_11b[core] = bcap_val; 28038c2ecf20Sopenharmony_ci scap_val_11n_20[core] = scap_val; 28048c2ecf20Sopenharmony_ci bcap_val_11n_20[core] = bcap_val; 28058c2ecf20Sopenharmony_ci scap_val_11n_40[core] = 0xc; 28068c2ecf20Sopenharmony_ci bcap_val_11n_40[core] = 0xc; 28078c2ecf20Sopenharmony_ci } 28088c2ecf20Sopenharmony_ci 28098c2ecf20Sopenharmony_ci rccal_ovrd = true; 28108c2ecf20Sopenharmony_ci } 28118c2ecf20Sopenharmony_ci if (phy->rev == 9) { 28128c2ecf20Sopenharmony_ci /* TODO: Radio version 1 (e.g. BCM5357B0) */ 28138c2ecf20Sopenharmony_ci } 28148c2ecf20Sopenharmony_ci break; 28158c2ecf20Sopenharmony_ci case 7: 28168c2ecf20Sopenharmony_ci case 8: 28178c2ecf20Sopenharmony_ci for (core = 0; core < 2; core++) { 28188c2ecf20Sopenharmony_ci scap_val_11b[core] = scap_val; 28198c2ecf20Sopenharmony_ci bcap_val_11b[core] = bcap_val; 28208c2ecf20Sopenharmony_ci lpf_ofdm_20mhz[core] = 4; 28218c2ecf20Sopenharmony_ci lpf_11b[core] = 1; 28228c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { 28238c2ecf20Sopenharmony_ci scap_val_11n_20[core] = 0xc; 28248c2ecf20Sopenharmony_ci bcap_val_11n_20[core] = 0xc; 28258c2ecf20Sopenharmony_ci scap_val_11n_40[core] = 0xa; 28268c2ecf20Sopenharmony_ci bcap_val_11n_40[core] = 0xa; 28278c2ecf20Sopenharmony_ci } else { 28288c2ecf20Sopenharmony_ci scap_val_11n_20[core] = 0x14; 28298c2ecf20Sopenharmony_ci bcap_val_11n_20[core] = 0x14; 28308c2ecf20Sopenharmony_ci scap_val_11n_40[core] = 0xf; 28318c2ecf20Sopenharmony_ci bcap_val_11n_40[core] = 0xf; 28328c2ecf20Sopenharmony_ci } 28338c2ecf20Sopenharmony_ci } 28348c2ecf20Sopenharmony_ci 28358c2ecf20Sopenharmony_ci rccal_ovrd = true; 28368c2ecf20Sopenharmony_ci break; 28378c2ecf20Sopenharmony_ci case 9: 28388c2ecf20Sopenharmony_ci for (core = 0; core < 2; core++) { 28398c2ecf20Sopenharmony_ci bcap_val_11b[core] = bcap_val; 28408c2ecf20Sopenharmony_ci scap_val_11b[core] = scap_val; 28418c2ecf20Sopenharmony_ci lpf_11b[core] = 1; 28428c2ecf20Sopenharmony_ci 28438c2ecf20Sopenharmony_ci if (ghz2) { 28448c2ecf20Sopenharmony_ci bcap_val_11n_20[core] = bcap_val + 13; 28458c2ecf20Sopenharmony_ci scap_val_11n_20[core] = scap_val + 15; 28468c2ecf20Sopenharmony_ci } else { 28478c2ecf20Sopenharmony_ci bcap_val_11n_20[core] = bcap_val + 14; 28488c2ecf20Sopenharmony_ci scap_val_11n_20[core] = scap_val + 15; 28498c2ecf20Sopenharmony_ci } 28508c2ecf20Sopenharmony_ci lpf_ofdm_20mhz[core] = 4; 28518c2ecf20Sopenharmony_ci 28528c2ecf20Sopenharmony_ci if (ghz2) { 28538c2ecf20Sopenharmony_ci bcap_val_11n_40[core] = bcap_val - 7; 28548c2ecf20Sopenharmony_ci scap_val_11n_40[core] = scap_val - 5; 28558c2ecf20Sopenharmony_ci } else { 28568c2ecf20Sopenharmony_ci bcap_val_11n_40[core] = bcap_val + 2; 28578c2ecf20Sopenharmony_ci scap_val_11n_40[core] = scap_val + 4; 28588c2ecf20Sopenharmony_ci } 28598c2ecf20Sopenharmony_ci lpf_ofdm_40mhz[core] = 4; 28608c2ecf20Sopenharmony_ci } 28618c2ecf20Sopenharmony_ci 28628c2ecf20Sopenharmony_ci rccal_ovrd = true; 28638c2ecf20Sopenharmony_ci break; 28648c2ecf20Sopenharmony_ci case 14: 28658c2ecf20Sopenharmony_ci for (core = 0; core < 2; core++) { 28668c2ecf20Sopenharmony_ci bcap_val_11b[core] = bcap_val; 28678c2ecf20Sopenharmony_ci scap_val_11b[core] = scap_val; 28688c2ecf20Sopenharmony_ci lpf_11b[core] = 1; 28698c2ecf20Sopenharmony_ci } 28708c2ecf20Sopenharmony_ci 28718c2ecf20Sopenharmony_ci bcap_val_11n_20[0] = bcap_val + 20; 28728c2ecf20Sopenharmony_ci scap_val_11n_20[0] = scap_val + 20; 28738c2ecf20Sopenharmony_ci lpf_ofdm_20mhz[0] = 3; 28748c2ecf20Sopenharmony_ci 28758c2ecf20Sopenharmony_ci bcap_val_11n_20[1] = bcap_val + 16; 28768c2ecf20Sopenharmony_ci scap_val_11n_20[1] = scap_val + 16; 28778c2ecf20Sopenharmony_ci lpf_ofdm_20mhz[1] = 3; 28788c2ecf20Sopenharmony_ci 28798c2ecf20Sopenharmony_ci bcap_val_11n_40[0] = bcap_val + 20; 28808c2ecf20Sopenharmony_ci scap_val_11n_40[0] = scap_val + 20; 28818c2ecf20Sopenharmony_ci lpf_ofdm_40mhz[0] = 4; 28828c2ecf20Sopenharmony_ci 28838c2ecf20Sopenharmony_ci bcap_val_11n_40[1] = bcap_val + 10; 28848c2ecf20Sopenharmony_ci scap_val_11n_40[1] = scap_val + 10; 28858c2ecf20Sopenharmony_ci lpf_ofdm_40mhz[1] = 4; 28868c2ecf20Sopenharmony_ci 28878c2ecf20Sopenharmony_ci rccal_ovrd = true; 28888c2ecf20Sopenharmony_ci break; 28898c2ecf20Sopenharmony_ci } 28908c2ecf20Sopenharmony_ci } else { 28918c2ecf20Sopenharmony_ci if (phy->radio_rev == 5) { 28928c2ecf20Sopenharmony_ci for (core = 0; core < 2; core++) { 28938c2ecf20Sopenharmony_ci lpf_ofdm_20mhz[core] = 1; 28948c2ecf20Sopenharmony_ci lpf_ofdm_40mhz[core] = 3; 28958c2ecf20Sopenharmony_ci scap_val_11b[core] = scap_val; 28968c2ecf20Sopenharmony_ci bcap_val_11b[core] = bcap_val; 28978c2ecf20Sopenharmony_ci scap_val_11n_20[core] = 0x11; 28988c2ecf20Sopenharmony_ci scap_val_11n_40[core] = 0x11; 28998c2ecf20Sopenharmony_ci bcap_val_11n_20[core] = 0x13; 29008c2ecf20Sopenharmony_ci bcap_val_11n_40[core] = 0x13; 29018c2ecf20Sopenharmony_ci } 29028c2ecf20Sopenharmony_ci 29038c2ecf20Sopenharmony_ci rccal_ovrd = true; 29048c2ecf20Sopenharmony_ci } 29058c2ecf20Sopenharmony_ci } 29068c2ecf20Sopenharmony_ci if (rccal_ovrd) { 29078c2ecf20Sopenharmony_ci u16 rx2tx_lut_20_11b[2], rx2tx_lut_20_11n[2], rx2tx_lut_40_11n[2]; 29088c2ecf20Sopenharmony_ci u8 rx2tx_lut_extra = 1; 29098c2ecf20Sopenharmony_ci 29108c2ecf20Sopenharmony_ci for (core = 0; core < 2; core++) { 29118c2ecf20Sopenharmony_ci bcap_val_11b[core] = clamp_val(bcap_val_11b[core], 0, 0x1f); 29128c2ecf20Sopenharmony_ci scap_val_11b[core] = clamp_val(scap_val_11b[core], 0, 0x1f); 29138c2ecf20Sopenharmony_ci bcap_val_11n_20[core] = clamp_val(bcap_val_11n_20[core], 0, 0x1f); 29148c2ecf20Sopenharmony_ci scap_val_11n_20[core] = clamp_val(scap_val_11n_20[core], 0, 0x1f); 29158c2ecf20Sopenharmony_ci bcap_val_11n_40[core] = clamp_val(bcap_val_11n_40[core], 0, 0x1f); 29168c2ecf20Sopenharmony_ci scap_val_11n_40[core] = clamp_val(scap_val_11n_40[core], 0, 0x1f); 29178c2ecf20Sopenharmony_ci 29188c2ecf20Sopenharmony_ci rx2tx_lut_20_11b[core] = (rx2tx_lut_extra << 13) | 29198c2ecf20Sopenharmony_ci (bcap_val_11b[core] << 8) | 29208c2ecf20Sopenharmony_ci (scap_val_11b[core] << 3) | 29218c2ecf20Sopenharmony_ci lpf_11b[core]; 29228c2ecf20Sopenharmony_ci rx2tx_lut_20_11n[core] = (rx2tx_lut_extra << 13) | 29238c2ecf20Sopenharmony_ci (bcap_val_11n_20[core] << 8) | 29248c2ecf20Sopenharmony_ci (scap_val_11n_20[core] << 3) | 29258c2ecf20Sopenharmony_ci lpf_ofdm_20mhz[core]; 29268c2ecf20Sopenharmony_ci rx2tx_lut_40_11n[core] = (rx2tx_lut_extra << 13) | 29278c2ecf20Sopenharmony_ci (bcap_val_11n_40[core] << 8) | 29288c2ecf20Sopenharmony_ci (scap_val_11n_40[core] << 3) | 29298c2ecf20Sopenharmony_ci lpf_ofdm_40mhz[core]; 29308c2ecf20Sopenharmony_ci } 29318c2ecf20Sopenharmony_ci 29328c2ecf20Sopenharmony_ci for (core = 0; core < 2; core++) { 29338c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(7, 0x152 + core * 16), 29348c2ecf20Sopenharmony_ci rx2tx_lut_20_11b[core]); 29358c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(7, 0x153 + core * 16), 29368c2ecf20Sopenharmony_ci rx2tx_lut_20_11n[core]); 29378c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(7, 0x154 + core * 16), 29388c2ecf20Sopenharmony_ci rx2tx_lut_20_11n[core]); 29398c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(7, 0x155 + core * 16), 29408c2ecf20Sopenharmony_ci rx2tx_lut_40_11n[core]); 29418c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(7, 0x156 + core * 16), 29428c2ecf20Sopenharmony_ci rx2tx_lut_40_11n[core]); 29438c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(7, 0x157 + core * 16), 29448c2ecf20Sopenharmony_ci rx2tx_lut_40_11n[core]); 29458c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(7, 0x158 + core * 16), 29468c2ecf20Sopenharmony_ci rx2tx_lut_40_11n[core]); 29478c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(7, 0x159 + core * 16), 29488c2ecf20Sopenharmony_ci rx2tx_lut_40_11n[core]); 29498c2ecf20Sopenharmony_ci } 29508c2ecf20Sopenharmony_ci } 29518c2ecf20Sopenharmony_ci 29528c2ecf20Sopenharmony_ci b43_phy_write(dev, 0x32F, 0x3); 29538c2ecf20Sopenharmony_ci 29548c2ecf20Sopenharmony_ci if (phy->radio_rev == 4 || phy->radio_rev == 6) 29558c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 4, 1, 3, false, 0); 29568c2ecf20Sopenharmony_ci 29578c2ecf20Sopenharmony_ci if (phy->radio_rev == 3 || phy->radio_rev == 4 || phy->radio_rev == 6) { 29588c2ecf20Sopenharmony_ci if (sprom->revision && 29598c2ecf20Sopenharmony_ci sprom->boardflags2_hi & B43_BFH2_IPALVLSHIFT_3P3) { 29608c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x5, 0x05); 29618c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x6, 0x30); 29628c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x7, 0x00); 29638c2ecf20Sopenharmony_ci b43_radio_set(dev, 0x4f, 0x1); 29648c2ecf20Sopenharmony_ci b43_radio_set(dev, 0xd4, 0x1); 29658c2ecf20Sopenharmony_ci bias = 0x1f; 29668c2ecf20Sopenharmony_ci conv = 0x6f; 29678c2ecf20Sopenharmony_ci filt = 0xaa; 29688c2ecf20Sopenharmony_ci } else { 29698c2ecf20Sopenharmony_ci bias = 0x2b; 29708c2ecf20Sopenharmony_ci conv = 0x7f; 29718c2ecf20Sopenharmony_ci filt = 0xee; 29728c2ecf20Sopenharmony_ci } 29738c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { 29748c2ecf20Sopenharmony_ci for (core = 0; core < 2; core++) { 29758c2ecf20Sopenharmony_ci if (core == 0) { 29768c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x5F, bias); 29778c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x64, conv); 29788c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x66, filt); 29798c2ecf20Sopenharmony_ci } else { 29808c2ecf20Sopenharmony_ci b43_radio_write(dev, 0xE8, bias); 29818c2ecf20Sopenharmony_ci b43_radio_write(dev, 0xE9, conv); 29828c2ecf20Sopenharmony_ci b43_radio_write(dev, 0xEB, filt); 29838c2ecf20Sopenharmony_ci } 29848c2ecf20Sopenharmony_ci } 29858c2ecf20Sopenharmony_ci } 29868c2ecf20Sopenharmony_ci } 29878c2ecf20Sopenharmony_ci 29888c2ecf20Sopenharmony_ci if (b43_nphy_ipa(dev)) { 29898c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { 29908c2ecf20Sopenharmony_ci if (phy->radio_rev == 3 || phy->radio_rev == 4 || 29918c2ecf20Sopenharmony_ci phy->radio_rev == 6) { 29928c2ecf20Sopenharmony_ci for (core = 0; core < 2; core++) { 29938c2ecf20Sopenharmony_ci if (core == 0) 29948c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x51, 29958c2ecf20Sopenharmony_ci 0x7f); 29968c2ecf20Sopenharmony_ci else 29978c2ecf20Sopenharmony_ci b43_radio_write(dev, 0xd6, 29988c2ecf20Sopenharmony_ci 0x7f); 29998c2ecf20Sopenharmony_ci } 30008c2ecf20Sopenharmony_ci } 30018c2ecf20Sopenharmony_ci switch (phy->radio_rev) { 30028c2ecf20Sopenharmony_ci case 3: 30038c2ecf20Sopenharmony_ci for (core = 0; core < 2; core++) { 30048c2ecf20Sopenharmony_ci if (core == 0) { 30058c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x64, 30068c2ecf20Sopenharmony_ci 0x13); 30078c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x5F, 30088c2ecf20Sopenharmony_ci 0x1F); 30098c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x66, 30108c2ecf20Sopenharmony_ci 0xEE); 30118c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x59, 30128c2ecf20Sopenharmony_ci 0x8A); 30138c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x80, 30148c2ecf20Sopenharmony_ci 0x3E); 30158c2ecf20Sopenharmony_ci } else { 30168c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x69, 30178c2ecf20Sopenharmony_ci 0x13); 30188c2ecf20Sopenharmony_ci b43_radio_write(dev, 0xE8, 30198c2ecf20Sopenharmony_ci 0x1F); 30208c2ecf20Sopenharmony_ci b43_radio_write(dev, 0xEB, 30218c2ecf20Sopenharmony_ci 0xEE); 30228c2ecf20Sopenharmony_ci b43_radio_write(dev, 0xDE, 30238c2ecf20Sopenharmony_ci 0x8A); 30248c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x105, 30258c2ecf20Sopenharmony_ci 0x3E); 30268c2ecf20Sopenharmony_ci } 30278c2ecf20Sopenharmony_ci } 30288c2ecf20Sopenharmony_ci break; 30298c2ecf20Sopenharmony_ci case 7: 30308c2ecf20Sopenharmony_ci case 8: 30318c2ecf20Sopenharmony_ci if (!b43_is_40mhz(dev)) { 30328c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x5F, 0x14); 30338c2ecf20Sopenharmony_ci b43_radio_write(dev, 0xE8, 0x12); 30348c2ecf20Sopenharmony_ci } else { 30358c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x5F, 0x16); 30368c2ecf20Sopenharmony_ci b43_radio_write(dev, 0xE8, 0x16); 30378c2ecf20Sopenharmony_ci } 30388c2ecf20Sopenharmony_ci break; 30398c2ecf20Sopenharmony_ci case 14: 30408c2ecf20Sopenharmony_ci for (core = 0; core < 2; core++) { 30418c2ecf20Sopenharmony_ci int o = core ? 0x85 : 0; 30428c2ecf20Sopenharmony_ci 30438c2ecf20Sopenharmony_ci b43_radio_write(dev, o + R2057_IPA2G_CASCONV_CORE0, 0x13); 30448c2ecf20Sopenharmony_ci b43_radio_write(dev, o + R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, 0x21); 30458c2ecf20Sopenharmony_ci b43_radio_write(dev, o + R2057_IPA2G_BIAS_FILTER_CORE0, 0xff); 30468c2ecf20Sopenharmony_ci b43_radio_write(dev, o + R2057_PAD2G_IDACS_CORE0, 0x88); 30478c2ecf20Sopenharmony_ci b43_radio_write(dev, o + R2057_PAD2G_TUNE_PUS_CORE0, 0x23); 30488c2ecf20Sopenharmony_ci b43_radio_write(dev, o + R2057_IPA2G_IMAIN_CORE0, 0x16); 30498c2ecf20Sopenharmony_ci b43_radio_write(dev, o + R2057_PAD_BIAS_FILTER_BWS_CORE0, 0x3e); 30508c2ecf20Sopenharmony_ci b43_radio_write(dev, o + R2057_BACKUP1_CORE0, 0x10); 30518c2ecf20Sopenharmony_ci } 30528c2ecf20Sopenharmony_ci break; 30538c2ecf20Sopenharmony_ci } 30548c2ecf20Sopenharmony_ci } else { 30558c2ecf20Sopenharmony_ci u16 freq = phy->chandef->chan->center_freq; 30568c2ecf20Sopenharmony_ci if ((freq >= 5180 && freq <= 5230) || 30578c2ecf20Sopenharmony_ci (freq >= 5745 && freq <= 5805)) { 30588c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x7D, 0xFF); 30598c2ecf20Sopenharmony_ci b43_radio_write(dev, 0xFE, 0xFF); 30608c2ecf20Sopenharmony_ci } 30618c2ecf20Sopenharmony_ci } 30628c2ecf20Sopenharmony_ci } else { 30638c2ecf20Sopenharmony_ci if (phy->radio_rev != 5) { 30648c2ecf20Sopenharmony_ci for (core = 0; core < 2; core++) { 30658c2ecf20Sopenharmony_ci if (core == 0) { 30668c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x5c, 0x61); 30678c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x51, 0x70); 30688c2ecf20Sopenharmony_ci } else { 30698c2ecf20Sopenharmony_ci b43_radio_write(dev, 0xe1, 0x61); 30708c2ecf20Sopenharmony_ci b43_radio_write(dev, 0xd6, 0x70); 30718c2ecf20Sopenharmony_ci } 30728c2ecf20Sopenharmony_ci } 30738c2ecf20Sopenharmony_ci } 30748c2ecf20Sopenharmony_ci } 30758c2ecf20Sopenharmony_ci 30768c2ecf20Sopenharmony_ci if (phy->radio_rev == 4) { 30778c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0x20); 30788c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0x20); 30798c2ecf20Sopenharmony_ci for (core = 0; core < 2; core++) { 30808c2ecf20Sopenharmony_ci if (core == 0) { 30818c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x1a1, 0x00); 30828c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x1a2, 0x3f); 30838c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x1a6, 0x3f); 30848c2ecf20Sopenharmony_ci } else { 30858c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x1a7, 0x00); 30868c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x1ab, 0x3f); 30878c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x1ac, 0x3f); 30888c2ecf20Sopenharmony_ci } 30898c2ecf20Sopenharmony_ci } 30908c2ecf20Sopenharmony_ci } else { 30918c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_AFECTL_C1, 0x4); 30928c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x4); 30938c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_AFECTL_C2, 0x4); 30948c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4); 30958c2ecf20Sopenharmony_ci 30968c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x1); 30978c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x1); 30988c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x1); 30998c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x1); 31008c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0); 31018c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0); 31028c2ecf20Sopenharmony_ci 31038c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x4); 31048c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x4); 31058c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x4); 31068c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4); 31078c2ecf20Sopenharmony_ci } 31088c2ecf20Sopenharmony_ci 31098c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, 0x2); 31108c2ecf20Sopenharmony_ci 31118c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB32(16, 0x100), 20); 31128c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x138), 2, ntab7_138_146); 31138c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(7, 0x141), 0x77); 31148c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x133), 3, ntab7_133); 31158c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB8(7, 0x146), 2, ntab7_138_146); 31168c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(7, 0x123), 0x77); 31178c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(7, 0x12A), 0x77); 31188c2ecf20Sopenharmony_ci 31198c2ecf20Sopenharmony_ci b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x02), 1, noise_tbl); 31208c2ecf20Sopenharmony_ci noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D; 31218c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x02), 2, noise_tbl); 31228c2ecf20Sopenharmony_ci 31238c2ecf20Sopenharmony_ci b43_ntab_read_bulk(dev, B43_NTAB32(16, 0x7E), 1, noise_tbl); 31248c2ecf20Sopenharmony_ci noise_tbl[1] = b43_is_40mhz(dev) ? 0x14D : 0x18D; 31258c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB32(16, 0x7E), 2, noise_tbl); 31268c2ecf20Sopenharmony_ci 31278c2ecf20Sopenharmony_ci b43_nphy_gain_ctl_workarounds(dev); 31288c2ecf20Sopenharmony_ci 31298c2ecf20Sopenharmony_ci /* TODO 31308c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4, 31318c2ecf20Sopenharmony_ci aux_adc_vmid_rev7_core0); 31328c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4, 31338c2ecf20Sopenharmony_ci aux_adc_vmid_rev7_core1); 31348c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0C), 4, 31358c2ecf20Sopenharmony_ci aux_adc_gain_rev7); 31368c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1C), 4, 31378c2ecf20Sopenharmony_ci aux_adc_gain_rev7); 31388c2ecf20Sopenharmony_ci */ 31398c2ecf20Sopenharmony_ci} 31408c2ecf20Sopenharmony_ci 31418c2ecf20Sopenharmony_cistatic void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev) 31428c2ecf20Sopenharmony_ci{ 31438c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 31448c2ecf20Sopenharmony_ci struct ssb_sprom *sprom = dev->dev->bus_sprom; 31458c2ecf20Sopenharmony_ci 31468c2ecf20Sopenharmony_ci /* TX to RX */ 31478c2ecf20Sopenharmony_ci u8 tx2rx_events[7] = { 0x4, 0x3, 0x5, 0x2, 0x1, 0x8, 0x1F }; 31488c2ecf20Sopenharmony_ci u8 tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1 }; 31498c2ecf20Sopenharmony_ci /* RX to TX */ 31508c2ecf20Sopenharmony_ci u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3, 31518c2ecf20Sopenharmony_ci 0x1F }; 31528c2ecf20Sopenharmony_ci u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; 31538c2ecf20Sopenharmony_ci u8 rx2tx_events[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0x3, 0x4, 0x1F }; 31548c2ecf20Sopenharmony_ci u8 rx2tx_delays[9] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 }; 31558c2ecf20Sopenharmony_ci 31568c2ecf20Sopenharmony_ci u16 vmids[5][4] = { 31578c2ecf20Sopenharmony_ci { 0xa2, 0xb4, 0xb4, 0x89, }, /* 0 */ 31588c2ecf20Sopenharmony_ci { 0xb4, 0xb4, 0xb4, 0x24, }, /* 1 */ 31598c2ecf20Sopenharmony_ci { 0xa2, 0xb4, 0xb4, 0x74, }, /* 2 */ 31608c2ecf20Sopenharmony_ci { 0xa2, 0xb4, 0xb4, 0x270, }, /* 3 */ 31618c2ecf20Sopenharmony_ci { 0xa2, 0xb4, 0xb4, 0x00, }, /* 4 and 5 */ 31628c2ecf20Sopenharmony_ci }; 31638c2ecf20Sopenharmony_ci u16 gains[5][4] = { 31648c2ecf20Sopenharmony_ci { 0x02, 0x02, 0x02, 0x00, }, /* 0 */ 31658c2ecf20Sopenharmony_ci { 0x02, 0x02, 0x02, 0x02, }, /* 1 */ 31668c2ecf20Sopenharmony_ci { 0x02, 0x02, 0x02, 0x04, }, /* 2 */ 31678c2ecf20Sopenharmony_ci { 0x02, 0x02, 0x02, 0x00, }, /* 3 */ 31688c2ecf20Sopenharmony_ci { 0x02, 0x02, 0x02, 0x00, }, /* 4 and 5 */ 31698c2ecf20Sopenharmony_ci }; 31708c2ecf20Sopenharmony_ci u16 *vmid, *gain; 31718c2ecf20Sopenharmony_ci 31728c2ecf20Sopenharmony_ci u8 pdet_range; 31738c2ecf20Sopenharmony_ci u16 tmp16; 31748c2ecf20Sopenharmony_ci u32 tmp32; 31758c2ecf20Sopenharmony_ci 31768c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1f8); 31778c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1f8); 31788c2ecf20Sopenharmony_ci 31798c2ecf20Sopenharmony_ci tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0)); 31808c2ecf20Sopenharmony_ci tmp32 &= 0xffffff; 31818c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32); 31828c2ecf20Sopenharmony_ci 31838c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125); 31848c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01B3); 31858c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105); 31868c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016E); 31878c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00CD); 31888c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020); 31898c2ecf20Sopenharmony_ci 31908c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_REV3_C1_CLIP_LOGAIN_B, 0x000C); 31918c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_REV3_C2_CLIP_LOGAIN_B, 0x000C); 31928c2ecf20Sopenharmony_ci 31938c2ecf20Sopenharmony_ci /* TX to RX */ 31948c2ecf20Sopenharmony_ci b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays, 31958c2ecf20Sopenharmony_ci ARRAY_SIZE(tx2rx_events)); 31968c2ecf20Sopenharmony_ci 31978c2ecf20Sopenharmony_ci /* RX to TX */ 31988c2ecf20Sopenharmony_ci if (b43_nphy_ipa(dev)) 31998c2ecf20Sopenharmony_ci b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa, 32008c2ecf20Sopenharmony_ci rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa)); 32018c2ecf20Sopenharmony_ci if (nphy->hw_phyrxchain != 3 && 32028c2ecf20Sopenharmony_ci nphy->hw_phyrxchain != nphy->hw_phytxchain) { 32038c2ecf20Sopenharmony_ci if (b43_nphy_ipa(dev)) { 32048c2ecf20Sopenharmony_ci rx2tx_delays[5] = 59; 32058c2ecf20Sopenharmony_ci rx2tx_delays[6] = 1; 32068c2ecf20Sopenharmony_ci rx2tx_events[7] = 0x1F; 32078c2ecf20Sopenharmony_ci } 32088c2ecf20Sopenharmony_ci b43_nphy_set_rf_sequence(dev, 0, rx2tx_events, rx2tx_delays, 32098c2ecf20Sopenharmony_ci ARRAY_SIZE(rx2tx_events)); 32108c2ecf20Sopenharmony_ci } 32118c2ecf20Sopenharmony_ci 32128c2ecf20Sopenharmony_ci tmp16 = (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) ? 32138c2ecf20Sopenharmony_ci 0x2 : 0x9C40; 32148c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16); 32158c2ecf20Sopenharmony_ci 32168c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_SGILTRNOFFSET, 0xF0FF, 0x0700); 32178c2ecf20Sopenharmony_ci 32188c2ecf20Sopenharmony_ci if (!b43_is_40mhz(dev)) { 32198c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D); 32208c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D); 32218c2ecf20Sopenharmony_ci } else { 32228c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB32(16, 3), 0x14D); 32238c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB32(16, 127), 0x14D); 32248c2ecf20Sopenharmony_ci } 32258c2ecf20Sopenharmony_ci 32268c2ecf20Sopenharmony_ci b43_nphy_gain_ctl_workarounds(dev); 32278c2ecf20Sopenharmony_ci 32288c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 0), 2); 32298c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 16), 2); 32308c2ecf20Sopenharmony_ci 32318c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) 32328c2ecf20Sopenharmony_ci pdet_range = sprom->fem.ghz2.pdet_range; 32338c2ecf20Sopenharmony_ci else 32348c2ecf20Sopenharmony_ci pdet_range = sprom->fem.ghz5.pdet_range; 32358c2ecf20Sopenharmony_ci vmid = vmids[min_t(u16, pdet_range, 4)]; 32368c2ecf20Sopenharmony_ci gain = gains[min_t(u16, pdet_range, 4)]; 32378c2ecf20Sopenharmony_ci switch (pdet_range) { 32388c2ecf20Sopenharmony_ci case 3: 32398c2ecf20Sopenharmony_ci if (!(dev->phy.rev >= 4 && 32408c2ecf20Sopenharmony_ci b43_current_band(dev->wl) == NL80211_BAND_2GHZ)) 32418c2ecf20Sopenharmony_ci break; 32428c2ecf20Sopenharmony_ci fallthrough; 32438c2ecf20Sopenharmony_ci case 0: 32448c2ecf20Sopenharmony_ci case 1: 32458c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4, vmid); 32468c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4, vmid); 32478c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0c), 4, gain); 32488c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1c), 4, gain); 32498c2ecf20Sopenharmony_ci break; 32508c2ecf20Sopenharmony_ci case 2: 32518c2ecf20Sopenharmony_ci if (dev->phy.rev >= 6) { 32528c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) 32538c2ecf20Sopenharmony_ci vmid[3] = 0x94; 32548c2ecf20Sopenharmony_ci else 32558c2ecf20Sopenharmony_ci vmid[3] = 0x8e; 32568c2ecf20Sopenharmony_ci gain[3] = 3; 32578c2ecf20Sopenharmony_ci } else if (dev->phy.rev == 5) { 32588c2ecf20Sopenharmony_ci vmid[3] = 0x84; 32598c2ecf20Sopenharmony_ci gain[3] = 2; 32608c2ecf20Sopenharmony_ci } 32618c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4, vmid); 32628c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4, vmid); 32638c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0c), 4, gain); 32648c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1c), 4, gain); 32658c2ecf20Sopenharmony_ci break; 32668c2ecf20Sopenharmony_ci case 4: 32678c2ecf20Sopenharmony_ci case 5: 32688c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) != NL80211_BAND_2GHZ) { 32698c2ecf20Sopenharmony_ci if (pdet_range == 4) { 32708c2ecf20Sopenharmony_ci vmid[3] = 0x8e; 32718c2ecf20Sopenharmony_ci tmp16 = 0x96; 32728c2ecf20Sopenharmony_ci gain[3] = 0x2; 32738c2ecf20Sopenharmony_ci } else { 32748c2ecf20Sopenharmony_ci vmid[3] = 0x89; 32758c2ecf20Sopenharmony_ci tmp16 = 0x89; 32768c2ecf20Sopenharmony_ci gain[3] = 0; 32778c2ecf20Sopenharmony_ci } 32788c2ecf20Sopenharmony_ci } else { 32798c2ecf20Sopenharmony_ci if (pdet_range == 4) { 32808c2ecf20Sopenharmony_ci vmid[3] = 0x89; 32818c2ecf20Sopenharmony_ci tmp16 = 0x8b; 32828c2ecf20Sopenharmony_ci gain[3] = 0x2; 32838c2ecf20Sopenharmony_ci } else { 32848c2ecf20Sopenharmony_ci vmid[3] = 0x74; 32858c2ecf20Sopenharmony_ci tmp16 = 0x70; 32868c2ecf20Sopenharmony_ci gain[3] = 0; 32878c2ecf20Sopenharmony_ci } 32888c2ecf20Sopenharmony_ci } 32898c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4, vmid); 32908c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0c), 4, gain); 32918c2ecf20Sopenharmony_ci vmid[3] = tmp16; 32928c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4, vmid); 32938c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1c), 4, gain); 32948c2ecf20Sopenharmony_ci break; 32958c2ecf20Sopenharmony_ci } 32968c2ecf20Sopenharmony_ci 32978c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_MAST_BIAS, 0x00); 32988c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_MAST_BIAS, 0x00); 32998c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN, 0x06); 33008c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN, 0x06); 33018c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_AUX, 0x07); 33028c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07); 33038c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88); 33048c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88); 33058c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_CMFB_IDAC, 0x00); 33068c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_CMFB_IDAC, 0x00); 33078c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00); 33088c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00); 33098c2ecf20Sopenharmony_ci 33108c2ecf20Sopenharmony_ci /* N PHY WAR TX Chain Update with hw_phytxchain as argument */ 33118c2ecf20Sopenharmony_ci 33128c2ecf20Sopenharmony_ci if ((sprom->boardflags2_lo & B43_BFL2_APLL_WAR && 33138c2ecf20Sopenharmony_ci b43_current_band(dev->wl) == NL80211_BAND_5GHZ) || 33148c2ecf20Sopenharmony_ci (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR && 33158c2ecf20Sopenharmony_ci b43_current_band(dev->wl) == NL80211_BAND_2GHZ)) 33168c2ecf20Sopenharmony_ci tmp32 = 0x00088888; 33178c2ecf20Sopenharmony_ci else 33188c2ecf20Sopenharmony_ci tmp32 = 0x88888888; 33198c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB32(30, 1), tmp32); 33208c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB32(30, 2), tmp32); 33218c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32); 33228c2ecf20Sopenharmony_ci 33238c2ecf20Sopenharmony_ci if (dev->phy.rev == 4 && 33248c2ecf20Sopenharmony_ci b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { 33258c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_TX0 | B2056_TX_GMBB_IDAC, 33268c2ecf20Sopenharmony_ci 0x70); 33278c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_TX1 | B2056_TX_GMBB_IDAC, 33288c2ecf20Sopenharmony_ci 0x70); 33298c2ecf20Sopenharmony_ci } 33308c2ecf20Sopenharmony_ci 33318c2ecf20Sopenharmony_ci /* Dropped probably-always-true condition */ 33328c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_ED_CRS40ASSERTTHRESH0, 0x03eb); 33338c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_ED_CRS40ASSERTTHRESH1, 0x03eb); 33348c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_ED_CRS40DEASSERTTHRESH0, 0x0341); 33358c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_ED_CRS40DEASSERTTHRESH1, 0x0341); 33368c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_ED_CRS20LASSERTTHRESH0, 0x042b); 33378c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_ED_CRS20LASSERTTHRESH1, 0x042b); 33388c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_ED_CRS20LDEASSERTTHRESH0, 0x0381); 33398c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_ED_CRS20LDEASSERTTHRESH1, 0x0381); 33408c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_ED_CRS20UASSERTTHRESH0, 0x042b); 33418c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_ED_CRS20UASSERTTHRESH1, 0x042b); 33428c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_ED_CRS20UDEASSERTTHRESH0, 0x0381); 33438c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_ED_CRS20UDEASSERTTHRESH1, 0x0381); 33448c2ecf20Sopenharmony_ci 33458c2ecf20Sopenharmony_ci if (dev->phy.rev >= 6 && sprom->boardflags2_lo & B43_BFL2_SINGLEANT_CCK) { 33468c2ecf20Sopenharmony_ci ; /* TODO: 0x0080000000000000 HF */ 33478c2ecf20Sopenharmony_ci } 33488c2ecf20Sopenharmony_ci} 33498c2ecf20Sopenharmony_ci 33508c2ecf20Sopenharmony_cistatic void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev) 33518c2ecf20Sopenharmony_ci{ 33528c2ecf20Sopenharmony_ci struct ssb_sprom *sprom = dev->dev->bus_sprom; 33538c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 33548c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = phy->n; 33558c2ecf20Sopenharmony_ci 33568c2ecf20Sopenharmony_ci u8 events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 }; 33578c2ecf20Sopenharmony_ci u8 delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 }; 33588c2ecf20Sopenharmony_ci 33598c2ecf20Sopenharmony_ci u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 }; 33608c2ecf20Sopenharmony_ci u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 }; 33618c2ecf20Sopenharmony_ci 33628c2ecf20Sopenharmony_ci if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD || 33638c2ecf20Sopenharmony_ci dev->dev->board_type == BCMA_BOARD_TYPE_BCM943224M93) { 33648c2ecf20Sopenharmony_ci delays1[0] = 0x1; 33658c2ecf20Sopenharmony_ci delays1[5] = 0x14; 33668c2ecf20Sopenharmony_ci } 33678c2ecf20Sopenharmony_ci 33688c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ && 33698c2ecf20Sopenharmony_ci nphy->band5g_pwrgain) { 33708c2ecf20Sopenharmony_ci b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8); 33718c2ecf20Sopenharmony_ci b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8); 33728c2ecf20Sopenharmony_ci } else { 33738c2ecf20Sopenharmony_ci b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8); 33748c2ecf20Sopenharmony_ci b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8); 33758c2ecf20Sopenharmony_ci } 33768c2ecf20Sopenharmony_ci 33778c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A); 33788c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A); 33798c2ecf20Sopenharmony_ci if (dev->phy.rev < 3) { 33808c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA); 33818c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA); 33828c2ecf20Sopenharmony_ci } 33838c2ecf20Sopenharmony_ci 33848c2ecf20Sopenharmony_ci if (dev->phy.rev < 2) { 33858c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000); 33868c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0x0000); 33878c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB); 33888c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB); 33898c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x0800); 33908c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x0800); 33918c2ecf20Sopenharmony_ci } 33928c2ecf20Sopenharmony_ci 33938c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); 33948c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301); 33958c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); 33968c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); 33978c2ecf20Sopenharmony_ci 33988c2ecf20Sopenharmony_ci b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7); 33998c2ecf20Sopenharmony_ci b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7); 34008c2ecf20Sopenharmony_ci 34018c2ecf20Sopenharmony_ci b43_nphy_gain_ctl_workarounds(dev); 34028c2ecf20Sopenharmony_ci 34038c2ecf20Sopenharmony_ci if (dev->phy.rev < 2) { 34048c2ecf20Sopenharmony_ci if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2) 34058c2ecf20Sopenharmony_ci b43_hf_write(dev, b43_hf_read(dev) | 34068c2ecf20Sopenharmony_ci B43_HF_MLADVW); 34078c2ecf20Sopenharmony_ci } else if (dev->phy.rev == 2) { 34088c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0); 34098c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0); 34108c2ecf20Sopenharmony_ci } 34118c2ecf20Sopenharmony_ci 34128c2ecf20Sopenharmony_ci if (dev->phy.rev < 2) 34138c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL, 34148c2ecf20Sopenharmony_ci ~B43_NPHY_SCRAM_SIGCTL_SCM); 34158c2ecf20Sopenharmony_ci 34168c2ecf20Sopenharmony_ci /* Set phase track alpha and beta */ 34178c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125); 34188c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3); 34198c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105); 34208c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E); 34218c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD); 34228c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20); 34238c2ecf20Sopenharmony_ci 34248c2ecf20Sopenharmony_ci if (dev->phy.rev < 3) { 34258c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_PIL_DW1, 34268c2ecf20Sopenharmony_ci ~B43_NPHY_PIL_DW_64QAM & 0xFFFF); 34278c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5); 34288c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4); 34298c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00); 34308c2ecf20Sopenharmony_ci } 34318c2ecf20Sopenharmony_ci 34328c2ecf20Sopenharmony_ci if (dev->phy.rev == 2) 34338c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_FINERX2_CGC, 34348c2ecf20Sopenharmony_ci B43_NPHY_FINERX2_CGC_DECGC); 34358c2ecf20Sopenharmony_ci} 34368c2ecf20Sopenharmony_ci 34378c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */ 34388c2ecf20Sopenharmony_cistatic void b43_nphy_workarounds(struct b43_wldev *dev) 34398c2ecf20Sopenharmony_ci{ 34408c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 34418c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = phy->n; 34428c2ecf20Sopenharmony_ci 34438c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) 34448c2ecf20Sopenharmony_ci b43_nphy_classifier(dev, 1, 0); 34458c2ecf20Sopenharmony_ci else 34468c2ecf20Sopenharmony_ci b43_nphy_classifier(dev, 1, 1); 34478c2ecf20Sopenharmony_ci 34488c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 34498c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, 1); 34508c2ecf20Sopenharmony_ci 34518c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_IQFLIP, 34528c2ecf20Sopenharmony_ci B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2); 34538c2ecf20Sopenharmony_ci 34548c2ecf20Sopenharmony_ci /* TODO: rev19+ */ 34558c2ecf20Sopenharmony_ci if (dev->phy.rev >= 7) 34568c2ecf20Sopenharmony_ci b43_nphy_workarounds_rev7plus(dev); 34578c2ecf20Sopenharmony_ci else if (dev->phy.rev >= 3) 34588c2ecf20Sopenharmony_ci b43_nphy_workarounds_rev3plus(dev); 34598c2ecf20Sopenharmony_ci else 34608c2ecf20Sopenharmony_ci b43_nphy_workarounds_rev1_2(dev); 34618c2ecf20Sopenharmony_ci 34628c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 34638c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, 0); 34648c2ecf20Sopenharmony_ci} 34658c2ecf20Sopenharmony_ci 34668c2ecf20Sopenharmony_ci/************************************************** 34678c2ecf20Sopenharmony_ci * Tx/Rx common 34688c2ecf20Sopenharmony_ci **************************************************/ 34698c2ecf20Sopenharmony_ci 34708c2ecf20Sopenharmony_ci/* 34718c2ecf20Sopenharmony_ci * Transmits a known value for LO calibration 34728c2ecf20Sopenharmony_ci * https://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone 34738c2ecf20Sopenharmony_ci */ 34748c2ecf20Sopenharmony_cistatic int b43_nphy_tx_tone(struct b43_wldev *dev, u32 freq, u16 max_val, 34758c2ecf20Sopenharmony_ci bool iqmode, bool dac_test, bool modify_bbmult) 34768c2ecf20Sopenharmony_ci{ 34778c2ecf20Sopenharmony_ci u16 samp = b43_nphy_gen_load_samples(dev, freq, max_val, dac_test); 34788c2ecf20Sopenharmony_ci if (samp == 0) 34798c2ecf20Sopenharmony_ci return -1; 34808c2ecf20Sopenharmony_ci b43_nphy_run_samples(dev, samp, 0xFFFF, 0, iqmode, dac_test, 34818c2ecf20Sopenharmony_ci modify_bbmult); 34828c2ecf20Sopenharmony_ci return 0; 34838c2ecf20Sopenharmony_ci} 34848c2ecf20Sopenharmony_ci 34858c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */ 34868c2ecf20Sopenharmony_cistatic void b43_nphy_update_txrx_chain(struct b43_wldev *dev) 34878c2ecf20Sopenharmony_ci{ 34888c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 34898c2ecf20Sopenharmony_ci 34908c2ecf20Sopenharmony_ci bool override = false; 34918c2ecf20Sopenharmony_ci u16 chain = 0x33; 34928c2ecf20Sopenharmony_ci 34938c2ecf20Sopenharmony_ci if (nphy->txrx_chain == 0) { 34948c2ecf20Sopenharmony_ci chain = 0x11; 34958c2ecf20Sopenharmony_ci override = true; 34968c2ecf20Sopenharmony_ci } else if (nphy->txrx_chain == 1) { 34978c2ecf20Sopenharmony_ci chain = 0x22; 34988c2ecf20Sopenharmony_ci override = true; 34998c2ecf20Sopenharmony_ci } 35008c2ecf20Sopenharmony_ci 35018c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_RFSEQCA, 35028c2ecf20Sopenharmony_ci ~(B43_NPHY_RFSEQCA_TXEN | B43_NPHY_RFSEQCA_RXEN), 35038c2ecf20Sopenharmony_ci chain); 35048c2ecf20Sopenharmony_ci 35058c2ecf20Sopenharmony_ci if (override) 35068c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_RFSEQMODE, 35078c2ecf20Sopenharmony_ci B43_NPHY_RFSEQMODE_CAOVER); 35088c2ecf20Sopenharmony_ci else 35098c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_RFSEQMODE, 35108c2ecf20Sopenharmony_ci ~B43_NPHY_RFSEQMODE_CAOVER); 35118c2ecf20Sopenharmony_ci} 35128c2ecf20Sopenharmony_ci 35138c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */ 35148c2ecf20Sopenharmony_cistatic void b43_nphy_stop_playback(struct b43_wldev *dev) 35158c2ecf20Sopenharmony_ci{ 35168c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 35178c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 35188c2ecf20Sopenharmony_ci u16 tmp; 35198c2ecf20Sopenharmony_ci 35208c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 35218c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, 1); 35228c2ecf20Sopenharmony_ci 35238c2ecf20Sopenharmony_ci tmp = b43_phy_read(dev, B43_NPHY_SAMP_STAT); 35248c2ecf20Sopenharmony_ci if (tmp & 0x1) 35258c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_SAMP_CMD, B43_NPHY_SAMP_CMD_STOP); 35268c2ecf20Sopenharmony_ci else if (tmp & 0x2) 35278c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF); 35288c2ecf20Sopenharmony_ci 35298c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_SAMP_CMD, ~0x0004); 35308c2ecf20Sopenharmony_ci 35318c2ecf20Sopenharmony_ci if (nphy->bb_mult_save & 0x80000000) { 35328c2ecf20Sopenharmony_ci tmp = nphy->bb_mult_save & 0xFFFF; 35338c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(15, 87), tmp); 35348c2ecf20Sopenharmony_ci nphy->bb_mult_save = 0; 35358c2ecf20Sopenharmony_ci } 35368c2ecf20Sopenharmony_ci 35378c2ecf20Sopenharmony_ci if (phy->rev >= 7 && nphy->lpf_bw_overrode_for_sample_play) { 35388c2ecf20Sopenharmony_ci if (phy->rev >= 19) 35398c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev19(dev, 0x80, 0, 0, true, 35408c2ecf20Sopenharmony_ci 1); 35418c2ecf20Sopenharmony_ci else 35428c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x80, 0, 0, true, 1); 35438c2ecf20Sopenharmony_ci nphy->lpf_bw_overrode_for_sample_play = false; 35448c2ecf20Sopenharmony_ci } 35458c2ecf20Sopenharmony_ci 35468c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 35478c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, 0); 35488c2ecf20Sopenharmony_ci} 35498c2ecf20Sopenharmony_ci 35508c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/IqCalGainParams */ 35518c2ecf20Sopenharmony_cistatic void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core, 35528c2ecf20Sopenharmony_ci struct nphy_txgains target, 35538c2ecf20Sopenharmony_ci struct nphy_iqcal_params *params) 35548c2ecf20Sopenharmony_ci{ 35558c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 35568c2ecf20Sopenharmony_ci int i, j, indx; 35578c2ecf20Sopenharmony_ci u16 gain; 35588c2ecf20Sopenharmony_ci 35598c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) { 35608c2ecf20Sopenharmony_ci params->tx_lpf = target.tx_lpf[core]; /* Rev 7+ */ 35618c2ecf20Sopenharmony_ci params->txgm = target.txgm[core]; 35628c2ecf20Sopenharmony_ci params->pga = target.pga[core]; 35638c2ecf20Sopenharmony_ci params->pad = target.pad[core]; 35648c2ecf20Sopenharmony_ci params->ipa = target.ipa[core]; 35658c2ecf20Sopenharmony_ci if (phy->rev >= 19) { 35668c2ecf20Sopenharmony_ci /* TODO */ 35678c2ecf20Sopenharmony_ci } else if (phy->rev >= 7) { 35688c2ecf20Sopenharmony_ci params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 3) | (params->ipa) | (params->tx_lpf << 15); 35698c2ecf20Sopenharmony_ci } else { 35708c2ecf20Sopenharmony_ci params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 4) | (params->ipa); 35718c2ecf20Sopenharmony_ci } 35728c2ecf20Sopenharmony_ci for (j = 0; j < 5; j++) 35738c2ecf20Sopenharmony_ci params->ncorr[j] = 0x79; 35748c2ecf20Sopenharmony_ci } else { 35758c2ecf20Sopenharmony_ci gain = (target.pad[core]) | (target.pga[core] << 4) | 35768c2ecf20Sopenharmony_ci (target.txgm[core] << 8); 35778c2ecf20Sopenharmony_ci 35788c2ecf20Sopenharmony_ci indx = (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ? 35798c2ecf20Sopenharmony_ci 1 : 0; 35808c2ecf20Sopenharmony_ci for (i = 0; i < 9; i++) 35818c2ecf20Sopenharmony_ci if (tbl_iqcal_gainparams[indx][i][0] == gain) 35828c2ecf20Sopenharmony_ci break; 35838c2ecf20Sopenharmony_ci i = min(i, 8); 35848c2ecf20Sopenharmony_ci 35858c2ecf20Sopenharmony_ci params->txgm = tbl_iqcal_gainparams[indx][i][1]; 35868c2ecf20Sopenharmony_ci params->pga = tbl_iqcal_gainparams[indx][i][2]; 35878c2ecf20Sopenharmony_ci params->pad = tbl_iqcal_gainparams[indx][i][3]; 35888c2ecf20Sopenharmony_ci params->cal_gain = (params->txgm << 7) | (params->pga << 4) | 35898c2ecf20Sopenharmony_ci (params->pad << 2); 35908c2ecf20Sopenharmony_ci for (j = 0; j < 4; j++) 35918c2ecf20Sopenharmony_ci params->ncorr[j] = tbl_iqcal_gainparams[indx][i][4 + j]; 35928c2ecf20Sopenharmony_ci } 35938c2ecf20Sopenharmony_ci} 35948c2ecf20Sopenharmony_ci 35958c2ecf20Sopenharmony_ci/************************************************** 35968c2ecf20Sopenharmony_ci * Tx and Rx 35978c2ecf20Sopenharmony_ci **************************************************/ 35988c2ecf20Sopenharmony_ci 35998c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */ 36008c2ecf20Sopenharmony_cistatic void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable) 36018c2ecf20Sopenharmony_ci{ 36028c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 36038c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 36048c2ecf20Sopenharmony_ci u8 i; 36058c2ecf20Sopenharmony_ci u16 bmask, val, tmp; 36068c2ecf20Sopenharmony_ci enum nl80211_band band = b43_current_band(dev->wl); 36078c2ecf20Sopenharmony_ci 36088c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 36098c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, 1); 36108c2ecf20Sopenharmony_ci 36118c2ecf20Sopenharmony_ci nphy->txpwrctrl = enable; 36128c2ecf20Sopenharmony_ci if (!enable) { 36138c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3 && 36148c2ecf20Sopenharmony_ci (b43_phy_read(dev, B43_NPHY_TXPCTL_CMD) & 36158c2ecf20Sopenharmony_ci (B43_NPHY_TXPCTL_CMD_COEFF | 36168c2ecf20Sopenharmony_ci B43_NPHY_TXPCTL_CMD_HWPCTLEN | 36178c2ecf20Sopenharmony_ci B43_NPHY_TXPCTL_CMD_PCTLEN))) { 36188c2ecf20Sopenharmony_ci /* We disable enabled TX pwr ctl, save it's state */ 36198c2ecf20Sopenharmony_ci nphy->tx_pwr_idx[0] = b43_phy_read(dev, 36208c2ecf20Sopenharmony_ci B43_NPHY_C1_TXPCTL_STAT) & 0x7f; 36218c2ecf20Sopenharmony_ci nphy->tx_pwr_idx[1] = b43_phy_read(dev, 36228c2ecf20Sopenharmony_ci B43_NPHY_C2_TXPCTL_STAT) & 0x7f; 36238c2ecf20Sopenharmony_ci } 36248c2ecf20Sopenharmony_ci 36258c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6840); 36268c2ecf20Sopenharmony_ci for (i = 0; i < 84; i++) 36278c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0); 36288c2ecf20Sopenharmony_ci 36298c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6C40); 36308c2ecf20Sopenharmony_ci for (i = 0; i < 84; i++) 36318c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0); 36328c2ecf20Sopenharmony_ci 36338c2ecf20Sopenharmony_ci tmp = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN; 36348c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) 36358c2ecf20Sopenharmony_ci tmp |= B43_NPHY_TXPCTL_CMD_PCTLEN; 36368c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD, ~tmp); 36378c2ecf20Sopenharmony_ci 36388c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) { 36398c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100); 36408c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100); 36418c2ecf20Sopenharmony_ci } else { 36428c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000); 36438c2ecf20Sopenharmony_ci } 36448c2ecf20Sopenharmony_ci 36458c2ecf20Sopenharmony_ci if (dev->phy.rev == 2) 36468c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, 36478c2ecf20Sopenharmony_ci ~B43_NPHY_BPHY_CTL3_SCALE, 0x53); 36488c2ecf20Sopenharmony_ci else if (dev->phy.rev < 2) 36498c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, 36508c2ecf20Sopenharmony_ci ~B43_NPHY_BPHY_CTL3_SCALE, 0x5A); 36518c2ecf20Sopenharmony_ci 36528c2ecf20Sopenharmony_ci if (dev->phy.rev < 2 && b43_is_40mhz(dev)) 36538c2ecf20Sopenharmony_ci b43_hf_write(dev, b43_hf_read(dev) | B43_HF_TSSIRPSMW); 36548c2ecf20Sopenharmony_ci } else { 36558c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84, 36568c2ecf20Sopenharmony_ci nphy->adj_pwr_tbl); 36578c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84, 36588c2ecf20Sopenharmony_ci nphy->adj_pwr_tbl); 36598c2ecf20Sopenharmony_ci 36608c2ecf20Sopenharmony_ci bmask = B43_NPHY_TXPCTL_CMD_COEFF | 36618c2ecf20Sopenharmony_ci B43_NPHY_TXPCTL_CMD_HWPCTLEN; 36628c2ecf20Sopenharmony_ci /* wl does useless check for "enable" param here */ 36638c2ecf20Sopenharmony_ci val = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN; 36648c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) { 36658c2ecf20Sopenharmony_ci bmask |= B43_NPHY_TXPCTL_CMD_PCTLEN; 36668c2ecf20Sopenharmony_ci if (val) 36678c2ecf20Sopenharmony_ci val |= B43_NPHY_TXPCTL_CMD_PCTLEN; 36688c2ecf20Sopenharmony_ci } 36698c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, ~(bmask), val); 36708c2ecf20Sopenharmony_ci 36718c2ecf20Sopenharmony_ci if (band == NL80211_BAND_5GHZ) { 36728c2ecf20Sopenharmony_ci if (phy->rev >= 19) { 36738c2ecf20Sopenharmony_ci /* TODO */ 36748c2ecf20Sopenharmony_ci } else if (phy->rev >= 7) { 36758c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, 36768c2ecf20Sopenharmony_ci ~B43_NPHY_TXPCTL_CMD_INIT, 36778c2ecf20Sopenharmony_ci 0x32); 36788c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT, 36798c2ecf20Sopenharmony_ci ~B43_NPHY_TXPCTL_INIT_PIDXI1, 36808c2ecf20Sopenharmony_ci 0x32); 36818c2ecf20Sopenharmony_ci } else { 36828c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, 36838c2ecf20Sopenharmony_ci ~B43_NPHY_TXPCTL_CMD_INIT, 36848c2ecf20Sopenharmony_ci 0x64); 36858c2ecf20Sopenharmony_ci if (phy->rev > 1) 36868c2ecf20Sopenharmony_ci b43_phy_maskset(dev, 36878c2ecf20Sopenharmony_ci B43_NPHY_TXPCTL_INIT, 36888c2ecf20Sopenharmony_ci ~B43_NPHY_TXPCTL_INIT_PIDXI1, 36898c2ecf20Sopenharmony_ci 0x64); 36908c2ecf20Sopenharmony_ci } 36918c2ecf20Sopenharmony_ci } 36928c2ecf20Sopenharmony_ci 36938c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) { 36948c2ecf20Sopenharmony_ci if (nphy->tx_pwr_idx[0] != 128 && 36958c2ecf20Sopenharmony_ci nphy->tx_pwr_idx[1] != 128) { 36968c2ecf20Sopenharmony_ci /* Recover TX pwr ctl state */ 36978c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, 36988c2ecf20Sopenharmony_ci ~B43_NPHY_TXPCTL_CMD_INIT, 36998c2ecf20Sopenharmony_ci nphy->tx_pwr_idx[0]); 37008c2ecf20Sopenharmony_ci if (dev->phy.rev > 1) 37018c2ecf20Sopenharmony_ci b43_phy_maskset(dev, 37028c2ecf20Sopenharmony_ci B43_NPHY_TXPCTL_INIT, 37038c2ecf20Sopenharmony_ci ~0xff, nphy->tx_pwr_idx[1]); 37048c2ecf20Sopenharmony_ci } 37058c2ecf20Sopenharmony_ci } 37068c2ecf20Sopenharmony_ci 37078c2ecf20Sopenharmony_ci if (phy->rev >= 7) { 37088c2ecf20Sopenharmony_ci /* TODO */ 37098c2ecf20Sopenharmony_ci } 37108c2ecf20Sopenharmony_ci 37118c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) { 37128c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x100); 37138c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x100); 37148c2ecf20Sopenharmony_ci } else { 37158c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4000); 37168c2ecf20Sopenharmony_ci } 37178c2ecf20Sopenharmony_ci 37188c2ecf20Sopenharmony_ci if (dev->phy.rev == 2) 37198c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x3b); 37208c2ecf20Sopenharmony_ci else if (dev->phy.rev < 2) 37218c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x40); 37228c2ecf20Sopenharmony_ci 37238c2ecf20Sopenharmony_ci if (dev->phy.rev < 2 && b43_is_40mhz(dev)) 37248c2ecf20Sopenharmony_ci b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_TSSIRPSMW); 37258c2ecf20Sopenharmony_ci 37268c2ecf20Sopenharmony_ci if (b43_nphy_ipa(dev)) { 37278c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x4); 37288c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x4); 37298c2ecf20Sopenharmony_ci } 37308c2ecf20Sopenharmony_ci } 37318c2ecf20Sopenharmony_ci 37328c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 37338c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, 0); 37348c2ecf20Sopenharmony_ci} 37358c2ecf20Sopenharmony_ci 37368c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrFix */ 37378c2ecf20Sopenharmony_cistatic void b43_nphy_tx_power_fix(struct b43_wldev *dev) 37388c2ecf20Sopenharmony_ci{ 37398c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 37408c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 37418c2ecf20Sopenharmony_ci struct ssb_sprom *sprom = dev->dev->bus_sprom; 37428c2ecf20Sopenharmony_ci 37438c2ecf20Sopenharmony_ci u8 txpi[2], bbmult, i; 37448c2ecf20Sopenharmony_ci u16 tmp, radio_gain, dac_gain; 37458c2ecf20Sopenharmony_ci u16 freq = phy->chandef->chan->center_freq; 37468c2ecf20Sopenharmony_ci u32 txgain; 37478c2ecf20Sopenharmony_ci /* u32 gaintbl; rev3+ */ 37488c2ecf20Sopenharmony_ci 37498c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 37508c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, 1); 37518c2ecf20Sopenharmony_ci 37528c2ecf20Sopenharmony_ci /* TODO: rev19+ */ 37538c2ecf20Sopenharmony_ci if (dev->phy.rev >= 7) { 37548c2ecf20Sopenharmony_ci txpi[0] = txpi[1] = 30; 37558c2ecf20Sopenharmony_ci } else if (dev->phy.rev >= 3) { 37568c2ecf20Sopenharmony_ci txpi[0] = 40; 37578c2ecf20Sopenharmony_ci txpi[1] = 40; 37588c2ecf20Sopenharmony_ci } else if (sprom->revision < 4) { 37598c2ecf20Sopenharmony_ci txpi[0] = 72; 37608c2ecf20Sopenharmony_ci txpi[1] = 72; 37618c2ecf20Sopenharmony_ci } else { 37628c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { 37638c2ecf20Sopenharmony_ci txpi[0] = sprom->txpid2g[0]; 37648c2ecf20Sopenharmony_ci txpi[1] = sprom->txpid2g[1]; 37658c2ecf20Sopenharmony_ci } else if (freq >= 4900 && freq < 5100) { 37668c2ecf20Sopenharmony_ci txpi[0] = sprom->txpid5gl[0]; 37678c2ecf20Sopenharmony_ci txpi[1] = sprom->txpid5gl[1]; 37688c2ecf20Sopenharmony_ci } else if (freq >= 5100 && freq < 5500) { 37698c2ecf20Sopenharmony_ci txpi[0] = sprom->txpid5g[0]; 37708c2ecf20Sopenharmony_ci txpi[1] = sprom->txpid5g[1]; 37718c2ecf20Sopenharmony_ci } else if (freq >= 5500) { 37728c2ecf20Sopenharmony_ci txpi[0] = sprom->txpid5gh[0]; 37738c2ecf20Sopenharmony_ci txpi[1] = sprom->txpid5gh[1]; 37748c2ecf20Sopenharmony_ci } else { 37758c2ecf20Sopenharmony_ci txpi[0] = 91; 37768c2ecf20Sopenharmony_ci txpi[1] = 91; 37778c2ecf20Sopenharmony_ci } 37788c2ecf20Sopenharmony_ci } 37798c2ecf20Sopenharmony_ci if (dev->phy.rev < 7 && 37808c2ecf20Sopenharmony_ci (txpi[0] < 40 || txpi[0] > 100 || txpi[1] < 40 || txpi[1] > 100)) 37818c2ecf20Sopenharmony_ci txpi[0] = txpi[1] = 91; 37828c2ecf20Sopenharmony_ci 37838c2ecf20Sopenharmony_ci /* 37848c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 37858c2ecf20Sopenharmony_ci nphy->txpwrindex[i].index_internal = txpi[i]; 37868c2ecf20Sopenharmony_ci nphy->txpwrindex[i].index_internal_save = txpi[i]; 37878c2ecf20Sopenharmony_ci } 37888c2ecf20Sopenharmony_ci */ 37898c2ecf20Sopenharmony_ci 37908c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 37918c2ecf20Sopenharmony_ci const u32 *table = b43_nphy_get_tx_gain_table(dev); 37928c2ecf20Sopenharmony_ci 37938c2ecf20Sopenharmony_ci if (!table) 37948c2ecf20Sopenharmony_ci break; 37958c2ecf20Sopenharmony_ci txgain = *(table + txpi[i]); 37968c2ecf20Sopenharmony_ci 37978c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) 37988c2ecf20Sopenharmony_ci radio_gain = (txgain >> 16) & 0x1FFFF; 37998c2ecf20Sopenharmony_ci else 38008c2ecf20Sopenharmony_ci radio_gain = (txgain >> 16) & 0x1FFF; 38018c2ecf20Sopenharmony_ci 38028c2ecf20Sopenharmony_ci if (dev->phy.rev >= 7) 38038c2ecf20Sopenharmony_ci dac_gain = (txgain >> 8) & 0x7; 38048c2ecf20Sopenharmony_ci else 38058c2ecf20Sopenharmony_ci dac_gain = (txgain >> 8) & 0x3F; 38068c2ecf20Sopenharmony_ci bbmult = txgain & 0xFF; 38078c2ecf20Sopenharmony_ci 38088c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) { 38098c2ecf20Sopenharmony_ci if (i == 0) 38108c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100); 38118c2ecf20Sopenharmony_ci else 38128c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100); 38138c2ecf20Sopenharmony_ci } else { 38148c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000); 38158c2ecf20Sopenharmony_ci } 38168c2ecf20Sopenharmony_ci 38178c2ecf20Sopenharmony_ci if (i == 0) 38188c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN1, dac_gain); 38198c2ecf20Sopenharmony_ci else 38208c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN2, dac_gain); 38218c2ecf20Sopenharmony_ci 38228c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(0x7, 0x110 + i), radio_gain); 38238c2ecf20Sopenharmony_ci 38248c2ecf20Sopenharmony_ci tmp = b43_ntab_read(dev, B43_NTAB16(0xF, 0x57)); 38258c2ecf20Sopenharmony_ci if (i == 0) 38268c2ecf20Sopenharmony_ci tmp = (tmp & 0x00FF) | (bbmult << 8); 38278c2ecf20Sopenharmony_ci else 38288c2ecf20Sopenharmony_ci tmp = (tmp & 0xFF00) | bbmult; 38298c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(0xF, 0x57), tmp); 38308c2ecf20Sopenharmony_ci 38318c2ecf20Sopenharmony_ci if (b43_nphy_ipa(dev)) { 38328c2ecf20Sopenharmony_ci u32 tmp32; 38338c2ecf20Sopenharmony_ci u16 reg = (i == 0) ? 38348c2ecf20Sopenharmony_ci B43_NPHY_PAPD_EN0 : B43_NPHY_PAPD_EN1; 38358c2ecf20Sopenharmony_ci tmp32 = b43_ntab_read(dev, B43_NTAB32(26 + i, 38368c2ecf20Sopenharmony_ci 576 + txpi[i])); 38378c2ecf20Sopenharmony_ci b43_phy_maskset(dev, reg, 0xE00F, (u32) tmp32 << 4); 38388c2ecf20Sopenharmony_ci b43_phy_set(dev, reg, 0x4); 38398c2ecf20Sopenharmony_ci } 38408c2ecf20Sopenharmony_ci } 38418c2ecf20Sopenharmony_ci 38428c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_BPHY_CTL2, ~B43_NPHY_BPHY_CTL2_LUT); 38438c2ecf20Sopenharmony_ci 38448c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 38458c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, 0); 38468c2ecf20Sopenharmony_ci} 38478c2ecf20Sopenharmony_ci 38488c2ecf20Sopenharmony_cistatic void b43_nphy_ipa_internal_tssi_setup(struct b43_wldev *dev) 38498c2ecf20Sopenharmony_ci{ 38508c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 38518c2ecf20Sopenharmony_ci 38528c2ecf20Sopenharmony_ci u8 core; 38538c2ecf20Sopenharmony_ci u16 r; /* routing */ 38548c2ecf20Sopenharmony_ci 38558c2ecf20Sopenharmony_ci if (phy->rev >= 19) { 38568c2ecf20Sopenharmony_ci /* TODO */ 38578c2ecf20Sopenharmony_ci } else if (phy->rev >= 7) { 38588c2ecf20Sopenharmony_ci for (core = 0; core < 2; core++) { 38598c2ecf20Sopenharmony_ci r = core ? 0x190 : 0x170; 38608c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { 38618c2ecf20Sopenharmony_ci b43_radio_write(dev, r + 0x5, 0x5); 38628c2ecf20Sopenharmony_ci b43_radio_write(dev, r + 0x9, 0xE); 38638c2ecf20Sopenharmony_ci if (phy->rev != 5) 38648c2ecf20Sopenharmony_ci b43_radio_write(dev, r + 0xA, 0); 38658c2ecf20Sopenharmony_ci if (phy->rev != 7) 38668c2ecf20Sopenharmony_ci b43_radio_write(dev, r + 0xB, 1); 38678c2ecf20Sopenharmony_ci else 38688c2ecf20Sopenharmony_ci b43_radio_write(dev, r + 0xB, 0x31); 38698c2ecf20Sopenharmony_ci } else { 38708c2ecf20Sopenharmony_ci b43_radio_write(dev, r + 0x5, 0x9); 38718c2ecf20Sopenharmony_ci b43_radio_write(dev, r + 0x9, 0xC); 38728c2ecf20Sopenharmony_ci b43_radio_write(dev, r + 0xB, 0x0); 38738c2ecf20Sopenharmony_ci if (phy->rev != 5) 38748c2ecf20Sopenharmony_ci b43_radio_write(dev, r + 0xA, 1); 38758c2ecf20Sopenharmony_ci else 38768c2ecf20Sopenharmony_ci b43_radio_write(dev, r + 0xA, 0x31); 38778c2ecf20Sopenharmony_ci } 38788c2ecf20Sopenharmony_ci b43_radio_write(dev, r + 0x6, 0); 38798c2ecf20Sopenharmony_ci b43_radio_write(dev, r + 0x7, 0); 38808c2ecf20Sopenharmony_ci b43_radio_write(dev, r + 0x8, 3); 38818c2ecf20Sopenharmony_ci b43_radio_write(dev, r + 0xC, 0); 38828c2ecf20Sopenharmony_ci } 38838c2ecf20Sopenharmony_ci } else { 38848c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) 38858c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_RESERVED_ADDR31, 0x128); 38868c2ecf20Sopenharmony_ci else 38878c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_RESERVED_ADDR31, 0x80); 38888c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_RESERVED_ADDR30, 0); 38898c2ecf20Sopenharmony_ci b43_radio_write(dev, B2056_SYN_GPIO_MASTER1, 0x29); 38908c2ecf20Sopenharmony_ci 38918c2ecf20Sopenharmony_ci for (core = 0; core < 2; core++) { 38928c2ecf20Sopenharmony_ci r = core ? B2056_TX1 : B2056_TX0; 38938c2ecf20Sopenharmony_ci 38948c2ecf20Sopenharmony_ci b43_radio_write(dev, r | B2056_TX_IQCAL_VCM_HG, 0); 38958c2ecf20Sopenharmony_ci b43_radio_write(dev, r | B2056_TX_IQCAL_IDAC, 0); 38968c2ecf20Sopenharmony_ci b43_radio_write(dev, r | B2056_TX_TSSI_VCM, 3); 38978c2ecf20Sopenharmony_ci b43_radio_write(dev, r | B2056_TX_TX_AMP_DET, 0); 38988c2ecf20Sopenharmony_ci b43_radio_write(dev, r | B2056_TX_TSSI_MISC1, 8); 38998c2ecf20Sopenharmony_ci b43_radio_write(dev, r | B2056_TX_TSSI_MISC2, 0); 39008c2ecf20Sopenharmony_ci b43_radio_write(dev, r | B2056_TX_TSSI_MISC3, 0); 39018c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { 39028c2ecf20Sopenharmony_ci b43_radio_write(dev, r | B2056_TX_TX_SSI_MASTER, 39038c2ecf20Sopenharmony_ci 0x5); 39048c2ecf20Sopenharmony_ci if (phy->rev != 5) 39058c2ecf20Sopenharmony_ci b43_radio_write(dev, r | B2056_TX_TSSIA, 39068c2ecf20Sopenharmony_ci 0x00); 39078c2ecf20Sopenharmony_ci if (phy->rev >= 5) 39088c2ecf20Sopenharmony_ci b43_radio_write(dev, r | B2056_TX_TSSIG, 39098c2ecf20Sopenharmony_ci 0x31); 39108c2ecf20Sopenharmony_ci else 39118c2ecf20Sopenharmony_ci b43_radio_write(dev, r | B2056_TX_TSSIG, 39128c2ecf20Sopenharmony_ci 0x11); 39138c2ecf20Sopenharmony_ci b43_radio_write(dev, r | B2056_TX_TX_SSI_MUX, 39148c2ecf20Sopenharmony_ci 0xE); 39158c2ecf20Sopenharmony_ci } else { 39168c2ecf20Sopenharmony_ci b43_radio_write(dev, r | B2056_TX_TX_SSI_MASTER, 39178c2ecf20Sopenharmony_ci 0x9); 39188c2ecf20Sopenharmony_ci b43_radio_write(dev, r | B2056_TX_TSSIA, 0x31); 39198c2ecf20Sopenharmony_ci b43_radio_write(dev, r | B2056_TX_TSSIG, 0x0); 39208c2ecf20Sopenharmony_ci b43_radio_write(dev, r | B2056_TX_TX_SSI_MUX, 39218c2ecf20Sopenharmony_ci 0xC); 39228c2ecf20Sopenharmony_ci } 39238c2ecf20Sopenharmony_ci } 39248c2ecf20Sopenharmony_ci } 39258c2ecf20Sopenharmony_ci} 39268c2ecf20Sopenharmony_ci 39278c2ecf20Sopenharmony_ci/* 39288c2ecf20Sopenharmony_ci * Stop radio and transmit known signal. Then check received signal strength to 39298c2ecf20Sopenharmony_ci * get TSSI (Transmit Signal Strength Indicator). 39308c2ecf20Sopenharmony_ci * https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlIdleTssi 39318c2ecf20Sopenharmony_ci */ 39328c2ecf20Sopenharmony_cistatic void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev) 39338c2ecf20Sopenharmony_ci{ 39348c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 39358c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 39368c2ecf20Sopenharmony_ci 39378c2ecf20Sopenharmony_ci u32 tmp; 39388c2ecf20Sopenharmony_ci s32 rssi[4] = { }; 39398c2ecf20Sopenharmony_ci 39408c2ecf20Sopenharmony_ci if (phy->chandef->chan->flags & IEEE80211_CHAN_NO_IR) 39418c2ecf20Sopenharmony_ci return; 39428c2ecf20Sopenharmony_ci 39438c2ecf20Sopenharmony_ci if (b43_nphy_ipa(dev)) 39448c2ecf20Sopenharmony_ci b43_nphy_ipa_internal_tssi_setup(dev); 39458c2ecf20Sopenharmony_ci 39468c2ecf20Sopenharmony_ci if (phy->rev >= 19) 39478c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev19(dev, 0x1000, 0, 3, false, 0); 39488c2ecf20Sopenharmony_ci else if (phy->rev >= 7) 39498c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x1000, 0, 3, false, 0); 39508c2ecf20Sopenharmony_ci else if (phy->rev >= 3) 39518c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, false); 39528c2ecf20Sopenharmony_ci 39538c2ecf20Sopenharmony_ci b43_nphy_stop_playback(dev); 39548c2ecf20Sopenharmony_ci b43_nphy_tx_tone(dev, 4000, 0, false, false, false); 39558c2ecf20Sopenharmony_ci udelay(20); 39568c2ecf20Sopenharmony_ci tmp = b43_nphy_poll_rssi(dev, N_RSSI_TSSI_2G, rssi, 1); 39578c2ecf20Sopenharmony_ci b43_nphy_stop_playback(dev); 39588c2ecf20Sopenharmony_ci 39598c2ecf20Sopenharmony_ci b43_nphy_rssi_select(dev, 0, N_RSSI_W1); 39608c2ecf20Sopenharmony_ci 39618c2ecf20Sopenharmony_ci if (phy->rev >= 19) 39628c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev19(dev, 0x1000, 0, 3, true, 0); 39638c2ecf20Sopenharmony_ci else if (phy->rev >= 7) 39648c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x1000, 0, 3, true, 0); 39658c2ecf20Sopenharmony_ci else if (phy->rev >= 3) 39668c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override(dev, 0x2000, 0, 3, true); 39678c2ecf20Sopenharmony_ci 39688c2ecf20Sopenharmony_ci if (phy->rev >= 19) { 39698c2ecf20Sopenharmony_ci /* TODO */ 39708c2ecf20Sopenharmony_ci return; 39718c2ecf20Sopenharmony_ci } else if (phy->rev >= 3) { 39728c2ecf20Sopenharmony_ci nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 24) & 0xFF; 39738c2ecf20Sopenharmony_ci nphy->pwr_ctl_info[1].idle_tssi_5g = (tmp >> 8) & 0xFF; 39748c2ecf20Sopenharmony_ci } else { 39758c2ecf20Sopenharmony_ci nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 16) & 0xFF; 39768c2ecf20Sopenharmony_ci nphy->pwr_ctl_info[1].idle_tssi_5g = tmp & 0xFF; 39778c2ecf20Sopenharmony_ci } 39788c2ecf20Sopenharmony_ci nphy->pwr_ctl_info[0].idle_tssi_2g = (tmp >> 24) & 0xFF; 39798c2ecf20Sopenharmony_ci nphy->pwr_ctl_info[1].idle_tssi_2g = (tmp >> 8) & 0xFF; 39808c2ecf20Sopenharmony_ci} 39818c2ecf20Sopenharmony_ci 39828c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/PHY/N/TxPwrLimitToTbl */ 39838c2ecf20Sopenharmony_cistatic void b43_nphy_tx_prepare_adjusted_power_table(struct b43_wldev *dev) 39848c2ecf20Sopenharmony_ci{ 39858c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 39868c2ecf20Sopenharmony_ci 39878c2ecf20Sopenharmony_ci u8 idx, delta; 39888c2ecf20Sopenharmony_ci u8 i, stf_mode; 39898c2ecf20Sopenharmony_ci 39908c2ecf20Sopenharmony_ci /* Array adj_pwr_tbl corresponds to the hardware table. It consists of 39918c2ecf20Sopenharmony_ci * 21 groups, each containing 4 entries. 39928c2ecf20Sopenharmony_ci * 39938c2ecf20Sopenharmony_ci * First group has entries for CCK modulation. 39948c2ecf20Sopenharmony_ci * The rest of groups has 1 entry per modulation (SISO, CDD, STBC, SDM). 39958c2ecf20Sopenharmony_ci * 39968c2ecf20Sopenharmony_ci * Group 0 is for CCK 39978c2ecf20Sopenharmony_ci * Groups 1..4 use BPSK (group per coding rate) 39988c2ecf20Sopenharmony_ci * Groups 5..8 use QPSK (group per coding rate) 39998c2ecf20Sopenharmony_ci * Groups 9..12 use 16-QAM (group per coding rate) 40008c2ecf20Sopenharmony_ci * Groups 13..16 use 64-QAM (group per coding rate) 40018c2ecf20Sopenharmony_ci * Groups 17..20 are unknown 40028c2ecf20Sopenharmony_ci */ 40038c2ecf20Sopenharmony_ci 40048c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 40058c2ecf20Sopenharmony_ci nphy->adj_pwr_tbl[i] = nphy->tx_power_offset[i]; 40068c2ecf20Sopenharmony_ci 40078c2ecf20Sopenharmony_ci for (stf_mode = 0; stf_mode < 4; stf_mode++) { 40088c2ecf20Sopenharmony_ci delta = 0; 40098c2ecf20Sopenharmony_ci switch (stf_mode) { 40108c2ecf20Sopenharmony_ci case 0: 40118c2ecf20Sopenharmony_ci if (b43_is_40mhz(dev) && dev->phy.rev >= 5) { 40128c2ecf20Sopenharmony_ci idx = 68; 40138c2ecf20Sopenharmony_ci } else { 40148c2ecf20Sopenharmony_ci delta = 1; 40158c2ecf20Sopenharmony_ci idx = b43_is_40mhz(dev) ? 52 : 4; 40168c2ecf20Sopenharmony_ci } 40178c2ecf20Sopenharmony_ci break; 40188c2ecf20Sopenharmony_ci case 1: 40198c2ecf20Sopenharmony_ci idx = b43_is_40mhz(dev) ? 76 : 28; 40208c2ecf20Sopenharmony_ci break; 40218c2ecf20Sopenharmony_ci case 2: 40228c2ecf20Sopenharmony_ci idx = b43_is_40mhz(dev) ? 84 : 36; 40238c2ecf20Sopenharmony_ci break; 40248c2ecf20Sopenharmony_ci case 3: 40258c2ecf20Sopenharmony_ci idx = b43_is_40mhz(dev) ? 92 : 44; 40268c2ecf20Sopenharmony_ci break; 40278c2ecf20Sopenharmony_ci } 40288c2ecf20Sopenharmony_ci 40298c2ecf20Sopenharmony_ci for (i = 0; i < 20; i++) { 40308c2ecf20Sopenharmony_ci nphy->adj_pwr_tbl[4 + 4 * i + stf_mode] = 40318c2ecf20Sopenharmony_ci nphy->tx_power_offset[idx]; 40328c2ecf20Sopenharmony_ci if (i == 0) 40338c2ecf20Sopenharmony_ci idx += delta; 40348c2ecf20Sopenharmony_ci if (i == 14) 40358c2ecf20Sopenharmony_ci idx += 1 - delta; 40368c2ecf20Sopenharmony_ci if (i == 3 || i == 4 || i == 7 || i == 8 || i == 11 || 40378c2ecf20Sopenharmony_ci i == 13) 40388c2ecf20Sopenharmony_ci idx += 1; 40398c2ecf20Sopenharmony_ci } 40408c2ecf20Sopenharmony_ci } 40418c2ecf20Sopenharmony_ci} 40428c2ecf20Sopenharmony_ci 40438c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlSetup */ 40448c2ecf20Sopenharmony_cistatic void b43_nphy_tx_power_ctl_setup(struct b43_wldev *dev) 40458c2ecf20Sopenharmony_ci{ 40468c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 40478c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 40488c2ecf20Sopenharmony_ci struct ssb_sprom *sprom = dev->dev->bus_sprom; 40498c2ecf20Sopenharmony_ci 40508c2ecf20Sopenharmony_ci s16 a1[2], b0[2], b1[2]; 40518c2ecf20Sopenharmony_ci u8 idle[2]; 40528c2ecf20Sopenharmony_ci u8 ppr_max; 40538c2ecf20Sopenharmony_ci s8 target[2]; 40548c2ecf20Sopenharmony_ci s32 num, den, pwr; 40558c2ecf20Sopenharmony_ci u32 regval[64]; 40568c2ecf20Sopenharmony_ci 40578c2ecf20Sopenharmony_ci u16 freq = phy->chandef->chan->center_freq; 40588c2ecf20Sopenharmony_ci u16 tmp; 40598c2ecf20Sopenharmony_ci u16 r; /* routing */ 40608c2ecf20Sopenharmony_ci u8 i, c; 40618c2ecf20Sopenharmony_ci 40628c2ecf20Sopenharmony_ci if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) { 40638c2ecf20Sopenharmony_ci b43_maskset32(dev, B43_MMIO_MACCTL, ~0, 0x200000); 40648c2ecf20Sopenharmony_ci b43_read32(dev, B43_MMIO_MACCTL); 40658c2ecf20Sopenharmony_ci udelay(1); 40668c2ecf20Sopenharmony_ci } 40678c2ecf20Sopenharmony_ci 40688c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 40698c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, true); 40708c2ecf20Sopenharmony_ci 40718c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_TSSIMODE, B43_NPHY_TSSIMODE_EN); 40728c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) 40738c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD, 40748c2ecf20Sopenharmony_ci ~B43_NPHY_TXPCTL_CMD_PCTLEN & 0xFFFF); 40758c2ecf20Sopenharmony_ci else 40768c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_TXPCTL_CMD, 40778c2ecf20Sopenharmony_ci B43_NPHY_TXPCTL_CMD_PCTLEN); 40788c2ecf20Sopenharmony_ci 40798c2ecf20Sopenharmony_ci if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) 40808c2ecf20Sopenharmony_ci b43_maskset32(dev, B43_MMIO_MACCTL, ~0x200000, 0); 40818c2ecf20Sopenharmony_ci 40828c2ecf20Sopenharmony_ci if (sprom->revision < 4) { 40838c2ecf20Sopenharmony_ci idle[0] = nphy->pwr_ctl_info[0].idle_tssi_2g; 40848c2ecf20Sopenharmony_ci idle[1] = nphy->pwr_ctl_info[1].idle_tssi_2g; 40858c2ecf20Sopenharmony_ci target[0] = target[1] = 52; 40868c2ecf20Sopenharmony_ci a1[0] = a1[1] = -424; 40878c2ecf20Sopenharmony_ci b0[0] = b0[1] = 5612; 40888c2ecf20Sopenharmony_ci b1[0] = b1[1] = -1393; 40898c2ecf20Sopenharmony_ci } else { 40908c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { 40918c2ecf20Sopenharmony_ci for (c = 0; c < 2; c++) { 40928c2ecf20Sopenharmony_ci idle[c] = nphy->pwr_ctl_info[c].idle_tssi_2g; 40938c2ecf20Sopenharmony_ci target[c] = sprom->core_pwr_info[c].maxpwr_2g; 40948c2ecf20Sopenharmony_ci a1[c] = sprom->core_pwr_info[c].pa_2g[0]; 40958c2ecf20Sopenharmony_ci b0[c] = sprom->core_pwr_info[c].pa_2g[1]; 40968c2ecf20Sopenharmony_ci b1[c] = sprom->core_pwr_info[c].pa_2g[2]; 40978c2ecf20Sopenharmony_ci } 40988c2ecf20Sopenharmony_ci } else if (freq >= 4900 && freq < 5100) { 40998c2ecf20Sopenharmony_ci for (c = 0; c < 2; c++) { 41008c2ecf20Sopenharmony_ci idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g; 41018c2ecf20Sopenharmony_ci target[c] = sprom->core_pwr_info[c].maxpwr_5gl; 41028c2ecf20Sopenharmony_ci a1[c] = sprom->core_pwr_info[c].pa_5gl[0]; 41038c2ecf20Sopenharmony_ci b0[c] = sprom->core_pwr_info[c].pa_5gl[1]; 41048c2ecf20Sopenharmony_ci b1[c] = sprom->core_pwr_info[c].pa_5gl[2]; 41058c2ecf20Sopenharmony_ci } 41068c2ecf20Sopenharmony_ci } else if (freq >= 5100 && freq < 5500) { 41078c2ecf20Sopenharmony_ci for (c = 0; c < 2; c++) { 41088c2ecf20Sopenharmony_ci idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g; 41098c2ecf20Sopenharmony_ci target[c] = sprom->core_pwr_info[c].maxpwr_5g; 41108c2ecf20Sopenharmony_ci a1[c] = sprom->core_pwr_info[c].pa_5g[0]; 41118c2ecf20Sopenharmony_ci b0[c] = sprom->core_pwr_info[c].pa_5g[1]; 41128c2ecf20Sopenharmony_ci b1[c] = sprom->core_pwr_info[c].pa_5g[2]; 41138c2ecf20Sopenharmony_ci } 41148c2ecf20Sopenharmony_ci } else if (freq >= 5500) { 41158c2ecf20Sopenharmony_ci for (c = 0; c < 2; c++) { 41168c2ecf20Sopenharmony_ci idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g; 41178c2ecf20Sopenharmony_ci target[c] = sprom->core_pwr_info[c].maxpwr_5gh; 41188c2ecf20Sopenharmony_ci a1[c] = sprom->core_pwr_info[c].pa_5gh[0]; 41198c2ecf20Sopenharmony_ci b0[c] = sprom->core_pwr_info[c].pa_5gh[1]; 41208c2ecf20Sopenharmony_ci b1[c] = sprom->core_pwr_info[c].pa_5gh[2]; 41218c2ecf20Sopenharmony_ci } 41228c2ecf20Sopenharmony_ci } else { 41238c2ecf20Sopenharmony_ci idle[0] = nphy->pwr_ctl_info[0].idle_tssi_5g; 41248c2ecf20Sopenharmony_ci idle[1] = nphy->pwr_ctl_info[1].idle_tssi_5g; 41258c2ecf20Sopenharmony_ci target[0] = target[1] = 52; 41268c2ecf20Sopenharmony_ci a1[0] = a1[1] = -424; 41278c2ecf20Sopenharmony_ci b0[0] = b0[1] = 5612; 41288c2ecf20Sopenharmony_ci b1[0] = b1[1] = -1393; 41298c2ecf20Sopenharmony_ci } 41308c2ecf20Sopenharmony_ci } 41318c2ecf20Sopenharmony_ci 41328c2ecf20Sopenharmony_ci ppr_max = b43_ppr_get_max(dev, &nphy->tx_pwr_max_ppr); 41338c2ecf20Sopenharmony_ci if (ppr_max) { 41348c2ecf20Sopenharmony_ci target[0] = ppr_max; 41358c2ecf20Sopenharmony_ci target[1] = ppr_max; 41368c2ecf20Sopenharmony_ci } 41378c2ecf20Sopenharmony_ci 41388c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) { 41398c2ecf20Sopenharmony_ci if (sprom->fem.ghz2.tssipos) 41408c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_TXPCTL_ITSSI, 0x4000); 41418c2ecf20Sopenharmony_ci if (dev->phy.rev >= 7) { 41428c2ecf20Sopenharmony_ci for (c = 0; c < 2; c++) { 41438c2ecf20Sopenharmony_ci r = c ? 0x190 : 0x170; 41448c2ecf20Sopenharmony_ci if (b43_nphy_ipa(dev)) 41458c2ecf20Sopenharmony_ci b43_radio_write(dev, r + 0x9, (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) ? 0xE : 0xC); 41468c2ecf20Sopenharmony_ci } 41478c2ecf20Sopenharmony_ci } else { 41488c2ecf20Sopenharmony_ci if (b43_nphy_ipa(dev)) { 41498c2ecf20Sopenharmony_ci tmp = (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) ? 0xC : 0xE; 41508c2ecf20Sopenharmony_ci b43_radio_write(dev, 41518c2ecf20Sopenharmony_ci B2056_TX0 | B2056_TX_TX_SSI_MUX, tmp); 41528c2ecf20Sopenharmony_ci b43_radio_write(dev, 41538c2ecf20Sopenharmony_ci B2056_TX1 | B2056_TX_TX_SSI_MUX, tmp); 41548c2ecf20Sopenharmony_ci } else { 41558c2ecf20Sopenharmony_ci b43_radio_write(dev, 41568c2ecf20Sopenharmony_ci B2056_TX0 | B2056_TX_TX_SSI_MUX, 0x11); 41578c2ecf20Sopenharmony_ci b43_radio_write(dev, 41588c2ecf20Sopenharmony_ci B2056_TX1 | B2056_TX_TX_SSI_MUX, 0x11); 41598c2ecf20Sopenharmony_ci } 41608c2ecf20Sopenharmony_ci } 41618c2ecf20Sopenharmony_ci } 41628c2ecf20Sopenharmony_ci 41638c2ecf20Sopenharmony_ci if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) { 41648c2ecf20Sopenharmony_ci b43_maskset32(dev, B43_MMIO_MACCTL, ~0, 0x200000); 41658c2ecf20Sopenharmony_ci b43_read32(dev, B43_MMIO_MACCTL); 41668c2ecf20Sopenharmony_ci udelay(1); 41678c2ecf20Sopenharmony_ci } 41688c2ecf20Sopenharmony_ci 41698c2ecf20Sopenharmony_ci if (phy->rev >= 19) { 41708c2ecf20Sopenharmony_ci /* TODO */ 41718c2ecf20Sopenharmony_ci } else if (phy->rev >= 7) { 41728c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, 41738c2ecf20Sopenharmony_ci ~B43_NPHY_TXPCTL_CMD_INIT, 0x19); 41748c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT, 41758c2ecf20Sopenharmony_ci ~B43_NPHY_TXPCTL_INIT_PIDXI1, 0x19); 41768c2ecf20Sopenharmony_ci } else { 41778c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, 41788c2ecf20Sopenharmony_ci ~B43_NPHY_TXPCTL_CMD_INIT, 0x40); 41798c2ecf20Sopenharmony_ci if (dev->phy.rev > 1) 41808c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT, 41818c2ecf20Sopenharmony_ci ~B43_NPHY_TXPCTL_INIT_PIDXI1, 0x40); 41828c2ecf20Sopenharmony_ci } 41838c2ecf20Sopenharmony_ci 41848c2ecf20Sopenharmony_ci if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) 41858c2ecf20Sopenharmony_ci b43_maskset32(dev, B43_MMIO_MACCTL, ~0x200000, 0); 41868c2ecf20Sopenharmony_ci 41878c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TXPCTL_N, 41888c2ecf20Sopenharmony_ci 0xF0 << B43_NPHY_TXPCTL_N_TSSID_SHIFT | 41898c2ecf20Sopenharmony_ci 3 << B43_NPHY_TXPCTL_N_NPTIL2_SHIFT); 41908c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TXPCTL_ITSSI, 41918c2ecf20Sopenharmony_ci idle[0] << B43_NPHY_TXPCTL_ITSSI_0_SHIFT | 41928c2ecf20Sopenharmony_ci idle[1] << B43_NPHY_TXPCTL_ITSSI_1_SHIFT | 41938c2ecf20Sopenharmony_ci B43_NPHY_TXPCTL_ITSSI_BINF); 41948c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TXPCTL_TPWR, 41958c2ecf20Sopenharmony_ci target[0] << B43_NPHY_TXPCTL_TPWR_0_SHIFT | 41968c2ecf20Sopenharmony_ci target[1] << B43_NPHY_TXPCTL_TPWR_1_SHIFT); 41978c2ecf20Sopenharmony_ci 41988c2ecf20Sopenharmony_ci for (c = 0; c < 2; c++) { 41998c2ecf20Sopenharmony_ci for (i = 0; i < 64; i++) { 42008c2ecf20Sopenharmony_ci num = 8 * (16 * b0[c] + b1[c] * i); 42018c2ecf20Sopenharmony_ci den = 32768 + a1[c] * i; 42028c2ecf20Sopenharmony_ci pwr = max((4 * num + den / 2) / den, -8); 42038c2ecf20Sopenharmony_ci if (dev->phy.rev < 3 && (i <= (31 - idle[c] + 1))) 42048c2ecf20Sopenharmony_ci pwr = max(pwr, target[c] + 1); 42058c2ecf20Sopenharmony_ci regval[i] = pwr; 42068c2ecf20Sopenharmony_ci } 42078c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB32(26 + c, 0), 64, regval); 42088c2ecf20Sopenharmony_ci } 42098c2ecf20Sopenharmony_ci 42108c2ecf20Sopenharmony_ci b43_nphy_tx_prepare_adjusted_power_table(dev); 42118c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84, nphy->adj_pwr_tbl); 42128c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84, nphy->adj_pwr_tbl); 42138c2ecf20Sopenharmony_ci 42148c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 42158c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, false); 42168c2ecf20Sopenharmony_ci} 42178c2ecf20Sopenharmony_ci 42188c2ecf20Sopenharmony_cistatic void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev) 42198c2ecf20Sopenharmony_ci{ 42208c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 42218c2ecf20Sopenharmony_ci 42228c2ecf20Sopenharmony_ci const u32 *table = NULL; 42238c2ecf20Sopenharmony_ci u32 rfpwr_offset; 42248c2ecf20Sopenharmony_ci u8 pga_gain, pad_gain; 42258c2ecf20Sopenharmony_ci int i; 42268c2ecf20Sopenharmony_ci const s16 *rf_pwr_offset_table = NULL; 42278c2ecf20Sopenharmony_ci 42288c2ecf20Sopenharmony_ci table = b43_nphy_get_tx_gain_table(dev); 42298c2ecf20Sopenharmony_ci if (!table) 42308c2ecf20Sopenharmony_ci return; 42318c2ecf20Sopenharmony_ci 42328c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table); 42338c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table); 42348c2ecf20Sopenharmony_ci 42358c2ecf20Sopenharmony_ci if (phy->rev < 3) 42368c2ecf20Sopenharmony_ci return; 42378c2ecf20Sopenharmony_ci 42388c2ecf20Sopenharmony_ci#if 0 42398c2ecf20Sopenharmony_ci nphy->gmval = (table[0] >> 16) & 0x7000; 42408c2ecf20Sopenharmony_ci#endif 42418c2ecf20Sopenharmony_ci 42428c2ecf20Sopenharmony_ci if (phy->rev >= 19) { 42438c2ecf20Sopenharmony_ci return; 42448c2ecf20Sopenharmony_ci } else if (phy->rev >= 7) { 42458c2ecf20Sopenharmony_ci rf_pwr_offset_table = b43_ntab_get_rf_pwr_offset_table(dev); 42468c2ecf20Sopenharmony_ci if (!rf_pwr_offset_table) 42478c2ecf20Sopenharmony_ci return; 42488c2ecf20Sopenharmony_ci /* TODO: Enable this once we have gains configured */ 42498c2ecf20Sopenharmony_ci return; 42508c2ecf20Sopenharmony_ci } 42518c2ecf20Sopenharmony_ci 42528c2ecf20Sopenharmony_ci for (i = 0; i < 128; i++) { 42538c2ecf20Sopenharmony_ci if (phy->rev >= 19) { 42548c2ecf20Sopenharmony_ci /* TODO */ 42558c2ecf20Sopenharmony_ci return; 42568c2ecf20Sopenharmony_ci } else if (phy->rev >= 7) { 42578c2ecf20Sopenharmony_ci pga_gain = (table[i] >> 24) & 0xf; 42588c2ecf20Sopenharmony_ci pad_gain = (table[i] >> 19) & 0x1f; 42598c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) 42608c2ecf20Sopenharmony_ci rfpwr_offset = rf_pwr_offset_table[pad_gain]; 42618c2ecf20Sopenharmony_ci else 42628c2ecf20Sopenharmony_ci rfpwr_offset = rf_pwr_offset_table[pga_gain]; 42638c2ecf20Sopenharmony_ci } else { 42648c2ecf20Sopenharmony_ci pga_gain = (table[i] >> 24) & 0xF; 42658c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) 42668c2ecf20Sopenharmony_ci rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain]; 42678c2ecf20Sopenharmony_ci else 42688c2ecf20Sopenharmony_ci rfpwr_offset = 0; /* FIXME */ 42698c2ecf20Sopenharmony_ci } 42708c2ecf20Sopenharmony_ci 42718c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB32(26, 576 + i), rfpwr_offset); 42728c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB32(27, 576 + i), rfpwr_offset); 42738c2ecf20Sopenharmony_ci } 42748c2ecf20Sopenharmony_ci} 42758c2ecf20Sopenharmony_ci 42768c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */ 42778c2ecf20Sopenharmony_cistatic void b43_nphy_pa_override(struct b43_wldev *dev, bool enable) 42788c2ecf20Sopenharmony_ci{ 42798c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 42808c2ecf20Sopenharmony_ci enum nl80211_band band; 42818c2ecf20Sopenharmony_ci u16 tmp; 42828c2ecf20Sopenharmony_ci 42838c2ecf20Sopenharmony_ci if (!enable) { 42848c2ecf20Sopenharmony_ci nphy->rfctrl_intc1_save = b43_phy_read(dev, 42858c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_INTC1); 42868c2ecf20Sopenharmony_ci nphy->rfctrl_intc2_save = b43_phy_read(dev, 42878c2ecf20Sopenharmony_ci B43_NPHY_RFCTL_INTC2); 42888c2ecf20Sopenharmony_ci band = b43_current_band(dev->wl); 42898c2ecf20Sopenharmony_ci if (dev->phy.rev >= 7) { 42908c2ecf20Sopenharmony_ci tmp = 0x1480; 42918c2ecf20Sopenharmony_ci } else if (dev->phy.rev >= 3) { 42928c2ecf20Sopenharmony_ci if (band == NL80211_BAND_5GHZ) 42938c2ecf20Sopenharmony_ci tmp = 0x600; 42948c2ecf20Sopenharmony_ci else 42958c2ecf20Sopenharmony_ci tmp = 0x480; 42968c2ecf20Sopenharmony_ci } else { 42978c2ecf20Sopenharmony_ci if (band == NL80211_BAND_5GHZ) 42988c2ecf20Sopenharmony_ci tmp = 0x180; 42998c2ecf20Sopenharmony_ci else 43008c2ecf20Sopenharmony_ci tmp = 0x120; 43018c2ecf20Sopenharmony_ci } 43028c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp); 43038c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp); 43048c2ecf20Sopenharmony_ci } else { 43058c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 43068c2ecf20Sopenharmony_ci nphy->rfctrl_intc1_save); 43078c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 43088c2ecf20Sopenharmony_ci nphy->rfctrl_intc2_save); 43098c2ecf20Sopenharmony_ci } 43108c2ecf20Sopenharmony_ci} 43118c2ecf20Sopenharmony_ci 43128c2ecf20Sopenharmony_ci/* 43138c2ecf20Sopenharmony_ci * TX low-pass filter bandwidth setup 43148c2ecf20Sopenharmony_ci * https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw 43158c2ecf20Sopenharmony_ci */ 43168c2ecf20Sopenharmony_cistatic void b43_nphy_tx_lpf_bw(struct b43_wldev *dev) 43178c2ecf20Sopenharmony_ci{ 43188c2ecf20Sopenharmony_ci u16 tmp; 43198c2ecf20Sopenharmony_ci 43208c2ecf20Sopenharmony_ci if (dev->phy.rev < 3 || dev->phy.rev >= 7) 43218c2ecf20Sopenharmony_ci return; 43228c2ecf20Sopenharmony_ci 43238c2ecf20Sopenharmony_ci if (b43_nphy_ipa(dev)) 43248c2ecf20Sopenharmony_ci tmp = b43_is_40mhz(dev) ? 5 : 4; 43258c2ecf20Sopenharmony_ci else 43268c2ecf20Sopenharmony_ci tmp = b43_is_40mhz(dev) ? 3 : 1; 43278c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2, 43288c2ecf20Sopenharmony_ci (tmp << 9) | (tmp << 6) | (tmp << 3) | tmp); 43298c2ecf20Sopenharmony_ci 43308c2ecf20Sopenharmony_ci if (b43_nphy_ipa(dev)) { 43318c2ecf20Sopenharmony_ci tmp = b43_is_40mhz(dev) ? 4 : 1; 43328c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S2, 43338c2ecf20Sopenharmony_ci (tmp << 9) | (tmp << 6) | (tmp << 3) | tmp); 43348c2ecf20Sopenharmony_ci } 43358c2ecf20Sopenharmony_ci} 43368c2ecf20Sopenharmony_ci 43378c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */ 43388c2ecf20Sopenharmony_cistatic void b43_nphy_rx_iq_est(struct b43_wldev *dev, struct nphy_iq_est *est, 43398c2ecf20Sopenharmony_ci u16 samps, u8 time, bool wait) 43408c2ecf20Sopenharmony_ci{ 43418c2ecf20Sopenharmony_ci int i; 43428c2ecf20Sopenharmony_ci u16 tmp; 43438c2ecf20Sopenharmony_ci 43448c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_IQEST_SAMCNT, samps); 43458c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_IQEST_WT, ~B43_NPHY_IQEST_WT_VAL, time); 43468c2ecf20Sopenharmony_ci if (wait) 43478c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_MODE); 43488c2ecf20Sopenharmony_ci else 43498c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_IQEST_CMD, ~B43_NPHY_IQEST_CMD_MODE); 43508c2ecf20Sopenharmony_ci 43518c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_START); 43528c2ecf20Sopenharmony_ci 43538c2ecf20Sopenharmony_ci for (i = 1000; i; i--) { 43548c2ecf20Sopenharmony_ci tmp = b43_phy_read(dev, B43_NPHY_IQEST_CMD); 43558c2ecf20Sopenharmony_ci if (!(tmp & B43_NPHY_IQEST_CMD_START)) { 43568c2ecf20Sopenharmony_ci est->i0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI0) << 16) | 43578c2ecf20Sopenharmony_ci b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO0); 43588c2ecf20Sopenharmony_ci est->q0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI0) << 16) | 43598c2ecf20Sopenharmony_ci b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO0); 43608c2ecf20Sopenharmony_ci est->iq0_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI0) << 16) | 43618c2ecf20Sopenharmony_ci b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO0); 43628c2ecf20Sopenharmony_ci 43638c2ecf20Sopenharmony_ci est->i1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI1) << 16) | 43648c2ecf20Sopenharmony_ci b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO1); 43658c2ecf20Sopenharmony_ci est->q1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI1) << 16) | 43668c2ecf20Sopenharmony_ci b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO1); 43678c2ecf20Sopenharmony_ci est->iq1_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI1) << 16) | 43688c2ecf20Sopenharmony_ci b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO1); 43698c2ecf20Sopenharmony_ci return; 43708c2ecf20Sopenharmony_ci } 43718c2ecf20Sopenharmony_ci udelay(10); 43728c2ecf20Sopenharmony_ci } 43738c2ecf20Sopenharmony_ci memset(est, 0, sizeof(*est)); 43748c2ecf20Sopenharmony_ci} 43758c2ecf20Sopenharmony_ci 43768c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */ 43778c2ecf20Sopenharmony_cistatic void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write, 43788c2ecf20Sopenharmony_ci struct b43_phy_n_iq_comp *pcomp) 43798c2ecf20Sopenharmony_ci{ 43808c2ecf20Sopenharmony_ci if (write) { 43818c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPA0, pcomp->a0); 43828c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPB0, pcomp->b0); 43838c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPA1, pcomp->a1); 43848c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPB1, pcomp->b1); 43858c2ecf20Sopenharmony_ci } else { 43868c2ecf20Sopenharmony_ci pcomp->a0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPA0); 43878c2ecf20Sopenharmony_ci pcomp->b0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPB0); 43888c2ecf20Sopenharmony_ci pcomp->a1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPA1); 43898c2ecf20Sopenharmony_ci pcomp->b1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPB1); 43908c2ecf20Sopenharmony_ci } 43918c2ecf20Sopenharmony_ci} 43928c2ecf20Sopenharmony_ci 43938c2ecf20Sopenharmony_ci#if 0 43948c2ecf20Sopenharmony_ci/* Ready but not used anywhere */ 43958c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */ 43968c2ecf20Sopenharmony_cistatic void b43_nphy_rx_cal_phy_cleanup(struct b43_wldev *dev, u8 core) 43978c2ecf20Sopenharmony_ci{ 43988c2ecf20Sopenharmony_ci u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs; 43998c2ecf20Sopenharmony_ci 44008c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFSEQCA, regs[0]); 44018c2ecf20Sopenharmony_ci if (core == 0) { 44028c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[1]); 44038c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]); 44048c2ecf20Sopenharmony_ci } else { 44058c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]); 44068c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]); 44078c2ecf20Sopenharmony_ci } 44088c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[3]); 44098c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[4]); 44108c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, regs[5]); 44118c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, regs[6]); 44128c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, regs[7]); 44138c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_OVER, regs[8]); 44148c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]); 44158c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]); 44168c2ecf20Sopenharmony_ci} 44178c2ecf20Sopenharmony_ci 44188c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhySetup */ 44198c2ecf20Sopenharmony_cistatic void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core) 44208c2ecf20Sopenharmony_ci{ 44218c2ecf20Sopenharmony_ci u8 rxval, txval; 44228c2ecf20Sopenharmony_ci u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs; 44238c2ecf20Sopenharmony_ci 44248c2ecf20Sopenharmony_ci regs[0] = b43_phy_read(dev, B43_NPHY_RFSEQCA); 44258c2ecf20Sopenharmony_ci if (core == 0) { 44268c2ecf20Sopenharmony_ci regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); 44278c2ecf20Sopenharmony_ci regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1); 44288c2ecf20Sopenharmony_ci } else { 44298c2ecf20Sopenharmony_ci regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); 44308c2ecf20Sopenharmony_ci regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); 44318c2ecf20Sopenharmony_ci } 44328c2ecf20Sopenharmony_ci regs[3] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); 44338c2ecf20Sopenharmony_ci regs[4] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); 44348c2ecf20Sopenharmony_ci regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1); 44358c2ecf20Sopenharmony_ci regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2); 44368c2ecf20Sopenharmony_ci regs[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S1); 44378c2ecf20Sopenharmony_ci regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER); 44388c2ecf20Sopenharmony_ci regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0); 44398c2ecf20Sopenharmony_ci regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1); 44408c2ecf20Sopenharmony_ci 44418c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001); 44428c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001); 44438c2ecf20Sopenharmony_ci 44448c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_RFSEQCA, 44458c2ecf20Sopenharmony_ci ~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF, 44468c2ecf20Sopenharmony_ci ((1 - core) << B43_NPHY_RFSEQCA_RXDIS_SHIFT)); 44478c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN, 44488c2ecf20Sopenharmony_ci ((1 - core) << B43_NPHY_RFSEQCA_TXEN_SHIFT)); 44498c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN, 44508c2ecf20Sopenharmony_ci (core << B43_NPHY_RFSEQCA_RXEN_SHIFT)); 44518c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXDIS, 44528c2ecf20Sopenharmony_ci (core << B43_NPHY_RFSEQCA_TXDIS_SHIFT)); 44538c2ecf20Sopenharmony_ci 44548c2ecf20Sopenharmony_ci if (core == 0) { 44558c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x0007); 44568c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0007); 44578c2ecf20Sopenharmony_ci } else { 44588c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x0007); 44598c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0007); 44608c2ecf20Sopenharmony_ci } 44618c2ecf20Sopenharmony_ci 44628c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA, 0, 3); 44638c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override(dev, 8, 0, 3, false); 44648c2ecf20Sopenharmony_ci b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); 44658c2ecf20Sopenharmony_ci 44668c2ecf20Sopenharmony_ci if (core == 0) { 44678c2ecf20Sopenharmony_ci rxval = 1; 44688c2ecf20Sopenharmony_ci txval = 8; 44698c2ecf20Sopenharmony_ci } else { 44708c2ecf20Sopenharmony_ci rxval = 4; 44718c2ecf20Sopenharmony_ci txval = 2; 44728c2ecf20Sopenharmony_ci } 44738c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, rxval, 44748c2ecf20Sopenharmony_ci core + 1); 44758c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, txval, 44768c2ecf20Sopenharmony_ci 2 - core); 44778c2ecf20Sopenharmony_ci} 44788c2ecf20Sopenharmony_ci#endif 44798c2ecf20Sopenharmony_ci 44808c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */ 44818c2ecf20Sopenharmony_cistatic void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask) 44828c2ecf20Sopenharmony_ci{ 44838c2ecf20Sopenharmony_ci int i; 44848c2ecf20Sopenharmony_ci s32 iq; 44858c2ecf20Sopenharmony_ci u32 ii; 44868c2ecf20Sopenharmony_ci u32 qq; 44878c2ecf20Sopenharmony_ci int iq_nbits, qq_nbits; 44888c2ecf20Sopenharmony_ci int arsh, brsh; 44898c2ecf20Sopenharmony_ci u16 tmp, a, b; 44908c2ecf20Sopenharmony_ci 44918c2ecf20Sopenharmony_ci struct nphy_iq_est est; 44928c2ecf20Sopenharmony_ci struct b43_phy_n_iq_comp old; 44938c2ecf20Sopenharmony_ci struct b43_phy_n_iq_comp new = { }; 44948c2ecf20Sopenharmony_ci bool error = false; 44958c2ecf20Sopenharmony_ci 44968c2ecf20Sopenharmony_ci if (mask == 0) 44978c2ecf20Sopenharmony_ci return; 44988c2ecf20Sopenharmony_ci 44998c2ecf20Sopenharmony_ci b43_nphy_rx_iq_coeffs(dev, false, &old); 45008c2ecf20Sopenharmony_ci b43_nphy_rx_iq_coeffs(dev, true, &new); 45018c2ecf20Sopenharmony_ci b43_nphy_rx_iq_est(dev, &est, 0x4000, 32, false); 45028c2ecf20Sopenharmony_ci new = old; 45038c2ecf20Sopenharmony_ci 45048c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 45058c2ecf20Sopenharmony_ci if (i == 0 && (mask & 1)) { 45068c2ecf20Sopenharmony_ci iq = est.iq0_prod; 45078c2ecf20Sopenharmony_ci ii = est.i0_pwr; 45088c2ecf20Sopenharmony_ci qq = est.q0_pwr; 45098c2ecf20Sopenharmony_ci } else if (i == 1 && (mask & 2)) { 45108c2ecf20Sopenharmony_ci iq = est.iq1_prod; 45118c2ecf20Sopenharmony_ci ii = est.i1_pwr; 45128c2ecf20Sopenharmony_ci qq = est.q1_pwr; 45138c2ecf20Sopenharmony_ci } else { 45148c2ecf20Sopenharmony_ci continue; 45158c2ecf20Sopenharmony_ci } 45168c2ecf20Sopenharmony_ci 45178c2ecf20Sopenharmony_ci if (ii + qq < 2) { 45188c2ecf20Sopenharmony_ci error = true; 45198c2ecf20Sopenharmony_ci break; 45208c2ecf20Sopenharmony_ci } 45218c2ecf20Sopenharmony_ci 45228c2ecf20Sopenharmony_ci iq_nbits = fls(abs(iq)); 45238c2ecf20Sopenharmony_ci qq_nbits = fls(qq); 45248c2ecf20Sopenharmony_ci 45258c2ecf20Sopenharmony_ci arsh = iq_nbits - 20; 45268c2ecf20Sopenharmony_ci if (arsh >= 0) { 45278c2ecf20Sopenharmony_ci a = -((iq << (30 - iq_nbits)) + (ii >> (1 + arsh))); 45288c2ecf20Sopenharmony_ci tmp = ii >> arsh; 45298c2ecf20Sopenharmony_ci } else { 45308c2ecf20Sopenharmony_ci a = -((iq << (30 - iq_nbits)) + (ii << (-1 - arsh))); 45318c2ecf20Sopenharmony_ci tmp = ii << -arsh; 45328c2ecf20Sopenharmony_ci } 45338c2ecf20Sopenharmony_ci if (tmp == 0) { 45348c2ecf20Sopenharmony_ci error = true; 45358c2ecf20Sopenharmony_ci break; 45368c2ecf20Sopenharmony_ci } 45378c2ecf20Sopenharmony_ci a /= tmp; 45388c2ecf20Sopenharmony_ci 45398c2ecf20Sopenharmony_ci brsh = qq_nbits - 11; 45408c2ecf20Sopenharmony_ci if (brsh >= 0) { 45418c2ecf20Sopenharmony_ci b = (qq << (31 - qq_nbits)); 45428c2ecf20Sopenharmony_ci tmp = ii >> brsh; 45438c2ecf20Sopenharmony_ci } else { 45448c2ecf20Sopenharmony_ci b = (qq << (31 - qq_nbits)); 45458c2ecf20Sopenharmony_ci tmp = ii << -brsh; 45468c2ecf20Sopenharmony_ci } 45478c2ecf20Sopenharmony_ci if (tmp == 0) { 45488c2ecf20Sopenharmony_ci error = true; 45498c2ecf20Sopenharmony_ci break; 45508c2ecf20Sopenharmony_ci } 45518c2ecf20Sopenharmony_ci b = int_sqrt(b / tmp - a * a) - (1 << 10); 45528c2ecf20Sopenharmony_ci 45538c2ecf20Sopenharmony_ci if (i == 0 && (mask & 0x1)) { 45548c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) { 45558c2ecf20Sopenharmony_ci new.a0 = a & 0x3FF; 45568c2ecf20Sopenharmony_ci new.b0 = b & 0x3FF; 45578c2ecf20Sopenharmony_ci } else { 45588c2ecf20Sopenharmony_ci new.a0 = b & 0x3FF; 45598c2ecf20Sopenharmony_ci new.b0 = a & 0x3FF; 45608c2ecf20Sopenharmony_ci } 45618c2ecf20Sopenharmony_ci } else if (i == 1 && (mask & 0x2)) { 45628c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) { 45638c2ecf20Sopenharmony_ci new.a1 = a & 0x3FF; 45648c2ecf20Sopenharmony_ci new.b1 = b & 0x3FF; 45658c2ecf20Sopenharmony_ci } else { 45668c2ecf20Sopenharmony_ci new.a1 = b & 0x3FF; 45678c2ecf20Sopenharmony_ci new.b1 = a & 0x3FF; 45688c2ecf20Sopenharmony_ci } 45698c2ecf20Sopenharmony_ci } 45708c2ecf20Sopenharmony_ci } 45718c2ecf20Sopenharmony_ci 45728c2ecf20Sopenharmony_ci if (error) 45738c2ecf20Sopenharmony_ci new = old; 45748c2ecf20Sopenharmony_ci 45758c2ecf20Sopenharmony_ci b43_nphy_rx_iq_coeffs(dev, true, &new); 45768c2ecf20Sopenharmony_ci} 45778c2ecf20Sopenharmony_ci 45788c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */ 45798c2ecf20Sopenharmony_cistatic void b43_nphy_tx_iq_workaround(struct b43_wldev *dev) 45808c2ecf20Sopenharmony_ci{ 45818c2ecf20Sopenharmony_ci u16 array[4]; 45828c2ecf20Sopenharmony_ci b43_ntab_read_bulk(dev, B43_NTAB16(0xF, 0x50), 4, array); 45838c2ecf20Sopenharmony_ci 45848c2ecf20Sopenharmony_ci b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW0, array[0]); 45858c2ecf20Sopenharmony_ci b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW1, array[1]); 45868c2ecf20Sopenharmony_ci b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW2, array[2]); 45878c2ecf20Sopenharmony_ci b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW3, array[3]); 45888c2ecf20Sopenharmony_ci} 45898c2ecf20Sopenharmony_ci 45908c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SpurWar */ 45918c2ecf20Sopenharmony_cistatic void b43_nphy_spur_workaround(struct b43_wldev *dev) 45928c2ecf20Sopenharmony_ci{ 45938c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 45948c2ecf20Sopenharmony_ci 45958c2ecf20Sopenharmony_ci u8 channel = dev->phy.channel; 45968c2ecf20Sopenharmony_ci int tone[2] = { 57, 58 }; 45978c2ecf20Sopenharmony_ci u32 noise[2] = { 0x3FF, 0x3FF }; 45988c2ecf20Sopenharmony_ci 45998c2ecf20Sopenharmony_ci B43_WARN_ON(dev->phy.rev < 3); 46008c2ecf20Sopenharmony_ci 46018c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 46028c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, 1); 46038c2ecf20Sopenharmony_ci 46048c2ecf20Sopenharmony_ci if (nphy->gband_spurwar_en) { 46058c2ecf20Sopenharmony_ci /* TODO: N PHY Adjust Analog Pfbw (7) */ 46068c2ecf20Sopenharmony_ci if (channel == 11 && b43_is_40mhz(dev)) { 46078c2ecf20Sopenharmony_ci ; /* TODO: N PHY Adjust Min Noise Var(2, tone, noise)*/ 46088c2ecf20Sopenharmony_ci } else { 46098c2ecf20Sopenharmony_ci ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/ 46108c2ecf20Sopenharmony_ci } 46118c2ecf20Sopenharmony_ci /* TODO: N PHY Adjust CRS Min Power (0x1E) */ 46128c2ecf20Sopenharmony_ci } 46138c2ecf20Sopenharmony_ci 46148c2ecf20Sopenharmony_ci if (nphy->aband_spurwar_en) { 46158c2ecf20Sopenharmony_ci if (channel == 54) { 46168c2ecf20Sopenharmony_ci tone[0] = 0x20; 46178c2ecf20Sopenharmony_ci noise[0] = 0x25F; 46188c2ecf20Sopenharmony_ci } else if (channel == 38 || channel == 102 || channel == 118) { 46198c2ecf20Sopenharmony_ci if (0 /* FIXME */) { 46208c2ecf20Sopenharmony_ci tone[0] = 0x20; 46218c2ecf20Sopenharmony_ci noise[0] = 0x21F; 46228c2ecf20Sopenharmony_ci } else { 46238c2ecf20Sopenharmony_ci tone[0] = 0; 46248c2ecf20Sopenharmony_ci noise[0] = 0; 46258c2ecf20Sopenharmony_ci } 46268c2ecf20Sopenharmony_ci } else if (channel == 134) { 46278c2ecf20Sopenharmony_ci tone[0] = 0x20; 46288c2ecf20Sopenharmony_ci noise[0] = 0x21F; 46298c2ecf20Sopenharmony_ci } else if (channel == 151) { 46308c2ecf20Sopenharmony_ci tone[0] = 0x10; 46318c2ecf20Sopenharmony_ci noise[0] = 0x23F; 46328c2ecf20Sopenharmony_ci } else if (channel == 153 || channel == 161) { 46338c2ecf20Sopenharmony_ci tone[0] = 0x30; 46348c2ecf20Sopenharmony_ci noise[0] = 0x23F; 46358c2ecf20Sopenharmony_ci } else { 46368c2ecf20Sopenharmony_ci tone[0] = 0; 46378c2ecf20Sopenharmony_ci noise[0] = 0; 46388c2ecf20Sopenharmony_ci } 46398c2ecf20Sopenharmony_ci 46408c2ecf20Sopenharmony_ci if (!tone[0] && !noise[0]) { 46418c2ecf20Sopenharmony_ci ; /* TODO: N PHY Adjust Min Noise Var(1, tone, noise)*/ 46428c2ecf20Sopenharmony_ci } else { 46438c2ecf20Sopenharmony_ci ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/ 46448c2ecf20Sopenharmony_ci } 46458c2ecf20Sopenharmony_ci } 46468c2ecf20Sopenharmony_ci 46478c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 46488c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, 0); 46498c2ecf20Sopenharmony_ci} 46508c2ecf20Sopenharmony_ci 46518c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */ 46528c2ecf20Sopenharmony_cistatic void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev) 46538c2ecf20Sopenharmony_ci{ 46548c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 46558c2ecf20Sopenharmony_ci int i, j; 46568c2ecf20Sopenharmony_ci u32 tmp; 46578c2ecf20Sopenharmony_ci u32 cur_real, cur_imag, real_part, imag_part; 46588c2ecf20Sopenharmony_ci 46598c2ecf20Sopenharmony_ci u16 buffer[7]; 46608c2ecf20Sopenharmony_ci 46618c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 46628c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, true); 46638c2ecf20Sopenharmony_ci 46648c2ecf20Sopenharmony_ci b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer); 46658c2ecf20Sopenharmony_ci 46668c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 46678c2ecf20Sopenharmony_ci tmp = ((buffer[i * 2] & 0x3FF) << 10) | 46688c2ecf20Sopenharmony_ci (buffer[i * 2 + 1] & 0x3FF); 46698c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 46708c2ecf20Sopenharmony_ci (((i + 26) << 10) | 320)); 46718c2ecf20Sopenharmony_ci for (j = 0; j < 128; j++) { 46728c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_DATAHI, 46738c2ecf20Sopenharmony_ci ((tmp >> 16) & 0xFFFF)); 46748c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 46758c2ecf20Sopenharmony_ci (tmp & 0xFFFF)); 46768c2ecf20Sopenharmony_ci } 46778c2ecf20Sopenharmony_ci } 46788c2ecf20Sopenharmony_ci 46798c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 46808c2ecf20Sopenharmony_ci tmp = buffer[5 + i]; 46818c2ecf20Sopenharmony_ci real_part = (tmp >> 8) & 0xFF; 46828c2ecf20Sopenharmony_ci imag_part = (tmp & 0xFF); 46838c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 46848c2ecf20Sopenharmony_ci (((i + 26) << 10) | 448)); 46858c2ecf20Sopenharmony_ci 46868c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) { 46878c2ecf20Sopenharmony_ci cur_real = real_part; 46888c2ecf20Sopenharmony_ci cur_imag = imag_part; 46898c2ecf20Sopenharmony_ci tmp = ((cur_real & 0xFF) << 8) | (cur_imag & 0xFF); 46908c2ecf20Sopenharmony_ci } 46918c2ecf20Sopenharmony_ci 46928c2ecf20Sopenharmony_ci for (j = 0; j < 128; j++) { 46938c2ecf20Sopenharmony_ci if (dev->phy.rev < 3) { 46948c2ecf20Sopenharmony_ci cur_real = (real_part * loscale[j] + 128) >> 8; 46958c2ecf20Sopenharmony_ci cur_imag = (imag_part * loscale[j] + 128) >> 8; 46968c2ecf20Sopenharmony_ci tmp = ((cur_real & 0xFF) << 8) | 46978c2ecf20Sopenharmony_ci (cur_imag & 0xFF); 46988c2ecf20Sopenharmony_ci } 46998c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_DATAHI, 47008c2ecf20Sopenharmony_ci ((tmp >> 16) & 0xFFFF)); 47018c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 47028c2ecf20Sopenharmony_ci (tmp & 0xFFFF)); 47038c2ecf20Sopenharmony_ci } 47048c2ecf20Sopenharmony_ci } 47058c2ecf20Sopenharmony_ci 47068c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) { 47078c2ecf20Sopenharmony_ci b43_shm_write16(dev, B43_SHM_SHARED, 47088c2ecf20Sopenharmony_ci B43_SHM_SH_NPHY_TXPWR_INDX0, 0xFFFF); 47098c2ecf20Sopenharmony_ci b43_shm_write16(dev, B43_SHM_SHARED, 47108c2ecf20Sopenharmony_ci B43_SHM_SH_NPHY_TXPWR_INDX1, 0xFFFF); 47118c2ecf20Sopenharmony_ci } 47128c2ecf20Sopenharmony_ci 47138c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 47148c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, false); 47158c2ecf20Sopenharmony_ci} 47168c2ecf20Sopenharmony_ci 47178c2ecf20Sopenharmony_ci/* 47188c2ecf20Sopenharmony_ci * Restore RSSI Calibration 47198c2ecf20Sopenharmony_ci * https://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal 47208c2ecf20Sopenharmony_ci */ 47218c2ecf20Sopenharmony_cistatic void b43_nphy_restore_rssi_cal(struct b43_wldev *dev) 47228c2ecf20Sopenharmony_ci{ 47238c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 47248c2ecf20Sopenharmony_ci 47258c2ecf20Sopenharmony_ci u16 *rssical_radio_regs = NULL; 47268c2ecf20Sopenharmony_ci u16 *rssical_phy_regs = NULL; 47278c2ecf20Sopenharmony_ci 47288c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { 47298c2ecf20Sopenharmony_ci if (!nphy->rssical_chanspec_2G.center_freq) 47308c2ecf20Sopenharmony_ci return; 47318c2ecf20Sopenharmony_ci rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G; 47328c2ecf20Sopenharmony_ci rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G; 47338c2ecf20Sopenharmony_ci } else { 47348c2ecf20Sopenharmony_ci if (!nphy->rssical_chanspec_5G.center_freq) 47358c2ecf20Sopenharmony_ci return; 47368c2ecf20Sopenharmony_ci rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G; 47378c2ecf20Sopenharmony_ci rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; 47388c2ecf20Sopenharmony_ci } 47398c2ecf20Sopenharmony_ci 47408c2ecf20Sopenharmony_ci if (dev->phy.rev >= 19) { 47418c2ecf20Sopenharmony_ci /* TODO */ 47428c2ecf20Sopenharmony_ci } else if (dev->phy.rev >= 7) { 47438c2ecf20Sopenharmony_ci b43_radio_maskset(dev, R2057_NB_MASTER_CORE0, ~R2057_VCM_MASK, 47448c2ecf20Sopenharmony_ci rssical_radio_regs[0]); 47458c2ecf20Sopenharmony_ci b43_radio_maskset(dev, R2057_NB_MASTER_CORE1, ~R2057_VCM_MASK, 47468c2ecf20Sopenharmony_ci rssical_radio_regs[1]); 47478c2ecf20Sopenharmony_ci } else { 47488c2ecf20Sopenharmony_ci b43_radio_maskset(dev, B2056_RX0 | B2056_RX_RSSI_MISC, 0xE3, 47498c2ecf20Sopenharmony_ci rssical_radio_regs[0]); 47508c2ecf20Sopenharmony_ci b43_radio_maskset(dev, B2056_RX1 | B2056_RX_RSSI_MISC, 0xE3, 47518c2ecf20Sopenharmony_ci rssical_radio_regs[1]); 47528c2ecf20Sopenharmony_ci } 47538c2ecf20Sopenharmony_ci 47548c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, rssical_phy_regs[0]); 47558c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, rssical_phy_regs[1]); 47568c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, rssical_phy_regs[2]); 47578c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, rssical_phy_regs[3]); 47588c2ecf20Sopenharmony_ci 47598c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, rssical_phy_regs[4]); 47608c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, rssical_phy_regs[5]); 47618c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, rssical_phy_regs[6]); 47628c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, rssical_phy_regs[7]); 47638c2ecf20Sopenharmony_ci 47648c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, rssical_phy_regs[8]); 47658c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, rssical_phy_regs[9]); 47668c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, rssical_phy_regs[10]); 47678c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]); 47688c2ecf20Sopenharmony_ci} 47698c2ecf20Sopenharmony_ci 47708c2ecf20Sopenharmony_cistatic void b43_nphy_tx_cal_radio_setup_rev19(struct b43_wldev *dev) 47718c2ecf20Sopenharmony_ci{ 47728c2ecf20Sopenharmony_ci /* TODO */ 47738c2ecf20Sopenharmony_ci} 47748c2ecf20Sopenharmony_ci 47758c2ecf20Sopenharmony_cistatic void b43_nphy_tx_cal_radio_setup_rev7(struct b43_wldev *dev) 47768c2ecf20Sopenharmony_ci{ 47778c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 47788c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 47798c2ecf20Sopenharmony_ci u16 *save = nphy->tx_rx_cal_radio_saveregs; 47808c2ecf20Sopenharmony_ci int core, off; 47818c2ecf20Sopenharmony_ci u16 r, tmp; 47828c2ecf20Sopenharmony_ci 47838c2ecf20Sopenharmony_ci for (core = 0; core < 2; core++) { 47848c2ecf20Sopenharmony_ci r = core ? 0x20 : 0; 47858c2ecf20Sopenharmony_ci off = core * 11; 47868c2ecf20Sopenharmony_ci 47878c2ecf20Sopenharmony_ci save[off + 0] = b43_radio_read(dev, r + R2057_TX0_TX_SSI_MASTER); 47888c2ecf20Sopenharmony_ci save[off + 1] = b43_radio_read(dev, r + R2057_TX0_IQCAL_VCM_HG); 47898c2ecf20Sopenharmony_ci save[off + 2] = b43_radio_read(dev, r + R2057_TX0_IQCAL_IDAC); 47908c2ecf20Sopenharmony_ci save[off + 3] = b43_radio_read(dev, r + R2057_TX0_TSSI_VCM); 47918c2ecf20Sopenharmony_ci save[off + 4] = 0; 47928c2ecf20Sopenharmony_ci save[off + 5] = b43_radio_read(dev, r + R2057_TX0_TX_SSI_MUX); 47938c2ecf20Sopenharmony_ci if (phy->radio_rev != 5) 47948c2ecf20Sopenharmony_ci save[off + 6] = b43_radio_read(dev, r + R2057_TX0_TSSIA); 47958c2ecf20Sopenharmony_ci save[off + 7] = b43_radio_read(dev, r + R2057_TX0_TSSIG); 47968c2ecf20Sopenharmony_ci save[off + 8] = b43_radio_read(dev, r + R2057_TX0_TSSI_MISC1); 47978c2ecf20Sopenharmony_ci 47988c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { 47998c2ecf20Sopenharmony_ci b43_radio_write(dev, r + R2057_TX0_TX_SSI_MASTER, 0xA); 48008c2ecf20Sopenharmony_ci b43_radio_write(dev, r + R2057_TX0_IQCAL_VCM_HG, 0x43); 48018c2ecf20Sopenharmony_ci b43_radio_write(dev, r + R2057_TX0_IQCAL_IDAC, 0x55); 48028c2ecf20Sopenharmony_ci b43_radio_write(dev, r + R2057_TX0_TSSI_VCM, 0); 48038c2ecf20Sopenharmony_ci b43_radio_write(dev, r + R2057_TX0_TSSIG, 0); 48048c2ecf20Sopenharmony_ci if (nphy->use_int_tx_iq_lo_cal) { 48058c2ecf20Sopenharmony_ci b43_radio_write(dev, r + R2057_TX0_TX_SSI_MUX, 0x4); 48068c2ecf20Sopenharmony_ci tmp = true ? 0x31 : 0x21; /* TODO */ 48078c2ecf20Sopenharmony_ci b43_radio_write(dev, r + R2057_TX0_TSSIA, tmp); 48088c2ecf20Sopenharmony_ci } 48098c2ecf20Sopenharmony_ci b43_radio_write(dev, r + R2057_TX0_TSSI_MISC1, 0x00); 48108c2ecf20Sopenharmony_ci } else { 48118c2ecf20Sopenharmony_ci b43_radio_write(dev, r + R2057_TX0_TX_SSI_MASTER, 0x6); 48128c2ecf20Sopenharmony_ci b43_radio_write(dev, r + R2057_TX0_IQCAL_VCM_HG, 0x43); 48138c2ecf20Sopenharmony_ci b43_radio_write(dev, r + R2057_TX0_IQCAL_IDAC, 0x55); 48148c2ecf20Sopenharmony_ci b43_radio_write(dev, r + R2057_TX0_TSSI_VCM, 0); 48158c2ecf20Sopenharmony_ci 48168c2ecf20Sopenharmony_ci if (phy->radio_rev != 5) 48178c2ecf20Sopenharmony_ci b43_radio_write(dev, r + R2057_TX0_TSSIA, 0); 48188c2ecf20Sopenharmony_ci if (nphy->use_int_tx_iq_lo_cal) { 48198c2ecf20Sopenharmony_ci b43_radio_write(dev, r + R2057_TX0_TX_SSI_MUX, 0x6); 48208c2ecf20Sopenharmony_ci tmp = true ? 0x31 : 0x21; /* TODO */ 48218c2ecf20Sopenharmony_ci b43_radio_write(dev, r + R2057_TX0_TSSIG, tmp); 48228c2ecf20Sopenharmony_ci } 48238c2ecf20Sopenharmony_ci b43_radio_write(dev, r + R2057_TX0_TSSI_MISC1, 0); 48248c2ecf20Sopenharmony_ci } 48258c2ecf20Sopenharmony_ci } 48268c2ecf20Sopenharmony_ci} 48278c2ecf20Sopenharmony_ci 48288c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */ 48298c2ecf20Sopenharmony_cistatic void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev) 48308c2ecf20Sopenharmony_ci{ 48318c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 48328c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 48338c2ecf20Sopenharmony_ci u16 *save = nphy->tx_rx_cal_radio_saveregs; 48348c2ecf20Sopenharmony_ci u16 tmp; 48358c2ecf20Sopenharmony_ci u8 offset, i; 48368c2ecf20Sopenharmony_ci 48378c2ecf20Sopenharmony_ci if (phy->rev >= 19) { 48388c2ecf20Sopenharmony_ci b43_nphy_tx_cal_radio_setup_rev19(dev); 48398c2ecf20Sopenharmony_ci } else if (phy->rev >= 7) { 48408c2ecf20Sopenharmony_ci b43_nphy_tx_cal_radio_setup_rev7(dev); 48418c2ecf20Sopenharmony_ci } else if (phy->rev >= 3) { 48428c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 48438c2ecf20Sopenharmony_ci tmp = (i == 0) ? 0x2000 : 0x3000; 48448c2ecf20Sopenharmony_ci offset = i * 11; 48458c2ecf20Sopenharmony_ci 48468c2ecf20Sopenharmony_ci save[offset + 0] = b43_radio_read(dev, B2055_CAL_RVARCTL); 48478c2ecf20Sopenharmony_ci save[offset + 1] = b43_radio_read(dev, B2055_CAL_LPOCTL); 48488c2ecf20Sopenharmony_ci save[offset + 2] = b43_radio_read(dev, B2055_CAL_TS); 48498c2ecf20Sopenharmony_ci save[offset + 3] = b43_radio_read(dev, B2055_CAL_RCCALRTS); 48508c2ecf20Sopenharmony_ci save[offset + 4] = b43_radio_read(dev, B2055_CAL_RCALRTS); 48518c2ecf20Sopenharmony_ci save[offset + 5] = b43_radio_read(dev, B2055_PADDRV); 48528c2ecf20Sopenharmony_ci save[offset + 6] = b43_radio_read(dev, B2055_XOCTL1); 48538c2ecf20Sopenharmony_ci save[offset + 7] = b43_radio_read(dev, B2055_XOCTL2); 48548c2ecf20Sopenharmony_ci save[offset + 8] = b43_radio_read(dev, B2055_XOREGUL); 48558c2ecf20Sopenharmony_ci save[offset + 9] = b43_radio_read(dev, B2055_XOMISC); 48568c2ecf20Sopenharmony_ci save[offset + 10] = b43_radio_read(dev, B2055_PLL_LFC1); 48578c2ecf20Sopenharmony_ci 48588c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { 48598c2ecf20Sopenharmony_ci b43_radio_write(dev, tmp | B2055_CAL_RVARCTL, 0x0A); 48608c2ecf20Sopenharmony_ci b43_radio_write(dev, tmp | B2055_CAL_LPOCTL, 0x40); 48618c2ecf20Sopenharmony_ci b43_radio_write(dev, tmp | B2055_CAL_TS, 0x55); 48628c2ecf20Sopenharmony_ci b43_radio_write(dev, tmp | B2055_CAL_RCCALRTS, 0); 48638c2ecf20Sopenharmony_ci b43_radio_write(dev, tmp | B2055_CAL_RCALRTS, 0); 48648c2ecf20Sopenharmony_ci if (nphy->ipa5g_on) { 48658c2ecf20Sopenharmony_ci b43_radio_write(dev, tmp | B2055_PADDRV, 4); 48668c2ecf20Sopenharmony_ci b43_radio_write(dev, tmp | B2055_XOCTL1, 1); 48678c2ecf20Sopenharmony_ci } else { 48688c2ecf20Sopenharmony_ci b43_radio_write(dev, tmp | B2055_PADDRV, 0); 48698c2ecf20Sopenharmony_ci b43_radio_write(dev, tmp | B2055_XOCTL1, 0x2F); 48708c2ecf20Sopenharmony_ci } 48718c2ecf20Sopenharmony_ci b43_radio_write(dev, tmp | B2055_XOCTL2, 0); 48728c2ecf20Sopenharmony_ci } else { 48738c2ecf20Sopenharmony_ci b43_radio_write(dev, tmp | B2055_CAL_RVARCTL, 0x06); 48748c2ecf20Sopenharmony_ci b43_radio_write(dev, tmp | B2055_CAL_LPOCTL, 0x40); 48758c2ecf20Sopenharmony_ci b43_radio_write(dev, tmp | B2055_CAL_TS, 0x55); 48768c2ecf20Sopenharmony_ci b43_radio_write(dev, tmp | B2055_CAL_RCCALRTS, 0); 48778c2ecf20Sopenharmony_ci b43_radio_write(dev, tmp | B2055_CAL_RCALRTS, 0); 48788c2ecf20Sopenharmony_ci b43_radio_write(dev, tmp | B2055_XOCTL1, 0); 48798c2ecf20Sopenharmony_ci if (nphy->ipa2g_on) { 48808c2ecf20Sopenharmony_ci b43_radio_write(dev, tmp | B2055_PADDRV, 6); 48818c2ecf20Sopenharmony_ci b43_radio_write(dev, tmp | B2055_XOCTL2, 48828c2ecf20Sopenharmony_ci (dev->phy.rev < 5) ? 0x11 : 0x01); 48838c2ecf20Sopenharmony_ci } else { 48848c2ecf20Sopenharmony_ci b43_radio_write(dev, tmp | B2055_PADDRV, 0); 48858c2ecf20Sopenharmony_ci b43_radio_write(dev, tmp | B2055_XOCTL2, 0); 48868c2ecf20Sopenharmony_ci } 48878c2ecf20Sopenharmony_ci } 48888c2ecf20Sopenharmony_ci b43_radio_write(dev, tmp | B2055_XOREGUL, 0); 48898c2ecf20Sopenharmony_ci b43_radio_write(dev, tmp | B2055_XOMISC, 0); 48908c2ecf20Sopenharmony_ci b43_radio_write(dev, tmp | B2055_PLL_LFC1, 0); 48918c2ecf20Sopenharmony_ci } 48928c2ecf20Sopenharmony_ci } else { 48938c2ecf20Sopenharmony_ci save[0] = b43_radio_read(dev, B2055_C1_TX_RF_IQCAL1); 48948c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C1_TX_RF_IQCAL1, 0x29); 48958c2ecf20Sopenharmony_ci 48968c2ecf20Sopenharmony_ci save[1] = b43_radio_read(dev, B2055_C1_TX_RF_IQCAL2); 48978c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C1_TX_RF_IQCAL2, 0x54); 48988c2ecf20Sopenharmony_ci 48998c2ecf20Sopenharmony_ci save[2] = b43_radio_read(dev, B2055_C2_TX_RF_IQCAL1); 49008c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C2_TX_RF_IQCAL1, 0x29); 49018c2ecf20Sopenharmony_ci 49028c2ecf20Sopenharmony_ci save[3] = b43_radio_read(dev, B2055_C2_TX_RF_IQCAL2); 49038c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C2_TX_RF_IQCAL2, 0x54); 49048c2ecf20Sopenharmony_ci 49058c2ecf20Sopenharmony_ci save[3] = b43_radio_read(dev, B2055_C1_PWRDET_RXTX); 49068c2ecf20Sopenharmony_ci save[4] = b43_radio_read(dev, B2055_C2_PWRDET_RXTX); 49078c2ecf20Sopenharmony_ci 49088c2ecf20Sopenharmony_ci if (!(b43_phy_read(dev, B43_NPHY_BANDCTL) & 49098c2ecf20Sopenharmony_ci B43_NPHY_BANDCTL_5GHZ)) { 49108c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C1_PWRDET_RXTX, 0x04); 49118c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C2_PWRDET_RXTX, 0x04); 49128c2ecf20Sopenharmony_ci } else { 49138c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C1_PWRDET_RXTX, 0x20); 49148c2ecf20Sopenharmony_ci b43_radio_write(dev, B2055_C2_PWRDET_RXTX, 0x20); 49158c2ecf20Sopenharmony_ci } 49168c2ecf20Sopenharmony_ci 49178c2ecf20Sopenharmony_ci if (dev->phy.rev < 2) { 49188c2ecf20Sopenharmony_ci b43_radio_set(dev, B2055_C1_TX_BB_MXGM, 0x20); 49198c2ecf20Sopenharmony_ci b43_radio_set(dev, B2055_C2_TX_BB_MXGM, 0x20); 49208c2ecf20Sopenharmony_ci } else { 49218c2ecf20Sopenharmony_ci b43_radio_mask(dev, B2055_C1_TX_BB_MXGM, ~0x20); 49228c2ecf20Sopenharmony_ci b43_radio_mask(dev, B2055_C2_TX_BB_MXGM, ~0x20); 49238c2ecf20Sopenharmony_ci } 49248c2ecf20Sopenharmony_ci } 49258c2ecf20Sopenharmony_ci} 49268c2ecf20Sopenharmony_ci 49278c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */ 49288c2ecf20Sopenharmony_cistatic void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core) 49298c2ecf20Sopenharmony_ci{ 49308c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 49318c2ecf20Sopenharmony_ci int i; 49328c2ecf20Sopenharmony_ci u16 scale, entry; 49338c2ecf20Sopenharmony_ci 49348c2ecf20Sopenharmony_ci u16 tmp = nphy->txcal_bbmult; 49358c2ecf20Sopenharmony_ci if (core == 0) 49368c2ecf20Sopenharmony_ci tmp >>= 8; 49378c2ecf20Sopenharmony_ci tmp &= 0xff; 49388c2ecf20Sopenharmony_ci 49398c2ecf20Sopenharmony_ci for (i = 0; i < 18; i++) { 49408c2ecf20Sopenharmony_ci scale = (ladder_lo[i].percent * tmp) / 100; 49418c2ecf20Sopenharmony_ci entry = ((scale & 0xFF) << 8) | ladder_lo[i].g_env; 49428c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(15, i), entry); 49438c2ecf20Sopenharmony_ci 49448c2ecf20Sopenharmony_ci scale = (ladder_iq[i].percent * tmp) / 100; 49458c2ecf20Sopenharmony_ci entry = ((scale & 0xFF) << 8) | ladder_iq[i].g_env; 49468c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(15, i + 32), entry); 49478c2ecf20Sopenharmony_ci } 49488c2ecf20Sopenharmony_ci} 49498c2ecf20Sopenharmony_ci 49508c2ecf20Sopenharmony_cistatic void b43_nphy_pa_set_tx_dig_filter(struct b43_wldev *dev, u16 offset, 49518c2ecf20Sopenharmony_ci const s16 *filter) 49528c2ecf20Sopenharmony_ci{ 49538c2ecf20Sopenharmony_ci int i; 49548c2ecf20Sopenharmony_ci 49558c2ecf20Sopenharmony_ci offset = B43_PHY_N(offset); 49568c2ecf20Sopenharmony_ci 49578c2ecf20Sopenharmony_ci for (i = 0; i < 15; i++, offset++) 49588c2ecf20Sopenharmony_ci b43_phy_write(dev, offset, filter[i]); 49598c2ecf20Sopenharmony_ci} 49608c2ecf20Sopenharmony_ci 49618c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */ 49628c2ecf20Sopenharmony_cistatic void b43_nphy_ext_pa_set_tx_dig_filters(struct b43_wldev *dev) 49638c2ecf20Sopenharmony_ci{ 49648c2ecf20Sopenharmony_ci b43_nphy_pa_set_tx_dig_filter(dev, 0x2C5, 49658c2ecf20Sopenharmony_ci tbl_tx_filter_coef_rev4[2]); 49668c2ecf20Sopenharmony_ci} 49678c2ecf20Sopenharmony_ci 49688c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */ 49698c2ecf20Sopenharmony_cistatic void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev) 49708c2ecf20Sopenharmony_ci{ 49718c2ecf20Sopenharmony_ci /* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */ 49728c2ecf20Sopenharmony_ci static const u16 offset[] = { 0x186, 0x195, 0x2C5 }; 49738c2ecf20Sopenharmony_ci static const s16 dig_filter_phy_rev16[] = { 49748c2ecf20Sopenharmony_ci -375, 136, -407, 208, -1527, 49758c2ecf20Sopenharmony_ci 956, 93, 186, 93, 230, 49768c2ecf20Sopenharmony_ci -44, 230, 201, -191, 201, 49778c2ecf20Sopenharmony_ci }; 49788c2ecf20Sopenharmony_ci int i; 49798c2ecf20Sopenharmony_ci 49808c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) 49818c2ecf20Sopenharmony_ci b43_nphy_pa_set_tx_dig_filter(dev, offset[i], 49828c2ecf20Sopenharmony_ci tbl_tx_filter_coef_rev4[i]); 49838c2ecf20Sopenharmony_ci 49848c2ecf20Sopenharmony_ci /* Verified with BCM43227 and BCM43228 */ 49858c2ecf20Sopenharmony_ci if (dev->phy.rev == 16) 49868c2ecf20Sopenharmony_ci b43_nphy_pa_set_tx_dig_filter(dev, 0x186, dig_filter_phy_rev16); 49878c2ecf20Sopenharmony_ci 49888c2ecf20Sopenharmony_ci /* Verified with BCM43131 and BCM43217 */ 49898c2ecf20Sopenharmony_ci if (dev->phy.rev == 17) { 49908c2ecf20Sopenharmony_ci b43_nphy_pa_set_tx_dig_filter(dev, 0x186, dig_filter_phy_rev16); 49918c2ecf20Sopenharmony_ci b43_nphy_pa_set_tx_dig_filter(dev, 0x195, 49928c2ecf20Sopenharmony_ci tbl_tx_filter_coef_rev4[1]); 49938c2ecf20Sopenharmony_ci } 49948c2ecf20Sopenharmony_ci 49958c2ecf20Sopenharmony_ci if (b43_is_40mhz(dev)) { 49968c2ecf20Sopenharmony_ci b43_nphy_pa_set_tx_dig_filter(dev, 0x186, 49978c2ecf20Sopenharmony_ci tbl_tx_filter_coef_rev4[3]); 49988c2ecf20Sopenharmony_ci } else { 49998c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) 50008c2ecf20Sopenharmony_ci b43_nphy_pa_set_tx_dig_filter(dev, 0x186, 50018c2ecf20Sopenharmony_ci tbl_tx_filter_coef_rev4[5]); 50028c2ecf20Sopenharmony_ci if (dev->phy.channel == 14) 50038c2ecf20Sopenharmony_ci b43_nphy_pa_set_tx_dig_filter(dev, 0x186, 50048c2ecf20Sopenharmony_ci tbl_tx_filter_coef_rev4[6]); 50058c2ecf20Sopenharmony_ci } 50068c2ecf20Sopenharmony_ci} 50078c2ecf20Sopenharmony_ci 50088c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */ 50098c2ecf20Sopenharmony_cistatic struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev) 50108c2ecf20Sopenharmony_ci{ 50118c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 50128c2ecf20Sopenharmony_ci 50138c2ecf20Sopenharmony_ci u16 curr_gain[2]; 50148c2ecf20Sopenharmony_ci struct nphy_txgains target; 50158c2ecf20Sopenharmony_ci const u32 *table = NULL; 50168c2ecf20Sopenharmony_ci 50178c2ecf20Sopenharmony_ci if (!nphy->txpwrctrl) { 50188c2ecf20Sopenharmony_ci int i; 50198c2ecf20Sopenharmony_ci 50208c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 50218c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, true); 50228c2ecf20Sopenharmony_ci b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, curr_gain); 50238c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 50248c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, false); 50258c2ecf20Sopenharmony_ci 50268c2ecf20Sopenharmony_ci for (i = 0; i < 2; ++i) { 50278c2ecf20Sopenharmony_ci if (dev->phy.rev >= 7) { 50288c2ecf20Sopenharmony_ci target.ipa[i] = curr_gain[i] & 0x0007; 50298c2ecf20Sopenharmony_ci target.pad[i] = (curr_gain[i] & 0x00F8) >> 3; 50308c2ecf20Sopenharmony_ci target.pga[i] = (curr_gain[i] & 0x0F00) >> 8; 50318c2ecf20Sopenharmony_ci target.txgm[i] = (curr_gain[i] & 0x7000) >> 12; 50328c2ecf20Sopenharmony_ci target.tx_lpf[i] = (curr_gain[i] & 0x8000) >> 15; 50338c2ecf20Sopenharmony_ci } else if (dev->phy.rev >= 3) { 50348c2ecf20Sopenharmony_ci target.ipa[i] = curr_gain[i] & 0x000F; 50358c2ecf20Sopenharmony_ci target.pad[i] = (curr_gain[i] & 0x00F0) >> 4; 50368c2ecf20Sopenharmony_ci target.pga[i] = (curr_gain[i] & 0x0F00) >> 8; 50378c2ecf20Sopenharmony_ci target.txgm[i] = (curr_gain[i] & 0x7000) >> 12; 50388c2ecf20Sopenharmony_ci } else { 50398c2ecf20Sopenharmony_ci target.ipa[i] = curr_gain[i] & 0x0003; 50408c2ecf20Sopenharmony_ci target.pad[i] = (curr_gain[i] & 0x000C) >> 2; 50418c2ecf20Sopenharmony_ci target.pga[i] = (curr_gain[i] & 0x0070) >> 4; 50428c2ecf20Sopenharmony_ci target.txgm[i] = (curr_gain[i] & 0x0380) >> 7; 50438c2ecf20Sopenharmony_ci } 50448c2ecf20Sopenharmony_ci } 50458c2ecf20Sopenharmony_ci } else { 50468c2ecf20Sopenharmony_ci int i; 50478c2ecf20Sopenharmony_ci u16 index[2]; 50488c2ecf20Sopenharmony_ci index[0] = (b43_phy_read(dev, B43_NPHY_C1_TXPCTL_STAT) & 50498c2ecf20Sopenharmony_ci B43_NPHY_TXPCTL_STAT_BIDX) >> 50508c2ecf20Sopenharmony_ci B43_NPHY_TXPCTL_STAT_BIDX_SHIFT; 50518c2ecf20Sopenharmony_ci index[1] = (b43_phy_read(dev, B43_NPHY_C2_TXPCTL_STAT) & 50528c2ecf20Sopenharmony_ci B43_NPHY_TXPCTL_STAT_BIDX) >> 50538c2ecf20Sopenharmony_ci B43_NPHY_TXPCTL_STAT_BIDX_SHIFT; 50548c2ecf20Sopenharmony_ci 50558c2ecf20Sopenharmony_ci for (i = 0; i < 2; ++i) { 50568c2ecf20Sopenharmony_ci table = b43_nphy_get_tx_gain_table(dev); 50578c2ecf20Sopenharmony_ci if (!table) 50588c2ecf20Sopenharmony_ci break; 50598c2ecf20Sopenharmony_ci 50608c2ecf20Sopenharmony_ci if (dev->phy.rev >= 7) { 50618c2ecf20Sopenharmony_ci target.ipa[i] = (table[index[i]] >> 16) & 0x7; 50628c2ecf20Sopenharmony_ci target.pad[i] = (table[index[i]] >> 19) & 0x1F; 50638c2ecf20Sopenharmony_ci target.pga[i] = (table[index[i]] >> 24) & 0xF; 50648c2ecf20Sopenharmony_ci target.txgm[i] = (table[index[i]] >> 28) & 0x7; 50658c2ecf20Sopenharmony_ci target.tx_lpf[i] = (table[index[i]] >> 31) & 0x1; 50668c2ecf20Sopenharmony_ci } else if (dev->phy.rev >= 3) { 50678c2ecf20Sopenharmony_ci target.ipa[i] = (table[index[i]] >> 16) & 0xF; 50688c2ecf20Sopenharmony_ci target.pad[i] = (table[index[i]] >> 20) & 0xF; 50698c2ecf20Sopenharmony_ci target.pga[i] = (table[index[i]] >> 24) & 0xF; 50708c2ecf20Sopenharmony_ci target.txgm[i] = (table[index[i]] >> 28) & 0xF; 50718c2ecf20Sopenharmony_ci } else { 50728c2ecf20Sopenharmony_ci target.ipa[i] = (table[index[i]] >> 16) & 0x3; 50738c2ecf20Sopenharmony_ci target.pad[i] = (table[index[i]] >> 18) & 0x3; 50748c2ecf20Sopenharmony_ci target.pga[i] = (table[index[i]] >> 20) & 0x7; 50758c2ecf20Sopenharmony_ci target.txgm[i] = (table[index[i]] >> 23) & 0x7; 50768c2ecf20Sopenharmony_ci } 50778c2ecf20Sopenharmony_ci } 50788c2ecf20Sopenharmony_ci } 50798c2ecf20Sopenharmony_ci 50808c2ecf20Sopenharmony_ci return target; 50818c2ecf20Sopenharmony_ci} 50828c2ecf20Sopenharmony_ci 50838c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhyCleanup */ 50848c2ecf20Sopenharmony_cistatic void b43_nphy_tx_cal_phy_cleanup(struct b43_wldev *dev) 50858c2ecf20Sopenharmony_ci{ 50868c2ecf20Sopenharmony_ci u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs; 50878c2ecf20Sopenharmony_ci 50888c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) { 50898c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[0]); 50908c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]); 50918c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]); 50928c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[3]); 50938c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_BBCFG, regs[4]); 50948c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 3), regs[5]); 50958c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 19), regs[6]); 50968c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[7]); 50978c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[8]); 50988c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]); 50998c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]); 51008c2ecf20Sopenharmony_ci b43_nphy_reset_cca(dev); 51018c2ecf20Sopenharmony_ci } else { 51028c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, regs[0]); 51038c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, regs[1]); 51048c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]); 51058c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 2), regs[3]); 51068c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 18), regs[4]); 51078c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[5]); 51088c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[6]); 51098c2ecf20Sopenharmony_ci } 51108c2ecf20Sopenharmony_ci} 51118c2ecf20Sopenharmony_ci 51128c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */ 51138c2ecf20Sopenharmony_cistatic void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev) 51148c2ecf20Sopenharmony_ci{ 51158c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 51168c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 51178c2ecf20Sopenharmony_ci u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs; 51188c2ecf20Sopenharmony_ci u16 tmp; 51198c2ecf20Sopenharmony_ci 51208c2ecf20Sopenharmony_ci regs[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); 51218c2ecf20Sopenharmony_ci regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); 51228c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) { 51238c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0xF0FF, 0x0A00); 51248c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0xF0FF, 0x0A00); 51258c2ecf20Sopenharmony_ci 51268c2ecf20Sopenharmony_ci tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1); 51278c2ecf20Sopenharmony_ci regs[2] = tmp; 51288c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, tmp | 0x0600); 51298c2ecf20Sopenharmony_ci 51308c2ecf20Sopenharmony_ci tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); 51318c2ecf20Sopenharmony_ci regs[3] = tmp; 51328c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x0600); 51338c2ecf20Sopenharmony_ci 51348c2ecf20Sopenharmony_ci regs[4] = b43_phy_read(dev, B43_NPHY_BBCFG); 51358c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_BBCFG, 51368c2ecf20Sopenharmony_ci ~B43_NPHY_BBCFG_RSTRX & 0xFFFF); 51378c2ecf20Sopenharmony_ci 51388c2ecf20Sopenharmony_ci tmp = b43_ntab_read(dev, B43_NTAB16(8, 3)); 51398c2ecf20Sopenharmony_ci regs[5] = tmp; 51408c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 3), 0); 51418c2ecf20Sopenharmony_ci 51428c2ecf20Sopenharmony_ci tmp = b43_ntab_read(dev, B43_NTAB16(8, 19)); 51438c2ecf20Sopenharmony_ci regs[6] = tmp; 51448c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 19), 0); 51458c2ecf20Sopenharmony_ci regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); 51468c2ecf20Sopenharmony_ci regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); 51478c2ecf20Sopenharmony_ci 51488c2ecf20Sopenharmony_ci if (!nphy->use_int_tx_iq_lo_cal) 51498c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA, 51508c2ecf20Sopenharmony_ci 1, 3); 51518c2ecf20Sopenharmony_ci else 51528c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_PA, 51538c2ecf20Sopenharmony_ci 0, 3); 51548c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 2, 1); 51558c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_intc_override(dev, N_INTC_OVERRIDE_TRSW, 8, 2); 51568c2ecf20Sopenharmony_ci 51578c2ecf20Sopenharmony_ci regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0); 51588c2ecf20Sopenharmony_ci regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1); 51598c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001); 51608c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001); 51618c2ecf20Sopenharmony_ci 51628c2ecf20Sopenharmony_ci tmp = b43_nphy_read_lpf_ctl(dev, 0); 51638c2ecf20Sopenharmony_ci if (phy->rev >= 19) 51648c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev19(dev, 0x80, tmp, 0, false, 51658c2ecf20Sopenharmony_ci 1); 51668c2ecf20Sopenharmony_ci else if (phy->rev >= 7) 51678c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x80, tmp, 0, false, 51688c2ecf20Sopenharmony_ci 1); 51698c2ecf20Sopenharmony_ci 51708c2ecf20Sopenharmony_ci if (nphy->use_int_tx_iq_lo_cal && true /* FIXME */) { 51718c2ecf20Sopenharmony_ci if (phy->rev >= 19) { 51728c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev19(dev, 0x8, 0, 0x3, 51738c2ecf20Sopenharmony_ci false, 0); 51748c2ecf20Sopenharmony_ci } else if (phy->rev >= 8) { 51758c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override_rev7(dev, 0x8, 0, 0x3, 51768c2ecf20Sopenharmony_ci false, 0); 51778c2ecf20Sopenharmony_ci } else if (phy->rev == 7) { 51788c2ecf20Sopenharmony_ci b43_radio_maskset(dev, R2057_OVR_REG0, 1 << 4, 1 << 4); 51798c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { 51808c2ecf20Sopenharmony_ci b43_radio_maskset(dev, R2057_PAD2G_TUNE_PUS_CORE0, ~1, 0); 51818c2ecf20Sopenharmony_ci b43_radio_maskset(dev, R2057_PAD2G_TUNE_PUS_CORE1, ~1, 0); 51828c2ecf20Sopenharmony_ci } else { 51838c2ecf20Sopenharmony_ci b43_radio_maskset(dev, R2057_IPA5G_CASCOFFV_PU_CORE0, ~1, 0); 51848c2ecf20Sopenharmony_ci b43_radio_maskset(dev, R2057_IPA5G_CASCOFFV_PU_CORE1, ~1, 0); 51858c2ecf20Sopenharmony_ci } 51868c2ecf20Sopenharmony_ci } 51878c2ecf20Sopenharmony_ci } 51888c2ecf20Sopenharmony_ci } else { 51898c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, 0xA000); 51908c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, 0xA000); 51918c2ecf20Sopenharmony_ci tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); 51928c2ecf20Sopenharmony_ci regs[2] = tmp; 51938c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x3000); 51948c2ecf20Sopenharmony_ci tmp = b43_ntab_read(dev, B43_NTAB16(8, 2)); 51958c2ecf20Sopenharmony_ci regs[3] = tmp; 51968c2ecf20Sopenharmony_ci tmp |= 0x2000; 51978c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 2), tmp); 51988c2ecf20Sopenharmony_ci tmp = b43_ntab_read(dev, B43_NTAB16(8, 18)); 51998c2ecf20Sopenharmony_ci regs[4] = tmp; 52008c2ecf20Sopenharmony_ci tmp |= 0x2000; 52018c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(8, 18), tmp); 52028c2ecf20Sopenharmony_ci regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); 52038c2ecf20Sopenharmony_ci regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); 52048c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) 52058c2ecf20Sopenharmony_ci tmp = 0x0180; 52068c2ecf20Sopenharmony_ci else 52078c2ecf20Sopenharmony_ci tmp = 0x0120; 52088c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp); 52098c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp); 52108c2ecf20Sopenharmony_ci } 52118c2ecf20Sopenharmony_ci} 52128c2ecf20Sopenharmony_ci 52138c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */ 52148c2ecf20Sopenharmony_cistatic void b43_nphy_save_cal(struct b43_wldev *dev) 52158c2ecf20Sopenharmony_ci{ 52168c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 52178c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 52188c2ecf20Sopenharmony_ci 52198c2ecf20Sopenharmony_ci struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; 52208c2ecf20Sopenharmony_ci u16 *txcal_radio_regs = NULL; 52218c2ecf20Sopenharmony_ci struct b43_chanspec *iqcal_chanspec; 52228c2ecf20Sopenharmony_ci u16 *table = NULL; 52238c2ecf20Sopenharmony_ci 52248c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 52258c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, 1); 52268c2ecf20Sopenharmony_ci 52278c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { 52288c2ecf20Sopenharmony_ci rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G; 52298c2ecf20Sopenharmony_ci txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G; 52308c2ecf20Sopenharmony_ci iqcal_chanspec = &nphy->iqcal_chanspec_2G; 52318c2ecf20Sopenharmony_ci table = nphy->cal_cache.txcal_coeffs_2G; 52328c2ecf20Sopenharmony_ci } else { 52338c2ecf20Sopenharmony_ci rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G; 52348c2ecf20Sopenharmony_ci txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G; 52358c2ecf20Sopenharmony_ci iqcal_chanspec = &nphy->iqcal_chanspec_5G; 52368c2ecf20Sopenharmony_ci table = nphy->cal_cache.txcal_coeffs_5G; 52378c2ecf20Sopenharmony_ci } 52388c2ecf20Sopenharmony_ci 52398c2ecf20Sopenharmony_ci b43_nphy_rx_iq_coeffs(dev, false, rxcal_coeffs); 52408c2ecf20Sopenharmony_ci /* TODO use some definitions */ 52418c2ecf20Sopenharmony_ci if (phy->rev >= 19) { 52428c2ecf20Sopenharmony_ci /* TODO */ 52438c2ecf20Sopenharmony_ci } else if (phy->rev >= 7) { 52448c2ecf20Sopenharmony_ci txcal_radio_regs[0] = b43_radio_read(dev, 52458c2ecf20Sopenharmony_ci R2057_TX0_LOFT_FINE_I); 52468c2ecf20Sopenharmony_ci txcal_radio_regs[1] = b43_radio_read(dev, 52478c2ecf20Sopenharmony_ci R2057_TX0_LOFT_FINE_Q); 52488c2ecf20Sopenharmony_ci txcal_radio_regs[4] = b43_radio_read(dev, 52498c2ecf20Sopenharmony_ci R2057_TX0_LOFT_COARSE_I); 52508c2ecf20Sopenharmony_ci txcal_radio_regs[5] = b43_radio_read(dev, 52518c2ecf20Sopenharmony_ci R2057_TX0_LOFT_COARSE_Q); 52528c2ecf20Sopenharmony_ci txcal_radio_regs[2] = b43_radio_read(dev, 52538c2ecf20Sopenharmony_ci R2057_TX1_LOFT_FINE_I); 52548c2ecf20Sopenharmony_ci txcal_radio_regs[3] = b43_radio_read(dev, 52558c2ecf20Sopenharmony_ci R2057_TX1_LOFT_FINE_Q); 52568c2ecf20Sopenharmony_ci txcal_radio_regs[6] = b43_radio_read(dev, 52578c2ecf20Sopenharmony_ci R2057_TX1_LOFT_COARSE_I); 52588c2ecf20Sopenharmony_ci txcal_radio_regs[7] = b43_radio_read(dev, 52598c2ecf20Sopenharmony_ci R2057_TX1_LOFT_COARSE_Q); 52608c2ecf20Sopenharmony_ci } else if (phy->rev >= 3) { 52618c2ecf20Sopenharmony_ci txcal_radio_regs[0] = b43_radio_read(dev, 0x2021); 52628c2ecf20Sopenharmony_ci txcal_radio_regs[1] = b43_radio_read(dev, 0x2022); 52638c2ecf20Sopenharmony_ci txcal_radio_regs[2] = b43_radio_read(dev, 0x3021); 52648c2ecf20Sopenharmony_ci txcal_radio_regs[3] = b43_radio_read(dev, 0x3022); 52658c2ecf20Sopenharmony_ci txcal_radio_regs[4] = b43_radio_read(dev, 0x2023); 52668c2ecf20Sopenharmony_ci txcal_radio_regs[5] = b43_radio_read(dev, 0x2024); 52678c2ecf20Sopenharmony_ci txcal_radio_regs[6] = b43_radio_read(dev, 0x3023); 52688c2ecf20Sopenharmony_ci txcal_radio_regs[7] = b43_radio_read(dev, 0x3024); 52698c2ecf20Sopenharmony_ci } else { 52708c2ecf20Sopenharmony_ci txcal_radio_regs[0] = b43_radio_read(dev, 0x8B); 52718c2ecf20Sopenharmony_ci txcal_radio_regs[1] = b43_radio_read(dev, 0xBA); 52728c2ecf20Sopenharmony_ci txcal_radio_regs[2] = b43_radio_read(dev, 0x8D); 52738c2ecf20Sopenharmony_ci txcal_radio_regs[3] = b43_radio_read(dev, 0xBC); 52748c2ecf20Sopenharmony_ci } 52758c2ecf20Sopenharmony_ci iqcal_chanspec->center_freq = dev->phy.chandef->chan->center_freq; 52768c2ecf20Sopenharmony_ci iqcal_chanspec->channel_type = 52778c2ecf20Sopenharmony_ci cfg80211_get_chandef_type(dev->phy.chandef); 52788c2ecf20Sopenharmony_ci b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 8, table); 52798c2ecf20Sopenharmony_ci 52808c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 52818c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, 0); 52828c2ecf20Sopenharmony_ci} 52838c2ecf20Sopenharmony_ci 52848c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */ 52858c2ecf20Sopenharmony_cistatic void b43_nphy_restore_cal(struct b43_wldev *dev) 52868c2ecf20Sopenharmony_ci{ 52878c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 52888c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 52898c2ecf20Sopenharmony_ci 52908c2ecf20Sopenharmony_ci u16 coef[4]; 52918c2ecf20Sopenharmony_ci u16 *loft = NULL; 52928c2ecf20Sopenharmony_ci u16 *table = NULL; 52938c2ecf20Sopenharmony_ci 52948c2ecf20Sopenharmony_ci int i; 52958c2ecf20Sopenharmony_ci u16 *txcal_radio_regs = NULL; 52968c2ecf20Sopenharmony_ci struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; 52978c2ecf20Sopenharmony_ci 52988c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { 52998c2ecf20Sopenharmony_ci if (!nphy->iqcal_chanspec_2G.center_freq) 53008c2ecf20Sopenharmony_ci return; 53018c2ecf20Sopenharmony_ci table = nphy->cal_cache.txcal_coeffs_2G; 53028c2ecf20Sopenharmony_ci loft = &nphy->cal_cache.txcal_coeffs_2G[5]; 53038c2ecf20Sopenharmony_ci } else { 53048c2ecf20Sopenharmony_ci if (!nphy->iqcal_chanspec_5G.center_freq) 53058c2ecf20Sopenharmony_ci return; 53068c2ecf20Sopenharmony_ci table = nphy->cal_cache.txcal_coeffs_5G; 53078c2ecf20Sopenharmony_ci loft = &nphy->cal_cache.txcal_coeffs_5G[5]; 53088c2ecf20Sopenharmony_ci } 53098c2ecf20Sopenharmony_ci 53108c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4, table); 53118c2ecf20Sopenharmony_ci 53128c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) { 53138c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) 53148c2ecf20Sopenharmony_ci coef[i] = table[i]; 53158c2ecf20Sopenharmony_ci else 53168c2ecf20Sopenharmony_ci coef[i] = 0; 53178c2ecf20Sopenharmony_ci } 53188c2ecf20Sopenharmony_ci 53198c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, coef); 53208c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, loft); 53218c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2, loft); 53228c2ecf20Sopenharmony_ci 53238c2ecf20Sopenharmony_ci if (dev->phy.rev < 2) 53248c2ecf20Sopenharmony_ci b43_nphy_tx_iq_workaround(dev); 53258c2ecf20Sopenharmony_ci 53268c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { 53278c2ecf20Sopenharmony_ci txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G; 53288c2ecf20Sopenharmony_ci rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G; 53298c2ecf20Sopenharmony_ci } else { 53308c2ecf20Sopenharmony_ci txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G; 53318c2ecf20Sopenharmony_ci rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G; 53328c2ecf20Sopenharmony_ci } 53338c2ecf20Sopenharmony_ci 53348c2ecf20Sopenharmony_ci /* TODO use some definitions */ 53358c2ecf20Sopenharmony_ci if (phy->rev >= 19) { 53368c2ecf20Sopenharmony_ci /* TODO */ 53378c2ecf20Sopenharmony_ci } else if (phy->rev >= 7) { 53388c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_TX0_LOFT_FINE_I, 53398c2ecf20Sopenharmony_ci txcal_radio_regs[0]); 53408c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_TX0_LOFT_FINE_Q, 53418c2ecf20Sopenharmony_ci txcal_radio_regs[1]); 53428c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_TX0_LOFT_COARSE_I, 53438c2ecf20Sopenharmony_ci txcal_radio_regs[4]); 53448c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_TX0_LOFT_COARSE_Q, 53458c2ecf20Sopenharmony_ci txcal_radio_regs[5]); 53468c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_TX1_LOFT_FINE_I, 53478c2ecf20Sopenharmony_ci txcal_radio_regs[2]); 53488c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_TX1_LOFT_FINE_Q, 53498c2ecf20Sopenharmony_ci txcal_radio_regs[3]); 53508c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_TX1_LOFT_COARSE_I, 53518c2ecf20Sopenharmony_ci txcal_radio_regs[6]); 53528c2ecf20Sopenharmony_ci b43_radio_write(dev, R2057_TX1_LOFT_COARSE_Q, 53538c2ecf20Sopenharmony_ci txcal_radio_regs[7]); 53548c2ecf20Sopenharmony_ci } else if (phy->rev >= 3) { 53558c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x2021, txcal_radio_regs[0]); 53568c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x2022, txcal_radio_regs[1]); 53578c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x3021, txcal_radio_regs[2]); 53588c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x3022, txcal_radio_regs[3]); 53598c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x2023, txcal_radio_regs[4]); 53608c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x2024, txcal_radio_regs[5]); 53618c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x3023, txcal_radio_regs[6]); 53628c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x3024, txcal_radio_regs[7]); 53638c2ecf20Sopenharmony_ci } else { 53648c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x8B, txcal_radio_regs[0]); 53658c2ecf20Sopenharmony_ci b43_radio_write(dev, 0xBA, txcal_radio_regs[1]); 53668c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x8D, txcal_radio_regs[2]); 53678c2ecf20Sopenharmony_ci b43_radio_write(dev, 0xBC, txcal_radio_regs[3]); 53688c2ecf20Sopenharmony_ci } 53698c2ecf20Sopenharmony_ci b43_nphy_rx_iq_coeffs(dev, true, rxcal_coeffs); 53708c2ecf20Sopenharmony_ci} 53718c2ecf20Sopenharmony_ci 53728c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/CalTxIqlo */ 53738c2ecf20Sopenharmony_cistatic int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, 53748c2ecf20Sopenharmony_ci struct nphy_txgains target, 53758c2ecf20Sopenharmony_ci bool full, bool mphase) 53768c2ecf20Sopenharmony_ci{ 53778c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 53788c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 53798c2ecf20Sopenharmony_ci int i; 53808c2ecf20Sopenharmony_ci int error = 0; 53818c2ecf20Sopenharmony_ci int freq; 53828c2ecf20Sopenharmony_ci bool avoid = false; 53838c2ecf20Sopenharmony_ci u8 length; 53848c2ecf20Sopenharmony_ci u16 tmp, core, type, count, max, numb, last = 0, cmd; 53858c2ecf20Sopenharmony_ci const u16 *table; 53868c2ecf20Sopenharmony_ci bool phy6or5x; 53878c2ecf20Sopenharmony_ci 53888c2ecf20Sopenharmony_ci u16 buffer[11]; 53898c2ecf20Sopenharmony_ci u16 diq_start = 0; 53908c2ecf20Sopenharmony_ci u16 save[2]; 53918c2ecf20Sopenharmony_ci u16 gain[2]; 53928c2ecf20Sopenharmony_ci struct nphy_iqcal_params params[2]; 53938c2ecf20Sopenharmony_ci bool updated[2] = { }; 53948c2ecf20Sopenharmony_ci 53958c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, true); 53968c2ecf20Sopenharmony_ci 53978c2ecf20Sopenharmony_ci if (dev->phy.rev >= 4) { 53988c2ecf20Sopenharmony_ci avoid = nphy->hang_avoid; 53998c2ecf20Sopenharmony_ci nphy->hang_avoid = false; 54008c2ecf20Sopenharmony_ci } 54018c2ecf20Sopenharmony_ci 54028c2ecf20Sopenharmony_ci b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, save); 54038c2ecf20Sopenharmony_ci 54048c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 54058c2ecf20Sopenharmony_ci b43_nphy_iq_cal_gain_params(dev, i, target, ¶ms[i]); 54068c2ecf20Sopenharmony_ci gain[i] = params[i].cal_gain; 54078c2ecf20Sopenharmony_ci } 54088c2ecf20Sopenharmony_ci 54098c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain); 54108c2ecf20Sopenharmony_ci 54118c2ecf20Sopenharmony_ci b43_nphy_tx_cal_radio_setup(dev); 54128c2ecf20Sopenharmony_ci b43_nphy_tx_cal_phy_setup(dev); 54138c2ecf20Sopenharmony_ci 54148c2ecf20Sopenharmony_ci phy6or5x = dev->phy.rev >= 6 || 54158c2ecf20Sopenharmony_ci (dev->phy.rev == 5 && nphy->ipa2g_on && 54168c2ecf20Sopenharmony_ci b43_current_band(dev->wl) == NL80211_BAND_2GHZ); 54178c2ecf20Sopenharmony_ci if (phy6or5x) { 54188c2ecf20Sopenharmony_ci if (b43_is_40mhz(dev)) { 54198c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18, 54208c2ecf20Sopenharmony_ci tbl_tx_iqlo_cal_loft_ladder_40); 54218c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18, 54228c2ecf20Sopenharmony_ci tbl_tx_iqlo_cal_iqimb_ladder_40); 54238c2ecf20Sopenharmony_ci } else { 54248c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18, 54258c2ecf20Sopenharmony_ci tbl_tx_iqlo_cal_loft_ladder_20); 54268c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18, 54278c2ecf20Sopenharmony_ci tbl_tx_iqlo_cal_iqimb_ladder_20); 54288c2ecf20Sopenharmony_ci } 54298c2ecf20Sopenharmony_ci } 54308c2ecf20Sopenharmony_ci 54318c2ecf20Sopenharmony_ci if (phy->rev >= 19) { 54328c2ecf20Sopenharmony_ci /* TODO */ 54338c2ecf20Sopenharmony_ci } else if (phy->rev >= 7) { 54348c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AD9); 54358c2ecf20Sopenharmony_ci } else { 54368c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9); 54378c2ecf20Sopenharmony_ci } 54388c2ecf20Sopenharmony_ci 54398c2ecf20Sopenharmony_ci if (!b43_is_40mhz(dev)) 54408c2ecf20Sopenharmony_ci freq = 2500; 54418c2ecf20Sopenharmony_ci else 54428c2ecf20Sopenharmony_ci freq = 5000; 54438c2ecf20Sopenharmony_ci 54448c2ecf20Sopenharmony_ci if (nphy->mphase_cal_phase_id > 2) 54458c2ecf20Sopenharmony_ci b43_nphy_run_samples(dev, (b43_is_40mhz(dev) ? 40 : 20) * 8, 54468c2ecf20Sopenharmony_ci 0xFFFF, 0, true, false, false); 54478c2ecf20Sopenharmony_ci else 54488c2ecf20Sopenharmony_ci error = b43_nphy_tx_tone(dev, freq, 250, true, false, false); 54498c2ecf20Sopenharmony_ci 54508c2ecf20Sopenharmony_ci if (error == 0) { 54518c2ecf20Sopenharmony_ci if (nphy->mphase_cal_phase_id > 2) { 54528c2ecf20Sopenharmony_ci table = nphy->mphase_txcal_bestcoeffs; 54538c2ecf20Sopenharmony_ci length = 11; 54548c2ecf20Sopenharmony_ci if (dev->phy.rev < 3) 54558c2ecf20Sopenharmony_ci length -= 2; 54568c2ecf20Sopenharmony_ci } else { 54578c2ecf20Sopenharmony_ci if (!full && nphy->txiqlocal_coeffsvalid) { 54588c2ecf20Sopenharmony_ci table = nphy->txiqlocal_bestc; 54598c2ecf20Sopenharmony_ci length = 11; 54608c2ecf20Sopenharmony_ci if (dev->phy.rev < 3) 54618c2ecf20Sopenharmony_ci length -= 2; 54628c2ecf20Sopenharmony_ci } else { 54638c2ecf20Sopenharmony_ci full = true; 54648c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) { 54658c2ecf20Sopenharmony_ci table = tbl_tx_iqlo_cal_startcoefs_nphyrev3; 54668c2ecf20Sopenharmony_ci length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3; 54678c2ecf20Sopenharmony_ci } else { 54688c2ecf20Sopenharmony_ci table = tbl_tx_iqlo_cal_startcoefs; 54698c2ecf20Sopenharmony_ci length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS; 54708c2ecf20Sopenharmony_ci } 54718c2ecf20Sopenharmony_ci } 54728c2ecf20Sopenharmony_ci } 54738c2ecf20Sopenharmony_ci 54748c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length, table); 54758c2ecf20Sopenharmony_ci 54768c2ecf20Sopenharmony_ci if (full) { 54778c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) 54788c2ecf20Sopenharmony_ci max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3; 54798c2ecf20Sopenharmony_ci else 54808c2ecf20Sopenharmony_ci max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL; 54818c2ecf20Sopenharmony_ci } else { 54828c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) 54838c2ecf20Sopenharmony_ci max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3; 54848c2ecf20Sopenharmony_ci else 54858c2ecf20Sopenharmony_ci max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL; 54868c2ecf20Sopenharmony_ci } 54878c2ecf20Sopenharmony_ci 54888c2ecf20Sopenharmony_ci if (mphase) { 54898c2ecf20Sopenharmony_ci count = nphy->mphase_txcal_cmdidx; 54908c2ecf20Sopenharmony_ci numb = min(max, 54918c2ecf20Sopenharmony_ci (u16)(count + nphy->mphase_txcal_numcmds)); 54928c2ecf20Sopenharmony_ci } else { 54938c2ecf20Sopenharmony_ci count = 0; 54948c2ecf20Sopenharmony_ci numb = max; 54958c2ecf20Sopenharmony_ci } 54968c2ecf20Sopenharmony_ci 54978c2ecf20Sopenharmony_ci for (; count < numb; count++) { 54988c2ecf20Sopenharmony_ci if (full) { 54998c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) 55008c2ecf20Sopenharmony_ci cmd = tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[count]; 55018c2ecf20Sopenharmony_ci else 55028c2ecf20Sopenharmony_ci cmd = tbl_tx_iqlo_cal_cmds_fullcal[count]; 55038c2ecf20Sopenharmony_ci } else { 55048c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) 55058c2ecf20Sopenharmony_ci cmd = tbl_tx_iqlo_cal_cmds_recal_nphyrev3[count]; 55068c2ecf20Sopenharmony_ci else 55078c2ecf20Sopenharmony_ci cmd = tbl_tx_iqlo_cal_cmds_recal[count]; 55088c2ecf20Sopenharmony_ci } 55098c2ecf20Sopenharmony_ci 55108c2ecf20Sopenharmony_ci core = (cmd & 0x3000) >> 12; 55118c2ecf20Sopenharmony_ci type = (cmd & 0x0F00) >> 8; 55128c2ecf20Sopenharmony_ci 55138c2ecf20Sopenharmony_ci if (phy6or5x && !updated[core]) { 55148c2ecf20Sopenharmony_ci b43_nphy_update_tx_cal_ladder(dev, core); 55158c2ecf20Sopenharmony_ci updated[core] = true; 55168c2ecf20Sopenharmony_ci } 55178c2ecf20Sopenharmony_ci 55188c2ecf20Sopenharmony_ci tmp = (params[core].ncorr[type] << 8) | 0x66; 55198c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDNNUM, tmp); 55208c2ecf20Sopenharmony_ci 55218c2ecf20Sopenharmony_ci if (type == 1 || type == 3 || type == 4) { 55228c2ecf20Sopenharmony_ci buffer[0] = b43_ntab_read(dev, 55238c2ecf20Sopenharmony_ci B43_NTAB16(15, 69 + core)); 55248c2ecf20Sopenharmony_ci diq_start = buffer[0]; 55258c2ecf20Sopenharmony_ci buffer[0] = 0; 55268c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(15, 69 + core), 55278c2ecf20Sopenharmony_ci 0); 55288c2ecf20Sopenharmony_ci } 55298c2ecf20Sopenharmony_ci 55308c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_IQLOCAL_CMD, cmd); 55318c2ecf20Sopenharmony_ci for (i = 0; i < 2000; i++) { 55328c2ecf20Sopenharmony_ci tmp = b43_phy_read(dev, B43_NPHY_IQLOCAL_CMD); 55338c2ecf20Sopenharmony_ci if (tmp & 0xC000) 55348c2ecf20Sopenharmony_ci break; 55358c2ecf20Sopenharmony_ci udelay(10); 55368c2ecf20Sopenharmony_ci } 55378c2ecf20Sopenharmony_ci 55388c2ecf20Sopenharmony_ci b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length, 55398c2ecf20Sopenharmony_ci buffer); 55408c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length, 55418c2ecf20Sopenharmony_ci buffer); 55428c2ecf20Sopenharmony_ci 55438c2ecf20Sopenharmony_ci if (type == 1 || type == 3 || type == 4) 55448c2ecf20Sopenharmony_ci buffer[0] = diq_start; 55458c2ecf20Sopenharmony_ci } 55468c2ecf20Sopenharmony_ci 55478c2ecf20Sopenharmony_ci if (mphase) 55488c2ecf20Sopenharmony_ci nphy->mphase_txcal_cmdidx = (numb >= max) ? 0 : numb; 55498c2ecf20Sopenharmony_ci 55508c2ecf20Sopenharmony_ci last = (dev->phy.rev < 3) ? 6 : 7; 55518c2ecf20Sopenharmony_ci 55528c2ecf20Sopenharmony_ci if (!mphase || nphy->mphase_cal_phase_id == last) { 55538c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(15, 96), 4, buffer); 55548c2ecf20Sopenharmony_ci b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 4, buffer); 55558c2ecf20Sopenharmony_ci if (dev->phy.rev < 3) { 55568c2ecf20Sopenharmony_ci buffer[0] = 0; 55578c2ecf20Sopenharmony_ci buffer[1] = 0; 55588c2ecf20Sopenharmony_ci buffer[2] = 0; 55598c2ecf20Sopenharmony_ci buffer[3] = 0; 55608c2ecf20Sopenharmony_ci } 55618c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, 55628c2ecf20Sopenharmony_ci buffer); 55638c2ecf20Sopenharmony_ci b43_ntab_read_bulk(dev, B43_NTAB16(15, 101), 2, 55648c2ecf20Sopenharmony_ci buffer); 55658c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, 55668c2ecf20Sopenharmony_ci buffer); 55678c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2, 55688c2ecf20Sopenharmony_ci buffer); 55698c2ecf20Sopenharmony_ci length = 11; 55708c2ecf20Sopenharmony_ci if (dev->phy.rev < 3) 55718c2ecf20Sopenharmony_ci length -= 2; 55728c2ecf20Sopenharmony_ci b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length, 55738c2ecf20Sopenharmony_ci nphy->txiqlocal_bestc); 55748c2ecf20Sopenharmony_ci nphy->txiqlocal_coeffsvalid = true; 55758c2ecf20Sopenharmony_ci nphy->txiqlocal_chanspec.center_freq = 55768c2ecf20Sopenharmony_ci phy->chandef->chan->center_freq; 55778c2ecf20Sopenharmony_ci nphy->txiqlocal_chanspec.channel_type = 55788c2ecf20Sopenharmony_ci cfg80211_get_chandef_type(phy->chandef); 55798c2ecf20Sopenharmony_ci } else { 55808c2ecf20Sopenharmony_ci length = 11; 55818c2ecf20Sopenharmony_ci if (dev->phy.rev < 3) 55828c2ecf20Sopenharmony_ci length -= 2; 55838c2ecf20Sopenharmony_ci b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length, 55848c2ecf20Sopenharmony_ci nphy->mphase_txcal_bestcoeffs); 55858c2ecf20Sopenharmony_ci } 55868c2ecf20Sopenharmony_ci 55878c2ecf20Sopenharmony_ci b43_nphy_stop_playback(dev); 55888c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0); 55898c2ecf20Sopenharmony_ci } 55908c2ecf20Sopenharmony_ci 55918c2ecf20Sopenharmony_ci b43_nphy_tx_cal_phy_cleanup(dev); 55928c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, save); 55938c2ecf20Sopenharmony_ci 55948c2ecf20Sopenharmony_ci if (dev->phy.rev < 2 && (!mphase || nphy->mphase_cal_phase_id == last)) 55958c2ecf20Sopenharmony_ci b43_nphy_tx_iq_workaround(dev); 55968c2ecf20Sopenharmony_ci 55978c2ecf20Sopenharmony_ci if (dev->phy.rev >= 4) 55988c2ecf20Sopenharmony_ci nphy->hang_avoid = avoid; 55998c2ecf20Sopenharmony_ci 56008c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, false); 56018c2ecf20Sopenharmony_ci 56028c2ecf20Sopenharmony_ci return error; 56038c2ecf20Sopenharmony_ci} 56048c2ecf20Sopenharmony_ci 56058c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/ReapplyTxCalCoeffs */ 56068c2ecf20Sopenharmony_cistatic void b43_nphy_reapply_tx_cal_coeffs(struct b43_wldev *dev) 56078c2ecf20Sopenharmony_ci{ 56088c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 56098c2ecf20Sopenharmony_ci u8 i; 56108c2ecf20Sopenharmony_ci u16 buffer[7]; 56118c2ecf20Sopenharmony_ci bool equal = true; 56128c2ecf20Sopenharmony_ci 56138c2ecf20Sopenharmony_ci if (!nphy->txiqlocal_coeffsvalid || 56148c2ecf20Sopenharmony_ci nphy->txiqlocal_chanspec.center_freq != dev->phy.chandef->chan->center_freq || 56158c2ecf20Sopenharmony_ci nphy->txiqlocal_chanspec.channel_type != cfg80211_get_chandef_type(dev->phy.chandef)) 56168c2ecf20Sopenharmony_ci return; 56178c2ecf20Sopenharmony_ci 56188c2ecf20Sopenharmony_ci b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer); 56198c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) { 56208c2ecf20Sopenharmony_ci if (buffer[i] != nphy->txiqlocal_bestc[i]) { 56218c2ecf20Sopenharmony_ci equal = false; 56228c2ecf20Sopenharmony_ci break; 56238c2ecf20Sopenharmony_ci } 56248c2ecf20Sopenharmony_ci } 56258c2ecf20Sopenharmony_ci 56268c2ecf20Sopenharmony_ci if (!equal) { 56278c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4, 56288c2ecf20Sopenharmony_ci nphy->txiqlocal_bestc); 56298c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 56308c2ecf20Sopenharmony_ci buffer[i] = 0; 56318c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, 56328c2ecf20Sopenharmony_ci buffer); 56338c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, 56348c2ecf20Sopenharmony_ci &nphy->txiqlocal_bestc[5]); 56358c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2, 56368c2ecf20Sopenharmony_ci &nphy->txiqlocal_bestc[5]); 56378c2ecf20Sopenharmony_ci } 56388c2ecf20Sopenharmony_ci} 56398c2ecf20Sopenharmony_ci 56408c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIqRev2 */ 56418c2ecf20Sopenharmony_cistatic int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, 56428c2ecf20Sopenharmony_ci struct nphy_txgains target, u8 type, bool debug) 56438c2ecf20Sopenharmony_ci{ 56448c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 56458c2ecf20Sopenharmony_ci int i, j, index; 56468c2ecf20Sopenharmony_ci u8 rfctl[2]; 56478c2ecf20Sopenharmony_ci u8 afectl_core; 56488c2ecf20Sopenharmony_ci u16 tmp[6]; 56498c2ecf20Sopenharmony_ci u16 cur_hpf1, cur_hpf2, cur_lna; 56508c2ecf20Sopenharmony_ci u32 real, imag; 56518c2ecf20Sopenharmony_ci enum nl80211_band band; 56528c2ecf20Sopenharmony_ci 56538c2ecf20Sopenharmony_ci u8 use; 56548c2ecf20Sopenharmony_ci u16 cur_hpf; 56558c2ecf20Sopenharmony_ci u16 lna[3] = { 3, 3, 1 }; 56568c2ecf20Sopenharmony_ci u16 hpf1[3] = { 7, 2, 0 }; 56578c2ecf20Sopenharmony_ci u16 hpf2[3] = { 2, 0, 0 }; 56588c2ecf20Sopenharmony_ci u32 power[3] = { }; 56598c2ecf20Sopenharmony_ci u16 gain_save[2]; 56608c2ecf20Sopenharmony_ci u16 cal_gain[2]; 56618c2ecf20Sopenharmony_ci struct nphy_iqcal_params cal_params[2]; 56628c2ecf20Sopenharmony_ci struct nphy_iq_est est; 56638c2ecf20Sopenharmony_ci int ret = 0; 56648c2ecf20Sopenharmony_ci bool playtone = true; 56658c2ecf20Sopenharmony_ci int desired = 13; 56668c2ecf20Sopenharmony_ci 56678c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, 1); 56688c2ecf20Sopenharmony_ci 56698c2ecf20Sopenharmony_ci if (dev->phy.rev < 2) 56708c2ecf20Sopenharmony_ci b43_nphy_reapply_tx_cal_coeffs(dev); 56718c2ecf20Sopenharmony_ci b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save); 56728c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 56738c2ecf20Sopenharmony_ci b43_nphy_iq_cal_gain_params(dev, i, target, &cal_params[i]); 56748c2ecf20Sopenharmony_ci cal_gain[i] = cal_params[i].cal_gain; 56758c2ecf20Sopenharmony_ci } 56768c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, cal_gain); 56778c2ecf20Sopenharmony_ci 56788c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 56798c2ecf20Sopenharmony_ci if (i == 0) { 56808c2ecf20Sopenharmony_ci rfctl[0] = B43_NPHY_RFCTL_INTC1; 56818c2ecf20Sopenharmony_ci rfctl[1] = B43_NPHY_RFCTL_INTC2; 56828c2ecf20Sopenharmony_ci afectl_core = B43_NPHY_AFECTL_C1; 56838c2ecf20Sopenharmony_ci } else { 56848c2ecf20Sopenharmony_ci rfctl[0] = B43_NPHY_RFCTL_INTC2; 56858c2ecf20Sopenharmony_ci rfctl[1] = B43_NPHY_RFCTL_INTC1; 56868c2ecf20Sopenharmony_ci afectl_core = B43_NPHY_AFECTL_C2; 56878c2ecf20Sopenharmony_ci } 56888c2ecf20Sopenharmony_ci 56898c2ecf20Sopenharmony_ci tmp[1] = b43_phy_read(dev, B43_NPHY_RFSEQCA); 56908c2ecf20Sopenharmony_ci tmp[2] = b43_phy_read(dev, afectl_core); 56918c2ecf20Sopenharmony_ci tmp[3] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); 56928c2ecf20Sopenharmony_ci tmp[4] = b43_phy_read(dev, rfctl[0]); 56938c2ecf20Sopenharmony_ci tmp[5] = b43_phy_read(dev, rfctl[1]); 56948c2ecf20Sopenharmony_ci 56958c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_RFSEQCA, 56968c2ecf20Sopenharmony_ci ~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF, 56978c2ecf20Sopenharmony_ci ((1 - i) << B43_NPHY_RFSEQCA_RXDIS_SHIFT)); 56988c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN, 56998c2ecf20Sopenharmony_ci (1 - i)); 57008c2ecf20Sopenharmony_ci b43_phy_set(dev, afectl_core, 0x0006); 57018c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0006); 57028c2ecf20Sopenharmony_ci 57038c2ecf20Sopenharmony_ci band = b43_current_band(dev->wl); 57048c2ecf20Sopenharmony_ci 57058c2ecf20Sopenharmony_ci if (nphy->rxcalparams & 0xFF000000) { 57068c2ecf20Sopenharmony_ci if (band == NL80211_BAND_5GHZ) 57078c2ecf20Sopenharmony_ci b43_phy_write(dev, rfctl[0], 0x140); 57088c2ecf20Sopenharmony_ci else 57098c2ecf20Sopenharmony_ci b43_phy_write(dev, rfctl[0], 0x110); 57108c2ecf20Sopenharmony_ci } else { 57118c2ecf20Sopenharmony_ci if (band == NL80211_BAND_5GHZ) 57128c2ecf20Sopenharmony_ci b43_phy_write(dev, rfctl[0], 0x180); 57138c2ecf20Sopenharmony_ci else 57148c2ecf20Sopenharmony_ci b43_phy_write(dev, rfctl[0], 0x120); 57158c2ecf20Sopenharmony_ci } 57168c2ecf20Sopenharmony_ci 57178c2ecf20Sopenharmony_ci if (band == NL80211_BAND_5GHZ) 57188c2ecf20Sopenharmony_ci b43_phy_write(dev, rfctl[1], 0x148); 57198c2ecf20Sopenharmony_ci else 57208c2ecf20Sopenharmony_ci b43_phy_write(dev, rfctl[1], 0x114); 57218c2ecf20Sopenharmony_ci 57228c2ecf20Sopenharmony_ci if (nphy->rxcalparams & 0x10000) { 57238c2ecf20Sopenharmony_ci b43_radio_maskset(dev, B2055_C1_GENSPARE2, 0xFC, 57248c2ecf20Sopenharmony_ci (i + 1)); 57258c2ecf20Sopenharmony_ci b43_radio_maskset(dev, B2055_C2_GENSPARE2, 0xFC, 57268c2ecf20Sopenharmony_ci (2 - i)); 57278c2ecf20Sopenharmony_ci } 57288c2ecf20Sopenharmony_ci 57298c2ecf20Sopenharmony_ci for (j = 0; j < 4; j++) { 57308c2ecf20Sopenharmony_ci if (j < 3) { 57318c2ecf20Sopenharmony_ci cur_lna = lna[j]; 57328c2ecf20Sopenharmony_ci cur_hpf1 = hpf1[j]; 57338c2ecf20Sopenharmony_ci cur_hpf2 = hpf2[j]; 57348c2ecf20Sopenharmony_ci } else { 57358c2ecf20Sopenharmony_ci if (power[1] > 10000) { 57368c2ecf20Sopenharmony_ci use = 1; 57378c2ecf20Sopenharmony_ci cur_hpf = cur_hpf1; 57388c2ecf20Sopenharmony_ci index = 2; 57398c2ecf20Sopenharmony_ci } else { 57408c2ecf20Sopenharmony_ci if (power[0] > 10000) { 57418c2ecf20Sopenharmony_ci use = 1; 57428c2ecf20Sopenharmony_ci cur_hpf = cur_hpf1; 57438c2ecf20Sopenharmony_ci index = 1; 57448c2ecf20Sopenharmony_ci } else { 57458c2ecf20Sopenharmony_ci index = 0; 57468c2ecf20Sopenharmony_ci use = 2; 57478c2ecf20Sopenharmony_ci cur_hpf = cur_hpf2; 57488c2ecf20Sopenharmony_ci } 57498c2ecf20Sopenharmony_ci } 57508c2ecf20Sopenharmony_ci cur_lna = lna[index]; 57518c2ecf20Sopenharmony_ci cur_hpf1 = hpf1[index]; 57528c2ecf20Sopenharmony_ci cur_hpf2 = hpf2[index]; 57538c2ecf20Sopenharmony_ci cur_hpf += desired - hweight32(power[index]); 57548c2ecf20Sopenharmony_ci cur_hpf = clamp_val(cur_hpf, 0, 10); 57558c2ecf20Sopenharmony_ci if (use == 1) 57568c2ecf20Sopenharmony_ci cur_hpf1 = cur_hpf; 57578c2ecf20Sopenharmony_ci else 57588c2ecf20Sopenharmony_ci cur_hpf2 = cur_hpf; 57598c2ecf20Sopenharmony_ci } 57608c2ecf20Sopenharmony_ci 57618c2ecf20Sopenharmony_ci tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) | 57628c2ecf20Sopenharmony_ci (cur_lna << 2)); 57638c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override(dev, 0x400, tmp[0], 3, 57648c2ecf20Sopenharmony_ci false); 57658c2ecf20Sopenharmony_ci b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); 57668c2ecf20Sopenharmony_ci b43_nphy_stop_playback(dev); 57678c2ecf20Sopenharmony_ci 57688c2ecf20Sopenharmony_ci if (playtone) { 57698c2ecf20Sopenharmony_ci ret = b43_nphy_tx_tone(dev, 4000, 57708c2ecf20Sopenharmony_ci (nphy->rxcalparams & 0xFFFF), 57718c2ecf20Sopenharmony_ci false, false, true); 57728c2ecf20Sopenharmony_ci playtone = false; 57738c2ecf20Sopenharmony_ci } else { 57748c2ecf20Sopenharmony_ci b43_nphy_run_samples(dev, 160, 0xFFFF, 0, false, 57758c2ecf20Sopenharmony_ci false, true); 57768c2ecf20Sopenharmony_ci } 57778c2ecf20Sopenharmony_ci 57788c2ecf20Sopenharmony_ci if (ret == 0) { 57798c2ecf20Sopenharmony_ci if (j < 3) { 57808c2ecf20Sopenharmony_ci b43_nphy_rx_iq_est(dev, &est, 1024, 32, 57818c2ecf20Sopenharmony_ci false); 57828c2ecf20Sopenharmony_ci if (i == 0) { 57838c2ecf20Sopenharmony_ci real = est.i0_pwr; 57848c2ecf20Sopenharmony_ci imag = est.q0_pwr; 57858c2ecf20Sopenharmony_ci } else { 57868c2ecf20Sopenharmony_ci real = est.i1_pwr; 57878c2ecf20Sopenharmony_ci imag = est.q1_pwr; 57888c2ecf20Sopenharmony_ci } 57898c2ecf20Sopenharmony_ci power[i] = ((real + imag) / 1024) + 1; 57908c2ecf20Sopenharmony_ci } else { 57918c2ecf20Sopenharmony_ci b43_nphy_calc_rx_iq_comp(dev, 1 << i); 57928c2ecf20Sopenharmony_ci } 57938c2ecf20Sopenharmony_ci b43_nphy_stop_playback(dev); 57948c2ecf20Sopenharmony_ci } 57958c2ecf20Sopenharmony_ci 57968c2ecf20Sopenharmony_ci if (ret != 0) 57978c2ecf20Sopenharmony_ci break; 57988c2ecf20Sopenharmony_ci } 57998c2ecf20Sopenharmony_ci 58008c2ecf20Sopenharmony_ci b43_radio_mask(dev, B2055_C1_GENSPARE2, 0xFC); 58018c2ecf20Sopenharmony_ci b43_radio_mask(dev, B2055_C2_GENSPARE2, 0xFC); 58028c2ecf20Sopenharmony_ci b43_phy_write(dev, rfctl[1], tmp[5]); 58038c2ecf20Sopenharmony_ci b43_phy_write(dev, rfctl[0], tmp[4]); 58048c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp[3]); 58058c2ecf20Sopenharmony_ci b43_phy_write(dev, afectl_core, tmp[2]); 58068c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFSEQCA, tmp[1]); 58078c2ecf20Sopenharmony_ci 58088c2ecf20Sopenharmony_ci if (ret != 0) 58098c2ecf20Sopenharmony_ci break; 58108c2ecf20Sopenharmony_ci } 58118c2ecf20Sopenharmony_ci 58128c2ecf20Sopenharmony_ci b43_nphy_rf_ctl_override(dev, 0x400, 0, 3, true); 58138c2ecf20Sopenharmony_ci b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); 58148c2ecf20Sopenharmony_ci b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save); 58158c2ecf20Sopenharmony_ci 58168c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, 0); 58178c2ecf20Sopenharmony_ci 58188c2ecf20Sopenharmony_ci return ret; 58198c2ecf20Sopenharmony_ci} 58208c2ecf20Sopenharmony_ci 58218c2ecf20Sopenharmony_cistatic int b43_nphy_rev3_cal_rx_iq(struct b43_wldev *dev, 58228c2ecf20Sopenharmony_ci struct nphy_txgains target, u8 type, bool debug) 58238c2ecf20Sopenharmony_ci{ 58248c2ecf20Sopenharmony_ci return -1; 58258c2ecf20Sopenharmony_ci} 58268c2ecf20Sopenharmony_ci 58278c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIq */ 58288c2ecf20Sopenharmony_cistatic int b43_nphy_cal_rx_iq(struct b43_wldev *dev, 58298c2ecf20Sopenharmony_ci struct nphy_txgains target, u8 type, bool debug) 58308c2ecf20Sopenharmony_ci{ 58318c2ecf20Sopenharmony_ci if (dev->phy.rev >= 7) 58328c2ecf20Sopenharmony_ci type = 0; 58338c2ecf20Sopenharmony_ci 58348c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) 58358c2ecf20Sopenharmony_ci return b43_nphy_rev3_cal_rx_iq(dev, target, type, debug); 58368c2ecf20Sopenharmony_ci else 58378c2ecf20Sopenharmony_ci return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug); 58388c2ecf20Sopenharmony_ci} 58398c2ecf20Sopenharmony_ci 58408c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */ 58418c2ecf20Sopenharmony_cistatic void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask) 58428c2ecf20Sopenharmony_ci{ 58438c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 58448c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = phy->n; 58458c2ecf20Sopenharmony_ci /* u16 buf[16]; it's rev3+ */ 58468c2ecf20Sopenharmony_ci 58478c2ecf20Sopenharmony_ci nphy->phyrxchain = mask; 58488c2ecf20Sopenharmony_ci 58498c2ecf20Sopenharmony_ci if (0 /* FIXME clk */) 58508c2ecf20Sopenharmony_ci return; 58518c2ecf20Sopenharmony_ci 58528c2ecf20Sopenharmony_ci b43_mac_suspend(dev); 58538c2ecf20Sopenharmony_ci 58548c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 58558c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, true); 58568c2ecf20Sopenharmony_ci 58578c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN, 58588c2ecf20Sopenharmony_ci (mask & 0x3) << B43_NPHY_RFSEQCA_RXEN_SHIFT); 58598c2ecf20Sopenharmony_ci 58608c2ecf20Sopenharmony_ci if ((mask & 0x3) != 0x3) { 58618c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 1); 58628c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) { 58638c2ecf20Sopenharmony_ci /* TODO */ 58648c2ecf20Sopenharmony_ci } 58658c2ecf20Sopenharmony_ci } else { 58668c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 0x1E); 58678c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) { 58688c2ecf20Sopenharmony_ci /* TODO */ 58698c2ecf20Sopenharmony_ci } 58708c2ecf20Sopenharmony_ci } 58718c2ecf20Sopenharmony_ci 58728c2ecf20Sopenharmony_ci b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); 58738c2ecf20Sopenharmony_ci 58748c2ecf20Sopenharmony_ci if (nphy->hang_avoid) 58758c2ecf20Sopenharmony_ci b43_nphy_stay_in_carrier_search(dev, false); 58768c2ecf20Sopenharmony_ci 58778c2ecf20Sopenharmony_ci b43_mac_enable(dev); 58788c2ecf20Sopenharmony_ci} 58798c2ecf20Sopenharmony_ci 58808c2ecf20Sopenharmony_cistatic enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev, 58818c2ecf20Sopenharmony_ci bool ignore_tssi) 58828c2ecf20Sopenharmony_ci{ 58838c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 58848c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 58858c2ecf20Sopenharmony_ci struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan; 58868c2ecf20Sopenharmony_ci struct b43_ppr *ppr = &nphy->tx_pwr_max_ppr; 58878c2ecf20Sopenharmony_ci u8 max; /* qdBm */ 58888c2ecf20Sopenharmony_ci 58898c2ecf20Sopenharmony_ci if (nphy->tx_pwr_last_recalc_freq == channel->center_freq && 58908c2ecf20Sopenharmony_ci nphy->tx_pwr_last_recalc_limit == phy->desired_txpower) 58918c2ecf20Sopenharmony_ci return B43_TXPWR_RES_DONE; 58928c2ecf20Sopenharmony_ci 58938c2ecf20Sopenharmony_ci /* Make sure we have a clean PPR */ 58948c2ecf20Sopenharmony_ci b43_ppr_clear(dev, ppr); 58958c2ecf20Sopenharmony_ci 58968c2ecf20Sopenharmony_ci /* HW limitations */ 58978c2ecf20Sopenharmony_ci b43_ppr_load_max_from_sprom(dev, ppr, B43_BAND_2G); 58988c2ecf20Sopenharmony_ci 58998c2ecf20Sopenharmony_ci /* Regulatory & user settings */ 59008c2ecf20Sopenharmony_ci max = INT_TO_Q52(phy->chandef->chan->max_power); 59018c2ecf20Sopenharmony_ci if (phy->desired_txpower) 59028c2ecf20Sopenharmony_ci max = min_t(u8, max, INT_TO_Q52(phy->desired_txpower)); 59038c2ecf20Sopenharmony_ci b43_ppr_apply_max(dev, ppr, max); 59048c2ecf20Sopenharmony_ci if (b43_debug(dev, B43_DBG_XMITPOWER)) 59058c2ecf20Sopenharmony_ci b43dbg(dev->wl, "Calculated TX power: " Q52_FMT "\n", 59068c2ecf20Sopenharmony_ci Q52_ARG(b43_ppr_get_max(dev, ppr))); 59078c2ecf20Sopenharmony_ci 59088c2ecf20Sopenharmony_ci /* TODO: Enable this once we get gains working */ 59098c2ecf20Sopenharmony_ci#if 0 59108c2ecf20Sopenharmony_ci /* Some extra gains */ 59118c2ecf20Sopenharmony_ci hw_gain = 6; /* N-PHY specific */ 59128c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) 59138c2ecf20Sopenharmony_ci hw_gain += sprom->antenna_gain.a0; 59148c2ecf20Sopenharmony_ci else 59158c2ecf20Sopenharmony_ci hw_gain += sprom->antenna_gain.a1; 59168c2ecf20Sopenharmony_ci b43_ppr_add(dev, ppr, -hw_gain); 59178c2ecf20Sopenharmony_ci#endif 59188c2ecf20Sopenharmony_ci 59198c2ecf20Sopenharmony_ci /* Make sure we didn't go too low */ 59208c2ecf20Sopenharmony_ci b43_ppr_apply_min(dev, ppr, INT_TO_Q52(8)); 59218c2ecf20Sopenharmony_ci 59228c2ecf20Sopenharmony_ci /* Apply */ 59238c2ecf20Sopenharmony_ci b43_mac_suspend(dev); 59248c2ecf20Sopenharmony_ci b43_nphy_tx_power_ctl_setup(dev); 59258c2ecf20Sopenharmony_ci if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) { 59268c2ecf20Sopenharmony_ci b43_maskset32(dev, B43_MMIO_MACCTL, ~0, B43_MACCTL_PHY_LOCK); 59278c2ecf20Sopenharmony_ci b43_read32(dev, B43_MMIO_MACCTL); 59288c2ecf20Sopenharmony_ci udelay(1); 59298c2ecf20Sopenharmony_ci } 59308c2ecf20Sopenharmony_ci b43_nphy_tx_power_ctrl(dev, nphy->txpwrctrl); 59318c2ecf20Sopenharmony_ci if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) 59328c2ecf20Sopenharmony_ci b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_PHY_LOCK, 0); 59338c2ecf20Sopenharmony_ci b43_mac_enable(dev); 59348c2ecf20Sopenharmony_ci 59358c2ecf20Sopenharmony_ci nphy->tx_pwr_last_recalc_freq = channel->center_freq; 59368c2ecf20Sopenharmony_ci nphy->tx_pwr_last_recalc_limit = phy->desired_txpower; 59378c2ecf20Sopenharmony_ci 59388c2ecf20Sopenharmony_ci return B43_TXPWR_RES_DONE; 59398c2ecf20Sopenharmony_ci} 59408c2ecf20Sopenharmony_ci 59418c2ecf20Sopenharmony_ci/************************************************** 59428c2ecf20Sopenharmony_ci * N-PHY init 59438c2ecf20Sopenharmony_ci **************************************************/ 59448c2ecf20Sopenharmony_ci 59458c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */ 59468c2ecf20Sopenharmony_cistatic void b43_nphy_update_mimo_config(struct b43_wldev *dev, s32 preamble) 59478c2ecf20Sopenharmony_ci{ 59488c2ecf20Sopenharmony_ci u16 mimocfg = b43_phy_read(dev, B43_NPHY_MIMOCFG); 59498c2ecf20Sopenharmony_ci 59508c2ecf20Sopenharmony_ci mimocfg |= B43_NPHY_MIMOCFG_AUTO; 59518c2ecf20Sopenharmony_ci if (preamble == 1) 59528c2ecf20Sopenharmony_ci mimocfg |= B43_NPHY_MIMOCFG_GFMIX; 59538c2ecf20Sopenharmony_ci else 59548c2ecf20Sopenharmony_ci mimocfg &= ~B43_NPHY_MIMOCFG_GFMIX; 59558c2ecf20Sopenharmony_ci 59568c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_MIMOCFG, mimocfg); 59578c2ecf20Sopenharmony_ci} 59588c2ecf20Sopenharmony_ci 59598c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/BPHYInit */ 59608c2ecf20Sopenharmony_cistatic void b43_nphy_bphy_init(struct b43_wldev *dev) 59618c2ecf20Sopenharmony_ci{ 59628c2ecf20Sopenharmony_ci unsigned int i; 59638c2ecf20Sopenharmony_ci u16 val; 59648c2ecf20Sopenharmony_ci 59658c2ecf20Sopenharmony_ci val = 0x1E1F; 59668c2ecf20Sopenharmony_ci for (i = 0; i < 16; i++) { 59678c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val); 59688c2ecf20Sopenharmony_ci val -= 0x202; 59698c2ecf20Sopenharmony_ci } 59708c2ecf20Sopenharmony_ci val = 0x3E3F; 59718c2ecf20Sopenharmony_ci for (i = 0; i < 16; i++) { 59728c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val); 59738c2ecf20Sopenharmony_ci val -= 0x202; 59748c2ecf20Sopenharmony_ci } 59758c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668); 59768c2ecf20Sopenharmony_ci} 59778c2ecf20Sopenharmony_ci 59788c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */ 59798c2ecf20Sopenharmony_cistatic void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init) 59808c2ecf20Sopenharmony_ci{ 59818c2ecf20Sopenharmony_ci if (dev->phy.rev >= 7) 59828c2ecf20Sopenharmony_ci return; 59838c2ecf20Sopenharmony_ci 59848c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) { 59858c2ecf20Sopenharmony_ci if (!init) 59868c2ecf20Sopenharmony_ci return; 59878c2ecf20Sopenharmony_ci if (0 /* FIXME */) { 59888c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(9, 2), 0x211); 59898c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(9, 3), 0x222); 59908c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(9, 8), 0x144); 59918c2ecf20Sopenharmony_ci b43_ntab_write(dev, B43_NTAB16(9, 12), 0x188); 59928c2ecf20Sopenharmony_ci } 59938c2ecf20Sopenharmony_ci } else { 59948c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0); 59958c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0); 59968c2ecf20Sopenharmony_ci 59978c2ecf20Sopenharmony_ci switch (dev->dev->bus_type) { 59988c2ecf20Sopenharmony_ci#ifdef CONFIG_B43_BCMA 59998c2ecf20Sopenharmony_ci case B43_BUS_BCMA: 60008c2ecf20Sopenharmony_ci bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc, 60018c2ecf20Sopenharmony_ci 0xFC00, 0xFC00); 60028c2ecf20Sopenharmony_ci break; 60038c2ecf20Sopenharmony_ci#endif 60048c2ecf20Sopenharmony_ci#ifdef CONFIG_B43_SSB 60058c2ecf20Sopenharmony_ci case B43_BUS_SSB: 60068c2ecf20Sopenharmony_ci ssb_chipco_gpio_control(&dev->dev->sdev->bus->chipco, 60078c2ecf20Sopenharmony_ci 0xFC00, 0xFC00); 60088c2ecf20Sopenharmony_ci break; 60098c2ecf20Sopenharmony_ci#endif 60108c2ecf20Sopenharmony_ci } 60118c2ecf20Sopenharmony_ci 60128c2ecf20Sopenharmony_ci b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0); 60138c2ecf20Sopenharmony_ci b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, 0xFC00); 60148c2ecf20Sopenharmony_ci b43_maskset16(dev, B43_MMIO_GPIO_CONTROL, (~0xFC00 & 0xFFFF), 60158c2ecf20Sopenharmony_ci 0); 60168c2ecf20Sopenharmony_ci 60178c2ecf20Sopenharmony_ci if (init) { 60188c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); 60198c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301); 60208c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); 60218c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); 60228c2ecf20Sopenharmony_ci } 60238c2ecf20Sopenharmony_ci } 60248c2ecf20Sopenharmony_ci} 60258c2ecf20Sopenharmony_ci 60268c2ecf20Sopenharmony_ci/* http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N */ 60278c2ecf20Sopenharmony_cistatic int b43_phy_initn(struct b43_wldev *dev) 60288c2ecf20Sopenharmony_ci{ 60298c2ecf20Sopenharmony_ci struct ssb_sprom *sprom = dev->dev->bus_sprom; 60308c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 60318c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = phy->n; 60328c2ecf20Sopenharmony_ci u8 tx_pwr_state; 60338c2ecf20Sopenharmony_ci struct nphy_txgains target; 60348c2ecf20Sopenharmony_ci u16 tmp; 60358c2ecf20Sopenharmony_ci bool do_rssi_cal; 60368c2ecf20Sopenharmony_ci 60378c2ecf20Sopenharmony_ci u16 clip[2]; 60388c2ecf20Sopenharmony_ci bool do_cal = false; 60398c2ecf20Sopenharmony_ci 60408c2ecf20Sopenharmony_ci if ((dev->phy.rev >= 3) && 60418c2ecf20Sopenharmony_ci (sprom->boardflags_lo & B43_BFL_EXTLNA) && 60428c2ecf20Sopenharmony_ci (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)) { 60438c2ecf20Sopenharmony_ci switch (dev->dev->bus_type) { 60448c2ecf20Sopenharmony_ci#ifdef CONFIG_B43_BCMA 60458c2ecf20Sopenharmony_ci case B43_BUS_BCMA: 60468c2ecf20Sopenharmony_ci bcma_cc_set32(&dev->dev->bdev->bus->drv_cc, 60478c2ecf20Sopenharmony_ci BCMA_CC_CHIPCTL, 0x40); 60488c2ecf20Sopenharmony_ci break; 60498c2ecf20Sopenharmony_ci#endif 60508c2ecf20Sopenharmony_ci#ifdef CONFIG_B43_SSB 60518c2ecf20Sopenharmony_ci case B43_BUS_SSB: 60528c2ecf20Sopenharmony_ci chipco_set32(&dev->dev->sdev->bus->chipco, 60538c2ecf20Sopenharmony_ci SSB_CHIPCO_CHIPCTL, 0x40); 60548c2ecf20Sopenharmony_ci break; 60558c2ecf20Sopenharmony_ci#endif 60568c2ecf20Sopenharmony_ci } 60578c2ecf20Sopenharmony_ci } 60588c2ecf20Sopenharmony_ci nphy->use_int_tx_iq_lo_cal = b43_nphy_ipa(dev) || 60598c2ecf20Sopenharmony_ci phy->rev >= 7 || 60608c2ecf20Sopenharmony_ci (phy->rev >= 5 && 60618c2ecf20Sopenharmony_ci sprom->boardflags2_hi & B43_BFH2_INTERNDET_TXIQCAL); 60628c2ecf20Sopenharmony_ci nphy->deaf_count = 0; 60638c2ecf20Sopenharmony_ci b43_nphy_tables_init(dev); 60648c2ecf20Sopenharmony_ci nphy->crsminpwr_adjusted = false; 60658c2ecf20Sopenharmony_ci nphy->noisevars_adjusted = false; 60668c2ecf20Sopenharmony_ci 60678c2ecf20Sopenharmony_ci /* Clear all overrides */ 60688c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) { 60698c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, 0); 60708c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0); 60718c2ecf20Sopenharmony_ci if (phy->rev >= 7) { 60728c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER3, 0); 60738c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER4, 0); 60748c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER5, 0); 60758c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_REV7_RF_CTL_OVER6, 0); 60768c2ecf20Sopenharmony_ci } 60778c2ecf20Sopenharmony_ci if (phy->rev >= 19) { 60788c2ecf20Sopenharmony_ci /* TODO */ 60798c2ecf20Sopenharmony_ci } 60808c2ecf20Sopenharmony_ci 60818c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, 0); 60828c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, 0); 60838c2ecf20Sopenharmony_ci } else { 60848c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0); 60858c2ecf20Sopenharmony_ci } 60868c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 0); 60878c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 0); 60888c2ecf20Sopenharmony_ci if (dev->phy.rev < 6) { 60898c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0); 60908c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0); 60918c2ecf20Sopenharmony_ci } 60928c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_RFSEQMODE, 60938c2ecf20Sopenharmony_ci ~(B43_NPHY_RFSEQMODE_CAOVER | 60948c2ecf20Sopenharmony_ci B43_NPHY_RFSEQMODE_TROVER)); 60958c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) 60968c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, 0); 60978c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 0); 60988c2ecf20Sopenharmony_ci 60998c2ecf20Sopenharmony_ci if (dev->phy.rev <= 2) { 61008c2ecf20Sopenharmony_ci tmp = (dev->phy.rev == 2) ? 0x3B : 0x40; 61018c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, 61028c2ecf20Sopenharmony_ci ~B43_NPHY_BPHY_CTL3_SCALE, 61038c2ecf20Sopenharmony_ci tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT); 61048c2ecf20Sopenharmony_ci } 61058c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20); 61068c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20); 61078c2ecf20Sopenharmony_ci 61088c2ecf20Sopenharmony_ci if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD || 61098c2ecf20Sopenharmony_ci (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE && 61108c2ecf20Sopenharmony_ci dev->dev->board_type == BCMA_BOARD_TYPE_BCM943224M93)) 61118c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0); 61128c2ecf20Sopenharmony_ci else 61138c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8); 61148c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 0xC8); 61158c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50); 61168c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30); 61178c2ecf20Sopenharmony_ci 61188c2ecf20Sopenharmony_ci if (phy->rev < 8) 61198c2ecf20Sopenharmony_ci b43_nphy_update_mimo_config(dev, nphy->preamble_override); 61208c2ecf20Sopenharmony_ci 61218c2ecf20Sopenharmony_ci b43_nphy_update_txrx_chain(dev); 61228c2ecf20Sopenharmony_ci 61238c2ecf20Sopenharmony_ci if (phy->rev < 2) { 61248c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8); 61258c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4); 61268c2ecf20Sopenharmony_ci } 61278c2ecf20Sopenharmony_ci 61288c2ecf20Sopenharmony_ci if (b43_nphy_ipa(dev)) { 61298c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_PAPD_EN0, 0x1); 61308c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ0, 0x007F, 61318c2ecf20Sopenharmony_ci nphy->papd_epsilon_offset[0] << 7); 61328c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_PAPD_EN1, 0x1); 61338c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ1, 0x007F, 61348c2ecf20Sopenharmony_ci nphy->papd_epsilon_offset[1] << 7); 61358c2ecf20Sopenharmony_ci b43_nphy_int_pa_set_tx_dig_filters(dev); 61368c2ecf20Sopenharmony_ci } else if (phy->rev >= 5) { 61378c2ecf20Sopenharmony_ci b43_nphy_ext_pa_set_tx_dig_filters(dev); 61388c2ecf20Sopenharmony_ci } 61398c2ecf20Sopenharmony_ci 61408c2ecf20Sopenharmony_ci b43_nphy_workarounds(dev); 61418c2ecf20Sopenharmony_ci 61428c2ecf20Sopenharmony_ci /* Reset CCA, in init code it differs a little from standard way */ 61438c2ecf20Sopenharmony_ci b43_phy_force_clock(dev, 1); 61448c2ecf20Sopenharmony_ci tmp = b43_phy_read(dev, B43_NPHY_BBCFG); 61458c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA); 61468c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA); 61478c2ecf20Sopenharmony_ci b43_phy_force_clock(dev, 0); 61488c2ecf20Sopenharmony_ci 61498c2ecf20Sopenharmony_ci b43_mac_phy_clock_set(dev, true); 61508c2ecf20Sopenharmony_ci 61518c2ecf20Sopenharmony_ci if (phy->rev < 7) { 61528c2ecf20Sopenharmony_ci b43_nphy_pa_override(dev, false); 61538c2ecf20Sopenharmony_ci b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); 61548c2ecf20Sopenharmony_ci b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); 61558c2ecf20Sopenharmony_ci b43_nphy_pa_override(dev, true); 61568c2ecf20Sopenharmony_ci } 61578c2ecf20Sopenharmony_ci 61588c2ecf20Sopenharmony_ci b43_nphy_classifier(dev, 0, 0); 61598c2ecf20Sopenharmony_ci b43_nphy_read_clip_detection(dev, clip); 61608c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) 61618c2ecf20Sopenharmony_ci b43_nphy_bphy_init(dev); 61628c2ecf20Sopenharmony_ci 61638c2ecf20Sopenharmony_ci tx_pwr_state = nphy->txpwrctrl; 61648c2ecf20Sopenharmony_ci b43_nphy_tx_power_ctrl(dev, false); 61658c2ecf20Sopenharmony_ci b43_nphy_tx_power_fix(dev); 61668c2ecf20Sopenharmony_ci b43_nphy_tx_power_ctl_idle_tssi(dev); 61678c2ecf20Sopenharmony_ci b43_nphy_tx_power_ctl_setup(dev); 61688c2ecf20Sopenharmony_ci b43_nphy_tx_gain_table_upload(dev); 61698c2ecf20Sopenharmony_ci 61708c2ecf20Sopenharmony_ci if (nphy->phyrxchain != 3) 61718c2ecf20Sopenharmony_ci b43_nphy_set_rx_core_state(dev, nphy->phyrxchain); 61728c2ecf20Sopenharmony_ci if (nphy->mphase_cal_phase_id > 0) { 61738c2ecf20Sopenharmony_ci ;/* TODO PHY Periodic Calibration Multi-Phase Restart */ 61748c2ecf20Sopenharmony_ci } 61758c2ecf20Sopenharmony_ci 61768c2ecf20Sopenharmony_ci do_rssi_cal = false; 61778c2ecf20Sopenharmony_ci if (phy->rev >= 3) { 61788c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) 61798c2ecf20Sopenharmony_ci do_rssi_cal = !nphy->rssical_chanspec_2G.center_freq; 61808c2ecf20Sopenharmony_ci else 61818c2ecf20Sopenharmony_ci do_rssi_cal = !nphy->rssical_chanspec_5G.center_freq; 61828c2ecf20Sopenharmony_ci 61838c2ecf20Sopenharmony_ci if (do_rssi_cal) 61848c2ecf20Sopenharmony_ci b43_nphy_rssi_cal(dev); 61858c2ecf20Sopenharmony_ci else 61868c2ecf20Sopenharmony_ci b43_nphy_restore_rssi_cal(dev); 61878c2ecf20Sopenharmony_ci } else { 61888c2ecf20Sopenharmony_ci b43_nphy_rssi_cal(dev); 61898c2ecf20Sopenharmony_ci } 61908c2ecf20Sopenharmony_ci 61918c2ecf20Sopenharmony_ci if (!((nphy->measure_hold & 0x6) != 0)) { 61928c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) 61938c2ecf20Sopenharmony_ci do_cal = !nphy->iqcal_chanspec_2G.center_freq; 61948c2ecf20Sopenharmony_ci else 61958c2ecf20Sopenharmony_ci do_cal = !nphy->iqcal_chanspec_5G.center_freq; 61968c2ecf20Sopenharmony_ci 61978c2ecf20Sopenharmony_ci if (nphy->mute) 61988c2ecf20Sopenharmony_ci do_cal = false; 61998c2ecf20Sopenharmony_ci 62008c2ecf20Sopenharmony_ci if (do_cal) { 62018c2ecf20Sopenharmony_ci target = b43_nphy_get_tx_gains(dev); 62028c2ecf20Sopenharmony_ci 62038c2ecf20Sopenharmony_ci if (nphy->antsel_type == 2) 62048c2ecf20Sopenharmony_ci b43_nphy_superswitch_init(dev, true); 62058c2ecf20Sopenharmony_ci if (nphy->perical != 2) { 62068c2ecf20Sopenharmony_ci b43_nphy_rssi_cal(dev); 62078c2ecf20Sopenharmony_ci if (phy->rev >= 3) { 62088c2ecf20Sopenharmony_ci nphy->cal_orig_pwr_idx[0] = 62098c2ecf20Sopenharmony_ci nphy->txpwrindex[0].index_internal; 62108c2ecf20Sopenharmony_ci nphy->cal_orig_pwr_idx[1] = 62118c2ecf20Sopenharmony_ci nphy->txpwrindex[1].index_internal; 62128c2ecf20Sopenharmony_ci /* TODO N PHY Pre Calibrate TX Gain */ 62138c2ecf20Sopenharmony_ci target = b43_nphy_get_tx_gains(dev); 62148c2ecf20Sopenharmony_ci } 62158c2ecf20Sopenharmony_ci if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false)) 62168c2ecf20Sopenharmony_ci if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0) 62178c2ecf20Sopenharmony_ci b43_nphy_save_cal(dev); 62188c2ecf20Sopenharmony_ci } else if (nphy->mphase_cal_phase_id == 0) { 62198c2ecf20Sopenharmony_ci ;/* N PHY Periodic Calibration with arg 3 */ 62208c2ecf20Sopenharmony_ci } 62218c2ecf20Sopenharmony_ci } else { 62228c2ecf20Sopenharmony_ci b43_nphy_restore_cal(dev); 62238c2ecf20Sopenharmony_ci } 62248c2ecf20Sopenharmony_ci } 62258c2ecf20Sopenharmony_ci 62268c2ecf20Sopenharmony_ci b43_nphy_tx_pwr_ctrl_coef_setup(dev); 62278c2ecf20Sopenharmony_ci b43_nphy_tx_power_ctrl(dev, tx_pwr_state); 62288c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TXMACIF_HOLDOFF, 0x0015); 62298c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320); 62308c2ecf20Sopenharmony_ci if (phy->rev >= 3 && phy->rev <= 6) 62318c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x0032); 62328c2ecf20Sopenharmony_ci b43_nphy_tx_lpf_bw(dev); 62338c2ecf20Sopenharmony_ci if (phy->rev >= 3) 62348c2ecf20Sopenharmony_ci b43_nphy_spur_workaround(dev); 62358c2ecf20Sopenharmony_ci 62368c2ecf20Sopenharmony_ci return 0; 62378c2ecf20Sopenharmony_ci} 62388c2ecf20Sopenharmony_ci 62398c2ecf20Sopenharmony_ci/************************************************** 62408c2ecf20Sopenharmony_ci * Channel switching ops. 62418c2ecf20Sopenharmony_ci **************************************************/ 62428c2ecf20Sopenharmony_ci 62438c2ecf20Sopenharmony_cistatic void b43_chantab_phy_upload(struct b43_wldev *dev, 62448c2ecf20Sopenharmony_ci const struct b43_phy_n_sfo_cfg *e) 62458c2ecf20Sopenharmony_ci{ 62468c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a); 62478c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2); 62488c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_BW3, e->phy_bw3); 62498c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_BW4, e->phy_bw4); 62508c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_BW5, e->phy_bw5); 62518c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_BW6, e->phy_bw6); 62528c2ecf20Sopenharmony_ci} 62538c2ecf20Sopenharmony_ci 62548c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PmuSpurAvoid */ 62558c2ecf20Sopenharmony_cistatic void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid) 62568c2ecf20Sopenharmony_ci{ 62578c2ecf20Sopenharmony_ci switch (dev->dev->bus_type) { 62588c2ecf20Sopenharmony_ci#ifdef CONFIG_B43_BCMA 62598c2ecf20Sopenharmony_ci case B43_BUS_BCMA: 62608c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pllupdate(&dev->dev->bdev->bus->drv_cc, 62618c2ecf20Sopenharmony_ci avoid); 62628c2ecf20Sopenharmony_ci break; 62638c2ecf20Sopenharmony_ci#endif 62648c2ecf20Sopenharmony_ci#ifdef CONFIG_B43_SSB 62658c2ecf20Sopenharmony_ci case B43_BUS_SSB: 62668c2ecf20Sopenharmony_ci ssb_pmu_spuravoid_pllupdate(&dev->dev->sdev->bus->chipco, 62678c2ecf20Sopenharmony_ci avoid); 62688c2ecf20Sopenharmony_ci break; 62698c2ecf20Sopenharmony_ci#endif 62708c2ecf20Sopenharmony_ci } 62718c2ecf20Sopenharmony_ci} 62728c2ecf20Sopenharmony_ci 62738c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */ 62748c2ecf20Sopenharmony_cistatic void b43_nphy_channel_setup(struct b43_wldev *dev, 62758c2ecf20Sopenharmony_ci const struct b43_phy_n_sfo_cfg *e, 62768c2ecf20Sopenharmony_ci struct ieee80211_channel *new_channel) 62778c2ecf20Sopenharmony_ci{ 62788c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 62798c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = dev->phy.n; 62808c2ecf20Sopenharmony_ci int ch = new_channel->hw_value; 62818c2ecf20Sopenharmony_ci u16 tmp16; 62828c2ecf20Sopenharmony_ci 62838c2ecf20Sopenharmony_ci if (new_channel->band == NL80211_BAND_5GHZ) { 62848c2ecf20Sopenharmony_ci /* Switch to 2 GHz for a moment to access B43_PHY_B_BBCFG */ 62858c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ); 62868c2ecf20Sopenharmony_ci 62878c2ecf20Sopenharmony_ci tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR); 62888c2ecf20Sopenharmony_ci b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4); 62898c2ecf20Sopenharmony_ci /* Put BPHY in the reset */ 62908c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_PHY_B_BBCFG, 62918c2ecf20Sopenharmony_ci B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX); 62928c2ecf20Sopenharmony_ci b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16); 62938c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ); 62948c2ecf20Sopenharmony_ci } else if (new_channel->band == NL80211_BAND_2GHZ) { 62958c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ); 62968c2ecf20Sopenharmony_ci tmp16 = b43_read16(dev, B43_MMIO_PSM_PHY_HDR); 62978c2ecf20Sopenharmony_ci b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16 | 4); 62988c2ecf20Sopenharmony_ci /* Take BPHY out of the reset */ 62998c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_PHY_B_BBCFG, 63008c2ecf20Sopenharmony_ci (u16)~(B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX)); 63018c2ecf20Sopenharmony_ci b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp16); 63028c2ecf20Sopenharmony_ci } 63038c2ecf20Sopenharmony_ci 63048c2ecf20Sopenharmony_ci b43_chantab_phy_upload(dev, e); 63058c2ecf20Sopenharmony_ci 63068c2ecf20Sopenharmony_ci if (new_channel->hw_value == 14) { 63078c2ecf20Sopenharmony_ci b43_nphy_classifier(dev, 2, 0); 63088c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_PHY_B_TEST, 0x0800); 63098c2ecf20Sopenharmony_ci } else { 63108c2ecf20Sopenharmony_ci b43_nphy_classifier(dev, 2, 2); 63118c2ecf20Sopenharmony_ci if (new_channel->band == NL80211_BAND_2GHZ) 63128c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_PHY_B_TEST, ~0x840); 63138c2ecf20Sopenharmony_ci } 63148c2ecf20Sopenharmony_ci 63158c2ecf20Sopenharmony_ci if (!nphy->txpwrctrl) 63168c2ecf20Sopenharmony_ci b43_nphy_tx_power_fix(dev); 63178c2ecf20Sopenharmony_ci 63188c2ecf20Sopenharmony_ci if (dev->phy.rev < 3) 63198c2ecf20Sopenharmony_ci b43_nphy_adjust_lna_gain_table(dev); 63208c2ecf20Sopenharmony_ci 63218c2ecf20Sopenharmony_ci b43_nphy_tx_lpf_bw(dev); 63228c2ecf20Sopenharmony_ci 63238c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3 && 63248c2ecf20Sopenharmony_ci dev->phy.n->spur_avoid != B43_SPUR_AVOID_DISABLE) { 63258c2ecf20Sopenharmony_ci u8 spuravoid = 0; 63268c2ecf20Sopenharmony_ci 63278c2ecf20Sopenharmony_ci if (dev->phy.n->spur_avoid == B43_SPUR_AVOID_FORCE) { 63288c2ecf20Sopenharmony_ci spuravoid = 1; 63298c2ecf20Sopenharmony_ci } else if (phy->rev >= 19) { 63308c2ecf20Sopenharmony_ci /* TODO */ 63318c2ecf20Sopenharmony_ci } else if (phy->rev >= 18) { 63328c2ecf20Sopenharmony_ci /* TODO */ 63338c2ecf20Sopenharmony_ci } else if (phy->rev >= 17) { 63348c2ecf20Sopenharmony_ci /* TODO: Off for channels 1-11, but check 12-14! */ 63358c2ecf20Sopenharmony_ci } else if (phy->rev >= 16) { 63368c2ecf20Sopenharmony_ci /* TODO: Off for 2 GHz, but check 5 GHz! */ 63378c2ecf20Sopenharmony_ci } else if (phy->rev >= 7) { 63388c2ecf20Sopenharmony_ci if (!b43_is_40mhz(dev)) { /* 20MHz */ 63398c2ecf20Sopenharmony_ci if (ch == 13 || ch == 14 || ch == 153) 63408c2ecf20Sopenharmony_ci spuravoid = 1; 63418c2ecf20Sopenharmony_ci } else { /* 40 MHz */ 63428c2ecf20Sopenharmony_ci if (ch == 54) 63438c2ecf20Sopenharmony_ci spuravoid = 1; 63448c2ecf20Sopenharmony_ci } 63458c2ecf20Sopenharmony_ci } else { 63468c2ecf20Sopenharmony_ci if (!b43_is_40mhz(dev)) { /* 20MHz */ 63478c2ecf20Sopenharmony_ci if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14) 63488c2ecf20Sopenharmony_ci spuravoid = 1; 63498c2ecf20Sopenharmony_ci } else { /* 40MHz */ 63508c2ecf20Sopenharmony_ci if (nphy->aband_spurwar_en && 63518c2ecf20Sopenharmony_ci (ch == 38 || ch == 102 || ch == 118)) 63528c2ecf20Sopenharmony_ci spuravoid = dev->dev->chip_id == 0x4716; 63538c2ecf20Sopenharmony_ci } 63548c2ecf20Sopenharmony_ci } 63558c2ecf20Sopenharmony_ci 63568c2ecf20Sopenharmony_ci b43_nphy_pmu_spur_avoid(dev, spuravoid); 63578c2ecf20Sopenharmony_ci 63588c2ecf20Sopenharmony_ci b43_mac_switch_freq(dev, spuravoid); 63598c2ecf20Sopenharmony_ci 63608c2ecf20Sopenharmony_ci if (dev->phy.rev == 3 || dev->phy.rev == 4) 63618c2ecf20Sopenharmony_ci b43_wireless_core_phy_pll_reset(dev); 63628c2ecf20Sopenharmony_ci 63638c2ecf20Sopenharmony_ci if (spuravoid) 63648c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTRX); 63658c2ecf20Sopenharmony_ci else 63668c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_BBCFG, 63678c2ecf20Sopenharmony_ci ~B43_NPHY_BBCFG_RSTRX & 0xFFFF); 63688c2ecf20Sopenharmony_ci 63698c2ecf20Sopenharmony_ci b43_nphy_reset_cca(dev); 63708c2ecf20Sopenharmony_ci 63718c2ecf20Sopenharmony_ci /* wl sets useless phy_isspuravoid here */ 63728c2ecf20Sopenharmony_ci } 63738c2ecf20Sopenharmony_ci 63748c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_NDATAT_DUP40, 0x3830); 63758c2ecf20Sopenharmony_ci 63768c2ecf20Sopenharmony_ci if (phy->rev >= 3) 63778c2ecf20Sopenharmony_ci b43_nphy_spur_workaround(dev); 63788c2ecf20Sopenharmony_ci} 63798c2ecf20Sopenharmony_ci 63808c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */ 63818c2ecf20Sopenharmony_cistatic int b43_nphy_set_channel(struct b43_wldev *dev, 63828c2ecf20Sopenharmony_ci struct ieee80211_channel *channel, 63838c2ecf20Sopenharmony_ci enum nl80211_channel_type channel_type) 63848c2ecf20Sopenharmony_ci{ 63858c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 63868c2ecf20Sopenharmony_ci 63878c2ecf20Sopenharmony_ci const struct b43_nphy_channeltab_entry_rev2 *tabent_r2 = NULL; 63888c2ecf20Sopenharmony_ci const struct b43_nphy_channeltab_entry_rev3 *tabent_r3 = NULL; 63898c2ecf20Sopenharmony_ci const struct b43_nphy_chantabent_rev7 *tabent_r7 = NULL; 63908c2ecf20Sopenharmony_ci const struct b43_nphy_chantabent_rev7_2g *tabent_r7_2g = NULL; 63918c2ecf20Sopenharmony_ci 63928c2ecf20Sopenharmony_ci u8 tmp; 63938c2ecf20Sopenharmony_ci 63948c2ecf20Sopenharmony_ci if (phy->rev >= 19) { 63958c2ecf20Sopenharmony_ci return -ESRCH; 63968c2ecf20Sopenharmony_ci /* TODO */ 63978c2ecf20Sopenharmony_ci } else if (phy->rev >= 7) { 63988c2ecf20Sopenharmony_ci r2057_get_chantabent_rev7(dev, channel->center_freq, 63998c2ecf20Sopenharmony_ci &tabent_r7, &tabent_r7_2g); 64008c2ecf20Sopenharmony_ci if (!tabent_r7 && !tabent_r7_2g) 64018c2ecf20Sopenharmony_ci return -ESRCH; 64028c2ecf20Sopenharmony_ci } else if (phy->rev >= 3) { 64038c2ecf20Sopenharmony_ci tabent_r3 = b43_nphy_get_chantabent_rev3(dev, 64048c2ecf20Sopenharmony_ci channel->center_freq); 64058c2ecf20Sopenharmony_ci if (!tabent_r3) 64068c2ecf20Sopenharmony_ci return -ESRCH; 64078c2ecf20Sopenharmony_ci } else { 64088c2ecf20Sopenharmony_ci tabent_r2 = b43_nphy_get_chantabent_rev2(dev, 64098c2ecf20Sopenharmony_ci channel->hw_value); 64108c2ecf20Sopenharmony_ci if (!tabent_r2) 64118c2ecf20Sopenharmony_ci return -ESRCH; 64128c2ecf20Sopenharmony_ci } 64138c2ecf20Sopenharmony_ci 64148c2ecf20Sopenharmony_ci /* Channel is set later in common code, but we need to set it on our 64158c2ecf20Sopenharmony_ci own to let this function's subcalls work properly. */ 64168c2ecf20Sopenharmony_ci phy->channel = channel->hw_value; 64178c2ecf20Sopenharmony_ci 64188c2ecf20Sopenharmony_ci#if 0 64198c2ecf20Sopenharmony_ci if (b43_channel_type_is_40mhz(phy->channel_type) != 64208c2ecf20Sopenharmony_ci b43_channel_type_is_40mhz(channel_type)) 64218c2ecf20Sopenharmony_ci ; /* TODO: BMAC BW Set (channel_type) */ 64228c2ecf20Sopenharmony_ci#endif 64238c2ecf20Sopenharmony_ci 64248c2ecf20Sopenharmony_ci if (channel_type == NL80211_CHAN_HT40PLUS) { 64258c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_NPHY_RXCTL, B43_NPHY_RXCTL_BSELU20); 64268c2ecf20Sopenharmony_ci if (phy->rev >= 7) 64278c2ecf20Sopenharmony_ci b43_phy_set(dev, 0x310, 0x8000); 64288c2ecf20Sopenharmony_ci } else if (channel_type == NL80211_CHAN_HT40MINUS) { 64298c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_RXCTL, ~B43_NPHY_RXCTL_BSELU20); 64308c2ecf20Sopenharmony_ci if (phy->rev >= 7) 64318c2ecf20Sopenharmony_ci b43_phy_mask(dev, 0x310, (u16)~0x8000); 64328c2ecf20Sopenharmony_ci } 64338c2ecf20Sopenharmony_ci 64348c2ecf20Sopenharmony_ci if (phy->rev >= 19) { 64358c2ecf20Sopenharmony_ci /* TODO */ 64368c2ecf20Sopenharmony_ci } else if (phy->rev >= 7) { 64378c2ecf20Sopenharmony_ci const struct b43_phy_n_sfo_cfg *phy_regs = tabent_r7 ? 64388c2ecf20Sopenharmony_ci &(tabent_r7->phy_regs) : &(tabent_r7_2g->phy_regs); 64398c2ecf20Sopenharmony_ci 64408c2ecf20Sopenharmony_ci if (phy->radio_rev <= 4 || phy->radio_rev == 6) { 64418c2ecf20Sopenharmony_ci tmp = (channel->band == NL80211_BAND_5GHZ) ? 2 : 0; 64428c2ecf20Sopenharmony_ci b43_radio_maskset(dev, R2057_TIA_CONFIG_CORE0, ~2, tmp); 64438c2ecf20Sopenharmony_ci b43_radio_maskset(dev, R2057_TIA_CONFIG_CORE1, ~2, tmp); 64448c2ecf20Sopenharmony_ci } 64458c2ecf20Sopenharmony_ci 64468c2ecf20Sopenharmony_ci b43_radio_2057_setup(dev, tabent_r7, tabent_r7_2g); 64478c2ecf20Sopenharmony_ci b43_nphy_channel_setup(dev, phy_regs, channel); 64488c2ecf20Sopenharmony_ci } else if (phy->rev >= 3) { 64498c2ecf20Sopenharmony_ci tmp = (channel->band == NL80211_BAND_5GHZ) ? 4 : 0; 64508c2ecf20Sopenharmony_ci b43_radio_maskset(dev, 0x08, 0xFFFB, tmp); 64518c2ecf20Sopenharmony_ci b43_radio_2056_setup(dev, tabent_r3); 64528c2ecf20Sopenharmony_ci b43_nphy_channel_setup(dev, &(tabent_r3->phy_regs), channel); 64538c2ecf20Sopenharmony_ci } else { 64548c2ecf20Sopenharmony_ci tmp = (channel->band == NL80211_BAND_5GHZ) ? 0x0020 : 0x0050; 64558c2ecf20Sopenharmony_ci b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp); 64568c2ecf20Sopenharmony_ci b43_radio_2055_setup(dev, tabent_r2); 64578c2ecf20Sopenharmony_ci b43_nphy_channel_setup(dev, &(tabent_r2->phy_regs), channel); 64588c2ecf20Sopenharmony_ci } 64598c2ecf20Sopenharmony_ci 64608c2ecf20Sopenharmony_ci return 0; 64618c2ecf20Sopenharmony_ci} 64628c2ecf20Sopenharmony_ci 64638c2ecf20Sopenharmony_ci/************************************************** 64648c2ecf20Sopenharmony_ci * Basic PHY ops. 64658c2ecf20Sopenharmony_ci **************************************************/ 64668c2ecf20Sopenharmony_ci 64678c2ecf20Sopenharmony_cistatic int b43_nphy_op_allocate(struct b43_wldev *dev) 64688c2ecf20Sopenharmony_ci{ 64698c2ecf20Sopenharmony_ci struct b43_phy_n *nphy; 64708c2ecf20Sopenharmony_ci 64718c2ecf20Sopenharmony_ci nphy = kzalloc(sizeof(*nphy), GFP_KERNEL); 64728c2ecf20Sopenharmony_ci if (!nphy) 64738c2ecf20Sopenharmony_ci return -ENOMEM; 64748c2ecf20Sopenharmony_ci 64758c2ecf20Sopenharmony_ci dev->phy.n = nphy; 64768c2ecf20Sopenharmony_ci 64778c2ecf20Sopenharmony_ci return 0; 64788c2ecf20Sopenharmony_ci} 64798c2ecf20Sopenharmony_ci 64808c2ecf20Sopenharmony_cistatic void b43_nphy_op_prepare_structs(struct b43_wldev *dev) 64818c2ecf20Sopenharmony_ci{ 64828c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 64838c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = phy->n; 64848c2ecf20Sopenharmony_ci struct ssb_sprom *sprom = dev->dev->bus_sprom; 64858c2ecf20Sopenharmony_ci 64868c2ecf20Sopenharmony_ci memset(nphy, 0, sizeof(*nphy)); 64878c2ecf20Sopenharmony_ci 64888c2ecf20Sopenharmony_ci nphy->hang_avoid = (phy->rev == 3 || phy->rev == 4); 64898c2ecf20Sopenharmony_ci nphy->spur_avoid = (phy->rev >= 3) ? 64908c2ecf20Sopenharmony_ci B43_SPUR_AVOID_AUTO : B43_SPUR_AVOID_DISABLE; 64918c2ecf20Sopenharmony_ci nphy->gain_boost = true; /* this way we follow wl, assume it is true */ 64928c2ecf20Sopenharmony_ci nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */ 64938c2ecf20Sopenharmony_ci nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */ 64948c2ecf20Sopenharmony_ci nphy->perical = 2; /* avoid additional rssi cal on init (like wl) */ 64958c2ecf20Sopenharmony_ci /* 128 can mean disabled-by-default state of TX pwr ctl. Max value is 64968c2ecf20Sopenharmony_ci * 0x7f == 127 and we check for 128 when restoring TX pwr ctl. */ 64978c2ecf20Sopenharmony_ci nphy->tx_pwr_idx[0] = 128; 64988c2ecf20Sopenharmony_ci nphy->tx_pwr_idx[1] = 128; 64998c2ecf20Sopenharmony_ci 65008c2ecf20Sopenharmony_ci /* Hardware TX power control and 5GHz power gain */ 65018c2ecf20Sopenharmony_ci nphy->txpwrctrl = false; 65028c2ecf20Sopenharmony_ci nphy->pwg_gain_5ghz = false; 65038c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3 || 65048c2ecf20Sopenharmony_ci (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE && 65058c2ecf20Sopenharmony_ci (dev->dev->core_rev == 11 || dev->dev->core_rev == 12))) { 65068c2ecf20Sopenharmony_ci nphy->txpwrctrl = true; 65078c2ecf20Sopenharmony_ci nphy->pwg_gain_5ghz = true; 65088c2ecf20Sopenharmony_ci } else if (sprom->revision >= 4) { 65098c2ecf20Sopenharmony_ci if (dev->phy.rev >= 2 && 65108c2ecf20Sopenharmony_ci (sprom->boardflags2_lo & B43_BFL2_TXPWRCTRL_EN)) { 65118c2ecf20Sopenharmony_ci nphy->txpwrctrl = true; 65128c2ecf20Sopenharmony_ci#ifdef CONFIG_B43_SSB 65138c2ecf20Sopenharmony_ci if (dev->dev->bus_type == B43_BUS_SSB && 65148c2ecf20Sopenharmony_ci dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI) { 65158c2ecf20Sopenharmony_ci struct pci_dev *pdev = 65168c2ecf20Sopenharmony_ci dev->dev->sdev->bus->host_pci; 65178c2ecf20Sopenharmony_ci if (pdev->device == 0x4328 || 65188c2ecf20Sopenharmony_ci pdev->device == 0x432a) 65198c2ecf20Sopenharmony_ci nphy->pwg_gain_5ghz = true; 65208c2ecf20Sopenharmony_ci } 65218c2ecf20Sopenharmony_ci#endif 65228c2ecf20Sopenharmony_ci } else if (sprom->boardflags2_lo & B43_BFL2_5G_PWRGAIN) { 65238c2ecf20Sopenharmony_ci nphy->pwg_gain_5ghz = true; 65248c2ecf20Sopenharmony_ci } 65258c2ecf20Sopenharmony_ci } 65268c2ecf20Sopenharmony_ci 65278c2ecf20Sopenharmony_ci if (dev->phy.rev >= 3) { 65288c2ecf20Sopenharmony_ci nphy->ipa2g_on = sprom->fem.ghz2.extpa_gain == 2; 65298c2ecf20Sopenharmony_ci nphy->ipa5g_on = sprom->fem.ghz5.extpa_gain == 2; 65308c2ecf20Sopenharmony_ci } 65318c2ecf20Sopenharmony_ci} 65328c2ecf20Sopenharmony_ci 65338c2ecf20Sopenharmony_cistatic void b43_nphy_op_free(struct b43_wldev *dev) 65348c2ecf20Sopenharmony_ci{ 65358c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 65368c2ecf20Sopenharmony_ci struct b43_phy_n *nphy = phy->n; 65378c2ecf20Sopenharmony_ci 65388c2ecf20Sopenharmony_ci kfree(nphy); 65398c2ecf20Sopenharmony_ci phy->n = NULL; 65408c2ecf20Sopenharmony_ci} 65418c2ecf20Sopenharmony_ci 65428c2ecf20Sopenharmony_cistatic int b43_nphy_op_init(struct b43_wldev *dev) 65438c2ecf20Sopenharmony_ci{ 65448c2ecf20Sopenharmony_ci return b43_phy_initn(dev); 65458c2ecf20Sopenharmony_ci} 65468c2ecf20Sopenharmony_ci 65478c2ecf20Sopenharmony_cistatic inline void check_phyreg(struct b43_wldev *dev, u16 offset) 65488c2ecf20Sopenharmony_ci{ 65498c2ecf20Sopenharmony_ci#if B43_DEBUG 65508c2ecf20Sopenharmony_ci if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) { 65518c2ecf20Sopenharmony_ci /* OFDM registers are onnly available on A/G-PHYs */ 65528c2ecf20Sopenharmony_ci b43err(dev->wl, "Invalid OFDM PHY access at " 65538c2ecf20Sopenharmony_ci "0x%04X on N-PHY\n", offset); 65548c2ecf20Sopenharmony_ci dump_stack(); 65558c2ecf20Sopenharmony_ci } 65568c2ecf20Sopenharmony_ci if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) { 65578c2ecf20Sopenharmony_ci /* Ext-G registers are only available on G-PHYs */ 65588c2ecf20Sopenharmony_ci b43err(dev->wl, "Invalid EXT-G PHY access at " 65598c2ecf20Sopenharmony_ci "0x%04X on N-PHY\n", offset); 65608c2ecf20Sopenharmony_ci dump_stack(); 65618c2ecf20Sopenharmony_ci } 65628c2ecf20Sopenharmony_ci#endif /* B43_DEBUG */ 65638c2ecf20Sopenharmony_ci} 65648c2ecf20Sopenharmony_ci 65658c2ecf20Sopenharmony_cistatic void b43_nphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask, 65668c2ecf20Sopenharmony_ci u16 set) 65678c2ecf20Sopenharmony_ci{ 65688c2ecf20Sopenharmony_ci check_phyreg(dev, reg); 65698c2ecf20Sopenharmony_ci b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg); 65708c2ecf20Sopenharmony_ci b43_maskset16(dev, B43_MMIO_PHY_DATA, mask, set); 65718c2ecf20Sopenharmony_ci dev->phy.writes_counter = 1; 65728c2ecf20Sopenharmony_ci} 65738c2ecf20Sopenharmony_ci 65748c2ecf20Sopenharmony_cistatic u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg) 65758c2ecf20Sopenharmony_ci{ 65768c2ecf20Sopenharmony_ci /* Register 1 is a 32-bit register. */ 65778c2ecf20Sopenharmony_ci B43_WARN_ON(dev->phy.rev < 7 && reg == 1); 65788c2ecf20Sopenharmony_ci 65798c2ecf20Sopenharmony_ci if (dev->phy.rev >= 7) 65808c2ecf20Sopenharmony_ci reg |= 0x200; /* Radio 0x2057 */ 65818c2ecf20Sopenharmony_ci else 65828c2ecf20Sopenharmony_ci reg |= 0x100; 65838c2ecf20Sopenharmony_ci 65848c2ecf20Sopenharmony_ci b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg); 65858c2ecf20Sopenharmony_ci return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW); 65868c2ecf20Sopenharmony_ci} 65878c2ecf20Sopenharmony_ci 65888c2ecf20Sopenharmony_cistatic void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) 65898c2ecf20Sopenharmony_ci{ 65908c2ecf20Sopenharmony_ci /* Register 1 is a 32-bit register. */ 65918c2ecf20Sopenharmony_ci B43_WARN_ON(dev->phy.rev < 7 && reg == 1); 65928c2ecf20Sopenharmony_ci 65938c2ecf20Sopenharmony_ci b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg); 65948c2ecf20Sopenharmony_ci b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); 65958c2ecf20Sopenharmony_ci} 65968c2ecf20Sopenharmony_ci 65978c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */ 65988c2ecf20Sopenharmony_cistatic void b43_nphy_op_software_rfkill(struct b43_wldev *dev, 65998c2ecf20Sopenharmony_ci bool blocked) 66008c2ecf20Sopenharmony_ci{ 66018c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 66028c2ecf20Sopenharmony_ci 66038c2ecf20Sopenharmony_ci if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED) 66048c2ecf20Sopenharmony_ci b43err(dev->wl, "MAC not suspended\n"); 66058c2ecf20Sopenharmony_ci 66068c2ecf20Sopenharmony_ci if (blocked) { 66078c2ecf20Sopenharmony_ci if (phy->rev >= 19) { 66088c2ecf20Sopenharmony_ci /* TODO */ 66098c2ecf20Sopenharmony_ci } else if (phy->rev >= 8) { 66108c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, 66118c2ecf20Sopenharmony_ci ~B43_NPHY_RFCTL_CMD_CHIP0PU); 66128c2ecf20Sopenharmony_ci } else if (phy->rev >= 7) { 66138c2ecf20Sopenharmony_ci /* Nothing needed */ 66148c2ecf20Sopenharmony_ci } else if (phy->rev >= 3) { 66158c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, 66168c2ecf20Sopenharmony_ci ~B43_NPHY_RFCTL_CMD_CHIP0PU); 66178c2ecf20Sopenharmony_ci 66188c2ecf20Sopenharmony_ci b43_radio_mask(dev, 0x09, ~0x2); 66198c2ecf20Sopenharmony_ci 66208c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x204D, 0); 66218c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x2053, 0); 66228c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x2058, 0); 66238c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x205E, 0); 66248c2ecf20Sopenharmony_ci b43_radio_mask(dev, 0x2062, ~0xF0); 66258c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x2064, 0); 66268c2ecf20Sopenharmony_ci 66278c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x304D, 0); 66288c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x3053, 0); 66298c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x3058, 0); 66308c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x305E, 0); 66318c2ecf20Sopenharmony_ci b43_radio_mask(dev, 0x3062, ~0xF0); 66328c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x3064, 0); 66338c2ecf20Sopenharmony_ci } 66348c2ecf20Sopenharmony_ci } else { 66358c2ecf20Sopenharmony_ci if (phy->rev >= 19) { 66368c2ecf20Sopenharmony_ci /* TODO */ 66378c2ecf20Sopenharmony_ci } else if (phy->rev >= 7) { 66388c2ecf20Sopenharmony_ci if (!dev->phy.radio_on) 66398c2ecf20Sopenharmony_ci b43_radio_2057_init(dev); 66408c2ecf20Sopenharmony_ci b43_switch_channel(dev, dev->phy.channel); 66418c2ecf20Sopenharmony_ci } else if (phy->rev >= 3) { 66428c2ecf20Sopenharmony_ci if (!dev->phy.radio_on) 66438c2ecf20Sopenharmony_ci b43_radio_init2056(dev); 66448c2ecf20Sopenharmony_ci b43_switch_channel(dev, dev->phy.channel); 66458c2ecf20Sopenharmony_ci } else { 66468c2ecf20Sopenharmony_ci b43_radio_init2055(dev); 66478c2ecf20Sopenharmony_ci } 66488c2ecf20Sopenharmony_ci } 66498c2ecf20Sopenharmony_ci} 66508c2ecf20Sopenharmony_ci 66518c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */ 66528c2ecf20Sopenharmony_cistatic void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on) 66538c2ecf20Sopenharmony_ci{ 66548c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 66558c2ecf20Sopenharmony_ci u16 override = on ? 0x0 : 0x7FFF; 66568c2ecf20Sopenharmony_ci u16 core = on ? 0xD : 0x00FD; 66578c2ecf20Sopenharmony_ci 66588c2ecf20Sopenharmony_ci if (phy->rev >= 19) { 66598c2ecf20Sopenharmony_ci /* TODO */ 66608c2ecf20Sopenharmony_ci } else if (phy->rev >= 3) { 66618c2ecf20Sopenharmony_ci if (on) { 66628c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_C1, core); 66638c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override); 66648c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_C2, core); 66658c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override); 66668c2ecf20Sopenharmony_ci } else { 66678c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override); 66688c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_C1, core); 66698c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override); 66708c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_C2, core); 66718c2ecf20Sopenharmony_ci } 66728c2ecf20Sopenharmony_ci } else { 66738c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override); 66748c2ecf20Sopenharmony_ci } 66758c2ecf20Sopenharmony_ci} 66768c2ecf20Sopenharmony_ci 66778c2ecf20Sopenharmony_cistatic int b43_nphy_op_switch_channel(struct b43_wldev *dev, 66788c2ecf20Sopenharmony_ci unsigned int new_channel) 66798c2ecf20Sopenharmony_ci{ 66808c2ecf20Sopenharmony_ci struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan; 66818c2ecf20Sopenharmony_ci enum nl80211_channel_type channel_type = 66828c2ecf20Sopenharmony_ci cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef); 66838c2ecf20Sopenharmony_ci 66848c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { 66858c2ecf20Sopenharmony_ci if ((new_channel < 1) || (new_channel > 14)) 66868c2ecf20Sopenharmony_ci return -EINVAL; 66878c2ecf20Sopenharmony_ci } else { 66888c2ecf20Sopenharmony_ci if (new_channel > 200) 66898c2ecf20Sopenharmony_ci return -EINVAL; 66908c2ecf20Sopenharmony_ci } 66918c2ecf20Sopenharmony_ci 66928c2ecf20Sopenharmony_ci return b43_nphy_set_channel(dev, channel, channel_type); 66938c2ecf20Sopenharmony_ci} 66948c2ecf20Sopenharmony_ci 66958c2ecf20Sopenharmony_cistatic unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev) 66968c2ecf20Sopenharmony_ci{ 66978c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) 66988c2ecf20Sopenharmony_ci return 1; 66998c2ecf20Sopenharmony_ci return 36; 67008c2ecf20Sopenharmony_ci} 67018c2ecf20Sopenharmony_ci 67028c2ecf20Sopenharmony_ciconst struct b43_phy_operations b43_phyops_n = { 67038c2ecf20Sopenharmony_ci .allocate = b43_nphy_op_allocate, 67048c2ecf20Sopenharmony_ci .free = b43_nphy_op_free, 67058c2ecf20Sopenharmony_ci .prepare_structs = b43_nphy_op_prepare_structs, 67068c2ecf20Sopenharmony_ci .init = b43_nphy_op_init, 67078c2ecf20Sopenharmony_ci .phy_maskset = b43_nphy_op_maskset, 67088c2ecf20Sopenharmony_ci .radio_read = b43_nphy_op_radio_read, 67098c2ecf20Sopenharmony_ci .radio_write = b43_nphy_op_radio_write, 67108c2ecf20Sopenharmony_ci .software_rfkill = b43_nphy_op_software_rfkill, 67118c2ecf20Sopenharmony_ci .switch_analog = b43_nphy_op_switch_analog, 67128c2ecf20Sopenharmony_ci .switch_channel = b43_nphy_op_switch_channel, 67138c2ecf20Sopenharmony_ci .get_default_chan = b43_nphy_op_get_default_chan, 67148c2ecf20Sopenharmony_ci .recalc_txpower = b43_nphy_op_recalc_txpower, 67158c2ecf20Sopenharmony_ci}; 6716