1300016Sadrian 2300016Sadrian/* 3300016Sadrian 4300016Sadrian Broadcom B43 wireless driver 5300016Sadrian IEEE 802.11n PHY data tables 6300016Sadrian 7300016Sadrian Copyright (c) 2008 Michael Buesch <m@bues.ch> 8300016Sadrian Copyright (c) 2010 Rafa�� Mi��ecki <zajec5@gmail.com> 9300016Sadrian 10300016Sadrian This program is free software; you can redistribute it and/or modify 11300016Sadrian it under the terms of the GNU General Public License as published by 12300016Sadrian the Free Software Foundation; either version 2 of the License, or 13300016Sadrian (at your option) any later version. 14300016Sadrian 15300016Sadrian This program is distributed in the hope that it will be useful, 16300016Sadrian but WITHOUT ANY WARRANTY; without even the implied warranty of 17300016Sadrian MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18300016Sadrian GNU General Public License for more details. 19300016Sadrian 20300016Sadrian You should have received a copy of the GNU General Public License 21300016Sadrian along with this program; see the file COPYING. If not, write to 22300016Sadrian the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, 23300016Sadrian Boston, MA 02110-1301, USA. 24300016Sadrian 25300016Sadrian*/ 26300016Sadrian 27300016Sadrian#include <sys/cdefs.h> 28300016Sadrian__FBSDID("$FreeBSD$"); 29300016Sadrian 30300016Sadrian/* 31300016Sadrian * The Broadcom Wireless LAN controller driver. 32300016Sadrian */ 33300016Sadrian 34300190Sadrian#include "opt_wlan.h" 35300190Sadrian#include "opt_bwn.h" 36300190Sadrian 37300016Sadrian#include <sys/param.h> 38300016Sadrian#include <sys/systm.h> 39300016Sadrian#include <sys/kernel.h> 40300016Sadrian#include <sys/malloc.h> 41300016Sadrian#include <sys/module.h> 42300016Sadrian#include <sys/endian.h> 43300016Sadrian#include <sys/errno.h> 44300016Sadrian#include <sys/firmware.h> 45300016Sadrian#include <sys/lock.h> 46300016Sadrian#include <sys/mutex.h> 47300016Sadrian#include <machine/bus.h> 48300016Sadrian#include <machine/resource.h> 49300016Sadrian#include <sys/bus.h> 50300016Sadrian#include <sys/rman.h> 51300016Sadrian#include <sys/socket.h> 52300016Sadrian#include <sys/sockio.h> 53300016Sadrian 54300016Sadrian#include <net/ethernet.h> 55300016Sadrian#include <net/if.h> 56300016Sadrian#include <net/if_var.h> 57300016Sadrian#include <net/if_arp.h> 58300016Sadrian#include <net/if_dl.h> 59300016Sadrian#include <net/if_llc.h> 60300016Sadrian#include <net/if_media.h> 61300016Sadrian#include <net/if_types.h> 62300016Sadrian 63300016Sadrian#include <dev/pci/pcivar.h> 64300016Sadrian#include <dev/pci/pcireg.h> 65300016Sadrian#include <dev/siba/siba_ids.h> 66300016Sadrian#include <dev/siba/sibareg.h> 67300016Sadrian#include <dev/siba/sibavar.h> 68300016Sadrian 69300016Sadrian#include <net80211/ieee80211_var.h> 70300016Sadrian#include <net80211/ieee80211_radiotap.h> 71300016Sadrian#include <net80211/ieee80211_regdomain.h> 72300016Sadrian#include <net80211/ieee80211_phy.h> 73300016Sadrian#include <net80211/ieee80211_ratectl.h> 74300016Sadrian 75300016Sadrian#include <dev/bwn/if_bwnreg.h> 76300016Sadrian#include <dev/bwn/if_bwnvar.h> 77300016Sadrian#include <dev/bwn/if_bwn_misc.h> 78300016Sadrian#include <dev/bwn/if_bwn_util.h> 79300016Sadrian#include <dev/bwn/if_bwn_debug.h> 80300016Sadrian#include <dev/bwn/if_bwn_phy_common.h> 81300016Sadrian#include <dev/bwn/if_bwn_chipid.h> 82300016Sadrian#include <dev/bwn/if_bwn_cordic.h> 83300016Sadrian 84300016Sadrian#include <gnu/dev/bwn/phy_n/if_bwn_phy_n_regs.h> 85300016Sadrian#include <gnu/dev/bwn/phy_n/if_bwn_phy_n_ppr.h> 86300016Sadrian#include <gnu/dev/bwn/phy_n/if_bwn_phy_n_tables.h> 87300016Sadrian#include <gnu/dev/bwn/phy_n/if_bwn_radio_2055.h> 88300016Sadrian#include <gnu/dev/bwn/phy_n/if_bwn_radio_2056.h> 89300016Sadrian#include <gnu/dev/bwn/phy_n/if_bwn_radio_2057.h> 90300016Sadrian#include <gnu/dev/bwn/phy_n/if_bwn_phy_n_core.h> 91300016Sadrian 92300016Sadrianstruct bwn_nphy_txgains { 93300016Sadrian uint16_t tx_lpf[2]; 94300016Sadrian uint16_t txgm[2]; 95300016Sadrian uint16_t pga[2]; 96300016Sadrian uint16_t pad[2]; 97300016Sadrian uint16_t ipa[2]; 98300016Sadrian}; 99300016Sadrian 100300016Sadrianstruct bwn_nphy_iqcal_params { 101300016Sadrian uint16_t tx_lpf; 102300016Sadrian uint16_t txgm; 103300016Sadrian uint16_t pga; 104300016Sadrian uint16_t pad; 105300016Sadrian uint16_t ipa; 106300016Sadrian uint16_t cal_gain; 107300016Sadrian uint16_t ncorr[5]; 108300016Sadrian}; 109300016Sadrian 110300016Sadrianstruct bwn_nphy_iq_est { 111300016Sadrian int32_t iq0_prod; 112300016Sadrian uint32_t i0_pwr; 113300016Sadrian uint32_t q0_pwr; 114300016Sadrian int32_t iq1_prod; 115300016Sadrian uint32_t i1_pwr; 116300016Sadrian uint32_t q1_pwr; 117300016Sadrian}; 118300016Sadrian 119300016Sadrianenum bwn_nphy_rf_sequence { 120300016Sadrian BWN_RFSEQ_RX2TX, 121300016Sadrian BWN_RFSEQ_TX2RX, 122300016Sadrian BWN_RFSEQ_RESET2RX, 123300016Sadrian BWN_RFSEQ_UPDATE_GAINH, 124300016Sadrian BWN_RFSEQ_UPDATE_GAINL, 125300016Sadrian BWN_RFSEQ_UPDATE_GAINU, 126300016Sadrian}; 127300016Sadrian 128300016Sadrianenum n_rf_ctl_over_cmd { 129300016Sadrian N_RF_CTL_OVER_CMD_RXRF_PU = 0, 130300016Sadrian N_RF_CTL_OVER_CMD_RX_PU = 1, 131300016Sadrian N_RF_CTL_OVER_CMD_TX_PU = 2, 132300016Sadrian N_RF_CTL_OVER_CMD_RX_GAIN = 3, 133300016Sadrian N_RF_CTL_OVER_CMD_TX_GAIN = 4, 134300016Sadrian}; 135300016Sadrian 136300016Sadrianenum n_intc_override { 137300016Sadrian N_INTC_OVERRIDE_OFF = 0, 138300016Sadrian N_INTC_OVERRIDE_TRSW = 1, 139300016Sadrian N_INTC_OVERRIDE_PA = 2, 140300016Sadrian N_INTC_OVERRIDE_EXT_LNA_PU = 3, 141300016Sadrian N_INTC_OVERRIDE_EXT_LNA_GAIN = 4, 142300016Sadrian}; 143300016Sadrian 144300016Sadrianenum n_rssi_type { 145300016Sadrian N_RSSI_W1 = 0, 146300016Sadrian N_RSSI_W2, 147300016Sadrian N_RSSI_NB, 148300016Sadrian N_RSSI_IQ, 149300016Sadrian N_RSSI_TSSI_2G, 150300016Sadrian N_RSSI_TSSI_5G, 151300016Sadrian N_RSSI_TBD, 152300016Sadrian}; 153300016Sadrian 154300016Sadrianenum n_rail_type { 155300016Sadrian N_RAIL_I = 0, 156300016Sadrian N_RAIL_Q = 1, 157300016Sadrian}; 158300016Sadrian 159300016Sadrianstatic inline bool bwn_nphy_ipa(struct bwn_mac *mac) 160300016Sadrian{ 161300016Sadrian bwn_band_t band = bwn_current_band(mac); 162300016Sadrian return ((mac->mac_phy.phy_n->ipa2g_on && band == BWN_BAND_2G) || 163300016Sadrian (mac->mac_phy.phy_n->ipa5g_on && band == BWN_BAND_5G)); 164300016Sadrian} 165300016Sadrian 166300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreGetState */ 167300016Sadrianstatic uint8_t bwn_nphy_get_rx_core_state(struct bwn_mac *mac) 168300016Sadrian{ 169300016Sadrian return (BWN_PHY_READ(mac, BWN_NPHY_RFSEQCA) & BWN_NPHY_RFSEQCA_RXEN) >> 170300016Sadrian BWN_NPHY_RFSEQCA_RXEN_SHIFT; 171300016Sadrian} 172300016Sadrian 173300016Sadrian/************************************************** 174300016Sadrian * RF (just without bwn_nphy_rf_ctl_intc_override) 175300016Sadrian **************************************************/ 176300016Sadrian 177300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */ 178300016Sadrianstatic void bwn_nphy_force_rf_sequence(struct bwn_mac *mac, 179300016Sadrian enum bwn_nphy_rf_sequence seq) 180300016Sadrian{ 181300016Sadrian static const uint16_t trigger[] = { 182300016Sadrian [BWN_RFSEQ_RX2TX] = BWN_NPHY_RFSEQTR_RX2TX, 183300016Sadrian [BWN_RFSEQ_TX2RX] = BWN_NPHY_RFSEQTR_TX2RX, 184300016Sadrian [BWN_RFSEQ_RESET2RX] = BWN_NPHY_RFSEQTR_RST2RX, 185300016Sadrian [BWN_RFSEQ_UPDATE_GAINH] = BWN_NPHY_RFSEQTR_UPGH, 186300016Sadrian [BWN_RFSEQ_UPDATE_GAINL] = BWN_NPHY_RFSEQTR_UPGL, 187300016Sadrian [BWN_RFSEQ_UPDATE_GAINU] = BWN_NPHY_RFSEQTR_UPGU, 188300016Sadrian }; 189300016Sadrian int i; 190300016Sadrian uint16_t seq_mode = BWN_PHY_READ(mac, BWN_NPHY_RFSEQMODE); 191300016Sadrian 192300016Sadrian if (seq >= nitems(trigger)) { 193300016Sadrian BWN_WARNPRINTF(mac->mac_sc, "%s: seq %d > max", __func__, seq); 194300016Sadrian } 195300016Sadrian 196300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFSEQMODE, 197300016Sadrian BWN_NPHY_RFSEQMODE_CAOVER | BWN_NPHY_RFSEQMODE_TROVER); 198300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFSEQTR, trigger[seq]); 199300016Sadrian for (i = 0; i < 200; i++) { 200300016Sadrian if (!(BWN_PHY_READ(mac, BWN_NPHY_RFSEQST) & trigger[seq])) 201300016Sadrian goto ok; 202300016Sadrian DELAY(1000); 203300016Sadrian } 204300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "RF sequence status timeout\n"); 205300016Sadrianok: 206300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFSEQMODE, seq_mode); 207300016Sadrian} 208300016Sadrian 209300016Sadrianstatic void bwn_nphy_rf_ctl_override_rev19(struct bwn_mac *mac, uint16_t field, 210300016Sadrian uint16_t value, uint8_t core, bool off, 211300016Sadrian uint8_t override_id) 212300016Sadrian{ 213300016Sadrian /* TODO */ 214300016Sadrian} 215300016Sadrian 216300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverrideRev7 */ 217300016Sadrianstatic void bwn_nphy_rf_ctl_override_rev7(struct bwn_mac *mac, uint16_t field, 218300016Sadrian uint16_t value, uint8_t core, bool off, 219300016Sadrian uint8_t override) 220300016Sadrian{ 221300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 222300016Sadrian const struct bwn_nphy_rf_control_override_rev7 *e; 223300016Sadrian uint16_t en_addrs[3][2] = { 224300016Sadrian { 0x0E7, 0x0EC }, { 0x342, 0x343 }, { 0x346, 0x347 } 225300016Sadrian }; 226300016Sadrian uint16_t en_addr; 227300016Sadrian uint16_t en_mask = field; 228300016Sadrian uint16_t val_addr; 229300016Sadrian uint8_t i; 230300016Sadrian 231300016Sadrian if (phy->rev >= 19 || phy->rev < 3) { 232300016Sadrian BWN_WARNPRINTF(mac->mac_sc, "%s: phy rev %d out of range\n", 233300016Sadrian __func__, 234300016Sadrian phy->rev); 235300016Sadrian return; 236300016Sadrian } 237300016Sadrian 238300016Sadrian /* Remember: we can get NULL! */ 239300016Sadrian e = bwn_nphy_get_rf_ctl_over_rev7(mac, field, override); 240300016Sadrian 241300016Sadrian for (i = 0; i < 2; i++) { 242300016Sadrian if (override >= nitems(en_addrs)) { 243300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "Invalid override value %d\n", override); 244300016Sadrian return; 245300016Sadrian } 246300016Sadrian en_addr = en_addrs[override][i]; 247300016Sadrian 248300016Sadrian if (e) 249300016Sadrian val_addr = (i == 0) ? e->val_addr_core0 : e->val_addr_core1; 250300016Sadrian 251300016Sadrian if (off) { 252300016Sadrian BWN_PHY_MASK(mac, en_addr, ~en_mask); 253300016Sadrian if (e) /* Do it safer, better than wl */ 254300016Sadrian BWN_PHY_MASK(mac, val_addr, ~e->val_mask); 255300016Sadrian } else { 256300016Sadrian if (!core || (core & (1 << i))) { 257300016Sadrian BWN_PHY_SET(mac, en_addr, en_mask); 258300016Sadrian if (e) 259300016Sadrian BWN_PHY_SETMASK(mac, val_addr, ~e->val_mask, (value << e->val_shift)); 260300016Sadrian } 261300016Sadrian } 262300016Sadrian } 263300016Sadrian} 264300016Sadrian 265300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverideOneToMany */ 266300016Sadrianstatic void bwn_nphy_rf_ctl_override_one_to_many(struct bwn_mac *mac, 267300016Sadrian enum n_rf_ctl_over_cmd cmd, 268300016Sadrian uint16_t value, uint8_t core, bool off) 269300016Sadrian{ 270300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 271300016Sadrian uint16_t tmp; 272300016Sadrian 273300016Sadrian if (phy->rev < 7) { 274300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "%s: phy rev %d out of range\n", 275300016Sadrian __func__, 276300016Sadrian phy->rev); 277300016Sadrian } 278300016Sadrian 279300016Sadrian switch (cmd) { 280300016Sadrian case N_RF_CTL_OVER_CMD_RXRF_PU: 281300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x20, value, core, off, 1); 282300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x10, value, core, off, 1); 283300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x08, value, core, off, 1); 284300016Sadrian break; 285300016Sadrian case N_RF_CTL_OVER_CMD_RX_PU: 286300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x4, value, core, off, 1); 287300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x2, value, core, off, 1); 288300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x1, value, core, off, 1); 289300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x2, value, core, off, 2); 290300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x0800, 0, core, off, 1); 291300016Sadrian break; 292300016Sadrian case N_RF_CTL_OVER_CMD_TX_PU: 293300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x4, value, core, off, 0); 294300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x2, value, core, off, 1); 295300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x1, value, core, off, 2); 296300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x0800, 1, core, off, 1); 297300016Sadrian break; 298300016Sadrian case N_RF_CTL_OVER_CMD_RX_GAIN: 299300016Sadrian tmp = value & 0xFF; 300300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x0800, tmp, core, off, 0); 301300016Sadrian tmp = value >> 8; 302300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x6000, tmp, core, off, 0); 303300016Sadrian break; 304300016Sadrian case N_RF_CTL_OVER_CMD_TX_GAIN: 305300016Sadrian tmp = value & 0x7FFF; 306300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x1000, tmp, core, off, 0); 307300016Sadrian tmp = value >> 14; 308300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x4000, tmp, core, off, 0); 309300016Sadrian break; 310300016Sadrian } 311300016Sadrian} 312300016Sadrian 313300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */ 314300016Sadrianstatic void bwn_nphy_rf_ctl_override(struct bwn_mac *mac, uint16_t field, 315300016Sadrian uint16_t value, uint8_t core, bool off) 316300016Sadrian{ 317300016Sadrian int i; 318300016Sadrian uint8_t index = fls(field); 319300016Sadrian uint8_t addr, en_addr, val_addr; 320300016Sadrian 321300016Sadrian /* we expect only one bit set */ 322300016Sadrian if (field & (~(1 << (index - 1)))) { 323300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "%s: field 0x%04x has >1 bit set\n", 324300016Sadrian __func__, 325300016Sadrian field); 326300016Sadrian } 327300016Sadrian 328300016Sadrian if (mac->mac_phy.rev >= 3) { 329300016Sadrian const struct bwn_nphy_rf_control_override_rev3 *rf_ctrl; 330300016Sadrian for (i = 0; i < 2; i++) { 331300016Sadrian if (index == 0 || index == 16) { 332300016Sadrian BWN_ERRPRINTF(mac->mac_sc, 333300016Sadrian "Unsupported RF Ctrl Override call\n"); 334300016Sadrian return; 335300016Sadrian } 336300016Sadrian 337300016Sadrian rf_ctrl = &tbl_rf_control_override_rev3[index - 1]; 338300016Sadrian en_addr = BWN_PHY_N((i == 0) ? 339300016Sadrian rf_ctrl->en_addr0 : rf_ctrl->en_addr1); 340300016Sadrian val_addr = BWN_PHY_N((i == 0) ? 341300016Sadrian rf_ctrl->val_addr0 : rf_ctrl->val_addr1); 342300016Sadrian 343300016Sadrian if (off) { 344300016Sadrian BWN_PHY_MASK(mac, en_addr, ~(field)); 345300016Sadrian BWN_PHY_MASK(mac, val_addr, 346300016Sadrian ~(rf_ctrl->val_mask)); 347300016Sadrian } else { 348300016Sadrian if (core == 0 || ((1 << i) & core)) { 349300016Sadrian BWN_PHY_SET(mac, en_addr, field); 350300016Sadrian BWN_PHY_SETMASK(mac, val_addr, 351300016Sadrian ~(rf_ctrl->val_mask), 352300016Sadrian (value << rf_ctrl->val_shift)); 353300016Sadrian } 354300016Sadrian } 355300016Sadrian } 356300016Sadrian } else { 357300016Sadrian const struct bwn_nphy_rf_control_override_rev2 *rf_ctrl; 358300016Sadrian if (off) { 359300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER, ~(field)); 360300016Sadrian value = 0; 361300016Sadrian } else { 362300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_OVER, field); 363300016Sadrian } 364300016Sadrian 365300016Sadrian for (i = 0; i < 2; i++) { 366300016Sadrian if (index <= 1 || index == 16) { 367300016Sadrian BWN_ERRPRINTF(mac->mac_sc, 368300016Sadrian "Unsupported RF Ctrl Override call\n"); 369300016Sadrian return; 370300016Sadrian } 371300016Sadrian 372300016Sadrian if (index == 2 || index == 10 || 373300016Sadrian (index >= 13 && index <= 15)) { 374300016Sadrian core = 1; 375300016Sadrian } 376300016Sadrian 377300016Sadrian rf_ctrl = &tbl_rf_control_override_rev2[index - 2]; 378300016Sadrian addr = BWN_PHY_N((i == 0) ? 379300016Sadrian rf_ctrl->addr0 : rf_ctrl->addr1); 380300016Sadrian 381300016Sadrian if ((1 << i) & core) 382300016Sadrian BWN_PHY_SETMASK(mac, addr, ~(rf_ctrl->bmask), 383300016Sadrian (value << rf_ctrl->shift)); 384300016Sadrian 385300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_OVER, 0x1); 386300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, 387300016Sadrian BWN_NPHY_RFCTL_CMD_START); 388300016Sadrian DELAY(1); 389300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER, 0xFFFE); 390300016Sadrian } 391300016Sadrian } 392300016Sadrian} 393300016Sadrian 394300016Sadrianstatic void bwn_nphy_rf_ctl_intc_override_rev7(struct bwn_mac *mac, 395300016Sadrian enum n_intc_override intc_override, 396300016Sadrian uint16_t value, uint8_t core_sel) 397300016Sadrian{ 398300016Sadrian uint16_t reg, tmp, tmp2, val; 399300016Sadrian int core; 400300016Sadrian 401300016Sadrian /* TODO: What about rev19+? Revs 3+ and 7+ are a bit similar */ 402300016Sadrian 403300016Sadrian for (core = 0; core < 2; core++) { 404300016Sadrian if ((core_sel == 1 && core != 0) || 405300016Sadrian (core_sel == 2 && core != 1)) 406300016Sadrian continue; 407300016Sadrian 408300016Sadrian reg = (core == 0) ? BWN_NPHY_RFCTL_INTC1 : BWN_NPHY_RFCTL_INTC2; 409300016Sadrian 410300016Sadrian switch (intc_override) { 411300016Sadrian case N_INTC_OVERRIDE_OFF: 412300016Sadrian BWN_PHY_WRITE(mac, reg, 0); 413300016Sadrian BWN_PHY_MASK(mac, 0x2ff, ~0x2000); 414300016Sadrian bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX); 415300016Sadrian break; 416300016Sadrian case N_INTC_OVERRIDE_TRSW: 417300016Sadrian BWN_PHY_SETMASK(mac, reg, ~0xC0, value << 6); 418300016Sadrian BWN_PHY_SET(mac, reg, 0x400); 419300016Sadrian 420300016Sadrian BWN_PHY_MASK(mac, 0x2ff, ~0xC000 & 0xFFFF); 421300016Sadrian BWN_PHY_SET(mac, 0x2ff, 0x2000); 422300016Sadrian BWN_PHY_SET(mac, 0x2ff, 0x0001); 423300016Sadrian break; 424300016Sadrian case N_INTC_OVERRIDE_PA: 425300016Sadrian tmp = 0x0030; 426300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G) 427300016Sadrian val = value << 5; 428300016Sadrian else 429300016Sadrian val = value << 4; 430300016Sadrian BWN_PHY_SETMASK(mac, reg, ~tmp, val); 431300016Sadrian BWN_PHY_SET(mac, reg, 0x1000); 432300016Sadrian break; 433300016Sadrian case N_INTC_OVERRIDE_EXT_LNA_PU: 434300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G) { 435300016Sadrian tmp = 0x0001; 436300016Sadrian tmp2 = 0x0004; 437300016Sadrian val = value; 438300016Sadrian } else { 439300016Sadrian tmp = 0x0004; 440300016Sadrian tmp2 = 0x0001; 441300016Sadrian val = value << 2; 442300016Sadrian } 443300016Sadrian BWN_PHY_SETMASK(mac, reg, ~tmp, val); 444300016Sadrian BWN_PHY_MASK(mac, reg, ~tmp2); 445300016Sadrian break; 446300016Sadrian case N_INTC_OVERRIDE_EXT_LNA_GAIN: 447300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G) { 448300016Sadrian tmp = 0x0002; 449300016Sadrian tmp2 = 0x0008; 450300016Sadrian val = value << 1; 451300016Sadrian } else { 452300016Sadrian tmp = 0x0008; 453300016Sadrian tmp2 = 0x0002; 454300016Sadrian val = value << 3; 455300016Sadrian } 456300016Sadrian BWN_PHY_SETMASK(mac, reg, ~tmp, val); 457300016Sadrian BWN_PHY_MASK(mac, reg, ~tmp2); 458300016Sadrian break; 459300016Sadrian } 460300016Sadrian } 461300016Sadrian} 462300016Sadrian 463300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlIntcOverride */ 464300016Sadrianstatic void bwn_nphy_rf_ctl_intc_override(struct bwn_mac *mac, 465300016Sadrian enum n_intc_override intc_override, 466300016Sadrian uint16_t value, uint8_t core) 467300016Sadrian{ 468300016Sadrian uint8_t i, j; 469300016Sadrian uint16_t reg, tmp, val; 470300016Sadrian 471300016Sadrian if (mac->mac_phy.rev >= 7) { 472300016Sadrian bwn_nphy_rf_ctl_intc_override_rev7(mac, intc_override, value, 473300016Sadrian core); 474300016Sadrian return; 475300016Sadrian } 476300016Sadrian 477300016Sadrian if (mac->mac_phy.rev < 3) { 478300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "%s: phy rev %d out of range\n", 479300016Sadrian __func__, 480300016Sadrian mac->mac_phy.rev); 481300016Sadrian } 482300016Sadrian 483300016Sadrian for (i = 0; i < 2; i++) { 484300016Sadrian if ((core == 1 && i == 1) || (core == 2 && !i)) 485300016Sadrian continue; 486300016Sadrian 487300016Sadrian reg = (i == 0) ? 488300016Sadrian BWN_NPHY_RFCTL_INTC1 : BWN_NPHY_RFCTL_INTC2; 489300016Sadrian BWN_PHY_SET(mac, reg, 0x400); 490300016Sadrian 491300016Sadrian switch (intc_override) { 492300016Sadrian case N_INTC_OVERRIDE_OFF: 493300016Sadrian BWN_PHY_WRITE(mac, reg, 0); 494300016Sadrian bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX); 495300016Sadrian break; 496300016Sadrian case N_INTC_OVERRIDE_TRSW: 497300016Sadrian if (!i) { 498300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFCTL_INTC1, 499300016Sadrian 0xFC3F, (value << 6)); 500300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_TXF_40CO_B1S1, 501300016Sadrian 0xFFFE, 1); 502300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, 503300016Sadrian BWN_NPHY_RFCTL_CMD_START); 504300016Sadrian for (j = 0; j < 100; j++) { 505300016Sadrian if (!(BWN_PHY_READ(mac, BWN_NPHY_RFCTL_CMD) & BWN_NPHY_RFCTL_CMD_START)) { 506300016Sadrian j = 0; 507300016Sadrian break; 508300016Sadrian } 509300016Sadrian DELAY(10); 510300016Sadrian } 511300016Sadrian if (j) 512300016Sadrian BWN_ERRPRINTF(mac->mac_sc, 513300016Sadrian "intc override timeout\n"); 514300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_TXF_40CO_B1S1, 515300016Sadrian 0xFFFE); 516300016Sadrian } else { 517300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFCTL_INTC2, 518300016Sadrian 0xFC3F, (value << 6)); 519300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFCTL_OVER, 520300016Sadrian 0xFFFE, 1); 521300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, 522300016Sadrian BWN_NPHY_RFCTL_CMD_RXTX); 523300016Sadrian for (j = 0; j < 100; j++) { 524300016Sadrian if (!(BWN_PHY_READ(mac, BWN_NPHY_RFCTL_CMD) & BWN_NPHY_RFCTL_CMD_RXTX)) { 525300016Sadrian j = 0; 526300016Sadrian break; 527300016Sadrian } 528300016Sadrian DELAY(10); 529300016Sadrian } 530300016Sadrian if (j) 531300016Sadrian BWN_ERRPRINTF(mac->mac_sc, 532300016Sadrian "intc override timeout\n"); 533300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER, 534300016Sadrian 0xFFFE); 535300016Sadrian } 536300016Sadrian break; 537300016Sadrian case N_INTC_OVERRIDE_PA: 538300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G) { 539300016Sadrian tmp = 0x0020; 540300016Sadrian val = value << 5; 541300016Sadrian } else { 542300016Sadrian tmp = 0x0010; 543300016Sadrian val = value << 4; 544300016Sadrian } 545300016Sadrian BWN_PHY_SETMASK(mac, reg, ~tmp, val); 546300016Sadrian break; 547300016Sadrian case N_INTC_OVERRIDE_EXT_LNA_PU: 548300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G) { 549300016Sadrian tmp = 0x0001; 550300016Sadrian val = value; 551300016Sadrian } else { 552300016Sadrian tmp = 0x0004; 553300016Sadrian val = value << 2; 554300016Sadrian } 555300016Sadrian BWN_PHY_SETMASK(mac, reg, ~tmp, val); 556300016Sadrian break; 557300016Sadrian case N_INTC_OVERRIDE_EXT_LNA_GAIN: 558300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G) { 559300016Sadrian tmp = 0x0002; 560300016Sadrian val = value << 1; 561300016Sadrian } else { 562300016Sadrian tmp = 0x0008; 563300016Sadrian val = value << 3; 564300016Sadrian } 565300016Sadrian BWN_PHY_SETMASK(mac, reg, ~tmp, val); 566300016Sadrian break; 567300016Sadrian } 568300016Sadrian } 569300016Sadrian} 570300016Sadrian 571300016Sadrian/************************************************** 572300016Sadrian * Various PHY ops 573300016Sadrian **************************************************/ 574300016Sadrian 575300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */ 576300016Sadrianstatic void bwn_nphy_write_clip_detection(struct bwn_mac *mac, 577300016Sadrian const uint16_t *clip_st) 578300016Sadrian{ 579300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_C1_CLIP1THRES, clip_st[0]); 580300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_C2_CLIP1THRES, clip_st[1]); 581300016Sadrian} 582300016Sadrian 583300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */ 584300016Sadrianstatic void bwn_nphy_read_clip_detection(struct bwn_mac *mac, uint16_t *clip_st) 585300016Sadrian{ 586300016Sadrian clip_st[0] = BWN_PHY_READ(mac, BWN_NPHY_C1_CLIP1THRES); 587300016Sadrian clip_st[1] = BWN_PHY_READ(mac, BWN_NPHY_C2_CLIP1THRES); 588300016Sadrian} 589300016Sadrian 590300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */ 591300016Sadrianstatic uint16_t bwn_nphy_classifier(struct bwn_mac *mac, uint16_t mask, uint16_t val) 592300016Sadrian{ 593300016Sadrian struct bwn_softc *sc = mac->mac_sc; 594300016Sadrian uint16_t tmp; 595300016Sadrian 596300016Sadrian if (siba_get_revid(sc->sc_dev) == 16) 597300016Sadrian bwn_mac_suspend(mac); 598300016Sadrian 599300016Sadrian tmp = BWN_PHY_READ(mac, BWN_NPHY_CLASSCTL); 600300016Sadrian tmp &= (BWN_NPHY_CLASSCTL_CCKEN | BWN_NPHY_CLASSCTL_OFDMEN | 601300016Sadrian BWN_NPHY_CLASSCTL_WAITEDEN); 602300016Sadrian tmp &= ~mask; 603300016Sadrian tmp |= (val & mask); 604300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_CLASSCTL, 0xFFF8, tmp); 605300016Sadrian 606300016Sadrian if (siba_get_revid(sc->sc_dev) == 16) 607300016Sadrian bwn_mac_enable(mac); 608300016Sadrian 609300016Sadrian return tmp; 610300016Sadrian} 611300016Sadrian 612300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */ 613300016Sadrianstatic void bwn_nphy_reset_cca(struct bwn_mac *mac) 614300016Sadrian{ 615300016Sadrian uint16_t bbcfg; 616300016Sadrian 617300016Sadrian bwn_phy_force_clock(mac, 1); 618300016Sadrian bbcfg = BWN_PHY_READ(mac, BWN_NPHY_BBCFG); 619300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_BBCFG, bbcfg | BWN_NPHY_BBCFG_RSTCCA); 620300016Sadrian DELAY(1); 621300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_BBCFG, bbcfg & ~BWN_NPHY_BBCFG_RSTCCA); 622300016Sadrian bwn_phy_force_clock(mac, 0); 623300016Sadrian bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX); 624300016Sadrian} 625300016Sadrian 626300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/carriersearch */ 627300016Sadrianstatic void bwn_nphy_stay_in_carrier_search(struct bwn_mac *mac, bool enable) 628300016Sadrian{ 629300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 630300016Sadrian struct bwn_phy_n *nphy = phy->phy_n; 631300016Sadrian 632300016Sadrian if (enable) { 633300016Sadrian static const uint16_t clip[] = { 0xFFFF, 0xFFFF }; 634300016Sadrian if (nphy->deaf_count++ == 0) { 635300016Sadrian nphy->classifier_state = bwn_nphy_classifier(mac, 0, 0); 636300016Sadrian bwn_nphy_classifier(mac, 0x7, 637300016Sadrian BWN_NPHY_CLASSCTL_WAITEDEN); 638300016Sadrian bwn_nphy_read_clip_detection(mac, nphy->clip_state); 639300016Sadrian bwn_nphy_write_clip_detection(mac, clip); 640300016Sadrian } 641300016Sadrian bwn_nphy_reset_cca(mac); 642300016Sadrian } else { 643300016Sadrian if (--nphy->deaf_count == 0) { 644300016Sadrian bwn_nphy_classifier(mac, 0x7, nphy->classifier_state); 645300016Sadrian bwn_nphy_write_clip_detection(mac, nphy->clip_state); 646300016Sadrian } 647300016Sadrian } 648300016Sadrian} 649300016Sadrian 650300016Sadrian/* http://bcm-v4.sipsolutions.net/PHY/N/Read_Lpf_Bw_Ctl */ 651300016Sadrianstatic uint16_t bwn_nphy_read_lpf_ctl(struct bwn_mac *mac, uint16_t offset) 652300016Sadrian{ 653300016Sadrian if (!offset) 654300016Sadrian offset = bwn_is_40mhz(mac) ? 0x159 : 0x154; 655300016Sadrian return bwn_ntab_read(mac, BWN_NTAB16(7, offset)) & 0x7; 656300016Sadrian} 657300016Sadrian 658300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */ 659300016Sadrianstatic void bwn_nphy_adjust_lna_gain_table(struct bwn_mac *mac) 660300016Sadrian{ 661300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 662300016Sadrian 663300016Sadrian uint8_t i; 664300016Sadrian int16_t tmp; 665300016Sadrian uint16_t data[4]; 666300016Sadrian int16_t gain[2]; 667300016Sadrian uint16_t minmax[2]; 668300016Sadrian static const uint16_t lna_gain[4] = { -2, 10, 19, 25 }; 669300016Sadrian 670300016Sadrian if (nphy->hang_avoid) 671300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 1); 672300016Sadrian 673300016Sadrian if (nphy->gain_boost) { 674300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 675300016Sadrian gain[0] = 6; 676300016Sadrian gain[1] = 6; 677300016Sadrian } else { 678300016Sadrian tmp = 40370 - 315 * bwn_get_chan(mac); 679300016Sadrian gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1)); 680300016Sadrian tmp = 23242 - 224 * bwn_get_chan(mac); 681300016Sadrian gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1)); 682300016Sadrian } 683300016Sadrian } else { 684300016Sadrian gain[0] = 0; 685300016Sadrian gain[1] = 0; 686300016Sadrian } 687300016Sadrian 688300016Sadrian for (i = 0; i < 2; i++) { 689300016Sadrian if (nphy->elna_gain_config) { 690300016Sadrian data[0] = 19 + gain[i]; 691300016Sadrian data[1] = 25 + gain[i]; 692300016Sadrian data[2] = 25 + gain[i]; 693300016Sadrian data[3] = 25 + gain[i]; 694300016Sadrian } else { 695300016Sadrian data[0] = lna_gain[0] + gain[i]; 696300016Sadrian data[1] = lna_gain[1] + gain[i]; 697300016Sadrian data[2] = lna_gain[2] + gain[i]; 698300016Sadrian data[3] = lna_gain[3] + gain[i]; 699300016Sadrian } 700300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(i, 8), 4, data); 701300016Sadrian 702300016Sadrian minmax[i] = 23 + gain[i]; 703300016Sadrian } 704300016Sadrian 705300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_C1_MINMAX_GAIN, ~BWN_NPHY_C1_MINGAIN, 706300016Sadrian minmax[0] << BWN_NPHY_C1_MINGAIN_SHIFT); 707300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_C2_MINMAX_GAIN, ~BWN_NPHY_C2_MINGAIN, 708300016Sadrian minmax[1] << BWN_NPHY_C2_MINGAIN_SHIFT); 709300016Sadrian 710300016Sadrian if (nphy->hang_avoid) 711300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 0); 712300016Sadrian} 713300016Sadrian 714300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRfSeq */ 715300016Sadrianstatic void bwn_nphy_set_rf_sequence(struct bwn_mac *mac, uint8_t cmd, 716300016Sadrian uint8_t *events, uint8_t *delays, uint8_t length) 717300016Sadrian{ 718300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 719300016Sadrian uint8_t i; 720300016Sadrian uint8_t end = (mac->mac_phy.rev >= 3) ? 0x1F : 0x0F; 721300016Sadrian uint16_t offset1 = cmd << 4; 722300016Sadrian uint16_t offset2 = offset1 + 0x80; 723300016Sadrian 724300016Sadrian if (nphy->hang_avoid) 725300016Sadrian bwn_nphy_stay_in_carrier_search(mac, true); 726300016Sadrian 727300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(7, offset1), length, events); 728300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(7, offset2), length, delays); 729300016Sadrian 730300016Sadrian for (i = length; i < 16; i++) { 731300016Sadrian bwn_ntab_write(mac, BWN_NTAB8(7, offset1 + i), end); 732300016Sadrian bwn_ntab_write(mac, BWN_NTAB8(7, offset2 + i), 1); 733300016Sadrian } 734300016Sadrian 735300016Sadrian if (nphy->hang_avoid) 736300016Sadrian bwn_nphy_stay_in_carrier_search(mac, false); 737300016Sadrian} 738300016Sadrian 739300016Sadrian/************************************************** 740300016Sadrian * Radio 0x2057 741300016Sadrian **************************************************/ 742300016Sadrian 743300016Sadrianstatic void bwn_radio_2057_chantab_upload(struct bwn_mac *mac, 744300016Sadrian const struct bwn_nphy_chantabent_rev7 *e_r7, 745300016Sadrian const struct bwn_nphy_chantabent_rev7_2g *e_r7_2g) 746300016Sadrian{ 747300016Sadrian if (e_r7_2g) { 748300016Sadrian BWN_RF_WRITE(mac, R2057_VCOCAL_COUNTVAL0, e_r7_2g->radio_vcocal_countval0); 749300016Sadrian BWN_RF_WRITE(mac, R2057_VCOCAL_COUNTVAL1, e_r7_2g->radio_vcocal_countval1); 750300016Sadrian BWN_RF_WRITE(mac, R2057_RFPLL_REFMASTER_SPAREXTALSIZE, e_r7_2g->radio_rfpll_refmaster_sparextalsize); 751300016Sadrian BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_R1, e_r7_2g->radio_rfpll_loopfilter_r1); 752300016Sadrian BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C2, e_r7_2g->radio_rfpll_loopfilter_c2); 753300016Sadrian BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C1, e_r7_2g->radio_rfpll_loopfilter_c1); 754300016Sadrian BWN_RF_WRITE(mac, R2057_CP_KPD_IDAC, e_r7_2g->radio_cp_kpd_idac); 755300016Sadrian BWN_RF_WRITE(mac, R2057_RFPLL_MMD0, e_r7_2g->radio_rfpll_mmd0); 756300016Sadrian BWN_RF_WRITE(mac, R2057_RFPLL_MMD1, e_r7_2g->radio_rfpll_mmd1); 757300016Sadrian BWN_RF_WRITE(mac, R2057_VCOBUF_TUNE, e_r7_2g->radio_vcobuf_tune); 758300016Sadrian BWN_RF_WRITE(mac, R2057_LOGEN_MX2G_TUNE, e_r7_2g->radio_logen_mx2g_tune); 759300016Sadrian BWN_RF_WRITE(mac, R2057_LOGEN_INDBUF2G_TUNE, e_r7_2g->radio_logen_indbuf2g_tune); 760300016Sadrian BWN_RF_WRITE(mac, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, e_r7_2g->radio_txmix2g_tune_boost_pu_core0); 761300016Sadrian BWN_RF_WRITE(mac, R2057_PAD2G_TUNE_PUS_CORE0, e_r7_2g->radio_pad2g_tune_pus_core0); 762300016Sadrian BWN_RF_WRITE(mac, R2057_LNA2G_TUNE_CORE0, e_r7_2g->radio_lna2g_tune_core0); 763300016Sadrian BWN_RF_WRITE(mac, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, e_r7_2g->radio_txmix2g_tune_boost_pu_core1); 764300016Sadrian BWN_RF_WRITE(mac, R2057_PAD2G_TUNE_PUS_CORE1, e_r7_2g->radio_pad2g_tune_pus_core1); 765300016Sadrian BWN_RF_WRITE(mac, R2057_LNA2G_TUNE_CORE1, e_r7_2g->radio_lna2g_tune_core1); 766300016Sadrian 767300016Sadrian } else { 768300016Sadrian BWN_RF_WRITE(mac, R2057_VCOCAL_COUNTVAL0, e_r7->radio_vcocal_countval0); 769300016Sadrian BWN_RF_WRITE(mac, R2057_VCOCAL_COUNTVAL1, e_r7->radio_vcocal_countval1); 770300016Sadrian BWN_RF_WRITE(mac, R2057_RFPLL_REFMASTER_SPAREXTALSIZE, e_r7->radio_rfpll_refmaster_sparextalsize); 771300016Sadrian BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_R1, e_r7->radio_rfpll_loopfilter_r1); 772300016Sadrian BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C2, e_r7->radio_rfpll_loopfilter_c2); 773300016Sadrian BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C1, e_r7->radio_rfpll_loopfilter_c1); 774300016Sadrian BWN_RF_WRITE(mac, R2057_CP_KPD_IDAC, e_r7->radio_cp_kpd_idac); 775300016Sadrian BWN_RF_WRITE(mac, R2057_RFPLL_MMD0, e_r7->radio_rfpll_mmd0); 776300016Sadrian BWN_RF_WRITE(mac, R2057_RFPLL_MMD1, e_r7->radio_rfpll_mmd1); 777300016Sadrian BWN_RF_WRITE(mac, R2057_VCOBUF_TUNE, e_r7->radio_vcobuf_tune); 778300016Sadrian BWN_RF_WRITE(mac, R2057_LOGEN_MX2G_TUNE, e_r7->radio_logen_mx2g_tune); 779300016Sadrian BWN_RF_WRITE(mac, R2057_LOGEN_MX5G_TUNE, e_r7->radio_logen_mx5g_tune); 780300016Sadrian BWN_RF_WRITE(mac, R2057_LOGEN_INDBUF2G_TUNE, e_r7->radio_logen_indbuf2g_tune); 781300016Sadrian BWN_RF_WRITE(mac, R2057_LOGEN_INDBUF5G_TUNE, e_r7->radio_logen_indbuf5g_tune); 782300016Sadrian BWN_RF_WRITE(mac, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, e_r7->radio_txmix2g_tune_boost_pu_core0); 783300016Sadrian BWN_RF_WRITE(mac, R2057_PAD2G_TUNE_PUS_CORE0, e_r7->radio_pad2g_tune_pus_core0); 784300016Sadrian BWN_RF_WRITE(mac, R2057_PGA_BOOST_TUNE_CORE0, e_r7->radio_pga_boost_tune_core0); 785300016Sadrian BWN_RF_WRITE(mac, R2057_TXMIX5G_BOOST_TUNE_CORE0, e_r7->radio_txmix5g_boost_tune_core0); 786300016Sadrian BWN_RF_WRITE(mac, R2057_PAD5G_TUNE_MISC_PUS_CORE0, e_r7->radio_pad5g_tune_misc_pus_core0); 787300016Sadrian BWN_RF_WRITE(mac, R2057_LNA2G_TUNE_CORE0, e_r7->radio_lna2g_tune_core0); 788300016Sadrian BWN_RF_WRITE(mac, R2057_LNA5G_TUNE_CORE0, e_r7->radio_lna5g_tune_core0); 789300016Sadrian BWN_RF_WRITE(mac, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, e_r7->radio_txmix2g_tune_boost_pu_core1); 790300016Sadrian BWN_RF_WRITE(mac, R2057_PAD2G_TUNE_PUS_CORE1, e_r7->radio_pad2g_tune_pus_core1); 791300016Sadrian BWN_RF_WRITE(mac, R2057_PGA_BOOST_TUNE_CORE1, e_r7->radio_pga_boost_tune_core1); 792300016Sadrian BWN_RF_WRITE(mac, R2057_TXMIX5G_BOOST_TUNE_CORE1, e_r7->radio_txmix5g_boost_tune_core1); 793300016Sadrian BWN_RF_WRITE(mac, R2057_PAD5G_TUNE_MISC_PUS_CORE1, e_r7->radio_pad5g_tune_misc_pus_core1); 794300016Sadrian BWN_RF_WRITE(mac, R2057_LNA2G_TUNE_CORE1, e_r7->radio_lna2g_tune_core1); 795300016Sadrian BWN_RF_WRITE(mac, R2057_LNA5G_TUNE_CORE1, e_r7->radio_lna5g_tune_core1); 796300016Sadrian } 797300016Sadrian} 798300016Sadrian 799300016Sadrianstatic void bwn_radio_2057_setup(struct bwn_mac *mac, 800300016Sadrian const struct bwn_nphy_chantabent_rev7 *tabent_r7, 801300016Sadrian const struct bwn_nphy_chantabent_rev7_2g *tabent_r7_2g) 802300016Sadrian{ 803300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 804300016Sadrian 805300016Sadrian bwn_radio_2057_chantab_upload(mac, tabent_r7, tabent_r7_2g); 806300016Sadrian 807300016Sadrian switch (phy->rf_rev) { 808300016Sadrian case 0 ... 4: 809300016Sadrian case 6: 810300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 811300016Sadrian BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_R1, 0x3f); 812300016Sadrian BWN_RF_WRITE(mac, R2057_CP_KPD_IDAC, 0x3f); 813300016Sadrian BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C1, 0x8); 814300016Sadrian BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C2, 0x8); 815300016Sadrian } else { 816300016Sadrian BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_R1, 0x1f); 817300016Sadrian BWN_RF_WRITE(mac, R2057_CP_KPD_IDAC, 0x3f); 818300016Sadrian BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C1, 0x8); 819300016Sadrian BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C2, 0x8); 820300016Sadrian } 821300016Sadrian break; 822300016Sadrian case 9: /* e.g. PHY rev 16 */ 823300016Sadrian BWN_RF_WRITE(mac, R2057_LOGEN_PTAT_RESETS, 0x20); 824300016Sadrian BWN_RF_WRITE(mac, R2057_VCOBUF_IDACS, 0x18); 825300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G) { 826300016Sadrian BWN_RF_WRITE(mac, R2057_LOGEN_PTAT_RESETS, 0x38); 827300016Sadrian BWN_RF_WRITE(mac, R2057_VCOBUF_IDACS, 0x0f); 828300016Sadrian 829300016Sadrian if (bwn_is_40mhz(mac)) { 830300016Sadrian /* TODO */ 831300016Sadrian } else { 832300016Sadrian BWN_RF_WRITE(mac, 833300016Sadrian R2057_PAD_BIAS_FILTER_BWS_CORE0, 834300016Sadrian 0x3c); 835300016Sadrian BWN_RF_WRITE(mac, 836300016Sadrian R2057_PAD_BIAS_FILTER_BWS_CORE1, 837300016Sadrian 0x3c); 838300016Sadrian } 839300016Sadrian } 840300016Sadrian break; 841300016Sadrian case 14: /* 2 GHz only */ 842300016Sadrian BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_R1, 0x1b); 843300016Sadrian BWN_RF_WRITE(mac, R2057_CP_KPD_IDAC, 0x3f); 844300016Sadrian BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C1, 0x1f); 845300016Sadrian BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C2, 0x1f); 846300016Sadrian break; 847300016Sadrian } 848300016Sadrian 849300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 850300016Sadrian uint16_t txmix2g_tune_boost_pu = 0; 851300016Sadrian uint16_t pad2g_tune_pus = 0; 852300016Sadrian 853300016Sadrian if (bwn_nphy_ipa(mac)) { 854300016Sadrian switch (phy->rf_rev) { 855300016Sadrian case 9: 856300016Sadrian txmix2g_tune_boost_pu = 0x0041; 857300016Sadrian /* TODO */ 858300016Sadrian break; 859300016Sadrian case 14: 860300016Sadrian txmix2g_tune_boost_pu = 0x21; 861300016Sadrian pad2g_tune_pus = 0x23; 862300016Sadrian break; 863300016Sadrian } 864300016Sadrian } 865300016Sadrian 866300016Sadrian if (txmix2g_tune_boost_pu) 867300016Sadrian BWN_RF_WRITE(mac, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, 868300016Sadrian txmix2g_tune_boost_pu); 869300016Sadrian if (pad2g_tune_pus) 870300016Sadrian BWN_RF_WRITE(mac, R2057_PAD2G_TUNE_PUS_CORE0, 871300016Sadrian pad2g_tune_pus); 872300016Sadrian if (txmix2g_tune_boost_pu) 873300016Sadrian BWN_RF_WRITE(mac, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, 874300016Sadrian txmix2g_tune_boost_pu); 875300016Sadrian if (pad2g_tune_pus) 876300016Sadrian BWN_RF_WRITE(mac, R2057_PAD2G_TUNE_PUS_CORE1, 877300016Sadrian pad2g_tune_pus); 878300016Sadrian } 879300016Sadrian 880300016Sadrian /* 50..100 */ 881300016Sadrian DELAY(100); 882300016Sadrian 883300016Sadrian /* VCO calibration */ 884300016Sadrian BWN_RF_MASK(mac, R2057_RFPLL_MISC_EN, ~0x01); 885300016Sadrian BWN_RF_MASK(mac, R2057_RFPLL_MISC_CAL_RESETN, ~0x04); 886300016Sadrian BWN_RF_SET(mac, R2057_RFPLL_MISC_CAL_RESETN, 0x4); 887300016Sadrian BWN_RF_SET(mac, R2057_RFPLL_MISC_EN, 0x01); 888300016Sadrian /* 300..600 */ 889300016Sadrian DELAY(600); 890300016Sadrian} 891300016Sadrian 892300016Sadrian/* Calibrate resistors in LPF of PLL? 893300016Sadrian * http://bcm-v4.sipsolutions.net/PHY/radio205x_rcal 894300016Sadrian */ 895300016Sadrianstatic uint8_t bwn_radio_2057_rcal(struct bwn_mac *mac) 896300016Sadrian{ 897300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 898300016Sadrian uint16_t saved_regs_phy[12]; 899300016Sadrian uint16_t saved_regs_phy_rf[6]; 900300016Sadrian uint16_t saved_regs_radio[2] = { }; 901300016Sadrian static const uint16_t phy_to_store[] = { 902300016Sadrian BWN_NPHY_RFCTL_RSSIO1, BWN_NPHY_RFCTL_RSSIO2, 903300016Sadrian BWN_NPHY_RFCTL_LUT_TRSW_LO1, BWN_NPHY_RFCTL_LUT_TRSW_LO2, 904300016Sadrian BWN_NPHY_RFCTL_RXG1, BWN_NPHY_RFCTL_RXG2, 905300016Sadrian BWN_NPHY_RFCTL_TXG1, BWN_NPHY_RFCTL_TXG2, 906300016Sadrian BWN_NPHY_REV7_RF_CTL_MISC_REG3, BWN_NPHY_REV7_RF_CTL_MISC_REG4, 907300016Sadrian BWN_NPHY_REV7_RF_CTL_MISC_REG5, BWN_NPHY_REV7_RF_CTL_MISC_REG6, 908300016Sadrian }; 909300016Sadrian static const uint16_t phy_to_store_rf[] = { 910300016Sadrian BWN_NPHY_REV3_RFCTL_OVER0, BWN_NPHY_REV3_RFCTL_OVER1, 911300016Sadrian BWN_NPHY_REV7_RF_CTL_OVER3, BWN_NPHY_REV7_RF_CTL_OVER4, 912300016Sadrian BWN_NPHY_REV7_RF_CTL_OVER5, BWN_NPHY_REV7_RF_CTL_OVER6, 913300016Sadrian }; 914300016Sadrian uint16_t tmp; 915300016Sadrian int i; 916300016Sadrian 917300016Sadrian /* Save */ 918300016Sadrian for (i = 0; i < nitems(phy_to_store); i++) 919300016Sadrian saved_regs_phy[i] = BWN_PHY_READ(mac, phy_to_store[i]); 920300016Sadrian for (i = 0; i < nitems(phy_to_store_rf); i++) 921300016Sadrian saved_regs_phy_rf[i] = BWN_PHY_READ(mac, phy_to_store_rf[i]); 922300016Sadrian 923300016Sadrian /* Set */ 924300016Sadrian for (i = 0; i < nitems(phy_to_store); i++) 925300016Sadrian BWN_PHY_WRITE(mac, phy_to_store[i], 0); 926300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV3_RFCTL_OVER0, 0x07ff); 927300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV3_RFCTL_OVER1, 0x07ff); 928300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER3, 0x07ff); 929300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER4, 0x07ff); 930300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER5, 0x007f); 931300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER6, 0x007f); 932300016Sadrian 933300016Sadrian switch (phy->rf_rev) { 934300016Sadrian case 5: 935300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_REV7_RF_CTL_OVER3, ~0x2); 936300016Sadrian DELAY(10); 937300016Sadrian BWN_RF_SET(mac, R2057_IQTEST_SEL_PU, 0x1); 938300016Sadrian BWN_RF_SETMASK(mac, R2057v7_IQTEST_SEL_PU2, ~0x2, 0x1); 939300016Sadrian break; 940300016Sadrian case 9: 941300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_REV7_RF_CTL_OVER3, 0x2); 942300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_REV7_RF_CTL_MISC_REG3, 0x2); 943300016Sadrian saved_regs_radio[0] = BWN_RF_READ(mac, R2057_IQTEST_SEL_PU); 944300016Sadrian BWN_RF_WRITE(mac, R2057_IQTEST_SEL_PU, 0x11); 945300016Sadrian break; 946300016Sadrian case 14: 947300016Sadrian saved_regs_radio[0] = BWN_RF_READ(mac, R2057_IQTEST_SEL_PU); 948300016Sadrian saved_regs_radio[1] = BWN_RF_READ(mac, R2057v7_IQTEST_SEL_PU2); 949300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_REV7_RF_CTL_MISC_REG3, 0x2); 950300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_REV7_RF_CTL_OVER3, 0x2); 951300016Sadrian BWN_RF_WRITE(mac, R2057v7_IQTEST_SEL_PU2, 0x2); 952300016Sadrian BWN_RF_WRITE(mac, R2057_IQTEST_SEL_PU, 0x1); 953300016Sadrian break; 954300016Sadrian } 955300016Sadrian 956300016Sadrian /* Enable */ 957300016Sadrian BWN_RF_SET(mac, R2057_RCAL_CONFIG, 0x1); 958300016Sadrian DELAY(10); 959300016Sadrian 960300016Sadrian /* Start */ 961300016Sadrian BWN_RF_SET(mac, R2057_RCAL_CONFIG, 0x2); 962300016Sadrian /* 100..200 */ 963300016Sadrian DELAY(200); 964300016Sadrian 965300016Sadrian /* Stop */ 966300016Sadrian BWN_RF_MASK(mac, R2057_RCAL_CONFIG, ~0x2); 967300016Sadrian 968300016Sadrian /* Wait and check for result */ 969300016Sadrian if (!bwn_radio_wait_value(mac, R2057_RCAL_STATUS, 1, 1, 100, 1000000)) { 970300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "Radio 0x2057 rcal timeout\n"); 971300016Sadrian return 0; 972300016Sadrian } 973300016Sadrian tmp = BWN_RF_READ(mac, R2057_RCAL_STATUS) & 0x3E; 974300016Sadrian 975300016Sadrian /* Disable */ 976300016Sadrian BWN_RF_MASK(mac, R2057_RCAL_CONFIG, ~0x1); 977300016Sadrian 978300016Sadrian /* Restore */ 979300016Sadrian for (i = 0; i < nitems(phy_to_store_rf); i++) 980300016Sadrian BWN_PHY_WRITE(mac, phy_to_store_rf[i], saved_regs_phy_rf[i]); 981300016Sadrian for (i = 0; i < nitems(phy_to_store); i++) 982300016Sadrian BWN_PHY_WRITE(mac, phy_to_store[i], saved_regs_phy[i]); 983300016Sadrian 984300016Sadrian switch (phy->rf_rev) { 985300016Sadrian case 0 ... 4: 986300016Sadrian case 6: 987300016Sadrian BWN_RF_SETMASK(mac, R2057_TEMPSENSE_CONFIG, ~0x3C, tmp); 988300016Sadrian BWN_RF_SETMASK(mac, R2057_BANDGAP_RCAL_TRIM, ~0xF0, 989300016Sadrian tmp << 2); 990300016Sadrian break; 991300016Sadrian case 5: 992300016Sadrian BWN_RF_MASK(mac, R2057_IPA2G_CASCONV_CORE0, ~0x1); 993300016Sadrian BWN_RF_MASK(mac, R2057v7_IQTEST_SEL_PU2, ~0x2); 994300016Sadrian break; 995300016Sadrian case 9: 996300016Sadrian BWN_RF_WRITE(mac, R2057_IQTEST_SEL_PU, saved_regs_radio[0]); 997300016Sadrian break; 998300016Sadrian case 14: 999300016Sadrian BWN_RF_WRITE(mac, R2057_IQTEST_SEL_PU, saved_regs_radio[0]); 1000300016Sadrian BWN_RF_WRITE(mac, R2057v7_IQTEST_SEL_PU2, saved_regs_radio[1]); 1001300016Sadrian break; 1002300016Sadrian } 1003300016Sadrian 1004300016Sadrian return tmp & 0x3e; 1005300016Sadrian} 1006300016Sadrian 1007300016Sadrian/* Calibrate the internal RC oscillator? 1008300016Sadrian * http://bcm-v4.sipsolutions.net/PHY/radio2057_rccal 1009300016Sadrian */ 1010300016Sadrianstatic uint16_t bwn_radio_2057_rccal(struct bwn_mac *mac) 1011300016Sadrian{ 1012300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 1013300016Sadrian bool special = (phy->rf_rev == 3 || phy->rf_rev == 4 || 1014300016Sadrian phy->rf_rev == 6); 1015300016Sadrian uint16_t tmp; 1016300016Sadrian 1017300016Sadrian /* Setup cal */ 1018300016Sadrian if (special) { 1019300016Sadrian BWN_RF_WRITE(mac, R2057_RCCAL_MASTER, 0x61); 1020300016Sadrian BWN_RF_WRITE(mac, R2057_RCCAL_TRC0, 0xC0); 1021300016Sadrian } else { 1022300016Sadrian BWN_RF_WRITE(mac, R2057v7_RCCAL_MASTER, 0x61); 1023300016Sadrian BWN_RF_WRITE(mac, R2057_RCCAL_TRC0, 0xE9); 1024300016Sadrian } 1025300016Sadrian BWN_RF_WRITE(mac, R2057_RCCAL_X1, 0x6E); 1026300016Sadrian 1027300016Sadrian /* Start, wait, stop */ 1028300016Sadrian BWN_RF_WRITE(mac, R2057_RCCAL_START_R1_Q1_P1, 0x55); 1029300016Sadrian if (!bwn_radio_wait_value(mac, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500, 1030300016Sadrian 5000000)) 1031300016Sadrian BWN_DBGPRINTF(mac, "Radio 0x2057 rccal timeout\n"); 1032300016Sadrian /* 35..70 */ 1033300016Sadrian DELAY(70); 1034300016Sadrian BWN_RF_WRITE(mac, R2057_RCCAL_START_R1_Q1_P1, 0x15); 1035300016Sadrian /* 70..140 */ 1036300016Sadrian DELAY(140); 1037300016Sadrian 1038300016Sadrian /* Setup cal */ 1039300016Sadrian if (special) { 1040300016Sadrian BWN_RF_WRITE(mac, R2057_RCCAL_MASTER, 0x69); 1041300016Sadrian BWN_RF_WRITE(mac, R2057_RCCAL_TRC0, 0xB0); 1042300016Sadrian } else { 1043300016Sadrian BWN_RF_WRITE(mac, R2057v7_RCCAL_MASTER, 0x69); 1044300016Sadrian BWN_RF_WRITE(mac, R2057_RCCAL_TRC0, 0xD5); 1045300016Sadrian } 1046300016Sadrian BWN_RF_WRITE(mac, R2057_RCCAL_X1, 0x6E); 1047300016Sadrian 1048300016Sadrian /* Start, wait, stop */ 1049300016Sadrian /* 35..70 */ 1050300016Sadrian DELAY(70); 1051300016Sadrian BWN_RF_WRITE(mac, R2057_RCCAL_START_R1_Q1_P1, 0x55); 1052300016Sadrian /* 70..140 */ 1053300016Sadrian DELAY(140); 1054300016Sadrian if (!bwn_radio_wait_value(mac, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500, 1055300016Sadrian 5000000)) 1056300016Sadrian BWN_DBGPRINTF(mac, "Radio 0x2057 rccal timeout\n"); 1057300016Sadrian /* 35..70 */ 1058300016Sadrian DELAY(70); 1059300016Sadrian BWN_RF_WRITE(mac, R2057_RCCAL_START_R1_Q1_P1, 0x15); 1060300016Sadrian /* 70..140 */ 1061300016Sadrian DELAY(140); 1062300016Sadrian 1063300016Sadrian /* Setup cal */ 1064300016Sadrian if (special) { 1065300016Sadrian BWN_RF_WRITE(mac, R2057_RCCAL_MASTER, 0x73); 1066300016Sadrian BWN_RF_WRITE(mac, R2057_RCCAL_X1, 0x28); 1067300016Sadrian BWN_RF_WRITE(mac, R2057_RCCAL_TRC0, 0xB0); 1068300016Sadrian } else { 1069300016Sadrian BWN_RF_WRITE(mac, R2057v7_RCCAL_MASTER, 0x73); 1070300016Sadrian BWN_RF_WRITE(mac, R2057_RCCAL_X1, 0x6E); 1071300016Sadrian BWN_RF_WRITE(mac, R2057_RCCAL_TRC0, 0x99); 1072300016Sadrian } 1073300016Sadrian 1074300016Sadrian /* Start, wait, stop */ 1075300016Sadrian /* 35..70 */ 1076300016Sadrian DELAY(70); 1077300016Sadrian BWN_RF_WRITE(mac, R2057_RCCAL_START_R1_Q1_P1, 0x55); 1078300016Sadrian /* 70..140 */ 1079300016Sadrian DELAY(140); 1080300016Sadrian if (!bwn_radio_wait_value(mac, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500, 1081300016Sadrian 5000000)) { 1082300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "Radio 0x2057 rcal timeout\n"); 1083300016Sadrian return 0; 1084300016Sadrian } 1085300016Sadrian tmp = BWN_RF_READ(mac, R2057_RCCAL_DONE_OSCCAP); 1086300016Sadrian /* 35..70 */ 1087300016Sadrian DELAY(70); 1088300016Sadrian BWN_RF_WRITE(mac, R2057_RCCAL_START_R1_Q1_P1, 0x15); 1089300016Sadrian /* 70..140 */ 1090300016Sadrian DELAY(140); 1091300016Sadrian 1092300016Sadrian if (special) 1093300016Sadrian BWN_RF_MASK(mac, R2057_RCCAL_MASTER, ~0x1); 1094300016Sadrian else 1095300016Sadrian BWN_RF_MASK(mac, R2057v7_RCCAL_MASTER, ~0x1); 1096300016Sadrian 1097300016Sadrian return tmp; 1098300016Sadrian} 1099300016Sadrian 1100300016Sadrianstatic void bwn_radio_2057_init_pre(struct bwn_mac *mac) 1101300016Sadrian{ 1102300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, ~BWN_NPHY_RFCTL_CMD_CHIP0PU); 1103300016Sadrian /* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */ 1104300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, BWN_NPHY_RFCTL_CMD_OEPORFORCE); 1105300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, ~BWN_NPHY_RFCTL_CMD_OEPORFORCE); 1106300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, BWN_NPHY_RFCTL_CMD_CHIP0PU); 1107300016Sadrian} 1108300016Sadrian 1109300016Sadrianstatic void bwn_radio_2057_init_post(struct bwn_mac *mac) 1110300016Sadrian{ 1111300016Sadrian BWN_RF_SET(mac, R2057_XTALPUOVR_PINCTRL, 0x1); 1112300016Sadrian 1113300016Sadrian if (0) /* FIXME: Is this BCM43217 specific? */ 1114300016Sadrian BWN_RF_SET(mac, R2057_XTALPUOVR_PINCTRL, 0x2); 1115300016Sadrian 1116300016Sadrian BWN_RF_SET(mac, R2057_RFPLL_MISC_CAL_RESETN, 0x78); 1117300016Sadrian BWN_RF_SET(mac, R2057_XTAL_CONFIG2, 0x80); 1118300016Sadrian DELAY(2000); 1119300016Sadrian BWN_RF_MASK(mac, R2057_RFPLL_MISC_CAL_RESETN, ~0x78); 1120300016Sadrian BWN_RF_MASK(mac, R2057_XTAL_CONFIG2, ~0x80); 1121300016Sadrian 1122300016Sadrian if (mac->mac_phy.phy_do_full_init) { 1123300016Sadrian bwn_radio_2057_rcal(mac); 1124300016Sadrian bwn_radio_2057_rccal(mac); 1125300016Sadrian } 1126300016Sadrian BWN_RF_MASK(mac, R2057_RFPLL_MASTER, ~0x8); 1127300016Sadrian} 1128300016Sadrian 1129300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/Radio/2057/Init */ 1130300016Sadrianstatic void bwn_radio_2057_init(struct bwn_mac *mac) 1131300016Sadrian{ 1132300016Sadrian bwn_radio_2057_init_pre(mac); 1133300016Sadrian r2057_upload_inittabs(mac); 1134300016Sadrian bwn_radio_2057_init_post(mac); 1135300016Sadrian} 1136300016Sadrian 1137300016Sadrian/************************************************** 1138300016Sadrian * Radio 0x2056 1139300016Sadrian **************************************************/ 1140300016Sadrian 1141300016Sadrianstatic void bwn_chantab_radio_2056_upload(struct bwn_mac *mac, 1142300016Sadrian const struct bwn_nphy_channeltab_entry_rev3 *e) 1143300016Sadrian{ 1144300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_VCOCAL1, e->radio_syn_pll_vcocal1); 1145300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_VCOCAL2, e->radio_syn_pll_vcocal2); 1146300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_REFDIV, e->radio_syn_pll_refdiv); 1147300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_MMD2, e->radio_syn_pll_mmd2); 1148300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_MMD1, e->radio_syn_pll_mmd1); 1149300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER1, 1150300016Sadrian e->radio_syn_pll_loopfilter1); 1151300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER2, 1152300016Sadrian e->radio_syn_pll_loopfilter2); 1153300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER3, 1154300016Sadrian e->radio_syn_pll_loopfilter3); 1155300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER4, 1156300016Sadrian e->radio_syn_pll_loopfilter4); 1157300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER5, 1158300016Sadrian e->radio_syn_pll_loopfilter5); 1159300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_RESERVED_ADDR27, 1160300016Sadrian e->radio_syn_reserved_addr27); 1161300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_RESERVED_ADDR28, 1162300016Sadrian e->radio_syn_reserved_addr28); 1163300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_RESERVED_ADDR29, 1164300016Sadrian e->radio_syn_reserved_addr29); 1165300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_LOGEN_VCOBUF1, 1166300016Sadrian e->radio_syn_logen_vcobuf1); 1167300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_LOGEN_MIXER2, e->radio_syn_logen_mixer2); 1168300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_LOGEN_BUF3, e->radio_syn_logen_buf3); 1169300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_LOGEN_BUF4, e->radio_syn_logen_buf4); 1170300016Sadrian 1171300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_LNAA_TUNE, 1172300016Sadrian e->radio_rx0_lnaa_tune); 1173300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_LNAG_TUNE, 1174300016Sadrian e->radio_rx0_lnag_tune); 1175300016Sadrian 1176300016Sadrian BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_INTPAA_BOOST_TUNE, 1177300016Sadrian e->radio_tx0_intpaa_boost_tune); 1178300016Sadrian BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_INTPAG_BOOST_TUNE, 1179300016Sadrian e->radio_tx0_intpag_boost_tune); 1180300016Sadrian BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_PADA_BOOST_TUNE, 1181300016Sadrian e->radio_tx0_pada_boost_tune); 1182300016Sadrian BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_PADG_BOOST_TUNE, 1183300016Sadrian e->radio_tx0_padg_boost_tune); 1184300016Sadrian BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_PGAA_BOOST_TUNE, 1185300016Sadrian e->radio_tx0_pgaa_boost_tune); 1186300016Sadrian BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_PGAG_BOOST_TUNE, 1187300016Sadrian e->radio_tx0_pgag_boost_tune); 1188300016Sadrian BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_MIXA_BOOST_TUNE, 1189300016Sadrian e->radio_tx0_mixa_boost_tune); 1190300016Sadrian BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_MIXG_BOOST_TUNE, 1191300016Sadrian e->radio_tx0_mixg_boost_tune); 1192300016Sadrian 1193300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_LNAA_TUNE, 1194300016Sadrian e->radio_rx1_lnaa_tune); 1195300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_LNAG_TUNE, 1196300016Sadrian e->radio_rx1_lnag_tune); 1197300016Sadrian 1198300016Sadrian BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_INTPAA_BOOST_TUNE, 1199300016Sadrian e->radio_tx1_intpaa_boost_tune); 1200300016Sadrian BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_INTPAG_BOOST_TUNE, 1201300016Sadrian e->radio_tx1_intpag_boost_tune); 1202300016Sadrian BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_PADA_BOOST_TUNE, 1203300016Sadrian e->radio_tx1_pada_boost_tune); 1204300016Sadrian BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_PADG_BOOST_TUNE, 1205300016Sadrian e->radio_tx1_padg_boost_tune); 1206300016Sadrian BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_PGAA_BOOST_TUNE, 1207300016Sadrian e->radio_tx1_pgaa_boost_tune); 1208300016Sadrian BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_PGAG_BOOST_TUNE, 1209300016Sadrian e->radio_tx1_pgag_boost_tune); 1210300016Sadrian BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_MIXA_BOOST_TUNE, 1211300016Sadrian e->radio_tx1_mixa_boost_tune); 1212300016Sadrian BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_MIXG_BOOST_TUNE, 1213300016Sadrian e->radio_tx1_mixg_boost_tune); 1214300016Sadrian} 1215300016Sadrian 1216300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2056Setup */ 1217300016Sadrianstatic void bwn_radio_2056_setup(struct bwn_mac *mac, 1218300016Sadrian const struct bwn_nphy_channeltab_entry_rev3 *e) 1219300016Sadrian{ 1220300016Sadrian struct bwn_softc *sc = mac->mac_sc; 1221300016Sadrian bwn_band_t band = bwn_current_band(mac); 1222300016Sadrian uint16_t offset; 1223300016Sadrian uint8_t i; 1224300016Sadrian uint16_t bias, cbias; 1225300016Sadrian uint16_t pag_boost, padg_boost, pgag_boost, mixg_boost; 1226300016Sadrian uint16_t paa_boost, pada_boost, pgaa_boost, mixa_boost; 1227300016Sadrian bool is_pkg_fab_smic; 1228300016Sadrian 1229300016Sadrian DPRINTF(mac->mac_sc, BWN_DEBUG_RF, "%s: called\n", __func__); 1230300016Sadrian 1231300016Sadrian if (mac->mac_phy.rev < 3) { 1232300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "%s: phy rev %d out of range\n", 1233300016Sadrian __func__, 1234300016Sadrian mac->mac_phy.rev); 1235300016Sadrian } 1236300016Sadrian 1237300016Sadrian is_pkg_fab_smic = 1238300016Sadrian ((siba_get_chipid(sc->sc_dev) == BCMA_CHIP_ID_BCM43224 || 1239300016Sadrian siba_get_chipid(sc->sc_dev) == BCMA_CHIP_ID_BCM43225 || 1240300016Sadrian siba_get_chipid(sc->sc_dev) == BCMA_CHIP_ID_BCM43421) && 1241300016Sadrian siba_get_chippkg(sc->sc_dev) == BCMA_PKG_ID_BCM43224_FAB_SMIC); 1242300016Sadrian 1243300016Sadrian bwn_chantab_radio_2056_upload(mac, e); 1244300016Sadrian b2056_upload_syn_pll_cp2(mac, band == BWN_BAND_5G); 1245300016Sadrian 1246300016Sadrian if (siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_GPLL_WAR && 1247300016Sadrian bwn_current_band(mac) == BWN_BAND_2G) { 1248300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER1, 0x1F); 1249300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER2, 0x1F); 1250300016Sadrian if (siba_get_chipid(sc->sc_dev) == BCMA_CHIP_ID_BCM4716 || 1251300016Sadrian siba_get_chipid(sc->sc_dev) == BCMA_CHIP_ID_BCM47162) { 1252300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER4, 0x14); 1253300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_CP2, 0); 1254300016Sadrian } else { 1255300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER4, 0x0B); 1256300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_CP2, 0x14); 1257300016Sadrian } 1258300016Sadrian } 1259300016Sadrian if (siba_sprom_get_bf2_hi(sc->sc_dev) & BWN_BFH2_GPLL_WAR2 && 1260300016Sadrian bwn_current_band(mac) == BWN_BAND_2G) { 1261300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER1, 0x1f); 1262300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER2, 0x1f); 1263300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER4, 0x0b); 1264300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_CP2, 0x20); 1265300016Sadrian } 1266300016Sadrian if (siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_APLL_WAR && 1267300016Sadrian bwn_current_band(mac) == BWN_BAND_5G) { 1268300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER1, 0x1F); 1269300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER2, 0x1F); 1270300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER4, 0x05); 1271300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_CP2, 0x0C); 1272300016Sadrian } 1273300016Sadrian 1274300016Sadrian if (mac->mac_phy.phy_n->ipa2g_on && band == BWN_BAND_2G) { 1275300016Sadrian for (i = 0; i < 2; i++) { 1276300016Sadrian offset = i ? B2056_TX1 : B2056_TX0; 1277300016Sadrian if (mac->mac_phy.rev >= 5) { 1278300016Sadrian BWN_RF_WRITE(mac, 1279300016Sadrian offset | B2056_TX_PADG_IDAC, 0xcc); 1280300016Sadrian 1281300016Sadrian if (siba_get_chipid(sc->sc_dev) == BCMA_CHIP_ID_BCM4716 || 1282300016Sadrian siba_get_chipid(sc->sc_dev) == BCMA_CHIP_ID_BCM47162) { 1283300016Sadrian bias = 0x40; 1284300016Sadrian cbias = 0x45; 1285300016Sadrian pag_boost = 0x5; 1286300016Sadrian pgag_boost = 0x33; 1287300016Sadrian mixg_boost = 0x55; 1288300016Sadrian } else { 1289300016Sadrian bias = 0x25; 1290300016Sadrian cbias = 0x20; 1291300016Sadrian if (is_pkg_fab_smic) { 1292300016Sadrian bias = 0x2a; 1293300016Sadrian cbias = 0x38; 1294300016Sadrian } 1295300016Sadrian pag_boost = 0x4; 1296300016Sadrian pgag_boost = 0x03; 1297300016Sadrian mixg_boost = 0x65; 1298300016Sadrian } 1299300016Sadrian padg_boost = 0x77; 1300300016Sadrian 1301300016Sadrian BWN_RF_WRITE(mac, 1302300016Sadrian offset | B2056_TX_INTPAG_IMAIN_STAT, 1303300016Sadrian bias); 1304300016Sadrian BWN_RF_WRITE(mac, 1305300016Sadrian offset | B2056_TX_INTPAG_IAUX_STAT, 1306300016Sadrian bias); 1307300016Sadrian BWN_RF_WRITE(mac, 1308300016Sadrian offset | B2056_TX_INTPAG_CASCBIAS, 1309300016Sadrian cbias); 1310300016Sadrian BWN_RF_WRITE(mac, 1311300016Sadrian offset | B2056_TX_INTPAG_BOOST_TUNE, 1312300016Sadrian pag_boost); 1313300016Sadrian BWN_RF_WRITE(mac, 1314300016Sadrian offset | B2056_TX_PGAG_BOOST_TUNE, 1315300016Sadrian pgag_boost); 1316300016Sadrian BWN_RF_WRITE(mac, 1317300016Sadrian offset | B2056_TX_PADG_BOOST_TUNE, 1318300016Sadrian padg_boost); 1319300016Sadrian BWN_RF_WRITE(mac, 1320300016Sadrian offset | B2056_TX_MIXG_BOOST_TUNE, 1321300016Sadrian mixg_boost); 1322300016Sadrian } else { 1323300016Sadrian bias = bwn_is_40mhz(mac) ? 0x40 : 0x20; 1324300016Sadrian BWN_RF_WRITE(mac, 1325300016Sadrian offset | B2056_TX_INTPAG_IMAIN_STAT, 1326300016Sadrian bias); 1327300016Sadrian BWN_RF_WRITE(mac, 1328300016Sadrian offset | B2056_TX_INTPAG_IAUX_STAT, 1329300016Sadrian bias); 1330300016Sadrian BWN_RF_WRITE(mac, 1331300016Sadrian offset | B2056_TX_INTPAG_CASCBIAS, 1332300016Sadrian 0x30); 1333300016Sadrian } 1334300016Sadrian BWN_RF_WRITE(mac, offset | B2056_TX_PA_SPARE1, 0xee); 1335300016Sadrian } 1336300016Sadrian } else if (mac->mac_phy.phy_n->ipa5g_on && band == BWN_BAND_5G) { 1337300016Sadrian uint16_t freq = bwn_get_centre_freq(mac); 1338300016Sadrian /* XXX 5g low/med/high? */ 1339300016Sadrian if (freq < 5100) { 1340300016Sadrian paa_boost = 0xA; 1341300016Sadrian pada_boost = 0x77; 1342300016Sadrian pgaa_boost = 0xF; 1343300016Sadrian mixa_boost = 0xF; 1344300016Sadrian } else if (freq < 5340) { 1345300016Sadrian paa_boost = 0x8; 1346300016Sadrian pada_boost = 0x77; 1347300016Sadrian pgaa_boost = 0xFB; 1348300016Sadrian mixa_boost = 0xF; 1349300016Sadrian } else if (freq < 5650) { 1350300016Sadrian paa_boost = 0x0; 1351300016Sadrian pada_boost = 0x77; 1352300016Sadrian pgaa_boost = 0xB; 1353300016Sadrian mixa_boost = 0xF; 1354300016Sadrian } else { 1355300016Sadrian paa_boost = 0x0; 1356300016Sadrian pada_boost = 0x77; 1357300016Sadrian if (freq != 5825) 1358300016Sadrian pgaa_boost = -(freq - 18) / 36 + 168; 1359300016Sadrian else 1360300016Sadrian pgaa_boost = 6; 1361300016Sadrian mixa_boost = 0xF; 1362300016Sadrian } 1363300016Sadrian 1364300016Sadrian cbias = is_pkg_fab_smic ? 0x35 : 0x30; 1365300016Sadrian 1366300016Sadrian for (i = 0; i < 2; i++) { 1367300016Sadrian offset = i ? B2056_TX1 : B2056_TX0; 1368300016Sadrian 1369300016Sadrian BWN_RF_WRITE(mac, 1370300016Sadrian offset | B2056_TX_INTPAA_BOOST_TUNE, paa_boost); 1371300016Sadrian BWN_RF_WRITE(mac, 1372300016Sadrian offset | B2056_TX_PADA_BOOST_TUNE, pada_boost); 1373300016Sadrian BWN_RF_WRITE(mac, 1374300016Sadrian offset | B2056_TX_PGAA_BOOST_TUNE, pgaa_boost); 1375300016Sadrian BWN_RF_WRITE(mac, 1376300016Sadrian offset | B2056_TX_MIXA_BOOST_TUNE, mixa_boost); 1377300016Sadrian BWN_RF_WRITE(mac, 1378300016Sadrian offset | B2056_TX_TXSPARE1, 0x30); 1379300016Sadrian BWN_RF_WRITE(mac, 1380300016Sadrian offset | B2056_TX_PA_SPARE2, 0xee); 1381300016Sadrian BWN_RF_WRITE(mac, 1382300016Sadrian offset | B2056_TX_PADA_CASCBIAS, 0x03); 1383300016Sadrian BWN_RF_WRITE(mac, 1384300016Sadrian offset | B2056_TX_INTPAA_IAUX_STAT, 0x30); 1385300016Sadrian BWN_RF_WRITE(mac, 1386300016Sadrian offset | B2056_TX_INTPAA_IMAIN_STAT, 0x30); 1387300016Sadrian BWN_RF_WRITE(mac, 1388300016Sadrian offset | B2056_TX_INTPAA_CASCBIAS, cbias); 1389300016Sadrian } 1390300016Sadrian } 1391300016Sadrian 1392300016Sadrian DELAY(50); 1393300016Sadrian /* VCO calibration */ 1394300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_VCOCAL12, 0x00); 1395300016Sadrian BWN_RF_WRITE(mac, B2056_TX_INTPAA_PA_MISC, 0x38); 1396300016Sadrian BWN_RF_WRITE(mac, B2056_TX_INTPAA_PA_MISC, 0x18); 1397300016Sadrian BWN_RF_WRITE(mac, B2056_TX_INTPAA_PA_MISC, 0x38); 1398300016Sadrian BWN_RF_WRITE(mac, B2056_TX_INTPAA_PA_MISC, 0x39); 1399300016Sadrian DELAY(300); 1400300016Sadrian} 1401300016Sadrian 1402300016Sadrianstatic uint8_t bwn_radio_2056_rcal(struct bwn_mac *mac) 1403300016Sadrian{ 1404300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 1405300016Sadrian uint16_t mast2, tmp; 1406300016Sadrian 1407300016Sadrian if (phy->rev != 3) 1408300016Sadrian return 0; 1409300191Sadrian DPRINTF(mac->mac_sc, BWN_DEBUG_RF, "%s: called\n", __func__); 1410300016Sadrian 1411300016Sadrian mast2 = BWN_RF_READ(mac, B2056_SYN_PLL_MAST2); 1412300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_MAST2, mast2 | 0x7); 1413300016Sadrian 1414300016Sadrian DELAY(10); 1415300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_RCAL_MASTER, 0x01); 1416300016Sadrian DELAY(10); 1417300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_RCAL_MASTER, 0x09); 1418300016Sadrian 1419300016Sadrian if (!bwn_radio_wait_value(mac, B2056_SYN_RCAL_CODE_OUT, 0x80, 0x80, 100, 1420300016Sadrian 1000000)) { 1421300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "Radio recalibration timeout\n"); 1422300016Sadrian return 0; 1423300016Sadrian } 1424300016Sadrian 1425300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_RCAL_MASTER, 0x01); 1426300016Sadrian tmp = BWN_RF_READ(mac, B2056_SYN_RCAL_CODE_OUT); 1427300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_RCAL_MASTER, 0x00); 1428300016Sadrian 1429300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_MAST2, mast2); 1430300016Sadrian 1431300016Sadrian return tmp & 0x1f; 1432300016Sadrian} 1433300016Sadrian 1434300016Sadrianstatic void bwn_radio_init2056_pre(struct bwn_mac *mac) 1435300016Sadrian{ 1436300191Sadrian DPRINTF(mac->mac_sc, BWN_DEBUG_RF, "%s: called\n", __func__); 1437300191Sadrian 1438300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, 1439300016Sadrian ~BWN_NPHY_RFCTL_CMD_CHIP0PU); 1440300016Sadrian /* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */ 1441300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, 1442300016Sadrian BWN_NPHY_RFCTL_CMD_OEPORFORCE); 1443300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, 1444300016Sadrian ~BWN_NPHY_RFCTL_CMD_OEPORFORCE); 1445300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, 1446300016Sadrian BWN_NPHY_RFCTL_CMD_CHIP0PU); 1447300016Sadrian} 1448300016Sadrian 1449300016Sadrianstatic void bwn_radio_init2056_post(struct bwn_mac *mac) 1450300016Sadrian{ 1451300191Sadrian DPRINTF(mac->mac_sc, BWN_DEBUG_RF, "%s: called\n", __func__); 1452300191Sadrian 1453300016Sadrian BWN_RF_SET(mac, B2056_SYN_COM_CTRL, 0xB); 1454300016Sadrian BWN_RF_SET(mac, B2056_SYN_COM_PU, 0x2); 1455300016Sadrian BWN_RF_SET(mac, B2056_SYN_COM_RESET, 0x2); 1456300016Sadrian DELAY(1000); 1457300016Sadrian BWN_RF_MASK(mac, B2056_SYN_COM_RESET, ~0x2); 1458300016Sadrian BWN_RF_MASK(mac, B2056_SYN_PLL_MAST2, ~0xFC); 1459300016Sadrian BWN_RF_MASK(mac, B2056_SYN_RCCAL_CTRL0, ~0x1); 1460300016Sadrian if (mac->mac_phy.phy_do_full_init) 1461300016Sadrian bwn_radio_2056_rcal(mac); 1462300016Sadrian} 1463300016Sadrian 1464300016Sadrian/* 1465300016Sadrian * Initialize a Broadcom 2056 N-radio 1466300016Sadrian * http://bcm-v4.sipsolutions.net/802.11/Radio/2056/Init 1467300016Sadrian */ 1468300016Sadrianstatic void bwn_radio_init2056(struct bwn_mac *mac) 1469300016Sadrian{ 1470300191Sadrian DPRINTF(mac->mac_sc, BWN_DEBUG_RF, "%s: called\n", __func__); 1471300191Sadrian 1472300016Sadrian bwn_radio_init2056_pre(mac); 1473300016Sadrian b2056_upload_inittabs(mac, 0, 0); 1474300016Sadrian bwn_radio_init2056_post(mac); 1475300016Sadrian} 1476300016Sadrian 1477300016Sadrian/************************************************** 1478300016Sadrian * Radio 0x2055 1479300016Sadrian **************************************************/ 1480300016Sadrian 1481300016Sadrianstatic void bwn_chantab_radio_upload(struct bwn_mac *mac, 1482300016Sadrian const struct bwn_nphy_channeltab_entry_rev2 *e) 1483300016Sadrian{ 1484300016Sadrian BWN_RF_WRITE(mac, B2055_PLL_REF, e->radio_pll_ref); 1485300016Sadrian BWN_RF_WRITE(mac, B2055_RF_PLLMOD0, e->radio_rf_pllmod0); 1486300016Sadrian BWN_RF_WRITE(mac, B2055_RF_PLLMOD1, e->radio_rf_pllmod1); 1487300016Sadrian BWN_RF_WRITE(mac, B2055_VCO_CAPTAIL, e->radio_vco_captail); 1488300016Sadrian BWN_READ_4(mac, BWN_MACCTL); /* flush writes */ 1489300016Sadrian 1490300016Sadrian BWN_RF_WRITE(mac, B2055_VCO_CAL1, e->radio_vco_cal1); 1491300016Sadrian BWN_RF_WRITE(mac, B2055_VCO_CAL2, e->radio_vco_cal2); 1492300016Sadrian BWN_RF_WRITE(mac, B2055_PLL_LFC1, e->radio_pll_lfc1); 1493300016Sadrian BWN_RF_WRITE(mac, B2055_PLL_LFR1, e->radio_pll_lfr1); 1494300016Sadrian BWN_READ_4(mac, BWN_MACCTL); /* flush writes */ 1495300016Sadrian 1496300016Sadrian BWN_RF_WRITE(mac, B2055_PLL_LFC2, e->radio_pll_lfc2); 1497300016Sadrian BWN_RF_WRITE(mac, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf); 1498300016Sadrian BWN_RF_WRITE(mac, B2055_LGEN_TUNE1, e->radio_lgen_tune1); 1499300016Sadrian BWN_RF_WRITE(mac, B2055_LGEN_TUNE2, e->radio_lgen_tune2); 1500300016Sadrian BWN_READ_4(mac, BWN_MACCTL); /* flush writes */ 1501300016Sadrian 1502300016Sadrian BWN_RF_WRITE(mac, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune); 1503300016Sadrian BWN_RF_WRITE(mac, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune); 1504300016Sadrian BWN_RF_WRITE(mac, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1); 1505300016Sadrian BWN_RF_WRITE(mac, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn); 1506300016Sadrian BWN_READ_4(mac, BWN_MACCTL); /* flush writes */ 1507300016Sadrian 1508300016Sadrian BWN_RF_WRITE(mac, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim); 1509300016Sadrian BWN_RF_WRITE(mac, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune); 1510300016Sadrian BWN_RF_WRITE(mac, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune); 1511300016Sadrian BWN_RF_WRITE(mac, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1); 1512300016Sadrian BWN_READ_4(mac, BWN_MACCTL); /* flush writes */ 1513300016Sadrian 1514300016Sadrian BWN_RF_WRITE(mac, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn); 1515300016Sadrian BWN_RF_WRITE(mac, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim); 1516300016Sadrian} 1517300016Sadrian 1518300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */ 1519300016Sadrianstatic void bwn_radio_2055_setup(struct bwn_mac *mac, 1520300016Sadrian const struct bwn_nphy_channeltab_entry_rev2 *e) 1521300016Sadrian{ 1522300016Sadrian 1523300016Sadrian if (mac->mac_phy.rev >= 3) { 1524300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "%s: phy rev %d out of range\n", 1525300016Sadrian __func__, 1526300016Sadrian mac->mac_phy.rev); 1527300016Sadrian } 1528300016Sadrian 1529300016Sadrian DPRINTF(mac->mac_sc, BWN_DEBUG_RF, "%s: called\n", __func__); 1530300016Sadrian 1531300016Sadrian bwn_chantab_radio_upload(mac, e); 1532300016Sadrian DELAY(50); 1533300016Sadrian BWN_RF_WRITE(mac, B2055_VCO_CAL10, 0x05); 1534300016Sadrian BWN_RF_WRITE(mac, B2055_VCO_CAL10, 0x45); 1535300016Sadrian BWN_READ_4(mac, BWN_MACCTL); /* flush writes */ 1536300016Sadrian BWN_RF_WRITE(mac, B2055_VCO_CAL10, 0x65); 1537300016Sadrian DELAY(300); 1538300016Sadrian} 1539300016Sadrian 1540300016Sadrianstatic void bwn_radio_init2055_pre(struct bwn_mac *mac) 1541300016Sadrian{ 1542300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, 1543300016Sadrian ~BWN_NPHY_RFCTL_CMD_PORFORCE); 1544300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, 1545300016Sadrian BWN_NPHY_RFCTL_CMD_CHIP0PU | 1546300016Sadrian BWN_NPHY_RFCTL_CMD_OEPORFORCE); 1547300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, 1548300016Sadrian BWN_NPHY_RFCTL_CMD_PORFORCE); 1549300016Sadrian} 1550300016Sadrian 1551300016Sadrianstatic void bwn_radio_init2055_post(struct bwn_mac *mac) 1552300016Sadrian{ 1553300016Sadrian struct bwn_softc *sc = mac->mac_sc; 1554300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 1555300016Sadrian bool workaround = false; 1556300016Sadrian 1557300016Sadrian if (siba_get_revid(sc->sc_dev) < 4) 1558300016Sadrian workaround = 1559300016Sadrian (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) 1560300016Sadrian && (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4321) 1561300016Sadrian && (siba_sprom_get_brev(sc->sc_dev) >= 0x41); 1562300016Sadrian else 1563300016Sadrian workaround = 1564300016Sadrian !(siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_RXBB_INT_REG_DIS); 1565300016Sadrian 1566300016Sadrian BWN_RF_MASK(mac, B2055_MASTER1, 0xFFF3); 1567300016Sadrian if (workaround) { 1568300016Sadrian BWN_RF_MASK(mac, B2055_C1_RX_BB_REG, 0x7F); 1569300016Sadrian BWN_RF_MASK(mac, B2055_C2_RX_BB_REG, 0x7F); 1570300016Sadrian } 1571300016Sadrian BWN_RF_SETMASK(mac, B2055_RRCCAL_NOPTSEL, 0xFFC0, 0x2C); 1572300016Sadrian BWN_RF_WRITE(mac, B2055_CAL_MISC, 0x3C); 1573300016Sadrian BWN_RF_MASK(mac, B2055_CAL_MISC, 0xFFBE); 1574300016Sadrian BWN_RF_SET(mac, B2055_CAL_LPOCTL, 0x80); 1575300016Sadrian BWN_RF_SET(mac, B2055_CAL_MISC, 0x1); 1576300016Sadrian DELAY(1000); 1577300016Sadrian BWN_RF_SET(mac, B2055_CAL_MISC, 0x40); 1578300016Sadrian if (!bwn_radio_wait_value(mac, B2055_CAL_COUT2, 0x80, 0x80, 10, 2000)) 1579300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "radio post init timeout\n"); 1580300016Sadrian BWN_RF_MASK(mac, B2055_CAL_LPOCTL, 0xFF7F); 1581300016Sadrian bwn_switch_channel(mac, bwn_get_chan(mac)); 1582300016Sadrian BWN_RF_WRITE(mac, B2055_C1_RX_BB_LPF, 0x9); 1583300016Sadrian BWN_RF_WRITE(mac, B2055_C2_RX_BB_LPF, 0x9); 1584300016Sadrian BWN_RF_WRITE(mac, B2055_C1_RX_BB_MIDACHP, 0x83); 1585300016Sadrian BWN_RF_WRITE(mac, B2055_C2_RX_BB_MIDACHP, 0x83); 1586300016Sadrian BWN_RF_SETMASK(mac, B2055_C1_LNA_GAINBST, 0xFFF8, 0x6); 1587300016Sadrian BWN_RF_SETMASK(mac, B2055_C2_LNA_GAINBST, 0xFFF8, 0x6); 1588300016Sadrian if (!nphy->gain_boost) { 1589300016Sadrian BWN_RF_SET(mac, B2055_C1_RX_RFSPC1, 0x2); 1590300016Sadrian BWN_RF_SET(mac, B2055_C2_RX_RFSPC1, 0x2); 1591300016Sadrian } else { 1592300016Sadrian BWN_RF_MASK(mac, B2055_C1_RX_RFSPC1, 0xFFFD); 1593300016Sadrian BWN_RF_MASK(mac, B2055_C2_RX_RFSPC1, 0xFFFD); 1594300016Sadrian } 1595300016Sadrian DELAY(2); 1596300016Sadrian} 1597300016Sadrian 1598300016Sadrian/* 1599300016Sadrian * Initialize a Broadcom 2055 N-radio 1600300016Sadrian * http://bcm-v4.sipsolutions.net/802.11/Radio/2055/Init 1601300016Sadrian */ 1602300016Sadrianstatic void bwn_radio_init2055(struct bwn_mac *mac) 1603300016Sadrian{ 1604300016Sadrian bwn_radio_init2055_pre(mac); 1605300016Sadrian if (mac->mac_status < BWN_MAC_STATUS_INITED) { 1606300016Sadrian /* Follow wl, not specs. Do not force uploading all regs */ 1607300016Sadrian b2055_upload_inittab(mac, 0, 0); 1608300016Sadrian } else { 1609300016Sadrian bool ghz5 = bwn_current_band(mac) == BWN_BAND_5G; 1610300016Sadrian b2055_upload_inittab(mac, ghz5, 0); 1611300016Sadrian } 1612300016Sadrian bwn_radio_init2055_post(mac); 1613300016Sadrian} 1614300016Sadrian 1615300016Sadrian/************************************************** 1616300016Sadrian * Samples 1617300016Sadrian **************************************************/ 1618300016Sadrian 1619300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/LoadSampleTable */ 1620300016Sadrianstatic int bwn_nphy_load_samples(struct bwn_mac *mac, 1621300016Sadrian struct bwn_c32 *samples, uint16_t len) { 1622300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 1623300016Sadrian uint16_t i; 1624300016Sadrian uint32_t *data; 1625300016Sadrian 1626300016Sadrian data = malloc(len * sizeof(uint32_t), M_DEVBUF, M_NOWAIT | M_ZERO); 1627300016Sadrian if (!data) { 1628300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "allocation for samples loading failed\n"); 1629300016Sadrian return -ENOMEM; 1630300016Sadrian } 1631300016Sadrian if (nphy->hang_avoid) 1632300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 1); 1633300016Sadrian 1634300016Sadrian for (i = 0; i < len; i++) { 1635300016Sadrian data[i] = (samples[i].i & 0x3FF << 10); 1636300016Sadrian data[i] |= samples[i].q & 0x3FF; 1637300016Sadrian } 1638300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB32(17, 0), len, data); 1639300016Sadrian 1640300016Sadrian free(data, M_DEVBUF); 1641300016Sadrian if (nphy->hang_avoid) 1642300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 0); 1643300016Sadrian return 0; 1644300016Sadrian} 1645300016Sadrian 1646300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GenLoadSamples */ 1647300016Sadrianstatic uint16_t bwn_nphy_gen_load_samples(struct bwn_mac *mac, uint32_t freq, uint16_t max, 1648300016Sadrian bool test) 1649300016Sadrian{ 1650300016Sadrian int i; 1651300016Sadrian uint16_t bw, len, rot, angle; 1652300016Sadrian struct bwn_c32 *samples; 1653300016Sadrian 1654300016Sadrian bw = bwn_is_40mhz(mac) ? 40 : 20; 1655300016Sadrian len = bw << 3; 1656300016Sadrian 1657300016Sadrian if (test) { 1658300016Sadrian if (BWN_PHY_READ(mac, BWN_NPHY_BBCFG) & BWN_NPHY_BBCFG_RSTRX) 1659300016Sadrian bw = 82; 1660300016Sadrian else 1661300016Sadrian bw = 80; 1662300016Sadrian 1663300016Sadrian if (bwn_is_40mhz(mac)) 1664300016Sadrian bw <<= 1; 1665300016Sadrian 1666300016Sadrian len = bw << 1; 1667300016Sadrian } 1668300016Sadrian 1669300016Sadrian samples = malloc(len * sizeof(struct bwn_c32), M_DEVBUF, M_NOWAIT | M_ZERO); 1670300016Sadrian if (!samples) { 1671300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "allocation for samples generation failed\n"); 1672300016Sadrian return 0; 1673300016Sadrian } 1674300016Sadrian rot = (((freq * 36) / bw) << 16) / 100; 1675300016Sadrian angle = 0; 1676300016Sadrian 1677300016Sadrian for (i = 0; i < len; i++) { 1678300016Sadrian samples[i] = bwn_cordic(angle); 1679300016Sadrian angle += rot; 1680300016Sadrian samples[i].q = CORDIC_CONVERT(samples[i].q * max); 1681300016Sadrian samples[i].i = CORDIC_CONVERT(samples[i].i * max); 1682300016Sadrian } 1683300016Sadrian 1684300016Sadrian i = bwn_nphy_load_samples(mac, samples, len); 1685300016Sadrian free(samples, M_DEVBUF); 1686300016Sadrian return (i < 0) ? 0 : len; 1687300016Sadrian} 1688300016Sadrian 1689300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */ 1690300016Sadrianstatic void bwn_nphy_run_samples(struct bwn_mac *mac, uint16_t samps, uint16_t loops, 1691300016Sadrian uint16_t wait, bool iqmode, bool dac_test, 1692300016Sadrian bool modify_bbmult) 1693300016Sadrian{ 1694300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 1695300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 1696300016Sadrian int i; 1697300016Sadrian uint16_t seq_mode; 1698300016Sadrian uint32_t tmp; 1699300016Sadrian 1700300016Sadrian bwn_nphy_stay_in_carrier_search(mac, true); 1701300016Sadrian 1702300016Sadrian if (phy->rev >= 7) { 1703300016Sadrian bool lpf_bw3, lpf_bw4; 1704300016Sadrian 1705300016Sadrian lpf_bw3 = BWN_PHY_READ(mac, BWN_NPHY_REV7_RF_CTL_OVER3) & 0x80; 1706300016Sadrian lpf_bw4 = BWN_PHY_READ(mac, BWN_NPHY_REV7_RF_CTL_OVER4) & 0x80; 1707300016Sadrian 1708300016Sadrian if (lpf_bw3 || lpf_bw4) { 1709300016Sadrian /* TODO */ 1710300016Sadrian } else { 1711300016Sadrian uint16_t value = bwn_nphy_read_lpf_ctl(mac, 0); 1712300016Sadrian if (phy->rev >= 19) 1713300016Sadrian bwn_nphy_rf_ctl_override_rev19(mac, 0x80, value, 1714300016Sadrian 0, false, 1); 1715300016Sadrian else 1716300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x80, value, 1717300016Sadrian 0, false, 1); 1718300016Sadrian nphy->lpf_bw_overrode_for_sample_play = true; 1719300016Sadrian } 1720300016Sadrian } 1721300016Sadrian 1722300016Sadrian if ((nphy->bb_mult_save & 0x80000000) == 0) { 1723300016Sadrian tmp = bwn_ntab_read(mac, BWN_NTAB16(15, 87)); 1724300016Sadrian nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000; 1725300016Sadrian } 1726300016Sadrian 1727300016Sadrian if (modify_bbmult) { 1728300016Sadrian tmp = !bwn_is_40mhz(mac) ? 0x6464 : 0x4747; 1729300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(15, 87), tmp); 1730300016Sadrian } 1731300016Sadrian 1732300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_SAMP_DEPCNT, (samps - 1)); 1733300016Sadrian 1734300016Sadrian if (loops != 0xFFFF) 1735300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_SAMP_LOOPCNT, (loops - 1)); 1736300016Sadrian else 1737300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_SAMP_LOOPCNT, loops); 1738300016Sadrian 1739300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_SAMP_WAITCNT, wait); 1740300016Sadrian 1741300016Sadrian seq_mode = BWN_PHY_READ(mac, BWN_NPHY_RFSEQMODE); 1742300016Sadrian 1743300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFSEQMODE, BWN_NPHY_RFSEQMODE_CAOVER); 1744300016Sadrian if (iqmode) { 1745300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0x7FFF); 1746300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0x8000); 1747300016Sadrian } else { 1748300016Sadrian tmp = dac_test ? 5 : 1; 1749300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_SAMP_CMD, tmp); 1750300016Sadrian } 1751300016Sadrian for (i = 0; i < 100; i++) { 1752300016Sadrian if (!(BWN_PHY_READ(mac, BWN_NPHY_RFSEQST) & 1)) { 1753300016Sadrian i = 0; 1754300016Sadrian break; 1755300016Sadrian } 1756300016Sadrian DELAY(10); 1757300016Sadrian } 1758300016Sadrian if (i) 1759300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "run samples timeout\n"); 1760300016Sadrian 1761300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFSEQMODE, seq_mode); 1762300016Sadrian 1763300016Sadrian bwn_nphy_stay_in_carrier_search(mac, false); 1764300016Sadrian} 1765300016Sadrian 1766300016Sadrian/************************************************** 1767300016Sadrian * RSSI 1768300016Sadrian **************************************************/ 1769300016Sadrian 1770300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */ 1771300016Sadrianstatic void bwn_nphy_scale_offset_rssi(struct bwn_mac *mac, uint16_t scale, 1772300016Sadrian int8_t offset, uint8_t core, 1773300016Sadrian enum n_rail_type rail, 1774300016Sadrian enum n_rssi_type rssi_type) 1775300016Sadrian{ 1776300016Sadrian uint16_t tmp; 1777300016Sadrian bool core1or5 = (core == 1) || (core == 5); 1778300016Sadrian bool core2or5 = (core == 2) || (core == 5); 1779300016Sadrian 1780300016Sadrian offset = bwn_clamp_val(offset, -32, 31); 1781300016Sadrian tmp = ((scale & 0x3F) << 8) | (offset & 0x3F); 1782300016Sadrian 1783300016Sadrian switch (rssi_type) { 1784300016Sadrian case N_RSSI_NB: 1785300016Sadrian if (core1or5 && rail == N_RAIL_I) 1786300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_Z, tmp); 1787300016Sadrian if (core1or5 && rail == N_RAIL_Q) 1788300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Z, tmp); 1789300016Sadrian if (core2or5 && rail == N_RAIL_I) 1790300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_Z, tmp); 1791300016Sadrian if (core2or5 && rail == N_RAIL_Q) 1792300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Z, tmp); 1793300016Sadrian break; 1794300016Sadrian case N_RSSI_W1: 1795300016Sadrian if (core1or5 && rail == N_RAIL_I) 1796300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_X, tmp); 1797300016Sadrian if (core1or5 && rail == N_RAIL_Q) 1798300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_X, tmp); 1799300016Sadrian if (core2or5 && rail == N_RAIL_I) 1800300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_X, tmp); 1801300016Sadrian if (core2or5 && rail == N_RAIL_Q) 1802300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_X, tmp); 1803300016Sadrian break; 1804300016Sadrian case N_RSSI_W2: 1805300016Sadrian if (core1or5 && rail == N_RAIL_I) 1806300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_Y, tmp); 1807300016Sadrian if (core1or5 && rail == N_RAIL_Q) 1808300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Y, tmp); 1809300016Sadrian if (core2or5 && rail == N_RAIL_I) 1810300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_Y, tmp); 1811300016Sadrian if (core2or5 && rail == N_RAIL_Q) 1812300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Y, tmp); 1813300016Sadrian break; 1814300016Sadrian case N_RSSI_TBD: 1815300016Sadrian if (core1or5 && rail == N_RAIL_I) 1816300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_TBD, tmp); 1817300016Sadrian if (core1or5 && rail == N_RAIL_Q) 1818300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_TBD, tmp); 1819300016Sadrian if (core2or5 && rail == N_RAIL_I) 1820300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_TBD, tmp); 1821300016Sadrian if (core2or5 && rail == N_RAIL_Q) 1822300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_TBD, tmp); 1823300016Sadrian break; 1824300016Sadrian case N_RSSI_IQ: 1825300016Sadrian if (core1or5 && rail == N_RAIL_I) 1826300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_PWRDET, tmp); 1827300016Sadrian if (core1or5 && rail == N_RAIL_Q) 1828300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_PWRDET, tmp); 1829300016Sadrian if (core2or5 && rail == N_RAIL_I) 1830300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_PWRDET, tmp); 1831300016Sadrian if (core2or5 && rail == N_RAIL_Q) 1832300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_PWRDET, tmp); 1833300016Sadrian break; 1834300016Sadrian case N_RSSI_TSSI_2G: 1835300016Sadrian if (core1or5) 1836300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_TSSI, tmp); 1837300016Sadrian if (core2or5) 1838300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_TSSI, tmp); 1839300016Sadrian break; 1840300016Sadrian case N_RSSI_TSSI_5G: 1841300016Sadrian if (core1or5) 1842300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_TSSI, tmp); 1843300016Sadrian if (core2or5) 1844300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_TSSI, tmp); 1845300016Sadrian break; 1846300016Sadrian } 1847300016Sadrian} 1848300016Sadrian 1849300016Sadrianstatic void bwn_nphy_rssi_select_rev19(struct bwn_mac *mac, uint8_t code, 1850300016Sadrian enum n_rssi_type rssi_type) 1851300016Sadrian{ 1852300016Sadrian /* TODO */ 1853300016Sadrian} 1854300016Sadrian 1855300016Sadrianstatic void bwn_nphy_rev3_rssi_select(struct bwn_mac *mac, uint8_t code, 1856300016Sadrian enum n_rssi_type rssi_type) 1857300016Sadrian{ 1858300016Sadrian uint8_t i; 1859300016Sadrian uint16_t reg, val; 1860300016Sadrian 1861300016Sadrian if (code == 0) { 1862300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER1, 0xFDFF); 1863300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER, 0xFDFF); 1864300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C1, 0xFCFF); 1865300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C2, 0xFCFF); 1866300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_TXF_40CO_B1S0, 0xFFDF); 1867300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_TXF_40CO_B32S1, 0xFFDF); 1868300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP1, 0xFFC3); 1869300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP2, 0xFFC3); 1870300016Sadrian } else { 1871300016Sadrian for (i = 0; i < 2; i++) { 1872300016Sadrian if ((code == 1 && i == 1) || (code == 2 && !i)) 1873300016Sadrian continue; 1874300016Sadrian 1875300016Sadrian reg = (i == 0) ? 1876300016Sadrian BWN_NPHY_AFECTL_OVER1 : BWN_NPHY_AFECTL_OVER; 1877300016Sadrian BWN_PHY_SETMASK(mac, reg, 0xFDFF, 0x0200); 1878300016Sadrian 1879300016Sadrian if (rssi_type == N_RSSI_W1 || 1880300016Sadrian rssi_type == N_RSSI_W2 || 1881300016Sadrian rssi_type == N_RSSI_NB) { 1882300016Sadrian reg = (i == 0) ? 1883300016Sadrian BWN_NPHY_AFECTL_C1 : 1884300016Sadrian BWN_NPHY_AFECTL_C2; 1885300016Sadrian BWN_PHY_SETMASK(mac, reg, 0xFCFF, 0); 1886300016Sadrian 1887300016Sadrian reg = (i == 0) ? 1888300016Sadrian BWN_NPHY_RFCTL_LUT_TRSW_UP1 : 1889300016Sadrian BWN_NPHY_RFCTL_LUT_TRSW_UP2; 1890300016Sadrian BWN_PHY_SETMASK(mac, reg, 0xFFC3, 0); 1891300016Sadrian 1892300016Sadrian if (rssi_type == N_RSSI_W1) 1893300016Sadrian val = (bwn_current_band(mac) == BWN_BAND_5G) ? 4 : 8; 1894300016Sadrian else if (rssi_type == N_RSSI_W2) 1895300016Sadrian val = 16; 1896300016Sadrian else 1897300016Sadrian val = 32; 1898300016Sadrian BWN_PHY_SET(mac, reg, val); 1899300016Sadrian 1900300016Sadrian reg = (i == 0) ? 1901300016Sadrian BWN_NPHY_TXF_40CO_B1S0 : 1902300016Sadrian BWN_NPHY_TXF_40CO_B32S1; 1903300016Sadrian BWN_PHY_SET(mac, reg, 0x0020); 1904300016Sadrian } else { 1905300016Sadrian if (rssi_type == N_RSSI_TBD) 1906300016Sadrian val = 0x0100; 1907300016Sadrian else if (rssi_type == N_RSSI_IQ) 1908300016Sadrian val = 0x0200; 1909300016Sadrian else 1910300016Sadrian val = 0x0300; 1911300016Sadrian 1912300016Sadrian reg = (i == 0) ? 1913300016Sadrian BWN_NPHY_AFECTL_C1 : 1914300016Sadrian BWN_NPHY_AFECTL_C2; 1915300016Sadrian 1916300016Sadrian BWN_PHY_SETMASK(mac, reg, 0xFCFF, val); 1917300016Sadrian BWN_PHY_SETMASK(mac, reg, 0xF3FF, val << 2); 1918300016Sadrian 1919300016Sadrian if (rssi_type != N_RSSI_IQ && 1920300016Sadrian rssi_type != N_RSSI_TBD) { 1921300016Sadrian bwn_band_t band = 1922300016Sadrian bwn_current_band(mac); 1923300016Sadrian 1924300016Sadrian if (mac->mac_phy.rev < 7) { 1925300016Sadrian if (bwn_nphy_ipa(mac)) 1926300016Sadrian val = (band == BWN_BAND_5G) ? 0xC : 0xE; 1927300016Sadrian else 1928300016Sadrian val = 0x11; 1929300016Sadrian reg = (i == 0) ? B2056_TX0 : B2056_TX1; 1930300016Sadrian reg |= B2056_TX_TX_SSI_MUX; 1931300016Sadrian BWN_RF_WRITE(mac, reg, val); 1932300016Sadrian } 1933300016Sadrian 1934300016Sadrian reg = (i == 0) ? 1935300016Sadrian BWN_NPHY_AFECTL_OVER1 : 1936300016Sadrian BWN_NPHY_AFECTL_OVER; 1937300016Sadrian BWN_PHY_SET(mac, reg, 0x0200); 1938300016Sadrian } 1939300016Sadrian } 1940300016Sadrian } 1941300016Sadrian } 1942300016Sadrian} 1943300016Sadrian 1944300016Sadrianstatic void bwn_nphy_rev2_rssi_select(struct bwn_mac *mac, uint8_t code, 1945300016Sadrian enum n_rssi_type rssi_type) 1946300016Sadrian{ 1947300016Sadrian uint16_t val; 1948300016Sadrian bool rssi_w1_w2_nb = false; 1949300016Sadrian 1950300016Sadrian switch (rssi_type) { 1951300016Sadrian case N_RSSI_W1: 1952300016Sadrian case N_RSSI_W2: 1953300016Sadrian case N_RSSI_NB: 1954300016Sadrian val = 0; 1955300016Sadrian rssi_w1_w2_nb = true; 1956300016Sadrian break; 1957300016Sadrian case N_RSSI_TBD: 1958300016Sadrian val = 1; 1959300016Sadrian break; 1960300016Sadrian case N_RSSI_IQ: 1961300016Sadrian val = 2; 1962300016Sadrian break; 1963300016Sadrian default: 1964300016Sadrian val = 3; 1965300016Sadrian } 1966300016Sadrian 1967300016Sadrian val = (val << 12) | (val << 14); 1968300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C1, 0x0FFF, val); 1969300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C2, 0x0FFF, val); 1970300016Sadrian 1971300016Sadrian if (rssi_w1_w2_nb) { 1972300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFCTL_RSSIO1, 0xFFCF, 1973300016Sadrian (rssi_type + 1) << 4); 1974300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFCTL_RSSIO2, 0xFFCF, 1975300016Sadrian (rssi_type + 1) << 4); 1976300016Sadrian } 1977300016Sadrian 1978300016Sadrian if (code == 0) { 1979300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER, ~0x3000); 1980300016Sadrian if (rssi_w1_w2_nb) { 1981300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, 1982300016Sadrian ~(BWN_NPHY_RFCTL_CMD_RXEN | 1983300016Sadrian BWN_NPHY_RFCTL_CMD_CORESEL)); 1984300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER, 1985300016Sadrian ~(0x1 << 12 | 1986300016Sadrian 0x1 << 5 | 1987300016Sadrian 0x1 << 1 | 1988300016Sadrian 0x1)); 1989300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, 1990300016Sadrian ~BWN_NPHY_RFCTL_CMD_START); 1991300016Sadrian DELAY(20); 1992300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER, ~0x1); 1993300016Sadrian } 1994300016Sadrian } else { 1995300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x3000); 1996300016Sadrian if (rssi_w1_w2_nb) { 1997300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFCTL_CMD, 1998300016Sadrian ~(BWN_NPHY_RFCTL_CMD_RXEN | 1999300016Sadrian BWN_NPHY_RFCTL_CMD_CORESEL), 2000300016Sadrian (BWN_NPHY_RFCTL_CMD_RXEN | 2001300016Sadrian code << BWN_NPHY_RFCTL_CMD_CORESEL_SHIFT)); 2002300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_OVER, 2003300016Sadrian (0x1 << 12 | 2004300016Sadrian 0x1 << 5 | 2005300016Sadrian 0x1 << 1 | 2006300016Sadrian 0x1)); 2007300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, 2008300016Sadrian BWN_NPHY_RFCTL_CMD_START); 2009300016Sadrian DELAY(20); 2010300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER, ~0x1); 2011300016Sadrian } 2012300016Sadrian } 2013300016Sadrian} 2014300016Sadrian 2015300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */ 2016300016Sadrianstatic void bwn_nphy_rssi_select(struct bwn_mac *mac, uint8_t code, 2017300016Sadrian enum n_rssi_type type) 2018300016Sadrian{ 2019300016Sadrian if (mac->mac_phy.rev >= 19) 2020300016Sadrian bwn_nphy_rssi_select_rev19(mac, code, type); 2021300016Sadrian else if (mac->mac_phy.rev >= 3) 2022300016Sadrian bwn_nphy_rev3_rssi_select(mac, code, type); 2023300016Sadrian else 2024300016Sadrian bwn_nphy_rev2_rssi_select(mac, code, type); 2025300016Sadrian} 2026300016Sadrian 2027300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */ 2028300016Sadrianstatic void bwn_nphy_set_rssi_2055_vcm(struct bwn_mac *mac, 2029300016Sadrian enum n_rssi_type rssi_type, uint8_t *buf) 2030300016Sadrian{ 2031300016Sadrian int i; 2032300016Sadrian for (i = 0; i < 2; i++) { 2033300016Sadrian if (rssi_type == N_RSSI_NB) { 2034300016Sadrian if (i == 0) { 2035300016Sadrian BWN_RF_SETMASK(mac, B2055_C1_B0NB_RSSIVCM, 2036300016Sadrian 0xFC, buf[0]); 2037300016Sadrian BWN_RF_SETMASK(mac, B2055_C1_RX_BB_RSSICTL5, 2038300016Sadrian 0xFC, buf[1]); 2039300016Sadrian } else { 2040300016Sadrian BWN_RF_SETMASK(mac, B2055_C2_B0NB_RSSIVCM, 2041300016Sadrian 0xFC, buf[2 * i]); 2042300016Sadrian BWN_RF_SETMASK(mac, B2055_C2_RX_BB_RSSICTL5, 2043300016Sadrian 0xFC, buf[2 * i + 1]); 2044300016Sadrian } 2045300016Sadrian } else { 2046300016Sadrian if (i == 0) 2047300016Sadrian BWN_RF_SETMASK(mac, B2055_C1_RX_BB_RSSICTL5, 2048300016Sadrian 0xF3, buf[0] << 2); 2049300016Sadrian else 2050300016Sadrian BWN_RF_SETMASK(mac, B2055_C2_RX_BB_RSSICTL5, 2051300016Sadrian 0xF3, buf[2 * i + 1] << 2); 2052300016Sadrian } 2053300016Sadrian } 2054300016Sadrian} 2055300016Sadrian 2056300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */ 2057300016Sadrianstatic int bwn_nphy_poll_rssi(struct bwn_mac *mac, enum n_rssi_type rssi_type, 2058300016Sadrian int32_t *buf, uint8_t nsamp) 2059300016Sadrian{ 2060300016Sadrian int i; 2061300016Sadrian int out; 2062300016Sadrian uint16_t save_regs_phy[9]; 2063300016Sadrian uint16_t s[2]; 2064300016Sadrian 2065300016Sadrian /* TODO: rev7+ is treated like rev3+, what about rev19+? */ 2066300016Sadrian 2067300016Sadrian if (mac->mac_phy.rev >= 3) { 2068300016Sadrian save_regs_phy[0] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C1); 2069300016Sadrian save_regs_phy[1] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C2); 2070300016Sadrian save_regs_phy[2] = BWN_PHY_READ(mac, 2071300016Sadrian BWN_NPHY_RFCTL_LUT_TRSW_UP1); 2072300016Sadrian save_regs_phy[3] = BWN_PHY_READ(mac, 2073300016Sadrian BWN_NPHY_RFCTL_LUT_TRSW_UP2); 2074300016Sadrian save_regs_phy[4] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER1); 2075300016Sadrian save_regs_phy[5] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER); 2076300016Sadrian save_regs_phy[6] = BWN_PHY_READ(mac, BWN_NPHY_TXF_40CO_B1S0); 2077300016Sadrian save_regs_phy[7] = BWN_PHY_READ(mac, BWN_NPHY_TXF_40CO_B32S1); 2078300016Sadrian save_regs_phy[8] = 0; 2079300016Sadrian } else { 2080300016Sadrian save_regs_phy[0] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C1); 2081300016Sadrian save_regs_phy[1] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C2); 2082300016Sadrian save_regs_phy[2] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER); 2083300016Sadrian save_regs_phy[3] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_CMD); 2084300016Sadrian save_regs_phy[4] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_OVER); 2085300016Sadrian save_regs_phy[5] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_RSSIO1); 2086300016Sadrian save_regs_phy[6] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_RSSIO2); 2087300016Sadrian save_regs_phy[7] = 0; 2088300016Sadrian save_regs_phy[8] = 0; 2089300016Sadrian } 2090300016Sadrian 2091300016Sadrian bwn_nphy_rssi_select(mac, 5, rssi_type); 2092300016Sadrian 2093300016Sadrian if (mac->mac_phy.rev < 2) { 2094300016Sadrian save_regs_phy[8] = BWN_PHY_READ(mac, BWN_NPHY_GPIO_SEL); 2095300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_GPIO_SEL, 5); 2096300016Sadrian } 2097300016Sadrian 2098300016Sadrian for (i = 0; i < 4; i++) 2099300016Sadrian buf[i] = 0; 2100300016Sadrian 2101300016Sadrian for (i = 0; i < nsamp; i++) { 2102300016Sadrian if (mac->mac_phy.rev < 2) { 2103300016Sadrian s[0] = BWN_PHY_READ(mac, BWN_NPHY_GPIO_LOOUT); 2104300016Sadrian s[1] = BWN_PHY_READ(mac, BWN_NPHY_GPIO_HIOUT); 2105300016Sadrian } else { 2106300016Sadrian s[0] = BWN_PHY_READ(mac, BWN_NPHY_RSSI1); 2107300016Sadrian s[1] = BWN_PHY_READ(mac, BWN_NPHY_RSSI2); 2108300016Sadrian } 2109300016Sadrian 2110300016Sadrian buf[0] += ((int8_t)((s[0] & 0x3F) << 2)) >> 2; 2111300016Sadrian buf[1] += ((int8_t)(((s[0] >> 8) & 0x3F) << 2)) >> 2; 2112300016Sadrian buf[2] += ((int8_t)((s[1] & 0x3F) << 2)) >> 2; 2113300016Sadrian buf[3] += ((int8_t)(((s[1] >> 8) & 0x3F) << 2)) >> 2; 2114300016Sadrian } 2115300016Sadrian out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 | 2116300016Sadrian (buf[2] & 0xFF) << 8 | (buf[3] & 0xFF); 2117300016Sadrian 2118300016Sadrian if (mac->mac_phy.rev < 2) 2119300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_GPIO_SEL, save_regs_phy[8]); 2120300016Sadrian 2121300016Sadrian if (mac->mac_phy.rev >= 3) { 2122300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, save_regs_phy[0]); 2123300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, save_regs_phy[1]); 2124300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP1, 2125300016Sadrian save_regs_phy[2]); 2126300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP2, 2127300016Sadrian save_regs_phy[3]); 2128300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, save_regs_phy[4]); 2129300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, save_regs_phy[5]); 2130300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B1S0, save_regs_phy[6]); 2131300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B32S1, save_regs_phy[7]); 2132300016Sadrian } else { 2133300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, save_regs_phy[0]); 2134300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, save_regs_phy[1]); 2135300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, save_regs_phy[2]); 2136300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_CMD, save_regs_phy[3]); 2137300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_OVER, save_regs_phy[4]); 2138300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_RSSIO1, save_regs_phy[5]); 2139300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_RSSIO2, save_regs_phy[6]); 2140300016Sadrian } 2141300016Sadrian 2142300016Sadrian return out; 2143300016Sadrian} 2144300016Sadrian 2145300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */ 2146300016Sadrianstatic void bwn_nphy_rev3_rssi_cal(struct bwn_mac *mac) 2147300016Sadrian{ 2148300016Sadrian //struct bwn_phy *phy = &mac->mac_phy; 2149300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 2150300016Sadrian 2151300016Sadrian uint16_t saved_regs_phy_rfctl[2]; 2152300016Sadrian uint16_t saved_regs_phy[22]; 2153300016Sadrian uint16_t regs_to_store_rev3[] = { 2154300016Sadrian BWN_NPHY_AFECTL_OVER1, BWN_NPHY_AFECTL_OVER, 2155300016Sadrian BWN_NPHY_AFECTL_C1, BWN_NPHY_AFECTL_C2, 2156300016Sadrian BWN_NPHY_TXF_40CO_B1S1, BWN_NPHY_RFCTL_OVER, 2157300016Sadrian BWN_NPHY_TXF_40CO_B1S0, BWN_NPHY_TXF_40CO_B32S1, 2158300016Sadrian BWN_NPHY_RFCTL_CMD, 2159300016Sadrian BWN_NPHY_RFCTL_LUT_TRSW_UP1, BWN_NPHY_RFCTL_LUT_TRSW_UP2, 2160300016Sadrian BWN_NPHY_RFCTL_RSSIO1, BWN_NPHY_RFCTL_RSSIO2 2161300016Sadrian }; 2162300016Sadrian uint16_t regs_to_store_rev7[] = { 2163300016Sadrian BWN_NPHY_AFECTL_OVER1, BWN_NPHY_AFECTL_OVER, 2164300016Sadrian BWN_NPHY_AFECTL_C1, BWN_NPHY_AFECTL_C2, 2165300016Sadrian BWN_NPHY_TXF_40CO_B1S1, BWN_NPHY_RFCTL_OVER, 2166300016Sadrian BWN_NPHY_REV7_RF_CTL_OVER3, BWN_NPHY_REV7_RF_CTL_OVER4, 2167300016Sadrian BWN_NPHY_REV7_RF_CTL_OVER5, BWN_NPHY_REV7_RF_CTL_OVER6, 2168300016Sadrian 0x2ff, 2169300016Sadrian BWN_NPHY_TXF_40CO_B1S0, BWN_NPHY_TXF_40CO_B32S1, 2170300016Sadrian BWN_NPHY_RFCTL_CMD, 2171300016Sadrian BWN_NPHY_RFCTL_LUT_TRSW_UP1, BWN_NPHY_RFCTL_LUT_TRSW_UP2, 2172300016Sadrian BWN_NPHY_REV7_RF_CTL_MISC_REG3, BWN_NPHY_REV7_RF_CTL_MISC_REG4, 2173300016Sadrian BWN_NPHY_REV7_RF_CTL_MISC_REG5, BWN_NPHY_REV7_RF_CTL_MISC_REG6, 2174300016Sadrian BWN_NPHY_RFCTL_RSSIO1, BWN_NPHY_RFCTL_RSSIO2 2175300016Sadrian }; 2176300016Sadrian uint16_t *regs_to_store; 2177300016Sadrian int regs_amount; 2178300016Sadrian 2179300016Sadrian uint16_t class; 2180300016Sadrian 2181300016Sadrian uint16_t clip_state[2]; 2182300016Sadrian uint16_t clip_off[2] = { 0xFFFF, 0xFFFF }; 2183300016Sadrian 2184300016Sadrian uint8_t vcm_final = 0; 2185300016Sadrian int32_t offset[4]; 2186300016Sadrian int32_t results[8][4] = { }; 2187300016Sadrian int32_t results_min[4] = { }; 2188300016Sadrian int32_t poll_results[4] = { }; 2189300016Sadrian 2190300016Sadrian uint16_t *rssical_radio_regs = NULL; 2191300016Sadrian uint16_t *rssical_phy_regs = NULL; 2192300016Sadrian 2193300016Sadrian uint16_t r; /* routing */ 2194300016Sadrian uint8_t rx_core_state; 2195300016Sadrian int core, i, j, vcm; 2196300016Sadrian 2197300016Sadrian if (mac->mac_phy.rev >= 7) { 2198300016Sadrian regs_to_store = regs_to_store_rev7; 2199300016Sadrian regs_amount = nitems(regs_to_store_rev7); 2200300016Sadrian } else { 2201300016Sadrian regs_to_store = regs_to_store_rev3; 2202300016Sadrian regs_amount = nitems(regs_to_store_rev3); 2203300016Sadrian } 2204300016Sadrian KASSERT((regs_amount <= nitems(saved_regs_phy)), 2205300016Sadrian ("%s: reg_amount (%d) too large\n", 2206300016Sadrian __func__, 2207300016Sadrian regs_amount)); 2208300016Sadrian 2209300016Sadrian class = bwn_nphy_classifier(mac, 0, 0); 2210300016Sadrian bwn_nphy_classifier(mac, 7, 4); 2211300016Sadrian bwn_nphy_read_clip_detection(mac, clip_state); 2212300016Sadrian bwn_nphy_write_clip_detection(mac, clip_off); 2213300016Sadrian 2214300016Sadrian saved_regs_phy_rfctl[0] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC1); 2215300016Sadrian saved_regs_phy_rfctl[1] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC2); 2216300016Sadrian for (i = 0; i < regs_amount; i++) 2217300016Sadrian saved_regs_phy[i] = BWN_PHY_READ(mac, regs_to_store[i]); 2218300016Sadrian 2219300016Sadrian bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_OFF, 0, 7); 2220300016Sadrian bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_TRSW, 1, 7); 2221300016Sadrian 2222300016Sadrian if (mac->mac_phy.rev >= 7) { 2223300016Sadrian bwn_nphy_rf_ctl_override_one_to_many(mac, 2224300016Sadrian N_RF_CTL_OVER_CMD_RXRF_PU, 2225300016Sadrian 0, 0, false); 2226300016Sadrian bwn_nphy_rf_ctl_override_one_to_many(mac, 2227300016Sadrian N_RF_CTL_OVER_CMD_RX_PU, 2228300016Sadrian 1, 0, false); 2229300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x80, 1, 0, false, 0); 2230300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x40, 1, 0, false, 0); 2231300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G) { 2232300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x20, 0, 0, false, 2233300016Sadrian 0); 2234300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x10, 1, 0, false, 2235300016Sadrian 0); 2236300016Sadrian } else { 2237300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x10, 0, 0, false, 2238300016Sadrian 0); 2239300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x20, 1, 0, false, 2240300016Sadrian 0); 2241300016Sadrian } 2242300016Sadrian } else { 2243300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x1, 0, 0, false); 2244300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x2, 1, 0, false); 2245300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x80, 1, 0, false); 2246300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x40, 1, 0, false); 2247300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G) { 2248300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x20, 0, 0, false); 2249300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x10, 1, 0, false); 2250300016Sadrian } else { 2251300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x10, 0, 0, false); 2252300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x20, 1, 0, false); 2253300016Sadrian } 2254300016Sadrian } 2255300016Sadrian 2256300016Sadrian rx_core_state = bwn_nphy_get_rx_core_state(mac); 2257300016Sadrian for (core = 0; core < 2; core++) { 2258300016Sadrian if (!(rx_core_state & (1 << core))) 2259300016Sadrian continue; 2260300016Sadrian r = core ? B2056_RX1 : B2056_RX0; 2261300016Sadrian bwn_nphy_scale_offset_rssi(mac, 0, 0, core + 1, N_RAIL_I, 2262300016Sadrian N_RSSI_NB); 2263300016Sadrian bwn_nphy_scale_offset_rssi(mac, 0, 0, core + 1, N_RAIL_Q, 2264300016Sadrian N_RSSI_NB); 2265300016Sadrian 2266300016Sadrian /* Grab RSSI results for every possible VCM */ 2267300016Sadrian for (vcm = 0; vcm < 8; vcm++) { 2268300016Sadrian if (mac->mac_phy.rev >= 7) 2269300016Sadrian BWN_RF_SETMASK(mac, 2270300016Sadrian core ? R2057_NB_MASTER_CORE1 : 2271300016Sadrian R2057_NB_MASTER_CORE0, 2272300016Sadrian ~R2057_VCM_MASK, vcm); 2273300016Sadrian else 2274300016Sadrian BWN_RF_SETMASK(mac, r | B2056_RX_RSSI_MISC, 2275300016Sadrian 0xE3, vcm << 2); 2276300016Sadrian bwn_nphy_poll_rssi(mac, N_RSSI_NB, results[vcm], 8); 2277300016Sadrian } 2278300016Sadrian 2279300016Sadrian /* Find out which VCM got the best results */ 2280300016Sadrian for (i = 0; i < 4; i += 2) { 2281300016Sadrian int32_t currd; 2282300016Sadrian int32_t mind = 0x100000; 2283300016Sadrian int32_t minpoll = 249; 2284300016Sadrian uint8_t minvcm = 0; 2285300016Sadrian if (2 * core != i) 2286300016Sadrian continue; 2287300016Sadrian for (vcm = 0; vcm < 8; vcm++) { 2288300016Sadrian currd = results[vcm][i] * results[vcm][i] + 2289300016Sadrian results[vcm][i + 1] * results[vcm][i]; 2290300016Sadrian if (currd < mind) { 2291300016Sadrian mind = currd; 2292300016Sadrian minvcm = vcm; 2293300016Sadrian } 2294300016Sadrian if (results[vcm][i] < minpoll) 2295300016Sadrian minpoll = results[vcm][i]; 2296300016Sadrian } 2297300016Sadrian vcm_final = minvcm; 2298300016Sadrian results_min[i] = minpoll; 2299300016Sadrian } 2300300016Sadrian 2301300016Sadrian /* Select the best VCM */ 2302300016Sadrian if (mac->mac_phy.rev >= 7) 2303300016Sadrian BWN_RF_SETMASK(mac, 2304300016Sadrian core ? R2057_NB_MASTER_CORE1 : 2305300016Sadrian R2057_NB_MASTER_CORE0, 2306300016Sadrian ~R2057_VCM_MASK, vcm); 2307300016Sadrian else 2308300016Sadrian BWN_RF_SETMASK(mac, r | B2056_RX_RSSI_MISC, 2309300016Sadrian 0xE3, vcm_final << 2); 2310300016Sadrian 2311300016Sadrian for (i = 0; i < 4; i++) { 2312300016Sadrian if (core != i / 2) 2313300016Sadrian continue; 2314300016Sadrian offset[i] = -results[vcm_final][i]; 2315300016Sadrian if (offset[i] < 0) 2316300016Sadrian offset[i] = -((abs(offset[i]) + 4) / 8); 2317300016Sadrian else 2318300016Sadrian offset[i] = (offset[i] + 4) / 8; 2319300016Sadrian if (results_min[i] == 248) 2320300016Sadrian offset[i] = -32; 2321300016Sadrian bwn_nphy_scale_offset_rssi(mac, 0, offset[i], 2322300016Sadrian (i / 2 == 0) ? 1 : 2, 2323300016Sadrian (i % 2 == 0) ? N_RAIL_I : N_RAIL_Q, 2324300016Sadrian N_RSSI_NB); 2325300016Sadrian } 2326300016Sadrian } 2327300016Sadrian 2328300016Sadrian for (core = 0; core < 2; core++) { 2329300016Sadrian if (!(rx_core_state & (1 << core))) 2330300016Sadrian continue; 2331300016Sadrian for (i = 0; i < 2; i++) { 2332300016Sadrian bwn_nphy_scale_offset_rssi(mac, 0, 0, core + 1, 2333300016Sadrian N_RAIL_I, i); 2334300016Sadrian bwn_nphy_scale_offset_rssi(mac, 0, 0, core + 1, 2335300016Sadrian N_RAIL_Q, i); 2336300016Sadrian bwn_nphy_poll_rssi(mac, i, poll_results, 8); 2337300016Sadrian for (j = 0; j < 4; j++) { 2338300016Sadrian if (j / 2 == core) { 2339300016Sadrian offset[j] = 232 - poll_results[j]; 2340300016Sadrian if (offset[j] < 0) 2341300016Sadrian offset[j] = -(abs(offset[j] + 4) / 8); 2342300016Sadrian else 2343300016Sadrian offset[j] = (offset[j] + 4) / 8; 2344300016Sadrian bwn_nphy_scale_offset_rssi(mac, 0, 2345300016Sadrian offset[2 * core], core + 1, j % 2, i); 2346300016Sadrian } 2347300016Sadrian } 2348300016Sadrian } 2349300016Sadrian } 2350300016Sadrian 2351300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, saved_regs_phy_rfctl[0]); 2352300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, saved_regs_phy_rfctl[1]); 2353300016Sadrian 2354300016Sadrian bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX); 2355300016Sadrian 2356300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_TXF_40CO_B1S1, 0x1); 2357300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, BWN_NPHY_RFCTL_CMD_START); 2358300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_TXF_40CO_B1S1, ~0x1); 2359300016Sadrian 2360300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_OVER, 0x1); 2361300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, BWN_NPHY_RFCTL_CMD_RXTX); 2362300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER, ~0x1); 2363300016Sadrian 2364300016Sadrian for (i = 0; i < regs_amount; i++) 2365300016Sadrian BWN_PHY_WRITE(mac, regs_to_store[i], saved_regs_phy[i]); 2366300016Sadrian 2367300016Sadrian /* Store for future configuration */ 2368300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 2369300016Sadrian rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G; 2370300016Sadrian rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G; 2371300016Sadrian } else { 2372300016Sadrian rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G; 2373300016Sadrian rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; 2374300016Sadrian } 2375300016Sadrian if (mac->mac_phy.rev >= 7) { 2376300016Sadrian rssical_radio_regs[0] = BWN_RF_READ(mac, 2377300016Sadrian R2057_NB_MASTER_CORE0); 2378300016Sadrian rssical_radio_regs[1] = BWN_RF_READ(mac, 2379300016Sadrian R2057_NB_MASTER_CORE1); 2380300016Sadrian } else { 2381300016Sadrian rssical_radio_regs[0] = BWN_RF_READ(mac, B2056_RX0 | 2382300016Sadrian B2056_RX_RSSI_MISC); 2383300016Sadrian rssical_radio_regs[1] = BWN_RF_READ(mac, B2056_RX1 | 2384300016Sadrian B2056_RX_RSSI_MISC); 2385300016Sadrian } 2386300016Sadrian rssical_phy_regs[0] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0I_RSSI_Z); 2387300016Sadrian rssical_phy_regs[1] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Z); 2388300016Sadrian rssical_phy_regs[2] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1I_RSSI_Z); 2389300016Sadrian rssical_phy_regs[3] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Z); 2390300016Sadrian rssical_phy_regs[4] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0I_RSSI_X); 2391300016Sadrian rssical_phy_regs[5] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0Q_RSSI_X); 2392300016Sadrian rssical_phy_regs[6] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1I_RSSI_X); 2393300016Sadrian rssical_phy_regs[7] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1Q_RSSI_X); 2394300016Sadrian rssical_phy_regs[8] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0I_RSSI_Y); 2395300016Sadrian rssical_phy_regs[9] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Y); 2396300016Sadrian rssical_phy_regs[10] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1I_RSSI_Y); 2397300016Sadrian rssical_phy_regs[11] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Y); 2398300016Sadrian 2399300016Sadrian /* Remember for which channel we store configuration */ 2400300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 2401300016Sadrian nphy->rssical_chanspec_2G.center_freq = bwn_get_centre_freq(mac); 2402300016Sadrian else 2403300016Sadrian nphy->rssical_chanspec_5G.center_freq = bwn_get_centre_freq(mac); 2404300016Sadrian 2405300016Sadrian /* End of calibration, restore configuration */ 2406300016Sadrian bwn_nphy_classifier(mac, 7, class); 2407300016Sadrian bwn_nphy_write_clip_detection(mac, clip_state); 2408300016Sadrian} 2409300016Sadrian 2410300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */ 2411300016Sadrianstatic void bwn_nphy_rev2_rssi_cal(struct bwn_mac *mac, enum n_rssi_type type) 2412300016Sadrian{ 2413300016Sadrian int i, j, vcm; 2414300016Sadrian uint8_t state[4]; 2415300016Sadrian uint8_t code, val; 2416300016Sadrian uint16_t class, override; 2417300016Sadrian uint8_t regs_save_radio[2]; 2418300016Sadrian uint16_t regs_save_phy[2]; 2419300016Sadrian 2420300016Sadrian int32_t offset[4]; 2421300016Sadrian uint8_t core; 2422300016Sadrian uint8_t rail; 2423300016Sadrian 2424300016Sadrian uint16_t clip_state[2]; 2425300016Sadrian uint16_t clip_off[2] = { 0xFFFF, 0xFFFF }; 2426300016Sadrian int32_t results_min[4] = { }; 2427300016Sadrian uint8_t vcm_final[4] = { }; 2428300016Sadrian int32_t results[4][4] = { }; 2429300016Sadrian int32_t miniq[4][2] = { }; 2430300016Sadrian 2431300016Sadrian if (type == N_RSSI_NB) { 2432300016Sadrian code = 0; 2433300016Sadrian val = 6; 2434300016Sadrian } else if (type == N_RSSI_W1 || type == N_RSSI_W2) { 2435300016Sadrian code = 25; 2436300016Sadrian val = 4; 2437300016Sadrian } else { 2438300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "%s: RSSI type %d invalid\n", 2439300016Sadrian __func__, 2440300016Sadrian type); 2441300016Sadrian return; 2442300016Sadrian } 2443300016Sadrian 2444300016Sadrian class = bwn_nphy_classifier(mac, 0, 0); 2445300016Sadrian bwn_nphy_classifier(mac, 7, 4); 2446300016Sadrian bwn_nphy_read_clip_detection(mac, clip_state); 2447300016Sadrian bwn_nphy_write_clip_detection(mac, clip_off); 2448300016Sadrian 2449300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G) 2450300016Sadrian override = 0x140; 2451300016Sadrian else 2452300016Sadrian override = 0x110; 2453300016Sadrian 2454300016Sadrian regs_save_phy[0] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC1); 2455300016Sadrian regs_save_radio[0] = BWN_RF_READ(mac, B2055_C1_PD_RXTX); 2456300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, override); 2457300016Sadrian BWN_RF_WRITE(mac, B2055_C1_PD_RXTX, val); 2458300016Sadrian 2459300016Sadrian regs_save_phy[1] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC2); 2460300016Sadrian regs_save_radio[1] = BWN_RF_READ(mac, B2055_C2_PD_RXTX); 2461300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, override); 2462300016Sadrian BWN_RF_WRITE(mac, B2055_C2_PD_RXTX, val); 2463300016Sadrian 2464300016Sadrian state[0] = BWN_RF_READ(mac, B2055_C1_PD_RSSIMISC) & 0x07; 2465300016Sadrian state[1] = BWN_RF_READ(mac, B2055_C2_PD_RSSIMISC) & 0x07; 2466300016Sadrian BWN_RF_MASK(mac, B2055_C1_PD_RSSIMISC, 0xF8); 2467300016Sadrian BWN_RF_MASK(mac, B2055_C2_PD_RSSIMISC, 0xF8); 2468300016Sadrian state[2] = BWN_RF_READ(mac, B2055_C1_SP_RSSI) & 0x07; 2469300016Sadrian state[3] = BWN_RF_READ(mac, B2055_C2_SP_RSSI) & 0x07; 2470300016Sadrian 2471300016Sadrian bwn_nphy_rssi_select(mac, 5, type); 2472300016Sadrian bwn_nphy_scale_offset_rssi(mac, 0, 0, 5, N_RAIL_I, type); 2473300016Sadrian bwn_nphy_scale_offset_rssi(mac, 0, 0, 5, N_RAIL_Q, type); 2474300016Sadrian 2475300016Sadrian for (vcm = 0; vcm < 4; vcm++) { 2476300016Sadrian uint8_t tmp[4]; 2477300016Sadrian for (j = 0; j < 4; j++) 2478300016Sadrian tmp[j] = vcm; 2479300016Sadrian if (type != N_RSSI_W2) 2480300016Sadrian bwn_nphy_set_rssi_2055_vcm(mac, type, tmp); 2481300016Sadrian bwn_nphy_poll_rssi(mac, type, results[vcm], 8); 2482300016Sadrian if (type == N_RSSI_W1 || type == N_RSSI_W2) 2483300016Sadrian for (j = 0; j < 2; j++) 2484300016Sadrian miniq[vcm][j] = min(results[vcm][2 * j], 2485300016Sadrian results[vcm][2 * j + 1]); 2486300016Sadrian } 2487300016Sadrian 2488300016Sadrian for (i = 0; i < 4; i++) { 2489300016Sadrian int32_t mind = 0x100000; 2490300016Sadrian uint8_t minvcm = 0; 2491300016Sadrian int32_t minpoll = 249; 2492300016Sadrian int32_t currd; 2493300016Sadrian for (vcm = 0; vcm < 4; vcm++) { 2494300016Sadrian if (type == N_RSSI_NB) 2495300016Sadrian currd = abs(results[vcm][i] - code * 8); 2496300016Sadrian else 2497300016Sadrian currd = abs(miniq[vcm][i / 2] - code * 8); 2498300016Sadrian 2499300016Sadrian if (currd < mind) { 2500300016Sadrian mind = currd; 2501300016Sadrian minvcm = vcm; 2502300016Sadrian } 2503300016Sadrian 2504300016Sadrian if (results[vcm][i] < minpoll) 2505300016Sadrian minpoll = results[vcm][i]; 2506300016Sadrian } 2507300016Sadrian results_min[i] = minpoll; 2508300016Sadrian vcm_final[i] = minvcm; 2509300016Sadrian } 2510300016Sadrian 2511300016Sadrian if (type != N_RSSI_W2) 2512300016Sadrian bwn_nphy_set_rssi_2055_vcm(mac, type, vcm_final); 2513300016Sadrian 2514300016Sadrian for (i = 0; i < 4; i++) { 2515300016Sadrian offset[i] = (code * 8) - results[vcm_final[i]][i]; 2516300016Sadrian 2517300016Sadrian if (offset[i] < 0) 2518300016Sadrian offset[i] = -((abs(offset[i]) + 4) / 8); 2519300016Sadrian else 2520300016Sadrian offset[i] = (offset[i] + 4) / 8; 2521300016Sadrian 2522300016Sadrian if (results_min[i] == 248) 2523300016Sadrian offset[i] = code - 32; 2524300016Sadrian 2525300016Sadrian core = (i / 2) ? 2 : 1; 2526300016Sadrian rail = (i % 2) ? N_RAIL_Q : N_RAIL_I; 2527300016Sadrian 2528300016Sadrian bwn_nphy_scale_offset_rssi(mac, 0, offset[i], core, rail, 2529300016Sadrian type); 2530300016Sadrian } 2531300016Sadrian 2532300016Sadrian BWN_RF_SETMASK(mac, B2055_C1_PD_RSSIMISC, 0xF8, state[0]); 2533300016Sadrian BWN_RF_SETMASK(mac, B2055_C2_PD_RSSIMISC, 0xF8, state[1]); 2534300016Sadrian 2535300016Sadrian switch (state[2]) { 2536300016Sadrian case 1: 2537300016Sadrian bwn_nphy_rssi_select(mac, 1, N_RSSI_NB); 2538300016Sadrian break; 2539300016Sadrian case 4: 2540300016Sadrian bwn_nphy_rssi_select(mac, 1, N_RSSI_W1); 2541300016Sadrian break; 2542300016Sadrian case 2: 2543300016Sadrian bwn_nphy_rssi_select(mac, 1, N_RSSI_W2); 2544300016Sadrian break; 2545300016Sadrian default: 2546300016Sadrian bwn_nphy_rssi_select(mac, 1, N_RSSI_W2); 2547300016Sadrian break; 2548300016Sadrian } 2549300016Sadrian 2550300016Sadrian switch (state[3]) { 2551300016Sadrian case 1: 2552300016Sadrian bwn_nphy_rssi_select(mac, 2, N_RSSI_NB); 2553300016Sadrian break; 2554300016Sadrian case 4: 2555300016Sadrian bwn_nphy_rssi_select(mac, 2, N_RSSI_W1); 2556300016Sadrian break; 2557300016Sadrian default: 2558300016Sadrian bwn_nphy_rssi_select(mac, 2, N_RSSI_W2); 2559300016Sadrian break; 2560300016Sadrian } 2561300016Sadrian 2562300016Sadrian bwn_nphy_rssi_select(mac, 0, type); 2563300016Sadrian 2564300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, regs_save_phy[0]); 2565300016Sadrian BWN_RF_WRITE(mac, B2055_C1_PD_RXTX, regs_save_radio[0]); 2566300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, regs_save_phy[1]); 2567300016Sadrian BWN_RF_WRITE(mac, B2055_C2_PD_RXTX, regs_save_radio[1]); 2568300016Sadrian 2569300016Sadrian bwn_nphy_classifier(mac, 7, class); 2570300016Sadrian bwn_nphy_write_clip_detection(mac, clip_state); 2571300016Sadrian /* Specs don't say about reset here, but it makes wl and b43 dumps 2572300016Sadrian identical, it really seems wl performs this */ 2573300016Sadrian bwn_nphy_reset_cca(mac); 2574300016Sadrian} 2575300016Sadrian 2576300016Sadrian/* 2577300016Sadrian * RSSI Calibration 2578300016Sadrian * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal 2579300016Sadrian */ 2580300016Sadrianstatic void bwn_nphy_rssi_cal(struct bwn_mac *mac) 2581300016Sadrian{ 2582300016Sadrian if (mac->mac_phy.rev >= 19) { 2583300016Sadrian /* TODO */ 2584300016Sadrian } else if (mac->mac_phy.rev >= 3) { 2585300016Sadrian bwn_nphy_rev3_rssi_cal(mac); 2586300016Sadrian } else { 2587300016Sadrian bwn_nphy_rev2_rssi_cal(mac, N_RSSI_NB); 2588300016Sadrian bwn_nphy_rev2_rssi_cal(mac, N_RSSI_W1); 2589300016Sadrian bwn_nphy_rev2_rssi_cal(mac, N_RSSI_W2); 2590300016Sadrian } 2591300016Sadrian} 2592300016Sadrian 2593300016Sadrian/************************************************** 2594300016Sadrian * Workarounds 2595300016Sadrian **************************************************/ 2596300016Sadrian 2597300016Sadrianstatic void bwn_nphy_gain_ctl_workarounds_rev19(struct bwn_mac *mac) 2598300016Sadrian{ 2599300016Sadrian /* TODO */ 2600300016Sadrian} 2601300016Sadrian 2602300016Sadrianstatic void bwn_nphy_gain_ctl_workarounds_rev7(struct bwn_mac *mac) 2603300016Sadrian{ 2604300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 2605300016Sadrian 2606300016Sadrian switch (phy->rev) { 2607300016Sadrian /* TODO */ 2608300016Sadrian } 2609300016Sadrian} 2610300016Sadrian 2611300016Sadrianstatic void bwn_nphy_gain_ctl_workarounds_rev3(struct bwn_mac *mac) 2612300016Sadrian{ 2613300016Sadrian struct bwn_softc *sc = mac->mac_sc; 2614300016Sadrian bool ghz5; 2615300016Sadrian bool ext_lna; 2616300016Sadrian uint16_t rssi_gain; 2617300016Sadrian struct bwn_nphy_gain_ctl_workaround_entry *e; 2618300016Sadrian uint8_t lpf_gain[6] = { 0x00, 0x06, 0x0C, 0x12, 0x12, 0x12 }; 2619300016Sadrian uint8_t lpf_bits[6] = { 0, 1, 2, 3, 3, 3 }; 2620300016Sadrian 2621300016Sadrian /* Prepare values */ 2622300016Sadrian ghz5 = BWN_PHY_READ(mac, BWN_NPHY_BANDCTL) 2623300016Sadrian & BWN_NPHY_BANDCTL_5GHZ; 2624300016Sadrian ext_lna = ghz5 ? siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_EXTLNA_5GHZ : 2625300016Sadrian siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA; 2626300016Sadrian e = bwn_nphy_get_gain_ctl_workaround_ent(mac, ghz5, ext_lna); 2627300016Sadrian if (ghz5 && mac->mac_phy.rev >= 5) 2628300016Sadrian rssi_gain = 0x90; 2629300016Sadrian else 2630300016Sadrian rssi_gain = 0x50; 2631300016Sadrian 2632300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RXCTL, 0x0040); 2633300016Sadrian 2634300016Sadrian /* Set Clip 2 detect */ 2635300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_C1_CGAINI, BWN_NPHY_C1_CGAINI_CL2DETECT); 2636300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_C2_CGAINI, BWN_NPHY_C2_CGAINI_CL2DETECT); 2637300016Sadrian 2638300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_BIASPOLE_LNAG1_IDAC, 2639300016Sadrian 0x17); 2640300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_BIASPOLE_LNAG1_IDAC, 2641300016Sadrian 0x17); 2642300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_LNAG2_IDAC, 0xF0); 2643300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_LNAG2_IDAC, 0xF0); 2644300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_RSSI_POLE, 0x00); 2645300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_RSSI_POLE, 0x00); 2646300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_RSSI_GAIN, 2647300016Sadrian rssi_gain); 2648300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_RSSI_GAIN, 2649300016Sadrian rssi_gain); 2650300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_BIASPOLE_LNAA1_IDAC, 2651300016Sadrian 0x17); 2652300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_BIASPOLE_LNAA1_IDAC, 2653300016Sadrian 0x17); 2654300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_LNAA2_IDAC, 0xFF); 2655300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_LNAA2_IDAC, 0xFF); 2656300016Sadrian 2657300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(0, 8), 4, e->lna1_gain); 2658300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(1, 8), 4, e->lna1_gain); 2659300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(0, 16), 4, e->lna2_gain); 2660300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(1, 16), 4, e->lna2_gain); 2661300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(0, 32), 10, e->gain_db); 2662300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(1, 32), 10, e->gain_db); 2663300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(2, 32), 10, e->gain_bits); 2664300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(3, 32), 10, e->gain_bits); 2665300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(0, 0x40), 6, lpf_gain); 2666300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(1, 0x40), 6, lpf_gain); 2667300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(2, 0x40), 6, lpf_bits); 2668300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(3, 0x40), 6, lpf_bits); 2669300016Sadrian 2670300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C1_INITGAIN_A, e->init_gain); 2671300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C2_INITGAIN_A, e->init_gain); 2672300016Sadrian 2673300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x106), 2, 2674300016Sadrian e->rfseq_init); 2675300016Sadrian 2676300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C1_CLIP_HIGAIN_A, e->cliphi_gain); 2677300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C2_CLIP_HIGAIN_A, e->cliphi_gain); 2678300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C1_CLIP_MEDGAIN_A, e->clipmd_gain); 2679300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C2_CLIP_MEDGAIN_A, e->clipmd_gain); 2680300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C1_CLIP_LOGAIN_A, e->cliplo_gain); 2681300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C2_CLIP_LOGAIN_A, e->cliplo_gain); 2682300016Sadrian 2683300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_CRSMINPOWER0, 0xFF00, e->crsmin); 2684300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_CRSMINPOWERL0, 0xFF00, e->crsminl); 2685300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_CRSMINPOWERU0, 0xFF00, e->crsminu); 2686300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_C1_NBCLIPTHRES, e->nbclip); 2687300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_C2_NBCLIPTHRES, e->nbclip); 2688300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_C1_CLIPWBTHRES, 2689300016Sadrian ~BWN_NPHY_C1_CLIPWBTHRES_CLIP2, e->wlclip); 2690300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_C2_CLIPWBTHRES, 2691300016Sadrian ~BWN_NPHY_C2_CLIPWBTHRES_CLIP2, e->wlclip); 2692300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_CCK_SHIFTB_REF, 0x809C); 2693300016Sadrian} 2694300016Sadrian 2695300016Sadrianstatic void bwn_nphy_gain_ctl_workarounds_rev1_2(struct bwn_mac *mac) 2696300016Sadrian{ 2697300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 2698300016Sadrian 2699300016Sadrian uint8_t i, j; 2700300016Sadrian uint8_t code; 2701300016Sadrian uint16_t tmp; 2702300016Sadrian uint8_t rfseq_events[3] = { 6, 8, 7 }; 2703300016Sadrian uint8_t rfseq_delays[3] = { 10, 30, 1 }; 2704300016Sadrian 2705300016Sadrian /* Set Clip 2 detect */ 2706300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_C1_CGAINI, BWN_NPHY_C1_CGAINI_CL2DETECT); 2707300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_C2_CGAINI, BWN_NPHY_C2_CGAINI_CL2DETECT); 2708300016Sadrian 2709300016Sadrian /* Set narrowband clip threshold */ 2710300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_C1_NBCLIPTHRES, 0x84); 2711300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_C2_NBCLIPTHRES, 0x84); 2712300016Sadrian 2713300016Sadrian if (!bwn_is_40mhz(mac)) { 2714300016Sadrian /* Set dwell lengths */ 2715300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_CLIP1_NBDWELL_LEN, 0x002B); 2716300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_CLIP2_NBDWELL_LEN, 0x002B); 2717300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_W1CLIP1_DWELL_LEN, 0x0009); 2718300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_W1CLIP2_DWELL_LEN, 0x0009); 2719300016Sadrian } 2720300016Sadrian 2721300016Sadrian /* Set wideband clip 2 threshold */ 2722300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_C1_CLIPWBTHRES, 2723300016Sadrian ~BWN_NPHY_C1_CLIPWBTHRES_CLIP2, 21); 2724300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_C2_CLIPWBTHRES, 2725300016Sadrian ~BWN_NPHY_C2_CLIPWBTHRES_CLIP2, 21); 2726300016Sadrian 2727300016Sadrian if (!bwn_is_40mhz(mac)) { 2728300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_C1_CGAINI, 2729300016Sadrian ~BWN_NPHY_C1_CGAINI_GAINBKOFF, 0x1); 2730300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_C2_CGAINI, 2731300016Sadrian ~BWN_NPHY_C2_CGAINI_GAINBKOFF, 0x1); 2732300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_C1_CCK_CGAINI, 2733300016Sadrian ~BWN_NPHY_C1_CCK_CGAINI_GAINBKOFF, 0x1); 2734300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_C2_CCK_CGAINI, 2735300016Sadrian ~BWN_NPHY_C2_CCK_CGAINI_GAINBKOFF, 0x1); 2736300016Sadrian } 2737300016Sadrian 2738300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_CCK_SHIFTB_REF, 0x809C); 2739300016Sadrian 2740300016Sadrian if (nphy->gain_boost) { 2741300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G && 2742300016Sadrian bwn_is_40mhz(mac)) 2743300016Sadrian code = 4; 2744300016Sadrian else 2745300016Sadrian code = 5; 2746300016Sadrian } else { 2747300016Sadrian code = bwn_is_40mhz(mac) ? 6 : 7; 2748300016Sadrian } 2749300016Sadrian 2750300016Sadrian /* Set HPVGA2 index */ 2751300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_C1_INITGAIN, ~BWN_NPHY_C1_INITGAIN_HPVGA2, 2752300016Sadrian code << BWN_NPHY_C1_INITGAIN_HPVGA2_SHIFT); 2753300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_C2_INITGAIN, ~BWN_NPHY_C2_INITGAIN_HPVGA2, 2754300016Sadrian code << BWN_NPHY_C2_INITGAIN_HPVGA2_SHIFT); 2755300016Sadrian 2756300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x1D06); 2757300016Sadrian /* specs say about 2 loops, but wl does 4 */ 2758300016Sadrian for (i = 0; i < 4; i++) 2759300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, (code << 8 | 0x7C)); 2760300016Sadrian 2761300016Sadrian bwn_nphy_adjust_lna_gain_table(mac); 2762300016Sadrian 2763300016Sadrian if (nphy->elna_gain_config) { 2764300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x0808); 2765300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x0); 2766300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1); 2767300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1); 2768300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1); 2769300016Sadrian 2770300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x0C08); 2771300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x0); 2772300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1); 2773300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1); 2774300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1); 2775300016Sadrian 2776300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x1D06); 2777300016Sadrian /* specs say about 2 loops, but wl does 4 */ 2778300016Sadrian for (i = 0; i < 4; i++) 2779300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 2780300016Sadrian (code << 8 | 0x74)); 2781300016Sadrian } 2782300016Sadrian 2783300016Sadrian if (mac->mac_phy.rev == 2) { 2784300016Sadrian for (i = 0; i < 4; i++) { 2785300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 2786300016Sadrian (0x0400 * i) + 0x0020); 2787300016Sadrian for (j = 0; j < 21; j++) { 2788300016Sadrian tmp = j * (i < 2 ? 3 : 1); 2789300016Sadrian BWN_PHY_WRITE(mac, 2790300016Sadrian BWN_NPHY_TABLE_DATALO, tmp); 2791300016Sadrian } 2792300016Sadrian } 2793300016Sadrian } 2794300016Sadrian 2795300016Sadrian bwn_nphy_set_rf_sequence(mac, 5, rfseq_events, rfseq_delays, 3); 2796300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_OVER_DGAIN1, 2797300016Sadrian ~BWN_NPHY_OVER_DGAIN_CCKDGECV & 0xFFFF, 2798300016Sadrian 0x5A << BWN_NPHY_OVER_DGAIN_CCKDGECV_SHIFT); 2799300016Sadrian 2800300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 2801300016Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_N(0xC5D), 0xFF80, 4); 2802300016Sadrian} 2803300016Sadrian 2804300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */ 2805300016Sadrianstatic void bwn_nphy_gain_ctl_workarounds(struct bwn_mac *mac) 2806300016Sadrian{ 2807300016Sadrian if (mac->mac_phy.rev >= 19) 2808300016Sadrian bwn_nphy_gain_ctl_workarounds_rev19(mac); 2809300016Sadrian else if (mac->mac_phy.rev >= 7) 2810300016Sadrian bwn_nphy_gain_ctl_workarounds_rev7(mac); 2811300016Sadrian else if (mac->mac_phy.rev >= 3) 2812300016Sadrian bwn_nphy_gain_ctl_workarounds_rev3(mac); 2813300016Sadrian else 2814300016Sadrian bwn_nphy_gain_ctl_workarounds_rev1_2(mac); 2815300016Sadrian} 2816300016Sadrian 2817300016Sadrianstatic void bwn_nphy_workarounds_rev7plus(struct bwn_mac *mac) 2818300016Sadrian{ 2819300016Sadrian struct bwn_softc *sc = mac->mac_sc; 2820300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 2821300016Sadrian 2822300016Sadrian /* TX to RX */ 2823300016Sadrian uint8_t tx2rx_events[7] = { 4, 3, 5, 2, 1, 8, 31, }; 2824300016Sadrian uint8_t tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1, }; 2825300016Sadrian /* RX to TX */ 2826300016Sadrian uint8_t rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3, 2827300016Sadrian 0x1F }; 2828300016Sadrian uint8_t rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; 2829300016Sadrian 2830300016Sadrian static const uint16_t ntab7_15e_16e[] = { 0, 0x10f, 0x10f }; 2831300016Sadrian uint8_t ntab7_138_146[] = { 0x11, 0x11 }; 2832300016Sadrian uint8_t ntab7_133[] = { 0x77, 0x11, 0x11 }; 2833300016Sadrian 2834300016Sadrian uint16_t lpf_ofdm_20mhz[2], lpf_ofdm_40mhz[2], lpf_11b[2]; 2835300016Sadrian uint16_t bcap_val; 2836300016Sadrian int16_t bcap_val_11b[2], bcap_val_11n_20[2], bcap_val_11n_40[2]; 2837300016Sadrian uint16_t scap_val; 2838300016Sadrian int16_t scap_val_11b[2], scap_val_11n_20[2], scap_val_11n_40[2]; 2839300016Sadrian bool rccal_ovrd = false; 2840300016Sadrian 2841300016Sadrian uint16_t bias, conv, filt; 2842300016Sadrian 2843300016Sadrian uint32_t noise_tbl[2]; 2844300016Sadrian 2845300016Sadrian uint32_t tmp32; 2846300016Sadrian uint8_t core; 2847300016Sadrian 2848300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A0, 0x0125); 2849300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A1, 0x01b3); 2850300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A2, 0x0105); 2851300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B0, 0x016e); 2852300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B1, 0x00cd); 2853300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B2, 0x0020); 2854300016Sadrian 2855300016Sadrian if (phy->rev == 7) { 2856300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_FINERX2_CGC, 0x10); 2857300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN0, 0xFF80, 0x0020); 2858300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN0, 0x80FF, 0x2700); 2859300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN1, 0xFF80, 0x002E); 2860300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN1, 0x80FF, 0x3300); 2861300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN2, 0xFF80, 0x0037); 2862300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN2, 0x80FF, 0x3A00); 2863300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN3, 0xFF80, 0x003C); 2864300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN3, 0x80FF, 0x3E00); 2865300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN4, 0xFF80, 0x003E); 2866300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN4, 0x80FF, 0x3F00); 2867300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN5, 0xFF80, 0x0040); 2868300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN5, 0x80FF, 0x4000); 2869300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN6, 0xFF80, 0x0040); 2870300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN6, 0x80FF, 0x4000); 2871300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN7, 0xFF80, 0x0040); 2872300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN7, 0x80FF, 0x4000); 2873300016Sadrian } 2874300016Sadrian 2875300016Sadrian if (phy->rev >= 16) { 2876300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT0, 0x7ff); 2877300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT1, 0x7ff); 2878300016Sadrian } else if (phy->rev <= 8) { 2879300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT0, 0x1B0); 2880300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT1, 0x1B0); 2881300016Sadrian } 2882300016Sadrian 2883300016Sadrian if (phy->rev >= 16) 2884300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_TXTAILCNT, ~0xFF, 0xa0); 2885300016Sadrian else if (phy->rev >= 8) 2886300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_TXTAILCNT, ~0xFF, 0x72); 2887300016Sadrian 2888300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x00), 2); 2889300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x10), 2); 2890300016Sadrian tmp32 = bwn_ntab_read(mac, BWN_NTAB32(30, 0)); 2891300016Sadrian tmp32 &= 0xffffff; 2892300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(30, 0), tmp32); 2893300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x15d), 3, ntab7_15e_16e); 2894300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x16d), 3, ntab7_15e_16e); 2895300016Sadrian 2896300016Sadrian bwn_nphy_set_rf_sequence(mac, 1, tx2rx_events, tx2rx_delays, 2897300016Sadrian nitems(tx2rx_events)); 2898300016Sadrian if (bwn_nphy_ipa(mac)) 2899300016Sadrian bwn_nphy_set_rf_sequence(mac, 0, rx2tx_events_ipa, 2900300016Sadrian rx2tx_delays_ipa, nitems(rx2tx_events_ipa)); 2901300016Sadrian 2902300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_EPS_OVERRIDEI_0, 0x3FFF, 0x4000); 2903300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_EPS_OVERRIDEI_1, 0x3FFF, 0x4000); 2904300016Sadrian 2905300016Sadrian for (core = 0; core < 2; core++) { 2906300016Sadrian lpf_ofdm_20mhz[core] = bwn_nphy_read_lpf_ctl(mac, 0x154 + core * 0x10); 2907300016Sadrian lpf_ofdm_40mhz[core] = bwn_nphy_read_lpf_ctl(mac, 0x159 + core * 0x10); 2908300016Sadrian lpf_11b[core] = bwn_nphy_read_lpf_ctl(mac, 0x152 + core * 0x10); 2909300016Sadrian } 2910300016Sadrian 2911300016Sadrian bcap_val = BWN_RF_READ(mac, R2057_RCCAL_BCAP_VAL); 2912300016Sadrian scap_val = BWN_RF_READ(mac, R2057_RCCAL_SCAP_VAL); 2913300016Sadrian 2914300016Sadrian if (bwn_nphy_ipa(mac)) { 2915300016Sadrian bool ghz2 = bwn_current_band(mac) == BWN_BAND_2G; 2916300016Sadrian 2917300016Sadrian switch (phy->rf_rev) { 2918300016Sadrian case 5: 2919300016Sadrian /* Check radio version (to be 0) by PHY rev for now */ 2920300016Sadrian if (phy->rev == 8 && bwn_is_40mhz(mac)) { 2921300016Sadrian for (core = 0; core < 2; core++) { 2922300016Sadrian scap_val_11b[core] = scap_val; 2923300016Sadrian bcap_val_11b[core] = bcap_val; 2924300016Sadrian scap_val_11n_20[core] = scap_val; 2925300016Sadrian bcap_val_11n_20[core] = bcap_val; 2926300016Sadrian scap_val_11n_40[core] = 0xc; 2927300016Sadrian bcap_val_11n_40[core] = 0xc; 2928300016Sadrian } 2929300016Sadrian 2930300016Sadrian rccal_ovrd = true; 2931300016Sadrian } 2932300016Sadrian if (phy->rev == 9) { 2933300016Sadrian /* TODO: Radio version 1 (e.g. BCM5357B0) */ 2934300016Sadrian } 2935300016Sadrian break; 2936300016Sadrian case 7: 2937300016Sadrian case 8: 2938300016Sadrian for (core = 0; core < 2; core++) { 2939300016Sadrian scap_val_11b[core] = scap_val; 2940300016Sadrian bcap_val_11b[core] = bcap_val; 2941300016Sadrian lpf_ofdm_20mhz[core] = 4; 2942300016Sadrian lpf_11b[core] = 1; 2943300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 2944300016Sadrian scap_val_11n_20[core] = 0xc; 2945300016Sadrian bcap_val_11n_20[core] = 0xc; 2946300016Sadrian scap_val_11n_40[core] = 0xa; 2947300016Sadrian bcap_val_11n_40[core] = 0xa; 2948300016Sadrian } else { 2949300016Sadrian scap_val_11n_20[core] = 0x14; 2950300016Sadrian bcap_val_11n_20[core] = 0x14; 2951300016Sadrian scap_val_11n_40[core] = 0xf; 2952300016Sadrian bcap_val_11n_40[core] = 0xf; 2953300016Sadrian } 2954300016Sadrian } 2955300016Sadrian 2956300016Sadrian rccal_ovrd = true; 2957300016Sadrian break; 2958300016Sadrian case 9: 2959300016Sadrian for (core = 0; core < 2; core++) { 2960300016Sadrian bcap_val_11b[core] = bcap_val; 2961300016Sadrian scap_val_11b[core] = scap_val; 2962300016Sadrian lpf_11b[core] = 1; 2963300016Sadrian 2964300016Sadrian if (ghz2) { 2965300016Sadrian bcap_val_11n_20[core] = bcap_val + 13; 2966300016Sadrian scap_val_11n_20[core] = scap_val + 15; 2967300016Sadrian } else { 2968300016Sadrian bcap_val_11n_20[core] = bcap_val + 14; 2969300016Sadrian scap_val_11n_20[core] = scap_val + 15; 2970300016Sadrian } 2971300016Sadrian lpf_ofdm_20mhz[core] = 4; 2972300016Sadrian 2973300016Sadrian if (ghz2) { 2974300016Sadrian bcap_val_11n_40[core] = bcap_val - 7; 2975300016Sadrian scap_val_11n_40[core] = scap_val - 5; 2976300016Sadrian } else { 2977300016Sadrian bcap_val_11n_40[core] = bcap_val + 2; 2978300016Sadrian scap_val_11n_40[core] = scap_val + 4; 2979300016Sadrian } 2980300016Sadrian lpf_ofdm_40mhz[core] = 4; 2981300016Sadrian } 2982300016Sadrian 2983300016Sadrian rccal_ovrd = true; 2984300016Sadrian break; 2985300016Sadrian case 14: 2986300016Sadrian for (core = 0; core < 2; core++) { 2987300016Sadrian bcap_val_11b[core] = bcap_val; 2988300016Sadrian scap_val_11b[core] = scap_val; 2989300016Sadrian lpf_11b[core] = 1; 2990300016Sadrian } 2991300016Sadrian 2992300016Sadrian bcap_val_11n_20[0] = bcap_val + 20; 2993300016Sadrian scap_val_11n_20[0] = scap_val + 20; 2994300016Sadrian lpf_ofdm_20mhz[0] = 3; 2995300016Sadrian 2996300016Sadrian bcap_val_11n_20[1] = bcap_val + 16; 2997300016Sadrian scap_val_11n_20[1] = scap_val + 16; 2998300016Sadrian lpf_ofdm_20mhz[1] = 3; 2999300016Sadrian 3000300016Sadrian bcap_val_11n_40[0] = bcap_val + 20; 3001300016Sadrian scap_val_11n_40[0] = scap_val + 20; 3002300016Sadrian lpf_ofdm_40mhz[0] = 4; 3003300016Sadrian 3004300016Sadrian bcap_val_11n_40[1] = bcap_val + 10; 3005300016Sadrian scap_val_11n_40[1] = scap_val + 10; 3006300016Sadrian lpf_ofdm_40mhz[1] = 4; 3007300016Sadrian 3008300016Sadrian rccal_ovrd = true; 3009300016Sadrian break; 3010300016Sadrian } 3011300016Sadrian } else { 3012300016Sadrian if (phy->rf_rev == 5) { 3013300016Sadrian for (core = 0; core < 2; core++) { 3014300016Sadrian lpf_ofdm_20mhz[core] = 1; 3015300016Sadrian lpf_ofdm_40mhz[core] = 3; 3016300016Sadrian scap_val_11b[core] = scap_val; 3017300016Sadrian bcap_val_11b[core] = bcap_val; 3018300016Sadrian scap_val_11n_20[core] = 0x11; 3019300016Sadrian scap_val_11n_40[core] = 0x11; 3020300016Sadrian bcap_val_11n_20[core] = 0x13; 3021300016Sadrian bcap_val_11n_40[core] = 0x13; 3022300016Sadrian } 3023300016Sadrian 3024300016Sadrian rccal_ovrd = true; 3025300016Sadrian } 3026300016Sadrian } 3027300016Sadrian if (rccal_ovrd) { 3028300016Sadrian uint16_t rx2tx_lut_20_11b[2], rx2tx_lut_20_11n[2], rx2tx_lut_40_11n[2]; 3029300016Sadrian uint8_t rx2tx_lut_extra = 1; 3030300016Sadrian 3031300016Sadrian for (core = 0; core < 2; core++) { 3032300016Sadrian bcap_val_11b[core] = bwn_clamp_val(bcap_val_11b[core], 0, 0x1f); 3033300016Sadrian scap_val_11b[core] = bwn_clamp_val(scap_val_11b[core], 0, 0x1f); 3034300016Sadrian bcap_val_11n_20[core] = bwn_clamp_val(bcap_val_11n_20[core], 0, 0x1f); 3035300016Sadrian scap_val_11n_20[core] = bwn_clamp_val(scap_val_11n_20[core], 0, 0x1f); 3036300016Sadrian bcap_val_11n_40[core] = bwn_clamp_val(bcap_val_11n_40[core], 0, 0x1f); 3037300016Sadrian scap_val_11n_40[core] = bwn_clamp_val(scap_val_11n_40[core], 0, 0x1f); 3038300016Sadrian 3039300016Sadrian rx2tx_lut_20_11b[core] = (rx2tx_lut_extra << 13) | 3040300016Sadrian (bcap_val_11b[core] << 8) | 3041300016Sadrian (scap_val_11b[core] << 3) | 3042300016Sadrian lpf_11b[core]; 3043300016Sadrian rx2tx_lut_20_11n[core] = (rx2tx_lut_extra << 13) | 3044300016Sadrian (bcap_val_11n_20[core] << 8) | 3045300016Sadrian (scap_val_11n_20[core] << 3) | 3046300016Sadrian lpf_ofdm_20mhz[core]; 3047300016Sadrian rx2tx_lut_40_11n[core] = (rx2tx_lut_extra << 13) | 3048300016Sadrian (bcap_val_11n_40[core] << 8) | 3049300016Sadrian (scap_val_11n_40[core] << 3) | 3050300016Sadrian lpf_ofdm_40mhz[core]; 3051300016Sadrian } 3052300016Sadrian 3053300016Sadrian for (core = 0; core < 2; core++) { 3054300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(7, 0x152 + core * 16), 3055300016Sadrian rx2tx_lut_20_11b[core]); 3056300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(7, 0x153 + core * 16), 3057300016Sadrian rx2tx_lut_20_11n[core]); 3058300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(7, 0x154 + core * 16), 3059300016Sadrian rx2tx_lut_20_11n[core]); 3060300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(7, 0x155 + core * 16), 3061300016Sadrian rx2tx_lut_40_11n[core]); 3062300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(7, 0x156 + core * 16), 3063300016Sadrian rx2tx_lut_40_11n[core]); 3064300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(7, 0x157 + core * 16), 3065300016Sadrian rx2tx_lut_40_11n[core]); 3066300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(7, 0x158 + core * 16), 3067300016Sadrian rx2tx_lut_40_11n[core]); 3068300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(7, 0x159 + core * 16), 3069300016Sadrian rx2tx_lut_40_11n[core]); 3070300016Sadrian } 3071300016Sadrian } 3072300016Sadrian 3073300016Sadrian BWN_PHY_WRITE(mac, 0x32F, 0x3); 3074300016Sadrian 3075300016Sadrian if (phy->rf_rev == 4 || phy->rf_rev == 6) 3076300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 4, 1, 3, false, 0); 3077300016Sadrian 3078300016Sadrian if (phy->rf_rev == 3 || phy->rf_rev == 4 || phy->rf_rev == 6) { 3079300016Sadrian if (siba_sprom_get_rev(sc->sc_dev) && 3080300016Sadrian siba_sprom_get_bf2_hi(sc->sc_dev) & BWN_BFH2_IPALVLSHIFT_3P3) { 3081300016Sadrian BWN_RF_WRITE(mac, 0x5, 0x05); 3082300016Sadrian BWN_RF_WRITE(mac, 0x6, 0x30); 3083300016Sadrian BWN_RF_WRITE(mac, 0x7, 0x00); 3084300016Sadrian BWN_RF_SET(mac, 0x4f, 0x1); 3085300016Sadrian BWN_RF_SET(mac, 0xd4, 0x1); 3086300016Sadrian bias = 0x1f; 3087300016Sadrian conv = 0x6f; 3088300016Sadrian filt = 0xaa; 3089300016Sadrian } else { 3090300016Sadrian bias = 0x2b; 3091300016Sadrian conv = 0x7f; 3092300016Sadrian filt = 0xee; 3093300016Sadrian } 3094300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 3095300016Sadrian for (core = 0; core < 2; core++) { 3096300016Sadrian if (core == 0) { 3097300016Sadrian BWN_RF_WRITE(mac, 0x5F, bias); 3098300016Sadrian BWN_RF_WRITE(mac, 0x64, conv); 3099300016Sadrian BWN_RF_WRITE(mac, 0x66, filt); 3100300016Sadrian } else { 3101300016Sadrian BWN_RF_WRITE(mac, 0xE8, bias); 3102300016Sadrian BWN_RF_WRITE(mac, 0xE9, conv); 3103300016Sadrian BWN_RF_WRITE(mac, 0xEB, filt); 3104300016Sadrian } 3105300016Sadrian } 3106300016Sadrian } 3107300016Sadrian } 3108300016Sadrian 3109300016Sadrian if (bwn_nphy_ipa(mac)) { 3110300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 3111300016Sadrian if (phy->rf_rev == 3 || phy->rf_rev == 4 || 3112300016Sadrian phy->rf_rev == 6) { 3113300016Sadrian for (core = 0; core < 2; core++) { 3114300016Sadrian if (core == 0) 3115300016Sadrian BWN_RF_WRITE(mac, 0x51, 3116300016Sadrian 0x7f); 3117300016Sadrian else 3118300016Sadrian BWN_RF_WRITE(mac, 0xd6, 3119300016Sadrian 0x7f); 3120300016Sadrian } 3121300016Sadrian } 3122300016Sadrian switch (phy->rf_rev) { 3123300016Sadrian case 3: 3124300016Sadrian for (core = 0; core < 2; core++) { 3125300016Sadrian if (core == 0) { 3126300016Sadrian BWN_RF_WRITE(mac, 0x64, 3127300016Sadrian 0x13); 3128300016Sadrian BWN_RF_WRITE(mac, 0x5F, 3129300016Sadrian 0x1F); 3130300016Sadrian BWN_RF_WRITE(mac, 0x66, 3131300016Sadrian 0xEE); 3132300016Sadrian BWN_RF_WRITE(mac, 0x59, 3133300016Sadrian 0x8A); 3134300016Sadrian BWN_RF_WRITE(mac, 0x80, 3135300016Sadrian 0x3E); 3136300016Sadrian } else { 3137300016Sadrian BWN_RF_WRITE(mac, 0x69, 3138300016Sadrian 0x13); 3139300016Sadrian BWN_RF_WRITE(mac, 0xE8, 3140300016Sadrian 0x1F); 3141300016Sadrian BWN_RF_WRITE(mac, 0xEB, 3142300016Sadrian 0xEE); 3143300016Sadrian BWN_RF_WRITE(mac, 0xDE, 3144300016Sadrian 0x8A); 3145300016Sadrian BWN_RF_WRITE(mac, 0x105, 3146300016Sadrian 0x3E); 3147300016Sadrian } 3148300016Sadrian } 3149300016Sadrian break; 3150300016Sadrian case 7: 3151300016Sadrian case 8: 3152300016Sadrian if (!bwn_is_40mhz(mac)) { 3153300016Sadrian BWN_RF_WRITE(mac, 0x5F, 0x14); 3154300016Sadrian BWN_RF_WRITE(mac, 0xE8, 0x12); 3155300016Sadrian } else { 3156300016Sadrian BWN_RF_WRITE(mac, 0x5F, 0x16); 3157300016Sadrian BWN_RF_WRITE(mac, 0xE8, 0x16); 3158300016Sadrian } 3159300016Sadrian break; 3160300016Sadrian case 14: 3161300016Sadrian for (core = 0; core < 2; core++) { 3162300016Sadrian int o = core ? 0x85 : 0; 3163300016Sadrian 3164300016Sadrian BWN_RF_WRITE(mac, o + R2057_IPA2G_CASCONV_CORE0, 0x13); 3165300016Sadrian BWN_RF_WRITE(mac, o + R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, 0x21); 3166300016Sadrian BWN_RF_WRITE(mac, o + R2057_IPA2G_BIAS_FILTER_CORE0, 0xff); 3167300016Sadrian BWN_RF_WRITE(mac, o + R2057_PAD2G_IDACS_CORE0, 0x88); 3168300016Sadrian BWN_RF_WRITE(mac, o + R2057_PAD2G_TUNE_PUS_CORE0, 0x23); 3169300016Sadrian BWN_RF_WRITE(mac, o + R2057_IPA2G_IMAIN_CORE0, 0x16); 3170300016Sadrian BWN_RF_WRITE(mac, o + R2057_PAD_BIAS_FILTER_BWS_CORE0, 0x3e); 3171300016Sadrian BWN_RF_WRITE(mac, o + R2057_BACKUP1_CORE0, 0x10); 3172300016Sadrian } 3173300016Sadrian break; 3174300016Sadrian } 3175300016Sadrian } else { 3176300016Sadrian uint16_t freq = bwn_get_centre_freq(mac); 3177300016Sadrian if ((freq >= 5180 && freq <= 5230) || 3178300016Sadrian (freq >= 5745 && freq <= 5805)) { 3179300016Sadrian BWN_RF_WRITE(mac, 0x7D, 0xFF); 3180300016Sadrian BWN_RF_WRITE(mac, 0xFE, 0xFF); 3181300016Sadrian } 3182300016Sadrian } 3183300016Sadrian } else { 3184300016Sadrian if (phy->rf_rev != 5) { 3185300016Sadrian for (core = 0; core < 2; core++) { 3186300016Sadrian if (core == 0) { 3187300016Sadrian BWN_RF_WRITE(mac, 0x5c, 0x61); 3188300016Sadrian BWN_RF_WRITE(mac, 0x51, 0x70); 3189300016Sadrian } else { 3190300016Sadrian BWN_RF_WRITE(mac, 0xe1, 0x61); 3191300016Sadrian BWN_RF_WRITE(mac, 0xd6, 0x70); 3192300016Sadrian } 3193300016Sadrian } 3194300016Sadrian } 3195300016Sadrian } 3196300016Sadrian 3197300016Sadrian if (phy->rf_rev == 4) { 3198300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x05), 0x20); 3199300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x15), 0x20); 3200300016Sadrian for (core = 0; core < 2; core++) { 3201300016Sadrian if (core == 0) { 3202300016Sadrian BWN_RF_WRITE(mac, 0x1a1, 0x00); 3203300016Sadrian BWN_RF_WRITE(mac, 0x1a2, 0x3f); 3204300016Sadrian BWN_RF_WRITE(mac, 0x1a6, 0x3f); 3205300016Sadrian } else { 3206300016Sadrian BWN_RF_WRITE(mac, 0x1a7, 0x00); 3207300016Sadrian BWN_RF_WRITE(mac, 0x1ab, 0x3f); 3208300016Sadrian BWN_RF_WRITE(mac, 0x1ac, 0x3f); 3209300016Sadrian } 3210300016Sadrian } 3211300016Sadrian } else { 3212300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_C1, 0x4); 3213300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER1, 0x4); 3214300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_C2, 0x4); 3215300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x4); 3216300016Sadrian 3217300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C1, ~0x1); 3218300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER1, 0x1); 3219300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C2, ~0x1); 3220300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x1); 3221300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x05), 0); 3222300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x15), 0); 3223300016Sadrian 3224300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C1, ~0x4); 3225300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER1, ~0x4); 3226300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C2, ~0x4); 3227300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER, ~0x4); 3228300016Sadrian } 3229300016Sadrian 3230300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ENDROP_TLEN, 0x2); 3231300016Sadrian 3232300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(16, 0x100), 20); 3233300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(7, 0x138), 2, ntab7_138_146); 3234300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(7, 0x141), 0x77); 3235300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(7, 0x133), 3, ntab7_133); 3236300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(7, 0x146), 2, ntab7_138_146); 3237300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(7, 0x123), 0x77); 3238300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(7, 0x12A), 0x77); 3239300016Sadrian 3240300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB32(16, 0x02), 1, noise_tbl); 3241300016Sadrian noise_tbl[1] = bwn_is_40mhz(mac) ? 0x14D : 0x18D; 3242300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB32(16, 0x02), 2, noise_tbl); 3243300016Sadrian 3244300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB32(16, 0x7E), 1, noise_tbl); 3245300016Sadrian noise_tbl[1] = bwn_is_40mhz(mac) ? 0x14D : 0x18D; 3246300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB32(16, 0x7E), 2, noise_tbl); 3247300016Sadrian 3248300016Sadrian bwn_nphy_gain_ctl_workarounds(mac); 3249300016Sadrian 3250300016Sadrian /* TODO 3251300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x08), 4, 3252300016Sadrian aux_adc_vmid_rev7_core0); 3253300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x18), 4, 3254300016Sadrian aux_adc_vmid_rev7_core1); 3255300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x0C), 4, 3256300016Sadrian aux_adc_gain_rev7); 3257300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x1C), 4, 3258300016Sadrian aux_adc_gain_rev7); 3259300016Sadrian */ 3260300016Sadrian} 3261300016Sadrian 3262300016Sadrianstatic void bwn_nphy_workarounds_rev3plus(struct bwn_mac *mac) 3263300016Sadrian{ 3264300016Sadrian struct bwn_softc *sc = mac->mac_sc; 3265300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 3266300016Sadrian 3267300016Sadrian /* TX to RX */ 3268300016Sadrian uint8_t tx2rx_events[7] = { 0x4, 0x3, 0x5, 0x2, 0x1, 0x8, 0x1F }; 3269300016Sadrian uint8_t tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1 }; 3270300016Sadrian /* RX to TX */ 3271300016Sadrian uint8_t rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3, 3272300016Sadrian 0x1F }; 3273300016Sadrian uint8_t rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; 3274300016Sadrian uint8_t rx2tx_events[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0x3, 0x4, 0x1F }; 3275300016Sadrian uint8_t rx2tx_delays[9] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 }; 3276300016Sadrian 3277300016Sadrian uint16_t vmids[5][4] = { 3278300016Sadrian { 0xa2, 0xb4, 0xb4, 0x89, }, /* 0 */ 3279300016Sadrian { 0xb4, 0xb4, 0xb4, 0x24, }, /* 1 */ 3280300016Sadrian { 0xa2, 0xb4, 0xb4, 0x74, }, /* 2 */ 3281300016Sadrian { 0xa2, 0xb4, 0xb4, 0x270, }, /* 3 */ 3282300016Sadrian { 0xa2, 0xb4, 0xb4, 0x00, }, /* 4 and 5 */ 3283300016Sadrian }; 3284300016Sadrian uint16_t gains[5][4] = { 3285300016Sadrian { 0x02, 0x02, 0x02, 0x00, }, /* 0 */ 3286300016Sadrian { 0x02, 0x02, 0x02, 0x02, }, /* 1 */ 3287300016Sadrian { 0x02, 0x02, 0x02, 0x04, }, /* 2 */ 3288300016Sadrian { 0x02, 0x02, 0x02, 0x00, }, /* 3 */ 3289300016Sadrian { 0x02, 0x02, 0x02, 0x00, }, /* 4 and 5 */ 3290300016Sadrian }; 3291300016Sadrian uint16_t *vmid, *gain; 3292300016Sadrian 3293300016Sadrian uint8_t pdet_range; 3294300016Sadrian uint16_t tmp16; 3295300016Sadrian uint32_t tmp32; 3296300016Sadrian 3297300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT0, 0x1f8); 3298300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT1, 0x1f8); 3299300016Sadrian 3300300016Sadrian tmp32 = bwn_ntab_read(mac, BWN_NTAB32(30, 0)); 3301300016Sadrian tmp32 &= 0xffffff; 3302300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(30, 0), tmp32); 3303300016Sadrian 3304300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A0, 0x0125); 3305300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A1, 0x01B3); 3306300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A2, 0x0105); 3307300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B0, 0x016E); 3308300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B1, 0x00CD); 3309300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B2, 0x0020); 3310300016Sadrian 3311300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C1_CLIP_LOGAIN_B, 0x000C); 3312300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C2_CLIP_LOGAIN_B, 0x000C); 3313300016Sadrian 3314300016Sadrian /* TX to RX */ 3315300016Sadrian bwn_nphy_set_rf_sequence(mac, 1, tx2rx_events, tx2rx_delays, 3316300016Sadrian nitems(tx2rx_events)); 3317300016Sadrian 3318300016Sadrian /* RX to TX */ 3319300016Sadrian if (bwn_nphy_ipa(mac)) 3320300016Sadrian bwn_nphy_set_rf_sequence(mac, 0, rx2tx_events_ipa, 3321300016Sadrian rx2tx_delays_ipa, nitems(rx2tx_events_ipa)); 3322300016Sadrian if (nphy->hw_phyrxchain != 3 && 3323300016Sadrian nphy->hw_phyrxchain != nphy->hw_phytxchain) { 3324300016Sadrian if (bwn_nphy_ipa(mac)) { 3325300016Sadrian rx2tx_delays[5] = 59; 3326300016Sadrian rx2tx_delays[6] = 1; 3327300016Sadrian rx2tx_events[7] = 0x1F; 3328300016Sadrian } 3329300016Sadrian bwn_nphy_set_rf_sequence(mac, 0, rx2tx_events, rx2tx_delays, 3330300016Sadrian nitems(rx2tx_events)); 3331300016Sadrian } 3332300016Sadrian 3333300016Sadrian tmp16 = (bwn_current_band(mac) == BWN_BAND_2G) ? 3334300016Sadrian 0x2 : 0x9C40; 3335300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ENDROP_TLEN, tmp16); 3336300016Sadrian 3337300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_SGILTRNOFFSET, 0xF0FF, 0x0700); 3338300016Sadrian 3339300016Sadrian if (!bwn_is_40mhz(mac)) { 3340300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(16, 3), 0x18D); 3341300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(16, 127), 0x18D); 3342300016Sadrian } else { 3343300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(16, 3), 0x14D); 3344300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(16, 127), 0x14D); 3345300016Sadrian } 3346300016Sadrian 3347300016Sadrian bwn_nphy_gain_ctl_workarounds(mac); 3348300016Sadrian 3349300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0), 2); 3350300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 16), 2); 3351300016Sadrian 3352300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 3353300016Sadrian pdet_range = siba_sprom_get_fem_2ghz_pdet_range(sc->sc_dev); 3354300016Sadrian else 3355300016Sadrian pdet_range = siba_sprom_get_fem_5ghz_pdet_range(sc->sc_dev); 3356300016Sadrian /* uint16_t min() */ 3357300016Sadrian vmid = vmids[min(pdet_range, 4)]; 3358300016Sadrian gain = gains[min(pdet_range, 4)]; 3359300016Sadrian switch (pdet_range) { 3360300016Sadrian case 3: 3361300016Sadrian if (!(mac->mac_phy.rev >= 4 && 3362300016Sadrian bwn_current_band(mac) == BWN_BAND_2G)) 3363300016Sadrian break; 3364300016Sadrian /* FALL THROUGH */ 3365300016Sadrian case 0: 3366300016Sadrian case 1: 3367300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x08), 4, vmid); 3368300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x18), 4, vmid); 3369300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x0c), 4, gain); 3370300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x1c), 4, gain); 3371300016Sadrian break; 3372300016Sadrian case 2: 3373300016Sadrian if (mac->mac_phy.rev >= 6) { 3374300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 3375300016Sadrian vmid[3] = 0x94; 3376300016Sadrian else 3377300016Sadrian vmid[3] = 0x8e; 3378300016Sadrian gain[3] = 3; 3379300016Sadrian } else if (mac->mac_phy.rev == 5) { 3380300016Sadrian vmid[3] = 0x84; 3381300016Sadrian gain[3] = 2; 3382300016Sadrian } 3383300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x08), 4, vmid); 3384300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x18), 4, vmid); 3385300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x0c), 4, gain); 3386300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x1c), 4, gain); 3387300016Sadrian break; 3388300016Sadrian case 4: 3389300016Sadrian case 5: 3390300016Sadrian if (bwn_current_band(mac) != BWN_BAND_2G) { 3391300016Sadrian if (pdet_range == 4) { 3392300016Sadrian vmid[3] = 0x8e; 3393300016Sadrian tmp16 = 0x96; 3394300016Sadrian gain[3] = 0x2; 3395300016Sadrian } else { 3396300016Sadrian vmid[3] = 0x89; 3397300016Sadrian tmp16 = 0x89; 3398300016Sadrian gain[3] = 0; 3399300016Sadrian } 3400300016Sadrian } else { 3401300016Sadrian if (pdet_range == 4) { 3402300016Sadrian vmid[3] = 0x89; 3403300016Sadrian tmp16 = 0x8b; 3404300016Sadrian gain[3] = 0x2; 3405300016Sadrian } else { 3406300016Sadrian vmid[3] = 0x74; 3407300016Sadrian tmp16 = 0x70; 3408300016Sadrian gain[3] = 0; 3409300016Sadrian } 3410300016Sadrian } 3411300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x08), 4, vmid); 3412300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x0c), 4, gain); 3413300016Sadrian vmid[3] = tmp16; 3414300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x18), 4, vmid); 3415300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x1c), 4, gain); 3416300016Sadrian break; 3417300016Sadrian } 3418300016Sadrian 3419300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXA_MAST_BIAS, 0x00); 3420300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXA_MAST_BIAS, 0x00); 3421300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN, 0x06); 3422300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN, 0x06); 3423300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXA_BIAS_AUX, 0x07); 3424300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07); 3425300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88); 3426300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88); 3427300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXA_CMFB_IDAC, 0x00); 3428300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXA_CMFB_IDAC, 0x00); 3429300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00); 3430300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00); 3431300016Sadrian 3432300016Sadrian /* N PHY WAR TX Chain Update with hw_phytxchain as argument */ 3433300016Sadrian 3434300016Sadrian if ((siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_APLL_WAR && 3435300016Sadrian bwn_current_band(mac) == BWN_BAND_5G) || 3436300016Sadrian (siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_GPLL_WAR && 3437300016Sadrian bwn_current_band(mac) == BWN_BAND_2G)) 3438300016Sadrian tmp32 = 0x00088888; 3439300016Sadrian else 3440300016Sadrian tmp32 = 0x88888888; 3441300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(30, 1), tmp32); 3442300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(30, 2), tmp32); 3443300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(30, 3), tmp32); 3444300016Sadrian 3445300016Sadrian if (mac->mac_phy.rev == 4 && 3446300016Sadrian bwn_current_band(mac) == BWN_BAND_5G) { 3447300016Sadrian BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_GMBB_IDAC, 3448300016Sadrian 0x70); 3449300016Sadrian BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_GMBB_IDAC, 3450300016Sadrian 0x70); 3451300016Sadrian } 3452300016Sadrian 3453300016Sadrian /* Dropped probably-always-true condition */ 3454300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS40ASSERTTHRESH0, 0x03eb); 3455300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS40ASSERTTHRESH1, 0x03eb); 3456300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS40DEASSERTTHRESH0, 0x0341); 3457300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS40DEASSERTTHRESH1, 0x0341); 3458300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20LASSERTTHRESH0, 0x042b); 3459300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20LASSERTTHRESH1, 0x042b); 3460300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20LDEASSERTTHRESH0, 0x0381); 3461300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20LDEASSERTTHRESH1, 0x0381); 3462300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20UASSERTTHRESH0, 0x042b); 3463300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20UASSERTTHRESH1, 0x042b); 3464300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20UDEASSERTTHRESH0, 0x0381); 3465300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20UDEASSERTTHRESH1, 0x0381); 3466300016Sadrian 3467300016Sadrian if (mac->mac_phy.rev >= 6 && siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_SINGLEANT_CCK) 3468300016Sadrian ; /* TODO: 0x0080000000000000 HF */ 3469300016Sadrian} 3470300016Sadrian 3471300016Sadrianstatic void bwn_nphy_workarounds_rev1_2(struct bwn_mac *mac) 3472300016Sadrian{ 3473300016Sadrian struct bwn_softc *sc = mac->mac_sc; 3474300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 3475300016Sadrian struct bwn_phy_n *nphy = phy->phy_n; 3476300016Sadrian 3477300016Sadrian uint8_t events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 }; 3478300016Sadrian uint8_t delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 }; 3479300016Sadrian 3480300016Sadrian uint8_t events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 }; 3481300016Sadrian uint8_t delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 }; 3482300016Sadrian 3483300016Sadrian if (siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_SKWRKFEM_BRD || 3484300016Sadrian siba_get_pci_subdevice(sc->sc_dev)== BCMA_BOARD_TYPE_BCM943224M93) { 3485300016Sadrian delays1[0] = 0x1; 3486300016Sadrian delays1[5] = 0x14; 3487300016Sadrian } 3488300016Sadrian 3489300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G && 3490300016Sadrian nphy->band5g_pwrgain) { 3491300016Sadrian BWN_RF_MASK(mac, B2055_C1_TX_RF_SPARE, ~0x8); 3492300016Sadrian BWN_RF_MASK(mac, B2055_C2_TX_RF_SPARE, ~0x8); 3493300016Sadrian } else { 3494300016Sadrian BWN_RF_SET(mac, B2055_C1_TX_RF_SPARE, 0x8); 3495300016Sadrian BWN_RF_SET(mac, B2055_C2_TX_RF_SPARE, 0x8); 3496300016Sadrian } 3497300016Sadrian 3498300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x00), 0x000A); 3499300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x10), 0x000A); 3500300016Sadrian if (mac->mac_phy.rev < 3) { 3501300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x02), 0xCDAA); 3502300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x12), 0xCDAA); 3503300016Sadrian } 3504300016Sadrian 3505300016Sadrian if (mac->mac_phy.rev < 2) { 3506300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x08), 0x0000); 3507300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x18), 0x0000); 3508300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x07), 0x7AAB); 3509300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x17), 0x7AAB); 3510300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x06), 0x0800); 3511300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x16), 0x0800); 3512300016Sadrian } 3513300016Sadrian 3514300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); 3515300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP1, 0x301); 3516300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); 3517300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); 3518300016Sadrian 3519300016Sadrian bwn_nphy_set_rf_sequence(mac, 0, events1, delays1, 7); 3520300016Sadrian bwn_nphy_set_rf_sequence(mac, 1, events2, delays2, 7); 3521300016Sadrian 3522300016Sadrian bwn_nphy_gain_ctl_workarounds(mac); 3523300016Sadrian 3524300016Sadrian if (mac->mac_phy.rev < 2) { 3525300016Sadrian if (BWN_PHY_READ(mac, BWN_NPHY_RXCTL) & 0x2) 3526300016Sadrian bwn_hf_write(mac, bwn_hf_read(mac) | 3527300016Sadrian BWN_HF_MLADVW); 3528300016Sadrian } else if (mac->mac_phy.rev == 2) { 3529300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_CRSCHECK2, 0); 3530300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_CRSCHECK3, 0); 3531300016Sadrian } 3532300016Sadrian 3533300016Sadrian if (mac->mac_phy.rev < 2) 3534300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_SCRAM_SIGCTL, 3535300016Sadrian ~BWN_NPHY_SCRAM_SIGCTL_SCM); 3536300016Sadrian 3537300016Sadrian /* Set phase track alpha and beta */ 3538300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A0, 0x125); 3539300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A1, 0x1B3); 3540300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A2, 0x105); 3541300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B0, 0x16E); 3542300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B1, 0xCD); 3543300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B2, 0x20); 3544300016Sadrian 3545300016Sadrian if (mac->mac_phy.rev < 3) { 3546300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_PIL_DW1, 3547300016Sadrian ~BWN_NPHY_PIL_DW_64QAM & 0xFFFF); 3548300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXF_20CO_S2B1, 0xB5); 3549300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXF_20CO_S2B2, 0xA4); 3550300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXF_20CO_S2B3, 0x00); 3551300016Sadrian } 3552300016Sadrian 3553300016Sadrian if (mac->mac_phy.rev == 2) 3554300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_FINERX2_CGC, 3555300016Sadrian BWN_NPHY_FINERX2_CGC_DECGC); 3556300016Sadrian} 3557300016Sadrian 3558300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */ 3559300016Sadrianstatic void bwn_nphy_workarounds(struct bwn_mac *mac) 3560300016Sadrian{ 3561300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 3562300016Sadrian struct bwn_phy_n *nphy = phy->phy_n; 3563300016Sadrian 3564300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G) 3565300016Sadrian bwn_nphy_classifier(mac, 1, 0); 3566300016Sadrian else 3567300016Sadrian bwn_nphy_classifier(mac, 1, 1); 3568300016Sadrian 3569300016Sadrian if (nphy->hang_avoid) 3570300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 1); 3571300016Sadrian 3572300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_IQFLIP, 3573300016Sadrian BWN_NPHY_IQFLIP_ADC1 | BWN_NPHY_IQFLIP_ADC2); 3574300016Sadrian 3575300016Sadrian /* TODO: rev19+ */ 3576300016Sadrian if (mac->mac_phy.rev >= 7) 3577300016Sadrian bwn_nphy_workarounds_rev7plus(mac); 3578300016Sadrian else if (mac->mac_phy.rev >= 3) 3579300016Sadrian bwn_nphy_workarounds_rev3plus(mac); 3580300016Sadrian else 3581300016Sadrian bwn_nphy_workarounds_rev1_2(mac); 3582300016Sadrian 3583300016Sadrian if (nphy->hang_avoid) 3584300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 0); 3585300016Sadrian} 3586300016Sadrian 3587300016Sadrian/************************************************** 3588300016Sadrian * Tx/Rx common 3589300016Sadrian **************************************************/ 3590300016Sadrian 3591300016Sadrian/* 3592300016Sadrian * Transmits a known value for LO calibration 3593300016Sadrian * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone 3594300016Sadrian */ 3595300016Sadrianstatic int bwn_nphy_tx_tone(struct bwn_mac *mac, uint32_t freq, uint16_t max_val, 3596300016Sadrian bool iqmode, bool dac_test, bool modify_bbmult) 3597300016Sadrian{ 3598300016Sadrian uint16_t samp = bwn_nphy_gen_load_samples(mac, freq, max_val, dac_test); 3599300016Sadrian if (samp == 0) 3600300016Sadrian return -1; 3601300016Sadrian bwn_nphy_run_samples(mac, samp, 0xFFFF, 0, iqmode, dac_test, 3602300016Sadrian modify_bbmult); 3603300016Sadrian return 0; 3604300016Sadrian} 3605300016Sadrian 3606300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */ 3607300016Sadrianstatic void bwn_nphy_update_txrx_chain(struct bwn_mac *mac) 3608300016Sadrian{ 3609300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 3610300016Sadrian 3611300016Sadrian bool override = false; 3612300016Sadrian uint16_t chain = 0x33; 3613300016Sadrian 3614300016Sadrian if (nphy->txrx_chain == 0) { 3615300016Sadrian chain = 0x11; 3616300016Sadrian override = true; 3617300016Sadrian } else if (nphy->txrx_chain == 1) { 3618300016Sadrian chain = 0x22; 3619300016Sadrian override = true; 3620300016Sadrian } 3621300016Sadrian 3622300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, 3623300016Sadrian ~(BWN_NPHY_RFSEQCA_TXEN | BWN_NPHY_RFSEQCA_RXEN), 3624300016Sadrian chain); 3625300016Sadrian 3626300016Sadrian if (override) 3627300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFSEQMODE, 3628300016Sadrian BWN_NPHY_RFSEQMODE_CAOVER); 3629300016Sadrian else 3630300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFSEQMODE, 3631300016Sadrian ~BWN_NPHY_RFSEQMODE_CAOVER); 3632300016Sadrian} 3633300016Sadrian 3634300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */ 3635300016Sadrianstatic void bwn_nphy_stop_playback(struct bwn_mac *mac) 3636300016Sadrian{ 3637300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 3638300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 3639300016Sadrian uint16_t tmp; 3640300016Sadrian 3641300016Sadrian if (nphy->hang_avoid) 3642300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 1); 3643300016Sadrian 3644300016Sadrian tmp = BWN_PHY_READ(mac, BWN_NPHY_SAMP_STAT); 3645300016Sadrian if (tmp & 0x1) 3646300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_SAMP_CMD, BWN_NPHY_SAMP_CMD_STOP); 3647300016Sadrian else if (tmp & 0x2) 3648300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0x7FFF); 3649300016Sadrian 3650300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_SAMP_CMD, ~0x0004); 3651300016Sadrian 3652300016Sadrian if (nphy->bb_mult_save & 0x80000000) { 3653300016Sadrian tmp = nphy->bb_mult_save & 0xFFFF; 3654300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(15, 87), tmp); 3655300016Sadrian nphy->bb_mult_save = 0; 3656300016Sadrian } 3657300016Sadrian 3658300016Sadrian if (phy->rev >= 7 && nphy->lpf_bw_overrode_for_sample_play) { 3659300016Sadrian if (phy->rev >= 19) 3660300016Sadrian bwn_nphy_rf_ctl_override_rev19(mac, 0x80, 0, 0, true, 3661300016Sadrian 1); 3662300016Sadrian else 3663300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x80, 0, 0, true, 1); 3664300016Sadrian nphy->lpf_bw_overrode_for_sample_play = false; 3665300016Sadrian } 3666300016Sadrian 3667300016Sadrian if (nphy->hang_avoid) 3668300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 0); 3669300016Sadrian} 3670300016Sadrian 3671300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IqCalGainParams */ 3672300016Sadrianstatic void bwn_nphy_iq_cal_gain_params(struct bwn_mac *mac, uint16_t core, 3673300016Sadrian struct bwn_nphy_txgains target, 3674300016Sadrian struct bwn_nphy_iqcal_params *params) 3675300016Sadrian{ 3676300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 3677300016Sadrian int i, j, indx; 3678300016Sadrian uint16_t gain; 3679300016Sadrian 3680300016Sadrian if (mac->mac_phy.rev >= 3) { 3681300016Sadrian params->tx_lpf = target.tx_lpf[core]; /* Rev 7+ */ 3682300016Sadrian params->txgm = target.txgm[core]; 3683300016Sadrian params->pga = target.pga[core]; 3684300016Sadrian params->pad = target.pad[core]; 3685300016Sadrian params->ipa = target.ipa[core]; 3686300016Sadrian if (phy->rev >= 19) { 3687300016Sadrian /* TODO */ 3688300016Sadrian } else if (phy->rev >= 7) { 3689300016Sadrian params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 3) | (params->ipa) | (params->tx_lpf << 15); 3690300016Sadrian } else { 3691300016Sadrian params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 4) | (params->ipa); 3692300016Sadrian } 3693300016Sadrian for (j = 0; j < 5; j++) 3694300016Sadrian params->ncorr[j] = 0x79; 3695300016Sadrian } else { 3696300016Sadrian gain = (target.pad[core]) | (target.pga[core] << 4) | 3697300016Sadrian (target.txgm[core] << 8); 3698300016Sadrian 3699300016Sadrian indx = (bwn_current_band(mac) == BWN_BAND_5G) ? 3700300016Sadrian 1 : 0; 3701300016Sadrian for (i = 0; i < 9; i++) 3702300016Sadrian if (tbl_iqcal_gainparams[indx][i][0] == gain) 3703300016Sadrian break; 3704300016Sadrian i = min(i, 8); 3705300016Sadrian 3706300016Sadrian params->txgm = tbl_iqcal_gainparams[indx][i][1]; 3707300016Sadrian params->pga = tbl_iqcal_gainparams[indx][i][2]; 3708300016Sadrian params->pad = tbl_iqcal_gainparams[indx][i][3]; 3709300016Sadrian params->cal_gain = (params->txgm << 7) | (params->pga << 4) | 3710300016Sadrian (params->pad << 2); 3711300016Sadrian for (j = 0; j < 4; j++) 3712300016Sadrian params->ncorr[j] = tbl_iqcal_gainparams[indx][i][4 + j]; 3713300016Sadrian } 3714300016Sadrian} 3715300016Sadrian 3716300016Sadrian/************************************************** 3717300016Sadrian * Tx and Rx 3718300016Sadrian **************************************************/ 3719300016Sadrian 3720300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */ 3721300016Sadrianstatic void bwn_nphy_tx_power_ctrl(struct bwn_mac *mac, bool enable) 3722300016Sadrian{ 3723300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 3724300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 3725300016Sadrian uint8_t i; 3726300016Sadrian uint16_t bmask, val, tmp; 3727300016Sadrian bwn_band_t band = bwn_current_band(mac); 3728300016Sadrian 3729300016Sadrian if (nphy->hang_avoid) 3730300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 1); 3731300016Sadrian 3732300016Sadrian nphy->txpwrctrl = enable; 3733300016Sadrian if (!enable) { 3734300016Sadrian if (mac->mac_phy.rev >= 3 && 3735300016Sadrian (BWN_PHY_READ(mac, BWN_NPHY_TXPCTL_CMD) & 3736300016Sadrian (BWN_NPHY_TXPCTL_CMD_COEFF | 3737300016Sadrian BWN_NPHY_TXPCTL_CMD_HWPCTLEN | 3738300016Sadrian BWN_NPHY_TXPCTL_CMD_PCTLEN))) { 3739300016Sadrian /* We disable enabled TX pwr ctl, save it's state */ 3740300016Sadrian nphy->tx_pwr_idx[0] = BWN_PHY_READ(mac, 3741300016Sadrian BWN_NPHY_C1_TXPCTL_STAT) & 0x7f; 3742300016Sadrian nphy->tx_pwr_idx[1] = BWN_PHY_READ(mac, 3743300016Sadrian BWN_NPHY_C2_TXPCTL_STAT) & 0x7f; 3744300016Sadrian } 3745300016Sadrian 3746300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x6840); 3747300016Sadrian for (i = 0; i < 84; i++) 3748300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0); 3749300016Sadrian 3750300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x6C40); 3751300016Sadrian for (i = 0; i < 84; i++) 3752300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0); 3753300016Sadrian 3754300016Sadrian tmp = BWN_NPHY_TXPCTL_CMD_COEFF | BWN_NPHY_TXPCTL_CMD_HWPCTLEN; 3755300016Sadrian if (mac->mac_phy.rev >= 3) 3756300016Sadrian tmp |= BWN_NPHY_TXPCTL_CMD_PCTLEN; 3757300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_TXPCTL_CMD, ~tmp); 3758300016Sadrian 3759300016Sadrian if (mac->mac_phy.rev >= 3) { 3760300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER1, 0x0100); 3761300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x0100); 3762300016Sadrian } else { 3763300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x4000); 3764300016Sadrian } 3765300016Sadrian 3766300016Sadrian if (mac->mac_phy.rev == 2) 3767300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_BPHY_CTL3, 3768300016Sadrian ~BWN_NPHY_BPHY_CTL3_SCALE, 0x53); 3769300016Sadrian else if (mac->mac_phy.rev < 2) 3770300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_BPHY_CTL3, 3771300016Sadrian ~BWN_NPHY_BPHY_CTL3_SCALE, 0x5A); 3772300016Sadrian 3773300016Sadrian if (mac->mac_phy.rev < 2 && bwn_is_40mhz(mac)) 3774300016Sadrian bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN); 3775300016Sadrian } else { 3776300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(26, 64), 84, 3777300016Sadrian nphy->adj_pwr_tbl); 3778300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(27, 64), 84, 3779300016Sadrian nphy->adj_pwr_tbl); 3780300016Sadrian 3781300016Sadrian bmask = BWN_NPHY_TXPCTL_CMD_COEFF | 3782300016Sadrian BWN_NPHY_TXPCTL_CMD_HWPCTLEN; 3783300016Sadrian /* wl does useless check for "enable" param here */ 3784300016Sadrian val = BWN_NPHY_TXPCTL_CMD_COEFF | BWN_NPHY_TXPCTL_CMD_HWPCTLEN; 3785300016Sadrian if (mac->mac_phy.rev >= 3) { 3786300016Sadrian bmask |= BWN_NPHY_TXPCTL_CMD_PCTLEN; 3787300016Sadrian if (val) 3788300016Sadrian val |= BWN_NPHY_TXPCTL_CMD_PCTLEN; 3789300016Sadrian } 3790300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD, ~(bmask), val); 3791300016Sadrian 3792300016Sadrian if (band == BWN_BAND_5G) { 3793300016Sadrian if (phy->rev >= 19) { 3794300016Sadrian /* TODO */ 3795300016Sadrian } else if (phy->rev >= 7) { 3796300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD, 3797300016Sadrian ~BWN_NPHY_TXPCTL_CMD_INIT, 3798300016Sadrian 0x32); 3799300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_INIT, 3800300016Sadrian ~BWN_NPHY_TXPCTL_INIT_PIDXI1, 3801300016Sadrian 0x32); 3802300016Sadrian } else { 3803300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD, 3804300016Sadrian ~BWN_NPHY_TXPCTL_CMD_INIT, 3805300016Sadrian 0x64); 3806300016Sadrian if (phy->rev > 1) 3807300016Sadrian BWN_PHY_SETMASK(mac, 3808300016Sadrian BWN_NPHY_TXPCTL_INIT, 3809300016Sadrian ~BWN_NPHY_TXPCTL_INIT_PIDXI1, 3810300016Sadrian 0x64); 3811300016Sadrian } 3812300016Sadrian } 3813300016Sadrian 3814300016Sadrian if (mac->mac_phy.rev >= 3) { 3815300016Sadrian if (nphy->tx_pwr_idx[0] != 128 && 3816300016Sadrian nphy->tx_pwr_idx[1] != 128) { 3817300016Sadrian /* Recover TX pwr ctl state */ 3818300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD, 3819300016Sadrian ~BWN_NPHY_TXPCTL_CMD_INIT, 3820300016Sadrian nphy->tx_pwr_idx[0]); 3821300016Sadrian if (mac->mac_phy.rev > 1) 3822300016Sadrian BWN_PHY_SETMASK(mac, 3823300016Sadrian BWN_NPHY_TXPCTL_INIT, 3824300016Sadrian ~0xff, nphy->tx_pwr_idx[1]); 3825300016Sadrian } 3826300016Sadrian } 3827300016Sadrian 3828300016Sadrian if (phy->rev >= 7) { 3829300016Sadrian /* TODO */ 3830300016Sadrian } 3831300016Sadrian 3832300016Sadrian if (mac->mac_phy.rev >= 3) { 3833300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER1, ~0x100); 3834300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER, ~0x100); 3835300016Sadrian } else { 3836300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER, ~0x4000); 3837300016Sadrian } 3838300016Sadrian 3839300016Sadrian if (mac->mac_phy.rev == 2) 3840300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_BPHY_CTL3, ~0xFF, 0x3b); 3841300016Sadrian else if (mac->mac_phy.rev < 2) 3842300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_BPHY_CTL3, ~0xFF, 0x40); 3843300016Sadrian 3844300016Sadrian if (mac->mac_phy.rev < 2 && bwn_is_40mhz(mac)) 3845300016Sadrian bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_TSSI_RESET_PSM_WORKAROUN); 3846300016Sadrian 3847300016Sadrian if (bwn_nphy_ipa(mac)) { 3848300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN0, ~0x4); 3849300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN1, ~0x4); 3850300016Sadrian } 3851300016Sadrian } 3852300016Sadrian 3853300016Sadrian if (nphy->hang_avoid) 3854300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 0); 3855300016Sadrian} 3856300016Sadrian 3857300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrFix */ 3858300016Sadrianstatic void bwn_nphy_tx_power_fix(struct bwn_mac *mac) 3859300016Sadrian{ 3860300016Sadrian struct bwn_softc *sc = mac->mac_sc; 3861300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 3862300016Sadrian 3863300016Sadrian uint8_t txpi[2], bbmult, i; 3864300016Sadrian uint16_t tmp, radio_gain, dac_gain; 3865300016Sadrian uint16_t freq = bwn_get_centre_freq(mac); 3866300016Sadrian uint32_t txgain; 3867300016Sadrian /* uint32_t gaintbl; rev3+ */ 3868300016Sadrian 3869300016Sadrian if (nphy->hang_avoid) 3870300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 1); 3871300016Sadrian 3872300016Sadrian /* TODO: rev19+ */ 3873300016Sadrian if (mac->mac_phy.rev >= 7) { 3874300016Sadrian txpi[0] = txpi[1] = 30; 3875300016Sadrian } else if (mac->mac_phy.rev >= 3) { 3876300016Sadrian txpi[0] = 40; 3877300016Sadrian txpi[1] = 40; 3878300016Sadrian } else if (siba_sprom_get_rev(sc->sc_dev) < 4) { 3879300016Sadrian txpi[0] = 72; 3880300016Sadrian txpi[1] = 72; 3881300016Sadrian } else { 3882300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 3883300016Sadrian txpi[0] = siba_sprom_get_txpid_2g_0(sc->sc_dev); 3884300016Sadrian txpi[1] = siba_sprom_get_txpid_2g_1(sc->sc_dev); 3885300016Sadrian } else if (freq >= 4900 && freq < 5100) { 3886300016Sadrian txpi[0] = siba_sprom_get_txpid_5gl_0(sc->sc_dev); 3887300016Sadrian txpi[1] = siba_sprom_get_txpid_5gl_1(sc->sc_dev); 3888300016Sadrian } else if (freq >= 5100 && freq < 5500) { 3889300016Sadrian txpi[0] = siba_sprom_get_txpid_5g_0(sc->sc_dev); 3890300016Sadrian txpi[1] = siba_sprom_get_txpid_5g_1(sc->sc_dev); 3891300016Sadrian } else if (freq >= 5500) { 3892300016Sadrian txpi[0] = siba_sprom_get_txpid_5gh_0(sc->sc_dev); 3893300016Sadrian txpi[1] = siba_sprom_get_txpid_5gh_1(sc->sc_dev); 3894300016Sadrian } else { 3895300016Sadrian txpi[0] = 91; 3896300016Sadrian txpi[1] = 91; 3897300016Sadrian } 3898300016Sadrian } 3899300016Sadrian if (mac->mac_phy.rev < 7 && 3900300016Sadrian (txpi[0] < 40 || txpi[0] > 100 || txpi[1] < 40 || txpi[1] > 100)) 3901300016Sadrian txpi[0] = txpi[1] = 91; 3902300016Sadrian 3903300016Sadrian /* 3904300016Sadrian for (i = 0; i < 2; i++) { 3905300016Sadrian nphy->txpwrindex[i].index_internal = txpi[i]; 3906300016Sadrian nphy->txpwrindex[i].index_internal_save = txpi[i]; 3907300016Sadrian } 3908300016Sadrian */ 3909300016Sadrian 3910300016Sadrian for (i = 0; i < 2; i++) { 3911300016Sadrian const uint32_t *table = bwn_nphy_get_tx_gain_table(mac); 3912300016Sadrian 3913300016Sadrian if (!table) 3914300016Sadrian break; 3915300016Sadrian txgain = *(table + txpi[i]); 3916300016Sadrian 3917300016Sadrian if (mac->mac_phy.rev >= 3) 3918300016Sadrian radio_gain = (txgain >> 16) & 0x1FFFF; 3919300016Sadrian else 3920300016Sadrian radio_gain = (txgain >> 16) & 0x1FFF; 3921300016Sadrian 3922300016Sadrian if (mac->mac_phy.rev >= 7) 3923300016Sadrian dac_gain = (txgain >> 8) & 0x7; 3924300016Sadrian else 3925300016Sadrian dac_gain = (txgain >> 8) & 0x3F; 3926300016Sadrian bbmult = txgain & 0xFF; 3927300016Sadrian 3928300016Sadrian if (mac->mac_phy.rev >= 3) { 3929300016Sadrian if (i == 0) 3930300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER1, 0x0100); 3931300016Sadrian else 3932300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x0100); 3933300016Sadrian } else { 3934300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x4000); 3935300016Sadrian } 3936300016Sadrian 3937300016Sadrian if (i == 0) 3938300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_DACGAIN1, dac_gain); 3939300016Sadrian else 3940300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_DACGAIN2, dac_gain); 3941300016Sadrian 3942300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(0x7, 0x110 + i), radio_gain); 3943300016Sadrian 3944300016Sadrian tmp = bwn_ntab_read(mac, BWN_NTAB16(0xF, 0x57)); 3945300016Sadrian if (i == 0) 3946300016Sadrian tmp = (tmp & 0x00FF) | (bbmult << 8); 3947300016Sadrian else 3948300016Sadrian tmp = (tmp & 0xFF00) | bbmult; 3949300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(0xF, 0x57), tmp); 3950300016Sadrian 3951300016Sadrian if (bwn_nphy_ipa(mac)) { 3952300016Sadrian uint32_t tmp32; 3953300016Sadrian uint16_t reg = (i == 0) ? 3954300016Sadrian BWN_NPHY_PAPD_EN0 : BWN_NPHY_PAPD_EN1; 3955300016Sadrian tmp32 = bwn_ntab_read(mac, BWN_NTAB32(26 + i, 3956300016Sadrian 576 + txpi[i])); 3957300016Sadrian BWN_PHY_SETMASK(mac, reg, 0xE00F, (uint32_t) tmp32 << 4); 3958300016Sadrian BWN_PHY_SET(mac, reg, 0x4); 3959300016Sadrian } 3960300016Sadrian } 3961300016Sadrian 3962300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_BPHY_CTL2, ~BWN_NPHY_BPHY_CTL2_LUT); 3963300016Sadrian 3964300016Sadrian if (nphy->hang_avoid) 3965300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 0); 3966300016Sadrian} 3967300016Sadrian 3968300016Sadrianstatic void bwn_nphy_ipa_internal_tssi_setup(struct bwn_mac *mac) 3969300016Sadrian{ 3970300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 3971300016Sadrian 3972300016Sadrian uint8_t core; 3973300016Sadrian uint16_t r; /* routing */ 3974300016Sadrian 3975300016Sadrian if (phy->rev >= 19) { 3976300016Sadrian /* TODO */ 3977300016Sadrian } else if (phy->rev >= 7) { 3978300016Sadrian for (core = 0; core < 2; core++) { 3979300016Sadrian r = core ? 0x190 : 0x170; 3980300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 3981300016Sadrian BWN_RF_WRITE(mac, r + 0x5, 0x5); 3982300016Sadrian BWN_RF_WRITE(mac, r + 0x9, 0xE); 3983300016Sadrian if (phy->rev != 5) 3984300016Sadrian BWN_RF_WRITE(mac, r + 0xA, 0); 3985300016Sadrian if (phy->rev != 7) 3986300016Sadrian BWN_RF_WRITE(mac, r + 0xB, 1); 3987300016Sadrian else 3988300016Sadrian BWN_RF_WRITE(mac, r + 0xB, 0x31); 3989300016Sadrian } else { 3990300016Sadrian BWN_RF_WRITE(mac, r + 0x5, 0x9); 3991300016Sadrian BWN_RF_WRITE(mac, r + 0x9, 0xC); 3992300016Sadrian BWN_RF_WRITE(mac, r + 0xB, 0x0); 3993300016Sadrian if (phy->rev != 5) 3994300016Sadrian BWN_RF_WRITE(mac, r + 0xA, 1); 3995300016Sadrian else 3996300016Sadrian BWN_RF_WRITE(mac, r + 0xA, 0x31); 3997300016Sadrian } 3998300016Sadrian BWN_RF_WRITE(mac, r + 0x6, 0); 3999300016Sadrian BWN_RF_WRITE(mac, r + 0x7, 0); 4000300016Sadrian BWN_RF_WRITE(mac, r + 0x8, 3); 4001300016Sadrian BWN_RF_WRITE(mac, r + 0xC, 0); 4002300016Sadrian } 4003300016Sadrian } else { 4004300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 4005300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_RESERVED_ADDR31, 0x128); 4006300016Sadrian else 4007300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_RESERVED_ADDR31, 0x80); 4008300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_RESERVED_ADDR30, 0); 4009300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_GPIO_MASTER1, 0x29); 4010300016Sadrian 4011300016Sadrian for (core = 0; core < 2; core++) { 4012300016Sadrian r = core ? B2056_TX1 : B2056_TX0; 4013300016Sadrian 4014300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_IQCAL_VCM_HG, 0); 4015300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_IQCAL_IDAC, 0); 4016300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TSSI_VCM, 3); 4017300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TX_AMP_DET, 0); 4018300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TSSI_MISC1, 8); 4019300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TSSI_MISC2, 0); 4020300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TSSI_MISC3, 0); 4021300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 4022300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TX_SSI_MASTER, 4023300016Sadrian 0x5); 4024300016Sadrian if (phy->rev != 5) 4025300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TSSIA, 4026300016Sadrian 0x00); 4027300016Sadrian if (phy->rev >= 5) 4028300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TSSIG, 4029300016Sadrian 0x31); 4030300016Sadrian else 4031300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TSSIG, 4032300016Sadrian 0x11); 4033300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TX_SSI_MUX, 4034300016Sadrian 0xE); 4035300016Sadrian } else { 4036300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TX_SSI_MASTER, 4037300016Sadrian 0x9); 4038300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TSSIA, 0x31); 4039300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TSSIG, 0x0); 4040300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TX_SSI_MUX, 4041300016Sadrian 0xC); 4042300016Sadrian } 4043300016Sadrian } 4044300016Sadrian } 4045300016Sadrian} 4046300016Sadrian 4047300016Sadrian/* 4048300016Sadrian * Stop radio and transmit known signal. Then check received signal strength to 4049300016Sadrian * get TSSI (Transmit Signal Strength Indicator). 4050300016Sadrian * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlIdleTssi 4051300016Sadrian */ 4052300016Sadrianstatic void bwn_nphy_tx_power_ctl_idle_tssi(struct bwn_mac *mac) 4053300016Sadrian{ 4054300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 4055300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4056300016Sadrian 4057300016Sadrian uint32_t tmp; 4058300016Sadrian int32_t rssi[4] = { }; 4059300016Sadrian 4060300016Sadrian if (bwn_is_chan_passive(mac)) 4061300016Sadrian return; 4062300016Sadrian 4063300016Sadrian if (bwn_nphy_ipa(mac)) 4064300016Sadrian bwn_nphy_ipa_internal_tssi_setup(mac); 4065300016Sadrian 4066300016Sadrian if (phy->rev >= 19) 4067300016Sadrian bwn_nphy_rf_ctl_override_rev19(mac, 0x1000, 0, 3, false, 0); 4068300016Sadrian else if (phy->rev >= 7) 4069300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x1000, 0, 3, false, 0); 4070300016Sadrian else if (phy->rev >= 3) 4071300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x2000, 0, 3, false); 4072300016Sadrian 4073300016Sadrian bwn_nphy_stop_playback(mac); 4074300016Sadrian bwn_nphy_tx_tone(mac, 4000, 0, false, false, false); 4075300016Sadrian DELAY(20); 4076300016Sadrian tmp = bwn_nphy_poll_rssi(mac, N_RSSI_TSSI_2G, rssi, 1); 4077300016Sadrian bwn_nphy_stop_playback(mac); 4078300016Sadrian 4079300016Sadrian bwn_nphy_rssi_select(mac, 0, N_RSSI_W1); 4080300016Sadrian 4081300016Sadrian if (phy->rev >= 19) 4082300016Sadrian bwn_nphy_rf_ctl_override_rev19(mac, 0x1000, 0, 3, true, 0); 4083300016Sadrian else if (phy->rev >= 7) 4084300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x1000, 0, 3, true, 0); 4085300016Sadrian else if (phy->rev >= 3) 4086300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x2000, 0, 3, true); 4087300016Sadrian 4088300016Sadrian if (phy->rev >= 19) { 4089300016Sadrian /* TODO */ 4090300016Sadrian return; 4091300016Sadrian } else if (phy->rev >= 3) { 4092300016Sadrian nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 24) & 0xFF; 4093300016Sadrian nphy->pwr_ctl_info[1].idle_tssi_5g = (tmp >> 8) & 0xFF; 4094300016Sadrian } else { 4095300016Sadrian nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 16) & 0xFF; 4096300016Sadrian nphy->pwr_ctl_info[1].idle_tssi_5g = tmp & 0xFF; 4097300016Sadrian } 4098300016Sadrian nphy->pwr_ctl_info[0].idle_tssi_2g = (tmp >> 24) & 0xFF; 4099300016Sadrian nphy->pwr_ctl_info[1].idle_tssi_2g = (tmp >> 8) & 0xFF; 4100300016Sadrian} 4101300016Sadrian 4102300016Sadrian/* http://bcm-v4.sipsolutions.net/PHY/N/TxPwrLimitToTbl */ 4103300016Sadrianstatic void bwn_nphy_tx_prepare_adjusted_power_table(struct bwn_mac *mac) 4104300016Sadrian{ 4105300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4106300016Sadrian 4107300016Sadrian uint8_t idx, delta; 4108300016Sadrian uint8_t i, stf_mode; 4109300016Sadrian 4110300016Sadrian /* Array adj_pwr_tbl corresponds to the hardware table. It consists of 4111300016Sadrian * 21 groups, each containing 4 entries. 4112300016Sadrian * 4113300016Sadrian * First group has entries for CCK modulation. 4114300016Sadrian * The rest of groups has 1 entry per modulation (SISO, CDD, STBC, SDM). 4115300016Sadrian * 4116300016Sadrian * Group 0 is for CCK 4117300016Sadrian * Groups 1..4 use BPSK (group per coding rate) 4118300016Sadrian * Groups 5..8 use QPSK (group per coding rate) 4119300016Sadrian * Groups 9..12 use 16-QAM (group per coding rate) 4120300016Sadrian * Groups 13..16 use 64-QAM (group per coding rate) 4121300016Sadrian * Groups 17..20 are unknown 4122300016Sadrian */ 4123300016Sadrian 4124300016Sadrian for (i = 0; i < 4; i++) 4125300016Sadrian nphy->adj_pwr_tbl[i] = nphy->tx_power_offset[i]; 4126300016Sadrian 4127300016Sadrian for (stf_mode = 0; stf_mode < 4; stf_mode++) { 4128300016Sadrian delta = 0; 4129300016Sadrian switch (stf_mode) { 4130300016Sadrian case 0: 4131300016Sadrian if (bwn_is_40mhz(mac) && mac->mac_phy.rev >= 5) { 4132300016Sadrian idx = 68; 4133300016Sadrian } else { 4134300016Sadrian delta = 1; 4135300016Sadrian idx = bwn_is_40mhz(mac) ? 52 : 4; 4136300016Sadrian } 4137300016Sadrian break; 4138300016Sadrian case 1: 4139300016Sadrian idx = bwn_is_40mhz(mac) ? 76 : 28; 4140300016Sadrian break; 4141300016Sadrian case 2: 4142300016Sadrian idx = bwn_is_40mhz(mac) ? 84 : 36; 4143300016Sadrian break; 4144300016Sadrian case 3: 4145300016Sadrian idx = bwn_is_40mhz(mac) ? 92 : 44; 4146300016Sadrian break; 4147300016Sadrian } 4148300016Sadrian 4149300016Sadrian for (i = 0; i < 20; i++) { 4150300016Sadrian nphy->adj_pwr_tbl[4 + 4 * i + stf_mode] = 4151300016Sadrian nphy->tx_power_offset[idx]; 4152300016Sadrian if (i == 0) 4153300016Sadrian idx += delta; 4154300016Sadrian if (i == 14) 4155300016Sadrian idx += 1 - delta; 4156300016Sadrian if (i == 3 || i == 4 || i == 7 || i == 8 || i == 11 || 4157300016Sadrian i == 13) 4158300016Sadrian idx += 1; 4159300016Sadrian } 4160300016Sadrian } 4161300016Sadrian} 4162300016Sadrian 4163300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlSetup */ 4164300016Sadrianstatic void bwn_nphy_tx_power_ctl_setup(struct bwn_mac *mac) 4165300016Sadrian{ 4166300016Sadrian struct bwn_softc *sc = mac->mac_sc; 4167300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 4168300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4169300016Sadrian struct siba_sprom_core_pwr_info core_pwr_info[4]; 4170300016Sadrian int n; 4171300016Sadrian 4172300016Sadrian int16_t a1[2], b0[2], b1[2]; 4173300016Sadrian uint8_t idle[2]; 4174300016Sadrian uint8_t ppr_max; 4175300016Sadrian int8_t target[2]; 4176300016Sadrian int32_t num, den, pwr; 4177300016Sadrian uint32_t regval[64]; 4178300016Sadrian 4179300016Sadrian uint16_t freq = bwn_get_centre_freq(mac); 4180300016Sadrian uint16_t tmp; 4181300016Sadrian uint16_t r; /* routing */ 4182300016Sadrian uint8_t i, c; 4183300016Sadrian 4184300016Sadrian for (n = 0; n < 4; n++) { 4185300016Sadrian bzero(&core_pwr_info[n], sizeof(core_pwr_info[n])); 4186300016Sadrian if (siba_sprom_get_core_power_info(sc->sc_dev, n, 4187300016Sadrian &core_pwr_info[n]) != 0) { 4188300016Sadrian BWN_ERRPRINTF(mac->mac_sc, 4189300016Sadrian "%s: failed to get core_pwr_info for core %d\n", 4190300016Sadrian __func__, 4191300016Sadrian n); 4192300016Sadrian } 4193300016Sadrian } 4194300016Sadrian 4195300016Sadrian if (siba_get_revid(sc->sc_dev) == 11 || siba_get_revid(sc->sc_dev) == 12) { 4196300016Sadrian BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~0, 0x200000); 4197300016Sadrian BWN_READ_4(mac, BWN_MACCTL); 4198300016Sadrian DELAY(1); 4199300016Sadrian } 4200300016Sadrian 4201300016Sadrian if (nphy->hang_avoid) 4202300016Sadrian bwn_nphy_stay_in_carrier_search(mac, true); 4203300016Sadrian 4204300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_TSSIMODE, BWN_NPHY_TSSIMODE_EN); 4205300016Sadrian if (mac->mac_phy.rev >= 3) 4206300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_TXPCTL_CMD, 4207300016Sadrian ~BWN_NPHY_TXPCTL_CMD_PCTLEN & 0xFFFF); 4208300016Sadrian else 4209300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_TXPCTL_CMD, 4210300016Sadrian BWN_NPHY_TXPCTL_CMD_PCTLEN); 4211300016Sadrian 4212300016Sadrian if (siba_get_revid(sc->sc_dev) == 11 || siba_get_revid(sc->sc_dev) == 12) 4213300016Sadrian BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~0x200000, 0); 4214300016Sadrian 4215300016Sadrian /* 4216300016Sadrian * XXX TODO: see if those bandsbelow map to 5g-lo, 5g-mid, 5g-hi in 4217300016Sadrian * any way. 4218300016Sadrian */ 4219300016Sadrian if (siba_sprom_get_rev(sc->sc_dev) < 4) { 4220300016Sadrian idle[0] = nphy->pwr_ctl_info[0].idle_tssi_2g; 4221300016Sadrian idle[1] = nphy->pwr_ctl_info[1].idle_tssi_2g; 4222300016Sadrian target[0] = target[1] = 52; 4223300016Sadrian a1[0] = a1[1] = -424; 4224300016Sadrian b0[0] = b0[1] = 5612; 4225300016Sadrian b1[0] = b1[1] = -1393; 4226300016Sadrian } else { 4227300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 4228300016Sadrian for (c = 0; c < 2; c++) { 4229300016Sadrian idle[c] = nphy->pwr_ctl_info[c].idle_tssi_2g; 4230300016Sadrian target[c] = core_pwr_info[c].maxpwr_2g; 4231300016Sadrian a1[c] = core_pwr_info[c].pa_2g[0]; 4232300016Sadrian b0[c] = core_pwr_info[c].pa_2g[1]; 4233300016Sadrian b1[c] = core_pwr_info[c].pa_2g[2]; 4234300016Sadrian } 4235300016Sadrian } else if (freq >= 4900 && freq < 5100) { 4236300016Sadrian for (c = 0; c < 2; c++) { 4237300016Sadrian idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g; 4238300016Sadrian target[c] = core_pwr_info[c].maxpwr_5gl; 4239300016Sadrian a1[c] = core_pwr_info[c].pa_5gl[0]; 4240300016Sadrian b0[c] = core_pwr_info[c].pa_5gl[1]; 4241300016Sadrian b1[c] = core_pwr_info[c].pa_5gl[2]; 4242300016Sadrian } 4243300016Sadrian } else if (freq >= 5100 && freq < 5500) { 4244300016Sadrian for (c = 0; c < 2; c++) { 4245300016Sadrian idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g; 4246300016Sadrian target[c] = core_pwr_info[c].maxpwr_5g; 4247300016Sadrian a1[c] = core_pwr_info[c].pa_5g[0]; 4248300016Sadrian b0[c] = core_pwr_info[c].pa_5g[1]; 4249300016Sadrian b1[c] = core_pwr_info[c].pa_5g[2]; 4250300016Sadrian } 4251300016Sadrian } else if (freq >= 5500) { 4252300016Sadrian for (c = 0; c < 2; c++) { 4253300016Sadrian idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g; 4254300016Sadrian target[c] = core_pwr_info[c].maxpwr_5gh; 4255300016Sadrian a1[c] = core_pwr_info[c].pa_5gh[0]; 4256300016Sadrian b0[c] = core_pwr_info[c].pa_5gh[1]; 4257300016Sadrian b1[c] = core_pwr_info[c].pa_5gh[2]; 4258300016Sadrian } 4259300016Sadrian } else { 4260300016Sadrian idle[0] = nphy->pwr_ctl_info[0].idle_tssi_5g; 4261300016Sadrian idle[1] = nphy->pwr_ctl_info[1].idle_tssi_5g; 4262300016Sadrian target[0] = target[1] = 52; 4263300016Sadrian a1[0] = a1[1] = -424; 4264300016Sadrian b0[0] = b0[1] = 5612; 4265300016Sadrian b1[0] = b1[1] = -1393; 4266300016Sadrian } 4267300016Sadrian } 4268300016Sadrian 4269300016Sadrian ppr_max = bwn_ppr_get_max(mac, &nphy->tx_pwr_max_ppr); 4270300016Sadrian if (ppr_max) { 4271300016Sadrian target[0] = ppr_max; 4272300016Sadrian target[1] = ppr_max; 4273300016Sadrian } 4274300016Sadrian 4275300016Sadrian if (mac->mac_phy.rev >= 3) { 4276300016Sadrian if (siba_sprom_get_fem_2ghz_tssipos(sc->sc_dev)) 4277300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_TXPCTL_ITSSI, 0x4000); 4278300016Sadrian if (mac->mac_phy.rev >= 7) { 4279300016Sadrian for (c = 0; c < 2; c++) { 4280300016Sadrian r = c ? 0x190 : 0x170; 4281300016Sadrian if (bwn_nphy_ipa(mac)) 4282300016Sadrian BWN_RF_WRITE(mac, r + 0x9, (bwn_current_band(mac) == BWN_BAND_2G) ? 0xE : 0xC); 4283300016Sadrian } 4284300016Sadrian } else { 4285300016Sadrian if (bwn_nphy_ipa(mac)) { 4286300016Sadrian tmp = (bwn_current_band(mac) == BWN_BAND_5G) ? 0xC : 0xE; 4287300016Sadrian BWN_RF_WRITE(mac, 4288300016Sadrian B2056_TX0 | B2056_TX_TX_SSI_MUX, tmp); 4289300016Sadrian BWN_RF_WRITE(mac, 4290300016Sadrian B2056_TX1 | B2056_TX_TX_SSI_MUX, tmp); 4291300016Sadrian } else { 4292300016Sadrian BWN_RF_WRITE(mac, 4293300016Sadrian B2056_TX0 | B2056_TX_TX_SSI_MUX, 0x11); 4294300016Sadrian BWN_RF_WRITE(mac, 4295300016Sadrian B2056_TX1 | B2056_TX_TX_SSI_MUX, 0x11); 4296300016Sadrian } 4297300016Sadrian } 4298300016Sadrian } 4299300016Sadrian 4300300016Sadrian if (siba_get_revid(sc->sc_dev) == 11 || siba_get_revid(sc->sc_dev) == 12) { 4301300016Sadrian BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~0, 0x200000); 4302300016Sadrian BWN_READ_4(mac, BWN_MACCTL); 4303300016Sadrian DELAY(1); 4304300016Sadrian } 4305300016Sadrian 4306300016Sadrian if (phy->rev >= 19) { 4307300016Sadrian /* TODO */ 4308300016Sadrian } else if (phy->rev >= 7) { 4309300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD, 4310300016Sadrian ~BWN_NPHY_TXPCTL_CMD_INIT, 0x19); 4311300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_INIT, 4312300016Sadrian ~BWN_NPHY_TXPCTL_INIT_PIDXI1, 0x19); 4313300016Sadrian } else { 4314300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD, 4315300016Sadrian ~BWN_NPHY_TXPCTL_CMD_INIT, 0x40); 4316300016Sadrian if (mac->mac_phy.rev > 1) 4317300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_INIT, 4318300016Sadrian ~BWN_NPHY_TXPCTL_INIT_PIDXI1, 0x40); 4319300016Sadrian } 4320300016Sadrian 4321300016Sadrian if (siba_get_revid(sc->sc_dev) == 11 || siba_get_revid(sc->sc_dev) == 12) 4322300016Sadrian BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~0x200000, 0); 4323300016Sadrian 4324300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXPCTL_N, 4325300016Sadrian 0xF0 << BWN_NPHY_TXPCTL_N_TSSID_SHIFT | 4326300016Sadrian 3 << BWN_NPHY_TXPCTL_N_NPTIL2_SHIFT); 4327300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXPCTL_ITSSI, 4328300016Sadrian idle[0] << BWN_NPHY_TXPCTL_ITSSI_0_SHIFT | 4329300016Sadrian idle[1] << BWN_NPHY_TXPCTL_ITSSI_1_SHIFT | 4330300016Sadrian BWN_NPHY_TXPCTL_ITSSI_BINF); 4331300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXPCTL_TPWR, 4332300016Sadrian target[0] << BWN_NPHY_TXPCTL_TPWR_0_SHIFT | 4333300016Sadrian target[1] << BWN_NPHY_TXPCTL_TPWR_1_SHIFT); 4334300016Sadrian 4335300016Sadrian for (c = 0; c < 2; c++) { 4336300016Sadrian for (i = 0; i < 64; i++) { 4337300016Sadrian num = 8 * (16 * b0[c] + b1[c] * i); 4338300016Sadrian den = 32768 + a1[c] * i; 4339300016Sadrian pwr = max((4 * num + den / 2) / den, -8); 4340300016Sadrian if (mac->mac_phy.rev < 3 && (i <= (31 - idle[c] + 1))) 4341300016Sadrian pwr = max(pwr, target[c] + 1); 4342300016Sadrian regval[i] = pwr; 4343300016Sadrian } 4344300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB32(26 + c, 0), 64, regval); 4345300016Sadrian } 4346300016Sadrian 4347300016Sadrian bwn_nphy_tx_prepare_adjusted_power_table(mac); 4348300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(26, 64), 84, nphy->adj_pwr_tbl); 4349300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(27, 64), 84, nphy->adj_pwr_tbl); 4350300016Sadrian 4351300016Sadrian if (nphy->hang_avoid) 4352300016Sadrian bwn_nphy_stay_in_carrier_search(mac, false); 4353300016Sadrian} 4354300016Sadrian 4355300016Sadrianstatic void bwn_nphy_tx_gain_table_upload(struct bwn_mac *mac) 4356300016Sadrian{ 4357300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 4358300016Sadrian 4359300016Sadrian const uint32_t *table = NULL; 4360300016Sadrian uint32_t rfpwr_offset; 4361300016Sadrian uint8_t pga_gain, pad_gain; 4362300016Sadrian int i; 4363300016Sadrian const int16_t *rf_pwr_offset_table = NULL; 4364300016Sadrian 4365300016Sadrian table = bwn_nphy_get_tx_gain_table(mac); 4366300016Sadrian if (!table) 4367300016Sadrian return; 4368300016Sadrian 4369300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB32(26, 192), 128, table); 4370300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB32(27, 192), 128, table); 4371300016Sadrian 4372300016Sadrian if (phy->rev < 3) 4373300016Sadrian return; 4374300016Sadrian 4375300016Sadrian#if 0 4376300016Sadrian nphy->gmval = (table[0] >> 16) & 0x7000; 4377300016Sadrian#endif 4378300016Sadrian 4379300016Sadrian if (phy->rev >= 19) { 4380300016Sadrian return; 4381300016Sadrian } else if (phy->rev >= 7) { 4382300016Sadrian rf_pwr_offset_table = bwn_ntab_get_rf_pwr_offset_table(mac); 4383300016Sadrian if (!rf_pwr_offset_table) 4384300016Sadrian return; 4385300016Sadrian /* TODO: Enable this once we have gains configured */ 4386300016Sadrian return; 4387300016Sadrian } 4388300016Sadrian 4389300016Sadrian for (i = 0; i < 128; i++) { 4390300016Sadrian if (phy->rev >= 19) { 4391300016Sadrian /* TODO */ 4392300016Sadrian return; 4393300016Sadrian } else if (phy->rev >= 7) { 4394300016Sadrian pga_gain = (table[i] >> 24) & 0xf; 4395300016Sadrian pad_gain = (table[i] >> 19) & 0x1f; 4396300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 4397300016Sadrian rfpwr_offset = rf_pwr_offset_table[pad_gain]; 4398300016Sadrian else 4399300016Sadrian rfpwr_offset = rf_pwr_offset_table[pga_gain]; 4400300016Sadrian } else { 4401300016Sadrian pga_gain = (table[i] >> 24) & 0xF; 4402300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 4403300016Sadrian rfpwr_offset = bwn_ntab_papd_pga_gain_delta_ipa_2g[pga_gain]; 4404300016Sadrian else 4405300016Sadrian rfpwr_offset = 0; /* FIXME */ 4406300016Sadrian } 4407300016Sadrian 4408300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(26, 576 + i), rfpwr_offset); 4409300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(27, 576 + i), rfpwr_offset); 4410300016Sadrian } 4411300016Sadrian} 4412300016Sadrian 4413300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */ 4414300016Sadrianstatic void bwn_nphy_pa_override(struct bwn_mac *mac, bool enable) 4415300016Sadrian{ 4416300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4417300016Sadrian bwn_band_t band; 4418300016Sadrian uint16_t tmp; 4419300016Sadrian 4420300016Sadrian if (!enable) { 4421300016Sadrian nphy->rfctrl_intc1_save = BWN_PHY_READ(mac, 4422300016Sadrian BWN_NPHY_RFCTL_INTC1); 4423300016Sadrian nphy->rfctrl_intc2_save = BWN_PHY_READ(mac, 4424300016Sadrian BWN_NPHY_RFCTL_INTC2); 4425300016Sadrian band = bwn_current_band(mac); 4426300016Sadrian if (mac->mac_phy.rev >= 7) { 4427300016Sadrian tmp = 0x1480; 4428300016Sadrian } else if (mac->mac_phy.rev >= 3) { 4429300016Sadrian if (band == BWN_BAND_5G) 4430300016Sadrian tmp = 0x600; 4431300016Sadrian else 4432300016Sadrian tmp = 0x480; 4433300016Sadrian } else { 4434300016Sadrian if (band == BWN_BAND_5G) 4435300016Sadrian tmp = 0x180; 4436300016Sadrian else 4437300016Sadrian tmp = 0x120; 4438300016Sadrian } 4439300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, tmp); 4440300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, tmp); 4441300016Sadrian } else { 4442300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, 4443300016Sadrian nphy->rfctrl_intc1_save); 4444300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, 4445300016Sadrian nphy->rfctrl_intc2_save); 4446300016Sadrian } 4447300016Sadrian} 4448300016Sadrian 4449300016Sadrian/* 4450300016Sadrian * TX low-pass filter bandwidth setup 4451300016Sadrian * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw 4452300016Sadrian */ 4453300016Sadrianstatic void bwn_nphy_tx_lpf_bw(struct bwn_mac *mac) 4454300016Sadrian{ 4455300016Sadrian uint16_t tmp; 4456300016Sadrian 4457300016Sadrian if (mac->mac_phy.rev < 3 || mac->mac_phy.rev >= 7) 4458300016Sadrian return; 4459300016Sadrian 4460300016Sadrian if (bwn_nphy_ipa(mac)) 4461300016Sadrian tmp = bwn_is_40mhz(mac) ? 5 : 4; 4462300016Sadrian else 4463300016Sadrian tmp = bwn_is_40mhz(mac) ? 3 : 1; 4464300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B32S2, 4465300016Sadrian (tmp << 9) | (tmp << 6) | (tmp << 3) | tmp); 4466300016Sadrian 4467300016Sadrian if (bwn_nphy_ipa(mac)) { 4468300016Sadrian tmp = bwn_is_40mhz(mac) ? 4 : 1; 4469300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B1S2, 4470300016Sadrian (tmp << 9) | (tmp << 6) | (tmp << 3) | tmp); 4471300016Sadrian } 4472300016Sadrian} 4473300016Sadrian 4474300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */ 4475300016Sadrianstatic void bwn_nphy_rx_iq_est(struct bwn_mac *mac, struct bwn_nphy_iq_est *est, 4476300016Sadrian uint16_t samps, uint8_t time, bool wait) 4477300016Sadrian{ 4478300016Sadrian int i; 4479300016Sadrian uint16_t tmp; 4480300016Sadrian 4481300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_IQEST_SAMCNT, samps); 4482300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_IQEST_WT, ~BWN_NPHY_IQEST_WT_VAL, time); 4483300016Sadrian if (wait) 4484300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_IQEST_CMD, BWN_NPHY_IQEST_CMD_MODE); 4485300016Sadrian else 4486300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_IQEST_CMD, ~BWN_NPHY_IQEST_CMD_MODE); 4487300016Sadrian 4488300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_IQEST_CMD, BWN_NPHY_IQEST_CMD_START); 4489300016Sadrian 4490300016Sadrian for (i = 1000; i; i--) { 4491300016Sadrian tmp = BWN_PHY_READ(mac, BWN_NPHY_IQEST_CMD); 4492300016Sadrian if (!(tmp & BWN_NPHY_IQEST_CMD_START)) { 4493300016Sadrian est->i0_pwr = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_IPACC_HI0) << 16) | 4494300016Sadrian BWN_PHY_READ(mac, BWN_NPHY_IQEST_IPACC_LO0); 4495300016Sadrian est->q0_pwr = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_QPACC_HI0) << 16) | 4496300016Sadrian BWN_PHY_READ(mac, BWN_NPHY_IQEST_QPACC_LO0); 4497300016Sadrian est->iq0_prod = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_IQACC_HI0) << 16) | 4498300016Sadrian BWN_PHY_READ(mac, BWN_NPHY_IQEST_IQACC_LO0); 4499300016Sadrian 4500300016Sadrian est->i1_pwr = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_IPACC_HI1) << 16) | 4501300016Sadrian BWN_PHY_READ(mac, BWN_NPHY_IQEST_IPACC_LO1); 4502300016Sadrian est->q1_pwr = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_QPACC_HI1) << 16) | 4503300016Sadrian BWN_PHY_READ(mac, BWN_NPHY_IQEST_QPACC_LO1); 4504300016Sadrian est->iq1_prod = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_IQACC_HI1) << 16) | 4505300016Sadrian BWN_PHY_READ(mac, BWN_NPHY_IQEST_IQACC_LO1); 4506300016Sadrian return; 4507300016Sadrian } 4508300016Sadrian DELAY(10); 4509300016Sadrian } 4510300016Sadrian memset(est, 0, sizeof(*est)); 4511300016Sadrian} 4512300016Sadrian 4513300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */ 4514300016Sadrianstatic void bwn_nphy_rx_iq_coeffs(struct bwn_mac *mac, bool write, 4515300016Sadrian struct bwn_phy_n_iq_comp *pcomp) 4516300016Sadrian{ 4517300016Sadrian if (write) { 4518300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_C1_RXIQ_COMPA0, pcomp->a0); 4519300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_C1_RXIQ_COMPB0, pcomp->b0); 4520300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_C2_RXIQ_COMPA1, pcomp->a1); 4521300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_C2_RXIQ_COMPB1, pcomp->b1); 4522300016Sadrian } else { 4523300016Sadrian pcomp->a0 = BWN_PHY_READ(mac, BWN_NPHY_C1_RXIQ_COMPA0); 4524300016Sadrian pcomp->b0 = BWN_PHY_READ(mac, BWN_NPHY_C1_RXIQ_COMPB0); 4525300016Sadrian pcomp->a1 = BWN_PHY_READ(mac, BWN_NPHY_C2_RXIQ_COMPA1); 4526300016Sadrian pcomp->b1 = BWN_PHY_READ(mac, BWN_NPHY_C2_RXIQ_COMPB1); 4527300016Sadrian } 4528300016Sadrian} 4529300016Sadrian 4530300016Sadrian#if 0 4531300016Sadrian/* Ready but not used anywhere */ 4532300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */ 4533300016Sadrianstatic void bwn_nphy_rx_cal_phy_cleanup(struct bwn_mac *mac, uint8_t core) 4534300016Sadrian{ 4535300016Sadrian uint16_t *regs = mac->mac_phy.phy_n->tx_rx_cal_phy_saveregs; 4536300016Sadrian 4537300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFSEQCA, regs[0]); 4538300016Sadrian if (core == 0) { 4539300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, regs[1]); 4540300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, regs[2]); 4541300016Sadrian } else { 4542300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, regs[1]); 4543300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, regs[2]); 4544300016Sadrian } 4545300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, regs[3]); 4546300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, regs[4]); 4547300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_RSSIO1, regs[5]); 4548300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_RSSIO2, regs[6]); 4549300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B1S1, regs[7]); 4550300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_OVER, regs[8]); 4551300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PAPD_EN0, regs[9]); 4552300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PAPD_EN1, regs[10]); 4553300016Sadrian} 4554300016Sadrian 4555300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhySetup */ 4556300016Sadrianstatic void bwn_nphy_rx_cal_phy_setup(struct bwn_mac *mac, uint8_t core) 4557300016Sadrian{ 4558300016Sadrian uint8_t rxval, txval; 4559300016Sadrian uint16_t *regs = mac->mac_phy.phy_n->tx_rx_cal_phy_saveregs; 4560300016Sadrian 4561300016Sadrian regs[0] = BWN_PHY_READ(mac, BWN_NPHY_RFSEQCA); 4562300016Sadrian if (core == 0) { 4563300016Sadrian regs[1] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C1); 4564300016Sadrian regs[2] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER1); 4565300016Sadrian } else { 4566300016Sadrian regs[1] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C2); 4567300016Sadrian regs[2] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER); 4568300016Sadrian } 4569300016Sadrian regs[3] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC1); 4570300016Sadrian regs[4] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC2); 4571300016Sadrian regs[5] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_RSSIO1); 4572300016Sadrian regs[6] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_RSSIO2); 4573300016Sadrian regs[7] = BWN_PHY_READ(mac, BWN_NPHY_TXF_40CO_B1S1); 4574300016Sadrian regs[8] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_OVER); 4575300016Sadrian regs[9] = BWN_PHY_READ(mac, BWN_NPHY_PAPD_EN0); 4576300016Sadrian regs[10] = BWN_PHY_READ(mac, BWN_NPHY_PAPD_EN1); 4577300016Sadrian 4578300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN0, ~0x0001); 4579300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN1, ~0x0001); 4580300016Sadrian 4581300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, 4582300016Sadrian ~BWN_NPHY_RFSEQCA_RXDIS & 0xFFFF, 4583300016Sadrian ((1 - core) << BWN_NPHY_RFSEQCA_RXDIS_SHIFT)); 4584300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, ~BWN_NPHY_RFSEQCA_TXEN, 4585300016Sadrian ((1 - core) << BWN_NPHY_RFSEQCA_TXEN_SHIFT)); 4586300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, ~BWN_NPHY_RFSEQCA_RXEN, 4587300016Sadrian (core << BWN_NPHY_RFSEQCA_RXEN_SHIFT)); 4588300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, ~BWN_NPHY_RFSEQCA_TXDIS, 4589300016Sadrian (core << BWN_NPHY_RFSEQCA_TXDIS_SHIFT)); 4590300016Sadrian 4591300016Sadrian if (core == 0) { 4592300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C1, ~0x0007); 4593300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER1, 0x0007); 4594300016Sadrian } else { 4595300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C2, ~0x0007); 4596300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x0007); 4597300016Sadrian } 4598300016Sadrian 4599300016Sadrian bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_PA, 0, 3); 4600300016Sadrian bwn_nphy_rf_ctl_override(mac, 8, 0, 3, false); 4601300016Sadrian bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RX2TX); 4602300016Sadrian 4603300016Sadrian if (core == 0) { 4604300016Sadrian rxval = 1; 4605300016Sadrian txval = 8; 4606300016Sadrian } else { 4607300016Sadrian rxval = 4; 4608300016Sadrian txval = 2; 4609300016Sadrian } 4610300016Sadrian bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_TRSW, rxval, 4611300016Sadrian core + 1); 4612300016Sadrian bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_TRSW, txval, 4613300016Sadrian 2 - core); 4614300016Sadrian} 4615300016Sadrian#endif 4616300016Sadrian 4617300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */ 4618300016Sadrianstatic void bwn_nphy_calc_rx_iq_comp(struct bwn_mac *mac, uint8_t mask) 4619300016Sadrian{ 4620300016Sadrian int i; 4621300016Sadrian int32_t iq; 4622300016Sadrian uint32_t ii; 4623300016Sadrian uint32_t qq; 4624300016Sadrian int iq_nbits, qq_nbits; 4625300016Sadrian int arsh, brsh; 4626300016Sadrian uint16_t tmp, a, b; 4627300016Sadrian 4628300016Sadrian struct bwn_nphy_iq_est est; 4629300016Sadrian struct bwn_phy_n_iq_comp old; 4630300016Sadrian struct bwn_phy_n_iq_comp new = { }; 4631300016Sadrian bool error = false; 4632300016Sadrian 4633300016Sadrian if (mask == 0) 4634300016Sadrian return; 4635300016Sadrian 4636300016Sadrian bwn_nphy_rx_iq_coeffs(mac, false, &old); 4637300016Sadrian bwn_nphy_rx_iq_coeffs(mac, true, &new); 4638300016Sadrian bwn_nphy_rx_iq_est(mac, &est, 0x4000, 32, false); 4639300016Sadrian new = old; 4640300016Sadrian 4641300016Sadrian for (i = 0; i < 2; i++) { 4642300016Sadrian if (i == 0 && (mask & 1)) { 4643300016Sadrian iq = est.iq0_prod; 4644300016Sadrian ii = est.i0_pwr; 4645300016Sadrian qq = est.q0_pwr; 4646300016Sadrian } else if (i == 1 && (mask & 2)) { 4647300016Sadrian iq = est.iq1_prod; 4648300016Sadrian ii = est.i1_pwr; 4649300016Sadrian qq = est.q1_pwr; 4650300016Sadrian } else { 4651300016Sadrian continue; 4652300016Sadrian } 4653300016Sadrian 4654300016Sadrian if (ii + qq < 2) { 4655300016Sadrian error = true; 4656300016Sadrian break; 4657300016Sadrian } 4658300016Sadrian 4659300016Sadrian iq_nbits = fls(abs(iq)); 4660300016Sadrian qq_nbits = fls(qq); 4661300016Sadrian 4662300016Sadrian arsh = iq_nbits - 20; 4663300016Sadrian if (arsh >= 0) { 4664300016Sadrian a = -((iq << (30 - iq_nbits)) + (ii >> (1 + arsh))); 4665300016Sadrian tmp = ii >> arsh; 4666300016Sadrian } else { 4667300016Sadrian a = -((iq << (30 - iq_nbits)) + (ii << (-1 - arsh))); 4668300016Sadrian tmp = ii << -arsh; 4669300016Sadrian } 4670300016Sadrian if (tmp == 0) { 4671300016Sadrian error = true; 4672300016Sadrian break; 4673300016Sadrian } 4674300016Sadrian a /= tmp; 4675300016Sadrian 4676300016Sadrian brsh = qq_nbits - 11; 4677300016Sadrian if (brsh >= 0) { 4678300016Sadrian b = (qq << (31 - qq_nbits)); 4679300016Sadrian tmp = ii >> brsh; 4680300016Sadrian } else { 4681300016Sadrian b = (qq << (31 - qq_nbits)); 4682300016Sadrian tmp = ii << -brsh; 4683300016Sadrian } 4684300016Sadrian if (tmp == 0) { 4685300016Sadrian error = true; 4686300016Sadrian break; 4687300016Sadrian } 4688300016Sadrian b = bwn_sqrt(mac, b / tmp - a * a) - (1 << 10); 4689300016Sadrian 4690300016Sadrian if (i == 0 && (mask & 0x1)) { 4691300016Sadrian if (mac->mac_phy.rev >= 3) { 4692300016Sadrian new.a0 = a & 0x3FF; 4693300016Sadrian new.b0 = b & 0x3FF; 4694300016Sadrian } else { 4695300016Sadrian new.a0 = b & 0x3FF; 4696300016Sadrian new.b0 = a & 0x3FF; 4697300016Sadrian } 4698300016Sadrian } else if (i == 1 && (mask & 0x2)) { 4699300016Sadrian if (mac->mac_phy.rev >= 3) { 4700300016Sadrian new.a1 = a & 0x3FF; 4701300016Sadrian new.b1 = b & 0x3FF; 4702300016Sadrian } else { 4703300016Sadrian new.a1 = b & 0x3FF; 4704300016Sadrian new.b1 = a & 0x3FF; 4705300016Sadrian } 4706300016Sadrian } 4707300016Sadrian } 4708300016Sadrian 4709300016Sadrian if (error) 4710300016Sadrian new = old; 4711300016Sadrian 4712300016Sadrian bwn_nphy_rx_iq_coeffs(mac, true, &new); 4713300016Sadrian} 4714300016Sadrian 4715300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */ 4716300016Sadrianstatic void bwn_nphy_tx_iq_workaround(struct bwn_mac *mac) 4717300016Sadrian{ 4718300016Sadrian uint16_t array[4]; 4719300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(0xF, 0x50), 4, array); 4720300016Sadrian 4721300016Sadrian bwn_shm_write_2(mac, BWN_SHARED, BWN_SHM_SH_NPHY_TXIQW0, array[0]); 4722300016Sadrian bwn_shm_write_2(mac, BWN_SHARED, BWN_SHM_SH_NPHY_TXIQW1, array[1]); 4723300016Sadrian bwn_shm_write_2(mac, BWN_SHARED, BWN_SHM_SH_NPHY_TXIQW2, array[2]); 4724300016Sadrian bwn_shm_write_2(mac, BWN_SHARED, BWN_SHM_SH_NPHY_TXIQW3, array[3]); 4725300016Sadrian} 4726300016Sadrian 4727300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SpurWar */ 4728300016Sadrianstatic void bwn_nphy_spur_workaround(struct bwn_mac *mac) 4729300016Sadrian{ 4730300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4731300016Sadrian 4732300016Sadrian uint8_t channel = bwn_get_chan(mac); 4733300016Sadrian int tone[2] = { 57, 58 }; 4734300016Sadrian uint32_t noise[2] = { 0x3FF, 0x3FF }; 4735300016Sadrian 4736300016Sadrian if (mac->mac_phy.rev < 3) { 4737300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "%s: phy rev %d out of range\n", 4738300016Sadrian __func__, 4739300016Sadrian mac->mac_phy.rev); 4740300016Sadrian } 4741300016Sadrian 4742300016Sadrian if (nphy->hang_avoid) 4743300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 1); 4744300016Sadrian 4745300016Sadrian if (nphy->gband_spurwar_en) { 4746300016Sadrian /* TODO: N PHY Adjust Analog Pfbw (7) */ 4747300016Sadrian if (channel == 11 && bwn_is_40mhz(mac)) 4748300016Sadrian ; /* TODO: N PHY Adjust Min Noise Var(2, tone, noise)*/ 4749300016Sadrian else 4750300016Sadrian ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/ 4751300016Sadrian /* TODO: N PHY Adjust CRS Min Power (0x1E) */ 4752300016Sadrian } 4753300016Sadrian 4754300016Sadrian if (nphy->aband_spurwar_en) { 4755300016Sadrian if (channel == 54) { 4756300016Sadrian tone[0] = 0x20; 4757300016Sadrian noise[0] = 0x25F; 4758300016Sadrian } else if (channel == 38 || channel == 102 || channel == 118) { 4759300016Sadrian if (0 /* FIXME */) { 4760300016Sadrian tone[0] = 0x20; 4761300016Sadrian noise[0] = 0x21F; 4762300016Sadrian } else { 4763300016Sadrian tone[0] = 0; 4764300016Sadrian noise[0] = 0; 4765300016Sadrian } 4766300016Sadrian } else if (channel == 134) { 4767300016Sadrian tone[0] = 0x20; 4768300016Sadrian noise[0] = 0x21F; 4769300016Sadrian } else if (channel == 151) { 4770300016Sadrian tone[0] = 0x10; 4771300016Sadrian noise[0] = 0x23F; 4772300016Sadrian } else if (channel == 153 || channel == 161) { 4773300016Sadrian tone[0] = 0x30; 4774300016Sadrian noise[0] = 0x23F; 4775300016Sadrian } else { 4776300016Sadrian tone[0] = 0; 4777300016Sadrian noise[0] = 0; 4778300016Sadrian } 4779300016Sadrian 4780300016Sadrian if (!tone[0] && !noise[0]) 4781300016Sadrian ; /* TODO: N PHY Adjust Min Noise Var(1, tone, noise)*/ 4782300016Sadrian else 4783300016Sadrian ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/ 4784300016Sadrian } 4785300016Sadrian 4786300016Sadrian if (nphy->hang_avoid) 4787300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 0); 4788300016Sadrian} 4789300016Sadrian 4790300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */ 4791300016Sadrianstatic void bwn_nphy_tx_pwr_ctrl_coef_setup(struct bwn_mac *mac) 4792300016Sadrian{ 4793300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4794300016Sadrian int i, j; 4795300016Sadrian uint32_t tmp; 4796300016Sadrian uint32_t cur_real, cur_imag, real_part, imag_part; 4797300016Sadrian 4798300016Sadrian uint16_t buffer[7]; 4799300016Sadrian 4800300016Sadrian if (nphy->hang_avoid) 4801300016Sadrian bwn_nphy_stay_in_carrier_search(mac, true); 4802300016Sadrian 4803300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 80), 7, buffer); 4804300016Sadrian 4805300016Sadrian for (i = 0; i < 2; i++) { 4806300016Sadrian tmp = ((buffer[i * 2] & 0x3FF) << 10) | 4807300016Sadrian (buffer[i * 2 + 1] & 0x3FF); 4808300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 4809300016Sadrian (((i + 26) << 10) | 320)); 4810300016Sadrian for (j = 0; j < 128; j++) { 4811300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATAHI, 4812300016Sadrian ((tmp >> 16) & 0xFFFF)); 4813300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 4814300016Sadrian (tmp & 0xFFFF)); 4815300016Sadrian } 4816300016Sadrian } 4817300016Sadrian 4818300016Sadrian for (i = 0; i < 2; i++) { 4819300016Sadrian tmp = buffer[5 + i]; 4820300016Sadrian real_part = (tmp >> 8) & 0xFF; 4821300016Sadrian imag_part = (tmp & 0xFF); 4822300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 4823300016Sadrian (((i + 26) << 10) | 448)); 4824300016Sadrian 4825300016Sadrian if (mac->mac_phy.rev >= 3) { 4826300016Sadrian cur_real = real_part; 4827300016Sadrian cur_imag = imag_part; 4828300016Sadrian tmp = ((cur_real & 0xFF) << 8) | (cur_imag & 0xFF); 4829300016Sadrian } 4830300016Sadrian 4831300016Sadrian for (j = 0; j < 128; j++) { 4832300016Sadrian if (mac->mac_phy.rev < 3) { 4833300016Sadrian cur_real = (real_part * loscale[j] + 128) >> 8; 4834300016Sadrian cur_imag = (imag_part * loscale[j] + 128) >> 8; 4835300016Sadrian tmp = ((cur_real & 0xFF) << 8) | 4836300016Sadrian (cur_imag & 0xFF); 4837300016Sadrian } 4838300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATAHI, 4839300016Sadrian ((tmp >> 16) & 0xFFFF)); 4840300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 4841300016Sadrian (tmp & 0xFFFF)); 4842300016Sadrian } 4843300016Sadrian } 4844300016Sadrian 4845300016Sadrian if (mac->mac_phy.rev >= 3) { 4846300016Sadrian bwn_shm_write_2(mac, BWN_SHARED, 4847300016Sadrian BWN_SHM_SH_NPHY_TXPWR_INDX0, 0xFFFF); 4848300016Sadrian bwn_shm_write_2(mac, BWN_SHARED, 4849300016Sadrian BWN_SHM_SH_NPHY_TXPWR_INDX1, 0xFFFF); 4850300016Sadrian } 4851300016Sadrian 4852300016Sadrian if (nphy->hang_avoid) 4853300016Sadrian bwn_nphy_stay_in_carrier_search(mac, false); 4854300016Sadrian} 4855300016Sadrian 4856300016Sadrian/* 4857300016Sadrian * Restore RSSI Calibration 4858300016Sadrian * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal 4859300016Sadrian */ 4860300016Sadrianstatic void bwn_nphy_restore_rssi_cal(struct bwn_mac *mac) 4861300016Sadrian{ 4862300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4863300016Sadrian 4864300016Sadrian uint16_t *rssical_radio_regs = NULL; 4865300016Sadrian uint16_t *rssical_phy_regs = NULL; 4866300016Sadrian 4867300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 4868300016Sadrian if (!nphy->rssical_chanspec_2G.center_freq) 4869300016Sadrian return; 4870300016Sadrian rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G; 4871300016Sadrian rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G; 4872300016Sadrian } else { 4873300016Sadrian if (!nphy->rssical_chanspec_5G.center_freq) 4874300016Sadrian return; 4875300016Sadrian rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G; 4876300016Sadrian rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; 4877300016Sadrian } 4878300016Sadrian 4879300016Sadrian if (mac->mac_phy.rev >= 19) { 4880300016Sadrian /* TODO */ 4881300016Sadrian } else if (mac->mac_phy.rev >= 7) { 4882300016Sadrian BWN_RF_SETMASK(mac, R2057_NB_MASTER_CORE0, ~R2057_VCM_MASK, 4883300016Sadrian rssical_radio_regs[0]); 4884300016Sadrian BWN_RF_SETMASK(mac, R2057_NB_MASTER_CORE1, ~R2057_VCM_MASK, 4885300016Sadrian rssical_radio_regs[1]); 4886300016Sadrian } else { 4887300016Sadrian BWN_RF_SETMASK(mac, B2056_RX0 | B2056_RX_RSSI_MISC, 0xE3, 4888300016Sadrian rssical_radio_regs[0]); 4889300016Sadrian BWN_RF_SETMASK(mac, B2056_RX1 | B2056_RX_RSSI_MISC, 0xE3, 4890300016Sadrian rssical_radio_regs[1]); 4891300016Sadrian } 4892300016Sadrian 4893300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_Z, rssical_phy_regs[0]); 4894300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Z, rssical_phy_regs[1]); 4895300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_Z, rssical_phy_regs[2]); 4896300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Z, rssical_phy_regs[3]); 4897300016Sadrian 4898300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_X, rssical_phy_regs[4]); 4899300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_X, rssical_phy_regs[5]); 4900300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_X, rssical_phy_regs[6]); 4901300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_X, rssical_phy_regs[7]); 4902300016Sadrian 4903300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_Y, rssical_phy_regs[8]); 4904300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Y, rssical_phy_regs[9]); 4905300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_Y, rssical_phy_regs[10]); 4906300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]); 4907300016Sadrian} 4908300016Sadrian 4909300016Sadrianstatic void bwn_nphy_tx_cal_radio_setup_rev19(struct bwn_mac *mac) 4910300016Sadrian{ 4911300016Sadrian /* TODO */ 4912300016Sadrian} 4913300016Sadrian 4914300016Sadrianstatic void bwn_nphy_tx_cal_radio_setup_rev7(struct bwn_mac *mac) 4915300016Sadrian{ 4916300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 4917300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4918300016Sadrian uint16_t *save = nphy->tx_rx_cal_radio_saveregs; 4919300016Sadrian int core, off; 4920300016Sadrian uint16_t r, tmp; 4921300016Sadrian 4922300016Sadrian for (core = 0; core < 2; core++) { 4923300016Sadrian r = core ? 0x20 : 0; 4924300016Sadrian off = core * 11; 4925300016Sadrian 4926300016Sadrian save[off + 0] = BWN_RF_READ(mac, r + R2057_TX0_TX_SSI_MASTER); 4927300016Sadrian save[off + 1] = BWN_RF_READ(mac, r + R2057_TX0_IQCAL_VCM_HG); 4928300016Sadrian save[off + 2] = BWN_RF_READ(mac, r + R2057_TX0_IQCAL_IDAC); 4929300016Sadrian save[off + 3] = BWN_RF_READ(mac, r + R2057_TX0_TSSI_VCM); 4930300016Sadrian save[off + 4] = 0; 4931300016Sadrian save[off + 5] = BWN_RF_READ(mac, r + R2057_TX0_TX_SSI_MUX); 4932300016Sadrian if (phy->rf_rev != 5) 4933300016Sadrian save[off + 6] = BWN_RF_READ(mac, r + R2057_TX0_TSSIA); 4934300016Sadrian save[off + 7] = BWN_RF_READ(mac, r + R2057_TX0_TSSIG); 4935300016Sadrian save[off + 8] = BWN_RF_READ(mac, r + R2057_TX0_TSSI_MISC1); 4936300016Sadrian 4937300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G) { 4938300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TX_SSI_MASTER, 0xA); 4939300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_IQCAL_VCM_HG, 0x43); 4940300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_IQCAL_IDAC, 0x55); 4941300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TSSI_VCM, 0); 4942300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TSSIG, 0); 4943300016Sadrian if (nphy->use_int_tx_iq_lo_cal) { 4944300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TX_SSI_MUX, 0x4); 4945300016Sadrian tmp = true ? 0x31 : 0x21; /* TODO */ 4946300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TSSIA, tmp); 4947300016Sadrian } 4948300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TSSI_MISC1, 0x00); 4949300016Sadrian } else { 4950300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TX_SSI_MASTER, 0x6); 4951300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_IQCAL_VCM_HG, 0x43); 4952300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_IQCAL_IDAC, 0x55); 4953300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TSSI_VCM, 0); 4954300016Sadrian 4955300016Sadrian if (phy->rf_rev != 5) 4956300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TSSIA, 0); 4957300016Sadrian if (nphy->use_int_tx_iq_lo_cal) { 4958300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TX_SSI_MUX, 0x6); 4959300016Sadrian tmp = true ? 0x31 : 0x21; /* TODO */ 4960300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TSSIG, tmp); 4961300016Sadrian } 4962300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TSSI_MISC1, 0); 4963300016Sadrian } 4964300016Sadrian } 4965300016Sadrian} 4966300016Sadrian 4967300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */ 4968300016Sadrianstatic void bwn_nphy_tx_cal_radio_setup(struct bwn_mac *mac) 4969300016Sadrian{ 4970300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 4971300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4972300016Sadrian uint16_t *save = nphy->tx_rx_cal_radio_saveregs; 4973300016Sadrian uint16_t tmp; 4974300016Sadrian uint8_t offset, i; 4975300016Sadrian 4976300016Sadrian if (phy->rev >= 19) { 4977300016Sadrian bwn_nphy_tx_cal_radio_setup_rev19(mac); 4978300016Sadrian } else if (phy->rev >= 7) { 4979300016Sadrian bwn_nphy_tx_cal_radio_setup_rev7(mac); 4980300016Sadrian } else if (phy->rev >= 3) { 4981300016Sadrian for (i = 0; i < 2; i++) { 4982300016Sadrian tmp = (i == 0) ? 0x2000 : 0x3000; 4983300016Sadrian offset = i * 11; 4984300016Sadrian 4985300016Sadrian save[offset + 0] = BWN_RF_READ(mac, B2055_CAL_RVARCTL); 4986300016Sadrian save[offset + 1] = BWN_RF_READ(mac, B2055_CAL_LPOCTL); 4987300016Sadrian save[offset + 2] = BWN_RF_READ(mac, B2055_CAL_TS); 4988300016Sadrian save[offset + 3] = BWN_RF_READ(mac, B2055_CAL_RCCALRTS); 4989300016Sadrian save[offset + 4] = BWN_RF_READ(mac, B2055_CAL_RCALRTS); 4990300016Sadrian save[offset + 5] = BWN_RF_READ(mac, B2055_PADDRV); 4991300016Sadrian save[offset + 6] = BWN_RF_READ(mac, B2055_XOCTL1); 4992300016Sadrian save[offset + 7] = BWN_RF_READ(mac, B2055_XOCTL2); 4993300016Sadrian save[offset + 8] = BWN_RF_READ(mac, B2055_XOREGUL); 4994300016Sadrian save[offset + 9] = BWN_RF_READ(mac, B2055_XOMISC); 4995300016Sadrian save[offset + 10] = BWN_RF_READ(mac, B2055_PLL_LFC1); 4996300016Sadrian 4997300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G) { 4998300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_CAL_RVARCTL, 0x0A); 4999300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_CAL_LPOCTL, 0x40); 5000300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_CAL_TS, 0x55); 5001300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_CAL_RCCALRTS, 0); 5002300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_CAL_RCALRTS, 0); 5003300016Sadrian if (nphy->ipa5g_on) { 5004300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_PADDRV, 4); 5005300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_XOCTL1, 1); 5006300016Sadrian } else { 5007300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_PADDRV, 0); 5008300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_XOCTL1, 0x2F); 5009300016Sadrian } 5010300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_XOCTL2, 0); 5011300016Sadrian } else { 5012300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_CAL_RVARCTL, 0x06); 5013300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_CAL_LPOCTL, 0x40); 5014300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_CAL_TS, 0x55); 5015300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_CAL_RCCALRTS, 0); 5016300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_CAL_RCALRTS, 0); 5017300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_XOCTL1, 0); 5018300016Sadrian if (nphy->ipa2g_on) { 5019300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_PADDRV, 6); 5020300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_XOCTL2, 5021300016Sadrian (mac->mac_phy.rev < 5) ? 0x11 : 0x01); 5022300016Sadrian } else { 5023300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_PADDRV, 0); 5024300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_XOCTL2, 0); 5025300016Sadrian } 5026300016Sadrian } 5027300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_XOREGUL, 0); 5028300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_XOMISC, 0); 5029300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_PLL_LFC1, 0); 5030300016Sadrian } 5031300016Sadrian } else { 5032300016Sadrian save[0] = BWN_RF_READ(mac, B2055_C1_TX_RF_IQCAL1); 5033300016Sadrian BWN_RF_WRITE(mac, B2055_C1_TX_RF_IQCAL1, 0x29); 5034300016Sadrian 5035300016Sadrian save[1] = BWN_RF_READ(mac, B2055_C1_TX_RF_IQCAL2); 5036300016Sadrian BWN_RF_WRITE(mac, B2055_C1_TX_RF_IQCAL2, 0x54); 5037300016Sadrian 5038300016Sadrian save[2] = BWN_RF_READ(mac, B2055_C2_TX_RF_IQCAL1); 5039300016Sadrian BWN_RF_WRITE(mac, B2055_C2_TX_RF_IQCAL1, 0x29); 5040300016Sadrian 5041300016Sadrian save[3] = BWN_RF_READ(mac, B2055_C2_TX_RF_IQCAL2); 5042300016Sadrian BWN_RF_WRITE(mac, B2055_C2_TX_RF_IQCAL2, 0x54); 5043300016Sadrian 5044300016Sadrian save[3] = BWN_RF_READ(mac, B2055_C1_PWRDET_RXTX); 5045300016Sadrian save[4] = BWN_RF_READ(mac, B2055_C2_PWRDET_RXTX); 5046300016Sadrian 5047300016Sadrian if (!(BWN_PHY_READ(mac, BWN_NPHY_BANDCTL) & 5048300016Sadrian BWN_NPHY_BANDCTL_5GHZ)) { 5049300016Sadrian BWN_RF_WRITE(mac, B2055_C1_PWRDET_RXTX, 0x04); 5050300016Sadrian BWN_RF_WRITE(mac, B2055_C2_PWRDET_RXTX, 0x04); 5051300016Sadrian } else { 5052300016Sadrian BWN_RF_WRITE(mac, B2055_C1_PWRDET_RXTX, 0x20); 5053300016Sadrian BWN_RF_WRITE(mac, B2055_C2_PWRDET_RXTX, 0x20); 5054300016Sadrian } 5055300016Sadrian 5056300016Sadrian if (mac->mac_phy.rev < 2) { 5057300016Sadrian BWN_RF_SET(mac, B2055_C1_TX_BB_MXGM, 0x20); 5058300016Sadrian BWN_RF_SET(mac, B2055_C2_TX_BB_MXGM, 0x20); 5059300016Sadrian } else { 5060300016Sadrian BWN_RF_MASK(mac, B2055_C1_TX_BB_MXGM, ~0x20); 5061300016Sadrian BWN_RF_MASK(mac, B2055_C2_TX_BB_MXGM, ~0x20); 5062300016Sadrian } 5063300016Sadrian } 5064300016Sadrian} 5065300016Sadrian 5066300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */ 5067300016Sadrianstatic void bwn_nphy_update_tx_cal_ladder(struct bwn_mac *mac, uint16_t core) 5068300016Sadrian{ 5069300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5070300016Sadrian int i; 5071300016Sadrian uint16_t scale, entry; 5072300016Sadrian 5073300016Sadrian uint16_t tmp = nphy->txcal_bbmult; 5074300016Sadrian if (core == 0) 5075300016Sadrian tmp >>= 8; 5076300016Sadrian tmp &= 0xff; 5077300016Sadrian 5078300016Sadrian for (i = 0; i < 18; i++) { 5079300016Sadrian scale = (ladder_lo[i].percent * tmp) / 100; 5080300016Sadrian entry = ((scale & 0xFF) << 8) | ladder_lo[i].g_env; 5081300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(15, i), entry); 5082300016Sadrian 5083300016Sadrian scale = (ladder_iq[i].percent * tmp) / 100; 5084300016Sadrian entry = ((scale & 0xFF) << 8) | ladder_iq[i].g_env; 5085300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(15, i + 32), entry); 5086300016Sadrian } 5087300016Sadrian} 5088300016Sadrian 5089300016Sadrianstatic void bwn_nphy_pa_set_tx_dig_filter(struct bwn_mac *mac, uint16_t offset, 5090300016Sadrian const int16_t *filter) 5091300016Sadrian{ 5092300016Sadrian int i; 5093300016Sadrian 5094300016Sadrian offset = BWN_PHY_N(offset); 5095300016Sadrian 5096300016Sadrian for (i = 0; i < 15; i++, offset++) 5097300016Sadrian BWN_PHY_WRITE(mac, offset, filter[i]); 5098300016Sadrian} 5099300016Sadrian 5100300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */ 5101300016Sadrianstatic void bwn_nphy_ext_pa_set_tx_dig_filters(struct bwn_mac *mac) 5102300016Sadrian{ 5103300016Sadrian bwn_nphy_pa_set_tx_dig_filter(mac, 0x2C5, 5104300016Sadrian tbl_tx_filter_coef_rev4[2]); 5105300016Sadrian} 5106300016Sadrian 5107300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */ 5108300016Sadrianstatic void bwn_nphy_int_pa_set_tx_dig_filters(struct bwn_mac *mac) 5109300016Sadrian{ 5110300016Sadrian /* BWN_NPHY_TXF_20CO_S0A1, BWN_NPHY_TXF_40CO_S0A1, unknown */ 5111300016Sadrian static const uint16_t offset[] = { 0x186, 0x195, 0x2C5 }; 5112300016Sadrian static const int16_t dig_filter_phy_rev16[] = { 5113300016Sadrian -375, 136, -407, 208, -1527, 5114300016Sadrian 956, 93, 186, 93, 230, 5115300016Sadrian -44, 230, 201, -191, 201, 5116300016Sadrian }; 5117300016Sadrian int i; 5118300016Sadrian 5119300016Sadrian for (i = 0; i < 3; i++) 5120300016Sadrian bwn_nphy_pa_set_tx_dig_filter(mac, offset[i], 5121300016Sadrian tbl_tx_filter_coef_rev4[i]); 5122300016Sadrian 5123300016Sadrian /* Verified with BCM43227 and BCM43228 */ 5124300016Sadrian if (mac->mac_phy.rev == 16) 5125300016Sadrian bwn_nphy_pa_set_tx_dig_filter(mac, 0x186, dig_filter_phy_rev16); 5126300016Sadrian 5127300016Sadrian /* Verified with BCM43131 and BCM43217 */ 5128300016Sadrian if (mac->mac_phy.rev == 17) { 5129300016Sadrian bwn_nphy_pa_set_tx_dig_filter(mac, 0x186, dig_filter_phy_rev16); 5130300016Sadrian bwn_nphy_pa_set_tx_dig_filter(mac, 0x195, 5131300016Sadrian tbl_tx_filter_coef_rev4[1]); 5132300016Sadrian } 5133300016Sadrian 5134300016Sadrian if (bwn_is_40mhz(mac)) { 5135300016Sadrian bwn_nphy_pa_set_tx_dig_filter(mac, 0x186, 5136300016Sadrian tbl_tx_filter_coef_rev4[3]); 5137300016Sadrian } else { 5138300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G) 5139300016Sadrian bwn_nphy_pa_set_tx_dig_filter(mac, 0x186, 5140300016Sadrian tbl_tx_filter_coef_rev4[5]); 5141300016Sadrian if (bwn_get_chan(mac) == 14) 5142300016Sadrian bwn_nphy_pa_set_tx_dig_filter(mac, 0x186, 5143300016Sadrian tbl_tx_filter_coef_rev4[6]); 5144300016Sadrian } 5145300016Sadrian} 5146300016Sadrian 5147300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */ 5148300016Sadrianstatic struct bwn_nphy_txgains bwn_nphy_get_tx_gains(struct bwn_mac *mac) 5149300016Sadrian{ 5150300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5151300016Sadrian 5152300016Sadrian uint16_t curr_gain[2]; 5153300016Sadrian struct bwn_nphy_txgains target; 5154300016Sadrian const uint32_t *table = NULL; 5155300016Sadrian 5156300016Sadrian if (!nphy->txpwrctrl) { 5157300016Sadrian int i; 5158300016Sadrian 5159300016Sadrian if (nphy->hang_avoid) 5160300016Sadrian bwn_nphy_stay_in_carrier_search(mac, true); 5161300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(7, 0x110), 2, curr_gain); 5162300016Sadrian if (nphy->hang_avoid) 5163300016Sadrian bwn_nphy_stay_in_carrier_search(mac, false); 5164300016Sadrian 5165300016Sadrian for (i = 0; i < 2; ++i) { 5166300016Sadrian if (mac->mac_phy.rev >= 7) { 5167300016Sadrian target.ipa[i] = curr_gain[i] & 0x0007; 5168300016Sadrian target.pad[i] = (curr_gain[i] & 0x00F8) >> 3; 5169300016Sadrian target.pga[i] = (curr_gain[i] & 0x0F00) >> 8; 5170300016Sadrian target.txgm[i] = (curr_gain[i] & 0x7000) >> 12; 5171300016Sadrian target.tx_lpf[i] = (curr_gain[i] & 0x8000) >> 15; 5172300016Sadrian } else if (mac->mac_phy.rev >= 3) { 5173300016Sadrian target.ipa[i] = curr_gain[i] & 0x000F; 5174300016Sadrian target.pad[i] = (curr_gain[i] & 0x00F0) >> 4; 5175300016Sadrian target.pga[i] = (curr_gain[i] & 0x0F00) >> 8; 5176300016Sadrian target.txgm[i] = (curr_gain[i] & 0x7000) >> 12; 5177300016Sadrian } else { 5178300016Sadrian target.ipa[i] = curr_gain[i] & 0x0003; 5179300016Sadrian target.pad[i] = (curr_gain[i] & 0x000C) >> 2; 5180300016Sadrian target.pga[i] = (curr_gain[i] & 0x0070) >> 4; 5181300016Sadrian target.txgm[i] = (curr_gain[i] & 0x0380) >> 7; 5182300016Sadrian } 5183300016Sadrian } 5184300016Sadrian } else { 5185300016Sadrian int i; 5186300016Sadrian uint16_t index[2]; 5187300016Sadrian index[0] = (BWN_PHY_READ(mac, BWN_NPHY_C1_TXPCTL_STAT) & 5188300016Sadrian BWN_NPHY_TXPCTL_STAT_BIDX) >> 5189300016Sadrian BWN_NPHY_TXPCTL_STAT_BIDX_SHIFT; 5190300016Sadrian index[1] = (BWN_PHY_READ(mac, BWN_NPHY_C2_TXPCTL_STAT) & 5191300016Sadrian BWN_NPHY_TXPCTL_STAT_BIDX) >> 5192300016Sadrian BWN_NPHY_TXPCTL_STAT_BIDX_SHIFT; 5193300016Sadrian 5194300016Sadrian for (i = 0; i < 2; ++i) { 5195300016Sadrian table = bwn_nphy_get_tx_gain_table(mac); 5196300016Sadrian if (!table) 5197300016Sadrian break; 5198300016Sadrian 5199300016Sadrian if (mac->mac_phy.rev >= 7) { 5200300016Sadrian target.ipa[i] = (table[index[i]] >> 16) & 0x7; 5201300016Sadrian target.pad[i] = (table[index[i]] >> 19) & 0x1F; 5202300016Sadrian target.pga[i] = (table[index[i]] >> 24) & 0xF; 5203300016Sadrian target.txgm[i] = (table[index[i]] >> 28) & 0x7; 5204300016Sadrian target.tx_lpf[i] = (table[index[i]] >> 31) & 0x1; 5205300016Sadrian } else if (mac->mac_phy.rev >= 3) { 5206300016Sadrian target.ipa[i] = (table[index[i]] >> 16) & 0xF; 5207300016Sadrian target.pad[i] = (table[index[i]] >> 20) & 0xF; 5208300016Sadrian target.pga[i] = (table[index[i]] >> 24) & 0xF; 5209300016Sadrian target.txgm[i] = (table[index[i]] >> 28) & 0xF; 5210300016Sadrian } else { 5211300016Sadrian target.ipa[i] = (table[index[i]] >> 16) & 0x3; 5212300016Sadrian target.pad[i] = (table[index[i]] >> 18) & 0x3; 5213300016Sadrian target.pga[i] = (table[index[i]] >> 20) & 0x7; 5214300016Sadrian target.txgm[i] = (table[index[i]] >> 23) & 0x7; 5215300016Sadrian } 5216300016Sadrian } 5217300016Sadrian } 5218300016Sadrian 5219300016Sadrian return target; 5220300016Sadrian} 5221300016Sadrian 5222300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhyCleanup */ 5223300016Sadrianstatic void bwn_nphy_tx_cal_phy_cleanup(struct bwn_mac *mac) 5224300016Sadrian{ 5225300016Sadrian uint16_t *regs = mac->mac_phy.phy_n->tx_rx_cal_phy_saveregs; 5226300016Sadrian 5227300016Sadrian if (mac->mac_phy.rev >= 3) { 5228300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, regs[0]); 5229300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, regs[1]); 5230300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, regs[2]); 5231300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, regs[3]); 5232300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_BBCFG, regs[4]); 5233300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 3), regs[5]); 5234300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 19), regs[6]); 5235300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, regs[7]); 5236300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, regs[8]); 5237300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PAPD_EN0, regs[9]); 5238300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PAPD_EN1, regs[10]); 5239300016Sadrian bwn_nphy_reset_cca(mac); 5240300016Sadrian } else { 5241300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C1, 0x0FFF, regs[0]); 5242300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C2, 0x0FFF, regs[1]); 5243300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, regs[2]); 5244300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 2), regs[3]); 5245300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 18), regs[4]); 5246300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, regs[5]); 5247300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, regs[6]); 5248300016Sadrian } 5249300016Sadrian} 5250300016Sadrian 5251300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */ 5252300016Sadrianstatic void bwn_nphy_tx_cal_phy_setup(struct bwn_mac *mac) 5253300016Sadrian{ 5254300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 5255300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5256300016Sadrian uint16_t *regs = mac->mac_phy.phy_n->tx_rx_cal_phy_saveregs; 5257300016Sadrian uint16_t tmp; 5258300016Sadrian 5259300016Sadrian regs[0] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C1); 5260300016Sadrian regs[1] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C2); 5261300016Sadrian if (mac->mac_phy.rev >= 3) { 5262300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C1, 0xF0FF, 0x0A00); 5263300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C2, 0xF0FF, 0x0A00); 5264300016Sadrian 5265300016Sadrian tmp = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER1); 5266300016Sadrian regs[2] = tmp; 5267300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, tmp | 0x0600); 5268300016Sadrian 5269300016Sadrian tmp = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER); 5270300016Sadrian regs[3] = tmp; 5271300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, tmp | 0x0600); 5272300016Sadrian 5273300016Sadrian regs[4] = BWN_PHY_READ(mac, BWN_NPHY_BBCFG); 5274300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_BBCFG, 5275300016Sadrian ~BWN_NPHY_BBCFG_RSTRX & 0xFFFF); 5276300016Sadrian 5277300016Sadrian tmp = bwn_ntab_read(mac, BWN_NTAB16(8, 3)); 5278300016Sadrian regs[5] = tmp; 5279300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 3), 0); 5280300016Sadrian 5281300016Sadrian tmp = bwn_ntab_read(mac, BWN_NTAB16(8, 19)); 5282300016Sadrian regs[6] = tmp; 5283300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 19), 0); 5284300016Sadrian regs[7] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC1); 5285300016Sadrian regs[8] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC2); 5286300016Sadrian 5287300016Sadrian if (!nphy->use_int_tx_iq_lo_cal) 5288300016Sadrian bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_PA, 5289300016Sadrian 1, 3); 5290300016Sadrian else 5291300016Sadrian bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_PA, 5292300016Sadrian 0, 3); 5293300016Sadrian bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_TRSW, 2, 1); 5294300016Sadrian bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_TRSW, 8, 2); 5295300016Sadrian 5296300016Sadrian regs[9] = BWN_PHY_READ(mac, BWN_NPHY_PAPD_EN0); 5297300016Sadrian regs[10] = BWN_PHY_READ(mac, BWN_NPHY_PAPD_EN1); 5298300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN0, ~0x0001); 5299300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN1, ~0x0001); 5300300016Sadrian 5301300016Sadrian tmp = bwn_nphy_read_lpf_ctl(mac, 0); 5302300016Sadrian if (phy->rev >= 19) 5303300016Sadrian bwn_nphy_rf_ctl_override_rev19(mac, 0x80, tmp, 0, false, 5304300016Sadrian 1); 5305300016Sadrian else if (phy->rev >= 7) 5306300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x80, tmp, 0, false, 5307300016Sadrian 1); 5308300016Sadrian 5309300016Sadrian if (nphy->use_int_tx_iq_lo_cal && true /* FIXME */) { 5310300016Sadrian if (phy->rev >= 19) { 5311300016Sadrian bwn_nphy_rf_ctl_override_rev19(mac, 0x8, 0, 0x3, 5312300016Sadrian false, 0); 5313300016Sadrian } else if (phy->rev >= 8) { 5314300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x8, 0, 0x3, 5315300016Sadrian false, 0); 5316300016Sadrian } else if (phy->rev == 7) { 5317300016Sadrian BWN_RF_SETMASK(mac, R2057_OVR_REG0, 1 << 4, 1 << 4); 5318300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 5319300016Sadrian BWN_RF_SETMASK(mac, R2057_PAD2G_TUNE_PUS_CORE0, ~1, 0); 5320300016Sadrian BWN_RF_SETMASK(mac, R2057_PAD2G_TUNE_PUS_CORE1, ~1, 0); 5321300016Sadrian } else { 5322300016Sadrian BWN_RF_SETMASK(mac, R2057_IPA5G_CASCOFFV_PU_CORE0, ~1, 0); 5323300016Sadrian BWN_RF_SETMASK(mac, R2057_IPA5G_CASCOFFV_PU_CORE1, ~1, 0); 5324300016Sadrian } 5325300016Sadrian } 5326300016Sadrian } 5327300016Sadrian } else { 5328300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C1, 0x0FFF, 0xA000); 5329300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C2, 0x0FFF, 0xA000); 5330300016Sadrian tmp = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER); 5331300016Sadrian regs[2] = tmp; 5332300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, tmp | 0x3000); 5333300016Sadrian tmp = bwn_ntab_read(mac, BWN_NTAB16(8, 2)); 5334300016Sadrian regs[3] = tmp; 5335300016Sadrian tmp |= 0x2000; 5336300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 2), tmp); 5337300016Sadrian tmp = bwn_ntab_read(mac, BWN_NTAB16(8, 18)); 5338300016Sadrian regs[4] = tmp; 5339300016Sadrian tmp |= 0x2000; 5340300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 18), tmp); 5341300016Sadrian regs[5] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC1); 5342300016Sadrian regs[6] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC2); 5343300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G) 5344300016Sadrian tmp = 0x0180; 5345300016Sadrian else 5346300016Sadrian tmp = 0x0120; 5347300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, tmp); 5348300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, tmp); 5349300016Sadrian } 5350300016Sadrian} 5351300016Sadrian 5352300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */ 5353300016Sadrianstatic void bwn_nphy_save_cal(struct bwn_mac *mac) 5354300016Sadrian{ 5355300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 5356300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5357300016Sadrian 5358300016Sadrian struct bwn_phy_n_iq_comp *rxcal_coeffs = NULL; 5359300016Sadrian uint16_t *txcal_radio_regs = NULL; 5360300016Sadrian struct bwn_chanspec *iqcal_chanspec; 5361300016Sadrian uint16_t *table = NULL; 5362300016Sadrian 5363300016Sadrian if (nphy->hang_avoid) 5364300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 1); 5365300016Sadrian 5366300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 5367300016Sadrian rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G; 5368300016Sadrian txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G; 5369300016Sadrian iqcal_chanspec = &nphy->iqcal_chanspec_2G; 5370300016Sadrian table = nphy->cal_cache.txcal_coeffs_2G; 5371300016Sadrian } else { 5372300016Sadrian rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G; 5373300016Sadrian txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G; 5374300016Sadrian iqcal_chanspec = &nphy->iqcal_chanspec_5G; 5375300016Sadrian table = nphy->cal_cache.txcal_coeffs_5G; 5376300016Sadrian } 5377300016Sadrian 5378300016Sadrian bwn_nphy_rx_iq_coeffs(mac, false, rxcal_coeffs); 5379300016Sadrian /* TODO use some definitions */ 5380300016Sadrian if (phy->rev >= 19) { 5381300016Sadrian /* TODO */ 5382300016Sadrian } else if (phy->rev >= 7) { 5383300016Sadrian txcal_radio_regs[0] = BWN_RF_READ(mac, 5384300016Sadrian R2057_TX0_LOFT_FINE_I); 5385300016Sadrian txcal_radio_regs[1] = BWN_RF_READ(mac, 5386300016Sadrian R2057_TX0_LOFT_FINE_Q); 5387300016Sadrian txcal_radio_regs[4] = BWN_RF_READ(mac, 5388300016Sadrian R2057_TX0_LOFT_COARSE_I); 5389300016Sadrian txcal_radio_regs[5] = BWN_RF_READ(mac, 5390300016Sadrian R2057_TX0_LOFT_COARSE_Q); 5391300016Sadrian txcal_radio_regs[2] = BWN_RF_READ(mac, 5392300016Sadrian R2057_TX1_LOFT_FINE_I); 5393300016Sadrian txcal_radio_regs[3] = BWN_RF_READ(mac, 5394300016Sadrian R2057_TX1_LOFT_FINE_Q); 5395300016Sadrian txcal_radio_regs[6] = BWN_RF_READ(mac, 5396300016Sadrian R2057_TX1_LOFT_COARSE_I); 5397300016Sadrian txcal_radio_regs[7] = BWN_RF_READ(mac, 5398300016Sadrian R2057_TX1_LOFT_COARSE_Q); 5399300016Sadrian } else if (phy->rev >= 3) { 5400300016Sadrian txcal_radio_regs[0] = BWN_RF_READ(mac, 0x2021); 5401300016Sadrian txcal_radio_regs[1] = BWN_RF_READ(mac, 0x2022); 5402300016Sadrian txcal_radio_regs[2] = BWN_RF_READ(mac, 0x3021); 5403300016Sadrian txcal_radio_regs[3] = BWN_RF_READ(mac, 0x3022); 5404300016Sadrian txcal_radio_regs[4] = BWN_RF_READ(mac, 0x2023); 5405300016Sadrian txcal_radio_regs[5] = BWN_RF_READ(mac, 0x2024); 5406300016Sadrian txcal_radio_regs[6] = BWN_RF_READ(mac, 0x3023); 5407300016Sadrian txcal_radio_regs[7] = BWN_RF_READ(mac, 0x3024); 5408300016Sadrian } else { 5409300016Sadrian txcal_radio_regs[0] = BWN_RF_READ(mac, 0x8B); 5410300016Sadrian txcal_radio_regs[1] = BWN_RF_READ(mac, 0xBA); 5411300016Sadrian txcal_radio_regs[2] = BWN_RF_READ(mac, 0x8D); 5412300016Sadrian txcal_radio_regs[3] = BWN_RF_READ(mac, 0xBC); 5413300016Sadrian } 5414300016Sadrian iqcal_chanspec->center_freq = bwn_get_centre_freq(mac); 5415300016Sadrian iqcal_chanspec->channel_type = bwn_get_chan_type(mac, NULL); 5416300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 80), 8, table); 5417300016Sadrian 5418300016Sadrian if (nphy->hang_avoid) 5419300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 0); 5420300016Sadrian} 5421300016Sadrian 5422300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */ 5423300016Sadrianstatic void bwn_nphy_restore_cal(struct bwn_mac *mac) 5424300016Sadrian{ 5425300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 5426300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5427300016Sadrian 5428300016Sadrian uint16_t coef[4]; 5429300016Sadrian uint16_t *loft = NULL; 5430300016Sadrian uint16_t *table = NULL; 5431300016Sadrian 5432300016Sadrian int i; 5433300016Sadrian uint16_t *txcal_radio_regs = NULL; 5434300016Sadrian struct bwn_phy_n_iq_comp *rxcal_coeffs = NULL; 5435300016Sadrian 5436300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 5437300016Sadrian if (!nphy->iqcal_chanspec_2G.center_freq) 5438300016Sadrian return; 5439300016Sadrian table = nphy->cal_cache.txcal_coeffs_2G; 5440300016Sadrian loft = &nphy->cal_cache.txcal_coeffs_2G[5]; 5441300016Sadrian } else { 5442300016Sadrian if (!nphy->iqcal_chanspec_5G.center_freq) 5443300016Sadrian return; 5444300016Sadrian table = nphy->cal_cache.txcal_coeffs_5G; 5445300016Sadrian loft = &nphy->cal_cache.txcal_coeffs_5G[5]; 5446300016Sadrian } 5447300016Sadrian 5448300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 80), 4, table); 5449300016Sadrian 5450300016Sadrian for (i = 0; i < 4; i++) { 5451300016Sadrian if (mac->mac_phy.rev >= 3) 5452300016Sadrian table[i] = coef[i]; 5453300016Sadrian else 5454300016Sadrian coef[i] = 0; 5455300016Sadrian } 5456300016Sadrian 5457300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 88), 4, coef); 5458300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 85), 2, loft); 5459300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 93), 2, loft); 5460300016Sadrian 5461300016Sadrian if (mac->mac_phy.rev < 2) 5462300016Sadrian bwn_nphy_tx_iq_workaround(mac); 5463300016Sadrian 5464300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 5465300016Sadrian txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G; 5466300016Sadrian rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G; 5467300016Sadrian } else { 5468300016Sadrian txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G; 5469300016Sadrian rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G; 5470300016Sadrian } 5471300016Sadrian 5472300016Sadrian /* TODO use some definitions */ 5473300016Sadrian if (phy->rev >= 19) { 5474300016Sadrian /* TODO */ 5475300016Sadrian } else if (phy->rev >= 7) { 5476300016Sadrian BWN_RF_WRITE(mac, R2057_TX0_LOFT_FINE_I, 5477300016Sadrian txcal_radio_regs[0]); 5478300016Sadrian BWN_RF_WRITE(mac, R2057_TX0_LOFT_FINE_Q, 5479300016Sadrian txcal_radio_regs[1]); 5480300016Sadrian BWN_RF_WRITE(mac, R2057_TX0_LOFT_COARSE_I, 5481300016Sadrian txcal_radio_regs[4]); 5482300016Sadrian BWN_RF_WRITE(mac, R2057_TX0_LOFT_COARSE_Q, 5483300016Sadrian txcal_radio_regs[5]); 5484300016Sadrian BWN_RF_WRITE(mac, R2057_TX1_LOFT_FINE_I, 5485300016Sadrian txcal_radio_regs[2]); 5486300016Sadrian BWN_RF_WRITE(mac, R2057_TX1_LOFT_FINE_Q, 5487300016Sadrian txcal_radio_regs[3]); 5488300016Sadrian BWN_RF_WRITE(mac, R2057_TX1_LOFT_COARSE_I, 5489300016Sadrian txcal_radio_regs[6]); 5490300016Sadrian BWN_RF_WRITE(mac, R2057_TX1_LOFT_COARSE_Q, 5491300016Sadrian txcal_radio_regs[7]); 5492300016Sadrian } else if (phy->rev >= 3) { 5493300016Sadrian BWN_RF_WRITE(mac, 0x2021, txcal_radio_regs[0]); 5494300016Sadrian BWN_RF_WRITE(mac, 0x2022, txcal_radio_regs[1]); 5495300016Sadrian BWN_RF_WRITE(mac, 0x3021, txcal_radio_regs[2]); 5496300016Sadrian BWN_RF_WRITE(mac, 0x3022, txcal_radio_regs[3]); 5497300016Sadrian BWN_RF_WRITE(mac, 0x2023, txcal_radio_regs[4]); 5498300016Sadrian BWN_RF_WRITE(mac, 0x2024, txcal_radio_regs[5]); 5499300016Sadrian BWN_RF_WRITE(mac, 0x3023, txcal_radio_regs[6]); 5500300016Sadrian BWN_RF_WRITE(mac, 0x3024, txcal_radio_regs[7]); 5501300016Sadrian } else { 5502300016Sadrian BWN_RF_WRITE(mac, 0x8B, txcal_radio_regs[0]); 5503300016Sadrian BWN_RF_WRITE(mac, 0xBA, txcal_radio_regs[1]); 5504300016Sadrian BWN_RF_WRITE(mac, 0x8D, txcal_radio_regs[2]); 5505300016Sadrian BWN_RF_WRITE(mac, 0xBC, txcal_radio_regs[3]); 5506300016Sadrian } 5507300016Sadrian bwn_nphy_rx_iq_coeffs(mac, true, rxcal_coeffs); 5508300016Sadrian} 5509300016Sadrian 5510300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalTxIqlo */ 5511300016Sadrianstatic int bwn_nphy_cal_tx_iq_lo(struct bwn_mac *mac, 5512300016Sadrian struct bwn_nphy_txgains target, 5513300016Sadrian bool full, bool mphase) 5514300016Sadrian{ 5515300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 5516300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5517300016Sadrian int i; 5518300016Sadrian int error = 0; 5519300016Sadrian int freq; 5520300016Sadrian bool avoid = false; 5521300016Sadrian uint8_t length; 5522300016Sadrian uint16_t tmp, core, type, count, max, numb, last = 0, cmd; 5523300016Sadrian const uint16_t *table; 5524300016Sadrian bool phy6or5x; 5525300016Sadrian 5526300016Sadrian uint16_t buffer[11]; 5527300016Sadrian uint16_t diq_start = 0; 5528300016Sadrian uint16_t save[2]; 5529300016Sadrian uint16_t gain[2]; 5530300016Sadrian struct bwn_nphy_iqcal_params params[2]; 5531300016Sadrian bool updated[2] = { }; 5532300016Sadrian 5533300016Sadrian bwn_nphy_stay_in_carrier_search(mac, true); 5534300016Sadrian 5535300016Sadrian if (mac->mac_phy.rev >= 4) { 5536300016Sadrian avoid = nphy->hang_avoid; 5537300016Sadrian nphy->hang_avoid = false; 5538300016Sadrian } 5539300016Sadrian 5540300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(7, 0x110), 2, save); 5541300016Sadrian 5542300016Sadrian for (i = 0; i < 2; i++) { 5543300016Sadrian bwn_nphy_iq_cal_gain_params(mac, i, target, ¶ms[i]); 5544300016Sadrian gain[i] = params[i].cal_gain; 5545300016Sadrian } 5546300016Sadrian 5547300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x110), 2, gain); 5548300016Sadrian 5549300016Sadrian bwn_nphy_tx_cal_radio_setup(mac); 5550300016Sadrian bwn_nphy_tx_cal_phy_setup(mac); 5551300016Sadrian 5552300016Sadrian phy6or5x = mac->mac_phy.rev >= 6 || 5553300016Sadrian (mac->mac_phy.rev == 5 && nphy->ipa2g_on && 5554300016Sadrian bwn_current_band(mac) == BWN_BAND_2G); 5555300016Sadrian if (phy6or5x) { 5556300016Sadrian if (bwn_is_40mhz(mac)) { 5557300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 0), 18, 5558300016Sadrian tbl_tx_iqlo_cal_loft_ladder_40); 5559300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 32), 18, 5560300016Sadrian tbl_tx_iqlo_cal_iqimb_ladder_40); 5561300016Sadrian } else { 5562300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 0), 18, 5563300016Sadrian tbl_tx_iqlo_cal_loft_ladder_20); 5564300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 32), 18, 5565300016Sadrian tbl_tx_iqlo_cal_iqimb_ladder_20); 5566300016Sadrian } 5567300016Sadrian } 5568300016Sadrian 5569300016Sadrian if (phy->rev >= 19) { 5570300016Sadrian /* TODO */ 5571300016Sadrian } else if (phy->rev >= 7) { 5572300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0x8AD9); 5573300016Sadrian } else { 5574300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0x8AA9); 5575300016Sadrian } 5576300016Sadrian 5577300016Sadrian if (!bwn_is_40mhz(mac)) 5578300016Sadrian freq = 2500; 5579300016Sadrian else 5580300016Sadrian freq = 5000; 5581300016Sadrian 5582300016Sadrian if (nphy->mphase_cal_phase_id > 2) 5583300016Sadrian bwn_nphy_run_samples(mac, (bwn_is_40mhz(mac) ? 40 : 20) * 8, 5584300016Sadrian 0xFFFF, 0, true, false, false); 5585300016Sadrian else 5586300016Sadrian error = bwn_nphy_tx_tone(mac, freq, 250, true, false, false); 5587300016Sadrian 5588300016Sadrian if (error == 0) { 5589300016Sadrian if (nphy->mphase_cal_phase_id > 2) { 5590300016Sadrian table = nphy->mphase_txcal_bestcoeffs; 5591300016Sadrian length = 11; 5592300016Sadrian if (mac->mac_phy.rev < 3) 5593300016Sadrian length -= 2; 5594300016Sadrian } else { 5595300016Sadrian if (!full && nphy->txiqlocal_coeffsvalid) { 5596300016Sadrian table = nphy->txiqlocal_bestc; 5597300016Sadrian length = 11; 5598300016Sadrian if (mac->mac_phy.rev < 3) 5599300016Sadrian length -= 2; 5600300016Sadrian } else { 5601300016Sadrian full = true; 5602300016Sadrian if (mac->mac_phy.rev >= 3) { 5603300016Sadrian table = tbl_tx_iqlo_cal_startcoefs_nphyrev3; 5604300016Sadrian length = BWN_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3; 5605300016Sadrian } else { 5606300016Sadrian table = tbl_tx_iqlo_cal_startcoefs; 5607300016Sadrian length = BWN_NTAB_TX_IQLO_CAL_STARTCOEFS; 5608300016Sadrian } 5609300016Sadrian } 5610300016Sadrian } 5611300016Sadrian 5612300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 64), length, table); 5613300016Sadrian 5614300016Sadrian if (full) { 5615300016Sadrian if (mac->mac_phy.rev >= 3) 5616300016Sadrian max = BWN_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3; 5617300016Sadrian else 5618300016Sadrian max = BWN_NTAB_TX_IQLO_CAL_CMDS_FULLCAL; 5619300016Sadrian } else { 5620300016Sadrian if (mac->mac_phy.rev >= 3) 5621300016Sadrian max = BWN_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3; 5622300016Sadrian else 5623300016Sadrian max = BWN_NTAB_TX_IQLO_CAL_CMDS_RECAL; 5624300016Sadrian } 5625300016Sadrian 5626300016Sadrian if (mphase) { 5627300016Sadrian count = nphy->mphase_txcal_cmdidx; 5628300016Sadrian numb = min(max, 5629300016Sadrian (uint16_t)(count + nphy->mphase_txcal_numcmds)); 5630300016Sadrian } else { 5631300016Sadrian count = 0; 5632300016Sadrian numb = max; 5633300016Sadrian } 5634300016Sadrian 5635300016Sadrian for (; count < numb; count++) { 5636300016Sadrian if (full) { 5637300016Sadrian if (mac->mac_phy.rev >= 3) 5638300016Sadrian cmd = tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[count]; 5639300016Sadrian else 5640300016Sadrian cmd = tbl_tx_iqlo_cal_cmds_fullcal[count]; 5641300016Sadrian } else { 5642300016Sadrian if (mac->mac_phy.rev >= 3) 5643300016Sadrian cmd = tbl_tx_iqlo_cal_cmds_recal_nphyrev3[count]; 5644300016Sadrian else 5645300016Sadrian cmd = tbl_tx_iqlo_cal_cmds_recal[count]; 5646300016Sadrian } 5647300016Sadrian 5648300016Sadrian core = (cmd & 0x3000) >> 12; 5649300016Sadrian type = (cmd & 0x0F00) >> 8; 5650300016Sadrian 5651300016Sadrian if (phy6or5x && updated[core] == 0) { 5652300016Sadrian bwn_nphy_update_tx_cal_ladder(mac, core); 5653300016Sadrian updated[core] = true; 5654300016Sadrian } 5655300016Sadrian 5656300016Sadrian tmp = (params[core].ncorr[type] << 8) | 0x66; 5657300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_IQLOCAL_CMDNNUM, tmp); 5658300016Sadrian 5659300016Sadrian if (type == 1 || type == 3 || type == 4) { 5660300016Sadrian buffer[0] = bwn_ntab_read(mac, 5661300016Sadrian BWN_NTAB16(15, 69 + core)); 5662300016Sadrian diq_start = buffer[0]; 5663300016Sadrian buffer[0] = 0; 5664300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(15, 69 + core), 5665300016Sadrian 0); 5666300016Sadrian } 5667300016Sadrian 5668300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_IQLOCAL_CMD, cmd); 5669300016Sadrian for (i = 0; i < 2000; i++) { 5670300016Sadrian tmp = BWN_PHY_READ(mac, BWN_NPHY_IQLOCAL_CMD); 5671300016Sadrian if (tmp & 0xC000) 5672300016Sadrian break; 5673300016Sadrian DELAY(10); 5674300016Sadrian } 5675300016Sadrian 5676300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 96), length, 5677300016Sadrian buffer); 5678300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 64), length, 5679300016Sadrian buffer); 5680300016Sadrian 5681300016Sadrian if (type == 1 || type == 3 || type == 4) 5682300016Sadrian buffer[0] = diq_start; 5683300016Sadrian } 5684300016Sadrian 5685300016Sadrian if (mphase) 5686300016Sadrian nphy->mphase_txcal_cmdidx = (numb >= max) ? 0 : numb; 5687300016Sadrian 5688300016Sadrian last = (mac->mac_phy.rev < 3) ? 6 : 7; 5689300016Sadrian 5690300016Sadrian if (!mphase || nphy->mphase_cal_phase_id == last) { 5691300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 96), 4, buffer); 5692300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 80), 4, buffer); 5693300016Sadrian if (mac->mac_phy.rev < 3) { 5694300016Sadrian buffer[0] = 0; 5695300016Sadrian buffer[1] = 0; 5696300016Sadrian buffer[2] = 0; 5697300016Sadrian buffer[3] = 0; 5698300016Sadrian } 5699300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 88), 4, 5700300016Sadrian buffer); 5701300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 101), 2, 5702300016Sadrian buffer); 5703300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 85), 2, 5704300016Sadrian buffer); 5705300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 93), 2, 5706300016Sadrian buffer); 5707300016Sadrian length = 11; 5708300016Sadrian if (mac->mac_phy.rev < 3) 5709300016Sadrian length -= 2; 5710300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 96), length, 5711300016Sadrian nphy->txiqlocal_bestc); 5712300016Sadrian nphy->txiqlocal_coeffsvalid = true; 5713300016Sadrian nphy->txiqlocal_chanspec.center_freq = 5714300016Sadrian bwn_get_centre_freq(mac); 5715300016Sadrian nphy->txiqlocal_chanspec.channel_type = bwn_get_chan_type(mac, NULL); 5716300016Sadrian } else { 5717300016Sadrian length = 11; 5718300016Sadrian if (mac->mac_phy.rev < 3) 5719300016Sadrian length -= 2; 5720300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 96), length, 5721300016Sadrian nphy->mphase_txcal_bestcoeffs); 5722300016Sadrian } 5723300016Sadrian 5724300016Sadrian bwn_nphy_stop_playback(mac); 5725300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0); 5726300016Sadrian } 5727300016Sadrian 5728300016Sadrian bwn_nphy_tx_cal_phy_cleanup(mac); 5729300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x110), 2, save); 5730300016Sadrian 5731300016Sadrian if (mac->mac_phy.rev < 2 && (!mphase || nphy->mphase_cal_phase_id == last)) 5732300016Sadrian bwn_nphy_tx_iq_workaround(mac); 5733300016Sadrian 5734300016Sadrian if (mac->mac_phy.rev >= 4) 5735300016Sadrian nphy->hang_avoid = avoid; 5736300016Sadrian 5737300016Sadrian bwn_nphy_stay_in_carrier_search(mac, false); 5738300016Sadrian 5739300016Sadrian return error; 5740300016Sadrian} 5741300016Sadrian 5742300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ReapplyTxCalCoeffs */ 5743300016Sadrianstatic void bwn_nphy_reapply_tx_cal_coeffs(struct bwn_mac *mac) 5744300016Sadrian{ 5745300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5746300016Sadrian uint8_t i; 5747300016Sadrian uint16_t buffer[7]; 5748300016Sadrian bool equal = true; 5749300016Sadrian 5750300016Sadrian if (!nphy->txiqlocal_coeffsvalid || 5751300016Sadrian nphy->txiqlocal_chanspec.center_freq != bwn_get_centre_freq(mac) || 5752300016Sadrian nphy->txiqlocal_chanspec.channel_type != bwn_get_chan_type(mac, NULL)) 5753300016Sadrian return; 5754300016Sadrian 5755300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 80), 7, buffer); 5756300016Sadrian for (i = 0; i < 4; i++) { 5757300016Sadrian if (buffer[i] != nphy->txiqlocal_bestc[i]) { 5758300016Sadrian equal = false; 5759300016Sadrian break; 5760300016Sadrian } 5761300016Sadrian } 5762300016Sadrian 5763300016Sadrian if (!equal) { 5764300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 80), 4, 5765300016Sadrian nphy->txiqlocal_bestc); 5766300016Sadrian for (i = 0; i < 4; i++) 5767300016Sadrian buffer[i] = 0; 5768300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 88), 4, 5769300016Sadrian buffer); 5770300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 85), 2, 5771300016Sadrian &nphy->txiqlocal_bestc[5]); 5772300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 93), 2, 5773300016Sadrian &nphy->txiqlocal_bestc[5]); 5774300016Sadrian } 5775300016Sadrian} 5776300016Sadrian 5777300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIqRev2 */ 5778300016Sadrianstatic int bwn_nphy_rev2_cal_rx_iq(struct bwn_mac *mac, 5779300016Sadrian struct bwn_nphy_txgains target, uint8_t type, bool debug) 5780300016Sadrian{ 5781300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5782300016Sadrian int i, j, index; 5783300016Sadrian uint8_t rfctl[2]; 5784300016Sadrian uint8_t afectl_core; 5785300016Sadrian uint16_t tmp[6]; 5786300016Sadrian uint16_t cur_hpf1, cur_hpf2, cur_lna; 5787300016Sadrian uint32_t real, imag; 5788300016Sadrian bwn_band_t band; 5789300016Sadrian 5790300016Sadrian uint8_t use; 5791300016Sadrian uint16_t cur_hpf; 5792300016Sadrian uint16_t lna[3] = { 3, 3, 1 }; 5793300016Sadrian uint16_t hpf1[3] = { 7, 2, 0 }; 5794300016Sadrian uint16_t hpf2[3] = { 2, 0, 0 }; 5795300016Sadrian uint32_t power[3] = { }; 5796300016Sadrian uint16_t gain_save[2]; 5797300016Sadrian uint16_t cal_gain[2]; 5798300016Sadrian struct bwn_nphy_iqcal_params cal_params[2]; 5799300016Sadrian struct bwn_nphy_iq_est est; 5800300016Sadrian int ret = 0; 5801300016Sadrian bool playtone = true; 5802300016Sadrian int desired = 13; 5803300016Sadrian 5804300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 1); 5805300016Sadrian 5806300016Sadrian if (mac->mac_phy.rev < 2) 5807300016Sadrian bwn_nphy_reapply_tx_cal_coeffs(mac); 5808300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(7, 0x110), 2, gain_save); 5809300016Sadrian for (i = 0; i < 2; i++) { 5810300016Sadrian bwn_nphy_iq_cal_gain_params(mac, i, target, &cal_params[i]); 5811300016Sadrian cal_gain[i] = cal_params[i].cal_gain; 5812300016Sadrian } 5813300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x110), 2, cal_gain); 5814300016Sadrian 5815300016Sadrian for (i = 0; i < 2; i++) { 5816300016Sadrian if (i == 0) { 5817300016Sadrian rfctl[0] = BWN_NPHY_RFCTL_INTC1; 5818300016Sadrian rfctl[1] = BWN_NPHY_RFCTL_INTC2; 5819300016Sadrian afectl_core = BWN_NPHY_AFECTL_C1; 5820300016Sadrian } else { 5821300016Sadrian rfctl[0] = BWN_NPHY_RFCTL_INTC2; 5822300016Sadrian rfctl[1] = BWN_NPHY_RFCTL_INTC1; 5823300016Sadrian afectl_core = BWN_NPHY_AFECTL_C2; 5824300016Sadrian } 5825300016Sadrian 5826300016Sadrian tmp[1] = BWN_PHY_READ(mac, BWN_NPHY_RFSEQCA); 5827300016Sadrian tmp[2] = BWN_PHY_READ(mac, afectl_core); 5828300016Sadrian tmp[3] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER); 5829300016Sadrian tmp[4] = BWN_PHY_READ(mac, rfctl[0]); 5830300016Sadrian tmp[5] = BWN_PHY_READ(mac, rfctl[1]); 5831300016Sadrian 5832300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, 5833300016Sadrian ~BWN_NPHY_RFSEQCA_RXDIS & 0xFFFF, 5834300016Sadrian ((1 - i) << BWN_NPHY_RFSEQCA_RXDIS_SHIFT)); 5835300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, ~BWN_NPHY_RFSEQCA_TXEN, 5836300016Sadrian (1 - i)); 5837300016Sadrian BWN_PHY_SET(mac, afectl_core, 0x0006); 5838300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x0006); 5839300016Sadrian 5840300016Sadrian band = bwn_current_band(mac); 5841300016Sadrian 5842300016Sadrian if (nphy->rxcalparams & 0xFF000000) { 5843300016Sadrian if (band == BWN_BAND_5G) 5844300016Sadrian BWN_PHY_WRITE(mac, rfctl[0], 0x140); 5845300016Sadrian else 5846300016Sadrian BWN_PHY_WRITE(mac, rfctl[0], 0x110); 5847300016Sadrian } else { 5848300016Sadrian if (band == BWN_BAND_5G) 5849300016Sadrian BWN_PHY_WRITE(mac, rfctl[0], 0x180); 5850300016Sadrian else 5851300016Sadrian BWN_PHY_WRITE(mac, rfctl[0], 0x120); 5852300016Sadrian } 5853300016Sadrian 5854300016Sadrian if (band == BWN_BAND_5G) 5855300016Sadrian BWN_PHY_WRITE(mac, rfctl[1], 0x148); 5856300016Sadrian else 5857300016Sadrian BWN_PHY_WRITE(mac, rfctl[1], 0x114); 5858300016Sadrian 5859300016Sadrian if (nphy->rxcalparams & 0x10000) { 5860300016Sadrian BWN_RF_SETMASK(mac, B2055_C1_GENSPARE2, 0xFC, 5861300016Sadrian (i + 1)); 5862300016Sadrian BWN_RF_SETMASK(mac, B2055_C2_GENSPARE2, 0xFC, 5863300016Sadrian (2 - i)); 5864300016Sadrian } 5865300016Sadrian 5866300016Sadrian for (j = 0; j < 4; j++) { 5867300016Sadrian if (j < 3) { 5868300016Sadrian cur_lna = lna[j]; 5869300016Sadrian cur_hpf1 = hpf1[j]; 5870300016Sadrian cur_hpf2 = hpf2[j]; 5871300016Sadrian } else { 5872300016Sadrian if (power[1] > 10000) { 5873300016Sadrian use = 1; 5874300016Sadrian cur_hpf = cur_hpf1; 5875300016Sadrian index = 2; 5876300016Sadrian } else { 5877300016Sadrian if (power[0] > 10000) { 5878300016Sadrian use = 1; 5879300016Sadrian cur_hpf = cur_hpf1; 5880300016Sadrian index = 1; 5881300016Sadrian } else { 5882300016Sadrian index = 0; 5883300016Sadrian use = 2; 5884300016Sadrian cur_hpf = cur_hpf2; 5885300016Sadrian } 5886300016Sadrian } 5887300016Sadrian cur_lna = lna[index]; 5888300016Sadrian cur_hpf1 = hpf1[index]; 5889300016Sadrian cur_hpf2 = hpf2[index]; 5890300016Sadrian cur_hpf += desired - bwn_hweight32(power[index]); 5891300016Sadrian cur_hpf = bwn_clamp_val(cur_hpf, 0, 10); 5892300016Sadrian if (use == 1) 5893300016Sadrian cur_hpf1 = cur_hpf; 5894300016Sadrian else 5895300016Sadrian cur_hpf2 = cur_hpf; 5896300016Sadrian } 5897300016Sadrian 5898300016Sadrian tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) | 5899300016Sadrian (cur_lna << 2)); 5900300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x400, tmp[0], 3, 5901300016Sadrian false); 5902300016Sadrian bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX); 5903300016Sadrian bwn_nphy_stop_playback(mac); 5904300016Sadrian 5905300016Sadrian if (playtone) { 5906300016Sadrian ret = bwn_nphy_tx_tone(mac, 4000, 5907300016Sadrian (nphy->rxcalparams & 0xFFFF), 5908300016Sadrian false, false, true); 5909300016Sadrian playtone = false; 5910300016Sadrian } else { 5911300016Sadrian bwn_nphy_run_samples(mac, 160, 0xFFFF, 0, false, 5912300016Sadrian false, true); 5913300016Sadrian } 5914300016Sadrian 5915300016Sadrian if (ret == 0) { 5916300016Sadrian if (j < 3) { 5917300016Sadrian bwn_nphy_rx_iq_est(mac, &est, 1024, 32, 5918300016Sadrian false); 5919300016Sadrian if (i == 0) { 5920300016Sadrian real = est.i0_pwr; 5921300016Sadrian imag = est.q0_pwr; 5922300016Sadrian } else { 5923300016Sadrian real = est.i1_pwr; 5924300016Sadrian imag = est.q1_pwr; 5925300016Sadrian } 5926300016Sadrian power[i] = ((real + imag) / 1024) + 1; 5927300016Sadrian } else { 5928300016Sadrian bwn_nphy_calc_rx_iq_comp(mac, 1 << i); 5929300016Sadrian } 5930300016Sadrian bwn_nphy_stop_playback(mac); 5931300016Sadrian } 5932300016Sadrian 5933300016Sadrian if (ret != 0) 5934300016Sadrian break; 5935300016Sadrian } 5936300016Sadrian 5937300016Sadrian BWN_RF_MASK(mac, B2055_C1_GENSPARE2, 0xFC); 5938300016Sadrian BWN_RF_MASK(mac, B2055_C2_GENSPARE2, 0xFC); 5939300016Sadrian BWN_PHY_WRITE(mac, rfctl[1], tmp[5]); 5940300016Sadrian BWN_PHY_WRITE(mac, rfctl[0], tmp[4]); 5941300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, tmp[3]); 5942300016Sadrian BWN_PHY_WRITE(mac, afectl_core, tmp[2]); 5943300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFSEQCA, tmp[1]); 5944300016Sadrian 5945300016Sadrian if (ret != 0) 5946300016Sadrian break; 5947300016Sadrian } 5948300016Sadrian 5949300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x400, 0, 3, true); 5950300016Sadrian bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX); 5951300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x110), 2, gain_save); 5952300016Sadrian 5953300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 0); 5954300016Sadrian 5955300016Sadrian return ret; 5956300016Sadrian} 5957300016Sadrian 5958300016Sadrianstatic int bwn_nphy_rev3_cal_rx_iq(struct bwn_mac *mac, 5959300016Sadrian struct bwn_nphy_txgains target, uint8_t type, bool debug) 5960300016Sadrian{ 5961300016Sadrian return -1; 5962300016Sadrian} 5963300016Sadrian 5964300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIq */ 5965300016Sadrianstatic int bwn_nphy_cal_rx_iq(struct bwn_mac *mac, 5966300016Sadrian struct bwn_nphy_txgains target, uint8_t type, bool debug) 5967300016Sadrian{ 5968300016Sadrian if (mac->mac_phy.rev >= 7) 5969300016Sadrian type = 0; 5970300016Sadrian 5971300016Sadrian if (mac->mac_phy.rev >= 3) 5972300016Sadrian return bwn_nphy_rev3_cal_rx_iq(mac, target, type, debug); 5973300016Sadrian else 5974300016Sadrian return bwn_nphy_rev2_cal_rx_iq(mac, target, type, debug); 5975300016Sadrian} 5976300016Sadrian 5977300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */ 5978300016Sadrianstatic void bwn_nphy_set_rx_core_state(struct bwn_mac *mac, uint8_t mask) 5979300016Sadrian{ 5980300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 5981300016Sadrian struct bwn_phy_n *nphy = phy->phy_n; 5982300016Sadrian /* uint16_t buf[16]; it's rev3+ */ 5983300016Sadrian 5984300016Sadrian nphy->phyrxchain = mask; 5985300016Sadrian 5986300016Sadrian if (0 /* FIXME clk */) 5987300016Sadrian return; 5988300016Sadrian 5989300016Sadrian bwn_mac_suspend(mac); 5990300016Sadrian 5991300016Sadrian if (nphy->hang_avoid) 5992300016Sadrian bwn_nphy_stay_in_carrier_search(mac, true); 5993300016Sadrian 5994300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, ~BWN_NPHY_RFSEQCA_RXEN, 5995300016Sadrian (mask & 0x3) << BWN_NPHY_RFSEQCA_RXEN_SHIFT); 5996300016Sadrian 5997300016Sadrian if ((mask & 0x3) != 0x3) { 5998300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_HPANT_SWTHRES, 1); 5999300016Sadrian if (mac->mac_phy.rev >= 3) { 6000300016Sadrian /* TODO */ 6001300016Sadrian } 6002300016Sadrian } else { 6003300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_HPANT_SWTHRES, 0x1E); 6004300016Sadrian if (mac->mac_phy.rev >= 3) { 6005300016Sadrian /* TODO */ 6006300016Sadrian } 6007300016Sadrian } 6008300016Sadrian 6009300016Sadrian bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX); 6010300016Sadrian 6011300016Sadrian if (nphy->hang_avoid) 6012300016Sadrian bwn_nphy_stay_in_carrier_search(mac, false); 6013300016Sadrian 6014300016Sadrian bwn_mac_enable(mac); 6015300016Sadrian} 6016300016Sadrian 6017300016Sadrianbwn_txpwr_result_t 6018300016Sadrianbwn_nphy_op_recalc_txpower(struct bwn_mac *mac, bool ignore_tssi) 6019300016Sadrian{ 6020300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 6021300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 6022300016Sadrian struct ieee80211_channel *channel = bwn_get_channel(mac); 6023300016Sadrian struct bwn_softc *sc = mac->mac_sc; 6024300016Sadrian struct bwn_ppr *ppr = &nphy->tx_pwr_max_ppr; 6025300016Sadrian uint8_t max; /* qdBm */ 6026300016Sadrian bool tx_pwr_state; 6027300016Sadrian 6028300016Sadrian if (nphy->tx_pwr_last_recalc_freq == bwn_get_centre_freq(mac) && 6029300016Sadrian nphy->tx_pwr_last_recalc_limit == phy->txpower) 6030300016Sadrian return BWN_TXPWR_RES_DONE; 6031300016Sadrian 6032300016Sadrian /* Make sure we have a clean PPR */ 6033300016Sadrian bwn_ppr_clear(mac, ppr); 6034300016Sadrian 6035300016Sadrian /* HW limitations */ 6036300016Sadrian bwn_ppr_load_max_from_sprom(mac, ppr, BWN_PHY_BAND_2G); 6037300016Sadrian /* XXX TODO: other bands? */ 6038300016Sadrian 6039300016Sadrian /* Regulatory & user settings */ 6040300016Sadrian max = INT_TO_Q52(bwn_get_chan_power(mac, channel)); 6041300016Sadrian /* uint8_t */ 6042300016Sadrian if (phy->txpower) 6043300016Sadrian max = min(max, INT_TO_Q52(phy->txpower)); 6044300016Sadrian bwn_ppr_apply_max(mac, ppr, max); 6045300016Sadrian DPRINTF(mac->mac_sc, BWN_DEBUG_XMIT_POWER, 6046300016Sadrian "Calculated TX power: " Q52_FMT "\n", 6047300016Sadrian Q52_ARG(bwn_ppr_get_max(mac, ppr))); 6048300016Sadrian 6049300016Sadrian /* TODO: Enable this once we get gains working */ 6050300016Sadrian#if 0 6051300016Sadrian /* Some extra gains */ 6052300016Sadrian hw_gain = 6; /* N-PHY specific */ 6053300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 6054300016Sadrian hw_gain += sprom->antenna_gain.a0; 6055300016Sadrian else 6056300016Sadrian hw_gain += sprom->antenna_gain.a1; 6057300016Sadrian bwn_ppr_add(mac, ppr, -hw_gain); 6058300016Sadrian#endif 6059300016Sadrian 6060300016Sadrian /* Make sure we didn't go too low */ 6061300016Sadrian bwn_ppr_apply_min(mac, ppr, INT_TO_Q52(8)); 6062300016Sadrian 6063300016Sadrian /* Apply */ 6064300016Sadrian tx_pwr_state = nphy->txpwrctrl; 6065300016Sadrian bwn_mac_suspend(mac); 6066300016Sadrian bwn_nphy_tx_power_ctl_setup(mac); 6067300016Sadrian if (siba_get_revid(sc->sc_dev) == 11 || siba_get_revid(sc->sc_dev) == 12) { 6068300016Sadrian BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~0, BWN_MACCTL_PHY_LOCK); 6069300016Sadrian BWN_READ_4(mac, BWN_MACCTL); 6070300016Sadrian DELAY(1); 6071300016Sadrian } 6072300016Sadrian bwn_nphy_tx_power_ctrl(mac, nphy->txpwrctrl); 6073300016Sadrian if (siba_get_revid(sc->sc_dev) == 11 || siba_get_revid(sc->sc_dev) == 12) 6074300016Sadrian BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~BWN_MACCTL_PHY_LOCK, 0); 6075300016Sadrian bwn_mac_enable(mac); 6076300016Sadrian 6077300016Sadrian nphy->tx_pwr_last_recalc_freq = bwn_get_centre_freq(mac); 6078300016Sadrian nphy->tx_pwr_last_recalc_limit = phy->txpower; 6079300016Sadrian 6080300016Sadrian return BWN_TXPWR_RES_DONE; 6081300016Sadrian} 6082300016Sadrian 6083300016Sadrian/************************************************** 6084300016Sadrian * N-PHY init 6085300016Sadrian **************************************************/ 6086300016Sadrian 6087300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */ 6088300016Sadrianstatic void bwn_nphy_update_mimo_config(struct bwn_mac *mac, int32_t preamble) 6089300016Sadrian{ 6090300016Sadrian uint16_t mimocfg = BWN_PHY_READ(mac, BWN_NPHY_MIMOCFG); 6091300016Sadrian 6092300016Sadrian mimocfg |= BWN_NPHY_MIMOCFG_AUTO; 6093300016Sadrian if (preamble == 1) 6094300016Sadrian mimocfg |= BWN_NPHY_MIMOCFG_GFMIX; 6095300016Sadrian else 6096300016Sadrian mimocfg &= ~BWN_NPHY_MIMOCFG_GFMIX; 6097300016Sadrian 6098300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_MIMOCFG, mimocfg); 6099300016Sadrian} 6100300016Sadrian 6101300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BPHYInit */ 6102300016Sadrianstatic void bwn_nphy_bphy_init(struct bwn_mac *mac) 6103300016Sadrian{ 6104300016Sadrian unsigned int i; 6105300016Sadrian uint16_t val; 6106300016Sadrian 6107300016Sadrian val = 0x1E1F; 6108300016Sadrian for (i = 0; i < 16; i++) { 6109300016Sadrian BWN_PHY_WRITE(mac, BWN_PHY_N_BMODE(0x88 + i), val); 6110300016Sadrian val -= 0x202; 6111300016Sadrian } 6112300016Sadrian val = 0x3E3F; 6113300016Sadrian for (i = 0; i < 16; i++) { 6114300016Sadrian BWN_PHY_WRITE(mac, BWN_PHY_N_BMODE(0x98 + i), val); 6115300016Sadrian val -= 0x202; 6116300016Sadrian } 6117300016Sadrian BWN_PHY_WRITE(mac, BWN_PHY_N_BMODE(0x38), 0x668); 6118300016Sadrian} 6119300016Sadrian 6120300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */ 6121300016Sadrianstatic void bwn_nphy_superswitch_init(struct bwn_mac *mac, bool init) 6122300016Sadrian{ 6123300016Sadrian struct bwn_softc *sc = mac->mac_sc; 6124300016Sadrian 6125300016Sadrian if (mac->mac_phy.rev >= 7) 6126300016Sadrian return; 6127300016Sadrian 6128300016Sadrian if (mac->mac_phy.rev >= 3) { 6129300016Sadrian if (!init) 6130300016Sadrian return; 6131300016Sadrian if (0 /* FIXME */) { 6132300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(9, 2), 0x211); 6133300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(9, 3), 0x222); 6134300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(9, 8), 0x144); 6135300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(9, 12), 0x188); 6136300016Sadrian } 6137300016Sadrian } else { 6138300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_GPIO_LOOEN, 0); 6139300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_GPIO_HIOEN, 0); 6140300016Sadrian 6141300016Sadrian /* XXX handle bhnd bus */ 6142300016Sadrian if (bwn_is_bus_siba(mac)) { 6143300016Sadrian siba_gpio_set(sc->sc_dev, 0xfc00); 6144300016Sadrian } 6145300016Sadrian 6146300016Sadrian BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~BWN_MACCTL_GPOUT_MASK, 0); 6147300016Sadrian BWN_WRITE_SETMASK2(mac, BWN_GPIO_MASK, ~0, 0xFC00); 6148300016Sadrian BWN_WRITE_SETMASK2(mac, BWN_GPIO_CONTROL, (~0xFC00 & 0xFFFF), 6149300016Sadrian 0); 6150300016Sadrian 6151300016Sadrian if (init) { 6152300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); 6153300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP1, 0x301); 6154300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); 6155300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); 6156300016Sadrian } 6157300016Sadrian } 6158300016Sadrian} 6159300016Sadrian 6160300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N */ 6161300016Sadrianstatic int bwn_phy_initn(struct bwn_mac *mac) 6162300016Sadrian{ 6163300016Sadrian struct bwn_softc *sc = mac->mac_sc; 6164300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 6165300016Sadrian struct bwn_phy_n *nphy = phy->phy_n; 6166300016Sadrian uint8_t tx_pwr_state; 6167300016Sadrian struct bwn_nphy_txgains target; 6168300016Sadrian uint16_t tmp; 6169300016Sadrian bwn_band_t tmp2; 6170300016Sadrian bool do_rssi_cal; 6171300016Sadrian 6172300016Sadrian uint16_t clip[2]; 6173300016Sadrian bool do_cal = false; 6174300016Sadrian 6175300016Sadrian if ((mac->mac_phy.rev >= 3) && 6176300016Sadrian (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) && 6177300016Sadrian (bwn_current_band(mac) == BWN_BAND_2G)) { 6178300016Sadrian /* XXX bhnd bus */ 6179300016Sadrian if (bwn_is_bus_siba(mac)) { 6180300016Sadrian siba_cc_set32(sc->sc_dev, SIBA_CC_CHIPCTL, 0x40); 6181300016Sadrian } 6182300016Sadrian } 6183300016Sadrian nphy->use_int_tx_iq_lo_cal = bwn_nphy_ipa(mac) || 6184300016Sadrian phy->rev >= 7 || 6185300016Sadrian (phy->rev >= 5 && 6186300016Sadrian siba_sprom_get_bf2_hi(sc->sc_dev) & BWN_BFH2_INTERNDET_TXIQCAL); 6187300016Sadrian nphy->deaf_count = 0; 6188300016Sadrian bwn_nphy_tables_init(mac); 6189300016Sadrian nphy->crsminpwr_adjusted = false; 6190300016Sadrian nphy->noisevars_adjusted = false; 6191300016Sadrian 6192300016Sadrian /* Clear all overrides */ 6193300016Sadrian if (mac->mac_phy.rev >= 3) { 6194300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B1S1, 0); 6195300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_OVER, 0); 6196300016Sadrian if (phy->rev >= 7) { 6197300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER3, 0); 6198300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER4, 0); 6199300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER5, 0); 6200300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER6, 0); 6201300016Sadrian } 6202300016Sadrian if (phy->rev >= 19) { 6203300016Sadrian /* TODO */ 6204300016Sadrian } 6205300016Sadrian 6206300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B1S0, 0); 6207300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B32S1, 0); 6208300016Sadrian } else { 6209300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_OVER, 0); 6210300016Sadrian } 6211300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, 0); 6212300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, 0); 6213300016Sadrian if (mac->mac_phy.rev < 6) { 6214300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC3, 0); 6215300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC4, 0); 6216300016Sadrian } 6217300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFSEQMODE, 6218300016Sadrian ~(BWN_NPHY_RFSEQMODE_CAOVER | 6219300016Sadrian BWN_NPHY_RFSEQMODE_TROVER)); 6220300016Sadrian if (mac->mac_phy.rev >= 3) 6221300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, 0); 6222300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, 0); 6223300016Sadrian 6224300016Sadrian if (mac->mac_phy.rev <= 2) { 6225300016Sadrian tmp = (mac->mac_phy.rev == 2) ? 0x3B : 0x40; 6226300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_BPHY_CTL3, 6227300016Sadrian ~BWN_NPHY_BPHY_CTL3_SCALE, 6228300016Sadrian tmp << BWN_NPHY_BPHY_CTL3_SCALE_SHIFT); 6229300016Sadrian } 6230300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20); 6231300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20); 6232300016Sadrian 6233300016Sadrian if (siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_SKWRKFEM_BRD || 6234300016Sadrian (siba_get_pci_subvendor(sc->sc_dev) == PCI_VENDOR_APPLE && 6235300016Sadrian siba_get_pci_subdevice(sc->sc_dev) == BCMA_BOARD_TYPE_BCM943224M93)) 6236300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXREALFD, 0xA0); 6237300016Sadrian else 6238300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXREALFD, 0xB8); 6239300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_MIMO_CRSTXEXT, 0xC8); 6240300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PLOAD_CSENSE_EXTLEN, 0x50); 6241300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXRIFS_FRDEL, 0x30); 6242300016Sadrian 6243300016Sadrian if (phy->rev < 8) 6244300016Sadrian bwn_nphy_update_mimo_config(mac, nphy->preamble_override); 6245300016Sadrian 6246300016Sadrian bwn_nphy_update_txrx_chain(mac); 6247300016Sadrian 6248300016Sadrian if (phy->rev < 2) { 6249300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_DUP40_GFBL, 0xAA8); 6250300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_DUP40_BL, 0x9A4); 6251300016Sadrian } 6252300016Sadrian 6253300016Sadrian tmp2 = bwn_current_band(mac); 6254300016Sadrian if (bwn_nphy_ipa(mac)) { 6255300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_PAPD_EN0, 0x1); 6256300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_EPS_TABLE_ADJ0, 0x007F, 6257300016Sadrian nphy->papd_epsilon_offset[0] << 7); 6258300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_PAPD_EN1, 0x1); 6259300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_EPS_TABLE_ADJ1, 0x007F, 6260300016Sadrian nphy->papd_epsilon_offset[1] << 7); 6261300016Sadrian bwn_nphy_int_pa_set_tx_dig_filters(mac); 6262300016Sadrian } else if (phy->rev >= 5) { 6263300016Sadrian bwn_nphy_ext_pa_set_tx_dig_filters(mac); 6264300016Sadrian } 6265300016Sadrian 6266300016Sadrian bwn_nphy_workarounds(mac); 6267300016Sadrian 6268300016Sadrian /* Reset CCA, in init code it differs a little from standard way */ 6269300016Sadrian bwn_phy_force_clock(mac, 1); 6270300016Sadrian tmp = BWN_PHY_READ(mac, BWN_NPHY_BBCFG); 6271300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_BBCFG, tmp | BWN_NPHY_BBCFG_RSTCCA); 6272300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_BBCFG, tmp & ~BWN_NPHY_BBCFG_RSTCCA); 6273300016Sadrian bwn_phy_force_clock(mac, 0); 6274300016Sadrian 6275300016Sadrian bwn_mac_phy_clock_set(mac, true); 6276300016Sadrian 6277300016Sadrian if (phy->rev < 7) { 6278300016Sadrian bwn_nphy_pa_override(mac, false); 6279300016Sadrian bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RX2TX); 6280300016Sadrian bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX); 6281300016Sadrian bwn_nphy_pa_override(mac, true); 6282300016Sadrian } 6283300016Sadrian 6284300016Sadrian bwn_nphy_classifier(mac, 0, 0); 6285300016Sadrian bwn_nphy_read_clip_detection(mac, clip); 6286300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 6287300016Sadrian bwn_nphy_bphy_init(mac); 6288300016Sadrian 6289300016Sadrian tx_pwr_state = nphy->txpwrctrl; 6290300016Sadrian bwn_nphy_tx_power_ctrl(mac, false); 6291300016Sadrian bwn_nphy_tx_power_fix(mac); 6292300016Sadrian bwn_nphy_tx_power_ctl_idle_tssi(mac); 6293300016Sadrian bwn_nphy_tx_power_ctl_setup(mac); 6294300016Sadrian bwn_nphy_tx_gain_table_upload(mac); 6295300016Sadrian 6296300016Sadrian if (nphy->phyrxchain != 3) 6297300016Sadrian bwn_nphy_set_rx_core_state(mac, nphy->phyrxchain); 6298300016Sadrian if (nphy->mphase_cal_phase_id > 0) 6299300016Sadrian ;/* TODO PHY Periodic Calibration Multi-Phase Restart */ 6300300016Sadrian 6301300016Sadrian do_rssi_cal = false; 6302300016Sadrian if (phy->rev >= 3) { 6303300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 6304300016Sadrian do_rssi_cal = !nphy->rssical_chanspec_2G.center_freq; 6305300016Sadrian else 6306300016Sadrian do_rssi_cal = !nphy->rssical_chanspec_5G.center_freq; 6307300016Sadrian 6308300016Sadrian if (do_rssi_cal) 6309300016Sadrian bwn_nphy_rssi_cal(mac); 6310300016Sadrian else 6311300016Sadrian bwn_nphy_restore_rssi_cal(mac); 6312300016Sadrian } else { 6313300016Sadrian bwn_nphy_rssi_cal(mac); 6314300016Sadrian } 6315300016Sadrian 6316300016Sadrian if (!((nphy->measure_hold & 0x6) != 0)) { 6317300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 6318300016Sadrian do_cal = !nphy->iqcal_chanspec_2G.center_freq; 6319300016Sadrian else 6320300016Sadrian do_cal = !nphy->iqcal_chanspec_5G.center_freq; 6321300016Sadrian 6322300016Sadrian if (nphy->mute) 6323300016Sadrian do_cal = false; 6324300016Sadrian 6325300016Sadrian if (do_cal) { 6326300016Sadrian target = bwn_nphy_get_tx_gains(mac); 6327300016Sadrian 6328300016Sadrian if (nphy->antsel_type == 2) 6329300016Sadrian bwn_nphy_superswitch_init(mac, true); 6330300016Sadrian if (nphy->perical != 2) { 6331300016Sadrian bwn_nphy_rssi_cal(mac); 6332300016Sadrian if (phy->rev >= 3) { 6333300016Sadrian nphy->cal_orig_pwr_idx[0] = 6334300016Sadrian nphy->txpwrindex[0].index_internal; 6335300016Sadrian nphy->cal_orig_pwr_idx[1] = 6336300016Sadrian nphy->txpwrindex[1].index_internal; 6337300016Sadrian /* TODO N PHY Pre Calibrate TX Gain */ 6338300016Sadrian target = bwn_nphy_get_tx_gains(mac); 6339300016Sadrian } 6340300016Sadrian if (!bwn_nphy_cal_tx_iq_lo(mac, target, true, false)) 6341300016Sadrian if (bwn_nphy_cal_rx_iq(mac, target, 2, 0) == 0) 6342300016Sadrian bwn_nphy_save_cal(mac); 6343300016Sadrian } else if (nphy->mphase_cal_phase_id == 0) 6344300016Sadrian ;/* N PHY Periodic Calibration with arg 3 */ 6345300016Sadrian } else { 6346300016Sadrian bwn_nphy_restore_cal(mac); 6347300016Sadrian } 6348300016Sadrian } 6349300016Sadrian 6350300016Sadrian bwn_nphy_tx_pwr_ctrl_coef_setup(mac); 6351300016Sadrian bwn_nphy_tx_power_ctrl(mac, tx_pwr_state); 6352300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXMACIF_HOLDOFF, 0x0015); 6353300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXMACDELAY, 0x0320); 6354300016Sadrian if (phy->rev >= 3 && phy->rev <= 6) 6355300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PLOAD_CSENSE_EXTLEN, 0x0032); 6356300016Sadrian bwn_nphy_tx_lpf_bw(mac); 6357300016Sadrian if (phy->rev >= 3) 6358300016Sadrian bwn_nphy_spur_workaround(mac); 6359300016Sadrian 6360300016Sadrian return 0; 6361300016Sadrian} 6362300016Sadrian 6363300016Sadrian/************************************************** 6364300016Sadrian * Channel switching ops. 6365300016Sadrian **************************************************/ 6366300016Sadrian 6367300016Sadrianstatic void bwn_chantab_phy_upload(struct bwn_mac *mac, 6368300016Sadrian const struct bwn_phy_n_sfo_cfg *e) 6369300016Sadrian{ 6370300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_BW1A, e->phy_bw1a); 6371300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_BW2, e->phy_bw2); 6372300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_BW3, e->phy_bw3); 6373300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_BW4, e->phy_bw4); 6374300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_BW5, e->phy_bw5); 6375300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_BW6, e->phy_bw6); 6376300016Sadrian} 6377300016Sadrian 6378300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PmuSpurAvoid */ 6379300016Sadrianstatic void bwn_nphy_pmu_spur_avoid(struct bwn_mac *mac, bool avoid) 6380300016Sadrian{ 6381300016Sadrian struct bwn_softc *sc = mac->mac_sc; 6382300016Sadrian 6383300016Sadrian /* XXX bhnd */ 6384300016Sadrian if (bwn_is_bus_siba(mac)) { 6385300191Sadrian DPRINTF(sc, BWN_DEBUG_RESET, "%s: spuravoid %d\n", __func__, avoid); 6386300016Sadrian siba_pmu_spuravoid_pllupdate(sc->sc_dev, avoid); 6387300016Sadrian } 6388300016Sadrian} 6389300016Sadrian 6390300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */ 6391300016Sadrianstatic void bwn_nphy_channel_setup(struct bwn_mac *mac, 6392300016Sadrian const struct bwn_phy_n_sfo_cfg *e, 6393300016Sadrian struct ieee80211_channel *new_channel) 6394300016Sadrian{ 6395300016Sadrian struct bwn_softc *sc = mac->mac_sc; 6396300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 6397300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 6398300016Sadrian int ch = new_channel->ic_ieee; 6399300016Sadrian uint16_t tmp16; 6400300016Sadrian 6401300016Sadrian if (bwn_channel_band(mac, new_channel) == BWN_BAND_5G) { 6402300191Sadrian DPRINTF(sc, BWN_DEBUG_RESET, "%s: BAND_5G; chan=%d\n", __func__, ch); 6403300016Sadrian /* Switch to 2 GHz for a moment to access BWN_PHY_B_BBCFG */ 6404300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_BANDCTL, ~BWN_NPHY_BANDCTL_5GHZ); 6405300016Sadrian 6406300016Sadrian tmp16 = BWN_READ_2(mac, BWN_PSM_PHY_HDR); 6407300016Sadrian BWN_WRITE_2(mac, BWN_PSM_PHY_HDR, tmp16 | 4); 6408300016Sadrian /* Put BPHY in the reset */ 6409300016Sadrian BWN_PHY_SET(mac, BWN_PHY_B_BBCFG, 6410300016Sadrian BWN_PHY_B_BBCFG_RSTCCA | BWN_PHY_B_BBCFG_RSTRX); 6411300016Sadrian BWN_WRITE_2(mac, BWN_PSM_PHY_HDR, tmp16); 6412300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_BANDCTL, BWN_NPHY_BANDCTL_5GHZ); 6413300016Sadrian } else if (bwn_channel_band(mac, new_channel) == BWN_BAND_2G) { 6414300191Sadrian DPRINTF(sc, BWN_DEBUG_RESET, "%s: BAND_2G; chan=%d\n", __func__, ch); 6415300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_BANDCTL, ~BWN_NPHY_BANDCTL_5GHZ); 6416300016Sadrian tmp16 = BWN_READ_2(mac, BWN_PSM_PHY_HDR); 6417300016Sadrian BWN_WRITE_2(mac, BWN_PSM_PHY_HDR, tmp16 | 4); 6418300016Sadrian /* Take BPHY out of the reset */ 6419300016Sadrian BWN_PHY_MASK(mac, BWN_PHY_B_BBCFG, 6420300016Sadrian (uint16_t)~(BWN_PHY_B_BBCFG_RSTCCA | BWN_PHY_B_BBCFG_RSTRX)); 6421300016Sadrian BWN_WRITE_2(mac, BWN_PSM_PHY_HDR, tmp16); 6422300016Sadrian } else { 6423300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "%s: unknown band?\n", __func__); 6424300016Sadrian } 6425300016Sadrian 6426300016Sadrian bwn_chantab_phy_upload(mac, e); 6427300016Sadrian 6428300016Sadrian if (new_channel->ic_ieee == 14) { 6429300016Sadrian bwn_nphy_classifier(mac, 2, 0); 6430300016Sadrian BWN_PHY_SET(mac, BWN_PHY_B_TEST, 0x0800); 6431300016Sadrian } else { 6432300016Sadrian bwn_nphy_classifier(mac, 2, 2); 6433300016Sadrian if (bwn_channel_band(mac, new_channel) == BWN_BAND_2G) 6434300016Sadrian BWN_PHY_MASK(mac, BWN_PHY_B_TEST, ~0x840); 6435300016Sadrian } 6436300016Sadrian 6437300016Sadrian if (!nphy->txpwrctrl) 6438300016Sadrian bwn_nphy_tx_power_fix(mac); 6439300016Sadrian 6440300016Sadrian if (mac->mac_phy.rev < 3) 6441300016Sadrian bwn_nphy_adjust_lna_gain_table(mac); 6442300016Sadrian 6443300016Sadrian bwn_nphy_tx_lpf_bw(mac); 6444300016Sadrian 6445300016Sadrian if (mac->mac_phy.rev >= 3 && 6446300016Sadrian mac->mac_phy.phy_n->spur_avoid != BWN_SPUR_AVOID_DISABLE) { 6447300016Sadrian uint8_t spuravoid = 0; 6448300016Sadrian 6449300016Sadrian if (mac->mac_phy.phy_n->spur_avoid == BWN_SPUR_AVOID_FORCE) { 6450300016Sadrian spuravoid = 1; 6451300016Sadrian } else if (phy->rev >= 19) { 6452300016Sadrian /* TODO */ 6453300016Sadrian } else if (phy->rev >= 18) { 6454300016Sadrian /* TODO */ 6455300016Sadrian } else if (phy->rev >= 17) { 6456300016Sadrian /* TODO: Off for channels 1-11, but check 12-14! */ 6457300016Sadrian } else if (phy->rev >= 16) { 6458300016Sadrian /* TODO: Off for 2 GHz, but check 5 GHz! */ 6459300016Sadrian } else if (phy->rev >= 7) { 6460300016Sadrian if (!bwn_is_40mhz(mac)) { /* 20MHz */ 6461300016Sadrian if (ch == 13 || ch == 14 || ch == 153) 6462300016Sadrian spuravoid = 1; 6463300016Sadrian } else { /* 40 MHz */ 6464300016Sadrian if (ch == 54) 6465300016Sadrian spuravoid = 1; 6466300016Sadrian } 6467300016Sadrian } else { 6468300016Sadrian if (!bwn_is_40mhz(mac)) { /* 20MHz */ 6469300016Sadrian if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14) 6470300016Sadrian spuravoid = 1; 6471300016Sadrian } else { /* 40MHz */ 6472300016Sadrian if (nphy->aband_spurwar_en && 6473300016Sadrian (ch == 38 || ch == 102 || ch == 118)) 6474300016Sadrian spuravoid = siba_get_chipid(sc->sc_dev) == 0x4716; 6475300016Sadrian } 6476300016Sadrian } 6477300016Sadrian 6478300016Sadrian bwn_nphy_pmu_spur_avoid(mac, spuravoid); 6479300016Sadrian 6480300016Sadrian bwn_mac_switch_freq(mac, spuravoid); 6481300016Sadrian 6482300016Sadrian if (mac->mac_phy.rev == 3 || mac->mac_phy.rev == 4) 6483300016Sadrian bwn_wireless_core_phy_pll_reset(mac); 6484300016Sadrian 6485300016Sadrian if (spuravoid) 6486300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_BBCFG, BWN_NPHY_BBCFG_RSTRX); 6487300016Sadrian else 6488300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_BBCFG, 6489300016Sadrian ~BWN_NPHY_BBCFG_RSTRX & 0xFFFF); 6490300016Sadrian 6491300016Sadrian bwn_nphy_reset_cca(mac); 6492300016Sadrian 6493300016Sadrian /* wl sets useless phy_isspuravoid here */ 6494300016Sadrian } 6495300016Sadrian 6496300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_NDATAT_DUP40, 0x3830); 6497300016Sadrian 6498300016Sadrian if (phy->rev >= 3) 6499300016Sadrian bwn_nphy_spur_workaround(mac); 6500300016Sadrian} 6501300016Sadrian 6502300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */ 6503300016Sadrianstatic int bwn_nphy_set_channel(struct bwn_mac *mac, 6504300016Sadrian struct ieee80211_channel *channel, 6505300016Sadrian bwn_chan_type_t channel_type) 6506300016Sadrian{ 6507300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 6508300016Sadrian 6509300016Sadrian const struct bwn_nphy_channeltab_entry_rev2 *tabent_r2 = NULL; 6510300016Sadrian const struct bwn_nphy_channeltab_entry_rev3 *tabent_r3 = NULL; 6511300016Sadrian const struct bwn_nphy_chantabent_rev7 *tabent_r7 = NULL; 6512300016Sadrian const struct bwn_nphy_chantabent_rev7_2g *tabent_r7_2g = NULL; 6513300016Sadrian 6514300016Sadrian uint8_t tmp; 6515300016Sadrian 6516300016Sadrian if (phy->rev >= 19) { 6517300016Sadrian return -ESRCH; 6518300016Sadrian /* TODO */ 6519300016Sadrian } else if (phy->rev >= 7) { 6520300016Sadrian r2057_get_chantabent_rev7(mac, bwn_get_chan_centre_freq(mac, channel), 6521300016Sadrian &tabent_r7, &tabent_r7_2g); 6522300016Sadrian if (!tabent_r7 && !tabent_r7_2g) 6523300016Sadrian return -ESRCH; 6524300016Sadrian } else if (phy->rev >= 3) { 6525300016Sadrian tabent_r3 = bwn_nphy_get_chantabent_rev3(mac, 6526300016Sadrian bwn_get_chan_centre_freq(mac, channel)); 6527300016Sadrian if (!tabent_r3) 6528300016Sadrian return -ESRCH; 6529300016Sadrian } else { 6530300016Sadrian tabent_r2 = bwn_nphy_get_chantabent_rev2(mac, 6531300016Sadrian channel->ic_ieee); 6532300016Sadrian if (!tabent_r2) 6533300016Sadrian return -ESRCH; 6534300016Sadrian } 6535300016Sadrian 6536300016Sadrian /* Channel is set later in common code, but we need to set it on our 6537300016Sadrian own to let this function's subcalls work properly. */ 6538300016Sadrian#if 0 6539300016Sadrian phy->channel = channel->ic_ieee; 6540300016Sadrian#endif 6541300016Sadrian 6542300016Sadrian#if 0 6543300016Sadrian if (bwn_channel_type_is_40mhz(phy->channel_type) != 6544300016Sadrian bwn_channel_type_is_40mhz(channel_type)) 6545300016Sadrian ; /* TODO: BMAC BW Set (channel_type) */ 6546300016Sadrian#endif 6547300016Sadrian 6548300016Sadrian if (channel_type == BWN_CHAN_TYPE_40_HT_U) { 6549300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RXCTL, BWN_NPHY_RXCTL_BSELU20); 6550300016Sadrian if (phy->rev >= 7) 6551300016Sadrian BWN_PHY_SET(mac, 0x310, 0x8000); 6552300016Sadrian } else if (channel_type == BWN_CHAN_TYPE_40_HT_D) { 6553300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RXCTL, ~BWN_NPHY_RXCTL_BSELU20); 6554300016Sadrian if (phy->rev >= 7) 6555300016Sadrian BWN_PHY_MASK(mac, 0x310, (uint16_t)~0x8000); 6556300016Sadrian } 6557300016Sadrian 6558300016Sadrian if (phy->rev >= 19) { 6559300016Sadrian /* TODO */ 6560300016Sadrian } else if (phy->rev >= 7) { 6561300016Sadrian const struct bwn_phy_n_sfo_cfg *phy_regs = tabent_r7 ? 6562300016Sadrian &(tabent_r7->phy_regs) : &(tabent_r7_2g->phy_regs); 6563300016Sadrian 6564300016Sadrian if (phy->rf_rev <= 4 || phy->rf_rev == 6) { 6565300016Sadrian tmp = (bwn_channel_band(mac, channel) == BWN_BAND_5G) ? 2 : 0; 6566300016Sadrian BWN_RF_SETMASK(mac, R2057_TIA_CONFIG_CORE0, ~2, tmp); 6567300016Sadrian BWN_RF_SETMASK(mac, R2057_TIA_CONFIG_CORE1, ~2, tmp); 6568300016Sadrian } 6569300016Sadrian 6570300016Sadrian bwn_radio_2057_setup(mac, tabent_r7, tabent_r7_2g); 6571300016Sadrian bwn_nphy_channel_setup(mac, phy_regs, channel); 6572300016Sadrian } else if (phy->rev >= 3) { 6573300016Sadrian tmp = (bwn_channel_band(mac, channel) == BWN_BAND_5G) ? 4 : 0; 6574300016Sadrian BWN_RF_SETMASK(mac, 0x08, 0xFFFB, tmp); 6575300016Sadrian bwn_radio_2056_setup(mac, tabent_r3); 6576300016Sadrian bwn_nphy_channel_setup(mac, &(tabent_r3->phy_regs), channel); 6577300016Sadrian } else { 6578300016Sadrian tmp = (bwn_channel_band(mac, channel) == BWN_BAND_5G) ? 0x0020 : 0x0050; 6579300016Sadrian BWN_RF_SETMASK(mac, B2055_MASTER1, 0xFF8F, tmp); 6580300016Sadrian bwn_radio_2055_setup(mac, tabent_r2); 6581300016Sadrian bwn_nphy_channel_setup(mac, &(tabent_r2->phy_regs), channel); 6582300016Sadrian } 6583300016Sadrian 6584300016Sadrian return 0; 6585300016Sadrian} 6586300016Sadrian 6587300016Sadrian/************************************************** 6588300016Sadrian * Basic PHY ops. 6589300016Sadrian **************************************************/ 6590300016Sadrian 6591300016Sadrianint 6592300016Sadrianbwn_nphy_op_allocate(struct bwn_mac *mac) 6593300016Sadrian{ 6594300016Sadrian struct bwn_phy_n *nphy; 6595300016Sadrian 6596300016Sadrian nphy = malloc(sizeof(*nphy), M_DEVBUF, M_ZERO | M_NOWAIT); 6597300016Sadrian if (!nphy) 6598300016Sadrian return -ENOMEM; 6599300016Sadrian 6600300016Sadrian mac->mac_phy.phy_n = nphy; 6601300016Sadrian 6602300016Sadrian return 0; 6603300016Sadrian} 6604300016Sadrian 6605300016Sadrianvoid 6606300016Sadrianbwn_nphy_op_prepare_structs(struct bwn_mac *mac) 6607300016Sadrian{ 6608300016Sadrian struct bwn_softc *sc = mac->mac_sc; 6609300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 6610300016Sadrian struct bwn_phy_n *nphy = phy->phy_n; 6611300016Sadrian 6612300016Sadrian memset(nphy, 0, sizeof(*nphy)); 6613300016Sadrian 6614300016Sadrian nphy->hang_avoid = (phy->rev == 3 || phy->rev == 4); 6615300016Sadrian nphy->spur_avoid = (phy->rev >= 3) ? 6616300016Sadrian BWN_SPUR_AVOID_AUTO : BWN_SPUR_AVOID_DISABLE; 6617300016Sadrian nphy->gain_boost = true; /* this way we follow wl, assume it is true */ 6618300016Sadrian nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */ 6619300016Sadrian nphy->phyrxchain = 3; /* to avoid bwn_nphy_set_rx_core_state like wl */ 6620300016Sadrian nphy->perical = 2; /* avoid additional rssi cal on init (like wl) */ 6621300016Sadrian /* 128 can mean disabled-by-default state of TX pwr ctl. Max value is 6622300016Sadrian * 0x7f == 127 and we check for 128 when restoring TX pwr ctl. */ 6623300016Sadrian nphy->tx_pwr_idx[0] = 128; 6624300016Sadrian nphy->tx_pwr_idx[1] = 128; 6625300016Sadrian 6626300016Sadrian /* Hardware TX power control and 5GHz power gain */ 6627300016Sadrian nphy->txpwrctrl = false; 6628300016Sadrian nphy->pwg_gain_5ghz = false; 6629300016Sadrian if (mac->mac_phy.rev >= 3 || 6630300016Sadrian (siba_get_pci_subvendor(sc->sc_dev) == PCI_VENDOR_APPLE && 6631300016Sadrian (siba_get_revid(sc->sc_dev) == 11 || siba_get_revid(sc->sc_dev) == 12))) { 6632300016Sadrian nphy->txpwrctrl = true; 6633300016Sadrian nphy->pwg_gain_5ghz = true; 6634300016Sadrian } else if (siba_sprom_get_rev(sc->sc_dev) >= 4) { 6635300016Sadrian if (mac->mac_phy.rev >= 2 && 6636300016Sadrian (siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_TXPWRCTRL_EN)) { 6637300016Sadrian nphy->txpwrctrl = true; 6638300448Sadrian if (bwn_is_bus_siba(mac) && 6639300448Sadrian (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI)) { 6640300448Sadrian if ((siba_get_pci_device(sc->sc_dev) == 0x4328) || 6641300448Sadrian (siba_get_pci_device(sc->sc_dev) == 0x432a)) 6642300016Sadrian nphy->pwg_gain_5ghz = true; 6643300016Sadrian } 6644300016Sadrian } else if (siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_5G_PWRGAIN) { 6645300016Sadrian nphy->pwg_gain_5ghz = true; 6646300016Sadrian } 6647300016Sadrian } 6648300016Sadrian 6649300016Sadrian if (mac->mac_phy.rev >= 3) { 6650300016Sadrian nphy->ipa2g_on = siba_sprom_get_fem_2ghz_extpa_gain(sc->sc_dev) == 2; 6651300016Sadrian nphy->ipa5g_on = siba_sprom_get_fem_5ghz_extpa_gain(sc->sc_dev) == 2; 6652300016Sadrian } 6653300016Sadrian} 6654300016Sadrian 6655300016Sadrianvoid 6656300016Sadrianbwn_nphy_op_free(struct bwn_mac *mac) 6657300016Sadrian{ 6658300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 6659300016Sadrian struct bwn_phy_n *nphy = phy->phy_n; 6660300016Sadrian 6661300016Sadrian free(nphy, M_DEVBUF); 6662300016Sadrian phy->phy_n = NULL; 6663300016Sadrian} 6664300016Sadrian 6665300016Sadrianint 6666300016Sadrianbwn_nphy_op_init(struct bwn_mac *mac) 6667300016Sadrian{ 6668300016Sadrian return bwn_phy_initn(mac); 6669300016Sadrian} 6670300016Sadrian 6671300016Sadrianstatic inline void check_phyreg(struct bwn_mac *mac, uint16_t offset) 6672300016Sadrian{ 6673300016Sadrian#ifdef BWN_DEBUG 6674300016Sadrian if ((offset & BWN_PHYROUTE_MASK) == BWN_PHYROUTE_OFDM_GPHY) { 6675300016Sadrian /* OFDM registers are onnly available on A/G-PHYs */ 6676300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "Invalid OFDM PHY access at " 6677300016Sadrian "0x%04X on N-PHY\n", offset); 6678300016Sadrian } 6679300016Sadrian if ((offset & BWN_PHYROUTE_MASK) == BWN_PHYROUTE_EXT_GPHY) { 6680300016Sadrian /* Ext-G registers are only available on G-PHYs */ 6681300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "Invalid EXT-G PHY access at " 6682300016Sadrian "0x%04X on N-PHY\n", offset); 6683300016Sadrian } 6684300016Sadrian#endif /* BWN_DEBUG */ 6685300016Sadrian} 6686300016Sadrian 6687300016Sadrianvoid 6688300016Sadrianbwn_nphy_op_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask, 6689300016Sadrian uint16_t set) 6690300016Sadrian{ 6691300016Sadrian check_phyreg(mac, reg); 6692300016Sadrian BWN_WRITE_2_F(mac, BWN_PHYCTL, reg); 6693300016Sadrian BWN_WRITE_SETMASK2(mac, BWN_PHYDATA, mask, set); 6694300016Sadrian} 6695300016Sadrian 6696300016Sadrian#if 0 6697300016Sadrianuint16_t 6698300016Sadrianbwn_nphy_op_radio_read(struct bwn_mac *mac, uint16_t reg) 6699300016Sadrian{ 6700300016Sadrian /* Register 1 is a 32-bit register. */ 6701300016Sadrian if (mac->mac_phy.rev < 7 && reg == 1) { 6702300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "%s: bad reg access\n", __func__); 6703300016Sadrian } 6704300016Sadrian 6705300016Sadrian if (mac->mac_phy.rev >= 7) 6706300016Sadrian reg |= 0x200; /* Radio 0x2057 */ 6707300016Sadrian else 6708300016Sadrian reg |= 0x100; 6709300016Sadrian 6710300016Sadrian BWN_WRITE_2_F(mac, BWN_RFCTL, reg); 6711300016Sadrian return BWN_READ_2(mac, BWN_RFDATALO); 6712300016Sadrian} 6713300016Sadrian#endif 6714300016Sadrian 6715300016Sadrian#if 0 6716300016Sadrianvoid 6717300016Sadrianbwn_nphy_op_radio_write(struct bwn_mac *mac, uint16_t reg, uint16_t value) 6718300016Sadrian{ 6719300016Sadrian /* Register 1 is a 32-bit register. */ 6720300016Sadrian if (mac->mac_phy.rev < 7 && reg == 1) { 6721300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "%s: bad reg access\n", __func__); 6722300016Sadrian } 6723300016Sadrian 6724300016Sadrian BWN_WRITE_2_F(mac, BWN_RFCTL, reg); 6725300016Sadrian BWN_WRITE_2(mac, BWN_RFDATALO, value); 6726300016Sadrian} 6727300016Sadrian#endif 6728300016Sadrian 6729300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */ 6730300016Sadrianvoid 6731300016Sadrianbwn_nphy_op_software_rfkill(struct bwn_mac *mac, bool active) 6732300016Sadrian{ 6733300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 6734300016Sadrian 6735300016Sadrian if (BWN_READ_4(mac, BWN_MACCTL) & BWN_MACCTL_ON) 6736300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "MAC not suspended\n"); 6737300016Sadrian 6738300191Sadrian DPRINTF(mac->mac_sc, BWN_DEBUG_RESET | BWN_DEBUG_PHY, 6739300191Sadrian "%s: called; rev=%d, rf_on=%d, active=%d\n", __func__, 6740300191Sadrian phy->rev, mac->mac_phy.rf_on, active); 6741300191Sadrian 6742300192Sadrian /* 6743300192Sadrian * XXX TODO: don't bother doing RF programming if it's 6744300192Sadrian * already done. But, bwn(4) currently sets rf_on in the 6745300192Sadrian * PHY setup and leaves it on after startup, which causes 6746300192Sadrian * the below to not init the 2056/2057 radios. 6747300192Sadrian */ 6748300016Sadrian if (active) { 6749300016Sadrian if (phy->rev >= 19) { 6750300016Sadrian /* TODO */ 6751300016Sadrian } else if (phy->rev >= 7) { 6752300192Sadrian// if (!mac->mac_phy.rf_on) 6753300016Sadrian bwn_radio_2057_init(mac); 6754300016Sadrian bwn_switch_channel(mac, bwn_get_chan(mac)); 6755300016Sadrian } else if (phy->rev >= 3) { 6756300192Sadrian// if (!mac->mac_phy.rf_on) 6757300016Sadrian bwn_radio_init2056(mac); 6758300016Sadrian bwn_switch_channel(mac, bwn_get_chan(mac)); 6759300016Sadrian } else { 6760300016Sadrian bwn_radio_init2055(mac); 6761300016Sadrian } 6762300016Sadrian } else { 6763300016Sadrian if (phy->rev >= 19) { 6764300016Sadrian /* TODO */ 6765300016Sadrian } else if (phy->rev >= 8) { 6766300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, 6767300016Sadrian ~BWN_NPHY_RFCTL_CMD_CHIP0PU); 6768300016Sadrian } else if (phy->rev >= 7) { 6769300016Sadrian /* Nothing needed */ 6770300016Sadrian } else if (phy->rev >= 3) { 6771300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, 6772300016Sadrian ~BWN_NPHY_RFCTL_CMD_CHIP0PU); 6773300016Sadrian 6774300016Sadrian BWN_RF_MASK(mac, 0x09, ~0x2); 6775300016Sadrian 6776300016Sadrian BWN_RF_WRITE(mac, 0x204D, 0); 6777300016Sadrian BWN_RF_WRITE(mac, 0x2053, 0); 6778300016Sadrian BWN_RF_WRITE(mac, 0x2058, 0); 6779300016Sadrian BWN_RF_WRITE(mac, 0x205E, 0); 6780300016Sadrian BWN_RF_MASK(mac, 0x2062, ~0xF0); 6781300016Sadrian BWN_RF_WRITE(mac, 0x2064, 0); 6782300016Sadrian 6783300016Sadrian BWN_RF_WRITE(mac, 0x304D, 0); 6784300016Sadrian BWN_RF_WRITE(mac, 0x3053, 0); 6785300016Sadrian BWN_RF_WRITE(mac, 0x3058, 0); 6786300016Sadrian BWN_RF_WRITE(mac, 0x305E, 0); 6787300016Sadrian BWN_RF_MASK(mac, 0x3062, ~0xF0); 6788300016Sadrian BWN_RF_WRITE(mac, 0x3064, 0); 6789300016Sadrian } 6790300016Sadrian } 6791300016Sadrian} 6792300016Sadrian 6793300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */ 6794300016Sadrianvoid 6795300016Sadrianbwn_nphy_op_switch_analog(struct bwn_mac *mac, bool on) 6796300016Sadrian{ 6797300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 6798300016Sadrian uint16_t override = on ? 0x0 : 0x7FFF; 6799300016Sadrian uint16_t core = on ? 0xD : 0x00FD; 6800300016Sadrian 6801300016Sadrian if (phy->rev >= 19) { 6802300016Sadrian /* TODO */ 6803300016Sadrian device_printf(mac->mac_sc->sc_dev, "%s: TODO\n", __func__); 6804300016Sadrian } else if (phy->rev >= 3) { 6805300016Sadrian if (on) { 6806300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, core); 6807300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, override); 6808300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, core); 6809300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, override); 6810300016Sadrian } else { 6811300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, override); 6812300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, core); 6813300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, override); 6814300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, core); 6815300016Sadrian } 6816300016Sadrian } else { 6817300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, override); 6818300016Sadrian } 6819300016Sadrian} 6820300016Sadrian 6821300016Sadrianint 6822300016Sadrianbwn_nphy_op_switch_channel(struct bwn_mac *mac, unsigned int new_channel) 6823300016Sadrian{ 6824300016Sadrian struct ieee80211_channel *channel = bwn_get_channel(mac); 6825300016Sadrian bwn_chan_type_t channel_type = bwn_get_chan_type(mac, NULL); 6826300016Sadrian 6827300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 6828300016Sadrian if ((new_channel < 1) || (new_channel > 14)) 6829300016Sadrian return -EINVAL; 6830300016Sadrian } else { 6831300016Sadrian if (new_channel > 200) 6832300016Sadrian return -EINVAL; 6833300016Sadrian } 6834300016Sadrian 6835300016Sadrian return bwn_nphy_set_channel(mac, channel, channel_type); 6836300016Sadrian} 6837300016Sadrian 6838300016Sadrian#if 0 6839300016Sadrianunsigned int 6840300016Sadrianbwn_nphy_op_get_default_chan(struct bwn_mac *mac) 6841300016Sadrian{ 6842300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 6843300016Sadrian return 1; 6844300016Sadrian return 36; 6845300016Sadrian} 6846300016Sadrian#endif 6847