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