1 /*- 2 * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification. 11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13 * redistribution must be conditioned upon including a substantially 14 * similar Disclaimer requirement for further binary redistribution. 15 * 16 * NO WARRANTY 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 * THE POSSIBILITY OF SUCH DAMAGES. 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include "opt_bwn.h" 34 #include "opt_wlan.h" 35 36 /* 37 * The Broadcom Wireless LAN controller driver. 38 */ 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/kernel.h> 43 #include <sys/malloc.h> 44 #include <sys/module.h> 45 #include <sys/endian.h> 46 #include <sys/errno.h> 47 #include <sys/firmware.h> 48 #include <sys/lock.h> 49 #include <sys/mutex.h> 50 #include <machine/bus.h> 51 #include <machine/resource.h> 52 #include <sys/bus.h> 53 #include <sys/rman.h> 54 #include <sys/socket.h> 55 #include <sys/sockio.h> 56 57 #include <net/ethernet.h> 58 #include <net/if.h> 59 #include <net/if_var.h> 60 #include <net/if_arp.h> 61 #include <net/if_dl.h> 62 #include <net/if_llc.h> 63 #include <net/if_media.h> 64 #include <net/if_types.h> 65 66 #include <dev/pci/pcivar.h> 67 #include <dev/pci/pcireg.h> 68 69 #include <net80211/ieee80211_var.h> 70 #include <net80211/ieee80211_radiotap.h> 71 #include <net80211/ieee80211_regdomain.h> 72 #include <net80211/ieee80211_phy.h> 73 #include <net80211/ieee80211_ratectl.h> 74 75 #include <dev/bwn/if_bwnreg.h> 76 #include <dev/bwn/if_bwnvar.h> 77 78 #include <dev/bwn/if_bwn_debug.h> 79 #include <dev/bwn/if_bwn_misc.h> 80 #include <dev/bwn/if_bwn_phy_g.h> 81 82 #include "bhnd_nvram_map.h" 83 84 static void bwn_phy_g_init_sub(struct bwn_mac *); 85 static uint8_t bwn_has_hwpctl(struct bwn_mac *); 86 static void bwn_phy_init_b5(struct bwn_mac *); 87 static void bwn_phy_init_b6(struct bwn_mac *); 88 static void bwn_phy_init_a(struct bwn_mac *); 89 static void bwn_loopback_calcgain(struct bwn_mac *); 90 static uint16_t bwn_rf_init_bcm2050(struct bwn_mac *); 91 static void bwn_lo_g_init(struct bwn_mac *); 92 static void bwn_lo_g_adjust(struct bwn_mac *); 93 static void bwn_lo_get_powervector(struct bwn_mac *); 94 static struct bwn_lo_calib *bwn_lo_calibset(struct bwn_mac *, 95 const struct bwn_bbatt *, const struct bwn_rfatt *); 96 static void bwn_lo_write(struct bwn_mac *, struct bwn_loctl *); 97 static void bwn_phy_hwpctl_init(struct bwn_mac *); 98 static void bwn_phy_g_switch_chan(struct bwn_mac *, int, uint8_t); 99 static void bwn_phy_g_set_txpwr_sub(struct bwn_mac *, 100 const struct bwn_bbatt *, const struct bwn_rfatt *, 101 uint8_t); 102 static void bwn_phy_g_set_bbatt(struct bwn_mac *, uint16_t); 103 static uint16_t bwn_rf_2050_rfoverval(struct bwn_mac *, uint16_t, uint32_t); 104 static void bwn_spu_workaround(struct bwn_mac *, uint8_t); 105 static void bwn_wa_init(struct bwn_mac *); 106 static void bwn_ofdmtab_write_2(struct bwn_mac *, uint16_t, uint16_t, 107 uint16_t); 108 static void bwn_ofdmtab_write_4(struct bwn_mac *, uint16_t, uint16_t, 109 uint32_t); 110 static void bwn_gtab_write(struct bwn_mac *, uint16_t, uint16_t, 111 uint16_t); 112 static int16_t bwn_nrssi_read(struct bwn_mac *, uint16_t); 113 static void bwn_nrssi_offset(struct bwn_mac *); 114 static void bwn_nrssi_threshold(struct bwn_mac *); 115 static void bwn_nrssi_slope_11g(struct bwn_mac *); 116 static void bwn_set_all_gains(struct bwn_mac *, int16_t, int16_t, 117 int16_t); 118 static void bwn_set_original_gains(struct bwn_mac *); 119 static void bwn_hwpctl_early_init(struct bwn_mac *); 120 static void bwn_hwpctl_init_gphy(struct bwn_mac *); 121 static uint16_t bwn_phy_g_chan2freq(uint8_t); 122 static void bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t); 123 124 /* Stuff we need */ 125 126 static uint16_t bwn_phy_g_txctl(struct bwn_mac *mac); 127 static int bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset); 128 static void bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp); 129 static void bwn_phy_lock(struct bwn_mac *mac); 130 static void bwn_phy_unlock(struct bwn_mac *mac); 131 static void bwn_rf_lock(struct bwn_mac *mac); 132 static void bwn_rf_unlock(struct bwn_mac *mac); 133 134 static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1; 135 static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2; 136 static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1; 137 static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2; 138 static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3; 139 const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE; 140 141 static uint8_t 142 bwn_has_hwpctl(struct bwn_mac *mac) 143 { 144 145 if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL) 146 return (0); 147 return (mac->mac_phy.use_hwpctl(mac)); 148 } 149 150 int 151 bwn_phy_g_attach(struct bwn_mac *mac) 152 { 153 struct bwn_softc *sc = mac->mac_sc; 154 struct bwn_phy *phy = &mac->mac_phy; 155 struct bwn_phy_g *pg = &phy->phy_g; 156 unsigned int i; 157 int16_t pab0, pab1, pab2; 158 static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE; 159 int8_t bg; 160 int error; 161 162 /* Fetch SPROM configuration */ 163 #define BWN_PHY_G_READVAR(_dev, _type, _name, _result) \ 164 do { \ 165 error = bhnd_nvram_getvar_ ##_type((_dev), (_name), (_result)); \ 166 if (error) { \ 167 device_printf((_dev), "NVRAM variable %s unreadable: " \ 168 "%d\n", (_name), error); \ 169 return (error); \ 170 } \ 171 } while(0) 172 173 BWN_PHY_G_READVAR(sc->sc_dev, int8, BHND_NVAR_PA0ITSSIT, &bg); 174 BWN_PHY_G_READVAR(sc->sc_dev, int16, BHND_NVAR_PA0B0, &pab0); 175 BWN_PHY_G_READVAR(sc->sc_dev, int16, BHND_NVAR_PA0B1, &pab1); 176 BWN_PHY_G_READVAR(sc->sc_dev, int16, BHND_NVAR_PA0B2, &pab2); 177 BWN_PHY_G_READVAR(sc->sc_dev, int16, BHND_NVAR_PA0MAXPWR, 178 &pg->pg_pa0maxpwr); 179 180 #undef BWN_PHY_G_READVAR 181 182 pg->pg_flags = 0; 183 if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 || 184 pab2 == -1) { 185 pg->pg_idletssi = 52; 186 pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table; 187 return (0); 188 } 189 190 pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg; 191 pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO); 192 if (pg->pg_tssi2dbm == NULL) { 193 device_printf(sc->sc_dev, "failed to allocate buffer\n"); 194 return (ENOMEM); 195 } 196 for (i = 0; i < 64; i++) { 197 int32_t m1, m2, f, q, delta; 198 int8_t j = 0; 199 200 m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32); 201 m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1); 202 f = 256; 203 204 do { 205 if (j > 15) { 206 device_printf(sc->sc_dev, 207 "failed to generate tssi2dBm\n"); 208 free(pg->pg_tssi2dbm, M_DEVBUF); 209 return (ENOMEM); 210 } 211 q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) * 212 f, 2048); 213 delta = abs(q - f); 214 f = q; 215 j++; 216 } while (delta >= 2); 217 218 pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127), 219 127); 220 } 221 222 pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC; 223 return (0); 224 } 225 226 void 227 bwn_phy_g_detach(struct bwn_mac *mac) 228 { 229 struct bwn_phy_g *pg = &mac->mac_phy.phy_g; 230 231 if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) { 232 free(pg->pg_tssi2dbm, M_DEVBUF); 233 pg->pg_tssi2dbm = NULL; 234 } 235 pg->pg_flags = 0; 236 } 237 238 void 239 bwn_phy_g_init_pre(struct bwn_mac *mac) 240 { 241 struct bwn_phy *phy = &mac->mac_phy; 242 struct bwn_phy_g *pg = &phy->phy_g; 243 void *tssi2dbm; 244 int idletssi; 245 unsigned int i; 246 247 tssi2dbm = pg->pg_tssi2dbm; 248 idletssi = pg->pg_idletssi; 249 250 memset(pg, 0, sizeof(*pg)); 251 252 pg->pg_tssi2dbm = tssi2dbm; 253 pg->pg_idletssi = idletssi; 254 255 memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig)); 256 257 for (i = 0; i < N(pg->pg_nrssi); i++) 258 pg->pg_nrssi[i] = -1000; 259 for (i = 0; i < N(pg->pg_nrssi_lt); i++) 260 pg->pg_nrssi_lt[i] = i; 261 pg->pg_lofcal = 0xffff; 262 pg->pg_initval = 0xffff; 263 pg->pg_immode = BWN_IMMODE_NONE; 264 pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN; 265 pg->pg_avgtssi = 0xff; 266 267 pg->pg_loctl.tx_bias = 0xff; 268 TAILQ_INIT(&pg->pg_loctl.calib_list); 269 } 270 271 int 272 bwn_phy_g_prepare_hw(struct bwn_mac *mac) 273 { 274 struct bwn_phy *phy = &mac->mac_phy; 275 struct bwn_phy_g *pg = &phy->phy_g; 276 struct bwn_softc *sc = mac->mac_sc; 277 struct bwn_txpwr_loctl *lo = &pg->pg_loctl; 278 static const struct bwn_rfatt rfatt0[] = { 279 { 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 }, { 9, 0 }, { 2, 0 }, 280 { 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 }, 281 { 3, 1 }, { 4, 1 } 282 }; 283 static const struct bwn_rfatt rfatt1[] = { 284 { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 }, 285 { 14, 1 } 286 }; 287 static const struct bwn_rfatt rfatt2[] = { 288 { 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 }, 289 { 9, 1 } 290 }; 291 static const struct bwn_bbatt bbatt_0[] = { 292 { 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 } 293 }; 294 295 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__)); 296 297 if (phy->rf_ver == 0x2050 && phy->rf_rev < 6) 298 pg->pg_bbatt.att = 0; 299 else 300 pg->pg_bbatt.att = 2; 301 302 /* prepare Radio Attenuation */ 303 pg->pg_rfatt.padmix = 0; 304 305 if (sc->sc_board_info.board_vendor == PCI_VENDOR_BROADCOM && 306 sc->sc_board_info.board_type == BHND_BOARD_BCM94309G) { 307 if (sc->sc_board_info.board_rev < 0x43) { 308 pg->pg_rfatt.att = 2; 309 goto done; 310 } else if (sc->sc_board_info.board_rev < 0x51) { 311 pg->pg_rfatt.att = 3; 312 goto done; 313 } 314 } 315 316 if (phy->type == BWN_PHYTYPE_A) { 317 pg->pg_rfatt.att = 0x60; 318 goto done; 319 } 320 321 switch (phy->rf_ver) { 322 case 0x2050: 323 switch (phy->rf_rev) { 324 case 0: 325 pg->pg_rfatt.att = 5; 326 goto done; 327 case 1: 328 if (phy->type == BWN_PHYTYPE_G) { 329 if (sc->sc_board_info.board_vendor == 330 PCI_VENDOR_BROADCOM && 331 sc->sc_board_info.board_type == 332 BHND_BOARD_BCM94309G && 333 sc->sc_board_info.board_rev >= 30) 334 pg->pg_rfatt.att = 3; 335 else if (sc->sc_board_info.board_vendor == 336 PCI_VENDOR_BROADCOM && 337 sc->sc_board_info.board_type == 338 BHND_BOARD_BU4306) 339 pg->pg_rfatt.att = 3; 340 else 341 pg->pg_rfatt.att = 1; 342 } else { 343 if (sc->sc_board_info.board_vendor == 344 PCI_VENDOR_BROADCOM && 345 sc->sc_board_info.board_type == 346 BHND_BOARD_BCM94309G && 347 sc->sc_board_info.board_rev >= 30) 348 pg->pg_rfatt.att = 7; 349 else 350 pg->pg_rfatt.att = 6; 351 } 352 goto done; 353 case 2: 354 if (phy->type == BWN_PHYTYPE_G) { 355 if (sc->sc_board_info.board_vendor == 356 PCI_VENDOR_BROADCOM && 357 sc->sc_board_info.board_type == 358 BHND_BOARD_BCM94309G && 359 sc->sc_board_info.board_rev >= 30) 360 pg->pg_rfatt.att = 3; 361 else if (sc->sc_board_info.board_vendor == 362 PCI_VENDOR_BROADCOM && 363 sc->sc_board_info.board_type == 364 BHND_BOARD_BU4306) 365 pg->pg_rfatt.att = 5; 366 else if (sc->sc_cid.chip_id == 367 BHND_CHIPID_BCM4320) 368 pg->pg_rfatt.att = 4; 369 else 370 pg->pg_rfatt.att = 3; 371 } else 372 pg->pg_rfatt.att = 6; 373 goto done; 374 case 3: 375 pg->pg_rfatt.att = 5; 376 goto done; 377 case 4: 378 case 5: 379 pg->pg_rfatt.att = 1; 380 goto done; 381 case 6: 382 case 7: 383 pg->pg_rfatt.att = 5; 384 goto done; 385 case 8: 386 pg->pg_rfatt.att = 0xa; 387 pg->pg_rfatt.padmix = 1; 388 goto done; 389 case 9: 390 default: 391 pg->pg_rfatt.att = 5; 392 goto done; 393 } 394 break; 395 case 0x2053: 396 switch (phy->rf_rev) { 397 case 1: 398 pg->pg_rfatt.att = 6; 399 goto done; 400 } 401 break; 402 } 403 pg->pg_rfatt.att = 5; 404 done: 405 pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4); 406 407 if (!bwn_has_hwpctl(mac)) { 408 lo->rfatt.array = rfatt0; 409 lo->rfatt.len = N(rfatt0); 410 lo->rfatt.min = 0; 411 lo->rfatt.max = 9; 412 goto genbbatt; 413 } 414 if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) { 415 lo->rfatt.array = rfatt1; 416 lo->rfatt.len = N(rfatt1); 417 lo->rfatt.min = 0; 418 lo->rfatt.max = 14; 419 goto genbbatt; 420 } 421 lo->rfatt.array = rfatt2; 422 lo->rfatt.len = N(rfatt2); 423 lo->rfatt.min = 0; 424 lo->rfatt.max = 9; 425 genbbatt: 426 lo->bbatt.array = bbatt_0; 427 lo->bbatt.len = N(bbatt_0); 428 lo->bbatt.min = 0; 429 lo->bbatt.max = 8; 430 431 BWN_READ_4(mac, BWN_MACCTL); 432 if (phy->rev == 1) { 433 phy->gmode = 0; 434 bwn_reset_core(mac, 0); 435 bwn_phy_g_init_sub(mac); 436 phy->gmode = 1; 437 bwn_reset_core(mac, 1); 438 } 439 return (0); 440 } 441 442 static uint16_t 443 bwn_phy_g_txctl(struct bwn_mac *mac) 444 { 445 struct bwn_phy *phy = &mac->mac_phy; 446 447 if (phy->rf_ver != 0x2050) 448 return (0); 449 if (phy->rf_rev == 1) 450 return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX); 451 if (phy->rf_rev < 6) 452 return (BWN_TXCTL_PA2DB); 453 if (phy->rf_rev == 8) 454 return (BWN_TXCTL_TXMIX); 455 return (0); 456 } 457 458 int 459 bwn_phy_g_init(struct bwn_mac *mac) 460 { 461 462 bwn_phy_g_init_sub(mac); 463 return (0); 464 } 465 466 void 467 bwn_phy_g_exit(struct bwn_mac *mac) 468 { 469 struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl; 470 struct bwn_lo_calib *cal, *tmp; 471 472 if (lo == NULL) 473 return; 474 TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) { 475 TAILQ_REMOVE(&lo->calib_list, cal, list); 476 free(cal, M_DEVBUF); 477 } 478 } 479 480 uint16_t 481 bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg) 482 { 483 484 BWN_WRITE_2(mac, BWN_PHYCTL, reg); 485 return (BWN_READ_2(mac, BWN_PHYDATA)); 486 } 487 488 void 489 bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value) 490 { 491 492 BWN_WRITE_2(mac, BWN_PHYCTL, reg); 493 BWN_WRITE_2(mac, BWN_PHYDATA, value); 494 } 495 496 uint16_t 497 bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg) 498 { 499 500 KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__)); 501 BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80); 502 return (BWN_READ_2(mac, BWN_RFDATALO)); 503 } 504 505 void 506 bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value) 507 { 508 509 KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__)); 510 BWN_WRITE_2(mac, BWN_RFCTL, reg); 511 BWN_WRITE_2(mac, BWN_RFDATALO, value); 512 } 513 514 int 515 bwn_phy_g_hwpctl(struct bwn_mac *mac) 516 { 517 518 return (mac->mac_phy.rev >= 6); 519 } 520 521 void 522 bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on) 523 { 524 struct bwn_phy *phy = &mac->mac_phy; 525 struct bwn_phy_g *pg = &phy->phy_g; 526 unsigned int channel; 527 uint16_t rfover, rfoverval; 528 529 if (on) { 530 if (phy->rf_on) 531 return; 532 533 BWN_PHY_WRITE(mac, 0x15, 0x8000); 534 BWN_PHY_WRITE(mac, 0x15, 0xcc00); 535 BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0)); 536 if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) { 537 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 538 pg->pg_radioctx_over); 539 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 540 pg->pg_radioctx_overval); 541 pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID; 542 } 543 channel = phy->chan; 544 bwn_phy_g_switch_chan(mac, 6, 1); 545 bwn_phy_g_switch_chan(mac, channel, 0); 546 return; 547 } 548 549 rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER); 550 rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL); 551 pg->pg_radioctx_over = rfover; 552 pg->pg_radioctx_overval = rfoverval; 553 pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID; 554 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c); 555 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73); 556 } 557 558 int 559 bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan) 560 { 561 562 if ((newchan < 1) || (newchan > 14)) 563 return (EINVAL); 564 bwn_phy_g_switch_chan(mac, newchan, 0); 565 566 return (0); 567 } 568 569 uint32_t 570 bwn_phy_g_get_default_chan(struct bwn_mac *mac) 571 { 572 573 return (1); 574 } 575 576 void 577 bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna) 578 { 579 struct bwn_phy *phy = &mac->mac_phy; 580 uint64_t hf; 581 int autodiv = 0; 582 uint16_t tmp; 583 584 if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1) 585 autodiv = 1; 586 587 hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER; 588 bwn_hf_write(mac, hf); 589 590 BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG, 591 (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) | 592 ((autodiv ? BWN_ANTAUTO1 : antenna) 593 << BWN_PHY_BBANDCFG_RXANT_SHIFT)); 594 595 if (autodiv) { 596 tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL); 597 if (antenna == BWN_ANTAUTO1) 598 tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1; 599 else 600 tmp |= BWN_PHY_ANTDWELL_AUTODIV1; 601 BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp); 602 } 603 tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT); 604 if (autodiv) 605 tmp |= BWN_PHY_ANTWRSETT_ARXDIV; 606 else 607 tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV; 608 BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp); 609 if (phy->rev >= 2) { 610 BWN_PHY_WRITE(mac, BWN_PHY_OFDM61, 611 BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10); 612 BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK, 613 (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) | 614 0x15); 615 if (phy->rev == 2) 616 BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8); 617 else 618 BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 619 (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) | 620 8); 621 } 622 if (phy->rev >= 6) 623 BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc); 624 625 hf |= BWN_HF_UCODE_ANTDIV_HELPER; 626 bwn_hf_write(mac, hf); 627 } 628 629 int 630 bwn_phy_g_im(struct bwn_mac *mac, int mode) 631 { 632 struct bwn_phy *phy = &mac->mac_phy; 633 struct bwn_phy_g *pg = &phy->phy_g; 634 635 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__)); 636 KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__)); 637 638 if (phy->rev == 0 || !phy->gmode) 639 return (ENODEV); 640 641 pg->pg_aci_wlan_automatic = 0; 642 return (0); 643 } 644 645 bwn_txpwr_result_t 646 bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi) 647 { 648 struct bwn_phy *phy = &mac->mac_phy; 649 struct bwn_phy_g *pg = &phy->phy_g; 650 struct bwn_softc *sc = mac->mac_sc; 651 unsigned int tssi; 652 int cck, ofdm; 653 int power; 654 int rfatt, bbatt; 655 unsigned int max; 656 657 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__)); 658 659 cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK); 660 ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G); 661 if (cck < 0 && ofdm < 0) { 662 if (ignore_tssi == 0) 663 return (BWN_TXPWR_RES_DONE); 664 cck = 0; 665 ofdm = 0; 666 } 667 tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2); 668 if (pg->pg_avgtssi != 0xff) 669 tssi = (tssi + pg->pg_avgtssi) / 2; 670 pg->pg_avgtssi = tssi; 671 KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__)); 672 673 max = pg->pg_pa0maxpwr; 674 if (sc->sc_board_info.board_flags & BHND_BFL_PACTRL) 675 max -= 3; 676 if (max >= 120) { 677 device_printf(sc->sc_dev, "invalid max TX-power value\n"); 678 max = 80; 679 pg->pg_pa0maxpwr = max; 680 } 681 682 power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) - 683 (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi + 684 tssi, 0x00), 0x3f)]); 685 if (power == 0) 686 return (BWN_TXPWR_RES_DONE); 687 688 rfatt = -((power + 7) / 8); 689 bbatt = (-(power / 2)) - (4 * rfatt); 690 if ((rfatt == 0) && (bbatt == 0)) 691 return (BWN_TXPWR_RES_DONE); 692 pg->pg_bbatt_delta = bbatt; 693 pg->pg_rfatt_delta = rfatt; 694 return (BWN_TXPWR_RES_NEED_ADJUST); 695 } 696 697 void 698 bwn_phy_g_set_txpwr(struct bwn_mac *mac) 699 { 700 struct bwn_phy *phy = &mac->mac_phy; 701 struct bwn_phy_g *pg = &phy->phy_g; 702 struct bwn_softc *sc = mac->mac_sc; 703 int rfatt, bbatt; 704 uint8_t txctl; 705 706 bwn_mac_suspend(mac); 707 708 BWN_ASSERT_LOCKED(sc); 709 710 bbatt = pg->pg_bbatt.att; 711 bbatt += pg->pg_bbatt_delta; 712 rfatt = pg->pg_rfatt.att; 713 rfatt += pg->pg_rfatt_delta; 714 715 bwn_phy_g_setatt(mac, &bbatt, &rfatt); 716 txctl = pg->pg_txctl; 717 if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) { 718 if (rfatt <= 1) { 719 if (txctl == 0) { 720 txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX; 721 rfatt += 2; 722 bbatt += 2; 723 } else if (sc->sc_board_info.board_flags & 724 BHND_BFL_PACTRL) { 725 bbatt += 4 * (rfatt - 2); 726 rfatt = 2; 727 } 728 } else if (rfatt > 4 && txctl) { 729 txctl = 0; 730 if (bbatt < 3) { 731 rfatt -= 3; 732 bbatt += 2; 733 } else { 734 rfatt -= 2; 735 bbatt -= 2; 736 } 737 } 738 } 739 pg->pg_txctl = txctl; 740 bwn_phy_g_setatt(mac, &bbatt, &rfatt); 741 pg->pg_rfatt.att = rfatt; 742 pg->pg_bbatt.att = bbatt; 743 744 DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__); 745 746 bwn_phy_lock(mac); 747 bwn_rf_lock(mac); 748 bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt, 749 pg->pg_txctl); 750 bwn_rf_unlock(mac); 751 bwn_phy_unlock(mac); 752 753 bwn_mac_enable(mac); 754 } 755 756 void 757 bwn_phy_g_task_15s(struct bwn_mac *mac) 758 { 759 struct bwn_phy *phy = &mac->mac_phy; 760 struct bwn_phy_g *pg = &phy->phy_g; 761 struct bwn_softc *sc = mac->mac_sc; 762 struct bwn_txpwr_loctl *lo = &pg->pg_loctl; 763 unsigned long expire, now; 764 struct bwn_lo_calib *cal, *tmp; 765 uint8_t expired = 0; 766 767 bwn_mac_suspend(mac); 768 769 if (lo == NULL) 770 goto fail; 771 772 BWN_GETTIME(now); 773 if (bwn_has_hwpctl(mac)) { 774 expire = now - BWN_LO_PWRVEC_EXPIRE; 775 if (ieee80211_time_before(lo->pwr_vec_read_time, expire)) { 776 bwn_lo_get_powervector(mac); 777 bwn_phy_g_dc_lookup_init(mac, 0); 778 } 779 goto fail; 780 } 781 782 expire = now - BWN_LO_CALIB_EXPIRE; 783 TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) { 784 if (!ieee80211_time_before(cal->calib_time, expire)) 785 continue; 786 if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) && 787 BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) { 788 KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__)); 789 expired = 1; 790 } 791 792 DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n", 793 cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix, 794 cal->ctl.i, cal->ctl.q); 795 796 TAILQ_REMOVE(&lo->calib_list, cal, list); 797 free(cal, M_DEVBUF); 798 } 799 if (expired || TAILQ_EMPTY(&lo->calib_list)) { 800 cal = bwn_lo_calibset(mac, &pg->pg_bbatt, 801 &pg->pg_rfatt); 802 if (cal == NULL) { 803 device_printf(sc->sc_dev, 804 "failed to recalibrate LO\n"); 805 goto fail; 806 } 807 TAILQ_INSERT_TAIL(&lo->calib_list, cal, list); 808 bwn_lo_write(mac, &cal->ctl); 809 } 810 811 fail: 812 bwn_mac_enable(mac); 813 } 814 815 void 816 bwn_phy_g_task_60s(struct bwn_mac *mac) 817 { 818 struct bwn_phy *phy = &mac->mac_phy; 819 struct bwn_softc *sc = mac->mac_sc; 820 uint8_t old = phy->chan; 821 822 if (!(sc->sc_board_info.board_flags & BHND_BFL_ADCDIV)) 823 return; 824 825 bwn_mac_suspend(mac); 826 bwn_nrssi_slope_11g(mac); 827 if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) { 828 bwn_switch_channel(mac, (old >= 8) ? 1 : 13); 829 bwn_switch_channel(mac, old); 830 } 831 bwn_mac_enable(mac); 832 } 833 834 void 835 bwn_phy_switch_analog(struct bwn_mac *mac, int on) 836 { 837 838 BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4); 839 } 840 841 static void 842 bwn_phy_g_init_sub(struct bwn_mac *mac) 843 { 844 struct bwn_phy *phy = &mac->mac_phy; 845 struct bwn_phy_g *pg = &phy->phy_g; 846 struct bwn_softc *sc = mac->mac_sc; 847 uint16_t i, tmp; 848 849 if (phy->rev == 1) 850 bwn_phy_init_b5(mac); 851 else 852 bwn_phy_init_b6(mac); 853 854 if (phy->rev >= 2 || phy->gmode) 855 bwn_phy_init_a(mac); 856 857 if (phy->rev >= 2) { 858 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0); 859 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0); 860 } 861 if (phy->rev == 2) { 862 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0); 863 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0); 864 } 865 if (phy->rev > 5) { 866 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400); 867 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0); 868 } 869 if (phy->gmode || phy->rev >= 2) { 870 tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM); 871 tmp &= BWN_PHYVER_VERSION; 872 if (tmp == 3 || tmp == 5) { 873 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816); 874 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006); 875 } 876 if (tmp == 5) { 877 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff, 878 0x1f00); 879 } 880 } 881 if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2) 882 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78); 883 if (phy->rf_rev == 8) { 884 BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80); 885 BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4); 886 } 887 if (BWN_HAS_LOOPBACK(phy)) 888 bwn_loopback_calcgain(mac); 889 890 if (phy->rf_rev != 8) { 891 if (pg->pg_initval == 0xffff) 892 pg->pg_initval = bwn_rf_init_bcm2050(mac); 893 else 894 BWN_RF_WRITE(mac, 0x0078, pg->pg_initval); 895 } 896 bwn_lo_g_init(mac); 897 if (BWN_HAS_TXMAG(phy)) { 898 BWN_RF_WRITE(mac, 0x52, 899 (BWN_RF_READ(mac, 0x52) & 0xff00) 900 | pg->pg_loctl.tx_bias | 901 pg->pg_loctl.tx_magn); 902 } else { 903 BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias); 904 } 905 if (phy->rev >= 6) { 906 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff, 907 (pg->pg_loctl.tx_bias << 12)); 908 } 909 if (sc->sc_board_info.board_flags & BHND_BFL_PACTRL) 910 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075); 911 else 912 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f); 913 if (phy->rev < 2) 914 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101); 915 else 916 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202); 917 if (phy->gmode || phy->rev >= 2) { 918 bwn_lo_g_adjust(mac); 919 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078); 920 } 921 922 if (!(sc->sc_board_info.board_flags & BHND_BFL_ADCDIV)) { 923 for (i = 0; i < 64; i++) { 924 BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i); 925 BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA, 926 (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff, 927 -32), 31)); 928 } 929 bwn_nrssi_threshold(mac); 930 } else if (phy->gmode || phy->rev >= 2) { 931 if (pg->pg_nrssi[0] == -1000) { 932 KASSERT(pg->pg_nrssi[1] == -1000, 933 ("%s:%d: fail", __func__, __LINE__)); 934 bwn_nrssi_slope_11g(mac); 935 } else 936 bwn_nrssi_threshold(mac); 937 } 938 if (phy->rf_rev == 8) 939 BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230); 940 bwn_phy_hwpctl_init(mac); 941 if ((sc->sc_cid.chip_id == BHND_CHIPID_BCM4306 942 && sc->sc_cid.chip_pkg == 2) || 0) { 943 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff); 944 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff); 945 } 946 } 947 948 static void 949 bwn_phy_init_b5(struct bwn_mac *mac) 950 { 951 struct bwn_phy *phy = &mac->mac_phy; 952 struct bwn_phy_g *pg = &phy->phy_g; 953 struct bwn_softc *sc = mac->mac_sc; 954 uint16_t offset, value; 955 uint8_t old_channel; 956 957 if (phy->analog == 1) 958 BWN_RF_SET(mac, 0x007a, 0x0050); 959 if ((sc->sc_board_info.board_vendor != PCI_VENDOR_BROADCOM) && 960 (sc->sc_board_info.board_type != BHND_BOARD_BU4306)) { 961 value = 0x2120; 962 for (offset = 0x00a8; offset < 0x00c7; offset++) { 963 BWN_PHY_WRITE(mac, offset, value); 964 value += 0x202; 965 } 966 } 967 BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700); 968 if (phy->rf_ver == 0x2050) 969 BWN_PHY_WRITE(mac, 0x0038, 0x0667); 970 971 if (phy->gmode || phy->rev >= 2) { 972 if (phy->rf_ver == 0x2050) { 973 BWN_RF_SET(mac, 0x007a, 0x0020); 974 BWN_RF_SET(mac, 0x0051, 0x0004); 975 } 976 BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000); 977 978 BWN_PHY_SET(mac, 0x0802, 0x0100); 979 BWN_PHY_SET(mac, 0x042b, 0x2000); 980 981 BWN_PHY_WRITE(mac, 0x001c, 0x186a); 982 983 BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900); 984 BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064); 985 BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a); 986 } 987 988 if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP) 989 BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11)); 990 991 if (phy->analog == 1) { 992 BWN_PHY_WRITE(mac, 0x0026, 0xce00); 993 BWN_PHY_WRITE(mac, 0x0021, 0x3763); 994 BWN_PHY_WRITE(mac, 0x0022, 0x1bc3); 995 BWN_PHY_WRITE(mac, 0x0023, 0x06f9); 996 BWN_PHY_WRITE(mac, 0x0024, 0x037e); 997 } else 998 BWN_PHY_WRITE(mac, 0x0026, 0xcc00); 999 BWN_PHY_WRITE(mac, 0x0030, 0x00c6); 1000 BWN_WRITE_2(mac, 0x03ec, 0x3f22); 1001 1002 if (phy->analog == 1) 1003 BWN_PHY_WRITE(mac, 0x0020, 0x3e1c); 1004 else 1005 BWN_PHY_WRITE(mac, 0x0020, 0x301c); 1006 1007 if (phy->analog == 0) 1008 BWN_WRITE_2(mac, 0x03e4, 0x3000); 1009 1010 old_channel = phy->chan; 1011 bwn_phy_g_switch_chan(mac, 7, 0); 1012 1013 if (phy->rf_ver != 0x2050) { 1014 BWN_RF_WRITE(mac, 0x0075, 0x0080); 1015 BWN_RF_WRITE(mac, 0x0079, 0x0081); 1016 } 1017 1018 BWN_RF_WRITE(mac, 0x0050, 0x0020); 1019 BWN_RF_WRITE(mac, 0x0050, 0x0023); 1020 1021 if (phy->rf_ver == 0x2050) { 1022 BWN_RF_WRITE(mac, 0x0050, 0x0020); 1023 BWN_RF_WRITE(mac, 0x005a, 0x0070); 1024 } 1025 1026 BWN_RF_WRITE(mac, 0x005b, 0x007b); 1027 BWN_RF_WRITE(mac, 0x005c, 0x00b0); 1028 BWN_RF_SET(mac, 0x007a, 0x0007); 1029 1030 bwn_phy_g_switch_chan(mac, old_channel, 0); 1031 BWN_PHY_WRITE(mac, 0x0014, 0x0080); 1032 BWN_PHY_WRITE(mac, 0x0032, 0x00ca); 1033 BWN_PHY_WRITE(mac, 0x002a, 0x88a3); 1034 1035 bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt, 1036 pg->pg_txctl); 1037 1038 if (phy->rf_ver == 0x2050) 1039 BWN_RF_WRITE(mac, 0x005d, 0x000d); 1040 1041 BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004); 1042 } 1043 1044 static void 1045 bwn_loopback_calcgain(struct bwn_mac *mac) 1046 { 1047 struct bwn_phy *phy = &mac->mac_phy; 1048 struct bwn_phy_g *pg = &phy->phy_g; 1049 struct bwn_softc *sc = mac->mac_sc; 1050 uint16_t backup_phy[16] = { 0 }; 1051 uint16_t backup_radio[3]; 1052 uint16_t backup_bband; 1053 uint16_t i, j, loop_i_max; 1054 uint16_t trsw_rx; 1055 uint16_t loop1_outer_done, loop1_inner_done; 1056 1057 backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0); 1058 backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG); 1059 backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER); 1060 backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL); 1061 if (phy->rev != 1) { 1062 backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER); 1063 backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL); 1064 } 1065 backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a)); 1066 backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59)); 1067 backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58)); 1068 backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a)); 1069 backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03)); 1070 backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK); 1071 backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL); 1072 backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b)); 1073 backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL); 1074 backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE); 1075 backup_bband = pg->pg_bbatt.att; 1076 backup_radio[0] = BWN_RF_READ(mac, 0x52); 1077 backup_radio[1] = BWN_RF_READ(mac, 0x43); 1078 backup_radio[2] = BWN_RF_READ(mac, 0x7a); 1079 1080 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff); 1081 BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000); 1082 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002); 1083 BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd); 1084 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001); 1085 BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe); 1086 if (phy->rev != 1) { 1087 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001); 1088 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe); 1089 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002); 1090 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd); 1091 } 1092 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c); 1093 BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c); 1094 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030); 1095 BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10); 1096 1097 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780); 1098 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810); 1099 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d); 1100 1101 BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000); 1102 if (phy->rev != 1) { 1103 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004); 1104 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb); 1105 } 1106 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40); 1107 1108 if (phy->rf_rev == 8) 1109 BWN_RF_WRITE(mac, 0x43, 0x000f); 1110 else { 1111 BWN_RF_WRITE(mac, 0x52, 0); 1112 BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9); 1113 } 1114 bwn_phy_g_set_bbatt(mac, 11); 1115 1116 if (phy->rev >= 3) 1117 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020); 1118 else 1119 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020); 1120 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0); 1121 1122 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01); 1123 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800); 1124 1125 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100); 1126 BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff); 1127 1128 if (sc->sc_board_info.board_flags & BHND_BFL_EXTLNA) { 1129 if (phy->rev >= 7) { 1130 BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800); 1131 BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000); 1132 } 1133 } 1134 BWN_RF_MASK(mac, 0x7a, 0x00f7); 1135 1136 j = 0; 1137 loop_i_max = (phy->rf_rev == 8) ? 15 : 9; 1138 for (i = 0; i < loop_i_max; i++) { 1139 for (j = 0; j < 16; j++) { 1140 BWN_RF_WRITE(mac, 0x43, i); 1141 BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, 1142 (j << 8)); 1143 BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000); 1144 BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000); 1145 DELAY(20); 1146 if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc) 1147 goto done0; 1148 } 1149 } 1150 done0: 1151 loop1_outer_done = i; 1152 loop1_inner_done = j; 1153 if (j >= 8) { 1154 BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30); 1155 trsw_rx = 0x1b; 1156 for (j = j - 8; j < 16; j++) { 1157 BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8); 1158 BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000); 1159 BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000); 1160 DELAY(20); 1161 trsw_rx -= 3; 1162 if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc) 1163 goto done1; 1164 } 1165 } else 1166 trsw_rx = 0x18; 1167 done1: 1168 1169 if (phy->rev != 1) { 1170 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]); 1171 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]); 1172 } 1173 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]); 1174 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]); 1175 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]); 1176 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]); 1177 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]); 1178 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]); 1179 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]); 1180 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]); 1181 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]); 1182 1183 bwn_phy_g_set_bbatt(mac, backup_bband); 1184 1185 BWN_RF_WRITE(mac, 0x52, backup_radio[0]); 1186 BWN_RF_WRITE(mac, 0x43, backup_radio[1]); 1187 BWN_RF_WRITE(mac, 0x7a, backup_radio[2]); 1188 1189 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003); 1190 DELAY(10); 1191 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]); 1192 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]); 1193 BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]); 1194 BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]); 1195 1196 pg->pg_max_lb_gain = 1197 ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11; 1198 pg->pg_trsw_rx_gain = trsw_rx * 2; 1199 } 1200 1201 static uint16_t 1202 bwn_rf_init_bcm2050(struct bwn_mac *mac) 1203 { 1204 struct bwn_phy *phy = &mac->mac_phy; 1205 uint32_t tmp1 = 0, tmp2 = 0; 1206 uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval, 1207 analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl, 1208 radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index; 1209 static const uint8_t rcc_table[] = { 1210 0x02, 0x03, 0x01, 0x0f, 1211 0x06, 0x07, 0x05, 0x0f, 1212 0x0a, 0x0b, 0x09, 0x0f, 1213 0x0e, 0x0f, 0x0d, 0x0f, 1214 }; 1215 1216 loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover = 1217 rfoverval = rfover = cck3 = 0; 1218 radio0 = BWN_RF_READ(mac, 0x43); 1219 radio1 = BWN_RF_READ(mac, 0x51); 1220 radio2 = BWN_RF_READ(mac, 0x52); 1221 pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL); 1222 cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a)); 1223 cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59)); 1224 cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58)); 1225 1226 if (phy->type == BWN_PHYTYPE_B) { 1227 cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30)); 1228 reg0 = BWN_READ_2(mac, 0x3ec); 1229 1230 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff); 1231 BWN_WRITE_2(mac, 0x3ec, 0x3f3f); 1232 } else if (phy->gmode || phy->rev >= 2) { 1233 rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER); 1234 rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL); 1235 analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER); 1236 analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL); 1237 crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0); 1238 classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL); 1239 1240 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003); 1241 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc); 1242 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff); 1243 BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc); 1244 if (BWN_HAS_LOOPBACK(phy)) { 1245 lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK); 1246 loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL); 1247 if (phy->rev >= 3) 1248 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020); 1249 else 1250 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020); 1251 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0); 1252 } 1253 1254 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 1255 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL, 1256 BWN_LPD(0, 1, 1))); 1257 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 1258 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0)); 1259 } 1260 BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000); 1261 1262 syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL); 1263 BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f); 1264 reg1 = BWN_READ_2(mac, 0x3e6); 1265 reg2 = BWN_READ_2(mac, 0x3f4); 1266 1267 if (phy->analog == 0) 1268 BWN_WRITE_2(mac, 0x03e6, 0x0122); 1269 else { 1270 if (phy->analog >= 2) 1271 BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40); 1272 BWN_WRITE_2(mac, BWN_CHANNEL_EXT, 1273 (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000)); 1274 } 1275 1276 reg = BWN_RF_READ(mac, 0x60); 1277 index = (reg & 0x001e) >> 1; 1278 rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020); 1279 1280 if (phy->type == BWN_PHYTYPE_B) 1281 BWN_RF_WRITE(mac, 0x78, 0x26); 1282 if (phy->gmode || phy->rev >= 2) { 1283 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 1284 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL, 1285 BWN_LPD(0, 1, 1))); 1286 } 1287 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf); 1288 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403); 1289 if (phy->gmode || phy->rev >= 2) { 1290 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 1291 bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL, 1292 BWN_LPD(0, 0, 1))); 1293 } 1294 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0); 1295 BWN_RF_SET(mac, 0x51, 0x0004); 1296 if (phy->rf_rev == 8) 1297 BWN_RF_WRITE(mac, 0x43, 0x1f); 1298 else { 1299 BWN_RF_WRITE(mac, 0x52, 0); 1300 BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009); 1301 } 1302 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0); 1303 1304 for (i = 0; i < 16; i++) { 1305 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480); 1306 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810); 1307 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d); 1308 if (phy->gmode || phy->rev >= 2) { 1309 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 1310 bwn_rf_2050_rfoverval(mac, 1311 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1))); 1312 } 1313 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0); 1314 DELAY(10); 1315 if (phy->gmode || phy->rev >= 2) { 1316 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 1317 bwn_rf_2050_rfoverval(mac, 1318 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1))); 1319 } 1320 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0); 1321 DELAY(10); 1322 if (phy->gmode || phy->rev >= 2) { 1323 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 1324 bwn_rf_2050_rfoverval(mac, 1325 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0))); 1326 } 1327 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0); 1328 DELAY(20); 1329 tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE); 1330 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0); 1331 if (phy->gmode || phy->rev >= 2) { 1332 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 1333 bwn_rf_2050_rfoverval(mac, 1334 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1))); 1335 } 1336 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0); 1337 } 1338 DELAY(10); 1339 1340 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0); 1341 tmp1++; 1342 tmp1 >>= 9; 1343 1344 for (i = 0; i < 16; i++) { 1345 radio78 = (BWN_BITREV4(i) << 1) | 0x0020; 1346 BWN_RF_WRITE(mac, 0x78, radio78); 1347 DELAY(10); 1348 for (j = 0; j < 16; j++) { 1349 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80); 1350 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810); 1351 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d); 1352 if (phy->gmode || phy->rev >= 2) { 1353 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 1354 bwn_rf_2050_rfoverval(mac, 1355 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1))); 1356 } 1357 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0); 1358 DELAY(10); 1359 if (phy->gmode || phy->rev >= 2) { 1360 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 1361 bwn_rf_2050_rfoverval(mac, 1362 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1))); 1363 } 1364 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0); 1365 DELAY(10); 1366 if (phy->gmode || phy->rev >= 2) { 1367 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 1368 bwn_rf_2050_rfoverval(mac, 1369 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0))); 1370 } 1371 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0); 1372 DELAY(10); 1373 tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE); 1374 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0); 1375 if (phy->gmode || phy->rev >= 2) { 1376 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, 1377 bwn_rf_2050_rfoverval(mac, 1378 BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1))); 1379 } 1380 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0); 1381 } 1382 tmp2++; 1383 tmp2 >>= 8; 1384 if (tmp1 < tmp2) 1385 break; 1386 } 1387 1388 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl); 1389 BWN_RF_WRITE(mac, 0x51, radio1); 1390 BWN_RF_WRITE(mac, 0x52, radio2); 1391 BWN_RF_WRITE(mac, 0x43, radio0); 1392 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0); 1393 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1); 1394 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2); 1395 BWN_WRITE_2(mac, 0x3e6, reg1); 1396 if (phy->analog != 0) 1397 BWN_WRITE_2(mac, 0x3f4, reg2); 1398 BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl); 1399 bwn_spu_workaround(mac, phy->chan); 1400 if (phy->type == BWN_PHYTYPE_B) { 1401 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3); 1402 BWN_WRITE_2(mac, 0x3ec, reg0); 1403 } else if (phy->gmode) { 1404 BWN_WRITE_2(mac, BWN_PHY_RADIO, 1405 BWN_READ_2(mac, BWN_PHY_RADIO) 1406 & 0x7fff); 1407 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover); 1408 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval); 1409 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover); 1410 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 1411 analogoverval); 1412 BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0); 1413 BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl); 1414 if (BWN_HAS_LOOPBACK(phy)) { 1415 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask); 1416 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl); 1417 } 1418 } 1419 1420 return ((i > 15) ? radio78 : rcc); 1421 } 1422 1423 static void 1424 bwn_phy_init_b6(struct bwn_mac *mac) 1425 { 1426 struct bwn_phy *phy = &mac->mac_phy; 1427 struct bwn_phy_g *pg = &phy->phy_g; 1428 struct bwn_softc *sc = mac->mac_sc; 1429 uint16_t offset, val; 1430 uint8_t old_channel; 1431 1432 KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7), 1433 ("%s:%d: fail", __func__, __LINE__)); 1434 1435 BWN_PHY_WRITE(mac, 0x003e, 0x817a); 1436 BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058); 1437 if (phy->rf_rev == 4 || phy->rf_rev == 5) { 1438 BWN_RF_WRITE(mac, 0x51, 0x37); 1439 BWN_RF_WRITE(mac, 0x52, 0x70); 1440 BWN_RF_WRITE(mac, 0x53, 0xb3); 1441 BWN_RF_WRITE(mac, 0x54, 0x9b); 1442 BWN_RF_WRITE(mac, 0x5a, 0x88); 1443 BWN_RF_WRITE(mac, 0x5b, 0x88); 1444 BWN_RF_WRITE(mac, 0x5d, 0x88); 1445 BWN_RF_WRITE(mac, 0x5e, 0x88); 1446 BWN_RF_WRITE(mac, 0x7d, 0x88); 1447 bwn_hf_write(mac, 1448 bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN); 1449 } 1450 if (phy->rf_rev == 8) { 1451 BWN_RF_WRITE(mac, 0x51, 0); 1452 BWN_RF_WRITE(mac, 0x52, 0x40); 1453 BWN_RF_WRITE(mac, 0x53, 0xb7); 1454 BWN_RF_WRITE(mac, 0x54, 0x98); 1455 BWN_RF_WRITE(mac, 0x5a, 0x88); 1456 BWN_RF_WRITE(mac, 0x5b, 0x6b); 1457 BWN_RF_WRITE(mac, 0x5c, 0x0f); 1458 if (sc->sc_board_info.board_flags & BHND_BFL_ALTIQ) { 1459 BWN_RF_WRITE(mac, 0x5d, 0xfa); 1460 BWN_RF_WRITE(mac, 0x5e, 0xd8); 1461 } else { 1462 BWN_RF_WRITE(mac, 0x5d, 0xf5); 1463 BWN_RF_WRITE(mac, 0x5e, 0xb8); 1464 } 1465 BWN_RF_WRITE(mac, 0x0073, 0x0003); 1466 BWN_RF_WRITE(mac, 0x007d, 0x00a8); 1467 BWN_RF_WRITE(mac, 0x007c, 0x0001); 1468 BWN_RF_WRITE(mac, 0x007e, 0x0008); 1469 } 1470 for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) { 1471 BWN_PHY_WRITE(mac, offset, val); 1472 val -= 0x0202; 1473 } 1474 for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) { 1475 BWN_PHY_WRITE(mac, offset, val); 1476 val -= 0x0202; 1477 } 1478 for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) { 1479 BWN_PHY_WRITE(mac, offset, (val & 0x3f3f)); 1480 val += 0x0202; 1481 } 1482 if (phy->type == BWN_PHYTYPE_G) { 1483 BWN_RF_SET(mac, 0x007a, 0x0020); 1484 BWN_RF_SET(mac, 0x0051, 0x0004); 1485 BWN_PHY_SET(mac, 0x0802, 0x0100); 1486 BWN_PHY_SET(mac, 0x042b, 0x2000); 1487 BWN_PHY_WRITE(mac, 0x5b, 0); 1488 BWN_PHY_WRITE(mac, 0x5c, 0); 1489 } 1490 1491 old_channel = phy->chan; 1492 bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0); 1493 1494 BWN_RF_WRITE(mac, 0x0050, 0x0020); 1495 BWN_RF_WRITE(mac, 0x0050, 0x0023); 1496 DELAY(40); 1497 if (phy->rf_rev < 6 || phy->rf_rev == 8) { 1498 BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002); 1499 BWN_RF_WRITE(mac, 0x50, 0x20); 1500 } 1501 if (phy->rf_rev <= 2) { 1502 BWN_RF_WRITE(mac, 0x7c, 0x20); 1503 BWN_RF_WRITE(mac, 0x5a, 0x70); 1504 BWN_RF_WRITE(mac, 0x5b, 0x7b); 1505 BWN_RF_WRITE(mac, 0x5c, 0xb0); 1506 } 1507 BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007); 1508 1509 bwn_phy_g_switch_chan(mac, old_channel, 0); 1510 1511 BWN_PHY_WRITE(mac, 0x0014, 0x0200); 1512 if (phy->rf_rev >= 6) 1513 BWN_PHY_WRITE(mac, 0x2a, 0x88c2); 1514 else 1515 BWN_PHY_WRITE(mac, 0x2a, 0x8ac0); 1516 BWN_PHY_WRITE(mac, 0x0038, 0x0668); 1517 bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt, 1518 pg->pg_txctl); 1519 if (phy->rf_rev <= 5) 1520 BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003); 1521 if (phy->rf_rev <= 2) 1522 BWN_RF_WRITE(mac, 0x005d, 0x000d); 1523 1524 if (phy->analog == 4) { 1525 BWN_WRITE_2(mac, 0x3e4, 9); 1526 BWN_PHY_MASK(mac, 0x61, 0x0fff); 1527 } else 1528 BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004); 1529 if (phy->type == BWN_PHYTYPE_B) 1530 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); 1531 else if (phy->type == BWN_PHYTYPE_G) 1532 BWN_WRITE_2(mac, 0x03e6, 0x0); 1533 } 1534 1535 static void 1536 bwn_phy_init_a(struct bwn_mac *mac) 1537 { 1538 struct bwn_phy *phy = &mac->mac_phy; 1539 struct bwn_softc *sc = mac->mac_sc; 1540 1541 KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G, 1542 ("%s:%d: fail", __func__, __LINE__)); 1543 1544 if (phy->rev >= 6) { 1545 if (phy->type == BWN_PHYTYPE_A) 1546 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000); 1547 if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN) 1548 BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010); 1549 else 1550 BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010); 1551 } 1552 1553 bwn_wa_init(mac); 1554 1555 if (phy->type == BWN_PHYTYPE_G && 1556 (sc->sc_board_info.board_flags & BHND_BFL_PACTRL)) 1557 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf); 1558 } 1559 1560 static void 1561 bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst) 1562 { 1563 int i; 1564 1565 for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++) 1566 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]); 1567 } 1568 1569 static void 1570 bwn_wa_agc(struct bwn_mac *mac) 1571 { 1572 struct bwn_phy *phy = &mac->mac_phy; 1573 1574 if (phy->rev == 1) { 1575 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254); 1576 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13); 1577 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19); 1578 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25); 1579 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710); 1580 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83); 1581 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83); 1582 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d); 1583 BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4); 1584 } else { 1585 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254); 1586 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13); 1587 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19); 1588 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25); 1589 } 1590 1591 BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00, 1592 0x5700); 1593 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f); 1594 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80); 1595 BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300); 1596 BWN_RF_SET(mac, 0x7a, 0x0008); 1597 BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008); 1598 BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600); 1599 BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700); 1600 BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100); 1601 if (phy->rev == 1) 1602 BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007); 1603 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c); 1604 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200); 1605 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c); 1606 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020); 1607 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200); 1608 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e); 1609 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00); 1610 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028); 1611 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00); 1612 if (phy->rev == 1) { 1613 BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b); 1614 BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002); 1615 } else { 1616 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e); 1617 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a); 1618 BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004); 1619 if (phy->rev >= 6) { 1620 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a); 1621 BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, 1622 (uint16_t)~0xf000, 0x3000); 1623 } 1624 } 1625 BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874); 1626 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00); 1627 if (phy->rev == 1) { 1628 BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600); 1629 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e); 1630 BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e); 1631 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002); 1632 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0); 1633 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7); 1634 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16); 1635 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28); 1636 } else { 1637 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0); 1638 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7); 1639 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16); 1640 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28); 1641 } 1642 if (phy->rev >= 6) { 1643 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003); 1644 BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000); 1645 } 1646 BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM); 1647 } 1648 1649 static void 1650 bwn_wa_grev1(struct bwn_mac *mac) 1651 { 1652 struct bwn_phy *phy = &mac->mac_phy; 1653 int i; 1654 static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G; 1655 static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD; 1656 static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR; 1657 1658 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__)); 1659 1660 /* init CRSTHRES and ANTDWELL */ 1661 if (phy->rev == 1) { 1662 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19); 1663 } else if (phy->rev == 2) { 1664 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861); 1665 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271); 1666 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800); 1667 } else { 1668 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098); 1669 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070); 1670 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080); 1671 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800); 1672 } 1673 BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000); 1674 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a); 1675 BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026); 1676 1677 /* XXX support PHY-A??? */ 1678 for (i = 0; i < N(bwn_tab_finefreqg); i++) 1679 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i, 1680 bwn_tab_finefreqg[i]); 1681 1682 /* XXX support PHY-A??? */ 1683 if (phy->rev == 1) 1684 for (i = 0; i < N(bwn_tab_noise_g1); i++) 1685 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i, 1686 bwn_tab_noise_g1[i]); 1687 else 1688 for (i = 0; i < N(bwn_tab_noise_g2); i++) 1689 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i, 1690 bwn_tab_noise_g2[i]); 1691 1692 1693 for (i = 0; i < N(bwn_tab_rotor); i++) 1694 bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i, 1695 bwn_tab_rotor[i]); 1696 1697 /* XXX support PHY-A??? */ 1698 if (phy->rev >= 6) { 1699 if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & 1700 BWN_PHY_ENCORE_EN) 1701 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3); 1702 else 1703 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2); 1704 } else 1705 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1); 1706 1707 for (i = 0; i < N(bwn_tab_retard); i++) 1708 bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i, 1709 bwn_tab_retard[i]); 1710 1711 if (phy->rev == 1) { 1712 for (i = 0; i < 16; i++) 1713 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, 1714 i, 0x0020); 1715 } else { 1716 for (i = 0; i < 32; i++) 1717 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820); 1718 } 1719 1720 bwn_wa_agc(mac); 1721 } 1722 1723 static void 1724 bwn_wa_grev26789(struct bwn_mac *mac) 1725 { 1726 struct bwn_phy *phy = &mac->mac_phy; 1727 int i; 1728 static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2; 1729 uint16_t ofdmrev; 1730 1731 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__)); 1732 1733 bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480); 1734 1735 /* init CRSTHRES and ANTDWELL */ 1736 if (phy->rev == 1) 1737 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19); 1738 else if (phy->rev == 2) { 1739 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861); 1740 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271); 1741 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800); 1742 } else { 1743 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098); 1744 BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070); 1745 BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080); 1746 BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800); 1747 } 1748 1749 for (i = 0; i < 64; i++) 1750 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i); 1751 1752 /* XXX support PHY-A??? */ 1753 if (phy->rev == 1) 1754 for (i = 0; i < N(bwn_tab_noise_g1); i++) 1755 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i, 1756 bwn_tab_noise_g1[i]); 1757 else 1758 for (i = 0; i < N(bwn_tab_noise_g2); i++) 1759 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i, 1760 bwn_tab_noise_g2[i]); 1761 1762 /* XXX support PHY-A??? */ 1763 if (phy->rev >= 6) { 1764 if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & 1765 BWN_PHY_ENCORE_EN) 1766 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3); 1767 else 1768 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2); 1769 } else 1770 bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1); 1771 1772 for (i = 0; i < N(bwn_tab_sigmasqr2); i++) 1773 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i, 1774 bwn_tab_sigmasqr2[i]); 1775 1776 if (phy->rev == 1) { 1777 for (i = 0; i < 16; i++) 1778 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i, 1779 0x0020); 1780 } else { 1781 for (i = 0; i < 32; i++) 1782 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820); 1783 } 1784 1785 bwn_wa_agc(mac); 1786 1787 ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION; 1788 if (ofdmrev > 2) { 1789 if (phy->type == BWN_PHYTYPE_A) 1790 BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808); 1791 else 1792 BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000); 1793 } else { 1794 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044); 1795 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201); 1796 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040); 1797 } 1798 1799 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15); 1800 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20); 1801 } 1802 1803 static void 1804 bwn_wa_init(struct bwn_mac *mac) 1805 { 1806 struct bwn_phy *phy = &mac->mac_phy; 1807 struct bwn_softc *sc = mac->mac_sc; 1808 1809 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__)); 1810 1811 switch (phy->rev) { 1812 case 1: 1813 bwn_wa_grev1(mac); 1814 break; 1815 case 2: 1816 case 6: 1817 case 7: 1818 case 8: 1819 case 9: 1820 bwn_wa_grev26789(mac); 1821 break; 1822 default: 1823 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); 1824 } 1825 1826 if (sc->sc_board_info.board_vendor != PCI_VENDOR_BROADCOM || 1827 sc->sc_board_info.board_type != BHND_BOARD_BU4306 || 1828 sc->sc_board_info.board_rev != 0x17) { 1829 if (phy->rev < 2) { 1830 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1, 1831 0x0002); 1832 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2, 1833 0x0001); 1834 } else { 1835 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002); 1836 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001); 1837 if ((sc->sc_board_info.board_flags & 1838 BHND_BFL_EXTLNA) && 1839 (phy->rev >= 7)) { 1840 BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff); 1841 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1842 0x0020, 0x0001); 1843 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1844 0x0021, 0x0001); 1845 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1846 0x0022, 0x0001); 1847 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1848 0x0023, 0x0000); 1849 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1850 0x0000, 0x0000); 1851 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1852 0x0003, 0x0002); 1853 } 1854 } 1855 } 1856 if (sc->sc_board_info.board_flags & BHND_BFL_FEM) { 1857 BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120); 1858 BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480); 1859 } 1860 1861 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0); 1862 bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0); 1863 } 1864 1865 static void 1866 bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset, 1867 uint16_t value) 1868 { 1869 struct bwn_phy_g *pg = &mac->mac_phy.phy_g; 1870 uint16_t addr; 1871 1872 addr = table + offset; 1873 if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) || 1874 (addr - 1 != pg->pg_ofdmtab_addr)) { 1875 BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr); 1876 pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE; 1877 } 1878 pg->pg_ofdmtab_addr = addr; 1879 BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value); 1880 } 1881 1882 static void 1883 bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset, 1884 uint32_t value) 1885 { 1886 struct bwn_phy_g *pg = &mac->mac_phy.phy_g; 1887 uint16_t addr; 1888 1889 addr = table + offset; 1890 if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) || 1891 (addr - 1 != pg->pg_ofdmtab_addr)) { 1892 BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr); 1893 pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE; 1894 } 1895 pg->pg_ofdmtab_addr = addr; 1896 1897 BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value); 1898 BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16)); 1899 } 1900 1901 static void 1902 bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset, 1903 uint16_t value) 1904 { 1905 1906 BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset); 1907 BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value); 1908 } 1909 1910 static void 1911 bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl) 1912 { 1913 uint16_t value; 1914 1915 KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G, 1916 ("%s:%d: fail", __func__, __LINE__)); 1917 1918 value = (uint8_t) (ctl->q); 1919 value |= ((uint8_t) (ctl->i)) << 8; 1920 BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value); 1921 } 1922 1923 static uint16_t 1924 bwn_lo_calcfeed(struct bwn_mac *mac, 1925 uint16_t lna, uint16_t pga, uint16_t trsw_rx) 1926 { 1927 struct bwn_phy *phy = &mac->mac_phy; 1928 struct bwn_softc *sc = mac->mac_sc; 1929 uint16_t rfover; 1930 uint16_t feedthrough; 1931 1932 if (phy->gmode) { 1933 lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT; 1934 pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT; 1935 1936 KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0, 1937 ("%s:%d: fail", __func__, __LINE__)); 1938 KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0, 1939 ("%s:%d: fail", __func__, __LINE__)); 1940 1941 trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW); 1942 1943 rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx; 1944 if ((sc->sc_board_info.board_flags & BHND_BFL_EXTLNA) && 1945 phy->rev > 6) 1946 rfover |= BWN_PHY_RFOVERVAL_EXTLNA; 1947 1948 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300); 1949 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover); 1950 DELAY(10); 1951 rfover |= BWN_PHY_RFOVERVAL_BW_LBW; 1952 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover); 1953 DELAY(10); 1954 rfover |= BWN_PHY_RFOVERVAL_BW_LPF; 1955 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover); 1956 DELAY(10); 1957 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300); 1958 } else { 1959 pga |= BWN_PHY_PGACTL_UNKNOWN; 1960 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga); 1961 DELAY(10); 1962 pga |= BWN_PHY_PGACTL_LOWBANDW; 1963 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga); 1964 DELAY(10); 1965 pga |= BWN_PHY_PGACTL_LPF; 1966 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga); 1967 } 1968 DELAY(21); 1969 feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE); 1970 1971 return (feedthrough); 1972 } 1973 1974 static uint16_t 1975 bwn_lo_txctl_regtable(struct bwn_mac *mac, 1976 uint16_t *value, uint16_t *pad_mix_gain) 1977 { 1978 struct bwn_phy *phy = &mac->mac_phy; 1979 uint16_t reg, v, padmix; 1980 1981 if (phy->type == BWN_PHYTYPE_B) { 1982 v = 0x30; 1983 if (phy->rf_rev <= 5) { 1984 reg = 0x43; 1985 padmix = 0; 1986 } else { 1987 reg = 0x52; 1988 padmix = 5; 1989 } 1990 } else { 1991 if (phy->rev >= 2 && phy->rf_rev == 8) { 1992 reg = 0x43; 1993 v = 0x10; 1994 padmix = 2; 1995 } else { 1996 reg = 0x52; 1997 v = 0x30; 1998 padmix = 5; 1999 } 2000 } 2001 if (value) 2002 *value = v; 2003 if (pad_mix_gain) 2004 *pad_mix_gain = padmix; 2005 2006 return (reg); 2007 } 2008 2009 static void 2010 bwn_lo_measure_txctl_values(struct bwn_mac *mac) 2011 { 2012 struct bwn_phy *phy = &mac->mac_phy; 2013 struct bwn_phy_g *pg = &phy->phy_g; 2014 struct bwn_txpwr_loctl *lo = &pg->pg_loctl; 2015 uint16_t reg, mask; 2016 uint16_t trsw_rx, pga; 2017 uint16_t rf_pctl_reg; 2018 2019 static const uint8_t tx_bias_values[] = { 2020 0x09, 0x08, 0x0a, 0x01, 0x00, 2021 0x02, 0x05, 0x04, 0x06, 2022 }; 2023 static const uint8_t tx_magn_values[] = { 2024 0x70, 0x40, 2025 }; 2026 2027 if (!BWN_HAS_LOOPBACK(phy)) { 2028 rf_pctl_reg = 6; 2029 trsw_rx = 2; 2030 pga = 0; 2031 } else { 2032 int lb_gain; 2033 2034 trsw_rx = 0; 2035 lb_gain = pg->pg_max_lb_gain / 2; 2036 if (lb_gain > 10) { 2037 rf_pctl_reg = 0; 2038 pga = abs(10 - lb_gain) / 6; 2039 pga = MIN(MAX(pga, 0), 15); 2040 } else { 2041 int cmp_val; 2042 int tmp; 2043 2044 pga = 0; 2045 cmp_val = 0x24; 2046 if ((phy->rev >= 2) && 2047 (phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) 2048 cmp_val = 0x3c; 2049 tmp = lb_gain; 2050 if ((10 - lb_gain) < cmp_val) 2051 tmp = (10 - lb_gain); 2052 if (tmp < 0) 2053 tmp += 6; 2054 else 2055 tmp += 3; 2056 cmp_val /= 4; 2057 tmp /= 4; 2058 if (tmp >= cmp_val) 2059 rf_pctl_reg = cmp_val; 2060 else 2061 rf_pctl_reg = tmp; 2062 } 2063 } 2064 BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg); 2065 bwn_phy_g_set_bbatt(mac, 2); 2066 2067 reg = bwn_lo_txctl_regtable(mac, &mask, NULL); 2068 mask = ~mask; 2069 BWN_RF_MASK(mac, reg, mask); 2070 2071 if (BWN_HAS_TXMAG(phy)) { 2072 int i, j; 2073 int feedthrough; 2074 int min_feedth = 0xffff; 2075 uint8_t tx_magn, tx_bias; 2076 2077 for (i = 0; i < N(tx_magn_values); i++) { 2078 tx_magn = tx_magn_values[i]; 2079 BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn); 2080 for (j = 0; j < N(tx_bias_values); j++) { 2081 tx_bias = tx_bias_values[j]; 2082 BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias); 2083 feedthrough = bwn_lo_calcfeed(mac, 0, pga, 2084 trsw_rx); 2085 if (feedthrough < min_feedth) { 2086 lo->tx_bias = tx_bias; 2087 lo->tx_magn = tx_magn; 2088 min_feedth = feedthrough; 2089 } 2090 if (lo->tx_bias == 0) 2091 break; 2092 } 2093 BWN_RF_WRITE(mac, 0x52, 2094 (BWN_RF_READ(mac, 0x52) 2095 & 0xff00) | lo->tx_bias | lo-> 2096 tx_magn); 2097 } 2098 } else { 2099 lo->tx_magn = 0; 2100 lo->tx_bias = 0; 2101 BWN_RF_MASK(mac, 0x52, 0xfff0); 2102 } 2103 2104 BWN_GETTIME(lo->txctl_measured_time); 2105 } 2106 2107 static void 2108 bwn_lo_get_powervector(struct bwn_mac *mac) 2109 { 2110 struct bwn_phy *phy = &mac->mac_phy; 2111 struct bwn_phy_g *pg = &phy->phy_g; 2112 struct bwn_txpwr_loctl *lo = &pg->pg_loctl; 2113 int i; 2114 uint64_t tmp; 2115 uint64_t power_vector = 0; 2116 2117 for (i = 0; i < 8; i += 2) { 2118 tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i); 2119 power_vector |= (tmp << (i * 8)); 2120 bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0); 2121 } 2122 if (power_vector) 2123 lo->power_vector = power_vector; 2124 2125 BWN_GETTIME(lo->pwr_vec_read_time); 2126 } 2127 2128 static void 2129 bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain, 2130 int use_trsw_rx) 2131 { 2132 struct bwn_phy *phy = &mac->mac_phy; 2133 struct bwn_phy_g *pg = &phy->phy_g; 2134 uint16_t tmp; 2135 2136 if (max_rx_gain < 0) 2137 max_rx_gain = 0; 2138 2139 if (BWN_HAS_LOOPBACK(phy)) { 2140 int trsw_rx = 0; 2141 int trsw_rx_gain; 2142 2143 if (use_trsw_rx) { 2144 trsw_rx_gain = pg->pg_trsw_rx_gain / 2; 2145 if (max_rx_gain >= trsw_rx_gain) { 2146 trsw_rx_gain = max_rx_gain - trsw_rx_gain; 2147 trsw_rx = 0x20; 2148 } 2149 } else 2150 trsw_rx_gain = max_rx_gain; 2151 if (trsw_rx_gain < 9) { 2152 pg->pg_lna_lod_gain = 0; 2153 } else { 2154 pg->pg_lna_lod_gain = 1; 2155 trsw_rx_gain -= 8; 2156 } 2157 trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d); 2158 pg->pg_pga_gain = trsw_rx_gain / 3; 2159 if (pg->pg_pga_gain >= 5) { 2160 pg->pg_pga_gain -= 5; 2161 pg->pg_lna_gain = 2; 2162 } else 2163 pg->pg_lna_gain = 0; 2164 } else { 2165 pg->pg_lna_gain = 0; 2166 pg->pg_trsw_rx_gain = 0x20; 2167 if (max_rx_gain >= 0x14) { 2168 pg->pg_lna_lod_gain = 1; 2169 pg->pg_pga_gain = 2; 2170 } else if (max_rx_gain >= 0x12) { 2171 pg->pg_lna_lod_gain = 1; 2172 pg->pg_pga_gain = 1; 2173 } else if (max_rx_gain >= 0xf) { 2174 pg->pg_lna_lod_gain = 1; 2175 pg->pg_pga_gain = 0; 2176 } else { 2177 pg->pg_lna_lod_gain = 0; 2178 pg->pg_pga_gain = 0; 2179 } 2180 } 2181 2182 tmp = BWN_RF_READ(mac, 0x7a); 2183 if (pg->pg_lna_lod_gain == 0) 2184 tmp &= ~0x0008; 2185 else 2186 tmp |= 0x0008; 2187 BWN_RF_WRITE(mac, 0x7a, tmp); 2188 } 2189 2190 static void 2191 bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav) 2192 { 2193 struct bwn_phy *phy = &mac->mac_phy; 2194 struct bwn_phy_g *pg = &phy->phy_g; 2195 struct bwn_softc *sc = mac->mac_sc; 2196 struct bwn_txpwr_loctl *lo = &pg->pg_loctl; 2197 struct timespec ts; 2198 uint16_t tmp; 2199 2200 if (bwn_has_hwpctl(mac)) { 2201 sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK); 2202 sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01)); 2203 sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL); 2204 sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14)); 2205 sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL); 2206 2207 BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100); 2208 BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40); 2209 BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40); 2210 BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200); 2211 } 2212 if (phy->type == BWN_PHYTYPE_B && 2213 phy->rf_ver == 0x2050 && phy->rf_rev < 6) { 2214 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410); 2215 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820); 2216 } 2217 if (phy->rev >= 2) { 2218 sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER); 2219 sav->phy_analogoverval = 2220 BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL); 2221 sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER); 2222 sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL); 2223 sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL); 2224 sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e)); 2225 sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0); 2226 2227 BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc); 2228 BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff); 2229 BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003); 2230 BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc); 2231 if (phy->type == BWN_PHYTYPE_G) { 2232 if ((phy->rev >= 7) && 2233 (sc->sc_board_info.board_flags & 2234 BHND_BFL_EXTLNA)) { 2235 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933); 2236 } else { 2237 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133); 2238 } 2239 } else { 2240 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0); 2241 } 2242 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0); 2243 } 2244 sav->reg0 = BWN_READ_2(mac, 0x3f4); 2245 sav->reg1 = BWN_READ_2(mac, 0x3e2); 2246 sav->rf0 = BWN_RF_READ(mac, 0x43); 2247 sav->rf1 = BWN_RF_READ(mac, 0x7a); 2248 sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL); 2249 sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a)); 2250 sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL); 2251 sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL); 2252 2253 if (!BWN_HAS_TXMAG(phy)) { 2254 sav->rf2 = BWN_RF_READ(mac, 0x52); 2255 sav->rf2 &= 0x00f0; 2256 } 2257 if (phy->type == BWN_PHYTYPE_B) { 2258 sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30)); 2259 sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06)); 2260 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff); 2261 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f); 2262 } else { 2263 BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) 2264 | 0x8000); 2265 } 2266 BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4) 2267 & 0xf000); 2268 2269 tmp = 2270 (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e); 2271 BWN_PHY_WRITE(mac, tmp, 0x007f); 2272 2273 tmp = sav->phy_syncctl; 2274 BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f); 2275 tmp = sav->rf1; 2276 BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0); 2277 2278 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3); 2279 if (phy->type == BWN_PHYTYPE_G || 2280 (phy->type == BWN_PHYTYPE_B && 2281 phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) { 2282 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003); 2283 } else 2284 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802); 2285 if (phy->rev >= 2) 2286 bwn_dummy_transmission(mac, 0, 1); 2287 bwn_phy_g_switch_chan(mac, 6, 0); 2288 BWN_RF_READ(mac, 0x51); 2289 if (phy->type == BWN_PHYTYPE_G) 2290 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0); 2291 2292 nanouptime(&ts); 2293 if (ieee80211_time_before(lo->txctl_measured_time, 2294 (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE)) 2295 bwn_lo_measure_txctl_values(mac); 2296 2297 if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3) 2298 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078); 2299 else { 2300 if (phy->type == BWN_PHYTYPE_B) 2301 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078); 2302 else 2303 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078); 2304 } 2305 } 2306 2307 static void 2308 bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav) 2309 { 2310 struct bwn_phy *phy = &mac->mac_phy; 2311 struct bwn_phy_g *pg = &phy->phy_g; 2312 uint16_t tmp; 2313 2314 if (phy->rev >= 2) { 2315 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300); 2316 tmp = (pg->pg_pga_gain << 8); 2317 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0); 2318 DELAY(5); 2319 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2); 2320 DELAY(2); 2321 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3); 2322 } else { 2323 tmp = (pg->pg_pga_gain | 0xefa0); 2324 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp); 2325 } 2326 if (phy->type == BWN_PHYTYPE_G) { 2327 if (phy->rev >= 3) 2328 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078); 2329 else 2330 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078); 2331 if (phy->rev >= 2) 2332 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202); 2333 else 2334 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101); 2335 } 2336 BWN_WRITE_2(mac, 0x3f4, sav->reg0); 2337 BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl); 2338 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2); 2339 BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl); 2340 BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl); 2341 BWN_RF_WRITE(mac, 0x43, sav->rf0); 2342 BWN_RF_WRITE(mac, 0x7a, sav->rf1); 2343 if (!BWN_HAS_TXMAG(phy)) { 2344 tmp = sav->rf2; 2345 BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp); 2346 } 2347 BWN_WRITE_2(mac, 0x3e2, sav->reg1); 2348 if (phy->type == BWN_PHYTYPE_B && 2349 phy->rf_ver == 0x2050 && phy->rf_rev <= 5) { 2350 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0); 2351 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1); 2352 } 2353 if (phy->rev >= 2) { 2354 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover); 2355 BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 2356 sav->phy_analogoverval); 2357 BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl); 2358 BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover); 2359 BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval); 2360 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3); 2361 BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0); 2362 } 2363 if (bwn_has_hwpctl(mac)) { 2364 tmp = (sav->phy_lomask & 0xbfff); 2365 BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp); 2366 BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg); 2367 BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl); 2368 BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4); 2369 BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl); 2370 } 2371 bwn_phy_g_switch_chan(mac, sav->old_channel, 1); 2372 } 2373 2374 static int 2375 bwn_lo_probe_loctl(struct bwn_mac *mac, 2376 struct bwn_loctl *probe, struct bwn_lo_g_sm *d) 2377 { 2378 struct bwn_phy *phy = &mac->mac_phy; 2379 struct bwn_phy_g *pg = &phy->phy_g; 2380 struct bwn_loctl orig, test; 2381 struct bwn_loctl prev = { -100, -100 }; 2382 static const struct bwn_loctl modifiers[] = { 2383 { 1, 1,}, { 1, 0,}, { 1, -1,}, { 0, -1,}, 2384 { -1, -1,}, { -1, 0,}, { -1, 1,}, { 0, 1,} 2385 }; 2386 int begin, end, lower = 0, i; 2387 uint16_t feedth; 2388 2389 if (d->curstate == 0) { 2390 begin = 1; 2391 end = 8; 2392 } else if (d->curstate % 2 == 0) { 2393 begin = d->curstate - 1; 2394 end = d->curstate + 1; 2395 } else { 2396 begin = d->curstate - 2; 2397 end = d->curstate + 2; 2398 } 2399 if (begin < 1) 2400 begin += 8; 2401 if (end > 8) 2402 end -= 8; 2403 2404 memcpy(&orig, probe, sizeof(struct bwn_loctl)); 2405 i = begin; 2406 d->curstate = i; 2407 while (1) { 2408 KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__)); 2409 memcpy(&test, &orig, sizeof(struct bwn_loctl)); 2410 test.i += modifiers[i - 1].i * d->multipler; 2411 test.q += modifiers[i - 1].q * d->multipler; 2412 if ((test.i != prev.i || test.q != prev.q) && 2413 (abs(test.i) <= 16 && abs(test.q) <= 16)) { 2414 bwn_lo_write(mac, &test); 2415 feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain, 2416 pg->pg_pga_gain, pg->pg_trsw_rx_gain); 2417 if (feedth < d->feedth) { 2418 memcpy(probe, &test, 2419 sizeof(struct bwn_loctl)); 2420 lower = 1; 2421 d->feedth = feedth; 2422 if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy)) 2423 break; 2424 } 2425 } 2426 memcpy(&prev, &test, sizeof(prev)); 2427 if (i == end) 2428 break; 2429 if (i == 8) 2430 i = 1; 2431 else 2432 i++; 2433 d->curstate = i; 2434 } 2435 2436 return (lower); 2437 } 2438 2439 static void 2440 bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain) 2441 { 2442 struct bwn_phy *phy = &mac->mac_phy; 2443 struct bwn_phy_g *pg = &phy->phy_g; 2444 struct bwn_lo_g_sm d; 2445 struct bwn_loctl probe; 2446 int lower, repeat, cnt = 0; 2447 uint16_t feedth; 2448 2449 d.nmeasure = 0; 2450 d.multipler = 1; 2451 if (BWN_HAS_LOOPBACK(phy)) 2452 d.multipler = 3; 2453 2454 memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl)); 2455 repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1; 2456 2457 do { 2458 bwn_lo_write(mac, &d.loctl); 2459 feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain, 2460 pg->pg_pga_gain, pg->pg_trsw_rx_gain); 2461 if (feedth < 0x258) { 2462 if (feedth >= 0x12c) 2463 *rxgain += 6; 2464 else 2465 *rxgain += 3; 2466 feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain, 2467 pg->pg_pga_gain, pg->pg_trsw_rx_gain); 2468 } 2469 d.feedth = feedth; 2470 d.curstate = 0; 2471 do { 2472 KASSERT(d.curstate >= 0 && d.curstate <= 8, 2473 ("%s:%d: fail", __func__, __LINE__)); 2474 memcpy(&probe, &d.loctl, 2475 sizeof(struct bwn_loctl)); 2476 lower = bwn_lo_probe_loctl(mac, &probe, &d); 2477 if (!lower) 2478 break; 2479 if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q)) 2480 break; 2481 memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl)); 2482 d.nmeasure++; 2483 } while (d.nmeasure < 24); 2484 memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl)); 2485 2486 if (BWN_HAS_LOOPBACK(phy)) { 2487 if (d.feedth > 0x1194) 2488 *rxgain -= 6; 2489 else if (d.feedth < 0x5dc) 2490 *rxgain += 3; 2491 if (cnt == 0) { 2492 if (d.feedth <= 0x5dc) { 2493 d.multipler = 1; 2494 cnt++; 2495 } else 2496 d.multipler = 2; 2497 } else if (cnt == 2) 2498 d.multipler = 1; 2499 } 2500 bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy)); 2501 } while (++cnt < repeat); 2502 } 2503 2504 static struct bwn_lo_calib * 2505 bwn_lo_calibset(struct bwn_mac *mac, 2506 const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt) 2507 { 2508 struct bwn_phy *phy = &mac->mac_phy; 2509 struct bwn_phy_g *pg = &phy->phy_g; 2510 struct bwn_loctl loctl = { 0, 0 }; 2511 struct bwn_lo_calib *cal; 2512 struct bwn_lo_g_value sval = { 0 }; 2513 int rxgain; 2514 uint16_t pad, reg, value; 2515 2516 sval.old_channel = phy->chan; 2517 bwn_mac_suspend(mac); 2518 bwn_lo_save(mac, &sval); 2519 2520 reg = bwn_lo_txctl_regtable(mac, &value, &pad); 2521 BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att); 2522 BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0)); 2523 2524 rxgain = (rfatt->att * 2) + (bbatt->att / 2); 2525 if (rfatt->padmix) 2526 rxgain -= pad; 2527 if (BWN_HAS_LOOPBACK(phy)) 2528 rxgain += pg->pg_max_lb_gain; 2529 bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy)); 2530 bwn_phy_g_set_bbatt(mac, bbatt->att); 2531 bwn_lo_probe_sm(mac, &loctl, &rxgain); 2532 2533 bwn_lo_restore(mac, &sval); 2534 bwn_mac_enable(mac); 2535 2536 cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO); 2537 if (!cal) { 2538 device_printf(mac->mac_sc->sc_dev, "out of memory\n"); 2539 return (NULL); 2540 } 2541 memcpy(&cal->bbatt, bbatt, sizeof(*bbatt)); 2542 memcpy(&cal->rfatt, rfatt, sizeof(*rfatt)); 2543 memcpy(&cal->ctl, &loctl, sizeof(loctl)); 2544 2545 BWN_GETTIME(cal->calib_time); 2546 2547 return (cal); 2548 } 2549 2550 static struct bwn_lo_calib * 2551 bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt, 2552 const struct bwn_rfatt *rfatt) 2553 { 2554 struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl; 2555 struct bwn_lo_calib *c; 2556 2557 TAILQ_FOREACH(c, &lo->calib_list, list) { 2558 if (!BWN_BBATTCMP(&c->bbatt, bbatt)) 2559 continue; 2560 if (!BWN_RFATTCMP(&c->rfatt, rfatt)) 2561 continue; 2562 return (c); 2563 } 2564 2565 c = bwn_lo_calibset(mac, bbatt, rfatt); 2566 if (!c) 2567 return (NULL); 2568 TAILQ_INSERT_TAIL(&lo->calib_list, c, list); 2569 2570 return (c); 2571 } 2572 2573 static void 2574 bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update) 2575 { 2576 struct bwn_phy *phy = &mac->mac_phy; 2577 struct bwn_phy_g *pg = &phy->phy_g; 2578 struct bwn_softc *sc = mac->mac_sc; 2579 struct bwn_txpwr_loctl *lo = &pg->pg_loctl; 2580 const struct bwn_rfatt *rfatt; 2581 const struct bwn_bbatt *bbatt; 2582 uint64_t pvector; 2583 int i; 2584 int rf_offset, bb_offset; 2585 uint8_t changed = 0; 2586 2587 KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__)); 2588 KASSERT(lo->rfatt.len * lo->bbatt.len <= 64, 2589 ("%s:%d: fail", __func__, __LINE__)); 2590 2591 pvector = lo->power_vector; 2592 if (!update && !pvector) 2593 return; 2594 2595 bwn_mac_suspend(mac); 2596 2597 for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) { 2598 struct bwn_lo_calib *cal; 2599 int idx; 2600 uint16_t val; 2601 2602 if (!update && !(pvector & (((uint64_t)1ULL) << i))) 2603 continue; 2604 bb_offset = i / lo->rfatt.len; 2605 rf_offset = i % lo->rfatt.len; 2606 bbatt = &(lo->bbatt.array[bb_offset]); 2607 rfatt = &(lo->rfatt.array[rf_offset]); 2608 2609 cal = bwn_lo_calibset(mac, bbatt, rfatt); 2610 if (!cal) { 2611 device_printf(sc->sc_dev, "LO: Could not " 2612 "calibrate DC table entry\n"); 2613 continue; 2614 } 2615 val = (uint8_t)(cal->ctl.q); 2616 val |= ((uint8_t)(cal->ctl.i)) << 4; 2617 free(cal, M_DEVBUF); 2618 2619 idx = i / 2; 2620 if (i % 2) 2621 lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff) 2622 | ((val & 0x00ff) << 8); 2623 else 2624 lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00) 2625 | (val & 0x00ff); 2626 changed = 1; 2627 } 2628 if (changed) { 2629 for (i = 0; i < BWN_DC_LT_SIZE; i++) 2630 BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]); 2631 } 2632 bwn_mac_enable(mac); 2633 } 2634 2635 static void 2636 bwn_lo_fixup_rfatt(struct bwn_rfatt *rf) 2637 { 2638 2639 if (!rf->padmix) 2640 return; 2641 if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3)) 2642 rf->att = 4; 2643 } 2644 2645 static void 2646 bwn_lo_g_adjust(struct bwn_mac *mac) 2647 { 2648 struct bwn_phy_g *pg = &mac->mac_phy.phy_g; 2649 struct bwn_lo_calib *cal; 2650 struct bwn_rfatt rf; 2651 2652 memcpy(&rf, &pg->pg_rfatt, sizeof(rf)); 2653 bwn_lo_fixup_rfatt(&rf); 2654 2655 cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf); 2656 if (!cal) 2657 return; 2658 bwn_lo_write(mac, &cal->ctl); 2659 } 2660 2661 static void 2662 bwn_lo_g_init(struct bwn_mac *mac) 2663 { 2664 2665 if (!bwn_has_hwpctl(mac)) 2666 return; 2667 2668 bwn_lo_get_powervector(mac); 2669 bwn_phy_g_dc_lookup_init(mac, 1); 2670 } 2671 2672 static int16_t 2673 bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset) 2674 { 2675 2676 BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset); 2677 return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA)); 2678 } 2679 2680 static void 2681 bwn_nrssi_threshold(struct bwn_mac *mac) 2682 { 2683 struct bwn_phy *phy = &mac->mac_phy; 2684 struct bwn_phy_g *pg = &phy->phy_g; 2685 struct bwn_softc *sc = mac->mac_sc; 2686 int32_t a, b; 2687 int16_t tmp16; 2688 uint16_t tmpu16; 2689 2690 KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__)); 2691 2692 if (phy->gmode && (sc->sc_board_info.board_flags & BHND_BFL_ADCDIV)) { 2693 if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) { 2694 a = 0x13; 2695 b = 0x12; 2696 } else { 2697 a = 0xe; 2698 b = 0x11; 2699 } 2700 2701 a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]); 2702 a += (pg->pg_nrssi[0] << 6); 2703 a += (a < 32) ? 31 : 32; 2704 a = a >> 6; 2705 a = MIN(MAX(a, -31), 31); 2706 2707 b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]); 2708 b += (pg->pg_nrssi[0] << 6); 2709 if (b < 32) 2710 b += 31; 2711 else 2712 b += 32; 2713 b = b >> 6; 2714 b = MIN(MAX(b, -31), 31); 2715 2716 tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000; 2717 tmpu16 |= ((uint32_t)b & 0x0000003f); 2718 tmpu16 |= (((uint32_t)a & 0x0000003f) << 6); 2719 BWN_PHY_WRITE(mac, 0x048a, tmpu16); 2720 return; 2721 } 2722 2723 tmp16 = bwn_nrssi_read(mac, 0x20); 2724 if (tmp16 >= 0x20) 2725 tmp16 -= 0x40; 2726 BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed); 2727 } 2728 2729 static void 2730 bwn_nrssi_slope_11g(struct bwn_mac *mac) 2731 { 2732 #define SAVE_RF_MAX 3 2733 #define SAVE_PHY_COMM_MAX 4 2734 #define SAVE_PHY3_MAX 8 2735 static const uint16_t save_rf_regs[SAVE_RF_MAX] = 2736 { 0x7a, 0x52, 0x43 }; 2737 static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = 2738 { 0x15, 0x5a, 0x59, 0x58 }; 2739 static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = { 2740 0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL, 2741 0x0801, 0x0060, 0x0014, 0x0478 2742 }; 2743 struct bwn_phy *phy = &mac->mac_phy; 2744 struct bwn_phy_g *pg = &phy->phy_g; 2745 int32_t i, tmp32, phy3_idx = 0; 2746 uint16_t delta, tmp; 2747 uint16_t save_rf[SAVE_RF_MAX]; 2748 uint16_t save_phy_comm[SAVE_PHY_COMM_MAX]; 2749 uint16_t save_phy3[SAVE_PHY3_MAX]; 2750 uint16_t ant_div, phy0, chan_ex; 2751 int16_t nrssi0, nrssi1; 2752 2753 KASSERT(phy->type == BWN_PHYTYPE_G, 2754 ("%s:%d: fail", __func__, __LINE__)); 2755 2756 if (phy->rf_rev >= 9) 2757 return; 2758 if (phy->rf_rev == 8) 2759 bwn_nrssi_offset(mac); 2760 2761 BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff); 2762 BWN_PHY_MASK(mac, 0x0802, 0xfffc); 2763 2764 /* 2765 * Save RF/PHY registers for later restoration 2766 */ 2767 ant_div = BWN_READ_2(mac, 0x03e2); 2768 BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000); 2769 for (i = 0; i < SAVE_RF_MAX; ++i) 2770 save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]); 2771 for (i = 0; i < SAVE_PHY_COMM_MAX; ++i) 2772 save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]); 2773 2774 phy0 = BWN_READ_2(mac, BWN_PHY0); 2775 chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT); 2776 if (phy->rev >= 3) { 2777 for (i = 0; i < SAVE_PHY3_MAX; ++i) 2778 save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]); 2779 BWN_PHY_WRITE(mac, 0x002e, 0); 2780 BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0); 2781 switch (phy->rev) { 2782 case 4: 2783 case 6: 2784 case 7: 2785 BWN_PHY_SET(mac, 0x0478, 0x0100); 2786 BWN_PHY_SET(mac, 0x0801, 0x0040); 2787 break; 2788 case 3: 2789 case 5: 2790 BWN_PHY_MASK(mac, 0x0801, 0xffbf); 2791 break; 2792 } 2793 BWN_PHY_SET(mac, 0x0060, 0x0040); 2794 BWN_PHY_SET(mac, 0x0014, 0x0200); 2795 } 2796 /* 2797 * Calculate nrssi0 2798 */ 2799 BWN_RF_SET(mac, 0x007a, 0x0070); 2800 bwn_set_all_gains(mac, 0, 8, 0); 2801 BWN_RF_MASK(mac, 0x007a, 0x00f7); 2802 if (phy->rev >= 2) { 2803 BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030); 2804 BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010); 2805 } 2806 BWN_RF_SET(mac, 0x007a, 0x0080); 2807 DELAY(20); 2808 2809 nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f); 2810 if (nrssi0 >= 0x0020) 2811 nrssi0 -= 0x0040; 2812 2813 /* 2814 * Calculate nrssi1 2815 */ 2816 BWN_RF_MASK(mac, 0x007a, 0x007f); 2817 if (phy->rev >= 2) 2818 BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040); 2819 2820 BWN_WRITE_2(mac, BWN_CHANNEL_EXT, 2821 BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000); 2822 BWN_RF_SET(mac, 0x007a, 0x000f); 2823 BWN_PHY_WRITE(mac, 0x0015, 0xf330); 2824 if (phy->rev >= 2) { 2825 BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020); 2826 BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020); 2827 } 2828 2829 bwn_set_all_gains(mac, 3, 0, 1); 2830 if (phy->rf_rev == 8) { 2831 BWN_RF_WRITE(mac, 0x0043, 0x001f); 2832 } else { 2833 tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f; 2834 BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060); 2835 tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0; 2836 BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009); 2837 } 2838 BWN_PHY_WRITE(mac, 0x005a, 0x0480); 2839 BWN_PHY_WRITE(mac, 0x0059, 0x0810); 2840 BWN_PHY_WRITE(mac, 0x0058, 0x000d); 2841 DELAY(20); 2842 nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f); 2843 2844 /* 2845 * Install calculated narrow RSSI values 2846 */ 2847 if (nrssi1 >= 0x0020) 2848 nrssi1 -= 0x0040; 2849 if (nrssi0 == nrssi1) 2850 pg->pg_nrssi_slope = 0x00010000; 2851 else 2852 pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1); 2853 if (nrssi0 >= -4) { 2854 pg->pg_nrssi[0] = nrssi1; 2855 pg->pg_nrssi[1] = nrssi0; 2856 } 2857 2858 /* 2859 * Restore saved RF/PHY registers 2860 */ 2861 if (phy->rev >= 3) { 2862 for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) { 2863 BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx], 2864 save_phy3[phy3_idx]); 2865 } 2866 } 2867 if (phy->rev >= 2) { 2868 BWN_PHY_MASK(mac, 0x0812, 0xffcf); 2869 BWN_PHY_MASK(mac, 0x0811, 0xffcf); 2870 } 2871 2872 for (i = 0; i < SAVE_RF_MAX; ++i) 2873 BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]); 2874 2875 BWN_WRITE_2(mac, 0x03e2, ant_div); 2876 BWN_WRITE_2(mac, 0x03e6, phy0); 2877 BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex); 2878 2879 for (i = 0; i < SAVE_PHY_COMM_MAX; ++i) 2880 BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]); 2881 2882 bwn_spu_workaround(mac, phy->chan); 2883 BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002)); 2884 bwn_set_original_gains(mac); 2885 BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000); 2886 if (phy->rev >= 3) { 2887 for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) { 2888 BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx], 2889 save_phy3[phy3_idx]); 2890 } 2891 } 2892 2893 delta = 0x1f - pg->pg_nrssi[0]; 2894 for (i = 0; i < 64; i++) { 2895 tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a; 2896 tmp32 = MIN(MAX(tmp32, 0), 0x3f); 2897 pg->pg_nrssi_lt[i] = tmp32; 2898 } 2899 2900 bwn_nrssi_threshold(mac); 2901 #undef SAVE_RF_MAX 2902 #undef SAVE_PHY_COMM_MAX 2903 #undef SAVE_PHY3_MAX 2904 } 2905 2906 static void 2907 bwn_nrssi_offset(struct bwn_mac *mac) 2908 { 2909 #define SAVE_RF_MAX 2 2910 #define SAVE_PHY_COMM_MAX 10 2911 #define SAVE_PHY6_MAX 8 2912 static const uint16_t save_rf_regs[SAVE_RF_MAX] = 2913 { 0x7a, 0x43 }; 2914 static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = { 2915 0x0001, 0x0811, 0x0812, 0x0814, 2916 0x0815, 0x005a, 0x0059, 0x0058, 2917 0x000a, 0x0003 2918 }; 2919 static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = { 2920 0x002e, 0x002f, 0x080f, 0x0810, 2921 0x0801, 0x0060, 0x0014, 0x0478 2922 }; 2923 struct bwn_phy *phy = &mac->mac_phy; 2924 int i, phy6_idx = 0; 2925 uint16_t save_rf[SAVE_RF_MAX]; 2926 uint16_t save_phy_comm[SAVE_PHY_COMM_MAX]; 2927 uint16_t save_phy6[SAVE_PHY6_MAX]; 2928 int16_t nrssi; 2929 uint16_t saved = 0xffff; 2930 2931 for (i = 0; i < SAVE_PHY_COMM_MAX; ++i) 2932 save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]); 2933 for (i = 0; i < SAVE_RF_MAX; ++i) 2934 save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]); 2935 2936 BWN_PHY_MASK(mac, 0x0429, 0x7fff); 2937 BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000); 2938 BWN_PHY_SET(mac, 0x0811, 0x000c); 2939 BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004); 2940 BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2)); 2941 if (phy->rev >= 6) { 2942 for (i = 0; i < SAVE_PHY6_MAX; ++i) 2943 save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]); 2944 2945 BWN_PHY_WRITE(mac, 0x002e, 0); 2946 BWN_PHY_WRITE(mac, 0x002f, 0); 2947 BWN_PHY_WRITE(mac, 0x080f, 0); 2948 BWN_PHY_WRITE(mac, 0x0810, 0); 2949 BWN_PHY_SET(mac, 0x0478, 0x0100); 2950 BWN_PHY_SET(mac, 0x0801, 0x0040); 2951 BWN_PHY_SET(mac, 0x0060, 0x0040); 2952 BWN_PHY_SET(mac, 0x0014, 0x0200); 2953 } 2954 BWN_RF_SET(mac, 0x007a, 0x0070); 2955 BWN_RF_SET(mac, 0x007a, 0x0080); 2956 DELAY(30); 2957 2958 nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f); 2959 if (nrssi >= 0x20) 2960 nrssi -= 0x40; 2961 if (nrssi == 31) { 2962 for (i = 7; i >= 4; i--) { 2963 BWN_RF_WRITE(mac, 0x007b, i); 2964 DELAY(20); 2965 nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 2966 0x003f); 2967 if (nrssi >= 0x20) 2968 nrssi -= 0x40; 2969 if (nrssi < 31 && saved == 0xffff) 2970 saved = i; 2971 } 2972 if (saved == 0xffff) 2973 saved = 4; 2974 } else { 2975 BWN_RF_MASK(mac, 0x007a, 0x007f); 2976 if (phy->rev != 1) { 2977 BWN_PHY_SET(mac, 0x0814, 0x0001); 2978 BWN_PHY_MASK(mac, 0x0815, 0xfffe); 2979 } 2980 BWN_PHY_SET(mac, 0x0811, 0x000c); 2981 BWN_PHY_SET(mac, 0x0812, 0x000c); 2982 BWN_PHY_SET(mac, 0x0811, 0x0030); 2983 BWN_PHY_SET(mac, 0x0812, 0x0030); 2984 BWN_PHY_WRITE(mac, 0x005a, 0x0480); 2985 BWN_PHY_WRITE(mac, 0x0059, 0x0810); 2986 BWN_PHY_WRITE(mac, 0x0058, 0x000d); 2987 if (phy->rev == 0) 2988 BWN_PHY_WRITE(mac, 0x0003, 0x0122); 2989 else 2990 BWN_PHY_SET(mac, 0x000a, 0x2000); 2991 if (phy->rev != 1) { 2992 BWN_PHY_SET(mac, 0x0814, 0x0004); 2993 BWN_PHY_MASK(mac, 0x0815, 0xfffb); 2994 } 2995 BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040); 2996 BWN_RF_SET(mac, 0x007a, 0x000f); 2997 bwn_set_all_gains(mac, 3, 0, 1); 2998 BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f); 2999 DELAY(30); 3000 nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f); 3001 if (nrssi >= 0x20) 3002 nrssi -= 0x40; 3003 if (nrssi == -32) { 3004 for (i = 0; i < 4; i++) { 3005 BWN_RF_WRITE(mac, 0x007b, i); 3006 DELAY(20); 3007 nrssi = (int16_t)((BWN_PHY_READ(mac, 3008 0x047f) >> 8) & 0x003f); 3009 if (nrssi >= 0x20) 3010 nrssi -= 0x40; 3011 if (nrssi > -31 && saved == 0xffff) 3012 saved = i; 3013 } 3014 if (saved == 0xffff) 3015 saved = 3; 3016 } else 3017 saved = 0; 3018 } 3019 BWN_RF_WRITE(mac, 0x007b, saved); 3020 3021 /* 3022 * Restore saved RF/PHY registers 3023 */ 3024 if (phy->rev >= 6) { 3025 for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) { 3026 BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx], 3027 save_phy6[phy6_idx]); 3028 } 3029 } 3030 if (phy->rev != 1) { 3031 for (i = 3; i < 5; i++) 3032 BWN_PHY_WRITE(mac, save_phy_comm_regs[i], 3033 save_phy_comm[i]); 3034 } 3035 for (i = 5; i < SAVE_PHY_COMM_MAX; i++) 3036 BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]); 3037 3038 for (i = SAVE_RF_MAX - 1; i >= 0; --i) 3039 BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]); 3040 3041 BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2); 3042 BWN_PHY_SET(mac, 0x0429, 0x8000); 3043 bwn_set_original_gains(mac); 3044 if (phy->rev >= 6) { 3045 for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) { 3046 BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx], 3047 save_phy6[phy6_idx]); 3048 } 3049 } 3050 3051 BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]); 3052 BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]); 3053 BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]); 3054 } 3055 3056 static void 3057 bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second, 3058 int16_t third) 3059 { 3060 struct bwn_phy *phy = &mac->mac_phy; 3061 uint16_t i; 3062 uint16_t start = 0x08, end = 0x18; 3063 uint16_t tmp; 3064 uint16_t table; 3065 3066 if (phy->rev <= 1) { 3067 start = 0x10; 3068 end = 0x20; 3069 } 3070 3071 table = BWN_OFDMTAB_GAINX; 3072 if (phy->rev <= 1) 3073 table = BWN_OFDMTAB_GAINX_R1; 3074 for (i = 0; i < 4; i++) 3075 bwn_ofdmtab_write_2(mac, table, i, first); 3076 3077 for (i = start; i < end; i++) 3078 bwn_ofdmtab_write_2(mac, table, i, second); 3079 3080 if (third != -1) { 3081 tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6); 3082 BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp); 3083 BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp); 3084 BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp); 3085 } 3086 bwn_dummy_transmission(mac, 0, 1); 3087 } 3088 3089 static void 3090 bwn_set_original_gains(struct bwn_mac *mac) 3091 { 3092 struct bwn_phy *phy = &mac->mac_phy; 3093 uint16_t i, tmp; 3094 uint16_t table; 3095 uint16_t start = 0x0008, end = 0x0018; 3096 3097 if (phy->rev <= 1) { 3098 start = 0x0010; 3099 end = 0x0020; 3100 } 3101 3102 table = BWN_OFDMTAB_GAINX; 3103 if (phy->rev <= 1) 3104 table = BWN_OFDMTAB_GAINX_R1; 3105 for (i = 0; i < 4; i++) { 3106 tmp = (i & 0xfffc); 3107 tmp |= (i & 0x0001) << 1; 3108 tmp |= (i & 0x0002) >> 1; 3109 3110 bwn_ofdmtab_write_2(mac, table, i, tmp); 3111 } 3112 3113 for (i = start; i < end; i++) 3114 bwn_ofdmtab_write_2(mac, table, i, i - start); 3115 3116 BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040); 3117 BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040); 3118 BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000); 3119 bwn_dummy_transmission(mac, 0, 1); 3120 } 3121 3122 static void 3123 bwn_phy_hwpctl_init(struct bwn_mac *mac) 3124 { 3125 struct bwn_phy *phy = &mac->mac_phy; 3126 struct bwn_phy_g *pg = &phy->phy_g; 3127 struct bwn_rfatt old_rfatt, rfatt; 3128 struct bwn_bbatt old_bbatt, bbatt; 3129 struct bwn_softc *sc = mac->mac_sc; 3130 uint8_t old_txctl = 0; 3131 3132 KASSERT(phy->type == BWN_PHYTYPE_G, 3133 ("%s:%d: fail", __func__, __LINE__)); 3134 3135 if ((sc->sc_board_info.board_vendor == PCI_VENDOR_BROADCOM) && 3136 (sc->sc_board_info.board_type == BHND_BOARD_BU4306)) 3137 return; 3138 3139 BWN_PHY_WRITE(mac, 0x0028, 0x8018); 3140 3141 BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf); 3142 3143 if (!phy->gmode) 3144 return; 3145 bwn_hwpctl_early_init(mac); 3146 if (pg->pg_curtssi == 0) { 3147 if (phy->rf_ver == 0x2050 && phy->analog == 0) { 3148 BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084); 3149 } else { 3150 memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt)); 3151 memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt)); 3152 old_txctl = pg->pg_txctl; 3153 3154 bbatt.att = 11; 3155 if (phy->rf_rev == 8) { 3156 rfatt.att = 15; 3157 rfatt.padmix = 1; 3158 } else { 3159 rfatt.att = 9; 3160 rfatt.padmix = 0; 3161 } 3162 bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0); 3163 } 3164 bwn_dummy_transmission(mac, 0, 1); 3165 pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI); 3166 if (phy->rf_ver == 0x2050 && phy->analog == 0) 3167 BWN_RF_MASK(mac, 0x0076, 0xff7b); 3168 else 3169 bwn_phy_g_set_txpwr_sub(mac, &old_bbatt, 3170 &old_rfatt, old_txctl); 3171 } 3172 bwn_hwpctl_init_gphy(mac); 3173 3174 /* clear TSSI */ 3175 bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f); 3176 bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f); 3177 bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f); 3178 bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f); 3179 } 3180 3181 static void 3182 bwn_hwpctl_early_init(struct bwn_mac *mac) 3183 { 3184 struct bwn_phy *phy = &mac->mac_phy; 3185 3186 if (!bwn_has_hwpctl(mac)) { 3187 BWN_PHY_WRITE(mac, 0x047a, 0xc111); 3188 return; 3189 } 3190 3191 BWN_PHY_MASK(mac, 0x0036, 0xfeff); 3192 BWN_PHY_WRITE(mac, 0x002f, 0x0202); 3193 BWN_PHY_SET(mac, 0x047c, 0x0002); 3194 BWN_PHY_SET(mac, 0x047a, 0xf000); 3195 if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) { 3196 BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010); 3197 BWN_PHY_SET(mac, 0x005d, 0x8000); 3198 BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010); 3199 BWN_PHY_WRITE(mac, 0x002e, 0xc07f); 3200 BWN_PHY_SET(mac, 0x0036, 0x0400); 3201 } else { 3202 BWN_PHY_SET(mac, 0x0036, 0x0200); 3203 BWN_PHY_SET(mac, 0x0036, 0x0400); 3204 BWN_PHY_MASK(mac, 0x005d, 0x7fff); 3205 BWN_PHY_MASK(mac, 0x004f, 0xfffe); 3206 BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010); 3207 BWN_PHY_WRITE(mac, 0x002e, 0xc07f); 3208 BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010); 3209 } 3210 } 3211 3212 static void 3213 bwn_hwpctl_init_gphy(struct bwn_mac *mac) 3214 { 3215 struct bwn_phy *phy = &mac->mac_phy; 3216 struct bwn_phy_g *pg = &phy->phy_g; 3217 struct bwn_txpwr_loctl *lo = &pg->pg_loctl; 3218 int i; 3219 uint16_t nr_written = 0, tmp, value; 3220 uint8_t rf, bb; 3221 3222 if (!bwn_has_hwpctl(mac)) { 3223 bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL); 3224 return; 3225 } 3226 3227 BWN_PHY_SETMASK(mac, 0x0036, 0xffc0, 3228 (pg->pg_idletssi - pg->pg_curtssi)); 3229 BWN_PHY_SETMASK(mac, 0x0478, 0xff00, 3230 (pg->pg_idletssi - pg->pg_curtssi)); 3231 3232 for (i = 0; i < 32; i++) 3233 bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]); 3234 for (i = 32; i < 64; i++) 3235 bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]); 3236 for (i = 0; i < 64; i += 2) { 3237 value = (uint16_t) pg->pg_tssi2dbm[i]; 3238 value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8; 3239 BWN_PHY_WRITE(mac, 0x380 + (i / 2), value); 3240 } 3241 3242 for (rf = 0; rf < lo->rfatt.len; rf++) { 3243 for (bb = 0; bb < lo->bbatt.len; bb++) { 3244 if (nr_written >= 0x40) 3245 return; 3246 tmp = lo->bbatt.array[bb].att; 3247 tmp <<= 8; 3248 if (phy->rf_rev == 8) 3249 tmp |= 0x50; 3250 else 3251 tmp |= 0x40; 3252 tmp |= lo->rfatt.array[rf].att; 3253 BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp); 3254 nr_written++; 3255 } 3256 } 3257 3258 BWN_PHY_MASK(mac, 0x0060, 0xffbf); 3259 BWN_PHY_WRITE(mac, 0x0014, 0x0000); 3260 3261 KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__)); 3262 BWN_PHY_SET(mac, 0x0478, 0x0800); 3263 BWN_PHY_MASK(mac, 0x0478, 0xfeff); 3264 BWN_PHY_MASK(mac, 0x0801, 0xffbf); 3265 3266 bwn_phy_g_dc_lookup_init(mac, 1); 3267 bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL); 3268 } 3269 3270 static void 3271 bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu) 3272 { 3273 struct bwn_softc *sc = mac->mac_sc; 3274 int error; 3275 3276 if (spu != 0) 3277 bwn_spu_workaround(mac, channel); 3278 3279 BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel)); 3280 3281 if (channel == 14) { 3282 uint8_t cc; 3283 3284 error = bhnd_nvram_getvar_uint8(sc->sc_dev, BHND_NVAR_CC, &cc); 3285 if (error) { 3286 device_printf(sc->sc_dev, "error reading country code " 3287 "from NVRAM, assuming channel 14 unavailable: %d\n", 3288 error); 3289 cc = BWN_SPROM1_CC_WORLDWIDE; 3290 } 3291 3292 if (cc == BWN_SPROM1_CC_JP) 3293 bwn_hf_write(mac, 3294 bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF); 3295 else 3296 bwn_hf_write(mac, 3297 bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF); 3298 BWN_WRITE_2(mac, BWN_CHANNEL_EXT, 3299 BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11)); 3300 return; 3301 } 3302 3303 BWN_WRITE_2(mac, BWN_CHANNEL_EXT, 3304 BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf); 3305 } 3306 3307 static uint16_t 3308 bwn_phy_g_chan2freq(uint8_t channel) 3309 { 3310 static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS; 3311 3312 KASSERT(channel >= 1 && channel <= 14, 3313 ("%s:%d: fail", __func__, __LINE__)); 3314 3315 return (bwn_phy_g_rf_channels[channel - 1]); 3316 } 3317 3318 static void 3319 bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt, 3320 const struct bwn_rfatt *rfatt, uint8_t txctl) 3321 { 3322 struct bwn_phy *phy = &mac->mac_phy; 3323 struct bwn_phy_g *pg = &phy->phy_g; 3324 struct bwn_txpwr_loctl *lo = &pg->pg_loctl; 3325 uint16_t bb, rf; 3326 uint16_t tx_bias, tx_magn; 3327 3328 bb = bbatt->att; 3329 rf = rfatt->att; 3330 tx_bias = lo->tx_bias; 3331 tx_magn = lo->tx_magn; 3332 if (tx_bias == 0xff) 3333 tx_bias = 0; 3334 3335 pg->pg_txctl = txctl; 3336 memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt)); 3337 pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0; 3338 memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt)); 3339 bwn_phy_g_set_bbatt(mac, bb); 3340 bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf); 3341 if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) 3342 BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070)); 3343 else { 3344 BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f)); 3345 BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070)); 3346 } 3347 if (BWN_HAS_TXMAG(phy)) 3348 BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias); 3349 else 3350 BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f)); 3351 bwn_lo_g_adjust(mac); 3352 } 3353 3354 static void 3355 bwn_phy_g_set_bbatt(struct bwn_mac *mac, 3356 uint16_t bbatt) 3357 { 3358 struct bwn_phy *phy = &mac->mac_phy; 3359 3360 if (phy->analog == 0) { 3361 BWN_WRITE_2(mac, BWN_PHY0, 3362 (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt); 3363 return; 3364 } 3365 if (phy->analog > 1) { 3366 BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2); 3367 return; 3368 } 3369 BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3); 3370 } 3371 3372 static uint16_t 3373 bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd) 3374 { 3375 struct bwn_phy *phy = &mac->mac_phy; 3376 struct bwn_phy_g *pg = &phy->phy_g; 3377 struct bwn_softc *sc = mac->mac_sc; 3378 int max_lb_gain; 3379 uint16_t extlna; 3380 uint16_t i; 3381 3382 if (phy->gmode == 0) 3383 return (0); 3384 3385 if (BWN_HAS_LOOPBACK(phy)) { 3386 max_lb_gain = pg->pg_max_lb_gain; 3387 max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26; 3388 if (max_lb_gain >= 0x46) { 3389 extlna = 0x3000; 3390 max_lb_gain -= 0x46; 3391 } else if (max_lb_gain >= 0x3a) { 3392 extlna = 0x1000; 3393 max_lb_gain -= 0x3a; 3394 } else if (max_lb_gain >= 0x2e) { 3395 extlna = 0x2000; 3396 max_lb_gain -= 0x2e; 3397 } else { 3398 extlna = 0; 3399 max_lb_gain -= 0x10; 3400 } 3401 3402 for (i = 0; i < 16; i++) { 3403 max_lb_gain -= (i * 6); 3404 if (max_lb_gain < 6) 3405 break; 3406 } 3407 3408 if ((phy->rev < 7) || 3409 !(sc->sc_board_info.board_flags & BHND_BFL_EXTLNA)) { 3410 if (reg == BWN_PHY_RFOVER) { 3411 return (0x1b3); 3412 } else if (reg == BWN_PHY_RFOVERVAL) { 3413 extlna |= (i << 8); 3414 switch (lpd) { 3415 case BWN_LPD(0, 1, 1): 3416 return (0x0f92); 3417 case BWN_LPD(0, 0, 1): 3418 case BWN_LPD(1, 0, 1): 3419 return (0x0092 | extlna); 3420 case BWN_LPD(1, 0, 0): 3421 return (0x0093 | extlna); 3422 } 3423 KASSERT(0 == 1, 3424 ("%s:%d: fail", __func__, __LINE__)); 3425 } 3426 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); 3427 } else { 3428 if (reg == BWN_PHY_RFOVER) 3429 return (0x9b3); 3430 if (reg == BWN_PHY_RFOVERVAL) { 3431 if (extlna) 3432 extlna |= 0x8000; 3433 extlna |= (i << 8); 3434 switch (lpd) { 3435 case BWN_LPD(0, 1, 1): 3436 return (0x8f92); 3437 case BWN_LPD(0, 0, 1): 3438 return (0x8092 | extlna); 3439 case BWN_LPD(1, 0, 1): 3440 return (0x2092 | extlna); 3441 case BWN_LPD(1, 0, 0): 3442 return (0x2093 | extlna); 3443 } 3444 KASSERT(0 == 1, 3445 ("%s:%d: fail", __func__, __LINE__)); 3446 } 3447 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); 3448 } 3449 return (0); 3450 } 3451 3452 if ((phy->rev < 7) || 3453 !(sc->sc_board_info.board_flags & BHND_BFL_EXTLNA)) { 3454 if (reg == BWN_PHY_RFOVER) { 3455 return (0x1b3); 3456 } else if (reg == BWN_PHY_RFOVERVAL) { 3457 switch (lpd) { 3458 case BWN_LPD(0, 1, 1): 3459 return (0x0fb2); 3460 case BWN_LPD(0, 0, 1): 3461 return (0x00b2); 3462 case BWN_LPD(1, 0, 1): 3463 return (0x30b2); 3464 case BWN_LPD(1, 0, 0): 3465 return (0x30b3); 3466 } 3467 KASSERT(0 == 1, 3468 ("%s:%d: fail", __func__, __LINE__)); 3469 } 3470 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); 3471 } else { 3472 if (reg == BWN_PHY_RFOVER) { 3473 return (0x9b3); 3474 } else if (reg == BWN_PHY_RFOVERVAL) { 3475 switch (lpd) { 3476 case BWN_LPD(0, 1, 1): 3477 return (0x8fb2); 3478 case BWN_LPD(0, 0, 1): 3479 return (0x80b2); 3480 case BWN_LPD(1, 0, 1): 3481 return (0x20b2); 3482 case BWN_LPD(1, 0, 0): 3483 return (0x20b3); 3484 } 3485 KASSERT(0 == 1, 3486 ("%s:%d: fail", __func__, __LINE__)); 3487 } 3488 KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__)); 3489 } 3490 return (0); 3491 } 3492 3493 static void 3494 bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel) 3495 { 3496 3497 if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6) 3498 return; 3499 BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ? 3500 bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1)); 3501 DELAY(1000); 3502 BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel)); 3503 } 3504 3505 static int 3506 bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset) 3507 { 3508 const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK); 3509 unsigned int a, b, c, d; 3510 unsigned int avg; 3511 uint32_t tmp; 3512 3513 tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset); 3514 a = tmp & 0xff; 3515 b = (tmp >> 8) & 0xff; 3516 c = (tmp >> 16) & 0xff; 3517 d = (tmp >> 24) & 0xff; 3518 if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX || 3519 c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX) 3520 return (ENOENT); 3521 bwn_shm_write_4(mac, BWN_SHARED, shm_offset, 3522 BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) | 3523 (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24)); 3524 3525 if (ofdm) { 3526 a = (a + 32) & 0x3f; 3527 b = (b + 32) & 0x3f; 3528 c = (c + 32) & 0x3f; 3529 d = (d + 32) & 0x3f; 3530 } 3531 3532 avg = (a + b + c + d + 2) / 4; 3533 if (ofdm) { 3534 if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO) 3535 & BWN_HF_4DB_CCK_POWERBOOST) 3536 avg = (avg >= 13) ? (avg - 13) : 0; 3537 } 3538 return (avg); 3539 } 3540 3541 static void 3542 bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp) 3543 { 3544 struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl; 3545 int rfatt = *rfattp; 3546 int bbatt = *bbattp; 3547 3548 while (1) { 3549 if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4) 3550 break; 3551 if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4) 3552 break; 3553 if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1) 3554 break; 3555 if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1) 3556 break; 3557 if (bbatt > lo->bbatt.max) { 3558 bbatt -= 4; 3559 rfatt += 1; 3560 continue; 3561 } 3562 if (bbatt < lo->bbatt.min) { 3563 bbatt += 4; 3564 rfatt -= 1; 3565 continue; 3566 } 3567 if (rfatt > lo->rfatt.max) { 3568 rfatt -= 1; 3569 bbatt += 4; 3570 continue; 3571 } 3572 if (rfatt < lo->rfatt.min) { 3573 rfatt += 1; 3574 bbatt -= 4; 3575 continue; 3576 } 3577 break; 3578 } 3579 3580 *rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max); 3581 *bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max); 3582 } 3583 3584 static void 3585 bwn_phy_lock(struct bwn_mac *mac) 3586 { 3587 struct bwn_softc *sc = mac->mac_sc; 3588 struct ieee80211com *ic = &sc->sc_ic; 3589 3590 KASSERT(bhnd_get_hwrev(sc->sc_dev) >= 3, 3591 ("%s: unsupported rev %d", __func__, bhnd_get_hwrev(sc->sc_dev))); 3592 3593 if (ic->ic_opmode != IEEE80211_M_HOSTAP) 3594 bwn_psctl(mac, BWN_PS_AWAKE); 3595 } 3596 3597 static void 3598 bwn_phy_unlock(struct bwn_mac *mac) 3599 { 3600 struct bwn_softc *sc = mac->mac_sc; 3601 struct ieee80211com *ic = &sc->sc_ic; 3602 3603 KASSERT(bhnd_get_hwrev(sc->sc_dev) >= 3, 3604 ("%s: unsupported rev %d", __func__, bhnd_get_hwrev(sc->sc_dev))); 3605 3606 if (ic->ic_opmode != IEEE80211_M_HOSTAP) 3607 bwn_psctl(mac, 0); 3608 } 3609 3610 static void 3611 bwn_rf_lock(struct bwn_mac *mac) 3612 { 3613 3614 BWN_WRITE_4(mac, BWN_MACCTL, 3615 BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK); 3616 BWN_READ_4(mac, BWN_MACCTL); 3617 DELAY(10); 3618 } 3619 3620 static void 3621 bwn_rf_unlock(struct bwn_mac *mac) 3622 { 3623 3624 BWN_READ_2(mac, BWN_PHYVER); 3625 BWN_WRITE_4(mac, BWN_MACCTL, 3626 BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK); 3627 } 3628