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