if_bwn_phy_n_core.c revision 300190
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: head/sys/gnu/dev/bwn/phy_n/if_bwn_phy_n_core.c 300190 2016-05-19 04:45:50Z adrian $"); 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; 1409300016Sadrian 1410300016Sadrian mast2 = BWN_RF_READ(mac, B2056_SYN_PLL_MAST2); 1411300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_MAST2, mast2 | 0x7); 1412300016Sadrian 1413300016Sadrian DELAY(10); 1414300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_RCAL_MASTER, 0x01); 1415300016Sadrian DELAY(10); 1416300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_RCAL_MASTER, 0x09); 1417300016Sadrian 1418300016Sadrian if (!bwn_radio_wait_value(mac, B2056_SYN_RCAL_CODE_OUT, 0x80, 0x80, 100, 1419300016Sadrian 1000000)) { 1420300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "Radio recalibration timeout\n"); 1421300016Sadrian return 0; 1422300016Sadrian } 1423300016Sadrian 1424300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_RCAL_MASTER, 0x01); 1425300016Sadrian tmp = BWN_RF_READ(mac, B2056_SYN_RCAL_CODE_OUT); 1426300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_RCAL_MASTER, 0x00); 1427300016Sadrian 1428300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_PLL_MAST2, mast2); 1429300016Sadrian 1430300016Sadrian return tmp & 0x1f; 1431300016Sadrian} 1432300016Sadrian 1433300016Sadrianstatic void bwn_radio_init2056_pre(struct bwn_mac *mac) 1434300016Sadrian{ 1435300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, 1436300016Sadrian ~BWN_NPHY_RFCTL_CMD_CHIP0PU); 1437300016Sadrian /* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */ 1438300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, 1439300016Sadrian BWN_NPHY_RFCTL_CMD_OEPORFORCE); 1440300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, 1441300016Sadrian ~BWN_NPHY_RFCTL_CMD_OEPORFORCE); 1442300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, 1443300016Sadrian BWN_NPHY_RFCTL_CMD_CHIP0PU); 1444300016Sadrian} 1445300016Sadrian 1446300016Sadrianstatic void bwn_radio_init2056_post(struct bwn_mac *mac) 1447300016Sadrian{ 1448300016Sadrian BWN_RF_SET(mac, B2056_SYN_COM_CTRL, 0xB); 1449300016Sadrian BWN_RF_SET(mac, B2056_SYN_COM_PU, 0x2); 1450300016Sadrian BWN_RF_SET(mac, B2056_SYN_COM_RESET, 0x2); 1451300016Sadrian DELAY(1000); 1452300016Sadrian BWN_RF_MASK(mac, B2056_SYN_COM_RESET, ~0x2); 1453300016Sadrian BWN_RF_MASK(mac, B2056_SYN_PLL_MAST2, ~0xFC); 1454300016Sadrian BWN_RF_MASK(mac, B2056_SYN_RCCAL_CTRL0, ~0x1); 1455300016Sadrian if (mac->mac_phy.phy_do_full_init) 1456300016Sadrian bwn_radio_2056_rcal(mac); 1457300016Sadrian} 1458300016Sadrian 1459300016Sadrian/* 1460300016Sadrian * Initialize a Broadcom 2056 N-radio 1461300016Sadrian * http://bcm-v4.sipsolutions.net/802.11/Radio/2056/Init 1462300016Sadrian */ 1463300016Sadrianstatic void bwn_radio_init2056(struct bwn_mac *mac) 1464300016Sadrian{ 1465300016Sadrian bwn_radio_init2056_pre(mac); 1466300016Sadrian b2056_upload_inittabs(mac, 0, 0); 1467300016Sadrian bwn_radio_init2056_post(mac); 1468300016Sadrian} 1469300016Sadrian 1470300016Sadrian/************************************************** 1471300016Sadrian * Radio 0x2055 1472300016Sadrian **************************************************/ 1473300016Sadrian 1474300016Sadrianstatic void bwn_chantab_radio_upload(struct bwn_mac *mac, 1475300016Sadrian const struct bwn_nphy_channeltab_entry_rev2 *e) 1476300016Sadrian{ 1477300016Sadrian BWN_RF_WRITE(mac, B2055_PLL_REF, e->radio_pll_ref); 1478300016Sadrian BWN_RF_WRITE(mac, B2055_RF_PLLMOD0, e->radio_rf_pllmod0); 1479300016Sadrian BWN_RF_WRITE(mac, B2055_RF_PLLMOD1, e->radio_rf_pllmod1); 1480300016Sadrian BWN_RF_WRITE(mac, B2055_VCO_CAPTAIL, e->radio_vco_captail); 1481300016Sadrian BWN_READ_4(mac, BWN_MACCTL); /* flush writes */ 1482300016Sadrian 1483300016Sadrian BWN_RF_WRITE(mac, B2055_VCO_CAL1, e->radio_vco_cal1); 1484300016Sadrian BWN_RF_WRITE(mac, B2055_VCO_CAL2, e->radio_vco_cal2); 1485300016Sadrian BWN_RF_WRITE(mac, B2055_PLL_LFC1, e->radio_pll_lfc1); 1486300016Sadrian BWN_RF_WRITE(mac, B2055_PLL_LFR1, e->radio_pll_lfr1); 1487300016Sadrian BWN_READ_4(mac, BWN_MACCTL); /* flush writes */ 1488300016Sadrian 1489300016Sadrian BWN_RF_WRITE(mac, B2055_PLL_LFC2, e->radio_pll_lfc2); 1490300016Sadrian BWN_RF_WRITE(mac, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf); 1491300016Sadrian BWN_RF_WRITE(mac, B2055_LGEN_TUNE1, e->radio_lgen_tune1); 1492300016Sadrian BWN_RF_WRITE(mac, B2055_LGEN_TUNE2, e->radio_lgen_tune2); 1493300016Sadrian BWN_READ_4(mac, BWN_MACCTL); /* flush writes */ 1494300016Sadrian 1495300016Sadrian BWN_RF_WRITE(mac, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune); 1496300016Sadrian BWN_RF_WRITE(mac, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune); 1497300016Sadrian BWN_RF_WRITE(mac, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1); 1498300016Sadrian BWN_RF_WRITE(mac, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn); 1499300016Sadrian BWN_READ_4(mac, BWN_MACCTL); /* flush writes */ 1500300016Sadrian 1501300016Sadrian BWN_RF_WRITE(mac, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim); 1502300016Sadrian BWN_RF_WRITE(mac, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune); 1503300016Sadrian BWN_RF_WRITE(mac, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune); 1504300016Sadrian BWN_RF_WRITE(mac, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1); 1505300016Sadrian BWN_READ_4(mac, BWN_MACCTL); /* flush writes */ 1506300016Sadrian 1507300016Sadrian BWN_RF_WRITE(mac, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn); 1508300016Sadrian BWN_RF_WRITE(mac, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim); 1509300016Sadrian} 1510300016Sadrian 1511300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */ 1512300016Sadrianstatic void bwn_radio_2055_setup(struct bwn_mac *mac, 1513300016Sadrian const struct bwn_nphy_channeltab_entry_rev2 *e) 1514300016Sadrian{ 1515300016Sadrian 1516300016Sadrian if (mac->mac_phy.rev >= 3) { 1517300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "%s: phy rev %d out of range\n", 1518300016Sadrian __func__, 1519300016Sadrian mac->mac_phy.rev); 1520300016Sadrian } 1521300016Sadrian 1522300016Sadrian DPRINTF(mac->mac_sc, BWN_DEBUG_RF, "%s: called\n", __func__); 1523300016Sadrian 1524300016Sadrian bwn_chantab_radio_upload(mac, e); 1525300016Sadrian DELAY(50); 1526300016Sadrian BWN_RF_WRITE(mac, B2055_VCO_CAL10, 0x05); 1527300016Sadrian BWN_RF_WRITE(mac, B2055_VCO_CAL10, 0x45); 1528300016Sadrian BWN_READ_4(mac, BWN_MACCTL); /* flush writes */ 1529300016Sadrian BWN_RF_WRITE(mac, B2055_VCO_CAL10, 0x65); 1530300016Sadrian DELAY(300); 1531300016Sadrian} 1532300016Sadrian 1533300016Sadrianstatic void bwn_radio_init2055_pre(struct bwn_mac *mac) 1534300016Sadrian{ 1535300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, 1536300016Sadrian ~BWN_NPHY_RFCTL_CMD_PORFORCE); 1537300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, 1538300016Sadrian BWN_NPHY_RFCTL_CMD_CHIP0PU | 1539300016Sadrian BWN_NPHY_RFCTL_CMD_OEPORFORCE); 1540300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, 1541300016Sadrian BWN_NPHY_RFCTL_CMD_PORFORCE); 1542300016Sadrian} 1543300016Sadrian 1544300016Sadrianstatic void bwn_radio_init2055_post(struct bwn_mac *mac) 1545300016Sadrian{ 1546300016Sadrian struct bwn_softc *sc = mac->mac_sc; 1547300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 1548300016Sadrian bool workaround = false; 1549300016Sadrian 1550300016Sadrian if (siba_get_revid(sc->sc_dev) < 4) 1551300016Sadrian workaround = 1552300016Sadrian (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) 1553300016Sadrian && (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4321) 1554300016Sadrian && (siba_sprom_get_brev(sc->sc_dev) >= 0x41); 1555300016Sadrian else 1556300016Sadrian workaround = 1557300016Sadrian !(siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_RXBB_INT_REG_DIS); 1558300016Sadrian 1559300016Sadrian BWN_RF_MASK(mac, B2055_MASTER1, 0xFFF3); 1560300016Sadrian if (workaround) { 1561300016Sadrian BWN_RF_MASK(mac, B2055_C1_RX_BB_REG, 0x7F); 1562300016Sadrian BWN_RF_MASK(mac, B2055_C2_RX_BB_REG, 0x7F); 1563300016Sadrian } 1564300016Sadrian BWN_RF_SETMASK(mac, B2055_RRCCAL_NOPTSEL, 0xFFC0, 0x2C); 1565300016Sadrian BWN_RF_WRITE(mac, B2055_CAL_MISC, 0x3C); 1566300016Sadrian BWN_RF_MASK(mac, B2055_CAL_MISC, 0xFFBE); 1567300016Sadrian BWN_RF_SET(mac, B2055_CAL_LPOCTL, 0x80); 1568300016Sadrian BWN_RF_SET(mac, B2055_CAL_MISC, 0x1); 1569300016Sadrian DELAY(1000); 1570300016Sadrian BWN_RF_SET(mac, B2055_CAL_MISC, 0x40); 1571300016Sadrian if (!bwn_radio_wait_value(mac, B2055_CAL_COUT2, 0x80, 0x80, 10, 2000)) 1572300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "radio post init timeout\n"); 1573300016Sadrian BWN_RF_MASK(mac, B2055_CAL_LPOCTL, 0xFF7F); 1574300016Sadrian bwn_switch_channel(mac, bwn_get_chan(mac)); 1575300016Sadrian BWN_RF_WRITE(mac, B2055_C1_RX_BB_LPF, 0x9); 1576300016Sadrian BWN_RF_WRITE(mac, B2055_C2_RX_BB_LPF, 0x9); 1577300016Sadrian BWN_RF_WRITE(mac, B2055_C1_RX_BB_MIDACHP, 0x83); 1578300016Sadrian BWN_RF_WRITE(mac, B2055_C2_RX_BB_MIDACHP, 0x83); 1579300016Sadrian BWN_RF_SETMASK(mac, B2055_C1_LNA_GAINBST, 0xFFF8, 0x6); 1580300016Sadrian BWN_RF_SETMASK(mac, B2055_C2_LNA_GAINBST, 0xFFF8, 0x6); 1581300016Sadrian if (!nphy->gain_boost) { 1582300016Sadrian BWN_RF_SET(mac, B2055_C1_RX_RFSPC1, 0x2); 1583300016Sadrian BWN_RF_SET(mac, B2055_C2_RX_RFSPC1, 0x2); 1584300016Sadrian } else { 1585300016Sadrian BWN_RF_MASK(mac, B2055_C1_RX_RFSPC1, 0xFFFD); 1586300016Sadrian BWN_RF_MASK(mac, B2055_C2_RX_RFSPC1, 0xFFFD); 1587300016Sadrian } 1588300016Sadrian DELAY(2); 1589300016Sadrian} 1590300016Sadrian 1591300016Sadrian/* 1592300016Sadrian * Initialize a Broadcom 2055 N-radio 1593300016Sadrian * http://bcm-v4.sipsolutions.net/802.11/Radio/2055/Init 1594300016Sadrian */ 1595300016Sadrianstatic void bwn_radio_init2055(struct bwn_mac *mac) 1596300016Sadrian{ 1597300016Sadrian bwn_radio_init2055_pre(mac); 1598300016Sadrian if (mac->mac_status < BWN_MAC_STATUS_INITED) { 1599300016Sadrian /* Follow wl, not specs. Do not force uploading all regs */ 1600300016Sadrian b2055_upload_inittab(mac, 0, 0); 1601300016Sadrian } else { 1602300016Sadrian bool ghz5 = bwn_current_band(mac) == BWN_BAND_5G; 1603300016Sadrian b2055_upload_inittab(mac, ghz5, 0); 1604300016Sadrian } 1605300016Sadrian bwn_radio_init2055_post(mac); 1606300016Sadrian} 1607300016Sadrian 1608300016Sadrian/************************************************** 1609300016Sadrian * Samples 1610300016Sadrian **************************************************/ 1611300016Sadrian 1612300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/LoadSampleTable */ 1613300016Sadrianstatic int bwn_nphy_load_samples(struct bwn_mac *mac, 1614300016Sadrian struct bwn_c32 *samples, uint16_t len) { 1615300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 1616300016Sadrian uint16_t i; 1617300016Sadrian uint32_t *data; 1618300016Sadrian 1619300016Sadrian data = malloc(len * sizeof(uint32_t), M_DEVBUF, M_NOWAIT | M_ZERO); 1620300016Sadrian if (!data) { 1621300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "allocation for samples loading failed\n"); 1622300016Sadrian return -ENOMEM; 1623300016Sadrian } 1624300016Sadrian if (nphy->hang_avoid) 1625300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 1); 1626300016Sadrian 1627300016Sadrian for (i = 0; i < len; i++) { 1628300016Sadrian data[i] = (samples[i].i & 0x3FF << 10); 1629300016Sadrian data[i] |= samples[i].q & 0x3FF; 1630300016Sadrian } 1631300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB32(17, 0), len, data); 1632300016Sadrian 1633300016Sadrian free(data, M_DEVBUF); 1634300016Sadrian if (nphy->hang_avoid) 1635300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 0); 1636300016Sadrian return 0; 1637300016Sadrian} 1638300016Sadrian 1639300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GenLoadSamples */ 1640300016Sadrianstatic uint16_t bwn_nphy_gen_load_samples(struct bwn_mac *mac, uint32_t freq, uint16_t max, 1641300016Sadrian bool test) 1642300016Sadrian{ 1643300016Sadrian int i; 1644300016Sadrian uint16_t bw, len, rot, angle; 1645300016Sadrian struct bwn_c32 *samples; 1646300016Sadrian 1647300016Sadrian bw = bwn_is_40mhz(mac) ? 40 : 20; 1648300016Sadrian len = bw << 3; 1649300016Sadrian 1650300016Sadrian if (test) { 1651300016Sadrian if (BWN_PHY_READ(mac, BWN_NPHY_BBCFG) & BWN_NPHY_BBCFG_RSTRX) 1652300016Sadrian bw = 82; 1653300016Sadrian else 1654300016Sadrian bw = 80; 1655300016Sadrian 1656300016Sadrian if (bwn_is_40mhz(mac)) 1657300016Sadrian bw <<= 1; 1658300016Sadrian 1659300016Sadrian len = bw << 1; 1660300016Sadrian } 1661300016Sadrian 1662300016Sadrian samples = malloc(len * sizeof(struct bwn_c32), M_DEVBUF, M_NOWAIT | M_ZERO); 1663300016Sadrian if (!samples) { 1664300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "allocation for samples generation failed\n"); 1665300016Sadrian return 0; 1666300016Sadrian } 1667300016Sadrian rot = (((freq * 36) / bw) << 16) / 100; 1668300016Sadrian angle = 0; 1669300016Sadrian 1670300016Sadrian for (i = 0; i < len; i++) { 1671300016Sadrian samples[i] = bwn_cordic(angle); 1672300016Sadrian angle += rot; 1673300016Sadrian samples[i].q = CORDIC_CONVERT(samples[i].q * max); 1674300016Sadrian samples[i].i = CORDIC_CONVERT(samples[i].i * max); 1675300016Sadrian } 1676300016Sadrian 1677300016Sadrian i = bwn_nphy_load_samples(mac, samples, len); 1678300016Sadrian free(samples, M_DEVBUF); 1679300016Sadrian return (i < 0) ? 0 : len; 1680300016Sadrian} 1681300016Sadrian 1682300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */ 1683300016Sadrianstatic void bwn_nphy_run_samples(struct bwn_mac *mac, uint16_t samps, uint16_t loops, 1684300016Sadrian uint16_t wait, bool iqmode, bool dac_test, 1685300016Sadrian bool modify_bbmult) 1686300016Sadrian{ 1687300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 1688300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 1689300016Sadrian int i; 1690300016Sadrian uint16_t seq_mode; 1691300016Sadrian uint32_t tmp; 1692300016Sadrian 1693300016Sadrian bwn_nphy_stay_in_carrier_search(mac, true); 1694300016Sadrian 1695300016Sadrian if (phy->rev >= 7) { 1696300016Sadrian bool lpf_bw3, lpf_bw4; 1697300016Sadrian 1698300016Sadrian lpf_bw3 = BWN_PHY_READ(mac, BWN_NPHY_REV7_RF_CTL_OVER3) & 0x80; 1699300016Sadrian lpf_bw4 = BWN_PHY_READ(mac, BWN_NPHY_REV7_RF_CTL_OVER4) & 0x80; 1700300016Sadrian 1701300016Sadrian if (lpf_bw3 || lpf_bw4) { 1702300016Sadrian /* TODO */ 1703300016Sadrian } else { 1704300016Sadrian uint16_t value = bwn_nphy_read_lpf_ctl(mac, 0); 1705300016Sadrian if (phy->rev >= 19) 1706300016Sadrian bwn_nphy_rf_ctl_override_rev19(mac, 0x80, value, 1707300016Sadrian 0, false, 1); 1708300016Sadrian else 1709300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x80, value, 1710300016Sadrian 0, false, 1); 1711300016Sadrian nphy->lpf_bw_overrode_for_sample_play = true; 1712300016Sadrian } 1713300016Sadrian } 1714300016Sadrian 1715300016Sadrian if ((nphy->bb_mult_save & 0x80000000) == 0) { 1716300016Sadrian tmp = bwn_ntab_read(mac, BWN_NTAB16(15, 87)); 1717300016Sadrian nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000; 1718300016Sadrian } 1719300016Sadrian 1720300016Sadrian if (modify_bbmult) { 1721300016Sadrian tmp = !bwn_is_40mhz(mac) ? 0x6464 : 0x4747; 1722300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(15, 87), tmp); 1723300016Sadrian } 1724300016Sadrian 1725300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_SAMP_DEPCNT, (samps - 1)); 1726300016Sadrian 1727300016Sadrian if (loops != 0xFFFF) 1728300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_SAMP_LOOPCNT, (loops - 1)); 1729300016Sadrian else 1730300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_SAMP_LOOPCNT, loops); 1731300016Sadrian 1732300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_SAMP_WAITCNT, wait); 1733300016Sadrian 1734300016Sadrian seq_mode = BWN_PHY_READ(mac, BWN_NPHY_RFSEQMODE); 1735300016Sadrian 1736300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFSEQMODE, BWN_NPHY_RFSEQMODE_CAOVER); 1737300016Sadrian if (iqmode) { 1738300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0x7FFF); 1739300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0x8000); 1740300016Sadrian } else { 1741300016Sadrian tmp = dac_test ? 5 : 1; 1742300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_SAMP_CMD, tmp); 1743300016Sadrian } 1744300016Sadrian for (i = 0; i < 100; i++) { 1745300016Sadrian if (!(BWN_PHY_READ(mac, BWN_NPHY_RFSEQST) & 1)) { 1746300016Sadrian i = 0; 1747300016Sadrian break; 1748300016Sadrian } 1749300016Sadrian DELAY(10); 1750300016Sadrian } 1751300016Sadrian if (i) 1752300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "run samples timeout\n"); 1753300016Sadrian 1754300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFSEQMODE, seq_mode); 1755300016Sadrian 1756300016Sadrian bwn_nphy_stay_in_carrier_search(mac, false); 1757300016Sadrian} 1758300016Sadrian 1759300016Sadrian/************************************************** 1760300016Sadrian * RSSI 1761300016Sadrian **************************************************/ 1762300016Sadrian 1763300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */ 1764300016Sadrianstatic void bwn_nphy_scale_offset_rssi(struct bwn_mac *mac, uint16_t scale, 1765300016Sadrian int8_t offset, uint8_t core, 1766300016Sadrian enum n_rail_type rail, 1767300016Sadrian enum n_rssi_type rssi_type) 1768300016Sadrian{ 1769300016Sadrian uint16_t tmp; 1770300016Sadrian bool core1or5 = (core == 1) || (core == 5); 1771300016Sadrian bool core2or5 = (core == 2) || (core == 5); 1772300016Sadrian 1773300016Sadrian offset = bwn_clamp_val(offset, -32, 31); 1774300016Sadrian tmp = ((scale & 0x3F) << 8) | (offset & 0x3F); 1775300016Sadrian 1776300016Sadrian switch (rssi_type) { 1777300016Sadrian case N_RSSI_NB: 1778300016Sadrian if (core1or5 && rail == N_RAIL_I) 1779300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_Z, tmp); 1780300016Sadrian if (core1or5 && rail == N_RAIL_Q) 1781300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Z, tmp); 1782300016Sadrian if (core2or5 && rail == N_RAIL_I) 1783300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_Z, tmp); 1784300016Sadrian if (core2or5 && rail == N_RAIL_Q) 1785300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Z, tmp); 1786300016Sadrian break; 1787300016Sadrian case N_RSSI_W1: 1788300016Sadrian if (core1or5 && rail == N_RAIL_I) 1789300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_X, tmp); 1790300016Sadrian if (core1or5 && rail == N_RAIL_Q) 1791300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_X, tmp); 1792300016Sadrian if (core2or5 && rail == N_RAIL_I) 1793300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_X, tmp); 1794300016Sadrian if (core2or5 && rail == N_RAIL_Q) 1795300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_X, tmp); 1796300016Sadrian break; 1797300016Sadrian case N_RSSI_W2: 1798300016Sadrian if (core1or5 && rail == N_RAIL_I) 1799300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_Y, tmp); 1800300016Sadrian if (core1or5 && rail == N_RAIL_Q) 1801300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Y, tmp); 1802300016Sadrian if (core2or5 && rail == N_RAIL_I) 1803300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_Y, tmp); 1804300016Sadrian if (core2or5 && rail == N_RAIL_Q) 1805300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Y, tmp); 1806300016Sadrian break; 1807300016Sadrian case N_RSSI_TBD: 1808300016Sadrian if (core1or5 && rail == N_RAIL_I) 1809300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_TBD, tmp); 1810300016Sadrian if (core1or5 && rail == N_RAIL_Q) 1811300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_TBD, tmp); 1812300016Sadrian if (core2or5 && rail == N_RAIL_I) 1813300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_TBD, tmp); 1814300016Sadrian if (core2or5 && rail == N_RAIL_Q) 1815300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_TBD, tmp); 1816300016Sadrian break; 1817300016Sadrian case N_RSSI_IQ: 1818300016Sadrian if (core1or5 && rail == N_RAIL_I) 1819300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_PWRDET, tmp); 1820300016Sadrian if (core1or5 && rail == N_RAIL_Q) 1821300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_PWRDET, tmp); 1822300016Sadrian if (core2or5 && rail == N_RAIL_I) 1823300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_PWRDET, tmp); 1824300016Sadrian if (core2or5 && rail == N_RAIL_Q) 1825300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_PWRDET, tmp); 1826300016Sadrian break; 1827300016Sadrian case N_RSSI_TSSI_2G: 1828300016Sadrian if (core1or5) 1829300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_TSSI, tmp); 1830300016Sadrian if (core2or5) 1831300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_TSSI, tmp); 1832300016Sadrian break; 1833300016Sadrian case N_RSSI_TSSI_5G: 1834300016Sadrian if (core1or5) 1835300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_TSSI, tmp); 1836300016Sadrian if (core2or5) 1837300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_TSSI, tmp); 1838300016Sadrian break; 1839300016Sadrian } 1840300016Sadrian} 1841300016Sadrian 1842300016Sadrianstatic void bwn_nphy_rssi_select_rev19(struct bwn_mac *mac, uint8_t code, 1843300016Sadrian enum n_rssi_type rssi_type) 1844300016Sadrian{ 1845300016Sadrian /* TODO */ 1846300016Sadrian} 1847300016Sadrian 1848300016Sadrianstatic void bwn_nphy_rev3_rssi_select(struct bwn_mac *mac, uint8_t code, 1849300016Sadrian enum n_rssi_type rssi_type) 1850300016Sadrian{ 1851300016Sadrian uint8_t i; 1852300016Sadrian uint16_t reg, val; 1853300016Sadrian 1854300016Sadrian if (code == 0) { 1855300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER1, 0xFDFF); 1856300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER, 0xFDFF); 1857300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C1, 0xFCFF); 1858300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C2, 0xFCFF); 1859300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_TXF_40CO_B1S0, 0xFFDF); 1860300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_TXF_40CO_B32S1, 0xFFDF); 1861300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP1, 0xFFC3); 1862300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP2, 0xFFC3); 1863300016Sadrian } else { 1864300016Sadrian for (i = 0; i < 2; i++) { 1865300016Sadrian if ((code == 1 && i == 1) || (code == 2 && !i)) 1866300016Sadrian continue; 1867300016Sadrian 1868300016Sadrian reg = (i == 0) ? 1869300016Sadrian BWN_NPHY_AFECTL_OVER1 : BWN_NPHY_AFECTL_OVER; 1870300016Sadrian BWN_PHY_SETMASK(mac, reg, 0xFDFF, 0x0200); 1871300016Sadrian 1872300016Sadrian if (rssi_type == N_RSSI_W1 || 1873300016Sadrian rssi_type == N_RSSI_W2 || 1874300016Sadrian rssi_type == N_RSSI_NB) { 1875300016Sadrian reg = (i == 0) ? 1876300016Sadrian BWN_NPHY_AFECTL_C1 : 1877300016Sadrian BWN_NPHY_AFECTL_C2; 1878300016Sadrian BWN_PHY_SETMASK(mac, reg, 0xFCFF, 0); 1879300016Sadrian 1880300016Sadrian reg = (i == 0) ? 1881300016Sadrian BWN_NPHY_RFCTL_LUT_TRSW_UP1 : 1882300016Sadrian BWN_NPHY_RFCTL_LUT_TRSW_UP2; 1883300016Sadrian BWN_PHY_SETMASK(mac, reg, 0xFFC3, 0); 1884300016Sadrian 1885300016Sadrian if (rssi_type == N_RSSI_W1) 1886300016Sadrian val = (bwn_current_band(mac) == BWN_BAND_5G) ? 4 : 8; 1887300016Sadrian else if (rssi_type == N_RSSI_W2) 1888300016Sadrian val = 16; 1889300016Sadrian else 1890300016Sadrian val = 32; 1891300016Sadrian BWN_PHY_SET(mac, reg, val); 1892300016Sadrian 1893300016Sadrian reg = (i == 0) ? 1894300016Sadrian BWN_NPHY_TXF_40CO_B1S0 : 1895300016Sadrian BWN_NPHY_TXF_40CO_B32S1; 1896300016Sadrian BWN_PHY_SET(mac, reg, 0x0020); 1897300016Sadrian } else { 1898300016Sadrian if (rssi_type == N_RSSI_TBD) 1899300016Sadrian val = 0x0100; 1900300016Sadrian else if (rssi_type == N_RSSI_IQ) 1901300016Sadrian val = 0x0200; 1902300016Sadrian else 1903300016Sadrian val = 0x0300; 1904300016Sadrian 1905300016Sadrian reg = (i == 0) ? 1906300016Sadrian BWN_NPHY_AFECTL_C1 : 1907300016Sadrian BWN_NPHY_AFECTL_C2; 1908300016Sadrian 1909300016Sadrian BWN_PHY_SETMASK(mac, reg, 0xFCFF, val); 1910300016Sadrian BWN_PHY_SETMASK(mac, reg, 0xF3FF, val << 2); 1911300016Sadrian 1912300016Sadrian if (rssi_type != N_RSSI_IQ && 1913300016Sadrian rssi_type != N_RSSI_TBD) { 1914300016Sadrian bwn_band_t band = 1915300016Sadrian bwn_current_band(mac); 1916300016Sadrian 1917300016Sadrian if (mac->mac_phy.rev < 7) { 1918300016Sadrian if (bwn_nphy_ipa(mac)) 1919300016Sadrian val = (band == BWN_BAND_5G) ? 0xC : 0xE; 1920300016Sadrian else 1921300016Sadrian val = 0x11; 1922300016Sadrian reg = (i == 0) ? B2056_TX0 : B2056_TX1; 1923300016Sadrian reg |= B2056_TX_TX_SSI_MUX; 1924300016Sadrian BWN_RF_WRITE(mac, reg, val); 1925300016Sadrian } 1926300016Sadrian 1927300016Sadrian reg = (i == 0) ? 1928300016Sadrian BWN_NPHY_AFECTL_OVER1 : 1929300016Sadrian BWN_NPHY_AFECTL_OVER; 1930300016Sadrian BWN_PHY_SET(mac, reg, 0x0200); 1931300016Sadrian } 1932300016Sadrian } 1933300016Sadrian } 1934300016Sadrian } 1935300016Sadrian} 1936300016Sadrian 1937300016Sadrianstatic void bwn_nphy_rev2_rssi_select(struct bwn_mac *mac, uint8_t code, 1938300016Sadrian enum n_rssi_type rssi_type) 1939300016Sadrian{ 1940300016Sadrian uint16_t val; 1941300016Sadrian bool rssi_w1_w2_nb = false; 1942300016Sadrian 1943300016Sadrian switch (rssi_type) { 1944300016Sadrian case N_RSSI_W1: 1945300016Sadrian case N_RSSI_W2: 1946300016Sadrian case N_RSSI_NB: 1947300016Sadrian val = 0; 1948300016Sadrian rssi_w1_w2_nb = true; 1949300016Sadrian break; 1950300016Sadrian case N_RSSI_TBD: 1951300016Sadrian val = 1; 1952300016Sadrian break; 1953300016Sadrian case N_RSSI_IQ: 1954300016Sadrian val = 2; 1955300016Sadrian break; 1956300016Sadrian default: 1957300016Sadrian val = 3; 1958300016Sadrian } 1959300016Sadrian 1960300016Sadrian val = (val << 12) | (val << 14); 1961300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C1, 0x0FFF, val); 1962300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C2, 0x0FFF, val); 1963300016Sadrian 1964300016Sadrian if (rssi_w1_w2_nb) { 1965300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFCTL_RSSIO1, 0xFFCF, 1966300016Sadrian (rssi_type + 1) << 4); 1967300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFCTL_RSSIO2, 0xFFCF, 1968300016Sadrian (rssi_type + 1) << 4); 1969300016Sadrian } 1970300016Sadrian 1971300016Sadrian if (code == 0) { 1972300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER, ~0x3000); 1973300016Sadrian if (rssi_w1_w2_nb) { 1974300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, 1975300016Sadrian ~(BWN_NPHY_RFCTL_CMD_RXEN | 1976300016Sadrian BWN_NPHY_RFCTL_CMD_CORESEL)); 1977300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER, 1978300016Sadrian ~(0x1 << 12 | 1979300016Sadrian 0x1 << 5 | 1980300016Sadrian 0x1 << 1 | 1981300016Sadrian 0x1)); 1982300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, 1983300016Sadrian ~BWN_NPHY_RFCTL_CMD_START); 1984300016Sadrian DELAY(20); 1985300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER, ~0x1); 1986300016Sadrian } 1987300016Sadrian } else { 1988300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x3000); 1989300016Sadrian if (rssi_w1_w2_nb) { 1990300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFCTL_CMD, 1991300016Sadrian ~(BWN_NPHY_RFCTL_CMD_RXEN | 1992300016Sadrian BWN_NPHY_RFCTL_CMD_CORESEL), 1993300016Sadrian (BWN_NPHY_RFCTL_CMD_RXEN | 1994300016Sadrian code << BWN_NPHY_RFCTL_CMD_CORESEL_SHIFT)); 1995300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_OVER, 1996300016Sadrian (0x1 << 12 | 1997300016Sadrian 0x1 << 5 | 1998300016Sadrian 0x1 << 1 | 1999300016Sadrian 0x1)); 2000300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, 2001300016Sadrian BWN_NPHY_RFCTL_CMD_START); 2002300016Sadrian DELAY(20); 2003300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER, ~0x1); 2004300016Sadrian } 2005300016Sadrian } 2006300016Sadrian} 2007300016Sadrian 2008300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */ 2009300016Sadrianstatic void bwn_nphy_rssi_select(struct bwn_mac *mac, uint8_t code, 2010300016Sadrian enum n_rssi_type type) 2011300016Sadrian{ 2012300016Sadrian if (mac->mac_phy.rev >= 19) 2013300016Sadrian bwn_nphy_rssi_select_rev19(mac, code, type); 2014300016Sadrian else if (mac->mac_phy.rev >= 3) 2015300016Sadrian bwn_nphy_rev3_rssi_select(mac, code, type); 2016300016Sadrian else 2017300016Sadrian bwn_nphy_rev2_rssi_select(mac, code, type); 2018300016Sadrian} 2019300016Sadrian 2020300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */ 2021300016Sadrianstatic void bwn_nphy_set_rssi_2055_vcm(struct bwn_mac *mac, 2022300016Sadrian enum n_rssi_type rssi_type, uint8_t *buf) 2023300016Sadrian{ 2024300016Sadrian int i; 2025300016Sadrian for (i = 0; i < 2; i++) { 2026300016Sadrian if (rssi_type == N_RSSI_NB) { 2027300016Sadrian if (i == 0) { 2028300016Sadrian BWN_RF_SETMASK(mac, B2055_C1_B0NB_RSSIVCM, 2029300016Sadrian 0xFC, buf[0]); 2030300016Sadrian BWN_RF_SETMASK(mac, B2055_C1_RX_BB_RSSICTL5, 2031300016Sadrian 0xFC, buf[1]); 2032300016Sadrian } else { 2033300016Sadrian BWN_RF_SETMASK(mac, B2055_C2_B0NB_RSSIVCM, 2034300016Sadrian 0xFC, buf[2 * i]); 2035300016Sadrian BWN_RF_SETMASK(mac, B2055_C2_RX_BB_RSSICTL5, 2036300016Sadrian 0xFC, buf[2 * i + 1]); 2037300016Sadrian } 2038300016Sadrian } else { 2039300016Sadrian if (i == 0) 2040300016Sadrian BWN_RF_SETMASK(mac, B2055_C1_RX_BB_RSSICTL5, 2041300016Sadrian 0xF3, buf[0] << 2); 2042300016Sadrian else 2043300016Sadrian BWN_RF_SETMASK(mac, B2055_C2_RX_BB_RSSICTL5, 2044300016Sadrian 0xF3, buf[2 * i + 1] << 2); 2045300016Sadrian } 2046300016Sadrian } 2047300016Sadrian} 2048300016Sadrian 2049300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */ 2050300016Sadrianstatic int bwn_nphy_poll_rssi(struct bwn_mac *mac, enum n_rssi_type rssi_type, 2051300016Sadrian int32_t *buf, uint8_t nsamp) 2052300016Sadrian{ 2053300016Sadrian int i; 2054300016Sadrian int out; 2055300016Sadrian uint16_t save_regs_phy[9]; 2056300016Sadrian uint16_t s[2]; 2057300016Sadrian 2058300016Sadrian /* TODO: rev7+ is treated like rev3+, what about rev19+? */ 2059300016Sadrian 2060300016Sadrian if (mac->mac_phy.rev >= 3) { 2061300016Sadrian save_regs_phy[0] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C1); 2062300016Sadrian save_regs_phy[1] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C2); 2063300016Sadrian save_regs_phy[2] = BWN_PHY_READ(mac, 2064300016Sadrian BWN_NPHY_RFCTL_LUT_TRSW_UP1); 2065300016Sadrian save_regs_phy[3] = BWN_PHY_READ(mac, 2066300016Sadrian BWN_NPHY_RFCTL_LUT_TRSW_UP2); 2067300016Sadrian save_regs_phy[4] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER1); 2068300016Sadrian save_regs_phy[5] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER); 2069300016Sadrian save_regs_phy[6] = BWN_PHY_READ(mac, BWN_NPHY_TXF_40CO_B1S0); 2070300016Sadrian save_regs_phy[7] = BWN_PHY_READ(mac, BWN_NPHY_TXF_40CO_B32S1); 2071300016Sadrian save_regs_phy[8] = 0; 2072300016Sadrian } else { 2073300016Sadrian save_regs_phy[0] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C1); 2074300016Sadrian save_regs_phy[1] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C2); 2075300016Sadrian save_regs_phy[2] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER); 2076300016Sadrian save_regs_phy[3] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_CMD); 2077300016Sadrian save_regs_phy[4] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_OVER); 2078300016Sadrian save_regs_phy[5] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_RSSIO1); 2079300016Sadrian save_regs_phy[6] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_RSSIO2); 2080300016Sadrian save_regs_phy[7] = 0; 2081300016Sadrian save_regs_phy[8] = 0; 2082300016Sadrian } 2083300016Sadrian 2084300016Sadrian bwn_nphy_rssi_select(mac, 5, rssi_type); 2085300016Sadrian 2086300016Sadrian if (mac->mac_phy.rev < 2) { 2087300016Sadrian save_regs_phy[8] = BWN_PHY_READ(mac, BWN_NPHY_GPIO_SEL); 2088300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_GPIO_SEL, 5); 2089300016Sadrian } 2090300016Sadrian 2091300016Sadrian for (i = 0; i < 4; i++) 2092300016Sadrian buf[i] = 0; 2093300016Sadrian 2094300016Sadrian for (i = 0; i < nsamp; i++) { 2095300016Sadrian if (mac->mac_phy.rev < 2) { 2096300016Sadrian s[0] = BWN_PHY_READ(mac, BWN_NPHY_GPIO_LOOUT); 2097300016Sadrian s[1] = BWN_PHY_READ(mac, BWN_NPHY_GPIO_HIOUT); 2098300016Sadrian } else { 2099300016Sadrian s[0] = BWN_PHY_READ(mac, BWN_NPHY_RSSI1); 2100300016Sadrian s[1] = BWN_PHY_READ(mac, BWN_NPHY_RSSI2); 2101300016Sadrian } 2102300016Sadrian 2103300016Sadrian buf[0] += ((int8_t)((s[0] & 0x3F) << 2)) >> 2; 2104300016Sadrian buf[1] += ((int8_t)(((s[0] >> 8) & 0x3F) << 2)) >> 2; 2105300016Sadrian buf[2] += ((int8_t)((s[1] & 0x3F) << 2)) >> 2; 2106300016Sadrian buf[3] += ((int8_t)(((s[1] >> 8) & 0x3F) << 2)) >> 2; 2107300016Sadrian } 2108300016Sadrian out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 | 2109300016Sadrian (buf[2] & 0xFF) << 8 | (buf[3] & 0xFF); 2110300016Sadrian 2111300016Sadrian if (mac->mac_phy.rev < 2) 2112300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_GPIO_SEL, save_regs_phy[8]); 2113300016Sadrian 2114300016Sadrian if (mac->mac_phy.rev >= 3) { 2115300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, save_regs_phy[0]); 2116300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, save_regs_phy[1]); 2117300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP1, 2118300016Sadrian save_regs_phy[2]); 2119300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP2, 2120300016Sadrian save_regs_phy[3]); 2121300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, save_regs_phy[4]); 2122300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, save_regs_phy[5]); 2123300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B1S0, save_regs_phy[6]); 2124300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B32S1, save_regs_phy[7]); 2125300016Sadrian } else { 2126300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, save_regs_phy[0]); 2127300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, save_regs_phy[1]); 2128300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, save_regs_phy[2]); 2129300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_CMD, save_regs_phy[3]); 2130300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_OVER, save_regs_phy[4]); 2131300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_RSSIO1, save_regs_phy[5]); 2132300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_RSSIO2, save_regs_phy[6]); 2133300016Sadrian } 2134300016Sadrian 2135300016Sadrian return out; 2136300016Sadrian} 2137300016Sadrian 2138300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */ 2139300016Sadrianstatic void bwn_nphy_rev3_rssi_cal(struct bwn_mac *mac) 2140300016Sadrian{ 2141300016Sadrian //struct bwn_phy *phy = &mac->mac_phy; 2142300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 2143300016Sadrian 2144300016Sadrian uint16_t saved_regs_phy_rfctl[2]; 2145300016Sadrian uint16_t saved_regs_phy[22]; 2146300016Sadrian uint16_t regs_to_store_rev3[] = { 2147300016Sadrian BWN_NPHY_AFECTL_OVER1, BWN_NPHY_AFECTL_OVER, 2148300016Sadrian BWN_NPHY_AFECTL_C1, BWN_NPHY_AFECTL_C2, 2149300016Sadrian BWN_NPHY_TXF_40CO_B1S1, BWN_NPHY_RFCTL_OVER, 2150300016Sadrian BWN_NPHY_TXF_40CO_B1S0, BWN_NPHY_TXF_40CO_B32S1, 2151300016Sadrian BWN_NPHY_RFCTL_CMD, 2152300016Sadrian BWN_NPHY_RFCTL_LUT_TRSW_UP1, BWN_NPHY_RFCTL_LUT_TRSW_UP2, 2153300016Sadrian BWN_NPHY_RFCTL_RSSIO1, BWN_NPHY_RFCTL_RSSIO2 2154300016Sadrian }; 2155300016Sadrian uint16_t regs_to_store_rev7[] = { 2156300016Sadrian BWN_NPHY_AFECTL_OVER1, BWN_NPHY_AFECTL_OVER, 2157300016Sadrian BWN_NPHY_AFECTL_C1, BWN_NPHY_AFECTL_C2, 2158300016Sadrian BWN_NPHY_TXF_40CO_B1S1, BWN_NPHY_RFCTL_OVER, 2159300016Sadrian BWN_NPHY_REV7_RF_CTL_OVER3, BWN_NPHY_REV7_RF_CTL_OVER4, 2160300016Sadrian BWN_NPHY_REV7_RF_CTL_OVER5, BWN_NPHY_REV7_RF_CTL_OVER6, 2161300016Sadrian 0x2ff, 2162300016Sadrian BWN_NPHY_TXF_40CO_B1S0, BWN_NPHY_TXF_40CO_B32S1, 2163300016Sadrian BWN_NPHY_RFCTL_CMD, 2164300016Sadrian BWN_NPHY_RFCTL_LUT_TRSW_UP1, BWN_NPHY_RFCTL_LUT_TRSW_UP2, 2165300016Sadrian BWN_NPHY_REV7_RF_CTL_MISC_REG3, BWN_NPHY_REV7_RF_CTL_MISC_REG4, 2166300016Sadrian BWN_NPHY_REV7_RF_CTL_MISC_REG5, BWN_NPHY_REV7_RF_CTL_MISC_REG6, 2167300016Sadrian BWN_NPHY_RFCTL_RSSIO1, BWN_NPHY_RFCTL_RSSIO2 2168300016Sadrian }; 2169300016Sadrian uint16_t *regs_to_store; 2170300016Sadrian int regs_amount; 2171300016Sadrian 2172300016Sadrian uint16_t class; 2173300016Sadrian 2174300016Sadrian uint16_t clip_state[2]; 2175300016Sadrian uint16_t clip_off[2] = { 0xFFFF, 0xFFFF }; 2176300016Sadrian 2177300016Sadrian uint8_t vcm_final = 0; 2178300016Sadrian int32_t offset[4]; 2179300016Sadrian int32_t results[8][4] = { }; 2180300016Sadrian int32_t results_min[4] = { }; 2181300016Sadrian int32_t poll_results[4] = { }; 2182300016Sadrian 2183300016Sadrian uint16_t *rssical_radio_regs = NULL; 2184300016Sadrian uint16_t *rssical_phy_regs = NULL; 2185300016Sadrian 2186300016Sadrian uint16_t r; /* routing */ 2187300016Sadrian uint8_t rx_core_state; 2188300016Sadrian int core, i, j, vcm; 2189300016Sadrian 2190300016Sadrian if (mac->mac_phy.rev >= 7) { 2191300016Sadrian regs_to_store = regs_to_store_rev7; 2192300016Sadrian regs_amount = nitems(regs_to_store_rev7); 2193300016Sadrian } else { 2194300016Sadrian regs_to_store = regs_to_store_rev3; 2195300016Sadrian regs_amount = nitems(regs_to_store_rev3); 2196300016Sadrian } 2197300016Sadrian KASSERT((regs_amount <= nitems(saved_regs_phy)), 2198300016Sadrian ("%s: reg_amount (%d) too large\n", 2199300016Sadrian __func__, 2200300016Sadrian regs_amount)); 2201300016Sadrian 2202300016Sadrian class = bwn_nphy_classifier(mac, 0, 0); 2203300016Sadrian bwn_nphy_classifier(mac, 7, 4); 2204300016Sadrian bwn_nphy_read_clip_detection(mac, clip_state); 2205300016Sadrian bwn_nphy_write_clip_detection(mac, clip_off); 2206300016Sadrian 2207300016Sadrian saved_regs_phy_rfctl[0] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC1); 2208300016Sadrian saved_regs_phy_rfctl[1] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC2); 2209300016Sadrian for (i = 0; i < regs_amount; i++) 2210300016Sadrian saved_regs_phy[i] = BWN_PHY_READ(mac, regs_to_store[i]); 2211300016Sadrian 2212300016Sadrian bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_OFF, 0, 7); 2213300016Sadrian bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_TRSW, 1, 7); 2214300016Sadrian 2215300016Sadrian if (mac->mac_phy.rev >= 7) { 2216300016Sadrian bwn_nphy_rf_ctl_override_one_to_many(mac, 2217300016Sadrian N_RF_CTL_OVER_CMD_RXRF_PU, 2218300016Sadrian 0, 0, false); 2219300016Sadrian bwn_nphy_rf_ctl_override_one_to_many(mac, 2220300016Sadrian N_RF_CTL_OVER_CMD_RX_PU, 2221300016Sadrian 1, 0, false); 2222300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x80, 1, 0, false, 0); 2223300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x40, 1, 0, false, 0); 2224300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G) { 2225300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x20, 0, 0, false, 2226300016Sadrian 0); 2227300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x10, 1, 0, false, 2228300016Sadrian 0); 2229300016Sadrian } else { 2230300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x10, 0, 0, false, 2231300016Sadrian 0); 2232300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x20, 1, 0, false, 2233300016Sadrian 0); 2234300016Sadrian } 2235300016Sadrian } else { 2236300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x1, 0, 0, false); 2237300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x2, 1, 0, false); 2238300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x80, 1, 0, false); 2239300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x40, 1, 0, false); 2240300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G) { 2241300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x20, 0, 0, false); 2242300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x10, 1, 0, false); 2243300016Sadrian } else { 2244300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x10, 0, 0, false); 2245300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x20, 1, 0, false); 2246300016Sadrian } 2247300016Sadrian } 2248300016Sadrian 2249300016Sadrian rx_core_state = bwn_nphy_get_rx_core_state(mac); 2250300016Sadrian for (core = 0; core < 2; core++) { 2251300016Sadrian if (!(rx_core_state & (1 << core))) 2252300016Sadrian continue; 2253300016Sadrian r = core ? B2056_RX1 : B2056_RX0; 2254300016Sadrian bwn_nphy_scale_offset_rssi(mac, 0, 0, core + 1, N_RAIL_I, 2255300016Sadrian N_RSSI_NB); 2256300016Sadrian bwn_nphy_scale_offset_rssi(mac, 0, 0, core + 1, N_RAIL_Q, 2257300016Sadrian N_RSSI_NB); 2258300016Sadrian 2259300016Sadrian /* Grab RSSI results for every possible VCM */ 2260300016Sadrian for (vcm = 0; vcm < 8; vcm++) { 2261300016Sadrian if (mac->mac_phy.rev >= 7) 2262300016Sadrian BWN_RF_SETMASK(mac, 2263300016Sadrian core ? R2057_NB_MASTER_CORE1 : 2264300016Sadrian R2057_NB_MASTER_CORE0, 2265300016Sadrian ~R2057_VCM_MASK, vcm); 2266300016Sadrian else 2267300016Sadrian BWN_RF_SETMASK(mac, r | B2056_RX_RSSI_MISC, 2268300016Sadrian 0xE3, vcm << 2); 2269300016Sadrian bwn_nphy_poll_rssi(mac, N_RSSI_NB, results[vcm], 8); 2270300016Sadrian } 2271300016Sadrian 2272300016Sadrian /* Find out which VCM got the best results */ 2273300016Sadrian for (i = 0; i < 4; i += 2) { 2274300016Sadrian int32_t currd; 2275300016Sadrian int32_t mind = 0x100000; 2276300016Sadrian int32_t minpoll = 249; 2277300016Sadrian uint8_t minvcm = 0; 2278300016Sadrian if (2 * core != i) 2279300016Sadrian continue; 2280300016Sadrian for (vcm = 0; vcm < 8; vcm++) { 2281300016Sadrian currd = results[vcm][i] * results[vcm][i] + 2282300016Sadrian results[vcm][i + 1] * results[vcm][i]; 2283300016Sadrian if (currd < mind) { 2284300016Sadrian mind = currd; 2285300016Sadrian minvcm = vcm; 2286300016Sadrian } 2287300016Sadrian if (results[vcm][i] < minpoll) 2288300016Sadrian minpoll = results[vcm][i]; 2289300016Sadrian } 2290300016Sadrian vcm_final = minvcm; 2291300016Sadrian results_min[i] = minpoll; 2292300016Sadrian } 2293300016Sadrian 2294300016Sadrian /* Select the best VCM */ 2295300016Sadrian if (mac->mac_phy.rev >= 7) 2296300016Sadrian BWN_RF_SETMASK(mac, 2297300016Sadrian core ? R2057_NB_MASTER_CORE1 : 2298300016Sadrian R2057_NB_MASTER_CORE0, 2299300016Sadrian ~R2057_VCM_MASK, vcm); 2300300016Sadrian else 2301300016Sadrian BWN_RF_SETMASK(mac, r | B2056_RX_RSSI_MISC, 2302300016Sadrian 0xE3, vcm_final << 2); 2303300016Sadrian 2304300016Sadrian for (i = 0; i < 4; i++) { 2305300016Sadrian if (core != i / 2) 2306300016Sadrian continue; 2307300016Sadrian offset[i] = -results[vcm_final][i]; 2308300016Sadrian if (offset[i] < 0) 2309300016Sadrian offset[i] = -((abs(offset[i]) + 4) / 8); 2310300016Sadrian else 2311300016Sadrian offset[i] = (offset[i] + 4) / 8; 2312300016Sadrian if (results_min[i] == 248) 2313300016Sadrian offset[i] = -32; 2314300016Sadrian bwn_nphy_scale_offset_rssi(mac, 0, offset[i], 2315300016Sadrian (i / 2 == 0) ? 1 : 2, 2316300016Sadrian (i % 2 == 0) ? N_RAIL_I : N_RAIL_Q, 2317300016Sadrian N_RSSI_NB); 2318300016Sadrian } 2319300016Sadrian } 2320300016Sadrian 2321300016Sadrian for (core = 0; core < 2; core++) { 2322300016Sadrian if (!(rx_core_state & (1 << core))) 2323300016Sadrian continue; 2324300016Sadrian for (i = 0; i < 2; i++) { 2325300016Sadrian bwn_nphy_scale_offset_rssi(mac, 0, 0, core + 1, 2326300016Sadrian N_RAIL_I, i); 2327300016Sadrian bwn_nphy_scale_offset_rssi(mac, 0, 0, core + 1, 2328300016Sadrian N_RAIL_Q, i); 2329300016Sadrian bwn_nphy_poll_rssi(mac, i, poll_results, 8); 2330300016Sadrian for (j = 0; j < 4; j++) { 2331300016Sadrian if (j / 2 == core) { 2332300016Sadrian offset[j] = 232 - poll_results[j]; 2333300016Sadrian if (offset[j] < 0) 2334300016Sadrian offset[j] = -(abs(offset[j] + 4) / 8); 2335300016Sadrian else 2336300016Sadrian offset[j] = (offset[j] + 4) / 8; 2337300016Sadrian bwn_nphy_scale_offset_rssi(mac, 0, 2338300016Sadrian offset[2 * core], core + 1, j % 2, i); 2339300016Sadrian } 2340300016Sadrian } 2341300016Sadrian } 2342300016Sadrian } 2343300016Sadrian 2344300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, saved_regs_phy_rfctl[0]); 2345300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, saved_regs_phy_rfctl[1]); 2346300016Sadrian 2347300016Sadrian bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX); 2348300016Sadrian 2349300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_TXF_40CO_B1S1, 0x1); 2350300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, BWN_NPHY_RFCTL_CMD_START); 2351300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_TXF_40CO_B1S1, ~0x1); 2352300016Sadrian 2353300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_OVER, 0x1); 2354300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, BWN_NPHY_RFCTL_CMD_RXTX); 2355300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER, ~0x1); 2356300016Sadrian 2357300016Sadrian for (i = 0; i < regs_amount; i++) 2358300016Sadrian BWN_PHY_WRITE(mac, regs_to_store[i], saved_regs_phy[i]); 2359300016Sadrian 2360300016Sadrian /* Store for future configuration */ 2361300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 2362300016Sadrian rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G; 2363300016Sadrian rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G; 2364300016Sadrian } else { 2365300016Sadrian rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G; 2366300016Sadrian rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; 2367300016Sadrian } 2368300016Sadrian if (mac->mac_phy.rev >= 7) { 2369300016Sadrian rssical_radio_regs[0] = BWN_RF_READ(mac, 2370300016Sadrian R2057_NB_MASTER_CORE0); 2371300016Sadrian rssical_radio_regs[1] = BWN_RF_READ(mac, 2372300016Sadrian R2057_NB_MASTER_CORE1); 2373300016Sadrian } else { 2374300016Sadrian rssical_radio_regs[0] = BWN_RF_READ(mac, B2056_RX0 | 2375300016Sadrian B2056_RX_RSSI_MISC); 2376300016Sadrian rssical_radio_regs[1] = BWN_RF_READ(mac, B2056_RX1 | 2377300016Sadrian B2056_RX_RSSI_MISC); 2378300016Sadrian } 2379300016Sadrian rssical_phy_regs[0] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0I_RSSI_Z); 2380300016Sadrian rssical_phy_regs[1] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Z); 2381300016Sadrian rssical_phy_regs[2] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1I_RSSI_Z); 2382300016Sadrian rssical_phy_regs[3] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Z); 2383300016Sadrian rssical_phy_regs[4] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0I_RSSI_X); 2384300016Sadrian rssical_phy_regs[5] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0Q_RSSI_X); 2385300016Sadrian rssical_phy_regs[6] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1I_RSSI_X); 2386300016Sadrian rssical_phy_regs[7] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1Q_RSSI_X); 2387300016Sadrian rssical_phy_regs[8] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0I_RSSI_Y); 2388300016Sadrian rssical_phy_regs[9] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Y); 2389300016Sadrian rssical_phy_regs[10] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1I_RSSI_Y); 2390300016Sadrian rssical_phy_regs[11] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Y); 2391300016Sadrian 2392300016Sadrian /* Remember for which channel we store configuration */ 2393300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 2394300016Sadrian nphy->rssical_chanspec_2G.center_freq = bwn_get_centre_freq(mac); 2395300016Sadrian else 2396300016Sadrian nphy->rssical_chanspec_5G.center_freq = bwn_get_centre_freq(mac); 2397300016Sadrian 2398300016Sadrian /* End of calibration, restore configuration */ 2399300016Sadrian bwn_nphy_classifier(mac, 7, class); 2400300016Sadrian bwn_nphy_write_clip_detection(mac, clip_state); 2401300016Sadrian} 2402300016Sadrian 2403300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */ 2404300016Sadrianstatic void bwn_nphy_rev2_rssi_cal(struct bwn_mac *mac, enum n_rssi_type type) 2405300016Sadrian{ 2406300016Sadrian int i, j, vcm; 2407300016Sadrian uint8_t state[4]; 2408300016Sadrian uint8_t code, val; 2409300016Sadrian uint16_t class, override; 2410300016Sadrian uint8_t regs_save_radio[2]; 2411300016Sadrian uint16_t regs_save_phy[2]; 2412300016Sadrian 2413300016Sadrian int32_t offset[4]; 2414300016Sadrian uint8_t core; 2415300016Sadrian uint8_t rail; 2416300016Sadrian 2417300016Sadrian uint16_t clip_state[2]; 2418300016Sadrian uint16_t clip_off[2] = { 0xFFFF, 0xFFFF }; 2419300016Sadrian int32_t results_min[4] = { }; 2420300016Sadrian uint8_t vcm_final[4] = { }; 2421300016Sadrian int32_t results[4][4] = { }; 2422300016Sadrian int32_t miniq[4][2] = { }; 2423300016Sadrian 2424300016Sadrian if (type == N_RSSI_NB) { 2425300016Sadrian code = 0; 2426300016Sadrian val = 6; 2427300016Sadrian } else if (type == N_RSSI_W1 || type == N_RSSI_W2) { 2428300016Sadrian code = 25; 2429300016Sadrian val = 4; 2430300016Sadrian } else { 2431300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "%s: RSSI type %d invalid\n", 2432300016Sadrian __func__, 2433300016Sadrian type); 2434300016Sadrian return; 2435300016Sadrian } 2436300016Sadrian 2437300016Sadrian class = bwn_nphy_classifier(mac, 0, 0); 2438300016Sadrian bwn_nphy_classifier(mac, 7, 4); 2439300016Sadrian bwn_nphy_read_clip_detection(mac, clip_state); 2440300016Sadrian bwn_nphy_write_clip_detection(mac, clip_off); 2441300016Sadrian 2442300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G) 2443300016Sadrian override = 0x140; 2444300016Sadrian else 2445300016Sadrian override = 0x110; 2446300016Sadrian 2447300016Sadrian regs_save_phy[0] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC1); 2448300016Sadrian regs_save_radio[0] = BWN_RF_READ(mac, B2055_C1_PD_RXTX); 2449300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, override); 2450300016Sadrian BWN_RF_WRITE(mac, B2055_C1_PD_RXTX, val); 2451300016Sadrian 2452300016Sadrian regs_save_phy[1] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC2); 2453300016Sadrian regs_save_radio[1] = BWN_RF_READ(mac, B2055_C2_PD_RXTX); 2454300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, override); 2455300016Sadrian BWN_RF_WRITE(mac, B2055_C2_PD_RXTX, val); 2456300016Sadrian 2457300016Sadrian state[0] = BWN_RF_READ(mac, B2055_C1_PD_RSSIMISC) & 0x07; 2458300016Sadrian state[1] = BWN_RF_READ(mac, B2055_C2_PD_RSSIMISC) & 0x07; 2459300016Sadrian BWN_RF_MASK(mac, B2055_C1_PD_RSSIMISC, 0xF8); 2460300016Sadrian BWN_RF_MASK(mac, B2055_C2_PD_RSSIMISC, 0xF8); 2461300016Sadrian state[2] = BWN_RF_READ(mac, B2055_C1_SP_RSSI) & 0x07; 2462300016Sadrian state[3] = BWN_RF_READ(mac, B2055_C2_SP_RSSI) & 0x07; 2463300016Sadrian 2464300016Sadrian bwn_nphy_rssi_select(mac, 5, type); 2465300016Sadrian bwn_nphy_scale_offset_rssi(mac, 0, 0, 5, N_RAIL_I, type); 2466300016Sadrian bwn_nphy_scale_offset_rssi(mac, 0, 0, 5, N_RAIL_Q, type); 2467300016Sadrian 2468300016Sadrian for (vcm = 0; vcm < 4; vcm++) { 2469300016Sadrian uint8_t tmp[4]; 2470300016Sadrian for (j = 0; j < 4; j++) 2471300016Sadrian tmp[j] = vcm; 2472300016Sadrian if (type != N_RSSI_W2) 2473300016Sadrian bwn_nphy_set_rssi_2055_vcm(mac, type, tmp); 2474300016Sadrian bwn_nphy_poll_rssi(mac, type, results[vcm], 8); 2475300016Sadrian if (type == N_RSSI_W1 || type == N_RSSI_W2) 2476300016Sadrian for (j = 0; j < 2; j++) 2477300016Sadrian miniq[vcm][j] = min(results[vcm][2 * j], 2478300016Sadrian results[vcm][2 * j + 1]); 2479300016Sadrian } 2480300016Sadrian 2481300016Sadrian for (i = 0; i < 4; i++) { 2482300016Sadrian int32_t mind = 0x100000; 2483300016Sadrian uint8_t minvcm = 0; 2484300016Sadrian int32_t minpoll = 249; 2485300016Sadrian int32_t currd; 2486300016Sadrian for (vcm = 0; vcm < 4; vcm++) { 2487300016Sadrian if (type == N_RSSI_NB) 2488300016Sadrian currd = abs(results[vcm][i] - code * 8); 2489300016Sadrian else 2490300016Sadrian currd = abs(miniq[vcm][i / 2] - code * 8); 2491300016Sadrian 2492300016Sadrian if (currd < mind) { 2493300016Sadrian mind = currd; 2494300016Sadrian minvcm = vcm; 2495300016Sadrian } 2496300016Sadrian 2497300016Sadrian if (results[vcm][i] < minpoll) 2498300016Sadrian minpoll = results[vcm][i]; 2499300016Sadrian } 2500300016Sadrian results_min[i] = minpoll; 2501300016Sadrian vcm_final[i] = minvcm; 2502300016Sadrian } 2503300016Sadrian 2504300016Sadrian if (type != N_RSSI_W2) 2505300016Sadrian bwn_nphy_set_rssi_2055_vcm(mac, type, vcm_final); 2506300016Sadrian 2507300016Sadrian for (i = 0; i < 4; i++) { 2508300016Sadrian offset[i] = (code * 8) - results[vcm_final[i]][i]; 2509300016Sadrian 2510300016Sadrian if (offset[i] < 0) 2511300016Sadrian offset[i] = -((abs(offset[i]) + 4) / 8); 2512300016Sadrian else 2513300016Sadrian offset[i] = (offset[i] + 4) / 8; 2514300016Sadrian 2515300016Sadrian if (results_min[i] == 248) 2516300016Sadrian offset[i] = code - 32; 2517300016Sadrian 2518300016Sadrian core = (i / 2) ? 2 : 1; 2519300016Sadrian rail = (i % 2) ? N_RAIL_Q : N_RAIL_I; 2520300016Sadrian 2521300016Sadrian bwn_nphy_scale_offset_rssi(mac, 0, offset[i], core, rail, 2522300016Sadrian type); 2523300016Sadrian } 2524300016Sadrian 2525300016Sadrian BWN_RF_SETMASK(mac, B2055_C1_PD_RSSIMISC, 0xF8, state[0]); 2526300016Sadrian BWN_RF_SETMASK(mac, B2055_C2_PD_RSSIMISC, 0xF8, state[1]); 2527300016Sadrian 2528300016Sadrian switch (state[2]) { 2529300016Sadrian case 1: 2530300016Sadrian bwn_nphy_rssi_select(mac, 1, N_RSSI_NB); 2531300016Sadrian break; 2532300016Sadrian case 4: 2533300016Sadrian bwn_nphy_rssi_select(mac, 1, N_RSSI_W1); 2534300016Sadrian break; 2535300016Sadrian case 2: 2536300016Sadrian bwn_nphy_rssi_select(mac, 1, N_RSSI_W2); 2537300016Sadrian break; 2538300016Sadrian default: 2539300016Sadrian bwn_nphy_rssi_select(mac, 1, N_RSSI_W2); 2540300016Sadrian break; 2541300016Sadrian } 2542300016Sadrian 2543300016Sadrian switch (state[3]) { 2544300016Sadrian case 1: 2545300016Sadrian bwn_nphy_rssi_select(mac, 2, N_RSSI_NB); 2546300016Sadrian break; 2547300016Sadrian case 4: 2548300016Sadrian bwn_nphy_rssi_select(mac, 2, N_RSSI_W1); 2549300016Sadrian break; 2550300016Sadrian default: 2551300016Sadrian bwn_nphy_rssi_select(mac, 2, N_RSSI_W2); 2552300016Sadrian break; 2553300016Sadrian } 2554300016Sadrian 2555300016Sadrian bwn_nphy_rssi_select(mac, 0, type); 2556300016Sadrian 2557300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, regs_save_phy[0]); 2558300016Sadrian BWN_RF_WRITE(mac, B2055_C1_PD_RXTX, regs_save_radio[0]); 2559300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, regs_save_phy[1]); 2560300016Sadrian BWN_RF_WRITE(mac, B2055_C2_PD_RXTX, regs_save_radio[1]); 2561300016Sadrian 2562300016Sadrian bwn_nphy_classifier(mac, 7, class); 2563300016Sadrian bwn_nphy_write_clip_detection(mac, clip_state); 2564300016Sadrian /* Specs don't say about reset here, but it makes wl and b43 dumps 2565300016Sadrian identical, it really seems wl performs this */ 2566300016Sadrian bwn_nphy_reset_cca(mac); 2567300016Sadrian} 2568300016Sadrian 2569300016Sadrian/* 2570300016Sadrian * RSSI Calibration 2571300016Sadrian * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal 2572300016Sadrian */ 2573300016Sadrianstatic void bwn_nphy_rssi_cal(struct bwn_mac *mac) 2574300016Sadrian{ 2575300016Sadrian if (mac->mac_phy.rev >= 19) { 2576300016Sadrian /* TODO */ 2577300016Sadrian } else if (mac->mac_phy.rev >= 3) { 2578300016Sadrian bwn_nphy_rev3_rssi_cal(mac); 2579300016Sadrian } else { 2580300016Sadrian bwn_nphy_rev2_rssi_cal(mac, N_RSSI_NB); 2581300016Sadrian bwn_nphy_rev2_rssi_cal(mac, N_RSSI_W1); 2582300016Sadrian bwn_nphy_rev2_rssi_cal(mac, N_RSSI_W2); 2583300016Sadrian } 2584300016Sadrian} 2585300016Sadrian 2586300016Sadrian/************************************************** 2587300016Sadrian * Workarounds 2588300016Sadrian **************************************************/ 2589300016Sadrian 2590300016Sadrianstatic void bwn_nphy_gain_ctl_workarounds_rev19(struct bwn_mac *mac) 2591300016Sadrian{ 2592300016Sadrian /* TODO */ 2593300016Sadrian} 2594300016Sadrian 2595300016Sadrianstatic void bwn_nphy_gain_ctl_workarounds_rev7(struct bwn_mac *mac) 2596300016Sadrian{ 2597300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 2598300016Sadrian 2599300016Sadrian switch (phy->rev) { 2600300016Sadrian /* TODO */ 2601300016Sadrian } 2602300016Sadrian} 2603300016Sadrian 2604300016Sadrianstatic void bwn_nphy_gain_ctl_workarounds_rev3(struct bwn_mac *mac) 2605300016Sadrian{ 2606300016Sadrian struct bwn_softc *sc = mac->mac_sc; 2607300016Sadrian bool ghz5; 2608300016Sadrian bool ext_lna; 2609300016Sadrian uint16_t rssi_gain; 2610300016Sadrian struct bwn_nphy_gain_ctl_workaround_entry *e; 2611300016Sadrian uint8_t lpf_gain[6] = { 0x00, 0x06, 0x0C, 0x12, 0x12, 0x12 }; 2612300016Sadrian uint8_t lpf_bits[6] = { 0, 1, 2, 3, 3, 3 }; 2613300016Sadrian 2614300016Sadrian /* Prepare values */ 2615300016Sadrian ghz5 = BWN_PHY_READ(mac, BWN_NPHY_BANDCTL) 2616300016Sadrian & BWN_NPHY_BANDCTL_5GHZ; 2617300016Sadrian ext_lna = ghz5 ? siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_EXTLNA_5GHZ : 2618300016Sadrian siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA; 2619300016Sadrian e = bwn_nphy_get_gain_ctl_workaround_ent(mac, ghz5, ext_lna); 2620300016Sadrian if (ghz5 && mac->mac_phy.rev >= 5) 2621300016Sadrian rssi_gain = 0x90; 2622300016Sadrian else 2623300016Sadrian rssi_gain = 0x50; 2624300016Sadrian 2625300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RXCTL, 0x0040); 2626300016Sadrian 2627300016Sadrian /* Set Clip 2 detect */ 2628300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_C1_CGAINI, BWN_NPHY_C1_CGAINI_CL2DETECT); 2629300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_C2_CGAINI, BWN_NPHY_C2_CGAINI_CL2DETECT); 2630300016Sadrian 2631300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_BIASPOLE_LNAG1_IDAC, 2632300016Sadrian 0x17); 2633300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_BIASPOLE_LNAG1_IDAC, 2634300016Sadrian 0x17); 2635300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_LNAG2_IDAC, 0xF0); 2636300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_LNAG2_IDAC, 0xF0); 2637300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_RSSI_POLE, 0x00); 2638300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_RSSI_POLE, 0x00); 2639300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_RSSI_GAIN, 2640300016Sadrian rssi_gain); 2641300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_RSSI_GAIN, 2642300016Sadrian rssi_gain); 2643300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_BIASPOLE_LNAA1_IDAC, 2644300016Sadrian 0x17); 2645300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_BIASPOLE_LNAA1_IDAC, 2646300016Sadrian 0x17); 2647300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_LNAA2_IDAC, 0xFF); 2648300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_LNAA2_IDAC, 0xFF); 2649300016Sadrian 2650300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(0, 8), 4, e->lna1_gain); 2651300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(1, 8), 4, e->lna1_gain); 2652300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(0, 16), 4, e->lna2_gain); 2653300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(1, 16), 4, e->lna2_gain); 2654300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(0, 32), 10, e->gain_db); 2655300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(1, 32), 10, e->gain_db); 2656300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(2, 32), 10, e->gain_bits); 2657300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(3, 32), 10, e->gain_bits); 2658300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(0, 0x40), 6, lpf_gain); 2659300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(1, 0x40), 6, lpf_gain); 2660300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(2, 0x40), 6, lpf_bits); 2661300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(3, 0x40), 6, lpf_bits); 2662300016Sadrian 2663300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C1_INITGAIN_A, e->init_gain); 2664300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C2_INITGAIN_A, e->init_gain); 2665300016Sadrian 2666300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x106), 2, 2667300016Sadrian e->rfseq_init); 2668300016Sadrian 2669300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C1_CLIP_HIGAIN_A, e->cliphi_gain); 2670300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C2_CLIP_HIGAIN_A, e->cliphi_gain); 2671300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C1_CLIP_MEDGAIN_A, e->clipmd_gain); 2672300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C2_CLIP_MEDGAIN_A, e->clipmd_gain); 2673300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C1_CLIP_LOGAIN_A, e->cliplo_gain); 2674300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C2_CLIP_LOGAIN_A, e->cliplo_gain); 2675300016Sadrian 2676300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_CRSMINPOWER0, 0xFF00, e->crsmin); 2677300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_CRSMINPOWERL0, 0xFF00, e->crsminl); 2678300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_CRSMINPOWERU0, 0xFF00, e->crsminu); 2679300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_C1_NBCLIPTHRES, e->nbclip); 2680300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_C2_NBCLIPTHRES, e->nbclip); 2681300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_C1_CLIPWBTHRES, 2682300016Sadrian ~BWN_NPHY_C1_CLIPWBTHRES_CLIP2, e->wlclip); 2683300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_C2_CLIPWBTHRES, 2684300016Sadrian ~BWN_NPHY_C2_CLIPWBTHRES_CLIP2, e->wlclip); 2685300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_CCK_SHIFTB_REF, 0x809C); 2686300016Sadrian} 2687300016Sadrian 2688300016Sadrianstatic void bwn_nphy_gain_ctl_workarounds_rev1_2(struct bwn_mac *mac) 2689300016Sadrian{ 2690300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 2691300016Sadrian 2692300016Sadrian uint8_t i, j; 2693300016Sadrian uint8_t code; 2694300016Sadrian uint16_t tmp; 2695300016Sadrian uint8_t rfseq_events[3] = { 6, 8, 7 }; 2696300016Sadrian uint8_t rfseq_delays[3] = { 10, 30, 1 }; 2697300016Sadrian 2698300016Sadrian /* Set Clip 2 detect */ 2699300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_C1_CGAINI, BWN_NPHY_C1_CGAINI_CL2DETECT); 2700300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_C2_CGAINI, BWN_NPHY_C2_CGAINI_CL2DETECT); 2701300016Sadrian 2702300016Sadrian /* Set narrowband clip threshold */ 2703300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_C1_NBCLIPTHRES, 0x84); 2704300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_C2_NBCLIPTHRES, 0x84); 2705300016Sadrian 2706300016Sadrian if (!bwn_is_40mhz(mac)) { 2707300016Sadrian /* Set dwell lengths */ 2708300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_CLIP1_NBDWELL_LEN, 0x002B); 2709300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_CLIP2_NBDWELL_LEN, 0x002B); 2710300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_W1CLIP1_DWELL_LEN, 0x0009); 2711300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_W1CLIP2_DWELL_LEN, 0x0009); 2712300016Sadrian } 2713300016Sadrian 2714300016Sadrian /* Set wideband clip 2 threshold */ 2715300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_C1_CLIPWBTHRES, 2716300016Sadrian ~BWN_NPHY_C1_CLIPWBTHRES_CLIP2, 21); 2717300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_C2_CLIPWBTHRES, 2718300016Sadrian ~BWN_NPHY_C2_CLIPWBTHRES_CLIP2, 21); 2719300016Sadrian 2720300016Sadrian if (!bwn_is_40mhz(mac)) { 2721300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_C1_CGAINI, 2722300016Sadrian ~BWN_NPHY_C1_CGAINI_GAINBKOFF, 0x1); 2723300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_C2_CGAINI, 2724300016Sadrian ~BWN_NPHY_C2_CGAINI_GAINBKOFF, 0x1); 2725300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_C1_CCK_CGAINI, 2726300016Sadrian ~BWN_NPHY_C1_CCK_CGAINI_GAINBKOFF, 0x1); 2727300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_C2_CCK_CGAINI, 2728300016Sadrian ~BWN_NPHY_C2_CCK_CGAINI_GAINBKOFF, 0x1); 2729300016Sadrian } 2730300016Sadrian 2731300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_CCK_SHIFTB_REF, 0x809C); 2732300016Sadrian 2733300016Sadrian if (nphy->gain_boost) { 2734300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G && 2735300016Sadrian bwn_is_40mhz(mac)) 2736300016Sadrian code = 4; 2737300016Sadrian else 2738300016Sadrian code = 5; 2739300016Sadrian } else { 2740300016Sadrian code = bwn_is_40mhz(mac) ? 6 : 7; 2741300016Sadrian } 2742300016Sadrian 2743300016Sadrian /* Set HPVGA2 index */ 2744300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_C1_INITGAIN, ~BWN_NPHY_C1_INITGAIN_HPVGA2, 2745300016Sadrian code << BWN_NPHY_C1_INITGAIN_HPVGA2_SHIFT); 2746300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_C2_INITGAIN, ~BWN_NPHY_C2_INITGAIN_HPVGA2, 2747300016Sadrian code << BWN_NPHY_C2_INITGAIN_HPVGA2_SHIFT); 2748300016Sadrian 2749300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x1D06); 2750300016Sadrian /* specs say about 2 loops, but wl does 4 */ 2751300016Sadrian for (i = 0; i < 4; i++) 2752300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, (code << 8 | 0x7C)); 2753300016Sadrian 2754300016Sadrian bwn_nphy_adjust_lna_gain_table(mac); 2755300016Sadrian 2756300016Sadrian if (nphy->elna_gain_config) { 2757300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x0808); 2758300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x0); 2759300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1); 2760300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1); 2761300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1); 2762300016Sadrian 2763300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x0C08); 2764300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x0); 2765300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1); 2766300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1); 2767300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1); 2768300016Sadrian 2769300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x1D06); 2770300016Sadrian /* specs say about 2 loops, but wl does 4 */ 2771300016Sadrian for (i = 0; i < 4; i++) 2772300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 2773300016Sadrian (code << 8 | 0x74)); 2774300016Sadrian } 2775300016Sadrian 2776300016Sadrian if (mac->mac_phy.rev == 2) { 2777300016Sadrian for (i = 0; i < 4; i++) { 2778300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 2779300016Sadrian (0x0400 * i) + 0x0020); 2780300016Sadrian for (j = 0; j < 21; j++) { 2781300016Sadrian tmp = j * (i < 2 ? 3 : 1); 2782300016Sadrian BWN_PHY_WRITE(mac, 2783300016Sadrian BWN_NPHY_TABLE_DATALO, tmp); 2784300016Sadrian } 2785300016Sadrian } 2786300016Sadrian } 2787300016Sadrian 2788300016Sadrian bwn_nphy_set_rf_sequence(mac, 5, rfseq_events, rfseq_delays, 3); 2789300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_OVER_DGAIN1, 2790300016Sadrian ~BWN_NPHY_OVER_DGAIN_CCKDGECV & 0xFFFF, 2791300016Sadrian 0x5A << BWN_NPHY_OVER_DGAIN_CCKDGECV_SHIFT); 2792300016Sadrian 2793300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 2794300016Sadrian BWN_PHY_SETMASK(mac, BWN_PHY_N(0xC5D), 0xFF80, 4); 2795300016Sadrian} 2796300016Sadrian 2797300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */ 2798300016Sadrianstatic void bwn_nphy_gain_ctl_workarounds(struct bwn_mac *mac) 2799300016Sadrian{ 2800300016Sadrian if (mac->mac_phy.rev >= 19) 2801300016Sadrian bwn_nphy_gain_ctl_workarounds_rev19(mac); 2802300016Sadrian else if (mac->mac_phy.rev >= 7) 2803300016Sadrian bwn_nphy_gain_ctl_workarounds_rev7(mac); 2804300016Sadrian else if (mac->mac_phy.rev >= 3) 2805300016Sadrian bwn_nphy_gain_ctl_workarounds_rev3(mac); 2806300016Sadrian else 2807300016Sadrian bwn_nphy_gain_ctl_workarounds_rev1_2(mac); 2808300016Sadrian} 2809300016Sadrian 2810300016Sadrianstatic void bwn_nphy_workarounds_rev7plus(struct bwn_mac *mac) 2811300016Sadrian{ 2812300016Sadrian struct bwn_softc *sc = mac->mac_sc; 2813300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 2814300016Sadrian 2815300016Sadrian /* TX to RX */ 2816300016Sadrian uint8_t tx2rx_events[7] = { 4, 3, 5, 2, 1, 8, 31, }; 2817300016Sadrian uint8_t tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1, }; 2818300016Sadrian /* RX to TX */ 2819300016Sadrian uint8_t rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3, 2820300016Sadrian 0x1F }; 2821300016Sadrian uint8_t rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; 2822300016Sadrian 2823300016Sadrian static const uint16_t ntab7_15e_16e[] = { 0, 0x10f, 0x10f }; 2824300016Sadrian uint8_t ntab7_138_146[] = { 0x11, 0x11 }; 2825300016Sadrian uint8_t ntab7_133[] = { 0x77, 0x11, 0x11 }; 2826300016Sadrian 2827300016Sadrian uint16_t lpf_ofdm_20mhz[2], lpf_ofdm_40mhz[2], lpf_11b[2]; 2828300016Sadrian uint16_t bcap_val; 2829300016Sadrian int16_t bcap_val_11b[2], bcap_val_11n_20[2], bcap_val_11n_40[2]; 2830300016Sadrian uint16_t scap_val; 2831300016Sadrian int16_t scap_val_11b[2], scap_val_11n_20[2], scap_val_11n_40[2]; 2832300016Sadrian bool rccal_ovrd = false; 2833300016Sadrian 2834300016Sadrian uint16_t bias, conv, filt; 2835300016Sadrian 2836300016Sadrian uint32_t noise_tbl[2]; 2837300016Sadrian 2838300016Sadrian uint32_t tmp32; 2839300016Sadrian uint8_t core; 2840300016Sadrian 2841300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A0, 0x0125); 2842300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A1, 0x01b3); 2843300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A2, 0x0105); 2844300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B0, 0x016e); 2845300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B1, 0x00cd); 2846300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B2, 0x0020); 2847300016Sadrian 2848300016Sadrian if (phy->rev == 7) { 2849300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_FINERX2_CGC, 0x10); 2850300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN0, 0xFF80, 0x0020); 2851300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN0, 0x80FF, 0x2700); 2852300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN1, 0xFF80, 0x002E); 2853300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN1, 0x80FF, 0x3300); 2854300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN2, 0xFF80, 0x0037); 2855300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN2, 0x80FF, 0x3A00); 2856300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN3, 0xFF80, 0x003C); 2857300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN3, 0x80FF, 0x3E00); 2858300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN4, 0xFF80, 0x003E); 2859300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN4, 0x80FF, 0x3F00); 2860300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN5, 0xFF80, 0x0040); 2861300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN5, 0x80FF, 0x4000); 2862300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN6, 0xFF80, 0x0040); 2863300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN6, 0x80FF, 0x4000); 2864300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN7, 0xFF80, 0x0040); 2865300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN7, 0x80FF, 0x4000); 2866300016Sadrian } 2867300016Sadrian 2868300016Sadrian if (phy->rev >= 16) { 2869300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT0, 0x7ff); 2870300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT1, 0x7ff); 2871300016Sadrian } else if (phy->rev <= 8) { 2872300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT0, 0x1B0); 2873300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT1, 0x1B0); 2874300016Sadrian } 2875300016Sadrian 2876300016Sadrian if (phy->rev >= 16) 2877300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_TXTAILCNT, ~0xFF, 0xa0); 2878300016Sadrian else if (phy->rev >= 8) 2879300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_TXTAILCNT, ~0xFF, 0x72); 2880300016Sadrian 2881300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x00), 2); 2882300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x10), 2); 2883300016Sadrian tmp32 = bwn_ntab_read(mac, BWN_NTAB32(30, 0)); 2884300016Sadrian tmp32 &= 0xffffff; 2885300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(30, 0), tmp32); 2886300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x15d), 3, ntab7_15e_16e); 2887300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x16d), 3, ntab7_15e_16e); 2888300016Sadrian 2889300016Sadrian bwn_nphy_set_rf_sequence(mac, 1, tx2rx_events, tx2rx_delays, 2890300016Sadrian nitems(tx2rx_events)); 2891300016Sadrian if (bwn_nphy_ipa(mac)) 2892300016Sadrian bwn_nphy_set_rf_sequence(mac, 0, rx2tx_events_ipa, 2893300016Sadrian rx2tx_delays_ipa, nitems(rx2tx_events_ipa)); 2894300016Sadrian 2895300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_EPS_OVERRIDEI_0, 0x3FFF, 0x4000); 2896300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_EPS_OVERRIDEI_1, 0x3FFF, 0x4000); 2897300016Sadrian 2898300016Sadrian for (core = 0; core < 2; core++) { 2899300016Sadrian lpf_ofdm_20mhz[core] = bwn_nphy_read_lpf_ctl(mac, 0x154 + core * 0x10); 2900300016Sadrian lpf_ofdm_40mhz[core] = bwn_nphy_read_lpf_ctl(mac, 0x159 + core * 0x10); 2901300016Sadrian lpf_11b[core] = bwn_nphy_read_lpf_ctl(mac, 0x152 + core * 0x10); 2902300016Sadrian } 2903300016Sadrian 2904300016Sadrian bcap_val = BWN_RF_READ(mac, R2057_RCCAL_BCAP_VAL); 2905300016Sadrian scap_val = BWN_RF_READ(mac, R2057_RCCAL_SCAP_VAL); 2906300016Sadrian 2907300016Sadrian if (bwn_nphy_ipa(mac)) { 2908300016Sadrian bool ghz2 = bwn_current_band(mac) == BWN_BAND_2G; 2909300016Sadrian 2910300016Sadrian switch (phy->rf_rev) { 2911300016Sadrian case 5: 2912300016Sadrian /* Check radio version (to be 0) by PHY rev for now */ 2913300016Sadrian if (phy->rev == 8 && bwn_is_40mhz(mac)) { 2914300016Sadrian for (core = 0; core < 2; core++) { 2915300016Sadrian scap_val_11b[core] = scap_val; 2916300016Sadrian bcap_val_11b[core] = bcap_val; 2917300016Sadrian scap_val_11n_20[core] = scap_val; 2918300016Sadrian bcap_val_11n_20[core] = bcap_val; 2919300016Sadrian scap_val_11n_40[core] = 0xc; 2920300016Sadrian bcap_val_11n_40[core] = 0xc; 2921300016Sadrian } 2922300016Sadrian 2923300016Sadrian rccal_ovrd = true; 2924300016Sadrian } 2925300016Sadrian if (phy->rev == 9) { 2926300016Sadrian /* TODO: Radio version 1 (e.g. BCM5357B0) */ 2927300016Sadrian } 2928300016Sadrian break; 2929300016Sadrian case 7: 2930300016Sadrian case 8: 2931300016Sadrian for (core = 0; core < 2; core++) { 2932300016Sadrian scap_val_11b[core] = scap_val; 2933300016Sadrian bcap_val_11b[core] = bcap_val; 2934300016Sadrian lpf_ofdm_20mhz[core] = 4; 2935300016Sadrian lpf_11b[core] = 1; 2936300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 2937300016Sadrian scap_val_11n_20[core] = 0xc; 2938300016Sadrian bcap_val_11n_20[core] = 0xc; 2939300016Sadrian scap_val_11n_40[core] = 0xa; 2940300016Sadrian bcap_val_11n_40[core] = 0xa; 2941300016Sadrian } else { 2942300016Sadrian scap_val_11n_20[core] = 0x14; 2943300016Sadrian bcap_val_11n_20[core] = 0x14; 2944300016Sadrian scap_val_11n_40[core] = 0xf; 2945300016Sadrian bcap_val_11n_40[core] = 0xf; 2946300016Sadrian } 2947300016Sadrian } 2948300016Sadrian 2949300016Sadrian rccal_ovrd = true; 2950300016Sadrian break; 2951300016Sadrian case 9: 2952300016Sadrian for (core = 0; core < 2; core++) { 2953300016Sadrian bcap_val_11b[core] = bcap_val; 2954300016Sadrian scap_val_11b[core] = scap_val; 2955300016Sadrian lpf_11b[core] = 1; 2956300016Sadrian 2957300016Sadrian if (ghz2) { 2958300016Sadrian bcap_val_11n_20[core] = bcap_val + 13; 2959300016Sadrian scap_val_11n_20[core] = scap_val + 15; 2960300016Sadrian } else { 2961300016Sadrian bcap_val_11n_20[core] = bcap_val + 14; 2962300016Sadrian scap_val_11n_20[core] = scap_val + 15; 2963300016Sadrian } 2964300016Sadrian lpf_ofdm_20mhz[core] = 4; 2965300016Sadrian 2966300016Sadrian if (ghz2) { 2967300016Sadrian bcap_val_11n_40[core] = bcap_val - 7; 2968300016Sadrian scap_val_11n_40[core] = scap_val - 5; 2969300016Sadrian } else { 2970300016Sadrian bcap_val_11n_40[core] = bcap_val + 2; 2971300016Sadrian scap_val_11n_40[core] = scap_val + 4; 2972300016Sadrian } 2973300016Sadrian lpf_ofdm_40mhz[core] = 4; 2974300016Sadrian } 2975300016Sadrian 2976300016Sadrian rccal_ovrd = true; 2977300016Sadrian break; 2978300016Sadrian case 14: 2979300016Sadrian for (core = 0; core < 2; core++) { 2980300016Sadrian bcap_val_11b[core] = bcap_val; 2981300016Sadrian scap_val_11b[core] = scap_val; 2982300016Sadrian lpf_11b[core] = 1; 2983300016Sadrian } 2984300016Sadrian 2985300016Sadrian bcap_val_11n_20[0] = bcap_val + 20; 2986300016Sadrian scap_val_11n_20[0] = scap_val + 20; 2987300016Sadrian lpf_ofdm_20mhz[0] = 3; 2988300016Sadrian 2989300016Sadrian bcap_val_11n_20[1] = bcap_val + 16; 2990300016Sadrian scap_val_11n_20[1] = scap_val + 16; 2991300016Sadrian lpf_ofdm_20mhz[1] = 3; 2992300016Sadrian 2993300016Sadrian bcap_val_11n_40[0] = bcap_val + 20; 2994300016Sadrian scap_val_11n_40[0] = scap_val + 20; 2995300016Sadrian lpf_ofdm_40mhz[0] = 4; 2996300016Sadrian 2997300016Sadrian bcap_val_11n_40[1] = bcap_val + 10; 2998300016Sadrian scap_val_11n_40[1] = scap_val + 10; 2999300016Sadrian lpf_ofdm_40mhz[1] = 4; 3000300016Sadrian 3001300016Sadrian rccal_ovrd = true; 3002300016Sadrian break; 3003300016Sadrian } 3004300016Sadrian } else { 3005300016Sadrian if (phy->rf_rev == 5) { 3006300016Sadrian for (core = 0; core < 2; core++) { 3007300016Sadrian lpf_ofdm_20mhz[core] = 1; 3008300016Sadrian lpf_ofdm_40mhz[core] = 3; 3009300016Sadrian scap_val_11b[core] = scap_val; 3010300016Sadrian bcap_val_11b[core] = bcap_val; 3011300016Sadrian scap_val_11n_20[core] = 0x11; 3012300016Sadrian scap_val_11n_40[core] = 0x11; 3013300016Sadrian bcap_val_11n_20[core] = 0x13; 3014300016Sadrian bcap_val_11n_40[core] = 0x13; 3015300016Sadrian } 3016300016Sadrian 3017300016Sadrian rccal_ovrd = true; 3018300016Sadrian } 3019300016Sadrian } 3020300016Sadrian if (rccal_ovrd) { 3021300016Sadrian uint16_t rx2tx_lut_20_11b[2], rx2tx_lut_20_11n[2], rx2tx_lut_40_11n[2]; 3022300016Sadrian uint8_t rx2tx_lut_extra = 1; 3023300016Sadrian 3024300016Sadrian for (core = 0; core < 2; core++) { 3025300016Sadrian bcap_val_11b[core] = bwn_clamp_val(bcap_val_11b[core], 0, 0x1f); 3026300016Sadrian scap_val_11b[core] = bwn_clamp_val(scap_val_11b[core], 0, 0x1f); 3027300016Sadrian bcap_val_11n_20[core] = bwn_clamp_val(bcap_val_11n_20[core], 0, 0x1f); 3028300016Sadrian scap_val_11n_20[core] = bwn_clamp_val(scap_val_11n_20[core], 0, 0x1f); 3029300016Sadrian bcap_val_11n_40[core] = bwn_clamp_val(bcap_val_11n_40[core], 0, 0x1f); 3030300016Sadrian scap_val_11n_40[core] = bwn_clamp_val(scap_val_11n_40[core], 0, 0x1f); 3031300016Sadrian 3032300016Sadrian rx2tx_lut_20_11b[core] = (rx2tx_lut_extra << 13) | 3033300016Sadrian (bcap_val_11b[core] << 8) | 3034300016Sadrian (scap_val_11b[core] << 3) | 3035300016Sadrian lpf_11b[core]; 3036300016Sadrian rx2tx_lut_20_11n[core] = (rx2tx_lut_extra << 13) | 3037300016Sadrian (bcap_val_11n_20[core] << 8) | 3038300016Sadrian (scap_val_11n_20[core] << 3) | 3039300016Sadrian lpf_ofdm_20mhz[core]; 3040300016Sadrian rx2tx_lut_40_11n[core] = (rx2tx_lut_extra << 13) | 3041300016Sadrian (bcap_val_11n_40[core] << 8) | 3042300016Sadrian (scap_val_11n_40[core] << 3) | 3043300016Sadrian lpf_ofdm_40mhz[core]; 3044300016Sadrian } 3045300016Sadrian 3046300016Sadrian for (core = 0; core < 2; core++) { 3047300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(7, 0x152 + core * 16), 3048300016Sadrian rx2tx_lut_20_11b[core]); 3049300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(7, 0x153 + core * 16), 3050300016Sadrian rx2tx_lut_20_11n[core]); 3051300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(7, 0x154 + core * 16), 3052300016Sadrian rx2tx_lut_20_11n[core]); 3053300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(7, 0x155 + core * 16), 3054300016Sadrian rx2tx_lut_40_11n[core]); 3055300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(7, 0x156 + core * 16), 3056300016Sadrian rx2tx_lut_40_11n[core]); 3057300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(7, 0x157 + core * 16), 3058300016Sadrian rx2tx_lut_40_11n[core]); 3059300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(7, 0x158 + core * 16), 3060300016Sadrian rx2tx_lut_40_11n[core]); 3061300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(7, 0x159 + core * 16), 3062300016Sadrian rx2tx_lut_40_11n[core]); 3063300016Sadrian } 3064300016Sadrian } 3065300016Sadrian 3066300016Sadrian BWN_PHY_WRITE(mac, 0x32F, 0x3); 3067300016Sadrian 3068300016Sadrian if (phy->rf_rev == 4 || phy->rf_rev == 6) 3069300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 4, 1, 3, false, 0); 3070300016Sadrian 3071300016Sadrian if (phy->rf_rev == 3 || phy->rf_rev == 4 || phy->rf_rev == 6) { 3072300016Sadrian if (siba_sprom_get_rev(sc->sc_dev) && 3073300016Sadrian siba_sprom_get_bf2_hi(sc->sc_dev) & BWN_BFH2_IPALVLSHIFT_3P3) { 3074300016Sadrian BWN_RF_WRITE(mac, 0x5, 0x05); 3075300016Sadrian BWN_RF_WRITE(mac, 0x6, 0x30); 3076300016Sadrian BWN_RF_WRITE(mac, 0x7, 0x00); 3077300016Sadrian BWN_RF_SET(mac, 0x4f, 0x1); 3078300016Sadrian BWN_RF_SET(mac, 0xd4, 0x1); 3079300016Sadrian bias = 0x1f; 3080300016Sadrian conv = 0x6f; 3081300016Sadrian filt = 0xaa; 3082300016Sadrian } else { 3083300016Sadrian bias = 0x2b; 3084300016Sadrian conv = 0x7f; 3085300016Sadrian filt = 0xee; 3086300016Sadrian } 3087300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 3088300016Sadrian for (core = 0; core < 2; core++) { 3089300016Sadrian if (core == 0) { 3090300016Sadrian BWN_RF_WRITE(mac, 0x5F, bias); 3091300016Sadrian BWN_RF_WRITE(mac, 0x64, conv); 3092300016Sadrian BWN_RF_WRITE(mac, 0x66, filt); 3093300016Sadrian } else { 3094300016Sadrian BWN_RF_WRITE(mac, 0xE8, bias); 3095300016Sadrian BWN_RF_WRITE(mac, 0xE9, conv); 3096300016Sadrian BWN_RF_WRITE(mac, 0xEB, filt); 3097300016Sadrian } 3098300016Sadrian } 3099300016Sadrian } 3100300016Sadrian } 3101300016Sadrian 3102300016Sadrian if (bwn_nphy_ipa(mac)) { 3103300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 3104300016Sadrian if (phy->rf_rev == 3 || phy->rf_rev == 4 || 3105300016Sadrian phy->rf_rev == 6) { 3106300016Sadrian for (core = 0; core < 2; core++) { 3107300016Sadrian if (core == 0) 3108300016Sadrian BWN_RF_WRITE(mac, 0x51, 3109300016Sadrian 0x7f); 3110300016Sadrian else 3111300016Sadrian BWN_RF_WRITE(mac, 0xd6, 3112300016Sadrian 0x7f); 3113300016Sadrian } 3114300016Sadrian } 3115300016Sadrian switch (phy->rf_rev) { 3116300016Sadrian case 3: 3117300016Sadrian for (core = 0; core < 2; core++) { 3118300016Sadrian if (core == 0) { 3119300016Sadrian BWN_RF_WRITE(mac, 0x64, 3120300016Sadrian 0x13); 3121300016Sadrian BWN_RF_WRITE(mac, 0x5F, 3122300016Sadrian 0x1F); 3123300016Sadrian BWN_RF_WRITE(mac, 0x66, 3124300016Sadrian 0xEE); 3125300016Sadrian BWN_RF_WRITE(mac, 0x59, 3126300016Sadrian 0x8A); 3127300016Sadrian BWN_RF_WRITE(mac, 0x80, 3128300016Sadrian 0x3E); 3129300016Sadrian } else { 3130300016Sadrian BWN_RF_WRITE(mac, 0x69, 3131300016Sadrian 0x13); 3132300016Sadrian BWN_RF_WRITE(mac, 0xE8, 3133300016Sadrian 0x1F); 3134300016Sadrian BWN_RF_WRITE(mac, 0xEB, 3135300016Sadrian 0xEE); 3136300016Sadrian BWN_RF_WRITE(mac, 0xDE, 3137300016Sadrian 0x8A); 3138300016Sadrian BWN_RF_WRITE(mac, 0x105, 3139300016Sadrian 0x3E); 3140300016Sadrian } 3141300016Sadrian } 3142300016Sadrian break; 3143300016Sadrian case 7: 3144300016Sadrian case 8: 3145300016Sadrian if (!bwn_is_40mhz(mac)) { 3146300016Sadrian BWN_RF_WRITE(mac, 0x5F, 0x14); 3147300016Sadrian BWN_RF_WRITE(mac, 0xE8, 0x12); 3148300016Sadrian } else { 3149300016Sadrian BWN_RF_WRITE(mac, 0x5F, 0x16); 3150300016Sadrian BWN_RF_WRITE(mac, 0xE8, 0x16); 3151300016Sadrian } 3152300016Sadrian break; 3153300016Sadrian case 14: 3154300016Sadrian for (core = 0; core < 2; core++) { 3155300016Sadrian int o = core ? 0x85 : 0; 3156300016Sadrian 3157300016Sadrian BWN_RF_WRITE(mac, o + R2057_IPA2G_CASCONV_CORE0, 0x13); 3158300016Sadrian BWN_RF_WRITE(mac, o + R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, 0x21); 3159300016Sadrian BWN_RF_WRITE(mac, o + R2057_IPA2G_BIAS_FILTER_CORE0, 0xff); 3160300016Sadrian BWN_RF_WRITE(mac, o + R2057_PAD2G_IDACS_CORE0, 0x88); 3161300016Sadrian BWN_RF_WRITE(mac, o + R2057_PAD2G_TUNE_PUS_CORE0, 0x23); 3162300016Sadrian BWN_RF_WRITE(mac, o + R2057_IPA2G_IMAIN_CORE0, 0x16); 3163300016Sadrian BWN_RF_WRITE(mac, o + R2057_PAD_BIAS_FILTER_BWS_CORE0, 0x3e); 3164300016Sadrian BWN_RF_WRITE(mac, o + R2057_BACKUP1_CORE0, 0x10); 3165300016Sadrian } 3166300016Sadrian break; 3167300016Sadrian } 3168300016Sadrian } else { 3169300016Sadrian uint16_t freq = bwn_get_centre_freq(mac); 3170300016Sadrian if ((freq >= 5180 && freq <= 5230) || 3171300016Sadrian (freq >= 5745 && freq <= 5805)) { 3172300016Sadrian BWN_RF_WRITE(mac, 0x7D, 0xFF); 3173300016Sadrian BWN_RF_WRITE(mac, 0xFE, 0xFF); 3174300016Sadrian } 3175300016Sadrian } 3176300016Sadrian } else { 3177300016Sadrian if (phy->rf_rev != 5) { 3178300016Sadrian for (core = 0; core < 2; core++) { 3179300016Sadrian if (core == 0) { 3180300016Sadrian BWN_RF_WRITE(mac, 0x5c, 0x61); 3181300016Sadrian BWN_RF_WRITE(mac, 0x51, 0x70); 3182300016Sadrian } else { 3183300016Sadrian BWN_RF_WRITE(mac, 0xe1, 0x61); 3184300016Sadrian BWN_RF_WRITE(mac, 0xd6, 0x70); 3185300016Sadrian } 3186300016Sadrian } 3187300016Sadrian } 3188300016Sadrian } 3189300016Sadrian 3190300016Sadrian if (phy->rf_rev == 4) { 3191300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x05), 0x20); 3192300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x15), 0x20); 3193300016Sadrian for (core = 0; core < 2; core++) { 3194300016Sadrian if (core == 0) { 3195300016Sadrian BWN_RF_WRITE(mac, 0x1a1, 0x00); 3196300016Sadrian BWN_RF_WRITE(mac, 0x1a2, 0x3f); 3197300016Sadrian BWN_RF_WRITE(mac, 0x1a6, 0x3f); 3198300016Sadrian } else { 3199300016Sadrian BWN_RF_WRITE(mac, 0x1a7, 0x00); 3200300016Sadrian BWN_RF_WRITE(mac, 0x1ab, 0x3f); 3201300016Sadrian BWN_RF_WRITE(mac, 0x1ac, 0x3f); 3202300016Sadrian } 3203300016Sadrian } 3204300016Sadrian } else { 3205300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_C1, 0x4); 3206300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER1, 0x4); 3207300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_C2, 0x4); 3208300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x4); 3209300016Sadrian 3210300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C1, ~0x1); 3211300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER1, 0x1); 3212300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C2, ~0x1); 3213300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x1); 3214300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x05), 0); 3215300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x15), 0); 3216300016Sadrian 3217300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C1, ~0x4); 3218300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER1, ~0x4); 3219300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C2, ~0x4); 3220300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER, ~0x4); 3221300016Sadrian } 3222300016Sadrian 3223300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ENDROP_TLEN, 0x2); 3224300016Sadrian 3225300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(16, 0x100), 20); 3226300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(7, 0x138), 2, ntab7_138_146); 3227300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(7, 0x141), 0x77); 3228300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(7, 0x133), 3, ntab7_133); 3229300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB8(7, 0x146), 2, ntab7_138_146); 3230300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(7, 0x123), 0x77); 3231300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(7, 0x12A), 0x77); 3232300016Sadrian 3233300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB32(16, 0x02), 1, noise_tbl); 3234300016Sadrian noise_tbl[1] = bwn_is_40mhz(mac) ? 0x14D : 0x18D; 3235300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB32(16, 0x02), 2, noise_tbl); 3236300016Sadrian 3237300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB32(16, 0x7E), 1, noise_tbl); 3238300016Sadrian noise_tbl[1] = bwn_is_40mhz(mac) ? 0x14D : 0x18D; 3239300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB32(16, 0x7E), 2, noise_tbl); 3240300016Sadrian 3241300016Sadrian bwn_nphy_gain_ctl_workarounds(mac); 3242300016Sadrian 3243300016Sadrian /* TODO 3244300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x08), 4, 3245300016Sadrian aux_adc_vmid_rev7_core0); 3246300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x18), 4, 3247300016Sadrian aux_adc_vmid_rev7_core1); 3248300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x0C), 4, 3249300016Sadrian aux_adc_gain_rev7); 3250300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x1C), 4, 3251300016Sadrian aux_adc_gain_rev7); 3252300016Sadrian */ 3253300016Sadrian} 3254300016Sadrian 3255300016Sadrianstatic void bwn_nphy_workarounds_rev3plus(struct bwn_mac *mac) 3256300016Sadrian{ 3257300016Sadrian struct bwn_softc *sc = mac->mac_sc; 3258300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 3259300016Sadrian 3260300016Sadrian /* TX to RX */ 3261300016Sadrian uint8_t tx2rx_events[7] = { 0x4, 0x3, 0x5, 0x2, 0x1, 0x8, 0x1F }; 3262300016Sadrian uint8_t tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1 }; 3263300016Sadrian /* RX to TX */ 3264300016Sadrian uint8_t rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3, 3265300016Sadrian 0x1F }; 3266300016Sadrian uint8_t rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; 3267300016Sadrian uint8_t rx2tx_events[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0x3, 0x4, 0x1F }; 3268300016Sadrian uint8_t rx2tx_delays[9] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 }; 3269300016Sadrian 3270300016Sadrian uint16_t vmids[5][4] = { 3271300016Sadrian { 0xa2, 0xb4, 0xb4, 0x89, }, /* 0 */ 3272300016Sadrian { 0xb4, 0xb4, 0xb4, 0x24, }, /* 1 */ 3273300016Sadrian { 0xa2, 0xb4, 0xb4, 0x74, }, /* 2 */ 3274300016Sadrian { 0xa2, 0xb4, 0xb4, 0x270, }, /* 3 */ 3275300016Sadrian { 0xa2, 0xb4, 0xb4, 0x00, }, /* 4 and 5 */ 3276300016Sadrian }; 3277300016Sadrian uint16_t gains[5][4] = { 3278300016Sadrian { 0x02, 0x02, 0x02, 0x00, }, /* 0 */ 3279300016Sadrian { 0x02, 0x02, 0x02, 0x02, }, /* 1 */ 3280300016Sadrian { 0x02, 0x02, 0x02, 0x04, }, /* 2 */ 3281300016Sadrian { 0x02, 0x02, 0x02, 0x00, }, /* 3 */ 3282300016Sadrian { 0x02, 0x02, 0x02, 0x00, }, /* 4 and 5 */ 3283300016Sadrian }; 3284300016Sadrian uint16_t *vmid, *gain; 3285300016Sadrian 3286300016Sadrian uint8_t pdet_range; 3287300016Sadrian uint16_t tmp16; 3288300016Sadrian uint32_t tmp32; 3289300016Sadrian 3290300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT0, 0x1f8); 3291300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT1, 0x1f8); 3292300016Sadrian 3293300016Sadrian tmp32 = bwn_ntab_read(mac, BWN_NTAB32(30, 0)); 3294300016Sadrian tmp32 &= 0xffffff; 3295300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(30, 0), tmp32); 3296300016Sadrian 3297300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A0, 0x0125); 3298300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A1, 0x01B3); 3299300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A2, 0x0105); 3300300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B0, 0x016E); 3301300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B1, 0x00CD); 3302300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B2, 0x0020); 3303300016Sadrian 3304300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C1_CLIP_LOGAIN_B, 0x000C); 3305300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C2_CLIP_LOGAIN_B, 0x000C); 3306300016Sadrian 3307300016Sadrian /* TX to RX */ 3308300016Sadrian bwn_nphy_set_rf_sequence(mac, 1, tx2rx_events, tx2rx_delays, 3309300016Sadrian nitems(tx2rx_events)); 3310300016Sadrian 3311300016Sadrian /* RX to TX */ 3312300016Sadrian if (bwn_nphy_ipa(mac)) 3313300016Sadrian bwn_nphy_set_rf_sequence(mac, 0, rx2tx_events_ipa, 3314300016Sadrian rx2tx_delays_ipa, nitems(rx2tx_events_ipa)); 3315300016Sadrian if (nphy->hw_phyrxchain != 3 && 3316300016Sadrian nphy->hw_phyrxchain != nphy->hw_phytxchain) { 3317300016Sadrian if (bwn_nphy_ipa(mac)) { 3318300016Sadrian rx2tx_delays[5] = 59; 3319300016Sadrian rx2tx_delays[6] = 1; 3320300016Sadrian rx2tx_events[7] = 0x1F; 3321300016Sadrian } 3322300016Sadrian bwn_nphy_set_rf_sequence(mac, 0, rx2tx_events, rx2tx_delays, 3323300016Sadrian nitems(rx2tx_events)); 3324300016Sadrian } 3325300016Sadrian 3326300016Sadrian tmp16 = (bwn_current_band(mac) == BWN_BAND_2G) ? 3327300016Sadrian 0x2 : 0x9C40; 3328300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ENDROP_TLEN, tmp16); 3329300016Sadrian 3330300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_SGILTRNOFFSET, 0xF0FF, 0x0700); 3331300016Sadrian 3332300016Sadrian if (!bwn_is_40mhz(mac)) { 3333300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(16, 3), 0x18D); 3334300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(16, 127), 0x18D); 3335300016Sadrian } else { 3336300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(16, 3), 0x14D); 3337300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(16, 127), 0x14D); 3338300016Sadrian } 3339300016Sadrian 3340300016Sadrian bwn_nphy_gain_ctl_workarounds(mac); 3341300016Sadrian 3342300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0), 2); 3343300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 16), 2); 3344300016Sadrian 3345300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 3346300016Sadrian pdet_range = siba_sprom_get_fem_2ghz_pdet_range(sc->sc_dev); 3347300016Sadrian else 3348300016Sadrian pdet_range = siba_sprom_get_fem_5ghz_pdet_range(sc->sc_dev); 3349300016Sadrian /* uint16_t min() */ 3350300016Sadrian vmid = vmids[min(pdet_range, 4)]; 3351300016Sadrian gain = gains[min(pdet_range, 4)]; 3352300016Sadrian switch (pdet_range) { 3353300016Sadrian case 3: 3354300016Sadrian if (!(mac->mac_phy.rev >= 4 && 3355300016Sadrian bwn_current_band(mac) == BWN_BAND_2G)) 3356300016Sadrian break; 3357300016Sadrian /* FALL THROUGH */ 3358300016Sadrian case 0: 3359300016Sadrian case 1: 3360300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x08), 4, vmid); 3361300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x18), 4, vmid); 3362300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x0c), 4, gain); 3363300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x1c), 4, gain); 3364300016Sadrian break; 3365300016Sadrian case 2: 3366300016Sadrian if (mac->mac_phy.rev >= 6) { 3367300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 3368300016Sadrian vmid[3] = 0x94; 3369300016Sadrian else 3370300016Sadrian vmid[3] = 0x8e; 3371300016Sadrian gain[3] = 3; 3372300016Sadrian } else if (mac->mac_phy.rev == 5) { 3373300016Sadrian vmid[3] = 0x84; 3374300016Sadrian gain[3] = 2; 3375300016Sadrian } 3376300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x08), 4, vmid); 3377300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x18), 4, vmid); 3378300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x0c), 4, gain); 3379300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x1c), 4, gain); 3380300016Sadrian break; 3381300016Sadrian case 4: 3382300016Sadrian case 5: 3383300016Sadrian if (bwn_current_band(mac) != BWN_BAND_2G) { 3384300016Sadrian if (pdet_range == 4) { 3385300016Sadrian vmid[3] = 0x8e; 3386300016Sadrian tmp16 = 0x96; 3387300016Sadrian gain[3] = 0x2; 3388300016Sadrian } else { 3389300016Sadrian vmid[3] = 0x89; 3390300016Sadrian tmp16 = 0x89; 3391300016Sadrian gain[3] = 0; 3392300016Sadrian } 3393300016Sadrian } else { 3394300016Sadrian if (pdet_range == 4) { 3395300016Sadrian vmid[3] = 0x89; 3396300016Sadrian tmp16 = 0x8b; 3397300016Sadrian gain[3] = 0x2; 3398300016Sadrian } else { 3399300016Sadrian vmid[3] = 0x74; 3400300016Sadrian tmp16 = 0x70; 3401300016Sadrian gain[3] = 0; 3402300016Sadrian } 3403300016Sadrian } 3404300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x08), 4, vmid); 3405300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x0c), 4, gain); 3406300016Sadrian vmid[3] = tmp16; 3407300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x18), 4, vmid); 3408300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x1c), 4, gain); 3409300016Sadrian break; 3410300016Sadrian } 3411300016Sadrian 3412300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXA_MAST_BIAS, 0x00); 3413300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXA_MAST_BIAS, 0x00); 3414300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN, 0x06); 3415300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN, 0x06); 3416300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXA_BIAS_AUX, 0x07); 3417300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07); 3418300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88); 3419300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88); 3420300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXA_CMFB_IDAC, 0x00); 3421300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXA_CMFB_IDAC, 0x00); 3422300016Sadrian BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00); 3423300016Sadrian BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00); 3424300016Sadrian 3425300016Sadrian /* N PHY WAR TX Chain Update with hw_phytxchain as argument */ 3426300016Sadrian 3427300016Sadrian if ((siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_APLL_WAR && 3428300016Sadrian bwn_current_band(mac) == BWN_BAND_5G) || 3429300016Sadrian (siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_GPLL_WAR && 3430300016Sadrian bwn_current_band(mac) == BWN_BAND_2G)) 3431300016Sadrian tmp32 = 0x00088888; 3432300016Sadrian else 3433300016Sadrian tmp32 = 0x88888888; 3434300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(30, 1), tmp32); 3435300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(30, 2), tmp32); 3436300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(30, 3), tmp32); 3437300016Sadrian 3438300016Sadrian if (mac->mac_phy.rev == 4 && 3439300016Sadrian bwn_current_band(mac) == BWN_BAND_5G) { 3440300016Sadrian BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_GMBB_IDAC, 3441300016Sadrian 0x70); 3442300016Sadrian BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_GMBB_IDAC, 3443300016Sadrian 0x70); 3444300016Sadrian } 3445300016Sadrian 3446300016Sadrian /* Dropped probably-always-true condition */ 3447300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS40ASSERTTHRESH0, 0x03eb); 3448300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS40ASSERTTHRESH1, 0x03eb); 3449300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS40DEASSERTTHRESH0, 0x0341); 3450300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS40DEASSERTTHRESH1, 0x0341); 3451300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20LASSERTTHRESH0, 0x042b); 3452300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20LASSERTTHRESH1, 0x042b); 3453300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20LDEASSERTTHRESH0, 0x0381); 3454300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20LDEASSERTTHRESH1, 0x0381); 3455300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20UASSERTTHRESH0, 0x042b); 3456300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20UASSERTTHRESH1, 0x042b); 3457300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20UDEASSERTTHRESH0, 0x0381); 3458300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20UDEASSERTTHRESH1, 0x0381); 3459300016Sadrian 3460300016Sadrian if (mac->mac_phy.rev >= 6 && siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_SINGLEANT_CCK) 3461300016Sadrian ; /* TODO: 0x0080000000000000 HF */ 3462300016Sadrian} 3463300016Sadrian 3464300016Sadrianstatic void bwn_nphy_workarounds_rev1_2(struct bwn_mac *mac) 3465300016Sadrian{ 3466300016Sadrian struct bwn_softc *sc = mac->mac_sc; 3467300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 3468300016Sadrian struct bwn_phy_n *nphy = phy->phy_n; 3469300016Sadrian 3470300016Sadrian uint8_t events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 }; 3471300016Sadrian uint8_t delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 }; 3472300016Sadrian 3473300016Sadrian uint8_t events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 }; 3474300016Sadrian uint8_t delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 }; 3475300016Sadrian 3476300016Sadrian if (siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_SKWRKFEM_BRD || 3477300016Sadrian siba_get_pci_subdevice(sc->sc_dev)== BCMA_BOARD_TYPE_BCM943224M93) { 3478300016Sadrian delays1[0] = 0x1; 3479300016Sadrian delays1[5] = 0x14; 3480300016Sadrian } 3481300016Sadrian 3482300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G && 3483300016Sadrian nphy->band5g_pwrgain) { 3484300016Sadrian BWN_RF_MASK(mac, B2055_C1_TX_RF_SPARE, ~0x8); 3485300016Sadrian BWN_RF_MASK(mac, B2055_C2_TX_RF_SPARE, ~0x8); 3486300016Sadrian } else { 3487300016Sadrian BWN_RF_SET(mac, B2055_C1_TX_RF_SPARE, 0x8); 3488300016Sadrian BWN_RF_SET(mac, B2055_C2_TX_RF_SPARE, 0x8); 3489300016Sadrian } 3490300016Sadrian 3491300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x00), 0x000A); 3492300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x10), 0x000A); 3493300016Sadrian if (mac->mac_phy.rev < 3) { 3494300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x02), 0xCDAA); 3495300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x12), 0xCDAA); 3496300016Sadrian } 3497300016Sadrian 3498300016Sadrian if (mac->mac_phy.rev < 2) { 3499300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x08), 0x0000); 3500300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x18), 0x0000); 3501300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x07), 0x7AAB); 3502300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x17), 0x7AAB); 3503300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x06), 0x0800); 3504300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 0x16), 0x0800); 3505300016Sadrian } 3506300016Sadrian 3507300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); 3508300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP1, 0x301); 3509300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); 3510300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); 3511300016Sadrian 3512300016Sadrian bwn_nphy_set_rf_sequence(mac, 0, events1, delays1, 7); 3513300016Sadrian bwn_nphy_set_rf_sequence(mac, 1, events2, delays2, 7); 3514300016Sadrian 3515300016Sadrian bwn_nphy_gain_ctl_workarounds(mac); 3516300016Sadrian 3517300016Sadrian if (mac->mac_phy.rev < 2) { 3518300016Sadrian if (BWN_PHY_READ(mac, BWN_NPHY_RXCTL) & 0x2) 3519300016Sadrian bwn_hf_write(mac, bwn_hf_read(mac) | 3520300016Sadrian BWN_HF_MLADVW); 3521300016Sadrian } else if (mac->mac_phy.rev == 2) { 3522300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_CRSCHECK2, 0); 3523300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_CRSCHECK3, 0); 3524300016Sadrian } 3525300016Sadrian 3526300016Sadrian if (mac->mac_phy.rev < 2) 3527300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_SCRAM_SIGCTL, 3528300016Sadrian ~BWN_NPHY_SCRAM_SIGCTL_SCM); 3529300016Sadrian 3530300016Sadrian /* Set phase track alpha and beta */ 3531300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A0, 0x125); 3532300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A1, 0x1B3); 3533300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A2, 0x105); 3534300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B0, 0x16E); 3535300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B1, 0xCD); 3536300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B2, 0x20); 3537300016Sadrian 3538300016Sadrian if (mac->mac_phy.rev < 3) { 3539300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_PIL_DW1, 3540300016Sadrian ~BWN_NPHY_PIL_DW_64QAM & 0xFFFF); 3541300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXF_20CO_S2B1, 0xB5); 3542300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXF_20CO_S2B2, 0xA4); 3543300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXF_20CO_S2B3, 0x00); 3544300016Sadrian } 3545300016Sadrian 3546300016Sadrian if (mac->mac_phy.rev == 2) 3547300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_FINERX2_CGC, 3548300016Sadrian BWN_NPHY_FINERX2_CGC_DECGC); 3549300016Sadrian} 3550300016Sadrian 3551300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */ 3552300016Sadrianstatic void bwn_nphy_workarounds(struct bwn_mac *mac) 3553300016Sadrian{ 3554300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 3555300016Sadrian struct bwn_phy_n *nphy = phy->phy_n; 3556300016Sadrian 3557300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G) 3558300016Sadrian bwn_nphy_classifier(mac, 1, 0); 3559300016Sadrian else 3560300016Sadrian bwn_nphy_classifier(mac, 1, 1); 3561300016Sadrian 3562300016Sadrian if (nphy->hang_avoid) 3563300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 1); 3564300016Sadrian 3565300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_IQFLIP, 3566300016Sadrian BWN_NPHY_IQFLIP_ADC1 | BWN_NPHY_IQFLIP_ADC2); 3567300016Sadrian 3568300016Sadrian /* TODO: rev19+ */ 3569300016Sadrian if (mac->mac_phy.rev >= 7) 3570300016Sadrian bwn_nphy_workarounds_rev7plus(mac); 3571300016Sadrian else if (mac->mac_phy.rev >= 3) 3572300016Sadrian bwn_nphy_workarounds_rev3plus(mac); 3573300016Sadrian else 3574300016Sadrian bwn_nphy_workarounds_rev1_2(mac); 3575300016Sadrian 3576300016Sadrian if (nphy->hang_avoid) 3577300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 0); 3578300016Sadrian} 3579300016Sadrian 3580300016Sadrian/************************************************** 3581300016Sadrian * Tx/Rx common 3582300016Sadrian **************************************************/ 3583300016Sadrian 3584300016Sadrian/* 3585300016Sadrian * Transmits a known value for LO calibration 3586300016Sadrian * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone 3587300016Sadrian */ 3588300016Sadrianstatic int bwn_nphy_tx_tone(struct bwn_mac *mac, uint32_t freq, uint16_t max_val, 3589300016Sadrian bool iqmode, bool dac_test, bool modify_bbmult) 3590300016Sadrian{ 3591300016Sadrian uint16_t samp = bwn_nphy_gen_load_samples(mac, freq, max_val, dac_test); 3592300016Sadrian if (samp == 0) 3593300016Sadrian return -1; 3594300016Sadrian bwn_nphy_run_samples(mac, samp, 0xFFFF, 0, iqmode, dac_test, 3595300016Sadrian modify_bbmult); 3596300016Sadrian return 0; 3597300016Sadrian} 3598300016Sadrian 3599300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */ 3600300016Sadrianstatic void bwn_nphy_update_txrx_chain(struct bwn_mac *mac) 3601300016Sadrian{ 3602300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 3603300016Sadrian 3604300016Sadrian bool override = false; 3605300016Sadrian uint16_t chain = 0x33; 3606300016Sadrian 3607300016Sadrian if (nphy->txrx_chain == 0) { 3608300016Sadrian chain = 0x11; 3609300016Sadrian override = true; 3610300016Sadrian } else if (nphy->txrx_chain == 1) { 3611300016Sadrian chain = 0x22; 3612300016Sadrian override = true; 3613300016Sadrian } 3614300016Sadrian 3615300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, 3616300016Sadrian ~(BWN_NPHY_RFSEQCA_TXEN | BWN_NPHY_RFSEQCA_RXEN), 3617300016Sadrian chain); 3618300016Sadrian 3619300016Sadrian if (override) 3620300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RFSEQMODE, 3621300016Sadrian BWN_NPHY_RFSEQMODE_CAOVER); 3622300016Sadrian else 3623300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFSEQMODE, 3624300016Sadrian ~BWN_NPHY_RFSEQMODE_CAOVER); 3625300016Sadrian} 3626300016Sadrian 3627300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */ 3628300016Sadrianstatic void bwn_nphy_stop_playback(struct bwn_mac *mac) 3629300016Sadrian{ 3630300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 3631300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 3632300016Sadrian uint16_t tmp; 3633300016Sadrian 3634300016Sadrian if (nphy->hang_avoid) 3635300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 1); 3636300016Sadrian 3637300016Sadrian tmp = BWN_PHY_READ(mac, BWN_NPHY_SAMP_STAT); 3638300016Sadrian if (tmp & 0x1) 3639300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_SAMP_CMD, BWN_NPHY_SAMP_CMD_STOP); 3640300016Sadrian else if (tmp & 0x2) 3641300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0x7FFF); 3642300016Sadrian 3643300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_SAMP_CMD, ~0x0004); 3644300016Sadrian 3645300016Sadrian if (nphy->bb_mult_save & 0x80000000) { 3646300016Sadrian tmp = nphy->bb_mult_save & 0xFFFF; 3647300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(15, 87), tmp); 3648300016Sadrian nphy->bb_mult_save = 0; 3649300016Sadrian } 3650300016Sadrian 3651300016Sadrian if (phy->rev >= 7 && nphy->lpf_bw_overrode_for_sample_play) { 3652300016Sadrian if (phy->rev >= 19) 3653300016Sadrian bwn_nphy_rf_ctl_override_rev19(mac, 0x80, 0, 0, true, 3654300016Sadrian 1); 3655300016Sadrian else 3656300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x80, 0, 0, true, 1); 3657300016Sadrian nphy->lpf_bw_overrode_for_sample_play = false; 3658300016Sadrian } 3659300016Sadrian 3660300016Sadrian if (nphy->hang_avoid) 3661300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 0); 3662300016Sadrian} 3663300016Sadrian 3664300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IqCalGainParams */ 3665300016Sadrianstatic void bwn_nphy_iq_cal_gain_params(struct bwn_mac *mac, uint16_t core, 3666300016Sadrian struct bwn_nphy_txgains target, 3667300016Sadrian struct bwn_nphy_iqcal_params *params) 3668300016Sadrian{ 3669300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 3670300016Sadrian int i, j, indx; 3671300016Sadrian uint16_t gain; 3672300016Sadrian 3673300016Sadrian if (mac->mac_phy.rev >= 3) { 3674300016Sadrian params->tx_lpf = target.tx_lpf[core]; /* Rev 7+ */ 3675300016Sadrian params->txgm = target.txgm[core]; 3676300016Sadrian params->pga = target.pga[core]; 3677300016Sadrian params->pad = target.pad[core]; 3678300016Sadrian params->ipa = target.ipa[core]; 3679300016Sadrian if (phy->rev >= 19) { 3680300016Sadrian /* TODO */ 3681300016Sadrian } else if (phy->rev >= 7) { 3682300016Sadrian params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 3) | (params->ipa) | (params->tx_lpf << 15); 3683300016Sadrian } else { 3684300016Sadrian params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 4) | (params->ipa); 3685300016Sadrian } 3686300016Sadrian for (j = 0; j < 5; j++) 3687300016Sadrian params->ncorr[j] = 0x79; 3688300016Sadrian } else { 3689300016Sadrian gain = (target.pad[core]) | (target.pga[core] << 4) | 3690300016Sadrian (target.txgm[core] << 8); 3691300016Sadrian 3692300016Sadrian indx = (bwn_current_band(mac) == BWN_BAND_5G) ? 3693300016Sadrian 1 : 0; 3694300016Sadrian for (i = 0; i < 9; i++) 3695300016Sadrian if (tbl_iqcal_gainparams[indx][i][0] == gain) 3696300016Sadrian break; 3697300016Sadrian i = min(i, 8); 3698300016Sadrian 3699300016Sadrian params->txgm = tbl_iqcal_gainparams[indx][i][1]; 3700300016Sadrian params->pga = tbl_iqcal_gainparams[indx][i][2]; 3701300016Sadrian params->pad = tbl_iqcal_gainparams[indx][i][3]; 3702300016Sadrian params->cal_gain = (params->txgm << 7) | (params->pga << 4) | 3703300016Sadrian (params->pad << 2); 3704300016Sadrian for (j = 0; j < 4; j++) 3705300016Sadrian params->ncorr[j] = tbl_iqcal_gainparams[indx][i][4 + j]; 3706300016Sadrian } 3707300016Sadrian} 3708300016Sadrian 3709300016Sadrian/************************************************** 3710300016Sadrian * Tx and Rx 3711300016Sadrian **************************************************/ 3712300016Sadrian 3713300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */ 3714300016Sadrianstatic void bwn_nphy_tx_power_ctrl(struct bwn_mac *mac, bool enable) 3715300016Sadrian{ 3716300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 3717300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 3718300016Sadrian uint8_t i; 3719300016Sadrian uint16_t bmask, val, tmp; 3720300016Sadrian bwn_band_t band = bwn_current_band(mac); 3721300016Sadrian 3722300016Sadrian if (nphy->hang_avoid) 3723300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 1); 3724300016Sadrian 3725300016Sadrian nphy->txpwrctrl = enable; 3726300016Sadrian if (!enable) { 3727300016Sadrian if (mac->mac_phy.rev >= 3 && 3728300016Sadrian (BWN_PHY_READ(mac, BWN_NPHY_TXPCTL_CMD) & 3729300016Sadrian (BWN_NPHY_TXPCTL_CMD_COEFF | 3730300016Sadrian BWN_NPHY_TXPCTL_CMD_HWPCTLEN | 3731300016Sadrian BWN_NPHY_TXPCTL_CMD_PCTLEN))) { 3732300016Sadrian /* We disable enabled TX pwr ctl, save it's state */ 3733300016Sadrian nphy->tx_pwr_idx[0] = BWN_PHY_READ(mac, 3734300016Sadrian BWN_NPHY_C1_TXPCTL_STAT) & 0x7f; 3735300016Sadrian nphy->tx_pwr_idx[1] = BWN_PHY_READ(mac, 3736300016Sadrian BWN_NPHY_C2_TXPCTL_STAT) & 0x7f; 3737300016Sadrian } 3738300016Sadrian 3739300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x6840); 3740300016Sadrian for (i = 0; i < 84; i++) 3741300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0); 3742300016Sadrian 3743300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x6C40); 3744300016Sadrian for (i = 0; i < 84; i++) 3745300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0); 3746300016Sadrian 3747300016Sadrian tmp = BWN_NPHY_TXPCTL_CMD_COEFF | BWN_NPHY_TXPCTL_CMD_HWPCTLEN; 3748300016Sadrian if (mac->mac_phy.rev >= 3) 3749300016Sadrian tmp |= BWN_NPHY_TXPCTL_CMD_PCTLEN; 3750300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_TXPCTL_CMD, ~tmp); 3751300016Sadrian 3752300016Sadrian if (mac->mac_phy.rev >= 3) { 3753300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER1, 0x0100); 3754300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x0100); 3755300016Sadrian } else { 3756300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x4000); 3757300016Sadrian } 3758300016Sadrian 3759300016Sadrian if (mac->mac_phy.rev == 2) 3760300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_BPHY_CTL3, 3761300016Sadrian ~BWN_NPHY_BPHY_CTL3_SCALE, 0x53); 3762300016Sadrian else if (mac->mac_phy.rev < 2) 3763300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_BPHY_CTL3, 3764300016Sadrian ~BWN_NPHY_BPHY_CTL3_SCALE, 0x5A); 3765300016Sadrian 3766300016Sadrian if (mac->mac_phy.rev < 2 && bwn_is_40mhz(mac)) 3767300016Sadrian bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN); 3768300016Sadrian } else { 3769300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(26, 64), 84, 3770300016Sadrian nphy->adj_pwr_tbl); 3771300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(27, 64), 84, 3772300016Sadrian nphy->adj_pwr_tbl); 3773300016Sadrian 3774300016Sadrian bmask = BWN_NPHY_TXPCTL_CMD_COEFF | 3775300016Sadrian BWN_NPHY_TXPCTL_CMD_HWPCTLEN; 3776300016Sadrian /* wl does useless check for "enable" param here */ 3777300016Sadrian val = BWN_NPHY_TXPCTL_CMD_COEFF | BWN_NPHY_TXPCTL_CMD_HWPCTLEN; 3778300016Sadrian if (mac->mac_phy.rev >= 3) { 3779300016Sadrian bmask |= BWN_NPHY_TXPCTL_CMD_PCTLEN; 3780300016Sadrian if (val) 3781300016Sadrian val |= BWN_NPHY_TXPCTL_CMD_PCTLEN; 3782300016Sadrian } 3783300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD, ~(bmask), val); 3784300016Sadrian 3785300016Sadrian if (band == BWN_BAND_5G) { 3786300016Sadrian if (phy->rev >= 19) { 3787300016Sadrian /* TODO */ 3788300016Sadrian } else if (phy->rev >= 7) { 3789300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD, 3790300016Sadrian ~BWN_NPHY_TXPCTL_CMD_INIT, 3791300016Sadrian 0x32); 3792300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_INIT, 3793300016Sadrian ~BWN_NPHY_TXPCTL_INIT_PIDXI1, 3794300016Sadrian 0x32); 3795300016Sadrian } else { 3796300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD, 3797300016Sadrian ~BWN_NPHY_TXPCTL_CMD_INIT, 3798300016Sadrian 0x64); 3799300016Sadrian if (phy->rev > 1) 3800300016Sadrian BWN_PHY_SETMASK(mac, 3801300016Sadrian BWN_NPHY_TXPCTL_INIT, 3802300016Sadrian ~BWN_NPHY_TXPCTL_INIT_PIDXI1, 3803300016Sadrian 0x64); 3804300016Sadrian } 3805300016Sadrian } 3806300016Sadrian 3807300016Sadrian if (mac->mac_phy.rev >= 3) { 3808300016Sadrian if (nphy->tx_pwr_idx[0] != 128 && 3809300016Sadrian nphy->tx_pwr_idx[1] != 128) { 3810300016Sadrian /* Recover TX pwr ctl state */ 3811300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD, 3812300016Sadrian ~BWN_NPHY_TXPCTL_CMD_INIT, 3813300016Sadrian nphy->tx_pwr_idx[0]); 3814300016Sadrian if (mac->mac_phy.rev > 1) 3815300016Sadrian BWN_PHY_SETMASK(mac, 3816300016Sadrian BWN_NPHY_TXPCTL_INIT, 3817300016Sadrian ~0xff, nphy->tx_pwr_idx[1]); 3818300016Sadrian } 3819300016Sadrian } 3820300016Sadrian 3821300016Sadrian if (phy->rev >= 7) { 3822300016Sadrian /* TODO */ 3823300016Sadrian } 3824300016Sadrian 3825300016Sadrian if (mac->mac_phy.rev >= 3) { 3826300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER1, ~0x100); 3827300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER, ~0x100); 3828300016Sadrian } else { 3829300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER, ~0x4000); 3830300016Sadrian } 3831300016Sadrian 3832300016Sadrian if (mac->mac_phy.rev == 2) 3833300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_BPHY_CTL3, ~0xFF, 0x3b); 3834300016Sadrian else if (mac->mac_phy.rev < 2) 3835300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_BPHY_CTL3, ~0xFF, 0x40); 3836300016Sadrian 3837300016Sadrian if (mac->mac_phy.rev < 2 && bwn_is_40mhz(mac)) 3838300016Sadrian bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_TSSI_RESET_PSM_WORKAROUN); 3839300016Sadrian 3840300016Sadrian if (bwn_nphy_ipa(mac)) { 3841300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN0, ~0x4); 3842300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN1, ~0x4); 3843300016Sadrian } 3844300016Sadrian } 3845300016Sadrian 3846300016Sadrian if (nphy->hang_avoid) 3847300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 0); 3848300016Sadrian} 3849300016Sadrian 3850300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrFix */ 3851300016Sadrianstatic void bwn_nphy_tx_power_fix(struct bwn_mac *mac) 3852300016Sadrian{ 3853300016Sadrian struct bwn_softc *sc = mac->mac_sc; 3854300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 3855300016Sadrian 3856300016Sadrian uint8_t txpi[2], bbmult, i; 3857300016Sadrian uint16_t tmp, radio_gain, dac_gain; 3858300016Sadrian uint16_t freq = bwn_get_centre_freq(mac); 3859300016Sadrian uint32_t txgain; 3860300016Sadrian /* uint32_t gaintbl; rev3+ */ 3861300016Sadrian 3862300016Sadrian if (nphy->hang_avoid) 3863300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 1); 3864300016Sadrian 3865300016Sadrian /* TODO: rev19+ */ 3866300016Sadrian if (mac->mac_phy.rev >= 7) { 3867300016Sadrian txpi[0] = txpi[1] = 30; 3868300016Sadrian } else if (mac->mac_phy.rev >= 3) { 3869300016Sadrian txpi[0] = 40; 3870300016Sadrian txpi[1] = 40; 3871300016Sadrian } else if (siba_sprom_get_rev(sc->sc_dev) < 4) { 3872300016Sadrian txpi[0] = 72; 3873300016Sadrian txpi[1] = 72; 3874300016Sadrian } else { 3875300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 3876300016Sadrian txpi[0] = siba_sprom_get_txpid_2g_0(sc->sc_dev); 3877300016Sadrian txpi[1] = siba_sprom_get_txpid_2g_1(sc->sc_dev); 3878300016Sadrian } else if (freq >= 4900 && freq < 5100) { 3879300016Sadrian txpi[0] = siba_sprom_get_txpid_5gl_0(sc->sc_dev); 3880300016Sadrian txpi[1] = siba_sprom_get_txpid_5gl_1(sc->sc_dev); 3881300016Sadrian } else if (freq >= 5100 && freq < 5500) { 3882300016Sadrian txpi[0] = siba_sprom_get_txpid_5g_0(sc->sc_dev); 3883300016Sadrian txpi[1] = siba_sprom_get_txpid_5g_1(sc->sc_dev); 3884300016Sadrian } else if (freq >= 5500) { 3885300016Sadrian txpi[0] = siba_sprom_get_txpid_5gh_0(sc->sc_dev); 3886300016Sadrian txpi[1] = siba_sprom_get_txpid_5gh_1(sc->sc_dev); 3887300016Sadrian } else { 3888300016Sadrian txpi[0] = 91; 3889300016Sadrian txpi[1] = 91; 3890300016Sadrian } 3891300016Sadrian } 3892300016Sadrian if (mac->mac_phy.rev < 7 && 3893300016Sadrian (txpi[0] < 40 || txpi[0] > 100 || txpi[1] < 40 || txpi[1] > 100)) 3894300016Sadrian txpi[0] = txpi[1] = 91; 3895300016Sadrian 3896300016Sadrian /* 3897300016Sadrian for (i = 0; i < 2; i++) { 3898300016Sadrian nphy->txpwrindex[i].index_internal = txpi[i]; 3899300016Sadrian nphy->txpwrindex[i].index_internal_save = txpi[i]; 3900300016Sadrian } 3901300016Sadrian */ 3902300016Sadrian 3903300016Sadrian for (i = 0; i < 2; i++) { 3904300016Sadrian const uint32_t *table = bwn_nphy_get_tx_gain_table(mac); 3905300016Sadrian 3906300016Sadrian if (!table) 3907300016Sadrian break; 3908300016Sadrian txgain = *(table + txpi[i]); 3909300016Sadrian 3910300016Sadrian if (mac->mac_phy.rev >= 3) 3911300016Sadrian radio_gain = (txgain >> 16) & 0x1FFFF; 3912300016Sadrian else 3913300016Sadrian radio_gain = (txgain >> 16) & 0x1FFF; 3914300016Sadrian 3915300016Sadrian if (mac->mac_phy.rev >= 7) 3916300016Sadrian dac_gain = (txgain >> 8) & 0x7; 3917300016Sadrian else 3918300016Sadrian dac_gain = (txgain >> 8) & 0x3F; 3919300016Sadrian bbmult = txgain & 0xFF; 3920300016Sadrian 3921300016Sadrian if (mac->mac_phy.rev >= 3) { 3922300016Sadrian if (i == 0) 3923300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER1, 0x0100); 3924300016Sadrian else 3925300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x0100); 3926300016Sadrian } else { 3927300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x4000); 3928300016Sadrian } 3929300016Sadrian 3930300016Sadrian if (i == 0) 3931300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_DACGAIN1, dac_gain); 3932300016Sadrian else 3933300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_DACGAIN2, dac_gain); 3934300016Sadrian 3935300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(0x7, 0x110 + i), radio_gain); 3936300016Sadrian 3937300016Sadrian tmp = bwn_ntab_read(mac, BWN_NTAB16(0xF, 0x57)); 3938300016Sadrian if (i == 0) 3939300016Sadrian tmp = (tmp & 0x00FF) | (bbmult << 8); 3940300016Sadrian else 3941300016Sadrian tmp = (tmp & 0xFF00) | bbmult; 3942300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(0xF, 0x57), tmp); 3943300016Sadrian 3944300016Sadrian if (bwn_nphy_ipa(mac)) { 3945300016Sadrian uint32_t tmp32; 3946300016Sadrian uint16_t reg = (i == 0) ? 3947300016Sadrian BWN_NPHY_PAPD_EN0 : BWN_NPHY_PAPD_EN1; 3948300016Sadrian tmp32 = bwn_ntab_read(mac, BWN_NTAB32(26 + i, 3949300016Sadrian 576 + txpi[i])); 3950300016Sadrian BWN_PHY_SETMASK(mac, reg, 0xE00F, (uint32_t) tmp32 << 4); 3951300016Sadrian BWN_PHY_SET(mac, reg, 0x4); 3952300016Sadrian } 3953300016Sadrian } 3954300016Sadrian 3955300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_BPHY_CTL2, ~BWN_NPHY_BPHY_CTL2_LUT); 3956300016Sadrian 3957300016Sadrian if (nphy->hang_avoid) 3958300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 0); 3959300016Sadrian} 3960300016Sadrian 3961300016Sadrianstatic void bwn_nphy_ipa_internal_tssi_setup(struct bwn_mac *mac) 3962300016Sadrian{ 3963300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 3964300016Sadrian 3965300016Sadrian uint8_t core; 3966300016Sadrian uint16_t r; /* routing */ 3967300016Sadrian 3968300016Sadrian if (phy->rev >= 19) { 3969300016Sadrian /* TODO */ 3970300016Sadrian } else if (phy->rev >= 7) { 3971300016Sadrian for (core = 0; core < 2; core++) { 3972300016Sadrian r = core ? 0x190 : 0x170; 3973300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 3974300016Sadrian BWN_RF_WRITE(mac, r + 0x5, 0x5); 3975300016Sadrian BWN_RF_WRITE(mac, r + 0x9, 0xE); 3976300016Sadrian if (phy->rev != 5) 3977300016Sadrian BWN_RF_WRITE(mac, r + 0xA, 0); 3978300016Sadrian if (phy->rev != 7) 3979300016Sadrian BWN_RF_WRITE(mac, r + 0xB, 1); 3980300016Sadrian else 3981300016Sadrian BWN_RF_WRITE(mac, r + 0xB, 0x31); 3982300016Sadrian } else { 3983300016Sadrian BWN_RF_WRITE(mac, r + 0x5, 0x9); 3984300016Sadrian BWN_RF_WRITE(mac, r + 0x9, 0xC); 3985300016Sadrian BWN_RF_WRITE(mac, r + 0xB, 0x0); 3986300016Sadrian if (phy->rev != 5) 3987300016Sadrian BWN_RF_WRITE(mac, r + 0xA, 1); 3988300016Sadrian else 3989300016Sadrian BWN_RF_WRITE(mac, r + 0xA, 0x31); 3990300016Sadrian } 3991300016Sadrian BWN_RF_WRITE(mac, r + 0x6, 0); 3992300016Sadrian BWN_RF_WRITE(mac, r + 0x7, 0); 3993300016Sadrian BWN_RF_WRITE(mac, r + 0x8, 3); 3994300016Sadrian BWN_RF_WRITE(mac, r + 0xC, 0); 3995300016Sadrian } 3996300016Sadrian } else { 3997300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 3998300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_RESERVED_ADDR31, 0x128); 3999300016Sadrian else 4000300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_RESERVED_ADDR31, 0x80); 4001300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_RESERVED_ADDR30, 0); 4002300016Sadrian BWN_RF_WRITE(mac, B2056_SYN_GPIO_MASTER1, 0x29); 4003300016Sadrian 4004300016Sadrian for (core = 0; core < 2; core++) { 4005300016Sadrian r = core ? B2056_TX1 : B2056_TX0; 4006300016Sadrian 4007300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_IQCAL_VCM_HG, 0); 4008300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_IQCAL_IDAC, 0); 4009300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TSSI_VCM, 3); 4010300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TX_AMP_DET, 0); 4011300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TSSI_MISC1, 8); 4012300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TSSI_MISC2, 0); 4013300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TSSI_MISC3, 0); 4014300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 4015300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TX_SSI_MASTER, 4016300016Sadrian 0x5); 4017300016Sadrian if (phy->rev != 5) 4018300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TSSIA, 4019300016Sadrian 0x00); 4020300016Sadrian if (phy->rev >= 5) 4021300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TSSIG, 4022300016Sadrian 0x31); 4023300016Sadrian else 4024300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TSSIG, 4025300016Sadrian 0x11); 4026300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TX_SSI_MUX, 4027300016Sadrian 0xE); 4028300016Sadrian } else { 4029300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TX_SSI_MASTER, 4030300016Sadrian 0x9); 4031300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TSSIA, 0x31); 4032300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TSSIG, 0x0); 4033300016Sadrian BWN_RF_WRITE(mac, r | B2056_TX_TX_SSI_MUX, 4034300016Sadrian 0xC); 4035300016Sadrian } 4036300016Sadrian } 4037300016Sadrian } 4038300016Sadrian} 4039300016Sadrian 4040300016Sadrian/* 4041300016Sadrian * Stop radio and transmit known signal. Then check received signal strength to 4042300016Sadrian * get TSSI (Transmit Signal Strength Indicator). 4043300016Sadrian * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlIdleTssi 4044300016Sadrian */ 4045300016Sadrianstatic void bwn_nphy_tx_power_ctl_idle_tssi(struct bwn_mac *mac) 4046300016Sadrian{ 4047300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 4048300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4049300016Sadrian 4050300016Sadrian uint32_t tmp; 4051300016Sadrian int32_t rssi[4] = { }; 4052300016Sadrian 4053300016Sadrian if (bwn_is_chan_passive(mac)) 4054300016Sadrian return; 4055300016Sadrian 4056300016Sadrian if (bwn_nphy_ipa(mac)) 4057300016Sadrian bwn_nphy_ipa_internal_tssi_setup(mac); 4058300016Sadrian 4059300016Sadrian if (phy->rev >= 19) 4060300016Sadrian bwn_nphy_rf_ctl_override_rev19(mac, 0x1000, 0, 3, false, 0); 4061300016Sadrian else if (phy->rev >= 7) 4062300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x1000, 0, 3, false, 0); 4063300016Sadrian else if (phy->rev >= 3) 4064300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x2000, 0, 3, false); 4065300016Sadrian 4066300016Sadrian bwn_nphy_stop_playback(mac); 4067300016Sadrian bwn_nphy_tx_tone(mac, 4000, 0, false, false, false); 4068300016Sadrian DELAY(20); 4069300016Sadrian tmp = bwn_nphy_poll_rssi(mac, N_RSSI_TSSI_2G, rssi, 1); 4070300016Sadrian bwn_nphy_stop_playback(mac); 4071300016Sadrian 4072300016Sadrian bwn_nphy_rssi_select(mac, 0, N_RSSI_W1); 4073300016Sadrian 4074300016Sadrian if (phy->rev >= 19) 4075300016Sadrian bwn_nphy_rf_ctl_override_rev19(mac, 0x1000, 0, 3, true, 0); 4076300016Sadrian else if (phy->rev >= 7) 4077300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x1000, 0, 3, true, 0); 4078300016Sadrian else if (phy->rev >= 3) 4079300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x2000, 0, 3, true); 4080300016Sadrian 4081300016Sadrian if (phy->rev >= 19) { 4082300016Sadrian /* TODO */ 4083300016Sadrian return; 4084300016Sadrian } else if (phy->rev >= 3) { 4085300016Sadrian nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 24) & 0xFF; 4086300016Sadrian nphy->pwr_ctl_info[1].idle_tssi_5g = (tmp >> 8) & 0xFF; 4087300016Sadrian } else { 4088300016Sadrian nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 16) & 0xFF; 4089300016Sadrian nphy->pwr_ctl_info[1].idle_tssi_5g = tmp & 0xFF; 4090300016Sadrian } 4091300016Sadrian nphy->pwr_ctl_info[0].idle_tssi_2g = (tmp >> 24) & 0xFF; 4092300016Sadrian nphy->pwr_ctl_info[1].idle_tssi_2g = (tmp >> 8) & 0xFF; 4093300016Sadrian} 4094300016Sadrian 4095300016Sadrian/* http://bcm-v4.sipsolutions.net/PHY/N/TxPwrLimitToTbl */ 4096300016Sadrianstatic void bwn_nphy_tx_prepare_adjusted_power_table(struct bwn_mac *mac) 4097300016Sadrian{ 4098300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4099300016Sadrian 4100300016Sadrian uint8_t idx, delta; 4101300016Sadrian uint8_t i, stf_mode; 4102300016Sadrian 4103300016Sadrian /* Array adj_pwr_tbl corresponds to the hardware table. It consists of 4104300016Sadrian * 21 groups, each containing 4 entries. 4105300016Sadrian * 4106300016Sadrian * First group has entries for CCK modulation. 4107300016Sadrian * The rest of groups has 1 entry per modulation (SISO, CDD, STBC, SDM). 4108300016Sadrian * 4109300016Sadrian * Group 0 is for CCK 4110300016Sadrian * Groups 1..4 use BPSK (group per coding rate) 4111300016Sadrian * Groups 5..8 use QPSK (group per coding rate) 4112300016Sadrian * Groups 9..12 use 16-QAM (group per coding rate) 4113300016Sadrian * Groups 13..16 use 64-QAM (group per coding rate) 4114300016Sadrian * Groups 17..20 are unknown 4115300016Sadrian */ 4116300016Sadrian 4117300016Sadrian for (i = 0; i < 4; i++) 4118300016Sadrian nphy->adj_pwr_tbl[i] = nphy->tx_power_offset[i]; 4119300016Sadrian 4120300016Sadrian for (stf_mode = 0; stf_mode < 4; stf_mode++) { 4121300016Sadrian delta = 0; 4122300016Sadrian switch (stf_mode) { 4123300016Sadrian case 0: 4124300016Sadrian if (bwn_is_40mhz(mac) && mac->mac_phy.rev >= 5) { 4125300016Sadrian idx = 68; 4126300016Sadrian } else { 4127300016Sadrian delta = 1; 4128300016Sadrian idx = bwn_is_40mhz(mac) ? 52 : 4; 4129300016Sadrian } 4130300016Sadrian break; 4131300016Sadrian case 1: 4132300016Sadrian idx = bwn_is_40mhz(mac) ? 76 : 28; 4133300016Sadrian break; 4134300016Sadrian case 2: 4135300016Sadrian idx = bwn_is_40mhz(mac) ? 84 : 36; 4136300016Sadrian break; 4137300016Sadrian case 3: 4138300016Sadrian idx = bwn_is_40mhz(mac) ? 92 : 44; 4139300016Sadrian break; 4140300016Sadrian } 4141300016Sadrian 4142300016Sadrian for (i = 0; i < 20; i++) { 4143300016Sadrian nphy->adj_pwr_tbl[4 + 4 * i + stf_mode] = 4144300016Sadrian nphy->tx_power_offset[idx]; 4145300016Sadrian if (i == 0) 4146300016Sadrian idx += delta; 4147300016Sadrian if (i == 14) 4148300016Sadrian idx += 1 - delta; 4149300016Sadrian if (i == 3 || i == 4 || i == 7 || i == 8 || i == 11 || 4150300016Sadrian i == 13) 4151300016Sadrian idx += 1; 4152300016Sadrian } 4153300016Sadrian } 4154300016Sadrian} 4155300016Sadrian 4156300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlSetup */ 4157300016Sadrianstatic void bwn_nphy_tx_power_ctl_setup(struct bwn_mac *mac) 4158300016Sadrian{ 4159300016Sadrian struct bwn_softc *sc = mac->mac_sc; 4160300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 4161300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4162300016Sadrian struct siba_sprom_core_pwr_info core_pwr_info[4]; 4163300016Sadrian int n; 4164300016Sadrian 4165300016Sadrian int16_t a1[2], b0[2], b1[2]; 4166300016Sadrian uint8_t idle[2]; 4167300016Sadrian uint8_t ppr_max; 4168300016Sadrian int8_t target[2]; 4169300016Sadrian int32_t num, den, pwr; 4170300016Sadrian uint32_t regval[64]; 4171300016Sadrian 4172300016Sadrian uint16_t freq = bwn_get_centre_freq(mac); 4173300016Sadrian uint16_t tmp; 4174300016Sadrian uint16_t r; /* routing */ 4175300016Sadrian uint8_t i, c; 4176300016Sadrian 4177300016Sadrian for (n = 0; n < 4; n++) { 4178300016Sadrian bzero(&core_pwr_info[n], sizeof(core_pwr_info[n])); 4179300016Sadrian if (siba_sprom_get_core_power_info(sc->sc_dev, n, 4180300016Sadrian &core_pwr_info[n]) != 0) { 4181300016Sadrian BWN_ERRPRINTF(mac->mac_sc, 4182300016Sadrian "%s: failed to get core_pwr_info for core %d\n", 4183300016Sadrian __func__, 4184300016Sadrian n); 4185300016Sadrian } 4186300016Sadrian } 4187300016Sadrian 4188300016Sadrian if (siba_get_revid(sc->sc_dev) == 11 || siba_get_revid(sc->sc_dev) == 12) { 4189300016Sadrian BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~0, 0x200000); 4190300016Sadrian BWN_READ_4(mac, BWN_MACCTL); 4191300016Sadrian DELAY(1); 4192300016Sadrian } 4193300016Sadrian 4194300016Sadrian if (nphy->hang_avoid) 4195300016Sadrian bwn_nphy_stay_in_carrier_search(mac, true); 4196300016Sadrian 4197300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_TSSIMODE, BWN_NPHY_TSSIMODE_EN); 4198300016Sadrian if (mac->mac_phy.rev >= 3) 4199300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_TXPCTL_CMD, 4200300016Sadrian ~BWN_NPHY_TXPCTL_CMD_PCTLEN & 0xFFFF); 4201300016Sadrian else 4202300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_TXPCTL_CMD, 4203300016Sadrian BWN_NPHY_TXPCTL_CMD_PCTLEN); 4204300016Sadrian 4205300016Sadrian if (siba_get_revid(sc->sc_dev) == 11 || siba_get_revid(sc->sc_dev) == 12) 4206300016Sadrian BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~0x200000, 0); 4207300016Sadrian 4208300016Sadrian /* 4209300016Sadrian * XXX TODO: see if those bandsbelow map to 5g-lo, 5g-mid, 5g-hi in 4210300016Sadrian * any way. 4211300016Sadrian */ 4212300016Sadrian if (siba_sprom_get_rev(sc->sc_dev) < 4) { 4213300016Sadrian idle[0] = nphy->pwr_ctl_info[0].idle_tssi_2g; 4214300016Sadrian idle[1] = nphy->pwr_ctl_info[1].idle_tssi_2g; 4215300016Sadrian target[0] = target[1] = 52; 4216300016Sadrian a1[0] = a1[1] = -424; 4217300016Sadrian b0[0] = b0[1] = 5612; 4218300016Sadrian b1[0] = b1[1] = -1393; 4219300016Sadrian } else { 4220300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 4221300016Sadrian for (c = 0; c < 2; c++) { 4222300016Sadrian idle[c] = nphy->pwr_ctl_info[c].idle_tssi_2g; 4223300016Sadrian target[c] = core_pwr_info[c].maxpwr_2g; 4224300016Sadrian a1[c] = core_pwr_info[c].pa_2g[0]; 4225300016Sadrian b0[c] = core_pwr_info[c].pa_2g[1]; 4226300016Sadrian b1[c] = core_pwr_info[c].pa_2g[2]; 4227300016Sadrian } 4228300016Sadrian } else if (freq >= 4900 && freq < 5100) { 4229300016Sadrian for (c = 0; c < 2; c++) { 4230300016Sadrian idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g; 4231300016Sadrian target[c] = core_pwr_info[c].maxpwr_5gl; 4232300016Sadrian a1[c] = core_pwr_info[c].pa_5gl[0]; 4233300016Sadrian b0[c] = core_pwr_info[c].pa_5gl[1]; 4234300016Sadrian b1[c] = core_pwr_info[c].pa_5gl[2]; 4235300016Sadrian } 4236300016Sadrian } else if (freq >= 5100 && freq < 5500) { 4237300016Sadrian for (c = 0; c < 2; c++) { 4238300016Sadrian idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g; 4239300016Sadrian target[c] = core_pwr_info[c].maxpwr_5g; 4240300016Sadrian a1[c] = core_pwr_info[c].pa_5g[0]; 4241300016Sadrian b0[c] = core_pwr_info[c].pa_5g[1]; 4242300016Sadrian b1[c] = core_pwr_info[c].pa_5g[2]; 4243300016Sadrian } 4244300016Sadrian } else if (freq >= 5500) { 4245300016Sadrian for (c = 0; c < 2; c++) { 4246300016Sadrian idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g; 4247300016Sadrian target[c] = core_pwr_info[c].maxpwr_5gh; 4248300016Sadrian a1[c] = core_pwr_info[c].pa_5gh[0]; 4249300016Sadrian b0[c] = core_pwr_info[c].pa_5gh[1]; 4250300016Sadrian b1[c] = core_pwr_info[c].pa_5gh[2]; 4251300016Sadrian } 4252300016Sadrian } else { 4253300016Sadrian idle[0] = nphy->pwr_ctl_info[0].idle_tssi_5g; 4254300016Sadrian idle[1] = nphy->pwr_ctl_info[1].idle_tssi_5g; 4255300016Sadrian target[0] = target[1] = 52; 4256300016Sadrian a1[0] = a1[1] = -424; 4257300016Sadrian b0[0] = b0[1] = 5612; 4258300016Sadrian b1[0] = b1[1] = -1393; 4259300016Sadrian } 4260300016Sadrian } 4261300016Sadrian 4262300016Sadrian ppr_max = bwn_ppr_get_max(mac, &nphy->tx_pwr_max_ppr); 4263300016Sadrian if (ppr_max) { 4264300016Sadrian target[0] = ppr_max; 4265300016Sadrian target[1] = ppr_max; 4266300016Sadrian } 4267300016Sadrian 4268300016Sadrian if (mac->mac_phy.rev >= 3) { 4269300016Sadrian if (siba_sprom_get_fem_2ghz_tssipos(sc->sc_dev)) 4270300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_TXPCTL_ITSSI, 0x4000); 4271300016Sadrian if (mac->mac_phy.rev >= 7) { 4272300016Sadrian for (c = 0; c < 2; c++) { 4273300016Sadrian r = c ? 0x190 : 0x170; 4274300016Sadrian if (bwn_nphy_ipa(mac)) 4275300016Sadrian BWN_RF_WRITE(mac, r + 0x9, (bwn_current_band(mac) == BWN_BAND_2G) ? 0xE : 0xC); 4276300016Sadrian } 4277300016Sadrian } else { 4278300016Sadrian if (bwn_nphy_ipa(mac)) { 4279300016Sadrian tmp = (bwn_current_band(mac) == BWN_BAND_5G) ? 0xC : 0xE; 4280300016Sadrian BWN_RF_WRITE(mac, 4281300016Sadrian B2056_TX0 | B2056_TX_TX_SSI_MUX, tmp); 4282300016Sadrian BWN_RF_WRITE(mac, 4283300016Sadrian B2056_TX1 | B2056_TX_TX_SSI_MUX, tmp); 4284300016Sadrian } else { 4285300016Sadrian BWN_RF_WRITE(mac, 4286300016Sadrian B2056_TX0 | B2056_TX_TX_SSI_MUX, 0x11); 4287300016Sadrian BWN_RF_WRITE(mac, 4288300016Sadrian B2056_TX1 | B2056_TX_TX_SSI_MUX, 0x11); 4289300016Sadrian } 4290300016Sadrian } 4291300016Sadrian } 4292300016Sadrian 4293300016Sadrian if (siba_get_revid(sc->sc_dev) == 11 || siba_get_revid(sc->sc_dev) == 12) { 4294300016Sadrian BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~0, 0x200000); 4295300016Sadrian BWN_READ_4(mac, BWN_MACCTL); 4296300016Sadrian DELAY(1); 4297300016Sadrian } 4298300016Sadrian 4299300016Sadrian if (phy->rev >= 19) { 4300300016Sadrian /* TODO */ 4301300016Sadrian } else if (phy->rev >= 7) { 4302300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD, 4303300016Sadrian ~BWN_NPHY_TXPCTL_CMD_INIT, 0x19); 4304300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_INIT, 4305300016Sadrian ~BWN_NPHY_TXPCTL_INIT_PIDXI1, 0x19); 4306300016Sadrian } else { 4307300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD, 4308300016Sadrian ~BWN_NPHY_TXPCTL_CMD_INIT, 0x40); 4309300016Sadrian if (mac->mac_phy.rev > 1) 4310300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_INIT, 4311300016Sadrian ~BWN_NPHY_TXPCTL_INIT_PIDXI1, 0x40); 4312300016Sadrian } 4313300016Sadrian 4314300016Sadrian if (siba_get_revid(sc->sc_dev) == 11 || siba_get_revid(sc->sc_dev) == 12) 4315300016Sadrian BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~0x200000, 0); 4316300016Sadrian 4317300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXPCTL_N, 4318300016Sadrian 0xF0 << BWN_NPHY_TXPCTL_N_TSSID_SHIFT | 4319300016Sadrian 3 << BWN_NPHY_TXPCTL_N_NPTIL2_SHIFT); 4320300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXPCTL_ITSSI, 4321300016Sadrian idle[0] << BWN_NPHY_TXPCTL_ITSSI_0_SHIFT | 4322300016Sadrian idle[1] << BWN_NPHY_TXPCTL_ITSSI_1_SHIFT | 4323300016Sadrian BWN_NPHY_TXPCTL_ITSSI_BINF); 4324300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXPCTL_TPWR, 4325300016Sadrian target[0] << BWN_NPHY_TXPCTL_TPWR_0_SHIFT | 4326300016Sadrian target[1] << BWN_NPHY_TXPCTL_TPWR_1_SHIFT); 4327300016Sadrian 4328300016Sadrian for (c = 0; c < 2; c++) { 4329300016Sadrian for (i = 0; i < 64; i++) { 4330300016Sadrian num = 8 * (16 * b0[c] + b1[c] * i); 4331300016Sadrian den = 32768 + a1[c] * i; 4332300016Sadrian pwr = max((4 * num + den / 2) / den, -8); 4333300016Sadrian if (mac->mac_phy.rev < 3 && (i <= (31 - idle[c] + 1))) 4334300016Sadrian pwr = max(pwr, target[c] + 1); 4335300016Sadrian regval[i] = pwr; 4336300016Sadrian } 4337300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB32(26 + c, 0), 64, regval); 4338300016Sadrian } 4339300016Sadrian 4340300016Sadrian bwn_nphy_tx_prepare_adjusted_power_table(mac); 4341300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(26, 64), 84, nphy->adj_pwr_tbl); 4342300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(27, 64), 84, nphy->adj_pwr_tbl); 4343300016Sadrian 4344300016Sadrian if (nphy->hang_avoid) 4345300016Sadrian bwn_nphy_stay_in_carrier_search(mac, false); 4346300016Sadrian} 4347300016Sadrian 4348300016Sadrianstatic void bwn_nphy_tx_gain_table_upload(struct bwn_mac *mac) 4349300016Sadrian{ 4350300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 4351300016Sadrian 4352300016Sadrian const uint32_t *table = NULL; 4353300016Sadrian uint32_t rfpwr_offset; 4354300016Sadrian uint8_t pga_gain, pad_gain; 4355300016Sadrian int i; 4356300016Sadrian const int16_t *rf_pwr_offset_table = NULL; 4357300016Sadrian 4358300016Sadrian table = bwn_nphy_get_tx_gain_table(mac); 4359300016Sadrian if (!table) 4360300016Sadrian return; 4361300016Sadrian 4362300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB32(26, 192), 128, table); 4363300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB32(27, 192), 128, table); 4364300016Sadrian 4365300016Sadrian if (phy->rev < 3) 4366300016Sadrian return; 4367300016Sadrian 4368300016Sadrian#if 0 4369300016Sadrian nphy->gmval = (table[0] >> 16) & 0x7000; 4370300016Sadrian#endif 4371300016Sadrian 4372300016Sadrian if (phy->rev >= 19) { 4373300016Sadrian return; 4374300016Sadrian } else if (phy->rev >= 7) { 4375300016Sadrian rf_pwr_offset_table = bwn_ntab_get_rf_pwr_offset_table(mac); 4376300016Sadrian if (!rf_pwr_offset_table) 4377300016Sadrian return; 4378300016Sadrian /* TODO: Enable this once we have gains configured */ 4379300016Sadrian return; 4380300016Sadrian } 4381300016Sadrian 4382300016Sadrian for (i = 0; i < 128; i++) { 4383300016Sadrian if (phy->rev >= 19) { 4384300016Sadrian /* TODO */ 4385300016Sadrian return; 4386300016Sadrian } else if (phy->rev >= 7) { 4387300016Sadrian pga_gain = (table[i] >> 24) & 0xf; 4388300016Sadrian pad_gain = (table[i] >> 19) & 0x1f; 4389300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 4390300016Sadrian rfpwr_offset = rf_pwr_offset_table[pad_gain]; 4391300016Sadrian else 4392300016Sadrian rfpwr_offset = rf_pwr_offset_table[pga_gain]; 4393300016Sadrian } else { 4394300016Sadrian pga_gain = (table[i] >> 24) & 0xF; 4395300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 4396300016Sadrian rfpwr_offset = bwn_ntab_papd_pga_gain_delta_ipa_2g[pga_gain]; 4397300016Sadrian else 4398300016Sadrian rfpwr_offset = 0; /* FIXME */ 4399300016Sadrian } 4400300016Sadrian 4401300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(26, 576 + i), rfpwr_offset); 4402300016Sadrian bwn_ntab_write(mac, BWN_NTAB32(27, 576 + i), rfpwr_offset); 4403300016Sadrian } 4404300016Sadrian} 4405300016Sadrian 4406300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */ 4407300016Sadrianstatic void bwn_nphy_pa_override(struct bwn_mac *mac, bool enable) 4408300016Sadrian{ 4409300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4410300016Sadrian bwn_band_t band; 4411300016Sadrian uint16_t tmp; 4412300016Sadrian 4413300016Sadrian if (!enable) { 4414300016Sadrian nphy->rfctrl_intc1_save = BWN_PHY_READ(mac, 4415300016Sadrian BWN_NPHY_RFCTL_INTC1); 4416300016Sadrian nphy->rfctrl_intc2_save = BWN_PHY_READ(mac, 4417300016Sadrian BWN_NPHY_RFCTL_INTC2); 4418300016Sadrian band = bwn_current_band(mac); 4419300016Sadrian if (mac->mac_phy.rev >= 7) { 4420300016Sadrian tmp = 0x1480; 4421300016Sadrian } else if (mac->mac_phy.rev >= 3) { 4422300016Sadrian if (band == BWN_BAND_5G) 4423300016Sadrian tmp = 0x600; 4424300016Sadrian else 4425300016Sadrian tmp = 0x480; 4426300016Sadrian } else { 4427300016Sadrian if (band == BWN_BAND_5G) 4428300016Sadrian tmp = 0x180; 4429300016Sadrian else 4430300016Sadrian tmp = 0x120; 4431300016Sadrian } 4432300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, tmp); 4433300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, tmp); 4434300016Sadrian } else { 4435300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, 4436300016Sadrian nphy->rfctrl_intc1_save); 4437300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, 4438300016Sadrian nphy->rfctrl_intc2_save); 4439300016Sadrian } 4440300016Sadrian} 4441300016Sadrian 4442300016Sadrian/* 4443300016Sadrian * TX low-pass filter bandwidth setup 4444300016Sadrian * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw 4445300016Sadrian */ 4446300016Sadrianstatic void bwn_nphy_tx_lpf_bw(struct bwn_mac *mac) 4447300016Sadrian{ 4448300016Sadrian uint16_t tmp; 4449300016Sadrian 4450300016Sadrian if (mac->mac_phy.rev < 3 || mac->mac_phy.rev >= 7) 4451300016Sadrian return; 4452300016Sadrian 4453300016Sadrian if (bwn_nphy_ipa(mac)) 4454300016Sadrian tmp = bwn_is_40mhz(mac) ? 5 : 4; 4455300016Sadrian else 4456300016Sadrian tmp = bwn_is_40mhz(mac) ? 3 : 1; 4457300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B32S2, 4458300016Sadrian (tmp << 9) | (tmp << 6) | (tmp << 3) | tmp); 4459300016Sadrian 4460300016Sadrian if (bwn_nphy_ipa(mac)) { 4461300016Sadrian tmp = bwn_is_40mhz(mac) ? 4 : 1; 4462300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B1S2, 4463300016Sadrian (tmp << 9) | (tmp << 6) | (tmp << 3) | tmp); 4464300016Sadrian } 4465300016Sadrian} 4466300016Sadrian 4467300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */ 4468300016Sadrianstatic void bwn_nphy_rx_iq_est(struct bwn_mac *mac, struct bwn_nphy_iq_est *est, 4469300016Sadrian uint16_t samps, uint8_t time, bool wait) 4470300016Sadrian{ 4471300016Sadrian int i; 4472300016Sadrian uint16_t tmp; 4473300016Sadrian 4474300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_IQEST_SAMCNT, samps); 4475300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_IQEST_WT, ~BWN_NPHY_IQEST_WT_VAL, time); 4476300016Sadrian if (wait) 4477300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_IQEST_CMD, BWN_NPHY_IQEST_CMD_MODE); 4478300016Sadrian else 4479300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_IQEST_CMD, ~BWN_NPHY_IQEST_CMD_MODE); 4480300016Sadrian 4481300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_IQEST_CMD, BWN_NPHY_IQEST_CMD_START); 4482300016Sadrian 4483300016Sadrian for (i = 1000; i; i--) { 4484300016Sadrian tmp = BWN_PHY_READ(mac, BWN_NPHY_IQEST_CMD); 4485300016Sadrian if (!(tmp & BWN_NPHY_IQEST_CMD_START)) { 4486300016Sadrian est->i0_pwr = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_IPACC_HI0) << 16) | 4487300016Sadrian BWN_PHY_READ(mac, BWN_NPHY_IQEST_IPACC_LO0); 4488300016Sadrian est->q0_pwr = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_QPACC_HI0) << 16) | 4489300016Sadrian BWN_PHY_READ(mac, BWN_NPHY_IQEST_QPACC_LO0); 4490300016Sadrian est->iq0_prod = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_IQACC_HI0) << 16) | 4491300016Sadrian BWN_PHY_READ(mac, BWN_NPHY_IQEST_IQACC_LO0); 4492300016Sadrian 4493300016Sadrian est->i1_pwr = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_IPACC_HI1) << 16) | 4494300016Sadrian BWN_PHY_READ(mac, BWN_NPHY_IQEST_IPACC_LO1); 4495300016Sadrian est->q1_pwr = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_QPACC_HI1) << 16) | 4496300016Sadrian BWN_PHY_READ(mac, BWN_NPHY_IQEST_QPACC_LO1); 4497300016Sadrian est->iq1_prod = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_IQACC_HI1) << 16) | 4498300016Sadrian BWN_PHY_READ(mac, BWN_NPHY_IQEST_IQACC_LO1); 4499300016Sadrian return; 4500300016Sadrian } 4501300016Sadrian DELAY(10); 4502300016Sadrian } 4503300016Sadrian memset(est, 0, sizeof(*est)); 4504300016Sadrian} 4505300016Sadrian 4506300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */ 4507300016Sadrianstatic void bwn_nphy_rx_iq_coeffs(struct bwn_mac *mac, bool write, 4508300016Sadrian struct bwn_phy_n_iq_comp *pcomp) 4509300016Sadrian{ 4510300016Sadrian if (write) { 4511300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_C1_RXIQ_COMPA0, pcomp->a0); 4512300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_C1_RXIQ_COMPB0, pcomp->b0); 4513300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_C2_RXIQ_COMPA1, pcomp->a1); 4514300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_C2_RXIQ_COMPB1, pcomp->b1); 4515300016Sadrian } else { 4516300016Sadrian pcomp->a0 = BWN_PHY_READ(mac, BWN_NPHY_C1_RXIQ_COMPA0); 4517300016Sadrian pcomp->b0 = BWN_PHY_READ(mac, BWN_NPHY_C1_RXIQ_COMPB0); 4518300016Sadrian pcomp->a1 = BWN_PHY_READ(mac, BWN_NPHY_C2_RXIQ_COMPA1); 4519300016Sadrian pcomp->b1 = BWN_PHY_READ(mac, BWN_NPHY_C2_RXIQ_COMPB1); 4520300016Sadrian } 4521300016Sadrian} 4522300016Sadrian 4523300016Sadrian#if 0 4524300016Sadrian/* Ready but not used anywhere */ 4525300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */ 4526300016Sadrianstatic void bwn_nphy_rx_cal_phy_cleanup(struct bwn_mac *mac, uint8_t core) 4527300016Sadrian{ 4528300016Sadrian uint16_t *regs = mac->mac_phy.phy_n->tx_rx_cal_phy_saveregs; 4529300016Sadrian 4530300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFSEQCA, regs[0]); 4531300016Sadrian if (core == 0) { 4532300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, regs[1]); 4533300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, regs[2]); 4534300016Sadrian } else { 4535300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, regs[1]); 4536300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, regs[2]); 4537300016Sadrian } 4538300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, regs[3]); 4539300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, regs[4]); 4540300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_RSSIO1, regs[5]); 4541300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_RSSIO2, regs[6]); 4542300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B1S1, regs[7]); 4543300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_OVER, regs[8]); 4544300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PAPD_EN0, regs[9]); 4545300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PAPD_EN1, regs[10]); 4546300016Sadrian} 4547300016Sadrian 4548300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhySetup */ 4549300016Sadrianstatic void bwn_nphy_rx_cal_phy_setup(struct bwn_mac *mac, uint8_t core) 4550300016Sadrian{ 4551300016Sadrian uint8_t rxval, txval; 4552300016Sadrian uint16_t *regs = mac->mac_phy.phy_n->tx_rx_cal_phy_saveregs; 4553300016Sadrian 4554300016Sadrian regs[0] = BWN_PHY_READ(mac, BWN_NPHY_RFSEQCA); 4555300016Sadrian if (core == 0) { 4556300016Sadrian regs[1] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C1); 4557300016Sadrian regs[2] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER1); 4558300016Sadrian } else { 4559300016Sadrian regs[1] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C2); 4560300016Sadrian regs[2] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER); 4561300016Sadrian } 4562300016Sadrian regs[3] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC1); 4563300016Sadrian regs[4] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC2); 4564300016Sadrian regs[5] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_RSSIO1); 4565300016Sadrian regs[6] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_RSSIO2); 4566300016Sadrian regs[7] = BWN_PHY_READ(mac, BWN_NPHY_TXF_40CO_B1S1); 4567300016Sadrian regs[8] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_OVER); 4568300016Sadrian regs[9] = BWN_PHY_READ(mac, BWN_NPHY_PAPD_EN0); 4569300016Sadrian regs[10] = BWN_PHY_READ(mac, BWN_NPHY_PAPD_EN1); 4570300016Sadrian 4571300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN0, ~0x0001); 4572300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN1, ~0x0001); 4573300016Sadrian 4574300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, 4575300016Sadrian ~BWN_NPHY_RFSEQCA_RXDIS & 0xFFFF, 4576300016Sadrian ((1 - core) << BWN_NPHY_RFSEQCA_RXDIS_SHIFT)); 4577300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, ~BWN_NPHY_RFSEQCA_TXEN, 4578300016Sadrian ((1 - core) << BWN_NPHY_RFSEQCA_TXEN_SHIFT)); 4579300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, ~BWN_NPHY_RFSEQCA_RXEN, 4580300016Sadrian (core << BWN_NPHY_RFSEQCA_RXEN_SHIFT)); 4581300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, ~BWN_NPHY_RFSEQCA_TXDIS, 4582300016Sadrian (core << BWN_NPHY_RFSEQCA_TXDIS_SHIFT)); 4583300016Sadrian 4584300016Sadrian if (core == 0) { 4585300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C1, ~0x0007); 4586300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER1, 0x0007); 4587300016Sadrian } else { 4588300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C2, ~0x0007); 4589300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x0007); 4590300016Sadrian } 4591300016Sadrian 4592300016Sadrian bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_PA, 0, 3); 4593300016Sadrian bwn_nphy_rf_ctl_override(mac, 8, 0, 3, false); 4594300016Sadrian bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RX2TX); 4595300016Sadrian 4596300016Sadrian if (core == 0) { 4597300016Sadrian rxval = 1; 4598300016Sadrian txval = 8; 4599300016Sadrian } else { 4600300016Sadrian rxval = 4; 4601300016Sadrian txval = 2; 4602300016Sadrian } 4603300016Sadrian bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_TRSW, rxval, 4604300016Sadrian core + 1); 4605300016Sadrian bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_TRSW, txval, 4606300016Sadrian 2 - core); 4607300016Sadrian} 4608300016Sadrian#endif 4609300016Sadrian 4610300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */ 4611300016Sadrianstatic void bwn_nphy_calc_rx_iq_comp(struct bwn_mac *mac, uint8_t mask) 4612300016Sadrian{ 4613300016Sadrian int i; 4614300016Sadrian int32_t iq; 4615300016Sadrian uint32_t ii; 4616300016Sadrian uint32_t qq; 4617300016Sadrian int iq_nbits, qq_nbits; 4618300016Sadrian int arsh, brsh; 4619300016Sadrian uint16_t tmp, a, b; 4620300016Sadrian 4621300016Sadrian struct bwn_nphy_iq_est est; 4622300016Sadrian struct bwn_phy_n_iq_comp old; 4623300016Sadrian struct bwn_phy_n_iq_comp new = { }; 4624300016Sadrian bool error = false; 4625300016Sadrian 4626300016Sadrian if (mask == 0) 4627300016Sadrian return; 4628300016Sadrian 4629300016Sadrian bwn_nphy_rx_iq_coeffs(mac, false, &old); 4630300016Sadrian bwn_nphy_rx_iq_coeffs(mac, true, &new); 4631300016Sadrian bwn_nphy_rx_iq_est(mac, &est, 0x4000, 32, false); 4632300016Sadrian new = old; 4633300016Sadrian 4634300016Sadrian for (i = 0; i < 2; i++) { 4635300016Sadrian if (i == 0 && (mask & 1)) { 4636300016Sadrian iq = est.iq0_prod; 4637300016Sadrian ii = est.i0_pwr; 4638300016Sadrian qq = est.q0_pwr; 4639300016Sadrian } else if (i == 1 && (mask & 2)) { 4640300016Sadrian iq = est.iq1_prod; 4641300016Sadrian ii = est.i1_pwr; 4642300016Sadrian qq = est.q1_pwr; 4643300016Sadrian } else { 4644300016Sadrian continue; 4645300016Sadrian } 4646300016Sadrian 4647300016Sadrian if (ii + qq < 2) { 4648300016Sadrian error = true; 4649300016Sadrian break; 4650300016Sadrian } 4651300016Sadrian 4652300016Sadrian iq_nbits = fls(abs(iq)); 4653300016Sadrian qq_nbits = fls(qq); 4654300016Sadrian 4655300016Sadrian arsh = iq_nbits - 20; 4656300016Sadrian if (arsh >= 0) { 4657300016Sadrian a = -((iq << (30 - iq_nbits)) + (ii >> (1 + arsh))); 4658300016Sadrian tmp = ii >> arsh; 4659300016Sadrian } else { 4660300016Sadrian a = -((iq << (30 - iq_nbits)) + (ii << (-1 - arsh))); 4661300016Sadrian tmp = ii << -arsh; 4662300016Sadrian } 4663300016Sadrian if (tmp == 0) { 4664300016Sadrian error = true; 4665300016Sadrian break; 4666300016Sadrian } 4667300016Sadrian a /= tmp; 4668300016Sadrian 4669300016Sadrian brsh = qq_nbits - 11; 4670300016Sadrian if (brsh >= 0) { 4671300016Sadrian b = (qq << (31 - qq_nbits)); 4672300016Sadrian tmp = ii >> brsh; 4673300016Sadrian } else { 4674300016Sadrian b = (qq << (31 - qq_nbits)); 4675300016Sadrian tmp = ii << -brsh; 4676300016Sadrian } 4677300016Sadrian if (tmp == 0) { 4678300016Sadrian error = true; 4679300016Sadrian break; 4680300016Sadrian } 4681300016Sadrian b = bwn_sqrt(mac, b / tmp - a * a) - (1 << 10); 4682300016Sadrian 4683300016Sadrian if (i == 0 && (mask & 0x1)) { 4684300016Sadrian if (mac->mac_phy.rev >= 3) { 4685300016Sadrian new.a0 = a & 0x3FF; 4686300016Sadrian new.b0 = b & 0x3FF; 4687300016Sadrian } else { 4688300016Sadrian new.a0 = b & 0x3FF; 4689300016Sadrian new.b0 = a & 0x3FF; 4690300016Sadrian } 4691300016Sadrian } else if (i == 1 && (mask & 0x2)) { 4692300016Sadrian if (mac->mac_phy.rev >= 3) { 4693300016Sadrian new.a1 = a & 0x3FF; 4694300016Sadrian new.b1 = b & 0x3FF; 4695300016Sadrian } else { 4696300016Sadrian new.a1 = b & 0x3FF; 4697300016Sadrian new.b1 = a & 0x3FF; 4698300016Sadrian } 4699300016Sadrian } 4700300016Sadrian } 4701300016Sadrian 4702300016Sadrian if (error) 4703300016Sadrian new = old; 4704300016Sadrian 4705300016Sadrian bwn_nphy_rx_iq_coeffs(mac, true, &new); 4706300016Sadrian} 4707300016Sadrian 4708300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */ 4709300016Sadrianstatic void bwn_nphy_tx_iq_workaround(struct bwn_mac *mac) 4710300016Sadrian{ 4711300016Sadrian uint16_t array[4]; 4712300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(0xF, 0x50), 4, array); 4713300016Sadrian 4714300016Sadrian bwn_shm_write_2(mac, BWN_SHARED, BWN_SHM_SH_NPHY_TXIQW0, array[0]); 4715300016Sadrian bwn_shm_write_2(mac, BWN_SHARED, BWN_SHM_SH_NPHY_TXIQW1, array[1]); 4716300016Sadrian bwn_shm_write_2(mac, BWN_SHARED, BWN_SHM_SH_NPHY_TXIQW2, array[2]); 4717300016Sadrian bwn_shm_write_2(mac, BWN_SHARED, BWN_SHM_SH_NPHY_TXIQW3, array[3]); 4718300016Sadrian} 4719300016Sadrian 4720300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SpurWar */ 4721300016Sadrianstatic void bwn_nphy_spur_workaround(struct bwn_mac *mac) 4722300016Sadrian{ 4723300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4724300016Sadrian 4725300016Sadrian uint8_t channel = bwn_get_chan(mac); 4726300016Sadrian int tone[2] = { 57, 58 }; 4727300016Sadrian uint32_t noise[2] = { 0x3FF, 0x3FF }; 4728300016Sadrian 4729300016Sadrian if (mac->mac_phy.rev < 3) { 4730300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "%s: phy rev %d out of range\n", 4731300016Sadrian __func__, 4732300016Sadrian mac->mac_phy.rev); 4733300016Sadrian } 4734300016Sadrian 4735300016Sadrian if (nphy->hang_avoid) 4736300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 1); 4737300016Sadrian 4738300016Sadrian if (nphy->gband_spurwar_en) { 4739300016Sadrian /* TODO: N PHY Adjust Analog Pfbw (7) */ 4740300016Sadrian if (channel == 11 && bwn_is_40mhz(mac)) 4741300016Sadrian ; /* TODO: N PHY Adjust Min Noise Var(2, tone, noise)*/ 4742300016Sadrian else 4743300016Sadrian ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/ 4744300016Sadrian /* TODO: N PHY Adjust CRS Min Power (0x1E) */ 4745300016Sadrian } 4746300016Sadrian 4747300016Sadrian if (nphy->aband_spurwar_en) { 4748300016Sadrian if (channel == 54) { 4749300016Sadrian tone[0] = 0x20; 4750300016Sadrian noise[0] = 0x25F; 4751300016Sadrian } else if (channel == 38 || channel == 102 || channel == 118) { 4752300016Sadrian if (0 /* FIXME */) { 4753300016Sadrian tone[0] = 0x20; 4754300016Sadrian noise[0] = 0x21F; 4755300016Sadrian } else { 4756300016Sadrian tone[0] = 0; 4757300016Sadrian noise[0] = 0; 4758300016Sadrian } 4759300016Sadrian } else if (channel == 134) { 4760300016Sadrian tone[0] = 0x20; 4761300016Sadrian noise[0] = 0x21F; 4762300016Sadrian } else if (channel == 151) { 4763300016Sadrian tone[0] = 0x10; 4764300016Sadrian noise[0] = 0x23F; 4765300016Sadrian } else if (channel == 153 || channel == 161) { 4766300016Sadrian tone[0] = 0x30; 4767300016Sadrian noise[0] = 0x23F; 4768300016Sadrian } else { 4769300016Sadrian tone[0] = 0; 4770300016Sadrian noise[0] = 0; 4771300016Sadrian } 4772300016Sadrian 4773300016Sadrian if (!tone[0] && !noise[0]) 4774300016Sadrian ; /* TODO: N PHY Adjust Min Noise Var(1, tone, noise)*/ 4775300016Sadrian else 4776300016Sadrian ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/ 4777300016Sadrian } 4778300016Sadrian 4779300016Sadrian if (nphy->hang_avoid) 4780300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 0); 4781300016Sadrian} 4782300016Sadrian 4783300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */ 4784300016Sadrianstatic void bwn_nphy_tx_pwr_ctrl_coef_setup(struct bwn_mac *mac) 4785300016Sadrian{ 4786300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4787300016Sadrian int i, j; 4788300016Sadrian uint32_t tmp; 4789300016Sadrian uint32_t cur_real, cur_imag, real_part, imag_part; 4790300016Sadrian 4791300016Sadrian uint16_t buffer[7]; 4792300016Sadrian 4793300016Sadrian if (nphy->hang_avoid) 4794300016Sadrian bwn_nphy_stay_in_carrier_search(mac, true); 4795300016Sadrian 4796300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 80), 7, buffer); 4797300016Sadrian 4798300016Sadrian for (i = 0; i < 2; i++) { 4799300016Sadrian tmp = ((buffer[i * 2] & 0x3FF) << 10) | 4800300016Sadrian (buffer[i * 2 + 1] & 0x3FF); 4801300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 4802300016Sadrian (((i + 26) << 10) | 320)); 4803300016Sadrian for (j = 0; j < 128; j++) { 4804300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATAHI, 4805300016Sadrian ((tmp >> 16) & 0xFFFF)); 4806300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 4807300016Sadrian (tmp & 0xFFFF)); 4808300016Sadrian } 4809300016Sadrian } 4810300016Sadrian 4811300016Sadrian for (i = 0; i < 2; i++) { 4812300016Sadrian tmp = buffer[5 + i]; 4813300016Sadrian real_part = (tmp >> 8) & 0xFF; 4814300016Sadrian imag_part = (tmp & 0xFF); 4815300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 4816300016Sadrian (((i + 26) << 10) | 448)); 4817300016Sadrian 4818300016Sadrian if (mac->mac_phy.rev >= 3) { 4819300016Sadrian cur_real = real_part; 4820300016Sadrian cur_imag = imag_part; 4821300016Sadrian tmp = ((cur_real & 0xFF) << 8) | (cur_imag & 0xFF); 4822300016Sadrian } 4823300016Sadrian 4824300016Sadrian for (j = 0; j < 128; j++) { 4825300016Sadrian if (mac->mac_phy.rev < 3) { 4826300016Sadrian cur_real = (real_part * loscale[j] + 128) >> 8; 4827300016Sadrian cur_imag = (imag_part * loscale[j] + 128) >> 8; 4828300016Sadrian tmp = ((cur_real & 0xFF) << 8) | 4829300016Sadrian (cur_imag & 0xFF); 4830300016Sadrian } 4831300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATAHI, 4832300016Sadrian ((tmp >> 16) & 0xFFFF)); 4833300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 4834300016Sadrian (tmp & 0xFFFF)); 4835300016Sadrian } 4836300016Sadrian } 4837300016Sadrian 4838300016Sadrian if (mac->mac_phy.rev >= 3) { 4839300016Sadrian bwn_shm_write_2(mac, BWN_SHARED, 4840300016Sadrian BWN_SHM_SH_NPHY_TXPWR_INDX0, 0xFFFF); 4841300016Sadrian bwn_shm_write_2(mac, BWN_SHARED, 4842300016Sadrian BWN_SHM_SH_NPHY_TXPWR_INDX1, 0xFFFF); 4843300016Sadrian } 4844300016Sadrian 4845300016Sadrian if (nphy->hang_avoid) 4846300016Sadrian bwn_nphy_stay_in_carrier_search(mac, false); 4847300016Sadrian} 4848300016Sadrian 4849300016Sadrian/* 4850300016Sadrian * Restore RSSI Calibration 4851300016Sadrian * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal 4852300016Sadrian */ 4853300016Sadrianstatic void bwn_nphy_restore_rssi_cal(struct bwn_mac *mac) 4854300016Sadrian{ 4855300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4856300016Sadrian 4857300016Sadrian uint16_t *rssical_radio_regs = NULL; 4858300016Sadrian uint16_t *rssical_phy_regs = NULL; 4859300016Sadrian 4860300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 4861300016Sadrian if (!nphy->rssical_chanspec_2G.center_freq) 4862300016Sadrian return; 4863300016Sadrian rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G; 4864300016Sadrian rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G; 4865300016Sadrian } else { 4866300016Sadrian if (!nphy->rssical_chanspec_5G.center_freq) 4867300016Sadrian return; 4868300016Sadrian rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G; 4869300016Sadrian rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; 4870300016Sadrian } 4871300016Sadrian 4872300016Sadrian if (mac->mac_phy.rev >= 19) { 4873300016Sadrian /* TODO */ 4874300016Sadrian } else if (mac->mac_phy.rev >= 7) { 4875300016Sadrian BWN_RF_SETMASK(mac, R2057_NB_MASTER_CORE0, ~R2057_VCM_MASK, 4876300016Sadrian rssical_radio_regs[0]); 4877300016Sadrian BWN_RF_SETMASK(mac, R2057_NB_MASTER_CORE1, ~R2057_VCM_MASK, 4878300016Sadrian rssical_radio_regs[1]); 4879300016Sadrian } else { 4880300016Sadrian BWN_RF_SETMASK(mac, B2056_RX0 | B2056_RX_RSSI_MISC, 0xE3, 4881300016Sadrian rssical_radio_regs[0]); 4882300016Sadrian BWN_RF_SETMASK(mac, B2056_RX1 | B2056_RX_RSSI_MISC, 0xE3, 4883300016Sadrian rssical_radio_regs[1]); 4884300016Sadrian } 4885300016Sadrian 4886300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_Z, rssical_phy_regs[0]); 4887300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Z, rssical_phy_regs[1]); 4888300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_Z, rssical_phy_regs[2]); 4889300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Z, rssical_phy_regs[3]); 4890300016Sadrian 4891300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_X, rssical_phy_regs[4]); 4892300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_X, rssical_phy_regs[5]); 4893300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_X, rssical_phy_regs[6]); 4894300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_X, rssical_phy_regs[7]); 4895300016Sadrian 4896300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_Y, rssical_phy_regs[8]); 4897300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Y, rssical_phy_regs[9]); 4898300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_Y, rssical_phy_regs[10]); 4899300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]); 4900300016Sadrian} 4901300016Sadrian 4902300016Sadrianstatic void bwn_nphy_tx_cal_radio_setup_rev19(struct bwn_mac *mac) 4903300016Sadrian{ 4904300016Sadrian /* TODO */ 4905300016Sadrian} 4906300016Sadrian 4907300016Sadrianstatic void bwn_nphy_tx_cal_radio_setup_rev7(struct bwn_mac *mac) 4908300016Sadrian{ 4909300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 4910300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4911300016Sadrian uint16_t *save = nphy->tx_rx_cal_radio_saveregs; 4912300016Sadrian int core, off; 4913300016Sadrian uint16_t r, tmp; 4914300016Sadrian 4915300016Sadrian for (core = 0; core < 2; core++) { 4916300016Sadrian r = core ? 0x20 : 0; 4917300016Sadrian off = core * 11; 4918300016Sadrian 4919300016Sadrian save[off + 0] = BWN_RF_READ(mac, r + R2057_TX0_TX_SSI_MASTER); 4920300016Sadrian save[off + 1] = BWN_RF_READ(mac, r + R2057_TX0_IQCAL_VCM_HG); 4921300016Sadrian save[off + 2] = BWN_RF_READ(mac, r + R2057_TX0_IQCAL_IDAC); 4922300016Sadrian save[off + 3] = BWN_RF_READ(mac, r + R2057_TX0_TSSI_VCM); 4923300016Sadrian save[off + 4] = 0; 4924300016Sadrian save[off + 5] = BWN_RF_READ(mac, r + R2057_TX0_TX_SSI_MUX); 4925300016Sadrian if (phy->rf_rev != 5) 4926300016Sadrian save[off + 6] = BWN_RF_READ(mac, r + R2057_TX0_TSSIA); 4927300016Sadrian save[off + 7] = BWN_RF_READ(mac, r + R2057_TX0_TSSIG); 4928300016Sadrian save[off + 8] = BWN_RF_READ(mac, r + R2057_TX0_TSSI_MISC1); 4929300016Sadrian 4930300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G) { 4931300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TX_SSI_MASTER, 0xA); 4932300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_IQCAL_VCM_HG, 0x43); 4933300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_IQCAL_IDAC, 0x55); 4934300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TSSI_VCM, 0); 4935300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TSSIG, 0); 4936300016Sadrian if (nphy->use_int_tx_iq_lo_cal) { 4937300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TX_SSI_MUX, 0x4); 4938300016Sadrian tmp = true ? 0x31 : 0x21; /* TODO */ 4939300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TSSIA, tmp); 4940300016Sadrian } 4941300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TSSI_MISC1, 0x00); 4942300016Sadrian } else { 4943300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TX_SSI_MASTER, 0x6); 4944300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_IQCAL_VCM_HG, 0x43); 4945300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_IQCAL_IDAC, 0x55); 4946300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TSSI_VCM, 0); 4947300016Sadrian 4948300016Sadrian if (phy->rf_rev != 5) 4949300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TSSIA, 0); 4950300016Sadrian if (nphy->use_int_tx_iq_lo_cal) { 4951300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TX_SSI_MUX, 0x6); 4952300016Sadrian tmp = true ? 0x31 : 0x21; /* TODO */ 4953300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TSSIG, tmp); 4954300016Sadrian } 4955300016Sadrian BWN_RF_WRITE(mac, r + R2057_TX0_TSSI_MISC1, 0); 4956300016Sadrian } 4957300016Sadrian } 4958300016Sadrian} 4959300016Sadrian 4960300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */ 4961300016Sadrianstatic void bwn_nphy_tx_cal_radio_setup(struct bwn_mac *mac) 4962300016Sadrian{ 4963300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 4964300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4965300016Sadrian uint16_t *save = nphy->tx_rx_cal_radio_saveregs; 4966300016Sadrian uint16_t tmp; 4967300016Sadrian uint8_t offset, i; 4968300016Sadrian 4969300016Sadrian if (phy->rev >= 19) { 4970300016Sadrian bwn_nphy_tx_cal_radio_setup_rev19(mac); 4971300016Sadrian } else if (phy->rev >= 7) { 4972300016Sadrian bwn_nphy_tx_cal_radio_setup_rev7(mac); 4973300016Sadrian } else if (phy->rev >= 3) { 4974300016Sadrian for (i = 0; i < 2; i++) { 4975300016Sadrian tmp = (i == 0) ? 0x2000 : 0x3000; 4976300016Sadrian offset = i * 11; 4977300016Sadrian 4978300016Sadrian save[offset + 0] = BWN_RF_READ(mac, B2055_CAL_RVARCTL); 4979300016Sadrian save[offset + 1] = BWN_RF_READ(mac, B2055_CAL_LPOCTL); 4980300016Sadrian save[offset + 2] = BWN_RF_READ(mac, B2055_CAL_TS); 4981300016Sadrian save[offset + 3] = BWN_RF_READ(mac, B2055_CAL_RCCALRTS); 4982300016Sadrian save[offset + 4] = BWN_RF_READ(mac, B2055_CAL_RCALRTS); 4983300016Sadrian save[offset + 5] = BWN_RF_READ(mac, B2055_PADDRV); 4984300016Sadrian save[offset + 6] = BWN_RF_READ(mac, B2055_XOCTL1); 4985300016Sadrian save[offset + 7] = BWN_RF_READ(mac, B2055_XOCTL2); 4986300016Sadrian save[offset + 8] = BWN_RF_READ(mac, B2055_XOREGUL); 4987300016Sadrian save[offset + 9] = BWN_RF_READ(mac, B2055_XOMISC); 4988300016Sadrian save[offset + 10] = BWN_RF_READ(mac, B2055_PLL_LFC1); 4989300016Sadrian 4990300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G) { 4991300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_CAL_RVARCTL, 0x0A); 4992300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_CAL_LPOCTL, 0x40); 4993300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_CAL_TS, 0x55); 4994300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_CAL_RCCALRTS, 0); 4995300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_CAL_RCALRTS, 0); 4996300016Sadrian if (nphy->ipa5g_on) { 4997300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_PADDRV, 4); 4998300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_XOCTL1, 1); 4999300016Sadrian } else { 5000300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_PADDRV, 0); 5001300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_XOCTL1, 0x2F); 5002300016Sadrian } 5003300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_XOCTL2, 0); 5004300016Sadrian } else { 5005300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_CAL_RVARCTL, 0x06); 5006300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_CAL_LPOCTL, 0x40); 5007300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_CAL_TS, 0x55); 5008300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_CAL_RCCALRTS, 0); 5009300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_CAL_RCALRTS, 0); 5010300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_XOCTL1, 0); 5011300016Sadrian if (nphy->ipa2g_on) { 5012300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_PADDRV, 6); 5013300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_XOCTL2, 5014300016Sadrian (mac->mac_phy.rev < 5) ? 0x11 : 0x01); 5015300016Sadrian } else { 5016300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_PADDRV, 0); 5017300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_XOCTL2, 0); 5018300016Sadrian } 5019300016Sadrian } 5020300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_XOREGUL, 0); 5021300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_XOMISC, 0); 5022300016Sadrian BWN_RF_WRITE(mac, tmp | B2055_PLL_LFC1, 0); 5023300016Sadrian } 5024300016Sadrian } else { 5025300016Sadrian save[0] = BWN_RF_READ(mac, B2055_C1_TX_RF_IQCAL1); 5026300016Sadrian BWN_RF_WRITE(mac, B2055_C1_TX_RF_IQCAL1, 0x29); 5027300016Sadrian 5028300016Sadrian save[1] = BWN_RF_READ(mac, B2055_C1_TX_RF_IQCAL2); 5029300016Sadrian BWN_RF_WRITE(mac, B2055_C1_TX_RF_IQCAL2, 0x54); 5030300016Sadrian 5031300016Sadrian save[2] = BWN_RF_READ(mac, B2055_C2_TX_RF_IQCAL1); 5032300016Sadrian BWN_RF_WRITE(mac, B2055_C2_TX_RF_IQCAL1, 0x29); 5033300016Sadrian 5034300016Sadrian save[3] = BWN_RF_READ(mac, B2055_C2_TX_RF_IQCAL2); 5035300016Sadrian BWN_RF_WRITE(mac, B2055_C2_TX_RF_IQCAL2, 0x54); 5036300016Sadrian 5037300016Sadrian save[3] = BWN_RF_READ(mac, B2055_C1_PWRDET_RXTX); 5038300016Sadrian save[4] = BWN_RF_READ(mac, B2055_C2_PWRDET_RXTX); 5039300016Sadrian 5040300016Sadrian if (!(BWN_PHY_READ(mac, BWN_NPHY_BANDCTL) & 5041300016Sadrian BWN_NPHY_BANDCTL_5GHZ)) { 5042300016Sadrian BWN_RF_WRITE(mac, B2055_C1_PWRDET_RXTX, 0x04); 5043300016Sadrian BWN_RF_WRITE(mac, B2055_C2_PWRDET_RXTX, 0x04); 5044300016Sadrian } else { 5045300016Sadrian BWN_RF_WRITE(mac, B2055_C1_PWRDET_RXTX, 0x20); 5046300016Sadrian BWN_RF_WRITE(mac, B2055_C2_PWRDET_RXTX, 0x20); 5047300016Sadrian } 5048300016Sadrian 5049300016Sadrian if (mac->mac_phy.rev < 2) { 5050300016Sadrian BWN_RF_SET(mac, B2055_C1_TX_BB_MXGM, 0x20); 5051300016Sadrian BWN_RF_SET(mac, B2055_C2_TX_BB_MXGM, 0x20); 5052300016Sadrian } else { 5053300016Sadrian BWN_RF_MASK(mac, B2055_C1_TX_BB_MXGM, ~0x20); 5054300016Sadrian BWN_RF_MASK(mac, B2055_C2_TX_BB_MXGM, ~0x20); 5055300016Sadrian } 5056300016Sadrian } 5057300016Sadrian} 5058300016Sadrian 5059300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */ 5060300016Sadrianstatic void bwn_nphy_update_tx_cal_ladder(struct bwn_mac *mac, uint16_t core) 5061300016Sadrian{ 5062300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5063300016Sadrian int i; 5064300016Sadrian uint16_t scale, entry; 5065300016Sadrian 5066300016Sadrian uint16_t tmp = nphy->txcal_bbmult; 5067300016Sadrian if (core == 0) 5068300016Sadrian tmp >>= 8; 5069300016Sadrian tmp &= 0xff; 5070300016Sadrian 5071300016Sadrian for (i = 0; i < 18; i++) { 5072300016Sadrian scale = (ladder_lo[i].percent * tmp) / 100; 5073300016Sadrian entry = ((scale & 0xFF) << 8) | ladder_lo[i].g_env; 5074300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(15, i), entry); 5075300016Sadrian 5076300016Sadrian scale = (ladder_iq[i].percent * tmp) / 100; 5077300016Sadrian entry = ((scale & 0xFF) << 8) | ladder_iq[i].g_env; 5078300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(15, i + 32), entry); 5079300016Sadrian } 5080300016Sadrian} 5081300016Sadrian 5082300016Sadrianstatic void bwn_nphy_pa_set_tx_dig_filter(struct bwn_mac *mac, uint16_t offset, 5083300016Sadrian const int16_t *filter) 5084300016Sadrian{ 5085300016Sadrian int i; 5086300016Sadrian 5087300016Sadrian offset = BWN_PHY_N(offset); 5088300016Sadrian 5089300016Sadrian for (i = 0; i < 15; i++, offset++) 5090300016Sadrian BWN_PHY_WRITE(mac, offset, filter[i]); 5091300016Sadrian} 5092300016Sadrian 5093300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */ 5094300016Sadrianstatic void bwn_nphy_ext_pa_set_tx_dig_filters(struct bwn_mac *mac) 5095300016Sadrian{ 5096300016Sadrian bwn_nphy_pa_set_tx_dig_filter(mac, 0x2C5, 5097300016Sadrian tbl_tx_filter_coef_rev4[2]); 5098300016Sadrian} 5099300016Sadrian 5100300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */ 5101300016Sadrianstatic void bwn_nphy_int_pa_set_tx_dig_filters(struct bwn_mac *mac) 5102300016Sadrian{ 5103300016Sadrian /* BWN_NPHY_TXF_20CO_S0A1, BWN_NPHY_TXF_40CO_S0A1, unknown */ 5104300016Sadrian static const uint16_t offset[] = { 0x186, 0x195, 0x2C5 }; 5105300016Sadrian static const int16_t dig_filter_phy_rev16[] = { 5106300016Sadrian -375, 136, -407, 208, -1527, 5107300016Sadrian 956, 93, 186, 93, 230, 5108300016Sadrian -44, 230, 201, -191, 201, 5109300016Sadrian }; 5110300016Sadrian int i; 5111300016Sadrian 5112300016Sadrian for (i = 0; i < 3; i++) 5113300016Sadrian bwn_nphy_pa_set_tx_dig_filter(mac, offset[i], 5114300016Sadrian tbl_tx_filter_coef_rev4[i]); 5115300016Sadrian 5116300016Sadrian /* Verified with BCM43227 and BCM43228 */ 5117300016Sadrian if (mac->mac_phy.rev == 16) 5118300016Sadrian bwn_nphy_pa_set_tx_dig_filter(mac, 0x186, dig_filter_phy_rev16); 5119300016Sadrian 5120300016Sadrian /* Verified with BCM43131 and BCM43217 */ 5121300016Sadrian if (mac->mac_phy.rev == 17) { 5122300016Sadrian bwn_nphy_pa_set_tx_dig_filter(mac, 0x186, dig_filter_phy_rev16); 5123300016Sadrian bwn_nphy_pa_set_tx_dig_filter(mac, 0x195, 5124300016Sadrian tbl_tx_filter_coef_rev4[1]); 5125300016Sadrian } 5126300016Sadrian 5127300016Sadrian if (bwn_is_40mhz(mac)) { 5128300016Sadrian bwn_nphy_pa_set_tx_dig_filter(mac, 0x186, 5129300016Sadrian tbl_tx_filter_coef_rev4[3]); 5130300016Sadrian } else { 5131300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G) 5132300016Sadrian bwn_nphy_pa_set_tx_dig_filter(mac, 0x186, 5133300016Sadrian tbl_tx_filter_coef_rev4[5]); 5134300016Sadrian if (bwn_get_chan(mac) == 14) 5135300016Sadrian bwn_nphy_pa_set_tx_dig_filter(mac, 0x186, 5136300016Sadrian tbl_tx_filter_coef_rev4[6]); 5137300016Sadrian } 5138300016Sadrian} 5139300016Sadrian 5140300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */ 5141300016Sadrianstatic struct bwn_nphy_txgains bwn_nphy_get_tx_gains(struct bwn_mac *mac) 5142300016Sadrian{ 5143300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5144300016Sadrian 5145300016Sadrian uint16_t curr_gain[2]; 5146300016Sadrian struct bwn_nphy_txgains target; 5147300016Sadrian const uint32_t *table = NULL; 5148300016Sadrian 5149300016Sadrian if (!nphy->txpwrctrl) { 5150300016Sadrian int i; 5151300016Sadrian 5152300016Sadrian if (nphy->hang_avoid) 5153300016Sadrian bwn_nphy_stay_in_carrier_search(mac, true); 5154300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(7, 0x110), 2, curr_gain); 5155300016Sadrian if (nphy->hang_avoid) 5156300016Sadrian bwn_nphy_stay_in_carrier_search(mac, false); 5157300016Sadrian 5158300016Sadrian for (i = 0; i < 2; ++i) { 5159300016Sadrian if (mac->mac_phy.rev >= 7) { 5160300016Sadrian target.ipa[i] = curr_gain[i] & 0x0007; 5161300016Sadrian target.pad[i] = (curr_gain[i] & 0x00F8) >> 3; 5162300016Sadrian target.pga[i] = (curr_gain[i] & 0x0F00) >> 8; 5163300016Sadrian target.txgm[i] = (curr_gain[i] & 0x7000) >> 12; 5164300016Sadrian target.tx_lpf[i] = (curr_gain[i] & 0x8000) >> 15; 5165300016Sadrian } else if (mac->mac_phy.rev >= 3) { 5166300016Sadrian target.ipa[i] = curr_gain[i] & 0x000F; 5167300016Sadrian target.pad[i] = (curr_gain[i] & 0x00F0) >> 4; 5168300016Sadrian target.pga[i] = (curr_gain[i] & 0x0F00) >> 8; 5169300016Sadrian target.txgm[i] = (curr_gain[i] & 0x7000) >> 12; 5170300016Sadrian } else { 5171300016Sadrian target.ipa[i] = curr_gain[i] & 0x0003; 5172300016Sadrian target.pad[i] = (curr_gain[i] & 0x000C) >> 2; 5173300016Sadrian target.pga[i] = (curr_gain[i] & 0x0070) >> 4; 5174300016Sadrian target.txgm[i] = (curr_gain[i] & 0x0380) >> 7; 5175300016Sadrian } 5176300016Sadrian } 5177300016Sadrian } else { 5178300016Sadrian int i; 5179300016Sadrian uint16_t index[2]; 5180300016Sadrian index[0] = (BWN_PHY_READ(mac, BWN_NPHY_C1_TXPCTL_STAT) & 5181300016Sadrian BWN_NPHY_TXPCTL_STAT_BIDX) >> 5182300016Sadrian BWN_NPHY_TXPCTL_STAT_BIDX_SHIFT; 5183300016Sadrian index[1] = (BWN_PHY_READ(mac, BWN_NPHY_C2_TXPCTL_STAT) & 5184300016Sadrian BWN_NPHY_TXPCTL_STAT_BIDX) >> 5185300016Sadrian BWN_NPHY_TXPCTL_STAT_BIDX_SHIFT; 5186300016Sadrian 5187300016Sadrian for (i = 0; i < 2; ++i) { 5188300016Sadrian table = bwn_nphy_get_tx_gain_table(mac); 5189300016Sadrian if (!table) 5190300016Sadrian break; 5191300016Sadrian 5192300016Sadrian if (mac->mac_phy.rev >= 7) { 5193300016Sadrian target.ipa[i] = (table[index[i]] >> 16) & 0x7; 5194300016Sadrian target.pad[i] = (table[index[i]] >> 19) & 0x1F; 5195300016Sadrian target.pga[i] = (table[index[i]] >> 24) & 0xF; 5196300016Sadrian target.txgm[i] = (table[index[i]] >> 28) & 0x7; 5197300016Sadrian target.tx_lpf[i] = (table[index[i]] >> 31) & 0x1; 5198300016Sadrian } else if (mac->mac_phy.rev >= 3) { 5199300016Sadrian target.ipa[i] = (table[index[i]] >> 16) & 0xF; 5200300016Sadrian target.pad[i] = (table[index[i]] >> 20) & 0xF; 5201300016Sadrian target.pga[i] = (table[index[i]] >> 24) & 0xF; 5202300016Sadrian target.txgm[i] = (table[index[i]] >> 28) & 0xF; 5203300016Sadrian } else { 5204300016Sadrian target.ipa[i] = (table[index[i]] >> 16) & 0x3; 5205300016Sadrian target.pad[i] = (table[index[i]] >> 18) & 0x3; 5206300016Sadrian target.pga[i] = (table[index[i]] >> 20) & 0x7; 5207300016Sadrian target.txgm[i] = (table[index[i]] >> 23) & 0x7; 5208300016Sadrian } 5209300016Sadrian } 5210300016Sadrian } 5211300016Sadrian 5212300016Sadrian return target; 5213300016Sadrian} 5214300016Sadrian 5215300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhyCleanup */ 5216300016Sadrianstatic void bwn_nphy_tx_cal_phy_cleanup(struct bwn_mac *mac) 5217300016Sadrian{ 5218300016Sadrian uint16_t *regs = mac->mac_phy.phy_n->tx_rx_cal_phy_saveregs; 5219300016Sadrian 5220300016Sadrian if (mac->mac_phy.rev >= 3) { 5221300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, regs[0]); 5222300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, regs[1]); 5223300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, regs[2]); 5224300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, regs[3]); 5225300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_BBCFG, regs[4]); 5226300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 3), regs[5]); 5227300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 19), regs[6]); 5228300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, regs[7]); 5229300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, regs[8]); 5230300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PAPD_EN0, regs[9]); 5231300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PAPD_EN1, regs[10]); 5232300016Sadrian bwn_nphy_reset_cca(mac); 5233300016Sadrian } else { 5234300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C1, 0x0FFF, regs[0]); 5235300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C2, 0x0FFF, regs[1]); 5236300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, regs[2]); 5237300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 2), regs[3]); 5238300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 18), regs[4]); 5239300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, regs[5]); 5240300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, regs[6]); 5241300016Sadrian } 5242300016Sadrian} 5243300016Sadrian 5244300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */ 5245300016Sadrianstatic void bwn_nphy_tx_cal_phy_setup(struct bwn_mac *mac) 5246300016Sadrian{ 5247300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 5248300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5249300016Sadrian uint16_t *regs = mac->mac_phy.phy_n->tx_rx_cal_phy_saveregs; 5250300016Sadrian uint16_t tmp; 5251300016Sadrian 5252300016Sadrian regs[0] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C1); 5253300016Sadrian regs[1] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C2); 5254300016Sadrian if (mac->mac_phy.rev >= 3) { 5255300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C1, 0xF0FF, 0x0A00); 5256300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C2, 0xF0FF, 0x0A00); 5257300016Sadrian 5258300016Sadrian tmp = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER1); 5259300016Sadrian regs[2] = tmp; 5260300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, tmp | 0x0600); 5261300016Sadrian 5262300016Sadrian tmp = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER); 5263300016Sadrian regs[3] = tmp; 5264300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, tmp | 0x0600); 5265300016Sadrian 5266300016Sadrian regs[4] = BWN_PHY_READ(mac, BWN_NPHY_BBCFG); 5267300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_BBCFG, 5268300016Sadrian ~BWN_NPHY_BBCFG_RSTRX & 0xFFFF); 5269300016Sadrian 5270300016Sadrian tmp = bwn_ntab_read(mac, BWN_NTAB16(8, 3)); 5271300016Sadrian regs[5] = tmp; 5272300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 3), 0); 5273300016Sadrian 5274300016Sadrian tmp = bwn_ntab_read(mac, BWN_NTAB16(8, 19)); 5275300016Sadrian regs[6] = tmp; 5276300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 19), 0); 5277300016Sadrian regs[7] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC1); 5278300016Sadrian regs[8] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC2); 5279300016Sadrian 5280300016Sadrian if (!nphy->use_int_tx_iq_lo_cal) 5281300016Sadrian bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_PA, 5282300016Sadrian 1, 3); 5283300016Sadrian else 5284300016Sadrian bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_PA, 5285300016Sadrian 0, 3); 5286300016Sadrian bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_TRSW, 2, 1); 5287300016Sadrian bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_TRSW, 8, 2); 5288300016Sadrian 5289300016Sadrian regs[9] = BWN_PHY_READ(mac, BWN_NPHY_PAPD_EN0); 5290300016Sadrian regs[10] = BWN_PHY_READ(mac, BWN_NPHY_PAPD_EN1); 5291300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN0, ~0x0001); 5292300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN1, ~0x0001); 5293300016Sadrian 5294300016Sadrian tmp = bwn_nphy_read_lpf_ctl(mac, 0); 5295300016Sadrian if (phy->rev >= 19) 5296300016Sadrian bwn_nphy_rf_ctl_override_rev19(mac, 0x80, tmp, 0, false, 5297300016Sadrian 1); 5298300016Sadrian else if (phy->rev >= 7) 5299300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x80, tmp, 0, false, 5300300016Sadrian 1); 5301300016Sadrian 5302300016Sadrian if (nphy->use_int_tx_iq_lo_cal && true /* FIXME */) { 5303300016Sadrian if (phy->rev >= 19) { 5304300016Sadrian bwn_nphy_rf_ctl_override_rev19(mac, 0x8, 0, 0x3, 5305300016Sadrian false, 0); 5306300016Sadrian } else if (phy->rev >= 8) { 5307300016Sadrian bwn_nphy_rf_ctl_override_rev7(mac, 0x8, 0, 0x3, 5308300016Sadrian false, 0); 5309300016Sadrian } else if (phy->rev == 7) { 5310300016Sadrian BWN_RF_SETMASK(mac, R2057_OVR_REG0, 1 << 4, 1 << 4); 5311300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 5312300016Sadrian BWN_RF_SETMASK(mac, R2057_PAD2G_TUNE_PUS_CORE0, ~1, 0); 5313300016Sadrian BWN_RF_SETMASK(mac, R2057_PAD2G_TUNE_PUS_CORE1, ~1, 0); 5314300016Sadrian } else { 5315300016Sadrian BWN_RF_SETMASK(mac, R2057_IPA5G_CASCOFFV_PU_CORE0, ~1, 0); 5316300016Sadrian BWN_RF_SETMASK(mac, R2057_IPA5G_CASCOFFV_PU_CORE1, ~1, 0); 5317300016Sadrian } 5318300016Sadrian } 5319300016Sadrian } 5320300016Sadrian } else { 5321300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C1, 0x0FFF, 0xA000); 5322300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C2, 0x0FFF, 0xA000); 5323300016Sadrian tmp = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER); 5324300016Sadrian regs[2] = tmp; 5325300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, tmp | 0x3000); 5326300016Sadrian tmp = bwn_ntab_read(mac, BWN_NTAB16(8, 2)); 5327300016Sadrian regs[3] = tmp; 5328300016Sadrian tmp |= 0x2000; 5329300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 2), tmp); 5330300016Sadrian tmp = bwn_ntab_read(mac, BWN_NTAB16(8, 18)); 5331300016Sadrian regs[4] = tmp; 5332300016Sadrian tmp |= 0x2000; 5333300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(8, 18), tmp); 5334300016Sadrian regs[5] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC1); 5335300016Sadrian regs[6] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC2); 5336300016Sadrian if (bwn_current_band(mac) == BWN_BAND_5G) 5337300016Sadrian tmp = 0x0180; 5338300016Sadrian else 5339300016Sadrian tmp = 0x0120; 5340300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, tmp); 5341300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, tmp); 5342300016Sadrian } 5343300016Sadrian} 5344300016Sadrian 5345300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */ 5346300016Sadrianstatic void bwn_nphy_save_cal(struct bwn_mac *mac) 5347300016Sadrian{ 5348300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 5349300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5350300016Sadrian 5351300016Sadrian struct bwn_phy_n_iq_comp *rxcal_coeffs = NULL; 5352300016Sadrian uint16_t *txcal_radio_regs = NULL; 5353300016Sadrian struct bwn_chanspec *iqcal_chanspec; 5354300016Sadrian uint16_t *table = NULL; 5355300016Sadrian 5356300016Sadrian if (nphy->hang_avoid) 5357300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 1); 5358300016Sadrian 5359300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 5360300016Sadrian rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G; 5361300016Sadrian txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G; 5362300016Sadrian iqcal_chanspec = &nphy->iqcal_chanspec_2G; 5363300016Sadrian table = nphy->cal_cache.txcal_coeffs_2G; 5364300016Sadrian } else { 5365300016Sadrian rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G; 5366300016Sadrian txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G; 5367300016Sadrian iqcal_chanspec = &nphy->iqcal_chanspec_5G; 5368300016Sadrian table = nphy->cal_cache.txcal_coeffs_5G; 5369300016Sadrian } 5370300016Sadrian 5371300016Sadrian bwn_nphy_rx_iq_coeffs(mac, false, rxcal_coeffs); 5372300016Sadrian /* TODO use some definitions */ 5373300016Sadrian if (phy->rev >= 19) { 5374300016Sadrian /* TODO */ 5375300016Sadrian } else if (phy->rev >= 7) { 5376300016Sadrian txcal_radio_regs[0] = BWN_RF_READ(mac, 5377300016Sadrian R2057_TX0_LOFT_FINE_I); 5378300016Sadrian txcal_radio_regs[1] = BWN_RF_READ(mac, 5379300016Sadrian R2057_TX0_LOFT_FINE_Q); 5380300016Sadrian txcal_radio_regs[4] = BWN_RF_READ(mac, 5381300016Sadrian R2057_TX0_LOFT_COARSE_I); 5382300016Sadrian txcal_radio_regs[5] = BWN_RF_READ(mac, 5383300016Sadrian R2057_TX0_LOFT_COARSE_Q); 5384300016Sadrian txcal_radio_regs[2] = BWN_RF_READ(mac, 5385300016Sadrian R2057_TX1_LOFT_FINE_I); 5386300016Sadrian txcal_radio_regs[3] = BWN_RF_READ(mac, 5387300016Sadrian R2057_TX1_LOFT_FINE_Q); 5388300016Sadrian txcal_radio_regs[6] = BWN_RF_READ(mac, 5389300016Sadrian R2057_TX1_LOFT_COARSE_I); 5390300016Sadrian txcal_radio_regs[7] = BWN_RF_READ(mac, 5391300016Sadrian R2057_TX1_LOFT_COARSE_Q); 5392300016Sadrian } else if (phy->rev >= 3) { 5393300016Sadrian txcal_radio_regs[0] = BWN_RF_READ(mac, 0x2021); 5394300016Sadrian txcal_radio_regs[1] = BWN_RF_READ(mac, 0x2022); 5395300016Sadrian txcal_radio_regs[2] = BWN_RF_READ(mac, 0x3021); 5396300016Sadrian txcal_radio_regs[3] = BWN_RF_READ(mac, 0x3022); 5397300016Sadrian txcal_radio_regs[4] = BWN_RF_READ(mac, 0x2023); 5398300016Sadrian txcal_radio_regs[5] = BWN_RF_READ(mac, 0x2024); 5399300016Sadrian txcal_radio_regs[6] = BWN_RF_READ(mac, 0x3023); 5400300016Sadrian txcal_radio_regs[7] = BWN_RF_READ(mac, 0x3024); 5401300016Sadrian } else { 5402300016Sadrian txcal_radio_regs[0] = BWN_RF_READ(mac, 0x8B); 5403300016Sadrian txcal_radio_regs[1] = BWN_RF_READ(mac, 0xBA); 5404300016Sadrian txcal_radio_regs[2] = BWN_RF_READ(mac, 0x8D); 5405300016Sadrian txcal_radio_regs[3] = BWN_RF_READ(mac, 0xBC); 5406300016Sadrian } 5407300016Sadrian iqcal_chanspec->center_freq = bwn_get_centre_freq(mac); 5408300016Sadrian iqcal_chanspec->channel_type = bwn_get_chan_type(mac, NULL); 5409300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 80), 8, table); 5410300016Sadrian 5411300016Sadrian if (nphy->hang_avoid) 5412300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 0); 5413300016Sadrian} 5414300016Sadrian 5415300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */ 5416300016Sadrianstatic void bwn_nphy_restore_cal(struct bwn_mac *mac) 5417300016Sadrian{ 5418300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 5419300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5420300016Sadrian 5421300016Sadrian uint16_t coef[4]; 5422300016Sadrian uint16_t *loft = NULL; 5423300016Sadrian uint16_t *table = NULL; 5424300016Sadrian 5425300016Sadrian int i; 5426300016Sadrian uint16_t *txcal_radio_regs = NULL; 5427300016Sadrian struct bwn_phy_n_iq_comp *rxcal_coeffs = NULL; 5428300016Sadrian 5429300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 5430300016Sadrian if (!nphy->iqcal_chanspec_2G.center_freq) 5431300016Sadrian return; 5432300016Sadrian table = nphy->cal_cache.txcal_coeffs_2G; 5433300016Sadrian loft = &nphy->cal_cache.txcal_coeffs_2G[5]; 5434300016Sadrian } else { 5435300016Sadrian if (!nphy->iqcal_chanspec_5G.center_freq) 5436300016Sadrian return; 5437300016Sadrian table = nphy->cal_cache.txcal_coeffs_5G; 5438300016Sadrian loft = &nphy->cal_cache.txcal_coeffs_5G[5]; 5439300016Sadrian } 5440300016Sadrian 5441300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 80), 4, table); 5442300016Sadrian 5443300016Sadrian for (i = 0; i < 4; i++) { 5444300016Sadrian if (mac->mac_phy.rev >= 3) 5445300016Sadrian table[i] = coef[i]; 5446300016Sadrian else 5447300016Sadrian coef[i] = 0; 5448300016Sadrian } 5449300016Sadrian 5450300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 88), 4, coef); 5451300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 85), 2, loft); 5452300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 93), 2, loft); 5453300016Sadrian 5454300016Sadrian if (mac->mac_phy.rev < 2) 5455300016Sadrian bwn_nphy_tx_iq_workaround(mac); 5456300016Sadrian 5457300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 5458300016Sadrian txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G; 5459300016Sadrian rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G; 5460300016Sadrian } else { 5461300016Sadrian txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G; 5462300016Sadrian rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G; 5463300016Sadrian } 5464300016Sadrian 5465300016Sadrian /* TODO use some definitions */ 5466300016Sadrian if (phy->rev >= 19) { 5467300016Sadrian /* TODO */ 5468300016Sadrian } else if (phy->rev >= 7) { 5469300016Sadrian BWN_RF_WRITE(mac, R2057_TX0_LOFT_FINE_I, 5470300016Sadrian txcal_radio_regs[0]); 5471300016Sadrian BWN_RF_WRITE(mac, R2057_TX0_LOFT_FINE_Q, 5472300016Sadrian txcal_radio_regs[1]); 5473300016Sadrian BWN_RF_WRITE(mac, R2057_TX0_LOFT_COARSE_I, 5474300016Sadrian txcal_radio_regs[4]); 5475300016Sadrian BWN_RF_WRITE(mac, R2057_TX0_LOFT_COARSE_Q, 5476300016Sadrian txcal_radio_regs[5]); 5477300016Sadrian BWN_RF_WRITE(mac, R2057_TX1_LOFT_FINE_I, 5478300016Sadrian txcal_radio_regs[2]); 5479300016Sadrian BWN_RF_WRITE(mac, R2057_TX1_LOFT_FINE_Q, 5480300016Sadrian txcal_radio_regs[3]); 5481300016Sadrian BWN_RF_WRITE(mac, R2057_TX1_LOFT_COARSE_I, 5482300016Sadrian txcal_radio_regs[6]); 5483300016Sadrian BWN_RF_WRITE(mac, R2057_TX1_LOFT_COARSE_Q, 5484300016Sadrian txcal_radio_regs[7]); 5485300016Sadrian } else if (phy->rev >= 3) { 5486300016Sadrian BWN_RF_WRITE(mac, 0x2021, txcal_radio_regs[0]); 5487300016Sadrian BWN_RF_WRITE(mac, 0x2022, txcal_radio_regs[1]); 5488300016Sadrian BWN_RF_WRITE(mac, 0x3021, txcal_radio_regs[2]); 5489300016Sadrian BWN_RF_WRITE(mac, 0x3022, txcal_radio_regs[3]); 5490300016Sadrian BWN_RF_WRITE(mac, 0x2023, txcal_radio_regs[4]); 5491300016Sadrian BWN_RF_WRITE(mac, 0x2024, txcal_radio_regs[5]); 5492300016Sadrian BWN_RF_WRITE(mac, 0x3023, txcal_radio_regs[6]); 5493300016Sadrian BWN_RF_WRITE(mac, 0x3024, txcal_radio_regs[7]); 5494300016Sadrian } else { 5495300016Sadrian BWN_RF_WRITE(mac, 0x8B, txcal_radio_regs[0]); 5496300016Sadrian BWN_RF_WRITE(mac, 0xBA, txcal_radio_regs[1]); 5497300016Sadrian BWN_RF_WRITE(mac, 0x8D, txcal_radio_regs[2]); 5498300016Sadrian BWN_RF_WRITE(mac, 0xBC, txcal_radio_regs[3]); 5499300016Sadrian } 5500300016Sadrian bwn_nphy_rx_iq_coeffs(mac, true, rxcal_coeffs); 5501300016Sadrian} 5502300016Sadrian 5503300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalTxIqlo */ 5504300016Sadrianstatic int bwn_nphy_cal_tx_iq_lo(struct bwn_mac *mac, 5505300016Sadrian struct bwn_nphy_txgains target, 5506300016Sadrian bool full, bool mphase) 5507300016Sadrian{ 5508300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 5509300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5510300016Sadrian int i; 5511300016Sadrian int error = 0; 5512300016Sadrian int freq; 5513300016Sadrian bool avoid = false; 5514300016Sadrian uint8_t length; 5515300016Sadrian uint16_t tmp, core, type, count, max, numb, last = 0, cmd; 5516300016Sadrian const uint16_t *table; 5517300016Sadrian bool phy6or5x; 5518300016Sadrian 5519300016Sadrian uint16_t buffer[11]; 5520300016Sadrian uint16_t diq_start = 0; 5521300016Sadrian uint16_t save[2]; 5522300016Sadrian uint16_t gain[2]; 5523300016Sadrian struct bwn_nphy_iqcal_params params[2]; 5524300016Sadrian bool updated[2] = { }; 5525300016Sadrian 5526300016Sadrian bwn_nphy_stay_in_carrier_search(mac, true); 5527300016Sadrian 5528300016Sadrian if (mac->mac_phy.rev >= 4) { 5529300016Sadrian avoid = nphy->hang_avoid; 5530300016Sadrian nphy->hang_avoid = false; 5531300016Sadrian } 5532300016Sadrian 5533300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(7, 0x110), 2, save); 5534300016Sadrian 5535300016Sadrian for (i = 0; i < 2; i++) { 5536300016Sadrian bwn_nphy_iq_cal_gain_params(mac, i, target, ¶ms[i]); 5537300016Sadrian gain[i] = params[i].cal_gain; 5538300016Sadrian } 5539300016Sadrian 5540300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x110), 2, gain); 5541300016Sadrian 5542300016Sadrian bwn_nphy_tx_cal_radio_setup(mac); 5543300016Sadrian bwn_nphy_tx_cal_phy_setup(mac); 5544300016Sadrian 5545300016Sadrian phy6or5x = mac->mac_phy.rev >= 6 || 5546300016Sadrian (mac->mac_phy.rev == 5 && nphy->ipa2g_on && 5547300016Sadrian bwn_current_band(mac) == BWN_BAND_2G); 5548300016Sadrian if (phy6or5x) { 5549300016Sadrian if (bwn_is_40mhz(mac)) { 5550300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 0), 18, 5551300016Sadrian tbl_tx_iqlo_cal_loft_ladder_40); 5552300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 32), 18, 5553300016Sadrian tbl_tx_iqlo_cal_iqimb_ladder_40); 5554300016Sadrian } else { 5555300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 0), 18, 5556300016Sadrian tbl_tx_iqlo_cal_loft_ladder_20); 5557300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 32), 18, 5558300016Sadrian tbl_tx_iqlo_cal_iqimb_ladder_20); 5559300016Sadrian } 5560300016Sadrian } 5561300016Sadrian 5562300016Sadrian if (phy->rev >= 19) { 5563300016Sadrian /* TODO */ 5564300016Sadrian } else if (phy->rev >= 7) { 5565300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0x8AD9); 5566300016Sadrian } else { 5567300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0x8AA9); 5568300016Sadrian } 5569300016Sadrian 5570300016Sadrian if (!bwn_is_40mhz(mac)) 5571300016Sadrian freq = 2500; 5572300016Sadrian else 5573300016Sadrian freq = 5000; 5574300016Sadrian 5575300016Sadrian if (nphy->mphase_cal_phase_id > 2) 5576300016Sadrian bwn_nphy_run_samples(mac, (bwn_is_40mhz(mac) ? 40 : 20) * 8, 5577300016Sadrian 0xFFFF, 0, true, false, false); 5578300016Sadrian else 5579300016Sadrian error = bwn_nphy_tx_tone(mac, freq, 250, true, false, false); 5580300016Sadrian 5581300016Sadrian if (error == 0) { 5582300016Sadrian if (nphy->mphase_cal_phase_id > 2) { 5583300016Sadrian table = nphy->mphase_txcal_bestcoeffs; 5584300016Sadrian length = 11; 5585300016Sadrian if (mac->mac_phy.rev < 3) 5586300016Sadrian length -= 2; 5587300016Sadrian } else { 5588300016Sadrian if (!full && nphy->txiqlocal_coeffsvalid) { 5589300016Sadrian table = nphy->txiqlocal_bestc; 5590300016Sadrian length = 11; 5591300016Sadrian if (mac->mac_phy.rev < 3) 5592300016Sadrian length -= 2; 5593300016Sadrian } else { 5594300016Sadrian full = true; 5595300016Sadrian if (mac->mac_phy.rev >= 3) { 5596300016Sadrian table = tbl_tx_iqlo_cal_startcoefs_nphyrev3; 5597300016Sadrian length = BWN_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3; 5598300016Sadrian } else { 5599300016Sadrian table = tbl_tx_iqlo_cal_startcoefs; 5600300016Sadrian length = BWN_NTAB_TX_IQLO_CAL_STARTCOEFS; 5601300016Sadrian } 5602300016Sadrian } 5603300016Sadrian } 5604300016Sadrian 5605300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 64), length, table); 5606300016Sadrian 5607300016Sadrian if (full) { 5608300016Sadrian if (mac->mac_phy.rev >= 3) 5609300016Sadrian max = BWN_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3; 5610300016Sadrian else 5611300016Sadrian max = BWN_NTAB_TX_IQLO_CAL_CMDS_FULLCAL; 5612300016Sadrian } else { 5613300016Sadrian if (mac->mac_phy.rev >= 3) 5614300016Sadrian max = BWN_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3; 5615300016Sadrian else 5616300016Sadrian max = BWN_NTAB_TX_IQLO_CAL_CMDS_RECAL; 5617300016Sadrian } 5618300016Sadrian 5619300016Sadrian if (mphase) { 5620300016Sadrian count = nphy->mphase_txcal_cmdidx; 5621300016Sadrian numb = min(max, 5622300016Sadrian (uint16_t)(count + nphy->mphase_txcal_numcmds)); 5623300016Sadrian } else { 5624300016Sadrian count = 0; 5625300016Sadrian numb = max; 5626300016Sadrian } 5627300016Sadrian 5628300016Sadrian for (; count < numb; count++) { 5629300016Sadrian if (full) { 5630300016Sadrian if (mac->mac_phy.rev >= 3) 5631300016Sadrian cmd = tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[count]; 5632300016Sadrian else 5633300016Sadrian cmd = tbl_tx_iqlo_cal_cmds_fullcal[count]; 5634300016Sadrian } else { 5635300016Sadrian if (mac->mac_phy.rev >= 3) 5636300016Sadrian cmd = tbl_tx_iqlo_cal_cmds_recal_nphyrev3[count]; 5637300016Sadrian else 5638300016Sadrian cmd = tbl_tx_iqlo_cal_cmds_recal[count]; 5639300016Sadrian } 5640300016Sadrian 5641300016Sadrian core = (cmd & 0x3000) >> 12; 5642300016Sadrian type = (cmd & 0x0F00) >> 8; 5643300016Sadrian 5644300016Sadrian if (phy6or5x && updated[core] == 0) { 5645300016Sadrian bwn_nphy_update_tx_cal_ladder(mac, core); 5646300016Sadrian updated[core] = true; 5647300016Sadrian } 5648300016Sadrian 5649300016Sadrian tmp = (params[core].ncorr[type] << 8) | 0x66; 5650300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_IQLOCAL_CMDNNUM, tmp); 5651300016Sadrian 5652300016Sadrian if (type == 1 || type == 3 || type == 4) { 5653300016Sadrian buffer[0] = bwn_ntab_read(mac, 5654300016Sadrian BWN_NTAB16(15, 69 + core)); 5655300016Sadrian diq_start = buffer[0]; 5656300016Sadrian buffer[0] = 0; 5657300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(15, 69 + core), 5658300016Sadrian 0); 5659300016Sadrian } 5660300016Sadrian 5661300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_IQLOCAL_CMD, cmd); 5662300016Sadrian for (i = 0; i < 2000; i++) { 5663300016Sadrian tmp = BWN_PHY_READ(mac, BWN_NPHY_IQLOCAL_CMD); 5664300016Sadrian if (tmp & 0xC000) 5665300016Sadrian break; 5666300016Sadrian DELAY(10); 5667300016Sadrian } 5668300016Sadrian 5669300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 96), length, 5670300016Sadrian buffer); 5671300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 64), length, 5672300016Sadrian buffer); 5673300016Sadrian 5674300016Sadrian if (type == 1 || type == 3 || type == 4) 5675300016Sadrian buffer[0] = diq_start; 5676300016Sadrian } 5677300016Sadrian 5678300016Sadrian if (mphase) 5679300016Sadrian nphy->mphase_txcal_cmdidx = (numb >= max) ? 0 : numb; 5680300016Sadrian 5681300016Sadrian last = (mac->mac_phy.rev < 3) ? 6 : 7; 5682300016Sadrian 5683300016Sadrian if (!mphase || nphy->mphase_cal_phase_id == last) { 5684300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 96), 4, buffer); 5685300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 80), 4, buffer); 5686300016Sadrian if (mac->mac_phy.rev < 3) { 5687300016Sadrian buffer[0] = 0; 5688300016Sadrian buffer[1] = 0; 5689300016Sadrian buffer[2] = 0; 5690300016Sadrian buffer[3] = 0; 5691300016Sadrian } 5692300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 88), 4, 5693300016Sadrian buffer); 5694300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 101), 2, 5695300016Sadrian buffer); 5696300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 85), 2, 5697300016Sadrian buffer); 5698300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 93), 2, 5699300016Sadrian buffer); 5700300016Sadrian length = 11; 5701300016Sadrian if (mac->mac_phy.rev < 3) 5702300016Sadrian length -= 2; 5703300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 96), length, 5704300016Sadrian nphy->txiqlocal_bestc); 5705300016Sadrian nphy->txiqlocal_coeffsvalid = true; 5706300016Sadrian nphy->txiqlocal_chanspec.center_freq = 5707300016Sadrian bwn_get_centre_freq(mac); 5708300016Sadrian nphy->txiqlocal_chanspec.channel_type = bwn_get_chan_type(mac, NULL); 5709300016Sadrian } else { 5710300016Sadrian length = 11; 5711300016Sadrian if (mac->mac_phy.rev < 3) 5712300016Sadrian length -= 2; 5713300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 96), length, 5714300016Sadrian nphy->mphase_txcal_bestcoeffs); 5715300016Sadrian } 5716300016Sadrian 5717300016Sadrian bwn_nphy_stop_playback(mac); 5718300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0); 5719300016Sadrian } 5720300016Sadrian 5721300016Sadrian bwn_nphy_tx_cal_phy_cleanup(mac); 5722300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x110), 2, save); 5723300016Sadrian 5724300016Sadrian if (mac->mac_phy.rev < 2 && (!mphase || nphy->mphase_cal_phase_id == last)) 5725300016Sadrian bwn_nphy_tx_iq_workaround(mac); 5726300016Sadrian 5727300016Sadrian if (mac->mac_phy.rev >= 4) 5728300016Sadrian nphy->hang_avoid = avoid; 5729300016Sadrian 5730300016Sadrian bwn_nphy_stay_in_carrier_search(mac, false); 5731300016Sadrian 5732300016Sadrian return error; 5733300016Sadrian} 5734300016Sadrian 5735300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ReapplyTxCalCoeffs */ 5736300016Sadrianstatic void bwn_nphy_reapply_tx_cal_coeffs(struct bwn_mac *mac) 5737300016Sadrian{ 5738300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5739300016Sadrian uint8_t i; 5740300016Sadrian uint16_t buffer[7]; 5741300016Sadrian bool equal = true; 5742300016Sadrian 5743300016Sadrian if (!nphy->txiqlocal_coeffsvalid || 5744300016Sadrian nphy->txiqlocal_chanspec.center_freq != bwn_get_centre_freq(mac) || 5745300016Sadrian nphy->txiqlocal_chanspec.channel_type != bwn_get_chan_type(mac, NULL)) 5746300016Sadrian return; 5747300016Sadrian 5748300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 80), 7, buffer); 5749300016Sadrian for (i = 0; i < 4; i++) { 5750300016Sadrian if (buffer[i] != nphy->txiqlocal_bestc[i]) { 5751300016Sadrian equal = false; 5752300016Sadrian break; 5753300016Sadrian } 5754300016Sadrian } 5755300016Sadrian 5756300016Sadrian if (!equal) { 5757300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 80), 4, 5758300016Sadrian nphy->txiqlocal_bestc); 5759300016Sadrian for (i = 0; i < 4; i++) 5760300016Sadrian buffer[i] = 0; 5761300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 88), 4, 5762300016Sadrian buffer); 5763300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 85), 2, 5764300016Sadrian &nphy->txiqlocal_bestc[5]); 5765300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 93), 2, 5766300016Sadrian &nphy->txiqlocal_bestc[5]); 5767300016Sadrian } 5768300016Sadrian} 5769300016Sadrian 5770300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIqRev2 */ 5771300016Sadrianstatic int bwn_nphy_rev2_cal_rx_iq(struct bwn_mac *mac, 5772300016Sadrian struct bwn_nphy_txgains target, uint8_t type, bool debug) 5773300016Sadrian{ 5774300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5775300016Sadrian int i, j, index; 5776300016Sadrian uint8_t rfctl[2]; 5777300016Sadrian uint8_t afectl_core; 5778300016Sadrian uint16_t tmp[6]; 5779300016Sadrian uint16_t cur_hpf1, cur_hpf2, cur_lna; 5780300016Sadrian uint32_t real, imag; 5781300016Sadrian bwn_band_t band; 5782300016Sadrian 5783300016Sadrian uint8_t use; 5784300016Sadrian uint16_t cur_hpf; 5785300016Sadrian uint16_t lna[3] = { 3, 3, 1 }; 5786300016Sadrian uint16_t hpf1[3] = { 7, 2, 0 }; 5787300016Sadrian uint16_t hpf2[3] = { 2, 0, 0 }; 5788300016Sadrian uint32_t power[3] = { }; 5789300016Sadrian uint16_t gain_save[2]; 5790300016Sadrian uint16_t cal_gain[2]; 5791300016Sadrian struct bwn_nphy_iqcal_params cal_params[2]; 5792300016Sadrian struct bwn_nphy_iq_est est; 5793300016Sadrian int ret = 0; 5794300016Sadrian bool playtone = true; 5795300016Sadrian int desired = 13; 5796300016Sadrian 5797300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 1); 5798300016Sadrian 5799300016Sadrian if (mac->mac_phy.rev < 2) 5800300016Sadrian bwn_nphy_reapply_tx_cal_coeffs(mac); 5801300016Sadrian bwn_ntab_read_bulk(mac, BWN_NTAB16(7, 0x110), 2, gain_save); 5802300016Sadrian for (i = 0; i < 2; i++) { 5803300016Sadrian bwn_nphy_iq_cal_gain_params(mac, i, target, &cal_params[i]); 5804300016Sadrian cal_gain[i] = cal_params[i].cal_gain; 5805300016Sadrian } 5806300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x110), 2, cal_gain); 5807300016Sadrian 5808300016Sadrian for (i = 0; i < 2; i++) { 5809300016Sadrian if (i == 0) { 5810300016Sadrian rfctl[0] = BWN_NPHY_RFCTL_INTC1; 5811300016Sadrian rfctl[1] = BWN_NPHY_RFCTL_INTC2; 5812300016Sadrian afectl_core = BWN_NPHY_AFECTL_C1; 5813300016Sadrian } else { 5814300016Sadrian rfctl[0] = BWN_NPHY_RFCTL_INTC2; 5815300016Sadrian rfctl[1] = BWN_NPHY_RFCTL_INTC1; 5816300016Sadrian afectl_core = BWN_NPHY_AFECTL_C2; 5817300016Sadrian } 5818300016Sadrian 5819300016Sadrian tmp[1] = BWN_PHY_READ(mac, BWN_NPHY_RFSEQCA); 5820300016Sadrian tmp[2] = BWN_PHY_READ(mac, afectl_core); 5821300016Sadrian tmp[3] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER); 5822300016Sadrian tmp[4] = BWN_PHY_READ(mac, rfctl[0]); 5823300016Sadrian tmp[5] = BWN_PHY_READ(mac, rfctl[1]); 5824300016Sadrian 5825300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, 5826300016Sadrian ~BWN_NPHY_RFSEQCA_RXDIS & 0xFFFF, 5827300016Sadrian ((1 - i) << BWN_NPHY_RFSEQCA_RXDIS_SHIFT)); 5828300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, ~BWN_NPHY_RFSEQCA_TXEN, 5829300016Sadrian (1 - i)); 5830300016Sadrian BWN_PHY_SET(mac, afectl_core, 0x0006); 5831300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x0006); 5832300016Sadrian 5833300016Sadrian band = bwn_current_band(mac); 5834300016Sadrian 5835300016Sadrian if (nphy->rxcalparams & 0xFF000000) { 5836300016Sadrian if (band == BWN_BAND_5G) 5837300016Sadrian BWN_PHY_WRITE(mac, rfctl[0], 0x140); 5838300016Sadrian else 5839300016Sadrian BWN_PHY_WRITE(mac, rfctl[0], 0x110); 5840300016Sadrian } else { 5841300016Sadrian if (band == BWN_BAND_5G) 5842300016Sadrian BWN_PHY_WRITE(mac, rfctl[0], 0x180); 5843300016Sadrian else 5844300016Sadrian BWN_PHY_WRITE(mac, rfctl[0], 0x120); 5845300016Sadrian } 5846300016Sadrian 5847300016Sadrian if (band == BWN_BAND_5G) 5848300016Sadrian BWN_PHY_WRITE(mac, rfctl[1], 0x148); 5849300016Sadrian else 5850300016Sadrian BWN_PHY_WRITE(mac, rfctl[1], 0x114); 5851300016Sadrian 5852300016Sadrian if (nphy->rxcalparams & 0x10000) { 5853300016Sadrian BWN_RF_SETMASK(mac, B2055_C1_GENSPARE2, 0xFC, 5854300016Sadrian (i + 1)); 5855300016Sadrian BWN_RF_SETMASK(mac, B2055_C2_GENSPARE2, 0xFC, 5856300016Sadrian (2 - i)); 5857300016Sadrian } 5858300016Sadrian 5859300016Sadrian for (j = 0; j < 4; j++) { 5860300016Sadrian if (j < 3) { 5861300016Sadrian cur_lna = lna[j]; 5862300016Sadrian cur_hpf1 = hpf1[j]; 5863300016Sadrian cur_hpf2 = hpf2[j]; 5864300016Sadrian } else { 5865300016Sadrian if (power[1] > 10000) { 5866300016Sadrian use = 1; 5867300016Sadrian cur_hpf = cur_hpf1; 5868300016Sadrian index = 2; 5869300016Sadrian } else { 5870300016Sadrian if (power[0] > 10000) { 5871300016Sadrian use = 1; 5872300016Sadrian cur_hpf = cur_hpf1; 5873300016Sadrian index = 1; 5874300016Sadrian } else { 5875300016Sadrian index = 0; 5876300016Sadrian use = 2; 5877300016Sadrian cur_hpf = cur_hpf2; 5878300016Sadrian } 5879300016Sadrian } 5880300016Sadrian cur_lna = lna[index]; 5881300016Sadrian cur_hpf1 = hpf1[index]; 5882300016Sadrian cur_hpf2 = hpf2[index]; 5883300016Sadrian cur_hpf += desired - bwn_hweight32(power[index]); 5884300016Sadrian cur_hpf = bwn_clamp_val(cur_hpf, 0, 10); 5885300016Sadrian if (use == 1) 5886300016Sadrian cur_hpf1 = cur_hpf; 5887300016Sadrian else 5888300016Sadrian cur_hpf2 = cur_hpf; 5889300016Sadrian } 5890300016Sadrian 5891300016Sadrian tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) | 5892300016Sadrian (cur_lna << 2)); 5893300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x400, tmp[0], 3, 5894300016Sadrian false); 5895300016Sadrian bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX); 5896300016Sadrian bwn_nphy_stop_playback(mac); 5897300016Sadrian 5898300016Sadrian if (playtone) { 5899300016Sadrian ret = bwn_nphy_tx_tone(mac, 4000, 5900300016Sadrian (nphy->rxcalparams & 0xFFFF), 5901300016Sadrian false, false, true); 5902300016Sadrian playtone = false; 5903300016Sadrian } else { 5904300016Sadrian bwn_nphy_run_samples(mac, 160, 0xFFFF, 0, false, 5905300016Sadrian false, true); 5906300016Sadrian } 5907300016Sadrian 5908300016Sadrian if (ret == 0) { 5909300016Sadrian if (j < 3) { 5910300016Sadrian bwn_nphy_rx_iq_est(mac, &est, 1024, 32, 5911300016Sadrian false); 5912300016Sadrian if (i == 0) { 5913300016Sadrian real = est.i0_pwr; 5914300016Sadrian imag = est.q0_pwr; 5915300016Sadrian } else { 5916300016Sadrian real = est.i1_pwr; 5917300016Sadrian imag = est.q1_pwr; 5918300016Sadrian } 5919300016Sadrian power[i] = ((real + imag) / 1024) + 1; 5920300016Sadrian } else { 5921300016Sadrian bwn_nphy_calc_rx_iq_comp(mac, 1 << i); 5922300016Sadrian } 5923300016Sadrian bwn_nphy_stop_playback(mac); 5924300016Sadrian } 5925300016Sadrian 5926300016Sadrian if (ret != 0) 5927300016Sadrian break; 5928300016Sadrian } 5929300016Sadrian 5930300016Sadrian BWN_RF_MASK(mac, B2055_C1_GENSPARE2, 0xFC); 5931300016Sadrian BWN_RF_MASK(mac, B2055_C2_GENSPARE2, 0xFC); 5932300016Sadrian BWN_PHY_WRITE(mac, rfctl[1], tmp[5]); 5933300016Sadrian BWN_PHY_WRITE(mac, rfctl[0], tmp[4]); 5934300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, tmp[3]); 5935300016Sadrian BWN_PHY_WRITE(mac, afectl_core, tmp[2]); 5936300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFSEQCA, tmp[1]); 5937300016Sadrian 5938300016Sadrian if (ret != 0) 5939300016Sadrian break; 5940300016Sadrian } 5941300016Sadrian 5942300016Sadrian bwn_nphy_rf_ctl_override(mac, 0x400, 0, 3, true); 5943300016Sadrian bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX); 5944300016Sadrian bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x110), 2, gain_save); 5945300016Sadrian 5946300016Sadrian bwn_nphy_stay_in_carrier_search(mac, 0); 5947300016Sadrian 5948300016Sadrian return ret; 5949300016Sadrian} 5950300016Sadrian 5951300016Sadrianstatic int bwn_nphy_rev3_cal_rx_iq(struct bwn_mac *mac, 5952300016Sadrian struct bwn_nphy_txgains target, uint8_t type, bool debug) 5953300016Sadrian{ 5954300016Sadrian return -1; 5955300016Sadrian} 5956300016Sadrian 5957300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIq */ 5958300016Sadrianstatic int bwn_nphy_cal_rx_iq(struct bwn_mac *mac, 5959300016Sadrian struct bwn_nphy_txgains target, uint8_t type, bool debug) 5960300016Sadrian{ 5961300016Sadrian if (mac->mac_phy.rev >= 7) 5962300016Sadrian type = 0; 5963300016Sadrian 5964300016Sadrian if (mac->mac_phy.rev >= 3) 5965300016Sadrian return bwn_nphy_rev3_cal_rx_iq(mac, target, type, debug); 5966300016Sadrian else 5967300016Sadrian return bwn_nphy_rev2_cal_rx_iq(mac, target, type, debug); 5968300016Sadrian} 5969300016Sadrian 5970300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */ 5971300016Sadrianstatic void bwn_nphy_set_rx_core_state(struct bwn_mac *mac, uint8_t mask) 5972300016Sadrian{ 5973300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 5974300016Sadrian struct bwn_phy_n *nphy = phy->phy_n; 5975300016Sadrian /* uint16_t buf[16]; it's rev3+ */ 5976300016Sadrian 5977300016Sadrian nphy->phyrxchain = mask; 5978300016Sadrian 5979300016Sadrian if (0 /* FIXME clk */) 5980300016Sadrian return; 5981300016Sadrian 5982300016Sadrian bwn_mac_suspend(mac); 5983300016Sadrian 5984300016Sadrian if (nphy->hang_avoid) 5985300016Sadrian bwn_nphy_stay_in_carrier_search(mac, true); 5986300016Sadrian 5987300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, ~BWN_NPHY_RFSEQCA_RXEN, 5988300016Sadrian (mask & 0x3) << BWN_NPHY_RFSEQCA_RXEN_SHIFT); 5989300016Sadrian 5990300016Sadrian if ((mask & 0x3) != 0x3) { 5991300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_HPANT_SWTHRES, 1); 5992300016Sadrian if (mac->mac_phy.rev >= 3) { 5993300016Sadrian /* TODO */ 5994300016Sadrian } 5995300016Sadrian } else { 5996300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_HPANT_SWTHRES, 0x1E); 5997300016Sadrian if (mac->mac_phy.rev >= 3) { 5998300016Sadrian /* TODO */ 5999300016Sadrian } 6000300016Sadrian } 6001300016Sadrian 6002300016Sadrian bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX); 6003300016Sadrian 6004300016Sadrian if (nphy->hang_avoid) 6005300016Sadrian bwn_nphy_stay_in_carrier_search(mac, false); 6006300016Sadrian 6007300016Sadrian bwn_mac_enable(mac); 6008300016Sadrian} 6009300016Sadrian 6010300016Sadrianbwn_txpwr_result_t 6011300016Sadrianbwn_nphy_op_recalc_txpower(struct bwn_mac *mac, bool ignore_tssi) 6012300016Sadrian{ 6013300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 6014300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 6015300016Sadrian struct ieee80211_channel *channel = bwn_get_channel(mac); 6016300016Sadrian struct bwn_softc *sc = mac->mac_sc; 6017300016Sadrian struct bwn_ppr *ppr = &nphy->tx_pwr_max_ppr; 6018300016Sadrian uint8_t max; /* qdBm */ 6019300016Sadrian bool tx_pwr_state; 6020300016Sadrian 6021300016Sadrian if (nphy->tx_pwr_last_recalc_freq == bwn_get_centre_freq(mac) && 6022300016Sadrian nphy->tx_pwr_last_recalc_limit == phy->txpower) 6023300016Sadrian return BWN_TXPWR_RES_DONE; 6024300016Sadrian 6025300016Sadrian /* Make sure we have a clean PPR */ 6026300016Sadrian bwn_ppr_clear(mac, ppr); 6027300016Sadrian 6028300016Sadrian /* HW limitations */ 6029300016Sadrian bwn_ppr_load_max_from_sprom(mac, ppr, BWN_PHY_BAND_2G); 6030300016Sadrian /* XXX TODO: other bands? */ 6031300016Sadrian 6032300016Sadrian /* Regulatory & user settings */ 6033300016Sadrian max = INT_TO_Q52(bwn_get_chan_power(mac, channel)); 6034300016Sadrian /* uint8_t */ 6035300016Sadrian if (phy->txpower) 6036300016Sadrian max = min(max, INT_TO_Q52(phy->txpower)); 6037300016Sadrian bwn_ppr_apply_max(mac, ppr, max); 6038300016Sadrian DPRINTF(mac->mac_sc, BWN_DEBUG_XMIT_POWER, 6039300016Sadrian "Calculated TX power: " Q52_FMT "\n", 6040300016Sadrian Q52_ARG(bwn_ppr_get_max(mac, ppr))); 6041300016Sadrian 6042300016Sadrian /* TODO: Enable this once we get gains working */ 6043300016Sadrian#if 0 6044300016Sadrian /* Some extra gains */ 6045300016Sadrian hw_gain = 6; /* N-PHY specific */ 6046300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 6047300016Sadrian hw_gain += sprom->antenna_gain.a0; 6048300016Sadrian else 6049300016Sadrian hw_gain += sprom->antenna_gain.a1; 6050300016Sadrian bwn_ppr_add(mac, ppr, -hw_gain); 6051300016Sadrian#endif 6052300016Sadrian 6053300016Sadrian /* Make sure we didn't go too low */ 6054300016Sadrian bwn_ppr_apply_min(mac, ppr, INT_TO_Q52(8)); 6055300016Sadrian 6056300016Sadrian /* Apply */ 6057300016Sadrian tx_pwr_state = nphy->txpwrctrl; 6058300016Sadrian bwn_mac_suspend(mac); 6059300016Sadrian bwn_nphy_tx_power_ctl_setup(mac); 6060300016Sadrian if (siba_get_revid(sc->sc_dev) == 11 || siba_get_revid(sc->sc_dev) == 12) { 6061300016Sadrian BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~0, BWN_MACCTL_PHY_LOCK); 6062300016Sadrian BWN_READ_4(mac, BWN_MACCTL); 6063300016Sadrian DELAY(1); 6064300016Sadrian } 6065300016Sadrian bwn_nphy_tx_power_ctrl(mac, nphy->txpwrctrl); 6066300016Sadrian if (siba_get_revid(sc->sc_dev) == 11 || siba_get_revid(sc->sc_dev) == 12) 6067300016Sadrian BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~BWN_MACCTL_PHY_LOCK, 0); 6068300016Sadrian bwn_mac_enable(mac); 6069300016Sadrian 6070300016Sadrian nphy->tx_pwr_last_recalc_freq = bwn_get_centre_freq(mac); 6071300016Sadrian nphy->tx_pwr_last_recalc_limit = phy->txpower; 6072300016Sadrian 6073300016Sadrian return BWN_TXPWR_RES_DONE; 6074300016Sadrian} 6075300016Sadrian 6076300016Sadrian/************************************************** 6077300016Sadrian * N-PHY init 6078300016Sadrian **************************************************/ 6079300016Sadrian 6080300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */ 6081300016Sadrianstatic void bwn_nphy_update_mimo_config(struct bwn_mac *mac, int32_t preamble) 6082300016Sadrian{ 6083300016Sadrian uint16_t mimocfg = BWN_PHY_READ(mac, BWN_NPHY_MIMOCFG); 6084300016Sadrian 6085300016Sadrian mimocfg |= BWN_NPHY_MIMOCFG_AUTO; 6086300016Sadrian if (preamble == 1) 6087300016Sadrian mimocfg |= BWN_NPHY_MIMOCFG_GFMIX; 6088300016Sadrian else 6089300016Sadrian mimocfg &= ~BWN_NPHY_MIMOCFG_GFMIX; 6090300016Sadrian 6091300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_MIMOCFG, mimocfg); 6092300016Sadrian} 6093300016Sadrian 6094300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BPHYInit */ 6095300016Sadrianstatic void bwn_nphy_bphy_init(struct bwn_mac *mac) 6096300016Sadrian{ 6097300016Sadrian unsigned int i; 6098300016Sadrian uint16_t val; 6099300016Sadrian 6100300016Sadrian val = 0x1E1F; 6101300016Sadrian for (i = 0; i < 16; i++) { 6102300016Sadrian BWN_PHY_WRITE(mac, BWN_PHY_N_BMODE(0x88 + i), val); 6103300016Sadrian val -= 0x202; 6104300016Sadrian } 6105300016Sadrian val = 0x3E3F; 6106300016Sadrian for (i = 0; i < 16; i++) { 6107300016Sadrian BWN_PHY_WRITE(mac, BWN_PHY_N_BMODE(0x98 + i), val); 6108300016Sadrian val -= 0x202; 6109300016Sadrian } 6110300016Sadrian BWN_PHY_WRITE(mac, BWN_PHY_N_BMODE(0x38), 0x668); 6111300016Sadrian} 6112300016Sadrian 6113300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */ 6114300016Sadrianstatic void bwn_nphy_superswitch_init(struct bwn_mac *mac, bool init) 6115300016Sadrian{ 6116300016Sadrian struct bwn_softc *sc = mac->mac_sc; 6117300016Sadrian 6118300016Sadrian if (mac->mac_phy.rev >= 7) 6119300016Sadrian return; 6120300016Sadrian 6121300016Sadrian if (mac->mac_phy.rev >= 3) { 6122300016Sadrian if (!init) 6123300016Sadrian return; 6124300016Sadrian if (0 /* FIXME */) { 6125300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(9, 2), 0x211); 6126300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(9, 3), 0x222); 6127300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(9, 8), 0x144); 6128300016Sadrian bwn_ntab_write(mac, BWN_NTAB16(9, 12), 0x188); 6129300016Sadrian } 6130300016Sadrian } else { 6131300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_GPIO_LOOEN, 0); 6132300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_GPIO_HIOEN, 0); 6133300016Sadrian 6134300016Sadrian /* XXX handle bhnd bus */ 6135300016Sadrian if (bwn_is_bus_siba(mac)) { 6136300016Sadrian siba_gpio_set(sc->sc_dev, 0xfc00); 6137300016Sadrian } 6138300016Sadrian 6139300016Sadrian BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~BWN_MACCTL_GPOUT_MASK, 0); 6140300016Sadrian BWN_WRITE_SETMASK2(mac, BWN_GPIO_MASK, ~0, 0xFC00); 6141300016Sadrian BWN_WRITE_SETMASK2(mac, BWN_GPIO_CONTROL, (~0xFC00 & 0xFFFF), 6142300016Sadrian 0); 6143300016Sadrian 6144300016Sadrian if (init) { 6145300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); 6146300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP1, 0x301); 6147300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); 6148300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); 6149300016Sadrian } 6150300016Sadrian } 6151300016Sadrian} 6152300016Sadrian 6153300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N */ 6154300016Sadrianstatic int bwn_phy_initn(struct bwn_mac *mac) 6155300016Sadrian{ 6156300016Sadrian struct bwn_softc *sc = mac->mac_sc; 6157300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 6158300016Sadrian struct bwn_phy_n *nphy = phy->phy_n; 6159300016Sadrian uint8_t tx_pwr_state; 6160300016Sadrian struct bwn_nphy_txgains target; 6161300016Sadrian uint16_t tmp; 6162300016Sadrian bwn_band_t tmp2; 6163300016Sadrian bool do_rssi_cal; 6164300016Sadrian 6165300016Sadrian uint16_t clip[2]; 6166300016Sadrian bool do_cal = false; 6167300016Sadrian 6168300016Sadrian if ((mac->mac_phy.rev >= 3) && 6169300016Sadrian (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) && 6170300016Sadrian (bwn_current_band(mac) == BWN_BAND_2G)) { 6171300016Sadrian /* XXX bhnd bus */ 6172300016Sadrian if (bwn_is_bus_siba(mac)) { 6173300016Sadrian siba_cc_set32(sc->sc_dev, SIBA_CC_CHIPCTL, 0x40); 6174300016Sadrian } 6175300016Sadrian } 6176300016Sadrian nphy->use_int_tx_iq_lo_cal = bwn_nphy_ipa(mac) || 6177300016Sadrian phy->rev >= 7 || 6178300016Sadrian (phy->rev >= 5 && 6179300016Sadrian siba_sprom_get_bf2_hi(sc->sc_dev) & BWN_BFH2_INTERNDET_TXIQCAL); 6180300016Sadrian nphy->deaf_count = 0; 6181300016Sadrian bwn_nphy_tables_init(mac); 6182300016Sadrian nphy->crsminpwr_adjusted = false; 6183300016Sadrian nphy->noisevars_adjusted = false; 6184300016Sadrian 6185300016Sadrian /* Clear all overrides */ 6186300016Sadrian if (mac->mac_phy.rev >= 3) { 6187300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B1S1, 0); 6188300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_OVER, 0); 6189300016Sadrian if (phy->rev >= 7) { 6190300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER3, 0); 6191300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER4, 0); 6192300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER5, 0); 6193300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER6, 0); 6194300016Sadrian } 6195300016Sadrian if (phy->rev >= 19) { 6196300016Sadrian /* TODO */ 6197300016Sadrian } 6198300016Sadrian 6199300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B1S0, 0); 6200300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B32S1, 0); 6201300016Sadrian } else { 6202300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_OVER, 0); 6203300016Sadrian } 6204300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, 0); 6205300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, 0); 6206300016Sadrian if (mac->mac_phy.rev < 6) { 6207300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC3, 0); 6208300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC4, 0); 6209300016Sadrian } 6210300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFSEQMODE, 6211300016Sadrian ~(BWN_NPHY_RFSEQMODE_CAOVER | 6212300016Sadrian BWN_NPHY_RFSEQMODE_TROVER)); 6213300016Sadrian if (mac->mac_phy.rev >= 3) 6214300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, 0); 6215300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, 0); 6216300016Sadrian 6217300016Sadrian if (mac->mac_phy.rev <= 2) { 6218300016Sadrian tmp = (mac->mac_phy.rev == 2) ? 0x3B : 0x40; 6219300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_BPHY_CTL3, 6220300016Sadrian ~BWN_NPHY_BPHY_CTL3_SCALE, 6221300016Sadrian tmp << BWN_NPHY_BPHY_CTL3_SCALE_SHIFT); 6222300016Sadrian } 6223300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20); 6224300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20); 6225300016Sadrian 6226300016Sadrian if (siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_SKWRKFEM_BRD || 6227300016Sadrian (siba_get_pci_subvendor(sc->sc_dev) == PCI_VENDOR_APPLE && 6228300016Sadrian siba_get_pci_subdevice(sc->sc_dev) == BCMA_BOARD_TYPE_BCM943224M93)) 6229300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXREALFD, 0xA0); 6230300016Sadrian else 6231300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXREALFD, 0xB8); 6232300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_MIMO_CRSTXEXT, 0xC8); 6233300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PLOAD_CSENSE_EXTLEN, 0x50); 6234300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXRIFS_FRDEL, 0x30); 6235300016Sadrian 6236300016Sadrian if (phy->rev < 8) 6237300016Sadrian bwn_nphy_update_mimo_config(mac, nphy->preamble_override); 6238300016Sadrian 6239300016Sadrian bwn_nphy_update_txrx_chain(mac); 6240300016Sadrian 6241300016Sadrian if (phy->rev < 2) { 6242300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_DUP40_GFBL, 0xAA8); 6243300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_DUP40_BL, 0x9A4); 6244300016Sadrian } 6245300016Sadrian 6246300016Sadrian tmp2 = bwn_current_band(mac); 6247300016Sadrian if (bwn_nphy_ipa(mac)) { 6248300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_PAPD_EN0, 0x1); 6249300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_EPS_TABLE_ADJ0, 0x007F, 6250300016Sadrian nphy->papd_epsilon_offset[0] << 7); 6251300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_PAPD_EN1, 0x1); 6252300016Sadrian BWN_PHY_SETMASK(mac, BWN_NPHY_EPS_TABLE_ADJ1, 0x007F, 6253300016Sadrian nphy->papd_epsilon_offset[1] << 7); 6254300016Sadrian bwn_nphy_int_pa_set_tx_dig_filters(mac); 6255300016Sadrian } else if (phy->rev >= 5) { 6256300016Sadrian bwn_nphy_ext_pa_set_tx_dig_filters(mac); 6257300016Sadrian } 6258300016Sadrian 6259300016Sadrian bwn_nphy_workarounds(mac); 6260300016Sadrian 6261300016Sadrian /* Reset CCA, in init code it differs a little from standard way */ 6262300016Sadrian bwn_phy_force_clock(mac, 1); 6263300016Sadrian tmp = BWN_PHY_READ(mac, BWN_NPHY_BBCFG); 6264300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_BBCFG, tmp | BWN_NPHY_BBCFG_RSTCCA); 6265300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_BBCFG, tmp & ~BWN_NPHY_BBCFG_RSTCCA); 6266300016Sadrian bwn_phy_force_clock(mac, 0); 6267300016Sadrian 6268300016Sadrian bwn_mac_phy_clock_set(mac, true); 6269300016Sadrian 6270300016Sadrian if (phy->rev < 7) { 6271300016Sadrian bwn_nphy_pa_override(mac, false); 6272300016Sadrian bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RX2TX); 6273300016Sadrian bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX); 6274300016Sadrian bwn_nphy_pa_override(mac, true); 6275300016Sadrian } 6276300016Sadrian 6277300016Sadrian bwn_nphy_classifier(mac, 0, 0); 6278300016Sadrian bwn_nphy_read_clip_detection(mac, clip); 6279300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 6280300016Sadrian bwn_nphy_bphy_init(mac); 6281300016Sadrian 6282300016Sadrian tx_pwr_state = nphy->txpwrctrl; 6283300016Sadrian bwn_nphy_tx_power_ctrl(mac, false); 6284300016Sadrian bwn_nphy_tx_power_fix(mac); 6285300016Sadrian bwn_nphy_tx_power_ctl_idle_tssi(mac); 6286300016Sadrian bwn_nphy_tx_power_ctl_setup(mac); 6287300016Sadrian bwn_nphy_tx_gain_table_upload(mac); 6288300016Sadrian 6289300016Sadrian if (nphy->phyrxchain != 3) 6290300016Sadrian bwn_nphy_set_rx_core_state(mac, nphy->phyrxchain); 6291300016Sadrian if (nphy->mphase_cal_phase_id > 0) 6292300016Sadrian ;/* TODO PHY Periodic Calibration Multi-Phase Restart */ 6293300016Sadrian 6294300016Sadrian do_rssi_cal = false; 6295300016Sadrian if (phy->rev >= 3) { 6296300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 6297300016Sadrian do_rssi_cal = !nphy->rssical_chanspec_2G.center_freq; 6298300016Sadrian else 6299300016Sadrian do_rssi_cal = !nphy->rssical_chanspec_5G.center_freq; 6300300016Sadrian 6301300016Sadrian if (do_rssi_cal) 6302300016Sadrian bwn_nphy_rssi_cal(mac); 6303300016Sadrian else 6304300016Sadrian bwn_nphy_restore_rssi_cal(mac); 6305300016Sadrian } else { 6306300016Sadrian bwn_nphy_rssi_cal(mac); 6307300016Sadrian } 6308300016Sadrian 6309300016Sadrian if (!((nphy->measure_hold & 0x6) != 0)) { 6310300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 6311300016Sadrian do_cal = !nphy->iqcal_chanspec_2G.center_freq; 6312300016Sadrian else 6313300016Sadrian do_cal = !nphy->iqcal_chanspec_5G.center_freq; 6314300016Sadrian 6315300016Sadrian if (nphy->mute) 6316300016Sadrian do_cal = false; 6317300016Sadrian 6318300016Sadrian if (do_cal) { 6319300016Sadrian target = bwn_nphy_get_tx_gains(mac); 6320300016Sadrian 6321300016Sadrian if (nphy->antsel_type == 2) 6322300016Sadrian bwn_nphy_superswitch_init(mac, true); 6323300016Sadrian if (nphy->perical != 2) { 6324300016Sadrian bwn_nphy_rssi_cal(mac); 6325300016Sadrian if (phy->rev >= 3) { 6326300016Sadrian nphy->cal_orig_pwr_idx[0] = 6327300016Sadrian nphy->txpwrindex[0].index_internal; 6328300016Sadrian nphy->cal_orig_pwr_idx[1] = 6329300016Sadrian nphy->txpwrindex[1].index_internal; 6330300016Sadrian /* TODO N PHY Pre Calibrate TX Gain */ 6331300016Sadrian target = bwn_nphy_get_tx_gains(mac); 6332300016Sadrian } 6333300016Sadrian if (!bwn_nphy_cal_tx_iq_lo(mac, target, true, false)) 6334300016Sadrian if (bwn_nphy_cal_rx_iq(mac, target, 2, 0) == 0) 6335300016Sadrian bwn_nphy_save_cal(mac); 6336300016Sadrian } else if (nphy->mphase_cal_phase_id == 0) 6337300016Sadrian ;/* N PHY Periodic Calibration with arg 3 */ 6338300016Sadrian } else { 6339300016Sadrian bwn_nphy_restore_cal(mac); 6340300016Sadrian } 6341300016Sadrian } 6342300016Sadrian 6343300016Sadrian bwn_nphy_tx_pwr_ctrl_coef_setup(mac); 6344300016Sadrian bwn_nphy_tx_power_ctrl(mac, tx_pwr_state); 6345300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXMACIF_HOLDOFF, 0x0015); 6346300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_TXMACDELAY, 0x0320); 6347300016Sadrian if (phy->rev >= 3 && phy->rev <= 6) 6348300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_PLOAD_CSENSE_EXTLEN, 0x0032); 6349300016Sadrian bwn_nphy_tx_lpf_bw(mac); 6350300016Sadrian if (phy->rev >= 3) 6351300016Sadrian bwn_nphy_spur_workaround(mac); 6352300016Sadrian 6353300016Sadrian return 0; 6354300016Sadrian} 6355300016Sadrian 6356300016Sadrian/************************************************** 6357300016Sadrian * Channel switching ops. 6358300016Sadrian **************************************************/ 6359300016Sadrian 6360300016Sadrianstatic void bwn_chantab_phy_upload(struct bwn_mac *mac, 6361300016Sadrian const struct bwn_phy_n_sfo_cfg *e) 6362300016Sadrian{ 6363300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_BW1A, e->phy_bw1a); 6364300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_BW2, e->phy_bw2); 6365300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_BW3, e->phy_bw3); 6366300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_BW4, e->phy_bw4); 6367300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_BW5, e->phy_bw5); 6368300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_BW6, e->phy_bw6); 6369300016Sadrian} 6370300016Sadrian 6371300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PmuSpurAvoid */ 6372300016Sadrianstatic void bwn_nphy_pmu_spur_avoid(struct bwn_mac *mac, bool avoid) 6373300016Sadrian{ 6374300016Sadrian struct bwn_softc *sc = mac->mac_sc; 6375300016Sadrian 6376300016Sadrian /* XXX bhnd */ 6377300016Sadrian if (bwn_is_bus_siba(mac)) { 6378300016Sadrian siba_pmu_spuravoid_pllupdate(sc->sc_dev, avoid); 6379300016Sadrian } 6380300016Sadrian} 6381300016Sadrian 6382300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */ 6383300016Sadrianstatic void bwn_nphy_channel_setup(struct bwn_mac *mac, 6384300016Sadrian const struct bwn_phy_n_sfo_cfg *e, 6385300016Sadrian struct ieee80211_channel *new_channel) 6386300016Sadrian{ 6387300016Sadrian struct bwn_softc *sc = mac->mac_sc; 6388300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 6389300016Sadrian struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 6390300016Sadrian int ch = new_channel->ic_ieee; 6391300016Sadrian uint16_t tmp16; 6392300016Sadrian 6393300016Sadrian if (bwn_channel_band(mac, new_channel) == BWN_BAND_5G) { 6394300016Sadrian DPRINTF(sc, BWN_DEBUG_RESET, "%s: BAND_2G\n", __func__); 6395300016Sadrian /* Switch to 2 GHz for a moment to access BWN_PHY_B_BBCFG */ 6396300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_BANDCTL, ~BWN_NPHY_BANDCTL_5GHZ); 6397300016Sadrian 6398300016Sadrian tmp16 = BWN_READ_2(mac, BWN_PSM_PHY_HDR); 6399300016Sadrian BWN_WRITE_2(mac, BWN_PSM_PHY_HDR, tmp16 | 4); 6400300016Sadrian /* Put BPHY in the reset */ 6401300016Sadrian BWN_PHY_SET(mac, BWN_PHY_B_BBCFG, 6402300016Sadrian BWN_PHY_B_BBCFG_RSTCCA | BWN_PHY_B_BBCFG_RSTRX); 6403300016Sadrian BWN_WRITE_2(mac, BWN_PSM_PHY_HDR, tmp16); 6404300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_BANDCTL, BWN_NPHY_BANDCTL_5GHZ); 6405300016Sadrian } else if (bwn_channel_band(mac, new_channel) == BWN_BAND_2G) { 6406300016Sadrian DPRINTF(sc, BWN_DEBUG_RESET, "%s: BAND_2G\n", __func__); 6407300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_BANDCTL, ~BWN_NPHY_BANDCTL_5GHZ); 6408300016Sadrian tmp16 = BWN_READ_2(mac, BWN_PSM_PHY_HDR); 6409300016Sadrian BWN_WRITE_2(mac, BWN_PSM_PHY_HDR, tmp16 | 4); 6410300016Sadrian /* Take BPHY out of the reset */ 6411300016Sadrian BWN_PHY_MASK(mac, BWN_PHY_B_BBCFG, 6412300016Sadrian (uint16_t)~(BWN_PHY_B_BBCFG_RSTCCA | BWN_PHY_B_BBCFG_RSTRX)); 6413300016Sadrian BWN_WRITE_2(mac, BWN_PSM_PHY_HDR, tmp16); 6414300016Sadrian } else { 6415300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "%s: unknown band?\n", __func__); 6416300016Sadrian } 6417300016Sadrian 6418300016Sadrian bwn_chantab_phy_upload(mac, e); 6419300016Sadrian 6420300016Sadrian if (new_channel->ic_ieee == 14) { 6421300016Sadrian bwn_nphy_classifier(mac, 2, 0); 6422300016Sadrian BWN_PHY_SET(mac, BWN_PHY_B_TEST, 0x0800); 6423300016Sadrian } else { 6424300016Sadrian bwn_nphy_classifier(mac, 2, 2); 6425300016Sadrian if (bwn_channel_band(mac, new_channel) == BWN_BAND_2G) 6426300016Sadrian BWN_PHY_MASK(mac, BWN_PHY_B_TEST, ~0x840); 6427300016Sadrian } 6428300016Sadrian 6429300016Sadrian if (!nphy->txpwrctrl) 6430300016Sadrian bwn_nphy_tx_power_fix(mac); 6431300016Sadrian 6432300016Sadrian if (mac->mac_phy.rev < 3) 6433300016Sadrian bwn_nphy_adjust_lna_gain_table(mac); 6434300016Sadrian 6435300016Sadrian bwn_nphy_tx_lpf_bw(mac); 6436300016Sadrian 6437300016Sadrian if (mac->mac_phy.rev >= 3 && 6438300016Sadrian mac->mac_phy.phy_n->spur_avoid != BWN_SPUR_AVOID_DISABLE) { 6439300016Sadrian uint8_t spuravoid = 0; 6440300016Sadrian 6441300016Sadrian if (mac->mac_phy.phy_n->spur_avoid == BWN_SPUR_AVOID_FORCE) { 6442300016Sadrian spuravoid = 1; 6443300016Sadrian } else if (phy->rev >= 19) { 6444300016Sadrian /* TODO */ 6445300016Sadrian } else if (phy->rev >= 18) { 6446300016Sadrian /* TODO */ 6447300016Sadrian } else if (phy->rev >= 17) { 6448300016Sadrian /* TODO: Off for channels 1-11, but check 12-14! */ 6449300016Sadrian } else if (phy->rev >= 16) { 6450300016Sadrian /* TODO: Off for 2 GHz, but check 5 GHz! */ 6451300016Sadrian } else if (phy->rev >= 7) { 6452300016Sadrian if (!bwn_is_40mhz(mac)) { /* 20MHz */ 6453300016Sadrian if (ch == 13 || ch == 14 || ch == 153) 6454300016Sadrian spuravoid = 1; 6455300016Sadrian } else { /* 40 MHz */ 6456300016Sadrian if (ch == 54) 6457300016Sadrian spuravoid = 1; 6458300016Sadrian } 6459300016Sadrian } else { 6460300016Sadrian if (!bwn_is_40mhz(mac)) { /* 20MHz */ 6461300016Sadrian if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14) 6462300016Sadrian spuravoid = 1; 6463300016Sadrian } else { /* 40MHz */ 6464300016Sadrian if (nphy->aband_spurwar_en && 6465300016Sadrian (ch == 38 || ch == 102 || ch == 118)) 6466300016Sadrian spuravoid = siba_get_chipid(sc->sc_dev) == 0x4716; 6467300016Sadrian } 6468300016Sadrian } 6469300016Sadrian 6470300016Sadrian bwn_nphy_pmu_spur_avoid(mac, spuravoid); 6471300016Sadrian 6472300016Sadrian bwn_mac_switch_freq(mac, spuravoid); 6473300016Sadrian 6474300016Sadrian if (mac->mac_phy.rev == 3 || mac->mac_phy.rev == 4) 6475300016Sadrian bwn_wireless_core_phy_pll_reset(mac); 6476300016Sadrian 6477300016Sadrian if (spuravoid) 6478300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_BBCFG, BWN_NPHY_BBCFG_RSTRX); 6479300016Sadrian else 6480300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_BBCFG, 6481300016Sadrian ~BWN_NPHY_BBCFG_RSTRX & 0xFFFF); 6482300016Sadrian 6483300016Sadrian bwn_nphy_reset_cca(mac); 6484300016Sadrian 6485300016Sadrian /* wl sets useless phy_isspuravoid here */ 6486300016Sadrian } 6487300016Sadrian 6488300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_NDATAT_DUP40, 0x3830); 6489300016Sadrian 6490300016Sadrian if (phy->rev >= 3) 6491300016Sadrian bwn_nphy_spur_workaround(mac); 6492300016Sadrian} 6493300016Sadrian 6494300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */ 6495300016Sadrianstatic int bwn_nphy_set_channel(struct bwn_mac *mac, 6496300016Sadrian struct ieee80211_channel *channel, 6497300016Sadrian bwn_chan_type_t channel_type) 6498300016Sadrian{ 6499300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 6500300016Sadrian 6501300016Sadrian const struct bwn_nphy_channeltab_entry_rev2 *tabent_r2 = NULL; 6502300016Sadrian const struct bwn_nphy_channeltab_entry_rev3 *tabent_r3 = NULL; 6503300016Sadrian const struct bwn_nphy_chantabent_rev7 *tabent_r7 = NULL; 6504300016Sadrian const struct bwn_nphy_chantabent_rev7_2g *tabent_r7_2g = NULL; 6505300016Sadrian 6506300016Sadrian uint8_t tmp; 6507300016Sadrian 6508300016Sadrian if (phy->rev >= 19) { 6509300016Sadrian return -ESRCH; 6510300016Sadrian /* TODO */ 6511300016Sadrian } else if (phy->rev >= 7) { 6512300016Sadrian r2057_get_chantabent_rev7(mac, bwn_get_chan_centre_freq(mac, channel), 6513300016Sadrian &tabent_r7, &tabent_r7_2g); 6514300016Sadrian if (!tabent_r7 && !tabent_r7_2g) 6515300016Sadrian return -ESRCH; 6516300016Sadrian } else if (phy->rev >= 3) { 6517300016Sadrian tabent_r3 = bwn_nphy_get_chantabent_rev3(mac, 6518300016Sadrian bwn_get_chan_centre_freq(mac, channel)); 6519300016Sadrian if (!tabent_r3) 6520300016Sadrian return -ESRCH; 6521300016Sadrian } else { 6522300016Sadrian tabent_r2 = bwn_nphy_get_chantabent_rev2(mac, 6523300016Sadrian channel->ic_ieee); 6524300016Sadrian if (!tabent_r2) 6525300016Sadrian return -ESRCH; 6526300016Sadrian } 6527300016Sadrian 6528300016Sadrian /* Channel is set later in common code, but we need to set it on our 6529300016Sadrian own to let this function's subcalls work properly. */ 6530300016Sadrian#if 0 6531300016Sadrian phy->channel = channel->ic_ieee; 6532300016Sadrian#endif 6533300016Sadrian 6534300016Sadrian#if 0 6535300016Sadrian if (bwn_channel_type_is_40mhz(phy->channel_type) != 6536300016Sadrian bwn_channel_type_is_40mhz(channel_type)) 6537300016Sadrian ; /* TODO: BMAC BW Set (channel_type) */ 6538300016Sadrian#endif 6539300016Sadrian 6540300016Sadrian if (channel_type == BWN_CHAN_TYPE_40_HT_U) { 6541300016Sadrian BWN_PHY_SET(mac, BWN_NPHY_RXCTL, BWN_NPHY_RXCTL_BSELU20); 6542300016Sadrian if (phy->rev >= 7) 6543300016Sadrian BWN_PHY_SET(mac, 0x310, 0x8000); 6544300016Sadrian } else if (channel_type == BWN_CHAN_TYPE_40_HT_D) { 6545300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RXCTL, ~BWN_NPHY_RXCTL_BSELU20); 6546300016Sadrian if (phy->rev >= 7) 6547300016Sadrian BWN_PHY_MASK(mac, 0x310, (uint16_t)~0x8000); 6548300016Sadrian } 6549300016Sadrian 6550300016Sadrian if (phy->rev >= 19) { 6551300016Sadrian /* TODO */ 6552300016Sadrian } else if (phy->rev >= 7) { 6553300016Sadrian const struct bwn_phy_n_sfo_cfg *phy_regs = tabent_r7 ? 6554300016Sadrian &(tabent_r7->phy_regs) : &(tabent_r7_2g->phy_regs); 6555300016Sadrian 6556300016Sadrian if (phy->rf_rev <= 4 || phy->rf_rev == 6) { 6557300016Sadrian tmp = (bwn_channel_band(mac, channel) == BWN_BAND_5G) ? 2 : 0; 6558300016Sadrian BWN_RF_SETMASK(mac, R2057_TIA_CONFIG_CORE0, ~2, tmp); 6559300016Sadrian BWN_RF_SETMASK(mac, R2057_TIA_CONFIG_CORE1, ~2, tmp); 6560300016Sadrian } 6561300016Sadrian 6562300016Sadrian bwn_radio_2057_setup(mac, tabent_r7, tabent_r7_2g); 6563300016Sadrian bwn_nphy_channel_setup(mac, phy_regs, channel); 6564300016Sadrian } else if (phy->rev >= 3) { 6565300016Sadrian tmp = (bwn_channel_band(mac, channel) == BWN_BAND_5G) ? 4 : 0; 6566300016Sadrian BWN_RF_SETMASK(mac, 0x08, 0xFFFB, tmp); 6567300016Sadrian bwn_radio_2056_setup(mac, tabent_r3); 6568300016Sadrian bwn_nphy_channel_setup(mac, &(tabent_r3->phy_regs), channel); 6569300016Sadrian } else { 6570300016Sadrian tmp = (bwn_channel_band(mac, channel) == BWN_BAND_5G) ? 0x0020 : 0x0050; 6571300016Sadrian BWN_RF_SETMASK(mac, B2055_MASTER1, 0xFF8F, tmp); 6572300016Sadrian bwn_radio_2055_setup(mac, tabent_r2); 6573300016Sadrian bwn_nphy_channel_setup(mac, &(tabent_r2->phy_regs), channel); 6574300016Sadrian } 6575300016Sadrian 6576300016Sadrian return 0; 6577300016Sadrian} 6578300016Sadrian 6579300016Sadrian/************************************************** 6580300016Sadrian * Basic PHY ops. 6581300016Sadrian **************************************************/ 6582300016Sadrian 6583300016Sadrianint 6584300016Sadrianbwn_nphy_op_allocate(struct bwn_mac *mac) 6585300016Sadrian{ 6586300016Sadrian struct bwn_phy_n *nphy; 6587300016Sadrian 6588300016Sadrian nphy = malloc(sizeof(*nphy), M_DEVBUF, M_ZERO | M_NOWAIT); 6589300016Sadrian if (!nphy) 6590300016Sadrian return -ENOMEM; 6591300016Sadrian 6592300016Sadrian mac->mac_phy.phy_n = nphy; 6593300016Sadrian 6594300016Sadrian return 0; 6595300016Sadrian} 6596300016Sadrian 6597300016Sadrianvoid 6598300016Sadrianbwn_nphy_op_prepare_structs(struct bwn_mac *mac) 6599300016Sadrian{ 6600300016Sadrian struct bwn_softc *sc = mac->mac_sc; 6601300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 6602300016Sadrian struct bwn_phy_n *nphy = phy->phy_n; 6603300016Sadrian 6604300016Sadrian memset(nphy, 0, sizeof(*nphy)); 6605300016Sadrian 6606300016Sadrian nphy->hang_avoid = (phy->rev == 3 || phy->rev == 4); 6607300016Sadrian nphy->spur_avoid = (phy->rev >= 3) ? 6608300016Sadrian BWN_SPUR_AVOID_AUTO : BWN_SPUR_AVOID_DISABLE; 6609300016Sadrian nphy->gain_boost = true; /* this way we follow wl, assume it is true */ 6610300016Sadrian nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */ 6611300016Sadrian nphy->phyrxchain = 3; /* to avoid bwn_nphy_set_rx_core_state like wl */ 6612300016Sadrian nphy->perical = 2; /* avoid additional rssi cal on init (like wl) */ 6613300016Sadrian /* 128 can mean disabled-by-default state of TX pwr ctl. Max value is 6614300016Sadrian * 0x7f == 127 and we check for 128 when restoring TX pwr ctl. */ 6615300016Sadrian nphy->tx_pwr_idx[0] = 128; 6616300016Sadrian nphy->tx_pwr_idx[1] = 128; 6617300016Sadrian 6618300016Sadrian /* Hardware TX power control and 5GHz power gain */ 6619300016Sadrian nphy->txpwrctrl = false; 6620300016Sadrian nphy->pwg_gain_5ghz = false; 6621300016Sadrian if (mac->mac_phy.rev >= 3 || 6622300016Sadrian (siba_get_pci_subvendor(sc->sc_dev) == PCI_VENDOR_APPLE && 6623300016Sadrian (siba_get_revid(sc->sc_dev) == 11 || siba_get_revid(sc->sc_dev) == 12))) { 6624300016Sadrian nphy->txpwrctrl = true; 6625300016Sadrian nphy->pwg_gain_5ghz = true; 6626300016Sadrian } else if (siba_sprom_get_rev(sc->sc_dev) >= 4) { 6627300016Sadrian if (mac->mac_phy.rev >= 2 && 6628300016Sadrian (siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_TXPWRCTRL_EN)) { 6629300016Sadrian nphy->txpwrctrl = true; 6630300016Sadrian#ifdef CONFIG_BWN_SSB 6631300016Sadrian if (dev->dev->bus_type == BWN_BUS_SSB && 6632300016Sadrian dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI) { 6633300016Sadrian struct pci_dev *pdev = 6634300016Sadrian dev->dev->sdev->bus->host_pci; 6635300016Sadrian if (pdev->device == 0x4328 || 6636300016Sadrian pdev->device == 0x432a) 6637300016Sadrian nphy->pwg_gain_5ghz = true; 6638300016Sadrian } 6639300016Sadrian#endif 6640300016Sadrian } else if (siba_sprom_get_bf2_lo(sc->sc_dev) & BWN_BFL2_5G_PWRGAIN) { 6641300016Sadrian nphy->pwg_gain_5ghz = true; 6642300016Sadrian } 6643300016Sadrian } 6644300016Sadrian 6645300016Sadrian if (mac->mac_phy.rev >= 3) { 6646300016Sadrian nphy->ipa2g_on = siba_sprom_get_fem_2ghz_extpa_gain(sc->sc_dev) == 2; 6647300016Sadrian nphy->ipa5g_on = siba_sprom_get_fem_5ghz_extpa_gain(sc->sc_dev) == 2; 6648300016Sadrian } 6649300016Sadrian} 6650300016Sadrian 6651300016Sadrianvoid 6652300016Sadrianbwn_nphy_op_free(struct bwn_mac *mac) 6653300016Sadrian{ 6654300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 6655300016Sadrian struct bwn_phy_n *nphy = phy->phy_n; 6656300016Sadrian 6657300016Sadrian free(nphy, M_DEVBUF); 6658300016Sadrian phy->phy_n = NULL; 6659300016Sadrian} 6660300016Sadrian 6661300016Sadrianint 6662300016Sadrianbwn_nphy_op_init(struct bwn_mac *mac) 6663300016Sadrian{ 6664300016Sadrian return bwn_phy_initn(mac); 6665300016Sadrian} 6666300016Sadrian 6667300016Sadrianstatic inline void check_phyreg(struct bwn_mac *mac, uint16_t offset) 6668300016Sadrian{ 6669300016Sadrian#ifdef BWN_DEBUG 6670300016Sadrian if ((offset & BWN_PHYROUTE_MASK) == BWN_PHYROUTE_OFDM_GPHY) { 6671300016Sadrian /* OFDM registers are onnly available on A/G-PHYs */ 6672300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "Invalid OFDM PHY access at " 6673300016Sadrian "0x%04X on N-PHY\n", offset); 6674300016Sadrian } 6675300016Sadrian if ((offset & BWN_PHYROUTE_MASK) == BWN_PHYROUTE_EXT_GPHY) { 6676300016Sadrian /* Ext-G registers are only available on G-PHYs */ 6677300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "Invalid EXT-G PHY access at " 6678300016Sadrian "0x%04X on N-PHY\n", offset); 6679300016Sadrian } 6680300016Sadrian#endif /* BWN_DEBUG */ 6681300016Sadrian} 6682300016Sadrian 6683300016Sadrianvoid 6684300016Sadrianbwn_nphy_op_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask, 6685300016Sadrian uint16_t set) 6686300016Sadrian{ 6687300016Sadrian check_phyreg(mac, reg); 6688300016Sadrian BWN_WRITE_2_F(mac, BWN_PHYCTL, reg); 6689300016Sadrian BWN_WRITE_SETMASK2(mac, BWN_PHYDATA, mask, set); 6690300016Sadrian} 6691300016Sadrian 6692300016Sadrian#if 0 6693300016Sadrianuint16_t 6694300016Sadrianbwn_nphy_op_radio_read(struct bwn_mac *mac, uint16_t reg) 6695300016Sadrian{ 6696300016Sadrian /* Register 1 is a 32-bit register. */ 6697300016Sadrian if (mac->mac_phy.rev < 7 && reg == 1) { 6698300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "%s: bad reg access\n", __func__); 6699300016Sadrian } 6700300016Sadrian 6701300016Sadrian if (mac->mac_phy.rev >= 7) 6702300016Sadrian reg |= 0x200; /* Radio 0x2057 */ 6703300016Sadrian else 6704300016Sadrian reg |= 0x100; 6705300016Sadrian 6706300016Sadrian BWN_WRITE_2_F(mac, BWN_RFCTL, reg); 6707300016Sadrian return BWN_READ_2(mac, BWN_RFDATALO); 6708300016Sadrian} 6709300016Sadrian#endif 6710300016Sadrian 6711300016Sadrian#if 0 6712300016Sadrianvoid 6713300016Sadrianbwn_nphy_op_radio_write(struct bwn_mac *mac, uint16_t reg, uint16_t value) 6714300016Sadrian{ 6715300016Sadrian /* Register 1 is a 32-bit register. */ 6716300016Sadrian if (mac->mac_phy.rev < 7 && reg == 1) { 6717300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "%s: bad reg access\n", __func__); 6718300016Sadrian } 6719300016Sadrian 6720300016Sadrian BWN_WRITE_2_F(mac, BWN_RFCTL, reg); 6721300016Sadrian BWN_WRITE_2(mac, BWN_RFDATALO, value); 6722300016Sadrian} 6723300016Sadrian#endif 6724300016Sadrian 6725300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */ 6726300016Sadrianvoid 6727300016Sadrianbwn_nphy_op_software_rfkill(struct bwn_mac *mac, bool active) 6728300016Sadrian{ 6729300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 6730300016Sadrian 6731300016Sadrian if (BWN_READ_4(mac, BWN_MACCTL) & BWN_MACCTL_ON) 6732300016Sadrian BWN_ERRPRINTF(mac->mac_sc, "MAC not suspended\n"); 6733300016Sadrian 6734300016Sadrian if (active) { 6735300016Sadrian DPRINTF(mac->mac_sc, BWN_DEBUG_RESET | BWN_DEBUG_PHY, 6736300016Sadrian "%s: called; rev=%d, rf_on=%d\n", __func__, 6737300016Sadrian phy->rev, mac->mac_phy.rf_on); 6738300016Sadrian if (phy->rev >= 19) { 6739300016Sadrian /* TODO */ 6740300016Sadrian } else if (phy->rev >= 7) { 6741300016Sadrian if (!mac->mac_phy.rf_on) 6742300016Sadrian bwn_radio_2057_init(mac); 6743300016Sadrian bwn_switch_channel(mac, bwn_get_chan(mac)); 6744300016Sadrian } else if (phy->rev >= 3) { 6745300016Sadrian if (!mac->mac_phy.rf_on) 6746300016Sadrian bwn_radio_init2056(mac); 6747300016Sadrian bwn_switch_channel(mac, bwn_get_chan(mac)); 6748300016Sadrian } else { 6749300016Sadrian bwn_radio_init2055(mac); 6750300016Sadrian } 6751300016Sadrian } else { 6752300016Sadrian if (phy->rev >= 19) { 6753300016Sadrian /* TODO */ 6754300016Sadrian } else if (phy->rev >= 8) { 6755300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, 6756300016Sadrian ~BWN_NPHY_RFCTL_CMD_CHIP0PU); 6757300016Sadrian } else if (phy->rev >= 7) { 6758300016Sadrian /* Nothing needed */ 6759300016Sadrian } else if (phy->rev >= 3) { 6760300016Sadrian BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, 6761300016Sadrian ~BWN_NPHY_RFCTL_CMD_CHIP0PU); 6762300016Sadrian 6763300016Sadrian BWN_RF_MASK(mac, 0x09, ~0x2); 6764300016Sadrian 6765300016Sadrian BWN_RF_WRITE(mac, 0x204D, 0); 6766300016Sadrian BWN_RF_WRITE(mac, 0x2053, 0); 6767300016Sadrian BWN_RF_WRITE(mac, 0x2058, 0); 6768300016Sadrian BWN_RF_WRITE(mac, 0x205E, 0); 6769300016Sadrian BWN_RF_MASK(mac, 0x2062, ~0xF0); 6770300016Sadrian BWN_RF_WRITE(mac, 0x2064, 0); 6771300016Sadrian 6772300016Sadrian BWN_RF_WRITE(mac, 0x304D, 0); 6773300016Sadrian BWN_RF_WRITE(mac, 0x3053, 0); 6774300016Sadrian BWN_RF_WRITE(mac, 0x3058, 0); 6775300016Sadrian BWN_RF_WRITE(mac, 0x305E, 0); 6776300016Sadrian BWN_RF_MASK(mac, 0x3062, ~0xF0); 6777300016Sadrian BWN_RF_WRITE(mac, 0x3064, 0); 6778300016Sadrian } 6779300016Sadrian } 6780300016Sadrian} 6781300016Sadrian 6782300016Sadrian/* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */ 6783300016Sadrianvoid 6784300016Sadrianbwn_nphy_op_switch_analog(struct bwn_mac *mac, bool on) 6785300016Sadrian{ 6786300016Sadrian struct bwn_phy *phy = &mac->mac_phy; 6787300016Sadrian uint16_t override = on ? 0x0 : 0x7FFF; 6788300016Sadrian uint16_t core = on ? 0xD : 0x00FD; 6789300016Sadrian 6790300016Sadrian if (phy->rev >= 19) { 6791300016Sadrian /* TODO */ 6792300016Sadrian device_printf(mac->mac_sc->sc_dev, "%s: TODO\n", __func__); 6793300016Sadrian } else if (phy->rev >= 3) { 6794300016Sadrian if (on) { 6795300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, core); 6796300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, override); 6797300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, core); 6798300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, override); 6799300016Sadrian } else { 6800300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, override); 6801300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, core); 6802300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, override); 6803300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, core); 6804300016Sadrian } 6805300016Sadrian } else { 6806300016Sadrian BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, override); 6807300016Sadrian } 6808300016Sadrian} 6809300016Sadrian 6810300016Sadrianint 6811300016Sadrianbwn_nphy_op_switch_channel(struct bwn_mac *mac, unsigned int new_channel) 6812300016Sadrian{ 6813300016Sadrian struct ieee80211_channel *channel = bwn_get_channel(mac); 6814300016Sadrian bwn_chan_type_t channel_type = bwn_get_chan_type(mac, NULL); 6815300016Sadrian 6816300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) { 6817300016Sadrian if ((new_channel < 1) || (new_channel > 14)) 6818300016Sadrian return -EINVAL; 6819300016Sadrian } else { 6820300016Sadrian if (new_channel > 200) 6821300016Sadrian return -EINVAL; 6822300016Sadrian } 6823300016Sadrian 6824300016Sadrian return bwn_nphy_set_channel(mac, channel, channel_type); 6825300016Sadrian} 6826300016Sadrian 6827300016Sadrian#if 0 6828300016Sadrianunsigned int 6829300016Sadrianbwn_nphy_op_get_default_chan(struct bwn_mac *mac) 6830300016Sadrian{ 6831300016Sadrian if (bwn_current_band(mac) == BWN_BAND_2G) 6832300016Sadrian return 1; 6833300016Sadrian return 36; 6834300016Sadrian} 6835300016Sadrian#endif 6836