1 2/* 3 4 Broadcom B43 wireless driver 5 IEEE 802.11n PHY data tables 6 7 Copyright (c) 2008 Michael Buesch <m@bues.ch> 8 Copyright (c) 2010 Rafa�� Mi��ecki <zajec5@gmail.com> 9 10 This program is free software; you can redistribute it and/or modify 11 it under the terms of the GNU General Public License as published by 12 the Free Software Foundation; either version 2 of the License, or 13 (at your option) any later version. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; see the file COPYING. If not, write to 22 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, 23 Boston, MA 02110-1301, USA. 24 25*/ 26 27#include <sys/cdefs.h> 28/* 29 * The Broadcom Wireless LAN controller driver. 30 */ 31 32#include "opt_wlan.h" 33#include "opt_bwn.h" 34 35#include <sys/param.h> 36#include <sys/systm.h> 37#include <sys/kernel.h> 38#include <sys/malloc.h> 39#include <sys/module.h> 40#include <sys/endian.h> 41#include <sys/errno.h> 42#include <sys/firmware.h> 43#include <sys/lock.h> 44#include <sys/mutex.h> 45#include <machine/bus.h> 46#include <machine/resource.h> 47#include <sys/bus.h> 48#include <sys/rman.h> 49#include <sys/socket.h> 50#include <sys/sockio.h> 51 52#include <net/ethernet.h> 53#include <net/if.h> 54#include <net/if_var.h> 55#include <net/if_arp.h> 56#include <net/if_dl.h> 57#include <net/if_llc.h> 58#include <net/if_media.h> 59#include <net/if_types.h> 60 61#include <dev/pci/pcivar.h> 62#include <dev/pci/pcireg.h> 63 64#include <net80211/ieee80211_var.h> 65#include <net80211/ieee80211_radiotap.h> 66#include <net80211/ieee80211_regdomain.h> 67#include <net80211/ieee80211_phy.h> 68#include <net80211/ieee80211_ratectl.h> 69 70#include <dev/bhnd/bhnd.h> 71#include <dev/bhnd/bhnd_ids.h> 72 73#include <dev/bhnd/cores/pmu/bhnd_pmu.h> 74#include <dev/bhnd/cores/chipc/chipc.h> 75 76#include <dev/bwn/if_bwnreg.h> 77#include <dev/bwn/if_bwnvar.h> 78#include <dev/bwn/if_bwn_misc.h> 79#include <dev/bwn/if_bwn_util.h> 80#include <dev/bwn/if_bwn_debug.h> 81#include <dev/bwn/if_bwn_phy_common.h> 82#include <dev/bwn/if_bwn_cordic.h> 83 84#include <gnu/dev/bwn/phy_n/if_bwn_phy_n_regs.h> 85#include <gnu/dev/bwn/phy_n/if_bwn_phy_n_ppr.h> 86#include <gnu/dev/bwn/phy_n/if_bwn_phy_n_sprom.h> 87#include <gnu/dev/bwn/phy_n/if_bwn_phy_n_tables.h> 88#include <gnu/dev/bwn/phy_n/if_bwn_radio_2055.h> 89#include <gnu/dev/bwn/phy_n/if_bwn_radio_2056.h> 90#include <gnu/dev/bwn/phy_n/if_bwn_radio_2057.h> 91#include <gnu/dev/bwn/phy_n/if_bwn_phy_n_core.h> 92 93#include "bhnd_nvram_map.h" 94 95struct bwn_nphy_txgains { 96 uint16_t tx_lpf[2]; 97 uint16_t txgm[2]; 98 uint16_t pga[2]; 99 uint16_t pad[2]; 100 uint16_t ipa[2]; 101}; 102 103struct bwn_nphy_iqcal_params { 104 uint16_t tx_lpf; 105 uint16_t txgm; 106 uint16_t pga; 107 uint16_t pad; 108 uint16_t ipa; 109 uint16_t cal_gain; 110 uint16_t ncorr[5]; 111}; 112 113struct bwn_nphy_iq_est { 114 int32_t iq0_prod; 115 uint32_t i0_pwr; 116 uint32_t q0_pwr; 117 int32_t iq1_prod; 118 uint32_t i1_pwr; 119 uint32_t q1_pwr; 120}; 121 122enum bwn_nphy_rf_sequence { 123 BWN_RFSEQ_RX2TX, 124 BWN_RFSEQ_TX2RX, 125 BWN_RFSEQ_RESET2RX, 126 BWN_RFSEQ_UPDATE_GAINH, 127 BWN_RFSEQ_UPDATE_GAINL, 128 BWN_RFSEQ_UPDATE_GAINU, 129}; 130 131enum n_rf_ctl_over_cmd { 132 N_RF_CTL_OVER_CMD_RXRF_PU = 0, 133 N_RF_CTL_OVER_CMD_RX_PU = 1, 134 N_RF_CTL_OVER_CMD_TX_PU = 2, 135 N_RF_CTL_OVER_CMD_RX_GAIN = 3, 136 N_RF_CTL_OVER_CMD_TX_GAIN = 4, 137}; 138 139enum n_intc_override { 140 N_INTC_OVERRIDE_OFF = 0, 141 N_INTC_OVERRIDE_TRSW = 1, 142 N_INTC_OVERRIDE_PA = 2, 143 N_INTC_OVERRIDE_EXT_LNA_PU = 3, 144 N_INTC_OVERRIDE_EXT_LNA_GAIN = 4, 145}; 146 147enum n_rssi_type { 148 N_RSSI_W1 = 0, 149 N_RSSI_W2, 150 N_RSSI_NB, 151 N_RSSI_IQ, 152 N_RSSI_TSSI_2G, 153 N_RSSI_TSSI_5G, 154 N_RSSI_TBD, 155}; 156 157enum n_rail_type { 158 N_RAIL_I = 0, 159 N_RAIL_Q = 1, 160}; 161 162static inline bool bwn_nphy_ipa(struct bwn_mac *mac) 163{ 164 bwn_band_t band = bwn_current_band(mac); 165 return ((mac->mac_phy.phy_n->ipa2g_on && band == BWN_BAND_2G) || 166 (mac->mac_phy.phy_n->ipa5g_on && band == BWN_BAND_5G)); 167} 168 169/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreGetState */ 170static uint8_t bwn_nphy_get_rx_core_state(struct bwn_mac *mac) 171{ 172 return (BWN_PHY_READ(mac, BWN_NPHY_RFSEQCA) & BWN_NPHY_RFSEQCA_RXEN) >> 173 BWN_NPHY_RFSEQCA_RXEN_SHIFT; 174} 175 176/************************************************** 177 * RF (just without bwn_nphy_rf_ctl_intc_override) 178 **************************************************/ 179 180/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */ 181static void bwn_nphy_force_rf_sequence(struct bwn_mac *mac, 182 enum bwn_nphy_rf_sequence seq) 183{ 184 static const uint16_t trigger[] = { 185 [BWN_RFSEQ_RX2TX] = BWN_NPHY_RFSEQTR_RX2TX, 186 [BWN_RFSEQ_TX2RX] = BWN_NPHY_RFSEQTR_TX2RX, 187 [BWN_RFSEQ_RESET2RX] = BWN_NPHY_RFSEQTR_RST2RX, 188 [BWN_RFSEQ_UPDATE_GAINH] = BWN_NPHY_RFSEQTR_UPGH, 189 [BWN_RFSEQ_UPDATE_GAINL] = BWN_NPHY_RFSEQTR_UPGL, 190 [BWN_RFSEQ_UPDATE_GAINU] = BWN_NPHY_RFSEQTR_UPGU, 191 }; 192 int i; 193 uint16_t seq_mode = BWN_PHY_READ(mac, BWN_NPHY_RFSEQMODE); 194 195 if (seq >= nitems(trigger)) { 196 BWN_WARNPRINTF(mac->mac_sc, "%s: seq %d > max", __func__, seq); 197 } 198 199 BWN_PHY_SET(mac, BWN_NPHY_RFSEQMODE, 200 BWN_NPHY_RFSEQMODE_CAOVER | BWN_NPHY_RFSEQMODE_TROVER); 201 BWN_PHY_SET(mac, BWN_NPHY_RFSEQTR, trigger[seq]); 202 for (i = 0; i < 200; i++) { 203 if (!(BWN_PHY_READ(mac, BWN_NPHY_RFSEQST) & trigger[seq])) 204 goto ok; 205 DELAY(1000); 206 } 207 BWN_ERRPRINTF(mac->mac_sc, "RF sequence status timeout\n"); 208ok: 209 BWN_PHY_WRITE(mac, BWN_NPHY_RFSEQMODE, seq_mode); 210} 211 212static void bwn_nphy_rf_ctl_override_rev19(struct bwn_mac *mac, uint16_t field, 213 uint16_t value, uint8_t core, bool off, 214 uint8_t override_id) 215{ 216 /* TODO */ 217} 218 219/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverrideRev7 */ 220static void bwn_nphy_rf_ctl_override_rev7(struct bwn_mac *mac, uint16_t field, 221 uint16_t value, uint8_t core, bool off, 222 uint8_t override) 223{ 224 struct bwn_phy *phy = &mac->mac_phy; 225 const struct bwn_nphy_rf_control_override_rev7 *e; 226 uint16_t en_addrs[3][2] = { 227 { 0x0E7, 0x0EC }, { 0x342, 0x343 }, { 0x346, 0x347 } 228 }; 229 uint16_t en_addr; 230 uint16_t en_mask = field; 231 uint16_t val_addr; 232 uint8_t i; 233 234 if (phy->rev >= 19 || phy->rev < 3) { 235 BWN_WARNPRINTF(mac->mac_sc, "%s: phy rev %d out of range\n", 236 __func__, 237 phy->rev); 238 return; 239 } 240 241 /* Remember: we can get NULL! */ 242 e = bwn_nphy_get_rf_ctl_over_rev7(mac, field, override); 243 244 for (i = 0; i < 2; i++) { 245 if (override >= nitems(en_addrs)) { 246 BWN_ERRPRINTF(mac->mac_sc, "Invalid override value %d\n", override); 247 return; 248 } 249 en_addr = en_addrs[override][i]; 250 251 if (e) 252 val_addr = (i == 0) ? e->val_addr_core0 : e->val_addr_core1; 253 254 if (off) { 255 BWN_PHY_MASK(mac, en_addr, ~en_mask); 256 if (e) /* Do it safer, better than wl */ 257 BWN_PHY_MASK(mac, val_addr, ~e->val_mask); 258 } else { 259 if (!core || (core & (1 << i))) { 260 BWN_PHY_SET(mac, en_addr, en_mask); 261 if (e) 262 BWN_PHY_SETMASK(mac, val_addr, ~e->val_mask, (value << e->val_shift)); 263 } 264 } 265 } 266} 267 268/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverideOneToMany */ 269static void bwn_nphy_rf_ctl_override_one_to_many(struct bwn_mac *mac, 270 enum n_rf_ctl_over_cmd cmd, 271 uint16_t value, uint8_t core, bool off) 272{ 273 struct bwn_phy *phy = &mac->mac_phy; 274 uint16_t tmp; 275 276 if (phy->rev < 7) { 277 BWN_ERRPRINTF(mac->mac_sc, "%s: phy rev %d out of range\n", 278 __func__, 279 phy->rev); 280 } 281 282 switch (cmd) { 283 case N_RF_CTL_OVER_CMD_RXRF_PU: 284 bwn_nphy_rf_ctl_override_rev7(mac, 0x20, value, core, off, 1); 285 bwn_nphy_rf_ctl_override_rev7(mac, 0x10, value, core, off, 1); 286 bwn_nphy_rf_ctl_override_rev7(mac, 0x08, value, core, off, 1); 287 break; 288 case N_RF_CTL_OVER_CMD_RX_PU: 289 bwn_nphy_rf_ctl_override_rev7(mac, 0x4, value, core, off, 1); 290 bwn_nphy_rf_ctl_override_rev7(mac, 0x2, value, core, off, 1); 291 bwn_nphy_rf_ctl_override_rev7(mac, 0x1, value, core, off, 1); 292 bwn_nphy_rf_ctl_override_rev7(mac, 0x2, value, core, off, 2); 293 bwn_nphy_rf_ctl_override_rev7(mac, 0x0800, 0, core, off, 1); 294 break; 295 case N_RF_CTL_OVER_CMD_TX_PU: 296 bwn_nphy_rf_ctl_override_rev7(mac, 0x4, value, core, off, 0); 297 bwn_nphy_rf_ctl_override_rev7(mac, 0x2, value, core, off, 1); 298 bwn_nphy_rf_ctl_override_rev7(mac, 0x1, value, core, off, 2); 299 bwn_nphy_rf_ctl_override_rev7(mac, 0x0800, 1, core, off, 1); 300 break; 301 case N_RF_CTL_OVER_CMD_RX_GAIN: 302 tmp = value & 0xFF; 303 bwn_nphy_rf_ctl_override_rev7(mac, 0x0800, tmp, core, off, 0); 304 tmp = value >> 8; 305 bwn_nphy_rf_ctl_override_rev7(mac, 0x6000, tmp, core, off, 0); 306 break; 307 case N_RF_CTL_OVER_CMD_TX_GAIN: 308 tmp = value & 0x7FFF; 309 bwn_nphy_rf_ctl_override_rev7(mac, 0x1000, tmp, core, off, 0); 310 tmp = value >> 14; 311 bwn_nphy_rf_ctl_override_rev7(mac, 0x4000, tmp, core, off, 0); 312 break; 313 } 314} 315 316/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */ 317static void bwn_nphy_rf_ctl_override(struct bwn_mac *mac, uint16_t field, 318 uint16_t value, uint8_t core, bool off) 319{ 320 int i; 321 uint8_t index = fls(field); 322 uint8_t addr, en_addr, val_addr; 323 324 /* we expect only one bit set */ 325 if (field & (~(1 << (index - 1)))) { 326 BWN_ERRPRINTF(mac->mac_sc, "%s: field 0x%04x has >1 bit set\n", 327 __func__, 328 field); 329 } 330 331 if (mac->mac_phy.rev >= 3) { 332 const struct bwn_nphy_rf_control_override_rev3 *rf_ctrl; 333 for (i = 0; i < 2; i++) { 334 if (index == 0 || index == 16) { 335 BWN_ERRPRINTF(mac->mac_sc, 336 "Unsupported RF Ctrl Override call\n"); 337 return; 338 } 339 340 rf_ctrl = &tbl_rf_control_override_rev3[index - 1]; 341 en_addr = BWN_PHY_N((i == 0) ? 342 rf_ctrl->en_addr0 : rf_ctrl->en_addr1); 343 val_addr = BWN_PHY_N((i == 0) ? 344 rf_ctrl->val_addr0 : rf_ctrl->val_addr1); 345 346 if (off) { 347 BWN_PHY_MASK(mac, en_addr, ~(field)); 348 BWN_PHY_MASK(mac, val_addr, 349 ~(rf_ctrl->val_mask)); 350 } else { 351 if (core == 0 || ((1 << i) & core)) { 352 BWN_PHY_SET(mac, en_addr, field); 353 BWN_PHY_SETMASK(mac, val_addr, 354 ~(rf_ctrl->val_mask), 355 (value << rf_ctrl->val_shift)); 356 } 357 } 358 } 359 } else { 360 const struct bwn_nphy_rf_control_override_rev2 *rf_ctrl; 361 if (off) { 362 BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER, ~(field)); 363 value = 0; 364 } else { 365 BWN_PHY_SET(mac, BWN_NPHY_RFCTL_OVER, field); 366 } 367 368 for (i = 0; i < 2; i++) { 369 if (index <= 1 || index == 16) { 370 BWN_ERRPRINTF(mac->mac_sc, 371 "Unsupported RF Ctrl Override call\n"); 372 return; 373 } 374 375 if (index == 2 || index == 10 || 376 (index >= 13 && index <= 15)) { 377 core = 1; 378 } 379 380 rf_ctrl = &tbl_rf_control_override_rev2[index - 2]; 381 addr = BWN_PHY_N((i == 0) ? 382 rf_ctrl->addr0 : rf_ctrl->addr1); 383 384 if ((1 << i) & core) 385 BWN_PHY_SETMASK(mac, addr, ~(rf_ctrl->bmask), 386 (value << rf_ctrl->shift)); 387 388 BWN_PHY_SET(mac, BWN_NPHY_RFCTL_OVER, 0x1); 389 BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, 390 BWN_NPHY_RFCTL_CMD_START); 391 DELAY(1); 392 BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER, 0xFFFE); 393 } 394 } 395} 396 397static void bwn_nphy_rf_ctl_intc_override_rev7(struct bwn_mac *mac, 398 enum n_intc_override intc_override, 399 uint16_t value, uint8_t core_sel) 400{ 401 uint16_t reg, tmp, tmp2, val; 402 int core; 403 404 /* TODO: What about rev19+? Revs 3+ and 7+ are a bit similar */ 405 406 for (core = 0; core < 2; core++) { 407 if ((core_sel == 1 && core != 0) || 408 (core_sel == 2 && core != 1)) 409 continue; 410 411 reg = (core == 0) ? BWN_NPHY_RFCTL_INTC1 : BWN_NPHY_RFCTL_INTC2; 412 413 switch (intc_override) { 414 case N_INTC_OVERRIDE_OFF: 415 BWN_PHY_WRITE(mac, reg, 0); 416 BWN_PHY_MASK(mac, 0x2ff, ~0x2000); 417 bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX); 418 break; 419 case N_INTC_OVERRIDE_TRSW: 420 BWN_PHY_SETMASK(mac, reg, ~0xC0, value << 6); 421 BWN_PHY_SET(mac, reg, 0x400); 422 423 BWN_PHY_MASK(mac, 0x2ff, ~0xC000 & 0xFFFF); 424 BWN_PHY_SET(mac, 0x2ff, 0x2000); 425 BWN_PHY_SET(mac, 0x2ff, 0x0001); 426 break; 427 case N_INTC_OVERRIDE_PA: 428 tmp = 0x0030; 429 if (bwn_current_band(mac) == BWN_BAND_5G) 430 val = value << 5; 431 else 432 val = value << 4; 433 BWN_PHY_SETMASK(mac, reg, ~tmp, val); 434 BWN_PHY_SET(mac, reg, 0x1000); 435 break; 436 case N_INTC_OVERRIDE_EXT_LNA_PU: 437 if (bwn_current_band(mac) == BWN_BAND_5G) { 438 tmp = 0x0001; 439 tmp2 = 0x0004; 440 val = value; 441 } else { 442 tmp = 0x0004; 443 tmp2 = 0x0001; 444 val = value << 2; 445 } 446 BWN_PHY_SETMASK(mac, reg, ~tmp, val); 447 BWN_PHY_MASK(mac, reg, ~tmp2); 448 break; 449 case N_INTC_OVERRIDE_EXT_LNA_GAIN: 450 if (bwn_current_band(mac) == BWN_BAND_5G) { 451 tmp = 0x0002; 452 tmp2 = 0x0008; 453 val = value << 1; 454 } else { 455 tmp = 0x0008; 456 tmp2 = 0x0002; 457 val = value << 3; 458 } 459 BWN_PHY_SETMASK(mac, reg, ~tmp, val); 460 BWN_PHY_MASK(mac, reg, ~tmp2); 461 break; 462 } 463 } 464} 465 466/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlIntcOverride */ 467static void bwn_nphy_rf_ctl_intc_override(struct bwn_mac *mac, 468 enum n_intc_override intc_override, 469 uint16_t value, uint8_t core) 470{ 471 uint8_t i, j; 472 uint16_t reg, tmp, val; 473 474 if (mac->mac_phy.rev >= 7) { 475 bwn_nphy_rf_ctl_intc_override_rev7(mac, intc_override, value, 476 core); 477 return; 478 } 479 480 if (mac->mac_phy.rev < 3) { 481 BWN_ERRPRINTF(mac->mac_sc, "%s: phy rev %d out of range\n", 482 __func__, 483 mac->mac_phy.rev); 484 } 485 486 for (i = 0; i < 2; i++) { 487 if ((core == 1 && i == 1) || (core == 2 && !i)) 488 continue; 489 490 reg = (i == 0) ? 491 BWN_NPHY_RFCTL_INTC1 : BWN_NPHY_RFCTL_INTC2; 492 BWN_PHY_SET(mac, reg, 0x400); 493 494 switch (intc_override) { 495 case N_INTC_OVERRIDE_OFF: 496 BWN_PHY_WRITE(mac, reg, 0); 497 bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX); 498 break; 499 case N_INTC_OVERRIDE_TRSW: 500 if (!i) { 501 BWN_PHY_SETMASK(mac, BWN_NPHY_RFCTL_INTC1, 502 0xFC3F, (value << 6)); 503 BWN_PHY_SETMASK(mac, BWN_NPHY_TXF_40CO_B1S1, 504 0xFFFE, 1); 505 BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, 506 BWN_NPHY_RFCTL_CMD_START); 507 for (j = 0; j < 100; j++) { 508 if (!(BWN_PHY_READ(mac, BWN_NPHY_RFCTL_CMD) & BWN_NPHY_RFCTL_CMD_START)) { 509 j = 0; 510 break; 511 } 512 DELAY(10); 513 } 514 if (j) 515 BWN_ERRPRINTF(mac->mac_sc, 516 "intc override timeout\n"); 517 BWN_PHY_MASK(mac, BWN_NPHY_TXF_40CO_B1S1, 518 0xFFFE); 519 } else { 520 BWN_PHY_SETMASK(mac, BWN_NPHY_RFCTL_INTC2, 521 0xFC3F, (value << 6)); 522 BWN_PHY_SETMASK(mac, BWN_NPHY_RFCTL_OVER, 523 0xFFFE, 1); 524 BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, 525 BWN_NPHY_RFCTL_CMD_RXTX); 526 for (j = 0; j < 100; j++) { 527 if (!(BWN_PHY_READ(mac, BWN_NPHY_RFCTL_CMD) & BWN_NPHY_RFCTL_CMD_RXTX)) { 528 j = 0; 529 break; 530 } 531 DELAY(10); 532 } 533 if (j) 534 BWN_ERRPRINTF(mac->mac_sc, 535 "intc override timeout\n"); 536 BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER, 537 0xFFFE); 538 } 539 break; 540 case N_INTC_OVERRIDE_PA: 541 if (bwn_current_band(mac) == BWN_BAND_5G) { 542 tmp = 0x0020; 543 val = value << 5; 544 } else { 545 tmp = 0x0010; 546 val = value << 4; 547 } 548 BWN_PHY_SETMASK(mac, reg, ~tmp, val); 549 break; 550 case N_INTC_OVERRIDE_EXT_LNA_PU: 551 if (bwn_current_band(mac) == BWN_BAND_5G) { 552 tmp = 0x0001; 553 val = value; 554 } else { 555 tmp = 0x0004; 556 val = value << 2; 557 } 558 BWN_PHY_SETMASK(mac, reg, ~tmp, val); 559 break; 560 case N_INTC_OVERRIDE_EXT_LNA_GAIN: 561 if (bwn_current_band(mac) == BWN_BAND_5G) { 562 tmp = 0x0002; 563 val = value << 1; 564 } else { 565 tmp = 0x0008; 566 val = value << 3; 567 } 568 BWN_PHY_SETMASK(mac, reg, ~tmp, val); 569 break; 570 } 571 } 572} 573 574/************************************************** 575 * Various PHY ops 576 **************************************************/ 577 578/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */ 579static void bwn_nphy_write_clip_detection(struct bwn_mac *mac, 580 const uint16_t *clip_st) 581{ 582 BWN_PHY_WRITE(mac, BWN_NPHY_C1_CLIP1THRES, clip_st[0]); 583 BWN_PHY_WRITE(mac, BWN_NPHY_C2_CLIP1THRES, clip_st[1]); 584} 585 586/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */ 587static void bwn_nphy_read_clip_detection(struct bwn_mac *mac, uint16_t *clip_st) 588{ 589 clip_st[0] = BWN_PHY_READ(mac, BWN_NPHY_C1_CLIP1THRES); 590 clip_st[1] = BWN_PHY_READ(mac, BWN_NPHY_C2_CLIP1THRES); 591} 592 593/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */ 594static uint16_t bwn_nphy_classifier(struct bwn_mac *mac, uint16_t mask, uint16_t val) 595{ 596 struct bwn_softc *sc = mac->mac_sc; 597 uint16_t tmp; 598 599 if (bhnd_get_hwrev(sc->sc_dev) == 16) 600 bwn_mac_suspend(mac); 601 602 tmp = BWN_PHY_READ(mac, BWN_NPHY_CLASSCTL); 603 tmp &= (BWN_NPHY_CLASSCTL_CCKEN | BWN_NPHY_CLASSCTL_OFDMEN | 604 BWN_NPHY_CLASSCTL_WAITEDEN); 605 tmp &= ~mask; 606 tmp |= (val & mask); 607 BWN_PHY_SETMASK(mac, BWN_NPHY_CLASSCTL, 0xFFF8, tmp); 608 609 if (bhnd_get_hwrev(sc->sc_dev) == 16) 610 bwn_mac_enable(mac); 611 612 return tmp; 613} 614 615/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */ 616static void bwn_nphy_reset_cca(struct bwn_mac *mac) 617{ 618 uint16_t bbcfg; 619 620 bwn_phy_force_clock(mac, 1); 621 bbcfg = BWN_PHY_READ(mac, BWN_NPHY_BBCFG); 622 BWN_PHY_WRITE(mac, BWN_NPHY_BBCFG, bbcfg | BWN_NPHY_BBCFG_RSTCCA); 623 DELAY(1); 624 BWN_PHY_WRITE(mac, BWN_NPHY_BBCFG, bbcfg & ~BWN_NPHY_BBCFG_RSTCCA); 625 bwn_phy_force_clock(mac, 0); 626 bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX); 627} 628 629/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/carriersearch */ 630static void bwn_nphy_stay_in_carrier_search(struct bwn_mac *mac, bool enable) 631{ 632 struct bwn_phy *phy = &mac->mac_phy; 633 struct bwn_phy_n *nphy = phy->phy_n; 634 635 if (enable) { 636 static const uint16_t clip[] = { 0xFFFF, 0xFFFF }; 637 if (nphy->deaf_count++ == 0) { 638 nphy->classifier_state = bwn_nphy_classifier(mac, 0, 0); 639 bwn_nphy_classifier(mac, 0x7, 640 BWN_NPHY_CLASSCTL_WAITEDEN); 641 bwn_nphy_read_clip_detection(mac, nphy->clip_state); 642 bwn_nphy_write_clip_detection(mac, clip); 643 } 644 bwn_nphy_reset_cca(mac); 645 } else { 646 if (--nphy->deaf_count == 0) { 647 bwn_nphy_classifier(mac, 0x7, nphy->classifier_state); 648 bwn_nphy_write_clip_detection(mac, nphy->clip_state); 649 } 650 } 651} 652 653/* http://bcm-v4.sipsolutions.net/PHY/N/Read_Lpf_Bw_Ctl */ 654static uint16_t bwn_nphy_read_lpf_ctl(struct bwn_mac *mac, uint16_t offset) 655{ 656 if (!offset) 657 offset = bwn_is_40mhz(mac) ? 0x159 : 0x154; 658 return bwn_ntab_read(mac, BWN_NTAB16(7, offset)) & 0x7; 659} 660 661/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */ 662static void bwn_nphy_adjust_lna_gain_table(struct bwn_mac *mac) 663{ 664 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 665 666 uint8_t i; 667 int16_t tmp; 668 uint16_t data[4]; 669 int16_t gain[2]; 670 uint16_t minmax[2]; 671 static const uint16_t lna_gain[4] = { -2, 10, 19, 25 }; 672 673 if (nphy->hang_avoid) 674 bwn_nphy_stay_in_carrier_search(mac, 1); 675 676 if (nphy->gain_boost) { 677 if (bwn_current_band(mac) == BWN_BAND_2G) { 678 gain[0] = 6; 679 gain[1] = 6; 680 } else { 681 tmp = 40370 - 315 * bwn_get_chan(mac); 682 gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1)); 683 tmp = 23242 - 224 * bwn_get_chan(mac); 684 gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1)); 685 } 686 } else { 687 gain[0] = 0; 688 gain[1] = 0; 689 } 690 691 for (i = 0; i < 2; i++) { 692 if (nphy->elna_gain_config) { 693 data[0] = 19 + gain[i]; 694 data[1] = 25 + gain[i]; 695 data[2] = 25 + gain[i]; 696 data[3] = 25 + gain[i]; 697 } else { 698 data[0] = lna_gain[0] + gain[i]; 699 data[1] = lna_gain[1] + gain[i]; 700 data[2] = lna_gain[2] + gain[i]; 701 data[3] = lna_gain[3] + gain[i]; 702 } 703 bwn_ntab_write_bulk(mac, BWN_NTAB16(i, 8), 4, data); 704 705 minmax[i] = 23 + gain[i]; 706 } 707 708 BWN_PHY_SETMASK(mac, BWN_NPHY_C1_MINMAX_GAIN, ~BWN_NPHY_C1_MINGAIN, 709 minmax[0] << BWN_NPHY_C1_MINGAIN_SHIFT); 710 BWN_PHY_SETMASK(mac, BWN_NPHY_C2_MINMAX_GAIN, ~BWN_NPHY_C2_MINGAIN, 711 minmax[1] << BWN_NPHY_C2_MINGAIN_SHIFT); 712 713 if (nphy->hang_avoid) 714 bwn_nphy_stay_in_carrier_search(mac, 0); 715} 716 717/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRfSeq */ 718static void bwn_nphy_set_rf_sequence(struct bwn_mac *mac, uint8_t cmd, 719 uint8_t *events, uint8_t *delays, uint8_t length) 720{ 721 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 722 uint8_t i; 723 uint8_t end = (mac->mac_phy.rev >= 3) ? 0x1F : 0x0F; 724 uint16_t offset1 = cmd << 4; 725 uint16_t offset2 = offset1 + 0x80; 726 727 if (nphy->hang_avoid) 728 bwn_nphy_stay_in_carrier_search(mac, true); 729 730 bwn_ntab_write_bulk(mac, BWN_NTAB8(7, offset1), length, events); 731 bwn_ntab_write_bulk(mac, BWN_NTAB8(7, offset2), length, delays); 732 733 for (i = length; i < 16; i++) { 734 bwn_ntab_write(mac, BWN_NTAB8(7, offset1 + i), end); 735 bwn_ntab_write(mac, BWN_NTAB8(7, offset2 + i), 1); 736 } 737 738 if (nphy->hang_avoid) 739 bwn_nphy_stay_in_carrier_search(mac, false); 740} 741 742/************************************************** 743 * Radio 0x2057 744 **************************************************/ 745 746static void bwn_radio_2057_chantab_upload(struct bwn_mac *mac, 747 const struct bwn_nphy_chantabent_rev7 *e_r7, 748 const struct bwn_nphy_chantabent_rev7_2g *e_r7_2g) 749{ 750 if (e_r7_2g) { 751 BWN_RF_WRITE(mac, R2057_VCOCAL_COUNTVAL0, e_r7_2g->radio_vcocal_countval0); 752 BWN_RF_WRITE(mac, R2057_VCOCAL_COUNTVAL1, e_r7_2g->radio_vcocal_countval1); 753 BWN_RF_WRITE(mac, R2057_RFPLL_REFMASTER_SPAREXTALSIZE, e_r7_2g->radio_rfpll_refmaster_sparextalsize); 754 BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_R1, e_r7_2g->radio_rfpll_loopfilter_r1); 755 BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C2, e_r7_2g->radio_rfpll_loopfilter_c2); 756 BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C1, e_r7_2g->radio_rfpll_loopfilter_c1); 757 BWN_RF_WRITE(mac, R2057_CP_KPD_IDAC, e_r7_2g->radio_cp_kpd_idac); 758 BWN_RF_WRITE(mac, R2057_RFPLL_MMD0, e_r7_2g->radio_rfpll_mmd0); 759 BWN_RF_WRITE(mac, R2057_RFPLL_MMD1, e_r7_2g->radio_rfpll_mmd1); 760 BWN_RF_WRITE(mac, R2057_VCOBUF_TUNE, e_r7_2g->radio_vcobuf_tune); 761 BWN_RF_WRITE(mac, R2057_LOGEN_MX2G_TUNE, e_r7_2g->radio_logen_mx2g_tune); 762 BWN_RF_WRITE(mac, R2057_LOGEN_INDBUF2G_TUNE, e_r7_2g->radio_logen_indbuf2g_tune); 763 BWN_RF_WRITE(mac, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, e_r7_2g->radio_txmix2g_tune_boost_pu_core0); 764 BWN_RF_WRITE(mac, R2057_PAD2G_TUNE_PUS_CORE0, e_r7_2g->radio_pad2g_tune_pus_core0); 765 BWN_RF_WRITE(mac, R2057_LNA2G_TUNE_CORE0, e_r7_2g->radio_lna2g_tune_core0); 766 BWN_RF_WRITE(mac, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, e_r7_2g->radio_txmix2g_tune_boost_pu_core1); 767 BWN_RF_WRITE(mac, R2057_PAD2G_TUNE_PUS_CORE1, e_r7_2g->radio_pad2g_tune_pus_core1); 768 BWN_RF_WRITE(mac, R2057_LNA2G_TUNE_CORE1, e_r7_2g->radio_lna2g_tune_core1); 769 770 } else { 771 BWN_RF_WRITE(mac, R2057_VCOCAL_COUNTVAL0, e_r7->radio_vcocal_countval0); 772 BWN_RF_WRITE(mac, R2057_VCOCAL_COUNTVAL1, e_r7->radio_vcocal_countval1); 773 BWN_RF_WRITE(mac, R2057_RFPLL_REFMASTER_SPAREXTALSIZE, e_r7->radio_rfpll_refmaster_sparextalsize); 774 BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_R1, e_r7->radio_rfpll_loopfilter_r1); 775 BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C2, e_r7->radio_rfpll_loopfilter_c2); 776 BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C1, e_r7->radio_rfpll_loopfilter_c1); 777 BWN_RF_WRITE(mac, R2057_CP_KPD_IDAC, e_r7->radio_cp_kpd_idac); 778 BWN_RF_WRITE(mac, R2057_RFPLL_MMD0, e_r7->radio_rfpll_mmd0); 779 BWN_RF_WRITE(mac, R2057_RFPLL_MMD1, e_r7->radio_rfpll_mmd1); 780 BWN_RF_WRITE(mac, R2057_VCOBUF_TUNE, e_r7->radio_vcobuf_tune); 781 BWN_RF_WRITE(mac, R2057_LOGEN_MX2G_TUNE, e_r7->radio_logen_mx2g_tune); 782 BWN_RF_WRITE(mac, R2057_LOGEN_MX5G_TUNE, e_r7->radio_logen_mx5g_tune); 783 BWN_RF_WRITE(mac, R2057_LOGEN_INDBUF2G_TUNE, e_r7->radio_logen_indbuf2g_tune); 784 BWN_RF_WRITE(mac, R2057_LOGEN_INDBUF5G_TUNE, e_r7->radio_logen_indbuf5g_tune); 785 BWN_RF_WRITE(mac, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, e_r7->radio_txmix2g_tune_boost_pu_core0); 786 BWN_RF_WRITE(mac, R2057_PAD2G_TUNE_PUS_CORE0, e_r7->radio_pad2g_tune_pus_core0); 787 BWN_RF_WRITE(mac, R2057_PGA_BOOST_TUNE_CORE0, e_r7->radio_pga_boost_tune_core0); 788 BWN_RF_WRITE(mac, R2057_TXMIX5G_BOOST_TUNE_CORE0, e_r7->radio_txmix5g_boost_tune_core0); 789 BWN_RF_WRITE(mac, R2057_PAD5G_TUNE_MISC_PUS_CORE0, e_r7->radio_pad5g_tune_misc_pus_core0); 790 BWN_RF_WRITE(mac, R2057_LNA2G_TUNE_CORE0, e_r7->radio_lna2g_tune_core0); 791 BWN_RF_WRITE(mac, R2057_LNA5G_TUNE_CORE0, e_r7->radio_lna5g_tune_core0); 792 BWN_RF_WRITE(mac, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, e_r7->radio_txmix2g_tune_boost_pu_core1); 793 BWN_RF_WRITE(mac, R2057_PAD2G_TUNE_PUS_CORE1, e_r7->radio_pad2g_tune_pus_core1); 794 BWN_RF_WRITE(mac, R2057_PGA_BOOST_TUNE_CORE1, e_r7->radio_pga_boost_tune_core1); 795 BWN_RF_WRITE(mac, R2057_TXMIX5G_BOOST_TUNE_CORE1, e_r7->radio_txmix5g_boost_tune_core1); 796 BWN_RF_WRITE(mac, R2057_PAD5G_TUNE_MISC_PUS_CORE1, e_r7->radio_pad5g_tune_misc_pus_core1); 797 BWN_RF_WRITE(mac, R2057_LNA2G_TUNE_CORE1, e_r7->radio_lna2g_tune_core1); 798 BWN_RF_WRITE(mac, R2057_LNA5G_TUNE_CORE1, e_r7->radio_lna5g_tune_core1); 799 } 800} 801 802static void bwn_radio_2057_setup(struct bwn_mac *mac, 803 const struct bwn_nphy_chantabent_rev7 *tabent_r7, 804 const struct bwn_nphy_chantabent_rev7_2g *tabent_r7_2g) 805{ 806 struct bwn_phy *phy = &mac->mac_phy; 807 808 bwn_radio_2057_chantab_upload(mac, tabent_r7, tabent_r7_2g); 809 810 switch (phy->rf_rev) { 811 case 0 ... 4: 812 case 6: 813 if (bwn_current_band(mac) == BWN_BAND_2G) { 814 BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_R1, 0x3f); 815 BWN_RF_WRITE(mac, R2057_CP_KPD_IDAC, 0x3f); 816 BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C1, 0x8); 817 BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C2, 0x8); 818 } else { 819 BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_R1, 0x1f); 820 BWN_RF_WRITE(mac, R2057_CP_KPD_IDAC, 0x3f); 821 BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C1, 0x8); 822 BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C2, 0x8); 823 } 824 break; 825 case 9: /* e.g. PHY rev 16 */ 826 BWN_RF_WRITE(mac, R2057_LOGEN_PTAT_RESETS, 0x20); 827 BWN_RF_WRITE(mac, R2057_VCOBUF_IDACS, 0x18); 828 if (bwn_current_band(mac) == BWN_BAND_5G) { 829 BWN_RF_WRITE(mac, R2057_LOGEN_PTAT_RESETS, 0x38); 830 BWN_RF_WRITE(mac, R2057_VCOBUF_IDACS, 0x0f); 831 832 if (bwn_is_40mhz(mac)) { 833 /* TODO */ 834 } else { 835 BWN_RF_WRITE(mac, 836 R2057_PAD_BIAS_FILTER_BWS_CORE0, 837 0x3c); 838 BWN_RF_WRITE(mac, 839 R2057_PAD_BIAS_FILTER_BWS_CORE1, 840 0x3c); 841 } 842 } 843 break; 844 case 14: /* 2 GHz only */ 845 BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_R1, 0x1b); 846 BWN_RF_WRITE(mac, R2057_CP_KPD_IDAC, 0x3f); 847 BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C1, 0x1f); 848 BWN_RF_WRITE(mac, R2057_RFPLL_LOOPFILTER_C2, 0x1f); 849 break; 850 } 851 852 if (bwn_current_band(mac) == BWN_BAND_2G) { 853 uint16_t txmix2g_tune_boost_pu = 0; 854 uint16_t pad2g_tune_pus = 0; 855 856 if (bwn_nphy_ipa(mac)) { 857 switch (phy->rf_rev) { 858 case 9: 859 txmix2g_tune_boost_pu = 0x0041; 860 /* TODO */ 861 break; 862 case 14: 863 txmix2g_tune_boost_pu = 0x21; 864 pad2g_tune_pus = 0x23; 865 break; 866 } 867 } 868 869 if (txmix2g_tune_boost_pu) 870 BWN_RF_WRITE(mac, R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, 871 txmix2g_tune_boost_pu); 872 if (pad2g_tune_pus) 873 BWN_RF_WRITE(mac, R2057_PAD2G_TUNE_PUS_CORE0, 874 pad2g_tune_pus); 875 if (txmix2g_tune_boost_pu) 876 BWN_RF_WRITE(mac, R2057_TXMIX2G_TUNE_BOOST_PU_CORE1, 877 txmix2g_tune_boost_pu); 878 if (pad2g_tune_pus) 879 BWN_RF_WRITE(mac, R2057_PAD2G_TUNE_PUS_CORE1, 880 pad2g_tune_pus); 881 } 882 883 /* 50..100 */ 884 DELAY(100); 885 886 /* VCO calibration */ 887 BWN_RF_MASK(mac, R2057_RFPLL_MISC_EN, ~0x01); 888 BWN_RF_MASK(mac, R2057_RFPLL_MISC_CAL_RESETN, ~0x04); 889 BWN_RF_SET(mac, R2057_RFPLL_MISC_CAL_RESETN, 0x4); 890 BWN_RF_SET(mac, R2057_RFPLL_MISC_EN, 0x01); 891 /* 300..600 */ 892 DELAY(600); 893} 894 895/* Calibrate resistors in LPF of PLL? 896 * http://bcm-v4.sipsolutions.net/PHY/radio205x_rcal 897 */ 898static uint8_t bwn_radio_2057_rcal(struct bwn_mac *mac) 899{ 900 struct bwn_phy *phy = &mac->mac_phy; 901 uint16_t saved_regs_phy[12]; 902 uint16_t saved_regs_phy_rf[6]; 903 uint16_t saved_regs_radio[2] = { }; 904 static const uint16_t phy_to_store[] = { 905 BWN_NPHY_RFCTL_RSSIO1, BWN_NPHY_RFCTL_RSSIO2, 906 BWN_NPHY_RFCTL_LUT_TRSW_LO1, BWN_NPHY_RFCTL_LUT_TRSW_LO2, 907 BWN_NPHY_RFCTL_RXG1, BWN_NPHY_RFCTL_RXG2, 908 BWN_NPHY_RFCTL_TXG1, BWN_NPHY_RFCTL_TXG2, 909 BWN_NPHY_REV7_RF_CTL_MISC_REG3, BWN_NPHY_REV7_RF_CTL_MISC_REG4, 910 BWN_NPHY_REV7_RF_CTL_MISC_REG5, BWN_NPHY_REV7_RF_CTL_MISC_REG6, 911 }; 912 static const uint16_t phy_to_store_rf[] = { 913 BWN_NPHY_REV3_RFCTL_OVER0, BWN_NPHY_REV3_RFCTL_OVER1, 914 BWN_NPHY_REV7_RF_CTL_OVER3, BWN_NPHY_REV7_RF_CTL_OVER4, 915 BWN_NPHY_REV7_RF_CTL_OVER5, BWN_NPHY_REV7_RF_CTL_OVER6, 916 }; 917 uint16_t tmp; 918 int i; 919 920 /* Save */ 921 for (i = 0; i < nitems(phy_to_store); i++) 922 saved_regs_phy[i] = BWN_PHY_READ(mac, phy_to_store[i]); 923 for (i = 0; i < nitems(phy_to_store_rf); i++) 924 saved_regs_phy_rf[i] = BWN_PHY_READ(mac, phy_to_store_rf[i]); 925 926 /* Set */ 927 for (i = 0; i < nitems(phy_to_store); i++) 928 BWN_PHY_WRITE(mac, phy_to_store[i], 0); 929 BWN_PHY_WRITE(mac, BWN_NPHY_REV3_RFCTL_OVER0, 0x07ff); 930 BWN_PHY_WRITE(mac, BWN_NPHY_REV3_RFCTL_OVER1, 0x07ff); 931 BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER3, 0x07ff); 932 BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER4, 0x07ff); 933 BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER5, 0x007f); 934 BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER6, 0x007f); 935 936 switch (phy->rf_rev) { 937 case 5: 938 BWN_PHY_MASK(mac, BWN_NPHY_REV7_RF_CTL_OVER3, ~0x2); 939 DELAY(10); 940 BWN_RF_SET(mac, R2057_IQTEST_SEL_PU, 0x1); 941 BWN_RF_SETMASK(mac, R2057v7_IQTEST_SEL_PU2, ~0x2, 0x1); 942 break; 943 case 9: 944 BWN_PHY_SET(mac, BWN_NPHY_REV7_RF_CTL_OVER3, 0x2); 945 BWN_PHY_SET(mac, BWN_NPHY_REV7_RF_CTL_MISC_REG3, 0x2); 946 saved_regs_radio[0] = BWN_RF_READ(mac, R2057_IQTEST_SEL_PU); 947 BWN_RF_WRITE(mac, R2057_IQTEST_SEL_PU, 0x11); 948 break; 949 case 14: 950 saved_regs_radio[0] = BWN_RF_READ(mac, R2057_IQTEST_SEL_PU); 951 saved_regs_radio[1] = BWN_RF_READ(mac, R2057v7_IQTEST_SEL_PU2); 952 BWN_PHY_SET(mac, BWN_NPHY_REV7_RF_CTL_MISC_REG3, 0x2); 953 BWN_PHY_SET(mac, BWN_NPHY_REV7_RF_CTL_OVER3, 0x2); 954 BWN_RF_WRITE(mac, R2057v7_IQTEST_SEL_PU2, 0x2); 955 BWN_RF_WRITE(mac, R2057_IQTEST_SEL_PU, 0x1); 956 break; 957 } 958 959 /* Enable */ 960 BWN_RF_SET(mac, R2057_RCAL_CONFIG, 0x1); 961 DELAY(10); 962 963 /* Start */ 964 BWN_RF_SET(mac, R2057_RCAL_CONFIG, 0x2); 965 /* 100..200 */ 966 DELAY(200); 967 968 /* Stop */ 969 BWN_RF_MASK(mac, R2057_RCAL_CONFIG, ~0x2); 970 971 /* Wait and check for result */ 972 if (!bwn_radio_wait_value(mac, R2057_RCAL_STATUS, 1, 1, 100, 1000000)) { 973 BWN_ERRPRINTF(mac->mac_sc, "Radio 0x2057 rcal timeout\n"); 974 return 0; 975 } 976 tmp = BWN_RF_READ(mac, R2057_RCAL_STATUS) & 0x3E; 977 978 /* Disable */ 979 BWN_RF_MASK(mac, R2057_RCAL_CONFIG, ~0x1); 980 981 /* Restore */ 982 for (i = 0; i < nitems(phy_to_store_rf); i++) 983 BWN_PHY_WRITE(mac, phy_to_store_rf[i], saved_regs_phy_rf[i]); 984 for (i = 0; i < nitems(phy_to_store); i++) 985 BWN_PHY_WRITE(mac, phy_to_store[i], saved_regs_phy[i]); 986 987 switch (phy->rf_rev) { 988 case 0 ... 4: 989 case 6: 990 BWN_RF_SETMASK(mac, R2057_TEMPSENSE_CONFIG, ~0x3C, tmp); 991 BWN_RF_SETMASK(mac, R2057_BANDGAP_RCAL_TRIM, ~0xF0, 992 tmp << 2); 993 break; 994 case 5: 995 BWN_RF_MASK(mac, R2057_IPA2G_CASCONV_CORE0, ~0x1); 996 BWN_RF_MASK(mac, R2057v7_IQTEST_SEL_PU2, ~0x2); 997 break; 998 case 9: 999 BWN_RF_WRITE(mac, R2057_IQTEST_SEL_PU, saved_regs_radio[0]); 1000 break; 1001 case 14: 1002 BWN_RF_WRITE(mac, R2057_IQTEST_SEL_PU, saved_regs_radio[0]); 1003 BWN_RF_WRITE(mac, R2057v7_IQTEST_SEL_PU2, saved_regs_radio[1]); 1004 break; 1005 } 1006 1007 return tmp & 0x3e; 1008} 1009 1010/* Calibrate the internal RC oscillator? 1011 * http://bcm-v4.sipsolutions.net/PHY/radio2057_rccal 1012 */ 1013static uint16_t bwn_radio_2057_rccal(struct bwn_mac *mac) 1014{ 1015 struct bwn_phy *phy = &mac->mac_phy; 1016 bool special = (phy->rf_rev == 3 || phy->rf_rev == 4 || 1017 phy->rf_rev == 6); 1018 uint16_t tmp; 1019 1020 /* Setup cal */ 1021 if (special) { 1022 BWN_RF_WRITE(mac, R2057_RCCAL_MASTER, 0x61); 1023 BWN_RF_WRITE(mac, R2057_RCCAL_TRC0, 0xC0); 1024 } else { 1025 BWN_RF_WRITE(mac, R2057v7_RCCAL_MASTER, 0x61); 1026 BWN_RF_WRITE(mac, R2057_RCCAL_TRC0, 0xE9); 1027 } 1028 BWN_RF_WRITE(mac, R2057_RCCAL_X1, 0x6E); 1029 1030 /* Start, wait, stop */ 1031 BWN_RF_WRITE(mac, R2057_RCCAL_START_R1_Q1_P1, 0x55); 1032 if (!bwn_radio_wait_value(mac, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500, 1033 5000000)) 1034 BWN_DBGPRINTF(mac, "Radio 0x2057 rccal timeout\n"); 1035 /* 35..70 */ 1036 DELAY(70); 1037 BWN_RF_WRITE(mac, R2057_RCCAL_START_R1_Q1_P1, 0x15); 1038 /* 70..140 */ 1039 DELAY(140); 1040 1041 /* Setup cal */ 1042 if (special) { 1043 BWN_RF_WRITE(mac, R2057_RCCAL_MASTER, 0x69); 1044 BWN_RF_WRITE(mac, R2057_RCCAL_TRC0, 0xB0); 1045 } else { 1046 BWN_RF_WRITE(mac, R2057v7_RCCAL_MASTER, 0x69); 1047 BWN_RF_WRITE(mac, R2057_RCCAL_TRC0, 0xD5); 1048 } 1049 BWN_RF_WRITE(mac, R2057_RCCAL_X1, 0x6E); 1050 1051 /* Start, wait, stop */ 1052 /* 35..70 */ 1053 DELAY(70); 1054 BWN_RF_WRITE(mac, R2057_RCCAL_START_R1_Q1_P1, 0x55); 1055 /* 70..140 */ 1056 DELAY(140); 1057 if (!bwn_radio_wait_value(mac, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500, 1058 5000000)) 1059 BWN_DBGPRINTF(mac, "Radio 0x2057 rccal timeout\n"); 1060 /* 35..70 */ 1061 DELAY(70); 1062 BWN_RF_WRITE(mac, R2057_RCCAL_START_R1_Q1_P1, 0x15); 1063 /* 70..140 */ 1064 DELAY(140); 1065 1066 /* Setup cal */ 1067 if (special) { 1068 BWN_RF_WRITE(mac, R2057_RCCAL_MASTER, 0x73); 1069 BWN_RF_WRITE(mac, R2057_RCCAL_X1, 0x28); 1070 BWN_RF_WRITE(mac, R2057_RCCAL_TRC0, 0xB0); 1071 } else { 1072 BWN_RF_WRITE(mac, R2057v7_RCCAL_MASTER, 0x73); 1073 BWN_RF_WRITE(mac, R2057_RCCAL_X1, 0x6E); 1074 BWN_RF_WRITE(mac, R2057_RCCAL_TRC0, 0x99); 1075 } 1076 1077 /* Start, wait, stop */ 1078 /* 35..70 */ 1079 DELAY(70); 1080 BWN_RF_WRITE(mac, R2057_RCCAL_START_R1_Q1_P1, 0x55); 1081 /* 70..140 */ 1082 DELAY(140); 1083 if (!bwn_radio_wait_value(mac, R2057_RCCAL_DONE_OSCCAP, 2, 2, 500, 1084 5000000)) { 1085 BWN_ERRPRINTF(mac->mac_sc, "Radio 0x2057 rcal timeout\n"); 1086 return 0; 1087 } 1088 tmp = BWN_RF_READ(mac, R2057_RCCAL_DONE_OSCCAP); 1089 /* 35..70 */ 1090 DELAY(70); 1091 BWN_RF_WRITE(mac, R2057_RCCAL_START_R1_Q1_P1, 0x15); 1092 /* 70..140 */ 1093 DELAY(140); 1094 1095 if (special) 1096 BWN_RF_MASK(mac, R2057_RCCAL_MASTER, ~0x1); 1097 else 1098 BWN_RF_MASK(mac, R2057v7_RCCAL_MASTER, ~0x1); 1099 1100 return tmp; 1101} 1102 1103static void bwn_radio_2057_init_pre(struct bwn_mac *mac) 1104{ 1105 BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, ~BWN_NPHY_RFCTL_CMD_CHIP0PU); 1106 /* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */ 1107 BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, BWN_NPHY_RFCTL_CMD_OEPORFORCE); 1108 BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, ~BWN_NPHY_RFCTL_CMD_OEPORFORCE); 1109 BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, BWN_NPHY_RFCTL_CMD_CHIP0PU); 1110} 1111 1112static void bwn_radio_2057_init_post(struct bwn_mac *mac) 1113{ 1114 BWN_RF_SET(mac, R2057_XTALPUOVR_PINCTRL, 0x1); 1115 1116 if (0) /* FIXME: Is this BCM43217 specific? */ 1117 BWN_RF_SET(mac, R2057_XTALPUOVR_PINCTRL, 0x2); 1118 1119 BWN_RF_SET(mac, R2057_RFPLL_MISC_CAL_RESETN, 0x78); 1120 BWN_RF_SET(mac, R2057_XTAL_CONFIG2, 0x80); 1121 DELAY(2000); 1122 BWN_RF_MASK(mac, R2057_RFPLL_MISC_CAL_RESETN, ~0x78); 1123 BWN_RF_MASK(mac, R2057_XTAL_CONFIG2, ~0x80); 1124 1125 if (mac->mac_phy.phy_do_full_init) { 1126 bwn_radio_2057_rcal(mac); 1127 bwn_radio_2057_rccal(mac); 1128 } 1129 BWN_RF_MASK(mac, R2057_RFPLL_MASTER, ~0x8); 1130} 1131 1132/* http://bcm-v4.sipsolutions.net/802.11/Radio/2057/Init */ 1133static void bwn_radio_2057_init(struct bwn_mac *mac) 1134{ 1135 bwn_radio_2057_init_pre(mac); 1136 r2057_upload_inittabs(mac); 1137 bwn_radio_2057_init_post(mac); 1138} 1139 1140/************************************************** 1141 * Radio 0x2056 1142 **************************************************/ 1143 1144static void bwn_chantab_radio_2056_upload(struct bwn_mac *mac, 1145 const struct bwn_nphy_channeltab_entry_rev3 *e) 1146{ 1147 BWN_RF_WRITE(mac, B2056_SYN_PLL_VCOCAL1, e->radio_syn_pll_vcocal1); 1148 BWN_RF_WRITE(mac, B2056_SYN_PLL_VCOCAL2, e->radio_syn_pll_vcocal2); 1149 BWN_RF_WRITE(mac, B2056_SYN_PLL_REFDIV, e->radio_syn_pll_refdiv); 1150 BWN_RF_WRITE(mac, B2056_SYN_PLL_MMD2, e->radio_syn_pll_mmd2); 1151 BWN_RF_WRITE(mac, B2056_SYN_PLL_MMD1, e->radio_syn_pll_mmd1); 1152 BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER1, 1153 e->radio_syn_pll_loopfilter1); 1154 BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER2, 1155 e->radio_syn_pll_loopfilter2); 1156 BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER3, 1157 e->radio_syn_pll_loopfilter3); 1158 BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER4, 1159 e->radio_syn_pll_loopfilter4); 1160 BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER5, 1161 e->radio_syn_pll_loopfilter5); 1162 BWN_RF_WRITE(mac, B2056_SYN_RESERVED_ADDR27, 1163 e->radio_syn_reserved_addr27); 1164 BWN_RF_WRITE(mac, B2056_SYN_RESERVED_ADDR28, 1165 e->radio_syn_reserved_addr28); 1166 BWN_RF_WRITE(mac, B2056_SYN_RESERVED_ADDR29, 1167 e->radio_syn_reserved_addr29); 1168 BWN_RF_WRITE(mac, B2056_SYN_LOGEN_VCOBUF1, 1169 e->radio_syn_logen_vcobuf1); 1170 BWN_RF_WRITE(mac, B2056_SYN_LOGEN_MIXER2, e->radio_syn_logen_mixer2); 1171 BWN_RF_WRITE(mac, B2056_SYN_LOGEN_BUF3, e->radio_syn_logen_buf3); 1172 BWN_RF_WRITE(mac, B2056_SYN_LOGEN_BUF4, e->radio_syn_logen_buf4); 1173 1174 BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_LNAA_TUNE, 1175 e->radio_rx0_lnaa_tune); 1176 BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_LNAG_TUNE, 1177 e->radio_rx0_lnag_tune); 1178 1179 BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_INTPAA_BOOST_TUNE, 1180 e->radio_tx0_intpaa_boost_tune); 1181 BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_INTPAG_BOOST_TUNE, 1182 e->radio_tx0_intpag_boost_tune); 1183 BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_PADA_BOOST_TUNE, 1184 e->radio_tx0_pada_boost_tune); 1185 BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_PADG_BOOST_TUNE, 1186 e->radio_tx0_padg_boost_tune); 1187 BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_PGAA_BOOST_TUNE, 1188 e->radio_tx0_pgaa_boost_tune); 1189 BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_PGAG_BOOST_TUNE, 1190 e->radio_tx0_pgag_boost_tune); 1191 BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_MIXA_BOOST_TUNE, 1192 e->radio_tx0_mixa_boost_tune); 1193 BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_MIXG_BOOST_TUNE, 1194 e->radio_tx0_mixg_boost_tune); 1195 1196 BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_LNAA_TUNE, 1197 e->radio_rx1_lnaa_tune); 1198 BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_LNAG_TUNE, 1199 e->radio_rx1_lnag_tune); 1200 1201 BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_INTPAA_BOOST_TUNE, 1202 e->radio_tx1_intpaa_boost_tune); 1203 BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_INTPAG_BOOST_TUNE, 1204 e->radio_tx1_intpag_boost_tune); 1205 BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_PADA_BOOST_TUNE, 1206 e->radio_tx1_pada_boost_tune); 1207 BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_PADG_BOOST_TUNE, 1208 e->radio_tx1_padg_boost_tune); 1209 BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_PGAA_BOOST_TUNE, 1210 e->radio_tx1_pgaa_boost_tune); 1211 BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_PGAG_BOOST_TUNE, 1212 e->radio_tx1_pgag_boost_tune); 1213 BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_MIXA_BOOST_TUNE, 1214 e->radio_tx1_mixa_boost_tune); 1215 BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_MIXG_BOOST_TUNE, 1216 e->radio_tx1_mixg_boost_tune); 1217} 1218 1219/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2056Setup */ 1220static void bwn_radio_2056_setup(struct bwn_mac *mac, 1221 const struct bwn_nphy_channeltab_entry_rev3 *e) 1222{ 1223 struct bwn_softc *sc = mac->mac_sc; 1224 bwn_band_t band = bwn_current_band(mac); 1225 uint16_t offset; 1226 uint8_t i; 1227 uint16_t bias, cbias; 1228 uint16_t pag_boost, padg_boost, pgag_boost, mixg_boost; 1229 uint16_t paa_boost, pada_boost, pgaa_boost, mixa_boost; 1230 bool is_pkg_fab_smic; 1231 1232 DPRINTF(mac->mac_sc, BWN_DEBUG_RF, "%s: called\n", __func__); 1233 1234 if (mac->mac_phy.rev < 3) { 1235 BWN_ERRPRINTF(mac->mac_sc, "%s: phy rev %d out of range\n", 1236 __func__, 1237 mac->mac_phy.rev); 1238 } 1239 1240 is_pkg_fab_smic = 1241 ((sc->sc_cid.chip_id == BHND_CHIPID_BCM43224 || 1242 sc->sc_cid.chip_id == BHND_CHIPID_BCM43225 || 1243 sc->sc_cid.chip_id == BHND_CHIPID_BCM43421) && 1244 sc->sc_cid.chip_pkg == BHND_PKGID_BCM43224_FAB_SMIC); 1245 1246 bwn_chantab_radio_2056_upload(mac, e); 1247 b2056_upload_syn_pll_cp2(mac, band == BWN_BAND_5G); 1248 1249 if (sc->sc_board_info.board_flags2 & BHND_BFL2_GPLL_WAR && 1250 bwn_current_band(mac) == BWN_BAND_2G) { 1251 BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER1, 0x1F); 1252 BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER2, 0x1F); 1253 if (sc->sc_cid.chip_id == BHND_CHIPID_BCM4716 || 1254 sc->sc_cid.chip_id == BHND_CHIPID_BCM47162) { 1255 BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER4, 0x14); 1256 BWN_RF_WRITE(mac, B2056_SYN_PLL_CP2, 0); 1257 } else { 1258 BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER4, 0x0B); 1259 BWN_RF_WRITE(mac, B2056_SYN_PLL_CP2, 0x14); 1260 } 1261 } 1262 if (sc->sc_board_info.board_flags2 & BHND_BFL2_GPLL_WAR && 1263 bwn_current_band(mac) == BWN_BAND_2G) { 1264 BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER1, 0x1f); 1265 BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER2, 0x1f); 1266 BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER4, 0x0b); 1267 BWN_RF_WRITE(mac, B2056_SYN_PLL_CP2, 0x20); 1268 } 1269 if (sc->sc_board_info.board_flags2 & BHND_BFL2_APLL_WAR && 1270 bwn_current_band(mac) == BWN_BAND_5G) { 1271 BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER1, 0x1F); 1272 BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER2, 0x1F); 1273 BWN_RF_WRITE(mac, B2056_SYN_PLL_LOOPFILTER4, 0x05); 1274 BWN_RF_WRITE(mac, B2056_SYN_PLL_CP2, 0x0C); 1275 } 1276 1277 if (mac->mac_phy.phy_n->ipa2g_on && band == BWN_BAND_2G) { 1278 for (i = 0; i < 2; i++) { 1279 offset = i ? B2056_TX1 : B2056_TX0; 1280 if (mac->mac_phy.rev >= 5) { 1281 BWN_RF_WRITE(mac, 1282 offset | B2056_TX_PADG_IDAC, 0xcc); 1283 1284 if (sc->sc_cid.chip_id == BHND_CHIPID_BCM4716 || 1285 sc->sc_cid.chip_id == BHND_CHIPID_BCM47162) { 1286 bias = 0x40; 1287 cbias = 0x45; 1288 pag_boost = 0x5; 1289 pgag_boost = 0x33; 1290 mixg_boost = 0x55; 1291 } else { 1292 bias = 0x25; 1293 cbias = 0x20; 1294 if (is_pkg_fab_smic) { 1295 bias = 0x2a; 1296 cbias = 0x38; 1297 } 1298 pag_boost = 0x4; 1299 pgag_boost = 0x03; 1300 mixg_boost = 0x65; 1301 } 1302 padg_boost = 0x77; 1303 1304 BWN_RF_WRITE(mac, 1305 offset | B2056_TX_INTPAG_IMAIN_STAT, 1306 bias); 1307 BWN_RF_WRITE(mac, 1308 offset | B2056_TX_INTPAG_IAUX_STAT, 1309 bias); 1310 BWN_RF_WRITE(mac, 1311 offset | B2056_TX_INTPAG_CASCBIAS, 1312 cbias); 1313 BWN_RF_WRITE(mac, 1314 offset | B2056_TX_INTPAG_BOOST_TUNE, 1315 pag_boost); 1316 BWN_RF_WRITE(mac, 1317 offset | B2056_TX_PGAG_BOOST_TUNE, 1318 pgag_boost); 1319 BWN_RF_WRITE(mac, 1320 offset | B2056_TX_PADG_BOOST_TUNE, 1321 padg_boost); 1322 BWN_RF_WRITE(mac, 1323 offset | B2056_TX_MIXG_BOOST_TUNE, 1324 mixg_boost); 1325 } else { 1326 bias = bwn_is_40mhz(mac) ? 0x40 : 0x20; 1327 BWN_RF_WRITE(mac, 1328 offset | B2056_TX_INTPAG_IMAIN_STAT, 1329 bias); 1330 BWN_RF_WRITE(mac, 1331 offset | B2056_TX_INTPAG_IAUX_STAT, 1332 bias); 1333 BWN_RF_WRITE(mac, 1334 offset | B2056_TX_INTPAG_CASCBIAS, 1335 0x30); 1336 } 1337 BWN_RF_WRITE(mac, offset | B2056_TX_PA_SPARE1, 0xee); 1338 } 1339 } else if (mac->mac_phy.phy_n->ipa5g_on && band == BWN_BAND_5G) { 1340 uint16_t freq = bwn_get_centre_freq(mac); 1341 /* XXX 5g low/med/high? */ 1342 if (freq < 5100) { 1343 paa_boost = 0xA; 1344 pada_boost = 0x77; 1345 pgaa_boost = 0xF; 1346 mixa_boost = 0xF; 1347 } else if (freq < 5340) { 1348 paa_boost = 0x8; 1349 pada_boost = 0x77; 1350 pgaa_boost = 0xFB; 1351 mixa_boost = 0xF; 1352 } else if (freq < 5650) { 1353 paa_boost = 0x0; 1354 pada_boost = 0x77; 1355 pgaa_boost = 0xB; 1356 mixa_boost = 0xF; 1357 } else { 1358 paa_boost = 0x0; 1359 pada_boost = 0x77; 1360 if (freq != 5825) 1361 pgaa_boost = -(freq - 18) / 36 + 168; 1362 else 1363 pgaa_boost = 6; 1364 mixa_boost = 0xF; 1365 } 1366 1367 cbias = is_pkg_fab_smic ? 0x35 : 0x30; 1368 1369 for (i = 0; i < 2; i++) { 1370 offset = i ? B2056_TX1 : B2056_TX0; 1371 1372 BWN_RF_WRITE(mac, 1373 offset | B2056_TX_INTPAA_BOOST_TUNE, paa_boost); 1374 BWN_RF_WRITE(mac, 1375 offset | B2056_TX_PADA_BOOST_TUNE, pada_boost); 1376 BWN_RF_WRITE(mac, 1377 offset | B2056_TX_PGAA_BOOST_TUNE, pgaa_boost); 1378 BWN_RF_WRITE(mac, 1379 offset | B2056_TX_MIXA_BOOST_TUNE, mixa_boost); 1380 BWN_RF_WRITE(mac, 1381 offset | B2056_TX_TXSPARE1, 0x30); 1382 BWN_RF_WRITE(mac, 1383 offset | B2056_TX_PA_SPARE2, 0xee); 1384 BWN_RF_WRITE(mac, 1385 offset | B2056_TX_PADA_CASCBIAS, 0x03); 1386 BWN_RF_WRITE(mac, 1387 offset | B2056_TX_INTPAA_IAUX_STAT, 0x30); 1388 BWN_RF_WRITE(mac, 1389 offset | B2056_TX_INTPAA_IMAIN_STAT, 0x30); 1390 BWN_RF_WRITE(mac, 1391 offset | B2056_TX_INTPAA_CASCBIAS, cbias); 1392 } 1393 } 1394 1395 DELAY(50); 1396 /* VCO calibration */ 1397 BWN_RF_WRITE(mac, B2056_SYN_PLL_VCOCAL12, 0x00); 1398 BWN_RF_WRITE(mac, B2056_TX_INTPAA_PA_MISC, 0x38); 1399 BWN_RF_WRITE(mac, B2056_TX_INTPAA_PA_MISC, 0x18); 1400 BWN_RF_WRITE(mac, B2056_TX_INTPAA_PA_MISC, 0x38); 1401 BWN_RF_WRITE(mac, B2056_TX_INTPAA_PA_MISC, 0x39); 1402 DELAY(300); 1403} 1404 1405static uint8_t bwn_radio_2056_rcal(struct bwn_mac *mac) 1406{ 1407 struct bwn_phy *phy = &mac->mac_phy; 1408 uint16_t mast2, tmp; 1409 1410 if (phy->rev != 3) 1411 return 0; 1412 DPRINTF(mac->mac_sc, BWN_DEBUG_RF, "%s: called\n", __func__); 1413 1414 mast2 = BWN_RF_READ(mac, B2056_SYN_PLL_MAST2); 1415 BWN_RF_WRITE(mac, B2056_SYN_PLL_MAST2, mast2 | 0x7); 1416 1417 DELAY(10); 1418 BWN_RF_WRITE(mac, B2056_SYN_RCAL_MASTER, 0x01); 1419 DELAY(10); 1420 BWN_RF_WRITE(mac, B2056_SYN_RCAL_MASTER, 0x09); 1421 1422 if (!bwn_radio_wait_value(mac, B2056_SYN_RCAL_CODE_OUT, 0x80, 0x80, 100, 1423 1000000)) { 1424 BWN_ERRPRINTF(mac->mac_sc, "Radio recalibration timeout\n"); 1425 return 0; 1426 } 1427 1428 BWN_RF_WRITE(mac, B2056_SYN_RCAL_MASTER, 0x01); 1429 tmp = BWN_RF_READ(mac, B2056_SYN_RCAL_CODE_OUT); 1430 BWN_RF_WRITE(mac, B2056_SYN_RCAL_MASTER, 0x00); 1431 1432 BWN_RF_WRITE(mac, B2056_SYN_PLL_MAST2, mast2); 1433 1434 return tmp & 0x1f; 1435} 1436 1437static void bwn_radio_init2056_pre(struct bwn_mac *mac) 1438{ 1439 DPRINTF(mac->mac_sc, BWN_DEBUG_RF, "%s: called\n", __func__); 1440 1441 BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, 1442 ~BWN_NPHY_RFCTL_CMD_CHIP0PU); 1443 /* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */ 1444 BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, 1445 BWN_NPHY_RFCTL_CMD_OEPORFORCE); 1446 BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, 1447 ~BWN_NPHY_RFCTL_CMD_OEPORFORCE); 1448 BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, 1449 BWN_NPHY_RFCTL_CMD_CHIP0PU); 1450} 1451 1452static void bwn_radio_init2056_post(struct bwn_mac *mac) 1453{ 1454 DPRINTF(mac->mac_sc, BWN_DEBUG_RF, "%s: called\n", __func__); 1455 1456 BWN_RF_SET(mac, B2056_SYN_COM_CTRL, 0xB); 1457 BWN_RF_SET(mac, B2056_SYN_COM_PU, 0x2); 1458 BWN_RF_SET(mac, B2056_SYN_COM_RESET, 0x2); 1459 DELAY(1000); 1460 BWN_RF_MASK(mac, B2056_SYN_COM_RESET, ~0x2); 1461 BWN_RF_MASK(mac, B2056_SYN_PLL_MAST2, ~0xFC); 1462 BWN_RF_MASK(mac, B2056_SYN_RCCAL_CTRL0, ~0x1); 1463 if (mac->mac_phy.phy_do_full_init) 1464 bwn_radio_2056_rcal(mac); 1465} 1466 1467/* 1468 * Initialize a Broadcom 2056 N-radio 1469 * http://bcm-v4.sipsolutions.net/802.11/Radio/2056/Init 1470 */ 1471static void bwn_radio_init2056(struct bwn_mac *mac) 1472{ 1473 DPRINTF(mac->mac_sc, BWN_DEBUG_RF, "%s: called\n", __func__); 1474 1475 bwn_radio_init2056_pre(mac); 1476 b2056_upload_inittabs(mac, 0, 0); 1477 bwn_radio_init2056_post(mac); 1478} 1479 1480/************************************************** 1481 * Radio 0x2055 1482 **************************************************/ 1483 1484static void bwn_chantab_radio_upload(struct bwn_mac *mac, 1485 const struct bwn_nphy_channeltab_entry_rev2 *e) 1486{ 1487 BWN_RF_WRITE(mac, B2055_PLL_REF, e->radio_pll_ref); 1488 BWN_RF_WRITE(mac, B2055_RF_PLLMOD0, e->radio_rf_pllmod0); 1489 BWN_RF_WRITE(mac, B2055_RF_PLLMOD1, e->radio_rf_pllmod1); 1490 BWN_RF_WRITE(mac, B2055_VCO_CAPTAIL, e->radio_vco_captail); 1491 BWN_READ_4(mac, BWN_MACCTL); /* flush writes */ 1492 1493 BWN_RF_WRITE(mac, B2055_VCO_CAL1, e->radio_vco_cal1); 1494 BWN_RF_WRITE(mac, B2055_VCO_CAL2, e->radio_vco_cal2); 1495 BWN_RF_WRITE(mac, B2055_PLL_LFC1, e->radio_pll_lfc1); 1496 BWN_RF_WRITE(mac, B2055_PLL_LFR1, e->radio_pll_lfr1); 1497 BWN_READ_4(mac, BWN_MACCTL); /* flush writes */ 1498 1499 BWN_RF_WRITE(mac, B2055_PLL_LFC2, e->radio_pll_lfc2); 1500 BWN_RF_WRITE(mac, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf); 1501 BWN_RF_WRITE(mac, B2055_LGEN_TUNE1, e->radio_lgen_tune1); 1502 BWN_RF_WRITE(mac, B2055_LGEN_TUNE2, e->radio_lgen_tune2); 1503 BWN_READ_4(mac, BWN_MACCTL); /* flush writes */ 1504 1505 BWN_RF_WRITE(mac, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune); 1506 BWN_RF_WRITE(mac, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune); 1507 BWN_RF_WRITE(mac, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1); 1508 BWN_RF_WRITE(mac, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn); 1509 BWN_READ_4(mac, BWN_MACCTL); /* flush writes */ 1510 1511 BWN_RF_WRITE(mac, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim); 1512 BWN_RF_WRITE(mac, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune); 1513 BWN_RF_WRITE(mac, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune); 1514 BWN_RF_WRITE(mac, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1); 1515 BWN_READ_4(mac, BWN_MACCTL); /* flush writes */ 1516 1517 BWN_RF_WRITE(mac, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn); 1518 BWN_RF_WRITE(mac, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim); 1519} 1520 1521/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */ 1522static void bwn_radio_2055_setup(struct bwn_mac *mac, 1523 const struct bwn_nphy_channeltab_entry_rev2 *e) 1524{ 1525 1526 if (mac->mac_phy.rev >= 3) { 1527 BWN_ERRPRINTF(mac->mac_sc, "%s: phy rev %d out of range\n", 1528 __func__, 1529 mac->mac_phy.rev); 1530 } 1531 1532 DPRINTF(mac->mac_sc, BWN_DEBUG_RF, "%s: called\n", __func__); 1533 1534 bwn_chantab_radio_upload(mac, e); 1535 DELAY(50); 1536 BWN_RF_WRITE(mac, B2055_VCO_CAL10, 0x05); 1537 BWN_RF_WRITE(mac, B2055_VCO_CAL10, 0x45); 1538 BWN_READ_4(mac, BWN_MACCTL); /* flush writes */ 1539 BWN_RF_WRITE(mac, B2055_VCO_CAL10, 0x65); 1540 DELAY(300); 1541} 1542 1543static void bwn_radio_init2055_pre(struct bwn_mac *mac) 1544{ 1545 BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, 1546 ~BWN_NPHY_RFCTL_CMD_PORFORCE); 1547 BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, 1548 BWN_NPHY_RFCTL_CMD_CHIP0PU | 1549 BWN_NPHY_RFCTL_CMD_OEPORFORCE); 1550 BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, 1551 BWN_NPHY_RFCTL_CMD_PORFORCE); 1552} 1553 1554static void bwn_radio_init2055_post(struct bwn_mac *mac) 1555{ 1556 struct bwn_softc *sc = mac->mac_sc; 1557 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 1558 bool workaround = false; 1559 1560 if (bhnd_get_hwrev(sc->sc_dev) < 4) 1561 workaround = 1562 (sc->sc_board_info.board_vendor != PCI_VENDOR_BROADCOM) 1563 && (sc->sc_board_info.board_type == BHND_BOARD_BCM4321CB2) 1564 && (sc->sc_board_info.board_rev >= 0x41); 1565 else 1566 workaround = 1567 !(sc->sc_board_info.board_flags2 & BHND_BFL2_RXBB_INT_REG_DIS); 1568 1569 BWN_RF_MASK(mac, B2055_MASTER1, 0xFFF3); 1570 if (workaround) { 1571 BWN_RF_MASK(mac, B2055_C1_RX_BB_REG, 0x7F); 1572 BWN_RF_MASK(mac, B2055_C2_RX_BB_REG, 0x7F); 1573 } 1574 BWN_RF_SETMASK(mac, B2055_RRCCAL_NOPTSEL, 0xFFC0, 0x2C); 1575 BWN_RF_WRITE(mac, B2055_CAL_MISC, 0x3C); 1576 BWN_RF_MASK(mac, B2055_CAL_MISC, 0xFFBE); 1577 BWN_RF_SET(mac, B2055_CAL_LPOCTL, 0x80); 1578 BWN_RF_SET(mac, B2055_CAL_MISC, 0x1); 1579 DELAY(1000); 1580 BWN_RF_SET(mac, B2055_CAL_MISC, 0x40); 1581 if (!bwn_radio_wait_value(mac, B2055_CAL_COUT2, 0x80, 0x80, 10, 2000)) 1582 BWN_ERRPRINTF(mac->mac_sc, "radio post init timeout\n"); 1583 BWN_RF_MASK(mac, B2055_CAL_LPOCTL, 0xFF7F); 1584 bwn_switch_channel(mac, bwn_get_chan(mac)); 1585 BWN_RF_WRITE(mac, B2055_C1_RX_BB_LPF, 0x9); 1586 BWN_RF_WRITE(mac, B2055_C2_RX_BB_LPF, 0x9); 1587 BWN_RF_WRITE(mac, B2055_C1_RX_BB_MIDACHP, 0x83); 1588 BWN_RF_WRITE(mac, B2055_C2_RX_BB_MIDACHP, 0x83); 1589 BWN_RF_SETMASK(mac, B2055_C1_LNA_GAINBST, 0xFFF8, 0x6); 1590 BWN_RF_SETMASK(mac, B2055_C2_LNA_GAINBST, 0xFFF8, 0x6); 1591 if (!nphy->gain_boost) { 1592 BWN_RF_SET(mac, B2055_C1_RX_RFSPC1, 0x2); 1593 BWN_RF_SET(mac, B2055_C2_RX_RFSPC1, 0x2); 1594 } else { 1595 BWN_RF_MASK(mac, B2055_C1_RX_RFSPC1, 0xFFFD); 1596 BWN_RF_MASK(mac, B2055_C2_RX_RFSPC1, 0xFFFD); 1597 } 1598 DELAY(2); 1599} 1600 1601/* 1602 * Initialize a Broadcom 2055 N-radio 1603 * http://bcm-v4.sipsolutions.net/802.11/Radio/2055/Init 1604 */ 1605static void bwn_radio_init2055(struct bwn_mac *mac) 1606{ 1607 bwn_radio_init2055_pre(mac); 1608 if (mac->mac_status < BWN_MAC_STATUS_INITED) { 1609 /* Follow wl, not specs. Do not force uploading all regs */ 1610 b2055_upload_inittab(mac, 0, 0); 1611 } else { 1612 bool ghz5 = bwn_current_band(mac) == BWN_BAND_5G; 1613 b2055_upload_inittab(mac, ghz5, 0); 1614 } 1615 bwn_radio_init2055_post(mac); 1616} 1617 1618/************************************************** 1619 * Samples 1620 **************************************************/ 1621 1622/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/LoadSampleTable */ 1623static int bwn_nphy_load_samples(struct bwn_mac *mac, 1624 struct bwn_c32 *samples, uint16_t len) { 1625 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 1626 uint16_t i; 1627 uint32_t *data; 1628 1629 data = malloc(len * sizeof(uint32_t), M_DEVBUF, M_NOWAIT | M_ZERO); 1630 if (!data) { 1631 BWN_ERRPRINTF(mac->mac_sc, "allocation for samples loading failed\n"); 1632 return -ENOMEM; 1633 } 1634 if (nphy->hang_avoid) 1635 bwn_nphy_stay_in_carrier_search(mac, 1); 1636 1637 for (i = 0; i < len; i++) { 1638 data[i] = (samples[i].i & 0x3FF << 10); 1639 data[i] |= samples[i].q & 0x3FF; 1640 } 1641 bwn_ntab_write_bulk(mac, BWN_NTAB32(17, 0), len, data); 1642 1643 free(data, M_DEVBUF); 1644 if (nphy->hang_avoid) 1645 bwn_nphy_stay_in_carrier_search(mac, 0); 1646 return 0; 1647} 1648 1649/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GenLoadSamples */ 1650static uint16_t bwn_nphy_gen_load_samples(struct bwn_mac *mac, uint32_t freq, uint16_t max, 1651 bool test) 1652{ 1653 int i; 1654 uint16_t bw, len, rot, angle; 1655 struct bwn_c32 *samples; 1656 1657 bw = bwn_is_40mhz(mac) ? 40 : 20; 1658 len = bw << 3; 1659 1660 if (test) { 1661 if (BWN_PHY_READ(mac, BWN_NPHY_BBCFG) & BWN_NPHY_BBCFG_RSTRX) 1662 bw = 82; 1663 else 1664 bw = 80; 1665 1666 if (bwn_is_40mhz(mac)) 1667 bw <<= 1; 1668 1669 len = bw << 1; 1670 } 1671 1672 samples = malloc(len * sizeof(struct bwn_c32), M_DEVBUF, M_NOWAIT | M_ZERO); 1673 if (!samples) { 1674 BWN_ERRPRINTF(mac->mac_sc, "allocation for samples generation failed\n"); 1675 return 0; 1676 } 1677 rot = (((freq * 36) / bw) << 16) / 100; 1678 angle = 0; 1679 1680 for (i = 0; i < len; i++) { 1681 samples[i] = bwn_cordic(angle); 1682 angle += rot; 1683 samples[i].q = CORDIC_CONVERT(samples[i].q * max); 1684 samples[i].i = CORDIC_CONVERT(samples[i].i * max); 1685 } 1686 1687 i = bwn_nphy_load_samples(mac, samples, len); 1688 free(samples, M_DEVBUF); 1689 return (i < 0) ? 0 : len; 1690} 1691 1692/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */ 1693static void bwn_nphy_run_samples(struct bwn_mac *mac, uint16_t samps, uint16_t loops, 1694 uint16_t wait, bool iqmode, bool dac_test, 1695 bool modify_bbmult) 1696{ 1697 struct bwn_phy *phy = &mac->mac_phy; 1698 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 1699 int i; 1700 uint16_t seq_mode; 1701 uint32_t tmp; 1702 1703 bwn_nphy_stay_in_carrier_search(mac, true); 1704 1705 if (phy->rev >= 7) { 1706 bool lpf_bw3, lpf_bw4; 1707 1708 lpf_bw3 = BWN_PHY_READ(mac, BWN_NPHY_REV7_RF_CTL_OVER3) & 0x80; 1709 lpf_bw4 = BWN_PHY_READ(mac, BWN_NPHY_REV7_RF_CTL_OVER4) & 0x80; 1710 1711 if (lpf_bw3 || lpf_bw4) { 1712 /* TODO */ 1713 } else { 1714 uint16_t value = bwn_nphy_read_lpf_ctl(mac, 0); 1715 if (phy->rev >= 19) 1716 bwn_nphy_rf_ctl_override_rev19(mac, 0x80, value, 1717 0, false, 1); 1718 else 1719 bwn_nphy_rf_ctl_override_rev7(mac, 0x80, value, 1720 0, false, 1); 1721 nphy->lpf_bw_overrode_for_sample_play = true; 1722 } 1723 } 1724 1725 if ((nphy->bb_mult_save & 0x80000000) == 0) { 1726 tmp = bwn_ntab_read(mac, BWN_NTAB16(15, 87)); 1727 nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000; 1728 } 1729 1730 if (modify_bbmult) { 1731 tmp = !bwn_is_40mhz(mac) ? 0x6464 : 0x4747; 1732 bwn_ntab_write(mac, BWN_NTAB16(15, 87), tmp); 1733 } 1734 1735 BWN_PHY_WRITE(mac, BWN_NPHY_SAMP_DEPCNT, (samps - 1)); 1736 1737 if (loops != 0xFFFF) 1738 BWN_PHY_WRITE(mac, BWN_NPHY_SAMP_LOOPCNT, (loops - 1)); 1739 else 1740 BWN_PHY_WRITE(mac, BWN_NPHY_SAMP_LOOPCNT, loops); 1741 1742 BWN_PHY_WRITE(mac, BWN_NPHY_SAMP_WAITCNT, wait); 1743 1744 seq_mode = BWN_PHY_READ(mac, BWN_NPHY_RFSEQMODE); 1745 1746 BWN_PHY_SET(mac, BWN_NPHY_RFSEQMODE, BWN_NPHY_RFSEQMODE_CAOVER); 1747 if (iqmode) { 1748 BWN_PHY_MASK(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0x7FFF); 1749 BWN_PHY_SET(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0x8000); 1750 } else { 1751 tmp = dac_test ? 5 : 1; 1752 BWN_PHY_WRITE(mac, BWN_NPHY_SAMP_CMD, tmp); 1753 } 1754 for (i = 0; i < 100; i++) { 1755 if (!(BWN_PHY_READ(mac, BWN_NPHY_RFSEQST) & 1)) { 1756 i = 0; 1757 break; 1758 } 1759 DELAY(10); 1760 } 1761 if (i) 1762 BWN_ERRPRINTF(mac->mac_sc, "run samples timeout\n"); 1763 1764 BWN_PHY_WRITE(mac, BWN_NPHY_RFSEQMODE, seq_mode); 1765 1766 bwn_nphy_stay_in_carrier_search(mac, false); 1767} 1768 1769/************************************************** 1770 * RSSI 1771 **************************************************/ 1772 1773/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */ 1774static void bwn_nphy_scale_offset_rssi(struct bwn_mac *mac, uint16_t scale, 1775 int8_t offset, uint8_t core, 1776 enum n_rail_type rail, 1777 enum n_rssi_type rssi_type) 1778{ 1779 uint16_t tmp; 1780 bool core1or5 = (core == 1) || (core == 5); 1781 bool core2or5 = (core == 2) || (core == 5); 1782 1783 offset = bwn_clamp_val(offset, -32, 31); 1784 tmp = ((scale & 0x3F) << 8) | (offset & 0x3F); 1785 1786 switch (rssi_type) { 1787 case N_RSSI_NB: 1788 if (core1or5 && rail == N_RAIL_I) 1789 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_Z, tmp); 1790 if (core1or5 && rail == N_RAIL_Q) 1791 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Z, tmp); 1792 if (core2or5 && rail == N_RAIL_I) 1793 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_Z, tmp); 1794 if (core2or5 && rail == N_RAIL_Q) 1795 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Z, tmp); 1796 break; 1797 case N_RSSI_W1: 1798 if (core1or5 && rail == N_RAIL_I) 1799 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_X, tmp); 1800 if (core1or5 && rail == N_RAIL_Q) 1801 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_X, tmp); 1802 if (core2or5 && rail == N_RAIL_I) 1803 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_X, tmp); 1804 if (core2or5 && rail == N_RAIL_Q) 1805 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_X, tmp); 1806 break; 1807 case N_RSSI_W2: 1808 if (core1or5 && rail == N_RAIL_I) 1809 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_Y, tmp); 1810 if (core1or5 && rail == N_RAIL_Q) 1811 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Y, tmp); 1812 if (core2or5 && rail == N_RAIL_I) 1813 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_Y, tmp); 1814 if (core2or5 && rail == N_RAIL_Q) 1815 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Y, tmp); 1816 break; 1817 case N_RSSI_TBD: 1818 if (core1or5 && rail == N_RAIL_I) 1819 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_TBD, tmp); 1820 if (core1or5 && rail == N_RAIL_Q) 1821 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_TBD, tmp); 1822 if (core2or5 && rail == N_RAIL_I) 1823 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_TBD, tmp); 1824 if (core2or5 && rail == N_RAIL_Q) 1825 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_TBD, tmp); 1826 break; 1827 case N_RSSI_IQ: 1828 if (core1or5 && rail == N_RAIL_I) 1829 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_PWRDET, tmp); 1830 if (core1or5 && rail == N_RAIL_Q) 1831 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_PWRDET, tmp); 1832 if (core2or5 && rail == N_RAIL_I) 1833 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_PWRDET, tmp); 1834 if (core2or5 && rail == N_RAIL_Q) 1835 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_PWRDET, tmp); 1836 break; 1837 case N_RSSI_TSSI_2G: 1838 if (core1or5) 1839 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_TSSI, tmp); 1840 if (core2or5) 1841 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_TSSI, tmp); 1842 break; 1843 case N_RSSI_TSSI_5G: 1844 if (core1or5) 1845 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_TSSI, tmp); 1846 if (core2or5) 1847 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_TSSI, tmp); 1848 break; 1849 } 1850} 1851 1852static void bwn_nphy_rssi_select_rev19(struct bwn_mac *mac, uint8_t code, 1853 enum n_rssi_type rssi_type) 1854{ 1855 /* TODO */ 1856} 1857 1858static void bwn_nphy_rev3_rssi_select(struct bwn_mac *mac, uint8_t code, 1859 enum n_rssi_type rssi_type) 1860{ 1861 uint8_t i; 1862 uint16_t reg, val; 1863 1864 if (code == 0) { 1865 BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER1, 0xFDFF); 1866 BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER, 0xFDFF); 1867 BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C1, 0xFCFF); 1868 BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C2, 0xFCFF); 1869 BWN_PHY_MASK(mac, BWN_NPHY_TXF_40CO_B1S0, 0xFFDF); 1870 BWN_PHY_MASK(mac, BWN_NPHY_TXF_40CO_B32S1, 0xFFDF); 1871 BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP1, 0xFFC3); 1872 BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP2, 0xFFC3); 1873 } else { 1874 for (i = 0; i < 2; i++) { 1875 if ((code == 1 && i == 1) || (code == 2 && !i)) 1876 continue; 1877 1878 reg = (i == 0) ? 1879 BWN_NPHY_AFECTL_OVER1 : BWN_NPHY_AFECTL_OVER; 1880 BWN_PHY_SETMASK(mac, reg, 0xFDFF, 0x0200); 1881 1882 if (rssi_type == N_RSSI_W1 || 1883 rssi_type == N_RSSI_W2 || 1884 rssi_type == N_RSSI_NB) { 1885 reg = (i == 0) ? 1886 BWN_NPHY_AFECTL_C1 : 1887 BWN_NPHY_AFECTL_C2; 1888 BWN_PHY_SETMASK(mac, reg, 0xFCFF, 0); 1889 1890 reg = (i == 0) ? 1891 BWN_NPHY_RFCTL_LUT_TRSW_UP1 : 1892 BWN_NPHY_RFCTL_LUT_TRSW_UP2; 1893 BWN_PHY_SETMASK(mac, reg, 0xFFC3, 0); 1894 1895 if (rssi_type == N_RSSI_W1) 1896 val = (bwn_current_band(mac) == BWN_BAND_5G) ? 4 : 8; 1897 else if (rssi_type == N_RSSI_W2) 1898 val = 16; 1899 else 1900 val = 32; 1901 BWN_PHY_SET(mac, reg, val); 1902 1903 reg = (i == 0) ? 1904 BWN_NPHY_TXF_40CO_B1S0 : 1905 BWN_NPHY_TXF_40CO_B32S1; 1906 BWN_PHY_SET(mac, reg, 0x0020); 1907 } else { 1908 if (rssi_type == N_RSSI_TBD) 1909 val = 0x0100; 1910 else if (rssi_type == N_RSSI_IQ) 1911 val = 0x0200; 1912 else 1913 val = 0x0300; 1914 1915 reg = (i == 0) ? 1916 BWN_NPHY_AFECTL_C1 : 1917 BWN_NPHY_AFECTL_C2; 1918 1919 BWN_PHY_SETMASK(mac, reg, 0xFCFF, val); 1920 BWN_PHY_SETMASK(mac, reg, 0xF3FF, val << 2); 1921 1922 if (rssi_type != N_RSSI_IQ && 1923 rssi_type != N_RSSI_TBD) { 1924 bwn_band_t band = 1925 bwn_current_band(mac); 1926 1927 if (mac->mac_phy.rev < 7) { 1928 if (bwn_nphy_ipa(mac)) 1929 val = (band == BWN_BAND_5G) ? 0xC : 0xE; 1930 else 1931 val = 0x11; 1932 reg = (i == 0) ? B2056_TX0 : B2056_TX1; 1933 reg |= B2056_TX_TX_SSI_MUX; 1934 BWN_RF_WRITE(mac, reg, val); 1935 } 1936 1937 reg = (i == 0) ? 1938 BWN_NPHY_AFECTL_OVER1 : 1939 BWN_NPHY_AFECTL_OVER; 1940 BWN_PHY_SET(mac, reg, 0x0200); 1941 } 1942 } 1943 } 1944 } 1945} 1946 1947static void bwn_nphy_rev2_rssi_select(struct bwn_mac *mac, uint8_t code, 1948 enum n_rssi_type rssi_type) 1949{ 1950 uint16_t val; 1951 bool rssi_w1_w2_nb = false; 1952 1953 switch (rssi_type) { 1954 case N_RSSI_W1: 1955 case N_RSSI_W2: 1956 case N_RSSI_NB: 1957 val = 0; 1958 rssi_w1_w2_nb = true; 1959 break; 1960 case N_RSSI_TBD: 1961 val = 1; 1962 break; 1963 case N_RSSI_IQ: 1964 val = 2; 1965 break; 1966 default: 1967 val = 3; 1968 } 1969 1970 val = (val << 12) | (val << 14); 1971 BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C1, 0x0FFF, val); 1972 BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C2, 0x0FFF, val); 1973 1974 if (rssi_w1_w2_nb) { 1975 BWN_PHY_SETMASK(mac, BWN_NPHY_RFCTL_RSSIO1, 0xFFCF, 1976 (rssi_type + 1) << 4); 1977 BWN_PHY_SETMASK(mac, BWN_NPHY_RFCTL_RSSIO2, 0xFFCF, 1978 (rssi_type + 1) << 4); 1979 } 1980 1981 if (code == 0) { 1982 BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER, ~0x3000); 1983 if (rssi_w1_w2_nb) { 1984 BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, 1985 ~(BWN_NPHY_RFCTL_CMD_RXEN | 1986 BWN_NPHY_RFCTL_CMD_CORESEL)); 1987 BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER, 1988 ~(0x1 << 12 | 1989 0x1 << 5 | 1990 0x1 << 1 | 1991 0x1)); 1992 BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, 1993 ~BWN_NPHY_RFCTL_CMD_START); 1994 DELAY(20); 1995 BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER, ~0x1); 1996 } 1997 } else { 1998 BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x3000); 1999 if (rssi_w1_w2_nb) { 2000 BWN_PHY_SETMASK(mac, BWN_NPHY_RFCTL_CMD, 2001 ~(BWN_NPHY_RFCTL_CMD_RXEN | 2002 BWN_NPHY_RFCTL_CMD_CORESEL), 2003 (BWN_NPHY_RFCTL_CMD_RXEN | 2004 code << BWN_NPHY_RFCTL_CMD_CORESEL_SHIFT)); 2005 BWN_PHY_SET(mac, BWN_NPHY_RFCTL_OVER, 2006 (0x1 << 12 | 2007 0x1 << 5 | 2008 0x1 << 1 | 2009 0x1)); 2010 BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, 2011 BWN_NPHY_RFCTL_CMD_START); 2012 DELAY(20); 2013 BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER, ~0x1); 2014 } 2015 } 2016} 2017 2018/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */ 2019static void bwn_nphy_rssi_select(struct bwn_mac *mac, uint8_t code, 2020 enum n_rssi_type type) 2021{ 2022 if (mac->mac_phy.rev >= 19) 2023 bwn_nphy_rssi_select_rev19(mac, code, type); 2024 else if (mac->mac_phy.rev >= 3) 2025 bwn_nphy_rev3_rssi_select(mac, code, type); 2026 else 2027 bwn_nphy_rev2_rssi_select(mac, code, type); 2028} 2029 2030/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */ 2031static void bwn_nphy_set_rssi_2055_vcm(struct bwn_mac *mac, 2032 enum n_rssi_type rssi_type, uint8_t *buf) 2033{ 2034 int i; 2035 for (i = 0; i < 2; i++) { 2036 if (rssi_type == N_RSSI_NB) { 2037 if (i == 0) { 2038 BWN_RF_SETMASK(mac, B2055_C1_B0NB_RSSIVCM, 2039 0xFC, buf[0]); 2040 BWN_RF_SETMASK(mac, B2055_C1_RX_BB_RSSICTL5, 2041 0xFC, buf[1]); 2042 } else { 2043 BWN_RF_SETMASK(mac, B2055_C2_B0NB_RSSIVCM, 2044 0xFC, buf[2 * i]); 2045 BWN_RF_SETMASK(mac, B2055_C2_RX_BB_RSSICTL5, 2046 0xFC, buf[2 * i + 1]); 2047 } 2048 } else { 2049 if (i == 0) 2050 BWN_RF_SETMASK(mac, B2055_C1_RX_BB_RSSICTL5, 2051 0xF3, buf[0] << 2); 2052 else 2053 BWN_RF_SETMASK(mac, B2055_C2_RX_BB_RSSICTL5, 2054 0xF3, buf[2 * i + 1] << 2); 2055 } 2056 } 2057} 2058 2059/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */ 2060static int bwn_nphy_poll_rssi(struct bwn_mac *mac, enum n_rssi_type rssi_type, 2061 int32_t *buf, uint8_t nsamp) 2062{ 2063 int i; 2064 int out; 2065 uint16_t save_regs_phy[9]; 2066 uint16_t s[2]; 2067 2068 /* TODO: rev7+ is treated like rev3+, what about rev19+? */ 2069 2070 if (mac->mac_phy.rev >= 3) { 2071 save_regs_phy[0] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C1); 2072 save_regs_phy[1] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C2); 2073 save_regs_phy[2] = BWN_PHY_READ(mac, 2074 BWN_NPHY_RFCTL_LUT_TRSW_UP1); 2075 save_regs_phy[3] = BWN_PHY_READ(mac, 2076 BWN_NPHY_RFCTL_LUT_TRSW_UP2); 2077 save_regs_phy[4] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER1); 2078 save_regs_phy[5] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER); 2079 save_regs_phy[6] = BWN_PHY_READ(mac, BWN_NPHY_TXF_40CO_B1S0); 2080 save_regs_phy[7] = BWN_PHY_READ(mac, BWN_NPHY_TXF_40CO_B32S1); 2081 save_regs_phy[8] = 0; 2082 } else { 2083 save_regs_phy[0] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C1); 2084 save_regs_phy[1] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C2); 2085 save_regs_phy[2] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER); 2086 save_regs_phy[3] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_CMD); 2087 save_regs_phy[4] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_OVER); 2088 save_regs_phy[5] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_RSSIO1); 2089 save_regs_phy[6] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_RSSIO2); 2090 save_regs_phy[7] = 0; 2091 save_regs_phy[8] = 0; 2092 } 2093 2094 bwn_nphy_rssi_select(mac, 5, rssi_type); 2095 2096 if (mac->mac_phy.rev < 2) { 2097 save_regs_phy[8] = BWN_PHY_READ(mac, BWN_NPHY_GPIO_SEL); 2098 BWN_PHY_WRITE(mac, BWN_NPHY_GPIO_SEL, 5); 2099 } 2100 2101 for (i = 0; i < 4; i++) 2102 buf[i] = 0; 2103 2104 for (i = 0; i < nsamp; i++) { 2105 if (mac->mac_phy.rev < 2) { 2106 s[0] = BWN_PHY_READ(mac, BWN_NPHY_GPIO_LOOUT); 2107 s[1] = BWN_PHY_READ(mac, BWN_NPHY_GPIO_HIOUT); 2108 } else { 2109 s[0] = BWN_PHY_READ(mac, BWN_NPHY_RSSI1); 2110 s[1] = BWN_PHY_READ(mac, BWN_NPHY_RSSI2); 2111 } 2112 2113 buf[0] += ((int8_t)((s[0] & 0x3F) << 2)) >> 2; 2114 buf[1] += ((int8_t)(((s[0] >> 8) & 0x3F) << 2)) >> 2; 2115 buf[2] += ((int8_t)((s[1] & 0x3F) << 2)) >> 2; 2116 buf[3] += ((int8_t)(((s[1] >> 8) & 0x3F) << 2)) >> 2; 2117 } 2118 out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 | 2119 (buf[2] & 0xFF) << 8 | (buf[3] & 0xFF); 2120 2121 if (mac->mac_phy.rev < 2) 2122 BWN_PHY_WRITE(mac, BWN_NPHY_GPIO_SEL, save_regs_phy[8]); 2123 2124 if (mac->mac_phy.rev >= 3) { 2125 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, save_regs_phy[0]); 2126 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, save_regs_phy[1]); 2127 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP1, 2128 save_regs_phy[2]); 2129 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP2, 2130 save_regs_phy[3]); 2131 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, save_regs_phy[4]); 2132 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, save_regs_phy[5]); 2133 BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B1S0, save_regs_phy[6]); 2134 BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B32S1, save_regs_phy[7]); 2135 } else { 2136 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, save_regs_phy[0]); 2137 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, save_regs_phy[1]); 2138 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, save_regs_phy[2]); 2139 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_CMD, save_regs_phy[3]); 2140 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_OVER, save_regs_phy[4]); 2141 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_RSSIO1, save_regs_phy[5]); 2142 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_RSSIO2, save_regs_phy[6]); 2143 } 2144 2145 return out; 2146} 2147 2148/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */ 2149static void bwn_nphy_rev3_rssi_cal(struct bwn_mac *mac) 2150{ 2151 //struct bwn_phy *phy = &mac->mac_phy; 2152 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 2153 2154 uint16_t saved_regs_phy_rfctl[2]; 2155 uint16_t saved_regs_phy[22]; 2156 uint16_t regs_to_store_rev3[] = { 2157 BWN_NPHY_AFECTL_OVER1, BWN_NPHY_AFECTL_OVER, 2158 BWN_NPHY_AFECTL_C1, BWN_NPHY_AFECTL_C2, 2159 BWN_NPHY_TXF_40CO_B1S1, BWN_NPHY_RFCTL_OVER, 2160 BWN_NPHY_TXF_40CO_B1S0, BWN_NPHY_TXF_40CO_B32S1, 2161 BWN_NPHY_RFCTL_CMD, 2162 BWN_NPHY_RFCTL_LUT_TRSW_UP1, BWN_NPHY_RFCTL_LUT_TRSW_UP2, 2163 BWN_NPHY_RFCTL_RSSIO1, BWN_NPHY_RFCTL_RSSIO2 2164 }; 2165 uint16_t regs_to_store_rev7[] = { 2166 BWN_NPHY_AFECTL_OVER1, BWN_NPHY_AFECTL_OVER, 2167 BWN_NPHY_AFECTL_C1, BWN_NPHY_AFECTL_C2, 2168 BWN_NPHY_TXF_40CO_B1S1, BWN_NPHY_RFCTL_OVER, 2169 BWN_NPHY_REV7_RF_CTL_OVER3, BWN_NPHY_REV7_RF_CTL_OVER4, 2170 BWN_NPHY_REV7_RF_CTL_OVER5, BWN_NPHY_REV7_RF_CTL_OVER6, 2171 0x2ff, 2172 BWN_NPHY_TXF_40CO_B1S0, BWN_NPHY_TXF_40CO_B32S1, 2173 BWN_NPHY_RFCTL_CMD, 2174 BWN_NPHY_RFCTL_LUT_TRSW_UP1, BWN_NPHY_RFCTL_LUT_TRSW_UP2, 2175 BWN_NPHY_REV7_RF_CTL_MISC_REG3, BWN_NPHY_REV7_RF_CTL_MISC_REG4, 2176 BWN_NPHY_REV7_RF_CTL_MISC_REG5, BWN_NPHY_REV7_RF_CTL_MISC_REG6, 2177 BWN_NPHY_RFCTL_RSSIO1, BWN_NPHY_RFCTL_RSSIO2 2178 }; 2179 uint16_t *regs_to_store; 2180 int regs_amount; 2181 2182 uint16_t class; 2183 2184 uint16_t clip_state[2]; 2185 uint16_t clip_off[2] = { 0xFFFF, 0xFFFF }; 2186 2187 uint8_t vcm_final = 0; 2188 int32_t offset[4]; 2189 int32_t results[8][4] = { }; 2190 int32_t results_min[4] = { }; 2191 int32_t poll_results[4] = { }; 2192 2193 uint16_t *rssical_radio_regs = NULL; 2194 uint16_t *rssical_phy_regs = NULL; 2195 2196 uint16_t r; /* routing */ 2197 uint8_t rx_core_state; 2198 int core, i, j, vcm; 2199 2200 if (mac->mac_phy.rev >= 7) { 2201 regs_to_store = regs_to_store_rev7; 2202 regs_amount = nitems(regs_to_store_rev7); 2203 } else { 2204 regs_to_store = regs_to_store_rev3; 2205 regs_amount = nitems(regs_to_store_rev3); 2206 } 2207 KASSERT((regs_amount <= nitems(saved_regs_phy)), 2208 ("%s: reg_amount (%d) too large\n", 2209 __func__, 2210 regs_amount)); 2211 2212 class = bwn_nphy_classifier(mac, 0, 0); 2213 bwn_nphy_classifier(mac, 7, 4); 2214 bwn_nphy_read_clip_detection(mac, clip_state); 2215 bwn_nphy_write_clip_detection(mac, clip_off); 2216 2217 saved_regs_phy_rfctl[0] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC1); 2218 saved_regs_phy_rfctl[1] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC2); 2219 for (i = 0; i < regs_amount; i++) 2220 saved_regs_phy[i] = BWN_PHY_READ(mac, regs_to_store[i]); 2221 2222 bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_OFF, 0, 7); 2223 bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_TRSW, 1, 7); 2224 2225 if (mac->mac_phy.rev >= 7) { 2226 bwn_nphy_rf_ctl_override_one_to_many(mac, 2227 N_RF_CTL_OVER_CMD_RXRF_PU, 2228 0, 0, false); 2229 bwn_nphy_rf_ctl_override_one_to_many(mac, 2230 N_RF_CTL_OVER_CMD_RX_PU, 2231 1, 0, false); 2232 bwn_nphy_rf_ctl_override_rev7(mac, 0x80, 1, 0, false, 0); 2233 bwn_nphy_rf_ctl_override_rev7(mac, 0x40, 1, 0, false, 0); 2234 if (bwn_current_band(mac) == BWN_BAND_5G) { 2235 bwn_nphy_rf_ctl_override_rev7(mac, 0x20, 0, 0, false, 2236 0); 2237 bwn_nphy_rf_ctl_override_rev7(mac, 0x10, 1, 0, false, 2238 0); 2239 } else { 2240 bwn_nphy_rf_ctl_override_rev7(mac, 0x10, 0, 0, false, 2241 0); 2242 bwn_nphy_rf_ctl_override_rev7(mac, 0x20, 1, 0, false, 2243 0); 2244 } 2245 } else { 2246 bwn_nphy_rf_ctl_override(mac, 0x1, 0, 0, false); 2247 bwn_nphy_rf_ctl_override(mac, 0x2, 1, 0, false); 2248 bwn_nphy_rf_ctl_override(mac, 0x80, 1, 0, false); 2249 bwn_nphy_rf_ctl_override(mac, 0x40, 1, 0, false); 2250 if (bwn_current_band(mac) == BWN_BAND_5G) { 2251 bwn_nphy_rf_ctl_override(mac, 0x20, 0, 0, false); 2252 bwn_nphy_rf_ctl_override(mac, 0x10, 1, 0, false); 2253 } else { 2254 bwn_nphy_rf_ctl_override(mac, 0x10, 0, 0, false); 2255 bwn_nphy_rf_ctl_override(mac, 0x20, 1, 0, false); 2256 } 2257 } 2258 2259 rx_core_state = bwn_nphy_get_rx_core_state(mac); 2260 for (core = 0; core < 2; core++) { 2261 if (!(rx_core_state & (1 << core))) 2262 continue; 2263 r = core ? B2056_RX1 : B2056_RX0; 2264 bwn_nphy_scale_offset_rssi(mac, 0, 0, core + 1, N_RAIL_I, 2265 N_RSSI_NB); 2266 bwn_nphy_scale_offset_rssi(mac, 0, 0, core + 1, N_RAIL_Q, 2267 N_RSSI_NB); 2268 2269 /* Grab RSSI results for every possible VCM */ 2270 for (vcm = 0; vcm < 8; vcm++) { 2271 if (mac->mac_phy.rev >= 7) 2272 BWN_RF_SETMASK(mac, 2273 core ? R2057_NB_MASTER_CORE1 : 2274 R2057_NB_MASTER_CORE0, 2275 ~R2057_VCM_MASK, vcm); 2276 else 2277 BWN_RF_SETMASK(mac, r | B2056_RX_RSSI_MISC, 2278 0xE3, vcm << 2); 2279 bwn_nphy_poll_rssi(mac, N_RSSI_NB, results[vcm], 8); 2280 } 2281 2282 /* Find out which VCM got the best results */ 2283 for (i = 0; i < 4; i += 2) { 2284 int32_t currd; 2285 int32_t mind = 0x100000; 2286 int32_t minpoll = 249; 2287 uint8_t minvcm = 0; 2288 if (2 * core != i) 2289 continue; 2290 for (vcm = 0; vcm < 8; vcm++) { 2291 currd = results[vcm][i] * results[vcm][i] + 2292 results[vcm][i + 1] * results[vcm][i]; 2293 if (currd < mind) { 2294 mind = currd; 2295 minvcm = vcm; 2296 } 2297 if (results[vcm][i] < minpoll) 2298 minpoll = results[vcm][i]; 2299 } 2300 vcm_final = minvcm; 2301 results_min[i] = minpoll; 2302 } 2303 2304 /* Select the best VCM */ 2305 if (mac->mac_phy.rev >= 7) 2306 BWN_RF_SETMASK(mac, 2307 core ? R2057_NB_MASTER_CORE1 : 2308 R2057_NB_MASTER_CORE0, 2309 ~R2057_VCM_MASK, vcm); 2310 else 2311 BWN_RF_SETMASK(mac, r | B2056_RX_RSSI_MISC, 2312 0xE3, vcm_final << 2); 2313 2314 for (i = 0; i < 4; i++) { 2315 if (core != i / 2) 2316 continue; 2317 offset[i] = -results[vcm_final][i]; 2318 if (offset[i] < 0) 2319 offset[i] = -((abs(offset[i]) + 4) / 8); 2320 else 2321 offset[i] = (offset[i] + 4) / 8; 2322 if (results_min[i] == 248) 2323 offset[i] = -32; 2324 bwn_nphy_scale_offset_rssi(mac, 0, offset[i], 2325 (i / 2 == 0) ? 1 : 2, 2326 (i % 2 == 0) ? N_RAIL_I : N_RAIL_Q, 2327 N_RSSI_NB); 2328 } 2329 } 2330 2331 for (core = 0; core < 2; core++) { 2332 if (!(rx_core_state & (1 << core))) 2333 continue; 2334 for (i = 0; i < 2; i++) { 2335 bwn_nphy_scale_offset_rssi(mac, 0, 0, core + 1, 2336 N_RAIL_I, i); 2337 bwn_nphy_scale_offset_rssi(mac, 0, 0, core + 1, 2338 N_RAIL_Q, i); 2339 bwn_nphy_poll_rssi(mac, i, poll_results, 8); 2340 for (j = 0; j < 4; j++) { 2341 if (j / 2 == core) { 2342 offset[j] = 232 - poll_results[j]; 2343 if (offset[j] < 0) 2344 offset[j] = -(abs(offset[j] + 4) / 8); 2345 else 2346 offset[j] = (offset[j] + 4) / 8; 2347 bwn_nphy_scale_offset_rssi(mac, 0, 2348 offset[2 * core], core + 1, j % 2, i); 2349 } 2350 } 2351 } 2352 } 2353 2354 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, saved_regs_phy_rfctl[0]); 2355 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, saved_regs_phy_rfctl[1]); 2356 2357 bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX); 2358 2359 BWN_PHY_SET(mac, BWN_NPHY_TXF_40CO_B1S1, 0x1); 2360 BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, BWN_NPHY_RFCTL_CMD_START); 2361 BWN_PHY_MASK(mac, BWN_NPHY_TXF_40CO_B1S1, ~0x1); 2362 2363 BWN_PHY_SET(mac, BWN_NPHY_RFCTL_OVER, 0x1); 2364 BWN_PHY_SET(mac, BWN_NPHY_RFCTL_CMD, BWN_NPHY_RFCTL_CMD_RXTX); 2365 BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_OVER, ~0x1); 2366 2367 for (i = 0; i < regs_amount; i++) 2368 BWN_PHY_WRITE(mac, regs_to_store[i], saved_regs_phy[i]); 2369 2370 /* Store for future configuration */ 2371 if (bwn_current_band(mac) == BWN_BAND_2G) { 2372 rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G; 2373 rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G; 2374 } else { 2375 rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G; 2376 rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; 2377 } 2378 if (mac->mac_phy.rev >= 7) { 2379 rssical_radio_regs[0] = BWN_RF_READ(mac, 2380 R2057_NB_MASTER_CORE0); 2381 rssical_radio_regs[1] = BWN_RF_READ(mac, 2382 R2057_NB_MASTER_CORE1); 2383 } else { 2384 rssical_radio_regs[0] = BWN_RF_READ(mac, B2056_RX0 | 2385 B2056_RX_RSSI_MISC); 2386 rssical_radio_regs[1] = BWN_RF_READ(mac, B2056_RX1 | 2387 B2056_RX_RSSI_MISC); 2388 } 2389 rssical_phy_regs[0] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0I_RSSI_Z); 2390 rssical_phy_regs[1] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Z); 2391 rssical_phy_regs[2] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1I_RSSI_Z); 2392 rssical_phy_regs[3] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Z); 2393 rssical_phy_regs[4] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0I_RSSI_X); 2394 rssical_phy_regs[5] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0Q_RSSI_X); 2395 rssical_phy_regs[6] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1I_RSSI_X); 2396 rssical_phy_regs[7] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1Q_RSSI_X); 2397 rssical_phy_regs[8] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0I_RSSI_Y); 2398 rssical_phy_regs[9] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Y); 2399 rssical_phy_regs[10] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1I_RSSI_Y); 2400 rssical_phy_regs[11] = BWN_PHY_READ(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Y); 2401 2402 /* Remember for which channel we store configuration */ 2403 if (bwn_current_band(mac) == BWN_BAND_2G) 2404 nphy->rssical_chanspec_2G.center_freq = bwn_get_centre_freq(mac); 2405 else 2406 nphy->rssical_chanspec_5G.center_freq = bwn_get_centre_freq(mac); 2407 2408 /* End of calibration, restore configuration */ 2409 bwn_nphy_classifier(mac, 7, class); 2410 bwn_nphy_write_clip_detection(mac, clip_state); 2411} 2412 2413/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */ 2414static void bwn_nphy_rev2_rssi_cal(struct bwn_mac *mac, enum n_rssi_type type) 2415{ 2416 int i, j, vcm; 2417 uint8_t state[4]; 2418 uint8_t code, val; 2419 uint16_t class, override; 2420 uint8_t regs_save_radio[2]; 2421 uint16_t regs_save_phy[2]; 2422 2423 int32_t offset[4]; 2424 uint8_t core; 2425 uint8_t rail; 2426 2427 uint16_t clip_state[2]; 2428 uint16_t clip_off[2] = { 0xFFFF, 0xFFFF }; 2429 int32_t results_min[4] = { }; 2430 uint8_t vcm_final[4] = { }; 2431 int32_t results[4][4] = { }; 2432 int32_t miniq[4][2] = { }; 2433 2434 if (type == N_RSSI_NB) { 2435 code = 0; 2436 val = 6; 2437 } else if (type == N_RSSI_W1 || type == N_RSSI_W2) { 2438 code = 25; 2439 val = 4; 2440 } else { 2441 BWN_ERRPRINTF(mac->mac_sc, "%s: RSSI type %d invalid\n", 2442 __func__, 2443 type); 2444 return; 2445 } 2446 2447 class = bwn_nphy_classifier(mac, 0, 0); 2448 bwn_nphy_classifier(mac, 7, 4); 2449 bwn_nphy_read_clip_detection(mac, clip_state); 2450 bwn_nphy_write_clip_detection(mac, clip_off); 2451 2452 if (bwn_current_band(mac) == BWN_BAND_5G) 2453 override = 0x140; 2454 else 2455 override = 0x110; 2456 2457 regs_save_phy[0] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC1); 2458 regs_save_radio[0] = BWN_RF_READ(mac, B2055_C1_PD_RXTX); 2459 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, override); 2460 BWN_RF_WRITE(mac, B2055_C1_PD_RXTX, val); 2461 2462 regs_save_phy[1] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC2); 2463 regs_save_radio[1] = BWN_RF_READ(mac, B2055_C2_PD_RXTX); 2464 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, override); 2465 BWN_RF_WRITE(mac, B2055_C2_PD_RXTX, val); 2466 2467 state[0] = BWN_RF_READ(mac, B2055_C1_PD_RSSIMISC) & 0x07; 2468 state[1] = BWN_RF_READ(mac, B2055_C2_PD_RSSIMISC) & 0x07; 2469 BWN_RF_MASK(mac, B2055_C1_PD_RSSIMISC, 0xF8); 2470 BWN_RF_MASK(mac, B2055_C2_PD_RSSIMISC, 0xF8); 2471 state[2] = BWN_RF_READ(mac, B2055_C1_SP_RSSI) & 0x07; 2472 state[3] = BWN_RF_READ(mac, B2055_C2_SP_RSSI) & 0x07; 2473 2474 bwn_nphy_rssi_select(mac, 5, type); 2475 bwn_nphy_scale_offset_rssi(mac, 0, 0, 5, N_RAIL_I, type); 2476 bwn_nphy_scale_offset_rssi(mac, 0, 0, 5, N_RAIL_Q, type); 2477 2478 for (vcm = 0; vcm < 4; vcm++) { 2479 uint8_t tmp[4]; 2480 for (j = 0; j < 4; j++) 2481 tmp[j] = vcm; 2482 if (type != N_RSSI_W2) 2483 bwn_nphy_set_rssi_2055_vcm(mac, type, tmp); 2484 bwn_nphy_poll_rssi(mac, type, results[vcm], 8); 2485 if (type == N_RSSI_W1 || type == N_RSSI_W2) 2486 for (j = 0; j < 2; j++) 2487 miniq[vcm][j] = min(results[vcm][2 * j], 2488 results[vcm][2 * j + 1]); 2489 } 2490 2491 for (i = 0; i < 4; i++) { 2492 int32_t mind = 0x100000; 2493 uint8_t minvcm = 0; 2494 int32_t minpoll = 249; 2495 int32_t currd; 2496 for (vcm = 0; vcm < 4; vcm++) { 2497 if (type == N_RSSI_NB) 2498 currd = abs(results[vcm][i] - code * 8); 2499 else 2500 currd = abs(miniq[vcm][i / 2] - code * 8); 2501 2502 if (currd < mind) { 2503 mind = currd; 2504 minvcm = vcm; 2505 } 2506 2507 if (results[vcm][i] < minpoll) 2508 minpoll = results[vcm][i]; 2509 } 2510 results_min[i] = minpoll; 2511 vcm_final[i] = minvcm; 2512 } 2513 2514 if (type != N_RSSI_W2) 2515 bwn_nphy_set_rssi_2055_vcm(mac, type, vcm_final); 2516 2517 for (i = 0; i < 4; i++) { 2518 offset[i] = (code * 8) - results[vcm_final[i]][i]; 2519 2520 if (offset[i] < 0) 2521 offset[i] = -((abs(offset[i]) + 4) / 8); 2522 else 2523 offset[i] = (offset[i] + 4) / 8; 2524 2525 if (results_min[i] == 248) 2526 offset[i] = code - 32; 2527 2528 core = (i / 2) ? 2 : 1; 2529 rail = (i % 2) ? N_RAIL_Q : N_RAIL_I; 2530 2531 bwn_nphy_scale_offset_rssi(mac, 0, offset[i], core, rail, 2532 type); 2533 } 2534 2535 BWN_RF_SETMASK(mac, B2055_C1_PD_RSSIMISC, 0xF8, state[0]); 2536 BWN_RF_SETMASK(mac, B2055_C2_PD_RSSIMISC, 0xF8, state[1]); 2537 2538 switch (state[2]) { 2539 case 1: 2540 bwn_nphy_rssi_select(mac, 1, N_RSSI_NB); 2541 break; 2542 case 4: 2543 bwn_nphy_rssi_select(mac, 1, N_RSSI_W1); 2544 break; 2545 case 2: 2546 bwn_nphy_rssi_select(mac, 1, N_RSSI_W2); 2547 break; 2548 default: 2549 bwn_nphy_rssi_select(mac, 1, N_RSSI_W2); 2550 break; 2551 } 2552 2553 switch (state[3]) { 2554 case 1: 2555 bwn_nphy_rssi_select(mac, 2, N_RSSI_NB); 2556 break; 2557 case 4: 2558 bwn_nphy_rssi_select(mac, 2, N_RSSI_W1); 2559 break; 2560 default: 2561 bwn_nphy_rssi_select(mac, 2, N_RSSI_W2); 2562 break; 2563 } 2564 2565 bwn_nphy_rssi_select(mac, 0, type); 2566 2567 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, regs_save_phy[0]); 2568 BWN_RF_WRITE(mac, B2055_C1_PD_RXTX, regs_save_radio[0]); 2569 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, regs_save_phy[1]); 2570 BWN_RF_WRITE(mac, B2055_C2_PD_RXTX, regs_save_radio[1]); 2571 2572 bwn_nphy_classifier(mac, 7, class); 2573 bwn_nphy_write_clip_detection(mac, clip_state); 2574 /* Specs don't say about reset here, but it makes wl and b43 dumps 2575 identical, it really seems wl performs this */ 2576 bwn_nphy_reset_cca(mac); 2577} 2578 2579/* 2580 * RSSI Calibration 2581 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal 2582 */ 2583static void bwn_nphy_rssi_cal(struct bwn_mac *mac) 2584{ 2585 if (mac->mac_phy.rev >= 19) { 2586 /* TODO */ 2587 } else if (mac->mac_phy.rev >= 3) { 2588 bwn_nphy_rev3_rssi_cal(mac); 2589 } else { 2590 bwn_nphy_rev2_rssi_cal(mac, N_RSSI_NB); 2591 bwn_nphy_rev2_rssi_cal(mac, N_RSSI_W1); 2592 bwn_nphy_rev2_rssi_cal(mac, N_RSSI_W2); 2593 } 2594} 2595 2596/************************************************** 2597 * Workarounds 2598 **************************************************/ 2599 2600static void bwn_nphy_gain_ctl_workarounds_rev19(struct bwn_mac *mac) 2601{ 2602 /* TODO */ 2603} 2604 2605static void bwn_nphy_gain_ctl_workarounds_rev7(struct bwn_mac *mac) 2606{ 2607 struct bwn_phy *phy = &mac->mac_phy; 2608 2609 switch (phy->rev) { 2610 /* TODO */ 2611 } 2612} 2613 2614static void bwn_nphy_gain_ctl_workarounds_rev3(struct bwn_mac *mac) 2615{ 2616 struct bwn_softc *sc = mac->mac_sc; 2617 bool ghz5; 2618 bool ext_lna; 2619 uint16_t rssi_gain; 2620 struct bwn_nphy_gain_ctl_workaround_entry *e; 2621 uint8_t lpf_gain[6] = { 0x00, 0x06, 0x0C, 0x12, 0x12, 0x12 }; 2622 uint8_t lpf_bits[6] = { 0, 1, 2, 3, 3, 3 }; 2623 2624 /* Prepare values */ 2625 ghz5 = BWN_PHY_READ(mac, BWN_NPHY_BANDCTL) 2626 & BWN_NPHY_BANDCTL_5GHZ; 2627 ext_lna = ghz5 ? sc->sc_board_info.board_flags & BHND_BFL_EXTLNA_5GHZ : 2628 sc->sc_board_info.board_flags & BHND_BFL_EXTLNA; 2629 e = bwn_nphy_get_gain_ctl_workaround_ent(mac, ghz5, ext_lna); 2630 if (ghz5 && mac->mac_phy.rev >= 5) 2631 rssi_gain = 0x90; 2632 else 2633 rssi_gain = 0x50; 2634 2635 BWN_PHY_SET(mac, BWN_NPHY_RXCTL, 0x0040); 2636 2637 /* Set Clip 2 detect */ 2638 BWN_PHY_SET(mac, BWN_NPHY_C1_CGAINI, BWN_NPHY_C1_CGAINI_CL2DETECT); 2639 BWN_PHY_SET(mac, BWN_NPHY_C2_CGAINI, BWN_NPHY_C2_CGAINI_CL2DETECT); 2640 2641 BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_BIASPOLE_LNAG1_IDAC, 2642 0x17); 2643 BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_BIASPOLE_LNAG1_IDAC, 2644 0x17); 2645 BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_LNAG2_IDAC, 0xF0); 2646 BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_LNAG2_IDAC, 0xF0); 2647 BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_RSSI_POLE, 0x00); 2648 BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_RSSI_POLE, 0x00); 2649 BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_RSSI_GAIN, 2650 rssi_gain); 2651 BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_RSSI_GAIN, 2652 rssi_gain); 2653 BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_BIASPOLE_LNAA1_IDAC, 2654 0x17); 2655 BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_BIASPOLE_LNAA1_IDAC, 2656 0x17); 2657 BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_LNAA2_IDAC, 0xFF); 2658 BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_LNAA2_IDAC, 0xFF); 2659 2660 bwn_ntab_write_bulk(mac, BWN_NTAB8(0, 8), 4, e->lna1_gain); 2661 bwn_ntab_write_bulk(mac, BWN_NTAB8(1, 8), 4, e->lna1_gain); 2662 bwn_ntab_write_bulk(mac, BWN_NTAB8(0, 16), 4, e->lna2_gain); 2663 bwn_ntab_write_bulk(mac, BWN_NTAB8(1, 16), 4, e->lna2_gain); 2664 bwn_ntab_write_bulk(mac, BWN_NTAB8(0, 32), 10, e->gain_db); 2665 bwn_ntab_write_bulk(mac, BWN_NTAB8(1, 32), 10, e->gain_db); 2666 bwn_ntab_write_bulk(mac, BWN_NTAB8(2, 32), 10, e->gain_bits); 2667 bwn_ntab_write_bulk(mac, BWN_NTAB8(3, 32), 10, e->gain_bits); 2668 bwn_ntab_write_bulk(mac, BWN_NTAB8(0, 0x40), 6, lpf_gain); 2669 bwn_ntab_write_bulk(mac, BWN_NTAB8(1, 0x40), 6, lpf_gain); 2670 bwn_ntab_write_bulk(mac, BWN_NTAB8(2, 0x40), 6, lpf_bits); 2671 bwn_ntab_write_bulk(mac, BWN_NTAB8(3, 0x40), 6, lpf_bits); 2672 2673 BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C1_INITGAIN_A, e->init_gain); 2674 BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C2_INITGAIN_A, e->init_gain); 2675 2676 bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x106), 2, 2677 e->rfseq_init); 2678 2679 BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C1_CLIP_HIGAIN_A, e->cliphi_gain); 2680 BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C2_CLIP_HIGAIN_A, e->cliphi_gain); 2681 BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C1_CLIP_MEDGAIN_A, e->clipmd_gain); 2682 BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C2_CLIP_MEDGAIN_A, e->clipmd_gain); 2683 BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C1_CLIP_LOGAIN_A, e->cliplo_gain); 2684 BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C2_CLIP_LOGAIN_A, e->cliplo_gain); 2685 2686 BWN_PHY_SETMASK(mac, BWN_NPHY_CRSMINPOWER0, 0xFF00, e->crsmin); 2687 BWN_PHY_SETMASK(mac, BWN_NPHY_CRSMINPOWERL0, 0xFF00, e->crsminl); 2688 BWN_PHY_SETMASK(mac, BWN_NPHY_CRSMINPOWERU0, 0xFF00, e->crsminu); 2689 BWN_PHY_WRITE(mac, BWN_NPHY_C1_NBCLIPTHRES, e->nbclip); 2690 BWN_PHY_WRITE(mac, BWN_NPHY_C2_NBCLIPTHRES, e->nbclip); 2691 BWN_PHY_SETMASK(mac, BWN_NPHY_C1_CLIPWBTHRES, 2692 ~BWN_NPHY_C1_CLIPWBTHRES_CLIP2, e->wlclip); 2693 BWN_PHY_SETMASK(mac, BWN_NPHY_C2_CLIPWBTHRES, 2694 ~BWN_NPHY_C2_CLIPWBTHRES_CLIP2, e->wlclip); 2695 BWN_PHY_WRITE(mac, BWN_NPHY_CCK_SHIFTB_REF, 0x809C); 2696} 2697 2698static void bwn_nphy_gain_ctl_workarounds_rev1_2(struct bwn_mac *mac) 2699{ 2700 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 2701 2702 uint8_t i, j; 2703 uint8_t code; 2704 uint16_t tmp; 2705 uint8_t rfseq_events[3] = { 6, 8, 7 }; 2706 uint8_t rfseq_delays[3] = { 10, 30, 1 }; 2707 2708 /* Set Clip 2 detect */ 2709 BWN_PHY_SET(mac, BWN_NPHY_C1_CGAINI, BWN_NPHY_C1_CGAINI_CL2DETECT); 2710 BWN_PHY_SET(mac, BWN_NPHY_C2_CGAINI, BWN_NPHY_C2_CGAINI_CL2DETECT); 2711 2712 /* Set narrowband clip threshold */ 2713 BWN_PHY_WRITE(mac, BWN_NPHY_C1_NBCLIPTHRES, 0x84); 2714 BWN_PHY_WRITE(mac, BWN_NPHY_C2_NBCLIPTHRES, 0x84); 2715 2716 if (!bwn_is_40mhz(mac)) { 2717 /* Set dwell lengths */ 2718 BWN_PHY_WRITE(mac, BWN_NPHY_CLIP1_NBDWELL_LEN, 0x002B); 2719 BWN_PHY_WRITE(mac, BWN_NPHY_CLIP2_NBDWELL_LEN, 0x002B); 2720 BWN_PHY_WRITE(mac, BWN_NPHY_W1CLIP1_DWELL_LEN, 0x0009); 2721 BWN_PHY_WRITE(mac, BWN_NPHY_W1CLIP2_DWELL_LEN, 0x0009); 2722 } 2723 2724 /* Set wideband clip 2 threshold */ 2725 BWN_PHY_SETMASK(mac, BWN_NPHY_C1_CLIPWBTHRES, 2726 ~BWN_NPHY_C1_CLIPWBTHRES_CLIP2, 21); 2727 BWN_PHY_SETMASK(mac, BWN_NPHY_C2_CLIPWBTHRES, 2728 ~BWN_NPHY_C2_CLIPWBTHRES_CLIP2, 21); 2729 2730 if (!bwn_is_40mhz(mac)) { 2731 BWN_PHY_SETMASK(mac, BWN_NPHY_C1_CGAINI, 2732 ~BWN_NPHY_C1_CGAINI_GAINBKOFF, 0x1); 2733 BWN_PHY_SETMASK(mac, BWN_NPHY_C2_CGAINI, 2734 ~BWN_NPHY_C2_CGAINI_GAINBKOFF, 0x1); 2735 BWN_PHY_SETMASK(mac, BWN_NPHY_C1_CCK_CGAINI, 2736 ~BWN_NPHY_C1_CCK_CGAINI_GAINBKOFF, 0x1); 2737 BWN_PHY_SETMASK(mac, BWN_NPHY_C2_CCK_CGAINI, 2738 ~BWN_NPHY_C2_CCK_CGAINI_GAINBKOFF, 0x1); 2739 } 2740 2741 BWN_PHY_WRITE(mac, BWN_NPHY_CCK_SHIFTB_REF, 0x809C); 2742 2743 if (nphy->gain_boost) { 2744 if (bwn_current_band(mac) == BWN_BAND_2G && 2745 bwn_is_40mhz(mac)) 2746 code = 4; 2747 else 2748 code = 5; 2749 } else { 2750 code = bwn_is_40mhz(mac) ? 6 : 7; 2751 } 2752 2753 /* Set HPVGA2 index */ 2754 BWN_PHY_SETMASK(mac, BWN_NPHY_C1_INITGAIN, ~BWN_NPHY_C1_INITGAIN_HPVGA2, 2755 code << BWN_NPHY_C1_INITGAIN_HPVGA2_SHIFT); 2756 BWN_PHY_SETMASK(mac, BWN_NPHY_C2_INITGAIN, ~BWN_NPHY_C2_INITGAIN_HPVGA2, 2757 code << BWN_NPHY_C2_INITGAIN_HPVGA2_SHIFT); 2758 2759 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x1D06); 2760 /* specs say about 2 loops, but wl does 4 */ 2761 for (i = 0; i < 4; i++) 2762 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, (code << 8 | 0x7C)); 2763 2764 bwn_nphy_adjust_lna_gain_table(mac); 2765 2766 if (nphy->elna_gain_config) { 2767 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x0808); 2768 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x0); 2769 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1); 2770 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1); 2771 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1); 2772 2773 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x0C08); 2774 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x0); 2775 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1); 2776 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1); 2777 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0x1); 2778 2779 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x1D06); 2780 /* specs say about 2 loops, but wl does 4 */ 2781 for (i = 0; i < 4; i++) 2782 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 2783 (code << 8 | 0x74)); 2784 } 2785 2786 if (mac->mac_phy.rev == 2) { 2787 for (i = 0; i < 4; i++) { 2788 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 2789 (0x0400 * i) + 0x0020); 2790 for (j = 0; j < 21; j++) { 2791 tmp = j * (i < 2 ? 3 : 1); 2792 BWN_PHY_WRITE(mac, 2793 BWN_NPHY_TABLE_DATALO, tmp); 2794 } 2795 } 2796 } 2797 2798 bwn_nphy_set_rf_sequence(mac, 5, rfseq_events, rfseq_delays, 3); 2799 BWN_PHY_SETMASK(mac, BWN_NPHY_OVER_DGAIN1, 2800 ~BWN_NPHY_OVER_DGAIN_CCKDGECV & 0xFFFF, 2801 0x5A << BWN_NPHY_OVER_DGAIN_CCKDGECV_SHIFT); 2802 2803 if (bwn_current_band(mac) == BWN_BAND_2G) 2804 BWN_PHY_SETMASK(mac, BWN_PHY_N(0xC5D), 0xFF80, 4); 2805} 2806 2807/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */ 2808static void bwn_nphy_gain_ctl_workarounds(struct bwn_mac *mac) 2809{ 2810 if (mac->mac_phy.rev >= 19) 2811 bwn_nphy_gain_ctl_workarounds_rev19(mac); 2812 else if (mac->mac_phy.rev >= 7) 2813 bwn_nphy_gain_ctl_workarounds_rev7(mac); 2814 else if (mac->mac_phy.rev >= 3) 2815 bwn_nphy_gain_ctl_workarounds_rev3(mac); 2816 else 2817 bwn_nphy_gain_ctl_workarounds_rev1_2(mac); 2818} 2819 2820static int bwn_nphy_workarounds_rev7plus(struct bwn_mac *mac) 2821{ 2822 struct bwn_softc *sc = mac->mac_sc; 2823 struct bwn_phy *phy = &mac->mac_phy; 2824 2825 /* TX to RX */ 2826 uint8_t tx2rx_events[7] = { 4, 3, 5, 2, 1, 8, 31, }; 2827 uint8_t tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1, }; 2828 /* RX to TX */ 2829 uint8_t rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3, 2830 0x1F }; 2831 uint8_t rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; 2832 2833 static const uint16_t ntab7_15e_16e[] = { 0, 0x10f, 0x10f }; 2834 uint8_t ntab7_138_146[] = { 0x11, 0x11 }; 2835 uint8_t ntab7_133[] = { 0x77, 0x11, 0x11 }; 2836 2837 uint16_t lpf_ofdm_20mhz[2], lpf_ofdm_40mhz[2], lpf_11b[2]; 2838 uint16_t bcap_val; 2839 int16_t bcap_val_11b[2], bcap_val_11n_20[2], bcap_val_11n_40[2]; 2840 uint16_t scap_val; 2841 int16_t scap_val_11b[2], scap_val_11n_20[2], scap_val_11n_40[2]; 2842 bool rccal_ovrd = false; 2843 2844 uint16_t bias, conv, filt; 2845 2846 uint32_t noise_tbl[2]; 2847 2848 uint32_t tmp32; 2849 uint8_t core; 2850 2851 BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A0, 0x0125); 2852 BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A1, 0x01b3); 2853 BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A2, 0x0105); 2854 BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B0, 0x016e); 2855 BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B1, 0x00cd); 2856 BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B2, 0x0020); 2857 2858 if (phy->rev == 7) { 2859 BWN_PHY_SET(mac, BWN_NPHY_FINERX2_CGC, 0x10); 2860 BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN0, 0xFF80, 0x0020); 2861 BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN0, 0x80FF, 0x2700); 2862 BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN1, 0xFF80, 0x002E); 2863 BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN1, 0x80FF, 0x3300); 2864 BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN2, 0xFF80, 0x0037); 2865 BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN2, 0x80FF, 0x3A00); 2866 BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN3, 0xFF80, 0x003C); 2867 BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN3, 0x80FF, 0x3E00); 2868 BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN4, 0xFF80, 0x003E); 2869 BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN4, 0x80FF, 0x3F00); 2870 BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN5, 0xFF80, 0x0040); 2871 BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN5, 0x80FF, 0x4000); 2872 BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN6, 0xFF80, 0x0040); 2873 BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN6, 0x80FF, 0x4000); 2874 BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN7, 0xFF80, 0x0040); 2875 BWN_PHY_SETMASK(mac, BWN_NPHY_FREQGAIN7, 0x80FF, 0x4000); 2876 } 2877 2878 if (phy->rev >= 16) { 2879 BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT0, 0x7ff); 2880 BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT1, 0x7ff); 2881 } else if (phy->rev <= 8) { 2882 BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT0, 0x1B0); 2883 BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT1, 0x1B0); 2884 } 2885 2886 if (phy->rev >= 16) 2887 BWN_PHY_SETMASK(mac, BWN_NPHY_TXTAILCNT, ~0xFF, 0xa0); 2888 else if (phy->rev >= 8) 2889 BWN_PHY_SETMASK(mac, BWN_NPHY_TXTAILCNT, ~0xFF, 0x72); 2890 2891 bwn_ntab_write(mac, BWN_NTAB16(8, 0x00), 2); 2892 bwn_ntab_write(mac, BWN_NTAB16(8, 0x10), 2); 2893 tmp32 = bwn_ntab_read(mac, BWN_NTAB32(30, 0)); 2894 tmp32 &= 0xffffff; 2895 bwn_ntab_write(mac, BWN_NTAB32(30, 0), tmp32); 2896 bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x15d), 3, ntab7_15e_16e); 2897 bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x16d), 3, ntab7_15e_16e); 2898 2899 bwn_nphy_set_rf_sequence(mac, 1, tx2rx_events, tx2rx_delays, 2900 nitems(tx2rx_events)); 2901 if (bwn_nphy_ipa(mac)) 2902 bwn_nphy_set_rf_sequence(mac, 0, rx2tx_events_ipa, 2903 rx2tx_delays_ipa, nitems(rx2tx_events_ipa)); 2904 2905 BWN_PHY_SETMASK(mac, BWN_NPHY_EPS_OVERRIDEI_0, 0x3FFF, 0x4000); 2906 BWN_PHY_SETMASK(mac, BWN_NPHY_EPS_OVERRIDEI_1, 0x3FFF, 0x4000); 2907 2908 for (core = 0; core < 2; core++) { 2909 lpf_ofdm_20mhz[core] = bwn_nphy_read_lpf_ctl(mac, 0x154 + core * 0x10); 2910 lpf_ofdm_40mhz[core] = bwn_nphy_read_lpf_ctl(mac, 0x159 + core * 0x10); 2911 lpf_11b[core] = bwn_nphy_read_lpf_ctl(mac, 0x152 + core * 0x10); 2912 } 2913 2914 bcap_val = BWN_RF_READ(mac, R2057_RCCAL_BCAP_VAL); 2915 scap_val = BWN_RF_READ(mac, R2057_RCCAL_SCAP_VAL); 2916 2917 if (bwn_nphy_ipa(mac)) { 2918 bool ghz2 = bwn_current_band(mac) == BWN_BAND_2G; 2919 2920 switch (phy->rf_rev) { 2921 case 5: 2922 /* Check radio version (to be 0) by PHY rev for now */ 2923 if (phy->rev == 8 && bwn_is_40mhz(mac)) { 2924 for (core = 0; core < 2; core++) { 2925 scap_val_11b[core] = scap_val; 2926 bcap_val_11b[core] = bcap_val; 2927 scap_val_11n_20[core] = scap_val; 2928 bcap_val_11n_20[core] = bcap_val; 2929 scap_val_11n_40[core] = 0xc; 2930 bcap_val_11n_40[core] = 0xc; 2931 } 2932 2933 rccal_ovrd = true; 2934 } 2935 if (phy->rev == 9) { 2936 /* TODO: Radio version 1 (e.g. BCM5357B0) */ 2937 } 2938 break; 2939 case 7: 2940 case 8: 2941 for (core = 0; core < 2; core++) { 2942 scap_val_11b[core] = scap_val; 2943 bcap_val_11b[core] = bcap_val; 2944 lpf_ofdm_20mhz[core] = 4; 2945 lpf_11b[core] = 1; 2946 if (bwn_current_band(mac) == BWN_BAND_2G) { 2947 scap_val_11n_20[core] = 0xc; 2948 bcap_val_11n_20[core] = 0xc; 2949 scap_val_11n_40[core] = 0xa; 2950 bcap_val_11n_40[core] = 0xa; 2951 } else { 2952 scap_val_11n_20[core] = 0x14; 2953 bcap_val_11n_20[core] = 0x14; 2954 scap_val_11n_40[core] = 0xf; 2955 bcap_val_11n_40[core] = 0xf; 2956 } 2957 } 2958 2959 rccal_ovrd = true; 2960 break; 2961 case 9: 2962 for (core = 0; core < 2; core++) { 2963 bcap_val_11b[core] = bcap_val; 2964 scap_val_11b[core] = scap_val; 2965 lpf_11b[core] = 1; 2966 2967 if (ghz2) { 2968 bcap_val_11n_20[core] = bcap_val + 13; 2969 scap_val_11n_20[core] = scap_val + 15; 2970 } else { 2971 bcap_val_11n_20[core] = bcap_val + 14; 2972 scap_val_11n_20[core] = scap_val + 15; 2973 } 2974 lpf_ofdm_20mhz[core] = 4; 2975 2976 if (ghz2) { 2977 bcap_val_11n_40[core] = bcap_val - 7; 2978 scap_val_11n_40[core] = scap_val - 5; 2979 } else { 2980 bcap_val_11n_40[core] = bcap_val + 2; 2981 scap_val_11n_40[core] = scap_val + 4; 2982 } 2983 lpf_ofdm_40mhz[core] = 4; 2984 } 2985 2986 rccal_ovrd = true; 2987 break; 2988 case 14: 2989 for (core = 0; core < 2; core++) { 2990 bcap_val_11b[core] = bcap_val; 2991 scap_val_11b[core] = scap_val; 2992 lpf_11b[core] = 1; 2993 } 2994 2995 bcap_val_11n_20[0] = bcap_val + 20; 2996 scap_val_11n_20[0] = scap_val + 20; 2997 lpf_ofdm_20mhz[0] = 3; 2998 2999 bcap_val_11n_20[1] = bcap_val + 16; 3000 scap_val_11n_20[1] = scap_val + 16; 3001 lpf_ofdm_20mhz[1] = 3; 3002 3003 bcap_val_11n_40[0] = bcap_val + 20; 3004 scap_val_11n_40[0] = scap_val + 20; 3005 lpf_ofdm_40mhz[0] = 4; 3006 3007 bcap_val_11n_40[1] = bcap_val + 10; 3008 scap_val_11n_40[1] = scap_val + 10; 3009 lpf_ofdm_40mhz[1] = 4; 3010 3011 rccal_ovrd = true; 3012 break; 3013 } 3014 } else { 3015 if (phy->rf_rev == 5) { 3016 for (core = 0; core < 2; core++) { 3017 lpf_ofdm_20mhz[core] = 1; 3018 lpf_ofdm_40mhz[core] = 3; 3019 scap_val_11b[core] = scap_val; 3020 bcap_val_11b[core] = bcap_val; 3021 scap_val_11n_20[core] = 0x11; 3022 scap_val_11n_40[core] = 0x11; 3023 bcap_val_11n_20[core] = 0x13; 3024 bcap_val_11n_40[core] = 0x13; 3025 } 3026 3027 rccal_ovrd = true; 3028 } 3029 } 3030 if (rccal_ovrd) { 3031 uint16_t rx2tx_lut_20_11b[2], rx2tx_lut_20_11n[2], rx2tx_lut_40_11n[2]; 3032 uint8_t rx2tx_lut_extra = 1; 3033 3034 for (core = 0; core < 2; core++) { 3035 bcap_val_11b[core] = bwn_clamp_val(bcap_val_11b[core], 0, 0x1f); 3036 scap_val_11b[core] = bwn_clamp_val(scap_val_11b[core], 0, 0x1f); 3037 bcap_val_11n_20[core] = bwn_clamp_val(bcap_val_11n_20[core], 0, 0x1f); 3038 scap_val_11n_20[core] = bwn_clamp_val(scap_val_11n_20[core], 0, 0x1f); 3039 bcap_val_11n_40[core] = bwn_clamp_val(bcap_val_11n_40[core], 0, 0x1f); 3040 scap_val_11n_40[core] = bwn_clamp_val(scap_val_11n_40[core], 0, 0x1f); 3041 3042 rx2tx_lut_20_11b[core] = (rx2tx_lut_extra << 13) | 3043 (bcap_val_11b[core] << 8) | 3044 (scap_val_11b[core] << 3) | 3045 lpf_11b[core]; 3046 rx2tx_lut_20_11n[core] = (rx2tx_lut_extra << 13) | 3047 (bcap_val_11n_20[core] << 8) | 3048 (scap_val_11n_20[core] << 3) | 3049 lpf_ofdm_20mhz[core]; 3050 rx2tx_lut_40_11n[core] = (rx2tx_lut_extra << 13) | 3051 (bcap_val_11n_40[core] << 8) | 3052 (scap_val_11n_40[core] << 3) | 3053 lpf_ofdm_40mhz[core]; 3054 } 3055 3056 for (core = 0; core < 2; core++) { 3057 bwn_ntab_write(mac, BWN_NTAB16(7, 0x152 + core * 16), 3058 rx2tx_lut_20_11b[core]); 3059 bwn_ntab_write(mac, BWN_NTAB16(7, 0x153 + core * 16), 3060 rx2tx_lut_20_11n[core]); 3061 bwn_ntab_write(mac, BWN_NTAB16(7, 0x154 + core * 16), 3062 rx2tx_lut_20_11n[core]); 3063 bwn_ntab_write(mac, BWN_NTAB16(7, 0x155 + core * 16), 3064 rx2tx_lut_40_11n[core]); 3065 bwn_ntab_write(mac, BWN_NTAB16(7, 0x156 + core * 16), 3066 rx2tx_lut_40_11n[core]); 3067 bwn_ntab_write(mac, BWN_NTAB16(7, 0x157 + core * 16), 3068 rx2tx_lut_40_11n[core]); 3069 bwn_ntab_write(mac, BWN_NTAB16(7, 0x158 + core * 16), 3070 rx2tx_lut_40_11n[core]); 3071 bwn_ntab_write(mac, BWN_NTAB16(7, 0x159 + core * 16), 3072 rx2tx_lut_40_11n[core]); 3073 } 3074 } 3075 3076 BWN_PHY_WRITE(mac, 0x32F, 0x3); 3077 3078 if (phy->rf_rev == 4 || phy->rf_rev == 6) 3079 bwn_nphy_rf_ctl_override_rev7(mac, 4, 1, 3, false, 0); 3080 3081 if (phy->rf_rev == 3 || phy->rf_rev == 4 || phy->rf_rev == 6) { 3082 if (sc->sc_board_info.board_srom_rev && 3083 sc->sc_board_info.board_flags2 & BHND_BFL2_IPALVLSHIFT_3P3) { 3084 BWN_RF_WRITE(mac, 0x5, 0x05); 3085 BWN_RF_WRITE(mac, 0x6, 0x30); 3086 BWN_RF_WRITE(mac, 0x7, 0x00); 3087 BWN_RF_SET(mac, 0x4f, 0x1); 3088 BWN_RF_SET(mac, 0xd4, 0x1); 3089 bias = 0x1f; 3090 conv = 0x6f; 3091 filt = 0xaa; 3092 } else { 3093 bias = 0x2b; 3094 conv = 0x7f; 3095 filt = 0xee; 3096 } 3097 if (bwn_current_band(mac) == BWN_BAND_2G) { 3098 for (core = 0; core < 2; core++) { 3099 if (core == 0) { 3100 BWN_RF_WRITE(mac, 0x5F, bias); 3101 BWN_RF_WRITE(mac, 0x64, conv); 3102 BWN_RF_WRITE(mac, 0x66, filt); 3103 } else { 3104 BWN_RF_WRITE(mac, 0xE8, bias); 3105 BWN_RF_WRITE(mac, 0xE9, conv); 3106 BWN_RF_WRITE(mac, 0xEB, filt); 3107 } 3108 } 3109 } 3110 } 3111 3112 if (bwn_nphy_ipa(mac)) { 3113 if (bwn_current_band(mac) == BWN_BAND_2G) { 3114 if (phy->rf_rev == 3 || phy->rf_rev == 4 || 3115 phy->rf_rev == 6) { 3116 for (core = 0; core < 2; core++) { 3117 if (core == 0) 3118 BWN_RF_WRITE(mac, 0x51, 3119 0x7f); 3120 else 3121 BWN_RF_WRITE(mac, 0xd6, 3122 0x7f); 3123 } 3124 } 3125 switch (phy->rf_rev) { 3126 case 3: 3127 for (core = 0; core < 2; core++) { 3128 if (core == 0) { 3129 BWN_RF_WRITE(mac, 0x64, 3130 0x13); 3131 BWN_RF_WRITE(mac, 0x5F, 3132 0x1F); 3133 BWN_RF_WRITE(mac, 0x66, 3134 0xEE); 3135 BWN_RF_WRITE(mac, 0x59, 3136 0x8A); 3137 BWN_RF_WRITE(mac, 0x80, 3138 0x3E); 3139 } else { 3140 BWN_RF_WRITE(mac, 0x69, 3141 0x13); 3142 BWN_RF_WRITE(mac, 0xE8, 3143 0x1F); 3144 BWN_RF_WRITE(mac, 0xEB, 3145 0xEE); 3146 BWN_RF_WRITE(mac, 0xDE, 3147 0x8A); 3148 BWN_RF_WRITE(mac, 0x105, 3149 0x3E); 3150 } 3151 } 3152 break; 3153 case 7: 3154 case 8: 3155 if (!bwn_is_40mhz(mac)) { 3156 BWN_RF_WRITE(mac, 0x5F, 0x14); 3157 BWN_RF_WRITE(mac, 0xE8, 0x12); 3158 } else { 3159 BWN_RF_WRITE(mac, 0x5F, 0x16); 3160 BWN_RF_WRITE(mac, 0xE8, 0x16); 3161 } 3162 break; 3163 case 14: 3164 for (core = 0; core < 2; core++) { 3165 int o = core ? 0x85 : 0; 3166 3167 BWN_RF_WRITE(mac, o + R2057_IPA2G_CASCONV_CORE0, 0x13); 3168 BWN_RF_WRITE(mac, o + R2057_TXMIX2G_TUNE_BOOST_PU_CORE0, 0x21); 3169 BWN_RF_WRITE(mac, o + R2057_IPA2G_BIAS_FILTER_CORE0, 0xff); 3170 BWN_RF_WRITE(mac, o + R2057_PAD2G_IDACS_CORE0, 0x88); 3171 BWN_RF_WRITE(mac, o + R2057_PAD2G_TUNE_PUS_CORE0, 0x23); 3172 BWN_RF_WRITE(mac, o + R2057_IPA2G_IMAIN_CORE0, 0x16); 3173 BWN_RF_WRITE(mac, o + R2057_PAD_BIAS_FILTER_BWS_CORE0, 0x3e); 3174 BWN_RF_WRITE(mac, o + R2057_BACKUP1_CORE0, 0x10); 3175 } 3176 break; 3177 } 3178 } else { 3179 uint16_t freq = bwn_get_centre_freq(mac); 3180 if ((freq >= 5180 && freq <= 5230) || 3181 (freq >= 5745 && freq <= 5805)) { 3182 BWN_RF_WRITE(mac, 0x7D, 0xFF); 3183 BWN_RF_WRITE(mac, 0xFE, 0xFF); 3184 } 3185 } 3186 } else { 3187 if (phy->rf_rev != 5) { 3188 for (core = 0; core < 2; core++) { 3189 if (core == 0) { 3190 BWN_RF_WRITE(mac, 0x5c, 0x61); 3191 BWN_RF_WRITE(mac, 0x51, 0x70); 3192 } else { 3193 BWN_RF_WRITE(mac, 0xe1, 0x61); 3194 BWN_RF_WRITE(mac, 0xd6, 0x70); 3195 } 3196 } 3197 } 3198 } 3199 3200 if (phy->rf_rev == 4) { 3201 bwn_ntab_write(mac, BWN_NTAB16(8, 0x05), 0x20); 3202 bwn_ntab_write(mac, BWN_NTAB16(8, 0x15), 0x20); 3203 for (core = 0; core < 2; core++) { 3204 if (core == 0) { 3205 BWN_RF_WRITE(mac, 0x1a1, 0x00); 3206 BWN_RF_WRITE(mac, 0x1a2, 0x3f); 3207 BWN_RF_WRITE(mac, 0x1a6, 0x3f); 3208 } else { 3209 BWN_RF_WRITE(mac, 0x1a7, 0x00); 3210 BWN_RF_WRITE(mac, 0x1ab, 0x3f); 3211 BWN_RF_WRITE(mac, 0x1ac, 0x3f); 3212 } 3213 } 3214 } else { 3215 BWN_PHY_SET(mac, BWN_NPHY_AFECTL_C1, 0x4); 3216 BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER1, 0x4); 3217 BWN_PHY_SET(mac, BWN_NPHY_AFECTL_C2, 0x4); 3218 BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x4); 3219 3220 BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C1, ~0x1); 3221 BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER1, 0x1); 3222 BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C2, ~0x1); 3223 BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x1); 3224 bwn_ntab_write(mac, BWN_NTAB16(8, 0x05), 0); 3225 bwn_ntab_write(mac, BWN_NTAB16(8, 0x15), 0); 3226 3227 BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C1, ~0x4); 3228 BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER1, ~0x4); 3229 BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C2, ~0x4); 3230 BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER, ~0x4); 3231 } 3232 3233 BWN_PHY_WRITE(mac, BWN_NPHY_ENDROP_TLEN, 0x2); 3234 3235 bwn_ntab_write(mac, BWN_NTAB32(16, 0x100), 20); 3236 bwn_ntab_write_bulk(mac, BWN_NTAB8(7, 0x138), 2, ntab7_138_146); 3237 bwn_ntab_write(mac, BWN_NTAB16(7, 0x141), 0x77); 3238 bwn_ntab_write_bulk(mac, BWN_NTAB8(7, 0x133), 3, ntab7_133); 3239 bwn_ntab_write_bulk(mac, BWN_NTAB8(7, 0x146), 2, ntab7_138_146); 3240 bwn_ntab_write(mac, BWN_NTAB16(7, 0x123), 0x77); 3241 bwn_ntab_write(mac, BWN_NTAB16(7, 0x12A), 0x77); 3242 3243 bwn_ntab_read_bulk(mac, BWN_NTAB32(16, 0x02), 1, noise_tbl); 3244 noise_tbl[1] = bwn_is_40mhz(mac) ? 0x14D : 0x18D; 3245 bwn_ntab_write_bulk(mac, BWN_NTAB32(16, 0x02), 2, noise_tbl); 3246 3247 bwn_ntab_read_bulk(mac, BWN_NTAB32(16, 0x7E), 1, noise_tbl); 3248 noise_tbl[1] = bwn_is_40mhz(mac) ? 0x14D : 0x18D; 3249 bwn_ntab_write_bulk(mac, BWN_NTAB32(16, 0x7E), 2, noise_tbl); 3250 3251 bwn_nphy_gain_ctl_workarounds(mac); 3252 3253 /* TODO 3254 bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x08), 4, 3255 aux_adc_vmid_rev7_core0); 3256 bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x18), 4, 3257 aux_adc_vmid_rev7_core1); 3258 bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x0C), 4, 3259 aux_adc_gain_rev7); 3260 bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x1C), 4, 3261 aux_adc_gain_rev7); 3262 */ 3263 3264 return (0); 3265} 3266 3267static int bwn_nphy_workarounds_rev3plus(struct bwn_mac *mac) 3268{ 3269 struct bwn_softc *sc = mac->mac_sc; 3270 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 3271 3272 /* TX to RX */ 3273 uint8_t tx2rx_events[7] = { 0x4, 0x3, 0x5, 0x2, 0x1, 0x8, 0x1F }; 3274 uint8_t tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1 }; 3275 /* RX to TX */ 3276 uint8_t rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3, 3277 0x1F }; 3278 uint8_t rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; 3279 uint8_t rx2tx_events[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0x3, 0x4, 0x1F }; 3280 uint8_t rx2tx_delays[9] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 }; 3281 3282 uint16_t vmids[5][4] = { 3283 { 0xa2, 0xb4, 0xb4, 0x89, }, /* 0 */ 3284 { 0xb4, 0xb4, 0xb4, 0x24, }, /* 1 */ 3285 { 0xa2, 0xb4, 0xb4, 0x74, }, /* 2 */ 3286 { 0xa2, 0xb4, 0xb4, 0x270, }, /* 3 */ 3287 { 0xa2, 0xb4, 0xb4, 0x00, }, /* 4 and 5 */ 3288 }; 3289 uint16_t gains[5][4] = { 3290 { 0x02, 0x02, 0x02, 0x00, }, /* 0 */ 3291 { 0x02, 0x02, 0x02, 0x02, }, /* 1 */ 3292 { 0x02, 0x02, 0x02, 0x04, }, /* 2 */ 3293 { 0x02, 0x02, 0x02, 0x00, }, /* 3 */ 3294 { 0x02, 0x02, 0x02, 0x00, }, /* 4 and 5 */ 3295 }; 3296 uint16_t *vmid, *gain; 3297 3298 const char *pdet_range_var; 3299 uint8_t pdet_range; 3300 uint16_t tmp16; 3301 uint32_t tmp32; 3302 int error; 3303 3304 BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT0, 0x1f8); 3305 BWN_PHY_WRITE(mac, BWN_NPHY_FORCEFRONT1, 0x1f8); 3306 3307 tmp32 = bwn_ntab_read(mac, BWN_NTAB32(30, 0)); 3308 tmp32 &= 0xffffff; 3309 bwn_ntab_write(mac, BWN_NTAB32(30, 0), tmp32); 3310 3311 BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A0, 0x0125); 3312 BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A1, 0x01B3); 3313 BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A2, 0x0105); 3314 BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B0, 0x016E); 3315 BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B1, 0x00CD); 3316 BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B2, 0x0020); 3317 3318 BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C1_CLIP_LOGAIN_B, 0x000C); 3319 BWN_PHY_WRITE(mac, BWN_NPHY_REV3_C2_CLIP_LOGAIN_B, 0x000C); 3320 3321 /* TX to RX */ 3322 bwn_nphy_set_rf_sequence(mac, 1, tx2rx_events, tx2rx_delays, 3323 nitems(tx2rx_events)); 3324 3325 /* RX to TX */ 3326 if (bwn_nphy_ipa(mac)) 3327 bwn_nphy_set_rf_sequence(mac, 0, rx2tx_events_ipa, 3328 rx2tx_delays_ipa, nitems(rx2tx_events_ipa)); 3329 if (nphy->hw_phyrxchain != 3 && 3330 nphy->hw_phyrxchain != nphy->hw_phytxchain) { 3331 if (bwn_nphy_ipa(mac)) { 3332 rx2tx_delays[5] = 59; 3333 rx2tx_delays[6] = 1; 3334 rx2tx_events[7] = 0x1F; 3335 } 3336 bwn_nphy_set_rf_sequence(mac, 0, rx2tx_events, rx2tx_delays, 3337 nitems(rx2tx_events)); 3338 } 3339 3340 tmp16 = (bwn_current_band(mac) == BWN_BAND_2G) ? 3341 0x2 : 0x9C40; 3342 BWN_PHY_WRITE(mac, BWN_NPHY_ENDROP_TLEN, tmp16); 3343 3344 BWN_PHY_SETMASK(mac, BWN_NPHY_SGILTRNOFFSET, 0xF0FF, 0x0700); 3345 3346 if (!bwn_is_40mhz(mac)) { 3347 bwn_ntab_write(mac, BWN_NTAB32(16, 3), 0x18D); 3348 bwn_ntab_write(mac, BWN_NTAB32(16, 127), 0x18D); 3349 } else { 3350 bwn_ntab_write(mac, BWN_NTAB32(16, 3), 0x14D); 3351 bwn_ntab_write(mac, BWN_NTAB32(16, 127), 0x14D); 3352 } 3353 3354 bwn_nphy_gain_ctl_workarounds(mac); 3355 3356 bwn_ntab_write(mac, BWN_NTAB16(8, 0), 2); 3357 bwn_ntab_write(mac, BWN_NTAB16(8, 16), 2); 3358 3359 if (bwn_current_band(mac) == BWN_BAND_2G) 3360 pdet_range_var = BHND_NVAR_PDETRANGE2G; 3361 else 3362 pdet_range_var = BHND_NVAR_PDETRANGE5G; 3363 3364 error = bhnd_nvram_getvar_uint8(sc->sc_dev, pdet_range_var, 3365 &pdet_range); 3366 if (error) { 3367 BWN_ERRPRINTF(mac->mac_sc, "Error reading PDet range %s from " 3368 "NVRAM: %d\n", pdet_range_var, error); 3369 return (error); 3370 } 3371 3372 /* uint16_t min() */ 3373 vmid = vmids[min(pdet_range, 4)]; 3374 gain = gains[min(pdet_range, 4)]; 3375 switch (pdet_range) { 3376 case 3: 3377 if (!(mac->mac_phy.rev >= 4 && 3378 bwn_current_band(mac) == BWN_BAND_2G)) 3379 break; 3380 /* FALL THROUGH */ 3381 case 0: 3382 case 1: 3383 bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x08), 4, vmid); 3384 bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x18), 4, vmid); 3385 bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x0c), 4, gain); 3386 bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x1c), 4, gain); 3387 break; 3388 case 2: 3389 if (mac->mac_phy.rev >= 6) { 3390 if (bwn_current_band(mac) == BWN_BAND_2G) 3391 vmid[3] = 0x94; 3392 else 3393 vmid[3] = 0x8e; 3394 gain[3] = 3; 3395 } else if (mac->mac_phy.rev == 5) { 3396 vmid[3] = 0x84; 3397 gain[3] = 2; 3398 } 3399 bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x08), 4, vmid); 3400 bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x18), 4, vmid); 3401 bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x0c), 4, gain); 3402 bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x1c), 4, gain); 3403 break; 3404 case 4: 3405 case 5: 3406 if (bwn_current_band(mac) != BWN_BAND_2G) { 3407 if (pdet_range == 4) { 3408 vmid[3] = 0x8e; 3409 tmp16 = 0x96; 3410 gain[3] = 0x2; 3411 } else { 3412 vmid[3] = 0x89; 3413 tmp16 = 0x89; 3414 gain[3] = 0; 3415 } 3416 } else { 3417 if (pdet_range == 4) { 3418 vmid[3] = 0x89; 3419 tmp16 = 0x8b; 3420 gain[3] = 0x2; 3421 } else { 3422 vmid[3] = 0x74; 3423 tmp16 = 0x70; 3424 gain[3] = 0; 3425 } 3426 } 3427 bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x08), 4, vmid); 3428 bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x0c), 4, gain); 3429 vmid[3] = tmp16; 3430 bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x18), 4, vmid); 3431 bwn_ntab_write_bulk(mac, BWN_NTAB16(8, 0x1c), 4, gain); 3432 break; 3433 } 3434 3435 BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXA_MAST_BIAS, 0x00); 3436 BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXA_MAST_BIAS, 0x00); 3437 BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN, 0x06); 3438 BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN, 0x06); 3439 BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXA_BIAS_AUX, 0x07); 3440 BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07); 3441 BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88); 3442 BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88); 3443 BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXA_CMFB_IDAC, 0x00); 3444 BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXA_CMFB_IDAC, 0x00); 3445 BWN_RF_WRITE(mac, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00); 3446 BWN_RF_WRITE(mac, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00); 3447 3448 /* N PHY WAR TX Chain Update with hw_phytxchain as argument */ 3449 3450 if ((sc->sc_board_info.board_flags2 & BHND_BFL2_APLL_WAR && 3451 bwn_current_band(mac) == BWN_BAND_5G) || 3452 (sc->sc_board_info.board_flags2 & BHND_BFL2_GPLL_WAR2 && 3453 bwn_current_band(mac) == BWN_BAND_2G)) 3454 tmp32 = 0x00088888; 3455 else 3456 tmp32 = 0x88888888; 3457 bwn_ntab_write(mac, BWN_NTAB32(30, 1), tmp32); 3458 bwn_ntab_write(mac, BWN_NTAB32(30, 2), tmp32); 3459 bwn_ntab_write(mac, BWN_NTAB32(30, 3), tmp32); 3460 3461 if (mac->mac_phy.rev == 4 && 3462 bwn_current_band(mac) == BWN_BAND_5G) { 3463 BWN_RF_WRITE(mac, B2056_TX0 | B2056_TX_GMBB_IDAC, 3464 0x70); 3465 BWN_RF_WRITE(mac, B2056_TX1 | B2056_TX_GMBB_IDAC, 3466 0x70); 3467 } 3468 3469 /* Dropped probably-always-true condition */ 3470 BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS40ASSERTTHRESH0, 0x03eb); 3471 BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS40ASSERTTHRESH1, 0x03eb); 3472 BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS40DEASSERTTHRESH0, 0x0341); 3473 BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS40DEASSERTTHRESH1, 0x0341); 3474 BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20LASSERTTHRESH0, 0x042b); 3475 BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20LASSERTTHRESH1, 0x042b); 3476 BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20LDEASSERTTHRESH0, 0x0381); 3477 BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20LDEASSERTTHRESH1, 0x0381); 3478 BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20UASSERTTHRESH0, 0x042b); 3479 BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20UASSERTTHRESH1, 0x042b); 3480 BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20UDEASSERTTHRESH0, 0x0381); 3481 BWN_PHY_WRITE(mac, BWN_NPHY_ED_CRS20UDEASSERTTHRESH1, 0x0381); 3482 3483 if (mac->mac_phy.rev >= 6 && sc->sc_board_info.board_flags2 & BHND_BFL2_SINGLEANT_CCK) 3484 ; /* TODO: 0x0080000000000000 HF */ 3485 3486 return (0); 3487} 3488 3489static int bwn_nphy_workarounds_rev1_2(struct bwn_mac *mac) 3490{ 3491 struct bwn_softc *sc = mac->mac_sc; 3492 struct bwn_phy *phy = &mac->mac_phy; 3493 struct bwn_phy_n *nphy = phy->phy_n; 3494 3495 uint8_t events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 }; 3496 uint8_t delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 }; 3497 3498 uint8_t events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 }; 3499 uint8_t delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 }; 3500 3501 if (sc->sc_board_info.board_flags2 & BHND_BFL2_SKWRKFEM_BRD || 3502 sc->sc_board_info.board_type == BHND_BOARD_BCM943224M93) { 3503 delays1[0] = 0x1; 3504 delays1[5] = 0x14; 3505 } 3506 3507 if (bwn_current_band(mac) == BWN_BAND_5G && 3508 nphy->band5g_pwrgain) { 3509 BWN_RF_MASK(mac, B2055_C1_TX_RF_SPARE, ~0x8); 3510 BWN_RF_MASK(mac, B2055_C2_TX_RF_SPARE, ~0x8); 3511 } else { 3512 BWN_RF_SET(mac, B2055_C1_TX_RF_SPARE, 0x8); 3513 BWN_RF_SET(mac, B2055_C2_TX_RF_SPARE, 0x8); 3514 } 3515 3516 bwn_ntab_write(mac, BWN_NTAB16(8, 0x00), 0x000A); 3517 bwn_ntab_write(mac, BWN_NTAB16(8, 0x10), 0x000A); 3518 if (mac->mac_phy.rev < 3) { 3519 bwn_ntab_write(mac, BWN_NTAB16(8, 0x02), 0xCDAA); 3520 bwn_ntab_write(mac, BWN_NTAB16(8, 0x12), 0xCDAA); 3521 } 3522 3523 if (mac->mac_phy.rev < 2) { 3524 bwn_ntab_write(mac, BWN_NTAB16(8, 0x08), 0x0000); 3525 bwn_ntab_write(mac, BWN_NTAB16(8, 0x18), 0x0000); 3526 bwn_ntab_write(mac, BWN_NTAB16(8, 0x07), 0x7AAB); 3527 bwn_ntab_write(mac, BWN_NTAB16(8, 0x17), 0x7AAB); 3528 bwn_ntab_write(mac, BWN_NTAB16(8, 0x06), 0x0800); 3529 bwn_ntab_write(mac, BWN_NTAB16(8, 0x16), 0x0800); 3530 } 3531 3532 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); 3533 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP1, 0x301); 3534 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); 3535 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); 3536 3537 bwn_nphy_set_rf_sequence(mac, 0, events1, delays1, 7); 3538 bwn_nphy_set_rf_sequence(mac, 1, events2, delays2, 7); 3539 3540 bwn_nphy_gain_ctl_workarounds(mac); 3541 3542 if (mac->mac_phy.rev < 2) { 3543 if (BWN_PHY_READ(mac, BWN_NPHY_RXCTL) & 0x2) 3544 bwn_hf_write(mac, bwn_hf_read(mac) | 3545 BWN_HF_MLADVW); 3546 } else if (mac->mac_phy.rev == 2) { 3547 BWN_PHY_WRITE(mac, BWN_NPHY_CRSCHECK2, 0); 3548 BWN_PHY_WRITE(mac, BWN_NPHY_CRSCHECK3, 0); 3549 } 3550 3551 if (mac->mac_phy.rev < 2) 3552 BWN_PHY_MASK(mac, BWN_NPHY_SCRAM_SIGCTL, 3553 ~BWN_NPHY_SCRAM_SIGCTL_SCM); 3554 3555 /* Set phase track alpha and beta */ 3556 BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A0, 0x125); 3557 BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A1, 0x1B3); 3558 BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_A2, 0x105); 3559 BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B0, 0x16E); 3560 BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B1, 0xCD); 3561 BWN_PHY_WRITE(mac, BWN_NPHY_PHASETR_B2, 0x20); 3562 3563 if (mac->mac_phy.rev < 3) { 3564 BWN_PHY_MASK(mac, BWN_NPHY_PIL_DW1, 3565 ~BWN_NPHY_PIL_DW_64QAM & 0xFFFF); 3566 BWN_PHY_WRITE(mac, BWN_NPHY_TXF_20CO_S2B1, 0xB5); 3567 BWN_PHY_WRITE(mac, BWN_NPHY_TXF_20CO_S2B2, 0xA4); 3568 BWN_PHY_WRITE(mac, BWN_NPHY_TXF_20CO_S2B3, 0x00); 3569 } 3570 3571 if (mac->mac_phy.rev == 2) 3572 BWN_PHY_SET(mac, BWN_NPHY_FINERX2_CGC, 3573 BWN_NPHY_FINERX2_CGC_DECGC); 3574 3575 return (0); 3576} 3577 3578/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */ 3579static int bwn_nphy_workarounds(struct bwn_mac *mac) 3580{ 3581 struct bwn_phy *phy = &mac->mac_phy; 3582 struct bwn_phy_n *nphy = phy->phy_n; 3583 int error; 3584 3585 if (bwn_current_band(mac) == BWN_BAND_5G) 3586 bwn_nphy_classifier(mac, 1, 0); 3587 else 3588 bwn_nphy_classifier(mac, 1, 1); 3589 3590 if (nphy->hang_avoid) 3591 bwn_nphy_stay_in_carrier_search(mac, 1); 3592 3593 BWN_PHY_SET(mac, BWN_NPHY_IQFLIP, 3594 BWN_NPHY_IQFLIP_ADC1 | BWN_NPHY_IQFLIP_ADC2); 3595 3596 /* TODO: rev19+ */ 3597 if (mac->mac_phy.rev >= 7) 3598 error = bwn_nphy_workarounds_rev7plus(mac); 3599 else if (mac->mac_phy.rev >= 3) 3600 error = bwn_nphy_workarounds_rev3plus(mac); 3601 else 3602 error = bwn_nphy_workarounds_rev1_2(mac); 3603 3604 if (error) 3605 return (error); 3606 3607 if (nphy->hang_avoid) 3608 bwn_nphy_stay_in_carrier_search(mac, 0); 3609 3610 return (0); 3611} 3612 3613/************************************************** 3614 * Tx/Rx common 3615 **************************************************/ 3616 3617/* 3618 * Transmits a known value for LO calibration 3619 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone 3620 */ 3621static int bwn_nphy_tx_tone(struct bwn_mac *mac, uint32_t freq, uint16_t max_val, 3622 bool iqmode, bool dac_test, bool modify_bbmult) 3623{ 3624 uint16_t samp = bwn_nphy_gen_load_samples(mac, freq, max_val, dac_test); 3625 if (samp == 0) 3626 return -1; 3627 bwn_nphy_run_samples(mac, samp, 0xFFFF, 0, iqmode, dac_test, 3628 modify_bbmult); 3629 return 0; 3630} 3631 3632/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */ 3633static void bwn_nphy_update_txrx_chain(struct bwn_mac *mac) 3634{ 3635 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 3636 3637 bool override = false; 3638 uint16_t chain = 0x33; 3639 3640 if (nphy->txrx_chain == 0) { 3641 chain = 0x11; 3642 override = true; 3643 } else if (nphy->txrx_chain == 1) { 3644 chain = 0x22; 3645 override = true; 3646 } 3647 3648 BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, 3649 ~(BWN_NPHY_RFSEQCA_TXEN | BWN_NPHY_RFSEQCA_RXEN), 3650 chain); 3651 3652 if (override) 3653 BWN_PHY_SET(mac, BWN_NPHY_RFSEQMODE, 3654 BWN_NPHY_RFSEQMODE_CAOVER); 3655 else 3656 BWN_PHY_MASK(mac, BWN_NPHY_RFSEQMODE, 3657 ~BWN_NPHY_RFSEQMODE_CAOVER); 3658} 3659 3660/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */ 3661static void bwn_nphy_stop_playback(struct bwn_mac *mac) 3662{ 3663 struct bwn_phy *phy = &mac->mac_phy; 3664 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 3665 uint16_t tmp; 3666 3667 if (nphy->hang_avoid) 3668 bwn_nphy_stay_in_carrier_search(mac, 1); 3669 3670 tmp = BWN_PHY_READ(mac, BWN_NPHY_SAMP_STAT); 3671 if (tmp & 0x1) 3672 BWN_PHY_SET(mac, BWN_NPHY_SAMP_CMD, BWN_NPHY_SAMP_CMD_STOP); 3673 else if (tmp & 0x2) 3674 BWN_PHY_MASK(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0x7FFF); 3675 3676 BWN_PHY_MASK(mac, BWN_NPHY_SAMP_CMD, ~0x0004); 3677 3678 if (nphy->bb_mult_save & 0x80000000) { 3679 tmp = nphy->bb_mult_save & 0xFFFF; 3680 bwn_ntab_write(mac, BWN_NTAB16(15, 87), tmp); 3681 nphy->bb_mult_save = 0; 3682 } 3683 3684 if (phy->rev >= 7 && nphy->lpf_bw_overrode_for_sample_play) { 3685 if (phy->rev >= 19) 3686 bwn_nphy_rf_ctl_override_rev19(mac, 0x80, 0, 0, true, 3687 1); 3688 else 3689 bwn_nphy_rf_ctl_override_rev7(mac, 0x80, 0, 0, true, 1); 3690 nphy->lpf_bw_overrode_for_sample_play = false; 3691 } 3692 3693 if (nphy->hang_avoid) 3694 bwn_nphy_stay_in_carrier_search(mac, 0); 3695} 3696 3697/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IqCalGainParams */ 3698static void bwn_nphy_iq_cal_gain_params(struct bwn_mac *mac, uint16_t core, 3699 struct bwn_nphy_txgains target, 3700 struct bwn_nphy_iqcal_params *params) 3701{ 3702 struct bwn_phy *phy = &mac->mac_phy; 3703 int i, j, indx; 3704 uint16_t gain; 3705 3706 if (mac->mac_phy.rev >= 3) { 3707 params->tx_lpf = target.tx_lpf[core]; /* Rev 7+ */ 3708 params->txgm = target.txgm[core]; 3709 params->pga = target.pga[core]; 3710 params->pad = target.pad[core]; 3711 params->ipa = target.ipa[core]; 3712 if (phy->rev >= 19) { 3713 /* TODO */ 3714 } else if (phy->rev >= 7) { 3715 params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 3) | (params->ipa) | (params->tx_lpf << 15); 3716 } else { 3717 params->cal_gain = (params->txgm << 12) | (params->pga << 8) | (params->pad << 4) | (params->ipa); 3718 } 3719 for (j = 0; j < 5; j++) 3720 params->ncorr[j] = 0x79; 3721 } else { 3722 gain = (target.pad[core]) | (target.pga[core] << 4) | 3723 (target.txgm[core] << 8); 3724 3725 indx = (bwn_current_band(mac) == BWN_BAND_5G) ? 3726 1 : 0; 3727 for (i = 0; i < 9; i++) 3728 if (tbl_iqcal_gainparams[indx][i][0] == gain) 3729 break; 3730 i = min(i, 8); 3731 3732 params->txgm = tbl_iqcal_gainparams[indx][i][1]; 3733 params->pga = tbl_iqcal_gainparams[indx][i][2]; 3734 params->pad = tbl_iqcal_gainparams[indx][i][3]; 3735 params->cal_gain = (params->txgm << 7) | (params->pga << 4) | 3736 (params->pad << 2); 3737 for (j = 0; j < 4; j++) 3738 params->ncorr[j] = tbl_iqcal_gainparams[indx][i][4 + j]; 3739 } 3740} 3741 3742/************************************************** 3743 * Tx and Rx 3744 **************************************************/ 3745 3746/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */ 3747static void bwn_nphy_tx_power_ctrl(struct bwn_mac *mac, bool enable) 3748{ 3749 struct bwn_phy *phy = &mac->mac_phy; 3750 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 3751 uint8_t i; 3752 uint16_t bmask, val, tmp; 3753 bwn_band_t band = bwn_current_band(mac); 3754 3755 if (nphy->hang_avoid) 3756 bwn_nphy_stay_in_carrier_search(mac, 1); 3757 3758 nphy->txpwrctrl = enable; 3759 if (!enable) { 3760 if (mac->mac_phy.rev >= 3 && 3761 (BWN_PHY_READ(mac, BWN_NPHY_TXPCTL_CMD) & 3762 (BWN_NPHY_TXPCTL_CMD_COEFF | 3763 BWN_NPHY_TXPCTL_CMD_HWPCTLEN | 3764 BWN_NPHY_TXPCTL_CMD_PCTLEN))) { 3765 /* We disable enabled TX pwr ctl, save it's state */ 3766 nphy->tx_pwr_idx[0] = BWN_PHY_READ(mac, 3767 BWN_NPHY_C1_TXPCTL_STAT) & 0x7f; 3768 nphy->tx_pwr_idx[1] = BWN_PHY_READ(mac, 3769 BWN_NPHY_C2_TXPCTL_STAT) & 0x7f; 3770 } 3771 3772 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x6840); 3773 for (i = 0; i < 84; i++) 3774 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0); 3775 3776 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 0x6C40); 3777 for (i = 0; i < 84; i++) 3778 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 0); 3779 3780 tmp = BWN_NPHY_TXPCTL_CMD_COEFF | BWN_NPHY_TXPCTL_CMD_HWPCTLEN; 3781 if (mac->mac_phy.rev >= 3) 3782 tmp |= BWN_NPHY_TXPCTL_CMD_PCTLEN; 3783 BWN_PHY_MASK(mac, BWN_NPHY_TXPCTL_CMD, ~tmp); 3784 3785 if (mac->mac_phy.rev >= 3) { 3786 BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER1, 0x0100); 3787 BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x0100); 3788 } else { 3789 BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x4000); 3790 } 3791 3792 if (mac->mac_phy.rev == 2) 3793 BWN_PHY_SETMASK(mac, BWN_NPHY_BPHY_CTL3, 3794 ~BWN_NPHY_BPHY_CTL3_SCALE, 0x53); 3795 else if (mac->mac_phy.rev < 2) 3796 BWN_PHY_SETMASK(mac, BWN_NPHY_BPHY_CTL3, 3797 ~BWN_NPHY_BPHY_CTL3_SCALE, 0x5A); 3798 3799 if (mac->mac_phy.rev < 2 && bwn_is_40mhz(mac)) 3800 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN); 3801 } else { 3802 bwn_ntab_write_bulk(mac, BWN_NTAB16(26, 64), 84, 3803 nphy->adj_pwr_tbl); 3804 bwn_ntab_write_bulk(mac, BWN_NTAB16(27, 64), 84, 3805 nphy->adj_pwr_tbl); 3806 3807 bmask = BWN_NPHY_TXPCTL_CMD_COEFF | 3808 BWN_NPHY_TXPCTL_CMD_HWPCTLEN; 3809 /* wl does useless check for "enable" param here */ 3810 val = BWN_NPHY_TXPCTL_CMD_COEFF | BWN_NPHY_TXPCTL_CMD_HWPCTLEN; 3811 if (mac->mac_phy.rev >= 3) { 3812 bmask |= BWN_NPHY_TXPCTL_CMD_PCTLEN; 3813 if (val) 3814 val |= BWN_NPHY_TXPCTL_CMD_PCTLEN; 3815 } 3816 BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD, ~(bmask), val); 3817 3818 if (band == BWN_BAND_5G) { 3819 if (phy->rev >= 19) { 3820 /* TODO */ 3821 } else if (phy->rev >= 7) { 3822 BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD, 3823 ~BWN_NPHY_TXPCTL_CMD_INIT, 3824 0x32); 3825 BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_INIT, 3826 ~BWN_NPHY_TXPCTL_INIT_PIDXI1, 3827 0x32); 3828 } else { 3829 BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD, 3830 ~BWN_NPHY_TXPCTL_CMD_INIT, 3831 0x64); 3832 if (phy->rev > 1) 3833 BWN_PHY_SETMASK(mac, 3834 BWN_NPHY_TXPCTL_INIT, 3835 ~BWN_NPHY_TXPCTL_INIT_PIDXI1, 3836 0x64); 3837 } 3838 } 3839 3840 if (mac->mac_phy.rev >= 3) { 3841 if (nphy->tx_pwr_idx[0] != 128 && 3842 nphy->tx_pwr_idx[1] != 128) { 3843 /* Recover TX pwr ctl state */ 3844 BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD, 3845 ~BWN_NPHY_TXPCTL_CMD_INIT, 3846 nphy->tx_pwr_idx[0]); 3847 if (mac->mac_phy.rev > 1) 3848 BWN_PHY_SETMASK(mac, 3849 BWN_NPHY_TXPCTL_INIT, 3850 ~0xff, nphy->tx_pwr_idx[1]); 3851 } 3852 } 3853 3854 if (phy->rev >= 7) { 3855 /* TODO */ 3856 } 3857 3858 if (mac->mac_phy.rev >= 3) { 3859 BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER1, ~0x100); 3860 BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER, ~0x100); 3861 } else { 3862 BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_OVER, ~0x4000); 3863 } 3864 3865 if (mac->mac_phy.rev == 2) 3866 BWN_PHY_SETMASK(mac, BWN_NPHY_BPHY_CTL3, ~0xFF, 0x3b); 3867 else if (mac->mac_phy.rev < 2) 3868 BWN_PHY_SETMASK(mac, BWN_NPHY_BPHY_CTL3, ~0xFF, 0x40); 3869 3870 if (mac->mac_phy.rev < 2 && bwn_is_40mhz(mac)) 3871 bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_TSSI_RESET_PSM_WORKAROUN); 3872 3873 if (bwn_nphy_ipa(mac)) { 3874 BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN0, ~0x4); 3875 BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN1, ~0x4); 3876 } 3877 } 3878 3879 if (nphy->hang_avoid) 3880 bwn_nphy_stay_in_carrier_search(mac, 0); 3881} 3882 3883/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrFix */ 3884static int bwn_nphy_tx_power_fix(struct bwn_mac *mac) 3885{ 3886 struct bwn_softc *sc = mac->mac_sc; 3887 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 3888 3889 uint8_t txpi[2], bbmult, i; 3890 uint16_t tmp, radio_gain, dac_gain; 3891 uint16_t freq = bwn_get_centre_freq(mac); 3892 uint32_t txgain; 3893 /* uint32_t gaintbl; rev3+ */ 3894 3895 if (nphy->hang_avoid) 3896 bwn_nphy_stay_in_carrier_search(mac, 1); 3897 3898 /* TODO: rev19+ */ 3899 if (mac->mac_phy.rev >= 7) { 3900 txpi[0] = txpi[1] = 30; 3901 } else if (mac->mac_phy.rev >= 3) { 3902 txpi[0] = 40; 3903 txpi[1] = 40; 3904 } else if (sc->sc_board_info.board_srom_rev < 4) { 3905 txpi[0] = 72; 3906 txpi[1] = 72; 3907 } else if (sc->sc_board_info.board_srom_rev > 7) { 3908 txpi[0] = 0; 3909 txpi[1] = 0; 3910 } else { 3911#define BWN_NPHY_GET_TXPI(_name, _result) \ 3912do { \ 3913 int error; \ 3914 error = bhnd_nvram_getvar_uint8(sc->sc_dev, (_name), \ 3915 (_result)); \ 3916 if (error) { \ 3917 device_printf(sc->sc_dev, "NVRAM variable %s " \ 3918 "unreadable: %d\n", (_name), error); \ 3919 return (error); \ 3920 } \ 3921} while(0) 3922 3923 if (bwn_current_band(mac) == BWN_BAND_2G) { 3924 BWN_NPHY_GET_TXPI(BHND_NVAR_TXPID2GA0, &txpi[0]); 3925 BWN_NPHY_GET_TXPI(BHND_NVAR_TXPID2GA1, &txpi[1]); 3926 } else if (freq >= 4900 && freq < 5100) { 3927 BWN_NPHY_GET_TXPI(BHND_NVAR_TXPID5GLA0, &txpi[0]); 3928 BWN_NPHY_GET_TXPI(BHND_NVAR_TXPID5GLA1, &txpi[1]); 3929 } else if (freq >= 5100 && freq < 5500) { 3930 BWN_NPHY_GET_TXPI(BHND_NVAR_TXPID5GA0, &txpi[0]); 3931 BWN_NPHY_GET_TXPI(BHND_NVAR_TXPID5GA1, &txpi[1]); 3932 } else if (freq >= 5500) { 3933 BWN_NPHY_GET_TXPI(BHND_NVAR_TXPID5GHA0, &txpi[0]); 3934 BWN_NPHY_GET_TXPI(BHND_NVAR_TXPID5GHA1, &txpi[1]); 3935 } else { 3936 txpi[0] = 91; 3937 txpi[1] = 91; 3938 } 3939 3940#undef BWN_NPHY_GET_TXPI 3941 } 3942 if (mac->mac_phy.rev < 7 && 3943 (txpi[0] < 40 || txpi[0] > 100 || txpi[1] < 40 || txpi[1] > 100)) 3944 txpi[0] = txpi[1] = 91; 3945 3946 /* 3947 for (i = 0; i < 2; i++) { 3948 nphy->txpwrindex[i].index_internal = txpi[i]; 3949 nphy->txpwrindex[i].index_internal_save = txpi[i]; 3950 } 3951 */ 3952 3953 for (i = 0; i < 2; i++) { 3954 const uint32_t *table = bwn_nphy_get_tx_gain_table(mac); 3955 3956 if (!table) 3957 break; 3958 txgain = *(table + txpi[i]); 3959 3960 if (mac->mac_phy.rev >= 3) 3961 radio_gain = (txgain >> 16) & 0x1FFFF; 3962 else 3963 radio_gain = (txgain >> 16) & 0x1FFF; 3964 3965 if (mac->mac_phy.rev >= 7) 3966 dac_gain = (txgain >> 8) & 0x7; 3967 else 3968 dac_gain = (txgain >> 8) & 0x3F; 3969 bbmult = txgain & 0xFF; 3970 3971 if (mac->mac_phy.rev >= 3) { 3972 if (i == 0) 3973 BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER1, 0x0100); 3974 else 3975 BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x0100); 3976 } else { 3977 BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x4000); 3978 } 3979 3980 if (i == 0) 3981 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_DACGAIN1, dac_gain); 3982 else 3983 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_DACGAIN2, dac_gain); 3984 3985 bwn_ntab_write(mac, BWN_NTAB16(0x7, 0x110 + i), radio_gain); 3986 3987 tmp = bwn_ntab_read(mac, BWN_NTAB16(0xF, 0x57)); 3988 if (i == 0) 3989 tmp = (tmp & 0x00FF) | (bbmult << 8); 3990 else 3991 tmp = (tmp & 0xFF00) | bbmult; 3992 bwn_ntab_write(mac, BWN_NTAB16(0xF, 0x57), tmp); 3993 3994 if (bwn_nphy_ipa(mac)) { 3995 uint32_t tmp32; 3996 uint16_t reg = (i == 0) ? 3997 BWN_NPHY_PAPD_EN0 : BWN_NPHY_PAPD_EN1; 3998 tmp32 = bwn_ntab_read(mac, BWN_NTAB32(26 + i, 3999 576 + txpi[i])); 4000 BWN_PHY_SETMASK(mac, reg, 0xE00F, (uint32_t) tmp32 << 4); 4001 BWN_PHY_SET(mac, reg, 0x4); 4002 } 4003 } 4004 4005 BWN_PHY_MASK(mac, BWN_NPHY_BPHY_CTL2, ~BWN_NPHY_BPHY_CTL2_LUT); 4006 4007 if (nphy->hang_avoid) 4008 bwn_nphy_stay_in_carrier_search(mac, 0); 4009 4010 return (0); 4011} 4012 4013static void bwn_nphy_ipa_internal_tssi_setup(struct bwn_mac *mac) 4014{ 4015 struct bwn_phy *phy = &mac->mac_phy; 4016 4017 uint8_t core; 4018 uint16_t r; /* routing */ 4019 4020 if (phy->rev >= 19) { 4021 /* TODO */ 4022 } else if (phy->rev >= 7) { 4023 for (core = 0; core < 2; core++) { 4024 r = core ? 0x190 : 0x170; 4025 if (bwn_current_band(mac) == BWN_BAND_2G) { 4026 BWN_RF_WRITE(mac, r + 0x5, 0x5); 4027 BWN_RF_WRITE(mac, r + 0x9, 0xE); 4028 if (phy->rev != 5) 4029 BWN_RF_WRITE(mac, r + 0xA, 0); 4030 if (phy->rev != 7) 4031 BWN_RF_WRITE(mac, r + 0xB, 1); 4032 else 4033 BWN_RF_WRITE(mac, r + 0xB, 0x31); 4034 } else { 4035 BWN_RF_WRITE(mac, r + 0x5, 0x9); 4036 BWN_RF_WRITE(mac, r + 0x9, 0xC); 4037 BWN_RF_WRITE(mac, r + 0xB, 0x0); 4038 if (phy->rev != 5) 4039 BWN_RF_WRITE(mac, r + 0xA, 1); 4040 else 4041 BWN_RF_WRITE(mac, r + 0xA, 0x31); 4042 } 4043 BWN_RF_WRITE(mac, r + 0x6, 0); 4044 BWN_RF_WRITE(mac, r + 0x7, 0); 4045 BWN_RF_WRITE(mac, r + 0x8, 3); 4046 BWN_RF_WRITE(mac, r + 0xC, 0); 4047 } 4048 } else { 4049 if (bwn_current_band(mac) == BWN_BAND_2G) 4050 BWN_RF_WRITE(mac, B2056_SYN_RESERVED_ADDR31, 0x128); 4051 else 4052 BWN_RF_WRITE(mac, B2056_SYN_RESERVED_ADDR31, 0x80); 4053 BWN_RF_WRITE(mac, B2056_SYN_RESERVED_ADDR30, 0); 4054 BWN_RF_WRITE(mac, B2056_SYN_GPIO_MASTER1, 0x29); 4055 4056 for (core = 0; core < 2; core++) { 4057 r = core ? B2056_TX1 : B2056_TX0; 4058 4059 BWN_RF_WRITE(mac, r | B2056_TX_IQCAL_VCM_HG, 0); 4060 BWN_RF_WRITE(mac, r | B2056_TX_IQCAL_IDAC, 0); 4061 BWN_RF_WRITE(mac, r | B2056_TX_TSSI_VCM, 3); 4062 BWN_RF_WRITE(mac, r | B2056_TX_TX_AMP_DET, 0); 4063 BWN_RF_WRITE(mac, r | B2056_TX_TSSI_MISC1, 8); 4064 BWN_RF_WRITE(mac, r | B2056_TX_TSSI_MISC2, 0); 4065 BWN_RF_WRITE(mac, r | B2056_TX_TSSI_MISC3, 0); 4066 if (bwn_current_band(mac) == BWN_BAND_2G) { 4067 BWN_RF_WRITE(mac, r | B2056_TX_TX_SSI_MASTER, 4068 0x5); 4069 if (phy->rev != 5) 4070 BWN_RF_WRITE(mac, r | B2056_TX_TSSIA, 4071 0x00); 4072 if (phy->rev >= 5) 4073 BWN_RF_WRITE(mac, r | B2056_TX_TSSIG, 4074 0x31); 4075 else 4076 BWN_RF_WRITE(mac, r | B2056_TX_TSSIG, 4077 0x11); 4078 BWN_RF_WRITE(mac, r | B2056_TX_TX_SSI_MUX, 4079 0xE); 4080 } else { 4081 BWN_RF_WRITE(mac, r | B2056_TX_TX_SSI_MASTER, 4082 0x9); 4083 BWN_RF_WRITE(mac, r | B2056_TX_TSSIA, 0x31); 4084 BWN_RF_WRITE(mac, r | B2056_TX_TSSIG, 0x0); 4085 BWN_RF_WRITE(mac, r | B2056_TX_TX_SSI_MUX, 4086 0xC); 4087 } 4088 } 4089 } 4090} 4091 4092/* 4093 * Stop radio and transmit known signal. Then check received signal strength to 4094 * get TSSI (Transmit Signal Strength Indicator). 4095 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlIdleTssi 4096 */ 4097static void bwn_nphy_tx_power_ctl_idle_tssi(struct bwn_mac *mac) 4098{ 4099 struct bwn_phy *phy = &mac->mac_phy; 4100 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4101 4102 uint32_t tmp; 4103 int32_t rssi[4] = { }; 4104 4105 if (bwn_is_chan_passive(mac)) 4106 return; 4107 4108 if (bwn_nphy_ipa(mac)) 4109 bwn_nphy_ipa_internal_tssi_setup(mac); 4110 4111 if (phy->rev >= 19) 4112 bwn_nphy_rf_ctl_override_rev19(mac, 0x1000, 0, 3, false, 0); 4113 else if (phy->rev >= 7) 4114 bwn_nphy_rf_ctl_override_rev7(mac, 0x1000, 0, 3, false, 0); 4115 else if (phy->rev >= 3) 4116 bwn_nphy_rf_ctl_override(mac, 0x2000, 0, 3, false); 4117 4118 bwn_nphy_stop_playback(mac); 4119 bwn_nphy_tx_tone(mac, 4000, 0, false, false, false); 4120 DELAY(20); 4121 tmp = bwn_nphy_poll_rssi(mac, N_RSSI_TSSI_2G, rssi, 1); 4122 bwn_nphy_stop_playback(mac); 4123 4124 bwn_nphy_rssi_select(mac, 0, N_RSSI_W1); 4125 4126 if (phy->rev >= 19) 4127 bwn_nphy_rf_ctl_override_rev19(mac, 0x1000, 0, 3, true, 0); 4128 else if (phy->rev >= 7) 4129 bwn_nphy_rf_ctl_override_rev7(mac, 0x1000, 0, 3, true, 0); 4130 else if (phy->rev >= 3) 4131 bwn_nphy_rf_ctl_override(mac, 0x2000, 0, 3, true); 4132 4133 if (phy->rev >= 19) { 4134 /* TODO */ 4135 return; 4136 } else if (phy->rev >= 3) { 4137 nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 24) & 0xFF; 4138 nphy->pwr_ctl_info[1].idle_tssi_5g = (tmp >> 8) & 0xFF; 4139 } else { 4140 nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 16) & 0xFF; 4141 nphy->pwr_ctl_info[1].idle_tssi_5g = tmp & 0xFF; 4142 } 4143 nphy->pwr_ctl_info[0].idle_tssi_2g = (tmp >> 24) & 0xFF; 4144 nphy->pwr_ctl_info[1].idle_tssi_2g = (tmp >> 8) & 0xFF; 4145} 4146 4147/* http://bcm-v4.sipsolutions.net/PHY/N/TxPwrLimitToTbl */ 4148static void bwn_nphy_tx_prepare_adjusted_power_table(struct bwn_mac *mac) 4149{ 4150 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4151 4152 uint8_t idx, delta; 4153 uint8_t i, stf_mode; 4154 4155 /* Array adj_pwr_tbl corresponds to the hardware table. It consists of 4156 * 21 groups, each containing 4 entries. 4157 * 4158 * First group has entries for CCK modulation. 4159 * The rest of groups has 1 entry per modulation (SISO, CDD, STBC, SDM). 4160 * 4161 * Group 0 is for CCK 4162 * Groups 1..4 use BPSK (group per coding rate) 4163 * Groups 5..8 use QPSK (group per coding rate) 4164 * Groups 9..12 use 16-QAM (group per coding rate) 4165 * Groups 13..16 use 64-QAM (group per coding rate) 4166 * Groups 17..20 are unknown 4167 */ 4168 4169 for (i = 0; i < 4; i++) 4170 nphy->adj_pwr_tbl[i] = nphy->tx_power_offset[i]; 4171 4172 for (stf_mode = 0; stf_mode < 4; stf_mode++) { 4173 delta = 0; 4174 switch (stf_mode) { 4175 case 0: 4176 if (bwn_is_40mhz(mac) && mac->mac_phy.rev >= 5) { 4177 idx = 68; 4178 } else { 4179 delta = 1; 4180 idx = bwn_is_40mhz(mac) ? 52 : 4; 4181 } 4182 break; 4183 case 1: 4184 idx = bwn_is_40mhz(mac) ? 76 : 28; 4185 break; 4186 case 2: 4187 idx = bwn_is_40mhz(mac) ? 84 : 36; 4188 break; 4189 case 3: 4190 idx = bwn_is_40mhz(mac) ? 92 : 44; 4191 break; 4192 } 4193 4194 for (i = 0; i < 20; i++) { 4195 nphy->adj_pwr_tbl[4 + 4 * i + stf_mode] = 4196 nphy->tx_power_offset[idx]; 4197 if (i == 0) 4198 idx += delta; 4199 if (i == 14) 4200 idx += 1 - delta; 4201 if (i == 3 || i == 4 || i == 7 || i == 8 || i == 11 || 4202 i == 13) 4203 idx += 1; 4204 } 4205 } 4206} 4207 4208/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlSetup */ 4209static void bwn_nphy_tx_power_ctl_setup(struct bwn_mac *mac) 4210{ 4211 struct bwn_softc *sc = mac->mac_sc; 4212 struct bwn_phy *phy = &mac->mac_phy; 4213 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4214 struct bwn_phy_n_core_pwr_info core_pwr_info[4]; 4215 int n; 4216 4217 int16_t a1[2], b0[2], b1[2]; 4218 uint8_t idle[2]; 4219 uint8_t ppr_max; 4220 int8_t target[2]; 4221 int32_t num, den, pwr; 4222 uint32_t regval[64]; 4223 4224 uint16_t freq = bwn_get_centre_freq(mac); 4225 uint16_t tmp; 4226 uint16_t r; /* routing */ 4227 uint8_t i, c; 4228 4229 for (n = 0; n < 4; n++) { 4230 bzero(&core_pwr_info[n], sizeof(core_pwr_info[n])); 4231 if (bwn_nphy_get_core_power_info(mac, n, 4232 &core_pwr_info[n]) != 0) { 4233 BWN_ERRPRINTF(mac->mac_sc, 4234 "%s: failed to get core_pwr_info for core %d\n", 4235 __func__, 4236 n); 4237 } 4238 } 4239 4240 if (bhnd_get_hwrev(sc->sc_dev) == 11 || bhnd_get_hwrev(sc->sc_dev) == 12) { 4241 BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~0, 0x200000); 4242 BWN_READ_4(mac, BWN_MACCTL); 4243 DELAY(1); 4244 } 4245 4246 if (nphy->hang_avoid) 4247 bwn_nphy_stay_in_carrier_search(mac, true); 4248 4249 BWN_PHY_SET(mac, BWN_NPHY_TSSIMODE, BWN_NPHY_TSSIMODE_EN); 4250 if (mac->mac_phy.rev >= 3) 4251 BWN_PHY_MASK(mac, BWN_NPHY_TXPCTL_CMD, 4252 ~BWN_NPHY_TXPCTL_CMD_PCTLEN & 0xFFFF); 4253 else 4254 BWN_PHY_SET(mac, BWN_NPHY_TXPCTL_CMD, 4255 BWN_NPHY_TXPCTL_CMD_PCTLEN); 4256 4257 if (bhnd_get_hwrev(sc->sc_dev) == 11 || bhnd_get_hwrev(sc->sc_dev) == 12) 4258 BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~0x200000, 0); 4259 4260 /* 4261 * XXX TODO: see if those bandsbelow map to 5g-lo, 5g-mid, 5g-hi in 4262 * any way. 4263 */ 4264 if (sc->sc_board_info.board_srom_rev < 4) { 4265 idle[0] = nphy->pwr_ctl_info[0].idle_tssi_2g; 4266 idle[1] = nphy->pwr_ctl_info[1].idle_tssi_2g; 4267 target[0] = target[1] = 52; 4268 a1[0] = a1[1] = -424; 4269 b0[0] = b0[1] = 5612; 4270 b1[0] = b1[1] = -1393; 4271 } else { 4272 if (bwn_current_band(mac) == BWN_BAND_2G) { 4273 for (c = 0; c < 2; c++) { 4274 idle[c] = nphy->pwr_ctl_info[c].idle_tssi_2g; 4275 target[c] = core_pwr_info[c].maxpwr_2g; 4276 a1[c] = core_pwr_info[c].pa_2g[0]; 4277 b0[c] = core_pwr_info[c].pa_2g[1]; 4278 b1[c] = core_pwr_info[c].pa_2g[2]; 4279 } 4280 } else if (freq >= 4900 && freq < 5100) { 4281 for (c = 0; c < 2; c++) { 4282 idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g; 4283 target[c] = core_pwr_info[c].maxpwr_5gl; 4284 a1[c] = core_pwr_info[c].pa_5gl[0]; 4285 b0[c] = core_pwr_info[c].pa_5gl[1]; 4286 b1[c] = core_pwr_info[c].pa_5gl[2]; 4287 } 4288 } else if (freq >= 5100 && freq < 5500) { 4289 for (c = 0; c < 2; c++) { 4290 idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g; 4291 target[c] = core_pwr_info[c].maxpwr_5g; 4292 a1[c] = core_pwr_info[c].pa_5g[0]; 4293 b0[c] = core_pwr_info[c].pa_5g[1]; 4294 b1[c] = core_pwr_info[c].pa_5g[2]; 4295 } 4296 } else if (freq >= 5500) { 4297 for (c = 0; c < 2; c++) { 4298 idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g; 4299 target[c] = core_pwr_info[c].maxpwr_5gh; 4300 a1[c] = core_pwr_info[c].pa_5gh[0]; 4301 b0[c] = core_pwr_info[c].pa_5gh[1]; 4302 b1[c] = core_pwr_info[c].pa_5gh[2]; 4303 } 4304 } else { 4305 idle[0] = nphy->pwr_ctl_info[0].idle_tssi_5g; 4306 idle[1] = nphy->pwr_ctl_info[1].idle_tssi_5g; 4307 target[0] = target[1] = 52; 4308 a1[0] = a1[1] = -424; 4309 b0[0] = b0[1] = 5612; 4310 b1[0] = b1[1] = -1393; 4311 } 4312 } 4313 4314 ppr_max = bwn_ppr_get_max(mac, &nphy->tx_pwr_max_ppr); 4315 if (ppr_max) { 4316 target[0] = ppr_max; 4317 target[1] = ppr_max; 4318 } 4319 4320 if (mac->mac_phy.rev >= 3) { 4321 if (nphy->tsspos_2g) 4322 BWN_PHY_SET(mac, BWN_NPHY_TXPCTL_ITSSI, 0x4000); 4323 if (mac->mac_phy.rev >= 7) { 4324 for (c = 0; c < 2; c++) { 4325 r = c ? 0x190 : 0x170; 4326 if (bwn_nphy_ipa(mac)) 4327 BWN_RF_WRITE(mac, r + 0x9, (bwn_current_band(mac) == BWN_BAND_2G) ? 0xE : 0xC); 4328 } 4329 } else { 4330 if (bwn_nphy_ipa(mac)) { 4331 tmp = (bwn_current_band(mac) == BWN_BAND_5G) ? 0xC : 0xE; 4332 BWN_RF_WRITE(mac, 4333 B2056_TX0 | B2056_TX_TX_SSI_MUX, tmp); 4334 BWN_RF_WRITE(mac, 4335 B2056_TX1 | B2056_TX_TX_SSI_MUX, tmp); 4336 } else { 4337 BWN_RF_WRITE(mac, 4338 B2056_TX0 | B2056_TX_TX_SSI_MUX, 0x11); 4339 BWN_RF_WRITE(mac, 4340 B2056_TX1 | B2056_TX_TX_SSI_MUX, 0x11); 4341 } 4342 } 4343 } 4344 4345 if (bhnd_get_hwrev(sc->sc_dev) == 11 || bhnd_get_hwrev(sc->sc_dev) == 12) { 4346 BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~0, 0x200000); 4347 BWN_READ_4(mac, BWN_MACCTL); 4348 DELAY(1); 4349 } 4350 4351 if (phy->rev >= 19) { 4352 /* TODO */ 4353 } else if (phy->rev >= 7) { 4354 BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD, 4355 ~BWN_NPHY_TXPCTL_CMD_INIT, 0x19); 4356 BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_INIT, 4357 ~BWN_NPHY_TXPCTL_INIT_PIDXI1, 0x19); 4358 } else { 4359 BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_CMD, 4360 ~BWN_NPHY_TXPCTL_CMD_INIT, 0x40); 4361 if (mac->mac_phy.rev > 1) 4362 BWN_PHY_SETMASK(mac, BWN_NPHY_TXPCTL_INIT, 4363 ~BWN_NPHY_TXPCTL_INIT_PIDXI1, 0x40); 4364 } 4365 4366 if (bhnd_get_hwrev(sc->sc_dev) == 11 || bhnd_get_hwrev(sc->sc_dev) == 12) 4367 BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~0x200000, 0); 4368 4369 BWN_PHY_WRITE(mac, BWN_NPHY_TXPCTL_N, 4370 0xF0 << BWN_NPHY_TXPCTL_N_TSSID_SHIFT | 4371 3 << BWN_NPHY_TXPCTL_N_NPTIL2_SHIFT); 4372 BWN_PHY_WRITE(mac, BWN_NPHY_TXPCTL_ITSSI, 4373 idle[0] << BWN_NPHY_TXPCTL_ITSSI_0_SHIFT | 4374 idle[1] << BWN_NPHY_TXPCTL_ITSSI_1_SHIFT | 4375 BWN_NPHY_TXPCTL_ITSSI_BINF); 4376 BWN_PHY_WRITE(mac, BWN_NPHY_TXPCTL_TPWR, 4377 target[0] << BWN_NPHY_TXPCTL_TPWR_0_SHIFT | 4378 target[1] << BWN_NPHY_TXPCTL_TPWR_1_SHIFT); 4379 4380 for (c = 0; c < 2; c++) { 4381 for (i = 0; i < 64; i++) { 4382 num = 8 * (16 * b0[c] + b1[c] * i); 4383 den = 32768 + a1[c] * i; 4384 pwr = max((4 * num + den / 2) / den, -8); 4385 if (mac->mac_phy.rev < 3 && (i <= (31 - idle[c] + 1))) 4386 pwr = max(pwr, target[c] + 1); 4387 regval[i] = pwr; 4388 } 4389 bwn_ntab_write_bulk(mac, BWN_NTAB32(26 + c, 0), 64, regval); 4390 } 4391 4392 bwn_nphy_tx_prepare_adjusted_power_table(mac); 4393 bwn_ntab_write_bulk(mac, BWN_NTAB16(26, 64), 84, nphy->adj_pwr_tbl); 4394 bwn_ntab_write_bulk(mac, BWN_NTAB16(27, 64), 84, nphy->adj_pwr_tbl); 4395 4396 if (nphy->hang_avoid) 4397 bwn_nphy_stay_in_carrier_search(mac, false); 4398} 4399 4400static void bwn_nphy_tx_gain_table_upload(struct bwn_mac *mac) 4401{ 4402 struct bwn_phy *phy = &mac->mac_phy; 4403 4404 const uint32_t *table = NULL; 4405 uint32_t rfpwr_offset; 4406 uint8_t pga_gain, pad_gain; 4407 int i; 4408 const int16_t *rf_pwr_offset_table = NULL; 4409 4410 table = bwn_nphy_get_tx_gain_table(mac); 4411 if (!table) 4412 return; 4413 4414 bwn_ntab_write_bulk(mac, BWN_NTAB32(26, 192), 128, table); 4415 bwn_ntab_write_bulk(mac, BWN_NTAB32(27, 192), 128, table); 4416 4417 if (phy->rev < 3) 4418 return; 4419 4420#if 0 4421 nphy->gmval = (table[0] >> 16) & 0x7000; 4422#endif 4423 4424 if (phy->rev >= 19) { 4425 return; 4426 } else if (phy->rev >= 7) { 4427 rf_pwr_offset_table = bwn_ntab_get_rf_pwr_offset_table(mac); 4428 if (!rf_pwr_offset_table) 4429 return; 4430 /* TODO: Enable this once we have gains configured */ 4431 return; 4432 } 4433 4434 for (i = 0; i < 128; i++) { 4435 if (phy->rev >= 19) { 4436 /* TODO */ 4437 return; 4438 } else if (phy->rev >= 7) { 4439 pga_gain = (table[i] >> 24) & 0xf; 4440 pad_gain = (table[i] >> 19) & 0x1f; 4441 if (bwn_current_band(mac) == BWN_BAND_2G) 4442 rfpwr_offset = rf_pwr_offset_table[pad_gain]; 4443 else 4444 rfpwr_offset = rf_pwr_offset_table[pga_gain]; 4445 } else { 4446 pga_gain = (table[i] >> 24) & 0xF; 4447 if (bwn_current_band(mac) == BWN_BAND_2G) 4448 rfpwr_offset = bwn_ntab_papd_pga_gain_delta_ipa_2g[pga_gain]; 4449 else 4450 rfpwr_offset = 0; /* FIXME */ 4451 } 4452 4453 bwn_ntab_write(mac, BWN_NTAB32(26, 576 + i), rfpwr_offset); 4454 bwn_ntab_write(mac, BWN_NTAB32(27, 576 + i), rfpwr_offset); 4455 } 4456} 4457 4458/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */ 4459static void bwn_nphy_pa_override(struct bwn_mac *mac, bool enable) 4460{ 4461 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4462 bwn_band_t band; 4463 uint16_t tmp; 4464 4465 if (!enable) { 4466 nphy->rfctrl_intc1_save = BWN_PHY_READ(mac, 4467 BWN_NPHY_RFCTL_INTC1); 4468 nphy->rfctrl_intc2_save = BWN_PHY_READ(mac, 4469 BWN_NPHY_RFCTL_INTC2); 4470 band = bwn_current_band(mac); 4471 if (mac->mac_phy.rev >= 7) { 4472 tmp = 0x1480; 4473 } else if (mac->mac_phy.rev >= 3) { 4474 if (band == BWN_BAND_5G) 4475 tmp = 0x600; 4476 else 4477 tmp = 0x480; 4478 } else { 4479 if (band == BWN_BAND_5G) 4480 tmp = 0x180; 4481 else 4482 tmp = 0x120; 4483 } 4484 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, tmp); 4485 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, tmp); 4486 } else { 4487 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, 4488 nphy->rfctrl_intc1_save); 4489 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, 4490 nphy->rfctrl_intc2_save); 4491 } 4492} 4493 4494/* 4495 * TX low-pass filter bandwidth setup 4496 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw 4497 */ 4498static void bwn_nphy_tx_lpf_bw(struct bwn_mac *mac) 4499{ 4500 uint16_t tmp; 4501 4502 if (mac->mac_phy.rev < 3 || mac->mac_phy.rev >= 7) 4503 return; 4504 4505 if (bwn_nphy_ipa(mac)) 4506 tmp = bwn_is_40mhz(mac) ? 5 : 4; 4507 else 4508 tmp = bwn_is_40mhz(mac) ? 3 : 1; 4509 BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B32S2, 4510 (tmp << 9) | (tmp << 6) | (tmp << 3) | tmp); 4511 4512 if (bwn_nphy_ipa(mac)) { 4513 tmp = bwn_is_40mhz(mac) ? 4 : 1; 4514 BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B1S2, 4515 (tmp << 9) | (tmp << 6) | (tmp << 3) | tmp); 4516 } 4517} 4518 4519/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */ 4520static void bwn_nphy_rx_iq_est(struct bwn_mac *mac, struct bwn_nphy_iq_est *est, 4521 uint16_t samps, uint8_t time, bool wait) 4522{ 4523 int i; 4524 uint16_t tmp; 4525 4526 BWN_PHY_WRITE(mac, BWN_NPHY_IQEST_SAMCNT, samps); 4527 BWN_PHY_SETMASK(mac, BWN_NPHY_IQEST_WT, ~BWN_NPHY_IQEST_WT_VAL, time); 4528 if (wait) 4529 BWN_PHY_SET(mac, BWN_NPHY_IQEST_CMD, BWN_NPHY_IQEST_CMD_MODE); 4530 else 4531 BWN_PHY_MASK(mac, BWN_NPHY_IQEST_CMD, ~BWN_NPHY_IQEST_CMD_MODE); 4532 4533 BWN_PHY_SET(mac, BWN_NPHY_IQEST_CMD, BWN_NPHY_IQEST_CMD_START); 4534 4535 for (i = 1000; i; i--) { 4536 tmp = BWN_PHY_READ(mac, BWN_NPHY_IQEST_CMD); 4537 if (!(tmp & BWN_NPHY_IQEST_CMD_START)) { 4538 est->i0_pwr = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_IPACC_HI0) << 16) | 4539 BWN_PHY_READ(mac, BWN_NPHY_IQEST_IPACC_LO0); 4540 est->q0_pwr = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_QPACC_HI0) << 16) | 4541 BWN_PHY_READ(mac, BWN_NPHY_IQEST_QPACC_LO0); 4542 est->iq0_prod = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_IQACC_HI0) << 16) | 4543 BWN_PHY_READ(mac, BWN_NPHY_IQEST_IQACC_LO0); 4544 4545 est->i1_pwr = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_IPACC_HI1) << 16) | 4546 BWN_PHY_READ(mac, BWN_NPHY_IQEST_IPACC_LO1); 4547 est->q1_pwr = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_QPACC_HI1) << 16) | 4548 BWN_PHY_READ(mac, BWN_NPHY_IQEST_QPACC_LO1); 4549 est->iq1_prod = (BWN_PHY_READ(mac, BWN_NPHY_IQEST_IQACC_HI1) << 16) | 4550 BWN_PHY_READ(mac, BWN_NPHY_IQEST_IQACC_LO1); 4551 return; 4552 } 4553 DELAY(10); 4554 } 4555 memset(est, 0, sizeof(*est)); 4556} 4557 4558/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */ 4559static void bwn_nphy_rx_iq_coeffs(struct bwn_mac *mac, bool write, 4560 struct bwn_phy_n_iq_comp *pcomp) 4561{ 4562 if (write) { 4563 BWN_PHY_WRITE(mac, BWN_NPHY_C1_RXIQ_COMPA0, pcomp->a0); 4564 BWN_PHY_WRITE(mac, BWN_NPHY_C1_RXIQ_COMPB0, pcomp->b0); 4565 BWN_PHY_WRITE(mac, BWN_NPHY_C2_RXIQ_COMPA1, pcomp->a1); 4566 BWN_PHY_WRITE(mac, BWN_NPHY_C2_RXIQ_COMPB1, pcomp->b1); 4567 } else { 4568 pcomp->a0 = BWN_PHY_READ(mac, BWN_NPHY_C1_RXIQ_COMPA0); 4569 pcomp->b0 = BWN_PHY_READ(mac, BWN_NPHY_C1_RXIQ_COMPB0); 4570 pcomp->a1 = BWN_PHY_READ(mac, BWN_NPHY_C2_RXIQ_COMPA1); 4571 pcomp->b1 = BWN_PHY_READ(mac, BWN_NPHY_C2_RXIQ_COMPB1); 4572 } 4573} 4574 4575#if 0 4576/* Ready but not used anywhere */ 4577/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */ 4578static void bwn_nphy_rx_cal_phy_cleanup(struct bwn_mac *mac, uint8_t core) 4579{ 4580 uint16_t *regs = mac->mac_phy.phy_n->tx_rx_cal_phy_saveregs; 4581 4582 BWN_PHY_WRITE(mac, BWN_NPHY_RFSEQCA, regs[0]); 4583 if (core == 0) { 4584 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, regs[1]); 4585 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, regs[2]); 4586 } else { 4587 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, regs[1]); 4588 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, regs[2]); 4589 } 4590 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, regs[3]); 4591 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, regs[4]); 4592 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_RSSIO1, regs[5]); 4593 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_RSSIO2, regs[6]); 4594 BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B1S1, regs[7]); 4595 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_OVER, regs[8]); 4596 BWN_PHY_WRITE(mac, BWN_NPHY_PAPD_EN0, regs[9]); 4597 BWN_PHY_WRITE(mac, BWN_NPHY_PAPD_EN1, regs[10]); 4598} 4599 4600/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhySetup */ 4601static void bwn_nphy_rx_cal_phy_setup(struct bwn_mac *mac, uint8_t core) 4602{ 4603 uint8_t rxval, txval; 4604 uint16_t *regs = mac->mac_phy.phy_n->tx_rx_cal_phy_saveregs; 4605 4606 regs[0] = BWN_PHY_READ(mac, BWN_NPHY_RFSEQCA); 4607 if (core == 0) { 4608 regs[1] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C1); 4609 regs[2] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER1); 4610 } else { 4611 regs[1] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C2); 4612 regs[2] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER); 4613 } 4614 regs[3] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC1); 4615 regs[4] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC2); 4616 regs[5] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_RSSIO1); 4617 regs[6] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_RSSIO2); 4618 regs[7] = BWN_PHY_READ(mac, BWN_NPHY_TXF_40CO_B1S1); 4619 regs[8] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_OVER); 4620 regs[9] = BWN_PHY_READ(mac, BWN_NPHY_PAPD_EN0); 4621 regs[10] = BWN_PHY_READ(mac, BWN_NPHY_PAPD_EN1); 4622 4623 BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN0, ~0x0001); 4624 BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN1, ~0x0001); 4625 4626 BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, 4627 ~BWN_NPHY_RFSEQCA_RXDIS & 0xFFFF, 4628 ((1 - core) << BWN_NPHY_RFSEQCA_RXDIS_SHIFT)); 4629 BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, ~BWN_NPHY_RFSEQCA_TXEN, 4630 ((1 - core) << BWN_NPHY_RFSEQCA_TXEN_SHIFT)); 4631 BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, ~BWN_NPHY_RFSEQCA_RXEN, 4632 (core << BWN_NPHY_RFSEQCA_RXEN_SHIFT)); 4633 BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, ~BWN_NPHY_RFSEQCA_TXDIS, 4634 (core << BWN_NPHY_RFSEQCA_TXDIS_SHIFT)); 4635 4636 if (core == 0) { 4637 BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C1, ~0x0007); 4638 BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER1, 0x0007); 4639 } else { 4640 BWN_PHY_MASK(mac, BWN_NPHY_AFECTL_C2, ~0x0007); 4641 BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x0007); 4642 } 4643 4644 bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_PA, 0, 3); 4645 bwn_nphy_rf_ctl_override(mac, 8, 0, 3, false); 4646 bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RX2TX); 4647 4648 if (core == 0) { 4649 rxval = 1; 4650 txval = 8; 4651 } else { 4652 rxval = 4; 4653 txval = 2; 4654 } 4655 bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_TRSW, rxval, 4656 core + 1); 4657 bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_TRSW, txval, 4658 2 - core); 4659} 4660#endif 4661 4662/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */ 4663static void bwn_nphy_calc_rx_iq_comp(struct bwn_mac *mac, uint8_t mask) 4664{ 4665 int i; 4666 int32_t iq; 4667 uint32_t ii; 4668 uint32_t qq; 4669 int iq_nbits, qq_nbits; 4670 int arsh, brsh; 4671 uint16_t tmp, a, b; 4672 4673 struct bwn_nphy_iq_est est; 4674 struct bwn_phy_n_iq_comp old; 4675 struct bwn_phy_n_iq_comp new = { }; 4676 bool error = false; 4677 4678 if (mask == 0) 4679 return; 4680 4681 bwn_nphy_rx_iq_coeffs(mac, false, &old); 4682 bwn_nphy_rx_iq_coeffs(mac, true, &new); 4683 bwn_nphy_rx_iq_est(mac, &est, 0x4000, 32, false); 4684 new = old; 4685 4686 for (i = 0; i < 2; i++) { 4687 if (i == 0 && (mask & 1)) { 4688 iq = est.iq0_prod; 4689 ii = est.i0_pwr; 4690 qq = est.q0_pwr; 4691 } else if (i == 1 && (mask & 2)) { 4692 iq = est.iq1_prod; 4693 ii = est.i1_pwr; 4694 qq = est.q1_pwr; 4695 } else { 4696 continue; 4697 } 4698 4699 if (ii + qq < 2) { 4700 error = true; 4701 break; 4702 } 4703 4704 iq_nbits = fls(abs(iq)); 4705 qq_nbits = fls(qq); 4706 4707 arsh = iq_nbits - 20; 4708 if (arsh >= 0) { 4709 a = -((iq << (30 - iq_nbits)) + (ii >> (1 + arsh))); 4710 tmp = ii >> arsh; 4711 } else { 4712 a = -((iq << (30 - iq_nbits)) + (ii << (-1 - arsh))); 4713 tmp = ii << -arsh; 4714 } 4715 if (tmp == 0) { 4716 error = true; 4717 break; 4718 } 4719 a /= tmp; 4720 4721 brsh = qq_nbits - 11; 4722 if (brsh >= 0) { 4723 b = (qq << (31 - qq_nbits)); 4724 tmp = ii >> brsh; 4725 } else { 4726 b = (qq << (31 - qq_nbits)); 4727 tmp = ii << -brsh; 4728 } 4729 if (tmp == 0) { 4730 error = true; 4731 break; 4732 } 4733 b = bwn_sqrt(mac, b / tmp - a * a) - (1 << 10); 4734 4735 if (i == 0 && (mask & 0x1)) { 4736 if (mac->mac_phy.rev >= 3) { 4737 new.a0 = a & 0x3FF; 4738 new.b0 = b & 0x3FF; 4739 } else { 4740 new.a0 = b & 0x3FF; 4741 new.b0 = a & 0x3FF; 4742 } 4743 } else if (i == 1 && (mask & 0x2)) { 4744 if (mac->mac_phy.rev >= 3) { 4745 new.a1 = a & 0x3FF; 4746 new.b1 = b & 0x3FF; 4747 } else { 4748 new.a1 = b & 0x3FF; 4749 new.b1 = a & 0x3FF; 4750 } 4751 } 4752 } 4753 4754 if (error) 4755 new = old; 4756 4757 bwn_nphy_rx_iq_coeffs(mac, true, &new); 4758} 4759 4760/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */ 4761static void bwn_nphy_tx_iq_workaround(struct bwn_mac *mac) 4762{ 4763 uint16_t array[4]; 4764 bwn_ntab_read_bulk(mac, BWN_NTAB16(0xF, 0x50), 4, array); 4765 4766 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHM_SH_NPHY_TXIQW0, array[0]); 4767 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHM_SH_NPHY_TXIQW1, array[1]); 4768 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHM_SH_NPHY_TXIQW2, array[2]); 4769 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHM_SH_NPHY_TXIQW3, array[3]); 4770} 4771 4772/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SpurWar */ 4773static void bwn_nphy_spur_workaround(struct bwn_mac *mac) 4774{ 4775 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4776 4777 uint8_t channel = bwn_get_chan(mac); 4778 int tone[2] = { 57, 58 }; 4779 uint32_t noise[2] = { 0x3FF, 0x3FF }; 4780 4781 if (mac->mac_phy.rev < 3) { 4782 BWN_ERRPRINTF(mac->mac_sc, "%s: phy rev %d out of range\n", 4783 __func__, 4784 mac->mac_phy.rev); 4785 } 4786 4787 if (nphy->hang_avoid) 4788 bwn_nphy_stay_in_carrier_search(mac, 1); 4789 4790 if (nphy->gband_spurwar_en) { 4791 /* TODO: N PHY Adjust Analog Pfbw (7) */ 4792 if (channel == 11 && bwn_is_40mhz(mac)) 4793 ; /* TODO: N PHY Adjust Min Noise Var(2, tone, noise)*/ 4794 else 4795 ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/ 4796 /* TODO: N PHY Adjust CRS Min Power (0x1E) */ 4797 } 4798 4799 if (nphy->aband_spurwar_en) { 4800 if (channel == 54) { 4801 tone[0] = 0x20; 4802 noise[0] = 0x25F; 4803 } else if (channel == 38 || channel == 102 || channel == 118) { 4804 if (0 /* FIXME */) { 4805 tone[0] = 0x20; 4806 noise[0] = 0x21F; 4807 } else { 4808 tone[0] = 0; 4809 noise[0] = 0; 4810 } 4811 } else if (channel == 134) { 4812 tone[0] = 0x20; 4813 noise[0] = 0x21F; 4814 } else if (channel == 151) { 4815 tone[0] = 0x10; 4816 noise[0] = 0x23F; 4817 } else if (channel == 153 || channel == 161) { 4818 tone[0] = 0x30; 4819 noise[0] = 0x23F; 4820 } else { 4821 tone[0] = 0; 4822 noise[0] = 0; 4823 } 4824 4825 if (!tone[0] && !noise[0]) 4826 ; /* TODO: N PHY Adjust Min Noise Var(1, tone, noise)*/ 4827 else 4828 ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/ 4829 } 4830 4831 if (nphy->hang_avoid) 4832 bwn_nphy_stay_in_carrier_search(mac, 0); 4833} 4834 4835/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */ 4836static void bwn_nphy_tx_pwr_ctrl_coef_setup(struct bwn_mac *mac) 4837{ 4838 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4839 int i, j; 4840 uint32_t tmp; 4841 uint32_t cur_real, cur_imag, real_part, imag_part; 4842 4843 uint16_t buffer[7]; 4844 4845 if (nphy->hang_avoid) 4846 bwn_nphy_stay_in_carrier_search(mac, true); 4847 4848 bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 80), 7, buffer); 4849 4850 for (i = 0; i < 2; i++) { 4851 tmp = ((buffer[i * 2] & 0x3FF) << 10) | 4852 (buffer[i * 2 + 1] & 0x3FF); 4853 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 4854 (((i + 26) << 10) | 320)); 4855 for (j = 0; j < 128; j++) { 4856 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATAHI, 4857 ((tmp >> 16) & 0xFFFF)); 4858 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 4859 (tmp & 0xFFFF)); 4860 } 4861 } 4862 4863 for (i = 0; i < 2; i++) { 4864 tmp = buffer[5 + i]; 4865 real_part = (tmp >> 8) & 0xFF; 4866 imag_part = (tmp & 0xFF); 4867 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_ADDR, 4868 (((i + 26) << 10) | 448)); 4869 4870 if (mac->mac_phy.rev >= 3) { 4871 cur_real = real_part; 4872 cur_imag = imag_part; 4873 tmp = ((cur_real & 0xFF) << 8) | (cur_imag & 0xFF); 4874 } 4875 4876 for (j = 0; j < 128; j++) { 4877 if (mac->mac_phy.rev < 3) { 4878 cur_real = (real_part * loscale[j] + 128) >> 8; 4879 cur_imag = (imag_part * loscale[j] + 128) >> 8; 4880 tmp = ((cur_real & 0xFF) << 8) | 4881 (cur_imag & 0xFF); 4882 } 4883 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATAHI, 4884 ((tmp >> 16) & 0xFFFF)); 4885 BWN_PHY_WRITE(mac, BWN_NPHY_TABLE_DATALO, 4886 (tmp & 0xFFFF)); 4887 } 4888 } 4889 4890 if (mac->mac_phy.rev >= 3) { 4891 bwn_shm_write_2(mac, BWN_SHARED, 4892 BWN_SHM_SH_NPHY_TXPWR_INDX0, 0xFFFF); 4893 bwn_shm_write_2(mac, BWN_SHARED, 4894 BWN_SHM_SH_NPHY_TXPWR_INDX1, 0xFFFF); 4895 } 4896 4897 if (nphy->hang_avoid) 4898 bwn_nphy_stay_in_carrier_search(mac, false); 4899} 4900 4901/* 4902 * Restore RSSI Calibration 4903 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal 4904 */ 4905static void bwn_nphy_restore_rssi_cal(struct bwn_mac *mac) 4906{ 4907 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4908 4909 uint16_t *rssical_radio_regs = NULL; 4910 uint16_t *rssical_phy_regs = NULL; 4911 4912 if (bwn_current_band(mac) == BWN_BAND_2G) { 4913 if (!nphy->rssical_chanspec_2G.center_freq) 4914 return; 4915 rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G; 4916 rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G; 4917 } else { 4918 if (!nphy->rssical_chanspec_5G.center_freq) 4919 return; 4920 rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G; 4921 rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; 4922 } 4923 4924 if (mac->mac_phy.rev >= 19) { 4925 /* TODO */ 4926 } else if (mac->mac_phy.rev >= 7) { 4927 BWN_RF_SETMASK(mac, R2057_NB_MASTER_CORE0, ~R2057_VCM_MASK, 4928 rssical_radio_regs[0]); 4929 BWN_RF_SETMASK(mac, R2057_NB_MASTER_CORE1, ~R2057_VCM_MASK, 4930 rssical_radio_regs[1]); 4931 } else { 4932 BWN_RF_SETMASK(mac, B2056_RX0 | B2056_RX_RSSI_MISC, 0xE3, 4933 rssical_radio_regs[0]); 4934 BWN_RF_SETMASK(mac, B2056_RX1 | B2056_RX_RSSI_MISC, 0xE3, 4935 rssical_radio_regs[1]); 4936 } 4937 4938 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_Z, rssical_phy_regs[0]); 4939 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Z, rssical_phy_regs[1]); 4940 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_Z, rssical_phy_regs[2]); 4941 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Z, rssical_phy_regs[3]); 4942 4943 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_X, rssical_phy_regs[4]); 4944 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_X, rssical_phy_regs[5]); 4945 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_X, rssical_phy_regs[6]); 4946 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_X, rssical_phy_regs[7]); 4947 4948 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0I_RSSI_Y, rssical_phy_regs[8]); 4949 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_0Q_RSSI_Y, rssical_phy_regs[9]); 4950 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1I_RSSI_Y, rssical_phy_regs[10]); 4951 BWN_PHY_WRITE(mac, BWN_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]); 4952} 4953 4954static void bwn_nphy_tx_cal_radio_setup_rev19(struct bwn_mac *mac) 4955{ 4956 /* TODO */ 4957} 4958 4959static void bwn_nphy_tx_cal_radio_setup_rev7(struct bwn_mac *mac) 4960{ 4961 struct bwn_phy *phy = &mac->mac_phy; 4962 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 4963 uint16_t *save = nphy->tx_rx_cal_radio_saveregs; 4964 int core, off; 4965 uint16_t r, tmp; 4966 4967 for (core = 0; core < 2; core++) { 4968 r = core ? 0x20 : 0; 4969 off = core * 11; 4970 4971 save[off + 0] = BWN_RF_READ(mac, r + R2057_TX0_TX_SSI_MASTER); 4972 save[off + 1] = BWN_RF_READ(mac, r + R2057_TX0_IQCAL_VCM_HG); 4973 save[off + 2] = BWN_RF_READ(mac, r + R2057_TX0_IQCAL_IDAC); 4974 save[off + 3] = BWN_RF_READ(mac, r + R2057_TX0_TSSI_VCM); 4975 save[off + 4] = 0; 4976 save[off + 5] = BWN_RF_READ(mac, r + R2057_TX0_TX_SSI_MUX); 4977 if (phy->rf_rev != 5) 4978 save[off + 6] = BWN_RF_READ(mac, r + R2057_TX0_TSSIA); 4979 save[off + 7] = BWN_RF_READ(mac, r + R2057_TX0_TSSIG); 4980 save[off + 8] = BWN_RF_READ(mac, r + R2057_TX0_TSSI_MISC1); 4981 4982 if (bwn_current_band(mac) == BWN_BAND_5G) { 4983 BWN_RF_WRITE(mac, r + R2057_TX0_TX_SSI_MASTER, 0xA); 4984 BWN_RF_WRITE(mac, r + R2057_TX0_IQCAL_VCM_HG, 0x43); 4985 BWN_RF_WRITE(mac, r + R2057_TX0_IQCAL_IDAC, 0x55); 4986 BWN_RF_WRITE(mac, r + R2057_TX0_TSSI_VCM, 0); 4987 BWN_RF_WRITE(mac, r + R2057_TX0_TSSIG, 0); 4988 if (nphy->use_int_tx_iq_lo_cal) { 4989 BWN_RF_WRITE(mac, r + R2057_TX0_TX_SSI_MUX, 0x4); 4990 tmp = true ? 0x31 : 0x21; /* TODO */ 4991 BWN_RF_WRITE(mac, r + R2057_TX0_TSSIA, tmp); 4992 } 4993 BWN_RF_WRITE(mac, r + R2057_TX0_TSSI_MISC1, 0x00); 4994 } else { 4995 BWN_RF_WRITE(mac, r + R2057_TX0_TX_SSI_MASTER, 0x6); 4996 BWN_RF_WRITE(mac, r + R2057_TX0_IQCAL_VCM_HG, 0x43); 4997 BWN_RF_WRITE(mac, r + R2057_TX0_IQCAL_IDAC, 0x55); 4998 BWN_RF_WRITE(mac, r + R2057_TX0_TSSI_VCM, 0); 4999 5000 if (phy->rf_rev != 5) 5001 BWN_RF_WRITE(mac, r + R2057_TX0_TSSIA, 0); 5002 if (nphy->use_int_tx_iq_lo_cal) { 5003 BWN_RF_WRITE(mac, r + R2057_TX0_TX_SSI_MUX, 0x6); 5004 tmp = true ? 0x31 : 0x21; /* TODO */ 5005 BWN_RF_WRITE(mac, r + R2057_TX0_TSSIG, tmp); 5006 } 5007 BWN_RF_WRITE(mac, r + R2057_TX0_TSSI_MISC1, 0); 5008 } 5009 } 5010} 5011 5012/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */ 5013static void bwn_nphy_tx_cal_radio_setup(struct bwn_mac *mac) 5014{ 5015 struct bwn_phy *phy = &mac->mac_phy; 5016 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5017 uint16_t *save = nphy->tx_rx_cal_radio_saveregs; 5018 uint16_t tmp; 5019 uint8_t offset, i; 5020 5021 if (phy->rev >= 19) { 5022 bwn_nphy_tx_cal_radio_setup_rev19(mac); 5023 } else if (phy->rev >= 7) { 5024 bwn_nphy_tx_cal_radio_setup_rev7(mac); 5025 } else if (phy->rev >= 3) { 5026 for (i = 0; i < 2; i++) { 5027 tmp = (i == 0) ? 0x2000 : 0x3000; 5028 offset = i * 11; 5029 5030 save[offset + 0] = BWN_RF_READ(mac, B2055_CAL_RVARCTL); 5031 save[offset + 1] = BWN_RF_READ(mac, B2055_CAL_LPOCTL); 5032 save[offset + 2] = BWN_RF_READ(mac, B2055_CAL_TS); 5033 save[offset + 3] = BWN_RF_READ(mac, B2055_CAL_RCCALRTS); 5034 save[offset + 4] = BWN_RF_READ(mac, B2055_CAL_RCALRTS); 5035 save[offset + 5] = BWN_RF_READ(mac, B2055_PADDRV); 5036 save[offset + 6] = BWN_RF_READ(mac, B2055_XOCTL1); 5037 save[offset + 7] = BWN_RF_READ(mac, B2055_XOCTL2); 5038 save[offset + 8] = BWN_RF_READ(mac, B2055_XOREGUL); 5039 save[offset + 9] = BWN_RF_READ(mac, B2055_XOMISC); 5040 save[offset + 10] = BWN_RF_READ(mac, B2055_PLL_LFC1); 5041 5042 if (bwn_current_band(mac) == BWN_BAND_5G) { 5043 BWN_RF_WRITE(mac, tmp | B2055_CAL_RVARCTL, 0x0A); 5044 BWN_RF_WRITE(mac, tmp | B2055_CAL_LPOCTL, 0x40); 5045 BWN_RF_WRITE(mac, tmp | B2055_CAL_TS, 0x55); 5046 BWN_RF_WRITE(mac, tmp | B2055_CAL_RCCALRTS, 0); 5047 BWN_RF_WRITE(mac, tmp | B2055_CAL_RCALRTS, 0); 5048 if (nphy->ipa5g_on) { 5049 BWN_RF_WRITE(mac, tmp | B2055_PADDRV, 4); 5050 BWN_RF_WRITE(mac, tmp | B2055_XOCTL1, 1); 5051 } else { 5052 BWN_RF_WRITE(mac, tmp | B2055_PADDRV, 0); 5053 BWN_RF_WRITE(mac, tmp | B2055_XOCTL1, 0x2F); 5054 } 5055 BWN_RF_WRITE(mac, tmp | B2055_XOCTL2, 0); 5056 } else { 5057 BWN_RF_WRITE(mac, tmp | B2055_CAL_RVARCTL, 0x06); 5058 BWN_RF_WRITE(mac, tmp | B2055_CAL_LPOCTL, 0x40); 5059 BWN_RF_WRITE(mac, tmp | B2055_CAL_TS, 0x55); 5060 BWN_RF_WRITE(mac, tmp | B2055_CAL_RCCALRTS, 0); 5061 BWN_RF_WRITE(mac, tmp | B2055_CAL_RCALRTS, 0); 5062 BWN_RF_WRITE(mac, tmp | B2055_XOCTL1, 0); 5063 if (nphy->ipa2g_on) { 5064 BWN_RF_WRITE(mac, tmp | B2055_PADDRV, 6); 5065 BWN_RF_WRITE(mac, tmp | B2055_XOCTL2, 5066 (mac->mac_phy.rev < 5) ? 0x11 : 0x01); 5067 } else { 5068 BWN_RF_WRITE(mac, tmp | B2055_PADDRV, 0); 5069 BWN_RF_WRITE(mac, tmp | B2055_XOCTL2, 0); 5070 } 5071 } 5072 BWN_RF_WRITE(mac, tmp | B2055_XOREGUL, 0); 5073 BWN_RF_WRITE(mac, tmp | B2055_XOMISC, 0); 5074 BWN_RF_WRITE(mac, tmp | B2055_PLL_LFC1, 0); 5075 } 5076 } else { 5077 save[0] = BWN_RF_READ(mac, B2055_C1_TX_RF_IQCAL1); 5078 BWN_RF_WRITE(mac, B2055_C1_TX_RF_IQCAL1, 0x29); 5079 5080 save[1] = BWN_RF_READ(mac, B2055_C1_TX_RF_IQCAL2); 5081 BWN_RF_WRITE(mac, B2055_C1_TX_RF_IQCAL2, 0x54); 5082 5083 save[2] = BWN_RF_READ(mac, B2055_C2_TX_RF_IQCAL1); 5084 BWN_RF_WRITE(mac, B2055_C2_TX_RF_IQCAL1, 0x29); 5085 5086 save[3] = BWN_RF_READ(mac, B2055_C2_TX_RF_IQCAL2); 5087 BWN_RF_WRITE(mac, B2055_C2_TX_RF_IQCAL2, 0x54); 5088 5089 save[3] = BWN_RF_READ(mac, B2055_C1_PWRDET_RXTX); 5090 save[4] = BWN_RF_READ(mac, B2055_C2_PWRDET_RXTX); 5091 5092 if (!(BWN_PHY_READ(mac, BWN_NPHY_BANDCTL) & 5093 BWN_NPHY_BANDCTL_5GHZ)) { 5094 BWN_RF_WRITE(mac, B2055_C1_PWRDET_RXTX, 0x04); 5095 BWN_RF_WRITE(mac, B2055_C2_PWRDET_RXTX, 0x04); 5096 } else { 5097 BWN_RF_WRITE(mac, B2055_C1_PWRDET_RXTX, 0x20); 5098 BWN_RF_WRITE(mac, B2055_C2_PWRDET_RXTX, 0x20); 5099 } 5100 5101 if (mac->mac_phy.rev < 2) { 5102 BWN_RF_SET(mac, B2055_C1_TX_BB_MXGM, 0x20); 5103 BWN_RF_SET(mac, B2055_C2_TX_BB_MXGM, 0x20); 5104 } else { 5105 BWN_RF_MASK(mac, B2055_C1_TX_BB_MXGM, ~0x20); 5106 BWN_RF_MASK(mac, B2055_C2_TX_BB_MXGM, ~0x20); 5107 } 5108 } 5109} 5110 5111/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */ 5112static void bwn_nphy_update_tx_cal_ladder(struct bwn_mac *mac, uint16_t core) 5113{ 5114 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5115 int i; 5116 uint16_t scale, entry; 5117 5118 uint16_t tmp = nphy->txcal_bbmult; 5119 if (core == 0) 5120 tmp >>= 8; 5121 tmp &= 0xff; 5122 5123 for (i = 0; i < 18; i++) { 5124 scale = (ladder_lo[i].percent * tmp) / 100; 5125 entry = ((scale & 0xFF) << 8) | ladder_lo[i].g_env; 5126 bwn_ntab_write(mac, BWN_NTAB16(15, i), entry); 5127 5128 scale = (ladder_iq[i].percent * tmp) / 100; 5129 entry = ((scale & 0xFF) << 8) | ladder_iq[i].g_env; 5130 bwn_ntab_write(mac, BWN_NTAB16(15, i + 32), entry); 5131 } 5132} 5133 5134static void bwn_nphy_pa_set_tx_dig_filter(struct bwn_mac *mac, uint16_t offset, 5135 const int16_t *filter) 5136{ 5137 int i; 5138 5139 offset = BWN_PHY_N(offset); 5140 5141 for (i = 0; i < 15; i++, offset++) 5142 BWN_PHY_WRITE(mac, offset, filter[i]); 5143} 5144 5145/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */ 5146static void bwn_nphy_ext_pa_set_tx_dig_filters(struct bwn_mac *mac) 5147{ 5148 bwn_nphy_pa_set_tx_dig_filter(mac, 0x2C5, 5149 tbl_tx_filter_coef_rev4[2]); 5150} 5151 5152/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */ 5153static void bwn_nphy_int_pa_set_tx_dig_filters(struct bwn_mac *mac) 5154{ 5155 /* BWN_NPHY_TXF_20CO_S0A1, BWN_NPHY_TXF_40CO_S0A1, unknown */ 5156 static const uint16_t offset[] = { 0x186, 0x195, 0x2C5 }; 5157 static const int16_t dig_filter_phy_rev16[] = { 5158 -375, 136, -407, 208, -1527, 5159 956, 93, 186, 93, 230, 5160 -44, 230, 201, -191, 201, 5161 }; 5162 int i; 5163 5164 for (i = 0; i < 3; i++) 5165 bwn_nphy_pa_set_tx_dig_filter(mac, offset[i], 5166 tbl_tx_filter_coef_rev4[i]); 5167 5168 /* Verified with BCM43227 and BCM43228 */ 5169 if (mac->mac_phy.rev == 16) 5170 bwn_nphy_pa_set_tx_dig_filter(mac, 0x186, dig_filter_phy_rev16); 5171 5172 /* Verified with BCM43131 and BCM43217 */ 5173 if (mac->mac_phy.rev == 17) { 5174 bwn_nphy_pa_set_tx_dig_filter(mac, 0x186, dig_filter_phy_rev16); 5175 bwn_nphy_pa_set_tx_dig_filter(mac, 0x195, 5176 tbl_tx_filter_coef_rev4[1]); 5177 } 5178 5179 if (bwn_is_40mhz(mac)) { 5180 bwn_nphy_pa_set_tx_dig_filter(mac, 0x186, 5181 tbl_tx_filter_coef_rev4[3]); 5182 } else { 5183 if (bwn_current_band(mac) == BWN_BAND_5G) 5184 bwn_nphy_pa_set_tx_dig_filter(mac, 0x186, 5185 tbl_tx_filter_coef_rev4[5]); 5186 if (bwn_get_chan(mac) == 14) 5187 bwn_nphy_pa_set_tx_dig_filter(mac, 0x186, 5188 tbl_tx_filter_coef_rev4[6]); 5189 } 5190} 5191 5192/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */ 5193static struct bwn_nphy_txgains bwn_nphy_get_tx_gains(struct bwn_mac *mac) 5194{ 5195 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5196 5197 uint16_t curr_gain[2]; 5198 struct bwn_nphy_txgains target; 5199 const uint32_t *table = NULL; 5200 5201 if (!nphy->txpwrctrl) { 5202 int i; 5203 5204 if (nphy->hang_avoid) 5205 bwn_nphy_stay_in_carrier_search(mac, true); 5206 bwn_ntab_read_bulk(mac, BWN_NTAB16(7, 0x110), 2, curr_gain); 5207 if (nphy->hang_avoid) 5208 bwn_nphy_stay_in_carrier_search(mac, false); 5209 5210 for (i = 0; i < 2; ++i) { 5211 if (mac->mac_phy.rev >= 7) { 5212 target.ipa[i] = curr_gain[i] & 0x0007; 5213 target.pad[i] = (curr_gain[i] & 0x00F8) >> 3; 5214 target.pga[i] = (curr_gain[i] & 0x0F00) >> 8; 5215 target.txgm[i] = (curr_gain[i] & 0x7000) >> 12; 5216 target.tx_lpf[i] = (curr_gain[i] & 0x8000) >> 15; 5217 } else if (mac->mac_phy.rev >= 3) { 5218 target.ipa[i] = curr_gain[i] & 0x000F; 5219 target.pad[i] = (curr_gain[i] & 0x00F0) >> 4; 5220 target.pga[i] = (curr_gain[i] & 0x0F00) >> 8; 5221 target.txgm[i] = (curr_gain[i] & 0x7000) >> 12; 5222 } else { 5223 target.ipa[i] = curr_gain[i] & 0x0003; 5224 target.pad[i] = (curr_gain[i] & 0x000C) >> 2; 5225 target.pga[i] = (curr_gain[i] & 0x0070) >> 4; 5226 target.txgm[i] = (curr_gain[i] & 0x0380) >> 7; 5227 } 5228 } 5229 } else { 5230 int i; 5231 uint16_t index[2]; 5232 index[0] = (BWN_PHY_READ(mac, BWN_NPHY_C1_TXPCTL_STAT) & 5233 BWN_NPHY_TXPCTL_STAT_BIDX) >> 5234 BWN_NPHY_TXPCTL_STAT_BIDX_SHIFT; 5235 index[1] = (BWN_PHY_READ(mac, BWN_NPHY_C2_TXPCTL_STAT) & 5236 BWN_NPHY_TXPCTL_STAT_BIDX) >> 5237 BWN_NPHY_TXPCTL_STAT_BIDX_SHIFT; 5238 5239 for (i = 0; i < 2; ++i) { 5240 table = bwn_nphy_get_tx_gain_table(mac); 5241 if (!table) 5242 break; 5243 5244 if (mac->mac_phy.rev >= 7) { 5245 target.ipa[i] = (table[index[i]] >> 16) & 0x7; 5246 target.pad[i] = (table[index[i]] >> 19) & 0x1F; 5247 target.pga[i] = (table[index[i]] >> 24) & 0xF; 5248 target.txgm[i] = (table[index[i]] >> 28) & 0x7; 5249 target.tx_lpf[i] = (table[index[i]] >> 31) & 0x1; 5250 } else if (mac->mac_phy.rev >= 3) { 5251 target.ipa[i] = (table[index[i]] >> 16) & 0xF; 5252 target.pad[i] = (table[index[i]] >> 20) & 0xF; 5253 target.pga[i] = (table[index[i]] >> 24) & 0xF; 5254 target.txgm[i] = (table[index[i]] >> 28) & 0xF; 5255 } else { 5256 target.ipa[i] = (table[index[i]] >> 16) & 0x3; 5257 target.pad[i] = (table[index[i]] >> 18) & 0x3; 5258 target.pga[i] = (table[index[i]] >> 20) & 0x7; 5259 target.txgm[i] = (table[index[i]] >> 23) & 0x7; 5260 } 5261 } 5262 } 5263 5264 return target; 5265} 5266 5267/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhyCleanup */ 5268static void bwn_nphy_tx_cal_phy_cleanup(struct bwn_mac *mac) 5269{ 5270 uint16_t *regs = mac->mac_phy.phy_n->tx_rx_cal_phy_saveregs; 5271 5272 if (mac->mac_phy.rev >= 3) { 5273 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, regs[0]); 5274 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, regs[1]); 5275 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, regs[2]); 5276 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, regs[3]); 5277 BWN_PHY_WRITE(mac, BWN_NPHY_BBCFG, regs[4]); 5278 bwn_ntab_write(mac, BWN_NTAB16(8, 3), regs[5]); 5279 bwn_ntab_write(mac, BWN_NTAB16(8, 19), regs[6]); 5280 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, regs[7]); 5281 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, regs[8]); 5282 BWN_PHY_WRITE(mac, BWN_NPHY_PAPD_EN0, regs[9]); 5283 BWN_PHY_WRITE(mac, BWN_NPHY_PAPD_EN1, regs[10]); 5284 bwn_nphy_reset_cca(mac); 5285 } else { 5286 BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C1, 0x0FFF, regs[0]); 5287 BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C2, 0x0FFF, regs[1]); 5288 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, regs[2]); 5289 bwn_ntab_write(mac, BWN_NTAB16(8, 2), regs[3]); 5290 bwn_ntab_write(mac, BWN_NTAB16(8, 18), regs[4]); 5291 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, regs[5]); 5292 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, regs[6]); 5293 } 5294} 5295 5296/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */ 5297static void bwn_nphy_tx_cal_phy_setup(struct bwn_mac *mac) 5298{ 5299 struct bwn_phy *phy = &mac->mac_phy; 5300 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5301 uint16_t *regs = mac->mac_phy.phy_n->tx_rx_cal_phy_saveregs; 5302 uint16_t tmp; 5303 5304 regs[0] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C1); 5305 regs[1] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_C2); 5306 if (mac->mac_phy.rev >= 3) { 5307 BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C1, 0xF0FF, 0x0A00); 5308 BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C2, 0xF0FF, 0x0A00); 5309 5310 tmp = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER1); 5311 regs[2] = tmp; 5312 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, tmp | 0x0600); 5313 5314 tmp = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER); 5315 regs[3] = tmp; 5316 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, tmp | 0x0600); 5317 5318 regs[4] = BWN_PHY_READ(mac, BWN_NPHY_BBCFG); 5319 BWN_PHY_MASK(mac, BWN_NPHY_BBCFG, 5320 ~BWN_NPHY_BBCFG_RSTRX & 0xFFFF); 5321 5322 tmp = bwn_ntab_read(mac, BWN_NTAB16(8, 3)); 5323 regs[5] = tmp; 5324 bwn_ntab_write(mac, BWN_NTAB16(8, 3), 0); 5325 5326 tmp = bwn_ntab_read(mac, BWN_NTAB16(8, 19)); 5327 regs[6] = tmp; 5328 bwn_ntab_write(mac, BWN_NTAB16(8, 19), 0); 5329 regs[7] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC1); 5330 regs[8] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC2); 5331 5332 if (!nphy->use_int_tx_iq_lo_cal) 5333 bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_PA, 5334 1, 3); 5335 else 5336 bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_PA, 5337 0, 3); 5338 bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_TRSW, 2, 1); 5339 bwn_nphy_rf_ctl_intc_override(mac, N_INTC_OVERRIDE_TRSW, 8, 2); 5340 5341 regs[9] = BWN_PHY_READ(mac, BWN_NPHY_PAPD_EN0); 5342 regs[10] = BWN_PHY_READ(mac, BWN_NPHY_PAPD_EN1); 5343 BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN0, ~0x0001); 5344 BWN_PHY_MASK(mac, BWN_NPHY_PAPD_EN1, ~0x0001); 5345 5346 tmp = bwn_nphy_read_lpf_ctl(mac, 0); 5347 if (phy->rev >= 19) 5348 bwn_nphy_rf_ctl_override_rev19(mac, 0x80, tmp, 0, false, 5349 1); 5350 else if (phy->rev >= 7) 5351 bwn_nphy_rf_ctl_override_rev7(mac, 0x80, tmp, 0, false, 5352 1); 5353 5354 if (nphy->use_int_tx_iq_lo_cal && true /* FIXME */) { 5355 if (phy->rev >= 19) { 5356 bwn_nphy_rf_ctl_override_rev19(mac, 0x8, 0, 0x3, 5357 false, 0); 5358 } else if (phy->rev >= 8) { 5359 bwn_nphy_rf_ctl_override_rev7(mac, 0x8, 0, 0x3, 5360 false, 0); 5361 } else if (phy->rev == 7) { 5362 BWN_RF_SETMASK(mac, R2057_OVR_REG0, 1 << 4, 1 << 4); 5363 if (bwn_current_band(mac) == BWN_BAND_2G) { 5364 BWN_RF_SETMASK(mac, R2057_PAD2G_TUNE_PUS_CORE0, ~1, 0); 5365 BWN_RF_SETMASK(mac, R2057_PAD2G_TUNE_PUS_CORE1, ~1, 0); 5366 } else { 5367 BWN_RF_SETMASK(mac, R2057_IPA5G_CASCOFFV_PU_CORE0, ~1, 0); 5368 BWN_RF_SETMASK(mac, R2057_IPA5G_CASCOFFV_PU_CORE1, ~1, 0); 5369 } 5370 } 5371 } 5372 } else { 5373 BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C1, 0x0FFF, 0xA000); 5374 BWN_PHY_SETMASK(mac, BWN_NPHY_AFECTL_C2, 0x0FFF, 0xA000); 5375 tmp = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER); 5376 regs[2] = tmp; 5377 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, tmp | 0x3000); 5378 tmp = bwn_ntab_read(mac, BWN_NTAB16(8, 2)); 5379 regs[3] = tmp; 5380 tmp |= 0x2000; 5381 bwn_ntab_write(mac, BWN_NTAB16(8, 2), tmp); 5382 tmp = bwn_ntab_read(mac, BWN_NTAB16(8, 18)); 5383 regs[4] = tmp; 5384 tmp |= 0x2000; 5385 bwn_ntab_write(mac, BWN_NTAB16(8, 18), tmp); 5386 regs[5] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC1); 5387 regs[6] = BWN_PHY_READ(mac, BWN_NPHY_RFCTL_INTC2); 5388 if (bwn_current_band(mac) == BWN_BAND_5G) 5389 tmp = 0x0180; 5390 else 5391 tmp = 0x0120; 5392 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, tmp); 5393 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, tmp); 5394 } 5395} 5396 5397/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */ 5398static void bwn_nphy_save_cal(struct bwn_mac *mac) 5399{ 5400 struct bwn_phy *phy = &mac->mac_phy; 5401 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5402 5403 struct bwn_phy_n_iq_comp *rxcal_coeffs = NULL; 5404 uint16_t *txcal_radio_regs = NULL; 5405 struct bwn_chanspec *iqcal_chanspec; 5406 uint16_t *table = NULL; 5407 5408 if (nphy->hang_avoid) 5409 bwn_nphy_stay_in_carrier_search(mac, 1); 5410 5411 if (bwn_current_band(mac) == BWN_BAND_2G) { 5412 rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G; 5413 txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G; 5414 iqcal_chanspec = &nphy->iqcal_chanspec_2G; 5415 table = nphy->cal_cache.txcal_coeffs_2G; 5416 } else { 5417 rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G; 5418 txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G; 5419 iqcal_chanspec = &nphy->iqcal_chanspec_5G; 5420 table = nphy->cal_cache.txcal_coeffs_5G; 5421 } 5422 5423 bwn_nphy_rx_iq_coeffs(mac, false, rxcal_coeffs); 5424 /* TODO use some definitions */ 5425 if (phy->rev >= 19) { 5426 /* TODO */ 5427 } else if (phy->rev >= 7) { 5428 txcal_radio_regs[0] = BWN_RF_READ(mac, 5429 R2057_TX0_LOFT_FINE_I); 5430 txcal_radio_regs[1] = BWN_RF_READ(mac, 5431 R2057_TX0_LOFT_FINE_Q); 5432 txcal_radio_regs[4] = BWN_RF_READ(mac, 5433 R2057_TX0_LOFT_COARSE_I); 5434 txcal_radio_regs[5] = BWN_RF_READ(mac, 5435 R2057_TX0_LOFT_COARSE_Q); 5436 txcal_radio_regs[2] = BWN_RF_READ(mac, 5437 R2057_TX1_LOFT_FINE_I); 5438 txcal_radio_regs[3] = BWN_RF_READ(mac, 5439 R2057_TX1_LOFT_FINE_Q); 5440 txcal_radio_regs[6] = BWN_RF_READ(mac, 5441 R2057_TX1_LOFT_COARSE_I); 5442 txcal_radio_regs[7] = BWN_RF_READ(mac, 5443 R2057_TX1_LOFT_COARSE_Q); 5444 } else if (phy->rev >= 3) { 5445 txcal_radio_regs[0] = BWN_RF_READ(mac, 0x2021); 5446 txcal_radio_regs[1] = BWN_RF_READ(mac, 0x2022); 5447 txcal_radio_regs[2] = BWN_RF_READ(mac, 0x3021); 5448 txcal_radio_regs[3] = BWN_RF_READ(mac, 0x3022); 5449 txcal_radio_regs[4] = BWN_RF_READ(mac, 0x2023); 5450 txcal_radio_regs[5] = BWN_RF_READ(mac, 0x2024); 5451 txcal_radio_regs[6] = BWN_RF_READ(mac, 0x3023); 5452 txcal_radio_regs[7] = BWN_RF_READ(mac, 0x3024); 5453 } else { 5454 txcal_radio_regs[0] = BWN_RF_READ(mac, 0x8B); 5455 txcal_radio_regs[1] = BWN_RF_READ(mac, 0xBA); 5456 txcal_radio_regs[2] = BWN_RF_READ(mac, 0x8D); 5457 txcal_radio_regs[3] = BWN_RF_READ(mac, 0xBC); 5458 } 5459 iqcal_chanspec->center_freq = bwn_get_centre_freq(mac); 5460 iqcal_chanspec->channel_type = bwn_get_chan_type(mac, NULL); 5461 bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 80), 8, table); 5462 5463 if (nphy->hang_avoid) 5464 bwn_nphy_stay_in_carrier_search(mac, 0); 5465} 5466 5467/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */ 5468static void bwn_nphy_restore_cal(struct bwn_mac *mac) 5469{ 5470 struct bwn_phy *phy = &mac->mac_phy; 5471 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5472 5473 uint16_t coef[4]; 5474 uint16_t *loft = NULL; 5475 uint16_t *table = NULL; 5476 5477 int i; 5478 uint16_t *txcal_radio_regs = NULL; 5479 struct bwn_phy_n_iq_comp *rxcal_coeffs = NULL; 5480 5481 if (bwn_current_band(mac) == BWN_BAND_2G) { 5482 if (!nphy->iqcal_chanspec_2G.center_freq) 5483 return; 5484 table = nphy->cal_cache.txcal_coeffs_2G; 5485 loft = &nphy->cal_cache.txcal_coeffs_2G[5]; 5486 } else { 5487 if (!nphy->iqcal_chanspec_5G.center_freq) 5488 return; 5489 table = nphy->cal_cache.txcal_coeffs_5G; 5490 loft = &nphy->cal_cache.txcal_coeffs_5G[5]; 5491 } 5492 5493 bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 80), 4, table); 5494 5495 for (i = 0; i < 4; i++) { 5496 if (mac->mac_phy.rev >= 3) 5497 table[i] = coef[i]; 5498 else 5499 coef[i] = 0; 5500 } 5501 5502 bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 88), 4, coef); 5503 bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 85), 2, loft); 5504 bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 93), 2, loft); 5505 5506 if (mac->mac_phy.rev < 2) 5507 bwn_nphy_tx_iq_workaround(mac); 5508 5509 if (bwn_current_band(mac) == BWN_BAND_2G) { 5510 txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G; 5511 rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G; 5512 } else { 5513 txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G; 5514 rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G; 5515 } 5516 5517 /* TODO use some definitions */ 5518 if (phy->rev >= 19) { 5519 /* TODO */ 5520 } else if (phy->rev >= 7) { 5521 BWN_RF_WRITE(mac, R2057_TX0_LOFT_FINE_I, 5522 txcal_radio_regs[0]); 5523 BWN_RF_WRITE(mac, R2057_TX0_LOFT_FINE_Q, 5524 txcal_radio_regs[1]); 5525 BWN_RF_WRITE(mac, R2057_TX0_LOFT_COARSE_I, 5526 txcal_radio_regs[4]); 5527 BWN_RF_WRITE(mac, R2057_TX0_LOFT_COARSE_Q, 5528 txcal_radio_regs[5]); 5529 BWN_RF_WRITE(mac, R2057_TX1_LOFT_FINE_I, 5530 txcal_radio_regs[2]); 5531 BWN_RF_WRITE(mac, R2057_TX1_LOFT_FINE_Q, 5532 txcal_radio_regs[3]); 5533 BWN_RF_WRITE(mac, R2057_TX1_LOFT_COARSE_I, 5534 txcal_radio_regs[6]); 5535 BWN_RF_WRITE(mac, R2057_TX1_LOFT_COARSE_Q, 5536 txcal_radio_regs[7]); 5537 } else if (phy->rev >= 3) { 5538 BWN_RF_WRITE(mac, 0x2021, txcal_radio_regs[0]); 5539 BWN_RF_WRITE(mac, 0x2022, txcal_radio_regs[1]); 5540 BWN_RF_WRITE(mac, 0x3021, txcal_radio_regs[2]); 5541 BWN_RF_WRITE(mac, 0x3022, txcal_radio_regs[3]); 5542 BWN_RF_WRITE(mac, 0x2023, txcal_radio_regs[4]); 5543 BWN_RF_WRITE(mac, 0x2024, txcal_radio_regs[5]); 5544 BWN_RF_WRITE(mac, 0x3023, txcal_radio_regs[6]); 5545 BWN_RF_WRITE(mac, 0x3024, txcal_radio_regs[7]); 5546 } else { 5547 BWN_RF_WRITE(mac, 0x8B, txcal_radio_regs[0]); 5548 BWN_RF_WRITE(mac, 0xBA, txcal_radio_regs[1]); 5549 BWN_RF_WRITE(mac, 0x8D, txcal_radio_regs[2]); 5550 BWN_RF_WRITE(mac, 0xBC, txcal_radio_regs[3]); 5551 } 5552 bwn_nphy_rx_iq_coeffs(mac, true, rxcal_coeffs); 5553} 5554 5555/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalTxIqlo */ 5556static int bwn_nphy_cal_tx_iq_lo(struct bwn_mac *mac, 5557 struct bwn_nphy_txgains target, 5558 bool full, bool mphase) 5559{ 5560 struct bwn_phy *phy = &mac->mac_phy; 5561 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5562 int i; 5563 int error = 0; 5564 int freq; 5565 bool avoid = false; 5566 uint8_t length; 5567 uint16_t tmp, core, type, count, max, numb, last = 0, cmd; 5568 const uint16_t *table; 5569 bool phy6or5x; 5570 5571 uint16_t buffer[11]; 5572 uint16_t diq_start = 0; 5573 uint16_t save[2]; 5574 uint16_t gain[2]; 5575 struct bwn_nphy_iqcal_params params[2]; 5576 bool updated[2] = { }; 5577 5578 bwn_nphy_stay_in_carrier_search(mac, true); 5579 5580 if (mac->mac_phy.rev >= 4) { 5581 avoid = nphy->hang_avoid; 5582 nphy->hang_avoid = false; 5583 } 5584 5585 bwn_ntab_read_bulk(mac, BWN_NTAB16(7, 0x110), 2, save); 5586 5587 for (i = 0; i < 2; i++) { 5588 bwn_nphy_iq_cal_gain_params(mac, i, target, ¶ms[i]); 5589 gain[i] = params[i].cal_gain; 5590 } 5591 5592 bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x110), 2, gain); 5593 5594 bwn_nphy_tx_cal_radio_setup(mac); 5595 bwn_nphy_tx_cal_phy_setup(mac); 5596 5597 phy6or5x = mac->mac_phy.rev >= 6 || 5598 (mac->mac_phy.rev == 5 && nphy->ipa2g_on && 5599 bwn_current_band(mac) == BWN_BAND_2G); 5600 if (phy6or5x) { 5601 if (bwn_is_40mhz(mac)) { 5602 bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 0), 18, 5603 tbl_tx_iqlo_cal_loft_ladder_40); 5604 bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 32), 18, 5605 tbl_tx_iqlo_cal_iqimb_ladder_40); 5606 } else { 5607 bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 0), 18, 5608 tbl_tx_iqlo_cal_loft_ladder_20); 5609 bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 32), 18, 5610 tbl_tx_iqlo_cal_iqimb_ladder_20); 5611 } 5612 } 5613 5614 if (phy->rev >= 19) { 5615 /* TODO */ 5616 } else if (phy->rev >= 7) { 5617 BWN_PHY_WRITE(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0x8AD9); 5618 } else { 5619 BWN_PHY_WRITE(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0x8AA9); 5620 } 5621 5622 if (!bwn_is_40mhz(mac)) 5623 freq = 2500; 5624 else 5625 freq = 5000; 5626 5627 if (nphy->mphase_cal_phase_id > 2) 5628 bwn_nphy_run_samples(mac, (bwn_is_40mhz(mac) ? 40 : 20) * 8, 5629 0xFFFF, 0, true, false, false); 5630 else 5631 error = bwn_nphy_tx_tone(mac, freq, 250, true, false, false); 5632 5633 if (error == 0) { 5634 if (nphy->mphase_cal_phase_id > 2) { 5635 table = nphy->mphase_txcal_bestcoeffs; 5636 length = 11; 5637 if (mac->mac_phy.rev < 3) 5638 length -= 2; 5639 } else { 5640 if (!full && nphy->txiqlocal_coeffsvalid) { 5641 table = nphy->txiqlocal_bestc; 5642 length = 11; 5643 if (mac->mac_phy.rev < 3) 5644 length -= 2; 5645 } else { 5646 full = true; 5647 if (mac->mac_phy.rev >= 3) { 5648 table = tbl_tx_iqlo_cal_startcoefs_nphyrev3; 5649 length = BWN_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3; 5650 } else { 5651 table = tbl_tx_iqlo_cal_startcoefs; 5652 length = BWN_NTAB_TX_IQLO_CAL_STARTCOEFS; 5653 } 5654 } 5655 } 5656 5657 bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 64), length, table); 5658 5659 if (full) { 5660 if (mac->mac_phy.rev >= 3) 5661 max = BWN_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3; 5662 else 5663 max = BWN_NTAB_TX_IQLO_CAL_CMDS_FULLCAL; 5664 } else { 5665 if (mac->mac_phy.rev >= 3) 5666 max = BWN_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3; 5667 else 5668 max = BWN_NTAB_TX_IQLO_CAL_CMDS_RECAL; 5669 } 5670 5671 if (mphase) { 5672 count = nphy->mphase_txcal_cmdidx; 5673 numb = min(max, 5674 (uint16_t)(count + nphy->mphase_txcal_numcmds)); 5675 } else { 5676 count = 0; 5677 numb = max; 5678 } 5679 5680 for (; count < numb; count++) { 5681 if (full) { 5682 if (mac->mac_phy.rev >= 3) 5683 cmd = tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[count]; 5684 else 5685 cmd = tbl_tx_iqlo_cal_cmds_fullcal[count]; 5686 } else { 5687 if (mac->mac_phy.rev >= 3) 5688 cmd = tbl_tx_iqlo_cal_cmds_recal_nphyrev3[count]; 5689 else 5690 cmd = tbl_tx_iqlo_cal_cmds_recal[count]; 5691 } 5692 5693 core = (cmd & 0x3000) >> 12; 5694 type = (cmd & 0x0F00) >> 8; 5695 5696 if (phy6or5x && updated[core] == 0) { 5697 bwn_nphy_update_tx_cal_ladder(mac, core); 5698 updated[core] = true; 5699 } 5700 5701 tmp = (params[core].ncorr[type] << 8) | 0x66; 5702 BWN_PHY_WRITE(mac, BWN_NPHY_IQLOCAL_CMDNNUM, tmp); 5703 5704 if (type == 1 || type == 3 || type == 4) { 5705 buffer[0] = bwn_ntab_read(mac, 5706 BWN_NTAB16(15, 69 + core)); 5707 diq_start = buffer[0]; 5708 buffer[0] = 0; 5709 bwn_ntab_write(mac, BWN_NTAB16(15, 69 + core), 5710 0); 5711 } 5712 5713 BWN_PHY_WRITE(mac, BWN_NPHY_IQLOCAL_CMD, cmd); 5714 for (i = 0; i < 2000; i++) { 5715 tmp = BWN_PHY_READ(mac, BWN_NPHY_IQLOCAL_CMD); 5716 if (tmp & 0xC000) 5717 break; 5718 DELAY(10); 5719 } 5720 5721 bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 96), length, 5722 buffer); 5723 bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 64), length, 5724 buffer); 5725 5726 if (type == 1 || type == 3 || type == 4) 5727 buffer[0] = diq_start; 5728 } 5729 5730 if (mphase) 5731 nphy->mphase_txcal_cmdidx = (numb >= max) ? 0 : numb; 5732 5733 last = (mac->mac_phy.rev < 3) ? 6 : 7; 5734 5735 if (!mphase || nphy->mphase_cal_phase_id == last) { 5736 bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 96), 4, buffer); 5737 bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 80), 4, buffer); 5738 if (mac->mac_phy.rev < 3) { 5739 buffer[0] = 0; 5740 buffer[1] = 0; 5741 buffer[2] = 0; 5742 buffer[3] = 0; 5743 } 5744 bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 88), 4, 5745 buffer); 5746 bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 101), 2, 5747 buffer); 5748 bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 85), 2, 5749 buffer); 5750 bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 93), 2, 5751 buffer); 5752 length = 11; 5753 if (mac->mac_phy.rev < 3) 5754 length -= 2; 5755 bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 96), length, 5756 nphy->txiqlocal_bestc); 5757 nphy->txiqlocal_coeffsvalid = true; 5758 nphy->txiqlocal_chanspec.center_freq = 5759 bwn_get_centre_freq(mac); 5760 nphy->txiqlocal_chanspec.channel_type = bwn_get_chan_type(mac, NULL); 5761 } else { 5762 length = 11; 5763 if (mac->mac_phy.rev < 3) 5764 length -= 2; 5765 bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 96), length, 5766 nphy->mphase_txcal_bestcoeffs); 5767 } 5768 5769 bwn_nphy_stop_playback(mac); 5770 BWN_PHY_WRITE(mac, BWN_NPHY_IQLOCAL_CMDGCTL, 0); 5771 } 5772 5773 bwn_nphy_tx_cal_phy_cleanup(mac); 5774 bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x110), 2, save); 5775 5776 if (mac->mac_phy.rev < 2 && (!mphase || nphy->mphase_cal_phase_id == last)) 5777 bwn_nphy_tx_iq_workaround(mac); 5778 5779 if (mac->mac_phy.rev >= 4) 5780 nphy->hang_avoid = avoid; 5781 5782 bwn_nphy_stay_in_carrier_search(mac, false); 5783 5784 return error; 5785} 5786 5787/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ReapplyTxCalCoeffs */ 5788static void bwn_nphy_reapply_tx_cal_coeffs(struct bwn_mac *mac) 5789{ 5790 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5791 uint8_t i; 5792 uint16_t buffer[7]; 5793 bool equal = true; 5794 5795 if (!nphy->txiqlocal_coeffsvalid || 5796 nphy->txiqlocal_chanspec.center_freq != bwn_get_centre_freq(mac) || 5797 nphy->txiqlocal_chanspec.channel_type != bwn_get_chan_type(mac, NULL)) 5798 return; 5799 5800 bwn_ntab_read_bulk(mac, BWN_NTAB16(15, 80), 7, buffer); 5801 for (i = 0; i < 4; i++) { 5802 if (buffer[i] != nphy->txiqlocal_bestc[i]) { 5803 equal = false; 5804 break; 5805 } 5806 } 5807 5808 if (!equal) { 5809 bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 80), 4, 5810 nphy->txiqlocal_bestc); 5811 for (i = 0; i < 4; i++) 5812 buffer[i] = 0; 5813 bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 88), 4, 5814 buffer); 5815 bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 85), 2, 5816 &nphy->txiqlocal_bestc[5]); 5817 bwn_ntab_write_bulk(mac, BWN_NTAB16(15, 93), 2, 5818 &nphy->txiqlocal_bestc[5]); 5819 } 5820} 5821 5822/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIqRev2 */ 5823static int bwn_nphy_rev2_cal_rx_iq(struct bwn_mac *mac, 5824 struct bwn_nphy_txgains target, uint8_t type, bool debug) 5825{ 5826 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 5827 int i, j, index; 5828 uint8_t rfctl[2]; 5829 uint8_t afectl_core; 5830 uint16_t tmp[6]; 5831 uint16_t cur_hpf1, cur_hpf2, cur_lna; 5832 uint32_t real, imag; 5833 bwn_band_t band; 5834 5835 uint8_t use; 5836 uint16_t cur_hpf; 5837 uint16_t lna[3] = { 3, 3, 1 }; 5838 uint16_t hpf1[3] = { 7, 2, 0 }; 5839 uint16_t hpf2[3] = { 2, 0, 0 }; 5840 uint32_t power[3] = { }; 5841 uint16_t gain_save[2]; 5842 uint16_t cal_gain[2]; 5843 struct bwn_nphy_iqcal_params cal_params[2]; 5844 struct bwn_nphy_iq_est est; 5845 int ret = 0; 5846 bool playtone = true; 5847 int desired = 13; 5848 5849 bwn_nphy_stay_in_carrier_search(mac, 1); 5850 5851 if (mac->mac_phy.rev < 2) 5852 bwn_nphy_reapply_tx_cal_coeffs(mac); 5853 bwn_ntab_read_bulk(mac, BWN_NTAB16(7, 0x110), 2, gain_save); 5854 for (i = 0; i < 2; i++) { 5855 bwn_nphy_iq_cal_gain_params(mac, i, target, &cal_params[i]); 5856 cal_gain[i] = cal_params[i].cal_gain; 5857 } 5858 bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x110), 2, cal_gain); 5859 5860 for (i = 0; i < 2; i++) { 5861 if (i == 0) { 5862 rfctl[0] = BWN_NPHY_RFCTL_INTC1; 5863 rfctl[1] = BWN_NPHY_RFCTL_INTC2; 5864 afectl_core = BWN_NPHY_AFECTL_C1; 5865 } else { 5866 rfctl[0] = BWN_NPHY_RFCTL_INTC2; 5867 rfctl[1] = BWN_NPHY_RFCTL_INTC1; 5868 afectl_core = BWN_NPHY_AFECTL_C2; 5869 } 5870 5871 tmp[1] = BWN_PHY_READ(mac, BWN_NPHY_RFSEQCA); 5872 tmp[2] = BWN_PHY_READ(mac, afectl_core); 5873 tmp[3] = BWN_PHY_READ(mac, BWN_NPHY_AFECTL_OVER); 5874 tmp[4] = BWN_PHY_READ(mac, rfctl[0]); 5875 tmp[5] = BWN_PHY_READ(mac, rfctl[1]); 5876 5877 BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, 5878 ~BWN_NPHY_RFSEQCA_RXDIS & 0xFFFF, 5879 ((1 - i) << BWN_NPHY_RFSEQCA_RXDIS_SHIFT)); 5880 BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, ~BWN_NPHY_RFSEQCA_TXEN, 5881 (1 - i)); 5882 BWN_PHY_SET(mac, afectl_core, 0x0006); 5883 BWN_PHY_SET(mac, BWN_NPHY_AFECTL_OVER, 0x0006); 5884 5885 band = bwn_current_band(mac); 5886 5887 if (nphy->rxcalparams & 0xFF000000) { 5888 if (band == BWN_BAND_5G) 5889 BWN_PHY_WRITE(mac, rfctl[0], 0x140); 5890 else 5891 BWN_PHY_WRITE(mac, rfctl[0], 0x110); 5892 } else { 5893 if (band == BWN_BAND_5G) 5894 BWN_PHY_WRITE(mac, rfctl[0], 0x180); 5895 else 5896 BWN_PHY_WRITE(mac, rfctl[0], 0x120); 5897 } 5898 5899 if (band == BWN_BAND_5G) 5900 BWN_PHY_WRITE(mac, rfctl[1], 0x148); 5901 else 5902 BWN_PHY_WRITE(mac, rfctl[1], 0x114); 5903 5904 if (nphy->rxcalparams & 0x10000) { 5905 BWN_RF_SETMASK(mac, B2055_C1_GENSPARE2, 0xFC, 5906 (i + 1)); 5907 BWN_RF_SETMASK(mac, B2055_C2_GENSPARE2, 0xFC, 5908 (2 - i)); 5909 } 5910 5911 for (j = 0; j < 4; j++) { 5912 if (j < 3) { 5913 cur_lna = lna[j]; 5914 cur_hpf1 = hpf1[j]; 5915 cur_hpf2 = hpf2[j]; 5916 } else { 5917 if (power[1] > 10000) { 5918 use = 1; 5919 cur_hpf = cur_hpf1; 5920 index = 2; 5921 } else { 5922 if (power[0] > 10000) { 5923 use = 1; 5924 cur_hpf = cur_hpf1; 5925 index = 1; 5926 } else { 5927 index = 0; 5928 use = 2; 5929 cur_hpf = cur_hpf2; 5930 } 5931 } 5932 cur_lna = lna[index]; 5933 cur_hpf1 = hpf1[index]; 5934 cur_hpf2 = hpf2[index]; 5935 cur_hpf += desired - bwn_hweight32(power[index]); 5936 cur_hpf = bwn_clamp_val(cur_hpf, 0, 10); 5937 if (use == 1) 5938 cur_hpf1 = cur_hpf; 5939 else 5940 cur_hpf2 = cur_hpf; 5941 } 5942 5943 tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) | 5944 (cur_lna << 2)); 5945 bwn_nphy_rf_ctl_override(mac, 0x400, tmp[0], 3, 5946 false); 5947 bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX); 5948 bwn_nphy_stop_playback(mac); 5949 5950 if (playtone) { 5951 ret = bwn_nphy_tx_tone(mac, 4000, 5952 (nphy->rxcalparams & 0xFFFF), 5953 false, false, true); 5954 playtone = false; 5955 } else { 5956 bwn_nphy_run_samples(mac, 160, 0xFFFF, 0, false, 5957 false, true); 5958 } 5959 5960 if (ret == 0) { 5961 if (j < 3) { 5962 bwn_nphy_rx_iq_est(mac, &est, 1024, 32, 5963 false); 5964 if (i == 0) { 5965 real = est.i0_pwr; 5966 imag = est.q0_pwr; 5967 } else { 5968 real = est.i1_pwr; 5969 imag = est.q1_pwr; 5970 } 5971 power[i] = ((real + imag) / 1024) + 1; 5972 } else { 5973 bwn_nphy_calc_rx_iq_comp(mac, 1 << i); 5974 } 5975 bwn_nphy_stop_playback(mac); 5976 } 5977 5978 if (ret != 0) 5979 break; 5980 } 5981 5982 BWN_RF_MASK(mac, B2055_C1_GENSPARE2, 0xFC); 5983 BWN_RF_MASK(mac, B2055_C2_GENSPARE2, 0xFC); 5984 BWN_PHY_WRITE(mac, rfctl[1], tmp[5]); 5985 BWN_PHY_WRITE(mac, rfctl[0], tmp[4]); 5986 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, tmp[3]); 5987 BWN_PHY_WRITE(mac, afectl_core, tmp[2]); 5988 BWN_PHY_WRITE(mac, BWN_NPHY_RFSEQCA, tmp[1]); 5989 5990 if (ret != 0) 5991 break; 5992 } 5993 5994 bwn_nphy_rf_ctl_override(mac, 0x400, 0, 3, true); 5995 bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX); 5996 bwn_ntab_write_bulk(mac, BWN_NTAB16(7, 0x110), 2, gain_save); 5997 5998 bwn_nphy_stay_in_carrier_search(mac, 0); 5999 6000 return ret; 6001} 6002 6003static int bwn_nphy_rev3_cal_rx_iq(struct bwn_mac *mac, 6004 struct bwn_nphy_txgains target, uint8_t type, bool debug) 6005{ 6006 return -1; 6007} 6008 6009/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIq */ 6010static int bwn_nphy_cal_rx_iq(struct bwn_mac *mac, 6011 struct bwn_nphy_txgains target, uint8_t type, bool debug) 6012{ 6013 if (mac->mac_phy.rev >= 7) 6014 type = 0; 6015 6016 if (mac->mac_phy.rev >= 3) 6017 return bwn_nphy_rev3_cal_rx_iq(mac, target, type, debug); 6018 else 6019 return bwn_nphy_rev2_cal_rx_iq(mac, target, type, debug); 6020} 6021 6022/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */ 6023static void bwn_nphy_set_rx_core_state(struct bwn_mac *mac, uint8_t mask) 6024{ 6025 struct bwn_phy *phy = &mac->mac_phy; 6026 struct bwn_phy_n *nphy = phy->phy_n; 6027 /* uint16_t buf[16]; it's rev3+ */ 6028 6029 nphy->phyrxchain = mask; 6030 6031 if (0 /* FIXME clk */) 6032 return; 6033 6034 bwn_mac_suspend(mac); 6035 6036 if (nphy->hang_avoid) 6037 bwn_nphy_stay_in_carrier_search(mac, true); 6038 6039 BWN_PHY_SETMASK(mac, BWN_NPHY_RFSEQCA, ~BWN_NPHY_RFSEQCA_RXEN, 6040 (mask & 0x3) << BWN_NPHY_RFSEQCA_RXEN_SHIFT); 6041 6042 if ((mask & 0x3) != 0x3) { 6043 BWN_PHY_WRITE(mac, BWN_NPHY_HPANT_SWTHRES, 1); 6044 if (mac->mac_phy.rev >= 3) { 6045 /* TODO */ 6046 } 6047 } else { 6048 BWN_PHY_WRITE(mac, BWN_NPHY_HPANT_SWTHRES, 0x1E); 6049 if (mac->mac_phy.rev >= 3) { 6050 /* TODO */ 6051 } 6052 } 6053 6054 bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX); 6055 6056 if (nphy->hang_avoid) 6057 bwn_nphy_stay_in_carrier_search(mac, false); 6058 6059 bwn_mac_enable(mac); 6060} 6061 6062bwn_txpwr_result_t 6063bwn_nphy_op_recalc_txpower(struct bwn_mac *mac, bool ignore_tssi) 6064{ 6065 struct bwn_phy *phy = &mac->mac_phy; 6066 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 6067 struct ieee80211_channel *channel = bwn_get_channel(mac); 6068 struct bwn_softc *sc = mac->mac_sc; 6069 struct bwn_ppr *ppr = &nphy->tx_pwr_max_ppr; 6070 uint8_t max; /* qdBm */ 6071 6072 if (nphy->tx_pwr_last_recalc_freq == bwn_get_centre_freq(mac) && 6073 nphy->tx_pwr_last_recalc_limit == phy->txpower) 6074 return BWN_TXPWR_RES_DONE; 6075 6076 /* Make sure we have a clean PPR */ 6077 bwn_ppr_clear(mac, ppr); 6078 6079 /* HW limitations */ 6080 bwn_ppr_load_max_from_sprom(mac, ppr, BWN_PHY_BAND_2G); 6081 /* XXX TODO: other bands? */ 6082 6083 /* Regulatory & user settings */ 6084 max = INT_TO_Q52(bwn_get_chan_power(mac, channel)); 6085 /* uint8_t */ 6086 if (phy->txpower) 6087 max = min(max, INT_TO_Q52(phy->txpower)); 6088 bwn_ppr_apply_max(mac, ppr, max); 6089 DPRINTF(mac->mac_sc, BWN_DEBUG_XMIT_POWER, 6090 "Calculated TX power: " Q52_FMT "\n", 6091 Q52_ARG(bwn_ppr_get_max(mac, ppr))); 6092 6093 /* TODO: Enable this once we get gains working */ 6094#if 0 6095 /* Some extra gains */ 6096 hw_gain = 6; /* N-PHY specific */ 6097 if (bwn_current_band(mac) == BWN_BAND_2G) 6098 hw_gain += sprom->antenna_gain.a0; 6099 else 6100 hw_gain += sprom->antenna_gain.a1; 6101 bwn_ppr_add(mac, ppr, -hw_gain); 6102#endif 6103 6104 /* Make sure we didn't go too low */ 6105 bwn_ppr_apply_min(mac, ppr, INT_TO_Q52(8)); 6106 6107 /* Apply */ 6108 bwn_mac_suspend(mac); 6109 bwn_nphy_tx_power_ctl_setup(mac); 6110 if (bhnd_get_hwrev(sc->sc_dev) == 11 || bhnd_get_hwrev(sc->sc_dev) == 12) { 6111 BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~0, BWN_MACCTL_PHY_LOCK); 6112 BWN_READ_4(mac, BWN_MACCTL); 6113 DELAY(1); 6114 } 6115 bwn_nphy_tx_power_ctrl(mac, nphy->txpwrctrl); 6116 if (bhnd_get_hwrev(sc->sc_dev) == 11 || bhnd_get_hwrev(sc->sc_dev) == 12) 6117 BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~BWN_MACCTL_PHY_LOCK, 0); 6118 bwn_mac_enable(mac); 6119 6120 nphy->tx_pwr_last_recalc_freq = bwn_get_centre_freq(mac); 6121 nphy->tx_pwr_last_recalc_limit = phy->txpower; 6122 6123 return BWN_TXPWR_RES_DONE; 6124} 6125 6126/************************************************** 6127 * N-PHY init 6128 **************************************************/ 6129 6130/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */ 6131static void bwn_nphy_update_mimo_config(struct bwn_mac *mac, int32_t preamble) 6132{ 6133 uint16_t mimocfg = BWN_PHY_READ(mac, BWN_NPHY_MIMOCFG); 6134 6135 mimocfg |= BWN_NPHY_MIMOCFG_AUTO; 6136 if (preamble == 1) 6137 mimocfg |= BWN_NPHY_MIMOCFG_GFMIX; 6138 else 6139 mimocfg &= ~BWN_NPHY_MIMOCFG_GFMIX; 6140 6141 BWN_PHY_WRITE(mac, BWN_NPHY_MIMOCFG, mimocfg); 6142} 6143 6144/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BPHYInit */ 6145static void bwn_nphy_bphy_init(struct bwn_mac *mac) 6146{ 6147 unsigned int i; 6148 uint16_t val; 6149 6150 val = 0x1E1F; 6151 for (i = 0; i < 16; i++) { 6152 BWN_PHY_WRITE(mac, BWN_PHY_N_BMODE(0x88 + i), val); 6153 val -= 0x202; 6154 } 6155 val = 0x3E3F; 6156 for (i = 0; i < 16; i++) { 6157 BWN_PHY_WRITE(mac, BWN_PHY_N_BMODE(0x98 + i), val); 6158 val -= 0x202; 6159 } 6160 BWN_PHY_WRITE(mac, BWN_PHY_N_BMODE(0x38), 0x668); 6161} 6162 6163/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */ 6164static int bwn_nphy_superswitch_init(struct bwn_mac *mac, bool init) 6165{ 6166 int error; 6167 6168 if (mac->mac_phy.rev >= 7) 6169 return (0); 6170 6171 if (mac->mac_phy.rev >= 3) { 6172 if (!init) 6173 return (0); 6174 if (0 /* FIXME */) { 6175 bwn_ntab_write(mac, BWN_NTAB16(9, 2), 0x211); 6176 bwn_ntab_write(mac, BWN_NTAB16(9, 3), 0x222); 6177 bwn_ntab_write(mac, BWN_NTAB16(9, 8), 0x144); 6178 bwn_ntab_write(mac, BWN_NTAB16(9, 12), 0x188); 6179 } 6180 } else { 6181 BWN_PHY_WRITE(mac, BWN_NPHY_GPIO_LOOEN, 0); 6182 BWN_PHY_WRITE(mac, BWN_NPHY_GPIO_HIOEN, 0); 6183 6184 if ((error = bwn_gpio_control(mac, 0xfc00))) 6185 return (error); 6186 6187 BWN_WRITE_SETMASK4(mac, BWN_MACCTL, ~BWN_MACCTL_GPOUT_MASK, 0); 6188 BWN_WRITE_SETMASK2(mac, BWN_GPIO_MASK, ~0, 0xFC00); 6189 BWN_WRITE_SETMASK2(mac, BWN_GPIO_CONTROL, (~0xFC00 & 0xFFFF), 6190 0); 6191 6192 if (init) { 6193 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); 6194 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP1, 0x301); 6195 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); 6196 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); 6197 } 6198 } 6199 6200 return (0); 6201} 6202 6203/* http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N */ 6204static int bwn_phy_initn(struct bwn_mac *mac) 6205{ 6206 struct bwn_softc *sc = mac->mac_sc; 6207 struct bwn_phy *phy = &mac->mac_phy; 6208 struct bwn_phy_n *nphy = phy->phy_n; 6209 uint8_t tx_pwr_state; 6210 struct bwn_nphy_txgains target; 6211 int error; 6212 uint16_t tmp; 6213 bool do_rssi_cal; 6214 6215 uint16_t clip[2]; 6216 bool do_cal = false; 6217 6218 if (mac->mac_phy.rev >= 3) { 6219 error = bhnd_nvram_getvar_uint8(sc->sc_dev, BHND_NVAR_TSSIPOS2G, 6220 &nphy->tsspos_2g); 6221 if (error) { 6222 BWN_ERRPRINTF(mac->mac_sc, "Error reading %s from " 6223 "NVRAM: %d\n", BHND_NVAR_TSSIPOS2G, error); 6224 return (error); 6225 } 6226 } else { 6227 nphy->tsspos_2g = 0; 6228 } 6229 6230 if ((mac->mac_phy.rev >= 3) && 6231 (sc->sc_board_info.board_flags & BHND_BFL_EXTLNA) && 6232 (bwn_current_band(mac) == BWN_BAND_2G)) 6233 { 6234 BHND_CHIPC_WRITE_CHIPCTRL(sc->sc_chipc, 0x40, 0x40); 6235 } 6236 nphy->use_int_tx_iq_lo_cal = bwn_nphy_ipa(mac) || 6237 phy->rev >= 7 || 6238 (phy->rev >= 5 && 6239 sc->sc_board_info.board_flags2 & BHND_BFL2_INTERNDET_TXIQCAL); 6240 nphy->deaf_count = 0; 6241 bwn_nphy_tables_init(mac); 6242 nphy->crsminpwr_adjusted = false; 6243 nphy->noisevars_adjusted = false; 6244 6245 /* Clear all overrides */ 6246 if (mac->mac_phy.rev >= 3) { 6247 BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B1S1, 0); 6248 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_OVER, 0); 6249 if (phy->rev >= 7) { 6250 BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER3, 0); 6251 BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER4, 0); 6252 BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER5, 0); 6253 BWN_PHY_WRITE(mac, BWN_NPHY_REV7_RF_CTL_OVER6, 0); 6254 } 6255 if (phy->rev >= 19) { 6256 /* TODO */ 6257 } 6258 6259 BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B1S0, 0); 6260 BWN_PHY_WRITE(mac, BWN_NPHY_TXF_40CO_B32S1, 0); 6261 } else { 6262 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_OVER, 0); 6263 } 6264 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC1, 0); 6265 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC2, 0); 6266 if (mac->mac_phy.rev < 6) { 6267 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC3, 0); 6268 BWN_PHY_WRITE(mac, BWN_NPHY_RFCTL_INTC4, 0); 6269 } 6270 BWN_PHY_MASK(mac, BWN_NPHY_RFSEQMODE, 6271 ~(BWN_NPHY_RFSEQMODE_CAOVER | 6272 BWN_NPHY_RFSEQMODE_TROVER)); 6273 if (mac->mac_phy.rev >= 3) 6274 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, 0); 6275 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, 0); 6276 6277 if (mac->mac_phy.rev <= 2) { 6278 tmp = (mac->mac_phy.rev == 2) ? 0x3B : 0x40; 6279 BWN_PHY_SETMASK(mac, BWN_NPHY_BPHY_CTL3, 6280 ~BWN_NPHY_BPHY_CTL3_SCALE, 6281 tmp << BWN_NPHY_BPHY_CTL3_SCALE_SHIFT); 6282 } 6283 BWN_PHY_WRITE(mac, BWN_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20); 6284 BWN_PHY_WRITE(mac, BWN_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20); 6285 6286 if (sc->sc_board_info.board_flags2 & BHND_BFL2_SKWRKFEM_BRD || 6287 (sc->sc_board_info.board_vendor == PCI_VENDOR_APPLE && 6288 sc->sc_board_info.board_type == BHND_BOARD_BCM943224M93)) 6289 BWN_PHY_WRITE(mac, BWN_NPHY_TXREALFD, 0xA0); 6290 else 6291 BWN_PHY_WRITE(mac, BWN_NPHY_TXREALFD, 0xB8); 6292 BWN_PHY_WRITE(mac, BWN_NPHY_MIMO_CRSTXEXT, 0xC8); 6293 BWN_PHY_WRITE(mac, BWN_NPHY_PLOAD_CSENSE_EXTLEN, 0x50); 6294 BWN_PHY_WRITE(mac, BWN_NPHY_TXRIFS_FRDEL, 0x30); 6295 6296 if (phy->rev < 8) 6297 bwn_nphy_update_mimo_config(mac, nphy->preamble_override); 6298 6299 bwn_nphy_update_txrx_chain(mac); 6300 6301 if (phy->rev < 2) { 6302 BWN_PHY_WRITE(mac, BWN_NPHY_DUP40_GFBL, 0xAA8); 6303 BWN_PHY_WRITE(mac, BWN_NPHY_DUP40_BL, 0x9A4); 6304 } 6305 6306 if (bwn_nphy_ipa(mac)) { 6307 BWN_PHY_SET(mac, BWN_NPHY_PAPD_EN0, 0x1); 6308 BWN_PHY_SETMASK(mac, BWN_NPHY_EPS_TABLE_ADJ0, 0x007F, 6309 nphy->papd_epsilon_offset[0] << 7); 6310 BWN_PHY_SET(mac, BWN_NPHY_PAPD_EN1, 0x1); 6311 BWN_PHY_SETMASK(mac, BWN_NPHY_EPS_TABLE_ADJ1, 0x007F, 6312 nphy->papd_epsilon_offset[1] << 7); 6313 bwn_nphy_int_pa_set_tx_dig_filters(mac); 6314 } else if (phy->rev >= 5) { 6315 bwn_nphy_ext_pa_set_tx_dig_filters(mac); 6316 } 6317 6318 if ((error = bwn_nphy_workarounds(mac))) 6319 return (error); 6320 6321 /* Reset CCA, in init code it differs a little from standard way */ 6322 bwn_phy_force_clock(mac, 1); 6323 tmp = BWN_PHY_READ(mac, BWN_NPHY_BBCFG); 6324 BWN_PHY_WRITE(mac, BWN_NPHY_BBCFG, tmp | BWN_NPHY_BBCFG_RSTCCA); 6325 BWN_PHY_WRITE(mac, BWN_NPHY_BBCFG, tmp & ~BWN_NPHY_BBCFG_RSTCCA); 6326 bwn_phy_force_clock(mac, 0); 6327 6328 bwn_mac_phy_clock_set(mac, true); 6329 6330 if (phy->rev < 7) { 6331 bwn_nphy_pa_override(mac, false); 6332 bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RX2TX); 6333 bwn_nphy_force_rf_sequence(mac, BWN_RFSEQ_RESET2RX); 6334 bwn_nphy_pa_override(mac, true); 6335 } 6336 6337 bwn_nphy_classifier(mac, 0, 0); 6338 bwn_nphy_read_clip_detection(mac, clip); 6339 if (bwn_current_band(mac) == BWN_BAND_2G) 6340 bwn_nphy_bphy_init(mac); 6341 6342 tx_pwr_state = nphy->txpwrctrl; 6343 bwn_nphy_tx_power_ctrl(mac, false); 6344 if ((error = bwn_nphy_tx_power_fix(mac))) 6345 return (error); 6346 bwn_nphy_tx_power_ctl_idle_tssi(mac); 6347 bwn_nphy_tx_power_ctl_setup(mac); 6348 bwn_nphy_tx_gain_table_upload(mac); 6349 6350 if (nphy->phyrxchain != 3) 6351 bwn_nphy_set_rx_core_state(mac, nphy->phyrxchain); 6352 if (nphy->mphase_cal_phase_id > 0) 6353 ;/* TODO PHY Periodic Calibration Multi-Phase Restart */ 6354 6355 do_rssi_cal = false; 6356 if (phy->rev >= 3) { 6357 if (bwn_current_band(mac) == BWN_BAND_2G) 6358 do_rssi_cal = !nphy->rssical_chanspec_2G.center_freq; 6359 else 6360 do_rssi_cal = !nphy->rssical_chanspec_5G.center_freq; 6361 6362 if (do_rssi_cal) 6363 bwn_nphy_rssi_cal(mac); 6364 else 6365 bwn_nphy_restore_rssi_cal(mac); 6366 } else { 6367 bwn_nphy_rssi_cal(mac); 6368 } 6369 6370 if (!((nphy->measure_hold & 0x6) != 0)) { 6371 if (bwn_current_band(mac) == BWN_BAND_2G) 6372 do_cal = !nphy->iqcal_chanspec_2G.center_freq; 6373 else 6374 do_cal = !nphy->iqcal_chanspec_5G.center_freq; 6375 6376 if (nphy->mute) 6377 do_cal = false; 6378 6379 if (do_cal) { 6380 target = bwn_nphy_get_tx_gains(mac); 6381 6382 if (nphy->antsel_type == 2) { 6383 error = bwn_nphy_superswitch_init(mac, true); 6384 if (error) 6385 return (error); 6386 } 6387 if (nphy->perical != 2) { 6388 bwn_nphy_rssi_cal(mac); 6389 if (phy->rev >= 3) { 6390 nphy->cal_orig_pwr_idx[0] = 6391 nphy->txpwrindex[0].index_internal; 6392 nphy->cal_orig_pwr_idx[1] = 6393 nphy->txpwrindex[1].index_internal; 6394 /* TODO N PHY Pre Calibrate TX Gain */ 6395 target = bwn_nphy_get_tx_gains(mac); 6396 } 6397 if (!bwn_nphy_cal_tx_iq_lo(mac, target, true, false)) 6398 if (bwn_nphy_cal_rx_iq(mac, target, 2, 0) == 0) 6399 bwn_nphy_save_cal(mac); 6400 } else if (nphy->mphase_cal_phase_id == 0) 6401 ;/* N PHY Periodic Calibration with arg 3 */ 6402 } else { 6403 bwn_nphy_restore_cal(mac); 6404 } 6405 } 6406 6407 bwn_nphy_tx_pwr_ctrl_coef_setup(mac); 6408 bwn_nphy_tx_power_ctrl(mac, tx_pwr_state); 6409 BWN_PHY_WRITE(mac, BWN_NPHY_TXMACIF_HOLDOFF, 0x0015); 6410 BWN_PHY_WRITE(mac, BWN_NPHY_TXMACDELAY, 0x0320); 6411 if (phy->rev >= 3 && phy->rev <= 6) 6412 BWN_PHY_WRITE(mac, BWN_NPHY_PLOAD_CSENSE_EXTLEN, 0x0032); 6413 bwn_nphy_tx_lpf_bw(mac); 6414 if (phy->rev >= 3) 6415 bwn_nphy_spur_workaround(mac); 6416 6417 return 0; 6418} 6419 6420/************************************************** 6421 * Channel switching ops. 6422 **************************************************/ 6423 6424static void bwn_chantab_phy_upload(struct bwn_mac *mac, 6425 const struct bwn_phy_n_sfo_cfg *e) 6426{ 6427 BWN_PHY_WRITE(mac, BWN_NPHY_BW1A, e->phy_bw1a); 6428 BWN_PHY_WRITE(mac, BWN_NPHY_BW2, e->phy_bw2); 6429 BWN_PHY_WRITE(mac, BWN_NPHY_BW3, e->phy_bw3); 6430 BWN_PHY_WRITE(mac, BWN_NPHY_BW4, e->phy_bw4); 6431 BWN_PHY_WRITE(mac, BWN_NPHY_BW5, e->phy_bw5); 6432 BWN_PHY_WRITE(mac, BWN_NPHY_BW6, e->phy_bw6); 6433} 6434 6435/* http://bcm-v4.sipsolutions.net/802.11/PmuSpurAvoid */ 6436static void bwn_nphy_pmu_spur_avoid(struct bwn_mac *mac, 6437 bhnd_pmu_spuravoid mode) 6438{ 6439 struct bwn_softc *sc = mac->mac_sc; 6440 int error; 6441 6442 DPRINTF(sc, BWN_DEBUG_RESET, "%s: spuravoid %d\n", __func__, mode); 6443 6444 if (sc->sc_pmu == NULL) { 6445 BWN_ERRPRINTF(mac->mac_sc, "no PMU; cannot configure spurious " 6446 "signal avoidance\n"); 6447 return; 6448 } 6449 6450 if ((error = bhnd_pmu_request_spuravoid(sc->sc_pmu, mode))) { 6451 device_printf(sc->sc_dev, "spuravoid request failed: %d", 6452 error); 6453 } 6454} 6455 6456/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */ 6457static int bwn_nphy_channel_setup(struct bwn_mac *mac, 6458 const struct bwn_phy_n_sfo_cfg *e, 6459 struct ieee80211_channel *new_channel) 6460{ 6461 struct bwn_softc *sc = mac->mac_sc; 6462 struct bwn_phy *phy = &mac->mac_phy; 6463 struct bwn_phy_n *nphy = mac->mac_phy.phy_n; 6464 int ch = new_channel->ic_ieee; 6465 int error; 6466 uint16_t tmp16; 6467 6468 if (bwn_channel_band(mac, new_channel) == BWN_BAND_5G) { 6469 DPRINTF(sc, BWN_DEBUG_RESET, "%s: BAND_5G; chan=%d\n", __func__, ch); 6470 /* Switch to 2 GHz for a moment to access BWN_PHY_B_BBCFG */ 6471 BWN_PHY_MASK(mac, BWN_NPHY_BANDCTL, ~BWN_NPHY_BANDCTL_5GHZ); 6472 6473 tmp16 = BWN_READ_2(mac, BWN_PSM_PHY_HDR); 6474 BWN_WRITE_2(mac, BWN_PSM_PHY_HDR, tmp16 | 4); 6475 /* Put BPHY in the reset */ 6476 BWN_PHY_SET(mac, BWN_PHY_B_BBCFG, 6477 BWN_PHY_B_BBCFG_RSTCCA | BWN_PHY_B_BBCFG_RSTRX); 6478 BWN_WRITE_2(mac, BWN_PSM_PHY_HDR, tmp16); 6479 BWN_PHY_SET(mac, BWN_NPHY_BANDCTL, BWN_NPHY_BANDCTL_5GHZ); 6480 } else if (bwn_channel_band(mac, new_channel) == BWN_BAND_2G) { 6481 DPRINTF(sc, BWN_DEBUG_RESET, "%s: BAND_2G; chan=%d\n", __func__, ch); 6482 BWN_PHY_MASK(mac, BWN_NPHY_BANDCTL, ~BWN_NPHY_BANDCTL_5GHZ); 6483 tmp16 = BWN_READ_2(mac, BWN_PSM_PHY_HDR); 6484 BWN_WRITE_2(mac, BWN_PSM_PHY_HDR, tmp16 | 4); 6485 /* Take BPHY out of the reset */ 6486 BWN_PHY_MASK(mac, BWN_PHY_B_BBCFG, 6487 (uint16_t)~(BWN_PHY_B_BBCFG_RSTCCA | BWN_PHY_B_BBCFG_RSTRX)); 6488 BWN_WRITE_2(mac, BWN_PSM_PHY_HDR, tmp16); 6489 } else { 6490 BWN_ERRPRINTF(mac->mac_sc, "%s: unknown band?\n", __func__); 6491 } 6492 6493 bwn_chantab_phy_upload(mac, e); 6494 6495 if (new_channel->ic_ieee == 14) { 6496 bwn_nphy_classifier(mac, 2, 0); 6497 BWN_PHY_SET(mac, BWN_PHY_B_TEST, 0x0800); 6498 } else { 6499 bwn_nphy_classifier(mac, 2, 2); 6500 if (bwn_channel_band(mac, new_channel) == BWN_BAND_2G) 6501 BWN_PHY_MASK(mac, BWN_PHY_B_TEST, ~0x840); 6502 } 6503 6504 if (!nphy->txpwrctrl) { 6505 if ((error = bwn_nphy_tx_power_fix(mac))) 6506 return (error); 6507 } 6508 6509 if (mac->mac_phy.rev < 3) 6510 bwn_nphy_adjust_lna_gain_table(mac); 6511 6512 bwn_nphy_tx_lpf_bw(mac); 6513 6514 if (mac->mac_phy.rev >= 3 && 6515 mac->mac_phy.phy_n->spur_avoid != BWN_SPUR_AVOID_DISABLE) { 6516 bhnd_pmu_spuravoid spuravoid = BHND_PMU_SPURAVOID_NONE; 6517 6518 if (mac->mac_phy.phy_n->spur_avoid == BWN_SPUR_AVOID_FORCE) { 6519 spuravoid = BHND_PMU_SPURAVOID_M1; 6520 } else if (phy->rev >= 19) { 6521 /* TODO */ 6522 } else if (phy->rev >= 18) { 6523 /* TODO */ 6524 } else if (phy->rev >= 17) { 6525 /* TODO: Off for channels 1-11, but check 12-14! */ 6526 } else if (phy->rev >= 16) { 6527 /* TODO: Off for 2 GHz, but check 5 GHz! */ 6528 } else if (phy->rev >= 7) { 6529 if (!bwn_is_40mhz(mac)) { /* 20MHz */ 6530 if (ch == 13 || ch == 14 || ch == 153) 6531 spuravoid = BHND_PMU_SPURAVOID_M1; 6532 } else { /* 40 MHz */ 6533 if (ch == 54) 6534 spuravoid = BHND_PMU_SPURAVOID_M1; 6535 } 6536 } else { 6537 if (!bwn_is_40mhz(mac)) { /* 20MHz */ 6538 if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14) 6539 spuravoid = BHND_PMU_SPURAVOID_M1; 6540 } else { /* 40MHz */ 6541 if (nphy->aband_spurwar_en && 6542 (ch == 38 || ch == 102 || ch == 118) && 6543 sc->sc_cid.chip_id == BHND_CHIPID_BCM4716) 6544 spuravoid = BHND_PMU_SPURAVOID_M1; 6545 } 6546 } 6547 6548 bwn_nphy_pmu_spur_avoid(mac, spuravoid); 6549 6550 bwn_mac_switch_freq(mac, spuravoid); 6551 6552 if (mac->mac_phy.rev == 3 || mac->mac_phy.rev == 4) 6553 bwn_wireless_core_phy_pll_reset(mac); 6554 6555 if (spuravoid != BHND_PMU_SPURAVOID_NONE) 6556 BWN_PHY_SET(mac, BWN_NPHY_BBCFG, BWN_NPHY_BBCFG_RSTRX); 6557 else 6558 BWN_PHY_MASK(mac, BWN_NPHY_BBCFG, 6559 ~BWN_NPHY_BBCFG_RSTRX & 0xFFFF); 6560 6561 bwn_nphy_reset_cca(mac); 6562 6563 /* wl sets useless phy_isspuravoid here */ 6564 } 6565 6566 BWN_PHY_WRITE(mac, BWN_NPHY_NDATAT_DUP40, 0x3830); 6567 6568 if (phy->rev >= 3) 6569 bwn_nphy_spur_workaround(mac); 6570 6571 return (0); 6572} 6573 6574/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */ 6575static int bwn_nphy_set_channel(struct bwn_mac *mac, 6576 struct ieee80211_channel *channel, 6577 bwn_chan_type_t channel_type) 6578{ 6579 struct bwn_phy *phy = &mac->mac_phy; 6580 6581 const struct bwn_nphy_channeltab_entry_rev2 *tabent_r2 = NULL; 6582 const struct bwn_nphy_channeltab_entry_rev3 *tabent_r3 = NULL; 6583 const struct bwn_nphy_chantabent_rev7 *tabent_r7 = NULL; 6584 const struct bwn_nphy_chantabent_rev7_2g *tabent_r7_2g = NULL; 6585 6586 int error; 6587 uint8_t tmp; 6588 6589 if (phy->rev >= 19) { 6590 return -ESRCH; 6591 /* TODO */ 6592 } else if (phy->rev >= 7) { 6593 r2057_get_chantabent_rev7(mac, bwn_get_chan_centre_freq(mac, channel), 6594 &tabent_r7, &tabent_r7_2g); 6595 if (!tabent_r7 && !tabent_r7_2g) 6596 return -ESRCH; 6597 } else if (phy->rev >= 3) { 6598 tabent_r3 = bwn_nphy_get_chantabent_rev3(mac, 6599 bwn_get_chan_centre_freq(mac, channel)); 6600 if (!tabent_r3) 6601 return -ESRCH; 6602 } else { 6603 tabent_r2 = bwn_nphy_get_chantabent_rev2(mac, 6604 channel->ic_ieee); 6605 if (!tabent_r2) 6606 return -ESRCH; 6607 } 6608 6609 /* Channel is set later in common code, but we need to set it on our 6610 own to let this function's subcalls work properly. */ 6611#if 0 6612 phy->channel = channel->ic_ieee; 6613#endif 6614 6615#if 0 6616 if (bwn_channel_type_is_40mhz(phy->channel_type) != 6617 bwn_channel_type_is_40mhz(channel_type)) 6618 ; /* TODO: BMAC BW Set (channel_type) */ 6619#endif 6620 6621 if (channel_type == BWN_CHAN_TYPE_40_HT_U) { 6622 BWN_PHY_SET(mac, BWN_NPHY_RXCTL, BWN_NPHY_RXCTL_BSELU20); 6623 if (phy->rev >= 7) 6624 BWN_PHY_SET(mac, 0x310, 0x8000); 6625 } else if (channel_type == BWN_CHAN_TYPE_40_HT_D) { 6626 BWN_PHY_MASK(mac, BWN_NPHY_RXCTL, ~BWN_NPHY_RXCTL_BSELU20); 6627 if (phy->rev >= 7) 6628 BWN_PHY_MASK(mac, 0x310, (uint16_t)~0x8000); 6629 } 6630 6631 if (phy->rev >= 19) { 6632 /* TODO */ 6633 error = ENODEV; 6634 } else if (phy->rev >= 7) { 6635 const struct bwn_phy_n_sfo_cfg *phy_regs = tabent_r7 ? 6636 &(tabent_r7->phy_regs) : &(tabent_r7_2g->phy_regs); 6637 6638 if (phy->rf_rev <= 4 || phy->rf_rev == 6) { 6639 tmp = (bwn_channel_band(mac, channel) == BWN_BAND_5G) ? 2 : 0; 6640 BWN_RF_SETMASK(mac, R2057_TIA_CONFIG_CORE0, ~2, tmp); 6641 BWN_RF_SETMASK(mac, R2057_TIA_CONFIG_CORE1, ~2, tmp); 6642 } 6643 6644 bwn_radio_2057_setup(mac, tabent_r7, tabent_r7_2g); 6645 error = bwn_nphy_channel_setup(mac, phy_regs, channel); 6646 } else if (phy->rev >= 3) { 6647 tmp = (bwn_channel_band(mac, channel) == BWN_BAND_5G) ? 4 : 0; 6648 BWN_RF_SETMASK(mac, 0x08, 0xFFFB, tmp); 6649 bwn_radio_2056_setup(mac, tabent_r3); 6650 error = bwn_nphy_channel_setup(mac, &(tabent_r3->phy_regs), 6651 channel); 6652 } else { 6653 tmp = (bwn_channel_band(mac, channel) == BWN_BAND_5G) ? 0x0020 : 0x0050; 6654 BWN_RF_SETMASK(mac, B2055_MASTER1, 0xFF8F, tmp); 6655 bwn_radio_2055_setup(mac, tabent_r2); 6656 error = bwn_nphy_channel_setup(mac, &(tabent_r2->phy_regs), 6657 channel); 6658 } 6659 6660 return (error); 6661} 6662 6663/************************************************** 6664 * Basic PHY ops. 6665 **************************************************/ 6666 6667int 6668bwn_nphy_op_allocate(struct bwn_mac *mac) 6669{ 6670 struct bwn_phy_n *nphy; 6671 6672 nphy = malloc(sizeof(*nphy), M_DEVBUF, M_ZERO | M_NOWAIT); 6673 if (!nphy) 6674 return -ENOMEM; 6675 6676 mac->mac_phy.phy_n = nphy; 6677 6678 return 0; 6679} 6680 6681int 6682bwn_nphy_op_prepare_structs(struct bwn_mac *mac) 6683{ 6684 struct bwn_softc *sc = mac->mac_sc; 6685 struct bwn_phy *phy = &mac->mac_phy; 6686 struct bwn_phy_n *nphy = phy->phy_n; 6687 int error; 6688 6689 memset(nphy, 0, sizeof(*nphy)); 6690 6691 nphy->hang_avoid = (phy->rev == 3 || phy->rev == 4); 6692 nphy->spur_avoid = (phy->rev >= 3) ? 6693 BWN_SPUR_AVOID_AUTO : BWN_SPUR_AVOID_DISABLE; 6694 nphy->gain_boost = true; /* this way we follow wl, assume it is true */ 6695 nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */ 6696 nphy->phyrxchain = 3; /* to avoid bwn_nphy_set_rx_core_state like wl */ 6697 nphy->perical = 2; /* avoid additional rssi cal on init (like wl) */ 6698 /* 128 can mean disabled-by-default state of TX pwr ctl. Max value is 6699 * 0x7f == 127 and we check for 128 when restoring TX pwr ctl. */ 6700 nphy->tx_pwr_idx[0] = 128; 6701 nphy->tx_pwr_idx[1] = 128; 6702 6703 /* Hardware TX power control and 5GHz power gain */ 6704 nphy->txpwrctrl = false; 6705 nphy->pwg_gain_5ghz = false; 6706 if (mac->mac_phy.rev >= 3 || 6707 (sc->sc_board_info.board_vendor == PCI_VENDOR_APPLE && 6708 (bhnd_get_hwrev(sc->sc_dev) == 11 || bhnd_get_hwrev(sc->sc_dev) == 12))) { 6709 nphy->txpwrctrl = true; 6710 nphy->pwg_gain_5ghz = true; 6711 } else if (sc->sc_board_info.board_srom_rev >= 4) { 6712 if (mac->mac_phy.rev >= 2 && 6713 (sc->sc_board_info.board_flags2 & BHND_BFL2_TXPWRCTRL_EN)) { 6714 nphy->txpwrctrl = true; 6715 if ((sc->sc_board_info.board_devid == PCI_DEVID_BCM4321_D11N) || 6716 (sc->sc_board_info.board_devid == PCI_DEVID_BCM4321_D11N5G)) 6717 nphy->pwg_gain_5ghz = true; 6718 } else if (sc->sc_board_info.board_flags2 & BHND_BFL2_5G_PWRGAIN) { 6719 nphy->pwg_gain_5ghz = true; 6720 } 6721 } 6722 6723 if (mac->mac_phy.rev >= 3) { 6724 uint8_t extpa_gain2g, extpa_gain5g; 6725 6726 error = bhnd_nvram_getvar_uint8(sc->sc_dev, 6727 BHND_NVAR_EXTPAGAIN2G, &extpa_gain2g); 6728 if (error) { 6729 BWN_ERRPRINTF(mac->mac_sc, "Error reading 2GHz EPA " 6730 "gain configuration from NVRAM: %d\n", error); 6731 return (error); 6732 } 6733 6734 error = bhnd_nvram_getvar_uint8(sc->sc_dev, 6735 BHND_NVAR_EXTPAGAIN5G, &extpa_gain5g); 6736 if (error) { 6737 BWN_ERRPRINTF(mac->mac_sc, "Error reading 5GHz EPA " 6738 "gain configuration from NVRAM: %d\n", error); 6739 return (error); 6740 } 6741 6742 nphy->ipa2g_on = (extpa_gain2g == 2); 6743 nphy->ipa5g_on = (extpa_gain5g == 2); 6744 } 6745 6746 return (0); 6747} 6748 6749void 6750bwn_nphy_op_free(struct bwn_mac *mac) 6751{ 6752 struct bwn_phy *phy = &mac->mac_phy; 6753 struct bwn_phy_n *nphy = phy->phy_n; 6754 6755 free(nphy, M_DEVBUF); 6756 phy->phy_n = NULL; 6757} 6758 6759int 6760bwn_nphy_op_init(struct bwn_mac *mac) 6761{ 6762 return bwn_phy_initn(mac); 6763} 6764 6765static inline void check_phyreg(struct bwn_mac *mac, uint16_t offset) 6766{ 6767#ifdef BWN_DEBUG 6768 if ((offset & BWN_PHYROUTE_MASK) == BWN_PHYROUTE_OFDM_GPHY) { 6769 /* OFDM registers are onnly available on A/G-PHYs */ 6770 BWN_ERRPRINTF(mac->mac_sc, "Invalid OFDM PHY access at " 6771 "0x%04X on N-PHY\n", offset); 6772 } 6773 if ((offset & BWN_PHYROUTE_MASK) == BWN_PHYROUTE_EXT_GPHY) { 6774 /* Ext-G registers are only available on G-PHYs */ 6775 BWN_ERRPRINTF(mac->mac_sc, "Invalid EXT-G PHY access at " 6776 "0x%04X on N-PHY\n", offset); 6777 } 6778#endif /* BWN_DEBUG */ 6779} 6780 6781void 6782bwn_nphy_op_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask, 6783 uint16_t set) 6784{ 6785 check_phyreg(mac, reg); 6786 BWN_WRITE_2_F(mac, BWN_PHYCTL, reg); 6787 BWN_WRITE_SETMASK2(mac, BWN_PHYDATA, mask, set); 6788} 6789 6790#if 0 6791uint16_t 6792bwn_nphy_op_radio_read(struct bwn_mac *mac, uint16_t reg) 6793{ 6794 /* Register 1 is a 32-bit register. */ 6795 if (mac->mac_phy.rev < 7 && reg == 1) { 6796 BWN_ERRPRINTF(mac->mac_sc, "%s: bad reg access\n", __func__); 6797 } 6798 6799 if (mac->mac_phy.rev >= 7) 6800 reg |= 0x200; /* Radio 0x2057 */ 6801 else 6802 reg |= 0x100; 6803 6804 BWN_WRITE_2_F(mac, BWN_RFCTL, reg); 6805 return BWN_READ_2(mac, BWN_RFDATALO); 6806} 6807#endif 6808 6809#if 0 6810void 6811bwn_nphy_op_radio_write(struct bwn_mac *mac, uint16_t reg, uint16_t value) 6812{ 6813 /* Register 1 is a 32-bit register. */ 6814 if (mac->mac_phy.rev < 7 && reg == 1) { 6815 BWN_ERRPRINTF(mac->mac_sc, "%s: bad reg access\n", __func__); 6816 } 6817 6818 BWN_WRITE_2_F(mac, BWN_RFCTL, reg); 6819 BWN_WRITE_2(mac, BWN_RFDATALO, value); 6820} 6821#endif 6822 6823/* http://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */ 6824void 6825bwn_nphy_op_software_rfkill(struct bwn_mac *mac, bool active) 6826{ 6827 struct bwn_phy *phy = &mac->mac_phy; 6828 6829 if (BWN_READ_4(mac, BWN_MACCTL) & BWN_MACCTL_ON) 6830 BWN_ERRPRINTF(mac->mac_sc, "MAC not suspended\n"); 6831 6832 DPRINTF(mac->mac_sc, BWN_DEBUG_RESET | BWN_DEBUG_PHY, 6833 "%s: called; rev=%d, rf_on=%d, active=%d\n", __func__, 6834 phy->rev, mac->mac_phy.rf_on, active); 6835 6836 /* 6837 * XXX TODO: don't bother doing RF programming if it's 6838 * already done. But, bwn(4) currently sets rf_on in the 6839 * PHY setup and leaves it on after startup, which causes 6840 * the below to not init the 2056/2057 radios. 6841 */ 6842 if (active) { 6843 if (phy->rev >= 19) { 6844 /* TODO */ 6845 } else if (phy->rev >= 7) { 6846// if (!mac->mac_phy.rf_on) 6847 bwn_radio_2057_init(mac); 6848 bwn_switch_channel(mac, bwn_get_chan(mac)); 6849 } else if (phy->rev >= 3) { 6850// if (!mac->mac_phy.rf_on) 6851 bwn_radio_init2056(mac); 6852 bwn_switch_channel(mac, bwn_get_chan(mac)); 6853 } else { 6854 bwn_radio_init2055(mac); 6855 } 6856 } else { 6857 if (phy->rev >= 19) { 6858 /* TODO */ 6859 } else if (phy->rev >= 8) { 6860 BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, 6861 ~BWN_NPHY_RFCTL_CMD_CHIP0PU); 6862 } else if (phy->rev >= 7) { 6863 /* Nothing needed */ 6864 } else if (phy->rev >= 3) { 6865 BWN_PHY_MASK(mac, BWN_NPHY_RFCTL_CMD, 6866 ~BWN_NPHY_RFCTL_CMD_CHIP0PU); 6867 6868 BWN_RF_MASK(mac, 0x09, ~0x2); 6869 6870 BWN_RF_WRITE(mac, 0x204D, 0); 6871 BWN_RF_WRITE(mac, 0x2053, 0); 6872 BWN_RF_WRITE(mac, 0x2058, 0); 6873 BWN_RF_WRITE(mac, 0x205E, 0); 6874 BWN_RF_MASK(mac, 0x2062, ~0xF0); 6875 BWN_RF_WRITE(mac, 0x2064, 0); 6876 6877 BWN_RF_WRITE(mac, 0x304D, 0); 6878 BWN_RF_WRITE(mac, 0x3053, 0); 6879 BWN_RF_WRITE(mac, 0x3058, 0); 6880 BWN_RF_WRITE(mac, 0x305E, 0); 6881 BWN_RF_MASK(mac, 0x3062, ~0xF0); 6882 BWN_RF_WRITE(mac, 0x3064, 0); 6883 } 6884 } 6885} 6886 6887/* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */ 6888void 6889bwn_nphy_op_switch_analog(struct bwn_mac *mac, bool on) 6890{ 6891 struct bwn_phy *phy = &mac->mac_phy; 6892 uint16_t override = on ? 0x0 : 0x7FFF; 6893 uint16_t core = on ? 0xD : 0x00FD; 6894 6895 if (phy->rev >= 19) { 6896 /* TODO */ 6897 device_printf(mac->mac_sc->sc_dev, "%s: TODO\n", __func__); 6898 } else if (phy->rev >= 3) { 6899 if (on) { 6900 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, core); 6901 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, override); 6902 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, core); 6903 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, override); 6904 } else { 6905 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER1, override); 6906 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C1, core); 6907 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, override); 6908 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_C2, core); 6909 } 6910 } else { 6911 BWN_PHY_WRITE(mac, BWN_NPHY_AFECTL_OVER, override); 6912 } 6913} 6914 6915int 6916bwn_nphy_op_switch_channel(struct bwn_mac *mac, unsigned int new_channel) 6917{ 6918 struct ieee80211_channel *channel = bwn_get_channel(mac); 6919 bwn_chan_type_t channel_type = bwn_get_chan_type(mac, NULL); 6920 6921 if (bwn_current_band(mac) == BWN_BAND_2G) { 6922 if ((new_channel < 1) || (new_channel > 14)) 6923 return -EINVAL; 6924 } else { 6925 if (new_channel > 200) 6926 return -EINVAL; 6927 } 6928 6929 return bwn_nphy_set_channel(mac, channel, channel_type); 6930} 6931 6932#if 0 6933unsigned int 6934bwn_nphy_op_get_default_chan(struct bwn_mac *mac) 6935{ 6936 if (bwn_current_band(mac) == BWN_BAND_2G) 6937 return 1; 6938 return 36; 6939} 6940#endif 6941